Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix a problem with fts5 locale=1 tables and UPDATE statements that may affect more than one row. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
70e42f941c0778a04b82655409c7caf4 |
User & Date: | dan 2024-09-07 16:22:22.943 |
Context
2024-09-09
| ||
15:12 | Fix harmless compiler warnings in FTS5. (check-in: aa75e701de user: drh tags: trunk) | |
14:50 | Move the vfstrace extension out of src/ over into ext/misc/ where it belongs. Make it part of the standard build for the CLI. Bring some of the vfstrace output up-to-date. (check-in: 055b97de8d user: drh tags: vfstrace) | |
2024-09-07
| ||
16:22 | Fix a problem with fts5 locale=1 tables and UPDATE statements that may affect more than one row. (check-in: 70e42f941c user: dan tags: trunk) | |
16:04 | Fix an off-by-one error in the routines that bind the special $test_TTT and $int_NNN parameters for fuzz testing. Fix to testing logic only - no changes to the SQLite core. (check-in: 6206b90a4e user: drh tags: trunk) | |
Changes
Changes to ext/fts5/fts5Int.h.
︙ | ︙ | |||
642 643 644 645 646 647 648 649 650 651 652 653 654 655 | int bContent, /* Loaded from content table */ int *pbResetTokenizer, /* OUT: True if ClearLocale() required */ const char **ppText, /* OUT: Pointer to text buffer */ int *pnText /* OUT: Size of (*ppText) in bytes */ ); void sqlite3Fts5ClearLocale(Fts5Config *pConfig); /* ** End of interface to code in fts5.c. **************************************************************************/ /************************************************************************** ** Interface to code in fts5_hash.c. | > > | 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 | int bContent, /* Loaded from content table */ int *pbResetTokenizer, /* OUT: True if ClearLocale() required */ const char **ppText, /* OUT: Pointer to text buffer */ int *pnText /* OUT: Size of (*ppText) in bytes */ ); void sqlite3Fts5ClearLocale(Fts5Config *pConfig); int sqlite3Fts5IsLocaleValue(Fts5Config *pConfig, sqlite3_value *pVal); /* ** End of interface to code in fts5.c. **************************************************************************/ /************************************************************************** ** Interface to code in fts5_hash.c. |
︙ | ︙ |
Changes to ext/fts5/fts5_main.c.
︙ | ︙ | |||
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | fts5_api api; /* User visible part of object (see fts5.h) */ sqlite3 *db; /* Associated database connection */ i64 iNextId; /* Used to allocate unique cursor ids */ Fts5Auxiliary *pAux; /* First in list of all aux. functions */ Fts5TokenizerModule *pTok; /* First in list of all tokenizer modules */ Fts5TokenizerModule *pDfltTok; /* Default tokenizer module */ Fts5Cursor *pCsr; /* First in list of all open cursors */ }; /* ** Each auxiliary function registered with the FTS5 module is represented ** by an object of the following type. All such objects are stored as part ** of the Fts5Global.pAux list. */ struct Fts5Auxiliary { | > > > > > > > > > | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | fts5_api api; /* User visible part of object (see fts5.h) */ sqlite3 *db; /* Associated database connection */ i64 iNextId; /* Used to allocate unique cursor ids */ Fts5Auxiliary *pAux; /* First in list of all aux. functions */ Fts5TokenizerModule *pTok; /* First in list of all tokenizer modules */ Fts5TokenizerModule *pDfltTok; /* Default tokenizer module */ Fts5Cursor *pCsr; /* First in list of all open cursors */ u32 aLocaleHdr[4]; }; /* ** Size of header on fts5_locale() values. And macro to access a buffer ** containing a copy of the header from an Fts5Config pointer. */ #define FTS5_LOCALE_HDR_SIZE sizeof( ((Fts5Global*)0)->aLocaleHdr ) #define FTS5_LOCALE_HDR(pConfig) ((const u8*)(pConfig->pGlobal->aLocaleHdr)) /* ** Each auxiliary function registered with the FTS5 module is represented ** by an object of the following type. All such objects are stored as part ** of the Fts5Global.pAux list. */ struct Fts5Auxiliary { |
︙ | ︙ | |||
243 244 245 246 247 248 249 | #define FTS5CSR_FREE_ZRANK 0x10 #define FTS5CSR_REQUIRE_RESEEK 0x20 #define FTS5CSR_REQUIRE_POSLIST 0x40 #define BitFlagAllTest(x,y) (((x) & (y))==(y)) #define BitFlagTest(x,y) (((x) & (y))!=0) | < < < < < < | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | #define FTS5CSR_FREE_ZRANK 0x10 #define FTS5CSR_REQUIRE_RESEEK 0x20 #define FTS5CSR_REQUIRE_POSLIST 0x40 #define BitFlagAllTest(x,y) (((x) & (y))==(y)) #define BitFlagTest(x,y) (((x) & (y))!=0) /* ** Macros to Set(), Clear() and Test() cursor flags. */ #define CsrFlagSet(pCsr, flag) ((pCsr)->csrflags |= (flag)) #define CsrFlagClear(pCsr, flag) ((pCsr)->csrflags &= ~(flag)) #define CsrFlagTest(pCsr, flag) ((pCsr)->csrflags & (flag)) |
︙ | ︙ | |||
1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 | /* ** Clear any locale configured by an earlier call to fts5SetLocale() or ** sqlite3Fts5ExtractText(). */ void sqlite3Fts5ClearLocale(Fts5Config *pConfig){ fts5SetLocale(pConfig, 0, 0); } /* ** This function is used to extract utf-8 text from an sqlite3_value. This ** is usually done in order to tokenize it. For example, when: ** ** * a value is written to an fts5 table, ** * a value is deleted from an FTS5_CONTENT_NORMAL table, ** * a value containing a query expression is passed to xFilter() ** ** and so on. ** ** This function handles 2 cases: ** ** 1) Ordinary values. The text can be extracted from these using ** sqlite3_value_text(). ** ** 2) Combination text/locale blobs created by fts5_locale(). There ** are several cases for these: ** | > > > > > > > > > > > > > > > > | < < | | | | | | 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 | /* ** Clear any locale configured by an earlier call to fts5SetLocale() or ** sqlite3Fts5ExtractText(). */ void sqlite3Fts5ClearLocale(Fts5Config *pConfig){ fts5SetLocale(pConfig, 0, 0); } /* ** Return true if the value passed as the only argument is an ** fts5_locale() value. */ int sqlite3Fts5IsLocaleValue(Fts5Config *pConfig, sqlite3_value *pVal){ int ret = 0; if( sqlite3_value_type(pVal)==SQLITE_BLOB ){ if( sqlite3_value_bytes(pVal)>FTS5_LOCALE_HDR_SIZE && 0==memcmp(sqlite3_value_blob(pVal), FTS5_LOCALE_HDR(pConfig), 4) ){ ret = 1; } } return ret; } /* ** This function is used to extract utf-8 text from an sqlite3_value. This ** is usually done in order to tokenize it. For example, when: ** ** * a value is written to an fts5 table, ** * a value is deleted from an FTS5_CONTENT_NORMAL table, ** * a value containing a query expression is passed to xFilter() ** ** and so on. ** ** This function handles 2 cases: ** ** 1) Ordinary values. The text can be extracted from these using ** sqlite3_value_text(). ** ** 2) Combination text/locale blobs created by fts5_locale(). There ** are several cases for these: ** ** * Blobs that have the 16-byte header, and ** * Blobs read from the content table of a locale=1 regular ** content table. ** ** The first case above has the 16 byte FTS5_LOCALE_HDR(pConfig) ** header. It is an error if a blob read from the content table of ** an external content table does not have the required header. A blob ** read from the content table of a regular locale=1 table does not ** have the header. This is to save space. ** ** If successful, SQLITE_OK is returned and output parameters (*ppText) ** and (*pnText) are set to point to a buffer containing the extracted utf-8 ** text and its length in bytes, respectively. The buffer is not ** nul-terminated. It has the same lifetime as the sqlite3_value object ** from which it is extracted. ** |
︙ | ︙ | |||
1326 1327 1328 1329 1330 1331 1332 | int *pbResetTokenizer, /* OUT: True if xSetLocale(NULL) required */ const char **ppText, /* OUT: Pointer to text buffer */ int *pnText /* OUT: Size of (*ppText) in bytes */ ){ const char *pText = 0; int nText = 0; int rc = SQLITE_OK; | > > > > > | < | | > > > | > > | < > | < < < | | | | < < < < | | | | | | | | | | | < | 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 | int *pbResetTokenizer, /* OUT: True if xSetLocale(NULL) required */ const char **ppText, /* OUT: Pointer to text buffer */ int *pnText /* OUT: Size of (*ppText) in bytes */ ){ const char *pText = 0; int nText = 0; int rc = SQLITE_OK; /* 0: Do not decode blob ** 1: Decode blob, expect fts5_locale() header ** 2: Decode blob, expect no fts5_locale() header */ int eDecodeBlob = 0; assert( pbResetTokenizer==0 || *pbResetTokenizer==0 ); assert( bContent==0 || pConfig->eContent!=FTS5_CONTENT_NONE ); if( sqlite3_value_type(pVal)==SQLITE_BLOB ){ if( bContent && pConfig->bLocale && pConfig->eContent==FTS5_CONTENT_NORMAL ){ eDecodeBlob = 2; }else if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){ eDecodeBlob = 1; }else if( bContent && pConfig->bLocale ){ return SQLITE_ERROR; } } if( eDecodeBlob ){ const u8 *pBlob = sqlite3_value_blob(pVal); int nBlob = sqlite3_value_bytes(pVal); int nLocale = 0; /* Unless this blob was read from the %_content table of an ** FTS5_CONTENT_NORMAL table, it should have the 4 byte fts5_locale() ** header. Check for this. If it is not found, return an error. */ if( eDecodeBlob==1 ){ pBlob += FTS5_LOCALE_HDR_SIZE; nBlob -= FTS5_LOCALE_HDR_SIZE; } for(nLocale=0; nLocale<nBlob; nLocale++){ if( pBlob[nLocale]==0x00 ) break; } if( nLocale==nBlob || nLocale==0 ){ rc = SQLITE_ERROR; }else{ pText = (const char*)&pBlob[nLocale+1]; nText = nBlob-nLocale-1; if( pbResetTokenizer ){ fts5SetLocale(pConfig, (const char*)pBlob, nLocale); *pbResetTokenizer = 1; } } }else{ pText = (const char*)sqlite3_value_text(pVal); nText = sqlite3_value_bytes(pVal); } |
︙ | ︙ | |||
1962 1963 1964 1965 1966 1967 1968 | bUpdateOrDelete = 1; } /* INSERT or UPDATE */ else{ int eType1 = sqlite3_value_numeric_type(apVal[1]); | < < < > | < < | < | | > > > > > | | > | 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 | bUpdateOrDelete = 1; } /* INSERT or UPDATE */ else{ int eType1 = sqlite3_value_numeric_type(apVal[1]); int ii; for(ii=0; ii<pConfig->nCol; ii++){ sqlite3_value *pVal = apVal[ii+2]; if( sqlite3_value_type(pVal)==SQLITE_BLOB ){ int isLocale = sqlite3Fts5IsLocaleValue(pConfig, pVal); if( pConfig->bLocale ){ if( isLocale==0 && pConfig->abUnindexed[ii]==0 ){ rc = SQLITE_MISMATCH; goto update_out; } }else{ if( isLocale ){ fts5SetVtabError(pTab, "fts5_locale() requires locale=1"); rc = SQLITE_MISMATCH; goto update_out; } } } } if( eType0!=SQLITE_INTEGER ){ /* An INSERT statement. If the conflict-mode is REPLACE, first remove ** the current entry (if any). */ |
︙ | ︙ | |||
2712 2713 2714 2715 2716 2717 2718 | && pConfig->bLocale ){ rc = fts5SeekCursor(pCsr, 0); if( rc==SQLITE_OK ){ /* Load the value into pVal. pVal is a locale/text pair iff: ** ** 1) It is an SQLITE_BLOB, and | | | | > | < | | | 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 | && pConfig->bLocale ){ rc = fts5SeekCursor(pCsr, 0); if( rc==SQLITE_OK ){ /* Load the value into pVal. pVal is a locale/text pair iff: ** ** 1) It is an SQLITE_BLOB, and ** 2) Either the FTS5_LOCALE_HDR header is present, or else the ** value was loaded from an FTS5_CONTENT_NORMAL table. ** ** If condition (1) is met but condition (2) is not, it is an error. */ sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, iCol+1); if( sqlite3_value_type(pVal)==SQLITE_BLOB ){ const u8 *pBlob = (const u8*)sqlite3_value_blob(pVal); int nBlob = sqlite3_value_bytes(pVal); if( pConfig->eContent==FTS5_CONTENT_EXTERNAL ){ if( sqlite3Fts5IsLocaleValue(pConfig, pVal)==0 ){ rc = SQLITE_ERROR; } pBlob += FTS5_LOCALE_HDR_SIZE; nBlob -= FTS5_LOCALE_HDR_SIZE; } if( rc==SQLITE_OK ){ int nLocale = 0; for(nLocale=0; nLocale<nBlob && pBlob[nLocale]!=0x00; nLocale++); if( nLocale==nBlob || nLocale==0 ){ rc = SQLITE_ERROR; }else{ |
︙ | ︙ | |||
2983 2984 2985 2986 2987 2988 2989 | ){ assert( pConfig->eContent!=FTS5_CONTENT_NONE ); if( pConfig->bLocale && sqlite3_value_type(pVal)==SQLITE_BLOB && pConfig->abUnindexed[iCol]==0 ){ | < > | > | | | 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 | ){ assert( pConfig->eContent!=FTS5_CONTENT_NONE ); if( pConfig->bLocale && sqlite3_value_type(pVal)==SQLITE_BLOB && pConfig->abUnindexed[iCol]==0 ){ const u8 *pBlob = sqlite3_value_blob(pVal); int nBlob = sqlite3_value_bytes(pVal); int ii; if( pConfig->eContent==FTS5_CONTENT_EXTERNAL ){ if( nBlob<FTS5_LOCALE_HDR_SIZE || memcmp(pBlob, FTS5_LOCALE_HDR(pConfig), FTS5_LOCALE_HDR_SIZE) ){ sqlite3_result_error_code(pCtx, SQLITE_ERROR); return; }else{ pBlob += FTS5_LOCALE_HDR_SIZE; nBlob -= FTS5_LOCALE_HDR_SIZE; } } for(ii=0; ii<nBlob && pBlob[ii]; ii++); if( ii==0 || ii==nBlob ){ sqlite3_result_error_code(pCtx, SQLITE_ERROR); }else{ |
︙ | ︙ | |||
3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 | zText = (const char*)sqlite3_value_text(apArg[1]); nText = sqlite3_value_bytes(apArg[1]); if( zLocale==0 || zLocale[0]=='\0' ){ sqlite3_result_text(pCtx, zText, nText, SQLITE_TRANSIENT); }else{ u8 *pBlob = 0; u8 *pCsr = 0; int nBlob = 0; | > < < | | | < | 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 | zText = (const char*)sqlite3_value_text(apArg[1]); nText = sqlite3_value_bytes(apArg[1]); if( zLocale==0 || zLocale[0]=='\0' ){ sqlite3_result_text(pCtx, zText, nText, SQLITE_TRANSIENT); }else{ Fts5Global *p = (Fts5Global*)sqlite3_user_data(pCtx); u8 *pBlob = 0; u8 *pCsr = 0; int nBlob = 0; nBlob = FTS5_LOCALE_HDR_SIZE + nLocale + 1 + nText; pBlob = (u8*)sqlite3_malloc(nBlob); if( pBlob==0 ){ sqlite3_result_error_nomem(pCtx); return; } pCsr = pBlob; memcpy(pCsr, (const u8*)p->aLocaleHdr, FTS5_LOCALE_HDR_SIZE); pCsr += FTS5_LOCALE_HDR_SIZE; memcpy(pCsr, zLocale, nLocale); pCsr += nLocale; (*pCsr++) = 0x00; if( zText ) memcpy(pCsr, zText, nText); assert( &pCsr[nText]==&pBlob[nBlob] ); sqlite3_result_blob(pCtx, pBlob, nBlob, sqlite3_free); } } /* ** Return true if zName is the extension on one of the shadow tables used ** by this module. */ |
︙ | ︙ | |||
3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 | pGlobal->db = db; pGlobal->api.iVersion = 3; pGlobal->api.xCreateFunction = fts5CreateAux; pGlobal->api.xCreateTokenizer = fts5CreateTokenizer; pGlobal->api.xFindTokenizer = fts5FindTokenizer; pGlobal->api.xCreateTokenizer_v2 = fts5CreateTokenizer_v2; pGlobal->api.xFindTokenizer_v2 = fts5FindTokenizer_v2; rc = sqlite3_create_module_v2(db, "fts5", &fts5Mod, p, fts5ModuleDestroy); if( rc==SQLITE_OK ) rc = sqlite3Fts5IndexInit(db); if( rc==SQLITE_OK ) rc = sqlite3Fts5ExprInit(pGlobal, db); if( rc==SQLITE_OK ) rc = sqlite3Fts5AuxInit(&pGlobal->api); if( rc==SQLITE_OK ) rc = sqlite3Fts5TokenizerInit(&pGlobal->api); if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db); if( rc==SQLITE_OK ){ | > > > > > > > > > > | 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 | pGlobal->db = db; pGlobal->api.iVersion = 3; pGlobal->api.xCreateFunction = fts5CreateAux; pGlobal->api.xCreateTokenizer = fts5CreateTokenizer; pGlobal->api.xFindTokenizer = fts5FindTokenizer; pGlobal->api.xCreateTokenizer_v2 = fts5CreateTokenizer_v2; pGlobal->api.xFindTokenizer_v2 = fts5FindTokenizer_v2; /* Initialize pGlobal->aLocaleHdr[] to a 128-bit pseudo-random vector. ** The constants below were generated randomly. */ sqlite3_randomness(sizeof(pGlobal->aLocaleHdr), pGlobal->aLocaleHdr); pGlobal->aLocaleHdr[0] ^= 0xF924976D; pGlobal->aLocaleHdr[1] ^= 0x16596E13; pGlobal->aLocaleHdr[2] ^= 0x7C80BEAA; pGlobal->aLocaleHdr[3] ^= 0x9B03A67F; assert( sizeof(pGlobal->aLocaleHdr)==16 ); rc = sqlite3_create_module_v2(db, "fts5", &fts5Mod, p, fts5ModuleDestroy); if( rc==SQLITE_OK ) rc = sqlite3Fts5IndexInit(db); if( rc==SQLITE_OK ) rc = sqlite3Fts5ExprInit(pGlobal, db); if( rc==SQLITE_OK ) rc = sqlite3Fts5AuxInit(&pGlobal->api); if( rc==SQLITE_OK ) rc = sqlite3Fts5TokenizerInit(&pGlobal->api); if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db); if( rc==SQLITE_OK ){ |
︙ | ︙ |
Changes to ext/fts5/fts5_storage.c.
︙ | ︙ | |||
887 888 889 890 891 892 893 | rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0); for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){ sqlite3_value *pVal = apVal[i]; if( sqlite3_value_nochange(pVal) && p->pSavedRow ){ /* This is an UPDATE statement, and column (i-2) was not modified. ** Retrieve the value from Fts5Storage.pSavedRow instead. */ pVal = sqlite3_column_value(p->pSavedRow, i-1); | | > | | | | | | > > | < | > | 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 | rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0); for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){ sqlite3_value *pVal = apVal[i]; if( sqlite3_value_nochange(pVal) && p->pSavedRow ){ /* This is an UPDATE statement, and column (i-2) was not modified. ** Retrieve the value from Fts5Storage.pSavedRow instead. */ pVal = sqlite3_column_value(p->pSavedRow, i-1); }else if( sqlite3_value_type(pVal)==SQLITE_BLOB && pConfig->bLocale ){ assert( pConfig->bLocale ); assert( i>1 ); if( pConfig->abUnindexed[i-2] ){ if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){ /* At attempt to insert an fts5_locale() value into an UNINDEXED ** column. Strip the locale away and just bind the text. */ const char *pText = 0; int nText = 0; rc = sqlite3Fts5ExtractText(pConfig, pVal, 0, 0, &pText, &nText); sqlite3_bind_text(pInsert, i, pText, nText, SQLITE_TRANSIENT); continue; } }else{ const u8 *pBlob = (const u8*)sqlite3_value_blob(pVal); int nBlob = sqlite3_value_bytes(pVal); assert( nBlob>4 ); sqlite3_bind_blob(pInsert, i, pBlob+16, nBlob-16, SQLITE_TRANSIENT); continue; } } rc = sqlite3_bind_value(pInsert, i, pVal); } if( rc==SQLITE_OK ){ sqlite3_step(pInsert); rc = sqlite3_reset(pInsert); |
︙ | ︙ |
Changes to ext/fts5/test/fts5locale.test.
︙ | ︙ | |||
484 485 486 487 488 489 490 | do_catchsql_test 10.2.$tn.3 { INSERT INTO ft(ft) VALUES('rebuild'); } {1 {SQL logic error}} do_catchsql_test 10.2.$tn.4 " SELECT * FROM ft( test_setsubtype($v, 76) ); | | | 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 | do_catchsql_test 10.2.$tn.3 { INSERT INTO ft(ft) VALUES('rebuild'); } {1 {SQL logic error}} do_catchsql_test 10.2.$tn.4 " SELECT * FROM ft( test_setsubtype($v, 76) ); " {1 {fts5: syntax error near ""}} do_execsql_test 10.2.$tn.5 { INSERT INTO ft(rowid, x) VALUES(1, 'hello world'); } if {"%DETAIL%"!="full"} { do_catchsql_test 10.2.$tn.6 { |
︙ | ︙ | |||
519 520 521 522 523 524 525 | do_execsql_test 10.2.$tn.10 { DELETE FROM x1; INSERT INTO x1(ii, x) VALUES(1, 'hello world'); } do_catchsql_test 10.2.$tn.11 " INSERT INTO ft(ft, rowid, x) VALUES('delete', 1, test_setsubtype($v,76) ) | | | | 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 | do_execsql_test 10.2.$tn.10 { DELETE FROM x1; INSERT INTO x1(ii, x) VALUES(1, 'hello world'); } do_catchsql_test 10.2.$tn.11 " INSERT INTO ft(ft, rowid, x) VALUES('delete', 1, test_setsubtype($v,76) ) " {0 {}} do_catchsql_test 10.2.$tn.12 " INSERT INTO ft(rowid, x) VALUES(2, test_setsubtype($v,76) ) " {1 {datatype mismatch}} do_execsql_test 10.2.$tn.13 { INSERT INTO ft2(rowid, x) VALUES(1, 'hello world'); } do_execsql_test 10.2.$tn.14 "UPDATE ft2_content SET c0=$v" do_catchsql_test 10.2.$tn.15 { |
︙ | ︙ | |||
658 659 660 661 662 663 664 665 666 667 | FROM ft('one AND three') ORDER BY rowid } {1 {non-integer argument passed to function fts5_get_locale()}} do_catchsql_test 13.2.7 { SELECT quote(fts5_get_locale(ft, 0.0)), quote(fts5_get_locale(ft, 1)) FROM ft('one AND three') ORDER BY rowid } {1 {non-integer argument passed to function fts5_get_locale()}} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > | 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 | FROM ft('one AND three') ORDER BY rowid } {1 {non-integer argument passed to function fts5_get_locale()}} do_catchsql_test 13.2.7 { SELECT quote(fts5_get_locale(ft, 0.0)), quote(fts5_get_locale(ft, 1)) FROM ft('one AND three') ORDER BY rowid } {1 {non-integer argument passed to function fts5_get_locale()}} #------------------------------------------------------------------------- # Check that UPDATE statements that may affect more than one row work. # reset_db do_execsql_test 14.1 { CREATE VIRTUAL TABLE ft USING fts5(a, b, locale=1); } do_execsql_test 14.2 { INSERT INTO ft VALUES('hello', 'world'); } do_execsql_test 14.3 { UPDATE ft SET b = fts5_locale('en_AU', 'world'); } do_catchsql_test 14.4 { INSERT INTO ft VALUES(X'abcd', X'1234'); } {1 {datatype mismatch}} do_execsql_test 14.4 { SELECT * FROM ft } {hello world} finish_test |
Changes to test/fts3corrupt4.test.
︙ | ︙ | |||
4400 4401 4402 4403 4404 4405 4406 | WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x%1 FROM c WHERE x<599237) INSERT INTO t1( a ) SELECT randomblob(3000) FROM t2 ; } {0 {}} do_catchsql_test 25.6 { INSERT INTO t1(t1) SELECT x FROM t2; INSERT INTO t1(t1) SELECT x FROM t2; | | | 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 | WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x%1 FROM c WHERE x<599237) INSERT INTO t1( a ) SELECT randomblob(3000) FROM t2 ; } {0 {}} do_catchsql_test 25.6 { INSERT INTO t1(t1) SELECT x FROM t2; INSERT INTO t1(t1) SELECT x FROM t2; } {0 {}} #------------------------------------------------------------------------- reset_db do_test 26.0 { sqlite3 db {} db deserialize [decode_hexdb { .open --hexdb |
︙ | ︙ |