From: dan Date: Tue, 2 Nov 2010 17:41:52 +0000 (+0000) Subject: Changes to allow FTS4 tables to be created without the underlying %_docsize table... X-Git-Tag: version-3.7.4~72 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=af4c214e1fa93cdbf66d9066ad3e00a2fb1d8d1c;p=thirdparty%2Fsqlite.git Changes to allow FTS4 tables to be created without the underlying %_docsize table (in order to save space). FossilOrigin-Name: 31989b18f53d97eddfb39660ef04fbf9463583e0 --- diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 5fcb77fb55..023787c3bf 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -595,6 +595,8 @@ static int fts3CreateTables(Fts3Table *p){ "CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);", p->zDb, p->zName ); + } + if( p->bHasStat ){ fts3DbExec(&rc, db, "CREATE TABLE %Q.'%q_stat'(id INTEGER PRIMARY KEY, value BLOB);", p->zDb, p->zName @@ -669,6 +671,36 @@ static void fts3DatabasePageSize(int *pRc, Fts3Table *p){ } } +/* +** "Special" FTS4 arguments are column specifications of the following form: +** +** = +** +** There may not be whitespace surrounding the "=" character. The +** term may be quoted, but the may not. +*/ +static int fts3IsSpecialColumn( + const char *z, + int *pnKey, + char **pzValue +){ + char *zValue; + const char *zCsr = z; + + while( *zCsr!='=' ){ + if( *zCsr=='\0' ) return 0; + zCsr++; + } + + *pnKey = zCsr-z; + zValue = sqlite3_mprintf("%s", &zCsr[1]); + if( zValue ){ + sqlite3Fts3Dequote(zValue); + } + *pzValue = zValue; + return 1; +} + /* ** This function is the implementation of both the xConnect and xCreate ** methods of the FTS3 virtual table. @@ -690,8 +722,8 @@ static int fts3InitVtab( char **pzErr /* Write any error message here */ ){ Fts3Hash *pHash = (Fts3Hash *)pAux; - Fts3Table *p; /* Pointer to allocated vtab */ - int rc; /* Return code */ + Fts3Table *p = 0; /* Pointer to allocated vtab */ + int rc = SQLITE_OK; /* Return code */ int i; /* Iterator variable */ int nByte; /* Size of allocation used for *p */ int iCol; /* Column index */ @@ -700,35 +732,90 @@ static int fts3InitVtab( char *zCsr; /* Space for holding column names */ int nDb; /* Bytes required to hold database name */ int nName; /* Bytes required to hold table name */ - - const char *zTokenizer = 0; /* Name of tokenizer to use */ + int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */ + int bNoDocsize = 0; /* True to omit %_docsize table */ + const char **aCol; /* Array of column names */ sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ + assert( strlen(argv[0])==4 ); + assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4) + || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4) + ); + nDb = (int)strlen(argv[1]) + 1; nName = (int)strlen(argv[2]) + 1; - for(i=3; i8 + && 0==sqlite3_strnicmp(z, "tokenize", 8) + && 0==sqlite3Fts3IsIdChar(z[8]) + ){ + rc = sqlite3Fts3InitTokenizer(pHash, &z[9], &pTokenizer, pzErr); } - if( z!=zTokenizer ){ - nString += (int)(strlen(z) + 1); + + /* Check if it is an FTS4 special argument. */ + else if( isFts4 && fts3IsSpecialColumn(z, &nKey, &zVal) ){ + if( !zVal ){ + rc = SQLITE_NOMEM; + goto fts3_init_out; + } + if( nKey==9 && 0==sqlite3_strnicmp(z, "matchinfo", 9) ){ + if( strlen(zVal)==4 && 0==sqlite3_strnicmp(zVal, "fts3", 4) ){ + bNoDocsize = 1; + }else{ + *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal); + rc = SQLITE_ERROR; + } + }else{ + *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z); + rc = SQLITE_ERROR; + } + sqlite3_free(zVal); } - } - nCol = argc - 3 - (zTokenizer!=0); - if( zTokenizer==0 ){ - rc = sqlite3Fts3InitTokenizer(pHash, 0, &pTokenizer, 0, pzErr); - if( rc!=SQLITE_OK ){ - return rc; + + /* Otherwise, the argument is a column name. */ + else { + nString += (int)(strlen(z) + 1); + aCol[nCol++] = z; } - assert( pTokenizer ); } + if( rc!=SQLITE_OK ) goto fts3_init_out; if( nCol==0 ){ + assert( nString==0 ); + aCol[0] = "content"; + nString = 8; nCol = 1; } + if( pTokenizer==0 ){ + rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr); + if( rc!=SQLITE_OK ) goto fts3_init_out; + } + assert( pTokenizer ); + + /* Allocate and populate the Fts3Table structure. */ nByte = sizeof(Fts3Table) + /* Fts3Table */ nCol * sizeof(char *) + /* azColumn */ @@ -741,7 +828,6 @@ static int fts3InitVtab( goto fts3_init_out; } memset(p, 0, nByte); - p->db = db; p->nColumn = nCol; p->nPendingData = 0; @@ -749,11 +835,12 @@ static int fts3InitVtab( p->pTokenizer = pTokenizer; p->nNodeSize = 1000; p->nMaxPendingData = FTS3_MAX_PENDING_DATA; - zCsr = (char *)&p->azColumn[nCol]; - + p->bHasDocsize = (isFts4 && bNoDocsize==0); + p->bHasStat = isFts4; fts3HashInit(&p->pendingTerms, FTS3_HASH_STRING, 1); /* Fill in the zName and zDb fields of the vtab structure. */ + zCsr = (char *)&p->azColumn[nCol]; p->zName = zCsr; memcpy(zCsr, argv[2], nName); zCsr += nName; @@ -762,36 +849,23 @@ static int fts3InitVtab( zCsr += nDb; /* Fill in the azColumn array */ - iCol = 0; - for(i=3; iazColumn[iCol++] = zCsr; - zCsr += n+1; - assert( zCsr <= &((char *)p)[nByte] ); - } - } - if( iCol==0 ){ - assert( nCol==1 ); - p->azColumn[0] = "content"; + for(iCol=0; iColazColumn[iCol] = zCsr; + zCsr += n+1; + assert( zCsr <= &((char *)p)[nByte] ); } /* If this is an xCreate call, create the underlying tables in the ** database. TODO: For xConnect(), it could verify that said tables exist. */ if( isCreate ){ - p->bHasContent = 1; - p->bHasDocsize = argv[0][3]=='4'; rc = fts3CreateTables(p); - }else{ - rc = SQLITE_OK; - fts3TableExists(&rc, db, argv[1], argv[2], "_content", &p->bHasContent); - fts3TableExists(&rc, db, argv[1], argv[2], "_docsize", &p->bHasDocsize); } /* Figure out the page-size for the database. This is required in order to @@ -804,11 +878,12 @@ static int fts3InitVtab( fts3DeclareVtab(&rc, p); fts3_init_out: - assert( p || (pTokenizer && rc!=SQLITE_OK) ); + + sqlite3_free(aCol); if( rc!=SQLITE_OK ){ if( p ){ fts3DisconnectMethod((sqlite3_vtab *)p); - }else{ + }else if( pTokenizer ){ pTokenizer->pModule->xDestroy(pTokenizer); } }else{ @@ -3302,6 +3377,8 @@ static int fts3RenameMethod( "ALTER TABLE %Q.'%q_docsize' RENAME TO '%q_docsize';", p->zDb, p->zName, zName ); + } + if( p->bHasStat ){ fts3DbExec(&rc, db, "ALTER TABLE %Q.'%q_stat' RENAME TO '%q_stat';", p->zDb, p->zName, zName diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h index 9ddf5e51d0..8ad560e316 100644 --- a/ext/fts3/fts3Int.h +++ b/ext/fts3/fts3Int.h @@ -131,7 +131,7 @@ struct Fts3Table { sqlite3_stmt *aStmt[24]; int nNodeSize; /* Soft limit for node size */ - u8 bHasContent; /* True if %_content table exists */ + u8 bHasStat; /* True if %_stat table exists */ u8 bHasDocsize; /* True if %_docsize table exists */ int nPgsz; /* Page size for host database */ char *zSegmentsTbl; /* Name of %_segments table */ @@ -329,9 +329,10 @@ int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int); /* fts3_tokenizer.c */ const char *sqlite3Fts3NextToken(const char *, int *); int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *); -int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, - const char *, sqlite3_tokenizer **, const char **, char ** +int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *, + sqlite3_tokenizer **, char ** ); +int sqlite3Fts3IsIdChar(char); /* fts3_snippet.c */ void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); diff --git a/ext/fts3/fts3_tokenizer.c b/ext/fts3/fts3_tokenizer.c index 54a91bfe45..cf392d38f7 100644 --- a/ext/fts3/fts3_tokenizer.c +++ b/ext/fts3/fts3_tokenizer.c @@ -97,7 +97,7 @@ static void scalarFunc( sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT); } -static int fts3IsIdChar(char c){ +int sqlite3Fts3IsIdChar(char c){ static const char isFtsIdChar[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ @@ -135,9 +135,9 @@ const char *sqlite3Fts3NextToken(const char *zStr, int *pn){ break; default: - if( fts3IsIdChar(*z1) ){ + if( sqlite3Fts3IsIdChar(*z1) ){ z2 = &z1[1]; - while( fts3IsIdChar(*z2) ) z2++; + while( sqlite3Fts3IsIdChar(*z2) ) z2++; }else{ z1++; } @@ -150,9 +150,8 @@ const char *sqlite3Fts3NextToken(const char *zStr, int *pn){ int sqlite3Fts3InitTokenizer( Fts3Hash *pHash, /* Tokenizer hash table */ - const char *zArg, /* Possible tokenizer specification */ + const char *zArg, /* Tokenizer name */ sqlite3_tokenizer **ppTok, /* OUT: Tokenizer (if applicable) */ - const char **pzTokenizer, /* OUT: Set to zArg if is tokenizer */ char **pzErr /* OUT: Set to malloced error message */ ){ int rc; @@ -162,26 +161,15 @@ int sqlite3Fts3InitTokenizer( char *zEnd; /* Pointer to nul-term of zCopy */ sqlite3_tokenizer_module *m; - if( !z ){ - zCopy = sqlite3_mprintf("simple"); - }else{ - if( sqlite3_strnicmp(z, "tokenize", 8) || fts3IsIdChar(z[8])){ - return SQLITE_OK; - } - zCopy = sqlite3_mprintf("%s", &z[8]); - *pzTokenizer = zArg; - } - if( !zCopy ){ - return SQLITE_NOMEM; - } - + zCopy = sqlite3_mprintf("%s", zArg); + if( !zCopy ) return SQLITE_NOMEM; zEnd = &zCopy[strlen(zCopy)]; z = (char *)sqlite3Fts3NextToken(zCopy, &n); z[n] = '\0'; sqlite3Fts3Dequote(z); - m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, z, (int)strlen(z)+1); + m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash,z,(int)strlen(z)+1); if( !m ){ *pzErr = sqlite3_mprintf("unknown tokenizer: %s", z); rc = SQLITE_ERROR; diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index 2f4db406ed..91699bedb7 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -683,6 +683,8 @@ static int fts3DeleteAll(Fts3Table *p){ fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0); if( p->bHasDocsize ){ fts3SqlExec(&rc, p, SQL_DELETE_ALL_DOCSIZE, 0); + } + if( p->bHasStat ){ fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0); } return rc; @@ -1035,7 +1037,7 @@ int sqlite3Fts3SegReaderCost( ** for the segment is stored on the root page of the b-tree, then the cost ** is zero. In this case all required data is already in main memory. */ - if( p->bHasDocsize + if( p->bHasStat && !fts3SegReaderIsPending(pReader) && !fts3SegReaderIsRootOnly(pReader) ){ @@ -2855,8 +2857,8 @@ int sqlite3Fts3UpdateMethod( fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, apVal); if( p->bHasDocsize ){ fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, apVal); - nChng--; } + nChng--; } } }else if( sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL ){ @@ -2874,12 +2876,12 @@ int sqlite3Fts3UpdateMethod( rc = fts3InsertTerms(p, apVal, aSzIns); } if( p->bHasDocsize ){ - nChng++; fts3InsertDocsize(&rc, p, aSzIns); } + nChng++; } - if( p->bHasDocsize ){ + if( p->bHasStat ){ fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng); } diff --git a/manifest b/manifest index e625fa9968..414c336c36 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Add\sevidence\smarks\sfor\sthe\ssqlite3_blob_reopen()\sinterface.\s\sFix\scompiler\nwarnings\sin\stest1.c.\s\sFix\sincorrect\sevidence\smarks\son\se_select.tcl. -D 2010-11-02T15:26:24 +C Changes\sto\sallow\sFTS4\stables\sto\sbe\screated\swithout\sthe\sunderlying\s%_docsize\stable\s(in\sorder\sto\ssave\sspace). +D 2010-11-02T17:41:53 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2c8cefd962eca0147132c7cf9eaa4bb24c656f3f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -64,19 +61,19 @@ F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c 48c37f640fb5837dcdbd04ef2d51ec40c8637503 +F ext/fts3/fts3.c 9da9f1d5bc4b087540255ffdb7a4428fe708edf0 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe -F ext/fts3/fts3Int.h 819bc2661c8f3b46221d146f1810dc6741819f55 +F ext/fts3/fts3Int.h bbcd6d671228c9ae2ed5514723fcc6217821d0a6 F ext/fts3/fts3_expr.c ee48b9278b8b2432a05a03320fbcacba151dbaa5 F ext/fts3/fts3_hash.c 3c8f6387a4a7f5305588b203fa7c887d753e1f1c F ext/fts3/fts3_hash.h 8331fb2206c609f9fc4c4735b9ab5ad6137c88ec F ext/fts3/fts3_icu.c ac494aed69835008185299315403044664bda295 F ext/fts3/fts3_porter.c 8df6f6efcc4e9e31f8bf73a4007c2e9abca1dfba F ext/fts3/fts3_snippet.c 300c12b7f0a2a6ae0491bb2d00e2d5ff9c28f685 -F ext/fts3/fts3_tokenizer.c b4f2d01c24573852755bc92864816785dae39318 +F ext/fts3/fts3_tokenizer.c 1301b0ee3ef414caae3257a702215925cc48cd9c F ext/fts3/fts3_tokenizer.h 13ffd9fcb397fec32a05ef5cd9e0fa659bf3dbd3 F ext/fts3/fts3_tokenizer1.c 6e5cbaa588924ac578263a598e4fb9f5c9bb179d -F ext/fts3/fts3_write.c 01478ee63bb321f240bb5565d9e36e8641b33928 +F ext/fts3/fts3_write.c 3d12dad6cbe788ff7214ef227520fb6600ff5112 F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9 @@ -438,13 +435,14 @@ F test/fts3corrupt.test d874ba27975aa8e5514bf58bf97b473404de0dbb F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7 F test/fts3d.test 95fb3c862cbc4297c93fceb9a635543744e9ef52 -F test/fts3defer.test eab4f24c8402fb4e1e6aad44bcdfbe5bf42160b2 +F test/fts3defer.test d6cb0db9b5997ecf863d96ff419f83f8f2c87f4f F test/fts3defer2.test d3c7db6584aab06a2781b8de58747c33b23cb19c F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851 F test/fts3expr.test 5e745b2b6348499d9ef8d59015de3182072c564c F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a -F test/fts3fault.test c45707ac123b511e4d8291ca3d84e25fd5029b43 +F test/fts3fault.test 2c8c26f9002be900056b63996a2891a043775f7b F test/fts3malloc.test 9c8cc3f885bb4dfc66d0460c52f68f45e4710d1b +F test/fts3matchinfo.test 5ded93253526033c662ec49c696e936da4e8885d F test/fts3near.test 2e318ee434d32babd27c167142e2b94ddbab4844 F test/fts3query.test 724a662dbbec4e9dbef66a1389588aa29aeb9b27 F test/fts3rnd.test 707533ce943f490443ce5e696236bb1675a37635 @@ -578,7 +576,7 @@ F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806 F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb F test/pcache.test 4118a183908ecaed343a06fcef3ba82e87e0129d F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16 -F test/permutations.test e54d5fc34708ecb4a67f2a18f7b8719b175a1652 +F test/permutations.test 193238b7828759805091ecddd9a0912767f236a4 F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea @@ -885,14 +883,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 6cae552927392d8b735aa118c318d7468097ebeb -R 99d449c40cc2af47a17f6b479744ba94 -U drh -Z e0eff9674ebb6295f2b6870d990e3417 ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFM0C2qoxKgR168RlERAtsWAJ0c+Qg4qImQebinYShOYuBIEoXfRwCfQdMI -MPI2wIAAWE4t5rkTCaRo+NI= -=5kvu ------END PGP SIGNATURE----- +P 3771faa88eda3eb91264ce0982e22f53596abd4b +R 1930e53dc41c38f7661c545902820ee1 +U dan +Z d5d5199f8f8688f85abc4cc6dcb16369 diff --git a/manifest.uuid b/manifest.uuid index 58981e0986..b78828ea1c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3771faa88eda3eb91264ce0982e22f53596abd4b \ No newline at end of file +31989b18f53d97eddfb39660ef04fbf9463583e0 \ No newline at end of file diff --git a/test/fts3defer.test b/test/fts3defer.test index f623143568..1c9056fd9d 100644 --- a/test/fts3defer.test +++ b/test/fts3defer.test @@ -233,6 +233,13 @@ foreach {tn setup} { execsql "INSERT INTO t1(t1) VALUES('optimize')" execsql $zero_long_doclists } + 5 { + set dmt_modes 0 + execsql { CREATE VIRTUAL TABLE t1 USING FTS4(matchinfo=fts3) } + foreach doc $data { execsql { INSERT INTO t1 VALUES($doc) } } + add_empty_records 1000 + execsql $zero_long_doclists + } } { execsql { DROP TABLE IF EXISTS t1 } diff --git a/test/fts3fault.test b/test/fts3fault.test index 67f47ddf8e..fe1f77f9a6 100644 --- a/test/fts3fault.test +++ b/test/fts3fault.test @@ -126,4 +126,30 @@ do_faultsim_test 6 -prep { faultsim_test_result {0 {}} } +# Test various malloc failures while processing FTS4 parameters. +# +do_faultsim_test 7.1 -prep { + faultsim_delete_and_reopen +} -body { + execsql { CREATE VIRTUAL TABLE t1 USING fts4(a, b, matchinfo=fts3) } +} -test { + faultsim_test_result {0 {}} +} +do_faultsim_test 7.2 -prep { + faultsim_delete_and_reopen +} -body { + execsql { CREATE VIRTUAL TABLE t1 USING fts4(a, b, matchinfo=fs3) } +} -test { + faultsim_test_result {1 {unrecognized matchinfo: fs3}} \ + {1 {vtable constructor failed: t1}} +} +do_faultsim_test 7.3 -prep { + faultsim_delete_and_reopen +} -body { + execsql { CREATE VIRTUAL TABLE t1 USING fts4(a, b, matchnfo=fts3) } +} -test { + faultsim_test_result {1 {unrecognized parameter: matchnfo=fts3}} \ + {1 {vtable constructor failed: t1}} +} + finish_test diff --git a/test/fts3matchinfo.test b/test/fts3matchinfo.test new file mode 100644 index 0000000000..44f111f3c9 --- /dev/null +++ b/test/fts3matchinfo.test @@ -0,0 +1,68 @@ +# 2010 November 02 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for the FTS3 module. The focus +# of this file is tables created with the "matchinfo=fts3" option. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +set testprefix fts3matchinfo + +proc mit {blob} { + set scan(littleEndian) i* + set scan(bigEndian) I* + binary scan $blob $scan($::tcl_platform(byteOrder)) r + return $r +} +db func mit mit + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts4(matchinfo=fts3); + SELECT name FROM sqlite_master WHERE type = 'table'; +} {t1 t1_content t1_segments t1_segdir t1_stat} + +do_execsql_test 1.1 { + INSERT INTO t1(content) VALUES('I wandered lonely as a cloud'); + INSERT INTO t1(content) VALUES('That floats on high o''er vales and hills,'); + INSERT INTO t1(content) VALUES('When all at once I saw a crowd,'); + INSERT INTO t1(content) VALUES('A host, of golden daffodils,'); + SELECT mit(matchinfo(t1)) FROM t1 WHERE t1 MATCH 'I'; +} {{1 1 1 2 2} {1 1 1 2 2}} + +# Now create an FTS4 table that does not specify matchinfo=fts3. The +# %_docsize table is created in this case and the array of integers returned +# by matchinfo() includes the extra data. +# +do_execsql_test 1.2 { + CREATE VIRTUAL TABLE t2 USING fts4; + INSERT INTO t2 SELECT * FROM t1; + SELECT mit(matchinfo(t2)) FROM t2 WHERE t2 MATCH 'I'; +} {{1 1 1 2 2 4 7 6} {1 1 1 2 2 4 7 8}} + +# Test some syntax-error handling. +# +do_catchsql_test 2.0 { + CREATE VIRTUAL TABLE x1 USING fts4(matchinfo=fs3); +} {1 {unrecognized matchinfo: fs3}} +do_catchsql_test 2.1 { + CREATE VIRTUAL TABLE x2 USING fts4(mtchinfo=fts3); +} {1 {unrecognized parameter: mtchinfo=fts3}} + +# Check that with fts3, the "=" character is permitted in column definitions. +# +do_execsql_test 3.1 { + CREATE VIRTUAL TABLE t3 USING fts3(mtchinfo=fts3); + INSERT INTO t3(mtchinfo) VALUES('Beside the lake, beneath the trees'); + SELECT mtchinfo FROM t3; +} {{Beside the lake, beneath the trees}} + +finish_test diff --git a/test/permutations.test b/test/permutations.test index 14cf3abfe6..5576f5bf39 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -168,7 +168,7 @@ test_suite "fts3" -prefix "" -description { fts3defer.test fts3defer2.test fts3e.test fts3expr.test fts3expr2.test fts3near.test fts3query.test fts3shared.test fts3snippet.test - fts3fault.test fts3malloc.test + fts3fault.test fts3malloc.test fts3matchinfo.test }