Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Improve the error message returned when fts5 finds a row is missing from its content table. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
9b1afd4acb8cf9738154e921dcb074d8 |
User & Date: | dan 2024-07-08 16:01:49.563 |
Context
2024-07-08
| ||
17:39 | Fix a use-after-free that could occur following an OOM introduced by [d8cedbe0]. (check-in: 4fabfacfcf user: dan tags: trunk) | |
16:01 | Improve the error message returned when fts5 finds a row is missing from its content table. (check-in: 9b1afd4acb user: dan tags: trunk) | |
2024-07-05
| ||
13:55 | Use a mini Bloom filter to help reduce the number of pointless searches for prior SubrtnSig objects when generating code for IN operators with subqueries as their right operand. (check-in: d8cedbe055 user: drh tags: trunk) | |
Changes
Changes to ext/fts5/fts5_main.c.
︙ | ︙ | |||
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 | int eType = sqlite3_value_numeric_type(pVal); if( eType==SQLITE_INTEGER ){ return sqlite3_value_int64(pVal); } } return iDefault; } /* ** This is the xFilter interface for the virtual table. See ** the virtual table xFilter method documentation for additional ** information. ** ** There are three possible query strategies: | > > > > > > > > > > > > | 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 | int eType = sqlite3_value_numeric_type(pVal); if( eType==SQLITE_INTEGER ){ return sqlite3_value_int64(pVal); } } return iDefault; } /* ** Set the error message on the virtual table passed as the first argument. */ static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){ va_list ap; /* ... printf arguments */ va_start(ap, zFormat); sqlite3_free(p->p.base.zErrMsg); p->p.base.zErrMsg = sqlite3_vmprintf(zFormat, ap); va_end(ap); } /* ** This is the xFilter interface for the virtual table. See ** the virtual table xFilter method documentation for additional ** information. ** ** There are three possible query strategies: |
︙ | ︙ | |||
1388 1389 1390 1391 1392 1393 1394 | rc = fts5CursorFirstSorted(pTab, pCsr, bDesc); }else{ pCsr->ePlan = FTS5_PLAN_MATCH; rc = fts5CursorFirst(pTab, pCsr, bDesc); } } }else if( pConfig->zContent==0 ){ | < | < | 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 | rc = fts5CursorFirstSorted(pTab, pCsr, bDesc); }else{ pCsr->ePlan = FTS5_PLAN_MATCH; rc = fts5CursorFirst(pTab, pCsr, bDesc); } } }else if( pConfig->zContent==0 ){ fts5SetVtabError(pTab,"%s: table does not support scanning",pConfig->zName); rc = SQLITE_ERROR; }else{ /* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup ** by rowid (ePlan==FTS5_PLAN_ROWID). */ pCsr->ePlan = (pRowidEq ? FTS5_PLAN_ROWID : FTS5_PLAN_SCAN); rc = sqlite3Fts5StorageStmt( pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->p.base.zErrMsg |
︙ | ︙ | |||
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 | *pRowid = 0; }else{ *pRowid = fts5CursorRowid(pCsr); } return SQLITE_OK; } /* ** If the cursor requires seeking (bSeekRequired flag is set), seek it. ** Return SQLITE_OK if no error occurs, or an SQLite error code otherwise. ** ** If argument bErrormsg is true and an error occurs, an error message may ** be left in sqlite3_vtab.zErrMsg. | > | 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 | *pRowid = 0; }else{ *pRowid = fts5CursorRowid(pCsr); } return SQLITE_OK; } /* ** If the cursor requires seeking (bSeekRequired flag is set), seek it. ** Return SQLITE_OK if no error occurs, or an SQLite error code otherwise. ** ** If argument bErrormsg is true and an error occurs, an error message may ** be left in sqlite3_vtab.zErrMsg. |
︙ | ︙ | |||
1501 1502 1503 1504 1505 1506 1507 1508 | if( rc==SQLITE_ROW ){ rc = SQLITE_OK; CsrFlagClear(pCsr, FTS5CSR_REQUIRE_CONTENT); }else{ rc = sqlite3_reset(pCsr->pStmt); if( rc==SQLITE_OK ){ rc = FTS5_CORRUPT; }else if( pTab->pConfig->pzErrmsg ){ | > > > > > | < < < < < < < < | 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 | if( rc==SQLITE_ROW ){ rc = SQLITE_OK; CsrFlagClear(pCsr, FTS5CSR_REQUIRE_CONTENT); }else{ rc = sqlite3_reset(pCsr->pStmt); if( rc==SQLITE_OK ){ rc = FTS5_CORRUPT; fts5SetVtabError((Fts5FullTable*)pTab, "fts5: missing row %lld from content table %s", fts5CursorRowid(pCsr), pTab->pConfig->zContent ); }else if( pTab->pConfig->pzErrmsg ){ fts5SetVtabError((Fts5FullTable*)pTab, "%s", sqlite3_errmsg(pTab->pConfig->db) ); } } } return rc; } /* ** This function is called to handle an FTS INSERT command. In other words, ** an INSERT statement of the form: ** ** INSERT INTO fts(fts) VALUES($pCmd) ** INSERT INTO fts(fts, rank) VALUES($pCmd, $pVal) ** |
︙ | ︙ | |||
2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 | pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId); if( pCsr==0 || pCsr->ePlan==0 ){ char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId); sqlite3_result_error(context, zErr, -1); sqlite3_free(zErr); }else{ fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]); } } /* ** Given cursor id iId, return a pointer to the corresponding Fts5Table ** object. Or NULL If the cursor id does not exist. | > > > | 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 | pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId); if( pCsr==0 || pCsr->ePlan==0 ){ char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId); sqlite3_result_error(context, zErr, -1); sqlite3_free(zErr); }else{ sqlite3_vtab *pTab = pCsr->base.pVtab; fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]); sqlite3_free(pTab->zErrMsg); pTab->zErrMsg = 0; } } /* ** Given cursor id iId, return a pointer to the corresponding Fts5Table ** object. Or NULL If the cursor id does not exist. |
︙ | ︙ |
Changes to ext/fts5/test/fts5content.test.
︙ | ︙ | |||
324 325 326 327 328 329 330 331 | db func text_value text_value do_execsql_test 8.3.1 { SELECT * FROM t1 } {one two} do_execsql_test 8.3.2 { INSERT INTO t1(t1) VALUES('rebuild') } do_execsql_test 8.3.3 { SELECT * FROM t1 WHERE rowid=1 } {one} do_execsql_test 8.3.4 { SELECT rowid FROM t1('two') } {2} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 | db func text_value text_value do_execsql_test 8.3.1 { SELECT * FROM t1 } {one two} do_execsql_test 8.3.2 { INSERT INTO t1(t1) VALUES('rebuild') } do_execsql_test 8.3.3 { SELECT * FROM t1 WHERE rowid=1 } {one} do_execsql_test 8.3.4 { SELECT rowid FROM t1('two') } {2} #------------------------------------------------------------------------- reset_db do_execsql_test 9.1 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b); INSERT INTO t1 VALUES(1, 'one two three'); INSERT INTO t1 VALUES(2, 'one two three'); CREATE VIRTUAL TABLE ft USING fts5(b, content=t1, content_rowid=a); INSERT INTO ft(ft) VALUES('rebuild'); } do_execsql_test 9.2 { SELECT rowid, b FROM ft('two'); } { 1 {one two three} 2 {one two three} } do_execsql_test 9.3 { DELETE FROM t1 WHERE a=2; } do_catchsql_test 9.4 { SELECT rowid FROM ft('two'); } {0 {1 2}} do_catchsql_test 9.5 { SELECT * FROM ft('two'); } {1 {fts5: missing row 2 from content table 'main'.'t1'}} fts5_aux_test_functions db do_catchsql_test 9.6 { SELECT rowid, fts5_columntext(ft, 0) FROM ft('two'); } {1 SQLITE_CORRUPT_VTAB} finish_test |
Changes to ext/fts5/test/fts5corrupt.test.
︙ | ︙ | |||
95 96 97 98 99 100 101 | do_execsql_test 3.1 { SELECT * FROM t3 WHERE t3 MATCH 'o' } {{one o} {three o} {five o}} sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 3.1 { DELETE FROM t3_content WHERE rowid = 3; SELECT * FROM t3 WHERE t3 MATCH 'o'; | | | 95 96 97 98 99 100 101 102 103 104 | do_execsql_test 3.1 { SELECT * FROM t3 WHERE t3 MATCH 'o' } {{one o} {three o} {five o}} sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 3.1 { DELETE FROM t3_content WHERE rowid = 3; SELECT * FROM t3 WHERE t3 MATCH 'o'; } {1 {fts5: missing row 3 from content table 'main'.'t3_content'}} finish_test |
Changes to ext/fts5/test/fts5corrupt3.test.
︙ | ︙ | |||
4263 4264 4265 4266 4267 4268 4269 | | 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb | 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 uild....optimize | end crash-ae135cb10977c7.db }]} {} do_catchsql_test 35.1 { SELECT * FROM t1 WHERE t1 MATCH 'e*'; | | | 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 | | 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb | 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 uild....optimize | end crash-ae135cb10977c7.db }]} {} do_catchsql_test 35.1 { SELECT * FROM t1 WHERE t1 MATCH 'e*'; } {1 {fts5: missing row 14 from content table 'main'.'t1_content'}} #------------------------------------------------------------------------- reset_db do_test 36.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 24576 pagesize 4096 filename crash-a6651222df1bd1.db |
︙ | ︙ |