Compare commits

...

9 Commits

Author SHA1 Message Date
dan cfd227aee2 Cherrypick [79ef8e3c77] (Apply the same restrictions on constant refactoring to statements within a trigger program as top-level statements).
FossilOrigin-Name: 34aafb743627e469681d9d3be4f831399418cc17
2012-12-06 20:27:49 +00:00
dan d916481b23 Cherrypick [557c69055a3] and [0064bab7714] (OP_Once-related fixes for triggers).
FossilOrigin-Name: 0d7b5d455cee06aac4a5b331f26aa5da6963d97f
2012-12-06 20:19:09 +00:00
drh f414af4578 Merge the omit-wal-fix branch into branch-3.7.9 where it belongs, and in so
doing get branch-3.7.9 working with SQLITE_OMIT_WAL.

FossilOrigin-Name: 0391951792c986555c996c654b9b5166267d9094
2012-11-05 16:36:10 +00:00
drh eb4b471f87 Use a constant string "BINARY" for the unspecified collating sequence.
This is part of check-in [635e3a762dd] that is being back-ported.

FossilOrigin-Name: 9078ea75f52fc76039100b3cc0b9a2a3b9a5bff0
2012-10-25 17:21:42 +00:00
drh d7986f29cb Change the ICU tokenizer so that it does not attempt to call strlen(NULL).
This is a cherry-pick of the fix in [04298f1ac42c40c] on 2012-03-31 first
appearing in release 3.7.12.

FossilOrigin-Name: 49ffbc11c5ea7e3cefd0370f39832dbfc7276ffe
2012-10-15 23:15:45 +00:00
drh 74f6123d10 Add QNX-specific performance tweaks to the unix VFS.
FossilOrigin-Name: b02849e7bde458dd8a2d91892f18bae7fdc7724d
2012-10-05 19:10:02 +00:00
drh 067dbab396 Fix an accidental fork on branch-3.7.9.
FossilOrigin-Name: cd9efeb3eb28efc6a92904bb426c3a50f95fc936
2012-10-05 18:38:26 +00:00
drh 4d1b68f8b2 Backport fixes to shared-cache mode, from the shared-cache-fix branch, to
version 3.7.9

