diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index e4b91a82ab..5246566e06 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -4950,8 +4950,15 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ } if( SQLITE_OK==rc && pCsr->nSegment==nSeg && SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter)) - && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr)) ){ + int bEmpty = 0; + rc = sqlite3Fts3SegReaderStep(p, pCsr); + if( rc==SQLITE_OK ){ + bEmpty = 1; + }else if( rc!=SQLITE_ROW ){ + sqlite3Fts3SegReaderFinish(pCsr); + break; + } if( bUseHint && iIdx>0 ){ const char *zKey = pCsr->zTerm; int nKey = pCsr->nTerm; @@ -4962,11 +4969,13 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ if( rc==SQLITE_OK && pWriter->nLeafEst ){ fts3LogMerge(nSeg, iAbsLevel); - do { - rc = fts3IncrmergeAppend(p, pWriter, pCsr); - if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr); - if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK; - }while( rc==SQLITE_ROW ); + if( bEmpty==0 ){ + do { + rc = fts3IncrmergeAppend(p, pWriter, pCsr); + if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr); + if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK; + }while( rc==SQLITE_ROW ); + } /* Update or delete the input segments */ if( rc==SQLITE_OK ){ diff --git a/manifest b/manifest index 685e339225..ec1a5b3065 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Get\sgenerated\scolumns\sworking\sfor\sWITHOUT\sROWID\stables. -D 2019-10-18T17:42:47.815 +C Merge\strunk\senhancements\sinto\sthe\sgenerated-columns\sbranch. +D 2019-10-18T17:47:47.787 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -99,7 +99,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 F ext/fts3/fts3_unicode.c 4b9af6151c29b35ed09574937083cece7c31e911f69615e168a39677569b684d F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f -F ext/fts3/fts3_write.c 5e35b790778039aaa1267e0ad557c2518274fff9d97ea09301ecb6371dbc6118 +F ext/fts3/fts3_write.c aef93982656ef63851470a86c8f145d54dd4ebd9341f7493aefe45ddff0ce600 F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73 @@ -486,7 +486,7 @@ F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 6a9f9899469e3da1c2e50677fe34597c8315c7daa14f1b907872e598f40b7f13 +F src/insert.c 1e565be06343e9d24a6c4f82023e5b0ffb0358c41fb4fb28f95fe50c9f9727b4 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 4ddc65ae13c0d93db0ceedc8b14a28c8c260513448b0eb8c5a2ac375e3b6a85d F src/main.c 3e01f6a1c96643381b5f9d79e4ff7f2520bc5712197746fb0852283e78cccf66 @@ -526,7 +526,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 2160146697e6e0ba251b5a954e16f542b6e684fb4778cec2994094ab401ef996 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 F src/select.c 7ef05eeb7f686f84dd1428cbdca280c898915bbf56e1ea97bd42ecc070af78d3 -F src/shell.c.in d70bcf630c4073eaa994fa74be98886c781918e794cb8b562be8df10f018e274 +F src/shell.c.in 3093bdf5eedd91da08f0268f1442aa510a60798c9441868149ddbecdf8bcaa79 F src/sqlite.h.in 5725a6b20190a1e8d662077a1c1c8ea889ad7be90dd803f914c2de226f5fe6ab F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h cef696ce3293242c67b2339763608427bf72ee66f1f3a05389ac2a7b46001c31 @@ -589,10 +589,10 @@ F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a9 F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c -F src/tokenize.c d3615f0cbe4db5949503bf5916f3cd4fa5de855d5b4ef560f3b6dd5629423a1e +F src/tokenize.c 7b17f6e2f20f6cbcb0b215025a86b7457c38451fc7622f705e553d7a488c572d F src/treeview.c fddeb413159c3eeeaea3f496172f121cf3695606c461dc4e6dcee51417952df5 F src/trigger.c 845ccc08f60716c58aa28fe6470385c18ef8c4e1d88c93dcf449bc13d464eb2e -F src/update.c c9020ecd59e80836a1bfccc406af3658a18bada4f17319fcc791db6643cbcac0 +F src/update.c ca754bbcb5662184bf5face4b67686bed8f53a36cf3def87cbb238deb1086b9b F src/upsert.c 710c91bb13e3c3fed5b6fe17cb13e09560bdd003ad8b8c51e6b16c80cfc48b10 F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507 F src/util.c 10d910e04a4f3842042485e0df01a484f57f912c10b60b3a09ccddd5019bd138 @@ -981,7 +981,7 @@ F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269 F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d F test/fts4langid.test 2168ba330af34f8a1c8832de0aab4c4b6fa195a16419c9c0c8aad59ceb6ff714 F test/fts4lastrowid.test 185835895948d5325c7710649824042373b2203149abe8024a9319d25234dfd7 -F test/fts4merge.test 1096e30b58ad616bd502141bfe5bfe4c3a518df89e958d41a5ed1ce322369b9c +F test/fts4merge.test e2b2ec21e287d54ec09824ccfb41e66896eeca568fc818ba0e0eb2efd94c35d2 F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891 F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0 F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b @@ -1060,7 +1060,7 @@ F test/indexexpr1.test c26c8b352311c1deb30642cd0379e5cb94e416c7e9e0885e92d9e0155 F test/indexexpr2.test b580f378423bca443ffab47ada677203cfcf8a60f48a8aa20065f27c8f7739b5 F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811 F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 -F test/insert.test 72004f6a900a25bd3f1ce9a72e73d02749644666a8ce6d6d2dba061137e5aa63 +F test/insert.test c0e1b23f6359e06316b3a49f7747c5d65c0b6473619011e4fb86f6801edba6df F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208 F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30 F test/insert4.test 7802ada6ba8738661b9f6c0e26858d3375b40cc7180289fd350644cd7a08fec9 @@ -1180,7 +1180,7 @@ F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1 F test/nockpt.test 8c43b25af63b0bd620cf1b003529e37b6f1dc53bd22690e96a1bd73f78dde53a F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e -F test/normalize.test 422027884ffb67ebba32bb78487c67cf67643496d19c077b07044bdba071a3f6 +F test/normalize.test f23b6c5926c59548635fcf39678ac613e726121e073dd902a3062fbb83903b72 F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161 F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934 @@ -1847,7 +1847,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e8426acb94179ff49549aced6ea3c26c49ba4761c2f414fa1772d6a031edc79d -R a1d17655d7716207219f9bae89301b1f +P 9f409649ec4282a47f0a8b079b419f1922e0c24779b297f477ced168d5b7910d 9dc0d34586eebf6705d9bd81494c417ac76707b8625d1ff99eda18b4ca2d8a50 +R 8ebd80e22c07677946c96a01428911bf U drh -Z 8a3f73b128c9189e66135d5ce5fb6bf2 +Z 73fa86e472de993d3352f53eb78454b7 diff --git a/manifest.uuid b/manifest.uuid index 3afd9384c6..5cd80d372b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9f409649ec4282a47f0a8b079b419f1922e0c24779b297f477ced168d5b7910d \ No newline at end of file +85bc4524d76999080faa4474e8880d2b6a2ac3a7f6a76239af4de1a42f8138c8 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index d2e1efd5db..fe275d5a01 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1680,6 +1680,8 @@ void sqlite3GenerateConstraintChecks( sqlite3MultiWrite(pParse); sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, regNewData, 1, 0, OE_Replace, 1, -1); + sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); + sqlite3RowidConstraint(pParse, OE_Abort, pTab); }else{ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK assert( HasRowid(pTab) ); @@ -1934,16 +1936,23 @@ void sqlite3GenerateConstraintChecks( } default: { Trigger *pTrigger = 0; + int bRetryConstraintCheck = 0; assert( onError==OE_Replace ); if( db->flags&SQLITE_RecTriggers ){ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); } if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ sqlite3MultiWrite(pParse); + bRetryConstraintCheck = 1; } sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, regR, nPkField, 0, OE_Replace, (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur); + if( bRetryConstraintCheck ){ + sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, + regIdx, pIdx->nKeyCol); VdbeCoverage(v); + sqlite3UniqueConstraint(pParse, OE_Abort, pIdx); + } seenReplace = 1; break; } diff --git a/src/shell.c.in b/src/shell.c.in index 7f82675e35..f2473ce155 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -7758,10 +7758,19 @@ static int do_meta_command(char *zLine, ShellState *p){ char *zCollist = 0; sqlite3_stmt *pStmt; int tnum = 0; + int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */ + int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */ int i; if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){ utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n" " .imposter off\n"); + /* Also allowed, but not documented: + ** + ** .imposter TABLE IMPOSTER + ** + ** where TABLE is a WITHOUT ROWID table. In that case, the + ** imposter is another WITHOUT ROWID table with the columns in + ** storage order. */ rc = 1; goto meta_command_exit; } @@ -7770,19 +7779,22 @@ static int do_meta_command(char *zLine, ShellState *p){ sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1); goto meta_command_exit; } - zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master" - " WHERE name='%q' AND type='index'", azArg[1]); + zSql = sqlite3_mprintf( + "SELECT rootpage, 0 FROM sqlite_master" + " WHERE name='%q' AND type='index'" + "UNION ALL " + "SELECT rootpage, 1 FROM sqlite_master" + " WHERE name='%q' AND type='table'" + " AND sql LIKE '%%without%%rowid%%'", + azArg[1], azArg[1] + ); sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( sqlite3_step(pStmt)==SQLITE_ROW ){ tnum = sqlite3_column_int(pStmt, 0); + isWO = sqlite3_column_int(pStmt, 1); } sqlite3_finalize(pStmt); - if( tnum==0 ){ - utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]); - rc = 1; - goto meta_command_exit; - } zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); @@ -7799,6 +7811,9 @@ static int do_meta_command(char *zLine, ShellState *p){ zCol = zLabel; } } + if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){ + lenPK = (int)strlen(zCollist); + } if( zCollist==0 ){ zCollist = sqlite3_mprintf("\"%w\"", zCol); }else{ @@ -7806,9 +7821,16 @@ static int do_meta_command(char *zLine, ShellState *p){ } } sqlite3_finalize(pStmt); + if( i==0 || tnum==0 ){ + utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]); + rc = 1; + sqlite3_free(zCollist); + goto meta_command_exit; + } + if( lenPK==0 ) lenPK = 100000; zSql = sqlite3_mprintf( - "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID", - azArg[2], zCollist, zCollist); + "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID", + azArg[2], zCollist, lenPK, zCollist); sqlite3_free(zCollist); rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum); if( rc==SQLITE_OK ){ @@ -7819,7 +7841,8 @@ static int do_meta_command(char *zLine, ShellState *p){ }else{ utf8_printf(stdout, "%s;\n", zSql); raw_printf(stdout, - "WARNING: writing to an imposter table will corrupt the index!\n" + "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n", + azArg[1], isWO ? "table" : "index" ); } }else{ diff --git a/src/tokenize.c b/src/tokenize.c index 40f7b4aad9..48f92218d3 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -757,7 +757,7 @@ char *sqlite3Normalize( int nParen; /* Number of nested levels of parentheses */ int iStartIN; /* Start of RHS of IN operator in z[] */ int nParenAtIN; /* Value of nParent at start of RHS of IN operator */ - int j; /* Bytes of normalized SQL generated so far */ + u32 j; /* Bytes of normalized SQL generated so far */ sqlite3_str *pStr; /* The normalized SQL string under construction */ db = sqlite3VdbeDb(pVdbe); @@ -801,7 +801,7 @@ char *sqlite3Normalize( } case TK_RP: { if( iStartIN>0 && nParen==nParenAtIN ){ - assert( pStr->nChar>=iStartIN ); + assert( pStr->nChar>=(u32)iStartIN ); pStr->nChar = iStartIN+1; sqlite3_str_append(pStr, "?,?,?", 5); iStartIN = 0; diff --git a/src/update.c b/src/update.c index 56ddec67bc..08502cf5e3 100644 --- a/src/update.c +++ b/src/update.c @@ -289,6 +289,10 @@ void sqlite3Update( sNC.uNC.pUpsert = pUpsert; sNC.ncFlags = NC_UUpsert; + /* Begin generating code. */ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto update_cleanup; + /* Resolve the column names in all the expressions of the ** of the UPDATE statement. Also find the column index ** for each column to be updated in the pChanges array. For each @@ -394,9 +398,6 @@ void sqlite3Update( memset(aToOpen, 1, nIdx+1); } - /* Begin generating code. */ - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto update_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb); diff --git a/test/fts4merge.test b/test/fts4merge.test index 48661afd71..3cd693209d 100644 --- a/test/fts4merge.test +++ b/test/fts4merge.test @@ -326,7 +326,22 @@ foreach mod {fts3 fts4} { execsql { INSERT INTO t1(t1) VALUES('merge=200,10') } expr { ([db total_changes] - $x)>1 } } {0} +} +#------------------------------------------------------------------------- +# Test cases 8.* - ticket [bf1aab89]. +# +set testprefix fts4merge +reset_db +do_execsql_test 8.0 { + CREATE VIRTUAL TABLE t1 USING fts4(a, order=DESC); + INSERT INTO t1(a) VALUES (0); + INSERT INTO t1(a) VALUES (0); + UPDATE t1 SET a = NULL; +} + +do_execsql_test 8.1 { + INSERT INTO t1(t1) VALUES('merge=1,4'); } finish_test diff --git a/test/insert.test b/test/insert.test index 397a0e6ff9..e9bd8d6d7b 100644 --- a/test/insert.test +++ b/test/insert.test @@ -1,4 +1,4 @@ -# 2001 September 15 +# 2001-09-15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: @@ -11,7 +11,6 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing the INSERT statement. # -# $Id: insert.test,v 1.31 2007/04/05 11:25:59 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -458,7 +457,7 @@ do_execsql_test insert-14.1 { SELECT x FROM t14; } {1} -integrity_check insert-99.0 +integrity_check insert-14.2 # 2019-08-12. # @@ -475,5 +474,53 @@ do_execsql_test insert-15.1 { SELECT a, length(b) FROM t1; } {4 33000} +# 2019-10-16 +# ticket https://www.sqlite.org/src/info/a8a4847a2d96f5de +# On a REPLACE INTO, if an AFTER trigger adds back the conflicting +# row, you can end up with the wrong number of rows in an index. +# +db close +sqlite3 db :memory: +do_catchsql_test insert-16.1 { + PRAGMA recursive_triggers = true; + CREATE TABLE t0(c0,c1); + CREATE UNIQUE INDEX i0 ON t0(c0); + INSERT INTO t0(c0,c1) VALUES(123,1); + CREATE TRIGGER tr0 AFTER DELETE ON t0 + BEGIN + INSERT INTO t0 VALUES(123,2); + END; + REPLACE INTO t0(c0,c1) VALUES(123,3); +} {1 {UNIQUE constraint failed: t0.c0}} +do_execsql_test insert-16.2 { + SELECT * FROM t0; +} {123 1} +integrity_check insert-16.3 +do_catchsql_test insert-16.4 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + CREATE INDEX t1b ON t1(b); + INSERT INTO t1 VALUES(1, 'one'); + CREATE TRIGGER tr3 AFTER DELETE ON t1 BEGIN + INSERT INTO t1 VALUES(1, 'three'); + END; + REPLACE INTO t1 VALUES(1, 'two'); +} {1 {UNIQUE constraint failed: t1.a}} +integrity_check insert-16.5 +do_catchsql_test insert-16.6 { + PRAGMA foreign_keys = 1; + CREATE TABLE p1(a, b UNIQUE); + CREATE TABLE c1(c, d REFERENCES p1(b) ON DELETE CASCADE); + CREATE TRIGGER tr6 AFTER DELETE ON c1 BEGIN + INSERT INTO p1 VALUES(4, 1); + END; + INSERT INTO p1 VALUES(1, 1); + INSERT INTO c1 VALUES(2, 1); + REPLACE INTO p1 VALUES(3, 1); +} {1 {UNIQUE constraint failed: p1.b}} +integrity_check insert-16.7 + + + + finish_test diff --git a/test/normalize.test b/test/normalize.test index 8b0c7ed8db..29a5aabb26 100644 --- a/test/normalize.test +++ b/test/normalize.test @@ -347,6 +347,36 @@ foreach {tnum sql flags norm} { {SELECT x FROM t1 WHERE x IN ([x] IS NOT NULL, NULL, 1, 'a', "b", x'00');} 0x2 {0 {SELECT x FROM t1 WHERE x IN(x IS NOT NULL,?,?,?,b,?);}} + + 800 + {ATTACH "normalize800.db" AS somefile;} + 0x2 + {0 {ATTACH"normalize800.db"AS somefile;}} + + 810 + {ATTACH DATABASE "normalize810.db" AS somefile;} + 0x2 + {0 {ATTACH DATABASE"normalize810.db"AS somefile;}} + + 900 + {INSERT INTO t1 (x) VALUES("sl1"), (1), ("sl2"), ('i');} + 0x2 + {0 {INSERT INTO t1(x)VALUES(?),(?),(?),(?);}} + + 910 + {UPDATE t1 SET x = "sl1" WHERE x IN (1, "sl2", 'i');} + 0x2 + {0 {UPDATE t1 SET x=?WHERE x IN(?,?,?);}} + + 920 + {UPDATE t1 SET x = "y" WHERE x IN (1, "sl1", 'i');} + 0x2 + {0 {UPDATE t1 SET x=y WHERE x IN(?,?,?);}} + + 930 + {DELETE FROM t1 WHERE x IN (1, "sl1", 'i');} + 0x2 + {0 {DELETE FROM t1 WHERE x IN(?,?,?);}} } { do_test $tnum { set code [catch {