};
void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
+ va_list ap;
+ va_start(ap, zFmt);
if( pParse->rc==SQLITE_OK ){
- va_list ap;
- va_start(ap, zFmt);
pParse->zErr = sqlite3_vmprintf(zFmt, ap);
- va_end(ap);
pParse->rc = SQLITE_ERROR;
}
+ va_end(ap);
}
static int fts5ExprIsspace(char t){
Fts5Expr **ppNew
){
int rc = SQLITE_OK; /* Return code */
- Fts5ExprPhrase *pOrig = 0; /* The phrase extracted from pExpr */
- int i; /* Used to iterate through phrase terms */
-
- /* Components of the new expression object */
- Fts5Expr *pNew;
- Fts5ExprPhrase **apPhrase;
- Fts5ExprNode *pNode;
- Fts5ExprNearset *pNear;
- Fts5ExprPhrase *pCopy;
+ Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */
+ Fts5ExprPhrase *pCopy; /* Copy of pOrig */
+ Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
pOrig = pExpr->apExprPhrase[iPhrase];
pCopy = (Fts5ExprPhrase*)fts5ExprMalloc(&rc,
sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * pOrig->nTerm
);
- pNew = (Fts5Expr*)fts5ExprMalloc(&rc, sizeof(Fts5Expr));
- apPhrase = (Fts5ExprPhrase**)fts5ExprMalloc(&rc, sizeof(Fts5ExprPhrase*));
- pNode = (Fts5ExprNode*)fts5ExprMalloc(&rc, sizeof(Fts5ExprNode));
- pNear = (Fts5ExprNearset*)fts5ExprMalloc(&rc,
- sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*)
- );
+ if( pCopy ){
+ int i; /* Used to iterate through phrase terms */
+ Fts5ExprPhrase **apPhrase;
+ Fts5ExprNode *pNode;
+ Fts5ExprNearset *pNear;
+
+ pNew = (Fts5Expr*)fts5ExprMalloc(&rc, sizeof(Fts5Expr));
+ apPhrase = (Fts5ExprPhrase**)fts5ExprMalloc(&rc, sizeof(Fts5ExprPhrase*));
+ pNode = (Fts5ExprNode*)fts5ExprMalloc(&rc, sizeof(Fts5ExprNode));
+ pNear = (Fts5ExprNearset*)fts5ExprMalloc(&rc,
+ sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*)
+ );
- for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
- pCopy->aTerm[i].zTerm = fts5ExprStrdup(&rc, pOrig->aTerm[i].zTerm);
- pCopy->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
- }
+ for(i=0; i<pOrig->nTerm; i++){
+ pCopy->aTerm[i].zTerm = fts5ExprStrdup(&rc, pOrig->aTerm[i].zTerm);
+ pCopy->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
+ }
- if( rc==SQLITE_OK ){
- /* All the allocations succeeded. Put the expression object together. */
- pNew->pIndex = pExpr->pIndex;
- pNew->pRoot = pNode;
- pNew->nPhrase = 1;
- pNew->apExprPhrase = apPhrase;
- pNew->apExprPhrase[0] = pCopy;
-
- pNode->eType = FTS5_STRING;
- pNode->pNear = pNear;
-
- pNear->iCol = -1;
- pNear->nPhrase = 1;
- pNear->apPhrase[0] = pCopy;
-
- pCopy->nTerm = pOrig->nTerm;
- pCopy->pNode = pNode;
- }else{
- /* At least one allocation failed. Free them all. */
- if( pCopy ){
+ if( rc==SQLITE_OK ){
+ /* All the allocations succeeded. Put the expression object together. */
+ pNew->pIndex = pExpr->pIndex;
+ pNew->pRoot = pNode;
+ pNew->nPhrase = 1;
+ pNew->apExprPhrase = apPhrase;
+ pNew->apExprPhrase[0] = pCopy;
+
+ pNode->eType = FTS5_STRING;
+ pNode->pNear = pNear;
+
+ pNear->iCol = -1;
+ pNear->nPhrase = 1;
+ pNear->apPhrase[0] = pCopy;
+
+ pCopy->nTerm = pOrig->nTerm;
+ pCopy->pNode = pNode;
+ }else{
+ /* At least one allocation failed. Free them all. */
for(i=0; i<pOrig->nTerm; i++){
sqlite3_free(pCopy->aTerm[i].zTerm);
}
/* If the aStatic[] array is not large enough, allocate a large array
** using sqlite3_malloc(). This approach could be improved upon. */
if( pNear->nPhrase>(sizeof(aStatic) / sizeof(aStatic[0])) ){
- int nByte = sizeof(Fts5LookaheadReader) * pNear->nPhrase;
+ int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
a = (Fts5NearTrimmer*)sqlite3_malloc(nByte);
if( !a ) return SQLITE_NOMEM;
memset(a, 0, nByte);
/* Advance the iterators until they all point to the same rowid */
rc = fts5ExprNearNextRowidMatch(pExpr, pNode, bFromValid, iFrom);
- if( pNode->bEof || rc!=SQLITE_OK ) break;
+ if( rc!=SQLITE_OK || pNode->bEof ) break;
/* Check that each phrase in the nearset matches the current row.
** Populate the pPhrase->poslist buffers at the same time. If any
#
#*************************************************************************
#
+# Test the fts5 expression parser directly using the fts5_expr() SQL
+# test function.
+#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5ea
8 {one OR two AND three} {"one" OR ("two" AND "three")}
9 {NEAR(one two)} {NEAR("one" "two", 10)}
10 {NEAR("one three"* two, 5)} {NEAR("one" + "three" * "two", 5)}
+ 11 {a OR b NOT c} {"a" OR ("b" NOT "c")}
+ 12 "\x20one\x20two\x20three" {("one" AND "two") AND "three"}
+ 13 "\x09one\x0Atwo\x0Dthree" {("one" AND "two") AND "three"}
+ 14 {"abc""def"} {"abc" + "def"}
} {
do_execsql_test 1.$tn {SELECT fts5_expr($expr)} [list $res]
}
do_execsql_test 2.$tn {SELECT fts5_expr($expr, 'c1', 'c2')} [list $res]
}
-breakpoint
foreach {tn expr err} {
1 {AND} {fts5: syntax error near "AND"}
2 {abc def AND} {fts5: syntax error near ""}
6 {(a OR b) NOT c)} {fts5: syntax error near ")"}
7 {nosuch: a nosuch2: b} {no such column: nosuch}
8 {addr: a nosuch2: b} {no such column: nosuch2}
+ 9 {NOT} {fts5: syntax error near "NOT"}
+ 10 {a AND "abc} {unterminated string}
} {
do_catchsql_test 3.$tn {SELECT fts5_expr($expr, 'name', 'addr')} [list 1 $err]
}
-# do_syntax_error_test 1.0 {NOT} {syntax error near "NOT"}
-
-
-
-# do_catchsql_test 1.1 {
- # SELECT fts5_expr('a OR b NOT c')
-#} {0 {"a" OR "b" NOT "c"}}
-
-
-#do_execsql_test 1.0 { SELECT fts5_expr('a') } {{"a"}}
finish_test
faultsim_test_result "0 {10-$::str {a b c}}"
}
-}
-
#-------------------------------------------------------------------------
# OOM errors within auxiliary functions.
faultsim_test_result {0 {0 2 7}} {1 SQLITE_NOMEM}
}
+#-------------------------------------------------------------------------
+# OOM error when querying for a phrase with many tokens.
+#
+reset_db
+do_execsql_test 7.0 {
+ CREATE VIRTUAL TABLE tt USING fts5(x, y);
+ INSERT INTO tt VALUES('f b g b c b', 'f a d c c b'); -- 1
+ INSERT INTO tt VALUES('d a e f e d', 'f b b d e e'); -- 2
+ INSERT INTO tt VALUES('f b g a d c', 'e f c f a d'); -- 3
+ INSERT INTO tt VALUES('f f c d g f', 'f a e b g b'); -- 4
+ INSERT INTO tt VALUES('a g b d a g', 'e g a e a c'); -- 5
+ INSERT INTO tt VALUES('c d b d e f', 'f g e g e e'); -- 6
+ INSERT INTO tt VALUES('e g f f b c', 'f c e f g f'); -- 7
+ INSERT INTO tt VALUES('e g c f c e', 'f e e a f g'); -- 8
+ INSERT INTO tt VALUES('e a e b e e', 'd c c f f f'); -- 9
+ INSERT INTO tt VALUES('f a g g c c', 'e g d g c e'); -- 10
+ INSERT INTO tt VALUES('c d b a e f', 'f g e h e e'); -- 11
+}
+
+do_faultsim_test 7.2 -faults oom-* -body {
+ db eval { SELECT rowid FROM tt WHERE tt MATCH 'f+g+e+g+e+e' }
+} -test {
+ faultsim_test_result {0 6} {1 SQLITE_NOMEM}
+}
+
+do_faultsim_test 7.3 -faults oom-* -body {
+ db eval { SELECT rowid FROM tt WHERE tt MATCH 'NEAR(a b c d e f)' }
+} -test {
+ faultsim_test_result {0 11} {1 SQLITE_NOMEM}
+}
+
+}
+
+#-------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 8.0 {
+ CREATE VIRTUAL TABLE tt USING fts5(x);
+ INSERT INTO tt(tt, rank) VALUES('pgsz', 32);
+ BEGIN;
+ INSERT INTO tt(rowid, x) VALUES(1, 'a b c d x x');
+ WITH ii(i) AS (SELECT 2 UNION ALL SELECT i+1 FROM ii WHERE i<99)
+ INSERT INTO tt(rowid, x) SELECT i, 'a b c x x d' FROM ii;
+ INSERT INTO tt(rowid, x) VALUES(100, 'a b c d x x');
+ COMMIT;
+}
+
+do_faultsim_test 8.1 -faults oom-t* -body {
+ db eval { SELECT rowid FROM tt WHERE tt MATCH 'NEAR(a b c d, 2)' }
+} -test {
+ faultsim_test_result {0 {1 100}} {1 SQLITE_NOMEM}
+}
+
+do_faultsim_test 8.2 -faults oom-t* -body {
+ db eval { SELECT count(*) FROM tt WHERE tt MATCH 'a OR d' }
+} -test {
+ faultsim_test_result {0 100} {1 SQLITE_NOMEM}
+}
-C Improve\stest\scoverage\sof\sfts5.c.
-D 2015-05-01T12:14:23.640
+C Further\simprovements\sto\stest\scoverage\sof\sfts5\scode.
+D 2015-05-01T20:38:57.153
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 31b38b9da2e4b36f54a013bd71a5c3f6e45ca78f
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F ext/fts5/fts5_aux.c d53f00f31ad615ca4f139dd8751f9041afa00971
F ext/fts5/fts5_buffer.c 8c8cfe7f09ca2767ab53ea883f9a0af0edb6bbae
F ext/fts5/fts5_config.c ecbbd5163758a958106867051892e0dfecf68b5c
-F ext/fts5/fts5_expr.c 663c75dfdb1bfd8809d696357d7b55f507815098
+F ext/fts5/fts5_expr.c e2005ba7823f4ac51d46a8e5aaa1ff66c701b32e
F ext/fts5/fts5_hash.c 29d8b0668727863cc1f1efa65efe4dd78635b016
F ext/fts5/fts5_index.c de588982b0237b1605d6c37afd115b34c95c3da1
F ext/fts5/fts5_storage.c ef60fc9dcc4e274f9589165e26833173c273ae18
F ext/fts5/test/fts5corrupt2.test 494111fd4f2dab36499cf97718eaba1f7c11e9d0
F ext/fts5/test/fts5dlidx.test 748a84ceb74a4154725096a26dfa854260b0182f
F ext/fts5/test/fts5doclist.test 635b80ac785627841a59c583bac702b55d49fdc5
-F ext/fts5/test/fts5ea.test 04695560a444fcc00c3c4f27783bdcfbf71f030c
+F ext/fts5/test/fts5ea.test 7cc498993c16849bb866dbdfb008d91a29f9870b
F ext/fts5/test/fts5eb.test 728a1f23f263548f5c29b29dfb851b5f2dbe723e
F ext/fts5/test/fts5fault1.test ed71717a479bef32d05f02d9c48691011d160d4d
F ext/fts5/test/fts5fault2.test 26c3d70648f691e2cc9391e14bbc11a973656383
F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3
-F ext/fts5/test/fts5fault4.test 087066bae36f41227eb85968a2436c8a9c960501
+F ext/fts5/test/fts5fault4.test 4090af395d8d3342c0a0b27349dd71eb7cc6262d
F ext/fts5/test/fts5full.test 0924bdca5416a242103239ace79c6f5aa34bab8d
F ext/fts5/test/fts5hash.test adb7b0442cc1c77c507f07e16d11490486e75dfa
F ext/fts5/test/fts5merge.test 453a0717881aa7784885217b2040f3f275caff03
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P c1f07a3aa98eac87e2747527d15e5e5562221ceb
-R 67c24377157269f998af5007c163ea4c
+P add4f4681c648dcbecaa68d08f7b2f4e6d63003c
+R 58de859125935eeaf7ecede3ffbb5a07
U dan
-Z 082bd0388383a4ef8c727daa5b60df05
+Z fc00d731e9356a3f17b66c35cad599ad
-add4f4681c648dcbecaa68d08f7b2f4e6d63003c
\ No newline at end of file
+d4331943dff259380c4025bb740d8aba6972d351
\ No newline at end of file