FossilOrigin-Name: ac81ae493f97e415f13ef517b0ff88a901bc276f
2012-10-05 18:35:33 +00:00
drh ec04dad11a Cherrypick the [5dbfaed8c3] patch so that SQLITE_OMIT_WAL works again.
FossilOrigin-Name: a499ae3835ed7f1591c40bea20e0c97f58ceedbb
2011-11-08 15:06:05 +00:00
25 changed files with 533 additions and 107 deletions
+4 -1
View File
@@ -110,7 +110,10 @@ static int icuOpen(
*ppCursor = 0;
if( nInput<0 ){
if( zInput==0 ){
nInput = 0;
zInput = "";
}else if( nInput<0 ){
nInput = strlen(zInput);
}
nChar = nInput+1;
+29 -31
View File
@@ -1,5 +1,5 @@
C Fix\sa\s8-byte\salignment\sproblem\sthat\scauses\sa\sSIGBUS\son\sSparc.
D 2011-11-14T02:53:54.950
C Cherrypick\s[79ef8e3c77]\s(Apply\sthe\ssame\srestrictions\son\sconstant\srefactoring\sto\sstatements\swithin\sa\strigger\sprogram\sas\stop-level\sstatements).
D 2012-12-06T20:27:49.877
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in a162fe39e249b8ed4a65ee947c30152786cfe897
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -70,7 +70,7 @@ F ext/fts3/fts3_aux.c 0ebfa7b86cf8ff6a0861605fcc63b83ec1b70691
F ext/fts3/fts3_expr.c f5df26bddf46a5916b2a5f80c4027996e92b7b15
F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914
F ext/fts3/fts3_hash.h 8331fb2206c609f9fc4c4735b9ab5ad6137c88ec
F ext/fts3/fts3_icu.c 6c8f395cdf9e1e3afa7fadb7e523dbbf381c6dfa
F ext/fts3/fts3_icu.c 62ec177c55f6a5c6e994dd3e5fd3194b4045c347
F ext/fts3/fts3_porter.c 8d946908f4812c005d3d33fcbe78418b1f4eb70c
F ext/fts3/fts3_snippet.c 1f9ee6a8e0e242649645968dcec4deb253d86c2a
F ext/fts3/fts3_term.c a5457992723455a58804cb75c8cbd8978db5c2ef
@@ -118,9 +118,9 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c ac80a0f31189f8b4a524ebf661e47e84536ee7f5
F src/alter.c ecf329684fcf1af4ae27d3368c30837479dbea71
F src/analyze.c 5a1db16a651ce6310c8b046b2cbb736e030e14b9
F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f
F src/attach.c 48c5736f89a2256237d8eef5da8c28eb0c81edab
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 4368158da74d4711888e03264105c5c527d76caf
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
@@ -128,13 +128,13 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 32199e2d939233ade25340eaba450f818b37c079
F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
F src/build.c 8915bb6d72ead998f94c2756ea8d143c77709b70
F src/build.c f354512133f3c3403df55d00602b9179249858ab
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c a9c26822515f81ec21588cbb482ca6724be02e33
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
F src/delete.c ff68e5ef23aee08c0ff528f699a19397ed8bbed8
F src/expr.c fbf116f90cabc917ae50bba24a73a0b55519a0c8
F src/delete.c e3a945da4aecffdb0fc9226da004f7273acecdcb
F src/expr.c 96d029a9b7b5c012cc00ce11c38215fb7d13488b
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5
F src/func.c 6261ce00aad9c63cd5b4219249b05683979060e9
@@ -142,7 +142,7 @@ F src/global.c e230227de13601714b29f9363028514aada5ae2f
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c ca18783512323f74aaf4ee74b46ffd75ec80d031
F src/insert.c abe16e63ef0865467e958fc28994eadc2849e169
F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416
@@ -166,9 +166,9 @@ F src/os.c 5d9b02782ed36345348d6fe21d7762ed3a9cfd2a
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
F src/os_unix.c ddda0b1c5ae536669634d7bff31b3f8f4d654866
F src/os_unix.c 97c346f849b0aeb8f1556141ee1875db5f1f6357
F src/os_win.c 49d418916428a59d773f39993db0ecde56ab4c37
F src/pager.c ad62daa0c21e27ae332b3ceb4f579a2a97046ddc
F src/pager.c db33d4bf1e3e019c34c220971cc6c3aa07c30f54
F src/pager.h 9f81b08efb06db4ba8be69446e10b005c351373d
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
F src/pcache.c 49e718c095810c6b3334e3a6d89970aceaddefce
@@ -180,11 +180,11 @@ F src/printf.c 03104cbff6959ff45df69dc9060ba6212f60a869
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 365ab1c870e38596d6869e76fb544fe6e4ffc809
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c 80f3ac44a8514b1d107b80f5df4a424ae059d2b6
F src/select.c 3d4543b9611030df49eca1618bde8bd8468bf3b3
F src/shell.c f0ab793261ab045a0b8c47fa2707e8a894d2898f
F src/sqlite.h.in ff950aef7b378963c67add42dda5d446a0b7330e
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
F src/sqliteInt.h c74457cd2c4bd77683bac76e698bf2ec2d3e13f9
F src/sqliteInt.h d660a5ad543d775f28a46cf9510b5cb86e8097d2
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 4568e72dfd36b6a5911f93457364deb072e0b03a
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -234,25 +234,25 @@ F src/test_vfstrace.c 0b884e06094a746da729119a2cabdc7aa790063d
F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c c819d9f72168a035d545a5bdafe9b085b20df705
F src/trigger.c 1cfb80e2290ef66ea89cb4e821caae65a02c0d56
F src/update.c 25e046a8f69d5e557aabde2000487b8545509d8d
F src/trigger.c 84f90c64d7118ad2be370063dc3a660001bb02ee
F src/update.c d3076782c887c10e882996550345da9c4c9f9dea
F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
F src/util.c df83983bd57057df4951516880066b42b7055269
F src/vacuum.c 0c0ba2242355c6048d65e2b333abe0f7c06348fa
F src/vdbe.c 326994a64a9a08853122200dc9f62cb96b8f0831
F src/vdbe.h f0725ee997db869ecae5bb70a71612aabeca7755
F src/vdbeInt.h 9498fc98a2c9e349a4ef13455ff5a3e898f40176
F src/vdbe.c fed44fdc7c34838d8c6a6a89a7e124944846f66c
F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb
F src/vdbeInt.h 23a9506c9ab31e7823d7257d1828d2d7843443a0
F src/vdbeapi.c 4dbba7f94f127f6ea8d2d0505ee1f98e5ffbf546
F src/vdbeaux.c a950e34449a508d48d90475acc287943a4094f3a
F src/vdbeaux.c 15b1ef21b59c308812e49b33b1b42516fdc48817
F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb
F src/vdbemem.c 2fc78b3e0fabcc1eaa23cd79dd2e30e6dcfe1e56
F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790
F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
F src/vtab.c e9318d88feac85be8e27ee783ac8f5397933fc8a
F src/vtab.c f36d8f8386e59c225f9c458ec45a3c20ff8efe78
F src/wal.c 9658df8d404b82e6b2d40fd05944463214e2d935
F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c 7c85f4c93058e27100d404f0777aaeb0d1b296ae
F src/where.c 13e6e3e15bd2b2991e73027cd23e584bf7a629ad
F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
@@ -472,7 +472,7 @@ F test/fts3corrupt.test 7b0f91780ca36118d73324ec803187208ad33b32
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
F test/fts3d.test bf640d79722b720fa1c81834c48cdaa45d531b1a
F test/fts3defer.test 2ea3fa028f8d9523f9c33dd8acc4555d567ea4ac
F test/fts3defer.test 6c2707be1b05b9790ba8ff91d3391d5fb425269e
F test/fts3defer2.test 35867d33ba6db03f6c73bd6f5fc333ae14f68c81
F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
@@ -735,6 +735,7 @@ F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
F test/tkt-752e1646fc.test ea78d88d14fe9866bdd991c634483334639e13bf
F test/tkt-78e04e52ea.test ab52f0c1e2de6e46c910f4cc16b086bba05952b7
F test/tkt-7bbfb7d442.test 8e7658f77d1ccea9d88dc9e255d3ed7fb68f8bdf
F test/tkt-80ba201079.test a09684db1a0bd55b8838f606adccee456a51ddbf
F test/tkt-80e031a00f.test 9a154173461a4dbe2de49cda73963e04842d52f7
F test/tkt-8454a207b9.test c583a9f814a82a2b5ba95207f55001c9f0cd816c
@@ -845,7 +846,7 @@ F test/trace2.test 962175290996d5f06dc4402ca218bbfc7df4cb20
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
F test/trans2.test d5337e61de45e66b1fcbf9db833fa8c82e624b22
F test/trans3.test d728abaa318ca364dc370e06576aa7e5fbed7e97
F test/trigger1.test 38c657eaf9907344c9e0bcb16af94a452c6babde
F test/trigger1.test c3e4093e57f6c962ca8e54ca5274d10e7a4e706a
F test/trigger2.test 834187beafd1db383af0c659cfa49b0576832816
F test/trigger3.test d2c60d8be271c355d61727411e753181e877230a
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
@@ -856,7 +857,7 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
F test/trigger9.test 5b0789f1c5c4600961f8e68511b825b87be53e31
F test/triggerA.test e0aaba16d3547193d36bbd82a1b0ed75e9c88d40
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
F test/triggerC.test 4d4bdaf0230c206b50d350330107ef9802bc2d4f
F test/triggerC.test c9e59c1c8834ef8024045202a2f64816e917c07a
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
F test/tt3_checkpoint.c 415eccce672d681b297485fc20f44cdf0eac93af
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
@@ -974,10 +975,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
P c7c6050ef060877ebe77b41d959e9df13f8c9b5e
R ff6342b74061a33cbd4fa1292ca6bba4
T *branch * branch-3.7.9
T *sym-branch-3.7.9 *
T -sym-trunk *
U drh
Z d03af58daca88e6314e5ea39548757b9
P 0d7b5d455cee06aac4a5b331f26aa5da6963d97f
R 1321c1938d7d3f11b7481c95ce141586
U dan
Z 4d8a6a6b21f3fade47676f63c6713742
+1 -1
View File
@@ -1 +1 @@
54cc11981127b52145e39f551d958580b1d45169
34aafb743627e469681d9d3be4f831399418cc17
+2 -2
View File
@@ -414,7 +414,7 @@ void sqlite3AlterRenameTable(
assert( pSrc->nSrc==1 );
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase);
pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
if( !pTab ) goto exit_rename_table;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
zDb = db->aDb[iDb].zName;
@@ -757,7 +757,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
assert( pParse->pNewTable==0 );
assert( sqlite3BtreeHoldsAllMutexes(db) );
if( db->mallocFailed ) goto exit_begin_add_column;
pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase);
pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
if( !pTab ) goto exit_begin_add_column;
#ifndef SQLITE_OMIT_VIRTUALTABLE
+5 -3
View File
@@ -434,6 +434,7 @@ int sqlite3FixInit(
assert( db->nDb>iDb );
pFix->pParse = pParse;
pFix->zDb = db->aDb[iDb].zName;
pFix->pSchema = db->aDb[iDb].pSchema;
pFix->zType = zType;
pFix->pName = pName;
return 1;
@@ -464,14 +465,15 @@ int sqlite3FixSrcList(
if( NEVER(pList==0) ) return 0;
zDb = pFix->zDb;
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pItem->zDatabase==0 ){
pItem->zDatabase = sqlite3DbStrDup(pFix->pParse->db, zDb);
}else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){
if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
sqlite3ErrorMsg(pFix->pParse,
"%s %T cannot reference objects in database %s",
pFix->zType, pFix->pName, pItem->zDatabase);
return 1;
}
sqlite3_free(pItem->zDatabase);
pItem->zDatabase = 0;
pItem->pSchema = pFix->pSchema;
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
+38 -5
View File
@@ -127,6 +127,7 @@ void sqlite3FinishCoding(Parse *pParse){
sqlite3 *db;
Vdbe *v;
assert( pParse->pToplevel==0 );
db = pParse->db;
if( db->mallocFailed ) return;
if( pParse->nested ) return;
@@ -319,6 +320,31 @@ Table *sqlite3LocateTable(
return p;
}
/*
** Locate the table identified by *p.
**
** This is a wrapper around sqlite3LocateTable(). The difference between
** sqlite3LocateTable() and this function is that this function restricts
** the search to schema (p->pSchema) if it is not NULL. p->pSchema may be
** non-NULL if it is part of a view or trigger program definition. See
** sqlite3FixSrcList() for details.
*/
Table *sqlite3LocateTableItem(
Parse *pParse,
int isView,
struct SrcList_item *p
){
const char *zDb;
assert( p->pSchema==0 || p->zDatabase==0 );
if( p->pSchema ){
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
zDb = pParse->db->aDb[iDb].zName;
}else{
zDb = p->zDatabase;
}
return sqlite3LocateTable(pParse, isView, p->zName, zDb);
}
/*
** Locate the in-memory structure that describes
** a particular index given the name of that index
@@ -2090,8 +2116,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
if( noErr ) db->suppressErr++;
pTab = sqlite3LocateTable(pParse, isView,
pName->a[0].zName, pName->a[0].zDatabase);
pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
if( noErr ) db->suppressErr--;
if( pTab==0 ){
@@ -2533,8 +2558,7 @@ Index *sqlite3CreateIndex(
** sqlite3FixSrcList can never fail. */
assert(0);
}
pTab = sqlite3LocateTable(pParse, 0, pTblName->a[0].zName,
pTblName->a[0].zDatabase);
pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
if( !pTab || db->mallocFailed ) goto exit_create_index;
assert( db->aDb[iDb].pSchema==pTab->pSchema );
}else{
@@ -2740,7 +2764,7 @@ Index *sqlite3CreateIndex(
}else{
zColl = pTab->aCol[j].zColl;
if( !zColl ){
zColl = db->pDfltColl->zName;
zColl = "BINARY";
}
}
if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
@@ -3549,6 +3573,15 @@ int sqlite3OpenTempDatabase(Parse *pParse){
void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
#ifndef SQLITE_OMIT_TRIGGER
if( pToplevel!=pParse ){
/* This branch is taken if a trigger is currently being coded. In this
** case, set cookieGoto to a non-zero value to show that this function
** has been called. This is used by the sqlite3ExprCodeConstants()
** function. */
pParse->cookieGoto = -1;
}
#endif
if( pToplevel->cookieGoto==0 ){
Vdbe *v = sqlite3GetVdbe(pToplevel);
if( v==0 ) return; /* This only happens if there was a prior error */
+1 -1
View File
@@ -32,7 +32,7 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
struct SrcList_item *pItem = pSrc->a;
Table *pTab;
assert( pItem && pSrc->nSrc==1 );
pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
pTab = sqlite3LocateTableItem(pParse, 0, pItem);
sqlite3DeleteTable(pParse->db, pItem->pTab);
pItem->pTab = pTab;
if( pTab ){
+17 -8
View File
@@ -897,6 +897,7 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
struct SrcList_item *pNewItem = &pNew->a[i];
struct SrcList_item *pOldItem = &p->a[i];
Table *pTab;
pNewItem->pSchema = pOldItem->pSchema;
pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
@@ -1373,6 +1374,15 @@ static int isCandidateForInOpt(Select *p){
}
#endif /* SQLITE_OMIT_SUBQUERY */
/*
** Code an OP_Once instruction and allocate space for its flag. Return the
** address of the new instruction.
*/
int sqlite3CodeOnce(Parse *pParse){
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++);
}
/*
** This function is used by the implementation of the IN (...) operator.
** It's job is to find or create a b-tree structure that may be used
@@ -1433,6 +1443,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
int eType = 0; /* Type of RHS table. IN_INDEX_* */
int iTab = pParse->nTab++; /* Cursor of the RHS table */
int mustBeUnique = (prNotFound==0); /* True if RHS must be unique */
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
assert( pX->op==TK_IN );
@@ -1443,7 +1454,6 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){
sqlite3 *db = pParse->db; /* Database connection */
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
Table *pTab; /* Table <table>. */
Expr *pExpr; /* Expression <column> */
int iCol; /* Index of column <column> */
@@ -1468,10 +1478,9 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
*/
assert(v);
if( iCol<0 ){
int iMem = ++pParse->nMem;
int iAddr;
iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
iAddr = sqlite3CodeOnce(pParse);
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
eType = IN_INDEX_ROWID;
@@ -1497,12 +1506,11 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
&& sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq
&& (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None))
){
int iMem = ++pParse->nMem;
int iAddr;
char *pKey;
pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
iAddr = sqlite3CodeOnce(pParse);
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
pKey,P4_KEYINFO_HANDOFF);
@@ -1512,6 +1520,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
sqlite3VdbeJumpHere(v, iAddr);
if( prNotFound && !pTab->aCol[iCol].notNull ){
*prNotFound = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
}
}
}
@@ -1527,6 +1536,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
eType = IN_INDEX_EPH;
if( prNotFound ){
*prNotFound = rMayHaveNull = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
}else{
testcase( pParse->nQueryLoop>(double)1 );
pParse->nQueryLoop = (double)1;
@@ -1599,9 +1609,8 @@ int sqlite3CodeSubselect(
** If all of the above are false, then we can run this code just once
** save the results, and reuse the same result on subsequent invocations.
*/
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
int mem = ++pParse->nMem;
testAddr = sqlite3VdbeAddOp1(v, OP_Once, mem);
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) ){
testAddr = sqlite3CodeOnce(pParse);
}
#ifndef SQLITE_OMIT_EXPLAIN
+5 -2
View File
@@ -239,6 +239,7 @@ void sqlite3AutoincrementBegin(Parse *pParse){
memId = p->regCtr;
assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1);
addr = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0);
sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9);
@@ -1215,8 +1216,9 @@ void sqlite3GenerateConstraintChecks(
#ifndef SQLITE_OMIT_CHECK
if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){
int allOk = sqlite3VdbeMakeLabel(v);
Expr *pDup = sqlite3ExprDup(pParse->db, pTab->pCheck, 0);
pParse->ckBase = regData;
sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, SQLITE_JUMPIFNULL);
sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL);
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
if( onError==OE_Ignore ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
@@ -1224,6 +1226,7 @@ void sqlite3GenerateConstraintChecks(
if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
sqlite3HaltConstraint(pParse, onError, 0, 0);
}
sqlite3ExprDelete(pParse->db, pDup);
sqlite3VdbeResolveLabel(v, allOk);
}
#endif /* !defined(SQLITE_OMIT_CHECK) */
@@ -1687,7 +1690,7 @@ static int xferOptimization(
** we have to check the semantics.
*/
pItem = pSelect->pSrc->a;
pSrc = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
pSrc = sqlite3LocateTableItem(pParse, 0, pItem);
if( pSrc==0 ){
return 0; /* FROM clause does not contain a real table */
}
+93 -2
View File
@@ -216,6 +216,10 @@ struct unixFile {
const char *zPath; /* Name of the file */
unixShm *pShm; /* Shared memory segment information */
int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
#ifdef __QNXNTO__
int sectorSize; /* Device sector size */
int deviceCharacteristics; /* Precomputed device characteristics */
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
int openFlags; /* The flags specified at open() */
#endif
@@ -3547,17 +3551,104 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
** a database and its journal file) that the sector size will be the
** same for both.
*/
#ifndef __QNXNTO__
static int unixSectorSize(sqlite3_file *NotUsed){
UNUSED_PARAMETER(NotUsed);
return SQLITE_DEFAULT_SECTOR_SIZE;
}
#endif
/*
** The following version of unixSectorSize() is optimized for QNX.
*/
#ifdef __QNXNTO__
#include <sys/dcmd_blk.h>
#include <sys/statvfs.h>
static int unixSectorSize(sqlite3_file *id){
unixFile *pFile = (unixFile*)id;
if( pFile->sectorSize == 0 ){
struct statvfs fsInfo;
/* Set defaults for non-supported filesystems */
pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
pFile->deviceCharacteristics = 0;
if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
return pFile->sectorSize;
}
if( !strcmp(fsInfo.f_basetype, "tmp") ) {
pFile->sectorSize = fsInfo.f_bsize;
pFile->deviceCharacteristics =
SQLITE_IOCAP_ATOMIC4K | /* All ram filesystem writes are atomic */
SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
** the write succeeds */
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
** so it is ordered */
0;
}else if( strstr(fsInfo.f_basetype, "etfs") ){
pFile->sectorSize = fsInfo.f_bsize;
pFile->deviceCharacteristics =
/* etfs cluster size writes are atomic */
(pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) |
SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
** the write succeeds */
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
** so it is ordered */
0;
}else if( !strcmp(fsInfo.f_basetype, "qnx6") ){
pFile->sectorSize = fsInfo.f_bsize;
pFile->deviceCharacteristics =
SQLITE_IOCAP_ATOMIC | /* All filesystem writes are atomic */
SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
** the write succeeds */
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
** so it is ordered */
0;
}else if( !strcmp(fsInfo.f_basetype, "qnx4") ){
pFile->sectorSize = fsInfo.f_bsize;
pFile->deviceCharacteristics =
/* full bitset of atomics from max sector size and smaller */
((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
** so it is ordered */
0;
}else if( strstr(fsInfo.f_basetype, "dos") ){
pFile->sectorSize = fsInfo.f_bsize;
pFile->deviceCharacteristics =
/* full bitset of atomics from max sector size and smaller */
((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
** so it is ordered */
0;
}else{
pFile->deviceCharacteristics =
SQLITE_IOCAP_ATOMIC512 | /* blocks are atomic */
SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
** the write succeeds */
0;
}
}
/* Last chance verification. If the sector size isn't a multiple of 512
** then it isn't valid.*/
if( pFile->sectorSize % 512 != 0 ){
pFile->deviceCharacteristics = 0;
pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
}
return pFile->sectorSize;
}
#endif /* __QNXNTO__ */
/*
** Return the device characteristics for the file. This is always 0 for unix.
*/
static int unixDeviceCharacteristics(sqlite3_file *NotUsed){
UNUSED_PARAMETER(NotUsed);
static int unixDeviceCharacteristics(sqlite3_file *id){
#ifdef __QNXNTO__
unixFile *p = (unixFile*)id;
if( p->sectorSize==0 ) unixSectorSize(id);
return p->deviceCharacteristics;
#else
return 0;
#endif
}
#ifndef SQLITE_OMIT_WAL
+9 -7
View File
@@ -6660,6 +6660,15 @@ sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
return &pPager->pBackup;
}
#ifndef SQLITE_OMIT_VACUUM
/*
** Unless this is an in-memory or temporary database, clear the pager cache.
*/
void sqlite3PagerClearCache(Pager *pPager){
if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager);
}
#endif
#ifndef SQLITE_OMIT_WAL
/*
** This function is called when the user invokes "PRAGMA wal_checkpoint",
@@ -6836,13 +6845,6 @@ int sqlite3PagerCloseWal(Pager *pPager){
return rc;
}
/*
** Unless this is an in-memory or temporary database, clear the pager cache.
*/
void sqlite3PagerClearCache(Pager *pPager){
if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager);
}
#ifdef SQLITE_HAS_CODEC
/*
** This function is called by the wal module when writing page content
+4 -5
View File
@@ -3239,8 +3239,7 @@ static int selectExpander(Walker *pWalker, Select *p){
}else{
/* An ordinary table or view name in the FROM clause */
assert( pFrom->pTab==0 );
pFrom->pTab = pTab =
sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
if( pTab==0 ) return WRC_Abort;
pTab->nRef++;
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
@@ -3845,12 +3844,11 @@ int sqlite3Select(
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
pItem->addrFillSub = topAddr+1;
VdbeNoopComment((v, "materialize %s", pItem->pTab->zName));
if( pItem->isCorrelated==0 && pParse->pTriggerTab==0 ){
if( pItem->isCorrelated==0 ){
/* If the subquery is no correlated and if we are not inside of
** a trigger, then we only need to compute the value of the subquery
** once. */
int regOnce = ++pParse->nMem;
onceAddr = sqlite3VdbeAddOp1(v, OP_Once, regOnce);
onceAddr = sqlite3CodeOnce(pParse);
}
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
@@ -4155,6 +4153,7 @@ int sqlite3Select(
VdbeComment((v, "clear abort flag"));
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
VdbeComment((v, "indicate accumulator empty"));
sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1);
/* Begin a loop that will extract all source rows in GROUP BY order.
** This might involve two separate loops with an OP_Sort in between, or
+5
View File
@@ -1861,6 +1861,7 @@ struct SrcList {
i16 nSrc; /* Number of tables or subqueries in the FROM clause */
i16 nAlloc; /* Number of entries allocated in a[] below */
struct SrcList_item {
Schema *pSchema; /* Schema to which this item is fixed */
char *zDatabase; /* Name of database holding this table */
char *zName; /* Name of the table */
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
@@ -2218,6 +2219,7 @@ struct Parse {
int nTab; /* Number of previously allocated VDBE cursors */
int nMem; /* Number of memory cells used so far */
int nSet; /* Number of sets used so far */
int nOnce; /* Number of OP_Once instructions so far */
int ckBase; /* Base register of data during check constraints */
int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
int iCacheCnt; /* Counter used to generate aColCache[].lru values */
@@ -2412,6 +2414,7 @@ struct TriggerStep {
typedef struct DbFixer DbFixer;
struct DbFixer {
Parse *pParse; /* The parsing context. Error messages written here */
Schema *pSchema; /* Fix items to this schema */
const char *zDb; /* Make sure all objects are contained in this database */
const char *zType; /* Type of the container - used for error messages */
const Token *pName; /* Name of the container - used for error messages */
@@ -2706,6 +2709,7 @@ void sqlite3AddCollateType(Parse*, Token*);
void sqlite3EndTable(Parse*,Token*,Token*,Select*);
int sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlite3_vfs**,char**,char **);
int sqlite3CodeOnce(Parse *);
Bitvec *sqlite3BitvecCreate(u32);
int sqlite3BitvecTest(Bitvec*, u32);
@@ -2790,6 +2794,7 @@ void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
Table *sqlite3FindTable(sqlite3*,const char*, const char*);
Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*);
Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *);
Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
+10
View File
@@ -729,6 +729,15 @@ static int codeTriggerProgram(
*/
pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
/* Clear the cookieGoto flag. When coding triggers, the cookieGoto
** variable is used as a flag to indicate to sqlite3ExprCodeConstants()
** that it is not safe to refactor constants (this happens after the
** start of the first loop in the SQL statement is coded - at that
** point code may be conditionally executed, so it is no longer safe to
** initialize constant register values). */
assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 );
pParse->cookieGoto = 0;
switch( pStep->op ){
case TK_UPDATE: {
sqlite3Update(pParse,
@@ -904,6 +913,7 @@ static TriggerPrg *codeRowTrigger(
}
pProgram->nMem = pSubParse->nMem;
pProgram->nCsr = pSubParse->nTab;
pProgram->nOnce = pSubParse->nOnce;
pProgram->token = (void *)pTrigger;
pPrg->aColmask[0] = pSubParse->oldmask;
pPrg->aColmask[1] = pSubParse->newmask;
+6 -5
View File
@@ -126,8 +126,8 @@ void sqlite3Update(
int regRowCount = 0; /* A count of rows changed */
int regOldRowid; /* The old rowid */
int regNewRowid; /* The new rowid */
int regNew;
int regOld = 0;
int regNew; /* Content of the NEW.* table in triggers */
int regOld = 0; /* Content of OLD.* table in triggers */
int regRowSet = 0; /* Rowset of rows to be updated */
memset(&sContext, 0, sizeof(sContext));
@@ -276,6 +276,7 @@ void sqlite3Update(
#endif
/* Allocate required registers. */
regRowSet = ++pParse->nMem;
regOldRowid = regNewRowid = ++pParse->nMem;
if( pTrigger || hasFK ){
regOld = pParse->nMem + 1;
@@ -310,7 +311,7 @@ void sqlite3Update(
/* Begin the database scan
*/
sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
pWInfo = sqlite3WhereBegin(
pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED
);
@@ -321,7 +322,6 @@ void sqlite3Update(
*/
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid);
if( !okOnePass ){
regRowSet = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
}
@@ -425,9 +425,10 @@ void sqlite3Update(
newmask = sqlite3TriggerColmask(
pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
);
sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);
for(i=0; i<pTab->nCol; i++){
if( i==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
/*sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);*/
}else{
j = aXRef[i];
if( j>=0 ){
+42 -22
View File
@@ -764,7 +764,8 @@ case OP_Goto: { /* jump */
** Write the current address onto register P1
** and then jump to address P2.
*/
case OP_Gosub: { /* jump, in1 */
case OP_Gosub: { /* jump */
assert( pOp->p1>0 && pOp->p1<=p->nMem );
pIn1 = &aMem[pOp->p1];
assert( (pIn1->flags & MEM_Dyn)==0 );
memAboutToChange(p, pIn1);
@@ -961,12 +962,25 @@ case OP_String: { /* out2-prerelease */
break;
}
/* Opcode: Null * P2 * * *
/* Opcode: Null * P2 P3 * *
**
** Write a NULL into register P2.
** Write a NULL into registers P2. If P3 greater than P2, then also write
** NULL into register P3 and ever register in between P2 and P3. If P3
** is less than P2 (typically P3 is zero) then only register P2 is
** set to NULL
*/
case OP_Null: { /* out2-prerelease */
int cnt;
cnt = pOp->p3-pOp->p2;
assert( pOp->p3<=p->nMem );
pOut->flags = MEM_Null;
while( cnt>0 ){
pOut++;
memAboutToChange(p, pOut);
MemReleaseExt(pOut);
pOut->flags = MEM_Null;
cnt--;
}
break;
}
@@ -2023,27 +2037,33 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
/* Opcode: Once P1 P2 * * *
**
** Jump to P2 if the value in register P1 is a not null or zero. If
** the value is NULL or zero, fall through and change the P1 register
** to an integer 1.
** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
** set the flag and fall through to the next instruction.
**
** When P1 is not used otherwise in a program, this opcode falls through
** once and jumps on all subsequent invocations. It is the equivalent
** of "OP_If P1 P2", followed by "OP_Integer 1 P1".
** See also: JumpOnce
*/
case OP_Once: { /* jump */
assert( pOp->p1<p->nOnceFlag );
if( p->aOnceFlag[pOp->p1] ){
pc = pOp->p2-1;
}else{
p->aOnceFlag[pOp->p1] = 1;
}
break;
}
/* Opcode: If P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is true. The value
** is considered true if it is numeric and non-zero. If the value
** in P1 is NULL then take the jump if P3 is true.
** in P1 is NULL then take the jump if P3 is non-zero.
*/
/* Opcode: IfNot P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is False. The value
** is considered true if it has a numeric value of zero. If the value
** in P1 is NULL then take the jump if P3 is true.
** is considered false if it has a numeric value of zero. If the value
** in P1 is NULL then take the jump if P3 is zero.
*/
case OP_Once: /* jump, in1 */
case OP_If: /* jump, in1 */
case OP_IfNot: { /* jump, in1 */
int c;
@@ -2060,12 +2080,6 @@ case OP_IfNot: { /* jump, in1 */
}
if( c ){
pc = pOp->p2-1;
}else if( pOp->opcode==OP_Once ){
assert( (pIn1->flags & (MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))==0 );
memAboutToChange(p, pIn1);
pIn1->flags = MEM_Int;
pIn1->u.i = 1;
REGISTER_TRACE(pOp->p1, pIn1);
}
break;
}
@@ -5071,7 +5085,6 @@ case OP_Program: { /* jump */
pProgram = pOp->p4.pProgram;
pRt = &aMem[pOp->p3];
assert( memIsValid(pRt) );
assert( pProgram->nOp>0 );
/* If the p5 flag is clear, then recursive invocation of triggers is
@@ -5110,7 +5123,8 @@ case OP_Program: { /* jump */
nMem = pProgram->nMem + pProgram->nCsr;
nByte = ROUND8(sizeof(VdbeFrame))
+ nMem * sizeof(Mem)
+ pProgram->nCsr * sizeof(VdbeCursor *);
+ pProgram->nCsr * sizeof(VdbeCursor *)
+ pProgram->nOnce * sizeof(u8);
pFrame = sqlite3DbMallocZero(db, nByte);
if( !pFrame ){
goto no_mem;
@@ -5130,10 +5144,12 @@ case OP_Program: { /* jump */
pFrame->aOp = p->aOp;
pFrame->nOp = p->nOp;
pFrame->token = pProgram->token;
pFrame->aOnceFlag = p->aOnceFlag;
pFrame->nOnceFlag = p->nOnceFlag;
pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
pMem->flags = MEM_Null;
pMem->flags = MEM_Invalid;
pMem->db = db;
}
}else{
@@ -5155,7 +5171,11 @@ case OP_Program: { /* jump */
p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
p->aOp = aOp = pProgram->aOp;
p->nOp = pProgram->nOp;
p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
p->nOnceFlag = pProgram->nOnce;
p->nOp = pProgram->nOp;
pc = -1;
memset(p->aOnceFlag, 0, p->nOnceFlag);
break;
}
+1
View File
@@ -82,6 +82,7 @@ struct SubProgram {
int nOp; /* Elements in aOp[] */
int nMem; /* Number of memory cells required */
int nCsr; /* Number of cursors required */
int nOnce; /* Number of OP_Once instructions */
void *token; /* id that may be used to recursive triggers */
SubProgram *pNext; /* Next sub-program already visited */
};
+4
View File
@@ -117,6 +117,8 @@ struct VdbeFrame {
int nOp; /* Size of aOp array */
Mem *aMem; /* Array of memory cells for parent frame */
int nMem; /* Number of entries in aMem */
u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */
int nOnceFlag; /* Number of entries in aOnceFlag */
VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
u16 nCursor; /* Number of entries in apCsr */
void *token; /* Copy of SubProgram.token */
@@ -326,6 +328,8 @@ struct Vdbe {
int nFrame; /* Number of frames in pFrame list */
u32 expmask; /* Binding to these vars invalidates VM */
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
int nOnceFlag; /* Size of array aOnceFlag[] */
u8 *aOnceFlag; /* Flags for OP_Once */
};
/*
+15 -5
View File
@@ -913,13 +913,14 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
}
case P4_MEM: {
Mem *pMem = pOp->p4.pMem;
assert( (pMem->flags & MEM_Null)==0 );
if( pMem->flags & MEM_Str ){
zP4 = pMem->z;
}else if( pMem->flags & MEM_Int ){
sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i);
}else if( pMem->flags & MEM_Real ){
sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r);
}else if( pMem->flags & MEM_Null ){
sqlite3_snprintf(nTemp, zTemp, "NULL");
}else{
assert( pMem->flags & MEM_Blob );
zP4 = "(blob)";
@@ -1094,7 +1095,7 @@ static void releaseMemArray(Mem *p, int N){
p->zMalloc = 0;
}
p->flags = MEM_Null;
p->flags = MEM_Invalid;
}
db->mallocFailed = malloc_failed;
}
@@ -1469,6 +1470,7 @@ void sqlite3VdbeMakeReady(
int nMem; /* Number of VM memory registers */
int nCursor; /* Number of cursors required */
int nArg; /* Number of arguments in subprograms */
int nOnce; /* Number of OP_Once instructions */
int n; /* Loop counter */
u8 *zCsr; /* Memory available for allocation */
u8 *zEnd; /* First byte past allocated memory */
@@ -1484,6 +1486,7 @@ void sqlite3VdbeMakeReady(
nMem = pParse->nMem;
nCursor = pParse->nTab;
nArg = pParse->nMaxArg;
nOnce = pParse->nOnce;
/* For each cursor required, also allocate a memory cell. Memory
** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
@@ -1530,6 +1533,7 @@ void sqlite3VdbeMakeReady(
p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
&zCsr, zEnd, &nByte);
p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte);
if( nByte ){
p->pFree = sqlite3DbMallocZero(db, nByte);
}
@@ -1538,6 +1542,7 @@ void sqlite3VdbeMakeReady(
}while( nByte && !db->mallocFailed );
p->nCursor = (u16)nCursor;
p->nOnceFlag = nOnce;
if( p->aVar ){
p->nVar = (ynVar)nVar;
for(n=0; n<nVar; n++){
@@ -1554,7 +1559,7 @@ void sqlite3VdbeMakeReady(
p->aMem--; /* aMem[] goes from 1..nMem */
p->nMem = nMem; /* not from 0..nMem-1 */
for(n=1; n<=nMem; n++){
p->aMem[n].flags = MEM_Null;
p->aMem[n].flags = MEM_Invalid;
p->aMem[n].db = db;
}
}
@@ -1596,6 +1601,8 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
*/
int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
Vdbe *v = pFrame->v;
v->aOnceFlag = pFrame->aOnceFlag;
v->nOnceFlag = pFrame->nOnceFlag;
v->aOp = pFrame->aOp;
v->nOp = pFrame->nOp;
v->aMem = pFrame->aMem;
@@ -1658,8 +1665,10 @@ static void Cleanup(Vdbe *p){
/* Execute assert() statements to ensure that the Vdbe.apCsr[] and
** Vdbe.aMem[] arrays have already been cleaned up. */
int i;
for(i=0; i<p->nCursor; i++) assert( p->apCsr==0 || p->apCsr[i]==0 );
for(i=1; i<=p->nMem; i++) assert( p->aMem==0 || p->aMem[i].flags==MEM_Null );
if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
if( p->aMem ){
for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Invalid );
}
#endif
sqlite3DbFree(db, p->zErrMsg);
@@ -2127,6 +2136,7 @@ int sqlite3VdbeHalt(Vdbe *p){
if( p->db->mallocFailed ){
p->rc = SQLITE_NOMEM;
}
if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag);
closeAllCursors(p);
if( p->magic!=VDBE_MAGIC_RUN ){
return SQLITE_OK;
+8 -1
View File
@@ -236,6 +236,7 @@ void sqlite3VtabClear(sqlite3 *db, Table *p){
if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
if( p->azModuleArg ){
int i;
assert( p->nModuleArg<2 || p->azModuleArg[1]==0 );
for(i=0; i<p->nModuleArg; i++){
sqlite3DbFree(db, p->azModuleArg[i]);
}
@@ -296,7 +297,7 @@ void sqlite3VtabBeginParse(
pTable->tabFlags |= TF_Virtual;
pTable->nModuleArg = 0;
addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
addModuleArgument(db, pTable, sqlite3DbStrDup(db, db->aDb[iDb].zName));
addModuleArgument(db, pTable, 0);
addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName));
pParse->sNameToken.n = (int)(&pModuleName->z[pModuleName->n] - pName1->z);
@@ -453,6 +454,7 @@ static int vtabCallConstructor(
int nArg = pTab->nModuleArg;
char *zErr = 0;
char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
int iDb;
if( !zModuleName ){
return SQLITE_NOMEM;
@@ -466,6 +468,10 @@ static int vtabCallConstructor(
pVTable->db = db;
pVTable->pMod = pMod;
assert( pTab->azModuleArg[1]==0 );
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
pTab->azModuleArg[1] = db->aDb[iDb].zName;
/* Invoke the virtual table constructor */
assert( &db->pVtabCtx );
assert( xConstruct );
@@ -475,6 +481,7 @@ static int vtabCallConstructor(
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
db->pVtabCtx = 0;
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
pTab->azModuleArg[1] = 0;
if( SQLITE_OK!=rc ){
if( zErr==0 ){
+1 -3
View File
@@ -2005,7 +2005,6 @@ static void constructAutomaticIndex(
int nByte; /* Byte of memory needed for pIdx */
Index *pIdx; /* Object describing the transient index */
Vdbe *v; /* Prepared statement under construction */
int regIsInit; /* Register set by initialization */
int addrInit; /* Address of the initialization bypass jump */
Table *pTable; /* The table being indexed */
KeyInfo *pKeyinfo; /* Key information for the index */
@@ -2022,8 +2021,7 @@ static void constructAutomaticIndex(
** transient index on 2nd and subsequent iterations of the loop. */
v = pParse->pVdbe;
assert( v!=0 );
regIsInit = ++pParse->nMem;
addrInit = sqlite3VdbeAddOp1(v, OP_Once, regIsInit);
addrInit = sqlite3CodeOnce(pParse);
/* Count the number of columns that will be added to the index
** and used to match WHERE clause constraints */
+34
View File
@@ -489,5 +489,39 @@ do_execsql_test 4.2 {
SELECT * FROM x2 WHERE x2 MATCH 'a b c d e f g h i j k l m n o p q r s';
} {{a b c d e f g h i j k l m n o p q r s t u v w x y m}}
set tokenizers {1 simple}
ifcapable icu { lappend tokenizers 2 {icu en_US} }
foreach {tn tokenizer} $tokenizers {
do_execsql_test 5.$tn.1 "
CREATE VIRTUAL TABLE x3 USING FTS4(a, b, TOKENIZE $tokenizer)
"
do_execsql_test 5.$tn.2 {
BEGIN;
INSERT INTO x3 VALUES('b b b b b b b b b b b', 'b b b b b b b b b b b b b');
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 SELECT * FROM x3;
INSERT INTO x3 VALUES('a b c', NULL);
INSERT INTO x3 VALUES('a x c', NULL);
COMMIT;
SELECT * FROM x3 WHERE x3 MATCH 'a b';
} {{a b c} {}}
do_execsql_test 5.$tn.3 { DROP TABLE x3 }
}
finish_test
+154
View File
@@ -0,0 +1,154 @@
# 2011 December 9
#
# 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 SQLite library.
#
# This file implements tests to verify that ticket [7bbfb7d442] has been
# fixed.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix tkt-7bbfb7d442
do_execsql_test 1.1 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 'one');
INSERT INTO t1 VALUES(2, 'two');
INSERT INTO t1 VALUES(3, 'three');
CREATE TABLE t2(c, d);
INSERT INTO t2 VALUES('one', 'I');
INSERT INTO t2 VALUES('two', 'II');
INSERT INTO t2 VALUES('three', 'III');
CREATE TABLE t3(t3_a PRIMARY KEY, t3_d);
CREATE TRIGGER t3t AFTER INSERT ON t3 WHEN new.t3_d IS NULL BEGIN
UPDATE t3 SET t3_d = (
SELECT d FROM
(SELECT * FROM t2 WHERE (new.t3_a%2)=(rowid%2) LIMIT 10),
(SELECT * FROM t1 WHERE (new.t3_a%2)=(rowid%2) LIMIT 10)
WHERE a = new.t3_a AND b = c
) WHERE t3_a = new.t3_a;
END;
}
do_execsql_test 1.2 {
INSERT INTO t3(t3_a) VALUES(1);
INSERT INTO t3(t3_a) VALUES(2);
INSERT INTO t3(t3_a) VALUES(3);
SELECT * FROM t3;
} {1 I 2 II 3 III}
do_execsql_test 1.3 { DELETE FROM t3 }
do_execsql_test 1.4 {
INSERT INTO t3(t3_a) SELECT 1 UNION SELECT 2 UNION SELECT 3;
SELECT * FROM t3;
} {1 I 2 II 3 III}
#-------------------------------------------------------------------------
# The following test case - 2.* - is from the original bug report as
# posted to the mailing list.
#
do_execsql_test 2.1 {
CREATE TABLE InventoryControl (
InventoryControlId INTEGER PRIMARY KEY AUTOINCREMENT,
SKU INTEGER NOT NULL,
Variant INTEGER NOT NULL DEFAULT 0,
ControlDate DATE NOT NULL,
ControlState INTEGER NOT NULL DEFAULT -1,
DeliveredQty VARCHAR(30)
);
CREATE TRIGGER TGR_InventoryControl_AfterInsert
AFTER INSERT ON InventoryControl
FOR EACH ROW WHEN NEW.ControlState=-1 BEGIN
INSERT OR REPLACE INTO InventoryControl(
InventoryControlId,SKU,Variant,ControlDate,ControlState,DeliveredQty
) SELECT
T1.InventoryControlId AS InventoryControlId,
T1.SKU AS SKU,
T1.Variant AS Variant,
T1.ControlDate AS ControlDate,
1 AS ControlState,
COALESCE(T2.DeliveredQty,0) AS DeliveredQty
FROM (
SELECT
NEW.InventoryControlId AS InventoryControlId,
II.SKU AS SKU,
II.Variant AS Variant,
COALESCE(LastClosedIC.ControlDate,NEW.ControlDate) AS ControlDate
FROM
InventoryItem II
LEFT JOIN
InventoryControl LastClosedIC
ON LastClosedIC.InventoryControlId IN ( SELECT 99999 )
WHERE
II.SKU=NEW.SKU AND
II.Variant=NEW.Variant
) T1
LEFT JOIN (
SELECT
TD.SKU AS SKU,
TD.Variant AS Variant,
10 AS DeliveredQty
FROM
TransactionDetail TD
WHERE
TD.SKU=NEW.SKU AND
TD.Variant=NEW.Variant
) T2
ON T2.SKU=T1.SKU AND
T2.Variant=T1.Variant;
END;
CREATE TABLE InventoryItem (
SKU INTEGER NOT NULL,
Variant INTEGER NOT NULL DEFAULT 0,
DeptCode INTEGER NOT NULL,
GroupCode INTEGER NOT NULL,
ItemDescription VARCHAR(120) NOT NULL,
PRIMARY KEY(SKU, Variant)
);
INSERT INTO InventoryItem VALUES(220,0,1,170,'Scoth Tampon Recurer');
INSERT INTO InventoryItem VALUES(31,0,1,110,'Fromage');
CREATE TABLE TransactionDetail (
TransactionId INTEGER NOT NULL,
SKU INTEGER NOT NULL,
Variant INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY(TransactionId, SKU, Variant)
);
INSERT INTO TransactionDetail(TransactionId, SKU, Variant) VALUES(44, 31, 0);
INSERT INTO InventoryControl(SKU, Variant, ControlDate) SELECT
II.SKU AS SKU, II.Variant AS Variant, '2011-08-30' AS ControlDate
FROM InventoryItem II;
}
do_execsql_test 2.2 {
SELECT SKU, DeliveredQty FROM InventoryControl WHERE SKU=31
} {31 10}
do_execsql_test 2.3 {
SELECT CASE WHEN DeliveredQty=10 THEN "TEST PASSED!" ELSE "TEST FAILED!" END
FROM InventoryControl WHERE SKU=31;
} {{TEST PASSED!}}
finish_test
+3 -3
View File
@@ -210,7 +210,7 @@ do_test trigger1-1.12 {
delete from t1 WHERE a=old.a+2;
end;
}
} {1 {cannot create INSTEAD OF trigger on table: main.t1}}
} {1 {cannot create INSTEAD OF trigger on table: t1}}
ifcapable view {
# Ensure that we cannot create BEFORE triggers on views
@@ -221,7 +221,7 @@ do_test trigger1-1.13 {
delete from t1 WHERE a=old.a+2;
end;
}
} {1 {cannot create BEFORE trigger on view: main.v1}}
} {1 {cannot create BEFORE trigger on view: v1}}
# Ensure that we cannot create AFTER triggers on views
do_test trigger1-1.14 {
catchsql {
@@ -231,7 +231,7 @@ do_test trigger1-1.14 {
delete from t1 WHERE a=old.a+2;
end;
}
} {1 {cannot create AFTER trigger on view: main.v1}}
} {1 {cannot create AFTER trigger on view: v1}}
} ;# ifcapable view
# Check for memory leaks in the trigger parser
+42
View File
@@ -949,6 +949,48 @@ do_catchsql_test triggerC-13.2 {
UPDATE t12 SET a=a+1, b=b+1;
} {1 {too many levels of trigger recursion}}
#-------------------------------------------------------------------------
# The following tests seek to verify that constant values (i.e. literals)
# are not factored out of loops within trigger programs. SQLite does
# not factor constants out of loops within trigger programs as it may only
# do so in code generated before the first table or index is opened. And
# by the time a trigger program is coded, at least one table or index has
# always been opened.
#
# At one point, due to a bug allowing constant factoring within triggers,
# the following SQL would produce the wrong result.
#
set SQL {
CREATE TABLE t1(a, b, c);
CREATE INDEX i1 ON t1(a, c);
CREATE INDEX i2 ON t1(b, c);
INSERT INTO t1 VALUES(1, 2, 3);
CREATE TABLE t2(e, f);
CREATE INDEX i3 ON t2(e);
INSERT INTO t2 VALUES(1234567, 3);
CREATE TABLE empty(x);
CREATE TABLE not_empty(x);
INSERT INTO not_empty VALUES(2);
CREATE TABLE t4(x);
CREATE TABLE t5(g, h, i);
CREATE TRIGGER trig BEFORE INSERT ON t4 BEGIN
INSERT INTO t5 SELECT * FROM t1 WHERE
(a IN (SELECT x FROM empty) OR b IN (SELECT x FROM not_empty))
AND c IN (SELECT f FROM t2 WHERE e=1234567);
END;
INSERT INTO t4 VALUES(0);
SELECT * FROM t5;
}
reset_db
do_execsql_test triggerC-14.1 $SQL {1 2 3}
reset_db
optimization_control db factor-constants 0
do_execsql_test triggerC-14.2 $SQL {1 2 3}
finish_test