From 46c47d4677a1eb17828ea121e0e97e90eee34639 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 1 Mar 2011 18:42:07 +0000 Subject: [PATCH 001/570] Add the experimental sqlite3_preupdate_hook() API. FossilOrigin-Name: 6145d7b89f83500318713779c60f79a7ab2098ba --- install-sh | 0 manifest | 57 +++++----- manifest.uuid | 2 +- src/delete.c | 13 ++- src/insert.c | 14 ++- src/main.c | 19 ++++ src/sqlite.h.in | 24 ++++ src/sqliteInt.h | 7 ++ src/tclsqlite.c | 184 +++++++++++++++++++++++++----- src/update.c | 13 ++- src/vdbe.c | 90 ++++++++++----- src/vdbeInt.h | 13 +++ src/vdbeapi.c | 115 ++++++++++++++++--- src/vdbeaux.c | 34 +++++- test/hook.test | 267 ++++++++++++++++++++++++++++++++++++++++++++ test/progress.test | 0 test/tclsqlite.test | 2 +- tool/mkopts.tcl | 0 18 files changed, 737 insertions(+), 117 deletions(-) mode change 100755 => 100644 install-sh mode change 100644 => 100755 test/progress.test mode change 100644 => 100755 tool/mkopts.tcl diff --git a/install-sh b/install-sh old mode 100755 new mode 100644 diff --git a/manifest b/manifest index 1d2716b2db..2608f60580 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Comment\sout\ssome\scode\sin\sos_unix.c\sthat\sonly\sruns\son\sMacOSX\swith\nSQLITE_ENABLE_LOCKING_STYLE. -D 2011-02-25T03:25:07.454 +C Add\sthe\sexperimental\ssqlite3_preupdate_hook()\sAPI. +D 2011-03-01T18:42:07 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -101,7 +98,7 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x +F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk 54190fab7cdba523e311c274c95ea480f32abfb5 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a @@ -131,7 +128,7 @@ F src/callback.c a1d1b1c9c85415dff013af033e2fed9c8382d33b F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 7deec4534f3b5a0c3b4a4cbadf809d321f64f9c4 F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b -F src/delete.c 7ed8a8c8b5f748ece92df173d7e0f7810c899ebd +F src/delete.c 3c0925e958a77804a004222baa1a2a8ad855306b F src/expr.c 8e2c607b3be87a35c75a1f5dac50c10666b083c0 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 17950a28f28b23e8ad3feaac5fc88c324d2f600a @@ -140,12 +137,12 @@ F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c a4995747c062256582a90b4f87f716e11b067050 +F src/insert.c c56a64b1488921794c3855d54acfe4674c7cea0c F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e F src/loadext.c 8af9fcc75708d60b88636ccba38b4a7b3c155c3e -F src/main.c 93d0d967d6898fc0408ece248342342e312aa753 +F src/main.c 9ab948225b8c362cdd6902c447abbf218607e0f3 F src/malloc.c 92d59a007d7a42857d4e9454aa25b6b703286be1 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206 @@ -180,13 +177,13 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 649c51979812f77f97507024a4cea480c6862b8b -F src/sqlite.h.in ccb23cc9378874c7c72682b739f311474a80848d +F src/sqlite.h.in 3a8a9f25a45735879cec195a2c129b48e34ebf8e F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h 4290fff17fabc6e07fc4338233df0e39e6350ca1 +F src/sqliteInt.h 3a262a299fa5b1f6916157ec2302e8987e50bac9 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e -F src/tclsqlite.c 879bf8a23d99fc0e99d9177fe1b48896bc796d65 +F src/tclsqlite.c 20a3bf120f3bba1914f0e5132dbe937dee135f36 F src/test1.c 9020310c7617234b33fd1c3064f89524db25f290 F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc @@ -228,15 +225,15 @@ F src/test_vfs.c 2ed8853c1e51ac6f9ea091f7ce4e0d618bba8b86 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080 F src/trigger.c b8bedb9c0084ceb51a40f54fcca2ce048c8de852 -F src/update.c 227e6cd512108b84f69421fc6c7aa1b83d60d6e0 +F src/update.c 1b9a82ede7df15e76ed86c6a3cbe4ce0f21eaa9b F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685 F src/util.c ab1c92426494f499f42b9e307537b03e923d75c1 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c 34305497d81daafdb1e500bfaa21d044c64503de +F src/vdbe.c 4330cc94597b9c95853c5e8ff87776f1e6ceaa3f F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 -F src/vdbeInt.h 6e6f28e9bccc6c703dca1372fd661c57b5c15fb0 -F src/vdbeapi.c 8e9324fd35eb70d0b5904bd1af40f2598744dc4d -F src/vdbeaux.c 5936a596324ad9f9aba02bdee8c8080d2a3264e1 +F src/vdbeInt.h 41b8e337332f279228196039ab86acd353ad0c6c +F src/vdbeapi.c c407f3f0e21d5de68b1269bfa12315ef7ed6e3fd +F src/vdbeaux.c 874e16966eb6e58183ee2746abb4e4c5238f2350 F src/vdbeblob.c 18955f0ee6b133cd08e1592010cb9a6b11e9984c F src/vdbemem.c 0fa2ed786cd207d5b988afef3562a8e663a75b50 F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -474,7 +471,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c -F test/hook.test f04c3412463f8ec117c1c704c74ca0f627ce733a +F test/hook.test 5fd01c30f47896d88bed8a09bf7773cff218e8ff F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 @@ -600,7 +597,7 @@ F test/permutations.test 5b2a4cb756ffb2407cb4743163668d1d769febb6 F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea -F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 +F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota.test ddafe133653093eb9a99ccd6264884ae43f9c9b8 @@ -670,7 +667,7 @@ F test/superlock.test 5d7a4954b0059c903f82c7b67867bc5451a7c082 F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3 F test/table.test 04ba066432430657712d167ebf28080fe878d305 F test/tableapi.test 7262a8cbaa9965d429f1cbd2747edc185fa56516 -F test/tclsqlite.test 8c154101e704170c2be10f137a5499ac2c6da8d3 +F test/tclsqlite.test 1ce9b6340d6d412420634e129a2e3722c651056a F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05 @@ -887,7 +884,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309 -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e +F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff @@ -912,14 +909,10 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P af4756184a255f5d8a5cd276bf9f2fc3b38d9169 -R 86eab7753acb1a027109135cae01654a -U drh -Z 475e4dbe6e8fc13f5f8796d1c18d588c ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFNZyEhoxKgR168RlERAohiAKCDC55xIULyuJJBl/uNZNCMqVF+ZgCeK05+ -18x49YRlHX+qQrvL/cMA0OY= -=QUmN ------END PGP SIGNATURE----- +P 4e50b0362ab6604a4b6c9f4ad849ec1733d6ce1a +R 0e3c3fa7441b432fef74ccddd445caf6 +T *branch * experimental +T *sym-experimental * +T -sym-trunk * +U dan +Z 1b63beda3df1a2343540c0064b366df4 diff --git a/manifest.uuid b/manifest.uuid index a2c2d650a2..c59fca196c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4e50b0362ab6604a4b6c9f4ad849ec1733d6ce1a \ No newline at end of file +6145d7b89f83500318713779c60f79a7ab2098ba \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index bd7ac3d1f3..c7a686a8bd 100644 --- a/src/delete.c +++ b/src/delete.c @@ -531,13 +531,18 @@ void sqlite3GenerateRowDelete( /* Delete the index and table entries. Skip this step if pTab is really ** a view (in which case the only effect of the DELETE statement is to - ** fire the INSTEAD OF triggers). */ + ** fire the INSTEAD OF triggers). + ** + ** If variable 'count' is non-zero, then this OP_Delete instruction should + ** invoke the update-hook. The pre-update-hook, on the other hand should + ** be invoked unless table pTab is a system table. The difference is that + ** the update-hook is not invoked for rows removed by REPLACE, but the + ** pre-update-hook is. + */ if( pTab->pSelect==0 ){ sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0); sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); - if( count ){ - sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); - } + sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); } /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to diff --git a/src/insert.c b/src/insert.c index adf6ef2ed4..98f00bfe3d 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1287,9 +1287,17 @@ void sqlite3GenerateConstraintChecks( sqlite3GenerateRowDelete( pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace ); - }else if( pTab->pIndex ){ - sqlite3MultiWrite(pParse); - sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0); + }else{ + /* This OP_Delete opcode fires the pre-update-hook only. It does + ** not modify the b-tree. It is more efficient to let the coming + ** OP_Insert replace the existing entry than it is to delete the + ** existing entry and then insert a new one. */ + sqlite3VdbeAddOp2(v, OP_Delete, baseCur, OPFLAG_ISNOOP); + sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); + if( pTab->pIndex ){ + sqlite3MultiWrite(pParse); + sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0); + } } seenReplace = 1; break; diff --git a/src/main.c b/src/main.c index 833b9812b0..3976f7ebc3 100644 --- a/src/main.c +++ b/src/main.c @@ -1271,6 +1271,25 @@ void *sqlite3_rollback_hook( return pRet; } +/* +** Register a callback to be invoked each time a row is updated, +** inserted or deleted using this database connection. +*/ +void *sqlite3_preupdate_hook( + sqlite3 *db, /* Attach the hook to this database */ + void(*xCallback)( /* Callback function */ + void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64), + void *pArg /* First callback argument */ +){ + void *pRet; + sqlite3_mutex_enter(db->mutex); + pRet = db->pPreUpdateArg; + db->xPreUpdateCallback = xCallback; + db->pPreUpdateArg = pArg; + sqlite3_mutex_leave(db->mutex); + return pRet; +} + #ifndef SQLITE_OMIT_WAL /* ** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 3400c6c916..413031ecfa 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6344,6 +6344,30 @@ int sqlite3_wal_checkpoint_v2( #define SQLITE_CHECKPOINT_FULL 1 #define SQLITE_CHECKPOINT_RESTART 2 +void *sqlite3_preupdate_hook( + sqlite3 *db, + void(*xPreUpdate)( + void *pCtx, /* Copy of third arg to preupdate_hook() */ + sqlite3 *db, /* Database handle */ + int op, /* SQLITE_UPDATE, DELETE or INSERT */ + char const *zDb, /* Database name */ + char const *zName, /* Table name */ + sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ + sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ + ), + void* +); + +/* +** The following APIs may only be used from within a pre-update callback. More +** specifically, the preupdate_old() API may only be used from within an +** SQLITE_UPDATE or SQLITE_DELETE pre-update callback. The preupdate_modified() +** API may only be used from within an SQLITE_UPDATE pre-update callback. +*/ +int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); +int sqlite3_preupdate_modified(sqlite3 *, int, int *); +int sqlite3_preupdate_count(sqlite3 *); + /* ** Undo the hack that converts floating point types to integer for diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 2987dcd483..2541936848 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -619,6 +619,7 @@ typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; typedef struct Parse Parse; +typedef struct PreUpdate PreUpdate; typedef struct RowSet RowSet; typedef struct Savepoint Savepoint; typedef struct Select Select; @@ -827,6 +828,11 @@ struct sqlite3 { void (*xRollbackCallback)(void*); /* Invoked at every commit. */ void *pUpdateArg; void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); + void *pPreUpdateArg; /* First argument to xPreUpdateCallback */ + void (*xPreUpdateCallback)( /* Registered using sqlite3_preupdate_hook() */ + void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64 + ); + PreUpdate *pPreUpdate; /* Context for active pre-update callback */ #ifndef SQLITE_OMIT_WAL int (*xWalCallback)(void *, sqlite3 *, const char *, int); void *pWalArg; @@ -2254,6 +2260,7 @@ struct AuthContext { #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ +#define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */ /* * Each trigger present in the database schema is stored as an instance of diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 57f38d78d1..91c6094fa9 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -122,6 +122,7 @@ struct SqliteDb { char *zNull; /* Text to substitute for an SQL NULL value */ SqlFunc *pFunc; /* List of SQL functions */ Tcl_Obj *pUpdateHook; /* Update hook script (if any) */ + Tcl_Obj *pPreUpdateHook; /* Pre-update hook script (if any) */ Tcl_Obj *pRollbackHook; /* Rollback hook script (if any) */ Tcl_Obj *pWalHook; /* WAL hook script (if any) */ Tcl_Obj *pUnlockNotify; /* Unlock notify script (if any) */ @@ -483,6 +484,9 @@ static void DbDeleteCmd(void *db){ if( pDb->pUpdateHook ){ Tcl_DecrRefCount(pDb->pUpdateHook); } + if( pDb->pPreUpdateHook ){ + Tcl_DecrRefCount(pDb->pPreUpdateHook); + } if( pDb->pRollbackHook ){ Tcl_DecrRefCount(pDb->pRollbackHook); } @@ -649,6 +653,40 @@ static void DbUnlockNotify(void **apArg, int nArg){ } #endif +/* +** Pre-update hook callback. +*/ +static void DbPreUpdateHandler( + void *p, + sqlite3 *db, + int op, + const char *zDb, + const char *zTbl, + sqlite_int64 iKey1, + sqlite_int64 iKey2 +){ + SqliteDb *pDb = (SqliteDb *)p; + Tcl_Obj *pCmd; + static const char *azStr[] = {"DELETE", "INSERT", "UPDATE"}; + + assert( (SQLITE_DELETE-1)/9 == 0 ); + assert( (SQLITE_INSERT-1)/9 == 1 ); + assert( (SQLITE_UPDATE-1)/9 == 2 ); + assert( pDb->pPreUpdateHook ); + assert( db==pDb->db ); + assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE ); + + pCmd = Tcl_DuplicateObj(pDb->pPreUpdateHook); + Tcl_IncrRefCount(pCmd); + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1)); + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1)); + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1)); + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey1)); + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey2)); + Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT); + Tcl_DecrRefCount(pCmd); +} + static void DbUpdateHandler( void *p, int op, @@ -658,14 +696,18 @@ static void DbUpdateHandler( ){ SqliteDb *pDb = (SqliteDb *)p; Tcl_Obj *pCmd; + static const char *azStr[] = {"DELETE", "INSERT", "UPDATE"}; + + assert( (SQLITE_DELETE-1)/9 == 0 ); + assert( (SQLITE_INSERT-1)/9 == 1 ); + assert( (SQLITE_UPDATE-1)/9 == 2 ); assert( pDb->pUpdateHook ); assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE ); pCmd = Tcl_DuplicateObj(pDb->pUpdateHook); Tcl_IncrRefCount(pCmd); - Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj( - ( (op==SQLITE_INSERT)?"INSERT":(op==SQLITE_UPDATE)?"UPDATE":"DELETE"), -1)); + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1)); Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1)); Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1)); Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(rowid)); @@ -1550,6 +1592,44 @@ static int DbEvalNextCmd( return rc; } +/* +** This function is used by the implementations of the following database +** handle sub-commands: +** +** $db update_hook ?SCRIPT? +** $db wal_hook ?SCRIPT? +** $db commit_hook ?SCRIPT? +** $db preupdate hook ?SCRIPT? +*/ +static void DbHookCmd( + Tcl_Interp *interp, /* Tcl interpreter */ + SqliteDb *pDb, /* Database handle */ + Tcl_Obj *pArg, /* SCRIPT argument (or NULL) */ + Tcl_Obj **ppHook /* Pointer to member of SqliteDb */ +){ + sqlite3 *db = pDb->db; + + if( *ppHook ){ + Tcl_SetObjResult(interp, *ppHook); + if( pArg ){ + Tcl_DecrRefCount(*ppHook); + *ppHook = 0; + } + } + if( pArg ){ + assert( !(*ppHook) ); + if( Tcl_GetCharLength(pArg)>0 ){ + *ppHook = pArg; + Tcl_IncrRefCount(*ppHook); + } + } + + sqlite3_preupdate_hook(db, (pDb->pPreUpdateHook?DbPreUpdateHandler:0), pDb); + sqlite3_update_hook(db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb); + sqlite3_rollback_hook(db, (pDb->pRollbackHook?DbRollbackHandler:0), pDb); + sqlite3_wal_hook(db, (pDb->pWalHook?DbWalHandler:0), pDb); +} + /* ** The "sqlite" command below creates a new Tcl command for each ** connection it opens to an SQLite database. This routine is invoked @@ -1575,6 +1655,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ "errorcode", "eval", "exists", "function", "incrblob", "interrupt", "last_insert_rowid", "nullvalue", "onecolumn", + "preupdate", "profile", "progress", "rekey", "restore", "rollback_hook", "status", "timeout", "total_changes", "trace", @@ -1589,6 +1670,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ DB_ERRORCODE, DB_EVAL, DB_EXISTS, DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN, + DB_PREUPDATE, DB_PROFILE, DB_PROGRESS, DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK, DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, @@ -2763,6 +2845,71 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ break; } + case DB_PREUPDATE: { + static const char *azSub[] = {"count", "hook", "modified", "old", 0}; + enum DbPreupdateSubCmd { + PRE_COUNT, PRE_HOOK, PRE_MODIFIED, PRE_OLD + }; + int iSub; + + if( objc<3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "SUB-COMMAND ?ARGS?"); + } + if( Tcl_GetIndexFromObj(interp, objv[2], azSub, "sub-command", 0, &iSub) ){ + return TCL_ERROR; + } + + switch( (enum DbPreupdateSubCmd)iSub ){ + case PRE_COUNT: { + int nCol = sqlite3_preupdate_count(pDb->db); + Tcl_SetObjResult(interp, Tcl_NewIntObj(nCol)); + break; + } + + case PRE_HOOK: { + if( objc>4 ){ + Tcl_WrongNumArgs(interp, 2, objv, "hook ?SCRIPT?"); + return TCL_ERROR; + } + DbHookCmd(interp, pDb, (objc==4 ? objv[3] : 0), &pDb->pPreUpdateHook); + break; + } + + case PRE_MODIFIED: + case PRE_OLD: { + int iIdx; + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 3, objv, "INDEX"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[3], &iIdx) ){ + return TCL_ERROR; + } + + if( iSub==PRE_MODIFIED ){ + int iRes; + rc = sqlite3_preupdate_modified(pDb->db, iIdx, &iRes); + if( rc==SQLITE_OK ) Tcl_SetObjResult(interp, Tcl_NewIntObj(iRes)); + }else{ + sqlite3_value *pValue; + assert( iSub==PRE_OLD ); + rc = sqlite3_preupdate_old(pDb->db, iIdx, &pValue); + if( rc==SQLITE_OK ){ + Tcl_Obj *pObj = Tcl_NewStringObj(sqlite3_value_text(pValue), -1); + Tcl_SetObjResult(interp, pObj); + } + } + + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0); + return TCL_ERROR; + } + } + } + + break; + } + /* ** $db wal_hook ?script? ** $db update_hook ?script? @@ -2771,42 +2918,21 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ case DB_WAL_HOOK: case DB_UPDATE_HOOK: case DB_ROLLBACK_HOOK: { + sqlite3 *db = pDb->db; /* set ppHook to point at pUpdateHook or pRollbackHook, depending on ** whether [$db update_hook] or [$db rollback_hook] was invoked. */ Tcl_Obj **ppHook; - if( choice==DB_UPDATE_HOOK ){ - ppHook = &pDb->pUpdateHook; - }else if( choice==DB_WAL_HOOK ){ - ppHook = &pDb->pWalHook; - }else{ - ppHook = &pDb->pRollbackHook; - } - - if( objc!=2 && objc!=3 ){ + if( choice==DB_WAL_HOOK ) ppHook = &pDb->pWalHook; + if( choice==DB_UPDATE_HOOK ) ppHook = &pDb->pUpdateHook; + if( choice==DB_ROLLBACK_HOOK ) ppHook = &pDb->pRollbackHook; + if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); return TCL_ERROR; } - if( *ppHook ){ - Tcl_SetObjResult(interp, *ppHook); - if( objc==3 ){ - Tcl_DecrRefCount(*ppHook); - *ppHook = 0; - } - } - if( objc==3 ){ - assert( !(*ppHook) ); - if( Tcl_GetCharLength(objv[2])>0 ){ - *ppHook = objv[2]; - Tcl_IncrRefCount(*ppHook); - } - } - - sqlite3_update_hook(pDb->db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb); - sqlite3_rollback_hook(pDb->db,(pDb->pRollbackHook?DbRollbackHandler:0),pDb); - sqlite3_wal_hook(pDb->db,(pDb->pWalHook?DbWalHandler:0),pDb); + DbHookCmd(interp, pDb, (objc==3 ? objv[2] : 0), ppHook); break; } diff --git a/src/update.c b/src/update.c index 8bf58d7666..ea8f95ad56 100644 --- a/src/update.c +++ b/src/update.c @@ -490,9 +490,16 @@ void sqlite3Update( j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid); sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx); - /* If changing the record number, delete the old record. */ - if( hasFK || chngRowid ){ - sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0); + /* If changing the rowid value, or if there are foreign key constraints + ** to process, delete the old record. Otherwise, add a noop OP_Delete + ** to invoke the pre-update hook. + */ + sqlite3VdbeAddOp3(v, OP_Delete, iCur, + OPFLAG_ISUPDATE | ((hasFK || chngRowid) ? 0 : OPFLAG_ISNOOP), + regNewRowid + ); + if( !pParse->nested ){ + sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); } sqlite3VdbeJumpHere(v, j1); diff --git a/src/vdbe.c b/src/vdbe.c index 00ed1438b5..c5492eedc8 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3868,6 +3868,24 @@ case OP_InsertInt: { iKey = pOp->p3; } + if( pOp->p4.z && (db->xPreUpdateCallback || db->xUpdateCallback) ){ + assert( pC->isTable ); + assert( pC->iDb>=0 ); + zDb = db->aDb[pC->iDb].zName; + zTbl = pOp->p4.z; + op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); + } + + /* Invoke the pre-update hook, if any */ + if( db->xPreUpdateCallback + && pOp->p4.z + && (!(pOp->p5 & OPFLAG_ISUPDATE) || pC->rowidIsValid==0) + ){ + sqlite3VdbePreUpdateHook(p, pC, + pC->rowidIsValid ? op : SQLITE_INSERT, zDb, zTbl, iKey, iKey + ); + } + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = iKey; if( pData->flags & MEM_Null ){ @@ -3893,17 +3911,12 @@ case OP_InsertInt: { /* Invoke the update-hook if required. */ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ - zDb = db->aDb[pC->iDb].zName; - zTbl = pOp->p4.z; - op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); - assert( pC->isTable ); db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey); - assert( pC->iDb>=0 ); } break; } -/* Opcode: Delete P1 P2 * P4 * +/* Opcode: Delete P1 P2 P3 P4 * ** ** Delete the record at which the P1 cursor is currently pointing. ** @@ -3918,30 +3931,31 @@ case OP_InsertInt: { ** P1 must not be pseudo-table. It has to be a real table with ** multiple rows. ** -** If P4 is not NULL, then it is the name of the table that P1 is -** pointing to. The update hook will be invoked, if it exists. -** If P4 is not NULL then the P1 cursor must have been positioned -** using OP_NotFound prior to invoking this opcode. +** If P4 is not NULL then, either the update or pre-update hook, or both, +** may be invoked. The P1 cursor must have been positioned using OP_NotFound +** prior to invoking this opcode in this case. Specifically, if one is +** configured, the pre-update hook is invoked if P4 is not NULL. The +** update-hook is invoked if one is configured, P4 is not NULL, and the +** OPFLAG_NCHANGE flag is set in P2. +** +** If the OPFLAG_ISUPDATE flag is set in P2, then P3 contains the address +** of the memory cell that contains the value that the rowid of the row will +** be set to by the update. */ case OP_Delete: { i64 iKey; VdbeCursor *pC; + const char *zDb; + const char *zTbl; + int opflags; + opflags = pOp->p2; iKey = 0; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */ - /* If the update-hook will be invoked, set iKey to the rowid of the - ** row being deleted. - */ - if( db->xUpdateCallback && pOp->p4.z ){ - assert( pC->isTable ); - assert( pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */ - iKey = pC->lastRowid; - } - /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or ** OP_Column on the same table without any intervening operations that ** might move or invalidate the cursor. Hence cursor pC is always pointing @@ -3953,18 +3967,42 @@ case OP_Delete: { rc = sqlite3VdbeCursorMoveto(pC); if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; + /* If the update-hook or pre-update-hook will be invoked, set iKey to + ** the rowid of the row being deleted. Set zDb and zTab as well. + */ + if( pOp->p4.z && (db->xPreUpdateCallback || db->xUpdateCallback) ){ + assert( pC->iDb>=0 ); + assert( pC->isTable ); + assert( pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */ + iKey = pC->lastRowid; + zDb = db->aDb[pC->iDb].zName; + zTbl = pOp->p4.z; + } + + /* Invoke the pre-update-hook if required. */ + if( db->xPreUpdateCallback && pOp->p4.z ){ + assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) ); + sqlite3VdbePreUpdateHook(p, pC, + (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, + zDb, zTbl, iKey, + (opflags & OPFLAG_ISUPDATE) ? aMem[pOp->p3].u.i : iKey + ); + } + + if( opflags & OPFLAG_ISNOOP ) break; + sqlite3BtreeSetCachedRowid(pC->pCursor, 0); rc = sqlite3BtreeDelete(pC->pCursor); pC->cacheStatus = CACHE_STALE; - /* Invoke the update-hook if required. */ - if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ - const char *zDb = db->aDb[pC->iDb].zName; - const char *zTbl = pOp->p4.z; - db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey); - assert( pC->iDb>=0 ); + /* Update the change-counter and invoke the update-hook if required. */ + if( opflags & OPFLAG_NCHANGE ){ + p->nChange++; + assert( pOp->p4.z ); + if( rc==SQLITE_OK && db->xUpdateCallback ){ + db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey); + } } - if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; break; } /* Opcode: ResetCount * * * * * diff --git a/src/vdbeInt.h b/src/vdbeInt.h index b42729d236..a764d23665 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -331,6 +331,17 @@ struct Vdbe { #define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */ #define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ +/* +** Structure used to store the context required by the +** sqlite3_preupdate_*() API functions. +*/ +struct PreUpdate { + VdbeCursor *pCsr; /* Cursor to read old values from */ + int op; /* One of SQLITE_INSERT, UPDATE, DELETE */ + u8 *aRecord; /* old.* database record */ + UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ +}; + /* ** Function prototypes */ @@ -387,6 +398,8 @@ int sqlite3VdbeCloseStatement(Vdbe *, int); void sqlite3VdbeFrameDelete(VdbeFrame*); int sqlite3VdbeFrameRestore(VdbeFrame *); void sqlite3VdbeMemStoreType(Mem *pMem); +void sqlite3VdbePreUpdateHook( + Vdbe *, VdbeCursor *, int, const char*, const char*, i64, i64); #ifdef SQLITE_DEBUG void sqlite3VdbeMemPrepareToChange(Vdbe*,Mem*); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 5578b868e1..8b1f2e21bb 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -673,6 +673,26 @@ int sqlite3_data_count(sqlite3_stmt *pStmt){ return pVm->nResColumn; } +/* +** Return a pointer to static memory containing an SQL NULL value. +*/ +static const Mem *columnNullValue(void){ + /* Even though the Mem structure contains an element + ** of type i64, on certain architecture (x86) with certain compiler + ** switches (-Os), gcc may align this Mem object on a 4-byte boundary + ** instead of an 8-byte one. This all works fine, except that when + ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s + ** that a Mem structure is located on an 8-byte boundary. To prevent + ** this assert() from failing, when building with SQLITE_DEBUG defined + ** using gcc, force nullMem to be 8-byte aligned using the magical + ** __attribute__((aligned(8))) macro. */ + static const Mem nullMem +#if defined(SQLITE_DEBUG) && defined(__GNUC__) + __attribute__((aligned(8))) +#endif + = {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0, 0, 0 }; + return &nullMem; +} /* ** Check to see if column iCol of the given statement is valid. If @@ -692,27 +712,13 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ pOut = &pVm->pResultSet[i]; }else{ /* If the value passed as the second argument is out of range, return - ** a pointer to the following static Mem object which contains the - ** value SQL NULL. Even though the Mem structure contains an element - ** of type i64, on certain architecture (x86) with certain compiler - ** switches (-Os), gcc may align this Mem object on a 4-byte boundary - ** instead of an 8-byte one. This all works fine, except that when - ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s - ** that a Mem structure is located on an 8-byte boundary. To prevent - ** this assert() from failing, when building with SQLITE_DEBUG defined - ** using gcc, force nullMem to be 8-byte aligned using the magical - ** __attribute__((aligned(8))) macro. */ - static const Mem nullMem -#if defined(SQLITE_DEBUG) && defined(__GNUC__) - __attribute__((aligned(8))) -#endif - = {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0, 0, 0 }; - + ** a pointer to a static Mem object that contains the value SQL NULL. + */ if( pVm && ALWAYS(pVm->db) ){ sqlite3_mutex_enter(pVm->db->mutex); sqlite3Error(pVm->db, SQLITE_RANGE, 0); } - pOut = (Mem*)&nullMem; + pOut = (Mem*)columnNullValue(); } return pOut; } @@ -1322,3 +1328,78 @@ int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ if( resetFlag ) pVdbe->aCounter[op-1] = 0; return v; } + +int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ + PreUpdate *p = db->pPreUpdate; + int rc = SQLITE_OK; + + if( !p || p->op==SQLITE_INSERT ){ + rc = SQLITE_MISUSE_BKPT; + goto preupdate_old_out; + } + if( iIdx>=p->pCsr->nField || iIdx<0 ){ + rc = SQLITE_RANGE; + goto preupdate_old_out; + } + + if( p->pUnpacked==0 ){ + KeyInfo keyinfo; + u32 nRecord; + u8 *aRecord; + + memset(&keyinfo, 0, sizeof(KeyInfo)); + keyinfo.db = db; + keyinfo.enc = ENC(db); + keyinfo.nField = p->pCsr->nField; + + rc = sqlite3BtreeDataSize(p->pCsr->pCursor, &nRecord); + if( rc!=SQLITE_OK ) goto preupdate_old_out; + aRecord = sqlite3DbMallocRaw(db, nRecord); + if( !aRecord ) goto preupdate_old_out; + rc = sqlite3BtreeData(p->pCsr->pCursor, 0, nRecord, aRecord); + if( rc!=SQLITE_OK ){ + sqlite3DbFree(db, aRecord); + goto preupdate_old_out; + } + + p->pUnpacked = sqlite3VdbeRecordUnpack(&keyinfo, nRecord, aRecord, 0, 0); + p->aRecord = aRecord; + } + + if( iIdx>=p->pUnpacked->nField ){ + *ppValue = (sqlite3_value *)columnNullValue(); + }else{ + *ppValue = &p->pUnpacked->aMem[iIdx]; + sqlite3VdbeMemStoreType(*ppValue); + } + + preupdate_old_out: + sqlite3Error(db, rc, 0); + return sqlite3ApiExit(db, rc); +} + +int sqlite3_preupdate_count(sqlite3 *db){ + PreUpdate *p = db->pPreUpdate; + return (p ? p->pCsr->nField : 0); +} + +int sqlite3_preupdate_modified(sqlite3 *db, int iIdx, int *pbMod){ + PreUpdate *p = db->pPreUpdate; + int rc = SQLITE_OK; + + if( !p || p->op!=SQLITE_UPDATE ){ + rc = SQLITE_MISUSE_BKPT; + goto preupdate_mod_out; + } + if( iIdx>=p->pCsr->nField || iIdx<0 ){ + rc = SQLITE_RANGE; + goto preupdate_mod_out; + } + *pbMod = 1; + + preupdate_mod_out: + sqlite3Error(db, rc, 0); + return sqlite3ApiExit(db, rc); +} + + diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 64ff489919..31cf669144 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2830,7 +2830,7 @@ void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){ ** strings and blobs static. And none of the elements are ** ever transformed, so there is never anything to delete. */ - if( NEVER(pMem->zMalloc) ) sqlite3VdbeMemRelease(pMem); + if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem); } if( p->flags & UNPACKED_NEED_FREE ){ sqlite3DbFree(p->pKeyInfo->db, p); @@ -3162,3 +3162,35 @@ void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ v->expmask |= ((u32)1 << (iVar-1)); } } + +/* +** Invoke the pre-update hook. If this is an UPDATE or DELETE pre-update call, +** then cursor passed as the second argument should point to the row about +** to be update or deleted. If the application calls sqlite3_preupdate_old(), +** the required value will be read from the row the cursor points to. +*/ +void sqlite3VdbePreUpdateHook( + Vdbe *v, /* Vdbe pre-update hook is invoked by */ + VdbeCursor *pCsr, /* Cursor to grab old.* values from */ + int op, /* SQLITE_INSERT, UPDATE or DELETE */ + const char *zDb, /* Database name */ + const char *zTbl, /* Table name */ + i64 iKey1, /* Initial key value */ + i64 iKey2 /* Final key value */ +){ + sqlite3 *db = v->db; + + PreUpdate preupdate; + memset(&preupdate, 0, sizeof(PreUpdate)); + + preupdate.pCsr = pCsr; + preupdate.op = op; + db->pPreUpdate = &preupdate; + db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); + db->pPreUpdate = 0; + sqlite3DbFree(db, preupdate.aRecord); + if( preupdate.pUnpacked ){ + sqlite3VdbeDeleteUnpackedRecord(preupdate.pUnpacked); + } +} + diff --git a/test/hook.test b/test/hook.test index 6496d41e13..827ce08b3d 100644 --- a/test/hook.test +++ b/test/hook.test @@ -21,6 +21,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set ::testprefix hook do_test hook-1.2 { db commit_hook @@ -361,4 +362,270 @@ do_test hook-6.2 { } {COMMIT ROLLBACK} unset ::hooks +#---------------------------------------------------------------------------- +# The following tests - hook-7.* - test the pre-update hook. +# +# 7.1.1 - INSERT statement. +# 7.1.2 - INSERT INTO ... SELECT statement. +# 7.1.3 - REPLACE INTO ... (rowid conflict) +# 7.1.4 - REPLACE INTO ... (other index conflicts) +# 7.1.5 - REPLACE INTO ... (both rowid and other index conflicts) +# +# 7.2.1 - DELETE statement. +# 7.2.2 - DELETE statement that uses the truncate optimization. +# +# 7.3.1 - UPDATE statement. +# 7.3.2 - UPDATE statement that modifies the rowid. +# 7.3.3 - UPDATE OR REPLACE ... (rowid conflict). +# 7.3.4 - UPDATE OR REPLACE ... (other index conflicts) +# 7.3.4 - UPDATE OR REPLACE ... (both rowid and other index conflicts) +# +# 7.4.1 - Test that the pre-update-hook is invoked only once if a row being +# deleted is removed by a BEFORE trigger. +# +# 7.4.2 - Test that the pre-update-hook is invoked if a BEFORE trigger +# removes a row being updated. In this case the update hook should +# be invoked with SQLITE_INSERT as the opcode when inserting the +# new version of the row. +# +# TODO: Short records (those created before a column is added to a table +# using ALTER TABLE) +# + +proc do_preupdate_test {tn sql x} { + set X [list] + foreach elem $x {lappend X $elem} + uplevel do_test $tn [list " + set ::preupdate \[list\] + execsql { $sql } + set ::preupdate + "] [list $X] +} + +proc preupdate_hook {args} { + set type [lindex $args 0] + eval lappend ::preupdate $args + if {$type != "SQLITE_INSERT"} { + for {set i 0} {$i < [db preupdate count]} {incr i} { + lappend ::preupdate [db preupdate old $i] + } + } +} + +db close +forcedelete test.db +sqlite3 db test.db +db preupdate hook preupdate_hook + +# Set up a schema to use for tests 7.1.* to 7.3.*. +do_execsql_test 7.0 { + CREATE TABLE t1(a, b); + CREATE TABLE t2(x, y); + CREATE TABLE t3(i, j, UNIQUE(i)); + + INSERT INTO t2 VALUES('a', 'b'); + INSERT INTO t2 VALUES('c', 'd'); + + INSERT INTO t3 VALUES(4, 16); + INSERT INTO t3 VALUES(5, 25); + INSERT INTO t3 VALUES(6, 36); +} + +do_preupdate_test 7.1.1 { + INSERT INTO t1 VALUES('x', 'y') +} {INSERT main t1 1 1} + +# 7.1.2.1 does not use the xfer optimization. 7.1.2.2 does. +do_preupdate_test 7.1.2.1 { + INSERT INTO t1 SELECT y, x FROM t2; +} {INSERT main t1 2 2 INSERT main t1 3 3} +do_preupdate_test 7.1.2.2 { + INSERT INTO t1 SELECT * FROM t2; +} {INSERT main t1 4 4 INSERT main t1 5 5} + +do_preupdate_test 7.1.3 { + REPLACE INTO t1(rowid, a, b) VALUES(1, 1, 1); +} { + DELETE main t1 1 1 x y + INSERT main t1 1 1 +} + +do_preupdate_test 7.1.4 { + REPLACE INTO t3 VALUES(4, NULL); +} { + DELETE main t3 1 1 4 16 + INSERT main t3 4 4 +} + +do_preupdate_test 7.1.5 { + REPLACE INTO t3(rowid, i, j) VALUES(2, 6, NULL); +} { + DELETE main t3 2 2 5 25 + DELETE main t3 3 3 6 36 + INSERT main t3 2 2 +} + +do_execsql_test 7.2.0 { SELECT rowid FROM t1 } {1 2 3 4 5} + +do_preupdate_test 7.2.1 { + DELETE FROM t1 WHERE rowid = 3 +} { + DELETE main t1 3 3 d c +} +do_preupdate_test 7.2.2 { + DELETE FROM t1 +} { + DELETE main t3 1 1 1 1 + DELETE main t3 2 2 b a + DELETE main t3 4 4 a b + DELETE main t3 5 5 c d +} + +do_execsql_test 7.3.0 { + DELETE FROM t1; + DELETE FROM t2; + DELETE FROM t3; + + INSERT INTO t2 VALUES('a', 'b'); + INSERT INTO t2 VALUES('c', 'd'); + + INSERT INTO t3 VALUES(4, 16); + INSERT INTO t3 VALUES(5, 25); + INSERT INTO t3 VALUES(6, 36); +} + +do_preupdate_test 7.3.1 { + UPDATE t2 SET y = y||y; +} { + UPDATE main t2 1 1 a b + UPDATE main t2 2 2 c d +} + +do_preupdate_test 7.3.2 { + UPDATE t2 SET rowid = rowid-1; +} { + UPDATE main t2 1 0 a bb + UPDATE main t2 2 1 c dd +} + +do_preupdate_test 7.3.3 { + UPDATE OR REPLACE t2 SET rowid = 1 WHERE x = 'a' +} { + DELETE main t2 1 1 c dd + UPDATE main t2 0 1 a bb +} + +do_preupdate_test 7.3.4.1 { + UPDATE OR REPLACE t3 SET i = 5 WHERE i = 6 +} { + DELETE main t3 2 2 5 25 + UPDATE main t3 3 3 6 36 +} + +do_execsql_test 7.3.4.2 { + INSERT INTO t3 VALUES(10, 100); + SELECT rowid, * FROM t3; +} {1 4 16 3 5 36 4 10 100} + +do_preupdate_test 7.3.5 { + UPDATE OR REPLACE t3 SET rowid = 1, i = 5 WHERE j = 100; +} { + DELETE main t3 1 1 4 16 + DELETE main t3 3 3 5 36 + UPDATE main t3 4 1 10 100 +} + +do_execsql_test 7.4.1.0 { + CREATE TABLE t4(a, b); + INSERT INTO t4 VALUES('a', 1); + INSERT INTO t4 VALUES('b', 2); + INSERT INTO t4 VALUES('c', 3); + + CREATE TRIGGER t4t BEFORE DELETE ON t4 BEGIN + DELETE FROM t4 WHERE b = 1; + END; +} + +do_preupdate_test 7.4.1.1 { + DELETE FROM t4 WHERE b = 3 +} { + DELETE main t4 1 1 a 1 + DELETE main t4 3 3 c 3 +} + +do_execsql_test 7.4.1.2 { + INSERT INTO t4(rowid, a, b) VALUES(1, 'a', 1); + INSERT INTO t4(rowid, a, b) VALUES(3, 'c', 3); +} +do_preupdate_test 7.4.1.3 { + DELETE FROM t4 WHERE b = 1 +} { + DELETE main t4 1 1 a 1 +} + +do_execsql_test 7.4.2.0 { + CREATE TABLE t5(a, b); + INSERT INTO t5 VALUES('a', 1); + INSERT INTO t5 VALUES('b', 2); + INSERT INTO t5 VALUES('c', 3); + + CREATE TRIGGER t5t BEFORE UPDATE ON t5 BEGIN + DELETE FROM t5 WHERE b = 1; + END; +} +do_preupdate_test 7.4.2.1 { + UPDATE t5 SET b = 4 WHERE a = 'c' +} { + DELETE main t5 1 1 a 1 + UPDATE main t5 3 3 c 3 +} + +do_execsql_test 7.4.2.2 { + INSERT INTO t5(rowid, a, b) VALUES(1, 'a', 1); +} + +do_preupdate_test 7.4.2.3 { + UPDATE t5 SET b = 5 WHERE a = 'a' +} { + DELETE main t5 1 1 a 1 +} + +do_execsql_test 7.5.1.0 { + CREATE TABLE t7(a, b); + INSERT INTO t7 VALUES('one', 'two'); + INSERT INTO t7 VALUES('three', 'four'); + ALTER TABLE t7 ADD COLUMN c DEFAULT NULL; +} + +do_preupdate_test 7.5.1.1 { + DELETE FROM t7 WHERE a = 'one' +} { + DELETE main t7 1 1 one two {} +} + +do_preupdate_test 7.5.1.2 { + UPDATE t7 SET b = 'five' +} { + UPDATE main t7 2 2 three four {} +} + +do_execsql_test 7.5.2.0 { + CREATE TABLE t8(a, b); + INSERT INTO t8 VALUES('one', 'two'); + INSERT INTO t8 VALUES('three', 'four'); + ALTER TABLE t8 ADD COLUMN c DEFAULT 'xxx'; +} + +do_preupdate_test 7.5.2.1 { + DELETE FROM t8 WHERE a = 'one' +} { + DELETE main t8 1 1 one two xxx +} + +do_preupdate_test 7.5.2.2 { + UPDATE t8 SET b = 'five' +} { + UPDATE main t8 2 2 three four xxx +} + finish_test diff --git a/test/progress.test b/test/progress.test old mode 100644 new mode 100755 diff --git a/test/tclsqlite.test b/test/tclsqlite.test index 8db04ebfa4..c9d562beb5 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -35,7 +35,7 @@ do_test tcl-1.1 { do_test tcl-1.2 { set v [catch {db bogus} msg] lappend v $msg -} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, transaction, unlock_notify, update_hook, version, or wal_hook}} +} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, transaction, unlock_notify, update_hook, version, or wal_hook}} do_test tcl-1.2.1 { set v [catch {db cache bogus} msg] lappend v $msg diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100644 new mode 100755 From 21e8d0126d3d89af3a979ebdac85a6837b5b5ef9 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 3 Mar 2011 20:05:59 +0000 Subject: [PATCH 002/570] Add the experimental sqlite3_transaction_hook() API. FossilOrigin-Name: 093d8cd8e2f3a6af5d40cf810e396f4919eb5cef --- manifest | 31 +++++----- manifest.uuid | 2 +- src/main.c | 42 ++++++++++++++ src/sqlite.h.in | 27 ++++++--- src/sqliteInt.h | 4 ++ src/tclsqlite.c | 37 +++++++++++- src/vdbe.c | 13 +++++ src/vdbeapi.c | 10 +++- src/vdbeaux.c | 9 +++ test/hook.test | 137 +++++++++++++++++++++++++++++++++++++++++++- test/tclsqlite.test | 2 +- 11 files changed, 282 insertions(+), 32 deletions(-) diff --git a/manifest b/manifest index 2608f60580..132ab8f068 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sexperimental\ssqlite3_preupdate_hook()\sAPI. -D 2011-03-01T18:42:07 +C Add\sthe\sexperimental\ssqlite3_transaction_hook()\sAPI. +D 2011-03-03T20:06:00 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -142,7 +142,7 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e F src/loadext.c 8af9fcc75708d60b88636ccba38b4a7b3c155c3e -F src/main.c 9ab948225b8c362cdd6902c447abbf218607e0f3 +F src/main.c 1a5cafdc1bee11f4322c837487bf6fa8e54b2f50 F src/malloc.c 92d59a007d7a42857d4e9454aa25b6b703286be1 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206 @@ -177,13 +177,13 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 649c51979812f77f97507024a4cea480c6862b8b -F src/sqlite.h.in 3a8a9f25a45735879cec195a2c129b48e34ebf8e +F src/sqlite.h.in 992688609e9a0274b56c156d4800be96364b3590 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h 3a262a299fa5b1f6916157ec2302e8987e50bac9 +F src/sqliteInt.h 85e635183013e806069320ffa6080a77183f9225 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e -F src/tclsqlite.c 20a3bf120f3bba1914f0e5132dbe937dee135f36 +F src/tclsqlite.c 64aeb4109ee2b38fd820b8e8de45b02377fcddc0 F src/test1.c 9020310c7617234b33fd1c3064f89524db25f290 F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc @@ -229,11 +229,11 @@ F src/update.c 1b9a82ede7df15e76ed86c6a3cbe4ce0f21eaa9b F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685 F src/util.c ab1c92426494f499f42b9e307537b03e923d75c1 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c 4330cc94597b9c95853c5e8ff87776f1e6ceaa3f +F src/vdbe.c 2c523bc17f915329f3db3745fc76ed9bfc5c26bb F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 41b8e337332f279228196039ab86acd353ad0c6c -F src/vdbeapi.c c407f3f0e21d5de68b1269bfa12315ef7ed6e3fd -F src/vdbeaux.c 874e16966eb6e58183ee2746abb4e4c5238f2350 +F src/vdbeapi.c ea741433042d95c392b29397ac6c2b08f6106317 +F src/vdbeaux.c cc817d8597307a2be361c24f3b436a7e41fa67dc F src/vdbeblob.c 18955f0ee6b133cd08e1592010cb9a6b11e9984c F src/vdbemem.c 0fa2ed786cd207d5b988afef3562a8e663a75b50 F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -471,7 +471,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c -F test/hook.test 5fd01c30f47896d88bed8a09bf7773cff218e8ff +F test/hook.test a90748e44c7ca53da46f857616fc7ce18bf7be13 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 @@ -667,7 +667,7 @@ F test/superlock.test 5d7a4954b0059c903f82c7b67867bc5451a7c082 F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3 F test/table.test 04ba066432430657712d167ebf28080fe878d305 F test/tableapi.test 7262a8cbaa9965d429f1cbd2747edc185fa56516 -F test/tclsqlite.test 1ce9b6340d6d412420634e129a2e3722c651056a +F test/tclsqlite.test 550f2268281d186b767b3ee14dd0be5f9e3ff25d F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05 @@ -909,10 +909,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 4e50b0362ab6604a4b6c9f4ad849ec1733d6ce1a -R 0e3c3fa7441b432fef74ccddd445caf6 -T *branch * experimental -T *sym-experimental * -T -sym-trunk * +P 6145d7b89f83500318713779c60f79a7ab2098ba +R 2617e052d0e8716cc0b428f99022eddb U dan -Z 1b63beda3df1a2343540c0064b366df4 +Z 24e44e929785c6b1d1f35eb2447fe0e7 diff --git a/manifest.uuid b/manifest.uuid index c59fca196c..e0c1dabe5a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6145d7b89f83500318713779c60f79a7ab2098ba \ No newline at end of file +093d8cd8e2f3a6af5d40cf810e396f4919eb5cef \ No newline at end of file diff --git a/src/main.c b/src/main.c index 3976f7ebc3..a8ac80039e 100644 --- a/src/main.c +++ b/src/main.c @@ -764,6 +764,26 @@ int sqlite3_close(sqlite3 *db){ return SQLITE_OK; } + +/* +** Invoke the transaction-hook. +*/ +void sqlite3TransactionHook(sqlite3 *db, int op, int iLevel){ + assert( op==SQLITE_BEGIN || op==SQLITE_COMMIT || op==SQLITE_ROLLBACK ); + assert( op==SQLITE_BEGIN || iLeveliOpenTrans || iLevel==0 ); + assert( op==SQLITE_BEGIN || iLeveliOpenTrans || db->iOpenTrans==0 ); + assert( op!=SQLITE_BEGIN || iLevel==db->iOpenTrans || iLevel==0 ); + assert( op!=SQLITE_BEGIN || iLevel==db->iOpenTrans || db->iOpenTrans==1 ); + + if( op==SQLITE_BEGIN && iLevel!=db->iOpenTrans ) return; + if( op!=SQLITE_BEGIN && iLevel>=db->iOpenTrans ) return; + + if( db->xTransCallback ){ + db->xTransCallback(db->pTransArg, op, iLevel); + } + db->iOpenTrans = iLevel + (op==SQLITE_BEGIN); +} + /* ** Rollback all database files. */ @@ -796,6 +816,10 @@ void sqlite3RollbackAll(sqlite3 *db){ if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ db->xRollbackCallback(db->pRollbackArg); } + + /* If a transaction-hook is configured, invoke it now to report on + ** the rollback operation. */ + sqlite3TransactionHook(db, SQLITE_ROLLBACK, 0); } /* @@ -1290,6 +1314,24 @@ void *sqlite3_preupdate_hook( return pRet; } +/* +** Register a callback to be invoked each time a transaction or savepoint +** is opened, committed or rolled back. +*/ +void *sqlite3_transaction_hook( + sqlite3 *db, /* Database handle */ + void(*xCallback)(void *, int, int), /* Callback function */ + void *pArg /* First callback argument */ +){ + void *pRet; + sqlite3_mutex_enter(db->mutex); + pRet = db->pTransArg; + db->xTransCallback = xCallback; + db->pTransArg = pArg; + sqlite3_mutex_leave(db->mutex); + return pRet; +} + #ifndef SQLITE_OMIT_WAL /* ** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 413031ecfa..137be57b89 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6344,7 +6344,15 @@ int sqlite3_wal_checkpoint_v2( #define SQLITE_CHECKPOINT_FULL 1 #define SQLITE_CHECKPOINT_RESTART 2 -void *sqlite3_preupdate_hook( + +/* +** CAPI3REF: The pre-update hook. +** +** The preupdate_old() API may only be used from within an SQLITE_UPDATE or +** SQLITE_DELETE pre-update callback. The preupdate_modified() API may only +** be used from within an SQLITE_UPDATE pre-update callback. +*/ +SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook( sqlite3 *db, void(*xPreUpdate)( void *pCtx, /* Copy of third arg to preupdate_hook() */ @@ -6357,16 +6365,19 @@ void *sqlite3_preupdate_hook( ), void* ); +SQLITE_EXPERIMENTAL int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); +SQLITE_EXPERIMENTAL int sqlite3_preupdate_modified(sqlite3 *, int, int *); +SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *); /* -** The following APIs may only be used from within a pre-update callback. More -** specifically, the preupdate_old() API may only be used from within an -** SQLITE_UPDATE or SQLITE_DELETE pre-update callback. The preupdate_modified() -** API may only be used from within an SQLITE_UPDATE pre-update callback. +** CAPI3REF: The transaction hook. */ -int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); -int sqlite3_preupdate_modified(sqlite3 *, int, int *); -int sqlite3_preupdate_count(sqlite3 *); +SQLITE_EXPERIMENTAL +void *sqlite3_transaction_hook(sqlite3 *, void(*)(void *, int, int), void *); + +#define SQLITE_BEGIN 1 +#define SQLITE_COMMIT 2 +#define SQLITE_ROLLBACK 3 /* diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 2541936848..1414fb68b5 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -833,6 +833,9 @@ struct sqlite3 { void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64 ); PreUpdate *pPreUpdate; /* Context for active pre-update callback */ + void *pTransArg; /* First argument to xTransCallback */ + void (*xTransCallback)(void*,int,int); + int iOpenTrans; /* Open transaction (xTransCallback) plus 1 */ #ifndef SQLITE_OMIT_WAL int (*xWalCallback)(void *, sqlite3 *, const char *, int); void *pWalArg; @@ -2748,6 +2751,7 @@ void sqlite3PrngSaveState(void); void sqlite3PrngRestoreState(void); void sqlite3PrngResetState(void); void sqlite3RollbackAll(sqlite3*); +void sqlite3TransactionHook(sqlite3 *, int, int); void sqlite3CodeVerifySchema(Parse*, int); void sqlite3BeginTransaction(Parse*, int); void sqlite3CommitTransaction(Parse*); diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 91c6094fa9..c7e6fda068 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -124,6 +124,7 @@ struct SqliteDb { Tcl_Obj *pUpdateHook; /* Update hook script (if any) */ Tcl_Obj *pPreUpdateHook; /* Pre-update hook script (if any) */ Tcl_Obj *pRollbackHook; /* Rollback hook script (if any) */ + Tcl_Obj *pTransHook; /* Transaction hook script (if any) */ Tcl_Obj *pWalHook; /* WAL hook script (if any) */ Tcl_Obj *pUnlockNotify; /* Unlock notify script (if any) */ SqlCollate *pCollate; /* List of SQL collation functions */ @@ -597,6 +598,30 @@ static void DbRollbackHandler(void *clientData){ } } +/* +** sqlite3_transaction_hook() callback. +*/ +static void DbTransHandler(void *clientData, int op, int iLevel){ + static const char *azStr[] = { "BEGIN", "COMMIT", "ROLLBACK" }; + SqliteDb *pDb = (SqliteDb*)clientData; + Tcl_Interp *interp = pDb->interp; + Tcl_Obj *pScript; + + assert(pDb->pTransHook); + assert( SQLITE_BEGIN==1 ); + assert( SQLITE_COMMIT==2 ); + assert( SQLITE_ROLLBACK==3 ); + + pScript = Tcl_DuplicateObj(pDb->pTransHook); + Tcl_IncrRefCount(pScript); + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(azStr[op-1], -1)); + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewIntObj(iLevel)); + if( TCL_OK!=Tcl_EvalObjEx(interp, pScript, 0) ){ + Tcl_BackgroundError(interp); + } + Tcl_DecrRefCount(pScript); +} + /* ** This procedure handles wal_hook callbacks. */ @@ -1628,6 +1653,7 @@ static void DbHookCmd( sqlite3_update_hook(db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb); sqlite3_rollback_hook(db, (pDb->pRollbackHook?DbRollbackHandler:0), pDb); sqlite3_wal_hook(db, (pDb->pWalHook?DbWalHandler:0), pDb); + sqlite3_transaction_hook(db, (pDb->pTransHook?DbTransHandler:0), pDb); } /* @@ -1659,7 +1685,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ "profile", "progress", "rekey", "restore", "rollback_hook", "status", "timeout", "total_changes", "trace", - "transaction", "unlock_notify", "update_hook", + "transaction", "transaction_hook", + "unlock_notify", "update_hook", "version", "wal_hook", 0 }; enum DB_enum { @@ -1674,7 +1701,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ DB_PROFILE, DB_PROGRESS, DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK, DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, - DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, + DB_TRANSACTION, DB_TRANSACTION_HOOK, + DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION, DB_WAL_HOOK }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ @@ -2914,10 +2942,12 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ ** $db wal_hook ?script? ** $db update_hook ?script? ** $db rollback_hook ?script? + ** $db transaction_hook ?script? */ case DB_WAL_HOOK: case DB_UPDATE_HOOK: - case DB_ROLLBACK_HOOK: { + case DB_ROLLBACK_HOOK: + case DB_TRANSACTION_HOOK: { sqlite3 *db = pDb->db; /* set ppHook to point at pUpdateHook or pRollbackHook, depending on @@ -2927,6 +2957,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ if( choice==DB_WAL_HOOK ) ppHook = &pDb->pWalHook; if( choice==DB_UPDATE_HOOK ) ppHook = &pDb->pUpdateHook; if( choice==DB_ROLLBACK_HOOK ) ppHook = &pDb->pRollbackHook; + if( choice==DB_TRANSACTION_HOOK ) ppHook = &pDb->pTransHook; if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); return TCL_ERROR; diff --git a/src/vdbe.c b/src/vdbe.c index c5492eedc8..252c53cb63 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2568,6 +2568,8 @@ case OP_Savepoint: { }else{ db->nSavepoint++; } + + sqlite3TransactionHook(db, SQLITE_BEGIN, db->nSavepoint); /* Link the new savepoint into the database handle's list. */ pNew->pNext = db->pSavepoint; @@ -2635,6 +2637,13 @@ case OP_Savepoint: { sqlite3ResetInternalSchema(db, 0); db->flags = (db->flags | SQLITE_InternChanges); } + + assert( SAVEPOINT_ROLLBACK+1==SQLITE_ROLLBACK ); + assert( SAVEPOINT_RELEASE+1==SQLITE_COMMIT ); + sqlite3TransactionHook(db, p1+1, iSavepoint+1); + if( p1==SAVEPOINT_ROLLBACK ){ + sqlite3TransactionHook(db, SQLITE_BEGIN, iSavepoint+1); + } } /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all @@ -2710,6 +2719,9 @@ case OP_AutoCommit: { }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ goto vdbe_return; }else{ + if( desiredAutoCommit==0 ){ + sqlite3TransactionHook(db, SQLITE_BEGIN, 0); + } db->autoCommit = (u8)desiredAutoCommit; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ p->pc = pc; @@ -2796,6 +2808,7 @@ case OP_Transaction: { p->iStatement = db->nSavepoint + db->nStatement; } rc = sqlite3BtreeBeginStmt(pBt, p->iStatement); + sqlite3TransactionHook(db, SQLITE_BEGIN, p->iStatement); /* Store the current value of the database handles deferred constraint ** counter. If the statement transaction needs to be rolled back, diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 8b1f2e21bb..cefca02a24 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -401,7 +401,15 @@ static int sqlite3Step(Vdbe *p){ #endif db->activeVdbeCnt++; - if( p->readOnly==0 ) db->writeVdbeCnt++; + if( p->readOnly==0 ){ + /* If this statement will open an implicit transaction, invoke the + ** transaction-hook here. */ + if( db->autoCommit && db->writeVdbeCnt==0 ){ + assert( db->nSavepoint==0 ); + sqlite3TransactionHook(db, SQLITE_BEGIN, 0); + } + db->writeVdbeCnt++; + } p->pc = 0; } #ifndef SQLITE_OMIT_EXPLAIN diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 31cf669144..937c2a1998 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1845,6 +1845,12 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ } #endif + /* If a transaction-hook is configured, invoke it now to report on the + ** successful commit operation. */ + if( rc==SQLITE_OK ){ + sqlite3TransactionHook(db, SQLITE_COMMIT, 0); + } + return rc; } @@ -1946,6 +1952,9 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ } } db->nStatement--; + assert( SAVEPOINT_ROLLBACK+1==SQLITE_ROLLBACK ); + assert( SAVEPOINT_RELEASE+1==SQLITE_COMMIT ); + sqlite3TransactionHook(db, eOp+1, p->iStatement); p->iStatement = 0; /* If the statement transaction is being rolled back, also restore the diff --git a/test/hook.test b/test/hook.test index 827ce08b3d..b2e0988828 100644 --- a/test/hook.test +++ b/test/hook.test @@ -616,16 +616,151 @@ do_execsql_test 7.5.2.0 { ALTER TABLE t8 ADD COLUMN c DEFAULT 'xxx'; } +# At time of writing, these two are broken. They demonstraight that the +# sqlite3_preupdate_old() method does not handle the case where ALTER TABLE +# has been used to add a column with a default value other than NULL. +# do_preupdate_test 7.5.2.1 { DELETE FROM t8 WHERE a = 'one' } { DELETE main t8 1 1 one two xxx } - do_preupdate_test 7.5.2.2 { UPDATE t8 SET b = 'five' } { UPDATE main t8 2 2 three four xxx } +#---------------------------------------------------------------------------- +# The following tests - hook-8.* - test the transaction hook. +# +db close +forcedelete test.db +sqlite3 db test.db + +proc transaction_hook {op iLevel} { + lappend ::transaction_hook $op $iLevel +} +db transaction_hook transaction_hook + +proc do_transaction_test {tn sql x} { + set X [list] + foreach elem $x {lappend X $elem} + + uplevel do_test $tn [list " + set ::transaction_hook \[list\] + catchsql { $sql } + set ::transaction_hook + "] [list $X] +} + +do_transaction_test 8.1.1 "CREATE TABLE t1(x)" {BEGIN 0 COMMIT 0} +do_transaction_test 8.1.2 "BEGIN" {BEGIN 0} +do_transaction_test 8.1.3 "COMMIT" {COMMIT 0} +do_transaction_test 8.1.4 "BEGIN ; ROLLBACK" {BEGIN 0 ROLLBACK 0} + +do_execsql_test 8.2.0 { + CREATE TABLE t2(a PRIMARY KEY, b); + INSERT INTO t2 VALUES(1, 'one'); + INSERT INTO t2 VALUES(2, 'two'); + INSERT INTO t2 VALUES(3, 'three'); +} +do_transaction_test 8.2.1 { + INSERT INTO t2 VALUES(2, 'xxx') +} {BEGIN 0 ROLLBACK 0} + +do_transaction_test 8.2.2 { + BEGIN; INSERT INTO t2 SELECT a-2, b FROM t2; +} {BEGIN 0 BEGIN 1 ROLLBACK 1} + +do_transaction_test 8.2.3 { + INSERT OR ROLLBACK INTO t2 SELECT a-2, b FROM t2; +} {ROLLBACK 0} + +do_transaction_test 8.2.4 { + BEGIN; INSERT INTO t2 SELECT a+3, b FROM t2; +} {BEGIN 0 BEGIN 1 COMMIT 1} + +do_transaction_test 8.2.5 "COMMIT" {COMMIT 0} + +do_transaction_test 8.3.1 {SELECT * FROM t2} {} + +do_transaction_test 8.4.1 { + SAVEPOINT top; + RELEASE top; +} {BEGIN 0 COMMIT 0} + +do_transaction_test 8.4.2 { + SAVEPOINT top; + ROLLBACK TO top; + RELEASE top; +} {BEGIN 0 ROLLBACK 0 BEGIN 0 COMMIT 0} + +do_transaction_test 8.4.3 { + SAVEPOINT zero; + SAVEPOINT one; + SAVEPOINT two; + SAVEPOINT three; + ROLLBACK TO zero; + SAVEPOINT one; + SAVEPOINT two; + SAVEPOINT three; + ROLLBACK TO one; + SAVEPOINT two; + RELEASE zero; + + SAVEPOINT zero; + SAVEPOINT one; + SAVEPOINT two; + RELEASE two; + SAVEPOINT two; + SAVEPOINT three; + RELEASE one; + ROLLBACK TO zero; + RELEASE zero; +} { + BEGIN 0 BEGIN 1 BEGIN 2 BEGIN 3 ROLLBACK 0 BEGIN 0 + BEGIN 1 BEGIN 2 BEGIN 3 ROLLBACK 1 BEGIN 1 BEGIN 2 + COMMIT 0 + + BEGIN 0 BEGIN 1 BEGIN 2 COMMIT 2 BEGIN 2 BEGIN 3 COMMIT 1 + ROLLBACK 0 BEGIN 0 COMMIT 0 +} + +do_transaction_test 8.4.4 { + BEGIN; + SAVEPOINT zero; + SAVEPOINT one; + SAVEPOINT two; + SAVEPOINT three; + ROLLBACK TO zero; + SAVEPOINT one; + SAVEPOINT two; + SAVEPOINT three; + ROLLBACK TO one; + SAVEPOINT two; + RELEASE zero; + + SAVEPOINT zero; + SAVEPOINT one; + SAVEPOINT two; + RELEASE two; + SAVEPOINT two; + SAVEPOINT three; + RELEASE one; + ROLLBACK TO zero; + RELEASE zero; + COMMIT; +} { + BEGIN 0 + BEGIN 1 BEGIN 2 BEGIN 3 BEGIN 4 ROLLBACK 1 BEGIN 1 + BEGIN 2 BEGIN 3 BEGIN 4 ROLLBACK 2 BEGIN 2 BEGIN 3 + COMMIT 1 + + BEGIN 1 BEGIN 2 BEGIN 3 COMMIT 3 BEGIN 3 BEGIN 4 COMMIT 2 + ROLLBACK 1 BEGIN 1 COMMIT 1 + COMMIT 0 +} + finish_test + diff --git a/test/tclsqlite.test b/test/tclsqlite.test index c9d562beb5..efc3e53ab6 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -35,7 +35,7 @@ do_test tcl-1.1 { do_test tcl-1.2 { set v [catch {db bogus} msg] lappend v $msg -} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, transaction, unlock_notify, update_hook, version, or wal_hook}} +} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, transaction, transaction_hook, unlock_notify, update_hook, version, or wal_hook}} do_test tcl-1.2.1 { set v [catch {db cache bogus} msg] lappend v $msg From 4fccf43aaede1a7f2a7b82f9a6a7bb310c2fc132 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 8 Mar 2011 19:22:50 +0000 Subject: [PATCH 003/570] Add start of sessions feature. FossilOrigin-Name: 269a81a37d7dbdcdec3c2322074916af0fbac91c --- ext/session/sqlite3session.c | 993 +++++++++++++++++++++++++++++++++++ ext/session/sqlite3session.h | 125 +++++ ext/session/test_session.c | 258 +++++++++ main.mk | 7 +- manifest | 24 +- manifest.uuid | 2 +- src/tclsqlite.c | 6 + src/vdbeInt.h | 1 + src/vdbeapi.c | 8 +- src/vdbeaux.c | 3 + test/session1.test | 118 +++++ 11 files changed, 1525 insertions(+), 20 deletions(-) create mode 100644 ext/session/sqlite3session.c create mode 100644 ext/session/sqlite3session.h create mode 100644 ext/session/test_session.c create mode 100644 test/session1.test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c new file mode 100644 index 0000000000..eb024775fd --- /dev/null +++ b/ext/session/sqlite3session.c @@ -0,0 +1,993 @@ + +#ifdef SQLITE_ENABLE_SESSION + +#include "sqlite3session.h" +#include +#include + +#include "sqliteInt.h" +#include "vdbeInt.h" + +typedef struct RowChange RowChange; +typedef struct SessionTable SessionTable; +typedef struct SessionChange SessionChange; + +#if 0 +#ifndef SQLITE_AMALGAMATION +typedef unsigned char u8; +typedef unsigned long u32; +typedef sqlite3_uint64 u64; +#endif +#endif + +struct sqlite3_session { + sqlite3 *db; /* Database handle session is attached to */ + char *zDb; /* Name of database session is attached to */ + int rc; /* Non-zero if an error has occurred */ + sqlite3_session *pNext; /* Next session object on same db. */ + SessionTable *pTable; /* List of attached tables */ +}; + +/* +** Each session object maintains a set of the following structures, one +** for each table the session object is monitoring. The structures are +** stored in a linked list starting at sqlite3_session.pTable. +** +** The keys of the SessionTable.aChange[] hash table are all rows that have +** been modified in any way since the session object was attached to the +** table. +** +** The data associated with each hash-table entry is a structure containing +** a subset of the initial values that the modified row contained at the +** start of the session. Or no initial values if the row was inserted. +*/ +struct SessionTable { + SessionTable *pNext; + char *zName; /* Local name of table */ + int nCol; /* Number of columns in table zName */ + + /* Hash table of modified rows */ + int nEntry; /* NUmber of entries in hash table */ + int nChange; /* Size of apChange[] array */ + SessionChange **apChange; /* Hash table buckets */ +}; + +/* +** RECORD FORMAT: +** +** The following record format is similar to (but not compatible with) that +** used in SQLite database files. This format is used as part of the +** change-set binary format, and so must be architecture independent. +** +** Unlike the SQLite database record format, each field is self-contained - +** there is no separation of header and data. Each field begins with a +** single byte describing its type, as follows: +** +** 0x00: Undefined value. +** 0x01: Integer value. +** 0x02: Real value. +** 0x03: Text value. +** 0x04: Blob value. +** 0x05: SQL NULL value. +** +** Note that the above match the definitions of SQLITE_INTEGER, SQLITE_TEXT +** and so on in sqlite3.h. For undefined and NULL values, the field consists +** only of the single type byte. For other types of values, the type byte +** is followed by: +** +** Text values: +** A varint containing the number of bytes in the value (encoded using +** UTF-8). Followed by a buffer containing the UTF-8 representation +** of the text value. There is no nul terminator. +** +** Blob values: +** A varint containing the number of bytes in the value, followed by +** a buffer containing the value itself. +** +** Integer values: +** An 8-byte big-endian integer value. +** +** Real values: +** An 8-byte big-endian IEEE 754-2008 real value. +** +** Varint values are encoded in the same way as varints in the SQLite +** record format. +** +** CHANGESET FORMAT: +** +** A changeset is a collection of DELETE, UPDATE and INSERT operations on +** one or more tables. Operations on a single table are grouped together, +** but may occur in any order (i.e. deletes, updates and inserts are all +** mixed together). +** +** Each group of changes begins with a table header: +** +** 1 byte: Constant 0x54 (capital 'T') +** Varint: Big-endian integer set to the number of columns in the table. +** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. +** +** Followed by one or more changes to the table. +** +** 1 byte: Either SQLITE_INSERT, UPDATE or DELETE. +** old.* record: (delete and update only) +** new.* record: (insert and update only) +*/ + +/* +** For each row modified during a session, there exists a single instance of +** this structure stored in a SessionTable.aChange[] hash table. +*/ +struct SessionChange { + sqlite3_int64 iKey; /* Key value */ + int nRecord; /* Number of bytes in buffer aRecord[] */ + u8 *aRecord; /* Buffer containing old.* record */ + SessionChange *pNext; /* For hash-table collisions */ +}; + + +static int sessionVarintPut(u8 *aBuf, u32 iVal){ + if( (iVal & ~0x7F)==0 ){ + if( aBuf ){ + aBuf[0] = (u8)iVal; + } + return 1; + } + if( (iVal & ~0x3FFF)==0 ){ + if( aBuf ){ + aBuf[0] = ((iVal >> 7) & 0x7F) | 0x80; + aBuf[1] = iVal & 0x7F; + } + return 2; + } + if( aBuf ){ + aBuf[0] = ((iVal >> 28) & 0x7F) | 0x80; + aBuf[1] = ((iVal >> 21) & 0x7F) | 0x80; + aBuf[2] = ((iVal >> 14) & 0x7F) | 0x80; + aBuf[3] = ((iVal >> 7) & 0x7F) | 0x80; + aBuf[4] = iVal & 0x7F; + } + return 5; +} + +static int sessionVarintGet(u8 *aBuf, int *piVal){ + int ret; + u64 v; + ret = (int)sqlite3GetVarint(aBuf, &v); + *piVal = (int)v; + return ret; +} + +static sqlite3_int64 sessionGetI64(u8 *aRec){ + return (((sqlite3_int64)aRec[0]) << 56) + + (((sqlite3_int64)aRec[1]) << 48) + + (((sqlite3_int64)aRec[2]) << 40) + + (((sqlite3_int64)aRec[3]) << 32) + + (((sqlite3_int64)aRec[4]) << 24) + + (((sqlite3_int64)aRec[5]) << 16) + + (((sqlite3_int64)aRec[6]) << 8) + + (((sqlite3_int64)aRec[7]) << 0); +} + +/* +** This function is used to serialize the contents of value pValue (see +** comment titled "RECORD FORMAT" above). +** +** If it is non-NULL, the serialized form of the value is written to +** buffer aBuf. *pnWrite is set to the number of bytes written before +** returning. Or, if aBuf is NULL, the only thing this function does is +** set *pnWrite. +** +** If no error occurs, SQLITE_OK is returned. Or, if an OOM error occurs +** within a call to sqlite3_value_text() (may fail if the db is utf-16)) +** SQLITE_NOMEM is returned. +*/ +static int sessionSerializeValue( + u8 *aBuf, /* If non-NULL, write serialized value here */ + sqlite3_value *pValue, /* Value to serialize */ + int *pnWrite /* IN/OUT: Increment by bytes written */ +){ + int eType; + int nByte; + + eType = sqlite3_value_type(pValue); + if( aBuf ) aBuf[0] = eType; + + switch( eType ){ + case SQLITE_NULL: + nByte = 1; + break; + + case SQLITE_INTEGER: + case SQLITE_FLOAT: + if( aBuf ){ + /* TODO: SQLite does something special to deal with mixed-endian + ** floating point values (e.g. ARM7). This code probably should + ** too. */ + u64 i; + if( eType==SQLITE_INTEGER ){ + i = (u64)sqlite3_value_int64(pValue); + }else{ + double r; + assert( sizeof(double)==8 && sizeof(u64)==8 ); + r = sqlite3_value_double(pValue); + memcpy(&i, &r, 8); + } + aBuf[1] = (i>>56) & 0xFF; + aBuf[2] = (i>>48) & 0xFF; + aBuf[3] = (i>>40) & 0xFF; + aBuf[4] = (i>>32) & 0xFF; + aBuf[5] = (i>>24) & 0xFF; + aBuf[6] = (i>>16) & 0xFF; + aBuf[7] = (i>> 8) & 0xFF; + aBuf[8] = (i>> 0) & 0xFF; + } + nByte = 9; + break; + + case SQLITE_TEXT: + case SQLITE_BLOB: { + int n = sqlite3_value_bytes(pValue); + int nVarint = sessionVarintPut(0, n); + if( aBuf ){ + sessionVarintPut(&aBuf[1], n); + memcpy(&aBuf[nVarint + 1], eType==SQLITE_TEXT ? + sqlite3_value_text(pValue) : sqlite3_value_blob(pValue), n + ); + } + + nByte = 1 + nVarint + n; + break; + } + } + + *pnWrite += nByte; + return SQLITE_OK; +} + +/* +** Return the hash of iKey, assuming there are nBucket hash buckets in +** the hash table. +*/ +static int sessionKeyhash(int nBucket, sqlite3_int64 iKey){ + return (iKey % nBucket); +} + +/* +** If required, grow the hash table used to store changes on table pTab +** (part of the session pSession). If a fatal OOM error occurs, set the +** session object to failed and return SQLITE_ERROR. Otherwise, return +** SQLITE_OK. +** +** It is possible that a non-fatal OOM error occurs in this function. In +** that case the hash-table does not grow, but SQLITE_OK is returned anyway. +** Growing the hash table in this case is a performance optimization only, +** it is not required for correct operation. +*/ +static int sessionGrowHash(sqlite3_session *pSession, SessionTable *pTab){ + if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){ + int i; + SessionChange **apNew; + int nNew = (pTab->nChange ? pTab->nChange : 128) * 2; + + apNew = (SessionChange **)sqlite3_malloc(sizeof(SessionChange *) * nNew); + if( apNew==0 ){ + if( pTab->nChange==0 ){ + pSession->rc = SQLITE_NOMEM; + return SQLITE_ERROR; + } + return SQLITE_OK; + } + memset(apNew, 0, sizeof(SessionChange *) * nNew); + + for(i=0; inChange; i++){ + SessionChange *p; + SessionChange *pNext; + for(p=pTab->apChange[i]; p; p=pNext){ + int iHash = sessionKeyhash(nNew, p->iKey); + pNext = p->pNext; + p->pNext = apNew[iHash]; + apNew[iHash] = p; + } + } + + sqlite3_free(pTab->apChange); + pTab->nChange = nNew; + pTab->apChange = apNew; + } + + return SQLITE_OK; +} + +static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ + if( pTab->nCol==0 ){ + pTab->nCol = sqlite3_preupdate_count(pSession->db); + } + + if( pTab->nCol!=sqlite3_preupdate_count(pSession->db) ){ + pSession->rc = SQLITE_SCHEMA; + return SQLITE_ERROR; + } + + return SQLITE_OK; +} + +/* +** The 'pre-update' hook registered by this module with SQLite databases. +*/ +static void xPreUpdate( + void *pCtx, /* Copy of third arg to preupdate_hook() */ + sqlite3 *db, /* Database handle */ + int op, /* SQLITE_UPDATE, DELETE or INSERT */ + char const *zDb, /* Database name */ + char const *zName, /* Table name */ + sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ + sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ +){ + sqlite3_session *pSession; + int nDb = strlen(zDb); + int nName = strlen(zDb); + + for(pSession=(sqlite3_session *)pCtx; pSession; pSession=pSession->pNext){ + SessionTable *pTab; + if( pSession->rc ) continue; + if( sqlite3_strnicmp(zDb, pSession->zDb, nDb+1) ) continue; + for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){ + if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ){ + SessionChange *pChange; + SessionChange *pC; + int iHash; + int rc = SQLITE_OK; + + /* Load table details if required */ + if( sessionInitTable(pSession, pTab) ) return; + + /* Grow the hash table if required */ + if( sessionGrowHash(pSession, pTab) ) return; + + /* Search the hash table for an existing entry for rowid=iKey2. If + ** one is found, store a pointer to it in pChange and unlink it from + ** the hash table. Otherwise, set pChange to NULL. + */ + iHash = sessionKeyhash(pTab->nChange, iKey2); + for(pC=pTab->apChange[iHash]; pC; pC=pC->pNext){ + if( pC->iKey==iKey2 ) break; + } + if( pC ) continue; + + pTab->nEntry++; + + /* Create a new change object containing all the old values (if + ** this is an SQLITE_UPDATE or SQLITE_DELETE), or no record at + ** all (if this is an INSERT). */ + if( op==SQLITE_INSERT ){ + pChange = (SessionChange *)sqlite3_malloc(sizeof(SessionChange)); + if( pChange ){ + memset(pChange, 0, sizeof(SessionChange)); + } + }else{ + int nByte; /* Number of bytes to allocate */ + int i; /* Used to iterate through columns */ + sqlite3_value *pValue; + + /* Figure out how large an allocation is required */ + nByte = sizeof(SessionChange); + for(i=0; inCol && rc==SQLITE_OK; i++){ + rc = sqlite3_preupdate_old(pSession->db, i, &pValue); + if( rc==SQLITE_OK ){ + rc = sessionSerializeValue(0, pValue, &nByte); + } + } + + /* Allocate the change object */ + pChange = (SessionChange *)sqlite3_malloc(nByte); + if( !pChange ){ + rc = SQLITE_NOMEM; + }else{ + memset(pChange, 0, sizeof(SessionChange)); + pChange->aRecord = (u8 *)&pChange[1]; + } + + /* Populate the change object */ + nByte = 0; + for(i=0; inCol && rc==SQLITE_OK; i++){ + rc = sqlite3_preupdate_old(pSession->db, i, &pValue); + if( rc==SQLITE_OK ){ + rc = sessionSerializeValue( + &pChange->aRecord[nByte], pValue, &nByte); + } + } + pChange->nRecord = nByte; + } + + /* If an error has occurred, mark the session object as failed. */ + if( rc!=SQLITE_OK ){ + sqlite3_free(pChange); + pSession->rc = rc; + return; + } + + /* Add the change back to the hash-table */ + pChange->iKey = iKey2; + pChange->pNext = pTab->apChange[iHash]; + pTab->apChange[iHash] = pChange; + } + break; + } + } +} + +/* +** Create a session object. This session object will record changes to +** database zDb attached to connection db. +*/ +int sqlite3session_create( + sqlite3 *db, /* Database handle */ + const char *zDb, /* Name of db (e.g. "main") */ + sqlite3_session **ppSession /* OUT: New session object */ +){ + sqlite3_session *pNew; + sqlite3_session *pOld; + int nDb = strlen(zDb); /* Length of zDb in bytes */ + + *ppSession = 0; + + /* Allocate and populate the new session object. */ + pNew = (sqlite3_session *)sqlite3_malloc(sizeof(sqlite3_session) + nDb + 1); + if( !pNew ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(sqlite3_session)); + pNew->db = db; + pNew->zDb = (char *)&pNew[1]; + memcpy(pNew->zDb, zDb, nDb+1); + + /* Add the new session object to the linked list of session objects + ** attached to database handle $db. Do this under the cover of the db + ** handle mutex. */ + sqlite3_mutex_enter(sqlite3_db_mutex(db)); + pOld = (sqlite3_session*)sqlite3_preupdate_hook(db, xPreUpdate, (void*)pNew); + pNew->pNext = pOld; + sqlite3_mutex_leave(sqlite3_db_mutex(db)); + + *ppSession = pNew; + return SQLITE_OK; +} + +/* +** Delete a session object previously allocated using sqlite3session_create(). +*/ +void sqlite3session_delete(sqlite3_session *pSession){ + sqlite3 *db = pSession->db; + sqlite3_session *pHead; + sqlite3_session **pp; + + sqlite3_mutex_enter(sqlite3_db_mutex(db)); + pHead = (sqlite3_session*)sqlite3_preupdate_hook(db, 0, 0); + for(pp=&pHead; (*pp)!=pSession; pp=&((*pp)->pNext)); + *pp = (*pp)->pNext; + if( pHead ) sqlite3_preupdate_hook(db, xPreUpdate, (void *)pHead); + sqlite3_mutex_leave(sqlite3_db_mutex(db)); + + while( pSession->pTable ){ + int i; + SessionTable *pTab = pSession->pTable; + pSession->pTable = pTab->pNext; + for(i=0; inChange; i++){ + SessionChange *p; + SessionChange *pNext; + for(p=pTab->apChange[i]; p; p=pNext){ + pNext = p->pNext; + sqlite3_free(p); + } + } + sqlite3_free(pTab->apChange); + sqlite3_free(pTab); + } + + sqlite3_free(pSession); +} + +/* +** Attach a table to a session. All subsequent changes made to the table +** while the session object is enabled will be recorded. +** +** Only tables that have a PRIMARY KEY defined may be attached. It does +** not matter if the PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) +** or not. +*/ +int sqlite3session_attach( + sqlite3_session *pSession, /* Session object */ + const char *zName /* Table name */ +){ + SessionTable *pTab; + int nName; + + /* First search for an existing entry. If one is found, this call is + ** a no-op. Return early. */ + nName = strlen(zName); + for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){ + if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ){ + return SQLITE_OK; + } + } + + /* Allocate new SessionTable object. */ + pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1); + if( !pTab ) return SQLITE_NOMEM; + + /* Populate the new SessionTable object and link it into the list. */ + memset(pTab, 0, sizeof(SessionTable)); + pTab->zName = (char *)&pTab[1]; + memcpy(pTab->zName, zName, nName+1); + pTab->pNext = pSession->pTable; + pSession->pTable = pTab; + + return SQLITE_OK; +} + +typedef struct SessionBuffer SessionBuffer; +struct SessionBuffer { + u8 *aBuf; /* Pointer to changeset buffer */ + int nBuf; /* Size of buffer aBuf */ + int nAlloc; /* Size of allocation containing aBuf */ +}; + +static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ + if( p->nAlloc-p->nBufnAlloc ? p->nAlloc : 128; + do { + nNew = nNew*2; + }while( nNew<(p->nAlloc+nByte) ); + + aNew = (u8 *)sqlite3_realloc(p->aBuf, nNew); + if( 0==aNew ){ + *pRc = SQLITE_NOMEM; + return 1; + } + p->aBuf = aNew; + p->nAlloc = nNew; + } + return 0; +} + +static void sessionAppendByte(SessionBuffer *p, u8 v, int *pRc){ + if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, 1, pRc) ){ + p->aBuf[p->nBuf++] = v; + } +} + +static void sessionAppendVarint(SessionBuffer *p, sqlite3_int64 v, int *pRc){ + if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, 9, pRc) ){ + p->nBuf += sessionVarintPut(&p->aBuf[p->nBuf], v); + } +} + +static void sessionAppendBlob( + SessionBuffer *p, + const u8 *aBlob, + int nBlob, + int *pRc +){ + if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, nBlob, pRc) ){ + memcpy(&p->aBuf[p->nBuf], aBlob, nBlob); + p->nBuf += nBlob; + } +} + +static void sessionAppendCol( + SessionBuffer *p, + sqlite3_stmt *pStmt, + int iCol, + int *pRc +){ + if( *pRc==SQLITE_OK ){ + int eType = sqlite3_column_type(pStmt, iCol); + sessionAppendByte(p, (u8)eType, pRc); + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + sqlite3_int64 i; + u8 aBuf[8]; + if( eType==SQLITE_INTEGER ){ + i = sqlite3_column_int64(pStmt, iCol); + }else{ + double r = sqlite3_column_double(pStmt, iCol); + memcpy(&i, &r, 8); + } + aBuf[0] = (i>>56) & 0xFF; + aBuf[1] = (i>>48) & 0xFF; + aBuf[2] = (i>>40) & 0xFF; + aBuf[3] = (i>>32) & 0xFF; + aBuf[4] = (i>>24) & 0xFF; + aBuf[5] = (i>>16) & 0xFF; + aBuf[6] = (i>> 8) & 0xFF; + aBuf[7] = (i>> 0) & 0xFF; + sessionAppendBlob(p, aBuf, 8, pRc); + } + if( eType==SQLITE_BLOB || eType==SQLITE_TEXT ){ + int nByte = sqlite3_column_bytes(pStmt, iCol); + sessionAppendVarint(p, nByte, pRc); + sessionAppendBlob(p, eType==SQLITE_BLOB ? + sqlite3_column_blob(pStmt, iCol) : sqlite3_column_text(pStmt, iCol), + nByte, pRc + ); + } + } +} + +static void sessionAppendUpdate( + sqlite3_stmt *pStmt, + SessionBuffer *pBuf, + SessionChange *p, + int *pRc +){ + if( *pRc==SQLITE_OK ){ + SessionBuffer buf2 = {0, 0, 0}; + int bNoop = 1; + int i; + u8 *pCsr = p->aRecord; + sessionAppendByte(pBuf, SQLITE_UPDATE, pRc); + for(i=0; inBuf -= (1 + sqlite3_column_count(pStmt)); + }else{ + sessionAppendBlob(pBuf, buf2.aBuf, buf2.nBuf, pRc); + sqlite3_free(buf2.aBuf); + } + } + + +} + +/* +** Obtain a changeset object containing all changes recorded by the +** session object passed as the first argument. +** +** It is the responsibility of the caller to eventually free the buffer +** using sqlite3_free(). +*/ +int sqlite3session_changeset( + sqlite3_session *pSession, /* Session object */ + int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ + void **ppChangeset /* OUT: Buffer containing changeset */ +){ + sqlite3 *db = pSession->db; + SessionTable *pTab; + SessionBuffer buf = {0, 0, 0}; + int rc; + + *pnChangeset = 0; + *ppChangeset = 0; + rc = pSession->rc; + + for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ + if( pTab->nEntry ){ + int i; + sqlite3_stmt *pStmt = 0; + int bNoop = 1; + int nRewind = buf.nBuf; + + /* Write a table header */ + sessionAppendByte(&buf, 'T', &rc); + sessionAppendVarint(&buf, pTab->nCol, &rc); + sessionAppendBlob(&buf, (u8 *)pTab->zName, strlen(pTab->zName)+1, &rc); + + /* Build and compile a statement to execute: */ + if( rc==SQLITE_OK ){ + char *zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q WHERE _rowid_ = ?", + pSession->zDb, pTab->zName + ); + if( !zSql ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + } + sqlite3_free(zSql); + } + + if( rc==SQLITE_OK && pTab->nCol!=sqlite3_column_count(pStmt) ){ + rc = SQLITE_SCHEMA; + } + + for(i=0; inChange; i++){ + SessionChange *p; + for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ + sqlite3_bind_int64(pStmt, 1, p->iKey); + if( sqlite3_step(pStmt)==SQLITE_ROW ){ + int iCol; + if( p->aRecord ){ + sessionAppendUpdate(pStmt, &buf, p, &rc); + }else{ + sessionAppendByte(&buf, SQLITE_INSERT, &rc); + for(iCol=0; iColnCol; iCol++){ + sessionAppendCol(&buf, pStmt, iCol, &rc); + } + } + bNoop = 0; + }else if( p->aRecord ){ + /* A DELETE change */ + sessionAppendByte(&buf, SQLITE_DELETE, &rc); + sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); + bNoop = 0; + } + rc = sqlite3_reset(pStmt); + } + } + + sqlite3_finalize(pStmt); + + if( bNoop ){ + buf.nBuf = nRewind; + } + } + } + + if( rc==SQLITE_OK ){ + *pnChangeset = buf.nBuf; + *ppChangeset = buf.aBuf; + }else{ + sqlite3_free(buf.aBuf); + } + + return rc; +} + +int sqlite3session_enable(sqlite3_session *pSession, int bEnable){ + return bEnable; +} + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +struct sqlite3_changeset_iter { + u8 *aChangeset; /* Pointer to buffer containing changeset */ + int nChangeset; /* Number of bytes in aChangeset */ + u8 *pNext; /* Pointer to next change within aChangeset */ + int rc; + + char *zTab; /* Current table */ + int nCol; /* Number of columns in zTab */ + int op; /* Current operation */ + sqlite3_value **apValue; /* old.* and new.* values */ +}; + +/* +** Create an iterator used to iterate through the contents of a changeset. +*/ +int sqlite3changeset_start( + sqlite3_changeset_iter **ppIter, + int nChangeset, + void *pChangeset +){ + sqlite3_changeset_iter *pRet; /* Iterator to return */ + int nByte; /* Number of bytes to allocate for iterator */ + + *ppIter = 0; + + nByte = sizeof(sqlite3_changeset_iter); + pRet = (sqlite3_changeset_iter *)sqlite3_malloc(nByte); + if( !pRet ) return SQLITE_NOMEM; + memset(pRet, 0, sizeof(sqlite3_changeset_iter)); + + pRet->aChangeset = (u8 *)pChangeset; + pRet->nChangeset = nChangeset; + pRet->pNext = pRet->aChangeset; + + *ppIter = pRet; + return SQLITE_OK; +} + +static int sessionReadRecord( + u8 **paChange, /* IN/OUT: Pointer to binary record */ + int nCol, /* Number of values in record */ + sqlite3_value **apOut /* Write values to this array */ +){ + int i; + u8 *aRec = *paChange; + + for(i=0; irc!=SQLITE_OK ) return p->rc; + + if( p->apValue ){ + for(i=0; inCol*2; i++){ + sqlite3ValueFree(p->apValue[i]); + } + memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2); + } + + /* If the iterator is already at the end of the changeset, return DONE. */ + if( p->pNext>=&p->aChangeset[p->nChangeset] ){ + return SQLITE_DONE; + } + aChange = p->pNext; + + c = *(aChange++); + if( c=='T' ){ + int nByte; /* Bytes to allocate for apValue */ + aChange += sessionVarintGet(aChange, &p->nCol); + p->zTab = (char *)aChange; + aChange += (strlen((char *)aChange) + 1); + p->op = *(aChange++); + sqlite3_free(p->apValue); + nByte = sizeof(sqlite3_value *) * p->nCol * 2; + p->apValue = (sqlite3_value **)sqlite3_malloc(nByte); + if( !p->apValue ){ + return (p->rc = SQLITE_NOMEM); + } + memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2); + }else{ + p->op = c; + } + if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){ + return (p->rc = SQLITE_CORRUPT); + } + + /* If this is an UPDATE or DELETE, read the old.* record. */ + if( p->op!=SQLITE_INSERT ){ + p->rc = sessionReadRecord(&aChange, p->nCol, p->apValue); + if( p->rc!=SQLITE_OK ) return p->rc; + } + + /* If this is an INSERT or UPDATE, read the new.* record. */ + if( p->op!=SQLITE_DELETE ){ + p->rc = sessionReadRecord(&aChange, p->nCol, &p->apValue[p->nCol]); + if( p->rc!=SQLITE_OK ) return p->rc; + } + + p->pNext = aChange; + return SQLITE_ROW; +} + +/* +** The following three functions extract information on the current change +** from a changeset iterator. They may only be called after changeset_next() +** has returned SQLITE_ROW. +*/ +int sqlite3changeset_op( + sqlite3_changeset_iter *pIter, + const char **pzTab, /* OUT: Pointer to table name */ + int *pnCol, /* OUT: Number of columns in table */ + int *pOp /* OUT: SQLITE_INSERT, DELETE or UPDATE */ +){ + *pOp = pIter->op; + *pnCol = pIter->nCol; + *pzTab = pIter->zTab; + return SQLITE_OK; +} + +int sqlite3changeset_old( + sqlite3_changeset_iter *pIter, + int iVal, + sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ +){ + if( iVal<0 || iVal>=pIter->nCol ){ + return SQLITE_RANGE; + } + *ppValue = pIter->apValue[iVal]; + return SQLITE_OK; +} + +int sqlite3changeset_new( + sqlite3_changeset_iter *pIter, + int iVal, + sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ +){ + if( iVal<0 || iVal>=pIter->nCol ){ + return SQLITE_RANGE; + } + *ppValue = pIter->apValue[pIter->nCol+iVal]; + return SQLITE_OK; +} + +/* +** Finalize an iterator allocated with sqlite3changeset_start(). +** +** This function may not be called on iterators passed to a conflict handler +** callback by changeset_apply(). +*/ +int sqlite3changeset_finalize(sqlite3_changeset_iter *p){ + int i; + int rc = p->rc; + for(i=0; inCol*2; i++) sqlite3ValueFree(p->apValue[i]); + sqlite3_free(p->apValue); + sqlite3_free(p); + return rc; +} + +#endif /* #ifdef SQLITE_ENABLE_SESSION */ diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h new file mode 100644 index 0000000000..a62b8b654e --- /dev/null +++ b/ext/session/sqlite3session.h @@ -0,0 +1,125 @@ + +#ifndef __SQLITESESSION_H_ +#define __SQLITESESSION_H_ 1 + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" { +#endif + +#include "sqlite3.h" + +typedef struct sqlite3_session sqlite3_session; +typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; + +/* +** Create a session object. This session object will record changes to +** database zDb attached to connection db. +*/ +int sqlite3session_create( + sqlite3 *db, /* Database handle */ + const char *zDb, /* Name of db (e.g. "main") */ + sqlite3_session **ppSession /* OUT: New session object */ +); + +/* +** Enable or disable the recording of changes by a session object. When +** enabled, a session object records changes made to the database. When +** disabled - it does not. A newly created session object is enabled. +** +** Passing zero to this function disables the session. Passing a value +** greater than zero enables it. Passing a value less than zero is a +** no-op, and may be used to query the current state of the session. +** +** The return value indicates the final state of the session object: 0 if +** the session is disabled, or 1 if it is enabled. +*/ +int sqlite3session_enable(sqlite3_session *pSession, int bEnable); + +/* +** Attach a table to a session. All subsequent changes made to the table +** while the session object is enabled will be recorded. +** +** Only tables that have a PRIMARY KEY defined may be attached. It does +** not matter if the PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) +** or not. +*/ +int sqlite3session_attach( + sqlite3_session *pSession, /* Session object */ + const char *zTab /* Table name */ +); + +/* +** Obtain a changeset object containing all changes recorded by the +** session object passed as the first argument. +** +** It is the responsibility of the caller to eventually free the buffer +** using sqlite3_free(). +*/ +int sqlite3session_changeset( + sqlite3_session *pSession, /* Session object */ + int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ + void **ppChangeset /* OUT: Buffer containing changeset */ +); + +/* +** Delete a session object previously allocated using sqlite3session_create(). +*/ +void sqlite3session_delete(sqlite3_session *pSession); + + +/* +** Create an iterator used to iterate through the contents of a changeset. +*/ +int sqlite3changeset_start( + sqlite3_changeset_iter **ppIter, + int nChangeset, + void *pChangeset +); + +/* +** Advance an iterator created by sqlite3changeset_start() to the next +** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE +** or SQLITE_CORRUPT. +** +** This function may not be called on iterators passed to a conflict handler +** callback by changeset_apply(). +*/ +int sqlite3changeset_next(sqlite3_changeset_iter *pIter); + +/* +** The following three functions extract information on the current change +** from a changeset iterator. They may only be called after changeset_next() +** has returned SQLITE_ROW. +*/ +int sqlite3changeset_op( + sqlite3_changeset_iter *pIter, /* Iterator object */ + const char **pzTab, /* OUT: Pointer to table name */ + int *pnCol, /* OUT: Number of columns in table */ + int *pOp /* OUT: SQLITE_INSERT, DELETE or UPDATE */ +); + +int sqlite3changeset_old( + sqlite3_changeset_iter *pIter, + int iVal, + sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ +); + +int sqlite3changeset_new( + sqlite3_changeset_iter *pIter, + int iVal, + sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ +); + +/* +** Finalize an iterator allocated with sqlite3changeset_start(). +** +** This function may not be called on iterators passed to a conflict handler +** callback by changeset_apply(). +*/ +int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); + +#endif + diff --git a/ext/session/test_session.c b/ext/session/test_session.c new file mode 100644 index 0000000000..9c37fdb285 --- /dev/null +++ b/ext/session/test_session.c @@ -0,0 +1,258 @@ + +#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_SESSION) + +#include "sqlite3session.h" +#include +#include +#include + +static int test_session_error(Tcl_Interp *interp, int rc){ + extern const char *sqlite3TestErrorName(int); + Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3TestErrorName(rc), -1)); + return TCL_ERROR; +} + +/* +** Tclcmd: $session attach TABLE +** $session changeset +** $session delete +** $session enable BOOL +*/ +static int test_session_cmd( + void *clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_session *pSession = (sqlite3_session *)clientData; + struct SessionSubcmd { + const char *zSub; + int nArg; + const char *zMsg; + int iSub; + } aSub[] = { + { "attach", 1, "TABLE", }, /* 0 */ + { "changeset", 0, "", }, /* 1 */ + { "delete", 0, "", }, /* 2 */ + { "enable", 1, "", }, /* 3 */ + { 0 } + }; + int iSub; + int rc; + + if( objc<2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); + return TCL_ERROR; + } + rc = Tcl_GetIndexFromObjStruct(interp, + objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iSub + ); + if( rc!=TCL_OK ) return rc; + if( objc!=2+aSub[iSub].nArg ){ + Tcl_WrongNumArgs(interp, 2, objv, aSub[iSub].zMsg); + return TCL_ERROR; + } + + switch( iSub ){ + case 0: /* attach */ + rc = sqlite3session_attach(pSession, Tcl_GetString(objv[2])); + if( rc!=SQLITE_OK ){ + return test_session_error(interp, rc); + } + break; + + case 1: { /* changeset */ + int nChange; + void *pChange; + rc = sqlite3session_changeset(pSession, &nChange, &pChange); + if( rc==SQLITE_OK ){ + Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pChange, nChange)); + sqlite3_free(pChange); + }else{ + return test_session_error(interp, rc); + } + break; + } + + case 2: /* delete */ + Tcl_DeleteCommand(interp, Tcl_GetString(objv[0])); + break; + + case 3: { /* enable */ + int val; + if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; + val = sqlite3session_enable(pSession, val); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val)); + break; + } + } + + return TCL_OK; +} + +static void test_session_del(void *clientData){ + sqlite3_session *pSession = (sqlite3_session *)clientData; + sqlite3session_delete(pSession); +} + +/* +** Tclcmd: sqlite3session CMD DB-HANDLE DB-NAME +*/ +static int test_sqlite3session( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + Tcl_CmdInfo info; + int rc; /* sqlite3session_create() return code */ + sqlite3_session *pSession; /* New session object */ + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "CMD DB-HANDLE DB-NAME"); + return TCL_ERROR; + } + + if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[2]), &info) ){ + Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(objv[2]), 0); + return TCL_ERROR; + } + db = *(sqlite3 **)info.objClientData; + + rc = sqlite3session_create(db, Tcl_GetString(objv[3]), &pSession); + if( rc!=SQLITE_OK ){ + return test_session_error(interp, rc); + } + + Tcl_CreateObjCommand( + interp, Tcl_GetString(objv[1]), test_session_cmd, (ClientData)pSession, + test_session_del + ); + Tcl_SetObjResult(interp, objv[1]); + return TCL_OK; +} + +static void test_append_value(Tcl_Obj *pList, sqlite3_value *pVal){ + if( pVal==0 ){ + Tcl_ListObjAppendElement(0, pList, Tcl_NewObj()); + Tcl_ListObjAppendElement(0, pList, Tcl_NewObj()); + }else{ + Tcl_Obj *pObj; + switch( sqlite3_value_type(pVal) ){ + case SQLITE_NULL: + Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("n", 1)); + pObj = Tcl_NewObj(); + break; + case SQLITE_INTEGER: + Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("i", 1)); + pObj = Tcl_NewWideIntObj(sqlite3_value_int64(pVal)); + break; + case SQLITE_FLOAT: + Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("f", 1)); + pObj = Tcl_NewDoubleObj(sqlite3_value_double(pVal)); + break; + case SQLITE_TEXT: + Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("t", 1)); + pObj = Tcl_NewStringObj((char *)sqlite3_value_text(pVal), -1); + break; + case SQLITE_BLOB: + Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("b", 1)); + pObj = Tcl_NewByteArrayObj( + sqlite3_value_blob(pVal), + sqlite3_value_bytes(pVal) + ); + break; + } + Tcl_ListObjAppendElement(0, pList, pObj); + } +} + +/* +** sqlite3session_foreach VARNAME CHANGESET SCRIPT +*/ +static int test_sqlite3session_foreach( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + void *pChangeSet; + int nChangeSet; + sqlite3_changeset_iter *pIter; + int rc; + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "VARNAME CHANGESET SCRIPT"); + return TCL_ERROR; + } + + pChangeSet = (void *)Tcl_GetByteArrayFromObj(objv[2], &nChangeSet); + rc = sqlite3changeset_start(&pIter, nChangeSet, pChangeSet); + if( rc!=SQLITE_OK ){ + return test_session_error(interp, rc); + } + + while( SQLITE_ROW==sqlite3changeset_next(pIter) ){ + int nCol; /* Number of columns in table */ + int op; /* SQLITE_INSERT, UPDATE or DELETE */ + const char *zTab; /* Name of table change applies to */ + Tcl_Obj *pVar; /* Tcl value to set $VARNAME to */ + Tcl_Obj *pOld; /* Vector of old.* values */ + Tcl_Obj *pNew; /* Vector of new.* values */ + + sqlite3changeset_op(pIter, &zTab, &nCol, &op); + pVar = Tcl_NewObj(); + Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj( + op==SQLITE_INSERT ? "INSERT" : + op==SQLITE_UPDATE ? "UPDATE" : + "DELETE", -1 + )); + Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zTab, -1)); + + pOld = Tcl_NewObj(); + if( op!=SQLITE_INSERT ){ + int i; + for(i=0; ipUnpacked==0 ){ - KeyInfo keyinfo; u32 nRecord; u8 *aRecord; - memset(&keyinfo, 0, sizeof(KeyInfo)); - keyinfo.db = db; - keyinfo.enc = ENC(db); - keyinfo.nField = p->pCsr->nField; - rc = sqlite3BtreeDataSize(p->pCsr->pCursor, &nRecord); if( rc!=SQLITE_OK ) goto preupdate_old_out; aRecord = sqlite3DbMallocRaw(db, nRecord); @@ -1370,7 +1364,7 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ goto preupdate_old_out; } - p->pUnpacked = sqlite3VdbeRecordUnpack(&keyinfo, nRecord, aRecord, 0, 0); + p->pUnpacked = sqlite3VdbeRecordUnpack(&p->keyinfo, nRecord, aRecord, 0, 0); p->aRecord = aRecord; } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 937c2a1998..cb6aefac08 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3194,6 +3194,9 @@ void sqlite3VdbePreUpdateHook( preupdate.pCsr = pCsr; preupdate.op = op; + preupdate.keyinfo.db = db; + preupdate.keyinfo.enc = ENC(db); + preupdate.keyinfo.nField = pCsr->nField; db->pPreUpdate = &preupdate; db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); db->pPreUpdate = 0; diff --git a/test/session1.test b/test/session1.test new file mode 100644 index 0000000000..0cb225a2fd --- /dev/null +++ b/test/session1.test @@ -0,0 +1,118 @@ +# 2011 March 07 +# +# 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. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set ::testprefix session1 + +do_execsql_test 1.0 { + CREATE TABLE t1(x, y); + INSERT INTO t1 VALUES('abc', 'def'); +} + +do_test 1.1 { sqlite3session S db main } {S} +do_test 1.2 { S delete } {} +do_test 1.3 { sqlite3session S db main } {S} +do_test 1.4 { S attach t1 } {} +do_test 1.5 { S delete } {} +do_test 1.6 { sqlite3session S db main } {S} +do_test 1.7 { S attach t1 ; S attach t2 ; S attach t3 } {} +do_test 1.8 { S attach t1 ; S attach t2 ; S attach t3 } {} +do_test 1.9 { S delete } {} +do_test 1.10 { + sqlite3session S db main + S attach t1 + execsql { INSERT INTO t1 VALUES('ghi', 'jkl') } +} {} +do_test 1.11 { S delete } {} +do_test 1.12 { + sqlite3session S db main + S attach t1 + execsql { INSERT INTO t1 VALUES('mno', 'pqr') } + execsql { UPDATE t1 SET x = 111 WHERE rowid = 1 } + execsql { DELETE FROM t1 WHERE rowid = 2 } +} {} +do_test 1.13 { + S changeset + S delete +} {} + +proc do_changeset_test {tn session res} { + set r [list] + foreach x $res {lappend r $x} + uplevel do_test $tn [list [subst -nocommands { + set x [list] + sqlite3session_foreach c [$session changeset] { lappend x [set c] } + set x + }]] [list $r] +} + +do_test 2.1.1 { + execsql { DELETE FROM t1 } + sqlite3session S db main + S attach t1 + execsql { INSERT INTO t1 VALUES(1, 'Sukhothai') } + execsql { INSERT INTO t1 VALUES(2, 'Ayutthaya') } + execsql { INSERT INTO t1 VALUES(3, 'Thonburi') } +} {} +do_changeset_test 2.1.2 S { + {INSERT t1 {} {i 1 t Sukhothai}} + {INSERT t1 {} {i 2 t Ayutthaya}} + {INSERT t1 {} {i 3 t Thonburi}} +} +do_test 2.1.3 { S delete } {} + +do_test 2.2.1 { + sqlite3session S db main + S attach t1 + execsql { DELETE FROM t1 WHERE 1 } +} {} +do_changeset_test 2.2.2 S { + {DELETE t1 {i 1 t Sukhothai} {}} + {DELETE t1 {i 2 t Ayutthaya} {}} + {DELETE t1 {i 3 t Thonburi} {}} +} +do_test 2.2.3 { S delete } {} + +do_test 2.3.1 { + sqlite3session S db main + execsql { INSERT INTO t1 VALUES(1, 'Sukhothai') } + execsql { INSERT INTO t1 VALUES(2, 'Ayutthaya') } + execsql { INSERT INTO t1 VALUES(3, 'Thonburi') } + S attach t1 + execsql { + UPDATE t1 SET x = 10 WHERE x = 1; + UPDATE t1 SET y = 'Surin' WHERE x = 2; + UPDATE t1 SET x = 20, y = 'Thapae' WHERE x = 3; + } +} {} + +do_changeset_test 2.3.2 S { + {UPDATE t1 {i 1 {} {}} {i 10 {} {}}} + {UPDATE t1 {{} {} t Ayutthaya} {{} {} t Surin}} + {UPDATE t1 {i 3 t Thonburi} {i 20 t Thapae}} +} +do_test 2.3.3 { S delete } {} + +do_test 2.4.1 { + sqlite3session S db main + S attach t1 + execsql { INSERT INTO t1 VALUES(100, 'Bangkok') } + execsql { DELETE FROM t1 WHERE x = 100 } +} {} + +breakpoint +do_changeset_test 2.4.2 S {} +do_test 2.4.3 { S delete } {} + +finish_test From 91ddd5595b0a7aaf0183765a705f29a95c6cfb2d Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 9 Mar 2011 11:17:05 +0000 Subject: [PATCH 004/570] Add a function to the session extension invert a changeset. FossilOrigin-Name: 75d5dff725dbb66d67d56ad042926f1daae56dbe --- ext/session/sqlite3session.c | 108 +++++++++++++++++++++++++++++++---- ext/session/sqlite3session.h | 9 +++ ext/session/test_session.c | 32 +++++++++++ manifest | 18 +++--- manifest.uuid | 2 +- test/session1.test | 64 +++++++++++++++------ 6 files changed, 195 insertions(+), 38 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index eb024775fd..0b6a985279 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -839,28 +839,34 @@ static int sessionReadRecord( for(i=0; i Date: Fri, 11 Mar 2011 19:05:52 +0000 Subject: [PATCH 005/570] Add the sqlite3changeset_apply() function. Does not yet handle all cases. FossilOrigin-Name: 2b19be7bf753c7dd12e1c3b384981a3ea1bc8145 --- ext/session/sqlite3session.c | 606 ++++++++++++++++++++++++++++++++++- ext/session/sqlite3session.h | 45 +++ ext/session/test_session.c | 137 ++++++++ manifest | 18 +- manifest.uuid | 2 +- test/session1.test | 132 ++++++++ 6 files changed, 924 insertions(+), 16 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 0b6a985279..86778d65f0 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -573,6 +573,47 @@ static void sessionAppendBlob( } } +static void sessionAppendStr( + SessionBuffer *p, + const char *zStr, + int *pRc +){ + int nStr = strlen(zStr); + if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, nStr, pRc) ){ + memcpy(&p->aBuf[p->nBuf], zStr, nStr); + p->nBuf += nStr; + } +} + +static void sessionAppendInteger( + SessionBuffer *p, + int iVal, + int *pRc +){ + char aBuf[24]; + sqlite3_snprintf(sizeof(aBuf)-1, aBuf, "%d", iVal); + sessionAppendStr(p, aBuf, pRc); +} + +static void sessionAppendIdent( + SessionBuffer *p, + const char *zStr, + int *pRc +){ + int nStr = strlen(zStr)*2 + 2 + 1; + if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, nStr, pRc) ){ + char *zOut = (char *)&p->aBuf[p->nBuf]; + const char *zIn = zStr; + *zOut++ = '"'; + while( *zIn ){ + if( *zIn=='"' ) *zOut++ = '"'; + *zOut++ = *(zIn++); + } + *zOut++ = '"'; + p->nBuf = ((u8 *)zOut - p->aBuf); + } +} + static void sessionAppendCol( SessionBuffer *p, sqlite3_stmt *pStmt, @@ -616,6 +657,7 @@ static void sessionAppendUpdate( sqlite3_stmt *pStmt, SessionBuffer *pBuf, SessionChange *p, + u8 *abPK, int *pRc ){ if( *pRc==SQLITE_OK ){ @@ -667,6 +709,9 @@ static void sessionAppendUpdate( nCopy = nAdvance; } } + if( abPK[i] ){ + nCopy = nAdvance; + } if( nCopy==0 ){ sessionAppendByte(pBuf, 0, pRc); @@ -686,8 +731,98 @@ static void sessionAppendUpdate( sqlite3_free(buf2.aBuf); } } +} +static int sessionTableInfo( + sqlite3 *db, /* Database connection */ + const char *zThis, /* Table name */ + int nCol, /* Expected number of columns */ + const char **pzTab, /* OUT: Copy of zThis */ + const char ***pazCol, /* OUT: Array of column names for table */ + u8 **pabPK /* OUT: Array of booleans - true for PK col */ +){ + char *zPragma; + sqlite3_stmt *pStmt; + int rc; + int nByte; + int nDbCol = 0; + int nThis; + int i; + u8 *pAlloc; + u8 *pFree = 0; + char **azCol; + u8 *abPK; + + nThis = strlen(zThis); + zPragma = sqlite3_mprintf("PRAGMA main.table_info('%q')", zThis); + if( !zPragma ) return SQLITE_NOMEM; + + rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0); + sqlite3_free(zPragma); + if( rc!=SQLITE_OK ) return rc; + + nByte = nThis + 1; + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + nByte += sqlite3_column_bytes(pStmt, 1); + nDbCol++; + } + rc = sqlite3_reset(pStmt); + + if( nDbCol!=nCol ){ + rc = SQLITE_SCHEMA; + } + if( rc==SQLITE_OK ){ + nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1); + pAlloc = sqlite3_malloc(nByte); + if( pAlloc==0 ){ + rc = SQLITE_NOMEM; + } + } + if( rc==SQLITE_OK ){ + pFree = pAlloc; + if( pazCol ){ + azCol = (char **)pAlloc; + pAlloc = (u8 *)&azCol[nCol]; + } + if( pabPK ){ + abPK = (u8 *)pAlloc; + pAlloc = &abPK[nCol]; + } + if( pzTab ){ + memcpy(pAlloc, zThis, nThis+1); + *pzTab = (char *)pAlloc; + pAlloc += nThis+1; + } + + i = 0; + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + int nName = sqlite3_column_bytes(pStmt, 1); + const unsigned char *zName = sqlite3_column_text(pStmt, 1); + if( zName==0 ) break; + if( pazCol ){ + memcpy(pAlloc, zName, nName+1); + azCol[i] = (char *)pAlloc; + pAlloc += nName+1; + } + if( pabPK ) abPK[i] = sqlite3_column_int(pStmt, 5); + i++; + } + rc = sqlite3_reset(pStmt); + + } + if( rc==SQLITE_OK ){ + if( pazCol ) *pazCol = (const char **)azCol; + if( pabPK ) *pabPK = abPK; + }else{ + if( pazCol ) *pazCol = 0; + if( pabPK ) *pabPK = 0; + if( pzTab ) *pzTab = 0; + sqlite3_free(pFree); + } + + sqlite3_finalize(pStmt); + return rc; } /* @@ -717,6 +852,7 @@ int sqlite3session_changeset( sqlite3_stmt *pStmt = 0; int bNoop = 1; int nRewind = buf.nBuf; + u8 *abPK = 0; /* Write a table header */ sessionAppendByte(&buf, 'T', &rc); @@ -740,6 +876,10 @@ int sqlite3session_changeset( rc = SQLITE_SCHEMA; } + if( rc==SQLITE_OK ){ + rc = sessionTableInfo(db, pTab->zName, pTab->nCol, 0, 0, &abPK); + } + for(i=0; inChange; i++){ SessionChange *p; for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ @@ -747,7 +887,7 @@ int sqlite3session_changeset( if( sqlite3_step(pStmt)==SQLITE_ROW ){ int iCol; if( p->aRecord ){ - sessionAppendUpdate(pStmt, &buf, p, &rc); + sessionAppendUpdate(pStmt, &buf, p, abPK, &rc); }else{ sessionAppendByte(&buf, SQLITE_INSERT, &rc); for(iCol=0; iColnCol; iCol++){ @@ -766,6 +906,7 @@ int sqlite3session_changeset( } sqlite3_finalize(pStmt); + sqlite3_free(abPK); if( bNoop ){ buf.nBuf = nRewind; @@ -797,6 +938,7 @@ struct sqlite3_changeset_iter { u8 *pNext; /* Pointer to next change within aChangeset */ int rc; + sqlite3_stmt *pConflict; /* Conflicting row, if any */ char *zTab; /* Current table */ int nCol; /* Number of columns in zTab */ int op; /* Current operation */ @@ -947,9 +1089,9 @@ int sqlite3changeset_next(sqlite3_changeset_iter *p){ */ int sqlite3changeset_op( sqlite3_changeset_iter *pIter, - const char **pzTab, /* OUT: Pointer to table name */ - int *pnCol, /* OUT: Number of columns in table */ - int *pOp /* OUT: SQLITE_INSERT, DELETE or UPDATE */ + const char **pzTab, /* OUT: Pointer to table name */ + int *pnCol, /* OUT: Number of columns in table */ + int *pOp /* OUT: SQLITE_INSERT, DELETE or UPDATE */ ){ *pOp = pIter->op; *pnCol = pIter->nCol; @@ -960,8 +1102,11 @@ int sqlite3changeset_op( int sqlite3changeset_old( sqlite3_changeset_iter *pIter, int iVal, - sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ + sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ ){ + if( pIter->op!=SQLITE_UPDATE && pIter->op!=SQLITE_DELETE ){ + return SQLITE_MISUSE; + } if( iVal<0 || iVal>=pIter->nCol ){ return SQLITE_RANGE; } @@ -972,8 +1117,11 @@ int sqlite3changeset_old( int sqlite3changeset_new( sqlite3_changeset_iter *pIter, int iVal, - sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ + sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ ){ + if( pIter->op!=SQLITE_UPDATE && pIter->op!=SQLITE_INSERT ){ + return SQLITE_MISUSE; + } if( iVal<0 || iVal>=pIter->nCol ){ return SQLITE_RANGE; } @@ -981,6 +1129,21 @@ int sqlite3changeset_new( return SQLITE_OK; } +int sqlite3changeset_conflict( + sqlite3_changeset_iter *pIter, + int iVal, + sqlite3_value **ppValue /* OUT: Value from conflicting row */ +){ + if( !pIter->pConflict ){ + return SQLITE_MISUSE; + } + if( iVal<0 || iVal>=sqlite3_column_count(pIter->pConflict) ){ + return SQLITE_RANGE; + } + *ppValue = sqlite3_column_value(pIter->pConflict, iVal); + return SQLITE_OK; +} + /* ** Finalize an iterator allocated with sqlite3changeset_start(). ** @@ -1073,5 +1236,436 @@ int sqlite3changeset_invert( return SQLITE_OK; } +static void sessionUpdateDeleteWhere( + SessionBuffer *pBuf, /* Buffer to append to */ + int nCol, /* Number of entries in azCol and abPK */ + const char **azCol, /* Column names */ + u8 *abPK, /* True for PK columns */ + int *pRc /* IN/OUT: Error code */ +){ + if( *pRc==SQLITE_OK ){ + int i; + const char *zSep = ""; + + sessionAppendStr(pBuf, " WHERE ", pRc); + + for(i=0; ipConflict = pSelect; + res = xConflict(pCtx, SQLITE_CHANGESET_DATA, pIter); + pIter->pConflict = 0; + sqlite3_reset(pSelect); + }else{ + rc = sqlite3_reset(pSelect); + if( rc==SQLITE_OK ){ + res = xConflict(pCtx, SQLITE_CHANGESET_NOTFOUND, pIter); + } + } + + }else if( rc==SQLITE_CONSTRAINT ){ + res = xConflict(pCtx, SQLITE_CHANGESET_CONSTRAINT, pIter); + rc = SQLITE_OK; + } + + if( rc!=SQLITE_OK ) break; + + }else if( op==SQLITE_UPDATE ){ + int i; + int res; + rc = sessionUpdateRow(db, zTab, nCol, azCol, abPK, &pUpdate); + for(i=0; rc==SQLITE_OK && ipConflict = pSelect; + res = xConflict(pCtx, SQLITE_CHANGESET_DATA, pIter); + pIter->pConflict = 0; + sqlite3_reset(pSelect); + }else{ + rc = sqlite3_reset(pSelect); + if( rc==SQLITE_OK ){ + res = xConflict(pCtx, SQLITE_CHANGESET_NOTFOUND, pIter); + } + } + }else if( rc==SQLITE_CONSTRAINT ){ + assert(0); + } + + }else{ + int i; + assert( op==SQLITE_INSERT ); + if( pInsert==0 ){ + SessionBuffer buf = {0, 0, 0}; + sessionAppendStr(&buf, "INSERT INTO main.", &rc); + sessionAppendIdent(&buf, zTab, &rc); + sessionAppendStr(&buf, " VALUES(?", &rc); + for(i=1; ipConflict = pSelect; + res = xConflict(pCtx, SQLITE_CHANGESET_CONFLICT, pIter); + pIter->pConflict = 0; + sqlite3_reset(pSelect); + }else{ + rc = sqlite3_reset(pSelect); + if( rc==SQLITE_OK ){ + res = xConflict(pCtx, SQLITE_CHANGESET_CONSTRAINT, pIter); + } + } + } + } + } + rc2 = sqlite3changeset_finalize(pIter); + if( rc==SQLITE_DONE ) rc = rc2; + + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); + }else{ + sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0); + sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); + } + + sqlite3_finalize(pInsert); + sqlite3_finalize(pDelete); + sqlite3_finalize(pUpdate); + sqlite3_finalize(pSelect); + sqlite3_free(azCol); + return rc; +} #endif /* #ifdef SQLITE_ENABLE_SESSION */ diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index fe6ca2075b..8c3a708ce8 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -112,6 +112,21 @@ int sqlite3changeset_new( int iVal, sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ ); +/* +** This function is only usable with sqlite3_changeset_iter objects passed +** to the xConflict callback by sqlite3changeset_apply(). It cannot be used +** with iterators created using sqlite3changeset_start(). +** +** It is used to access the "conflicting row" information available to the +** conflict handler if the second argument is either SQLITE_CHANGESET_DATA +** or SQLITE_CHANGESET_CONFLICT. +*/ +int sqlite3changeset_conflict( + sqlite3_changeset_iter *pIter, + int iVal, + sqlite3_value **ppValue /* OUT: Value from conflicting row */ +); + /* ** Finalize an iterator allocated with sqlite3changeset_start(). @@ -129,6 +144,36 @@ int sqlite3changeset_invert( int *pnOut, void **ppOut /* OUT: Inverse of input */ ); +/* +** Apply a changeset to a database. +** +** It is safe to execute SQL statements, including those that write to the +** table that the callback related to, from within the xConflict callback. +** This can be used to further customize the applications conflict +** resolution strategy. +*/ +int sqlite3changeset_apply( + sqlite3 *db, + int nChangeset, + void *pChangeset, + int(*xConflict)( + void *pCtx, /* Copy of fifth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx +); + +/* Values passed as the second argument to a conflict-handler */ +#define SQLITE_CHANGESET_DATA 1 +#define SQLITE_CHANGESET_NOTFOUND 2 +#define SQLITE_CHANGESET_CONFLICT 3 +#define SQLITE_CHANGESET_CONSTRAINT 4 + +/* Valid return values from a conflict-handler */ +#define SQLITE_CHANGESET_OMIT 0 +#define SQLITE_CHANGESET_REPLACE 1 +#define SQLITE_CHANGESET_ABORT 2 #endif diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 1e8a9eccf6..a805280787 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -168,6 +168,139 @@ static void test_append_value(Tcl_Obj *pList, sqlite3_value *pVal){ } } +typedef struct TestConflictHandler TestConflictHandler; +struct TestConflictHandler { + Tcl_Interp *interp; + Tcl_Obj *pScript; +}; + +static int test_conflict_handler( + void *pCtx, /* Pointer to TestConflictHandler structure */ + int eConf, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *pIter /* Handle describing change and conflict */ +){ + TestConflictHandler *p = (TestConflictHandler *)pCtx; + Tcl_Obj *pEval; + Tcl_Interp *interp = p->interp; + + int op; /* SQLITE_UPDATE, DELETE or INSERT */ + const char *zTab; /* Name of table conflict is on */ + int nCol; /* Number of columns in table zTab */ + + pEval = Tcl_DuplicateObj(p->pScript); + Tcl_IncrRefCount(pEval); + + sqlite3changeset_op(pIter, &zTab, &nCol, &op); + + /* Append the operation type. */ + Tcl_ListObjAppendElement(0, pEval, Tcl_NewStringObj( + op==SQLITE_INSERT ? "INSERT" : + op==SQLITE_UPDATE ? "UPDATE" : + "DELETE", -1 + )); + + /* Append the table name. */ + Tcl_ListObjAppendElement(0, pEval, Tcl_NewStringObj(zTab, -1)); + + /* Append the conflict type. */ + switch( eConf ){ + case SQLITE_CHANGESET_DATA: + Tcl_ListObjAppendElement(interp, pEval,Tcl_NewStringObj("DATA",-1)); + break; + case SQLITE_CHANGESET_NOTFOUND: + Tcl_ListObjAppendElement(interp, pEval,Tcl_NewStringObj("NOTFOUND",-1)); + break; + case SQLITE_CHANGESET_CONFLICT: + Tcl_ListObjAppendElement(interp, pEval,Tcl_NewStringObj("CONFLICT",-1)); + break; + case SQLITE_CHANGESET_CONSTRAINT: + Tcl_ListObjAppendElement(interp, pEval,Tcl_NewStringObj("CONSTRAINT",-1)); + break; + } + + /* If this is not an INSERT, append the old row */ + if( op!=SQLITE_INSERT ){ + int i; + Tcl_Obj *pOld = Tcl_NewObj(); + for(i=0; i Date: Sat, 12 Mar 2011 17:22:46 +0000 Subject: [PATCH 006/570] Fix some issues with UPDATE changes in the session module. FossilOrigin-Name: 57862efe718fdc93401998f9058511292a0e1a50 --- ext/session/sqlite3session.c | 134 +++++++++++++++++++++++++---------- manifest | 14 ++-- manifest.uuid | 2 +- test/session1.test | 21 ++++-- 4 files changed, 120 insertions(+), 51 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 86778d65f0..2ff0bc56fe 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -667,14 +667,14 @@ static void sessionAppendUpdate( u8 *pCsr = p->aRecord; sessionAppendByte(pBuf, SQLITE_UPDATE, pRc); for(i=0; ipConflict = pSelect; + res = xConflict(pCtx, SQLITE_CHANGESET_CONFLICT, pIter); + pIter->pConflict = 0; + sqlite3_reset(pSelect); + }else{ + /* No other row with the new.* primary key. */ + rc = sqlite3_reset(pSelect); + if( rc==SQLITE_OK ){ + res = xConflict(pCtx, SQLITE_CHANGESET_CONSTRAINT, pIter); + } + } + + return rc; +} + int sqlite3changeset_apply( sqlite3 *db, int nChangeset, @@ -1479,6 +1527,8 @@ int sqlite3changeset_apply( sqlite3_stmt *pSelect = 0; /* SELECT statement */ rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); + if( rc!=SQLITE_OK ) return rc; + sqlite3changeset_start(&pIter, nChangeset, pChangeset); while( SQLITE_ROW==sqlite3changeset_next(pIter) ){ int op; @@ -1494,6 +1544,13 @@ int sqlite3changeset_apply( sqlite3_finalize(pInsert); sqlite3_finalize(pSelect); pSelect = pUpdate = pInsert = pDelete = 0; + + if( (rc = sessionSelectRow(db, zTab, nCol, azCol, abPK, &pSelect)) + || (rc = sessionUpdateRow(db, zTab, nCol, azCol, abPK, &pUpdate)) + || (rc = sessionDeleteRow(db, zTab, nCol, azCol, abPK, &pDelete)) + ){ + break; + } } if( op==SQLITE_DELETE ){ @@ -1559,7 +1616,7 @@ int sqlite3changeset_apply( if( rc==SQLITE_OK ){ if( pOld ) sqlite3_bind_value(pUpdate, i*3+1, pOld); sqlite3_bind_int(pUpdate, i*3+2, !!pNew); - if( pNew ) sqlite3_bind_value(pUpdate, i*3+3, pOld); + if( pNew ) sqlite3_bind_value(pUpdate, i*3+3, pNew); } } if( rc==SQLITE_OK ) rc = sqlite3_bind_int(pUpdate, nCol*3+1, 0); @@ -1592,7 +1649,32 @@ int sqlite3changeset_apply( } } }else if( rc==SQLITE_CONSTRAINT ){ - assert(0); + /* This may be a CONSTRAINT or CONFLICT error. It is a CONFLICT if + ** the only problem is a duplicate PRIMARY KEY, or a CONSTRAINT + ** otherwise. */ + int bPKChange = 0; + + /* Check if the PK has been modified. */ + rc = SQLITE_OK; + for(i=0; ipConflict = pSelect; - res = xConflict(pCtx, SQLITE_CHANGESET_CONFLICT, pIter); - pIter->pConflict = 0; - sqlite3_reset(pSelect); - }else{ - rc = sqlite3_reset(pSelect); - if( rc==SQLITE_OK ){ - res = xConflict(pCtx, SQLITE_CHANGESET_CONSTRAINT, pIter); - } - } + rc = sessionConstraintConflict( + db, pIter, abPK, pSelect, xConflict, pCtx + ); } } } diff --git a/manifest b/manifest index b3938bacd9..38e0a86e95 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssqlite3changeset_apply()\sfunction.\sDoes\snot\syet\shandle\sall\scases. -D 2011-03-11T19:05:52 +C Fix\ssome\sissues\swith\sUPDATE\schanges\sin\sthe\ssession\smodule. +D 2011-03-12T17:22:46 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -98,7 +98,7 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/sqlite3session.c 724a064f0d9a909c12dfb668b42ce007378f352e +F ext/session/sqlite3session.c af63d87b8787c19b4a4b681f77331a9cc13d67af F ext/session/sqlite3session.h 3246613b20857e58f7419e4e26dbe9161677aff0 F ext/session/test_session.c 1b4f278d0ae164e2d02c11f5e1f2df3a2567ba41 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 @@ -639,7 +639,7 @@ F test/selectA.test 06d1032fa9009314c95394f2ca2e60d9f7ae8532 F test/selectB.test f305cc6660804cb239aab4e2f26b0e288b59958b F test/selectC.test f9bf1bc4581b5b8158caa6e4e4f682acb379fb25 F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c -F test/session1.test 6a2e0db809e44879cec5314a6fd238ad768d9723 +F test/session1.test 6ec522f3491fbdbf8a5b6c27f50b9e35f24e3dba F test/shared.test b9114eaea7e748a3a4c8ff7b9ca806c8f95cef3e F test/shared2.test 7f6ad2d857d0f4e5d6a0b9a897b5e56a6b6ea18c F test/shared3.test d69bdd5f156580876c5345652d21dc2092e85962 @@ -913,7 +913,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 75d5dff725dbb66d67d56ad042926f1daae56dbe -R 7203b6a6763bad83d70ecbe2db2167c5 +P 2b19be7bf753c7dd12e1c3b384981a3ea1bc8145 +R 222ffce3b378b2ba18950183bb251367 U dan -Z 77d8992b93ad5a2a0231fb47a635b3cb +Z b642b18410bb67d03067201d5612ecd6 diff --git a/manifest.uuid b/manifest.uuid index f741e56cff..b6d1059b89 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2b19be7bf753c7dd12e1c3b384981a3ea1bc8145 \ No newline at end of file +57862efe718fdc93401998f9058511292a0e1a50 \ No newline at end of file diff --git a/test/session1.test b/test/session1.test index 737d796ba3..5706b77bc5 100644 --- a/test/session1.test +++ b/test/session1.test @@ -259,22 +259,29 @@ do_execsql_test 3.3.1 { CREATE TABLE t4(a, b, c, PRIMARY KEY(b, c)); INSERT INTO t4 VALUES(1, 2, 3); INSERT INTO t4 VALUES(4, 5, 6); + INSERT INTO t4 VALUES(7, 8, 9); + INSERT INTO t4 VALUES(10, 11, 12); } do_db2_test 3.3.2 { - CREATE TABLE t4(a, b, c, PRIMARY KEY(b, c)); + CREATE TABLE t4(a NOT NULL, b, c, PRIMARY KEY(b, c)); INSERT INTO t4 VALUES(0, 2, 3); INSERT INTO t4 VALUES(4, 5, 7); + INSERT INTO t4 VALUES(7, 8, 9); + INSERT INTO t4 VALUES(10, 11, 12); } - -do_conflict_test 3.2.3 -tables t4 -sql { +do_conflict_test 3.3.3 -tables t4 -sql { UPDATE t4 SET a = -1 WHERE b = 2; + UPDATE t4 SET a = -1 WHERE b = 5; + UPDATE t4 SET a = NULL WHERE c = 9; + UPDATE t4 SET a = 'x' WHERE b = 11; } -conflicts { - {UPDATE t4 DATA {i 1 i 2 i 3} {i -1 i 2 i 3} {i 0 i 2 i 3}} + {UPDATE t4 DATA {i 1 i 2 i 3} {i -1 {} {} {} {}} {i 0 i 2 i 3}} + {UPDATE t4 NOTFOUND {i 4 i 5 i 6} {i -1 {} {} {} {}}} + {UPDATE t4 CONSTRAINT {i 7 i 8 i 9} {n {} {} {} {} {}}} } -do_db2_test 3.3.4 { - SELECT * FROM t4 -} {0 2 3 4 5 7} +do_db2_test 3.3.4 { SELECT * FROM t4 } {0 2 3 4 5 7 7 8 9 x 11 12} +do_execsql_test 3.3.5 { SELECT * FROM t4 } {-1 2 3 -1 5 6 {} 8 9 x 11 12} catch { db2 close } From 0c698471d1e3b4205826f2790f1a857d90841f8a Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 14 Mar 2011 19:49:23 +0000 Subject: [PATCH 007/570] Fix handling of return values from the conflict handler. Document the conflict handler arguments and return codes in sqlite3session.h. FossilOrigin-Name: cbbb274e500237dbf7155a51d4f9c17583d704ea --- ext/session/sqlite3session.c | 677 ++++++++++++++++++++--------------- ext/session/sqlite3session.h | 66 +++- ext/session/test_session.c | 32 +- manifest | 18 +- manifest.uuid | 2 +- test/session1.test | 127 ++++++- 6 files changed, 610 insertions(+), 312 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 2ff0bc56fe..ae3139badc 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1279,6 +1279,19 @@ static void sessionUpdateDeleteWhere( } } + +typedef struct SessionApplyCtx SessionApplyCtx; +struct SessionApplyCtx { + sqlite3 *db; + sqlite3_stmt *pDelete; /* DELETE statement */ + sqlite3_stmt *pUpdate; /* DELETE statement */ + sqlite3_stmt *pInsert; /* INSERT statement */ + sqlite3_stmt *pSelect; /* SELECT statement */ + int nCol; /* Size of azCol[] and abPK[] arrays */ + const char **azCol; /* Array of column names */ + u8 *abPK; /* Boolean array - true if column is in PK */ +}; + /* ** Formulate a statement to DELETE a row from database db. Assuming a table ** structure like this: @@ -1296,25 +1309,19 @@ static void sessionUpdateDeleteWhere( static int sessionDeleteRow( sqlite3 *db, /* Database handle */ const char *zTab, /* Table name */ - int nCol, /* Number of entries in azCol and abPK */ - const char **azCol, /* Column names */ - u8 *abPK, /* True for PK columns */ - sqlite3_stmt **ppStmt /* OUT: Compiled SELECT statement. */ + SessionApplyCtx *p /* Session changeset-apply context */ ){ int rc = SQLITE_OK; - if( *ppStmt==0 ){ - SessionBuffer buf = {0, 0, 0}; + SessionBuffer buf = {0, 0, 0}; - sessionAppendStr(&buf, "DELETE FROM ", &rc); - sessionAppendIdent(&buf, zTab, &rc); + sessionAppendStr(&buf, "DELETE FROM ", &rc); + sessionAppendIdent(&buf, zTab, &rc); + sessionUpdateDeleteWhere(&buf, p->nCol, p->azCol, p->abPK, &rc); - sessionUpdateDeleteWhere(&buf, nCol, azCol, abPK, &rc); - - if( rc==SQLITE_OK ){ - rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, ppStmt, 0); - } - sqlite3_free(buf.aBuf); + if( rc==SQLITE_OK ){ + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pDelete, 0); } + sqlite3_free(buf.aBuf); return rc; } @@ -1351,149 +1358,344 @@ static int sessionDeleteRow( static int sessionUpdateRow( sqlite3 *db, /* Database handle */ const char *zTab, /* Table name */ - int nCol, /* Number of entries in azCol and abPK */ - const char **azCol, /* Column names */ - u8 *abPK, /* True for PK columns */ - sqlite3_stmt **ppStmt /* OUT: Compiled SELECT statement. */ + SessionApplyCtx *p /* Session changeset-apply context */ ){ int rc = SQLITE_OK; - if( *ppStmt==0 ){ - int i; - const char *zSep = ""; - SessionBuffer buf = {0, 0, 0}; + int i; + const char *zSep = ""; + SessionBuffer buf = {0, 0, 0}; - /* Append "UPDATE tbl SET " */ - sessionAppendStr(&buf, "UPDATE ", &rc); - sessionAppendIdent(&buf, zTab, &rc); - sessionAppendStr(&buf, " SET ", &rc); + /* Append "UPDATE tbl SET " */ + sessionAppendStr(&buf, "UPDATE ", &rc); + sessionAppendIdent(&buf, zTab, &rc); + sessionAppendStr(&buf, " SET ", &rc); - /* Append the assignments */ - for(i=0; inCol; i++){ + sessionAppendStr(&buf, zSep, &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " = CASE WHEN ?", &rc); + sessionAppendInteger(&buf, i*3+2, &rc); + sessionAppendStr(&buf, " THEN ?", &rc); + sessionAppendInteger(&buf, i*3+3, &rc); + sessionAppendStr(&buf, " ELSE ", &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " END", &rc); + zSep = ", "; } + /* Append the PK part of the WHERE clause */ + sessionAppendStr(&buf, " WHERE ", &rc); + for(i=0; inCol; i++){ + if( p->abPK[i] ){ + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " = ?", &rc); + sessionAppendInteger(&buf, i*3+1, &rc); + sessionAppendStr(&buf, " AND ", &rc); + } + } + + /* Append the non-PK part of the WHERE clause */ + sessionAppendStr(&buf, " (?", &rc); + sessionAppendInteger(&buf, p->nCol*3+1, &rc); + sessionAppendStr(&buf, " OR 1", &rc); + for(i=0; inCol; i++){ + if( !p->abPK[i] ){ + sessionAppendStr(&buf, " AND (?", &rc); + sessionAppendInteger(&buf, i*3+2, &rc); + sessionAppendStr(&buf, "=0 OR ", &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " IS ?", &rc); + sessionAppendInteger(&buf, i*3+1, &rc); + sessionAppendStr(&buf, ")", &rc); + } + } + sessionAppendStr(&buf, ")", &rc); + + if( rc==SQLITE_OK ){ + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pUpdate, 0); + } + sqlite3_free(buf.aBuf); + return rc; } static int sessionSelectRow( sqlite3 *db, /* Database handle */ const char *zTab, /* Table name */ - int nCol, /* Number of entries in azCol and abPK */ - const char **azCol, /* Column names */ - u8 *abPK, /* True for PK columns */ - sqlite3_stmt **ppStmt /* OUT: Compiled SELECT statement. */ + SessionApplyCtx *p /* Session changeset-apply context */ ){ int rc = SQLITE_OK; - if( *ppStmt==0 ){ - int i; - const char *zSep = ""; - SessionBuffer buf = {0, 0, 0}; - - sessionAppendStr(&buf, "SELECT * FROM ", &rc); - sessionAppendIdent(&buf, zTab, &rc); - sessionAppendStr(&buf, " WHERE ", &rc); - - for(i=0; inCol; i++){ + if( p->abPK[i] ){ + sessionAppendStr(&buf, zSep, &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " = ?", &rc); + sessionAppendInteger(&buf, i+1, &rc); + zSep = " AND "; } - - if( rc==SQLITE_OK ){ - rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, ppStmt, 0); - } - sqlite3_free(buf.aBuf); } + if( rc==SQLITE_OK ){ + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pSelect, 0); + } + sqlite3_free(buf.aBuf); return rc; } -static int sessionConstraintConflict( +static int sessionInsertRow( + sqlite3 *db, /* Database handle */ + const char *zTab, /* Table name */ + SessionApplyCtx *p /* Session changeset-apply context */ +){ + int rc = SQLITE_OK; + int i; + SessionBuffer buf = {0, 0, 0}; + + sessionAppendStr(&buf, "INSERT INTO main.", &rc); + sessionAppendIdent(&buf, zTab, &rc); + sessionAppendStr(&buf, " VALUES(?", &rc); + for(i=1; inCol; i++){ + sessionAppendStr(&buf, ", ?", &rc); + } + sessionAppendStr(&buf, ")", &rc); + + if( rc==SQLITE_OK ){ + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pInsert, 0); + } + sqlite3_free(buf.aBuf); + return rc; +} + +static int sessionSeekToRow( sqlite3 *db, /* Database handle */ sqlite3_changeset_iter *pIter, /* Changeset iterator */ u8 *abPK, /* Primary key flags array */ - sqlite3_stmt *pSelect, /* SELECT statement from sessionSelectRow() */ - int(*xConflict)(void *, int, sqlite3_changeset_iter*), - void *pCtx + sqlite3_stmt *pSelect /* SELECT statement from sessionSelectRow() */ ){ - int res; - int rc; + int rc = SQLITE_OK; + int i; int nCol; int op; const char *zDummy; sqlite3changeset_op(pIter, &zDummy, &nCol, &op); - assert( op==SQLITE_UPDATE || op==SQLITE_INSERT ); - /* Bind the new.* PRIMARY KEY values to the SELECT statement. */ - for(i=0; idb, pIter, p->abPK, p->pSelect); + }else{ + rc = SQLITE_DONE; + } + + if( rc==SQLITE_ROW ){ /* There exists another row with the new.* primary key. */ - pIter->pConflict = pSelect; - res = xConflict(pCtx, SQLITE_CHANGESET_CONFLICT, pIter); + pIter->pConflict = p->pSelect; + res = xConflict(pCtx, eType, pIter); pIter->pConflict = 0; - sqlite3_reset(pSelect); + rc = sqlite3_reset(p->pSelect); }else{ /* No other row with the new.* primary key. */ - rc = sqlite3_reset(pSelect); + rc = sqlite3_reset(p->pSelect); if( rc==SQLITE_OK ){ - res = xConflict(pCtx, SQLITE_CHANGESET_CONSTRAINT, pIter); + res = xConflict(pCtx, eType+1, pIter); + if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE; + } + } + + if( rc==SQLITE_OK ){ + switch( res ){ + case SQLITE_CHANGESET_REPLACE: + if( pbReplace ) *pbReplace = 1; + break; + + case SQLITE_CHANGESET_OMIT: + break; + + case SQLITE_CHANGESET_ABORT: + rc = SQLITE_ABORT; + break; + + default: + rc = SQLITE_MISUSE; + break; + } + } + + return rc; +} + +static int sessionApplyOneOp( + sqlite3_changeset_iter *pIter, + SessionApplyCtx *p, + int(*xConflict)(void *, int, sqlite3_changeset_iter *), + void *pCtx, + int *pbReplace, + int *pbRetry +){ + const char *zDummy; + int op; + int nCol; + int rc = SQLITE_OK; + + assert( p->pDelete && p->pUpdate && p->pInsert && p->pSelect ); + assert( p->azCol && p->abPK ); + assert( !pbReplace || *pbReplace==0 ); + + sqlite3changeset_op(pIter, &zDummy, &nCol, &op); + + if( op==SQLITE_DELETE ){ + int i; + + /* Bind values to the DELETE statement. */ + for(i=0; rc==SQLITE_OK && ipDelete, i+1, pVal); + } + } + if( rc==SQLITE_OK ) rc = sqlite3_bind_int(p->pDelete, nCol+1, pbRetry==0); + if( rc!=SQLITE_OK ) return rc; + + sqlite3_step(p->pDelete); + rc = sqlite3_reset(p->pDelete); + if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){ + rc = sessionConflictHandler( + SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry + ); + }else if( rc==SQLITE_CONSTRAINT ){ + rc = sessionConflictHandler( + SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0 + ); + } + + }else if( op==SQLITE_UPDATE ){ + int i; + + /* Bind values to the UPDATE statement. */ + for(i=0; rc==SQLITE_OK && ipUpdate, i*3+1, pOld); + sqlite3_bind_int(p->pUpdate, i*3+2, !!pNew); + if( pNew ) sqlite3_bind_value(p->pUpdate, i*3+3, pNew); + } + } + if( rc==SQLITE_OK ) rc = sqlite3_bind_int(p->pUpdate, nCol*3+1, pbRetry==0); + if( rc!=SQLITE_OK ) return rc; + + /* Attempt the UPDATE. In the case of a NOTFOUND or DATA conflict, + ** the result will be SQLITE_OK with 0 rows modified. */ + sqlite3_step(p->pUpdate); + rc = sqlite3_reset(p->pUpdate); + + if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){ + /* A NOTFOUND or DATA error. Search the table to see if it contains + ** a row with a matching primary key. If so, this is a DATA conflict. + ** Otherwise, if there is no primary key match, it is a NOTFOUND. */ + + rc = sessionConflictHandler( + SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry + ); + + }else if( rc==SQLITE_CONSTRAINT ){ + /* This may be a CONSTRAINT or CONFLICT error. It is a CONFLICT if + ** the only problem is a duplicate PRIMARY KEY, or a CONSTRAINT + ** otherwise. */ + int bPKChange = 0; + + /* Check if the PK has been modified. */ + rc = SQLITE_OK; + for(i=0; iabPK[i] ){ + sqlite3_value *pNew; + rc = sqlite3changeset_new(pIter, i, &pNew); + if( rc==SQLITE_OK && pNew ){ + bPKChange = 1; + break; + } + } + } + + rc = sessionConflictHandler(SQLITE_CHANGESET_CONFLICT, + p, pIter, xConflict, pCtx, (bPKChange ? pbReplace : 0) + ); + } + + }else{ + int i; + assert( op==SQLITE_INSERT ); + for(i=0; rc==SQLITE_OK && ipInsert, i+1, pVal); + } + } + if( rc!=SQLITE_OK ) return rc; + + sqlite3_step(p->pInsert); + rc = sqlite3_reset(p->pInsert); + if( rc==SQLITE_CONSTRAINT && xConflict ){ + rc = sessionConflictHandler( + SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, pbReplace + ); } } @@ -1511,209 +1713,90 @@ int sqlite3changeset_apply( ), void *pCtx ){ - sqlite3_changeset_iter *pIter; + sqlite3_changeset_iter *pIter = 0; int rc; int rc2; const char *zTab = 0; /* Name of current table */ int nTab = 0; /* Result of strlen(zTab) */ - int nCol = 0; /* Number of columns in table zTab */ - const char **azCol = 0; /* Array of column names */ - u8 *abPK = 0; /* Boolean array - true if column is in PK */ - sqlite3_stmt *pDelete = 0; /* DELETE statement */ - sqlite3_stmt *pUpdate = 0; /* DELETE statement */ - sqlite3_stmt *pInsert = 0; /* INSERT statement */ - sqlite3_stmt *pSelect = 0; /* SELECT statement */ - - rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); - if( rc!=SQLITE_OK ) return rc; + SessionApplyCtx sApply; + memset(&sApply, 0, sizeof(sApply)); sqlite3changeset_start(&pIter, nChangeset, pChangeset); - while( SQLITE_ROW==sqlite3changeset_next(pIter) ){ + + rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){ + int nCol; int op; - const char *zThis; - sqlite3changeset_op(pIter, &zThis, &nCol, &op); - if( zTab==0 || sqlite3_strnicmp(zThis, zTab, nTab+1) ){ - sqlite3_free(azCol); - rc = sessionTableInfo(db, zThis, nCol, &zTab, &azCol, &abPK); - nTab = strlen(zTab); + int bReplace = 0; + int bRetry = 0; + const char *zNew; + sqlite3changeset_op(pIter, &zNew, &nCol, &op); - sqlite3_finalize(pDelete); - sqlite3_finalize(pUpdate); - sqlite3_finalize(pInsert); - sqlite3_finalize(pSelect); - pSelect = pUpdate = pInsert = pDelete = 0; + if( zTab==0 || sqlite3_strnicmp(zNew, zTab, nTab+1) ){ + sqlite3_free(sApply.azCol); + sqlite3_finalize(sApply.pDelete); + sqlite3_finalize(sApply.pUpdate); + sqlite3_finalize(sApply.pInsert); + sqlite3_finalize(sApply.pSelect); + memset(&sApply, 0, sizeof(sApply)); + sApply.db = db; + sApply.nCol = nCol; - if( (rc = sessionSelectRow(db, zTab, nCol, azCol, abPK, &pSelect)) - || (rc = sessionUpdateRow(db, zTab, nCol, azCol, abPK, &pUpdate)) - || (rc = sessionDeleteRow(db, zTab, nCol, azCol, abPK, &pDelete)) + rc = sessionTableInfo(db, zNew, nCol, &zTab, &sApply.azCol, &sApply.abPK); + + if( rc!=SQLITE_OK + || (rc = sessionSelectRow(db, zTab, &sApply)) + || (rc = sessionUpdateRow(db, zTab, &sApply)) + || (rc = sessionDeleteRow(db, zTab, &sApply)) + || (rc = sessionInsertRow(db, zTab, &sApply)) ){ break; } + + nTab = strlen(zTab); } - if( op==SQLITE_DELETE ){ - int res; - int i; - rc = sessionDeleteRow(db, zTab, nCol, azCol, abPK, &pDelete); - for(i=0; rc==SQLITE_OK && ipConflict = pSelect; - res = xConflict(pCtx, SQLITE_CHANGESET_DATA, pIter); - pIter->pConflict = 0; - sqlite3_reset(pSelect); - }else{ - rc = sqlite3_reset(pSelect); - if( rc==SQLITE_OK ){ - res = xConflict(pCtx, SQLITE_CHANGESET_NOTFOUND, pIter); - } - } - - }else if( rc==SQLITE_CONSTRAINT ){ - res = xConflict(pCtx, SQLITE_CHANGESET_CONSTRAINT, pIter); - rc = SQLITE_OK; - } - - if( rc!=SQLITE_OK ) break; - - }else if( op==SQLITE_UPDATE ){ - int i; - int res; - rc = sessionUpdateRow(db, zTab, nCol, azCol, abPK, &pUpdate); - for(i=0; rc==SQLITE_OK && ipConflict = pSelect; - res = xConflict(pCtx, SQLITE_CHANGESET_DATA, pIter); - pIter->pConflict = 0; - sqlite3_reset(pSelect); - }else{ - rc = sqlite3_reset(pSelect); - if( rc==SQLITE_OK ){ - res = xConflict(pCtx, SQLITE_CHANGESET_NOTFOUND, pIter); - } - } - }else if( rc==SQLITE_CONSTRAINT ){ - /* This may be a CONSTRAINT or CONFLICT error. It is a CONFLICT if - ** the only problem is a duplicate PRIMARY KEY, or a CONSTRAINT - ** otherwise. */ - int bPKChange = 0; - - /* Check if the PK has been modified. */ - rc = SQLITE_OK; - for(i=0; iinterp; + int ret = 0; /* Return value */ int op; /* SQLITE_UPDATE, DELETE or INSERT */ const char *zTab; /* Name of table conflict is on */ @@ -257,9 +269,27 @@ static int test_conflict_handler( if( TCL_OK!=Tcl_EvalObjEx(interp, pEval, TCL_EVAL_GLOBAL) ){ Tcl_BackgroundError(interp); + }else{ + Tcl_Obj *pRes = Tcl_GetObjResult(interp); + if( test_obj_eq_string(pRes, "OMIT") || test_obj_eq_string(pRes, "") ){ + ret = SQLITE_CHANGESET_OMIT; + }else if( test_obj_eq_string(pRes, "REPLACE") ){ + ret = SQLITE_CHANGESET_REPLACE; + }else if( test_obj_eq_string(pRes, "ABORT") ){ + ret = SQLITE_CHANGESET_ABORT; + }else{ + Tcl_IncrRefCount(pRes); + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "unrecognized conflict handler return: \"", + Tcl_GetString(pRes), "\"", 0 + ); + Tcl_DecrRefCount(pRes); + Tcl_BackgroundError(interp); + } } + Tcl_DecrRefCount(pEval); - return SQLITE_CHANGESET_OMIT; + return ret; } /* diff --git a/manifest b/manifest index 38e0a86e95..89b9043680 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\sissues\swith\sUPDATE\schanges\sin\sthe\ssession\smodule. -D 2011-03-12T17:22:46 +C Fix\shandling\sof\sreturn\svalues\sfrom\sthe\sconflict\shandler.\sDocument\sthe\sconflict\shandler\sarguments\sand\sreturn\scodes\sin\ssqlite3session.h. +D 2011-03-14T19:49:23 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -98,9 +98,9 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/sqlite3session.c af63d87b8787c19b4a4b681f77331a9cc13d67af -F ext/session/sqlite3session.h 3246613b20857e58f7419e4e26dbe9161677aff0 -F ext/session/test_session.c 1b4f278d0ae164e2d02c11f5e1f2df3a2567ba41 +F ext/session/sqlite3session.c 111a988b4734b7419f23bb07e45bf5e991510270 +F ext/session/sqlite3session.h 55ca208bddbc1284c83427f423748eb720f5c68f +F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk ae0868e05c76eaa8a0ae3d6927a949b1c8e810d7 @@ -639,7 +639,7 @@ F test/selectA.test 06d1032fa9009314c95394f2ca2e60d9f7ae8532 F test/selectB.test f305cc6660804cb239aab4e2f26b0e288b59958b F test/selectC.test f9bf1bc4581b5b8158caa6e4e4f682acb379fb25 F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c -F test/session1.test 6ec522f3491fbdbf8a5b6c27f50b9e35f24e3dba +F test/session1.test edbd6078b86b3f6337d779552671125fbd885e19 F test/shared.test b9114eaea7e748a3a4c8ff7b9ca806c8f95cef3e F test/shared2.test 7f6ad2d857d0f4e5d6a0b9a897b5e56a6b6ea18c F test/shared3.test d69bdd5f156580876c5345652d21dc2092e85962 @@ -913,7 +913,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 2b19be7bf753c7dd12e1c3b384981a3ea1bc8145 -R 222ffce3b378b2ba18950183bb251367 +P 57862efe718fdc93401998f9058511292a0e1a50 +R 17f2f6e54c1cfa1876ed6a58e92b5c4b U dan -Z b642b18410bb67d03067201d5612ecd6 +Z e9add8546b195a8b303123ffee5a5609 diff --git a/manifest.uuid b/manifest.uuid index b6d1059b89..f68965ee4d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -57862efe718fdc93401998f9058511292a0e1a50 \ No newline at end of file +cbbb274e500237dbf7155a51d4f9c17583d704ea \ No newline at end of file diff --git a/test/session1.test b/test/session1.test index 5706b77bc5..46b9d3442d 100644 --- a/test/session1.test +++ b/test/session1.test @@ -148,7 +148,9 @@ do_changeset_invert_test 2.4.3 S {} do_test 2.4.4 { S delete } {} #------------------------------------------------------------------------- -# Test the application of simple changesets. +# Test the application of simple changesets. These tests also test that +# the conflict callback is invoked correctly. For these tests, the +# conflict callback always returns OMIT. # db close forcedelete test.db test.db2 @@ -160,6 +162,8 @@ proc xConflict {args} { return "" } +proc bgerror {args} { set ::background_error $args } + proc do_conflict_test {tn args} { set O(-tables) [list] set O(-sql) [list] @@ -183,6 +187,9 @@ proc do_conflict_test {tn args} { lappend conflicts $c } + after 1 {set go 1} + vwait go + uplevel do_test $tn [list { set ::xConflict }] [list $conflicts] S delete } @@ -279,10 +286,126 @@ do_conflict_test 3.3.3 -tables t4 -sql { {UPDATE t4 NOTFOUND {i 4 i 5 i 6} {i -1 {} {} {} {}}} {UPDATE t4 CONSTRAINT {i 7 i 8 i 9} {n {} {} {} {} {}}} } - do_db2_test 3.3.4 { SELECT * FROM t4 } {0 2 3 4 5 7 7 8 9 x 11 12} do_execsql_test 3.3.5 { SELECT * FROM t4 } {-1 2 3 -1 5 6 {} 8 9 x 11 12} +#------------------------------------------------------------------------- +# This next block of tests verifies that values returned by the conflict +# handler are intepreted correctly. The following cases are tested: +# +# Test case Operation Conflict Return Code +# UPDATE DATA OMIT +# UPDATE DATA REPLACE +# + +proc test_reset {} { + db close + db2 close + forcedelete test.db test.db2 + sqlite3 db test.db + sqlite3 db2 test.db2 +} + +proc xConflict {args} { + lappend ::xConflict $args + return $::conflict_return +} + +foreach {tn conflict_return after} { + 1 OMIT {1 2 value1 4 5 7 7 8 9 10 x x} + 2 REPLACE {1 2 value1 4 5 value2 10 8 9} +} { + test_reset + + do_test 4.$tn.1 { + foreach db {db db2} { + execsql { + CREATE TABLE t1(a, b, c, PRIMARY KEY(a)); + INSERT INTO t1 VALUES(1, 2, 3); + INSERT INTO t1 VALUES(4, 5, 6); + INSERT INTO t1 VALUES(7, 8, 9); + } $db + } + execsql { + REPLACE INTO t1 VALUES(4, 5, 7); + REPLACE INTO t1 VALUES(10, 'x', 'x'); + } db2 + } {} + + do_conflict_test 4.$tn.2 -tables t1 -sql { + UPDATE t1 SET c = 'value1' WHERE a = 1; -- no conflict + UPDATE t1 SET c = 'value2' WHERE a = 4; -- DATA conflict + UPDATE t1 SET a = 10 WHERE a = 7; -- CONFLICT conflict + } -conflicts { + {UPDATE t1 DATA {i 4 {} {} i 6} {{} {} {} {} t value2} {i 4 i 5 i 7}} + {UPDATE t1 CONFLICT {i 7 {} {} {} {}} {i 10 {} {} {} {}} {i 10 t x t x}} + } + + do_db2_test 4.$tn.3 "SELECT * FROM t1 ORDER BY a" $after +} + +foreach {tn conflict_return} { + 1 OMIT + 2 REPLACE +} { + test_reset + + do_test 5.$tn.1 { + # Create an identical schema in both databases. + set schema { + CREATE TABLE "'foolish name'"(x, y, z, PRIMARY KEY(x, y)); + } + execsql $schema db + execsql $schema db2 + + # Add some rows to [db2]. These rows will cause conflicts later + # on when the changeset from [db] is applied to it. + execsql { + INSERT INTO "'foolish name'" VALUES('one', 'one', 'ii'); + INSERT INTO "'foolish name'" VALUES('one', 'two', 'i'); + INSERT INTO "'foolish name'" VALUES('two', 'two', 'ii'); + } db2 + + } {} + + do_conflict_test 5.$tn.2 -tables {{'foolish name'}} -sql { + INSERT INTO "'foolish name'" VALUES('one', 'two', 2); + } -conflicts { + {INSERT {'foolish name'} CONFLICT {t one t two i 2} {t one t two t i}} + } + + set res(REPLACE) {one one ii one two 2 two two ii} + set res(OMIT) {one one ii one two i two two ii} + do_db2_test 5.$tn.3 { + SELECT * FROM "'foolish name'" ORDER BY x, y + } $res($conflict_return) + + + do_test 5.$tn.1 { + set schema { + CREATE TABLE d1("z""z" PRIMARY KEY, y); + INSERT INTO d1 VALUES(1, 'one'); + INSERT INTO d1 VALUES(2, 'two'); + } + execsql $schema db + execsql $schema db2 + + execsql { + UPDATE d1 SET y = 'TWO' WHERE "z""z" = 2; + } db2 + + } {} + + do_conflict_test 5.$tn.2 -tables d1 -sql { + DELETE FROM d1 WHERE "z""z" = 2; + } -conflicts { + {DELETE d1 DATA {i 2 t two} {i 2 t TWO}} + } + + set res(REPLACE) {1 one} + set res(OMIT) {1 one 2 TWO} + do_db2_test 5.$tn.3 "SELECT * FROM d1" $res($conflict_return) +} catch { db2 close } finish_test From 296c76589fb6e535994c49ad7df0783431e28318 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 15 Mar 2011 16:37:27 +0000 Subject: [PATCH 008/570] Fix some bugs and other code issues in the session module. FossilOrigin-Name: f2930840e4af3d7d9cb199d316502932fcbbb867 --- ext/session/sqlite3session.c | 731 ++++++++++++++++++++++++----------- ext/session/sqlite3session.h | 38 +- manifest | 16 +- manifest.uuid | 2 +- test/session1.test | 35 +- 5 files changed, 570 insertions(+), 252 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index ae3139badc..d454d4d345 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -11,23 +11,35 @@ typedef struct RowChange RowChange; typedef struct SessionTable SessionTable; typedef struct SessionChange SessionChange; +typedef struct SessionBuffer SessionBuffer; -#if 0 -#ifndef SQLITE_AMALGAMATION -typedef unsigned char u8; -typedef unsigned long u32; -typedef sqlite3_uint64 u64; -#endif -#endif - +/* +** Session handle structure. +*/ struct sqlite3_session { sqlite3 *db; /* Database handle session is attached to */ char *zDb; /* Name of database session is attached to */ + int bEnable; /* True if currently recording */ int rc; /* Non-zero if an error has occurred */ sqlite3_session *pNext; /* Next session object on same db. */ SessionTable *pTable; /* List of attached tables */ }; +/* +** Structure for changeset iterators. +*/ +struct sqlite3_changeset_iter { + u8 *aChangeset; /* Pointer to buffer containing changeset */ + int nChangeset; /* Number of bytes in aChangeset */ + u8 *pNext; /* Pointer to next change within aChangeset */ + int rc; /* Iterator error code */ + sqlite3_stmt *pConflict; /* Points to conflicting row, if any */ + char *zTab; /* Current table */ + int nCol; /* Number of columns in zTab */ + int op; /* Current operation */ + sqlite3_value **apValue; /* old.* and new.* values */ +}; + /* ** Each session object maintains a set of the following structures, one ** for each table the session object is monitoring. The structures are @@ -45,9 +57,7 @@ struct SessionTable { SessionTable *pNext; char *zName; /* Local name of table */ int nCol; /* Number of columns in table zName */ - - /* Hash table of modified rows */ - int nEntry; /* NUmber of entries in hash table */ + int nEntry; /* Total number of entries in hash table */ int nChange; /* Size of apChange[] array */ SessionChange **apChange; /* Hash table buckets */ }; @@ -124,39 +134,42 @@ struct SessionChange { SessionChange *pNext; /* For hash-table collisions */ }; +/* +** Instances of this structure are used to build strings or binary records. +*/ +struct SessionBuffer { + u8 *aBuf; /* Pointer to changeset buffer */ + int nBuf; /* Size of buffer aBuf */ + int nAlloc; /* Size of allocation containing aBuf */ +}; -static int sessionVarintPut(u8 *aBuf, u32 iVal){ - if( (iVal & ~0x7F)==0 ){ - if( aBuf ){ - aBuf[0] = (u8)iVal; - } - return 1; - } - if( (iVal & ~0x3FFF)==0 ){ - if( aBuf ){ - aBuf[0] = ((iVal >> 7) & 0x7F) | 0x80; - aBuf[1] = iVal & 0x7F; - } - return 2; - } - if( aBuf ){ - aBuf[0] = ((iVal >> 28) & 0x7F) | 0x80; - aBuf[1] = ((iVal >> 21) & 0x7F) | 0x80; - aBuf[2] = ((iVal >> 14) & 0x7F) | 0x80; - aBuf[3] = ((iVal >> 7) & 0x7F) | 0x80; - aBuf[4] = iVal & 0x7F; - } - return 5; +/* +** Write a varint with value iVal into the buffer at aBuf. Return the +** number of bytes written. +*/ +static int sessionVarintPut(u8 *aBuf, int iVal){ + return putVarint32(aBuf, iVal); } +/* +** Return the number of bytes required to store value iVal as a varint. +*/ +static int sessionVarintLen(int iVal){ + return sqlite3VarintLen(iVal); +} + +/* +** Read a varint value from aBuf[] into *piVal. Return the number of +** bytes read. +*/ static int sessionVarintGet(u8 *aBuf, int *piVal){ - int ret; - u64 v; - ret = (int)sqlite3GetVarint(aBuf, &v); - *piVal = (int)v; - return ret; + return getVarint32(aBuf, *piVal); } +/* +** Read a 64-bit big-endian integer value from buffer aRec[]. Return +** the value read. +*/ static sqlite3_int64 sessionGetI64(u8 *aRec){ return (((sqlite3_int64)aRec[0]) << 56) + (((sqlite3_int64)aRec[1]) << 48) @@ -168,6 +181,20 @@ static sqlite3_int64 sessionGetI64(u8 *aRec){ + (((sqlite3_int64)aRec[7]) << 0); } +/* +** Write a 64-bit big-endian integer value to the buffer aBuf[]. +*/ +static void sessionPutI64(u8 *aBuf, sqlite3_int64 i){ + aBuf[0] = (i>>56) & 0xFF; + aBuf[1] = (i>>48) & 0xFF; + aBuf[2] = (i>>40) & 0xFF; + aBuf[3] = (i>>32) & 0xFF; + aBuf[4] = (i>>24) & 0xFF; + aBuf[5] = (i>>16) & 0xFF; + aBuf[6] = (i>> 8) & 0xFF; + aBuf[7] = (i>> 0) & 0xFF; +} + /* ** This function is used to serialize the contents of value pValue (see ** comment titled "RECORD FORMAT" above). @@ -186,8 +213,8 @@ static int sessionSerializeValue( sqlite3_value *pValue, /* Value to serialize */ int *pnWrite /* IN/OUT: Increment by bytes written */ ){ - int eType; - int nByte; + int eType; /* Value type (SQLITE_NULL, TEXT etc.) */ + int nByte; /* Size of serialized value in bytes */ eType = sqlite3_value_type(pValue); if( aBuf ) aBuf[0] = eType; @@ -212,14 +239,7 @@ static int sessionSerializeValue( r = sqlite3_value_double(pValue); memcpy(&i, &r, 8); } - aBuf[1] = (i>>56) & 0xFF; - aBuf[2] = (i>>48) & 0xFF; - aBuf[3] = (i>>40) & 0xFF; - aBuf[4] = (i>>32) & 0xFF; - aBuf[5] = (i>>24) & 0xFF; - aBuf[6] = (i>>16) & 0xFF; - aBuf[7] = (i>> 8) & 0xFF; - aBuf[8] = (i>> 0) & 0xFF; + sessionPutI64(&aBuf[1], i); } nByte = 9; break; @@ -227,7 +247,7 @@ static int sessionSerializeValue( case SQLITE_TEXT: case SQLITE_BLOB: { int n = sqlite3_value_bytes(pValue); - int nVarint = sessionVarintPut(0, n); + int nVarint = sessionVarintLen(n); if( aBuf ){ sessionVarintPut(&aBuf[1], n); memcpy(&aBuf[nVarint + 1], eType==SQLITE_TEXT ? @@ -298,16 +318,29 @@ static int sessionGrowHash(sqlite3_session *pSession, SessionTable *pTab){ return SQLITE_OK; } +/* +** This function is only called from within a pre-update handler for a +** write to table pTab, part of session pSession. If this is the first +** write to this table, set the SessionTable.nCol variable to the number +** of columns in the table. +** +** Otherwise, if this is not the first time this table has been written +** to, check that the number of columns in the table has not changed. If +** it has not, return zero. +** +** If the number of columns in the table has changed since the last write +** was recorded, set the session error-code to SQLITE_SCHEMA and return +** non-zero. Users are not allowed to change the number of columns in a table +** for which changes are being recorded by the session module. If they do so, +** it is an error. +*/ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ if( pTab->nCol==0 ){ pTab->nCol = sqlite3_preupdate_count(pSession->db); - } - - if( pTab->nCol!=sqlite3_preupdate_count(pSession->db) ){ + }else if( pTab->nCol!=sqlite3_preupdate_count(pSession->db) ){ pSession->rc = SQLITE_SCHEMA; return SQLITE_ERROR; } - return SQLITE_OK; } @@ -329,8 +362,15 @@ static void xPreUpdate( for(pSession=(sqlite3_session *)pCtx; pSession; pSession=pSession->pNext){ SessionTable *pTab; + + /* If this session is already in the error-state, or if it is attached + ** to a different database ("main", "temp" etc.), or if it is not + ** currently enabled, there is nothing to do. Skip to the next session + ** object attached to this database. */ + if( pSession->bEnable==0 ) continue; if( pSession->rc ) continue; if( sqlite3_strnicmp(zDb, pSession->zDb, nDb+1) ) continue; + for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){ if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ){ SessionChange *pChange; @@ -365,16 +405,16 @@ static void xPreUpdate( memset(pChange, 0, sizeof(SessionChange)); } }else{ - int nByte; /* Number of bytes to allocate */ - int i; /* Used to iterate through columns */ - sqlite3_value *pValue; + int nByte; /* Number of bytes to allocate */ + int i; /* Used to iterate through columns */ /* Figure out how large an allocation is required */ nByte = sizeof(SessionChange); for(i=0; inCol && rc==SQLITE_OK; i++){ - rc = sqlite3_preupdate_old(pSession->db, i, &pValue); + sqlite3_value *p; /* old.* value */ + rc = sqlite3_preupdate_old(pSession->db, i, &p); if( rc==SQLITE_OK ){ - rc = sessionSerializeValue(0, pValue, &nByte); + rc = sessionSerializeValue(0, p, &nByte); } } @@ -390,10 +430,10 @@ static void xPreUpdate( /* Populate the change object */ nByte = 0; for(i=0; inCol && rc==SQLITE_OK; i++){ - rc = sqlite3_preupdate_old(pSession->db, i, &pValue); + sqlite3_value *p; /* old.* value */ + rc = sqlite3_preupdate_old(pSession->db, i, &p); if( rc==SQLITE_OK ){ - rc = sessionSerializeValue( - &pChange->aRecord[nByte], pValue, &nByte); + rc = sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte); } } pChange->nRecord = nByte; @@ -410,8 +450,8 @@ static void xPreUpdate( pChange->iKey = iKey2; pChange->pNext = pTab->apChange[iHash]; pTab->apChange[iHash] = pChange; + break; } - break; } } } @@ -425,10 +465,11 @@ int sqlite3session_create( const char *zDb, /* Name of db (e.g. "main") */ sqlite3_session **ppSession /* OUT: New session object */ ){ - sqlite3_session *pNew; - sqlite3_session *pOld; + sqlite3_session *pNew; /* Newly allocated session object */ + sqlite3_session *pOld; /* Session object already attached to db */ int nDb = strlen(zDb); /* Length of zDb in bytes */ + /* Zero the output value in case an error occurs. */ *ppSession = 0; /* Allocate and populate the new session object. */ @@ -437,6 +478,7 @@ int sqlite3session_create( memset(pNew, 0, sizeof(sqlite3_session)); pNew->db = db; pNew->zDb = (char *)&pNew[1]; + pNew->bEnable = 1; memcpy(pNew->zDb, zDb, nDb+1); /* Add the new session object to the linked list of session objects @@ -459,6 +501,8 @@ void sqlite3session_delete(sqlite3_session *pSession){ sqlite3_session *pHead; sqlite3_session **pp; + /* Unlink the session from the linked list of sessions attached to the + ** database handle. Hold the db mutex while doing so. */ sqlite3_mutex_enter(sqlite3_db_mutex(db)); pHead = (sqlite3_session*)sqlite3_preupdate_hook(db, 0, 0); for(pp=&pHead; (*pp)!=pSession; pp=&((*pp)->pNext)); @@ -466,6 +510,8 @@ void sqlite3session_delete(sqlite3_session *pSession){ if( pHead ) sqlite3_preupdate_hook(db, xPreUpdate, (void *)pHead); sqlite3_mutex_leave(sqlite3_db_mutex(db)); + /* Delete all attached table objects. And the contents of their + ** associated hash-tables. */ while( pSession->pTable ){ int i; SessionTable *pTab = pSession->pTable; @@ -482,6 +528,7 @@ void sqlite3session_delete(sqlite3_session *pSession){ sqlite3_free(pTab); } + /* Free the session object itself. */ sqlite3_free(pSession); } @@ -497,8 +544,8 @@ int sqlite3session_attach( sqlite3_session *pSession, /* Session object */ const char *zName /* Table name */ ){ - SessionTable *pTab; - int nName; + SessionTable *pTab; /* New table object (if required) */ + int nName; /* Number of bytes in string zName */ /* First search for an existing entry. If one is found, this call is ** a no-op. Return early. */ @@ -523,13 +570,13 @@ int sqlite3session_attach( return SQLITE_OK; } -typedef struct SessionBuffer SessionBuffer; -struct SessionBuffer { - u8 *aBuf; /* Pointer to changeset buffer */ - int nBuf; /* Size of buffer aBuf */ - int nAlloc; /* Size of allocation containing aBuf */ -}; - +/* +** Ensure that there is room in the buffer to append nByte bytes of data. +** If not, use sqlite3_realloc() to grow the buffer so that there is. +** +** If successful, return zero. Otherwise, if an OOM condition is encountered, +** set *pRc to SQLITE_NOMEM and return non-zero. +*/ static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ if( p->nAlloc-p->nBufaBuf[p->nBuf++] = v; } } +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append a single varint to the buffer. +** +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before +** returning. +*/ static void sessionAppendVarint(SessionBuffer *p, sqlite3_int64 v, int *pRc){ if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, 9, pRc) ){ p->nBuf += sessionVarintPut(&p->aBuf[p->nBuf], v); } } +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append a blob of data to the buffer. +** +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before +** returning. +*/ static void sessionAppendBlob( SessionBuffer *p, const u8 *aBlob, @@ -573,6 +641,14 @@ static void sessionAppendBlob( } } +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append a string to the buffer. All bytes in the string +** up to (but not including) the nul-terminator are written to the buffer. +** +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before +** returning. +*/ static void sessionAppendStr( SessionBuffer *p, const char *zStr, @@ -585,20 +661,37 @@ static void sessionAppendStr( } } +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append the string representation of integer iVal +** to the buffer. No nul-terminator is written. +** +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before +** returning. +*/ static void sessionAppendInteger( - SessionBuffer *p, - int iVal, - int *pRc + SessionBuffer *p, /* Buffer to append to */ + int iVal, /* Value to write the string rep. of */ + int *pRc /* IN/OUT: Error code */ ){ char aBuf[24]; sqlite3_snprintf(sizeof(aBuf)-1, aBuf, "%d", iVal); sessionAppendStr(p, aBuf, pRc); } +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append the string zStr enclosed in quotes (") and +** with any embedded quote characters escaped to the buffer. No +** nul-terminator byte is written. +** +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before +** returning. +*/ static void sessionAppendIdent( - SessionBuffer *p, - const char *zStr, - int *pRc + SessionBuffer *p, /* Buffer to a append to */ + const char *zStr, /* String to quote, escape and append */ + int *pRc /* IN/OUT: Error code */ ){ int nStr = strlen(zStr)*2 + 2 + 1; if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, nStr, pRc) ){ @@ -614,11 +707,17 @@ static void sessionAppendIdent( } } +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwse, it appends the serialized version of the value stored +** in column iCol of the row that SQL statement pStmt currently points +** to to the buffer. +*/ static void sessionAppendCol( - SessionBuffer *p, - sqlite3_stmt *pStmt, - int iCol, - int *pRc + SessionBuffer *p, /* Buffer to append to */ + sqlite3_stmt *pStmt, /* Handle pointing to row containing value */ + int iCol, /* Column to read value from */ + int *pRc /* IN/OUT: Error code */ ){ if( *pRc==SQLITE_OK ){ int eType = sqlite3_column_type(pStmt, iCol); @@ -632,14 +731,7 @@ static void sessionAppendCol( double r = sqlite3_column_double(pStmt, iCol); memcpy(&i, &r, 8); } - aBuf[0] = (i>>56) & 0xFF; - aBuf[1] = (i>>48) & 0xFF; - aBuf[2] = (i>>40) & 0xFF; - aBuf[3] = (i>>32) & 0xFF; - aBuf[4] = (i>>24) & 0xFF; - aBuf[5] = (i>>16) & 0xFF; - aBuf[6] = (i>> 8) & 0xFF; - aBuf[7] = (i>> 0) & 0xFF; + sessionPutI64(aBuf, i); sessionAppendBlob(p, aBuf, 8, pRc); } if( eType==SQLITE_BLOB || eType==SQLITE_TEXT ){ @@ -653,18 +745,43 @@ static void sessionAppendCol( } } +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. +** +** Otherwse, if *pRc is SQLITE_OK, then it appends an update change to +** the buffer (see the comments under "CHANGESET FORMAT" at the top of the +** file). An update change consists of: +** +** 1 byte: SQLITE_UPDATE (0x17) +** n bytes: old.* record (see RECORD FORMAT) +** m bytes: new.* record (see RECORD FORMAT) +** +** The SessionChange object passed as the third argument contains the +** values that were stored in the row when the session began (the old.* +** values). The statement handle passed as the second argument points +** at the current version of the row (the new.* values). +** +** If all of the old.* values are equal to their corresponding new.* value +** (i.e. nothing has changed), then no data at all is appended to the buffer. +** +** Otherwise, the old.* record contains all primary key values and the +** original values of any fields that have been modified. The new.* record +** contains the new values of only those fields that have been modified. +*/ static void sessionAppendUpdate( - sqlite3_stmt *pStmt, - SessionBuffer *pBuf, - SessionChange *p, - u8 *abPK, - int *pRc + SessionBuffer *pBuf, /* Buffer to append to */ + sqlite3_stmt *pStmt, /* Statement handle pointing at new row */ + SessionChange *p, /* Object containing old values */ + u8 *abPK, /* Boolean array - true for PK columns */ + int *pRc /* IN/OUT: Error code */ ){ if( *pRc==SQLITE_OK ){ - SessionBuffer buf2 = {0, 0, 0}; - int bNoop = 1; - int i; - u8 *pCsr = p->aRecord; + SessionBuffer buf2 = {0,0,0}; /* Buffer to accumulate new.* record in */ + int bNoop = 1; /* Set to zero if any values are modified */ + int i; /* Used to iterate through columns */ + u8 *pCsr = p->aRecord; /* Used to iterate through old.* values */ + sessionAppendByte(pBuf, SQLITE_UPDATE, pRc); for(i=0; idb; - SessionTable *pTab; - SessionBuffer buf = {0, 0, 0}; - int rc; + sqlite3 *db = pSession->db; /* Source database handle */ + SessionTable *pTab; /* Used to iterate through attached tables */ + SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */ + int rc; /* Return code */ + /* Zero the output variables in case an error occurs. If this session + ** object is already in the error state (sqlite3_session.rc != SQLITE_OK), + ** this call will be a no-op. */ *pnChangeset = 0; *ppChangeset = 0; rc = pSession->rc; @@ -879,7 +1031,8 @@ int sqlite3session_changeset( } if( rc==SQLITE_OK ){ - rc = sessionTableInfo(db, pTab->zName, pTab->nCol, 0, 0, &abPK); + rc = sessionTableInfo( + db, pSession->zDb, pTab->zName, pTab->nCol, 0, 0, &abPK); } for(i=0; inChange; i++){ @@ -889,7 +1042,7 @@ int sqlite3session_changeset( if( sqlite3_step(pStmt)==SQLITE_ROW ){ int iCol; if( p->aRecord ){ - sessionAppendUpdate(pStmt, &buf, p, abPK, &rc); + sessionAppendUpdate(&buf, pStmt, p, abPK, &rc); }else{ sessionAppendByte(&buf, SQLITE_INSERT, &rc); for(iCol=0; iColnCol; iCol++){ @@ -922,67 +1075,78 @@ int sqlite3session_changeset( }else{ sqlite3_free(buf.aBuf); } - return rc; } +/* +** Enable or disable the session object passed as the first argument. +*/ int sqlite3session_enable(sqlite3_session *pSession, int bEnable){ - return bEnable; + if( bEnable>=0 ){ + pSession->bEnable = bEnable; + } + return pSession->bEnable; } -/************************************************************************/ -/************************************************************************/ -/************************************************************************/ - -struct sqlite3_changeset_iter { - u8 *aChangeset; /* Pointer to buffer containing changeset */ - int nChangeset; /* Number of bytes in aChangeset */ - u8 *pNext; /* Pointer to next change within aChangeset */ - int rc; - - sqlite3_stmt *pConflict; /* Conflicting row, if any */ - char *zTab; /* Current table */ - int nCol; /* Number of columns in zTab */ - int op; /* Current operation */ - sqlite3_value **apValue; /* old.* and new.* values */ -}; - /* ** Create an iterator used to iterate through the contents of a changeset. */ int sqlite3changeset_start( - sqlite3_changeset_iter **ppIter, - int nChangeset, - void *pChangeset + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ + int nChangeset, /* Size of buffer pChangeset in bytes */ + void *pChangeset /* Pointer to buffer containing changeset */ ){ sqlite3_changeset_iter *pRet; /* Iterator to return */ int nByte; /* Number of bytes to allocate for iterator */ - *ppIter = 0; + /* Zero the output variable in case an error occurs. */ + *pp = 0; + /* Allocate and initialize the iterator structure. */ nByte = sizeof(sqlite3_changeset_iter); pRet = (sqlite3_changeset_iter *)sqlite3_malloc(nByte); if( !pRet ) return SQLITE_NOMEM; memset(pRet, 0, sizeof(sqlite3_changeset_iter)); - pRet->aChangeset = (u8 *)pChangeset; pRet->nChangeset = nChangeset; pRet->pNext = pRet->aChangeset; - *ppIter = pRet; + /* Populate the output variable and return success. */ + *pp = pRet; return SQLITE_OK; } +/* +** Deserialize a single record from a buffer in memory. See "RECORD FORMAT" +** for details. +** +** When this function is called, *paChange points to the start of the record +** to deserialize. Assuming no error occurs, *paChange is set to point to +** one byte after the end of the same record before this function returns. +** +** If successful, each element of the apOut[] array (allocated by the caller) +** is set to point to an sqlite3_value object containing the value read +** from the corresponding position in the record. If that value is not +** included in the record (i.e. because the record is part of an UPDATE change +** and the field was not modified), the corresponding element of apOut[] is +** set to NULL. +** +** It is the responsibility of the caller to free all sqlite_value structures +** using sqlite3_free(). +** +** If an error occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. +** The apOut[] array may have been partially populated in this case. +*/ static int sessionReadRecord( u8 **paChange, /* IN/OUT: Pointer to binary record */ int nCol, /* Number of values in record */ sqlite3_value **apOut /* Write values to this array */ ){ - int i; - u8 *aRec = *paChange; + int i; /* Used to iterate through columns */ + u8 *aRec = *paChange; /* Cursor for the serialized record */ for(i=0; irc!=SQLITE_OK ) return p->rc; + /* Free the current contents of p->apValue[]. */ if( p->apValue ){ for(i=0; inCol*2; i++){ sqlite3ValueFree(p->apValue[i]); @@ -1090,7 +1256,7 @@ int sqlite3changeset_next(sqlite3_changeset_iter *p){ ** has returned SQLITE_ROW. */ int sqlite3changeset_op( - sqlite3_changeset_iter *pIter, + sqlite3_changeset_iter *pIter, /* Iterator handle */ const char **pzTab, /* OUT: Pointer to table name */ int *pnCol, /* OUT: Number of columns in table */ int *pOp /* OUT: SQLITE_INSERT, DELETE or UPDATE */ @@ -1101,9 +1267,22 @@ int sqlite3changeset_op( return SQLITE_OK; } +/* +** This function may only be called while the iterator is pointing to an +** SQLITE_UPDATE or SQLITE_DELETE change (see sqlite3changeset_op()). +** Otherwise, SQLITE_MISUSE is returned. +** +** It sets *ppValue to point to an sqlite3_value structure containing the +** iVal'th value in the old.* record. Or, if that particular value is not +** included in the record (because the change is an UPDATE and the field +** was not modified and is not a PK column), set *ppValue to NULL. +** +** If value iVal is out-of-range, SQLITE_RANGE is returned and *ppValue is +** not modified. Otherwise, SQLITE_OK. +*/ int sqlite3changeset_old( - sqlite3_changeset_iter *pIter, - int iVal, + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Index of old.* value to retrieve */ sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ ){ if( pIter->op!=SQLITE_UPDATE && pIter->op!=SQLITE_DELETE ){ @@ -1116,9 +1295,22 @@ int sqlite3changeset_old( return SQLITE_OK; } +/* +** This function may only be called while the iterator is pointing to an +** SQLITE_UPDATE or SQLITE_INSERT change (see sqlite3changeset_op()). +** Otherwise, SQLITE_MISUSE is returned. +** +** It sets *ppValue to point to an sqlite3_value structure containing the +** iVal'th value in the new.* record. Or, if that particular value is not +** included in the record (because the change is an UPDATE and the field +** was not modified), set *ppValue to NULL. +** +** If value iVal is out-of-range, SQLITE_RANGE is returned and *ppValue is +** not modified. Otherwise, SQLITE_OK. +*/ int sqlite3changeset_new( - sqlite3_changeset_iter *pIter, - int iVal, + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Index of new.* value to retrieve */ sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ ){ if( pIter->op!=SQLITE_UPDATE && pIter->op!=SQLITE_INSERT ){ @@ -1131,9 +1323,20 @@ int sqlite3changeset_new( return SQLITE_OK; } +/* +** This function may only be called with a changeset iterator that has been +** passed to an SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT +** conflict-handler function. Otherwise, SQLITE_MISUSE is returned. +** +** If successful, *ppValue is set to point to an sqlite3_value structure +** containing the iVal'th value of the conflicting record. +** +** If value iVal is out-of-range or some other error occurs, an SQLite error +** code is returned. Otherwise, SQLITE_OK. +*/ int sqlite3changeset_conflict( - sqlite3_changeset_iter *pIter, - int iVal, + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Index of conflict record value to fetch */ sqlite3_value **ppValue /* OUT: Value from conflicting row */ ){ if( !pIter->pConflict ){ @@ -1153,8 +1356,8 @@ int sqlite3changeset_conflict( ** callback by changeset_apply(). */ int sqlite3changeset_finalize(sqlite3_changeset_iter *p){ - int i; - int rc = p->rc; + int i; /* Used to iterate through p->apValue[] */ + int rc = p->rc; /* Return code */ for(i=0; inCol*2; i++) sqlite3ValueFree(p->apValue[i]); sqlite3_free(p->apValue); sqlite3_free(p); @@ -1238,48 +1441,6 @@ int sqlite3changeset_invert( return SQLITE_OK; } -static void sessionUpdateDeleteWhere( - SessionBuffer *pBuf, /* Buffer to append to */ - int nCol, /* Number of entries in azCol and abPK */ - const char **azCol, /* Column names */ - u8 *abPK, /* True for PK columns */ - int *pRc /* IN/OUT: Error code */ -){ - if( *pRc==SQLITE_OK ){ - int i; - const char *zSep = ""; - - sessionAppendStr(pBuf, " WHERE ", pRc); - - for(i=0; inCol, p->azCol, p->abPK, &rc); + sessionAppendStr(&buf, " WHERE ", &rc); + + for(i=0; inCol; i++){ + if( p->abPK[i] ){ + sessionAppendStr(&buf, zSep, &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " = ?", &rc); + sessionAppendInteger(&buf, i+1, &rc); + zSep = "AND "; + } + } + + sessionAppendStr(&buf, " AND (?", &rc); + sessionAppendInteger(&buf, p->nCol+1, &rc); + sessionAppendStr(&buf, " OR ", &rc); + + zSep = ""; + for(i=0; inCol; i++){ + if( !p->abPK[i] ){ + sessionAppendStr(&buf, zSep, &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " IS ?", &rc); + sessionAppendInteger(&buf, i+1, &rc); + zSep = "AND "; + } + } + sessionAppendStr(&buf, ")", &rc); if( rc==SQLITE_OK ){ rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pDelete, 0); @@ -1354,6 +1546,8 @@ static int sessionDeleteRow( ** conflict-handler is invoked with CHANGESET_DATA and returns ** CHANGESET_REPLACE. This is variable "?(nCol*3+1)". ** +** If successful, SQLITE_OK is returned and SessionApplyCtx.pUpdate is left +** pointing to the prepared version of the SQL statement. */ static int sessionUpdateRow( sqlite3 *db, /* Database handle */ @@ -1420,6 +1614,19 @@ static int sessionUpdateRow( return rc; } +/* +** Formulate and prepare an SQL statement to query table zTab by primary +** key. Assuming the following table structure: +** +** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c)); +** +** The SELECT statement looks like this: +** +** SELECT * FROM x WHERE a = ?1 AND c = ?3 +** +** If successful, SQLITE_OK is returned and SessionApplyCtx.pSelect is left +** pointing to the prepared version of the SQL statement. +*/ static int sessionSelectRow( sqlite3 *db, /* Database handle */ const char *zTab, /* Table name */ @@ -1449,6 +1656,15 @@ static int sessionSelectRow( return rc; } +/* +** Formulate and prepare an INSERT statement to add a record to table zTab. +** For example: +** +** INSERT INTO main."zTab" VALUES(?1, ?2, ?3 ...); +** +** If successful, SQLITE_OK is returned and SessionApplyCtx.pInsert is left +** pointing to the prepared version of the SQL statement. +*/ static int sessionInsertRow( sqlite3 *db, /* Database handle */ const char *zTab, /* Table name */ @@ -1473,18 +1689,32 @@ static int sessionInsertRow( return rc; } +/* +** SQL statement pSelect is as generated by the sessionSelectRow() function. +** This function binds the primary key values from the change that changeset +** iterator pIter points to to the SELECT and attempts to seek to the table +** entry. If a row is found, the SELECT statement left pointing at the row +** and SQLITE_ROW is returned. Otherwise, if no row is found and no error +** has occured, the statement is reset and SQLITE_OK is returned. If an +** error occurs, an SQLite error code is returned. +** +** If the iterator currently points to an INSERT record, bind values from the +** new.* record to the SELECT statement. Or, if it points to a DELETE, bind +** values from the old.* record. If the changeset iterator points to an +** UPDATE, bind values from the new.* record, but use old.* values in place +** of any undefined new.* values. +*/ static int sessionSeekToRow( sqlite3 *db, /* Database handle */ sqlite3_changeset_iter *pIter, /* Changeset iterator */ u8 *abPK, /* Primary key flags array */ sqlite3_stmt *pSelect /* SELECT statement from sessionSelectRow() */ ){ - int rc = SQLITE_OK; - - int i; - int nCol; - int op; - const char *zDummy; + int rc = SQLITE_OK; /* Return code */ + int i; /* Used to iterate through table columns */ + int nCol; /* Number of columns in table */ + int op; /* Changset operation (SQLITE_UPDATE etc.) */ + const char *zDummy; /* Unused */ sqlite3changeset_op(pIter, &zDummy, &nCol, &op); @@ -1511,15 +1741,50 @@ static int sessionSeekToRow( return rc; } +/* +** Invoke the conflict handler for the change that the changeset iterator +** currently points to. +** +** Argument eType must be either CHANGESET_DATA or CHANGESET_CONFLICT. +** If argument pbReplace is NULL, then the type of conflict handler invoked +** depends solely on eType, as follows: +** +** eType value Value passed to xConflict +** ------------------------------------------------- +** CHANGESET_DATA CHANGESET_NOTFOUND +** CHANGESET_CONFLICT CHANGESET_CONSTRAINT +** +** Or, if pbReplace is not NULL, then an attempt is made to find an existing +** record with the same primary key as the record about to be deleted, updated +** or inserted. If such a record can be found, it is available to the conflict +** handler as the "conflicting" record. In this case the type of conflict +** handler invoked is as follows: +** +** eType value PK Record found? Value passed to xConflict +** ---------------------------------------------------------------- +** CHANGESET_DATA Yes CHANGESET_DATA +** CHANGESET_DATA No CHANGESET_NOTFOUND +** CHANGESET_CONFLICT Yes CHANGESET_CONFLICT +** CHANGESET_CONFLICT No CHANGESET_CONSTRAINT +** +** If pbReplace is not NULL, and a record with a matching PK is found, and +** the conflict handler function returns SQLITE_CHANGESET_REPLACE, *pbReplace +** is set to non-zero before returning SQLITE_OK. +** +** If the conflict handler returns SQLITE_CHANGESET_ABORT, SQLITE_ABORT is +** returned. Or, if the conflict handler returns an invalid value, +** SQLITE_MISUSE. If the conflict handler returns SQLITE_CHANGESET_OMIT, +** this function returns SQLITE_OK. +*/ static int sessionConflictHandler( - int eType, - SessionApplyCtx *p, + int eType, /* Either CHANGESET_DATA or CONFLICT */ + SessionApplyCtx *p, /* changeset_apply() context */ sqlite3_changeset_iter *pIter, /* Changeset iterator */ int(*xConflict)(void *, int, sqlite3_changeset_iter*), - void *pCtx, - int *pbReplace + void *pCtx, /* First argument for conflict handler */ + int *pbReplace /* OUT: Set to true if PK row is found */ ){ - int res; + int res; /* Value returned by conflict handler */ int rc; int nCol; int op; @@ -1575,13 +1840,37 @@ static int sessionConflictHandler( return rc; } +/* +** Attempt to apply the change that the iterator passed as the first argument +** currently points to to the database. If a conflict is encountered, invoke +** the conflict handler callback. +** +** If argument pbRetry is NULL, then ignore any CHANGESET_DATA conflict. If +** one is encountered, update or delete the row with the matching primary key +** instead. Or, if pbRetry is not NULL and a CHANGESET_DATA conflict occurs, +** invoke the conflict handler. If it returns CHANGESET_REPLACE, set *pbRetry +** to true before returning. In this case the caller will invoke this function +** again, this time with pbRetry set to NULL. +** +** If argument pbReplace is NULL and a CHANGESET_CONFLICT conflict is +** encountered invoke the conflict handler with CHANGESET_CONSTRAINT instead. +** Or, if pbReplace is not NULL, invoke it with CHANGESET_CONFLICT. If such +** an invocation returns SQLITE_CHANGESET_REPLACE, set *pbReplace to true +** before retrying. In this case the caller attempts to remove the conflicting +** row before invoking this function again, this time with pbReplace set +** to NULL. +** +** If any conflict handler returns SQLITE_CHANGESET_ABORT, this function +** returns SQLITE_ABORT. Otherwise, if no error occurs, SQLITE_OK is +** returned. +*/ static int sessionApplyOneOp( - sqlite3_changeset_iter *pIter, - SessionApplyCtx *p, + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + SessionApplyCtx *p, /* changeset_apply() context */ int(*xConflict)(void *, int, sqlite3_changeset_iter *), - void *pCtx, - int *pbReplace, - int *pbRetry + void *pCtx, /* First argument for the conflict handler */ + int *pbReplace, /* OUT: True to remove PK row and retry */ + int *pbRetry /* OUT: True to retry. */ ){ const char *zDummy; int op; @@ -1702,27 +1991,29 @@ static int sessionApplyOneOp( return rc; } +/* +** Apply the changeset passed via pChangeset/nChangeset to the main database +** attached to handle "db". Invoke the supplied conflict handler callback +** to resolve any conflicts encountered while applying the change. +*/ int sqlite3changeset_apply( - sqlite3 *db, - int nChangeset, - void *pChangeset, + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ int(*xConflict)( void *pCtx, /* Copy of fifth arg to _apply() */ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), - void *pCtx + void *pCtx /* First argument passed to xConflict */ ){ - sqlite3_changeset_iter *pIter = 0; - int rc; - int rc2; - + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ + int rc; /* Return code */ const char *zTab = 0; /* Name of current table */ int nTab = 0; /* Result of strlen(zTab) */ + SessionApplyCtx sApply; /* changeset_apply() context object */ - SessionApplyCtx sApply; memset(&sApply, 0, sizeof(sApply)); - sqlite3changeset_start(&pIter, nChangeset, pChangeset); rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); @@ -1744,7 +2035,8 @@ int sqlite3changeset_apply( sApply.db = db; sApply.nCol = nCol; - rc = sessionTableInfo(db, zNew, nCol, &zTab, &sApply.azCol, &sApply.abPK); + rc = sessionTableInfo( + db, "main", zNew, nCol, &zTab, &sApply.azCol, &sApply.abPK); if( rc!=SQLITE_OK || (rc = sessionSelectRow(db, zTab, &sApply)) @@ -1795,8 +2087,11 @@ int sqlite3changeset_apply( } } - rc2 = sqlite3changeset_finalize(pIter); - if( rc==SQLITE_OK ) rc = rc2; + if( rc==SQLITE_OK ){ + rc = sqlite3changeset_finalize(pIter); + }else{ + sqlite3changeset_finalize(pIter); + } if( rc==SQLITE_OK ){ rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index a034dca9ec..c4053e3dbe 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -69,7 +69,6 @@ int sqlite3session_changeset( */ void sqlite3session_delete(sqlite3_session *pSession); - /* ** Create an iterator used to iterate through the contents of a changeset. */ @@ -95,23 +94,22 @@ int sqlite3changeset_next(sqlite3_changeset_iter *pIter); ** has returned SQLITE_ROW. */ int sqlite3changeset_op( - sqlite3_changeset_iter *pIter, /* Iterator object */ - const char **pzTab, /* OUT: Pointer to table name */ - int *pnCol, /* OUT: Number of columns in table */ - int *pOp /* OUT: SQLITE_INSERT, DELETE or UPDATE */ + sqlite3_changeset_iter *pIter, /* Iterator object */ + const char **pzTab, /* OUT: Pointer to table name */ + int *pnCol, /* OUT: Number of columns in table */ + int *pOp /* OUT: SQLITE_INSERT, DELETE or UPDATE */ ); - int sqlite3changeset_old( - sqlite3_changeset_iter *pIter, - int iVal, - sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ +); +int sqlite3changeset_new( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ ); -int sqlite3changeset_new( - sqlite3_changeset_iter *pIter, - int iVal, - sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ -); /* ** This function is only usable with sqlite3_changeset_iter objects passed ** to the xConflict callback by sqlite3changeset_apply(). It cannot be used @@ -122,8 +120,8 @@ int sqlite3changeset_new( ** or SQLITE_CHANGESET_CONFLICT. */ int sqlite3changeset_conflict( - sqlite3_changeset_iter *pIter, - int iVal, + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ sqlite3_value **ppValue /* OUT: Value from conflicting row */ ); @@ -153,15 +151,15 @@ int sqlite3changeset_invert( ** resolution strategy. */ int sqlite3changeset_apply( - sqlite3 *db, - int nChangeset, - void *pChangeset, + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ int(*xConflict)( void *pCtx, /* Copy of fifth arg to _apply() */ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), - void *pCtx + void *pCtx /* First argument passed to xConflict */ ); /* diff --git a/manifest b/manifest index 89b9043680..7e8b8c7747 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\shandling\sof\sreturn\svalues\sfrom\sthe\sconflict\shandler.\sDocument\sthe\sconflict\shandler\sarguments\sand\sreturn\scodes\sin\ssqlite3session.h. -D 2011-03-14T19:49:23 +C Fix\ssome\sbugs\sand\sother\scode\sissues\sin\sthe\ssession\smodule. +D 2011-03-15T16:37:28 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -98,8 +98,8 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/sqlite3session.c 111a988b4734b7419f23bb07e45bf5e991510270 -F ext/session/sqlite3session.h 55ca208bddbc1284c83427f423748eb720f5c68f +F ext/session/sqlite3session.c 9b8d123418c024f6851163375fca99042757772f +F ext/session/sqlite3session.h 01aac9a1185b7db6716217f3aa3f7a835ab864b9 F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -639,7 +639,7 @@ F test/selectA.test 06d1032fa9009314c95394f2ca2e60d9f7ae8532 F test/selectB.test f305cc6660804cb239aab4e2f26b0e288b59958b F test/selectC.test f9bf1bc4581b5b8158caa6e4e4f682acb379fb25 F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c -F test/session1.test edbd6078b86b3f6337d779552671125fbd885e19 +F test/session1.test 1e85c2eedb14587dff41901faa5a66c117fe0405 F test/shared.test b9114eaea7e748a3a4c8ff7b9ca806c8f95cef3e F test/shared2.test 7f6ad2d857d0f4e5d6a0b9a897b5e56a6b6ea18c F test/shared3.test d69bdd5f156580876c5345652d21dc2092e85962 @@ -913,7 +913,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 57862efe718fdc93401998f9058511292a0e1a50 -R 17f2f6e54c1cfa1876ed6a58e92b5c4b +P cbbb274e500237dbf7155a51d4f9c17583d704ea +R c267abdc5c97771dbd3d62995c13d672 U dan -Z e9add8546b195a8b303123ffee5a5609 +Z 5fed91a90fa4060d0a5ac8127dba8c51 diff --git a/manifest.uuid b/manifest.uuid index f68965ee4d..79ca836129 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cbbb274e500237dbf7155a51d4f9c17583d704ea \ No newline at end of file +f2930840e4af3d7d9cb199d316502932fcbbb867 \ No newline at end of file diff --git a/test/session1.test b/test/session1.test index 46b9d3442d..ca8d9a78f1 100644 --- a/test/session1.test +++ b/test/session1.test @@ -291,11 +291,7 @@ do_execsql_test 3.3.5 { SELECT * FROM t4 } {-1 2 3 -1 5 6 {} 8 9 x 11 12} #------------------------------------------------------------------------- # This next block of tests verifies that values returned by the conflict -# handler are intepreted correctly. The following cases are tested: -# -# Test case Operation Conflict Return Code -# UPDATE DATA OMIT -# UPDATE DATA REPLACE +# handler are intepreted correctly. # proc test_reset {} { @@ -407,6 +403,35 @@ foreach {tn conflict_return} { do_db2_test 5.$tn.3 "SELECT * FROM d1" $res($conflict_return) } +#------------------------------------------------------------------------- +# Test that two tables can be monitored by a single session object. +# +test_reset +set schema { + CREATE TABLE t1(a COLLATE nocase PRIMARY KEY, b); + CREATE TABLE t2(a, b PRIMARY KEY); +} +do_test 6.0 { + execsql $schema db + execsql $schema db2 + execsql { + INSERT INTO t1 VALUES('a', 'b'); + INSERT INTO t2 VALUES('a', 'b'); + } db2 +} {} + +set conflict_return "" +do_conflict_test 6.1 -tables {t1 t2} -sql { + INSERT INTO t1 VALUES('1', '2'); + INSERT INTO t1 VALUES('A', 'B'); + INSERT INTO t2 VALUES('A', 'B'); +} -conflicts { + {INSERT t1 CONFLICT {t A t B} {t a t b}} +} + +do_db2_test 6.2 "SELECT * FROM t1" {a b 1 2} +do_db2_test 6.3 "SELECT * FROM t2" {a b A B} + catch { db2 close } finish_test From 6566ebe1b630c04d66dc92e709674786f81ba191 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 16 Mar 2011 09:49:14 +0000 Subject: [PATCH 009/570] Remove the sqlite3_transaction_hook() API. FossilOrigin-Name: b0015a1cfe63c924ee5f250aa08460522882009b --- manifest | 28 +++++----- manifest.uuid | 2 +- src/main.c | 42 -------------- src/sqlite.h.in | 11 ---- src/sqliteInt.h | 3 - src/tclsqlite.c | 37 +------------ src/vdbe.c | 13 ----- src/vdbeapi.c | 10 +--- src/vdbeaux.c | 9 --- test/hook.test | 131 -------------------------------------------- test/tclsqlite.test | 2 +- 11 files changed, 20 insertions(+), 268 deletions(-) diff --git a/manifest b/manifest index 7e8b8c7747..4061dea410 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\sbugs\sand\sother\scode\sissues\sin\sthe\ssession\smodule. -D 2011-03-15T16:37:28 +C Remove\sthe\ssqlite3_transaction_hook()\sAPI. +D 2011-03-16T09:49:15 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -145,7 +145,7 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e F src/loadext.c 8af9fcc75708d60b88636ccba38b4a7b3c155c3e -F src/main.c 1a5cafdc1bee11f4322c837487bf6fa8e54b2f50 +F src/main.c 9ab948225b8c362cdd6902c447abbf218607e0f3 F src/malloc.c 92d59a007d7a42857d4e9454aa25b6b703286be1 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206 @@ -180,13 +180,13 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 649c51979812f77f97507024a4cea480c6862b8b -F src/sqlite.h.in 992688609e9a0274b56c156d4800be96364b3590 +F src/sqlite.h.in 8da2897e3c9b251b29aa48d11bfb1f30f1de0733 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h 85e635183013e806069320ffa6080a77183f9225 +F src/sqliteInt.h db209477de559911d7f14c1d208cbf2bc46e9224 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e -F src/tclsqlite.c b124fb73120d1bc4b78ae8153bce71dbd2d93db5 +F src/tclsqlite.c 0aa7e768b3bd72bf4c4b0312c9a84d6cdedb7638 F src/test1.c 9020310c7617234b33fd1c3064f89524db25f290 F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc @@ -232,11 +232,11 @@ F src/update.c 1b9a82ede7df15e76ed86c6a3cbe4ce0f21eaa9b F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685 F src/util.c ab1c92426494f499f42b9e307537b03e923d75c1 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c 2c523bc17f915329f3db3745fc76ed9bfc5c26bb +F src/vdbe.c 117644088f89c40b01c917d06f7b2ed706ca125f F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 9dd04435bd5a68e30cd07e7a91c17b062bf1c23d -F src/vdbeapi.c 750dcdea999762adbac6eddde5bd790803911edf -F src/vdbeaux.c 9ba08ed7de89e923ba6b95a5a75a460e6507a81f +F src/vdbeapi.c 256029b0a2ed2373ebbcce7a497b3a702a52689b +F src/vdbeaux.c f789da7d55231d779c26deaf5a1e6ccb3e550c09 F src/vdbeblob.c 18955f0ee6b133cd08e1592010cb9a6b11e9984c F src/vdbemem.c 0fa2ed786cd207d5b988afef3562a8e663a75b50 F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -474,7 +474,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c -F test/hook.test a90748e44c7ca53da46f857616fc7ce18bf7be13 +F test/hook.test 85059721ef537317af679aca5435f94ab316d074 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 @@ -671,7 +671,7 @@ F test/superlock.test 5d7a4954b0059c903f82c7b67867bc5451a7c082 F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3 F test/table.test 04ba066432430657712d167ebf28080fe878d305 F test/tableapi.test 7262a8cbaa9965d429f1cbd2747edc185fa56516 -F test/tclsqlite.test 550f2268281d186b767b3ee14dd0be5f9e3ff25d +F test/tclsqlite.test 1ce9b6340d6d412420634e129a2e3722c651056a F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05 @@ -913,7 +913,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P cbbb274e500237dbf7155a51d4f9c17583d704ea -R c267abdc5c97771dbd3d62995c13d672 +P f2930840e4af3d7d9cb199d316502932fcbbb867 +R fadac1472cdeb40a0e5c985ec43cbe17 U dan -Z 5fed91a90fa4060d0a5ac8127dba8c51 +Z 22d8aae45d188380f4801c8d2b2db4e1 diff --git a/manifest.uuid b/manifest.uuid index 79ca836129..2664939330 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f2930840e4af3d7d9cb199d316502932fcbbb867 \ No newline at end of file +b0015a1cfe63c924ee5f250aa08460522882009b \ No newline at end of file diff --git a/src/main.c b/src/main.c index a8ac80039e..3976f7ebc3 100644 --- a/src/main.c +++ b/src/main.c @@ -764,26 +764,6 @@ int sqlite3_close(sqlite3 *db){ return SQLITE_OK; } - -/* -** Invoke the transaction-hook. -*/ -void sqlite3TransactionHook(sqlite3 *db, int op, int iLevel){ - assert( op==SQLITE_BEGIN || op==SQLITE_COMMIT || op==SQLITE_ROLLBACK ); - assert( op==SQLITE_BEGIN || iLeveliOpenTrans || iLevel==0 ); - assert( op==SQLITE_BEGIN || iLeveliOpenTrans || db->iOpenTrans==0 ); - assert( op!=SQLITE_BEGIN || iLevel==db->iOpenTrans || iLevel==0 ); - assert( op!=SQLITE_BEGIN || iLevel==db->iOpenTrans || db->iOpenTrans==1 ); - - if( op==SQLITE_BEGIN && iLevel!=db->iOpenTrans ) return; - if( op!=SQLITE_BEGIN && iLevel>=db->iOpenTrans ) return; - - if( db->xTransCallback ){ - db->xTransCallback(db->pTransArg, op, iLevel); - } - db->iOpenTrans = iLevel + (op==SQLITE_BEGIN); -} - /* ** Rollback all database files. */ @@ -816,10 +796,6 @@ void sqlite3RollbackAll(sqlite3 *db){ if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ db->xRollbackCallback(db->pRollbackArg); } - - /* If a transaction-hook is configured, invoke it now to report on - ** the rollback operation. */ - sqlite3TransactionHook(db, SQLITE_ROLLBACK, 0); } /* @@ -1314,24 +1290,6 @@ void *sqlite3_preupdate_hook( return pRet; } -/* -** Register a callback to be invoked each time a transaction or savepoint -** is opened, committed or rolled back. -*/ -void *sqlite3_transaction_hook( - sqlite3 *db, /* Database handle */ - void(*xCallback)(void *, int, int), /* Callback function */ - void *pArg /* First callback argument */ -){ - void *pRet; - sqlite3_mutex_enter(db->mutex); - pRet = db->pTransArg; - db->xTransCallback = xCallback; - db->pTransArg = pArg; - sqlite3_mutex_leave(db->mutex); - return pRet; -} - #ifndef SQLITE_OMIT_WAL /* ** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 137be57b89..d3c9ac5f24 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6369,17 +6369,6 @@ SQLITE_EXPERIMENTAL int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); SQLITE_EXPERIMENTAL int sqlite3_preupdate_modified(sqlite3 *, int, int *); SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *); -/* -** CAPI3REF: The transaction hook. -*/ -SQLITE_EXPERIMENTAL -void *sqlite3_transaction_hook(sqlite3 *, void(*)(void *, int, int), void *); - -#define SQLITE_BEGIN 1 -#define SQLITE_COMMIT 2 -#define SQLITE_ROLLBACK 3 - - /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 1414fb68b5..2582d7c990 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -833,9 +833,6 @@ struct sqlite3 { void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64 ); PreUpdate *pPreUpdate; /* Context for active pre-update callback */ - void *pTransArg; /* First argument to xTransCallback */ - void (*xTransCallback)(void*,int,int); - int iOpenTrans; /* Open transaction (xTransCallback) plus 1 */ #ifndef SQLITE_OMIT_WAL int (*xWalCallback)(void *, sqlite3 *, const char *, int); void *pWalArg; diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 1743b40cf6..b5ac5faf88 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -124,7 +124,6 @@ struct SqliteDb { Tcl_Obj *pUpdateHook; /* Update hook script (if any) */ Tcl_Obj *pPreUpdateHook; /* Pre-update hook script (if any) */ Tcl_Obj *pRollbackHook; /* Rollback hook script (if any) */ - Tcl_Obj *pTransHook; /* Transaction hook script (if any) */ Tcl_Obj *pWalHook; /* WAL hook script (if any) */ Tcl_Obj *pUnlockNotify; /* Unlock notify script (if any) */ SqlCollate *pCollate; /* List of SQL collation functions */ @@ -598,30 +597,6 @@ static void DbRollbackHandler(void *clientData){ } } -/* -** sqlite3_transaction_hook() callback. -*/ -static void DbTransHandler(void *clientData, int op, int iLevel){ - static const char *azStr[] = { "BEGIN", "COMMIT", "ROLLBACK" }; - SqliteDb *pDb = (SqliteDb*)clientData; - Tcl_Interp *interp = pDb->interp; - Tcl_Obj *pScript; - - assert(pDb->pTransHook); - assert( SQLITE_BEGIN==1 ); - assert( SQLITE_COMMIT==2 ); - assert( SQLITE_ROLLBACK==3 ); - - pScript = Tcl_DuplicateObj(pDb->pTransHook); - Tcl_IncrRefCount(pScript); - Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(azStr[op-1], -1)); - Tcl_ListObjAppendElement(interp, pScript, Tcl_NewIntObj(iLevel)); - if( TCL_OK!=Tcl_EvalObjEx(interp, pScript, 0) ){ - Tcl_BackgroundError(interp); - } - Tcl_DecrRefCount(pScript); -} - /* ** This procedure handles wal_hook callbacks. */ @@ -1653,7 +1628,6 @@ static void DbHookCmd( sqlite3_update_hook(db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb); sqlite3_rollback_hook(db, (pDb->pRollbackHook?DbRollbackHandler:0), pDb); sqlite3_wal_hook(db, (pDb->pWalHook?DbWalHandler:0), pDb); - sqlite3_transaction_hook(db, (pDb->pTransHook?DbTransHandler:0), pDb); } /* @@ -1685,8 +1659,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ "profile", "progress", "rekey", "restore", "rollback_hook", "status", "timeout", "total_changes", "trace", - "transaction", "transaction_hook", - "unlock_notify", "update_hook", + "transaction", "unlock_notify", "update_hook", "version", "wal_hook", 0 }; enum DB_enum { @@ -1701,8 +1674,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ DB_PROFILE, DB_PROGRESS, DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK, DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, - DB_TRANSACTION, DB_TRANSACTION_HOOK, - DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, + DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION, DB_WAL_HOOK }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ @@ -2942,12 +2914,10 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ ** $db wal_hook ?script? ** $db update_hook ?script? ** $db rollback_hook ?script? - ** $db transaction_hook ?script? */ case DB_WAL_HOOK: case DB_UPDATE_HOOK: - case DB_ROLLBACK_HOOK: - case DB_TRANSACTION_HOOK: { + case DB_ROLLBACK_HOOK: { sqlite3 *db = pDb->db; /* set ppHook to point at pUpdateHook or pRollbackHook, depending on @@ -2957,7 +2927,6 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ if( choice==DB_WAL_HOOK ) ppHook = &pDb->pWalHook; if( choice==DB_UPDATE_HOOK ) ppHook = &pDb->pUpdateHook; if( choice==DB_ROLLBACK_HOOK ) ppHook = &pDb->pRollbackHook; - if( choice==DB_TRANSACTION_HOOK ) ppHook = &pDb->pTransHook; if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); return TCL_ERROR; diff --git a/src/vdbe.c b/src/vdbe.c index 252c53cb63..041e93025b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2569,8 +2569,6 @@ case OP_Savepoint: { db->nSavepoint++; } - sqlite3TransactionHook(db, SQLITE_BEGIN, db->nSavepoint); - /* Link the new savepoint into the database handle's list. */ pNew->pNext = db->pSavepoint; db->pSavepoint = pNew; @@ -2637,13 +2635,6 @@ case OP_Savepoint: { sqlite3ResetInternalSchema(db, 0); db->flags = (db->flags | SQLITE_InternChanges); } - - assert( SAVEPOINT_ROLLBACK+1==SQLITE_ROLLBACK ); - assert( SAVEPOINT_RELEASE+1==SQLITE_COMMIT ); - sqlite3TransactionHook(db, p1+1, iSavepoint+1); - if( p1==SAVEPOINT_ROLLBACK ){ - sqlite3TransactionHook(db, SQLITE_BEGIN, iSavepoint+1); - } } /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all @@ -2719,9 +2710,6 @@ case OP_AutoCommit: { }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ goto vdbe_return; }else{ - if( desiredAutoCommit==0 ){ - sqlite3TransactionHook(db, SQLITE_BEGIN, 0); - } db->autoCommit = (u8)desiredAutoCommit; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ p->pc = pc; @@ -2808,7 +2796,6 @@ case OP_Transaction: { p->iStatement = db->nSavepoint + db->nStatement; } rc = sqlite3BtreeBeginStmt(pBt, p->iStatement); - sqlite3TransactionHook(db, SQLITE_BEGIN, p->iStatement); /* Store the current value of the database handles deferred constraint ** counter. If the statement transaction needs to be rolled back, diff --git a/src/vdbeapi.c b/src/vdbeapi.c index d3bd6478cf..0d5fd94021 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -401,15 +401,7 @@ static int sqlite3Step(Vdbe *p){ #endif db->activeVdbeCnt++; - if( p->readOnly==0 ){ - /* If this statement will open an implicit transaction, invoke the - ** transaction-hook here. */ - if( db->autoCommit && db->writeVdbeCnt==0 ){ - assert( db->nSavepoint==0 ); - sqlite3TransactionHook(db, SQLITE_BEGIN, 0); - } - db->writeVdbeCnt++; - } + if( p->readOnly==0 ) db->writeVdbeCnt++; p->pc = 0; } #ifndef SQLITE_OMIT_EXPLAIN diff --git a/src/vdbeaux.c b/src/vdbeaux.c index cb6aefac08..1c870c2404 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1845,12 +1845,6 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ } #endif - /* If a transaction-hook is configured, invoke it now to report on the - ** successful commit operation. */ - if( rc==SQLITE_OK ){ - sqlite3TransactionHook(db, SQLITE_COMMIT, 0); - } - return rc; } @@ -1952,9 +1946,6 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ } } db->nStatement--; - assert( SAVEPOINT_ROLLBACK+1==SQLITE_ROLLBACK ); - assert( SAVEPOINT_RELEASE+1==SQLITE_COMMIT ); - sqlite3TransactionHook(db, eOp+1, p->iStatement); p->iStatement = 0; /* If the statement transaction is being rolled back, also restore the diff --git a/test/hook.test b/test/hook.test index b2e0988828..0ba4b19e40 100644 --- a/test/hook.test +++ b/test/hook.test @@ -631,136 +631,5 @@ do_preupdate_test 7.5.2.2 { UPDATE main t8 2 2 three four xxx } -#---------------------------------------------------------------------------- -# The following tests - hook-8.* - test the transaction hook. -# -db close -forcedelete test.db -sqlite3 db test.db - -proc transaction_hook {op iLevel} { - lappend ::transaction_hook $op $iLevel -} -db transaction_hook transaction_hook - -proc do_transaction_test {tn sql x} { - set X [list] - foreach elem $x {lappend X $elem} - - uplevel do_test $tn [list " - set ::transaction_hook \[list\] - catchsql { $sql } - set ::transaction_hook - "] [list $X] -} - -do_transaction_test 8.1.1 "CREATE TABLE t1(x)" {BEGIN 0 COMMIT 0} -do_transaction_test 8.1.2 "BEGIN" {BEGIN 0} -do_transaction_test 8.1.3 "COMMIT" {COMMIT 0} -do_transaction_test 8.1.4 "BEGIN ; ROLLBACK" {BEGIN 0 ROLLBACK 0} - -do_execsql_test 8.2.0 { - CREATE TABLE t2(a PRIMARY KEY, b); - INSERT INTO t2 VALUES(1, 'one'); - INSERT INTO t2 VALUES(2, 'two'); - INSERT INTO t2 VALUES(3, 'three'); -} -do_transaction_test 8.2.1 { - INSERT INTO t2 VALUES(2, 'xxx') -} {BEGIN 0 ROLLBACK 0} - -do_transaction_test 8.2.2 { - BEGIN; INSERT INTO t2 SELECT a-2, b FROM t2; -} {BEGIN 0 BEGIN 1 ROLLBACK 1} - -do_transaction_test 8.2.3 { - INSERT OR ROLLBACK INTO t2 SELECT a-2, b FROM t2; -} {ROLLBACK 0} - -do_transaction_test 8.2.4 { - BEGIN; INSERT INTO t2 SELECT a+3, b FROM t2; -} {BEGIN 0 BEGIN 1 COMMIT 1} - -do_transaction_test 8.2.5 "COMMIT" {COMMIT 0} - -do_transaction_test 8.3.1 {SELECT * FROM t2} {} - -do_transaction_test 8.4.1 { - SAVEPOINT top; - RELEASE top; -} {BEGIN 0 COMMIT 0} - -do_transaction_test 8.4.2 { - SAVEPOINT top; - ROLLBACK TO top; - RELEASE top; -} {BEGIN 0 ROLLBACK 0 BEGIN 0 COMMIT 0} - -do_transaction_test 8.4.3 { - SAVEPOINT zero; - SAVEPOINT one; - SAVEPOINT two; - SAVEPOINT three; - ROLLBACK TO zero; - SAVEPOINT one; - SAVEPOINT two; - SAVEPOINT three; - ROLLBACK TO one; - SAVEPOINT two; - RELEASE zero; - - SAVEPOINT zero; - SAVEPOINT one; - SAVEPOINT two; - RELEASE two; - SAVEPOINT two; - SAVEPOINT three; - RELEASE one; - ROLLBACK TO zero; - RELEASE zero; -} { - BEGIN 0 BEGIN 1 BEGIN 2 BEGIN 3 ROLLBACK 0 BEGIN 0 - BEGIN 1 BEGIN 2 BEGIN 3 ROLLBACK 1 BEGIN 1 BEGIN 2 - COMMIT 0 - - BEGIN 0 BEGIN 1 BEGIN 2 COMMIT 2 BEGIN 2 BEGIN 3 COMMIT 1 - ROLLBACK 0 BEGIN 0 COMMIT 0 -} - -do_transaction_test 8.4.4 { - BEGIN; - SAVEPOINT zero; - SAVEPOINT one; - SAVEPOINT two; - SAVEPOINT three; - ROLLBACK TO zero; - SAVEPOINT one; - SAVEPOINT two; - SAVEPOINT three; - ROLLBACK TO one; - SAVEPOINT two; - RELEASE zero; - - SAVEPOINT zero; - SAVEPOINT one; - SAVEPOINT two; - RELEASE two; - SAVEPOINT two; - SAVEPOINT three; - RELEASE one; - ROLLBACK TO zero; - RELEASE zero; - COMMIT; -} { - BEGIN 0 - BEGIN 1 BEGIN 2 BEGIN 3 BEGIN 4 ROLLBACK 1 BEGIN 1 - BEGIN 2 BEGIN 3 BEGIN 4 ROLLBACK 2 BEGIN 2 BEGIN 3 - COMMIT 1 - - BEGIN 1 BEGIN 2 BEGIN 3 COMMIT 3 BEGIN 3 BEGIN 4 COMMIT 2 - ROLLBACK 1 BEGIN 1 COMMIT 1 - COMMIT 0 -} - finish_test diff --git a/test/tclsqlite.test b/test/tclsqlite.test index efc3e53ab6..c9d562beb5 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -35,7 +35,7 @@ do_test tcl-1.1 { do_test tcl-1.2 { set v [catch {db bogus} msg] lappend v $msg -} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, transaction, transaction_hook, unlock_notify, update_hook, version, or wal_hook}} +} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, transaction, unlock_notify, update_hook, version, or wal_hook}} do_test tcl-1.2.1 { set v [catch {db cache bogus} msg] lappend v $msg From 37db03bf73f9692fdd86388d677668c09be128d7 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 16 Mar 2011 19:59:18 +0000 Subject: [PATCH 010/570] Add the sqlite3_preupdate_new() API, for retrieving the new.* values from within a pre-update callback. FossilOrigin-Name: 526545c49f64d9063d1b888cfc14ece62fa3c13c --- ext/session/sqlite3session.h | 58 +++++++++++++++++++++++------ manifest | 28 +++++++------- manifest.uuid | 2 +- src/sqlite.h.in | 2 +- src/tclsqlite.c | 27 ++++++-------- src/update.c | 6 +++ src/vdbe.c | 6 +-- src/vdbeInt.h | 6 ++- src/vdbeapi.c | 71 +++++++++++++++++++++++++++++++++--- src/vdbeaux.c | 21 ++++++++++- test/hook.test | 40 +++++++++++--------- 11 files changed, 196 insertions(+), 71 deletions(-) diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index c4053e3dbe..573b2ff3fc 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -15,8 +15,32 @@ typedef struct sqlite3_session sqlite3_session; typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; /* -** Create a session object. This session object will record changes to -** database zDb attached to connection db. +** Create a new session object attached to database handle db. If successful, +** a pointer to the new object is written to *ppSession and SQLITE_OK is +** returned. If an error occurs, *ppSession is set to NULL and an SQLite +** error code (e.g. [SQLITE_NOMEM]) is returned. +** +** It is possible to create multiple session objects attached to a single +** database handle. +** +** Session objects created using this function should be deleted using the +** [sqlite3session_delete()] function before the database handle that they +** are attached to is itself closed. If the database handle is closed before +** the session object is deleted, then the results of calling any session +** module function, including [sqlite3session_delete()] on the session object +** are undefined. +** +** Because the session module uses the [sqlite3_preupdate_hook()] API, it +** is not possible for an application to register a pre-update hook on a +** database handle that has one or more session objects attached. Nor is +** it possible to create a session object attached to a database handle for +** which a pre-update hook is already defined. The results of attempting +** either of these things are undefined. +** +** The session object will be used to create changesets for tables in +** database zDb, where zDb is either "main", or "temp", or the name of an +** attached database. It is not an error if database zDb does not exist +** to the database when the session object is created. */ int sqlite3session_create( sqlite3 *db, /* Database handle */ @@ -24,6 +48,18 @@ int sqlite3session_create( sqlite3_session **ppSession /* OUT: New session object */ ); +/* +** Delete a session object previously allocated using +** [sqlite3session_create()]. Once a session object has been deleted, the +** results of attempting to use pSession with any other session module +** function are undefined. +** +** Session objects must be deleted before the database handle to which they +** are attached is closed. Refer to the documentation for +** [sqlite3session_create()] for details. +*/ +void sqlite3session_delete(sqlite3_session *pSession); + /* ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When @@ -52,11 +88,16 @@ int sqlite3session_attach( ); /* -** Obtain a changeset object containing all changes recorded by the -** session object passed as the first argument. +** Obtain a changeset containing changes to the tables attached to the +** session object passed as the first argument. If successful, +** set *ppChangeset to point to a buffer containing the changeset +** and *pnChangeset to the size of the changeset in bytes before returning +** SQLITE_OK. If an error occurs, set both *ppChangeset and *pnChangeset to +** zero and return an SQLite error code. ** -** It is the responsibility of the caller to eventually free the buffer -** using sqlite3_free(). +** Following a successful call to this function, it is the responsibility of +** the caller to eventually free the buffer that *ppChangeset points to using +** [sqlite3_free()]. */ int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ @@ -64,11 +105,6 @@ int sqlite3session_changeset( void **ppChangeset /* OUT: Buffer containing changeset */ ); -/* -** Delete a session object previously allocated using sqlite3session_create(). -*/ -void sqlite3session_delete(sqlite3_session *pSession); - /* ** Create an iterator used to iterate through the contents of a changeset. */ diff --git a/manifest b/manifest index 4061dea410..796df369be 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\ssqlite3_transaction_hook()\sAPI. -D 2011-03-16T09:49:15 +C Add\sthe\ssqlite3_preupdate_new()\sAPI,\sfor\sretrieving\sthe\snew.*\svalues\sfrom\swithin\sa\spre-update\scallback. +D 2011-03-16T19:59:19 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -99,7 +99,7 @@ F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/sqlite3session.c 9b8d123418c024f6851163375fca99042757772f -F ext/session/sqlite3session.h 01aac9a1185b7db6716217f3aa3f7a835ab864b9 +F ext/session/sqlite3session.h 63045871564085669b5cb1fb92e6efc2e1b1120a F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -180,13 +180,13 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 649c51979812f77f97507024a4cea480c6862b8b -F src/sqlite.h.in 8da2897e3c9b251b29aa48d11bfb1f30f1de0733 +F src/sqlite.h.in 992c54d9bd451a041fb0b74fb5cd3b14db98e544 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 F src/sqliteInt.h db209477de559911d7f14c1d208cbf2bc46e9224 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e -F src/tclsqlite.c 0aa7e768b3bd72bf4c4b0312c9a84d6cdedb7638 +F src/tclsqlite.c fc0321c62a3c3929b9b0659b94b7d37bac84e769 F src/test1.c 9020310c7617234b33fd1c3064f89524db25f290 F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc @@ -228,15 +228,15 @@ F src/test_vfs.c 2ed8853c1e51ac6f9ea091f7ce4e0d618bba8b86 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080 F src/trigger.c b8bedb9c0084ceb51a40f54fcca2ce048c8de852 -F src/update.c 1b9a82ede7df15e76ed86c6a3cbe4ce0f21eaa9b +F src/update.c 18a862e3e08377a5afb26d6f16182a8f700a1ca7 F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685 F src/util.c ab1c92426494f499f42b9e307537b03e923d75c1 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c 117644088f89c40b01c917d06f7b2ed706ca125f +F src/vdbe.c fbf11bd681fd2313aaf59fb2fd7f02cd8324a88a F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 -F src/vdbeInt.h 9dd04435bd5a68e30cd07e7a91c17b062bf1c23d -F src/vdbeapi.c 256029b0a2ed2373ebbcce7a497b3a702a52689b -F src/vdbeaux.c f789da7d55231d779c26deaf5a1e6ccb3e550c09 +F src/vdbeInt.h 20d13da932eed0667a2e2383a9cb0f80099a5fd3 +F src/vdbeapi.c 3066456f64fb10c9c5151c684b5f5e8d67a5f4f2 +F src/vdbeaux.c 896844f9bf663202b3afa8c139e2caddcf855765 F src/vdbeblob.c 18955f0ee6b133cd08e1592010cb9a6b11e9984c F src/vdbemem.c 0fa2ed786cd207d5b988afef3562a8e663a75b50 F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -474,7 +474,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c -F test/hook.test 85059721ef537317af679aca5435f94ab316d074 +F test/hook.test d0a277022888caf75ae1d4ec79917668f2f0f2e6 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 @@ -913,7 +913,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P f2930840e4af3d7d9cb199d316502932fcbbb867 -R fadac1472cdeb40a0e5c985ec43cbe17 +P b0015a1cfe63c924ee5f250aa08460522882009b +R 4b62a15aa3feb03b0e54e624839e53a1 U dan -Z 22d8aae45d188380f4801c8d2b2db4e1 +Z 0b4af75dcf5347bcbba47251e978ee95 diff --git a/manifest.uuid b/manifest.uuid index 2664939330..69c5255486 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b0015a1cfe63c924ee5f250aa08460522882009b \ No newline at end of file +526545c49f64d9063d1b888cfc14ece62fa3c13c \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index d3c9ac5f24..0f920bd6dd 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6366,8 +6366,8 @@ SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook( void* ); SQLITE_EXPERIMENTAL int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); -SQLITE_EXPERIMENTAL int sqlite3_preupdate_modified(sqlite3 *, int, int *); SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *); +SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); /* ** Undo the hack that converts floating point types to integer for diff --git a/src/tclsqlite.c b/src/tclsqlite.c index b5ac5faf88..b3f98126c0 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -2846,9 +2846,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ } case DB_PREUPDATE: { - static const char *azSub[] = {"count", "hook", "modified", "old", 0}; + static const char *azSub[] = {"count", "hook", "new", "old", 0}; enum DbPreupdateSubCmd { - PRE_COUNT, PRE_HOOK, PRE_MODIFIED, PRE_OLD + PRE_COUNT, PRE_HOOK, PRE_NEW, PRE_OLD }; int iSub; @@ -2875,9 +2875,10 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ break; } - case PRE_MODIFIED: + case PRE_NEW: case PRE_OLD: { int iIdx; + sqlite3_value *pValue; if( objc!=4 ){ Tcl_WrongNumArgs(interp, 3, objv, "INDEX"); return TCL_ERROR; @@ -2886,21 +2887,17 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ return TCL_ERROR; } - if( iSub==PRE_MODIFIED ){ - int iRes; - rc = sqlite3_preupdate_modified(pDb->db, iIdx, &iRes); - if( rc==SQLITE_OK ) Tcl_SetObjResult(interp, Tcl_NewIntObj(iRes)); - }else{ - sqlite3_value *pValue; - assert( iSub==PRE_OLD ); + if( iSub==PRE_OLD ){ rc = sqlite3_preupdate_old(pDb->db, iIdx, &pValue); - if( rc==SQLITE_OK ){ - Tcl_Obj *pObj = Tcl_NewStringObj(sqlite3_value_text(pValue), -1); - Tcl_SetObjResult(interp, pObj); - } + }else{ + assert( iSub==PRE_NEW ); + rc = sqlite3_preupdate_new(pDb->db, iIdx, &pValue); } - if( rc!=SQLITE_OK ){ + if( rc==SQLITE_OK ){ + Tcl_Obj *pObj = Tcl_NewStringObj(sqlite3_value_text(pValue), -1); + Tcl_SetObjResult(interp, pObj); + }else{ Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0); return TCL_ERROR; } diff --git a/src/update.c b/src/update.c index ea8f95ad56..4bf4a880b1 100644 --- a/src/update.c +++ b/src/update.c @@ -493,7 +493,13 @@ void sqlite3Update( /* If changing the rowid value, or if there are foreign key constraints ** to process, delete the old record. Otherwise, add a noop OP_Delete ** to invoke the pre-update hook. + ** + ** That (regNew==regnewRowid+1) is true is also important for the + ** pre-update hook. If hte caller invokes preupdate_new(), the returned + ** value is copied from memory cell (regNewRowid+1+iCol), where iCol + ** is the column index supplied by the user. */ + assert( regNew==regNewRowid+1 ); sqlite3VdbeAddOp3(v, OP_Delete, iCur, OPFLAG_ISUPDATE | ((hasFK || chngRowid) ? 0 : OPFLAG_ISNOOP), regNewRowid diff --git a/src/vdbe.c b/src/vdbe.c index 041e93025b..1ef59d0a39 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3881,9 +3881,7 @@ case OP_InsertInt: { && pOp->p4.z && (!(pOp->p5 & OPFLAG_ISUPDATE) || pC->rowidIsValid==0) ){ - sqlite3VdbePreUpdateHook(p, pC, - pC->rowidIsValid ? op : SQLITE_INSERT, zDb, zTbl, iKey, iKey - ); + sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, zTbl, iKey, pOp->p2); } if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; @@ -3985,7 +3983,7 @@ case OP_Delete: { sqlite3VdbePreUpdateHook(p, pC, (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, zDb, zTbl, iKey, - (opflags & OPFLAG_ISUPDATE) ? aMem[pOp->p3].u.i : iKey + pOp->p3 ); } diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 0b4178aacd..447e025e94 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -336,11 +336,15 @@ struct Vdbe { ** sqlite3_preupdate_*() API functions. */ struct PreUpdate { + Vdbe *v; VdbeCursor *pCsr; /* Cursor to read old values from */ int op; /* One of SQLITE_INSERT, UPDATE, DELETE */ u8 *aRecord; /* old.* database record */ KeyInfo keyinfo; UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ + UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ + int iNewReg; /* Register for new.* values */ + Mem *aNew; /* Array of new.* values */ }; /* @@ -400,7 +404,7 @@ void sqlite3VdbeFrameDelete(VdbeFrame*); int sqlite3VdbeFrameRestore(VdbeFrame *); void sqlite3VdbeMemStoreType(Mem *pMem); void sqlite3VdbePreUpdateHook( - Vdbe *, VdbeCursor *, int, const char*, const char*, i64, i64); + Vdbe *, VdbeCursor *, int, const char*, const char*, i64, int); #ifdef SQLITE_DEBUG void sqlite3VdbeMemPrepareToChange(Vdbe*,Mem*); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 0d5fd94021..66f8c0857f 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -1329,10 +1329,16 @@ int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ return v; } +/* +** This function is called from within a pre-update callback to retrieve +** a field of the row currently being updated or deleted. +*/ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ PreUpdate *p = db->pPreUpdate; int rc = SQLITE_OK; + /* Test that this call is being made from within an SQLITE_DELETE or + ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */ if( !p || p->op==SQLITE_INSERT ){ rc = SQLITE_MISUSE_BKPT; goto preupdate_old_out; @@ -1342,6 +1348,7 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ goto preupdate_old_out; } + /* If the old.* record has not yet been loaded into memory, do so now. */ if( p->pUnpacked==0 ){ u32 nRecord; u8 *aRecord; @@ -1372,26 +1379,78 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ return sqlite3ApiExit(db, rc); } +/* +** This function is called from within a pre-update callback to retrieve +** the number of columns in the row being updated, deleted or inserted. +*/ int sqlite3_preupdate_count(sqlite3 *db){ PreUpdate *p = db->pPreUpdate; return (p ? p->pCsr->nField : 0); } -int sqlite3_preupdate_modified(sqlite3 *db, int iIdx, int *pbMod){ +/* +** This function is called from within a pre-update callback to retrieve +** a field of the row currently being updated or inserted. +*/ +int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ PreUpdate *p = db->pPreUpdate; int rc = SQLITE_OK; + Mem *pMem; - if( !p || p->op!=SQLITE_UPDATE ){ + if( !p || p->op==SQLITE_DELETE ){ rc = SQLITE_MISUSE_BKPT; - goto preupdate_mod_out; + goto preupdate_new_out; } if( iIdx>=p->pCsr->nField || iIdx<0 ){ rc = SQLITE_RANGE; - goto preupdate_mod_out; + goto preupdate_new_out; } - *pbMod = 1; - preupdate_mod_out: + if( p->op==SQLITE_INSERT ){ + /* For an INSERT, memory cell p->iNewReg contains the serialized record + ** that is being inserted. Deserialize it. */ + UnpackedRecord *pUnpack = p->pNewUnpacked; + if( !pUnpack ){ + Mem *pData = &p->v->aMem[p->iNewReg]; + rc = sqlite3VdbeMemExpandBlob(pData); + if( rc!=SQLITE_OK ) goto preupdate_new_out; + pUnpack = sqlite3VdbeRecordUnpack(&p->keyinfo, pData->n, pData->z, 0, 0); + if( !pUnpack ){ + rc = SQLITE_NOMEM; + goto preupdate_new_out; + } + p->pNewUnpacked = pUnpack; + } + if( iIdx>=pUnpack->nField ){ + pMem = (sqlite3_value *)columnNullValue(); + }else{ + pMem = &pUnpack->aMem[iIdx]; + sqlite3VdbeMemStoreType(pMem); + } + }else{ + /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required + ** value. Make a copy of the cell contents and return a pointer to it. + ** It is not safe to return a pointer to the memory cell itself as the + ** caller may modify the value text encoding. + */ + assert( p->op==SQLITE_UPDATE ); + if( !p->aNew ){ + p->aNew = (Mem *)sqlite3DbMallocZero(db, sizeof(Mem) * p->pCsr->nField); + if( !p->aNew ){ + rc = SQLITE_NOMEM; + goto preupdate_new_out; + } + } + pMem = &p->aNew[iIdx]; + if( pMem->flags==0 ){ + rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); + if( rc!=SQLITE_OK ) goto preupdate_new_out; + sqlite3VdbeMemStoreType(pMem); + } + } + *ppValue = pMem; + + preupdate_new_out: sqlite3Error(db, rc, 0); return sqlite3ApiExit(db, rc); } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 1c870c2404..9749251585 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3176,15 +3176,24 @@ void sqlite3VdbePreUpdateHook( const char *zDb, /* Database name */ const char *zTbl, /* Table name */ i64 iKey1, /* Initial key value */ - i64 iKey2 /* Final key value */ + int iReg /* Register for new.* record */ ){ sqlite3 *db = v->db; + i64 iKey2; PreUpdate preupdate; memset(&preupdate, 0, sizeof(PreUpdate)); + if( op==SQLITE_UPDATE ){ + iKey2 = v->aMem[iReg].u.i; + }else{ + iKey2 = iKey1; + } + + preupdate.v = v; preupdate.pCsr = pCsr; preupdate.op = op; + preupdate.iNewReg = iReg; preupdate.keyinfo.db = db; preupdate.keyinfo.enc = ENC(db); preupdate.keyinfo.nField = pCsr->nField; @@ -3195,5 +3204,15 @@ void sqlite3VdbePreUpdateHook( if( preupdate.pUnpacked ){ sqlite3VdbeDeleteUnpackedRecord(preupdate.pUnpacked); } + if( preupdate.pNewUnpacked ){ + sqlite3VdbeDeleteUnpackedRecord(preupdate.pNewUnpacked); + } + if( preupdate.aNew ){ + int i; + for(i=0; inField; i++){ + sqlite3VdbeMemRelease(&preupdate.aNew[i]); + } + sqlite3_free(preupdate.aNew); + } } diff --git a/test/hook.test b/test/hook.test index 0ba4b19e40..001e8ddf4a 100644 --- a/test/hook.test +++ b/test/hook.test @@ -405,11 +405,17 @@ proc do_preupdate_test {tn sql x} { proc preupdate_hook {args} { set type [lindex $args 0] eval lappend ::preupdate $args - if {$type != "SQLITE_INSERT"} { + if {$type != "INSERT"} { for {set i 0} {$i < [db preupdate count]} {incr i} { lappend ::preupdate [db preupdate old $i] } } + if {$type != "DELETE"} { + for {set i 0} {$i < [db preupdate count]} {incr i} { + set rc [catch { db preupdate new $i } v] + lappend ::preupdate $v + } + } } db close @@ -433,28 +439,28 @@ do_execsql_test 7.0 { do_preupdate_test 7.1.1 { INSERT INTO t1 VALUES('x', 'y') -} {INSERT main t1 1 1} +} {INSERT main t1 1 1 x y} # 7.1.2.1 does not use the xfer optimization. 7.1.2.2 does. do_preupdate_test 7.1.2.1 { INSERT INTO t1 SELECT y, x FROM t2; -} {INSERT main t1 2 2 INSERT main t1 3 3} +} {INSERT main t1 2 2 b a INSERT main t1 3 3 d c} do_preupdate_test 7.1.2.2 { INSERT INTO t1 SELECT * FROM t2; -} {INSERT main t1 4 4 INSERT main t1 5 5} +} {INSERT main t1 4 4 a b INSERT main t1 5 5 c d} do_preupdate_test 7.1.3 { REPLACE INTO t1(rowid, a, b) VALUES(1, 1, 1); } { DELETE main t1 1 1 x y - INSERT main t1 1 1 + INSERT main t1 1 1 1 1 } do_preupdate_test 7.1.4 { REPLACE INTO t3 VALUES(4, NULL); } { DELETE main t3 1 1 4 16 - INSERT main t3 4 4 + INSERT main t3 4 4 4 {} } do_preupdate_test 7.1.5 { @@ -462,7 +468,7 @@ do_preupdate_test 7.1.5 { } { DELETE main t3 2 2 5 25 DELETE main t3 3 3 6 36 - INSERT main t3 2 2 + INSERT main t3 2 2 6 {} } do_execsql_test 7.2.0 { SELECT rowid FROM t1 } {1 2 3 4 5} @@ -497,29 +503,29 @@ do_execsql_test 7.3.0 { do_preupdate_test 7.3.1 { UPDATE t2 SET y = y||y; } { - UPDATE main t2 1 1 a b - UPDATE main t2 2 2 c d + UPDATE main t2 1 1 a b a bb + UPDATE main t2 2 2 c d c dd } do_preupdate_test 7.3.2 { UPDATE t2 SET rowid = rowid-1; } { - UPDATE main t2 1 0 a bb - UPDATE main t2 2 1 c dd + UPDATE main t2 1 0 a bb a bb + UPDATE main t2 2 1 c dd c dd } do_preupdate_test 7.3.3 { UPDATE OR REPLACE t2 SET rowid = 1 WHERE x = 'a' } { DELETE main t2 1 1 c dd - UPDATE main t2 0 1 a bb + UPDATE main t2 0 1 a bb a bb } do_preupdate_test 7.3.4.1 { UPDATE OR REPLACE t3 SET i = 5 WHERE i = 6 } { DELETE main t3 2 2 5 25 - UPDATE main t3 3 3 6 36 + UPDATE main t3 3 3 6 36 5 36 } do_execsql_test 7.3.4.2 { @@ -532,7 +538,7 @@ do_preupdate_test 7.3.5 { } { DELETE main t3 1 1 4 16 DELETE main t3 3 3 5 36 - UPDATE main t3 4 1 10 100 + UPDATE main t3 4 1 10 100 5 100 } do_execsql_test 7.4.1.0 { @@ -577,7 +583,7 @@ do_preupdate_test 7.4.2.1 { UPDATE t5 SET b = 4 WHERE a = 'c' } { DELETE main t5 1 1 a 1 - UPDATE main t5 3 3 c 3 + UPDATE main t5 3 3 c 3 c 4 } do_execsql_test 7.4.2.2 { @@ -606,7 +612,7 @@ do_preupdate_test 7.5.1.1 { do_preupdate_test 7.5.1.2 { UPDATE t7 SET b = 'five' } { - UPDATE main t7 2 2 three four {} + UPDATE main t7 2 2 three four {} three five {} } do_execsql_test 7.5.2.0 { @@ -628,7 +634,7 @@ do_preupdate_test 7.5.2.1 { do_preupdate_test 7.5.2.2 { UPDATE t8 SET b = 'five' } { - UPDATE main t8 2 2 three four xxx + UPDATE main t8 2 2 three four xxx three five xxx } finish_test From e8d5648e168300c5ed3f0cf89158a55474f7520e Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 17 Mar 2011 19:20:27 +0000 Subject: [PATCH 011/570] Change to the session module to use user-defined primary keys instead of rowids when collecting changes. FossilOrigin-Name: 6614cfcb9c41da71ddec3c44a3de0d4d849e1cdd --- ext/session/sqlite3session.c | 775 +++++++++++++++++++++++------------ manifest | 14 +- manifest.uuid | 2 +- test/session1.test | 37 +- 4 files changed, 548 insertions(+), 280 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index d454d4d345..296875052e 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -8,7 +8,6 @@ #include "sqliteInt.h" #include "vdbeInt.h" -typedef struct RowChange RowChange; typedef struct SessionTable SessionTable; typedef struct SessionChange SessionChange; typedef struct SessionBuffer SessionBuffer; @@ -57,6 +56,8 @@ struct SessionTable { SessionTable *pNext; char *zName; /* Local name of table */ int nCol; /* Number of columns in table zName */ + const char **azCol; /* Column names */ + u8 *abPK; /* Array of primary key flags */ int nEntry; /* Total number of entries in hash table */ int nChange; /* Size of apChange[] array */ SessionChange **apChange; /* Hash table buckets */ @@ -128,7 +129,7 @@ struct SessionTable { ** this structure stored in a SessionTable.aChange[] hash table. */ struct SessionChange { - sqlite3_int64 iKey; /* Key value */ + int bInsert; /* True if row was inserted this session */ int nRecord; /* Number of bytes in buffer aRecord[] */ u8 *aRecord; /* Buffer containing old.* record */ SessionChange *pNext; /* For hash-table collisions */ @@ -264,12 +265,188 @@ static int sessionSerializeValue( return SQLITE_OK; } +#define HASH_APPEND(hash, add) ((hash) << 3) ^ (hash) ^ (int)(add) +static int sessionHashAppendI64(int h, i64 i){ + h = HASH_APPEND(h, i & 0xFFFFFFFF); + return HASH_APPEND(h, (i>>32)&0xFFFFFFFF); +} +static int sessionHashAppendBlob(int h, int n, const u8 *z){ + int i; + for(i=0; inCol==sqlite3_preupdate_count(db) ); + for(i=0; inCol; i++){ + if( pTab->abPK[i] ){ + int rc; + int eType; + sqlite3_value *pVal; + + if( bNew ){ + rc = sqlite3_preupdate_new(db, i, &pVal); + }else{ + rc = sqlite3_preupdate_old(db, i, &pVal); + } + + eType = sqlite3_value_type(pVal); + h = HASH_APPEND(h, eType); + switch( eType ){ + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + i64 iVal; + if( eType==SQLITE_INTEGER ){ + iVal = sqlite3_value_int64(pVal); + }else{ + double rVal = sqlite3_value_double(pVal); + assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); + memcpy(&iVal, &rVal, 8); + } + h = sessionHashAppendI64(h, iVal); + break; + } + + case SQLITE_TEXT: + case SQLITE_BLOB: { + int n = sqlite3_value_bytes(pVal); + const u8 *z = eType==SQLITE_TEXT ? + sqlite3_value_text(pVal) : sqlite3_value_blob(pVal); + h = sessionHashAppendBlob(h, n, z); + break; + } + } + } + } + + *piHash = (h % pTab->nChange); + return SQLITE_OK; +} + +static int sessionChangeHash( + sqlite3 *db, + SessionTable *pTab, + SessionChange *pChange, + int nBucket +){ + int h = 0; + int i; + u8 *a = pChange->aRecord; + + for(i=0; inCol; i++){ + int eType = *a++; + int isPK = pTab->abPK[i]; + + if( isPK ) h = HASH_APPEND(h, eType); + switch( eType ){ + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + if( isPK ){ + i64 iVal = sessionGetI64(a); + h = sessionHashAppendI64(h, iVal); + } + a += 8; + break; + } + case SQLITE_TEXT: + case SQLITE_BLOB: { + int n; + a += sessionVarintGet(a, &n); + if( isPK ){ + h = sessionHashAppendBlob(h, n, a); + } + a += n; + break; + } + } + } + return (h % nBucket); +} + +static int sessionPreupdateEqual( + sqlite3 *db, + SessionTable *pTab, + SessionChange *pChange, + int bNew, + int *pbEqual +){ + int i; + u8 *a = pChange->aRecord; + + *pbEqual = 0; + + for(i=0; inCol; i++){ + int eType = *a++; + if( !pTab->abPK[i] ){ + switch( eType ){ + case SQLITE_INTEGER: + case SQLITE_FLOAT: + a += 8; + break; + + case SQLITE_TEXT: + case SQLITE_BLOB: { + int n; + a += sessionVarintGet(a, &n); + a += n; + break; + } + } + }else{ + sqlite3_value *pVal; + int rc; + if( bNew ){ + rc = sqlite3_preupdate_new(db, i, &pVal); + }else{ + rc = sqlite3_preupdate_old(db, i, &pVal); + } + if( rc!=SQLITE_OK || sqlite3_value_type(pVal)!=eType ) return rc; + + switch( eType ){ + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + i64 iVal = sessionGetI64(a); + a += 8; + if( eType==SQLITE_INTEGER ){ + if( sqlite3_value_int64(pVal)!=iVal ) return SQLITE_OK; + }else{ + double rVal; + assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); + memcpy(&rVal, &iVal, 8); + if( sqlite3_value_double(pVal)!=rVal ) return SQLITE_OK; + } + break; + } + case SQLITE_TEXT: + case SQLITE_BLOB: { + int n; + const u8 *z; + a += sessionVarintGet(a, &n); + if( sqlite3_value_bytes(pVal)!=n ) return SQLITE_OK; + z = eType==SQLITE_TEXT ? + sqlite3_value_text(pVal) : sqlite3_value_blob(pVal); + if( memcmp(a, z, n) ) return SQLITE_OK; + a += n; + break; + } + } + } + } + + *pbEqual = 1; + return SQLITE_OK; } /* @@ -303,7 +480,7 @@ static int sessionGrowHash(sqlite3_session *pSession, SessionTable *pTab){ SessionChange *p; SessionChange *pNext; for(p=pTab->apChange[i]; p; p=pNext){ - int iHash = sessionKeyhash(nNew, p->iKey); + int iHash = sessionChangeHash(pSession->db, pTab, p, nNew); pNext = p->pNext; p->pNext = apNew[iHash]; apNew[iHash] = p; @@ -318,6 +495,130 @@ static int sessionGrowHash(sqlite3_session *pSession, SessionTable *pTab){ return SQLITE_OK; } +/* +** This function queries the database for the names of the columns of table +** zThis, in schema zDb. It is expected that the table has nCol columns. If +** not, SQLITE_SCHEMA is returned and none of the output variables are +** populated. +** +** Otherwise, if it is not NULL, variable *pzTab is set to point to a +** nul-terminated copy of the table name. *pazCol (if not NULL) is set to +** point to an array of pointers to column names. And *pabPK (again, if not +** NULL) is set to point to an array of booleans - true if the corresponding +** column is part of the primary key. +** +** For example, if the table is declared as: +** +** CREATE TABLE tbl1(w, x, y, z, PRIMARY KEY(w, z)); +** +** Then the three output variables are populated as follows: +** +** *pzTab = "tbl1" +** *pazCol = {"w", "x", "y", "z"} +** *pabPK = {1, 0, 0, 1} +** +** All returned buffers are part of the same single allocation, which must +** be freed using sqlite3_free() by the caller. If pazCol was not NULL, then +** pointer *pazCol should be freed to release all memory. Otherwise, pointer +** *pabPK. It is illegal for both pazCol and pabPK to be NULL. +*/ +static int sessionTableInfo( + sqlite3 *db, /* Database connection */ + const char *zDb, /* Name of attached database (e.g. "main") */ + const char *zThis, /* Table name */ + int nCol, /* Expected number of columns */ + const char **pzTab, /* OUT: Copy of zThis */ + const char ***pazCol, /* OUT: Array of column names for table */ + u8 **pabPK /* OUT: Array of booleans - true for PK col */ +){ + char *zPragma; + sqlite3_stmt *pStmt; + int rc; + int nByte; + int nDbCol = 0; + int nThis; + int i; + u8 *pAlloc; + u8 *pFree = 0; + char **azCol; + u8 *abPK; + + assert( pazCol || pabPK ); + + nThis = strlen(zThis); + zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis); + if( !zPragma ) return SQLITE_NOMEM; + + rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0); + sqlite3_free(zPragma); + if( rc!=SQLITE_OK ) return rc; + + nByte = nThis + 1; + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + nByte += sqlite3_column_bytes(pStmt, 1); + nDbCol++; + } + rc = sqlite3_reset(pStmt); + + if( nDbCol!=nCol ){ + rc = SQLITE_SCHEMA; + } + if( rc==SQLITE_OK ){ + nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1); + pAlloc = sqlite3_malloc(nByte); + if( pAlloc==0 ){ + rc = SQLITE_NOMEM; + } + } + if( rc==SQLITE_OK ){ + pFree = pAlloc; + if( pazCol ){ + azCol = (char **)pAlloc; + pAlloc = (u8 *)&azCol[nCol]; + } + if( pabPK ){ + abPK = (u8 *)pAlloc; + pAlloc = &abPK[nCol]; + } + if( pzTab ){ + memcpy(pAlloc, zThis, nThis+1); + *pzTab = (char *)pAlloc; + pAlloc += nThis+1; + } + + i = 0; + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + int nName = sqlite3_column_bytes(pStmt, 1); + const unsigned char *zName = sqlite3_column_text(pStmt, 1); + if( zName==0 ) break; + if( pazCol ){ + memcpy(pAlloc, zName, nName+1); + azCol[i] = (char *)pAlloc; + pAlloc += nName+1; + } + if( pabPK ) abPK[i] = sqlite3_column_int(pStmt, 5); + i++; + } + rc = sqlite3_reset(pStmt); + + } + + /* If successful, populate the output variables. Otherwise, zero them and + ** free any allocation made. An error code will be returned in this case. + */ + if( rc==SQLITE_OK ){ + if( pazCol ) *pazCol = (const char **)azCol; + if( pabPK ) *pabPK = abPK; + }else{ + if( pazCol ) *pazCol = 0; + if( pabPK ) *pabPK = 0; + if( pzTab ) *pzTab = 0; + sqlite3_free(pFree); + } + sqlite3_finalize(pStmt); + return rc; +} + /* ** This function is only called from within a pre-update handler for a ** write to table pTab, part of session pSession. If this is the first @@ -336,12 +637,104 @@ static int sessionGrowHash(sqlite3_session *pSession, SessionTable *pTab){ */ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ if( pTab->nCol==0 ){ + assert( pTab->azCol==0 || pTab->abPK==0 ); pTab->nCol = sqlite3_preupdate_count(pSession->db); + pSession->rc = sessionTableInfo(pSession->db, pSession->zDb, + pTab->zName, pTab->nCol, 0, &pTab->azCol, &pTab->abPK + ); }else if( pTab->nCol!=sqlite3_preupdate_count(pSession->db) ){ pSession->rc = SQLITE_SCHEMA; - return SQLITE_ERROR; } - return SQLITE_OK; + return pSession->rc; +} + +static void sessionPreupdateOneChange( + int op, + sqlite3_session *pSession, + SessionTable *pTab +){ + sqlite3 *db = pSession->db; + SessionChange *pChange; + SessionChange *pC; + int iHash; + int rc = SQLITE_OK; + + if( pSession->rc ) return; + + /* Load table details if required */ + if( sessionInitTable(pSession, pTab) ) return; + + /* Grow the hash table if required */ + if( sessionGrowHash(pSession, pTab) ) return; + + /* Search the hash table for an existing entry for rowid=iKey2. If + ** one is found, store a pointer to it in pChange and unlink it from + ** the hash table. Otherwise, set pChange to NULL. + */ + rc = sessionPreupdateHash(db, pTab, op==SQLITE_INSERT, &iHash); + for(pC=pTab->apChange[iHash]; rc==SQLITE_OK && pC; pC=pC->pNext){ + int bEqual; + rc = sessionPreupdateEqual(db, pTab, pC, op==SQLITE_INSERT, &bEqual); + if( bEqual ) break; + } + if( pC==0 ){ + /* Create a new change object containing all the old values (if + ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK + ** values (if this is an INSERT). */ + int nByte; /* Number of bytes to allocate */ + int i; /* Used to iterate through columns */ + + pTab->nEntry++; + + /* Figure out how large an allocation is required */ + nByte = sizeof(SessionChange); + for(i=0; inCol && rc==SQLITE_OK; i++){ + sqlite3_value *p = 0; + if( op!=SQLITE_INSERT ){ + rc = sqlite3_preupdate_old(pSession->db, i, &p); + }else if( 1 || pTab->abPK[i] ){ + rc = sqlite3_preupdate_new(pSession->db, i, &p); + } + if( p && rc==SQLITE_OK ){ + rc = sessionSerializeValue(0, p, &nByte); + } + } + + /* Allocate the change object */ + pChange = (SessionChange *)sqlite3_malloc(nByte); + if( !pChange ){ + rc = SQLITE_NOMEM; + }else{ + memset(pChange, 0, sizeof(SessionChange)); + pChange->aRecord = (u8 *)&pChange[1]; + } + + /* Populate the change object */ + nByte = 0; + for(i=0; inCol && rc==SQLITE_OK; i++){ + sqlite3_value *p = 0; + if( op!=SQLITE_INSERT ){ + rc = sqlite3_preupdate_old(pSession->db, i, &p); + }else if( 1 || pTab->abPK[i] ){ + rc = sqlite3_preupdate_new(pSession->db, i, &p); + } + if( p && rc==SQLITE_OK ){ + rc = sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte); + } + } + pChange->nRecord = nByte; + + /* If an error has occurred, mark the session object as failed. */ + if( rc!=SQLITE_OK ){ + sqlite3_free(pChange); + pSession->rc = rc; + }else{ + /* Add the change back to the hash-table */ + pChange->bInsert = (op==SQLITE_INSERT); + pChange->pNext = pTab->apChange[iHash]; + pTab->apChange[iHash] = pChange; + } + } } /* @@ -363,93 +756,19 @@ static void xPreUpdate( for(pSession=(sqlite3_session *)pCtx; pSession; pSession=pSession->pNext){ SessionTable *pTab; - /* If this session is already in the error-state, or if it is attached - ** to a different database ("main", "temp" etc.), or if it is not - ** currently enabled, there is nothing to do. Skip to the next session - ** object attached to this database. */ + /* If this session is attached to a different database ("main", "temp" + ** etc.), or if it is not currently enabled, there is nothing to do. Skip + ** to the next session object attached to this database. */ if( pSession->bEnable==0 ) continue; if( pSession->rc ) continue; if( sqlite3_strnicmp(zDb, pSession->zDb, nDb+1) ) continue; for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){ if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ){ - SessionChange *pChange; - SessionChange *pC; - int iHash; - int rc = SQLITE_OK; - - /* Load table details if required */ - if( sessionInitTable(pSession, pTab) ) return; - - /* Grow the hash table if required */ - if( sessionGrowHash(pSession, pTab) ) return; - - /* Search the hash table for an existing entry for rowid=iKey2. If - ** one is found, store a pointer to it in pChange and unlink it from - ** the hash table. Otherwise, set pChange to NULL. - */ - iHash = sessionKeyhash(pTab->nChange, iKey2); - for(pC=pTab->apChange[iHash]; pC; pC=pC->pNext){ - if( pC->iKey==iKey2 ) break; + sessionPreupdateOneChange(op, pSession, pTab); + if( op==SQLITE_UPDATE ){ + sessionPreupdateOneChange(SQLITE_INSERT, pSession, pTab); } - if( pC ) continue; - - pTab->nEntry++; - - /* Create a new change object containing all the old values (if - ** this is an SQLITE_UPDATE or SQLITE_DELETE), or no record at - ** all (if this is an INSERT). */ - if( op==SQLITE_INSERT ){ - pChange = (SessionChange *)sqlite3_malloc(sizeof(SessionChange)); - if( pChange ){ - memset(pChange, 0, sizeof(SessionChange)); - } - }else{ - int nByte; /* Number of bytes to allocate */ - int i; /* Used to iterate through columns */ - - /* Figure out how large an allocation is required */ - nByte = sizeof(SessionChange); - for(i=0; inCol && rc==SQLITE_OK; i++){ - sqlite3_value *p; /* old.* value */ - rc = sqlite3_preupdate_old(pSession->db, i, &p); - if( rc==SQLITE_OK ){ - rc = sessionSerializeValue(0, p, &nByte); - } - } - - /* Allocate the change object */ - pChange = (SessionChange *)sqlite3_malloc(nByte); - if( !pChange ){ - rc = SQLITE_NOMEM; - }else{ - memset(pChange, 0, sizeof(SessionChange)); - pChange->aRecord = (u8 *)&pChange[1]; - } - - /* Populate the change object */ - nByte = 0; - for(i=0; inCol && rc==SQLITE_OK; i++){ - sqlite3_value *p; /* old.* value */ - rc = sqlite3_preupdate_old(pSession->db, i, &p); - if( rc==SQLITE_OK ){ - rc = sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte); - } - } - pChange->nRecord = nByte; - } - - /* If an error has occurred, mark the session object as failed. */ - if( rc!=SQLITE_OK ){ - sqlite3_free(pChange); - pSession->rc = rc; - return; - } - - /* Add the change back to the hash-table */ - pChange->iKey = iKey2; - pChange->pNext = pTab->apChange[iHash]; - pTab->apChange[iHash] = pChange; break; } } @@ -524,6 +843,7 @@ void sqlite3session_delete(sqlite3_session *pSession){ sqlite3_free(p); } } + sqlite3_free(pTab->azCol); sqlite3_free(pTab->apChange); sqlite3_free(pTab); } @@ -852,127 +1172,99 @@ static void sessionAppendUpdate( } } -/* -** This function queries the database for the names of the columns of table -** zThis, in schema zDb. It is expected that the table has nCol columns. If -** not, SQLITE_SCHEMA is returned and none of the output variables are -** populated. -** -** Otherwise, if it is not NULL, variable *pzTab is set to point to a -** nul-terminated copy of the table name. *pazCol (if not NULL) is set to -** point to an array of pointers to column names. And *pabPK (again, if not -** NULL) is set to point to an array of booleans - true if the corresponding -** column is part of the primary key. -** -** For example, if the table is declared as: -** -** CREATE TABLE tbl1(w, x, y, z, PRIMARY KEY(w, z)); -** -** Then the three output variables are populated as follows: -** -** *pzTab = "tbl1" -** *pazCol = {"w", "x", "y", "z"} -** *pabPK = {1, 0, 0, 1} -** -** All returned buffers are part of the same single allocation, which must -** be freed using sqlite3_free() by the caller. If pazCol was not NULL, then -** pointer *pazCol should be freed to release all memory. Otherwise, pointer -** *pabPK. It is illegal for both pazCol and pabPK to be NULL. -*/ -static int sessionTableInfo( - sqlite3 *db, /* Database connection */ - const char *zDb, /* Name of attached database (e.g. "main") */ - const char *zThis, /* Table name */ - int nCol, /* Expected number of columns */ - const char **pzTab, /* OUT: Copy of zThis */ - const char ***pazCol, /* OUT: Array of column names for table */ - u8 **pabPK /* OUT: Array of booleans - true for PK col */ +static int sessionSelectStmt( + sqlite3 *db, /* Database handle */ + const char *zTab, /* Table name */ + int nCol, + const char **azCol, + u8 *abPK, + sqlite3_stmt **ppStmt ){ - char *zPragma; - sqlite3_stmt *pStmt; - int rc; - int nByte; - int nDbCol = 0; - int nThis; + int rc = SQLITE_OK; int i; - u8 *pAlloc; - u8 *pFree = 0; - char **azCol; - u8 *abPK; + const char *zSep = ""; + SessionBuffer buf = {0, 0, 0}; - assert( pazCol || pabPK ); - - nThis = strlen(zThis); - zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis); - if( !zPragma ) return SQLITE_NOMEM; - - rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0); - sqlite3_free(zPragma); - if( rc!=SQLITE_OK ) return rc; - - nByte = nThis + 1; - while( SQLITE_ROW==sqlite3_step(pStmt) ){ - nByte += sqlite3_column_bytes(pStmt, 1); - nDbCol++; - } - rc = sqlite3_reset(pStmt); - - if( nDbCol!=nCol ){ - rc = SQLITE_SCHEMA; - } - if( rc==SQLITE_OK ){ - nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1); - pAlloc = sqlite3_malloc(nByte); - if( pAlloc==0 ){ - rc = SQLITE_NOMEM; + sessionAppendStr(&buf, "SELECT * FROM ", &rc); + sessionAppendIdent(&buf, zTab, &rc); + sessionAppendStr(&buf, " WHERE ", &rc); + for(i=0; ipTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ if( pTab->nEntry ){ + int nCol = pTab->nCol; /* Local copy of member variable */ + u8 *abPK = pTab->abPK; /* Local copy of member variable */ int i; sqlite3_stmt *pStmt = 0; int bNoop = 1; int nRewind = buf.nBuf; - u8 *abPK = 0; /* Write a table header */ sessionAppendByte(&buf, 'T', &rc); - sessionAppendVarint(&buf, pTab->nCol, &rc); + sessionAppendVarint(&buf, nCol, &rc); sessionAppendBlob(&buf, (u8 *)pTab->zName, strlen(pTab->zName)+1, &rc); /* Build and compile a statement to execute: */ if( rc==SQLITE_OK ){ - char *zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q WHERE _rowid_ = ?", - pSession->zDb, pTab->zName - ); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - } - sqlite3_free(zSql); + rc = sessionSelectStmt(db, pTab->zName, nCol, pTab->azCol, abPK,&pStmt); } - if( rc==SQLITE_OK && pTab->nCol!=sqlite3_column_count(pStmt) ){ + if( rc==SQLITE_OK && nCol!=sqlite3_column_count(pStmt) ){ rc = SQLITE_SCHEMA; } - if( rc==SQLITE_OK ){ - rc = sessionTableInfo( - db, pSession->zDb, pTab->zName, pTab->nCol, 0, 0, &abPK); - } - for(i=0; inChange; i++){ - SessionChange *p; + SessionChange *p; /* Used to iterate through changes */ + for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ - sqlite3_bind_int64(pStmt, 1, p->iKey); - if( sqlite3_step(pStmt)==SQLITE_ROW ){ - int iCol; - if( p->aRecord ){ - sessionAppendUpdate(&buf, pStmt, p, abPK, &rc); - }else{ - sessionAppendByte(&buf, SQLITE_INSERT, &rc); - for(iCol=0; iColnCol; iCol++){ - sessionAppendCol(&buf, pStmt, iCol, &rc); + rc = sessionSelectBind(pStmt, nCol, abPK, p->aRecord, p->nRecord); + if( rc==SQLITE_OK ){ + if( sqlite3_step(pStmt)==SQLITE_ROW ){ + int iCol; + if( p->bInsert ){ + sessionAppendByte(&buf, SQLITE_INSERT, &rc); + for(iCol=0; iColbInsert ){ + /* A DELETE change */ + sessionAppendByte(&buf, SQLITE_DELETE, &rc); + sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); + bNoop = 0; } - bNoop = 0; - }else if( p->aRecord ){ - /* A DELETE change */ - sessionAppendByte(&buf, SQLITE_DELETE, &rc); - sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); - bNoop = 0; + rc = sqlite3_reset(pStmt); } - rc = sqlite3_reset(pStmt); } } sqlite3_finalize(pStmt); - sqlite3_free(abPK); if( bNoop ){ buf.nBuf = nRewind; @@ -1632,28 +1914,7 @@ static int sessionSelectRow( const char *zTab, /* Table name */ SessionApplyCtx *p /* Session changeset-apply context */ ){ - int rc = SQLITE_OK; - int i; - const char *zSep = ""; - SessionBuffer buf = {0, 0, 0}; - - sessionAppendStr(&buf, "SELECT * FROM ", &rc); - sessionAppendIdent(&buf, zTab, &rc); - sessionAppendStr(&buf, " WHERE ", &rc); - for(i=0; inCol; i++){ - if( p->abPK[i] ){ - sessionAppendStr(&buf, zSep, &rc); - sessionAppendIdent(&buf, p->azCol[i], &rc); - sessionAppendStr(&buf, " = ?", &rc); - sessionAppendInteger(&buf, i+1, &rc); - zSep = " AND "; - } - } - if( rc==SQLITE_OK ){ - rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pSelect, 0); - } - sqlite3_free(buf.aBuf); - return rc; + return sessionSelectStmt(db, zTab, p->nCol, p->azCol, p->abPK, &p->pSelect); } /* diff --git a/manifest b/manifest index 796df369be..2ab7a1eec9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssqlite3_preupdate_new()\sAPI,\sfor\sretrieving\sthe\snew.*\svalues\sfrom\swithin\sa\spre-update\scallback. -D 2011-03-16T19:59:19 +C Change\sto\sthe\ssession\smodule\sto\suse\suser-defined\sprimary\skeys\sinstead\sof\srowids\swhen\scollecting\schanges. +D 2011-03-17T19:20:27 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -98,7 +98,7 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/sqlite3session.c 9b8d123418c024f6851163375fca99042757772f +F ext/session/sqlite3session.c 4183792547af5b5d3ec1c8a3f858beb172682503 F ext/session/sqlite3session.h 63045871564085669b5cb1fb92e6efc2e1b1120a F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 @@ -639,7 +639,7 @@ F test/selectA.test 06d1032fa9009314c95394f2ca2e60d9f7ae8532 F test/selectB.test f305cc6660804cb239aab4e2f26b0e288b59958b F test/selectC.test f9bf1bc4581b5b8158caa6e4e4f682acb379fb25 F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c -F test/session1.test 1e85c2eedb14587dff41901faa5a66c117fe0405 +F test/session1.test c6851e2e1066269cad5370566ce5494c7dbdfa7e F test/shared.test b9114eaea7e748a3a4c8ff7b9ca806c8f95cef3e F test/shared2.test 7f6ad2d857d0f4e5d6a0b9a897b5e56a6b6ea18c F test/shared3.test d69bdd5f156580876c5345652d21dc2092e85962 @@ -913,7 +913,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P b0015a1cfe63c924ee5f250aa08460522882009b -R 4b62a15aa3feb03b0e54e624839e53a1 +P 526545c49f64d9063d1b888cfc14ece62fa3c13c +R cab2f9d8485568249e1bae732085445e U dan -Z 0b4af75dcf5347bcbba47251e978ee95 +Z 0451d1109f54d52c16342adf23f8ece9 diff --git a/manifest.uuid b/manifest.uuid index 69c5255486..412c6f3bf5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -526545c49f64d9063d1b888cfc14ece62fa3c13c \ No newline at end of file +6614cfcb9c41da71ddec3c44a3de0d4d849e1cdd \ No newline at end of file diff --git a/test/session1.test b/test/session1.test index ca8d9a78f1..872bee416f 100644 --- a/test/session1.test +++ b/test/session1.test @@ -37,7 +37,7 @@ proc do_changeset_invert_test {tn session res} { } do_execsql_test 1.0 { - CREATE TABLE t1(x, y); + CREATE TABLE t1(x PRIMARY KEY, y); INSERT INTO t1 VALUES('abc', 'def'); } @@ -113,6 +113,7 @@ do_changeset_invert_test 2.2.3 S { do_test 2.2.4 { S delete } {} do_test 2.3.1 { + execsql { DELETE FROM t1 } sqlite3session S db main execsql { INSERT INTO t1 VALUES(1, 'Sukhothai') } execsql { INSERT INTO t1 VALUES(2, 'Ayutthaya') } @@ -126,14 +127,19 @@ do_test 2.3.1 { } {} do_changeset_test 2.3.2 S { - {UPDATE t1 {i 1 {} {}} {i 10 {} {}}} - {UPDATE t1 {{} {} t Ayutthaya} {{} {} t Surin}} - {UPDATE t1 {i 3 t Thonburi} {i 20 t Thapae}} + {INSERT t1 {} {i 10 t Sukhothai}} + {DELETE t1 {i 1 t Sukhothai} {}} + {UPDATE t1 {i 2 t Ayutthaya} {{} {} t Surin}} + {DELETE t1 {i 3 t Thonburi} {}} + {INSERT t1 {} {i 20 t Thapae}} } + do_changeset_invert_test 2.3.3 S { - {UPDATE t1 {i 10 {} {}} {i 1 {} {}}} - {UPDATE t1 {{} {} t Surin} {{} {} t Ayutthaya}} - {UPDATE t1 {i 20 t Thapae} {i 3 t Thonburi}} + {DELETE t1 {i 10 t Sukhothai} {}} + {INSERT t1 {} {i 1 t Sukhothai}} + {UPDATE t1 {{} {} t Surin} {i 2 t Ayutthaya}} + {INSERT t1 {} {i 3 t Thonburi}} + {DELETE t1 {i 20 t Thapae} {}} } do_test 2.3.4 { S delete } {} @@ -209,7 +215,7 @@ do_test 3.1.0 { } db } {} do_db2_test 3.1.1 "INSERT INTO t1 VALUES(6, 'VI')" -do_conflict_test 3.2.2 -tables t1 -sql { +do_conflict_test 3.1.2 -tables t1 -sql { INSERT INTO t1 VALUES(3, 'three'); INSERT INTO t1 VALUES(4, 'four'); INSERT INTO t1 VALUES(5, 'five'); @@ -217,13 +223,14 @@ do_conflict_test 3.2.2 -tables t1 -sql { INSERT INTO t1 VALUES(7, 'seven'); INSERT INTO t1 VALUES(8, NULL); } -conflicts { - {INSERT t1 CONFLICT {i 6 t six} {i 6 t VI}} {INSERT t1 CONSTRAINT {i 8 n {}}} + {INSERT t1 CONFLICT {i 6 t six} {i 6 t VI}} } -do_db2_test 3.1.2 "SELECT * FROM t1" { + +do_db2_test 3.1.3 "SELECT * FROM t1" { 6 VI 3 three 4 four 5 five 7 seven } -do_execsql_test 3.1.3 "SELECT * FROM t1" { +do_execsql_test 3.1.4 "SELECT * FROM t1" { 1 one 2 two 3 three 4 four 5 five 6 six 7 seven 8 {} } @@ -282,9 +289,9 @@ do_conflict_test 3.3.3 -tables t4 -sql { UPDATE t4 SET a = NULL WHERE c = 9; UPDATE t4 SET a = 'x' WHERE b = 11; } -conflicts { + {UPDATE t4 CONSTRAINT {i 7 i 8 i 9} {n {} {} {} {} {}}} {UPDATE t4 DATA {i 1 i 2 i 3} {i -1 {} {} {} {}} {i 0 i 2 i 3}} {UPDATE t4 NOTFOUND {i 4 i 5 i 6} {i -1 {} {} {} {}}} - {UPDATE t4 CONSTRAINT {i 7 i 8 i 9} {n {} {} {} {} {}}} } do_db2_test 3.3.4 { SELECT * FROM t4 } {0 2 3 4 5 7 7 8 9 x 11 12} do_execsql_test 3.3.5 { SELECT * FROM t4 } {-1 2 3 -1 5 6 {} 8 9 x 11 12} @@ -308,8 +315,8 @@ proc xConflict {args} { } foreach {tn conflict_return after} { - 1 OMIT {1 2 value1 4 5 7 7 8 9 10 x x} - 2 REPLACE {1 2 value1 4 5 value2 10 8 9} + 1 OMIT {1 2 value1 4 5 7 10 x x} + 2 REPLACE {1 2 value1 4 5 value2 10 8 9} } { test_reset @@ -333,8 +340,8 @@ foreach {tn conflict_return after} { UPDATE t1 SET c = 'value2' WHERE a = 4; -- DATA conflict UPDATE t1 SET a = 10 WHERE a = 7; -- CONFLICT conflict } -conflicts { + {INSERT t1 CONFLICT {i 10 i 8 i 9} {i 10 t x t x}} {UPDATE t1 DATA {i 4 {} {} i 6} {{} {} {} {} t value2} {i 4 i 5 i 7}} - {UPDATE t1 CONFLICT {i 7 {} {} {} {}} {i 10 {} {} {} {}} {i 10 t x t x}} } do_db2_test 4.$tn.3 "SELECT * FROM t1 ORDER BY a" $after From c21111daffd0cba6c099c91242052c047f3b54b2 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 18 Mar 2011 13:05:15 +0000 Subject: [PATCH 012/570] Update comments in sqlite3session.h. More to come. FossilOrigin-Name: e73e9082f3b14088752717193a10dd7657deb8af --- ext/session/sqlite3session.h | 252 +++++++++++++++++++++++++++++++---- install-sh | 0 manifest | 30 ++--- manifest.uuid | 2 +- test/progress.test | 0 tool/mkopts.tcl | 0 6 files changed, 239 insertions(+), 45 deletions(-) mode change 100755 => 100644 install-sh mode change 100644 => 100755 test/progress.test mode change 100644 => 100755 tool/mkopts.tcl diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 573b2ff3fc..9cf7cda488 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -18,7 +18,7 @@ typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; ** Create a new session object attached to database handle db. If successful, ** a pointer to the new object is written to *ppSession and SQLITE_OK is ** returned. If an error occurs, *ppSession is set to NULL and an SQLite -** error code (e.g. [SQLITE_NOMEM]) is returned. +** error code (e.g. SQLITE_NOMEM) is returned. ** ** It is possible to create multiple session objects attached to a single ** database handle. @@ -64,6 +64,9 @@ void sqlite3session_delete(sqlite3_session *pSession); ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When ** disabled - it does not. A newly created session object is enabled. +** Refer to the documentation for [sqlite3session_changeset()] for further +** details regarding how enabling and disabling a session object affects +** the eventual changesets. ** ** Passing zero to this function disables the session. Passing a value ** greater than zero enables it. Passing a value less than zero is a @@ -76,11 +79,21 @@ int sqlite3session_enable(sqlite3_session *pSession, int bEnable); /* ** Attach a table to a session. All subsequent changes made to the table -** while the session object is enabled will be recorded. +** while the session object is enabled will be recorded. See documentation +** for [sqlite3session_changeset()] for further details. ** -** Only tables that have a PRIMARY KEY defined may be attached. It does -** not matter if the PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) -** or not. +** Changes can only be recorded for tables that have a PRIMARY KEY explicitly +** defined as part of their CREATE TABLE statement. It does not matter if the +** PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) or not. The PRIMARY +** KEY may consist of a single column, or may be a composite key. +** +** It is not an error if the named table does not exist in the database. Nor +** is it an error if the named table does not have a PRIMARY KEY. However, +** no changes will be recorded in either of these scenarios. +** +** SQLITE_OK is returned if the table is successfully attached to the session +** object. Or, if an error occurs, an SQLite error code (e.g. SQLITE_NOMEM) +** is returned. */ int sqlite3session_attach( sqlite3_session *pSession, /* Session object */ @@ -95,9 +108,77 @@ int sqlite3session_attach( ** SQLITE_OK. If an error occurs, set both *ppChangeset and *pnChangeset to ** zero and return an SQLite error code. ** +** A changeset consists of zero or more INSERT, UPDATE and/or DELETE changes, +** each representing a change to a single row of an attached table. An INSERT +** change contains the values of each field of a new database row. A DELETE +** contains the original values of each field of a deleted database row. An +** UPDATE change contains the original values of each field of an updated +** database row along with the updated values for each updated non-primary-key +** column. It is not possible for an UPDATE change to represent a change that +** modifies the values of primary key columns. If such a change is made, it +** is represented in a changeset as a DELETE followed by an INSERT. +** +** The contents of a changeset may be traversed using an iterator created +** using the [sqlite3changeset_start()] API. A changeset may be applied to +** a database with a compatible schema using the [sqlite3changset_apply()] +** API. +** ** Following a successful call to this function, it is the responsibility of ** the caller to eventually free the buffer that *ppChangeset points to using ** [sqlite3_free()]. +** +**

Changeset Generation

+** +** Once a table has been attached to a session object, the session object +** records the primary key values of all new rows inserted into the table. +** It also records the original primary key and other column values of any +** deleted or updated rows. For each unique primary key value, data is only +** recorded once - the first time a row with said primary key is inserted, +** updated or deleted in the lifetime of the session. +** +** The session object therefore accumulates two types of records - those +** that consist of primary key values only (created when the user inserts +** a new record) and those that consist of the primary key values and the +** original values of other table columns (created when the users deletes +** or updates a record). +** +** When this function is called, the requested changeset is created using +** both the accumulated records and the current contents of the database +** file. Specifically: +** +**
    +**
  • For each record generated by an insert, the database is queried +** for a row with a matching primary key. If one is found, an INSERT +** change is added to the changeset. If no such row is found, no change +** is added to the changeset. +** +**
  • For each record generated by an update or delete, the database is +** queried for a row with a matching primary key. If such a row is +** found and one or more of the non-primary key fields have been +** modified from their original values, an UPDATE change is added to +** the changeset. Or, if no such row is found in the table, a DELETE +** change is added to the changeset. If there is a row with a matching +** primary key in the database, but all fields contain their original +** values, no change is added to the changeset. +**
+** +** This means, amongst other things, that if a row is inserted and then later +** deleted while a session object is active, neither the insert or the delete +** will be present in the changeset. Or if a row is deleted and then later a +** row with the same primary key values inserted while a session object is +** active, the resulting changeset will contain an UPDATE change instead of +** a DELETE and an INSERT. +** +** When a session object is disabled (see the [sqlite3session_enable()] API), +** it does not accumulate records when rows are inserted, updated or deleted. +** This may appear to have some counter-intuitive effects if a single row +** is written to more than once during a session. For example, if a row +** is inserted while a session object is enabled, then later deleted while +** the same session object is disabled, no INSERT record will appear in the +** changeset, even though the delete took place while the session was disabled. +** Or, if one field of a row is updated while a session is disabled, and +** another field of the same row is updated while the session is enabled, the +** resulting changeset will contain an UPDATE change that updates both fields. */ int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ @@ -107,27 +188,73 @@ int sqlite3session_changeset( /* ** Create an iterator used to iterate through the contents of a changeset. +** If successful, *pp is set to point to the iterator handle and SQLITE_OK +** is returned. Otherwise, if an error occurs, *pp is set to zero and an +** SQLite error code is returned. +** +** The following functions can be used to advance and query a changeset +** iterator created by this function: +** +**
    +**
  • [sqlite3changeset_next()] +**
  • [sqlite3changeset_op()] +**
  • [sqlite3changeset_new()] +**
  • [sqlite3changeset_old()] +**
+** +** It is the responsibility of the caller to eventually destroy the iterator +** by passing it to [sqlite3changeset_finalize()]. The buffer containing the +** changeset (pChangeset) must remain valid until after the iterator is +** destroyed. */ int sqlite3changeset_start( - sqlite3_changeset_iter **ppIter, - int nChangeset, - void *pChangeset + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ + int nChangeset, /* Size of changeset blob in bytes */ + void *pChangeset /* Pointer to blob containing changeset */ ); /* -** Advance an iterator created by sqlite3changeset_start() to the next -** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE -** or SQLITE_CORRUPT. +** This function may only be used with iterators created by function +** [sqlite3changeset_start()]. If it is called on an iterator passed to +** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE +** is returned and the call has no effect. ** -** This function may not be called on iterators passed to a conflict handler -** callback by changeset_apply(). +** Immediately after an iterator is created by sqlite3changeset_start(), it +** does not point to any change in the changeset. Assuming the changeset +** is not empty, the first call to this function advances the iterator to +** point to the first change in the changeset. Each subsequent call advances +** the iterator to point to the next change in the changeset (if any). If +** no error occurs and the iterator points to a valid change after a call +** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned. +** Otherwise, if all changes in the changeset have already been visited, +** SQLITE_DONE is returned. +** +** If an error occurs, an SQLite error code is returned. Possible error +** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or +** SQLITE_NOMEM. */ int sqlite3changeset_next(sqlite3_changeset_iter *pIter); /* -** The following three functions extract information on the current change -** from a changeset iterator. They may only be called after changeset_next() -** has returned SQLITE_ROW. +** The pIter argument passed to this function may either be an iterator +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +** created by [sqlite3changeset_start()]. In the latter case, the most recent +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. If this +** is not the case, this function returns SQLITE_MISUSE. +** +** If argument pzTab is not NULL, then *pzTab is set to point to a +** nul-terminated utf-8 encoded string containing the name of the table +** affected by the current change. The buffer remains valid until either +** sqlite3changeset_next() is called on the iterator or until the +** conflict-handler function returns. If pnCol is not NULL, then *pnCol is +** set to the number of columns in the table affected by the change. Finally, +** if pOp is not NULL, then *pOp is set to one of SQLITE_INSERT, SQLITE_DELETE +** or SQLITE_UPDATE, depending on the type of change that the iterator +** currently points to. +** +** If no error occurs, SQLITE_OK is returned. If an error does occur, an +** SQLite error code is returned. The values of the output variables may not +** be trusted in this case. */ int sqlite3changeset_op( sqlite3_changeset_iter *pIter, /* Iterator object */ @@ -135,11 +262,60 @@ int sqlite3changeset_op( int *pnCol, /* OUT: Number of columns in table */ int *pOp /* OUT: SQLITE_INSERT, DELETE or UPDATE */ ); + +/* +** The pIter argument passed to this function may either be an iterator +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +** created by [sqlite3changeset_start()]. In the latter case, the most recent +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. +** Furthermore, it may only be called if the type of change that the iterator +** currently points to is either SQLITE_DELETE or SQLITE_UPDATE. Otherwise, +** this function returns SQLITE_MISUSE and sets *ppValue to NULL. +** +** Argument iVal must be greater than or equal to 0, and less than the number +** of columns in the table affected by the current change. Otherwise, +** SQLITE_RANGE is returned and *ppValue is set to NULL. +** +** If successful, this function sets *ppValue to point to a protected +** sqlite3_value object containing the iVal'th value from the vector of +** original row values stored as part of the UPDATE or DELETE change and +** returns SQLITE_OK. The name of the function comes from the fact that this +** is similar to the "old.*" columns available to update or delete triggers. +** +** If some other error occurs (e.g. an OOM condition), an SQLite error code +** is returned and *ppValue is set to NULL. +*/ int sqlite3changeset_old( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int iVal, /* Column number */ sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ ); + +/* +** The pIter argument passed to this function may either be an iterator +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +** created by [sqlite3changeset_start()]. In the latter case, the most recent +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. +** Furthermore, it may only be called if the type of change that the iterator +** currently points to is either SQLITE_UPDATE or SQLITE_INSERT. Otherwise, +** this function returns SQLITE_MISUSE and sets *ppValue to NULL. +** +** Argument iVal must be greater than or equal to 0, and less than the number +** of columns in the table affected by the current change. Otherwise, +** SQLITE_RANGE is returned and *ppValue is set to NULL. +** +** If successful, this function sets *ppValue to point to a protected +** sqlite3_value object containing the iVal'th value from the vector of +** new row values stored as part of the UPDATE or INSERT change and +** returns SQLITE_OK. If the change is an UPDATE and does not include +** a new value for the requested column, *ppValue is set to NULL and +** SQLITE_OK returned. The name of the function comes from the fact that +** this is similar to the "new.*" columns available to update or delete +** triggers. +** +** If some other error occurs (e.g. an OOM condition), an SQLite error code +** is returned and *ppValue is set to NULL. +*/ int sqlite3changeset_new( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int iVal, /* Column number */ @@ -147,13 +323,23 @@ int sqlite3changeset_new( ); /* -** This function is only usable with sqlite3_changeset_iter objects passed -** to the xConflict callback by sqlite3changeset_apply(). It cannot be used -** with iterators created using sqlite3changeset_start(). +** This function should only be used with iterator objects passed to a +** conflict-handler callback by [sqlite3changeset_apply()] with either +** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this function +** is called on any other iterator, SQLITE_MISUSE is returned and *ppValue +** is set to NULL. ** -** It is used to access the "conflicting row" information available to the -** conflict handler if the second argument is either SQLITE_CHANGESET_DATA -** or SQLITE_CHANGESET_CONFLICT. +** Argument iVal must be greater than or equal to 0, and less than the number +** of columns in the table affected by the current change. Otherwise, +** SQLITE_RANGE is returned and *ppValue is set to NULL. +** +** If successful, this function sets *ppValue to point to a protected +** sqlite3_value object containing the iVal'th value from the +** "conflicting row" associated with the current conflict-handler callback +** and returns SQLITE_OK. +** +** If some other error occurs (e.g. an OOM condition), an SQLite error code +** is returned and *ppValue is set to NULL. */ int sqlite3changeset_conflict( sqlite3_changeset_iter *pIter, /* Changeset iterator */ @@ -165,8 +351,26 @@ int sqlite3changeset_conflict( /* ** Finalize an iterator allocated with sqlite3changeset_start(). ** -** This function may not be called on iterators passed to a conflict handler -** callback by changeset_apply(). +** This function should only be called on iterators created using the +** [sqlite3changeset_start()] function. If an application calls this +** function with an iterator passed to a conflict-handler by +** [sqlite3changeset_apply()], SQLITE_MISUSE is immediately returned and the +** call has no effect. +** +** If an error was encountered within a call to an sqlite3changeset_xxx() +** function (for example an SQLITE_CORRUPT in sqlite3changeset_next() or an +** SQLITE_NOMEM in sqlite3changeset_new()) then an error code corresponding +** to that error is returned by this function. Otherwise, SQLITE_OK is +** returned. This is to allow the following pattern (pseudo-code): +** +** sqlite3changeset_start(); +** while( SQLITE_ROW==sqlite3changeset_next() ){ +** // Do something with change. +** } +** rc = sqlite3changeset_finalize(); +** if( rc!=SQLITE_OK ){ +** // An error has occurred +** } */ int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); diff --git a/install-sh b/install-sh old mode 100755 new mode 100644 diff --git a/manifest b/manifest index 212e1e9851..a137b38bb3 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Merge\sall\sthe\slatest\strunk\senhancements\sinto\sthe\ssessions\sbranch. -D 2011-03-18T12:35:36.113 +C Update\scomments\sin\ssqlite3session.h.\sMore\sto\scome. +D 2011-03-18T13:05:15 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -103,9 +100,9 @@ F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/sqlite3session.c 4183792547af5b5d3ec1c8a3f858beb172682503 -F ext/session/sqlite3session.h 63045871564085669b5cb1fb92e6efc2e1b1120a +F ext/session/sqlite3session.h 3e342facbb95589dfba34545df383df68cc44ebf F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 -F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x +F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk ae0868e05c76eaa8a0ae3d6927a949b1c8e810d7 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a @@ -608,7 +605,7 @@ F test/permutations.test 5b2a4cb756ffb2407cb4743163668d1d769febb6 F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea -F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 +F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota.test ddafe133653093eb9a99ccd6264884ae43f9c9b8 @@ -896,7 +893,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309 -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e +F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff @@ -921,14 +918,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 6614cfcb9c41da71ddec3c44a3de0d4d849e1cdd 54bacb95dd6e2d6ac4971391a40484ccb9126d29 -R e54868c8ee7f58a0691b9e0694987cf6 -U drh -Z 8149dc4ff84780eb7c2d29113d1dc5ec ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFNg1GboxKgR168RlERAptpAJ4+cfNBHl8w0y578KOanLZsuj14mgCffUXp -W65/Ci2dAe+flL3fcPt3X+4= -=uYuP ------END PGP SIGNATURE----- +P 94fd5bb6da5ef4d850c2ed4ad38afabc5569dae6 +R eb9573de7a3fa964ba524a7a8e9a976a +U dan +Z f742ca024227ec41f9ba4edac43a23a5 diff --git a/manifest.uuid b/manifest.uuid index 2d0f8d52c6..d587d908a1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -94fd5bb6da5ef4d850c2ed4ad38afabc5569dae6 \ No newline at end of file +e73e9082f3b14088752717193a10dd7657deb8af \ No newline at end of file diff --git a/test/progress.test b/test/progress.test old mode 100644 new mode 100755 diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100644 new mode 100755 From ea022cffdd9e81e9bf52761e923e0e95a32624bc Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 Mar 2011 15:13:31 +0000 Subject: [PATCH 013/570] Fix a memory allocation issues in the preupdate hook so that the hook.test script runs clean in valgrind. FossilOrigin-Name: bd94f4c8b1c4590c437030f0122015f1a37e2582 --- install-sh | 0 manifest | 30 ++++++++++++++++++++---------- manifest.uuid | 2 +- src/vdbeaux.c | 5 ++--- test/progress.test | 0 tool/mkopts.tcl | 0 6 files changed, 23 insertions(+), 14 deletions(-) mode change 100644 => 100755 install-sh mode change 100755 => 100644 test/progress.test mode change 100755 => 100644 tool/mkopts.tcl diff --git a/install-sh b/install-sh old mode 100644 new mode 100755 diff --git a/manifest b/manifest index a137b38bb3..47e7037226 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,8 @@ -C Update\scomments\sin\ssqlite3session.h.\sMore\sto\scome. -D 2011-03-18T13:05:15 +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +C Fix\sa\smemory\sallocation\sissues\sin\sthe\spreupdate\shook\sso\sthat\sthe\shook.test\nscript\sruns\sclean\sin\svalgrind. +D 2011-03-18T15:13:31.545 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -102,7 +105,7 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/sqlite3session.c 4183792547af5b5d3ec1c8a3f858beb172682503 F ext/session/sqlite3session.h 3e342facbb95589dfba34545df383df68cc44ebf F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 -F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 +F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk ae0868e05c76eaa8a0ae3d6927a949b1c8e810d7 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a @@ -238,7 +241,7 @@ F src/vdbe.c 94cd191b1b20b0124e09b056bbce3d09f79821b3 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 20d13da932eed0667a2e2383a9cb0f80099a5fd3 F src/vdbeapi.c 988ee9420acf8c130d644e6d7282893efe927bbd -F src/vdbeaux.c ce48afec3f218b755f7b0ef1bef54a4be44cd833 +F src/vdbeaux.c bb194e1250a0e35e3a5e17e51631da858e23930a F src/vdbeblob.c 18955f0ee6b133cd08e1592010cb9a6b11e9984c F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -605,7 +608,7 @@ F test/permutations.test 5b2a4cb756ffb2407cb4743163668d1d769febb6 F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea -F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x +F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota.test ddafe133653093eb9a99ccd6264884ae43f9c9b8 @@ -893,7 +896,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309 -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x +F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff @@ -918,7 +921,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 94fd5bb6da5ef4d850c2ed4ad38afabc5569dae6 -R eb9573de7a3fa964ba524a7a8e9a976a -U dan -Z f742ca024227ec41f9ba4edac43a23a5 +P e73e9082f3b14088752717193a10dd7657deb8af +R 150a0d4d8ebf26c7dc0eae89afa852c9 +U drh +Z f580a5a873ab613c2a5bfc6ce81e4e03 +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.6 (GNU/Linux) + +iD8DBQFNg3aeoxKgR168RlERAnluAJ9mJTScCzmLzWj8hzyPNreCvcU53ACcDZ+U +AOCmfmp9NGd52IWhvYcR1co= +=4fKC +-----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index d587d908a1..8974aa69db 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e73e9082f3b14088752717193a10dd7657deb8af \ No newline at end of file +bd94f4c8b1c4590c437030f0122015f1a37e2582 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 97026b89fd..094c4d3a7b 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2812,7 +2812,7 @@ UnpackedRecord *sqlite3VdbeRecordUnpack( pMem->enc = pKeyInfo->enc; pMem->db = pKeyInfo->db; pMem->flags = 0; - pMem->zMalloc = 0; + pMem->zMalloc = pMem->z = 0; d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); pMem++; u++; @@ -3219,7 +3219,6 @@ void sqlite3VdbePreUpdateHook( for(i=0; inField; i++){ sqlite3VdbeMemRelease(&preupdate.aNew[i]); } - sqlite3_free(preupdate.aNew); + sqlite3DbFree(db, preupdate.aNew); } } - diff --git a/test/progress.test b/test/progress.test old mode 100755 new mode 100644 diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100755 new mode 100644 From 2635a3be20c3800ebea63b6f04c3d377d2caff2c Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 18 Mar 2011 16:13:53 +0000 Subject: [PATCH 014/570] Further improvements to documentation in sqlite3session.h. FossilOrigin-Name: 07019bb9e8d8f2445d1e0342f74ab520e9804cb5 --- ext/session/sqlite3session.h | 163 +++++++++++++++++++++++++++++++---- install-sh | 0 manifest | 30 +++---- manifest.uuid | 2 +- test/progress.test | 0 tool/mkopts.tcl | 0 6 files changed, 159 insertions(+), 36 deletions(-) mode change 100755 => 100644 install-sh mode change 100644 => 100755 test/progress.test mode change 100644 => 100755 tool/mkopts.tcl diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 9cf7cda488..dd0e114f73 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -375,7 +375,24 @@ int sqlite3changeset_conflict( int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); /* -** Invert a changeset object. +** This function is used to "invert" a changeset object. Applying an inverted +** changeset to a database reverses the effects of applying the uninverted +** changeset. Specifically: +** +**
    +**
  • Each DELETE change is changed to an INSERT, and +**
  • Each INSERT change is changed to a DELETE, and +**
  • For each UPDATE change, the old.* and new.* values are exchanged. +**
+** +** If successful, a pointer to a buffer containing the inverted changeset +** is stored in *ppOut, the size of the same buffer is stored in *pnOut, and +** SQLITE_OK is returned. If an error occurs, both *pnOut and *ppOut are +** zeroed and an SQLite error code returned. +** +** It is the responsibility of the caller to eventually call sqlite3_free() +** on the *ppOut pointer to free the buffer allocation following a successful +** call to this function. */ int sqlite3changeset_invert( int nIn, void *pIn, /* Input changeset */ @@ -383,12 +400,124 @@ int sqlite3changeset_invert( ); /* -** Apply a changeset to a database. +** Apply a changeset to a database. This function attempts to update the +** "main" database attached to handle db with the changes found in the +** changeset passed via the second and third arguments. +** +** For each change in the changeset, this function tests that the target +** database contains a compatible table. A table is considered compatible +** if all of the following are true: +** +**
    +**
  • The table has the same name as the name recorded in the +** changeset, and +**
  • The table has the same number of columns as recorded in the +** changeset, and +**
  • The table has primary key columns in the same position as +** recorded in the changeset. +**
+** +** If there is no compatible table, it is not an error, but the change is +** not applied. A warning message is issued via the sqlite3_log() mechanism +** with the error code SQLITE_SCHEMA. At most one such warning is issued for +** each table in the changeset. +** +** Otherwise, if there is a compatible table, an attempt is made to modify +** the table contents according to the UPDATE, INSERT or DELETE change. +** If a change cannot be applied cleanly, the conflict handler function +** passed as the fourth argument to sqlite3changeset_apply() may be invoked. +** A description of exactly when the conflict handler is invoked for each +** type of change is below. +** +** Each time the conflict handler function is invoked, it must return one +** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or +** [SQLITE_CHANGESET_REPLACE]. SQLITE_CHANGESET_REPLACE may only be returned +** if the second argument passed to the conflict handler is either +** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If the conflict-handler +** returns an illegal value, any changes already made are rolled back and +** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different +** actions are taken by sqlite3changeset_apply() depending on the value +** returned by each invocation of the conflict-handler function. Refer to +** the documentation for the three +** [SQLITE_CHANGESET_OMIT|available return values] for details. +** +**
+**
DELETE Changes
+** For each DELETE change, this function checks if the target database +** contains a row with the same primary key value (or values) as the +** original row values stored in the changeset. If it does, and the values +** stored in all non-primary key columns also match the values stored in +** the changeset the row is deleted from the target database. +** +** If a row with matching primary key values is found, but one or more of +** the non-primary key fields contains a value different from the original +** row value stored in the changeset, the conflict-handler function is +** invoked with [SQLITE_CHANGESET_DATA] as the second argument. +** +** If no row with matching primary key values is found in the database, +** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] +** passed as the second argument. +** +** If the DELETE operation is attempted, but SQLite returns SQLITE_CONSTRAINT +** (which can only happen if a foreign key constraint is violated), the +** conflict-handler function is invoked with [SQLITE_CHANGESET_CONSTRAINT] +** passed as the second argument. This includes the case where the DELETE +** operation is attempted because an earlier call to the conflict handler +** function returned [SQLITE_CHANGESET_REPLACE]. +** +**
INSERT Changes
+** For each INSERT change, an attempt is made to insert the new row into +** the database. +** +** If the attempt to insert the row fails because the database already +** contains a row with the same primary key values, the conflict handler +** function is invoked with the second argument set to +** [SQLITE_CHANGESET_CONFLICT]. +** +** If the attempt to insert the row fails because of some other constraint +** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is +** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT]. +** This includes the case where the INSERT operation is re-attempted because +** an earlier call to the conflict handler function returned +** [SQLITE_CHANGESET_REPLACE]. +** +**
UPDATE Changes
+** For each DELETE change, this function checks if the target database +** contains a row with the same primary key value (or values) as the +** original row values stored in the changeset. If it does, and the values +** stored in all non-primary key columns also match the values stored in +** the changeset the row is updated within the target database. +** +** If a row with matching primary key values is found, but one or more of +** the non-primary key fields contains a value different from an original +** row value stored in the changeset, the conflict-handler function is +** invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since +** UPDATE changes only contain values for non-primary key fields that are +** to be modified, only those fields need to match the original values to +** avoid the SQLITE_CHANGESET_DATA conflict-handler callback. +** +** If no row with matching primary key values is found in the database, +** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] +** passed as the second argument. +** +** If the UPDATE operation is attempted, but SQLite returns +** SQLITE_CONSTRAINT, the conflict-handler function is invoked with +** [SQLITE_CHANGESET_CONSTRAINT] passed as the second argument. +** This includes the case where the UPDATE operation is attempted after +** an earlier call to the conflict handler function returned +** [SQLITE_CHANGESET_REPLACE]. +**
** ** It is safe to execute SQL statements, including those that write to the ** table that the callback related to, from within the xConflict callback. ** This can be used to further customize the applications conflict ** resolution strategy. +** +** All changes made by this function are enclosed in a savepoint transaction. +** If any other error (aside from a constraint failure when attempting to +** write to the target database) occurs, then the savepoint transaction is +** rolled back, restoring the target database to its original state, and an +** SQLite error code returned. */ int sqlite3changeset_apply( sqlite3 *db, /* Apply change to "main" db of this handle */ @@ -403,9 +532,10 @@ int sqlite3changeset_apply( ); /* -** Values passed as the second argument to a conflict-handler. +** Values that may be passed as the second argument to a conflict-handler. ** -** SQLITE_CHANGESET_DATA: +**
+**
SQLITE_CHANGESET_DATA
** The conflict handler is invoked with CHANGESET_DATA as the second argument ** when processing a DELETE or UPDATE change if a row with the required ** PRIMARY KEY fields is present in the database, but one or more other @@ -415,7 +545,7 @@ int sqlite3changeset_apply( ** The conflicting row, in this case, is the database row with the matching ** primary key. ** -** SQLITE_CHANGESET_NOTFOUND: +**
SQLITE_CHANGESET_NOTFOUND
** The conflict handler is invoked with CHANGESET_NOTFOUND as the second ** argument when processing a DELETE or UPDATE change if a row with the ** required PRIMARY KEY fields is not present in the database. @@ -423,21 +553,22 @@ int sqlite3changeset_apply( ** There is no conflicting row in this case. The results of invoking the ** sqlite3changeset_conflict() API are undefined. ** -** SQLITE_CHANGESET_CONFLICT: +**
SQLITE_CHANGESET_CONFLICT
** CHANGESET_CONFLICT is passed as the second argument to the conflict -** handler while processing an UPDATE or an INSERT if the operation would -** result in duplicate primary key values. +** handler while processing an INSERT change if the operation would result +** in duplicate primary key values. ** ** The conflicting row in this case is the database row with the matching ** primary key. ** -** SQLITE_CHANGESET_CONSTRAINT: +**
SQLITE_CHANGESET_CONSTRAINT
** If any other constraint violation occurs while applying a change (i.e. ** a FOREIGN KEY, UNIQUE, CHECK or NOT NULL constraint), the conflict ** handler is invoked with CHANGESET_CONSTRAINT as the second argument. ** ** There is no conflicting row in this case. The results of invoking the ** sqlite3changeset_conflict() API are undefined. +**
*/ #define SQLITE_CHANGESET_DATA 1 #define SQLITE_CHANGESET_NOTFOUND 2 @@ -447,12 +578,13 @@ int sqlite3changeset_apply( /* ** Valid return values from a conflict-handler. ** -** SQLITE_CHANGESET_OMIT: +**
+**
SQLITE_CHANGESET_OMIT
** If a conflict handler returns this value no special action is taken. The -** change is not applied. The session module continues to the next change -** in the changeset. +** change that caused the conflict is not applied. The session module +** continues to the next change in the changeset. ** -** SQLITE_CHANGESET_REPLACE: +**
SQLITE_CHANGESET_REPLACE
** This value may only be returned if the second argument to the conflict ** handler was SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this ** is not the case, any changes applied so far are rolled back and the @@ -467,9 +599,10 @@ int sqlite3changeset_apply( ** second attempt to apply the change is made. If this second attempt fails, ** the original row is restored to the database before continuing. ** -** SQLITE_CHANGESET_ABORT: +**
SQLITE_CHANGESET_ABORT
** If this value is returned, any changes applied so far are rolled back -** and the call to sqlite3changeset_apply() returns SQLITE_MISUSE. +** and the call to sqlite3changeset_apply() returns SQLITE_ABORT. +**
*/ #define SQLITE_CHANGESET_OMIT 0 #define SQLITE_CHANGESET_REPLACE 1 diff --git a/install-sh b/install-sh old mode 100755 new mode 100644 diff --git a/manifest b/manifest index 47e7037226..f680f79bca 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Fix\sa\smemory\sallocation\sissues\sin\sthe\spreupdate\shook\sso\sthat\sthe\shook.test\nscript\sruns\sclean\sin\svalgrind. -D 2011-03-18T15:13:31.545 +C Further\simprovements\sto\sdocumentation\sin\ssqlite3session.h. +D 2011-03-18T16:13:53 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -103,9 +100,9 @@ F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/sqlite3session.c 4183792547af5b5d3ec1c8a3f858beb172682503 -F ext/session/sqlite3session.h 3e342facbb95589dfba34545df383df68cc44ebf +F ext/session/sqlite3session.h 9551c002efd5fde07c52994c6b592308e0df2d6a F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 -F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x +F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk ae0868e05c76eaa8a0ae3d6927a949b1c8e810d7 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a @@ -608,7 +605,7 @@ F test/permutations.test 5b2a4cb756ffb2407cb4743163668d1d769febb6 F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea -F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 +F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota.test ddafe133653093eb9a99ccd6264884ae43f9c9b8 @@ -896,7 +893,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309 -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e +F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff @@ -921,14 +918,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P e73e9082f3b14088752717193a10dd7657deb8af -R 150a0d4d8ebf26c7dc0eae89afa852c9 -U drh -Z f580a5a873ab613c2a5bfc6ce81e4e03 ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFNg3aeoxKgR168RlERAnluAJ9mJTScCzmLzWj8hzyPNreCvcU53ACcDZ+U -AOCmfmp9NGd52IWhvYcR1co= -=4fKC ------END PGP SIGNATURE----- +P bd94f4c8b1c4590c437030f0122015f1a37e2582 +R fb83d41281a4d5ba8505f15c6f6b6372 +U dan +Z ff00d37e3af9047c8539a141cf64a629 diff --git a/manifest.uuid b/manifest.uuid index 8974aa69db..c2dbebadb1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bd94f4c8b1c4590c437030f0122015f1a37e2582 \ No newline at end of file +07019bb9e8d8f2445d1e0342f74ab520e9804cb5 \ No newline at end of file diff --git a/test/progress.test b/test/progress.test old mode 100644 new mode 100755 diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100644 new mode 100755 From 304637c026622adf6354f295e7c298ad7c04ae68 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 Mar 2011 16:47:27 +0000 Subject: [PATCH 015/570] Fixes for compiler warnings. Minor code cleanup. FossilOrigin-Name: 9604d13001e0a195718c7f03fc0e73e352226caa --- install-sh | 0 manifest | 36 +++++++++++++++++++++++------------- manifest.uuid | 2 +- src/sqliteInt.h | 1 - src/tclsqlite.c | 34 +++++++++++++++++++--------------- src/vdbeapi.c | 3 +-- src/vdbeaux.c | 5 +++-- test/progress.test | 0 tool/mkopts.tcl | 0 9 files changed, 47 insertions(+), 34 deletions(-) mode change 100644 => 100755 install-sh mode change 100755 => 100644 test/progress.test mode change 100755 => 100644 tool/mkopts.tcl diff --git a/install-sh b/install-sh old mode 100644 new mode 100755 diff --git a/manifest b/manifest index f680f79bca..ad7e4b5e21 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,8 @@ -C Further\simprovements\sto\sdocumentation\sin\ssqlite3session.h. -D 2011-03-18T16:13:53 +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +C Fixes\sfor\scompiler\swarnings.\s\sMinor\scode\scleanup. +D 2011-03-18T16:47:27.202 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -102,7 +105,7 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/sqlite3session.c 4183792547af5b5d3ec1c8a3f858beb172682503 F ext/session/sqlite3session.h 9551c002efd5fde07c52994c6b592308e0df2d6a F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 -F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 +F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk ae0868e05c76eaa8a0ae3d6927a949b1c8e810d7 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a @@ -183,11 +186,11 @@ F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 4a5e0ad845475c84881f0b25b1abba2ddaab0a72 F src/sqlite.h.in 208dc372c9b8d89ca962babcb7cb0c1b16d32bc4 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h d65b832eb82bd3f04cd27a750698c7f4b3d9273a +F src/sqliteInt.h e427f9cff8fcf85ea23f95eb8b70e4b588d24212 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e -F src/tclsqlite.c fc0321c62a3c3929b9b0659b94b7d37bac84e769 +F src/tclsqlite.c 520e124994e68fd8804ade95b5d3e2e791d0958d F src/test1.c 9020310c7617234b33fd1c3064f89524db25f290 F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc @@ -237,8 +240,8 @@ F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f F src/vdbe.c 94cd191b1b20b0124e09b056bbce3d09f79821b3 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 20d13da932eed0667a2e2383a9cb0f80099a5fd3 -F src/vdbeapi.c 988ee9420acf8c130d644e6d7282893efe927bbd -F src/vdbeaux.c bb194e1250a0e35e3a5e17e51631da858e23930a +F src/vdbeapi.c 0e53620e9a4889257eece201d517163d3093ee41 +F src/vdbeaux.c 9807ae2e6974172b1d7b077327f862f6bd4dda2a F src/vdbeblob.c 18955f0ee6b133cd08e1592010cb9a6b11e9984c F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -605,7 +608,7 @@ F test/permutations.test 5b2a4cb756ffb2407cb4743163668d1d769febb6 F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea -F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x +F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota.test ddafe133653093eb9a99ccd6264884ae43f9c9b8 @@ -893,7 +896,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309 -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x +F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff @@ -918,7 +921,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P bd94f4c8b1c4590c437030f0122015f1a37e2582 -R fb83d41281a4d5ba8505f15c6f6b6372 -U dan -Z ff00d37e3af9047c8539a141cf64a629 +P 07019bb9e8d8f2445d1e0342f74ab520e9804cb5 +R e362c18925cab750a71fcf91528dddfb +U drh +Z 33df56341351167813c56b1a83010bf4 +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.6 (GNU/Linux) + +iD8DBQFNg4yioxKgR168RlERAsv6AJ9WZ1HLGm+YuNBznpVVZgVxxs49RwCdFrGC +OY796dAcZJ0MQ5I3+TprmmI= +=87W+ +-----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index c2dbebadb1..fe2f62ed4f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -07019bb9e8d8f2445d1e0342f74ab520e9804cb5 \ No newline at end of file +9604d13001e0a195718c7f03fc0e73e352226caa \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 9fa4161d2e..cf35f54635 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2748,7 +2748,6 @@ void sqlite3PrngSaveState(void); void sqlite3PrngRestoreState(void); void sqlite3PrngResetState(void); void sqlite3RollbackAll(sqlite3*); -void sqlite3TransactionHook(sqlite3 *, int, int); void sqlite3CodeVerifySchema(Parse*, int); void sqlite3BeginTransaction(Parse*, int); void sqlite3CommitTransaction(Parse*); diff --git a/src/tclsqlite.c b/src/tclsqlite.c index b3f98126c0..092295a2d1 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -1655,12 +1655,12 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ "errorcode", "eval", "exists", "function", "incrblob", "interrupt", "last_insert_rowid", "nullvalue", "onecolumn", - "preupdate", - "profile", "progress", "rekey", - "restore", "rollback_hook", "status", - "timeout", "total_changes", "trace", - "transaction", "unlock_notify", "update_hook", - "version", "wal_hook", 0 + "preupdate", "profile", "progress", + "rekey", "restore", "rollback_hook", + "status", "timeout", "total_changes", + "trace", "transaction", "unlock_notify", + "update_hook", "version", "wal_hook", + 0 }; enum DB_enum { DB_AUTHORIZER, DB_BACKUP, DB_BUSY, @@ -1670,12 +1670,11 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ DB_ERRORCODE, DB_EVAL, DB_EXISTS, DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN, - DB_PREUPDATE, - DB_PROFILE, DB_PROGRESS, DB_REKEY, - DB_RESTORE, DB_ROLLBACK_HOOK, DB_STATUS, - DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, - DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, - DB_VERSION, DB_WAL_HOOK + DB_PREUPDATE, DB_PROFILE, DB_PROGRESS, + DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK, + DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, + DB_TRACE, DB_TRANSACTION, DB_UNLOCK_NOTIFY, + DB_UPDATE_HOOK, DB_VERSION, DB_WAL_HOOK, }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ @@ -2845,6 +2844,12 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ break; } + /* + ** $db preupdate_hook count + ** $db preupdate_hook hook ?SCRIPT? + ** $db preupdate_hook new INDEX + ** $db preupdate_hook old INDEX + */ case DB_PREUPDATE: { static const char *azSub[] = {"count", "hook", "new", "old", 0}; enum DbPreupdateSubCmd { @@ -2895,7 +2900,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ } if( rc==SQLITE_OK ){ - Tcl_Obj *pObj = Tcl_NewStringObj(sqlite3_value_text(pValue), -1); + Tcl_Obj *pObj; + pObj = Tcl_NewStringObj((char*)sqlite3_value_text(pValue), -1); Tcl_SetObjResult(interp, pObj); }else{ Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0); @@ -2915,8 +2921,6 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ case DB_WAL_HOOK: case DB_UPDATE_HOOK: case DB_ROLLBACK_HOOK: { - sqlite3 *db = pDb->db; - /* set ppHook to point at pUpdateHook or pRollbackHook, depending on ** whether [$db update_hook] or [$db rollback_hook] was invoked. */ diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 64cd2191c8..4fde5893b6 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -1439,6 +1439,7 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ goto preupdate_new_out; } } + assert( iIdx>=0 && iIdxpCsr->nField ); pMem = &p->aNew[iIdx]; if( pMem->flags==0 ){ rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); @@ -1452,5 +1453,3 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ sqlite3Error(db, rc, 0); return sqlite3ApiExit(db, rc); } - - diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 094c4d3a7b..368330720d 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2813,6 +2813,7 @@ UnpackedRecord *sqlite3VdbeRecordUnpack( pMem->db = pKeyInfo->db; pMem->flags = 0; pMem->zMalloc = pMem->z = 0; + pMem->z = 0; d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); pMem++; u++; @@ -3187,10 +3188,10 @@ void sqlite3VdbePreUpdateHook( ){ sqlite3 *db = v->db; i64 iKey2; - PreUpdate preupdate; - memset(&preupdate, 0, sizeof(PreUpdate)); + assert( db->pPreUpdate==0 ); + memset(&preupdate, 0, sizeof(PreUpdate)); if( op==SQLITE_UPDATE ){ iKey2 = v->aMem[iReg].u.i; }else{ diff --git a/test/progress.test b/test/progress.test old mode 100755 new mode 100644 diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100755 new mode 100644 From 4c22025225fdef09f13b27fd5d364cd612136066 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 18 Mar 2011 18:03:13 +0000 Subject: [PATCH 016/570] Hold the database mutex for the duration of an sqlite3changeset_apply() call. Also for the duration of all sqlite3session_xxx() calls. FossilOrigin-Name: c615c38c3283e21c33550c093099a793761123a7 --- ext/session/sqlite3session.c | 50 ++++++++++++++++++++++++------------ install-sh | 0 manifest | 30 ++++++++-------------- manifest.uuid | 2 +- test/progress.test | 0 tool/mkopts.tcl | 0 6 files changed, 45 insertions(+), 37 deletions(-) mode change 100755 => 100644 install-sh mode change 100644 => 100755 test/progress.test mode change 100644 => 100755 tool/mkopts.tcl diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 296875052e..64114718de 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -752,7 +752,9 @@ static void xPreUpdate( sqlite3_session *pSession; int nDb = strlen(zDb); int nName = strlen(zDb); - + + assert( sqlite3_mutex_held(db->mutex) ); + for(pSession=(sqlite3_session *)pCtx; pSession; pSession=pSession->pNext){ SessionTable *pTab; @@ -866,28 +868,34 @@ int sqlite3session_attach( ){ SessionTable *pTab; /* New table object (if required) */ int nName; /* Number of bytes in string zName */ + int rc = SQLITE_OK; + + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); /* First search for an existing entry. If one is found, this call is ** a no-op. Return early. */ nName = strlen(zName); for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){ - if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ){ - return SQLITE_OK; + if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ) break; + } + + if( !pTab ){ + /* Allocate new SessionTable object. */ + pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1); + if( !pTab ){ + rc = SQLITE_NOMEM; + }else{ + /* Populate the new SessionTable object and link it into the list. */ + memset(pTab, 0, sizeof(SessionTable)); + pTab->zName = (char *)&pTab[1]; + memcpy(pTab->zName, zName, nName+1); + pTab->pNext = pSession->pTable; + pSession->pTable = pTab; } } - /* Allocate new SessionTable object. */ - pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1); - if( !pTab ) return SQLITE_NOMEM; - - /* Populate the new SessionTable object and link it into the list. */ - memset(pTab, 0, sizeof(SessionTable)); - pTab->zName = (char *)&pTab[1]; - memcpy(pTab->zName, zName, nName+1); - pTab->pNext = pSession->pTable; - pSession->pTable = pTab; - - return SQLITE_OK; + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); + return rc; } /* @@ -1285,6 +1293,8 @@ int sqlite3session_changeset( SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */ int rc; /* Return code */ + sqlite3_mutex_enter(sqlite3_db_mutex(db)); + /* Zero the output variables in case an error occurs. If this session ** object is already in the error state (sqlite3_session.rc != SQLITE_OK), ** this call will be a no-op. */ @@ -1357,6 +1367,8 @@ int sqlite3session_changeset( }else{ sqlite3_free(buf.aBuf); } + + sqlite3_mutex_leave(sqlite3_db_mutex(db)); return rc; } @@ -1364,10 +1376,14 @@ int sqlite3session_changeset( ** Enable or disable the session object passed as the first argument. */ int sqlite3session_enable(sqlite3_session *pSession, int bEnable){ + int ret; + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); if( bEnable>=0 ){ pSession->bEnable = bEnable; } - return pSession->bEnable; + ret = pSession->bEnable; + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); + return ret; } /* @@ -2277,6 +2293,7 @@ int sqlite3changeset_apply( memset(&sApply, 0, sizeof(sApply)); sqlite3changeset_start(&pIter, nChangeset, pChangeset); + sqlite3_mutex_enter(sqlite3_db_mutex(db)); rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){ int nCol; @@ -2366,6 +2383,7 @@ int sqlite3changeset_apply( sqlite3_finalize(sApply.pUpdate); sqlite3_finalize(sApply.pSelect); sqlite3_free(sApply.azCol); + sqlite3_mutex_leave(sqlite3_db_mutex(db)); return rc; } diff --git a/install-sh b/install-sh old mode 100755 new mode 100644 diff --git a/manifest b/manifest index ad7e4b5e21..0bcad83403 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Fixes\sfor\scompiler\swarnings.\s\sMinor\scode\scleanup. -D 2011-03-18T16:47:27.202 +C Hold\sthe\sdatabase\smutex\sfor\sthe\sduration\sof\san\ssqlite3changeset_apply()\scall.\sAlso\sfor\sthe\sduration\sof\sall\ssqlite3session_xxx()\scalls. +D 2011-03-18T18:03:14 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -102,10 +99,10 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/sqlite3session.c 4183792547af5b5d3ec1c8a3f858beb172682503 +F ext/session/sqlite3session.c d4ba709d457a7b184a72ccd3ab07e5a1e9dd9196 F ext/session/sqlite3session.h 9551c002efd5fde07c52994c6b592308e0df2d6a F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 -F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x +F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk ae0868e05c76eaa8a0ae3d6927a949b1c8e810d7 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a @@ -608,7 +605,7 @@ F test/permutations.test 5b2a4cb756ffb2407cb4743163668d1d769febb6 F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea -F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 +F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota.test ddafe133653093eb9a99ccd6264884ae43f9c9b8 @@ -896,7 +893,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309 -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e +F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff @@ -921,14 +918,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 07019bb9e8d8f2445d1e0342f74ab520e9804cb5 -R e362c18925cab750a71fcf91528dddfb -U drh -Z 33df56341351167813c56b1a83010bf4 ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFNg4yioxKgR168RlERAsv6AJ9WZ1HLGm+YuNBznpVVZgVxxs49RwCdFrGC -OY796dAcZJ0MQ5I3+TprmmI= -=87W+ ------END PGP SIGNATURE----- +P 9604d13001e0a195718c7f03fc0e73e352226caa +R 54e501f64ecb85ba88c3d3201e5dcd9b +U dan +Z 255e99dc78fad5aee707e21b8ff77ea9 diff --git a/manifest.uuid b/manifest.uuid index fe2f62ed4f..235b1b6cb5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9604d13001e0a195718c7f03fc0e73e352226caa \ No newline at end of file +c615c38c3283e21c33550c093099a793761123a7 \ No newline at end of file diff --git a/test/progress.test b/test/progress.test old mode 100644 new mode 100755 diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100644 new mode 100755 From 319eeb7b33eb9380924475f799ec66773c7ea953 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Mar 2011 08:38:50 +0000 Subject: [PATCH 017/570] Fix a problem with INTEGER PRIMARY KEY columns and the pre-update hook. FossilOrigin-Name: 24d4d5dd007197a141555bcca6f2ac9ab47cde80 --- install-sh | 0 manifest | 46 ++++++++++++++++++---------------------------- manifest.uuid | 2 +- src/delete.c | 2 +- src/insert.c | 6 +++--- src/update.c | 2 +- src/vdbe.c | 40 +++++++++++++++++++++------------------- src/vdbe.h | 2 ++ src/vdbeInt.h | 5 ++++- src/vdbeapi.c | 14 ++++++++++++-- src/vdbeaux.c | 7 ++++++- test/hook.test | 17 ++++++++++++++++- test/progress.test | 0 tool/mkopts.tcl | 0 14 files changed, 85 insertions(+), 58 deletions(-) mode change 100755 => 100644 install-sh mode change 100644 => 100755 test/progress.test mode change 100644 => 100755 tool/mkopts.tcl diff --git a/install-sh b/install-sh old mode 100755 new mode 100644 diff --git a/manifest b/manifest index a02bffa46b..fffd7c5851 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Merge\sthe\sfix\sto\sticket\s[f7b4edece25c99485]\sinto\sthe\ssessions\sbranch. -D 2011-03-19T02:37:38.712 +C Fix\sa\sproblem\swith\sINTEGER\sPRIMARY\sKEY\scolumns\sand\sthe\spre-update\shook. +D 2011-03-19T08:38:50 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -105,7 +102,7 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/sqlite3session.c d4ba709d457a7b184a72ccd3ab07e5a1e9dd9196 F ext/session/sqlite3session.h 9551c002efd5fde07c52994c6b592308e0df2d6a F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 -F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x +F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk ae0868e05c76eaa8a0ae3d6927a949b1c8e810d7 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a @@ -135,7 +132,7 @@ F src/callback.c 5069f224882cbdccd559f591271d28d7f37745bc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01 F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b -F src/delete.c 3c0925e958a77804a004222baa1a2a8ad855306b +F src/delete.c 122c1a767883c439ad6393d32920152ecb560429 F src/expr.c 00817c672af554321fd67c44325afd7cef0e4648 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 418b840007c873975fd0d071746d952f8bca20ce @@ -144,7 +141,7 @@ F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c b0d4150ae6d6fae7c3e8b69b65bcf37988d80ac0 +F src/insert.c c46747b4bdde2ae4c2815526a151fefb66ba64a6 F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e @@ -233,15 +230,15 @@ F src/test_vfstrace.c f5c3b3b893d81a580d0f577e6d9bcfc1fd496136 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080 F src/trigger.c 95d2ff4b2996fabe886c9764b5978980e29f4afa -F src/update.c aa39db6c39a1e234e8badf49768e1389dbb34650 +F src/update.c ca6d4ad2d87e743d22c47f1a6715cc5abf5cda05 F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685 F src/util.c cd997077bad039efc0597eb027c929658f93c018 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c 3f6d91163b5b7b3d2609bf5f21461d902989cdc5 -F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 -F src/vdbeInt.h 20d13da932eed0667a2e2383a9cb0f80099a5fd3 -F src/vdbeapi.c 0e53620e9a4889257eece201d517163d3093ee41 -F src/vdbeaux.c 9807ae2e6974172b1d7b077327f862f6bd4dda2a +F src/vdbe.c c90edafd941481506f001b17cd8523683fdac853 +F src/vdbe.h edef9c4f0be83e1f1dccd049da37b40e021b63d9 +F src/vdbeInt.h 2cf77c1d151a4a54facd596d52be6d60c1cb26e8 +F src/vdbeapi.c c4692c74b31f4abe638fbcbae3944c52b54e2c36 +F src/vdbeaux.c 0216b2c37509a44c3833b297765bee7bdd04fa2f F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -480,7 +477,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c -F test/hook.test d0a277022888caf75ae1d4ec79917668f2f0f2e6 +F test/hook.test d054aad1a3772dd9045510382875468a9dcae15f F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 @@ -608,7 +605,7 @@ F test/permutations.test 5b2a4cb756ffb2407cb4743163668d1d769febb6 F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea -F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 +F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota.test ddafe133653093eb9a99ccd6264884ae43f9c9b8 @@ -897,7 +894,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309 -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e +F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff @@ -922,14 +919,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P c615c38c3283e21c33550c093099a793761123a7 eedbcf0a0ba91bb8b9cd3d115081ba297e9959fe -R d0ca47f6483ae12a6d0c994e1006aea9 -U drh -Z 5fff78b74e6c376b68b45fceb2b4a735 ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFNhBb2oxKgR168RlERAgoXAKCNG+a12IdNjhU70FvIK6nf6CqkoQCfbtYL -k5XHY8ri1b+IAtTgBjHO+hs= -=5lEb ------END PGP SIGNATURE----- +P 1b736ac2934f2361dee5062e9033cbf26b41fc3a +R 162f72638a0f38fbe0fc1273d5b87dc2 +U dan +Z 3b532fd3ba73ffa805a9d5e7143aadc5 diff --git a/manifest.uuid b/manifest.uuid index a441a6b6ae..e62b7f494c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1b736ac2934f2361dee5062e9033cbf26b41fc3a \ No newline at end of file +24d4d5dd007197a141555bcca6f2ac9ab47cde80 \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index c7a686a8bd..3075df05fc 100644 --- a/src/delete.c +++ b/src/delete.c @@ -542,7 +542,7 @@ void sqlite3GenerateRowDelete( if( pTab->pSelect==0 ){ sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0); sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); - sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); + sqlite3VdbeChangeP4(v, -1, pTab, P4_TABLE); } /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to diff --git a/src/insert.c b/src/insert.c index 85b19ae3f7..cf48d0ffe7 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1291,7 +1291,7 @@ void sqlite3GenerateConstraintChecks( ** OP_Insert replace the existing entry than it is to delete the ** existing entry and then insert a new one. */ sqlite3VdbeAddOp2(v, OP_Delete, baseCur, OPFLAG_ISNOOP); - sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); + sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE); if( pTab->pIndex ){ sqlite3MultiWrite(pParse); sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0); @@ -1481,7 +1481,7 @@ void sqlite3CompleteInsertion( } sqlite3VdbeAddOp3(v, OP_Insert, baseCur, regRec, regRowid); if( !pParse->nested ){ - sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); + sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE); } sqlite3VdbeChangeP5(v, pik_flags); } @@ -1803,7 +1803,7 @@ static int xferOptimization( sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData); sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid); sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); - sqlite3VdbeChangeP4(v, -1, pDest->zName, 0); + sqlite3VdbeChangeP4(v, -1, (char *)pDest, P4_TABLE); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){ diff --git a/src/update.c b/src/update.c index 2c9f246d77..b67c76f5fe 100644 --- a/src/update.c +++ b/src/update.c @@ -503,7 +503,7 @@ void sqlite3Update( regNewRowid ); if( !pParse->nested ){ - sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); + sqlite3VdbeChangeP4(v, -1, pTab, P4_TABLE); } sqlite3VdbeJumpHere(v, j1); diff --git a/src/vdbe.c b/src/vdbe.c index d6cdaaafca..de979b1cbb 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3838,9 +3838,9 @@ case OP_NewRowid: { /* out2-prerelease */ ** is part of an INSERT operation. The difference is only important to ** the update hook. ** -** Parameter P4 may point to a string containing the table-name, or -** may be NULL. If it is not NULL, then the update-hook -** (sqlite3.xUpdateCallback) is invoked following a successful insert. +** Parameter P4 may point to a Table structure, or may be NULL. If it is +** not NULL, then the update-hook (sqlite3.xUpdateCallback) is invoked +** following a successful insert. ** ** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically ** allocated, then ownership of P2 is transferred to the pseudo-cursor @@ -3865,7 +3865,7 @@ case OP_InsertInt: { int nZero; /* Number of zero-bytes to append */ int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */ const char *zDb; /* database name - used by the update hook */ - const char *zTbl; /* Table name - used by the opdate hook */ + Table *pTab; /* Table structure - used by update and pre-update hooks */ int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ pData = &aMem[pOp->p2]; @@ -3876,6 +3876,7 @@ case OP_InsertInt: { assert( pC->pCursor!=0 ); assert( pC->pseudoTableReg==0 ); assert( pC->isTable ); + assert( pOp->p4type==P4_TABLE || pOp->p4type==P4_NOTUSED ); REGISTER_TRACE(pOp->p2, pData); if( pOp->opcode==OP_Insert ){ @@ -3889,20 +3890,20 @@ case OP_InsertInt: { iKey = pOp->p3; } - if( pOp->p4.z && (db->xPreUpdateCallback || db->xUpdateCallback) ){ + if( pOp->p4type==P4_TABLE && (db->xPreUpdateCallback||db->xUpdateCallback) ){ assert( pC->isTable ); assert( pC->iDb>=0 ); zDb = db->aDb[pC->iDb].zName; - zTbl = pOp->p4.z; + pTab = pOp->p4.pTab; op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); } /* Invoke the pre-update hook, if any */ if( db->xPreUpdateCallback - && pOp->p4.z + && pOp->p4type==P4_TABLE && (!(pOp->p5 & OPFLAG_ISUPDATE) || pC->rowidIsValid==0) ){ - sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, zTbl, iKey, pOp->p2); + sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, iKey, pOp->p2); } if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; @@ -3930,7 +3931,7 @@ case OP_InsertInt: { /* Invoke the update-hook if required. */ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ - db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey); + db->xUpdateCallback(db->pUpdateArg, op, zDb, pTab->zName, iKey); } break; } @@ -3950,12 +3951,12 @@ case OP_InsertInt: { ** P1 must not be pseudo-table. It has to be a real table with ** multiple rows. ** -** If P4 is not NULL then, either the update or pre-update hook, or both, -** may be invoked. The P1 cursor must have been positioned using OP_NotFound -** prior to invoking this opcode in this case. Specifically, if one is -** configured, the pre-update hook is invoked if P4 is not NULL. The -** update-hook is invoked if one is configured, P4 is not NULL, and the -** OPFLAG_NCHANGE flag is set in P2. +** If P4 is not NULL then it points to a Table struture. In this case either +** the update or pre-update hook, or both, may be invoked. The P1 cursor must +** have been positioned using OP_NotFound prior to invoking this opcode in +** this case. Specifically, if one is configured, the pre-update hook is +** invoked if P4 is not NULL. The update-hook is invoked if one is configured, +** P4 is not NULL, and the OPFLAG_NCHANGE flag is set in P2. ** ** If the OPFLAG_ISUPDATE flag is set in P2, then P3 contains the address ** of the memory cell that contains the value that the rowid of the row will @@ -3965,7 +3966,7 @@ case OP_Delete: { i64 iKey; VdbeCursor *pC; const char *zDb; - const char *zTbl; + Table *pTab; int opflags; opflags = pOp->p2; @@ -3974,6 +3975,7 @@ case OP_Delete: { pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */ + assert( pOp->p4type==P4_TABLE || pOp->p4type==P4_NOTUSED ); /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or ** OP_Column on the same table without any intervening operations that @@ -3995,7 +3997,7 @@ case OP_Delete: { assert( pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */ iKey = pC->lastRowid; zDb = db->aDb[pC->iDb].zName; - zTbl = pOp->p4.z; + pTab = pOp->p4.pTab; } /* Invoke the pre-update-hook if required. */ @@ -4003,7 +4005,7 @@ case OP_Delete: { assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) ); sqlite3VdbePreUpdateHook(p, pC, (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, - zDb, zTbl, iKey, + zDb, pTab, iKey, pOp->p3 ); } @@ -4019,7 +4021,7 @@ case OP_Delete: { p->nChange++; assert( pOp->p4.z ); if( rc==SQLITE_OK && db->xUpdateCallback ){ - db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey); + db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName,iKey); } } break; diff --git a/src/vdbe.h b/src/vdbe.h index 71c871d52f..2a6fe95fd4 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -61,6 +61,7 @@ struct VdbeOp { KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ int *ai; /* Used when p4type is P4_INTARRAY */ SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ + Table *pTab; /* Used when p4type is P4_TABLE */ } p4; #ifdef SQLITE_DEBUG char *zComment; /* Comment to improve readability */ @@ -116,6 +117,7 @@ typedef struct VdbeOpList VdbeOpList; #define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ #define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */ +#define P4_TABLE (-19) /* P4 is a pointer to a Table structure */ /* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure ** is made. That copy is freed when the Vdbe is finalized. But if the diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 447e025e94..cac88af71e 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -344,6 +344,9 @@ struct PreUpdate { UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ int iNewReg; /* Register for new.* values */ + i64 iKey1; /* First key value passed to hook */ + i64 iKey2; /* Second key value passed to hook */ + int iPKey; /* If not negative index of IPK column */ Mem *aNew; /* Array of new.* values */ }; @@ -404,7 +407,7 @@ void sqlite3VdbeFrameDelete(VdbeFrame*); int sqlite3VdbeFrameRestore(VdbeFrame *); void sqlite3VdbeMemStoreType(Mem *pMem); void sqlite3VdbePreUpdateHook( - Vdbe *, VdbeCursor *, int, const char*, const char*, i64, int); + Vdbe *, VdbeCursor *, int, const char*, Table *, i64, int); #ifdef SQLITE_DEBUG void sqlite3VdbeMemPrepareToChange(Vdbe*,Mem*); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 4fde5893b6..284e565e13 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -1369,6 +1369,9 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ *ppValue = (sqlite3_value *)columnNullValue(); }else{ *ppValue = &p->pUnpacked->aMem[iIdx]; + if( iIdx==p->iPKey ){ + sqlite3VdbeMemSetInt64(*ppValue, p->iKey1); + } sqlite3VdbeMemStoreType(*ppValue); } @@ -1423,6 +1426,9 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ pMem = (sqlite3_value *)columnNullValue(); }else{ pMem = &pUnpack->aMem[iIdx]; + if( iIdx==p->iPKey ){ + sqlite3VdbeMemSetInt64(pMem, p->iKey2); + } sqlite3VdbeMemStoreType(pMem); } }else{ @@ -1442,8 +1448,12 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ assert( iIdx>=0 && iIdxpCsr->nField ); pMem = &p->aNew[iIdx]; if( pMem->flags==0 ){ - rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); - if( rc!=SQLITE_OK ) goto preupdate_new_out; + if( iIdx==p->iPKey ){ + sqlite3VdbeMemSetInt64(pMem, p->iKey2); + }else{ + rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); + if( rc!=SQLITE_OK ) goto preupdate_new_out; + } sqlite3VdbeMemStoreType(pMem); } } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 368330720d..a2526ace20 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3182,13 +3182,14 @@ void sqlite3VdbePreUpdateHook( VdbeCursor *pCsr, /* Cursor to grab old.* values from */ int op, /* SQLITE_INSERT, UPDATE or DELETE */ const char *zDb, /* Database name */ - const char *zTbl, /* Table name */ + Table *pTab, /* Modified table */ i64 iKey1, /* Initial key value */ int iReg /* Register for new.* record */ ){ sqlite3 *db = v->db; i64 iKey2; PreUpdate preupdate; + const char *zTbl = pTab->zName; assert( db->pPreUpdate==0 ); memset(&preupdate, 0, sizeof(PreUpdate)); @@ -3205,6 +3206,10 @@ void sqlite3VdbePreUpdateHook( preupdate.keyinfo.db = db; preupdate.keyinfo.enc = ENC(db); preupdate.keyinfo.nField = pCsr->nField; + preupdate.iKey1 = iKey1; + preupdate.iKey2 = iKey2; + preupdate.iPKey = pTab->iPKey; + db->pPreUpdate = &preupdate; db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); db->pPreUpdate = 0; diff --git a/test/hook.test b/test/hook.test index 001e8ddf4a..9ceedbb75d 100644 --- a/test/hook.test +++ b/test/hook.test @@ -622,7 +622,7 @@ do_execsql_test 7.5.2.0 { ALTER TABLE t8 ADD COLUMN c DEFAULT 'xxx'; } -# At time of writing, these two are broken. They demonstraight that the +# At time of writing, these two are broken. They demonstrate that the # sqlite3_preupdate_old() method does not handle the case where ALTER TABLE # has been used to add a column with a default value other than NULL. # @@ -637,5 +637,20 @@ do_preupdate_test 7.5.2.2 { UPDATE main t8 2 2 three four xxx three five xxx } +# This block of tests verifies that IPK values are correctly reported +# by the sqlite3_preupdate_old() and sqlite3_preupdate_new() functions. +# +do_execsql_test 7.6.1 { CREATE TABLE t9(a, b INTEGER PRIMARY KEY, c) } +do_preupdate_test 7.6.2 { + INSERT INTO t9 VALUES(1, 2, 3); + UPDATE t9 SET b = b+1, c = c+1; + DELETE FROM t9 WHERE a = 1; +} { + INSERT main t9 2 2 1 2 3 + UPDATE main t9 2 3 1 2 3 1 3 4 + DELETE main t9 3 3 1 3 4 +} + + finish_test diff --git a/test/progress.test b/test/progress.test old mode 100644 new mode 100755 diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100644 new mode 100755 From 7cf7df7d35579c9575ded280577b8337efd9c1c5 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Mar 2011 15:37:02 +0000 Subject: [PATCH 018/570] Fix some bugs in sqlite3changeset_apply(). FossilOrigin-Name: 7250318dda542c5bbf28852c1f1d0f3c52ae8f96 --- ext/session/session2.test | 138 +++++++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 34 +++++---- manifest | 18 +++-- manifest.uuid | 2 +- src/test_config.c | 6 ++ test/permutations.test | 9 ++- test/session.test | 18 +++++ 7 files changed, 201 insertions(+), 24 deletions(-) create mode 100644 ext/session/session2.test create mode 100644 test/session.test diff --git a/ext/session/session2.test b/ext/session/session2.test new file mode 100644 index 0000000000..21a457fde9 --- /dev/null +++ b/ext/session/session2.test @@ -0,0 +1,138 @@ +# 2011 Mar 16 +# +# 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. +# +#*********************************************************************** +# +# The focus of this file is testing the session module. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl + +set testprefix session2 + +proc test_reset {} { + catch { db close } + catch { db2 close } + forcedelete test.db test.db2 + sqlite3 db test.db + sqlite3 db2 test.db2 +} + +proc do_common_sql {sql} { + execsql $sql db + execsql $sql db2 +} +proc xConflict args { return "OMIT" } + +proc do_then_apply_sql {sql} { + sqlite3session S db main + db eval {SELECT name FROM sqlite_master WHERE type = 'table'} { + S attach $name + } + + db eval $sql + sqlite3changeset_apply db2 [S changeset] xConflict + S delete +} + +proc do_iterator_test {tn tbl_list sql res} { + sqlite3session S db main + foreach t $tbl_list {S attach $t} + execsql $sql + + set r [list] + foreach v $res { lappend r $v } + + set x [list] + sqlite3session_foreach c [S changeset] { lappend x $c } + uplevel do_test $tn [list [list set {} $x]] [list $r] + + S delete +} + +# Compare the contents of all tables in [db1] and [db2]. Throw an error if +# they are not identical, or return an empty string if they are. +# +proc compare_db {db1 db2} { + + set sql {SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name} + set lot1 [$db1 eval $sql] + set lot2 [$db2 eval $sql] + + if {$lot1 != $lot2} { error "databases contain different tables" } + + foreach tbl $lot1 { + set col1 [list] + set col2 [list] + + $db1 eval "PRAGMA table_info = $tbl" { lappend col1 $name } + $db2 eval "PRAGMA table_info = $tbl" { lappend col2 $name } + if {$col1 != $col2} { error "table $tbl schema mismatch" } + + set sql "SELECT * FROM $tbl ORDER BY [join $col1 ,]" + set data1 [$db1 eval $sql] + set data2 [$db2 eval $sql] + if {$data1 != $data2} { error "table $tbl data mismatch" } + } + + return "" +} + +########################################################################## +# End of proc definitions. Start of tests. +########################################################################## + +test_reset +do_execsql_test 1.0 { + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES('i', 'one'); +} +do_iterator_test 1.1 t1 { + DELETE FROM t1 WHERE a = 'i'; + INSERT INTO t1 VALUES('ii', 'two'); +} { + {DELETE t1 {t i t one} {}} + {INSERT t1 {} {t ii t two}} +} + +test_reset +do_common_sql { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(a, b INTEGER PRIMARY KEY); + CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b)); +} + +foreach {tn sql} { + 1 { INSERT INTO t1 VALUES(1, 2) } + 2 { + INSERT INTO t2 VALUES(1, NULL); + INSERT INTO t2 VALUES(2, NULL); + INSERT INTO t2 VALUES(3, NULL); + DELETE FROM t2 WHERE a = 2; + INSERT INTO t2 VALUES(4, NULL); + UPDATE t2 SET b=0 WHERE b=1; + } + 3 { INSERT INTO t3 SELECT *, NULL FROM t2 } + 4 { + INSERT INTO t3 SELECT a||a, b||b, NULL FROM t3; + DELETE FROM t3 WHERE rowid%2; + } + 5 { UPDATE t3 SET c = a||b } + 6 { UPDATE t1 SET a = 32 } +} { + do_then_apply_sql $sql + do_test $tn { compare_db db db2 } {} +} + +finish_test + diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 64114718de..411e082377 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1777,6 +1777,7 @@ static int sessionDeleteRow( const char *zSep = ""; int rc = SQLITE_OK; SessionBuffer buf = {0, 0, 0}; + int nPk = 0; sessionAppendStr(&buf, "DELETE FROM ", &rc); sessionAppendIdent(&buf, zTab, &rc); @@ -1784,29 +1785,32 @@ static int sessionDeleteRow( for(i=0; inCol; i++){ if( p->abPK[i] ){ + nPk++; sessionAppendStr(&buf, zSep, &rc); sessionAppendIdent(&buf, p->azCol[i], &rc); sessionAppendStr(&buf, " = ?", &rc); sessionAppendInteger(&buf, i+1, &rc); - zSep = "AND "; + zSep = " AND "; } } - sessionAppendStr(&buf, " AND (?", &rc); - sessionAppendInteger(&buf, p->nCol+1, &rc); - sessionAppendStr(&buf, " OR ", &rc); + if( nPknCol ){ + sessionAppendStr(&buf, " AND (?", &rc); + sessionAppendInteger(&buf, p->nCol+1, &rc); + sessionAppendStr(&buf, " OR ", &rc); - zSep = ""; - for(i=0; inCol; i++){ - if( !p->abPK[i] ){ - sessionAppendStr(&buf, zSep, &rc); - sessionAppendIdent(&buf, p->azCol[i], &rc); - sessionAppendStr(&buf, " IS ?", &rc); - sessionAppendInteger(&buf, i+1, &rc); - zSep = "AND "; + zSep = ""; + for(i=0; inCol; i++){ + if( !p->abPK[i] ){ + sessionAppendStr(&buf, zSep, &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " IS ?", &rc); + sessionAppendInteger(&buf, i+1, &rc); + zSep = "AND "; + } } + sessionAppendStr(&buf, ")", &rc); } - sessionAppendStr(&buf, ")", &rc); if( rc==SQLITE_OK ){ rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pDelete, 0); @@ -2171,7 +2175,9 @@ static int sessionApplyOneOp( rc = sqlite3_bind_value(p->pDelete, i+1, pVal); } } - if( rc==SQLITE_OK ) rc = sqlite3_bind_int(p->pDelete, nCol+1, pbRetry==0); + if( rc==SQLITE_OK && sqlite3_bind_parameter_count(p->pDelete)>nCol ){ + rc = sqlite3_bind_int(p->pDelete, nCol+1, pbRetry==0); + } if( rc!=SQLITE_OK ) return rc; sqlite3_step(p->pDelete); diff --git a/manifest b/manifest index fffd7c5851..15369f40cd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\sINTEGER\sPRIMARY\sKEY\scolumns\sand\sthe\spre-update\shook. -D 2011-03-19T08:38:50 +C Fix\ssome\sbugs\sin\ssqlite3changeset_apply(). +D 2011-03-19T15:37:02 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -99,7 +99,8 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/sqlite3session.c d4ba709d457a7b184a72ccd3ab07e5a1e9dd9196 +F ext/session/session2.test 72f5926805b46a9a5f240db856dab0e5f59fc693 +F ext/session/sqlite3session.c 6518a335592f4b118d9e6b9ed9dcbe27b0ebcda7 F ext/session/sqlite3session.h 9551c002efd5fde07c52994c6b592308e0df2d6a F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 @@ -201,7 +202,7 @@ F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2 -F src/test_config.c 62f0f8f934b1d5c7e4cd4f506ae453a1117b47d7 +F src/test_config.c e9a4ce02dec5bcced1c13e0cf8b72edfd5903d74 F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5 @@ -601,7 +602,7 @@ F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806 F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16 F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16 -F test/permutations.test 5b2a4cb756ffb2407cb4743163668d1d769febb6 +F test/permutations.test 1e35edce72e6d9e2e392420caed18652a97b1a95 F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea @@ -644,6 +645,7 @@ F test/selectA.test 06d1032fa9009314c95394f2ca2e60d9f7ae8532 F test/selectB.test f305cc6660804cb239aab4e2f26b0e288b59958b F test/selectC.test f9bf1bc4581b5b8158caa6e4e4f682acb379fb25 F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c +F test/session.test c1a17c11ef7d01c24fe2b9f7871190d949a8e718 F test/session1.test c6851e2e1066269cad5370566ce5494c7dbdfa7e F test/shared.test b9114eaea7e748a3a4c8ff7b9ca806c8f95cef3e F test/shared2.test 7f6ad2d857d0f4e5d6a0b9a897b5e56a6b6ea18c @@ -919,7 +921,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 1b736ac2934f2361dee5062e9033cbf26b41fc3a -R 162f72638a0f38fbe0fc1273d5b87dc2 +P 24d4d5dd007197a141555bcca6f2ac9ab47cde80 +R 985767b788ac43658b5fdac318a5d51e U dan -Z 3b532fd3ba73ffa805a9d5e7143aadc5 +Z e6cf037758a8ddd02cc6b33f9980e9f6 diff --git a/manifest.uuid b/manifest.uuid index e62b7f494c..75eb322606 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -24d4d5dd007197a141555bcca6f2ac9ab47cde80 \ No newline at end of file +7250318dda542c5bbf28852c1f1d0f3c52ae8f96 \ No newline at end of file diff --git a/src/test_config.c b/src/test_config.c index 6eee524c09..24ddbaa027 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -404,6 +404,12 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double", Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_SESSION + Tcl_SetVar2(interp, "sqlite_options", "session", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "session", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_ENABLE_STAT2 Tcl_SetVar2(interp, "sqlite_options", "stat2", "1", TCL_GLOBAL_ONLY); #else diff --git a/test/permutations.test b/test/permutations.test index 9c48d9aa2a..7e336b16aa 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -89,6 +89,9 @@ foreach f [glob $testdir/*.test] { lappend alltests [file tail $f] } foreach f [glob -nocomplain $testdir/../ext/rtree/*.test] { lappend alltests $f } +foreach f [glob -nocomplain $testdir/../ext/session/*.test] { + lappend alltests $f +} if {$::tcl_platform(platform)!="unix"} { set alltests [test_set $alltests -exclude crash.test crash2.test] @@ -96,7 +99,7 @@ if {$::tcl_platform(platform)!="unix"} { set alltests [test_set $alltests -exclude { all.test async.test quick.test veryquick.test memleak.test permutations.test soak.test fts3.test - mallocAll.test rtree.test + mallocAll.test rtree.test session.test }] set allquicktests [test_set $alltests -exclude { @@ -762,6 +765,10 @@ test_suite "rtree" -description { All R-tree related tests. Provides coverage of source file rtree.c. } -files [glob -nocomplain $::testdir/../ext/rtree/*.test] +test_suite "session" -description { + All session module related tests. +} -files [glob -nocomplain $::testdir/../ext/session/*.test] + test_suite "no_optimization" -description { Run test scripts with optimizations disabled using the sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS) interface. diff --git a/test/session.test b/test/session.test new file mode 100644 index 0000000000..bf159c3b22 --- /dev/null +++ b/test/session.test @@ -0,0 +1,18 @@ +# 2008 June 23 +# +# 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 runs all rtree related tests. +# + +set testdir [file dirname $argv0] +source $testdir/permutations.test + +ifcapable session { + run_test_suite session +} + +finish_test From 4131639c6362eb0dc26ea486edb7b6be74011a1b Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Mar 2011 16:26:11 +0000 Subject: [PATCH 019/570] Fix a problem with resizing a hash table in sqlite3session.c. FossilOrigin-Name: 6e5907e14d3316d56313243c4f8ce8f14d0858fc --- ext/session/session2.test | 21 +++++++++++++++++++ ext/session/sqlite3session.c | 40 +++++++++++++++++++++--------------- manifest | 14 ++++++------- manifest.uuid | 2 +- 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/ext/session/session2.test b/ext/session/session2.test index 21a457fde9..ee5cbd2daf 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -114,6 +114,7 @@ do_common_sql { foreach {tn sql} { 1 { INSERT INTO t1 VALUES(1, 2) } + 2 { INSERT INTO t2 VALUES(1, NULL); INSERT INTO t2 VALUES(2, NULL); @@ -122,13 +123,33 @@ foreach {tn sql} { INSERT INTO t2 VALUES(4, NULL); UPDATE t2 SET b=0 WHERE b=1; } + 3 { INSERT INTO t3 SELECT *, NULL FROM t2 } + 4 { INSERT INTO t3 SELECT a||a, b||b, NULL FROM t3; DELETE FROM t3 WHERE rowid%2; } + 5 { UPDATE t3 SET c = a||b } + 6 { UPDATE t1 SET a = 32 } + + 7 { + INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 2 + INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 4 + INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 8 + INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 16 + INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 32 + INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 64 + INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 128 + INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 256 + INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 512 + INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 1024 + INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 2048 + DELETE FROM t1 WHERE (rowid%3)==0; + } + } { do_then_apply_sql $sql do_test $tn { compare_db db db2 } {} diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 411e082377..a76d2d29f3 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -265,29 +265,31 @@ static int sessionSerializeValue( return SQLITE_OK; } -#define HASH_APPEND(hash, add) ((hash) << 3) ^ (hash) ^ (int)(add) -static int sessionHashAppendI64(int h, i64 i){ +#define HASH_APPEND(hash, add) ((hash) << 3) ^ (hash) ^ (unsigned int)(add) +static unsigned int sessionHashAppendI64(unsigned int h, i64 i){ h = HASH_APPEND(h, i & 0xFFFFFFFF); return HASH_APPEND(h, (i>>32)&0xFFFFFFFF); } -static int sessionHashAppendBlob(int h, int n, const u8 *z){ +static unsigned int sessionHashAppendBlob(unsigned int h, int n, const u8 *z){ int i; for(i=0; inBucket. */ -static int sessionPreupdateHash( +static unsigned int sessionPreupdateHash( sqlite3 *db, /* Database handle */ SessionTable *pTab, /* Session table handle */ int bNew, /* True to hash the new.* PK */ int *piHash /* OUT: Hash value */ ){ - int h = 0; - int i; + unsigned int h = 0; /* Hash value to return */ + int i; /* Used to iterate through columns */ assert( pTab->nCol==sqlite3_preupdate_count(db) ); for(i=0; inCol; i++){ @@ -335,15 +337,21 @@ static int sessionPreupdateHash( return SQLITE_OK; } -static int sessionChangeHash( - sqlite3 *db, - SessionTable *pTab, - SessionChange *pChange, - int nBucket +/* +** Based on the primary key values stored in change pChange, calculate a +** hash key, assuming the has table has nBucket buckets. The hash keys +** calculated by this function are compatible with those calculated by +** sessionPreupdateHash(). +*/ +static unsigned int sessionChangeHash( + sqlite3 *db, /* Database handle */ + SessionTable *pTab, /* Table handle */ + SessionChange *pChange, /* Change handle */ + int nBucket /* Assume this many buckets in hash table */ ){ - int h = 0; - int i; - u8 *a = pChange->aRecord; + unsigned int h = 0; /* Value to return */ + int i; /* Used to iterate through columns */ + u8 *a = pChange->aRecord; /* Used to iterate through change record */ for(i=0; inCol; i++){ int eType = *a++; diff --git a/manifest b/manifest index 15369f40cd..3aa28c08c6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\sbugs\sin\ssqlite3changeset_apply(). -D 2011-03-19T15:37:02 +C Fix\sa\sproblem\swith\sresizing\sa\shash\stable\sin\ssqlite3session.c. +D 2011-03-19T16:26:12 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -99,8 +99,8 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/session2.test 72f5926805b46a9a5f240db856dab0e5f59fc693 -F ext/session/sqlite3session.c 6518a335592f4b118d9e6b9ed9dcbe27b0ebcda7 +F ext/session/session2.test 61c7ee56d158ab614b058b860508c85db2985810 +F ext/session/sqlite3session.c 55ec4205c7a12e417c38743d81e229a31a0f7e25 F ext/session/sqlite3session.h 9551c002efd5fde07c52994c6b592308e0df2d6a F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 @@ -921,7 +921,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 24d4d5dd007197a141555bcca6f2ac9ab47cde80 -R 985767b788ac43658b5fdac318a5d51e +P 7250318dda542c5bbf28852c1f1d0f3c52ae8f96 +R fb3197b98aa7c2cdada7337c44e7d717 U dan -Z e6cf037758a8ddd02cc6b33f9980e9f6 +Z 1901f146e1ed8385b77ee721ba556bd6 diff --git a/manifest.uuid b/manifest.uuid index 75eb322606..cb8c1bd8be 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7250318dda542c5bbf28852c1f1d0f3c52ae8f96 \ No newline at end of file +6e5907e14d3316d56313243c4f8ce8f14d0858fc \ No newline at end of file From 4565faa990e0e4b0ed3704ff689fd19d6dcaa74f Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Mar 2011 17:07:57 +0000 Subject: [PATCH 020/570] Move session1.test from test/ to ext/session/. FossilOrigin-Name: c4436a936ab302aec3b7f41a4552f69ad5815744 --- {test => ext/session}/session1.test | 8 ++++++-- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) rename {test => ext/session}/session1.test (98%) diff --git a/test/session1.test b/ext/session/session1.test similarity index 98% rename from test/session1.test rename to ext/session/session1.test index 872bee416f..fd09b47cc5 100644 --- a/test/session1.test +++ b/ext/session/session1.test @@ -11,9 +11,13 @@ # This file implements regression tests for SQLite library. # -set testdir [file dirname $argv0] +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl -set ::testprefix session1 + +set testprefix session1 proc do_changeset_test {tn session res} { set r [list] diff --git a/manifest b/manifest index 3aa28c08c6..7ea0d559c0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\sresizing\sa\shash\stable\sin\ssqlite3session.c. -D 2011-03-19T16:26:12 +C Move\ssession1.test\sfrom\stest/\sto\sext/session/. +D 2011-03-19T17:07:58 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -99,6 +99,7 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 +F ext/session/session1.test 3f982c74ee4ba97069917cc35aae25b4ed858e6a w test/session1.test F ext/session/session2.test 61c7ee56d158ab614b058b860508c85db2985810 F ext/session/sqlite3session.c 55ec4205c7a12e417c38743d81e229a31a0f7e25 F ext/session/sqlite3session.h 9551c002efd5fde07c52994c6b592308e0df2d6a @@ -646,7 +647,6 @@ F test/selectB.test f305cc6660804cb239aab4e2f26b0e288b59958b F test/selectC.test f9bf1bc4581b5b8158caa6e4e4f682acb379fb25 F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c F test/session.test c1a17c11ef7d01c24fe2b9f7871190d949a8e718 -F test/session1.test c6851e2e1066269cad5370566ce5494c7dbdfa7e F test/shared.test b9114eaea7e748a3a4c8ff7b9ca806c8f95cef3e F test/shared2.test 7f6ad2d857d0f4e5d6a0b9a897b5e56a6b6ea18c F test/shared3.test d69bdd5f156580876c5345652d21dc2092e85962 @@ -921,7 +921,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 7250318dda542c5bbf28852c1f1d0f3c52ae8f96 -R fb3197b98aa7c2cdada7337c44e7d717 +P 6e5907e14d3316d56313243c4f8ce8f14d0858fc +R 611730f89810ada9d2f188c5b6da861b U dan -Z 1901f146e1ed8385b77ee721ba556bd6 +Z a6a229bf3ddc4c217d0e04afae66c6a2 diff --git a/manifest.uuid b/manifest.uuid index cb8c1bd8be..5208758a65 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6e5907e14d3316d56313243c4f8ce8f14d0858fc \ No newline at end of file +c4436a936ab302aec3b7f41a4552f69ad5815744 \ No newline at end of file From 1f34f8cc719478a2225fc9dc8f0a42ba08bdabe6 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Mar 2011 18:46:15 +0000 Subject: [PATCH 021/570] Fix a bug in changeset generation code. FossilOrigin-Name: 825df75ba453c853953e17ec29653e11c46f92bb --- ext/session/session2.test | 21 +++++++++++++++++++++ ext/session/sqlite3session.c | 34 +++++++++++++++++----------------- manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 47 insertions(+), 26 deletions(-) diff --git a/ext/session/session2.test b/ext/session/session2.test index ee5cbd2daf..6436a2724b 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -112,6 +112,11 @@ do_common_sql { CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b)); } +# Execute each of the following blocks of SQL on database [db1]. Collect +# changes using a session object. Apply the resulting changeset to +# database [db2]. Then check that the contents of the two databases are +# identical. +# foreach {tn sql} { 1 { INSERT INTO t1 VALUES(1, 2) } @@ -150,7 +155,23 @@ foreach {tn sql} { DELETE FROM t1 WHERE (rowid%3)==0; } + 8 { + BEGIN; + INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; + ROLLBACK; + } + 9 { + BEGIN; + UPDATE t1 SET b = 'xxx'; + ROLLBACK; + } + 10 { + BEGIN; + DELETE FROM t1 WHERE 1; + ROLLBACK; + } } { +if {$tn==9} breakpoint do_then_apply_sql $sql do_test $tn { compare_db db db2 } {} } diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index a76d2d29f3..c234f8ce3b 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1115,6 +1115,7 @@ static void sessionAppendUpdate( if( *pRc==SQLITE_OK ){ SessionBuffer buf2 = {0,0,0}; /* Buffer to accumulate new.* record in */ int bNoop = 1; /* Set to zero if any values are modified */ + int nRewind = pBuf->nBuf; /* Set to zero if any values are modified */ int i; /* Used to iterate through columns */ u8 *pCsr = p->aRecord; /* Used to iterate through old.* values */ @@ -1180,11 +1181,11 @@ static void sessionAppendUpdate( } if( bNoop ){ - pBuf->nBuf -= (1 + sqlite3_column_count(pStmt)); + pBuf->nBuf = nRewind; }else{ sessionAppendBlob(pBuf, buf2.aBuf, buf2.nBuf, pRc); - sqlite3_free(buf2.aBuf); } + sqlite3_free(buf2.aBuf); } } @@ -1314,10 +1315,10 @@ int sqlite3session_changeset( if( pTab->nEntry ){ int nCol = pTab->nCol; /* Local copy of member variable */ u8 *abPK = pTab->abPK; /* Local copy of member variable */ - int i; - sqlite3_stmt *pStmt = 0; - int bNoop = 1; - int nRewind = buf.nBuf; + int i; /* Used to iterate through hash buckets */ + sqlite3_stmt *pSel = 0; /* SELECT statement to query table pTab */ + int nRewind = buf.nBuf; /* Initial size of write buffer */ + int nNoop; /* Size of buffer after writing tbl header */ /* Write a table header */ sessionAppendByte(&buf, 'T', &rc); @@ -1326,44 +1327,43 @@ int sqlite3session_changeset( /* Build and compile a statement to execute: */ if( rc==SQLITE_OK ){ - rc = sessionSelectStmt(db, pTab->zName, nCol, pTab->azCol, abPK,&pStmt); + rc = sessionSelectStmt(db, pTab->zName, nCol, pTab->azCol, abPK, &pSel); } - if( rc==SQLITE_OK && nCol!=sqlite3_column_count(pStmt) ){ + if( rc==SQLITE_OK && nCol!=sqlite3_column_count(pSel) ){ rc = SQLITE_SCHEMA; } + nNoop = buf.nBuf; for(i=0; inChange; i++){ SessionChange *p; /* Used to iterate through changes */ for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ - rc = sessionSelectBind(pStmt, nCol, abPK, p->aRecord, p->nRecord); + rc = sessionSelectBind(pSel, nCol, abPK, p->aRecord, p->nRecord); if( rc==SQLITE_OK ){ - if( sqlite3_step(pStmt)==SQLITE_ROW ){ + if( sqlite3_step(pSel)==SQLITE_ROW ){ int iCol; if( p->bInsert ){ sessionAppendByte(&buf, SQLITE_INSERT, &rc); for(iCol=0; iColbInsert ){ /* A DELETE change */ sessionAppendByte(&buf, SQLITE_DELETE, &rc); sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); - bNoop = 0; } - rc = sqlite3_reset(pStmt); + rc = sqlite3_reset(pSel); } } } - sqlite3_finalize(pStmt); + sqlite3_finalize(pSel); - if( bNoop ){ + if( buf.nBuf==nNoop ){ buf.nBuf = nRewind; } } diff --git a/manifest b/manifest index 7ea0d559c0..44b5abf093 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Move\ssession1.test\sfrom\stest/\sto\sext/session/. -D 2011-03-19T17:07:58 +C Fix\sa\sbug\sin\schangeset\sgeneration\scode. +D 2011-03-19T18:46:16 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -99,9 +99,9 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/session1.test 3f982c74ee4ba97069917cc35aae25b4ed858e6a w test/session1.test -F ext/session/session2.test 61c7ee56d158ab614b058b860508c85db2985810 -F ext/session/sqlite3session.c 55ec4205c7a12e417c38743d81e229a31a0f7e25 +F ext/session/session1.test 3f982c74ee4ba97069917cc35aae25b4ed858e6a +F ext/session/session2.test 09cbe57d949a315c68fb59822314990fd0e2af33 +F ext/session/sqlite3session.c 4cb15010040b093e452e6de52e8b5a9161032ebf F ext/session/sqlite3session.h 9551c002efd5fde07c52994c6b592308e0df2d6a F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 @@ -921,7 +921,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 6e5907e14d3316d56313243c4f8ce8f14d0858fc -R 611730f89810ada9d2f188c5b6da861b +P c4436a936ab302aec3b7f41a4552f69ad5815744 +R 633c4c2a52a8f04fd2ba1fea02dc8ad5 U dan -Z a6a229bf3ddc4c217d0e04afae66c6a2 +Z 046a676deaa5ff1f82305a84f859a0a7 diff --git a/manifest.uuid b/manifest.uuid index 5208758a65..40658a2e58 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c4436a936ab302aec3b7f41a4552f69ad5815744 \ No newline at end of file +825df75ba453c853953e17ec29653e11c46f92bb \ No newline at end of file From d7fb7d24c6b4f56026fb69663d30a7b3e6ba581d Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Mar 2011 19:19:26 +0000 Subject: [PATCH 022/570] Fix a problem involving session objects and attached databases. FossilOrigin-Name: ad91d30073a8faa7eb064dd2e1cc4d2297d7b3f8 --- ext/session/session2.test | 97 ++++++++++++++++++++++++++++++++++-- ext/session/sqlite3session.c | 12 +++-- manifest | 14 +++--- manifest.uuid | 2 +- 4 files changed, 109 insertions(+), 16 deletions(-) diff --git a/ext/session/session2.test b/ext/session/session2.test index 6436a2724b..453dc627a2 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -34,9 +34,10 @@ proc do_common_sql {sql} { } proc xConflict args { return "OMIT" } -proc do_then_apply_sql {sql} { - sqlite3session S db main - db eval {SELECT name FROM sqlite_master WHERE type = 'table'} { +proc do_then_apply_sql {sql {dbname main}} { + + sqlite3session S db $dbname + db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" { S attach $name } @@ -171,10 +172,96 @@ foreach {tn sql} { ROLLBACK; } } { -if {$tn==9} breakpoint do_then_apply_sql $sql - do_test $tn { compare_db db db2 } {} + do_test 1.$tn { compare_db db db2 } {} } +# The following block of tests is similar to the last, except that the +# session object is recording changes made to an attached database. The +# main database contains a table of the same name as the table being +# modified within the attached db. +# +test_reset +forcedelete test.db3 +sqlite3 db3 test.db3 +do_test 2.0 { + execsql { + ATTACH 'test.db3' AS 'aux'; + CREATE TABLE t1(a, b PRIMARY KEY); + CREATE TABLE t2(x, y, z); + CREATE TABLE t3(a); + + CREATE TABLE aux.t1(a PRIMARY KEY, b); + CREATE TABLE aux.t2(a, b INTEGER PRIMARY KEY); + CREATE TABLE aux.t3(a, b, c, PRIMARY KEY(a, b)); + } + execsql { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(a, b INTEGER PRIMARY KEY); + CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b)); + } db2 +} {} + +foreach {tn sql} { + 1 { INSERT INTO aux.t1 VALUES(1, 2) } + + 2 { + INSERT INTO aux.t2 VALUES(1, NULL); + INSERT INTO aux.t2 VALUES(2, NULL); + INSERT INTO aux.t2 VALUES(3, NULL); + DELETE FROM aux.t2 WHERE a = 2; + INSERT INTO aux.t2 VALUES(4, NULL); + UPDATE aux.t2 SET b=0 WHERE b=1; + } + + 3 { INSERT INTO aux.t3 SELECT *, NULL FROM aux.t2 } + + 4 { + INSERT INTO aux.t3 SELECT a||a, b||b, NULL FROM aux.t3; + DELETE FROM aux.t3 WHERE rowid%2; + } + + 5 { UPDATE aux.t3 SET c = a||b } + + 6 { UPDATE aux.t1 SET a = 32 } + + 7 { + INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; + INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; + INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; + INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; + INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; + INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; + INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; + INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; + INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; + INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; + INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; + DELETE FROM aux.t1 WHERE (rowid%3)==0; + } + + 8 { + BEGIN; + INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; + ROLLBACK; + } + 9 { + BEGIN; + UPDATE aux.t1 SET b = 'xxx'; + ROLLBACK; + } + 10 { + BEGIN; + DELETE FROM aux.t1 WHERE 1; + ROLLBACK; + } +} { + do_then_apply_sql $sql aux + do_test 2.$tn { compare_db db3 db2 } {} +} + + +catch {db3 close} + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index c234f8ce3b..d934fad6a7 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1191,6 +1191,7 @@ static void sessionAppendUpdate( static int sessionSelectStmt( sqlite3 *db, /* Database handle */ + const char *zDb, /* Database name */ const char *zTab, /* Table name */ int nCol, const char **azCol, @@ -1203,6 +1204,8 @@ static int sessionSelectStmt( SessionBuffer buf = {0, 0, 0}; sessionAppendStr(&buf, "SELECT * FROM ", &rc); + sessionAppendIdent(&buf, zDb, &rc); + sessionAppendStr(&buf, ".", &rc); sessionAppendIdent(&buf, zTab, &rc); sessionAppendStr(&buf, " WHERE ", &rc); for(i=0; ipTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ if( pTab->nEntry ){ + const char *zName = pTab->zName; int nCol = pTab->nCol; /* Local copy of member variable */ u8 *abPK = pTab->abPK; /* Local copy of member variable */ int i; /* Used to iterate through hash buckets */ @@ -1323,11 +1327,12 @@ int sqlite3session_changeset( /* Write a table header */ sessionAppendByte(&buf, 'T', &rc); sessionAppendVarint(&buf, nCol, &rc); - sessionAppendBlob(&buf, (u8 *)pTab->zName, strlen(pTab->zName)+1, &rc); + sessionAppendBlob(&buf, (u8 *)zName, strlen(zName)+1, &rc); /* Build and compile a statement to execute: */ if( rc==SQLITE_OK ){ - rc = sessionSelectStmt(db, pTab->zName, nCol, pTab->azCol, abPK, &pSel); + rc = sessionSelectStmt( + db, pSession->zDb, zName, nCol, pTab->azCol, abPK, &pSel); } if( rc==SQLITE_OK && nCol!=sqlite3_column_count(pSel) ){ @@ -1942,7 +1947,8 @@ static int sessionSelectRow( const char *zTab, /* Table name */ SessionApplyCtx *p /* Session changeset-apply context */ ){ - return sessionSelectStmt(db, zTab, p->nCol, p->azCol, p->abPK, &p->pSelect); + return sessionSelectStmt( + db, "main", zTab, p->nCol, p->azCol, p->abPK, &p->pSelect); } /* diff --git a/manifest b/manifest index 44b5abf093..bf593dda01 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sbug\sin\schangeset\sgeneration\scode. -D 2011-03-19T18:46:16 +C Fix\sa\sproblem\sinvolving\ssession\sobjects\sand\sattached\sdatabases. +D 2011-03-19T19:19:26 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -100,8 +100,8 @@ F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test 3f982c74ee4ba97069917cc35aae25b4ed858e6a -F ext/session/session2.test 09cbe57d949a315c68fb59822314990fd0e2af33 -F ext/session/sqlite3session.c 4cb15010040b093e452e6de52e8b5a9161032ebf +F ext/session/session2.test 96ff08995ab9935d1992ac554a240052883a0ebc +F ext/session/sqlite3session.c d211ce2e95483dfc144494f6c67879d85dddabfa F ext/session/sqlite3session.h 9551c002efd5fde07c52994c6b592308e0df2d6a F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 @@ -921,7 +921,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P c4436a936ab302aec3b7f41a4552f69ad5815744 -R 633c4c2a52a8f04fd2ba1fea02dc8ad5 +P 825df75ba453c853953e17ec29653e11c46f92bb +R 1e82a0bf18f9b8bb4d549f268721a5ef U dan -Z 046a676deaa5ff1f82305a84f859a0a7 +Z 935cff1eff2f640f29c72314cdd47105 diff --git a/manifest.uuid b/manifest.uuid index 40658a2e58..966ef9d6fc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -825df75ba453c853953e17ec29653e11c46f92bb \ No newline at end of file +ad91d30073a8faa7eb064dd2e1cc4d2297d7b3f8 \ No newline at end of file From a2df3d9f95e02214f2bc27faa999f442e3c2c3da Mon Sep 17 00:00:00 2001 From: dan Date: Sun, 20 Mar 2011 11:20:41 +0000 Subject: [PATCH 023/570] Documentation format updates to sqlite3session.h. FossilOrigin-Name: f227f60210fba3930f3050aebb1facee8bac9c0b --- ext/session/sqlite3session.h | 50 ++++++++++++++++++++++++++++++++---- manifest | 12 ++++----- manifest.uuid | 2 +- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index dd0e114f73..2ddad6a8a3 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -11,10 +11,19 @@ extern "C" { #include "sqlite3.h" +/* +** CAPI3REF: Session Object Handle +*/ typedef struct sqlite3_session sqlite3_session; + +/* +** CAPI3REF: Changeset Iterator Handle +*/ typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; /* +** CAPI3REF: Create A New Session Object +** ** Create a new session object attached to database handle db. If successful, ** a pointer to the new object is written to *ppSession and SQLITE_OK is ** returned. If an error occurs, *ppSession is set to NULL and an SQLite @@ -49,6 +58,8 @@ int sqlite3session_create( ); /* +** CAPI3REF: Delete A Session Object +** ** Delete a session object previously allocated using ** [sqlite3session_create()]. Once a session object has been deleted, the ** results of attempting to use pSession with any other session module @@ -61,6 +72,8 @@ int sqlite3session_create( void sqlite3session_delete(sqlite3_session *pSession); /* +** CAPI3REF: Enable Or Disable A Session Object +** ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When ** disabled - it does not. A newly created session object is enabled. @@ -78,6 +91,8 @@ void sqlite3session_delete(sqlite3_session *pSession); int sqlite3session_enable(sqlite3_session *pSession, int bEnable); /* +** CAPI3REF: Attach a Table to a Session Object +** ** Attach a table to a session. All subsequent changes made to the table ** while the session object is enabled will be recorded. See documentation ** for [sqlite3session_changeset()] for further details. @@ -101,6 +116,8 @@ int sqlite3session_attach( ); /* +** CAPI3REF: Generate A Changeset From A Session Object +** ** Obtain a changeset containing changes to the tables attached to the ** session object passed as the first argument. If successful, ** set *ppChangeset to point to a buffer containing the changeset @@ -120,14 +137,14 @@ int sqlite3session_attach( ** ** The contents of a changeset may be traversed using an iterator created ** using the [sqlite3changeset_start()] API. A changeset may be applied to -** a database with a compatible schema using the [sqlite3changset_apply()] +** a database with a compatible schema using the [sqlite3changeset_apply()] ** API. ** ** Following a successful call to this function, it is the responsibility of ** the caller to eventually free the buffer that *ppChangeset points to using ** [sqlite3_free()]. ** -**

Changeset Generation

+**

Changeset Generation

** ** Once a table has been attached to a session object, the session object ** records the primary key values of all new rows inserted into the table. @@ -187,6 +204,8 @@ int sqlite3session_changeset( ); /* +** CAPI3REF: Create An Iterator To Traverse A Changeset +** ** Create an iterator used to iterate through the contents of a changeset. ** If successful, *pp is set to point to the iterator handle and SQLITE_OK ** is returned. Otherwise, if an error occurs, *pp is set to zero and an @@ -214,6 +233,8 @@ int sqlite3changeset_start( ); /* +** CAPI3REF: Advance A Changeset Iterator +** ** This function may only be used with iterators created by function ** [sqlite3changeset_start()]. If it is called on an iterator passed to ** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE @@ -236,6 +257,8 @@ int sqlite3changeset_start( int sqlite3changeset_next(sqlite3_changeset_iter *pIter); /* +** CAPI3REF: Obtain The Current Operation From A Changeset Iterator +** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator ** created by [sqlite3changeset_start()]. In the latter case, the most recent @@ -264,6 +287,8 @@ int sqlite3changeset_op( ); /* +** CAPI3REF: Obtain old.* Values From A Changeset Iterator +** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator ** created by [sqlite3changeset_start()]. In the latter case, the most recent @@ -292,6 +317,8 @@ int sqlite3changeset_old( ); /* +** CAPI3REF: Obtain new.* Values From A Changeset Iterator +** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator ** created by [sqlite3changeset_start()]. In the latter case, the most recent @@ -323,6 +350,8 @@ int sqlite3changeset_new( ); /* +** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator +** ** This function should only be used with iterator objects passed to a ** conflict-handler callback by [sqlite3changeset_apply()] with either ** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this function @@ -349,7 +378,10 @@ int sqlite3changeset_conflict( /* -** Finalize an iterator allocated with sqlite3changeset_start(). +** CAPI3REF: Finalize a Changeset Iterator +** +** This function is used to finalize an iterator allocated with +** sqlite3changeset_start(). ** ** This function should only be called on iterators created using the ** [sqlite3changeset_start()] function. If an application calls this @@ -375,6 +407,8 @@ int sqlite3changeset_conflict( int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); /* +** CAPI3REF: Invert A Changeset +** ** This function is used to "invert" a changeset object. Applying an inverted ** changeset to a database reverses the effects of applying the uninverted ** changeset. Specifically: @@ -400,6 +434,8 @@ int sqlite3changeset_invert( ); /* +** CAPI3REF: Apply A Changeset To A Database +** ** Apply a changeset to a database. This function attempts to update the ** "main" database attached to handle db with the changes found in the ** changeset passed via the second and third arguments. @@ -482,7 +518,7 @@ int sqlite3changeset_invert( ** [SQLITE_CHANGESET_REPLACE]. ** **
UPDATE Changes
-** For each DELETE change, this function checks if the target database +** For each UPDATE change, this function checks if the target database ** contains a row with the same primary key value (or values) as the ** original row values stored in the changeset. If it does, and the values ** stored in all non-primary key columns also match the values stored in @@ -532,6 +568,8 @@ int sqlite3changeset_apply( ); /* +** CAPI3REF: Constants Passed to The Conflict Handler +** ** Values that may be passed as the second argument to a conflict-handler. ** **
@@ -576,7 +614,9 @@ int sqlite3changeset_apply( #define SQLITE_CHANGESET_CONSTRAINT 4 /* -** Valid return values from a conflict-handler. +** CAPI3REF: Constants Returned By The Conflict Handler +** +** A conflict handler callback must return one of the following three values. ** **
**
SQLITE_CHANGESET_OMIT
diff --git a/manifest b/manifest index bf593dda01..7a06b76e97 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\sinvolving\ssession\sobjects\sand\sattached\sdatabases. -D 2011-03-19T19:19:26 +C Documentation\sformat\supdates\sto\ssqlite3session.h. +D 2011-03-20T11:20:41 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -102,7 +102,7 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test 3f982c74ee4ba97069917cc35aae25b4ed858e6a F ext/session/session2.test 96ff08995ab9935d1992ac554a240052883a0ebc F ext/session/sqlite3session.c d211ce2e95483dfc144494f6c67879d85dddabfa -F ext/session/sqlite3session.h 9551c002efd5fde07c52994c6b592308e0df2d6a +F ext/session/sqlite3session.h 3b99c2498ca86c8d45b29d3956225e09faabc414 F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -921,7 +921,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 825df75ba453c853953e17ec29653e11c46f92bb -R 1e82a0bf18f9b8bb4d549f268721a5ef +P ad91d30073a8faa7eb064dd2e1cc4d2297d7b3f8 +R b83a18c2f45208301f57e8f22417178c U dan -Z 935cff1eff2f640f29c72314cdd47105 +Z e800e514ce176ffa56c1f9535016cce8 diff --git a/manifest.uuid b/manifest.uuid index 966ef9d6fc..c0fb35d699 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ad91d30073a8faa7eb064dd2e1cc4d2297d7b3f8 \ No newline at end of file +f227f60210fba3930f3050aebb1facee8bac9c0b \ No newline at end of file From 77e65004737c9c974838729e6de5c4ae52f1853c Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 21 Mar 2011 07:23:09 +0000 Subject: [PATCH 024/570] Fix some typos in sqlite3session.h. FossilOrigin-Name: 0853e530cc8d96f025f5160540e8ab3243dea11b --- ext/session/sqlite3session.h | 36 ++++++++++++++++++------------------ manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 2ddad6a8a3..2819bfece6 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -262,8 +262,8 @@ int sqlite3changeset_next(sqlite3_changeset_iter *pIter); ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator ** created by [sqlite3changeset_start()]. In the latter case, the most recent -** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. If this -** is not the case, this function returns SQLITE_MISUSE. +** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this +** is not the case, this function returns [SQLITE_MISUSE]. ** ** If argument pzTab is not NULL, then *pzTab is set to point to a ** nul-terminated utf-8 encoded string containing the name of the table @@ -271,9 +271,9 @@ int sqlite3changeset_next(sqlite3_changeset_iter *pIter); ** sqlite3changeset_next() is called on the iterator or until the ** conflict-handler function returns. If pnCol is not NULL, then *pnCol is ** set to the number of columns in the table affected by the change. Finally, -** if pOp is not NULL, then *pOp is set to one of SQLITE_INSERT, SQLITE_DELETE -** or SQLITE_UPDATE, depending on the type of change that the iterator -** currently points to. +** if pOp is not NULL, then *pOp is set to one of [SQLITE_INSERT], +** [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the type of change that +** the iterator currently points to. ** ** If no error occurs, SQLITE_OK is returned. If an error does occur, an ** SQLite error code is returned. The values of the output variables may not @@ -294,12 +294,12 @@ int sqlite3changeset_op( ** created by [sqlite3changeset_start()]. In the latter case, the most recent ** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. ** Furthermore, it may only be called if the type of change that the iterator -** currently points to is either SQLITE_DELETE or SQLITE_UPDATE. Otherwise, -** this function returns SQLITE_MISUSE and sets *ppValue to NULL. +** currently points to is either [SQLITE_DELETE] or [SQLITE_UPDATE]. Otherwise, +** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. ** ** Argument iVal must be greater than or equal to 0, and less than the number ** of columns in the table affected by the current change. Otherwise, -** SQLITE_RANGE is returned and *ppValue is set to NULL. +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. ** ** If successful, this function sets *ppValue to point to a protected ** sqlite3_value object containing the iVal'th value from the vector of @@ -324,12 +324,12 @@ int sqlite3changeset_old( ** created by [sqlite3changeset_start()]. In the latter case, the most recent ** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. ** Furthermore, it may only be called if the type of change that the iterator -** currently points to is either SQLITE_UPDATE or SQLITE_INSERT. Otherwise, -** this function returns SQLITE_MISUSE and sets *ppValue to NULL. +** currently points to is either [SQLITE_UPDATE] or [SQLITE_INSERT]. Otherwise, +** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. ** ** Argument iVal must be greater than or equal to 0, and less than the number ** of columns in the table affected by the current change. Otherwise, -** SQLITE_RANGE is returned and *ppValue is set to NULL. +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. ** ** If successful, this function sets *ppValue to point to a protected ** sqlite3_value object containing the iVal'th value from the vector of @@ -354,13 +354,13 @@ int sqlite3changeset_new( ** ** This function should only be used with iterator objects passed to a ** conflict-handler callback by [sqlite3changeset_apply()] with either -** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this function -** is called on any other iterator, SQLITE_MISUSE is returned and *ppValue +** [SQLITE_CHANGESET_DATA] or [SQLITE_CHANGESET_CONFLICT]. If this function +** is called on any other iterator, [SQLITE_MISUSE] is returned and *ppValue ** is set to NULL. ** ** Argument iVal must be greater than or equal to 0, and less than the number ** of columns in the table affected by the current change. Otherwise, -** SQLITE_RANGE is returned and *ppValue is set to NULL. +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. ** ** If successful, this function sets *ppValue to point to a protected ** sqlite3_value object containing the iVal'th value from the @@ -381,17 +381,17 @@ int sqlite3changeset_conflict( ** CAPI3REF: Finalize a Changeset Iterator ** ** This function is used to finalize an iterator allocated with -** sqlite3changeset_start(). +** [sqlite3changeset_start()]. ** ** This function should only be called on iterators created using the ** [sqlite3changeset_start()] function. If an application calls this ** function with an iterator passed to a conflict-handler by -** [sqlite3changeset_apply()], SQLITE_MISUSE is immediately returned and the +** [sqlite3changeset_apply()], [SQLITE_MISUSE] is immediately returned and the ** call has no effect. ** ** If an error was encountered within a call to an sqlite3changeset_xxx() -** function (for example an SQLITE_CORRUPT in sqlite3changeset_next() or an -** SQLITE_NOMEM in sqlite3changeset_new()) then an error code corresponding +** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an +** [SQLITE_NOMEM] in [sqlite3changeset_new()]) then an error code corresponding ** to that error is returned by this function. Otherwise, SQLITE_OK is ** returned. This is to allow the following pattern (pseudo-code): ** diff --git a/manifest b/manifest index 7a06b76e97..b318127f95 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Documentation\sformat\supdates\sto\ssqlite3session.h. -D 2011-03-20T11:20:41 +C Fix\ssome\stypos\sin\ssqlite3session.h. +D 2011-03-21T07:23:09 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -102,7 +102,7 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test 3f982c74ee4ba97069917cc35aae25b4ed858e6a F ext/session/session2.test 96ff08995ab9935d1992ac554a240052883a0ebc F ext/session/sqlite3session.c d211ce2e95483dfc144494f6c67879d85dddabfa -F ext/session/sqlite3session.h 3b99c2498ca86c8d45b29d3956225e09faabc414 +F ext/session/sqlite3session.h b77b014793162a77ac16507d720fe085cc15d06c F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -921,7 +921,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P ad91d30073a8faa7eb064dd2e1cc4d2297d7b3f8 -R b83a18c2f45208301f57e8f22417178c +P f227f60210fba3930f3050aebb1facee8bac9c0b +R 1d7fc8f92183ec1b52bc0fb00c30936f U dan -Z e800e514ce176ffa56c1f9535016cce8 +Z c7cce5161a77eeb6aa8085cb909dead1 diff --git a/manifest.uuid b/manifest.uuid index c0fb35d699..781e099e42 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f227f60210fba3930f3050aebb1facee8bac9c0b \ No newline at end of file +0853e530cc8d96f025f5160540e8ab3243dea11b \ No newline at end of file From 4e895da185c5571094cbdc45a76f62abb631c65d Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 21 Mar 2011 11:03:24 +0000 Subject: [PATCH 025/570] Fix session module problems with real (floating point) values. FossilOrigin-Name: a192d04f4e3a9e4960a4d96d1d3ee8635bc1034d --- ext/session/session2.test | 14 ++++++++++++++ ext/session/sqlite3session.c | 8 ++++---- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/ext/session/session2.test b/ext/session/session2.test index 453dc627a2..5411563f2e 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -105,6 +105,11 @@ do_iterator_test 1.1 t1 { {DELETE t1 {t i t one} {}} {INSERT t1 {} {t ii t two}} } +do_iterator_test 1.1 t1 { + INSERT INTO t1 VALUES(1.5, 99.9) +} { + {INSERT t1 {} {f 1.5 f 99.9}} +} test_reset do_common_sql { @@ -202,7 +207,10 @@ do_test 2.0 { } db2 } {} +proc xTrace {args} { puts $args } + foreach {tn sql} { + 1 { INSERT INTO aux.t1 VALUES(1, 2) } 2 { @@ -255,6 +263,12 @@ foreach {tn sql} { DELETE FROM aux.t1 WHERE 1; ROLLBACK; } + 11 { + INSERT INTO aux.t1 VALUES(randomblob(21000), randomblob(0)); + INSERT INTO aux.t1 VALUES(1.5, 1.5); + INSERT INTO aux.t1 VALUES(4.56, -99.999999999999999999999); + } + } { do_then_apply_sql $sql aux do_test 2.$tn { compare_db db3 db2 } {} diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index d934fad6a7..676ea3b44c 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -245,10 +245,10 @@ static int sessionSerializeValue( nByte = 9; break; - case SQLITE_TEXT: - case SQLITE_BLOB: { + default: { int n = sqlite3_value_bytes(pValue); int nVarint = sessionVarintLen(n); + assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); if( aBuf ){ sessionVarintPut(&aBuf[1], n); memcpy(&aBuf[nVarint + 1], eType==SQLITE_TEXT ? @@ -1257,7 +1257,7 @@ static int sessionSelectBind( double rVal; i64 iVal = sessionGetI64(a); memcpy(&rVal, &iVal, 8); - rc = sqlite3_bind_int64(pSelect, i+1, rVal); + rc = sqlite3_bind_double(pSelect, i+1, rVal); } a += 8; break; @@ -1481,7 +1481,7 @@ static int sessionReadRecord( sqlite3VdbeMemSetInt64(apOut[i], v); }else{ double d; - memcpy(&d, &i, 8); + memcpy(&d, &v, 8); sqlite3VdbeMemSetDouble(apOut[i], d); } } diff --git a/manifest b/manifest index b318127f95..46016a2034 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\stypos\sin\ssqlite3session.h. -D 2011-03-21T07:23:09 +C Fix\ssession\smodule\sproblems\swith\sreal\s(floating\spoint)\svalues. +D 2011-03-21T11:03:25 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -100,8 +100,8 @@ F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test 3f982c74ee4ba97069917cc35aae25b4ed858e6a -F ext/session/session2.test 96ff08995ab9935d1992ac554a240052883a0ebc -F ext/session/sqlite3session.c d211ce2e95483dfc144494f6c67879d85dddabfa +F ext/session/session2.test 45c9ff2052bf132d25d272b1d4b53f95c1c31463 +F ext/session/sqlite3session.c 3ed836ee8c6faff866bc59da800b6f20b0285071 F ext/session/sqlite3session.h b77b014793162a77ac16507d720fe085cc15d06c F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 @@ -921,7 +921,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P f227f60210fba3930f3050aebb1facee8bac9c0b -R 1d7fc8f92183ec1b52bc0fb00c30936f +P 0853e530cc8d96f025f5160540e8ab3243dea11b +R 482fc377ccc3f262af8beae8e4f384bf U dan -Z c7cce5161a77eeb6aa8085cb909dead1 +Z 767fabeb255e365fd4d794b5ace5ff7b diff --git a/manifest.uuid b/manifest.uuid index 781e099e42..e7426fdf05 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0853e530cc8d96f025f5160540e8ab3243dea11b \ No newline at end of file +a192d04f4e3a9e4960a4d96d1d3ee8635bc1034d \ No newline at end of file From 27453faef872f35e90984d9a083e0fcb3e547e18 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 21 Mar 2011 11:55:06 +0000 Subject: [PATCH 026/570] Clarify handling of NULL values in PK columns in sqlite3session.h. Add tests and fixes for the same. FossilOrigin-Name: aed4273054cbd150c86b36ea951d17c981633ba0 --- ext/session/session2.test | 243 +++++++++++++++++------------------ ext/session/sqlite3session.c | 171 ++++++++++++------------ ext/session/sqlite3session.h | 17 +++ manifest | 16 +-- manifest.uuid | 2 +- 5 files changed, 235 insertions(+), 214 deletions(-) diff --git a/ext/session/session2.test b/ext/session/session2.test index 5411563f2e..357b806043 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -111,6 +111,75 @@ do_iterator_test 1.1 t1 { {INSERT t1 {} {f 1.5 f 99.9}} } +# Execute each of the following blocks of SQL on database [db1]. Collect +# changes using a session object. Apply the resulting changeset to +# database [db2]. Then check that the contents of the two databases are +# identical. +# + +set set_of_tests { + 1 { INSERT INTO %T1% VALUES(1, 2) } + + 2 { + INSERT INTO %T2% VALUES(1, NULL); + INSERT INTO %T2% VALUES(2, NULL); + INSERT INTO %T2% VALUES(3, NULL); + DELETE FROM %T2% WHERE a = 2; + INSERT INTO %T2% VALUES(4, NULL); + UPDATE %T2% SET b=0 WHERE b=1; + } + + 3 { INSERT INTO %T3% SELECT *, NULL FROM %T2% } + + 4 { + INSERT INTO %T3% SELECT a||a, b||b, NULL FROM %T3%; + DELETE FROM %T3% WHERE rowid%2; + } + + 5 { UPDATE %T3% SET c = a||b } + + 6 { UPDATE %T1% SET a = 32 } + + 7 { + INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%; + INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%; + INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%; + INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%; + INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%; + INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%; + INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%; + INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%; + INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%; + INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%; + INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%; + DELETE FROM %T1% WHERE (rowid%3)==0; + } + + 8 { + BEGIN; + INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%; + ROLLBACK; + } + 9 { + BEGIN; + UPDATE %T1% SET b = 'xxx'; + ROLLBACK; + } + 10 { + BEGIN; + DELETE FROM %T1% WHERE 1; + ROLLBACK; + } + 11 { + INSERT INTO %T1% VALUES(randomblob(21000), randomblob(0)); + INSERT INTO %T1% VALUES(1.5, 1.5); + INSERT INTO %T1% VALUES(4.56, -99.999999999999999999999); + } + 12 { + INSERT INTO %T2% VALUES(NULL, NULL); + } +} + test_reset do_common_sql { CREATE TABLE t1(a PRIMARY KEY, b); @@ -118,65 +187,7 @@ do_common_sql { CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b)); } -# Execute each of the following blocks of SQL on database [db1]. Collect -# changes using a session object. Apply the resulting changeset to -# database [db2]. Then check that the contents of the two databases are -# identical. -# -foreach {tn sql} { - 1 { INSERT INTO t1 VALUES(1, 2) } - - 2 { - INSERT INTO t2 VALUES(1, NULL); - INSERT INTO t2 VALUES(2, NULL); - INSERT INTO t2 VALUES(3, NULL); - DELETE FROM t2 WHERE a = 2; - INSERT INTO t2 VALUES(4, NULL); - UPDATE t2 SET b=0 WHERE b=1; - } - - 3 { INSERT INTO t3 SELECT *, NULL FROM t2 } - - 4 { - INSERT INTO t3 SELECT a||a, b||b, NULL FROM t3; - DELETE FROM t3 WHERE rowid%2; - } - - 5 { UPDATE t3 SET c = a||b } - - 6 { UPDATE t1 SET a = 32 } - - 7 { - INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 2 - INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 4 - INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 8 - INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 16 - INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 32 - INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 64 - INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 128 - INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 256 - INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 512 - INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 1024 - INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 2048 - DELETE FROM t1 WHERE (rowid%3)==0; - } - - 8 { - BEGIN; - INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; - ROLLBACK; - } - 9 { - BEGIN; - UPDATE t1 SET b = 'xxx'; - ROLLBACK; - } - 10 { - BEGIN; - DELETE FROM t1 WHERE 1; - ROLLBACK; - } -} { +foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3} $set_of_tests] { do_then_apply_sql $sql do_test 1.$tn { compare_db db db2 } {} } @@ -209,73 +220,61 @@ do_test 2.0 { proc xTrace {args} { puts $args } -foreach {tn sql} { - - 1 { INSERT INTO aux.t1 VALUES(1, 2) } - - 2 { - INSERT INTO aux.t2 VALUES(1, NULL); - INSERT INTO aux.t2 VALUES(2, NULL); - INSERT INTO aux.t2 VALUES(3, NULL); - DELETE FROM aux.t2 WHERE a = 2; - INSERT INTO aux.t2 VALUES(4, NULL); - UPDATE aux.t2 SET b=0 WHERE b=1; - } - - 3 { INSERT INTO aux.t3 SELECT *, NULL FROM aux.t2 } - - 4 { - INSERT INTO aux.t3 SELECT a||a, b||b, NULL FROM aux.t3; - DELETE FROM aux.t3 WHERE rowid%2; - } - - 5 { UPDATE aux.t3 SET c = a||b } - - 6 { UPDATE aux.t1 SET a = 32 } - - 7 { - INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; - INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; - INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; - INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; - INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; - INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; - INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; - INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; - INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; - INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; - INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; - DELETE FROM aux.t1 WHERE (rowid%3)==0; - } - - 8 { - BEGIN; - INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; - ROLLBACK; - } - 9 { - BEGIN; - UPDATE aux.t1 SET b = 'xxx'; - ROLLBACK; - } - 10 { - BEGIN; - DELETE FROM aux.t1 WHERE 1; - ROLLBACK; - } - 11 { - INSERT INTO aux.t1 VALUES(randomblob(21000), randomblob(0)); - INSERT INTO aux.t1 VALUES(1.5, 1.5); - INSERT INTO aux.t1 VALUES(4.56, -99.999999999999999999999); - } - -} { +foreach {tn sql} [ + string map {%T1% aux.t1 %T2% aux.t2 %T3% aux.t3} $set_of_tests +] { do_then_apply_sql $sql aux do_test 2.$tn { compare_db db3 db2 } {} } - - catch {db3 close} + +#------------------------------------------------------------------------- +# The following tests verify that NULL values in primary key columns are +# handled correctly by the session module. +# +test_reset +do_execsql_test 3.0 { + CREATE TABLE t1(a PRIMARY KEY); + CREATE TABLE t2(a, b, c, PRIMARY KEY(c, b)); + CREATE TABLE t3(a, b INTEGER PRIMARY KEY); +} + +foreach {tn sql changeset} { + 1 { + INSERT INTO t1 VALUES(123); + INSERT INTO t1 VALUES(NULL); + INSERT INTO t1 VALUES(456); + } { + {INSERT t1 {} {i 456}} + {INSERT t1 {} {i 123}} + } + + 2 { + UPDATE t1 SET a = NULL; + } { + {DELETE t1 {i 456} {}} + {DELETE t1 {i 123} {}} + } + + 3 { DELETE FROM t1 } { } + + 4 { + INSERT INTO t3 VALUES(NULL, NULL) + } { + {INSERT t3 {} {n {} i 1}} + } + + 5 { INSERT INTO t2 VALUES(1, 2, NULL) } { } + 6 { INSERT INTO t2 VALUES(1, NULL, 3) } { } + 7 { INSERT INTO t2 VALUES(1, NULL, NULL) } { } + 8 { INSERT INTO t2 VALUES(1, 2, 3) } { {INSERT t2 {} {i 1 i 2 i 3}} } + 9 { DELETE FROM t2 WHERE 1 } { {DELETE t2 {i 1 i 2 i 3} {}} } + +} { + do_iterator_test 3.$tn {t1 t2 t3} $sql $changeset +} + + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 676ea3b44c..4663938bb2 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -286,11 +286,13 @@ static unsigned int sessionPreupdateHash( sqlite3 *db, /* Database handle */ SessionTable *pTab, /* Session table handle */ int bNew, /* True to hash the new.* PK */ - int *piHash /* OUT: Hash value */ + int *piHash, /* OUT: Hash value */ + int *pbNullPK ){ unsigned int h = 0; /* Hash value to return */ int i; /* Used to iterate through columns */ + assert( *pbNullPK==0 ); assert( pTab->nCol==sqlite3_preupdate_count(db) ); for(i=0; inCol; i++){ if( pTab->abPK[i] ){ @@ -329,6 +331,11 @@ static unsigned int sessionPreupdateHash( h = sessionHashAppendBlob(h, n, z); break; } + + default: + assert( eType==SQLITE_NULL ); + *pbNullPK = 1; + return SQLITE_OK; } } } @@ -357,27 +364,22 @@ static unsigned int sessionChangeHash( int eType = *a++; int isPK = pTab->abPK[i]; + /* It is not possible for eType to be SQLITE_NULL here. The session + ** module does not record changes for rows with NULL values stored in + ** primary key columns. */ + assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT + || eType==SQLITE_TEXT || eType==SQLITE_BLOB + ); + if( isPK ) h = HASH_APPEND(h, eType); - switch( eType ){ - case SQLITE_INTEGER: - case SQLITE_FLOAT: { - if( isPK ){ - i64 iVal = sessionGetI64(a); - h = sessionHashAppendI64(h, iVal); - } - a += 8; - break; - } - case SQLITE_TEXT: - case SQLITE_BLOB: { - int n; - a += sessionVarintGet(a, &n); - if( isPK ){ - h = sessionHashAppendBlob(h, n, a); - } - a += n; - break; - } + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + if( isPK ) h = sessionHashAppendI64(h, sessionGetI64(a)); + a += 8; + }else{ + int n; + a += sessionVarintGet(a, &n); + if( isPK ) h = sessionHashAppendBlob(h, n, a); + a += n; } } return (h % nBucket); @@ -665,6 +667,7 @@ static void sessionPreupdateOneChange( SessionChange *pChange; SessionChange *pC; int iHash; + int bNullPk = 0; int rc = SQLITE_OK; if( pSession->rc ) return; @@ -676,71 +679,73 @@ static void sessionPreupdateOneChange( if( sessionGrowHash(pSession, pTab) ) return; /* Search the hash table for an existing entry for rowid=iKey2. If - ** one is found, store a pointer to it in pChange and unlink it from - ** the hash table. Otherwise, set pChange to NULL. - */ - rc = sessionPreupdateHash(db, pTab, op==SQLITE_INSERT, &iHash); - for(pC=pTab->apChange[iHash]; rc==SQLITE_OK && pC; pC=pC->pNext){ - int bEqual; - rc = sessionPreupdateEqual(db, pTab, pC, op==SQLITE_INSERT, &bEqual); - if( bEqual ) break; - } - if( pC==0 ){ - /* Create a new change object containing all the old values (if - ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK - ** values (if this is an INSERT). */ - int nByte; /* Number of bytes to allocate */ - int i; /* Used to iterate through columns */ - - pTab->nEntry++; - - /* Figure out how large an allocation is required */ - nByte = sizeof(SessionChange); - for(i=0; inCol && rc==SQLITE_OK; i++){ - sqlite3_value *p = 0; - if( op!=SQLITE_INSERT ){ - rc = sqlite3_preupdate_old(pSession->db, i, &p); - }else if( 1 || pTab->abPK[i] ){ - rc = sqlite3_preupdate_new(pSession->db, i, &p); - } - if( p && rc==SQLITE_OK ){ - rc = sessionSerializeValue(0, p, &nByte); - } + ** one is found, store a pointer to it in pChange and unlink it from + ** the hash table. Otherwise, set pChange to NULL. + */ + rc = sessionPreupdateHash(db, pTab, op==SQLITE_INSERT, &iHash, &bNullPk); + if( bNullPk==0 ){ + for(pC=pTab->apChange[iHash]; rc==SQLITE_OK && pC; pC=pC->pNext){ + int bEqual; + rc = sessionPreupdateEqual(db, pTab, pC, op==SQLITE_INSERT, &bEqual); + if( bEqual ) break; } - - /* Allocate the change object */ - pChange = (SessionChange *)sqlite3_malloc(nByte); - if( !pChange ){ - rc = SQLITE_NOMEM; - }else{ - memset(pChange, 0, sizeof(SessionChange)); - pChange->aRecord = (u8 *)&pChange[1]; - } - - /* Populate the change object */ - nByte = 0; - for(i=0; inCol && rc==SQLITE_OK; i++){ - sqlite3_value *p = 0; - if( op!=SQLITE_INSERT ){ - rc = sqlite3_preupdate_old(pSession->db, i, &p); - }else if( 1 || pTab->abPK[i] ){ - rc = sqlite3_preupdate_new(pSession->db, i, &p); + if( pC==0 ){ + /* Create a new change object containing all the old values (if + ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK + ** values (if this is an INSERT). */ + int nByte; /* Number of bytes to allocate */ + int i; /* Used to iterate through columns */ + + pTab->nEntry++; + + /* Figure out how large an allocation is required */ + nByte = sizeof(SessionChange); + for(i=0; inCol && rc==SQLITE_OK; i++){ + sqlite3_value *p = 0; + if( op!=SQLITE_INSERT ){ + rc = sqlite3_preupdate_old(pSession->db, i, &p); + }else if( 1 || pTab->abPK[i] ){ + rc = sqlite3_preupdate_new(pSession->db, i, &p); + } + if( p && rc==SQLITE_OK ){ + rc = sessionSerializeValue(0, p, &nByte); + } } - if( p && rc==SQLITE_OK ){ - rc = sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte); + + /* Allocate the change object */ + pChange = (SessionChange *)sqlite3_malloc(nByte); + if( !pChange ){ + rc = SQLITE_NOMEM; + }else{ + memset(pChange, 0, sizeof(SessionChange)); + pChange->aRecord = (u8 *)&pChange[1]; + } + + /* Populate the change object */ + nByte = 0; + for(i=0; inCol && rc==SQLITE_OK; i++){ + sqlite3_value *p = 0; + if( op!=SQLITE_INSERT ){ + rc = sqlite3_preupdate_old(pSession->db, i, &p); + }else if( 1 || pTab->abPK[i] ){ + rc = sqlite3_preupdate_new(pSession->db, i, &p); + } + if( p && rc==SQLITE_OK ){ + rc = sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte); + } + } + pChange->nRecord = nByte; + + /* If an error has occurred, mark the session object as failed. */ + if( rc!=SQLITE_OK ){ + sqlite3_free(pChange); + pSession->rc = rc; + }else{ + /* Add the change back to the hash-table */ + pChange->bInsert = (op==SQLITE_INSERT); + pChange->pNext = pTab->apChange[iHash]; + pTab->apChange[iHash] = pChange; } - } - pChange->nRecord = nByte; - - /* If an error has occurred, mark the session object as failed. */ - if( rc!=SQLITE_OK ){ - sqlite3_free(pChange); - pSession->rc = rc; - }else{ - /* Add the change back to the hash-table */ - pChange->bInsert = (op==SQLITE_INSERT); - pChange->pNext = pTab->apChange[iHash]; - pTab->apChange[iHash] = pChange; } } } diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 2819bfece6..44b58eada8 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -106,6 +106,9 @@ int sqlite3session_enable(sqlite3_session *pSession, int bEnable); ** is it an error if the named table does not have a PRIMARY KEY. However, ** no changes will be recorded in either of these scenarios. ** +** Changes are not recorded for individual rows that have NULL values stored +** in one or more of their PRIMARY KEY columns. +** ** SQLITE_OK is returned if the table is successfully attached to the session ** object. Or, if an error occurs, an SQLite error code (e.g. SQLITE_NOMEM) ** is returned. @@ -135,6 +138,16 @@ int sqlite3session_attach( ** modifies the values of primary key columns. If such a change is made, it ** is represented in a changeset as a DELETE followed by an INSERT. ** +** Changes are not recorded for rows that have NULL values stored in one or +** more of their PRIMARY KEY columns. If such a row is inserted or deleted, +** no corresponding change is present in the changesets returned by this +** function. If an existing row with one or more NULL values stored in +** PRIMARY KEY columns is updated so that all PRIMARY KEY columns are non-NULL, +** only an INSERT is appears in the changeset. Similarly, if an existing row +** with non-NULL PRIMARY KEY values is updated so that one or more of its +** PRIMARY KEY columns are set to NULL, the resulting changeset contains a +** DELETE change only. +** ** The contents of a changeset may be traversed using an iterator created ** using the [sqlite3changeset_start()] API. A changeset may be applied to ** a database with a compatible schema using the [sqlite3changeset_apply()] @@ -153,6 +166,10 @@ int sqlite3session_attach( ** recorded once - the first time a row with said primary key is inserted, ** updated or deleted in the lifetime of the session. ** +** There is one exception to the previous paragraph: when a row is inserted, +** updated or deleted, if one or more of its primary key columns contains a +** NULL value, no record of the change is made. +** ** The session object therefore accumulates two types of records - those ** that consist of primary key values only (created when the user inserts ** a new record) and those that consist of the primary key values and the diff --git a/manifest b/manifest index 46016a2034..63945fc241 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssession\smodule\sproblems\swith\sreal\s(floating\spoint)\svalues. -D 2011-03-21T11:03:25 +C Clarify\shandling\sof\sNULL\svalues\sin\sPK\scolumns\sin\ssqlite3session.h.\sAdd\stests\sand\sfixes\sfor\sthe\ssame. +D 2011-03-21T11:55:07 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -100,9 +100,9 @@ F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test 3f982c74ee4ba97069917cc35aae25b4ed858e6a -F ext/session/session2.test 45c9ff2052bf132d25d272b1d4b53f95c1c31463 -F ext/session/sqlite3session.c 3ed836ee8c6faff866bc59da800b6f20b0285071 -F ext/session/sqlite3session.h b77b014793162a77ac16507d720fe085cc15d06c +F ext/session/session2.test 3ef304f660b2a929e6bfec2df125c1809f5501ff +F ext/session/sqlite3session.c 70b19f80eadf7060836eaa90928f08a58aa3b35f +F ext/session/sqlite3session.h 2c071ee5925e82c21c7c9c296a0422c039607106 F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -921,7 +921,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 0853e530cc8d96f025f5160540e8ab3243dea11b -R 482fc377ccc3f262af8beae8e4f384bf +P a192d04f4e3a9e4960a4d96d1d3ee8635bc1034d +R 0282a54a03134becd2cdef1929ff705c U dan -Z 767fabeb255e365fd4d794b5ace5ff7b +Z 9cc92283568709d19359195efd9bde16 diff --git a/manifest.uuid b/manifest.uuid index e7426fdf05..754c4bfa3c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a192d04f4e3a9e4960a4d96d1d3ee8635bc1034d \ No newline at end of file +aed4273054cbd150c86b36ea951d17c981633ba0 \ No newline at end of file From 12ca0b5695b874340a4c3e3a45b3d951cd0840ce Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 21 Mar 2011 16:17:42 +0000 Subject: [PATCH 027/570] Add start of fault-injection tests for session module. Fix some bugs related to the same. FossilOrigin-Name: 32e95164d1192b87b1ab019549fd2394642cd3fe --- ext/session/session2.test | 106 ++++++++++++--------------------- ext/session/session_common.tcl | 106 +++++++++++++++++++++++++++++++++ ext/session/sessionfault.test | 85 ++++++++++++++++++++++++++ ext/session/sqlite3session.c | 83 ++++++++++++++------------ manifest | 18 +++--- manifest.uuid | 2 +- src/vdbeapi.c | 22 +++---- 7 files changed, 299 insertions(+), 123 deletions(-) create mode 100644 ext/session/session_common.tcl create mode 100644 ext/session/sessionfault.test diff --git a/ext/session/session2.test b/ext/session/session2.test index 357b806043..9065df99a0 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -28,67 +28,6 @@ proc test_reset {} { sqlite3 db2 test.db2 } -proc do_common_sql {sql} { - execsql $sql db - execsql $sql db2 -} -proc xConflict args { return "OMIT" } - -proc do_then_apply_sql {sql {dbname main}} { - - sqlite3session S db $dbname - db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" { - S attach $name - } - - db eval $sql - sqlite3changeset_apply db2 [S changeset] xConflict - S delete -} - -proc do_iterator_test {tn tbl_list sql res} { - sqlite3session S db main - foreach t $tbl_list {S attach $t} - execsql $sql - - set r [list] - foreach v $res { lappend r $v } - - set x [list] - sqlite3session_foreach c [S changeset] { lappend x $c } - uplevel do_test $tn [list [list set {} $x]] [list $r] - - S delete -} - -# Compare the contents of all tables in [db1] and [db2]. Throw an error if -# they are not identical, or return an empty string if they are. -# -proc compare_db {db1 db2} { - - set sql {SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name} - set lot1 [$db1 eval $sql] - set lot2 [$db2 eval $sql] - - if {$lot1 != $lot2} { error "databases contain different tables" } - - foreach tbl $lot1 { - set col1 [list] - set col2 [list] - - $db1 eval "PRAGMA table_info = $tbl" { lappend col1 $name } - $db2 eval "PRAGMA table_info = $tbl" { lappend col2 $name } - if {$col1 != $col2} { error "table $tbl schema mismatch" } - - set sql "SELECT * FROM $tbl ORDER BY [join $col1 ,]" - set data1 [$db1 eval $sql] - set data2 [$db2 eval $sql] - if {$data1 != $data2} { error "table $tbl data mismatch" } - } - - return "" -} - ########################################################################## # End of proc definitions. Start of tests. ########################################################################## @@ -105,12 +44,13 @@ do_iterator_test 1.1 t1 { {DELETE t1 {t i t one} {}} {INSERT t1 {} {t ii t two}} } -do_iterator_test 1.1 t1 { +do_iterator_test 1.2 t1 { INSERT INTO t1 VALUES(1.5, 99.9) } { {INSERT t1 {} {f 1.5 f 99.9}} } + # Execute each of the following blocks of SQL on database [db1]. Collect # changes using a session object. Apply the resulting changeset to # database [db2]. Then check that the contents of the two databases are @@ -178,6 +118,38 @@ set set_of_tests { 12 { INSERT INTO %T2% VALUES(NULL, NULL); } + + 13 { + DELETE FROM %T1% WHERE 1; + + -- Insert many rows with real primary keys. Enough to force the session + -- objects hash table to resize. + INSERT INTO %T1% VALUES(0.1, 0.1); + INSERT INTO %T1% SELECT a+0.1, b+0.1 FROM %T1%; + INSERT INTO %T1% SELECT a+0.2, b+0.2 FROM %T1%; + INSERT INTO %T1% SELECT a+0.4, b+0.4 FROM %T1%; + INSERT INTO %T1% SELECT a+0.8, b+0.8 FROM %T1%; + INSERT INTO %T1% SELECT a+1.6, b+1.6 FROM %T1%; + INSERT INTO %T1% SELECT a+3.2, b+3.2 FROM %T1%; + INSERT INTO %T1% SELECT a+6.4, b+6.4 FROM %T1%; + INSERT INTO %T1% SELECT a+12.8, b+12.8 FROM %T1%; + INSERT INTO %T1% SELECT a+25.6, b+25.6 FROM %T1%; + INSERT INTO %T1% SELECT a+51.2, b+51.2 FROM %T1%; + INSERT INTO %T1% SELECT a+102.4, b+102.4 FROM %T1%; + INSERT INTO %T1% SELECT a+204.8, b+204.8 FROM %T1%; + } + + 14 { + DELETE FROM %T1% WHERE 1; + } + + 15 { + INSERT INTO %T1% VALUES(1, 1); + INSERT INTO %T1% SELECT a+2, b+2 FROM %T1%; + INSERT INTO %T1% SELECT a+4, b+4 FROM %T1%; + INSERT INTO %T1% SELECT a+8, b+8 FROM %T1%; + INSERT INTO %T1% SELECT a+256, b+256 FROM %T1%; + } } test_reset @@ -189,7 +161,7 @@ do_common_sql { foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3} $set_of_tests] { do_then_apply_sql $sql - do_test 1.$tn { compare_db db db2 } {} + do_test 2.$tn { compare_db db db2 } {} } # The following block of tests is similar to the last, except that the @@ -200,7 +172,7 @@ foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3} $set_of_tests] { test_reset forcedelete test.db3 sqlite3 db3 test.db3 -do_test 2.0 { +do_test 3.0 { execsql { ATTACH 'test.db3' AS 'aux'; CREATE TABLE t1(a, b PRIMARY KEY); @@ -224,7 +196,7 @@ foreach {tn sql} [ string map {%T1% aux.t1 %T2% aux.t2 %T3% aux.t3} $set_of_tests ] { do_then_apply_sql $sql aux - do_test 2.$tn { compare_db db3 db2 } {} + do_test 3.$tn { compare_db db3 db2 } {} } catch {db3 close} @@ -234,7 +206,7 @@ catch {db3 close} # handled correctly by the session module. # test_reset -do_execsql_test 3.0 { +do_execsql_test 4.0 { CREATE TABLE t1(a PRIMARY KEY); CREATE TABLE t2(a, b, c, PRIMARY KEY(c, b)); CREATE TABLE t3(a, b INTEGER PRIMARY KEY); @@ -272,7 +244,7 @@ foreach {tn sql changeset} { 9 { DELETE FROM t2 WHERE 1 } { {DELETE t2 {i 1 i 2 i 3} {}} } } { - do_iterator_test 3.$tn {t1 t2 t3} $sql $changeset + do_iterator_test 4.$tn {t1 t2 t3} $sql $changeset } diff --git a/ext/session/session_common.tcl b/ext/session/session_common.tcl new file mode 100644 index 0000000000..1b5ebc5b97 --- /dev/null +++ b/ext/session/session_common.tcl @@ -0,0 +1,106 @@ + + +proc do_conflict_test {tn args} { + proc xConflict {args} { + lappend ::xConflict $args + return "" + } + proc bgerror {args} { set ::background_error $args } + + + set O(-tables) [list] + set O(-sql) [list] + set O(-conflicts) [list] + + array set V $args + foreach key [array names V] { + if {![info exists O($key)]} {error "no such option: $key"} + } + array set O $args + + sqlite3session S db main + foreach t $O(-tables) { S attach $t } + execsql $O(-sql) + + set ::xConflict [list] + sqlite3changeset_apply db2 [S changeset] xConflict + + set conflicts [list] + foreach c $O(-conflicts) { + lappend conflicts $c + } + + after 1 {set go 1} + vwait go + + uplevel do_test $tn [list { set ::xConflict }] [list $conflicts] + S delete +} + +proc do_common_sql {sql} { + execsql $sql db + execsql $sql db2 +} + +proc do_then_apply_sql {sql {dbname main}} { + proc xConflict args { return "OMIT" } + + set rc [catch { + sqlite3session S db $dbname + db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" { + S attach $name + } + db eval $sql + sqlite3changeset_apply db2 [S changeset] xConflict + } msg] + + catch { S delete } + + if {$rc} {error $msg} +} + +proc do_iterator_test {tn tbl_list sql res} { + sqlite3session S db main + foreach t $tbl_list {S attach $t} + execsql $sql + + set r [list] + foreach v $res { lappend r $v } + + set x [list] + sqlite3session_foreach c [S changeset] { lappend x $c } + uplevel do_test $tn [list [list set {} $x]] [list $r] + + S delete +} + +# Compare the contents of all tables in [db1] and [db2]. Throw an error if +# they are not identical, or return an empty string if they are. +# +proc compare_db {db1 db2} { + + set sql {SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name} + set lot1 [$db1 eval $sql] + set lot2 [$db2 eval $sql] + + if {$lot1 != $lot2} { error "databases contain different tables" } + + foreach tbl $lot1 { + set col1 [list] + set col2 [list] + + $db1 eval "PRAGMA table_info = $tbl" { lappend col1 $name } + $db2 eval "PRAGMA table_info = $tbl" { lappend col2 $name } + if {$col1 != $col2} { error "table $tbl schema mismatch" } + + set sql "SELECT * FROM $tbl ORDER BY [join $col1 ,]" + set data1 [$db1 eval $sql] + set data2 [$db2 eval $sql] + if {$data1 != $data2} { error "table $tbl data mismatch" } + } + + return "" +} + + + diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test new file mode 100644 index 0000000000..d6dd361b00 --- /dev/null +++ b/ext/session/sessionfault.test @@ -0,0 +1,85 @@ +# 2011 Mar 21 +# +# 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. +# +#*********************************************************************** +# +# The focus of this file is testing the session module. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl + +set testprefix sessionfault + +forcedelete test.db2 +sqlite3 db2 test.db2 + +do_common_sql { + CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)); + INSERT INTO t1 VALUES(1, 2, 3); + INSERT INTO t1 VALUES(4, 5, 6); +} +faultsim_save_and_close +db2 close + +# Test OOM error handling when collecting and applying a simple changeset. +# +do_faultsim_test pagerfault-1 -faults oom-* -prep { + catch {db2 close} + catch {db close} + faultsim_restore_and_reopen + sqlite3 db2 test.db2 +} -body { + do_then_apply_sql { + INSERT INTO t1 VALUES(7, 8, 9); + UPDATE t1 SET c = 10 WHERE a = 1; + DELETE FROM t1 WHERE a = 4; + } +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + faultsim_integrity_check + if {$testrc==0} { compare_db db db2 } +} + +# This test case is designed so that a malloc() failure occurs while +# resizing the session object hash-table from 256 to 512 buckets. This +# is not an error, just a sub-optimal condition. +# +do_faultsim_test pagerfault-2 -faults oom-* -prep { + catch {db2 close} + catch {db close} + faultsim_restore_and_reopen + sqlite3 db2 test.db2 + + sqlite3session S db main + S attach t1 + execsql { BEGIN } + for {set i 0} {$i < 125} {incr i} { + execsql {INSERT INTO t1 VALUES(10+$i, 10+$i, 10+$i)} + } +} -body { + for {set i 125} {$i < 133} {incr i} { + execsql {INSERT INTO t1 VALUES(10+$i, 10+$i, 1-+$i)} + } + S changeset + set {} {} +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + if {$testrc==0} { + sqlite3changeset_apply db2 [S changeset] xConflict + compare_db db db2 + } + catch { S delete } + faultsim_integrity_check +} + +finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 4663938bb2..e6d4675b08 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -305,6 +305,7 @@ static unsigned int sessionPreupdateHash( }else{ rc = sqlite3_preupdate_old(db, i, &pVal); } + if( rc!=SQLITE_OK ) return rc; eType = sqlite3_value_type(pVal); h = HASH_APPEND(h, eType); @@ -424,33 +425,35 @@ static int sessionPreupdateEqual( } if( rc!=SQLITE_OK || sqlite3_value_type(pVal)!=eType ) return rc; - switch( eType ){ - case SQLITE_INTEGER: - case SQLITE_FLOAT: { - i64 iVal = sessionGetI64(a); - a += 8; - if( eType==SQLITE_INTEGER ){ - if( sqlite3_value_int64(pVal)!=iVal ) return SQLITE_OK; - }else{ - double rVal; - assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); - memcpy(&rVal, &iVal, 8); - if( sqlite3_value_double(pVal)!=rVal ) return SQLITE_OK; - } - break; + /* A SessionChange object never has a NULL value in a PK column */ + assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT + || eType==SQLITE_BLOB || eType==SQLITE_TEXT + ); + + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + i64 iVal = sessionGetI64(a); + a += 8; + if( eType==SQLITE_INTEGER ){ + if( sqlite3_value_int64(pVal)!=iVal ) return SQLITE_OK; + }else{ + double rVal; + assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); + memcpy(&rVal, &iVal, 8); + if( sqlite3_value_double(pVal)!=rVal ) return SQLITE_OK; } - case SQLITE_TEXT: - case SQLITE_BLOB: { - int n; - const u8 *z; - a += sessionVarintGet(a, &n); - if( sqlite3_value_bytes(pVal)!=n ) return SQLITE_OK; - z = eType==SQLITE_TEXT ? - sqlite3_value_text(pVal) : sqlite3_value_blob(pVal); - if( memcmp(a, z, n) ) return SQLITE_OK; - a += n; - break; + }else{ + int n; + const u8 *z; + a += sessionVarintGet(a, &n); + if( sqlite3_value_bytes(pVal)!=n ) return SQLITE_OK; + if( eType==SQLITE_TEXT ){ + z = sqlite3_value_text(pVal); + }else{ + z = sqlite3_value_blob(pVal); } + if( memcmp(a, z, n) ) return SQLITE_OK; + a += n; + break; } } } @@ -734,20 +737,22 @@ static void sessionPreupdateOneChange( rc = sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte); } } - pChange->nRecord = nByte; - - /* If an error has occurred, mark the session object as failed. */ - if( rc!=SQLITE_OK ){ - sqlite3_free(pChange); - pSession->rc = rc; - }else{ + if( rc==SQLITE_OK ){ /* Add the change back to the hash-table */ + pChange->nRecord = nByte; pChange->bInsert = (op==SQLITE_INSERT); pChange->pNext = pTab->apChange[iHash]; pTab->apChange[iHash] = pChange; + }else{ + sqlite3_free(pChange); } } } + + /* If an error has occurred, mark the session object as failed. */ + if( rc!=SQLITE_OK ){ + pSession->rc = rc; + } } /* @@ -1345,7 +1350,7 @@ int sqlite3session_changeset( } nNoop = buf.nBuf; - for(i=0; inChange; i++){ + for(i=0; inChange && rc==SQLITE_OK; i++){ SessionChange *p; /* Used to iterate through changes */ for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ @@ -1366,13 +1371,14 @@ int sqlite3session_changeset( sessionAppendByte(&buf, SQLITE_DELETE, &rc); sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); } - rc = sqlite3_reset(pSel); + if( rc==SQLITE_OK ){ + rc = sqlite3_reset(pSel); + } } } } sqlite3_finalize(pSel); - if( buf.nBuf==nNoop ){ buf.nBuf = nRewind; } @@ -1674,7 +1680,9 @@ int sqlite3changeset_conflict( int sqlite3changeset_finalize(sqlite3_changeset_iter *p){ int i; /* Used to iterate through p->apValue[] */ int rc = p->rc; /* Return code */ - for(i=0; inCol*2; i++) sqlite3ValueFree(p->apValue[i]); + if( p->apValue ){ + for(i=0; inCol*2; i++) sqlite3ValueFree(p->apValue[i]); + } sqlite3_free(p->apValue); sqlite3_free(p); return rc; @@ -2316,7 +2324,8 @@ int sqlite3changeset_apply( SessionApplyCtx sApply; /* changeset_apply() context object */ memset(&sApply, 0, sizeof(sApply)); - sqlite3changeset_start(&pIter, nChangeset, pChangeset); + rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + if( rc!=SQLITE_OK ) return rc; sqlite3_mutex_enter(sqlite3_db_mutex(db)); rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); diff --git a/manifest b/manifest index 63945fc241..3c63f1b8cc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Clarify\shandling\sof\sNULL\svalues\sin\sPK\scolumns\sin\ssqlite3session.h.\sAdd\stests\sand\sfixes\sfor\sthe\ssame. -D 2011-03-21T11:55:07 +C Add\sstart\sof\sfault-injection\stests\sfor\ssession\smodule.\sFix\ssome\sbugs\srelated\sto\sthe\ssame. +D 2011-03-21T16:17:42 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -100,8 +100,10 @@ F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test 3f982c74ee4ba97069917cc35aae25b4ed858e6a -F ext/session/session2.test 3ef304f660b2a929e6bfec2df125c1809f5501ff -F ext/session/sqlite3session.c 70b19f80eadf7060836eaa90928f08a58aa3b35f +F ext/session/session2.test 6462c21d3795d9e48ffea2e7550d1b2d6da66dfb +F ext/session/session_common.tcl 880b554b0bcadcabe1331afb87d58ad1ed2510c4 +F ext/session/sessionfault.test 4190de237b2c76ca7529ef415778a862d7d0fa30 +F ext/session/sqlite3session.c c5a60c2cf21f8892f9ae4850fad2d7859c2c3692 F ext/session/sqlite3session.h 2c071ee5925e82c21c7c9c296a0422c039607106 F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 @@ -239,7 +241,7 @@ F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f F src/vdbe.c c90edafd941481506f001b17cd8523683fdac853 F src/vdbe.h edef9c4f0be83e1f1dccd049da37b40e021b63d9 F src/vdbeInt.h 2cf77c1d151a4a54facd596d52be6d60c1cb26e8 -F src/vdbeapi.c c4692c74b31f4abe638fbcbae3944c52b54e2c36 +F src/vdbeapi.c 3d620e00cb74b6034343009af42d5ff5eb7c19dc F src/vdbeaux.c 0216b2c37509a44c3833b297765bee7bdd04fa2f F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b @@ -921,7 +923,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P a192d04f4e3a9e4960a4d96d1d3ee8635bc1034d -R 0282a54a03134becd2cdef1929ff705c +P aed4273054cbd150c86b36ea951d17c981633ba0 +R 3ee0056f48f594a086fa203e62ad6366 U dan -Z 9cc92283568709d19359195efd9bde16 +Z 9a232200bb7ff725d52774ff9ca627f1 diff --git a/manifest.uuid b/manifest.uuid index 754c4bfa3c..7adc729880 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -aed4273054cbd150c86b36ea951d17c981633ba0 \ No newline at end of file +32e95164d1192b87b1ab019549fd2394642cd3fe \ No newline at end of file diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 284e565e13..829d4678b6 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -1348,21 +1348,23 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ /* If the old.* record has not yet been loaded into memory, do so now. */ if( p->pUnpacked==0 ){ - u32 nRecord; - u8 *aRecord; + u32 nRec; + u8 *aRec; - rc = sqlite3BtreeDataSize(p->pCsr->pCursor, &nRecord); + rc = sqlite3BtreeDataSize(p->pCsr->pCursor, &nRec); if( rc!=SQLITE_OK ) goto preupdate_old_out; - aRecord = sqlite3DbMallocRaw(db, nRecord); - if( !aRecord ) goto preupdate_old_out; - rc = sqlite3BtreeData(p->pCsr->pCursor, 0, nRecord, aRecord); + aRec = sqlite3DbMallocRaw(db, nRec); + if( !aRec ) goto preupdate_old_out; + rc = sqlite3BtreeData(p->pCsr->pCursor, 0, nRec, aRec); + if( rc==SQLITE_OK ){ + p->pUnpacked = sqlite3VdbeRecordUnpack(&p->keyinfo, nRec, aRec, 0, 0); + if( !p->pUnpacked ) rc = SQLITE_NOMEM; + } if( rc!=SQLITE_OK ){ - sqlite3DbFree(db, aRecord); + sqlite3DbFree(db, aRec); goto preupdate_old_out; } - - p->pUnpacked = sqlite3VdbeRecordUnpack(&p->keyinfo, nRecord, aRecord, 0, 0); - p->aRecord = aRecord; + p->aRecord = aRec; } if( iIdx>=p->pUnpacked->nField ){ From db04571c79364fcfffc2dfd7fc655dc9d1b7d071 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 21 Mar 2011 19:41:29 +0000 Subject: [PATCH 028/570] Remove some unreachable code in sqlite3session.c. Add test cases. FossilOrigin-Name: 39cdfa5324ae91bfbbac733b1e3e2d33ca883340 --- ext/session/session1.test | 1 - ext/session/session2.test | 16 +++- ext/session/session_common.tcl | 6 +- ext/session/sessionfault.test | 52 +++++++++++ ext/session/sqlite3session.c | 164 ++++++++++++++------------------- manifest | 32 +++---- manifest.uuid | 2 +- 7 files changed, 150 insertions(+), 123 deletions(-) diff --git a/ext/session/session1.test b/ext/session/session1.test index fd09b47cc5..1d8b1921b9 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -188,7 +188,6 @@ proc do_conflict_test {tn args} { sqlite3session S db main foreach t $O(-tables) { S attach $t } execsql $O(-sql) - set ::xConflict [list] sqlite3changeset_apply db2 [S changeset] xConflict diff --git a/ext/session/session2.test b/ext/session/session2.test index 9065df99a0..984559bb12 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -150,6 +150,13 @@ set set_of_tests { INSERT INTO %T1% SELECT a+8, b+8 FROM %T1%; INSERT INTO %T1% SELECT a+256, b+256 FROM %T1%; } + + 16 { + INSERT INTO %T4% VALUES('abc', 'def'); + INSERT INTO %T4% VALUES('def', 'abc'); + } + 17 { UPDATE %T4% SET b = 1 } + 18 { DELETE FROM %T4% WHERE 1 } } test_reset @@ -157,9 +164,10 @@ do_common_sql { CREATE TABLE t1(a PRIMARY KEY, b); CREATE TABLE t2(a, b INTEGER PRIMARY KEY); CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b)); + CREATE TABLE t4(a, b, PRIMARY KEY(b, a)); } -foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3} $set_of_tests] { +foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3 %T4% t4} $set_of_tests] { do_then_apply_sql $sql do_test 2.$tn { compare_db db db2 } {} } @@ -182,21 +190,23 @@ do_test 3.0 { CREATE TABLE aux.t1(a PRIMARY KEY, b); CREATE TABLE aux.t2(a, b INTEGER PRIMARY KEY); CREATE TABLE aux.t3(a, b, c, PRIMARY KEY(a, b)); + CREATE TABLE aux.t4(a, b, PRIMARY KEY(b, a)); } execsql { CREATE TABLE t1(a PRIMARY KEY, b); CREATE TABLE t2(a, b INTEGER PRIMARY KEY); CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b)); + CREATE TABLE t4(a, b, PRIMARY KEY(b, a)); } db2 } {} proc xTrace {args} { puts $args } foreach {tn sql} [ - string map {%T1% aux.t1 %T2% aux.t2 %T3% aux.t3} $set_of_tests + string map {%T1% aux.t1 %T2% aux.t2 %T3% aux.t3 %T4% aux.t4} $set_of_tests ] { do_then_apply_sql $sql aux - do_test 3.$tn { compare_db db3 db2 } {} + do_test 3.$tn { compare_db db2 db3 } {} } catch {db3 close} diff --git a/ext/session/session_common.tcl b/ext/session/session_common.tcl index 1b5ebc5b97..c1a6440396 100644 --- a/ext/session/session_common.tcl +++ b/ext/session/session_common.tcl @@ -83,7 +83,11 @@ proc compare_db {db1 db2} { set lot1 [$db1 eval $sql] set lot2 [$db2 eval $sql] - if {$lot1 != $lot2} { error "databases contain different tables" } + if {$lot1 != $lot2} { + puts $lot1 + puts $lot2 + error "databases contain different tables" + } foreach tbl $lot1 { set col1 [list] diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index d6dd361b00..8f38fe63e8 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -82,4 +82,56 @@ do_faultsim_test pagerfault-2 -faults oom-* -prep { faultsim_integrity_check } +catch { db close } +catch { db2 close } +forcedelete test.db2 test.db +sqlite3 db2 test.db2 +sqlite3 db test.db + +proc xConflict {op tbl type args} { + if { $type=="CONFLICT" || $type=="DATA" } { + return "REPLACE" + } + return "OMIT" +} + +do_test 3.0 { + execsql { + PRAGMA encoding = 'utf16'; + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES(5, 32); + } + execsql { + PRAGMA encoding = 'utf16'; + CREATE TABLE t1(a PRIMARY KEY, b NOT NULL); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(2, 4); + INSERT INTO t1 VALUES(4, 16); + } db2 +} {} + +faultsim_save_and_close +db2 close + +do_faultsim_test pagerfault-3 -faults oom-transient -prep { + catch {db2 close} + catch {db close} + faultsim_restore_and_reopen + sqlite3 db2 test.db2 + sqlite3session S db main + S attach t1 + execsql { + INSERT INTO t1 VALUES(1, 45); + INSERT INTO t1 VALUES(2, 55); + INSERT INTO t1 VALUES(3, 55); + UPDATE t1 SET a = 4 WHERE a = 5; + } +} -body { + sqlite3changeset_apply db2 [S changeset] xConflict +} -test { + catch { S delete } + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + if {$testrc==0} { compare_db db db2 } +} + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index e6d4675b08..3c6a972961 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -552,11 +552,10 @@ static int sessionTableInfo( int nThis; int i; u8 *pAlloc; - u8 *pFree = 0; - char **azCol; + char **azCol = 0; u8 *abPK; - assert( pazCol || pabPK ); + assert( pazCol && pabPK ); nThis = strlen(zThis); zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis); @@ -584,15 +583,10 @@ static int sessionTableInfo( } } if( rc==SQLITE_OK ){ - pFree = pAlloc; - if( pazCol ){ - azCol = (char **)pAlloc; - pAlloc = (u8 *)&azCol[nCol]; - } - if( pabPK ){ - abPK = (u8 *)pAlloc; - pAlloc = &abPK[nCol]; - } + azCol = (char **)pAlloc; + pAlloc = (u8 *)&azCol[nCol]; + abPK = (u8 *)pAlloc; + pAlloc = &abPK[nCol]; if( pzTab ){ memcpy(pAlloc, zThis, nThis+1); *pzTab = (char *)pAlloc; @@ -604,12 +598,10 @@ static int sessionTableInfo( int nName = sqlite3_column_bytes(pStmt, 1); const unsigned char *zName = sqlite3_column_text(pStmt, 1); if( zName==0 ) break; - if( pazCol ){ - memcpy(pAlloc, zName, nName+1); - azCol[i] = (char *)pAlloc; - pAlloc += nName+1; - } - if( pabPK ) abPK[i] = sqlite3_column_int(pStmt, 5); + memcpy(pAlloc, zName, nName+1); + azCol[i] = (char *)pAlloc; + pAlloc += nName+1; + abPK[i] = sqlite3_column_int(pStmt, 5); i++; } rc = sqlite3_reset(pStmt); @@ -620,13 +612,13 @@ static int sessionTableInfo( ** free any allocation made. An error code will be returned in this case. */ if( rc==SQLITE_OK ){ - if( pazCol ) *pazCol = (const char **)azCol; - if( pabPK ) *pabPK = abPK; + *pazCol = (const char **)azCol; + *pabPK = abPK; }else{ - if( pazCol ) *pazCol = 0; - if( pabPK ) *pabPK = 0; + *pazCol = 0; + *pabPK = 0; if( pzTab ) *pzTab = 0; - sqlite3_free(pFree); + sqlite3_free(azCol); } sqlite3_finalize(pStmt); return rc; @@ -1785,7 +1777,7 @@ struct SessionApplyCtx { ** ** The DELETE statement looks like this: ** -** DELETE FROM x WHERE a = :1 AND c = :3 AND :5 OR (b IS :2 AND d IS :4) +** DELETE FROM x WHERE a = :1 AND c = :3 AND (:5 OR b IS :2 AND d IS :4) ** ** Variable :5 (nCol+1) is a boolean. It should be set to 0 if we require ** matching b and d values, or 1 otherwise. The second case comes up if the @@ -1997,6 +1989,41 @@ static int sessionInsertRow( return rc; } +/* +** Iterator pIter must point to an SQLITE_INSERT entry. This function +** transfers new.* values from the current iterator entry to statement +** pStmt. The table being inserted into has nCol columns. +** +** New.* value $i 0 from the iterator is bound to variable ($i+1) of +** statement pStmt. If parameter abPK is NULL, all values from 0 to (nCol-1) +** are transfered to the statement. Otherwise, if abPK is not NULL, it points +** to an array nCol elements in size. In this case only those values for +** which abPK[$i] is true are read from the iterator and bound to the +** statement. +** +** An SQLite error code is returned if an error occurs. Otherwise, SQLITE_OK. +*/ +static int sessionBindValues( + sqlite3_changeset_iter *pIter, /* Iterator to read values from */ + int(*xIterValue)(sqlite3_changeset_iter *, int, sqlite3_value **), + int nCol, /* Number of columns */ + u8 *abPK, /* If not NULL, bind only if true */ + sqlite3_stmt *pStmt /* Bind values to this statement */ +){ + int i; + int rc = SQLITE_OK; + for(i=0; rc==SQLITE_OK && idb, pIter, p->abPK, p->pSelect); }else{ - rc = SQLITE_DONE; + rc = SQLITE_OK; } if( rc==SQLITE_ROW ){ @@ -2117,7 +2130,7 @@ static int sessionConflictHandler( res = xConflict(pCtx, eType, pIter); pIter->pConflict = 0; rc = sqlite3_reset(p->pSelect); - }else{ + }else if( rc==SQLITE_OK ){ /* No other row with the new.* primary key. */ rc = sqlite3_reset(p->pSelect); if( rc==SQLITE_OK ){ @@ -2192,16 +2205,9 @@ static int sessionApplyOneOp( sqlite3changeset_op(pIter, &zDummy, &nCol, &op); if( op==SQLITE_DELETE ){ - int i; /* Bind values to the DELETE statement. */ - for(i=0; rc==SQLITE_OK && ipDelete, i+1, pVal); - } - } + rc = sessionBindValues(pIter, sqlite3changeset_old, nCol, 0, p->pDelete); if( rc==SQLITE_OK && sqlite3_bind_parameter_count(p->pDelete)>nCol ){ rc = sqlite3_bind_int(p->pDelete, nCol+1, pbRetry==0); } @@ -2254,44 +2260,20 @@ static int sessionApplyOneOp( ); }else if( rc==SQLITE_CONSTRAINT ){ - /* This may be a CONSTRAINT or CONFLICT error. It is a CONFLICT if - ** the only problem is a duplicate PRIMARY KEY, or a CONSTRAINT - ** otherwise. */ - int bPKChange = 0; - - /* Check if the PK has been modified. */ - rc = SQLITE_OK; - for(i=0; iabPK[i] ){ - sqlite3_value *pNew; - rc = sqlite3changeset_new(pIter, i, &pNew); - if( rc==SQLITE_OK && pNew ){ - bPKChange = 1; - break; - } - } - } - - rc = sessionConflictHandler(SQLITE_CHANGESET_CONFLICT, - p, pIter, xConflict, pCtx, (bPKChange ? pbReplace : 0) + /* This is always a CONSTRAINT conflict. */ + rc = sessionConflictHandler( + SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0 ); } }else{ - int i; assert( op==SQLITE_INSERT ); - for(i=0; rc==SQLITE_OK && ipInsert, i+1, pVal); - } - } + rc = sessionBindValues(pIter, sqlite3changeset_new, nCol, 0, p->pInsert); if( rc!=SQLITE_OK ) return rc; sqlite3_step(p->pInsert); rc = sqlite3_reset(p->pInsert); - if( rc==SQLITE_CONSTRAINT && xConflict ){ + if( rc==SQLITE_CONSTRAINT ){ rc = sessionConflictHandler( SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, pbReplace ); @@ -2369,21 +2351,11 @@ int sqlite3changeset_apply( } if( bReplace ){ + assert( pIter->op==SQLITE_INSERT ); rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); if( rc==SQLITE_OK ){ - int i; - for(i=0; i Date: Tue, 22 Mar 2011 02:03:23 +0000 Subject: [PATCH 029/570] Fix a couple typos for consistency in sessions documentation. FossilOrigin-Name: 510198f171b9f77a4ad49c06c978c5fbb3a5b7f9 --- ext/session/sqlite3session.h | 10 +++++----- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 44b58eada8..8e1767efab 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -91,7 +91,7 @@ void sqlite3session_delete(sqlite3_session *pSession); int sqlite3session_enable(sqlite3_session *pSession, int bEnable); /* -** CAPI3REF: Attach a Table to a Session Object +** CAPI3REF: Attach A Table To A Session Object ** ** Attach a table to a session. All subsequent changes made to the table ** while the session object is enabled will be recorded. See documentation @@ -167,7 +167,7 @@ int sqlite3session_attach( ** updated or deleted in the lifetime of the session. ** ** There is one exception to the previous paragraph: when a row is inserted, -** updated or deleted, if one or more of its primary key columns contains a +** updated or deleted, if one or more of its primary key columns contain a ** NULL value, no record of the change is made. ** ** The session object therefore accumulates two types of records - those @@ -197,7 +197,7 @@ int sqlite3session_attach( ** ** ** This means, amongst other things, that if a row is inserted and then later -** deleted while a session object is active, neither the insert or the delete +** deleted while a session object is active, neither the insert nor the delete ** will be present in the changeset. Or if a row is deleted and then later a ** row with the same primary key values inserted while a session object is ** active, the resulting changeset will contain an UPDATE change instead of @@ -395,7 +395,7 @@ int sqlite3changeset_conflict( /* -** CAPI3REF: Finalize a Changeset Iterator +** CAPI3REF: Finalize A Changeset Iterator ** ** This function is used to finalize an iterator allocated with ** [sqlite3changeset_start()]. @@ -585,7 +585,7 @@ int sqlite3changeset_apply( ); /* -** CAPI3REF: Constants Passed to The Conflict Handler +** CAPI3REF: Constants Passed To The Conflict Handler ** ** Values that may be passed as the second argument to a conflict-handler. ** diff --git a/manifest b/manifest index 90e7ad14b4..6310e57e5f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\ssome\sunreachable\scode\sin\ssqlite3session.c.\sAdd\stest\scases. -D 2011-03-21T19:41:30 +C Fix\sa\scouple\stypos\sfor\sconsistency\sin\ssessions\sdocumentation. +D 2011-03-22T02:03:23.754 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -104,7 +104,7 @@ F ext/session/session2.test 54c3a5ecdc60548a8ab0a86793b136de6f32a255 F ext/session/session_common.tcl d7bb85c3fd76d53bd9b909da808d5c16f5213111 F ext/session/sessionfault.test da234166d5d044c91964863174d7171b0561708b F ext/session/sqlite3session.c 1ca39db8a10b8bcb973b35a68c0924b6a64c4a97 -F ext/session/sqlite3session.h 2c071ee5925e82c21c7c9c296a0422c039607106 +F ext/session/sqlite3session.h 2b7b2b983bba8f7a299922056884912084b32c68 F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -923,7 +923,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 2b3c8b9d9aa909f64a29ed8167de24c328c50d85 -R c6506b08e053cfdd0bd616ee1b17add6 -U dan -Z 4cc9deaf80e50ac14cbc33555ec1ddf1 +P 39cdfa5324ae91bfbbac733b1e3e2d33ca883340 +R 7e8df5e06663856423ec54de25f0cd9f +U shaneh +Z a8ae98277851bb377ac869793dff328e diff --git a/manifest.uuid b/manifest.uuid index 3a13c2368c..e429e99a7c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -39cdfa5324ae91bfbbac733b1e3e2d33ca883340 \ No newline at end of file +510198f171b9f77a4ad49c06c978c5fbb3a5b7f9 \ No newline at end of file From 7aa469cdd35ad80d486361617630abc528442e45 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 22 Mar 2011 12:08:00 +0000 Subject: [PATCH 030/570] Add OOM tests and related fixes for the session module. FossilOrigin-Name: 06048a68b351e3eb15a890cb54db8a1d4b345fbc --- ext/session/session_common.tcl | 24 ++++++++- ext/session/sessionfault.test | 95 ++++++++++++++++++++++++++++++++-- ext/session/sqlite3session.c | 85 ++++++++++++++++++++---------- manifest | 18 +++---- manifest.uuid | 2 +- 5 files changed, 181 insertions(+), 43 deletions(-) diff --git a/ext/session/session_common.tcl b/ext/session/session_common.tcl index c1a6440396..41c80dee82 100644 --- a/ext/session/session_common.tcl +++ b/ext/session/session_common.tcl @@ -42,9 +42,25 @@ proc do_common_sql {sql} { execsql $sql db2 } +proc changeset_from_sql {sql {dbname main}} { + set rc [catch { + sqlite3session S db $dbname + db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" { + S attach $name + } + db eval $sql + S changeset + } changeset] + catch { S delete } + + if {$rc} { + error $changeset + } + return $changeset +} + proc do_then_apply_sql {sql {dbname main}} { proc xConflict args { return "OMIT" } - set rc [catch { sqlite3session S db $dbname db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" { @@ -100,7 +116,11 @@ proc compare_db {db1 db2} { set sql "SELECT * FROM $tbl ORDER BY [join $col1 ,]" set data1 [$db1 eval $sql] set data2 [$db2 eval $sql] - if {$data1 != $data2} { error "table $tbl data mismatch" } + if {$data1 != $data2} { + puts "$data1" + puts "$data2" + error "table $tbl data mismatch" + } } return "" diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index 8f38fe63e8..7ba05bbb22 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -22,7 +22,6 @@ set testprefix sessionfault forcedelete test.db2 sqlite3 db2 test.db2 - do_common_sql { CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)); INSERT INTO t1 VALUES(1, 2, 3); @@ -31,6 +30,8 @@ do_common_sql { faultsim_save_and_close db2 close + +#------------------------------------------------------------------------- # Test OOM error handling when collecting and applying a simple changeset. # do_faultsim_test pagerfault-1 -faults oom-* -prep { @@ -50,11 +51,58 @@ do_faultsim_test pagerfault-1 -faults oom-* -prep { if {$testrc==0} { compare_db db db2 } } +#------------------------------------------------------------------------- +# The following block of tests - pagerfault-2.* - are designed to check +# the handling of faults in the sqlite3changeset_apply() function. +# +catch {db close} +catch {db2 close} +forcedelete test.db2 test.db +sqlite3 db2 test.db2 +sqlite3 db test.db +do_common_sql { + CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)); + INSERT INTO t1 VALUES('apple', 'orange', 'pear'); + + CREATE TABLE t2(x PRIMARY KEY, y); +} +db2 close +faultsim_save_and_close + + +foreach {tn conflict_policy sql sql2} { + 1 OMIT { INSERT INTO t1 VALUES('one text', 'two text', X'00ff00') } {} + 2 OMIT { DELETE FROM t1 WHERE a = 'apple' } {} + 3 OMIT { UPDATE t1 SET c = 'banana' WHERE b = 'orange' } {} + 4 REPLACE { INSERT INTO t2 VALUES('keyvalue', 'value 1') } { + INSERT INTO t2 VALUES('keyvalue', 'value 2'); + } +} { + proc xConflict args [list return $conflict_policy] + + do_faultsim_test pagerfault-2.$tn -faults oom-transient -prep { + catch {db2 close} + catch {db close} + faultsim_restore_and_reopen + set ::changeset [changeset_from_sql $::sql] + sqlite3 db2 test.db2 + sqlite3_db_config_lookaside db2 0 0 0 + execsql $::sql2 db2 + } -body { + sqlite3changeset_apply db2 $::changeset xConflict + } -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + faultsim_integrity_check + if {$testrc==0} { compare_db db db2 } + } +} + +#------------------------------------------------------------------------- # This test case is designed so that a malloc() failure occurs while # resizing the session object hash-table from 256 to 512 buckets. This # is not an error, just a sub-optimal condition. # -do_faultsim_test pagerfault-2 -faults oom-* -prep { +do_faultsim_test pagerfault-3 -faults oom-* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen @@ -95,7 +143,7 @@ proc xConflict {op tbl type args} { return "OMIT" } -do_test 3.0 { +do_test 4.0 { execsql { PRAGMA encoding = 'utf16'; CREATE TABLE t1(a PRIMARY KEY, b); @@ -113,7 +161,7 @@ do_test 3.0 { faultsim_save_and_close db2 close -do_faultsim_test pagerfault-3 -faults oom-transient -prep { +do_faultsim_test pagerfault-4 -faults oom-* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen @@ -134,4 +182,43 @@ do_faultsim_test pagerfault-3 -faults oom-transient -prep { if {$testrc==0} { compare_db db db2 } } +#------------------------------------------------------------------------- +# This block of tests verifies that OOM faults in the +# sqlite3changeset_invert() function are handled correctly. +# +catch {db close} +catch {db2 close} +forcedelete test.db +sqlite3 db test.db +execsql { + CREATE TABLE t1(a, b, PRIMARY KEY(b)); + CREATE TABLE t2(a PRIMARY KEY, b); + INSERT INTO t1 VALUES('string', 1); + INSERT INTO t1 VALUES(4, 2); + INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3); +} +set changeset [changeset_from_sql { + INSERT INTO t1 VALUES('xxx', 'yyy'); + DELETE FROM t1 WHERE a = 'string'; + UPDATE t1 SET a = 20 WHERE b = 2; +}] +db close + +do_faultsim_test pagerfault-5 -faults oom* -body { + set ::inverse [sqlite3changeset_invert $::changeset] + set {} {} +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + if {$testrc==0} { + set x [list] + sqlite3session_foreach c $::inverse { lappend x $c } + foreach c { + {DELETE t1 {t xxx t yyy} {}} + {INSERT t1 {} {t string i 1}} + {UPDATE t1 {i 20 {} {}} {i 4 i 2}} + } { lappend y $c } + if {$x != $y} { error "changeset no good" } + } +} + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 3c6a972961..7c7890aed2 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1637,6 +1637,14 @@ int sqlite3changeset_new( return SQLITE_OK; } +/* +** The following two macros are used internally. They are similar to the +** sqlite3changeset_new() and sqlite3changeset_old() functions, except that +** they omit all error checking and return a pointer to the requested value. +*/ +#define sessionChangesetNew(pIter, iVal) (pIter)->apValue[(pIter)->nCol+(iVal)] +#define sessionChangesetOld(pIter, iVal) (pIter)->apValue[(iVal)] + /* ** This function may only be called with a changeset iterator that has been ** passed to an SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT @@ -1989,6 +1997,24 @@ static int sessionInsertRow( return rc; } +/* +** A wrapper around sqlite3_bind_value() that detects an extra problem. +** See comments in the body of this function for details. +*/ +static int sessionBindValue( + sqlite3_stmt *pStmt, /* Statement to bind value to */ + int i, /* Parameter number to bind to */ + sqlite3_value *pVal /* Value to bind */ +){ + if( (pVal->type==SQLITE_TEXT || pVal->type==SQLITE_BLOB) && pVal->z==0 ){ + /* This condition occurs when an earlier OOM in a call to + ** sqlite3_value_text() or sqlite3_value_blob() (perhaps from within + ** a conflict-hanler) has zeroed the pVal->z pointer. Return NOMEM. */ + return SQLITE_NOMEM; + } + return sqlite3_bind_value(pStmt, i, pVal); +} + /* ** Iterator pIter must point to an SQLITE_INSERT entry. This function ** transfers new.* values from the current iterator entry to statement @@ -2003,22 +2029,27 @@ static int sessionInsertRow( ** ** An SQLite error code is returned if an error occurs. Otherwise, SQLITE_OK. */ -static int sessionBindValues( +static int sessionBindRow( sqlite3_changeset_iter *pIter, /* Iterator to read values from */ - int(*xIterValue)(sqlite3_changeset_iter *, int, sqlite3_value **), + int(*xValue)(sqlite3_changeset_iter *, int, sqlite3_value **), int nCol, /* Number of columns */ u8 *abPK, /* If not NULL, bind only if true */ sqlite3_stmt *pStmt /* Bind values to this statement */ ){ int i; int rc = SQLITE_OK; + + /* Neither sqlite3changeset_old or sqlite3changeset_new can fail if the + ** argument iterator points to a suitable entry. Make sure that xValue + ** is one of these to guarantee that it is safe to ignore the return + ** in the code below. */ + assert( xValue==sqlite3changeset_old || xValue==sqlite3changeset_new ); + for(i=0; rc==SQLITE_OK && ipSelect); }else if( rc==SQLITE_OK ){ /* No other row with the new.* primary key. */ - rc = sqlite3_reset(p->pSelect); - if( rc==SQLITE_OK ){ - res = xConflict(pCtx, eType+1, pIter); - if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE; - } + res = xConflict(pCtx, eType+1, pIter); + if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE; } if( rc==SQLITE_OK ){ @@ -2207,7 +2239,7 @@ static int sessionApplyOneOp( if( op==SQLITE_DELETE ){ /* Bind values to the DELETE statement. */ - rc = sessionBindValues(pIter, sqlite3changeset_old, nCol, 0, p->pDelete); + rc = sessionBindRow(pIter, sqlite3changeset_old, nCol, 0, p->pDelete); if( rc==SQLITE_OK && sqlite3_bind_parameter_count(p->pDelete)>nCol ){ rc = sqlite3_bind_int(p->pDelete, nCol+1, pbRetry==0); } @@ -2230,19 +2262,18 @@ static int sessionApplyOneOp( /* Bind values to the UPDATE statement. */ for(i=0; rc==SQLITE_OK && ipUpdate, i*3+2, !!pNew); + if( pOld ){ + rc = sessionBindValue(p->pUpdate, i*3+1, pOld); } - if( rc==SQLITE_OK ){ - if( pOld ) sqlite3_bind_value(p->pUpdate, i*3+1, pOld); - sqlite3_bind_int(p->pUpdate, i*3+2, !!pNew); - if( pNew ) sqlite3_bind_value(p->pUpdate, i*3+3, pNew); + if( rc==SQLITE_OK && pNew ){ + rc = sessionBindValue(p->pUpdate, i*3+3, pNew); } } - if( rc==SQLITE_OK ) rc = sqlite3_bind_int(p->pUpdate, nCol*3+1, pbRetry==0); + if( rc==SQLITE_OK ) sqlite3_bind_int(p->pUpdate, nCol*3+1, pbRetry==0); if( rc!=SQLITE_OK ) return rc; /* Attempt the UPDATE. In the case of a NOTFOUND or DATA conflict, @@ -2268,7 +2299,7 @@ static int sessionApplyOneOp( }else{ assert( op==SQLITE_INSERT ); - rc = sessionBindValues(pIter, sqlite3changeset_new, nCol, 0, p->pInsert); + rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert); if( rc!=SQLITE_OK ) return rc; sqlite3_step(p->pInsert); @@ -2354,7 +2385,7 @@ int sqlite3changeset_apply( assert( pIter->op==SQLITE_INSERT ); rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); if( rc==SQLITE_OK ){ - rc = sessionBindValues(pIter, + rc = sessionBindRow(pIter, sqlite3changeset_new, sApply.nCol, sApply.abPK, sApply.pDelete); sqlite3_bind_int(sApply.pDelete, sApply.nCol+1, 1); } diff --git a/manifest b/manifest index 6310e57e5f..a2a6acaf3d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scouple\stypos\sfor\sconsistency\sin\ssessions\sdocumentation. -D 2011-03-22T02:03:23.754 +C Add\sOOM\stests\sand\srelated\sfixes\sfor\sthe\ssession\smodule. +D 2011-03-22T12:08:00 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -101,9 +101,9 @@ F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test 1e8cda2cc8a60171dabc0fbec4124f9f7c943f23 F ext/session/session2.test 54c3a5ecdc60548a8ab0a86793b136de6f32a255 -F ext/session/session_common.tcl d7bb85c3fd76d53bd9b909da808d5c16f5213111 -F ext/session/sessionfault.test da234166d5d044c91964863174d7171b0561708b -F ext/session/sqlite3session.c 1ca39db8a10b8bcb973b35a68c0924b6a64c4a97 +F ext/session/session_common.tcl c40e81e86b46adc92b7bcb0182eaa70c8523ad8e +F ext/session/sessionfault.test 2dcf303379d0c01d8320f3c7d0452e6a0dcebd48 +F ext/session/sqlite3session.c 2fd432583cc79928b6d31792fc4cb8bfc3e50588 F ext/session/sqlite3session.h 2b7b2b983bba8f7a299922056884912084b32c68 F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 @@ -923,7 +923,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 39cdfa5324ae91bfbbac733b1e3e2d33ca883340 -R 7e8df5e06663856423ec54de25f0cd9f -U shaneh -Z a8ae98277851bb377ac869793dff328e +P 510198f171b9f77a4ad49c06c978c5fbb3a5b7f9 +R 64f2c206ae40e85e14ca00143e665617 +U dan +Z 4313381608751ccada39ab0745df4a8f diff --git a/manifest.uuid b/manifest.uuid index e429e99a7c..58da30c0cd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -510198f171b9f77a4ad49c06c978c5fbb3a5b7f9 \ No newline at end of file +06048a68b351e3eb15a890cb54db8a1d4b345fbc \ No newline at end of file From ff4d0f41bb739cc66bcd055b14a201252a31193c Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 22 Mar 2011 15:21:03 +0000 Subject: [PATCH 031/570] If a NULL pointer is passed to sqlite3session_attach() in place of a table name, attach all database tables to the session object. FossilOrigin-Name: e9037e4e4ccaa5c633759c4d041b60b631b92c6c --- ext/session/session2.test | 24 +++++++++++++++ ext/session/session_common.tcl | 2 ++ ext/session/sqlite3session.c | 56 +++++++++++++++++++++------------- ext/session/sqlite3session.h | 17 +++++++---- ext/session/test_session.c | 7 +++-- manifest | 20 ++++++------ manifest.uuid | 2 +- 7 files changed, 88 insertions(+), 40 deletions(-) diff --git a/ext/session/session2.test b/ext/session/session2.test index 984559bb12..d0d8fa5617 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -258,5 +258,29 @@ foreach {tn sql changeset} { } +#------------------------------------------------------------------------- +# Test that if NULL is passed to sqlite3session_attach(), all database +# tables are attached to the session object. +# +test_reset +do_execsql_test 5.0 { + CREATE TABLE t1(a PRIMARY KEY); + CREATE TABLE t2(x, y PRIMARY KEY); +} + +foreach {tn sql changeset} { + 1 { INSERT INTO t1 VALUES(35) } { {INSERT t1 {} {i 35}} } + 2 { INSERT INTO t2 VALUES(36, 37) } { {INSERT t2 {} {i 36 i 37}} } + 3 { + DELETE FROM t1 WHERE 1; + UPDATE t2 SET x = 34; + } { + {UPDATE t2 {i 36 i 37} {i 34 {} {}}} + {DELETE t1 {i 35} {}} + } +} { + do_iterator_test 5.$tn * $sql $changeset +} + finish_test diff --git a/ext/session/session_common.tcl b/ext/session/session_common.tcl index 41c80dee82..d5c74fba5c 100644 --- a/ext/session/session_common.tcl +++ b/ext/session/session_common.tcl @@ -77,7 +77,9 @@ proc do_then_apply_sql {sql {dbname main}} { proc do_iterator_test {tn tbl_list sql res} { sqlite3session S db main + if {[llength $tbl_list]==0} { S attach * } foreach t $tbl_list {S attach $t} + execsql $sql set r [list] diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 7c7890aed2..2b0e3ac6bb 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -19,6 +19,7 @@ struct sqlite3_session { sqlite3 *db; /* Database handle session is attached to */ char *zDb; /* Name of database session is attached to */ int bEnable; /* True if currently recording */ + int bAutoAttach; /* True to auto-attach tables */ int rc; /* Non-zero if an error has occurred */ sqlite3_session *pNext; /* Next session object on same db. */ SessionTable *pTable; /* List of attached tables */ @@ -775,7 +776,16 @@ static void xPreUpdate( if( pSession->rc ) continue; if( sqlite3_strnicmp(zDb, pSession->zDb, nDb+1) ) continue; - for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){ + for(pTab=pSession->pTable; pTab || pSession->bAutoAttach; pTab=pTab->pNext){ + if( !pTab ){ + /* This branch is taken if table zName has not yet been attached to + ** this session and the auto-attach flag is set. */ + pSession->rc = sqlite3session_attach(pSession,zName); + if( pSession->rc ) continue; + pTab = pSession->pTable; + assert( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ); + } + if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ){ sessionPreupdateOneChange(op, pSession, pTab); if( op==SQLITE_UPDATE ){ @@ -876,31 +886,35 @@ int sqlite3session_attach( sqlite3_session *pSession, /* Session object */ const char *zName /* Table name */ ){ - SessionTable *pTab; /* New table object (if required) */ - int nName; /* Number of bytes in string zName */ int rc = SQLITE_OK; - sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); - /* First search for an existing entry. If one is found, this call is - ** a no-op. Return early. */ - nName = strlen(zName); - for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){ - if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ) break; - } + if( !zName ){ + pSession->bAutoAttach = 1; + }else{ + SessionTable *pTab; /* New table object (if required) */ + int nName; /* Number of bytes in string zName */ + + /* First search for an existing entry. If one is found, this call is + ** a no-op. Return early. */ + nName = strlen(zName); + for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){ + if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ) break; + } - if( !pTab ){ - /* Allocate new SessionTable object. */ - pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1); if( !pTab ){ - rc = SQLITE_NOMEM; - }else{ - /* Populate the new SessionTable object and link it into the list. */ - memset(pTab, 0, sizeof(SessionTable)); - pTab->zName = (char *)&pTab[1]; - memcpy(pTab->zName, zName, nName+1); - pTab->pNext = pSession->pTable; - pSession->pTable = pTab; + /* Allocate new SessionTable object. */ + pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1); + if( !pTab ){ + rc = SQLITE_NOMEM; + }else{ + /* Populate the new SessionTable object and link it into the list. */ + memset(pTab, 0, sizeof(SessionTable)); + pTab->zName = (char *)&pTab[1]; + memcpy(pTab->zName, zName, nName+1); + pTab->pNext = pSession->pTable; + pSession->pTable = pTab; + } } } diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 8e1767efab..d9d0ae1f54 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -93,9 +93,15 @@ int sqlite3session_enable(sqlite3_session *pSession, int bEnable); /* ** CAPI3REF: Attach A Table To A Session Object ** -** Attach a table to a session. All subsequent changes made to the table -** while the session object is enabled will be recorded. See documentation -** for [sqlite3session_changeset()] for further details. +** If argument zTab is not NULL, then it is the name of a table to attach +** to the session object passed as the first argument. All subsequent changes +** made to the table while the session object is enabled will be recorded. See +** documentation for [sqlite3session_changeset()] for further details. +** +** Or, if argument zTab is NULL, then changes are recorded for all tables +** in the database. If additional tables are added to the database (by +** executing "CREATE TABLE" statements) after this call is made, changes for +** the new tables are also recorded. ** ** Changes can only be recorded for tables that have a PRIMARY KEY explicitly ** defined as part of their CREATE TABLE statement. It does not matter if the @@ -109,9 +115,8 @@ int sqlite3session_enable(sqlite3_session *pSession, int bEnable); ** Changes are not recorded for individual rows that have NULL values stored ** in one or more of their PRIMARY KEY columns. ** -** SQLITE_OK is returned if the table is successfully attached to the session -** object. Or, if an error occurs, an SQLite error code (e.g. SQLITE_NOMEM) -** is returned. +** SQLITE_OK is returned if the call completes without error. Or, if an error +** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. */ int sqlite3session_attach( sqlite3_session *pSession, /* Session object */ diff --git a/ext/session/test_session.c b/ext/session/test_session.c index e3c7f4a216..ecc07187d3 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -54,11 +54,14 @@ static int test_session_cmd( } switch( iSub ){ - case 0: /* attach */ - rc = sqlite3session_attach(pSession, Tcl_GetString(objv[2])); + case 0: { /* attach */ + char *zArg = Tcl_GetString(objv[2]); + if( zArg[0]=='*' && zArg[1]=='\0' ) zArg = 0; + rc = sqlite3session_attach(pSession, zArg); if( rc!=SQLITE_OK ){ return test_session_error(interp, rc); } + } break; case 1: { /* changeset */ diff --git a/manifest b/manifest index a2a6acaf3d..1573c82507 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sOOM\stests\sand\srelated\sfixes\sfor\sthe\ssession\smodule. -D 2011-03-22T12:08:00 +C If\sa\sNULL\spointer\sis\spassed\sto\ssqlite3session_attach()\sin\splace\sof\sa\stable\sname,\sattach\sall\sdatabase\stables\sto\sthe\ssession\sobject. +D 2011-03-22T15:21:04 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -100,12 +100,12 @@ F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test 1e8cda2cc8a60171dabc0fbec4124f9f7c943f23 -F ext/session/session2.test 54c3a5ecdc60548a8ab0a86793b136de6f32a255 -F ext/session/session_common.tcl c40e81e86b46adc92b7bcb0182eaa70c8523ad8e +F ext/session/session2.test f993ee243db15025a7d9b1dae903fe3f82f04229 +F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 F ext/session/sessionfault.test 2dcf303379d0c01d8320f3c7d0452e6a0dcebd48 -F ext/session/sqlite3session.c 2fd432583cc79928b6d31792fc4cb8bfc3e50588 -F ext/session/sqlite3session.h 2b7b2b983bba8f7a299922056884912084b32c68 -F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535 +F ext/session/sqlite3session.c c2cc2149e682af9d2ddaab09152ef578c8f97864 +F ext/session/sqlite3session.h 5055e21ca0cb6ddacd46b773a15d90bc0298b0a2 +F ext/session/test_session.c d31fbf5902d0cff5e5495a5ce62efda77b596f2b F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk ae0868e05c76eaa8a0ae3d6927a949b1c8e810d7 @@ -923,7 +923,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 510198f171b9f77a4ad49c06c978c5fbb3a5b7f9 -R 64f2c206ae40e85e14ca00143e665617 +P 06048a68b351e3eb15a890cb54db8a1d4b345fbc +R aba670c08b10d639853d25c358b85571 U dan -Z 4313381608751ccada39ab0745df4a8f +Z 48e2e8d1a1883a86d400f9c1e1c32110 diff --git a/manifest.uuid b/manifest.uuid index 58da30c0cd..f56d01fe0f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -06048a68b351e3eb15a890cb54db8a1d4b345fbc \ No newline at end of file +e9037e4e4ccaa5c633759c4d041b60b631b92c6c \ No newline at end of file From 245b49b2030989768c410ea1459f791a131216cb Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 22 Mar 2011 16:54:12 +0000 Subject: [PATCH 032/570] Fix a crash that can follow an OOM when "all tables" are registered with a session module. FossilOrigin-Name: 183c236e991faaabdc768e52e926c52cf4a7abc9 --- ext/session/sessionfault.test | 32 +++++++++++++++++++++++++++++++- ext/session/sqlite3session.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index 7ba05bbb22..c8ce9e48af 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -34,7 +34,11 @@ db2 close #------------------------------------------------------------------------- # Test OOM error handling when collecting and applying a simple changeset. # -do_faultsim_test pagerfault-1 -faults oom-* -prep { +# Test 1.1 attaches tables individually by name to the session object. +# Whereas test 1.2 passes NULL to sqlite3session_attach() to attach all +# tables. +# +do_faultsim_test pagerfault-1.1 -faults oom-* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen @@ -51,6 +55,32 @@ do_faultsim_test pagerfault-1 -faults oom-* -prep { if {$testrc==0} { compare_db db db2 } } +do_faultsim_test pagerfault-1.2 -faults oom-* -prep { + catch {db2 close} + catch {db close} + faultsim_restore_and_reopen +} -body { + sqlite3session S db main + S attach * + execsql { + INSERT INTO t1 VALUES(7, 8, 9); + UPDATE t1 SET c = 10 WHERE a = 1; + DELETE FROM t1 WHERE a = 4; + } + set ::changeset [S changeset] + set {} {} +} -test { + catch { S delete } + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + faultsim_integrity_check + if {$testrc==0} { + proc xConflict {args} { return "OMIT" } + sqlite3 db2 test.db2 + sqlite3changeset_apply db2 $::changeset xConflict + compare_db db db2 + } +} + #------------------------------------------------------------------------- # The following block of tests - pagerfault-2.* - are designed to check # the handling of faults in the sqlite3changeset_apply() function. diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 2b0e3ac6bb..3619e7c4b6 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -781,7 +781,7 @@ static void xPreUpdate( /* This branch is taken if table zName has not yet been attached to ** this session and the auto-attach flag is set. */ pSession->rc = sqlite3session_attach(pSession,zName); - if( pSession->rc ) continue; + if( pSession->rc ) break; pTab = pSession->pTable; assert( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ); } diff --git a/manifest b/manifest index 1573c82507..8c992e020b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\sa\sNULL\spointer\sis\spassed\sto\ssqlite3session_attach()\sin\splace\sof\sa\stable\sname,\sattach\sall\sdatabase\stables\sto\sthe\ssession\sobject. -D 2011-03-22T15:21:04 +C Fix\sa\scrash\sthat\scan\sfollow\san\sOOM\swhen\s"all\stables"\sare\sregistered\swith\sa\ssession\smodule. +D 2011-03-22T16:54:12 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -102,8 +102,8 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test 1e8cda2cc8a60171dabc0fbec4124f9f7c943f23 F ext/session/session2.test f993ee243db15025a7d9b1dae903fe3f82f04229 F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 -F ext/session/sessionfault.test 2dcf303379d0c01d8320f3c7d0452e6a0dcebd48 -F ext/session/sqlite3session.c c2cc2149e682af9d2ddaab09152ef578c8f97864 +F ext/session/sessionfault.test 495f87fb9bd764ae90d4b40d0c33a76d86d9063e +F ext/session/sqlite3session.c ec0f440ae73229ae8ae307a31e631b9d71991cd4 F ext/session/sqlite3session.h 5055e21ca0cb6ddacd46b773a15d90bc0298b0a2 F ext/session/test_session.c d31fbf5902d0cff5e5495a5ce62efda77b596f2b F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 @@ -923,7 +923,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 06048a68b351e3eb15a890cb54db8a1d4b345fbc -R aba670c08b10d639853d25c358b85571 +P e9037e4e4ccaa5c633759c4d041b60b631b92c6c +R 93198cfc6613c93be1aa416f0de3d035 U dan -Z 48e2e8d1a1883a86d400f9c1e1c32110 +Z ee6ba5845d31702e943c5fa7b7c9db34 diff --git a/manifest.uuid b/manifest.uuid index f56d01fe0f..406e8e8902 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e9037e4e4ccaa5c633759c4d041b60b631b92c6c \ No newline at end of file +183c236e991faaabdc768e52e926c52cf4a7abc9 \ No newline at end of file From 1e7a2d431532c931e0d2e122a43c3a70e2e4ffb5 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 22 Mar 2011 18:45:29 +0000 Subject: [PATCH 033/570] Add API function sqlite3_preupdate_depth(), for determining the depth of the trigger stack from within a pre-update callback. FossilOrigin-Name: bdea70895c2c686a4dd3f4bf0a475fd1501d9551 --- manifest | 18 ++++---- manifest.uuid | 2 +- src/sqlite.h.in | 1 + src/tclsqlite.c | 15 ++++++- src/vdbeapi.c | 16 +++++++ test/hook.test | 112 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 152 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 8c992e020b..20662eaa2f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scrash\sthat\scan\sfollow\san\sOOM\swhen\s"all\stables"\sare\sregistered\swith\sa\ssession\smodule. -D 2011-03-22T16:54:12 +C Add\sAPI\sfunction\ssqlite3_preupdate_depth(),\sfor\sdetermining\sthe\sdepth\sof\sthe\strigger\sstack\sfrom\swithin\sa\spre-update\scallback. +D 2011-03-22T18:45:30 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -185,13 +185,13 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 4a5e0ad845475c84881f0b25b1abba2ddaab0a72 -F src/sqlite.h.in 62de507787b39cb58b52002a1ee974e09dd5c83a +F src/sqlite.h.in 6b93765e048e0023e23c1d9827a561d7ead7100a F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 F src/sqliteInt.h 10707dc735a0077741e1b4b1550891abc26d7582 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e -F src/tclsqlite.c 520e124994e68fd8804ade95b5d3e2e791d0958d +F src/tclsqlite.c 78713534e628ea92b032bfa20ea8a1afc6cdb124 F src/test1.c 9020310c7617234b33fd1c3064f89524db25f290 F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc @@ -241,7 +241,7 @@ F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f F src/vdbe.c c90edafd941481506f001b17cd8523683fdac853 F src/vdbe.h edef9c4f0be83e1f1dccd049da37b40e021b63d9 F src/vdbeInt.h 2cf77c1d151a4a54facd596d52be6d60c1cb26e8 -F src/vdbeapi.c 3d620e00cb74b6034343009af42d5ff5eb7c19dc +F src/vdbeapi.c e472b3e5985175e948e70025cb3bffa8a2e185c8 F src/vdbeaux.c 0216b2c37509a44c3833b297765bee7bdd04fa2f F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b @@ -481,7 +481,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c -F test/hook.test d054aad1a3772dd9045510382875468a9dcae15f +F test/hook.test 14b2439b878c9aae03a3684cba717be4bfdcc1c1 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 @@ -923,7 +923,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P e9037e4e4ccaa5c633759c4d041b60b631b92c6c -R 93198cfc6613c93be1aa416f0de3d035 +P 183c236e991faaabdc768e52e926c52cf4a7abc9 +R 3714f49d9e3ab391fe868f9d204fa8d5 U dan -Z ee6ba5845d31702e943c5fa7b7c9db34 +Z 4e2f4fe62e6298f01b15895da5c35a23 diff --git a/manifest.uuid b/manifest.uuid index 406e8e8902..cf0cd54d72 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -183c236e991faaabdc768e52e926c52cf4a7abc9 \ No newline at end of file +bdea70895c2c686a4dd3f4bf0a475fd1501d9551 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 80a19002fa..2ee63f24f1 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6405,6 +6405,7 @@ SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook( ); SQLITE_EXPERIMENTAL int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *); +SQLITE_EXPERIMENTAL int sqlite3_preupdate_depth(sqlite3 *); SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); /* diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 092295a2d1..2d945be532 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -2851,9 +2851,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ ** $db preupdate_hook old INDEX */ case DB_PREUPDATE: { - static const char *azSub[] = {"count", "hook", "new", "old", 0}; + static const char *azSub[] = {"count", "depth", "hook", "new", "old", 0}; enum DbPreupdateSubCmd { - PRE_COUNT, PRE_HOOK, PRE_NEW, PRE_OLD + PRE_COUNT, PRE_DEPTH, PRE_HOOK, PRE_NEW, PRE_OLD }; int iSub; @@ -2880,6 +2880,17 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ break; } + case PRE_DEPTH: { + Tcl_Obj *pRet; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 3, objv, ""); + return TCL_ERROR; + } + pRet = Tcl_NewIntObj(sqlite3_preupdate_depth(pDb->db)); + Tcl_SetObjResult(interp, pRet); + break; + } + case PRE_NEW: case PRE_OLD: { int iIdx; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 829d4678b6..b485aa7483 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -1391,6 +1391,22 @@ int sqlite3_preupdate_count(sqlite3 *db){ return (p ? p->pCsr->nField : 0); } +/* +** This function is designed to be called from within a pre-update callback +** only. It returns zero if the change that caused the callback was made +** immediately by a user SQL statement. Or, if the change was made by a +** trigger program, it returns the number of trigger programs currently +** on the stack (1 for a top-level trigger, 2 for a trigger fired by a +** top-level trigger etc.). +** +** For the purposes of the previous paragraph, a foreign key CASCADE, SET NULL +** or SET DEFAULT action is considered a trigger. +*/ +int sqlite3_preupdate_depth(sqlite3 *db){ + PreUpdate *p = db->pPreUpdate; + return (p ? p->v->nFrame : 0); +} + /* ** This function is called from within a pre-update callback to retrieve ** a field of the row currently being updated or inserted. diff --git a/test/hook.test b/test/hook.test index 9ceedbb75d..016569f0ae 100644 --- a/test/hook.test +++ b/test/hook.test @@ -651,6 +651,118 @@ do_preupdate_test 7.6.2 { DELETE main t9 3 3 1 3 4 } +#-------------------------------------------------------------------------- +# Test that the sqlite3_preupdate_depth() API seems to work. +# +proc preupdate_hook {args} { + set type [lindex $args 0] + eval lappend ::preupdate $args + eval lappend ::preupdate [db preupdate depth] + + if {$type != "INSERT"} { + for {set i 0} {$i < [db preupdate count]} {incr i} { + lappend ::preupdate [db preupdate old $i] + } + } + if {$type != "DELETE"} { + for {set i 0} {$i < [db preupdate count]} {incr i} { + set rc [catch { db preupdate new $i } v] + lappend ::preupdate $v + } + } +} + +db close +forcedelete test.db +sqlite3 db test.db +db preupdate hook preupdate_hook + +do_execsql_test 7.6.1 { + CREATE TABLE t1(x PRIMARY KEY); + CREATE TABLE t2(x PRIMARY KEY); + CREATE TABLE t3(x PRIMARY KEY); + CREATE TABLE t4(x PRIMARY KEY); + + CREATE TRIGGER a AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(new.x); END; + CREATE TRIGGER b AFTER INSERT ON t2 BEGIN INSERT INTO t3 VALUES(new.x); END; + CREATE TRIGGER c AFTER INSERT ON t3 BEGIN INSERT INTO t4 VALUES(new.x); END; + + CREATE TRIGGER d AFTER UPDATE ON t1 BEGIN UPDATE t2 SET x = new.x; END; + CREATE TRIGGER e AFTER UPDATE ON t2 BEGIN UPDATE t3 SET x = new.x; END; + CREATE TRIGGER f AFTER UPDATE ON t3 BEGIN UPDATE t4 SET x = new.x; END; + + CREATE TRIGGER g AFTER DELETE ON t1 BEGIN DELETE FROM t2 WHERE 1; END; + CREATE TRIGGER h AFTER DELETE ON t2 BEGIN DELETE FROM t3 WHERE 1; END; + CREATE TRIGGER i AFTER DELETE ON t3 BEGIN DELETE FROM t4 WHERE 1; END; +} + +do_preupdate_test 7.6.2 { + INSERT INTO t1 VALUES('xyz'); +} { + INSERT main t1 1 1 0 xyz + INSERT main t2 1 1 1 xyz + INSERT main t3 1 1 2 xyz + INSERT main t4 1 1 3 xyz +} +do_preupdate_test 7.6.3 { + UPDATE t1 SET x = 'abc'; +} { + UPDATE main t1 1 1 0 xyz abc + UPDATE main t2 1 1 1 xyz abc + UPDATE main t3 1 1 2 xyz abc + UPDATE main t4 1 1 3 xyz abc +} +do_preupdate_test 7.6.4 { + DELETE FROM t1 WHERE 1; +} { + DELETE main t1 1 1 0 abc + DELETE main t2 1 1 1 abc + DELETE main t3 1 1 2 abc + DELETE main t4 1 1 3 abc +} + +do_execsql_test 7.6.5 { + DROP TRIGGER a; DROP TRIGGER b; DROP TRIGGER c; + DROP TRIGGER d; DROP TRIGGER e; DROP TRIGGER f; + DROP TRIGGER g; DROP TRIGGER h; DROP TRIGGER i; + + CREATE TRIGGER a BEFORE INSERT ON t1 BEGIN INSERT INTO t2 VALUES(new.x); END; + CREATE TRIGGER b BEFORE INSERT ON t2 BEGIN INSERT INTO t3 VALUES(new.x); END; + CREATE TRIGGER c BEFORE INSERT ON t3 BEGIN INSERT INTO t4 VALUES(new.x); END; + + CREATE TRIGGER d BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET x = new.x; END; + CREATE TRIGGER e BEFORE UPDATE ON t2 BEGIN UPDATE t3 SET x = new.x; END; + CREATE TRIGGER f BEFORE UPDATE ON t3 BEGIN UPDATE t4 SET x = new.x; END; + + CREATE TRIGGER g BEFORE DELETE ON t1 BEGIN DELETE FROM t2 WHERE 1; END; + CREATE TRIGGER h BEFORE DELETE ON t2 BEGIN DELETE FROM t3 WHERE 1; END; + CREATE TRIGGER i BEFORE DELETE ON t3 BEGIN DELETE FROM t4 WHERE 1; END; +} + +do_preupdate_test 7.6.6 { + INSERT INTO t1 VALUES('xyz'); +} { + INSERT main t4 1 1 3 xyz + INSERT main t3 1 1 2 xyz + INSERT main t2 1 1 1 xyz + INSERT main t1 1 1 0 xyz +} +do_preupdate_test 7.6.3 { + UPDATE t1 SET x = 'abc'; +} { + UPDATE main t4 1 1 3 xyz abc + UPDATE main t3 1 1 2 xyz abc + UPDATE main t2 1 1 1 xyz abc + UPDATE main t1 1 1 0 xyz abc +} +do_preupdate_test 7.6.4 { + DELETE FROM t1 WHERE 1; +} { + DELETE main t4 1 1 3 abc + DELETE main t3 1 1 2 abc + DELETE main t2 1 1 1 abc + DELETE main t1 1 1 0 abc +} finish_test From b4480e942ff9480be5d60e5e1cca6b4d83181e2f Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 23 Mar 2011 16:03:11 +0000 Subject: [PATCH 034/570] Add the "indirect flag" to the changeset blob format. Also the sqlite3session_indirect() API. FossilOrigin-Name: 1feaf2d35fd9ec777319717ae2c2929d66fe7baa --- ext/session/session1.test | 44 ++++++------ ext/session/session2.test | 124 ++++++++++++++++++++++++++++++---- ext/session/sessionfault.test | 20 +++--- ext/session/sqlite3session.c | 72 +++++++++++++++----- ext/session/sqlite3session.h | 43 ++++++++++-- ext/session/test_session.c | 18 ++++- manifest | 22 +++--- manifest.uuid | 2 +- 8 files changed, 260 insertions(+), 85 deletions(-) diff --git a/ext/session/session1.test b/ext/session/session1.test index 1d8b1921b9..582f802bea 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -88,14 +88,14 @@ do_test 2.1.1 { execsql { INSERT INTO t1 VALUES(3, 'Thonburi') } } {} do_changeset_test 2.1.2 S { - {INSERT t1 {} {i 1 t Sukhothai}} - {INSERT t1 {} {i 2 t Ayutthaya}} - {INSERT t1 {} {i 3 t Thonburi}} + {INSERT t1 0 {} {i 1 t Sukhothai}} + {INSERT t1 0 {} {i 2 t Ayutthaya}} + {INSERT t1 0 {} {i 3 t Thonburi}} } do_changeset_invert_test 2.1.3 S { - {DELETE t1 {i 1 t Sukhothai} {}} - {DELETE t1 {i 2 t Ayutthaya} {}} - {DELETE t1 {i 3 t Thonburi} {}} + {DELETE t1 0 {i 1 t Sukhothai} {}} + {DELETE t1 0 {i 2 t Ayutthaya} {}} + {DELETE t1 0 {i 3 t Thonburi} {}} } do_test 2.1.4 { S delete } {} @@ -105,14 +105,14 @@ do_test 2.2.1 { execsql { DELETE FROM t1 WHERE 1 } } {} do_changeset_test 2.2.2 S { - {DELETE t1 {i 1 t Sukhothai} {}} - {DELETE t1 {i 2 t Ayutthaya} {}} - {DELETE t1 {i 3 t Thonburi} {}} + {DELETE t1 0 {i 1 t Sukhothai} {}} + {DELETE t1 0 {i 2 t Ayutthaya} {}} + {DELETE t1 0 {i 3 t Thonburi} {}} } do_changeset_invert_test 2.2.3 S { - {INSERT t1 {} {i 1 t Sukhothai}} - {INSERT t1 {} {i 2 t Ayutthaya}} - {INSERT t1 {} {i 3 t Thonburi}} + {INSERT t1 0 {} {i 1 t Sukhothai}} + {INSERT t1 0 {} {i 2 t Ayutthaya}} + {INSERT t1 0 {} {i 3 t Thonburi}} } do_test 2.2.4 { S delete } {} @@ -131,19 +131,19 @@ do_test 2.3.1 { } {} do_changeset_test 2.3.2 S { - {INSERT t1 {} {i 10 t Sukhothai}} - {DELETE t1 {i 1 t Sukhothai} {}} - {UPDATE t1 {i 2 t Ayutthaya} {{} {} t Surin}} - {DELETE t1 {i 3 t Thonburi} {}} - {INSERT t1 {} {i 20 t Thapae}} + {INSERT t1 0 {} {i 10 t Sukhothai}} + {DELETE t1 0 {i 1 t Sukhothai} {}} + {UPDATE t1 0 {i 2 t Ayutthaya} {{} {} t Surin}} + {DELETE t1 0 {i 3 t Thonburi} {}} + {INSERT t1 0 {} {i 20 t Thapae}} } do_changeset_invert_test 2.3.3 S { - {DELETE t1 {i 10 t Sukhothai} {}} - {INSERT t1 {} {i 1 t Sukhothai}} - {UPDATE t1 {{} {} t Surin} {i 2 t Ayutthaya}} - {INSERT t1 {} {i 3 t Thonburi}} - {DELETE t1 {i 20 t Thapae} {}} + {DELETE t1 0 {i 10 t Sukhothai} {}} + {INSERT t1 0 {} {i 1 t Sukhothai}} + {UPDATE t1 0 {{} {} t Surin} {i 2 t Ayutthaya}} + {INSERT t1 0 {} {i 3 t Thonburi}} + {DELETE t1 0 {i 20 t Thapae} {}} } do_test 2.3.4 { S delete } {} diff --git a/ext/session/session2.test b/ext/session/session2.test index d0d8fa5617..d6cb284659 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -41,13 +41,13 @@ do_iterator_test 1.1 t1 { DELETE FROM t1 WHERE a = 'i'; INSERT INTO t1 VALUES('ii', 'two'); } { - {DELETE t1 {t i t one} {}} - {INSERT t1 {} {t ii t two}} + {DELETE t1 0 {t i t one} {}} + {INSERT t1 0 {} {t ii t two}} } do_iterator_test 1.2 t1 { INSERT INTO t1 VALUES(1.5, 99.9) } { - {INSERT t1 {} {f 1.5 f 99.9}} + {INSERT t1 0 {} {f 1.5 f 99.9}} } @@ -228,15 +228,15 @@ foreach {tn sql changeset} { INSERT INTO t1 VALUES(NULL); INSERT INTO t1 VALUES(456); } { - {INSERT t1 {} {i 456}} - {INSERT t1 {} {i 123}} + {INSERT t1 0 {} {i 456}} + {INSERT t1 0 {} {i 123}} } 2 { UPDATE t1 SET a = NULL; } { - {DELETE t1 {i 456} {}} - {DELETE t1 {i 123} {}} + {DELETE t1 0 {i 456} {}} + {DELETE t1 0 {i 123} {}} } 3 { DELETE FROM t1 } { } @@ -244,14 +244,14 @@ foreach {tn sql changeset} { 4 { INSERT INTO t3 VALUES(NULL, NULL) } { - {INSERT t3 {} {n {} i 1}} + {INSERT t3 0 {} {n {} i 1}} } 5 { INSERT INTO t2 VALUES(1, 2, NULL) } { } 6 { INSERT INTO t2 VALUES(1, NULL, 3) } { } 7 { INSERT INTO t2 VALUES(1, NULL, NULL) } { } - 8 { INSERT INTO t2 VALUES(1, 2, 3) } { {INSERT t2 {} {i 1 i 2 i 3}} } - 9 { DELETE FROM t2 WHERE 1 } { {DELETE t2 {i 1 i 2 i 3} {}} } + 8 { INSERT INTO t2 VALUES(1, 2, 3) } { {INSERT t2 0 {} {i 1 i 2 i 3}} } + 9 { DELETE FROM t2 WHERE 1 } { {DELETE t2 0 {i 1 i 2 i 3} {}} } } { do_iterator_test 4.$tn {t1 t2 t3} $sql $changeset @@ -269,18 +269,112 @@ do_execsql_test 5.0 { } foreach {tn sql changeset} { - 1 { INSERT INTO t1 VALUES(35) } { {INSERT t1 {} {i 35}} } - 2 { INSERT INTO t2 VALUES(36, 37) } { {INSERT t2 {} {i 36 i 37}} } + 1 { INSERT INTO t1 VALUES(35) } { {INSERT t1 0 {} {i 35}} } + 2 { INSERT INTO t2 VALUES(36, 37) } { {INSERT t2 0 {} {i 36 i 37}} } 3 { DELETE FROM t1 WHERE 1; UPDATE t2 SET x = 34; } { - {UPDATE t2 {i 36 i 37} {i 34 {} {}}} - {DELETE t1 {i 35} {}} + {UPDATE t2 0 {i 36 i 37} {i 34 {} {}}} + {DELETE t1 0 {i 35} {}} } } { do_iterator_test 5.$tn * $sql $changeset } -finish_test +#------------------------------------------------------------------------- +# The next block of tests verify that the "indirect" flag is set +# correctly within changesets. The indirect flag is set for a change +# if either of the following are true: +# +# * The sqlite3session_indirect() API has been used to set the session +# indirect flag to true, or +# * The change was made by a trigger. +# +# If the same row is updated more than once during a session, then the +# change is considered indirect only if all changes meet the criteria +# above. +# +test_reset +db function indirect [list S indirect] +do_execsql_test 6.0 { + CREATE TABLE t1(a PRIMARY KEY, b, c); + + CREATE TABLE t2(x PRIMARY KEY, y); + CREATE TRIGGER AFTER INSERT ON t2 WHEN new.x%2 BEGIN + INSERT INTO t2 VALUES(new.x+1, NULL); + END; +} + +do_iterator_test 6.1.1 * { + INSERT INTO t1 VALUES(1, 'one', 'i'); + SELECT indirect(1); + INSERT INTO t1 VALUES(2, 'two', 'ii'); + SELECT indirect(0); + INSERT INTO t1 VALUES(3, 'three', 'iii'); +} { + {INSERT t1 0 {} {i 1 t one t i}} + {INSERT t1 1 {} {i 2 t two t ii}} + {INSERT t1 0 {} {i 3 t three t iii}} +} + +do_iterator_test 6.1.2 * { + SELECT indirect(1); + UPDATE t1 SET c = 'I' WHERE a = 1; + SELECT indirect(0); +} { + {UPDATE t1 1 {i 1 {} {} t i} {{} {} {} {} t I}} +} +do_iterator_test 6.1.3 * { + SELECT indirect(1); + UPDATE t1 SET c = '.' WHERE a = 1; + SELECT indirect(0); + UPDATE t1 SET c = 'o' WHERE a = 1; +} { + {UPDATE t1 0 {i 1 {} {} t I} {{} {} {} {} t o}} +} +do_iterator_test 6.1.4 * { + SELECT indirect(0); + UPDATE t1 SET c = 'x' WHERE a = 1; + SELECT indirect(1); + UPDATE t1 SET c = 'i' WHERE a = 1; +} { + {UPDATE t1 0 {i 1 {} {} t o} {{} {} {} {} t i}} +} +do_iterator_test 6.1.4 * { + SELECT indirect(1); + UPDATE t1 SET c = 'y' WHERE a = 1; + SELECT indirect(1); + UPDATE t1 SET c = 'I' WHERE a = 1; +} { + {UPDATE t1 1 {i 1 {} {} t i} {{} {} {} {} t I}} +} + +do_iterator_test 6.1.5 * { + INSERT INTO t2 VALUES(1, 'x'); +} { + {INSERT t2 0 {} {i 1 t x}} + {INSERT t2 1 {} {i 2 n {}}} +} + +do_iterator_test 6.1.6 * { + SELECT indirect(1); + INSERT INTO t2 VALUES(3, 'x'); + SELECT indirect(0); + UPDATE t2 SET y = 'y' WHERE x>2; +} { + {INSERT t2 0 {} {i 3 t y}} + {INSERT t2 0 {} {i 4 t y}} +} + +do_iterator_test 6.1.7 * { + SELECT indirect(1); + DELETE FROM t2 WHERE x = 4; + SELECT indirect(0); + INSERT INTO t2 VALUES(4, 'new'); +} { + {UPDATE t2 0 {i 4 t y} {{} {} t new}} +} + +finish_test diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index c8ce9e48af..04ac8b8b88 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -38,7 +38,7 @@ db2 close # Whereas test 1.2 passes NULL to sqlite3session_attach() to attach all # tables. # -do_faultsim_test pagerfault-1.1 -faults oom-* -prep { +do_faultsim_test 1.1 -faults oom-* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen @@ -55,7 +55,7 @@ do_faultsim_test pagerfault-1.1 -faults oom-* -prep { if {$testrc==0} { compare_db db db2 } } -do_faultsim_test pagerfault-1.2 -faults oom-* -prep { +do_faultsim_test 1.2 -faults oom-* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen @@ -82,7 +82,7 @@ do_faultsim_test pagerfault-1.2 -faults oom-* -prep { } #------------------------------------------------------------------------- -# The following block of tests - pagerfault-2.* - are designed to check +# The following block of tests - 2.* - are designed to check # the handling of faults in the sqlite3changeset_apply() function. # catch {db close} @@ -110,7 +110,7 @@ foreach {tn conflict_policy sql sql2} { } { proc xConflict args [list return $conflict_policy] - do_faultsim_test pagerfault-2.$tn -faults oom-transient -prep { + do_faultsim_test 2.$tn -faults oom-transient -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen @@ -132,7 +132,7 @@ foreach {tn conflict_policy sql sql2} { # resizing the session object hash-table from 256 to 512 buckets. This # is not an error, just a sub-optimal condition. # -do_faultsim_test pagerfault-3 -faults oom-* -prep { +do_faultsim_test 3 -faults oom-* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen @@ -191,7 +191,7 @@ do_test 4.0 { faultsim_save_and_close db2 close -do_faultsim_test pagerfault-4 -faults oom-* -prep { +do_faultsim_test 4 -faults oom-* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen @@ -234,7 +234,7 @@ set changeset [changeset_from_sql { }] db close -do_faultsim_test pagerfault-5 -faults oom* -body { +do_faultsim_test 5 -faults oom* -body { set ::inverse [sqlite3changeset_invert $::changeset] set {} {} } -test { @@ -243,9 +243,9 @@ do_faultsim_test pagerfault-5 -faults oom* -body { set x [list] sqlite3session_foreach c $::inverse { lappend x $c } foreach c { - {DELETE t1 {t xxx t yyy} {}} - {INSERT t1 {} {t string i 1}} - {UPDATE t1 {i 20 {} {}} {i 4 i 2}} + {DELETE t1 0 {t xxx t yyy} {}} + {INSERT t1 0 {} {t string i 1}} + {UPDATE t1 0 {i 20 {} {}} {i 4 i 2}} } { lappend y $c } if {$x != $y} { error "changeset no good" } } diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 3619e7c4b6..ff28487d3c 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -19,6 +19,7 @@ struct sqlite3_session { sqlite3 *db; /* Database handle session is attached to */ char *zDb; /* Name of database session is attached to */ int bEnable; /* True if currently recording */ + int bIndirect; /* True if all changes are indirect */ int bAutoAttach; /* True to auto-attach tables */ int rc; /* Non-zero if an error has occurred */ sqlite3_session *pNext; /* Next session object on same db. */ @@ -37,6 +38,7 @@ struct sqlite3_changeset_iter { char *zTab; /* Current table */ int nCol; /* Number of columns in zTab */ int op; /* Current operation */ + int bIndirect; /* True if current change was indirect */ sqlite3_value **apValue; /* old.* and new.* values */ }; @@ -131,6 +133,7 @@ struct SessionTable { */ struct SessionChange { int bInsert; /* True if row was inserted this session */ + int bIndirect; /* True if this change is "indirect" */ int nRecord; /* Number of bytes in buffer aRecord[] */ u8 *aRecord; /* Buffer containing old.* record */ SessionChange *pNext; /* For hash-table collisions */ @@ -660,8 +663,6 @@ static void sessionPreupdateOneChange( SessionTable *pTab ){ sqlite3 *db = pSession->db; - SessionChange *pChange; - SessionChange *pC; int iHash; int bNullPk = 0; int rc = SQLITE_OK; @@ -679,7 +680,8 @@ static void sessionPreupdateOneChange( ** the hash table. Otherwise, set pChange to NULL. */ rc = sessionPreupdateHash(db, pTab, op==SQLITE_INSERT, &iHash, &bNullPk); - if( bNullPk==0 ){ + if( rc==SQLITE_OK && bNullPk==0 ){ + SessionChange *pC; for(pC=pTab->apChange[iHash]; rc==SQLITE_OK && pC; pC=pC->pNext){ int bEqual; rc = sessionPreupdateEqual(db, pTab, pC, op==SQLITE_INSERT, &bEqual); @@ -689,9 +691,11 @@ static void sessionPreupdateOneChange( /* Create a new change object containing all the old values (if ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK ** values (if this is an INSERT). */ + SessionChange *pChange; /* New change object */ int nByte; /* Number of bytes to allocate */ int i; /* Used to iterate through columns */ + assert( rc==SQLITE_OK ); pTab->nEntry++; /* Figure out how large an allocation is required */ @@ -732,6 +736,9 @@ static void sessionPreupdateOneChange( } if( rc==SQLITE_OK ){ /* Add the change back to the hash-table */ + if( pSession->bIndirect || sqlite3_preupdate_depth(pSession->db) ){ + pChange->bIndirect = 1; + } pChange->nRecord = nByte; pChange->bInsert = (op==SQLITE_INSERT); pChange->pNext = pTab->apChange[iHash]; @@ -739,6 +746,12 @@ static void sessionPreupdateOneChange( }else{ sqlite3_free(pChange); } + }else if( rc==SQLITE_OK && pC->bIndirect ){ + /* If the existing change is considered "indirect", but this current + ** change is "direct", mark the change object as direct. */ + if( sqlite3_preupdate_depth(pSession->db)==0 && pSession->bIndirect==0 ){ + pC->bIndirect = 0; + } } } @@ -1136,6 +1149,7 @@ static void sessionAppendUpdate( u8 *pCsr = p->aRecord; /* Used to iterate through old.* values */ sessionAppendByte(pBuf, SQLITE_UPDATE, pRc); + sessionAppendByte(pBuf, p->bIndirect, pRc); for(i=0; ibInsert ){ sessionAppendByte(&buf, SQLITE_INSERT, &rc); + sessionAppendByte(&buf, p->bIndirect, &rc); for(iCol=0; iColbInsert ){ /* A DELETE change */ sessionAppendByte(&buf, SQLITE_DELETE, &rc); + sessionAppendByte(&buf, p->bIndirect, &rc); sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); } if( rc==SQLITE_OK ){ @@ -1416,6 +1432,20 @@ int sqlite3session_enable(sqlite3_session *pSession, int bEnable){ return ret; } +/* +** Enable or disable the session object passed as the first argument. +*/ +int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect){ + int ret; + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); + if( bIndirect>=0 ){ + pSession->bIndirect = bIndirect; + } + ret = pSession->bIndirect; + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); + return ret; +} + /* ** Create an iterator used to iterate through the contents of a changeset. */ @@ -1548,6 +1578,7 @@ int sqlite3changeset_next(sqlite3_changeset_iter *p){ p->zTab = (char *)aChange; aChange += (strlen((char *)aChange) + 1); p->op = *(aChange++); + p->bIndirect = *(aChange++); sqlite3_free(p->apValue); nByte = sizeof(sqlite3_value *) * p->nCol * 2; p->apValue = (sqlite3_value **)sqlite3_malloc(nByte); @@ -1557,6 +1588,7 @@ int sqlite3changeset_next(sqlite3_changeset_iter *p){ memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2); }else{ p->op = c; + p->bIndirect = *(aChange++); } if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){ return (p->rc = SQLITE_CORRUPT); @@ -1587,11 +1619,13 @@ int sqlite3changeset_op( sqlite3_changeset_iter *pIter, /* Iterator handle */ const char **pzTab, /* OUT: Pointer to table name */ int *pnCol, /* OUT: Number of columns in table */ - int *pOp /* OUT: SQLITE_INSERT, DELETE or UPDATE */ + int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */ + int *pbIndirect /* OUT: True if change is indirect */ ){ *pOp = pIter->op; *pnCol = pIter->nCol; *pzTab = pIter->zTab; + if( pbIndirect ) *pbIndirect = pIter->bIndirect; return SQLITE_OK; } @@ -1740,31 +1774,33 @@ int sqlite3changeset_invert( case SQLITE_INSERT: case SQLITE_DELETE: { int nByte; - u8 *aEnd = &aIn[i+1]; + u8 *aEnd = &aIn[i+2]; sessionReadRecord(&aEnd, nCol, 0); aOut[i] = (eType==SQLITE_DELETE ? SQLITE_INSERT : SQLITE_DELETE); - nByte = aEnd - &aIn[i+1]; - memcpy(&aOut[i+1], &aIn[i+1], nByte); - i += 1 + nByte; + aOut[i+1] = aIn[i+1]; + nByte = aEnd - &aIn[i+2]; + memcpy(&aOut[i+2], &aIn[i+2], nByte); + i += 2 + nByte; break; } case SQLITE_UPDATE: { int nByte1; /* Size of old.* record in bytes */ int nByte2; /* Size of new.* record in bytes */ - u8 *aEnd = &aIn[i+1]; + u8 *aEnd = &aIn[i+2]; sessionReadRecord(&aEnd, nCol, 0); - nByte1 = aEnd - &aIn[i+1]; + nByte1 = aEnd - &aIn[i+2]; sessionReadRecord(&aEnd, nCol, 0); - nByte2 = aEnd - &aIn[i+1] - nByte1; + nByte2 = aEnd - &aIn[i+2] - nByte1; aOut[i] = SQLITE_UPDATE; - memcpy(&aOut[i+1], &aIn[i+1+nByte1], nByte2); - memcpy(&aOut[i+1+nByte2], &aIn[i+1], nByte1); + aOut[i+1] = aIn[i+1]; + memcpy(&aOut[i+2], &aIn[i+2+nByte1], nByte2); + memcpy(&aOut[i+2+nByte2], &aIn[i+2], nByte1); - i += 1 + nByte1 + nByte2; + i += 2 + nByte1 + nByte2; break; } @@ -2097,7 +2133,7 @@ static int sessionSeekToRow( int op; /* Changset operation (SQLITE_UPDATE etc.) */ const char *zDummy; /* Unused */ - sqlite3changeset_op(pIter, &zDummy, &nCol, &op); + sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0); rc = sessionBindRow(pIter, op==SQLITE_INSERT ? sqlite3changeset_new : sqlite3changeset_old, nCol, abPK, pSelect @@ -2160,7 +2196,7 @@ static int sessionConflictHandler( int op; const char *zDummy; - sqlite3changeset_op(pIter, &zDummy, &nCol, &op); + sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0); assert( eType==SQLITE_CHANGESET_CONFLICT || eType==SQLITE_CHANGESET_DATA ); assert( SQLITE_CHANGESET_CONFLICT+1==SQLITE_CHANGESET_CONSTRAINT ); @@ -2248,7 +2284,7 @@ static int sessionApplyOneOp( assert( p->azCol && p->abPK ); assert( !pbReplace || *pbReplace==0 ); - sqlite3changeset_op(pIter, &zDummy, &nCol, &op); + sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0); if( op==SQLITE_DELETE ){ @@ -2362,7 +2398,7 @@ int sqlite3changeset_apply( int bReplace = 0; int bRetry = 0; const char *zNew; - sqlite3changeset_op(pIter, &zNew, &nCol, &op); + sqlite3changeset_op(pIter, &zNew, &nCol, &op, 0); if( zTab==0 || sqlite3_strnicmp(zNew, zTab, nTab+1) ){ sqlite3_free(sApply.azCol); diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index d9d0ae1f54..ee0402bffa 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -90,6 +90,35 @@ void sqlite3session_delete(sqlite3_session *pSession); */ int sqlite3session_enable(sqlite3_session *pSession, int bEnable); +/* +** CAPI3REF: Set Or Clear the Indirect Change Flag +** +** Each change recorded by a session object is marked as either direct or +** indirect. A change is marked as indirect if either: +** +**
    +**
  • The session object "indirect" flag is set when the change is +** made, or +**
  • The change is made by an SQL trigger or foreign key action +** instead of directly as a result of a users SQL statement. +**
+** +** If a single row is affected by more than one operation within a session, +** then the change is considered indirect if all operations meet the criteria +** for an indirect change above, or direct otherwise. +** +** This function is used to set, clear or query the session object indirect +** flag. If the second argument passed to this function is zero, then the +** indirect flag is cleared. If it is greater than zero, the indirect flag +** is set. Passing a value less than zero does not modify the current value +** of the indirect flag, and may be used to query the current state of the +** indirect flag for the specified session object. +** +** The return value indicates the final state of the indirect flag: 0 if +** it is clear, or 1 if it is set. +*/ +int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect); + /* ** CAPI3REF: Attach A Table To A Session Object ** @@ -292,10 +321,13 @@ int sqlite3changeset_next(sqlite3_changeset_iter *pIter); ** affected by the current change. The buffer remains valid until either ** sqlite3changeset_next() is called on the iterator or until the ** conflict-handler function returns. If pnCol is not NULL, then *pnCol is -** set to the number of columns in the table affected by the change. Finally, -** if pOp is not NULL, then *pOp is set to one of [SQLITE_INSERT], -** [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the type of change that -** the iterator currently points to. +** set to the number of columns in the table affected by the change. If +** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change +** is an indirect change, or false (0) otherwise. See the documentation for +** [sqlite3session_indirect()] for a description of direct and indirect +** changes. Finally, if pOp is not NULL, then *pOp is set to one of +** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the +** type of change that the iterator currently points to. ** ** If no error occurs, SQLITE_OK is returned. If an error does occur, an ** SQLite error code is returned. The values of the output variables may not @@ -305,7 +337,8 @@ int sqlite3changeset_op( sqlite3_changeset_iter *pIter, /* Iterator object */ const char **pzTab, /* OUT: Pointer to table name */ int *pnCol, /* OUT: Number of columns in table */ - int *pOp /* OUT: SQLITE_INSERT, DELETE or UPDATE */ + int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */ + int *pbIndirect /* OUT: True for an 'indirect' change */ ); /* diff --git a/ext/session/test_session.c b/ext/session/test_session.c index ecc07187d3..fee52d7f9c 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -17,6 +17,7 @@ static int test_session_error(Tcl_Interp *interp, int rc){ ** $session changeset ** $session delete ** $session enable BOOL +** $session indirect BOOL */ static int test_session_cmd( void *clientData, @@ -34,7 +35,8 @@ static int test_session_cmd( { "attach", 1, "TABLE", }, /* 0 */ { "changeset", 0, "", }, /* 1 */ { "delete", 0, "", }, /* 2 */ - { "enable", 1, "", }, /* 3 */ + { "enable", 1, "BOOL", }, /* 3 */ + { "indirect", 1, "BOOL", }, /* 4 */ { 0 } }; int iSub; @@ -88,6 +90,14 @@ static int test_session_cmd( Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val)); break; } + + case 4: { /* indirect */ + int val; + if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; + val = sqlite3session_indirect(pSession, val); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val)); + break; + } } return TCL_OK; @@ -205,7 +215,7 @@ static int test_conflict_handler( pEval = Tcl_DuplicateObj(p->pScript); Tcl_IncrRefCount(pEval); - sqlite3changeset_op(pIter, &zTab, &nCol, &op); + sqlite3changeset_op(pIter, &zTab, &nCol, &op, 0); /* Append the operation type. */ Tcl_ListObjAppendElement(0, pEval, Tcl_NewStringObj( @@ -396,8 +406,9 @@ static int test_sqlite3session_foreach( Tcl_Obj *pVar; /* Tcl value to set $VARNAME to */ Tcl_Obj *pOld; /* Vector of old.* values */ Tcl_Obj *pNew; /* Vector of new.* values */ + int bIndirect; - sqlite3changeset_op(pIter, &zTab, &nCol, &op); + sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect); pVar = Tcl_NewObj(); Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj( op==SQLITE_INSERT ? "INSERT" : @@ -405,6 +416,7 @@ static int test_sqlite3session_foreach( "DELETE", -1 )); Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zTab, -1)); + Tcl_ListObjAppendElement(0, pVar, Tcl_NewBooleanObj(bIndirect)); pOld = Tcl_NewObj(); if( op!=SQLITE_INSERT ){ diff --git a/manifest b/manifest index 20662eaa2f..1178e77cb3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sAPI\sfunction\ssqlite3_preupdate_depth(),\sfor\sdetermining\sthe\sdepth\sof\sthe\strigger\sstack\sfrom\swithin\sa\spre-update\scallback. -D 2011-03-22T18:45:30 +C Add\sthe\s"indirect\sflag"\sto\sthe\schangeset\sblob\sformat.\sAlso\sthe\ssqlite3session_indirect()\sAPI. +D 2011-03-23T16:03:12 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -99,13 +99,13 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/session1.test 1e8cda2cc8a60171dabc0fbec4124f9f7c943f23 -F ext/session/session2.test f993ee243db15025a7d9b1dae903fe3f82f04229 +F ext/session/session1.test bca38efbc34c0cdecc10e599246962860e3f664b +F ext/session/session2.test b0d305ee1397d7c17f9743126f636e97ddf88542 F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 -F ext/session/sessionfault.test 495f87fb9bd764ae90d4b40d0c33a76d86d9063e -F ext/session/sqlite3session.c ec0f440ae73229ae8ae307a31e631b9d71991cd4 -F ext/session/sqlite3session.h 5055e21ca0cb6ddacd46b773a15d90bc0298b0a2 -F ext/session/test_session.c d31fbf5902d0cff5e5495a5ce62efda77b596f2b +F ext/session/sessionfault.test 4489a49d2d44c74c24251d5802b2cc011dbdac21 +F ext/session/sqlite3session.c 0c2e8f6a6d9872943edd04d0a19bf7b05db9df83 +F ext/session/sqlite3session.h 000c1ed86322d9d8e8118cd5ba815269aac608f2 +F ext/session/test_session.c 0fcfbd51e3f5885b958fbc8cdd8cba01b85b8b16 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk ae0868e05c76eaa8a0ae3d6927a949b1c8e810d7 @@ -923,7 +923,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 183c236e991faaabdc768e52e926c52cf4a7abc9 -R 3714f49d9e3ab391fe868f9d204fa8d5 +P bdea70895c2c686a4dd3f4bf0a475fd1501d9551 +R c02abbe676895f559af6fe54b071c0da U dan -Z 4e2f4fe62e6298f01b15895da5c35a23 +Z 27e4954529d298836a72824c8b085018 diff --git a/manifest.uuid b/manifest.uuid index cf0cd54d72..f85c8efaad 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bdea70895c2c686a4dd3f4bf0a475fd1501d9551 \ No newline at end of file +1feaf2d35fd9ec777319717ae2c2929d66fe7baa \ No newline at end of file From 244593c8460bf9ab836921643a1ae94154c90989 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 24 Mar 2011 11:22:59 +0000 Subject: [PATCH 035/570] Store primary key definitions for modified tables in changesets. Add the sqlite3changeset_pk() API to extract this data from a changeset iterator. FossilOrigin-Name: 54298ee5ed183d1f1c49524f25e8ae1407f3d4b5 --- ext/session/session1.test | 44 ++++++++++++++--------------- ext/session/session2.test | 52 +++++++++++++++++------------------ ext/session/sessionfault.test | 6 ++-- ext/session/sqlite3session.c | 24 +++++++++++++++- ext/session/sqlite3session.h | 31 +++++++++++++++++++++ ext/session/test_session.c | 14 ++++++++++ manifest | 34 ++++++++--------------- manifest.uuid | 2 +- 8 files changed, 132 insertions(+), 75 deletions(-) diff --git a/ext/session/session1.test b/ext/session/session1.test index 582f802bea..4a2b50e6c6 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -88,14 +88,14 @@ do_test 2.1.1 { execsql { INSERT INTO t1 VALUES(3, 'Thonburi') } } {} do_changeset_test 2.1.2 S { - {INSERT t1 0 {} {i 1 t Sukhothai}} - {INSERT t1 0 {} {i 2 t Ayutthaya}} - {INSERT t1 0 {} {i 3 t Thonburi}} + {INSERT t1 0 X. {} {i 1 t Sukhothai}} + {INSERT t1 0 X. {} {i 2 t Ayutthaya}} + {INSERT t1 0 X. {} {i 3 t Thonburi}} } do_changeset_invert_test 2.1.3 S { - {DELETE t1 0 {i 1 t Sukhothai} {}} - {DELETE t1 0 {i 2 t Ayutthaya} {}} - {DELETE t1 0 {i 3 t Thonburi} {}} + {DELETE t1 0 X. {i 1 t Sukhothai} {}} + {DELETE t1 0 X. {i 2 t Ayutthaya} {}} + {DELETE t1 0 X. {i 3 t Thonburi} {}} } do_test 2.1.4 { S delete } {} @@ -105,14 +105,14 @@ do_test 2.2.1 { execsql { DELETE FROM t1 WHERE 1 } } {} do_changeset_test 2.2.2 S { - {DELETE t1 0 {i 1 t Sukhothai} {}} - {DELETE t1 0 {i 2 t Ayutthaya} {}} - {DELETE t1 0 {i 3 t Thonburi} {}} + {DELETE t1 0 X. {i 1 t Sukhothai} {}} + {DELETE t1 0 X. {i 2 t Ayutthaya} {}} + {DELETE t1 0 X. {i 3 t Thonburi} {}} } do_changeset_invert_test 2.2.3 S { - {INSERT t1 0 {} {i 1 t Sukhothai}} - {INSERT t1 0 {} {i 2 t Ayutthaya}} - {INSERT t1 0 {} {i 3 t Thonburi}} + {INSERT t1 0 X. {} {i 1 t Sukhothai}} + {INSERT t1 0 X. {} {i 2 t Ayutthaya}} + {INSERT t1 0 X. {} {i 3 t Thonburi}} } do_test 2.2.4 { S delete } {} @@ -131,19 +131,19 @@ do_test 2.3.1 { } {} do_changeset_test 2.3.2 S { - {INSERT t1 0 {} {i 10 t Sukhothai}} - {DELETE t1 0 {i 1 t Sukhothai} {}} - {UPDATE t1 0 {i 2 t Ayutthaya} {{} {} t Surin}} - {DELETE t1 0 {i 3 t Thonburi} {}} - {INSERT t1 0 {} {i 20 t Thapae}} + {INSERT t1 0 X. {} {i 10 t Sukhothai}} + {DELETE t1 0 X. {i 1 t Sukhothai} {}} + {UPDATE t1 0 X. {i 2 t Ayutthaya} {{} {} t Surin}} + {DELETE t1 0 X. {i 3 t Thonburi} {}} + {INSERT t1 0 X. {} {i 20 t Thapae}} } do_changeset_invert_test 2.3.3 S { - {DELETE t1 0 {i 10 t Sukhothai} {}} - {INSERT t1 0 {} {i 1 t Sukhothai}} - {UPDATE t1 0 {{} {} t Surin} {i 2 t Ayutthaya}} - {INSERT t1 0 {} {i 3 t Thonburi}} - {DELETE t1 0 {i 20 t Thapae} {}} + {DELETE t1 0 X. {i 10 t Sukhothai} {}} + {INSERT t1 0 X. {} {i 1 t Sukhothai}} + {UPDATE t1 0 X. {{} {} t Surin} {i 2 t Ayutthaya}} + {INSERT t1 0 X. {} {i 3 t Thonburi}} + {DELETE t1 0 X. {i 20 t Thapae} {}} } do_test 2.3.4 { S delete } {} diff --git a/ext/session/session2.test b/ext/session/session2.test index d6cb284659..a4776d80e5 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -41,13 +41,13 @@ do_iterator_test 1.1 t1 { DELETE FROM t1 WHERE a = 'i'; INSERT INTO t1 VALUES('ii', 'two'); } { - {DELETE t1 0 {t i t one} {}} - {INSERT t1 0 {} {t ii t two}} + {DELETE t1 0 X. {t i t one} {}} + {INSERT t1 0 X. {} {t ii t two}} } do_iterator_test 1.2 t1 { INSERT INTO t1 VALUES(1.5, 99.9) } { - {INSERT t1 0 {} {f 1.5 f 99.9}} + {INSERT t1 0 X. {} {f 1.5 f 99.9}} } @@ -228,15 +228,15 @@ foreach {tn sql changeset} { INSERT INTO t1 VALUES(NULL); INSERT INTO t1 VALUES(456); } { - {INSERT t1 0 {} {i 456}} - {INSERT t1 0 {} {i 123}} + {INSERT t1 0 X {} {i 456}} + {INSERT t1 0 X {} {i 123}} } 2 { UPDATE t1 SET a = NULL; } { - {DELETE t1 0 {i 456} {}} - {DELETE t1 0 {i 123} {}} + {DELETE t1 0 X {i 456} {}} + {DELETE t1 0 X {i 123} {}} } 3 { DELETE FROM t1 } { } @@ -244,14 +244,14 @@ foreach {tn sql changeset} { 4 { INSERT INTO t3 VALUES(NULL, NULL) } { - {INSERT t3 0 {} {n {} i 1}} + {INSERT t3 0 .X {} {n {} i 1}} } 5 { INSERT INTO t2 VALUES(1, 2, NULL) } { } 6 { INSERT INTO t2 VALUES(1, NULL, 3) } { } 7 { INSERT INTO t2 VALUES(1, NULL, NULL) } { } - 8 { INSERT INTO t2 VALUES(1, 2, 3) } { {INSERT t2 0 {} {i 1 i 2 i 3}} } - 9 { DELETE FROM t2 WHERE 1 } { {DELETE t2 0 {i 1 i 2 i 3} {}} } + 8 { INSERT INTO t2 VALUES(1, 2, 3) } { {INSERT t2 0 .XX {} {i 1 i 2 i 3}} } + 9 { DELETE FROM t2 WHERE 1 } { {DELETE t2 0 .XX {i 1 i 2 i 3} {}} } } { do_iterator_test 4.$tn {t1 t2 t3} $sql $changeset @@ -269,14 +269,14 @@ do_execsql_test 5.0 { } foreach {tn sql changeset} { - 1 { INSERT INTO t1 VALUES(35) } { {INSERT t1 0 {} {i 35}} } - 2 { INSERT INTO t2 VALUES(36, 37) } { {INSERT t2 0 {} {i 36 i 37}} } + 1 { INSERT INTO t1 VALUES(35) } { {INSERT t1 0 X {} {i 35}} } + 2 { INSERT INTO t2 VALUES(36, 37) } { {INSERT t2 0 .X {} {i 36 i 37}} } 3 { DELETE FROM t1 WHERE 1; UPDATE t2 SET x = 34; } { - {UPDATE t2 0 {i 36 i 37} {i 34 {} {}}} - {DELETE t1 0 {i 35} {}} + {UPDATE t2 0 .X {i 36 i 37} {i 34 {} {}}} + {DELETE t1 0 X {i 35} {}} } } { do_iterator_test 5.$tn * $sql $changeset @@ -314,9 +314,9 @@ do_iterator_test 6.1.1 * { SELECT indirect(0); INSERT INTO t1 VALUES(3, 'three', 'iii'); } { - {INSERT t1 0 {} {i 1 t one t i}} - {INSERT t1 1 {} {i 2 t two t ii}} - {INSERT t1 0 {} {i 3 t three t iii}} + {INSERT t1 0 X.. {} {i 1 t one t i}} + {INSERT t1 1 X.. {} {i 2 t two t ii}} + {INSERT t1 0 X.. {} {i 3 t three t iii}} } do_iterator_test 6.1.2 * { @@ -324,7 +324,7 @@ do_iterator_test 6.1.2 * { UPDATE t1 SET c = 'I' WHERE a = 1; SELECT indirect(0); } { - {UPDATE t1 1 {i 1 {} {} t i} {{} {} {} {} t I}} + {UPDATE t1 1 X.. {i 1 {} {} t i} {{} {} {} {} t I}} } do_iterator_test 6.1.3 * { SELECT indirect(1); @@ -332,7 +332,7 @@ do_iterator_test 6.1.3 * { SELECT indirect(0); UPDATE t1 SET c = 'o' WHERE a = 1; } { - {UPDATE t1 0 {i 1 {} {} t I} {{} {} {} {} t o}} + {UPDATE t1 0 X.. {i 1 {} {} t I} {{} {} {} {} t o}} } do_iterator_test 6.1.4 * { SELECT indirect(0); @@ -340,7 +340,7 @@ do_iterator_test 6.1.4 * { SELECT indirect(1); UPDATE t1 SET c = 'i' WHERE a = 1; } { - {UPDATE t1 0 {i 1 {} {} t o} {{} {} {} {} t i}} + {UPDATE t1 0 X.. {i 1 {} {} t o} {{} {} {} {} t i}} } do_iterator_test 6.1.4 * { SELECT indirect(1); @@ -348,14 +348,14 @@ do_iterator_test 6.1.4 * { SELECT indirect(1); UPDATE t1 SET c = 'I' WHERE a = 1; } { - {UPDATE t1 1 {i 1 {} {} t i} {{} {} {} {} t I}} + {UPDATE t1 1 X.. {i 1 {} {} t i} {{} {} {} {} t I}} } do_iterator_test 6.1.5 * { INSERT INTO t2 VALUES(1, 'x'); } { - {INSERT t2 0 {} {i 1 t x}} - {INSERT t2 1 {} {i 2 n {}}} + {INSERT t2 0 X. {} {i 1 t x}} + {INSERT t2 1 X. {} {i 2 n {}}} } do_iterator_test 6.1.6 * { @@ -364,8 +364,8 @@ do_iterator_test 6.1.6 * { SELECT indirect(0); UPDATE t2 SET y = 'y' WHERE x>2; } { - {INSERT t2 0 {} {i 3 t y}} - {INSERT t2 0 {} {i 4 t y}} + {INSERT t2 0 X. {} {i 3 t y}} + {INSERT t2 0 X. {} {i 4 t y}} } do_iterator_test 6.1.7 * { @@ -374,7 +374,7 @@ do_iterator_test 6.1.7 * { SELECT indirect(0); INSERT INTO t2 VALUES(4, 'new'); } { - {UPDATE t2 0 {i 4 t y} {{} {} t new}} + {UPDATE t2 0 X. {i 4 t y} {{} {} t new}} } finish_test diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index 04ac8b8b88..e1c2980b79 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -243,9 +243,9 @@ do_faultsim_test 5 -faults oom* -body { set x [list] sqlite3session_foreach c $::inverse { lappend x $c } foreach c { - {DELETE t1 0 {t xxx t yyy} {}} - {INSERT t1 0 {} {t string i 1}} - {UPDATE t1 0 {i 20 {} {}} {i 4 i 2}} + {DELETE t1 0 .X {t xxx t yyy} {}} + {INSERT t1 0 .X {} {t string i 1}} + {UPDATE t1 0 .X {i 20 {} {}} {i 4 i 2}} } { lappend y $c } if {$x != $y} { error "changeset no good" } } diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index ff28487d3c..4ab8bb32ce 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -39,6 +39,7 @@ struct sqlite3_changeset_iter { int nCol; /* Number of columns in zTab */ int op; /* Current operation */ int bIndirect; /* True if current change was indirect */ + u8 *abPK; /* Primary key array */ sqlite3_value **apValue; /* old.* and new.* values */ }; @@ -1357,6 +1358,7 @@ int sqlite3session_changeset( /* Write a table header */ sessionAppendByte(&buf, 'T', &rc); sessionAppendVarint(&buf, nCol, &rc); + sessionAppendBlob(&buf, pTab->abPK, nCol, &rc); sessionAppendBlob(&buf, (u8 *)zName, strlen(zName)+1, &rc); /* Build and compile a statement to execute: */ @@ -1575,6 +1577,8 @@ int sqlite3changeset_next(sqlite3_changeset_iter *p){ if( c=='T' ){ int nByte; /* Bytes to allocate for apValue */ aChange += sessionVarintGet(aChange, &p->nCol); + p->abPK = (u8 *)aChange; + aChange += p->nCol; p->zTab = (char *)aChange; aChange += (strlen((char *)aChange) + 1); p->op = *(aChange++); @@ -1611,7 +1615,7 @@ int sqlite3changeset_next(sqlite3_changeset_iter *p){ } /* -** The following three functions extract information on the current change +** The following function extracts information on the current change ** from a changeset iterator. They may only be called after changeset_next() ** has returned SQLITE_ROW. */ @@ -1629,6 +1633,16 @@ int sqlite3changeset_op( return SQLITE_OK; } +int sqlite3changeset_pk( + sqlite3_changeset_iter *pIter, /* Iterator object */ + unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */ + int *pnCol /* OUT: Number of entries in output array */ +){ + *pabPK = pIter->abPK; + if( pnCol ) *pnCol = pIter->nCol; + return SQLITE_OK; +} + /* ** This function may only be called while the iterator is pointing to an ** SQLITE_UPDATE or SQLITE_DELETE change (see sqlite3changeset_op()). @@ -1764,7 +1778,15 @@ int sqlite3changeset_invert( u8 eType = aIn[i]; switch( eType ){ case 'T': { + /* A 'table' record consists of: + ** + ** * A constant 'T' character, + ** * Number of columns in said table (a varint), + ** * An array of nCol bytes (abPK), + ** * A nul-terminated table name. + */ int nByte = 1 + sessionVarintGet(&aIn[i+1], &nCol); + nByte += nCol; nByte += 1 + strlen((char *)&aIn[i+nByte]); memcpy(&aOut[i], &aIn[i], nByte); i += nByte; diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index ee0402bffa..b6ea72522d 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -341,6 +341,37 @@ int sqlite3changeset_op( int *pbIndirect /* OUT: True for an 'indirect' change */ ); +/* +** CAPI3REF: Obtain The Primary Key Definition Of A Table +** +** For each modified table, a changeset includes the following: +** +**
    +**
  • The number of columns in the table, and +**
  • Which of those columns make up the tables PRIMARY KEY. +**
+** +** This function is used to find which columns comprise the PRIMARY KEY of +** the table modified by the change that iterator pIter currently points to. +** If successful, *pabPK is set to point to an array of nCol entries, where +** nCol is the number of columns in the table. Elements of *pabPK are set to +** 0x01 if the corresponding column is part of the tables primary key, or +** 0x00 if it is not. +** +** If argumet pnCol is not NULL, then *pnCol is set to the number of columns +** in the table. +** +** If this function is called when the iterator does not point to a valid +** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, +** SQLITE_OK is returned and the output variables populated as described +** above. +*/ +int sqlite3changeset_pk( + sqlite3_changeset_iter *pIter, /* Iterator object */ + unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */ + int *pnCol /* OUT: Number of entries in output array */ +); + /* ** CAPI3REF: Obtain old.* Values From A Changeset Iterator ** diff --git a/ext/session/test_session.c b/ext/session/test_session.c index fee52d7f9c..e3d6d60c22 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -408,6 +408,10 @@ static int test_sqlite3session_foreach( Tcl_Obj *pNew; /* Vector of new.* values */ int bIndirect; + char *zPK; + unsigned char *abPK; + int i; + sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect); pVar = Tcl_NewObj(); Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj( @@ -415,9 +419,19 @@ static int test_sqlite3session_foreach( op==SQLITE_UPDATE ? "UPDATE" : "DELETE", -1 )); + Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zTab, -1)); Tcl_ListObjAppendElement(0, pVar, Tcl_NewBooleanObj(bIndirect)); + zPK = ckalloc(nCol+1); + memset(zPK, 0, nCol+1); + sqlite3changeset_pk(pIter, &abPK, 0); + for(i=0; i Date: Thu, 24 Mar 2011 16:04:54 +0000 Subject: [PATCH 036/570] Fix handling of schema mismatches in sqlite3session.c so that it matches the docs in sqlite3session.h. FossilOrigin-Name: 506a0d7a710e1ff2f367821e73f5080fcf63fbc5 --- ext/session/session3.test | 88 ++++++++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 58 ++++++++++++++++++------ ext/session/sqlite3session.h | 2 +- manifest | 15 +++--- manifest.uuid | 2 +- 5 files changed, 142 insertions(+), 23 deletions(-) create mode 100644 ext/session/session3.test diff --git a/ext/session/session3.test b/ext/session/session3.test new file mode 100644 index 0000000000..e07032fccd --- /dev/null +++ b/ext/session/session3.test @@ -0,0 +1,88 @@ +# 2011 March 24 +# +# 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 the session module. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl + +set testprefix session3 + +# These tests - session3-1.* - verify that the session module behaves +# correctly when confronted with a schema mismatch when applying a +# changeset (in function sqlite3changeset_apply()). +# +# session3-1.1.*: Table does not exist in target db. +# session3-1.2.*: Table has wrong number of columns in target db. +# session3-1.3.*: Table has wrong PK columns in target db. +# + +db close +sqlite3_shutdown +test_sqlite3_log log +sqlite3 db test.db + +proc log {code msg} { lappend ::log $code $msg } + +forcedelete test.db2 +sqlite3 db2 test.db2 + +do_execsql_test 1.0 { + CREATE TABLE t1(a PRIMARY KEY, b); +} +do_test 1.1 { + set ::log {} + do_then_apply_sql { + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(3, 4); + } + set ::log +} {SQLITE_SCHEMA {sqlite3changeset_apply(): no such table: t1}} + +do_test 1.2.0 { + execsql { CREATE TABLE t1(a PRIMARY KEY, b, c) } db2 +} {} +do_test 1.2.1 { + set ::log {} + do_then_apply_sql { + INSERT INTO t1 VALUES(5, 6); + INSERT INTO t1 VALUES(7, 8); + } + set ::log +} {SQLITE_SCHEMA {sqlite3changeset_apply(): table t1 has 3 columns, expected 2}} + +do_test 1.3.0 { + execsql { + DROP TABLE t1; + CREATE TABLE t1(a, b PRIMARY KEY); + } db2 +} {} +do_test 1.3.1 { + set ::log {} + do_then_apply_sql { + INSERT INTO t1 VALUES(9, 10); + INSERT INTO t1 VALUES(11, 12); + } + set ::log +} {SQLITE_SCHEMA {sqlite3changeset_apply(): primary key mismatch for table t1}} + + +catch { db close } +catch { db2 close } +sqlite3_shutdown +test_sqlite3_log +sqlite3_initialize + +finish_test + diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 4ab8bb32ce..c64f567f90 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -544,7 +544,7 @@ static int sessionTableInfo( sqlite3 *db, /* Database connection */ const char *zDb, /* Name of attached database (e.g. "main") */ const char *zThis, /* Table name */ - int nCol, /* Expected number of columns */ + int *pnCol, /* OUT: number of columns */ const char **pzTab, /* OUT: Copy of zThis */ const char ***pazCol, /* OUT: Array of column names for table */ u8 **pabPK /* OUT: Array of booleans - true for PK col */ @@ -577,9 +577,6 @@ static int sessionTableInfo( } rc = sqlite3_reset(pStmt); - if( nDbCol!=nCol ){ - rc = SQLITE_SCHEMA; - } if( rc==SQLITE_OK ){ nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1); pAlloc = sqlite3_malloc(nByte); @@ -589,9 +586,9 @@ static int sessionTableInfo( } if( rc==SQLITE_OK ){ azCol = (char **)pAlloc; - pAlloc = (u8 *)&azCol[nCol]; + pAlloc = (u8 *)&azCol[nDbCol]; abPK = (u8 *)pAlloc; - pAlloc = &abPK[nCol]; + pAlloc = &abPK[nDbCol]; if( pzTab ){ memcpy(pAlloc, zThis, nThis+1); *pzTab = (char *)pAlloc; @@ -619,9 +616,11 @@ static int sessionTableInfo( if( rc==SQLITE_OK ){ *pazCol = (const char **)azCol; *pabPK = abPK; + *pnCol = nDbCol; }else{ *pazCol = 0; *pabPK = 0; + *pnCol = 0; if( pzTab ) *pzTab = 0; sqlite3_free(azCol); } @@ -648,11 +647,13 @@ static int sessionTableInfo( static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ if( pTab->nCol==0 ){ assert( pTab->azCol==0 || pTab->abPK==0 ); - pTab->nCol = sqlite3_preupdate_count(pSession->db); pSession->rc = sessionTableInfo(pSession->db, pSession->zDb, - pTab->zName, pTab->nCol, 0, &pTab->azCol, &pTab->abPK + pTab->zName, &pTab->nCol, 0, &pTab->azCol, &pTab->abPK ); - }else if( pTab->nCol!=sqlite3_preupdate_count(pSession->db) ){ + } + if( pSession->rc==SQLITE_OK + && pTab->nCol!=sqlite3_preupdate_count(pSession->db) + ){ pSession->rc = SQLITE_SCHEMA; } return pSession->rc; @@ -2402,6 +2403,7 @@ int sqlite3changeset_apply( ), void *pCtx /* First argument passed to xConflict */ ){ + int schemaMismatch = 0; sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ int rc; /* Return code */ const char *zTab = 0; /* Name of current table */ @@ -2420,9 +2422,13 @@ int sqlite3changeset_apply( int bReplace = 0; int bRetry = 0; const char *zNew; + sqlite3changeset_op(pIter, &zNew, &nCol, &op, 0); if( zTab==0 || sqlite3_strnicmp(zNew, zTab, nTab+1) ){ + u8 *abPK; + + schemaMismatch = 0; sqlite3_free(sApply.azCol); sqlite3_finalize(sApply.pDelete); sqlite3_finalize(sApply.pUpdate); @@ -2430,23 +2436,47 @@ int sqlite3changeset_apply( sqlite3_finalize(sApply.pSelect); memset(&sApply, 0, sizeof(sApply)); sApply.db = db; - sApply.nCol = nCol; + sqlite3changeset_pk(pIter, &abPK, 0); rc = sessionTableInfo( - db, "main", zNew, nCol, &zTab, &sApply.azCol, &sApply.abPK); + db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK + ); + if( rc!=SQLITE_OK ) break; - if( rc!=SQLITE_OK - || (rc = sessionSelectRow(db, zTab, &sApply)) + if( sApply.nCol==0 ){ + schemaMismatch = 1; + sqlite3_log(SQLITE_SCHEMA, + "sqlite3changeset_apply(): no such table: %s", zTab + ); + } + else if( sApply.nCol!=nCol ){ + schemaMismatch = 1; + sqlite3_log(SQLITE_SCHEMA, + "sqlite3changeset_apply(): table %s has %d columns, expected %d", + zTab, sApply.nCol, nCol + ); + } + else if( memcmp(sApply.abPK, abPK, nCol)!=0 ){ + schemaMismatch = 1; + sqlite3_log(SQLITE_SCHEMA, + "sqlite3changeset_apply(): primary key mismatch for table %s", zTab + ); + } + else if( + (rc = sessionSelectRow(db, zTab, &sApply)) || (rc = sessionUpdateRow(db, zTab, &sApply)) || (rc = sessionDeleteRow(db, zTab, &sApply)) || (rc = sessionInsertRow(db, zTab, &sApply)) ){ break; } - nTab = strlen(zTab); } + /* If there is a schema mismatch on the current table, proceed to the + ** next change. A log message has already been issued. */ + if( schemaMismatch ) continue; + rc = sessionApplyOneOp(pIter, &sApply, xConflict, pCtx, &bReplace, &bRetry); if( rc==SQLITE_OK && bRetry ){ diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index b6ea72522d..5d19379ec8 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -48,7 +48,7 @@ typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; ** ** The session object will be used to create changesets for tables in ** database zDb, where zDb is either "main", or "temp", or the name of an -** attached database. It is not an error if database zDb does not exist +** attached database. It is not an error if database zDb is not attached ** to the database when the session object is created. */ int sqlite3session_create( diff --git a/manifest b/manifest index edccb68924..e59c27fb75 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Store\sprimary\skey\sdefinitions\sfor\smodified\stables\sin\schangesets.\sAdd\sthe\ssqlite3changeset_pk()\sAPI\sto\sextract\sthis\sdata\sfrom\sa\schangeset\siterator. -D 2011-03-24T11:22:59 +C Fix\shandling\sof\sschema\smismatches\sin\ssqlite3session.c\sso\sthat\sit\smatches\sthe\sdocs\sin\ssqlite3session.h. +D 2011-03-24T16:04:55 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -101,10 +101,11 @@ F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test b2da15b9d727d7f4e5fe95599b32b92d93b5a970 F ext/session/session2.test 8da094318ac88953478c43d0bfb0aa723ee0e379 +F ext/session/session3.test b8b9ff7efcb19234892c406dba8bd56792560efe F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 F ext/session/sessionfault.test d7e6154a30e85622d0733b1a1e3c63e9b8b7004b -F ext/session/sqlite3session.c 886827f10de75576baf9f9d860414fa155e1c8c1 -F ext/session/sqlite3session.h 8d3e00c0a2e323e6f47b1204ec9ff714ca3bee4a +F ext/session/sqlite3session.c cf91fe0efb0728c219c8bc2b2174a49758fbd3f8 +F ext/session/sqlite3session.h 900d900bb6a827f84754fc252a05638e0f413a6e F ext/session/test_session.c e0f500ec5e20478afc2c7998133e8acea7ec5104 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -923,7 +924,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 9c3a6e479988e96086bef00c79dbce508a14da0d -R f502a856cffb82507c875b00a2fb9d4d +P 54298ee5ed183d1f1c49524f25e8ae1407f3d4b5 +R 73cd0f1e5ce098769e9cee2c7d1f1ebc U dan -Z 3fdb3d84abab55a6e9fe1eeceb839a7c +Z 8a40e5171d2567a1ae6ca1b697973f9a diff --git a/manifest.uuid b/manifest.uuid index 12934424cd..e8475cfcd0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -54298ee5ed183d1f1c49524f25e8ae1407f3d4b5 \ No newline at end of file +506a0d7a710e1ff2f367821e73f5080fcf63fbc5 \ No newline at end of file From a9605b912552c6d6b33c787917d79187fbf4c3ce Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 24 Mar 2011 16:53:57 +0000 Subject: [PATCH 037/570] Fix handling of schema changes mid-session. FossilOrigin-Name: 76d2d2ad3b2a5171393b7894f35f463ff284e53b --- ext/session/session3.test | 92 +++++++++++++++++++++++++++++++++++- ext/session/sqlite3session.c | 14 ++++-- manifest | 14 +++--- manifest.uuid | 2 +- 4 files changed, 110 insertions(+), 12 deletions(-) diff --git a/ext/session/session3.test b/ext/session/session3.test index e07032fccd..d0d2c31fa4 100644 --- a/ext/session/session3.test +++ b/ext/session/session3.test @@ -19,6 +19,7 @@ source $testdir/tester.tcl set testprefix session3 +#------------------------------------------------------------------------- # These tests - session3-1.* - verify that the session module behaves # correctly when confronted with a schema mismatch when applying a # changeset (in function sqlite3changeset_apply()). @@ -27,7 +28,6 @@ set testprefix session3 # session3-1.2.*: Table has wrong number of columns in target db. # session3-1.3.*: Table has wrong PK columns in target db. # - db close sqlite3_shutdown test_sqlite3_log log @@ -77,6 +77,96 @@ do_test 1.3.1 { set ::log } {SQLITE_SCHEMA {sqlite3changeset_apply(): primary key mismatch for table t1}} +#------------------------------------------------------------------------- +# These tests - session3-2.* - verify that the session module behaves +# correctly when the schema of an attached table is modified during the +# session. +# +# session3-2.1.*: Table is dropped midway through the session. +# session3-2.2.*: Table is dropped and recreated with a different # cols. +# session3-2.3.*: Table is dropped and recreated with a different PK. +# +# In all of these scenarios, the call to sqlite3session_changeset() will +# return SQLITE_SCHEMA. Also: +# +# session3-2.4.*: Table is dropped and recreated with an identical schema. +# In this case sqlite3session_changeset() returns SQLITE_OK. +# + +do_test 2.1 { + execsql { CREATE TABLE t2(a, b PRIMARY KEY) } + sqlite3session S db main + S attach t2 + execsql { + INSERT INTO t2 VALUES(1, 2); + DROP TABLE t2; + } + list [catch { S changeset } msg] $msg +} {1 SQLITE_SCHEMA} + +do_test 2.2.1 { + S delete + sqlite3session S db main + execsql { CREATE TABLE t2(a, b PRIMARY KEY, c) } + S attach t2 + execsql { + INSERT INTO t2 VALUES(1, 2, 3); + DROP TABLE t2; + CREATE TABLE t2(a, b PRIMARY KEY); + } + list [catch { S changeset } msg] $msg +} {1 SQLITE_SCHEMA} + +do_test 2.2.2 { + S delete + sqlite3session S db main + execsql { + DROP TABLE t2; + CREATE TABLE t2(a, b PRIMARY KEY, c); + } + S attach t2 + execsql { + INSERT INTO t2 VALUES(1, 2, 3); + DROP TABLE t2; + CREATE TABLE t2(a, b PRIMARY KEY, c, d); + } + list [catch { S changeset } msg] $msg +} {1 SQLITE_SCHEMA} + +do_test 2.3 { + S delete + sqlite3session S db main + execsql { + DROP TABLE t2; + CREATE TABLE t2(a, b PRIMARY KEY); + } + S attach t2 + execsql { + INSERT INTO t2 VALUES(1, 2); + DROP TABLE t2; + CREATE TABLE t2(a PRIMARY KEY, b, c); + } + list [catch { S changeset } msg] $msg +} {1 SQLITE_SCHEMA} + +do_test 2.4 { + S delete + sqlite3session S db main + execsql { + DROP TABLE t2; + CREATE TABLE t2(a, b PRIMARY KEY); + } + S attach t2 + execsql { + INSERT INTO t2 VALUES(1, 2); + DROP TABLE t2; + CREATE TABLE t2(a, b PRIMARY KEY); + } + list [catch { S changeset } msg] $msg +} {0 {}} + +S delete + catch { db close } catch { db2 close } diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index c64f567f90..ffc2e13f5e 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1349,13 +1349,20 @@ int sqlite3session_changeset( for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ if( pTab->nEntry ){ const char *zName = pTab->zName; - int nCol = pTab->nCol; /* Local copy of member variable */ - u8 *abPK = pTab->abPK; /* Local copy of member variable */ + int nCol; /* Number of columns in table */ + u8 *abPK; /* Primary key array */ + const char **azCol = 0; /* Table columns */ int i; /* Used to iterate through hash buckets */ sqlite3_stmt *pSel = 0; /* SELECT statement to query table pTab */ int nRewind = buf.nBuf; /* Initial size of write buffer */ int nNoop; /* Size of buffer after writing tbl header */ + /* Check the table schema is still Ok. */ + rc = sessionTableInfo(db, pSession->zDb, zName, &nCol, 0, &azCol, &abPK); + if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){ + rc = SQLITE_SCHEMA; + } + /* Write a table header */ sessionAppendByte(&buf, 'T', &rc); sessionAppendVarint(&buf, nCol, &rc); @@ -1365,7 +1372,7 @@ int sqlite3session_changeset( /* Build and compile a statement to execute: */ if( rc==SQLITE_OK ){ rc = sessionSelectStmt( - db, pSession->zDb, zName, nCol, pTab->azCol, abPK, &pSel); + db, pSession->zDb, zName, nCol, azCol, abPK, &pSel); } if( rc==SQLITE_OK && nCol!=sqlite3_column_count(pSel) ){ @@ -1407,6 +1414,7 @@ int sqlite3session_changeset( if( buf.nBuf==nNoop ){ buf.nBuf = nRewind; } + sqlite3_free(azCol); } } diff --git a/manifest b/manifest index e59c27fb75..1f7e7a7bdd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\shandling\sof\sschema\smismatches\sin\ssqlite3session.c\sso\sthat\sit\smatches\sthe\sdocs\sin\ssqlite3session.h. -D 2011-03-24T16:04:55 +C Fix\shandling\sof\sschema\schanges\smid-session. +D 2011-03-24T16:53:57 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -101,10 +101,10 @@ F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test b2da15b9d727d7f4e5fe95599b32b92d93b5a970 F ext/session/session2.test 8da094318ac88953478c43d0bfb0aa723ee0e379 -F ext/session/session3.test b8b9ff7efcb19234892c406dba8bd56792560efe +F ext/session/session3.test c58ebb3273a23da9b5f4eb202d522aa759530a4c F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 F ext/session/sessionfault.test d7e6154a30e85622d0733b1a1e3c63e9b8b7004b -F ext/session/sqlite3session.c cf91fe0efb0728c219c8bc2b2174a49758fbd3f8 +F ext/session/sqlite3session.c 33a5d4be9c22099aed8e7f6c80b63540953e84c2 F ext/session/sqlite3session.h 900d900bb6a827f84754fc252a05638e0f413a6e F ext/session/test_session.c e0f500ec5e20478afc2c7998133e8acea7ec5104 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 @@ -924,7 +924,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 54298ee5ed183d1f1c49524f25e8ae1407f3d4b5 -R 73cd0f1e5ce098769e9cee2c7d1f1ebc +P 506a0d7a710e1ff2f367821e73f5080fcf63fbc5 +R 3234ab73592ecae31c60c0a6f501bbfd U dan -Z 8a40e5171d2567a1ae6ca1b697973f9a +Z 29af2cd6e2d7044fdb214ebc342ad1ba diff --git a/manifest.uuid b/manifest.uuid index e8475cfcd0..5f9877e0ed 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -506a0d7a710e1ff2f367821e73f5080fcf63fbc5 \ No newline at end of file +76d2d2ad3b2a5171393b7894f35f463ff284e53b \ No newline at end of file From f51e5f6c9950c9ed0efcbca08608f462bb4db0ed Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 25 Mar 2011 10:52:01 +0000 Subject: [PATCH 038/570] Improve coverage of session module code. FossilOrigin-Name: 666123c8d07be87d477e67b1cebef2b0fba5b4bc --- ext/session/session2.test | 145 +++++++++++++++++++++++++++++++++++ ext/session/session3.test | 6 +- ext/session/session4.test | 62 +++++++++++++++ ext/session/sqlite3session.c | 3 +- ext/session/sqlite3session.h | 3 + ext/session/test_session.c | 57 +++++++++++--- manifest | 21 ++--- manifest.uuid | 2 +- 8 files changed, 274 insertions(+), 25 deletions(-) create mode 100644 ext/session/session4.test diff --git a/ext/session/session2.test b/ext/session/session2.test index a4776d80e5..6662173d49 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -377,4 +377,149 @@ do_iterator_test 6.1.7 * { {UPDATE t2 0 X. {i 4 t y} {{} {} t new}} } +sqlite3session S db main +do_execsql_test 6.2.1 { + SELECT indirect(0); + SELECT indirect(-1); + SELECT indirect(45); + SELECT indirect(-100); +} {0 0 1 1} +S delete + +#------------------------------------------------------------------------- +# Test that if a conflict-handler that has been passed either NOTFOUND or +# CONSTRAINT returns REPLACE - the sqlite3changeset_apply() call returns +# MISUSE and rolls back any changes made so far. +# +# 7.1.*: NOTFOUND conflict-callback. +# 7.2.*: CONSTRAINT conflict-callback. +# +proc xConflict {args} {return REPLACE} +test_reset + +do_execsql_test 7.1.1 { + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES(1, 'one'); + INSERT INTO t1 VALUES(2, 'two'); +} +do_test 7.1.2 { + execsql { + CREATE TABLE t1(a PRIMARY KEY, b NOT NULL); + INSERT INTO t1 VALUES(1, 'one'); + } db2 +} {} +do_test 7.1.3 { + set changeset [changeset_from_sql { + UPDATE t1 SET b = 'five' WHERE a = 1; + UPDATE t1 SET b = 'six' WHERE a = 2; + }] + set x [list] + sqlite3session_foreach c $changeset { lappend x $c } + set x +} [list \ + {UPDATE t1 0 X. {i 1 t one} {{} {} t five}} \ + {UPDATE t1 0 X. {i 2 t two} {{} {} t six}} \ +] +do_test 7.1.4 { + list [catch {sqlite3changeset_apply db2 $changeset xConflict} msg] $msg +} {1 SQLITE_MISUSE} +do_test 7.1.5 { execsql { SELECT * FROM t1 } db2 } {1 one} + +do_test 7.2.1 { + set changeset [changeset_from_sql { UPDATE t1 SET b = NULL WHERE a = 1 }] + + set x [list] + sqlite3session_foreach c $changeset { lappend x $c } + set x +} [list \ + {UPDATE t1 0 X. {i 1 t five} {{} {} n {}}} \ +] +do_test 7.2.2 { + list [catch {sqlite3changeset_apply db2 $changeset xConflict} msg] $msg +} {1 SQLITE_MISUSE} +do_test 7.2.3 { execsql { SELECT * FROM t1 } db2 } {1 one} + +#------------------------------------------------------------------------- +# Test that if a conflict-handler returns ABORT, application of the +# changeset is rolled back and the sqlite3changeset_apply() method returns +# SQLITE_ABORT. +# +# Also test that the same thing happens if a conflict handler returns an +# unrecognized integer value. Except, in this case SQLITE_MISUSE is returned +# instead of SQLITE_ABORT. +# +foreach {tn conflict_return apply_return} { + 1 ABORT SQLITE_ABORT + 2 567 SQLITE_MISUSE +} { + test_reset + proc xConflict {args} [list return $conflict_return] + + do_test 8.$tn.0 { + do_common_sql { + CREATE TABLE t1(x, y, PRIMARY KEY(x, y)); + INSERT INTO t1 VALUES('x', 'y'); + } + execsql { INSERT INTO t1 VALUES('w', 'w') } + + set changeset [changeset_from_sql { DELETE FROM t1 WHERE 1 }] + + set x [list] + sqlite3session_foreach c $changeset { lappend x $c } + set x + } [list \ + {DELETE t1 0 XX {t w t w} {}} \ + {DELETE t1 0 XX {t x t y} {}} \ + ] + + do_test 8.$tn.1 { + list [catch {sqlite3changeset_apply db2 $changeset xConflict} msg] $msg + } [list 1 $apply_return] + + do_test 8.$tn.2 { + execsql {SELECT * FROM t1} db2 + } {x y} +} + + +#------------------------------------------------------------------------- +# Try to cause an infinite loop as follows: +# +# 1. Have a changeset insert a row that causes a CONFLICT callback, +# 2. Have the conflict handler return REPLACE, +# 3. After the session module deletes the conflicting row, have a trigger +# re-insert it. +# 4. Goto step 1... +# +# This doesn't work, as the second invocation of the conflict handler is a +# CONSTRAINT, not a CONFLICT. There is at most one CONFLICT callback for +# each change in the changeset. +# +test_reset +proc xConflict {type args} { + if {$type == "CONFLICT"} { return REPLACE } + return OMIT +} +do_test 9.1 { + execsql { + CREATE TABLE t1(a PRIMARY KEY, b); + } + execsql { + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES('x', 2); + CREATE TRIGGER tr1 AFTER DELETE ON t1 BEGIN + INSERT INTO t1 VALUES(old.a, old.b); + END; + } db2 +} {} +do_test 9.2 { + set changeset [changeset_from_sql { INSERT INTO t1 VALUES('x', 1) }] + sqlite3changeset_apply db2 $changeset xConflict +} {} +do_test 9.3 { + execsql { SELECT * FROM t1 } db2 +} {x 2} + + + finish_test diff --git a/ext/session/session3.test b/ext/session/session3.test index d0d2c31fa4..a0946f3099 100644 --- a/ext/session/session3.test +++ b/ext/session/session3.test @@ -8,8 +8,10 @@ # May you share freely, never taking more than you give. # #*********************************************************************** -# This file implements regression tests for the session module. -# +# This file implements regression tests for the session module. More +# specifically, it focuses on testing the session modules response to +# database schema modifications and mismatches. +# if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] diff --git a/ext/session/session4.test b/ext/session/session4.test new file mode 100644 index 0000000000..c69fa85fc4 --- /dev/null +++ b/ext/session/session4.test @@ -0,0 +1,62 @@ +# 2011 March 25 +# +# 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 the session module. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl + +set testprefix session4 + +do_test 1.0 { + execsql { + CREATE TABLE x(a, b, c, d, e, PRIMARY KEY(c, e)); + INSERT INTO x VALUES(65.21, X'28B0', 16.35, NULL, 'doers'); + INSERT INTO x VALUES(NULL, 78.49, 2, X'60', -66); + INSERT INTO x VALUES('cathedral', NULL, 35, NULL, X'B220937E80A2D8'); + INSERT INTO x VALUES(NULL, 'masking', -91.37, NULL, X'596D'); + INSERT INTO x VALUES(19, 'domains', 'espouse', -94, 'throw'); + } + + sqlite3session S db main + set changeset [changeset_from_sql { + DELETE FROM x WHERE e = -66; + UPDATE x SET a = 'parameterizable', b = 31.8 WHERE c = 35; + INSERT INTO x VALUES(-75.61, -17, 16.85, NULL, X'D73DB02678'); + }] + set {} {} +} {} + + +# This currently causes crashes. sqlite3changeset_invert() does not handle +# corrupt changesets well. +if 0 { + do_test 1.1 { + for {set i 0} {$i < [string length $changeset]} {incr i} { + set before [string range $changeset 0 [expr $i-1]] + set after [string range $changeset [expr $i+1] end] + for {set j 10} {$j < 260} {incr j} { + set x [binary format "a*ca*" $before $j $after] + catch { sqlite3changeset_invert $x } + } + } + } {} +} + +do_test 1.2 { + set x [binary format "ca*" 0 [string range $changeset 1 end]] + list [catch { sqlite3changeset_invert $x } msg] $msg +} {1 SQLITE_CORRUPT} + +finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index ffc2e13f5e..36d83e6b8e 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2255,7 +2255,8 @@ static int sessionConflictHandler( if( rc==SQLITE_OK ){ switch( res ){ case SQLITE_CHANGESET_REPLACE: - if( pbReplace ) *pbReplace = 1; + assert( pbReplace ); + *pbReplace = 1; break; case SQLITE_CHANGESET_OMIT: diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 5d19379ec8..bcb901667c 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -513,6 +513,9 @@ int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); ** It is the responsibility of the caller to eventually call sqlite3_free() ** on the *ppOut pointer to free the buffer allocation following a successful ** call to this function. +** +** WARNING/TODO: This function currently assumes that the input is a valid +** changeset. If it is not, the results are undefined. */ int sqlite3changeset_invert( int nIn, void *pIn, /* Input changeset */ diff --git a/ext/session/test_session.c b/ext/session/test_session.c index e3d6d60c22..4befd0fe68 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -17,7 +17,7 @@ static int test_session_error(Tcl_Interp *interp, int rc){ ** $session changeset ** $session delete ** $session enable BOOL -** $session indirect BOOL +** $session indirect INTEGER */ static int test_session_cmd( void *clientData, @@ -93,7 +93,7 @@ static int test_session_cmd( case 4: { /* indirect */ int val; - if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &val) ) return TCL_ERROR; val = sqlite3session_indirect(pSession, val); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val)); break; @@ -268,18 +268,59 @@ static int test_conflict_handler( } /* If this is a CHANGESET_DATA or CHANGESET_CONFLICT conflict, append - ** the conflicting row. */ + ** the conflicting row. */ if( eConf==SQLITE_CHANGESET_DATA || eConf==SQLITE_CHANGESET_CONFLICT ){ int i; Tcl_Obj *pConflict = Tcl_NewObj(); for(i=0; i Date: Fri, 25 Mar 2011 19:06:09 +0000 Subject: [PATCH 039/570] Improve coverage of session module a bit more. FossilOrigin-Name: 4255a9f609c4fd43582a0874143eabe211199726 --- ext/session/session2.test | 38 ++++++++++++++++++++ ext/session/session3.test | 2 +- ext/session/session4.test | 5 +++ ext/session/sessionfault.test | 4 +-- ext/session/sqlite3session.c | 66 +++++++++++++++++------------------ ext/session/test_session.c | 6 ++-- manifest | 22 ++++++------ manifest.uuid | 2 +- 8 files changed, 94 insertions(+), 51 deletions(-) diff --git a/ext/session/session2.test b/ext/session/session2.test index 6662173d49..7adbfd5b6f 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -44,12 +44,24 @@ do_iterator_test 1.1 t1 { {DELETE t1 0 X. {t i t one} {}} {INSERT t1 0 X. {} {t ii t two}} } + do_iterator_test 1.2 t1 { INSERT INTO t1 VALUES(1.5, 99.9) } { {INSERT t1 0 X. {} {f 1.5 f 99.9}} } +do_iterator_test 1.3 t1 { + UPDATE t1 SET b = 100.1 WHERE a = 1.5; + UPDATE t1 SET b = 99.9 WHERE a = 1.5; +} { } + +do_iterator_test 1.4 t1 { + UPDATE t1 SET b = 100.1 WHERE a = 1.5; +} { + {UPDATE t1 0 X. {f 1.5 f 99.9} {{} {} f 100.1}} +} + # Execute each of the following blocks of SQL on database [db1]. Collect # changes using a session object. Apply the resulting changeset to @@ -520,6 +532,32 @@ do_test 9.3 { execsql { SELECT * FROM t1 } db2 } {x 2} +#------------------------------------------------------------------------- +# +test_reset +db function enable [list S enable] +do_common_sql { + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES('x', 'X'); +} + +do_iterator_test 10.1 t1 { + INSERT INTO t1 VALUES('y', 'Y'); + SELECT enable(0); + INSERT INTO t1 VALUES('z', 'Z'); + SELECT enable(1); +} { + {INSERT t1 0 X. {} {t y t Y}} +} + +sqlite3session S db main +do_execsql_test 10.2 { + SELECT enable(0); + SELECT enable(-1); + SELECT enable(1); + SELECT enable(-1); +} {0 0 1 1} +S delete finish_test diff --git a/ext/session/session3.test b/ext/session/session3.test index a0946f3099..c7046d9c8f 100644 --- a/ext/session/session3.test +++ b/ext/session/session3.test @@ -146,7 +146,7 @@ do_test 2.3 { execsql { INSERT INTO t2 VALUES(1, 2); DROP TABLE t2; - CREATE TABLE t2(a PRIMARY KEY, b, c); + CREATE TABLE t2(a PRIMARY KEY, b); } list [catch { S changeset } msg] $msg } {1 SQLITE_SCHEMA} diff --git a/ext/session/session4.test b/ext/session/session4.test index c69fa85fc4..f695c2e467 100644 --- a/ext/session/session4.test +++ b/ext/session/session4.test @@ -59,4 +59,9 @@ do_test 1.2 { list [catch { sqlite3changeset_invert $x } msg] $msg } {1 SQLITE_CORRUPT} +do_test 1.3 { + set x [binary format "ca*" 0 [string range $changeset 1 end]] + list [catch { sqlite3changeset_apply db $x xConflict } msg] $msg +} {1 SQLITE_CORRUPT} + finish_test diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index e1c2980b79..cf155f4f3d 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -45,7 +45,7 @@ do_faultsim_test 1.1 -faults oom-* -prep { sqlite3 db2 test.db2 } -body { do_then_apply_sql { - INSERT INTO t1 VALUES(7, 8, 9); + INSERT INTO t1 VALUES('a string value', 8, 9); UPDATE t1 SET c = 10 WHERE a = 1; DELETE FROM t1 WHERE a = 4; } @@ -63,7 +63,7 @@ do_faultsim_test 1.2 -faults oom-* -prep { sqlite3session S db main S attach * execsql { - INSERT INTO t1 VALUES(7, 8, 9); + INSERT INTO t1 VALUES('a string value', 8, 9); UPDATE t1 SET c = 10 WHERE a = 1; DELETE FROM t1 WHERE a = 4; } diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 36d83e6b8e..75385e5f2e 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1181,10 +1181,10 @@ static void sessionAppendUpdate( break; } - case SQLITE_TEXT: - case SQLITE_BLOB: { + default: { int nByte; int nHdr = 1 + sessionVarintGet(&pCsr[1], &nByte); + assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); nAdvance = nHdr + nByte; if( eType==sqlite3_column_type(pStmt, i) && nByte==sqlite3_column_bytes(pStmt, i) @@ -1260,19 +1260,18 @@ static int sessionSelectBind( sqlite3_stmt *pSelect, int nCol, u8 *abPK, - u8 *aRecord, - int nRecord + SessionChange *pChange ){ int i; int rc = SQLITE_OK; - u8 *a = aRecord; + u8 *a = pChange->aRecord; for(i=0; irc; + + if( pSession->rc ) return pSession->rc; + rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0); + if( rc!=SQLITE_OK ) return rc; + + sqlite3_mutex_enter(sqlite3_db_mutex(db)); for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ if( pTab->nEntry ){ @@ -1375,37 +1378,31 @@ int sqlite3session_changeset( db, pSession->zDb, zName, nCol, azCol, abPK, &pSel); } - if( rc==SQLITE_OK && nCol!=sqlite3_column_count(pSel) ){ - rc = SQLITE_SCHEMA; - } - nNoop = buf.nBuf; for(i=0; inChange && rc==SQLITE_OK; i++){ SessionChange *p; /* Used to iterate through changes */ for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ - rc = sessionSelectBind(pSel, nCol, abPK, p->aRecord, p->nRecord); - if( rc==SQLITE_OK ){ - if( sqlite3_step(pSel)==SQLITE_ROW ){ - int iCol; - if( p->bInsert ){ - sessionAppendByte(&buf, SQLITE_INSERT, &rc); - sessionAppendByte(&buf, p->bIndirect, &rc); - for(iCol=0; iColbInsert ){ - /* A DELETE change */ - sessionAppendByte(&buf, SQLITE_DELETE, &rc); + rc = sessionSelectBind(pSel, nCol, abPK, p); + if( sqlite3_step(pSel)==SQLITE_ROW ){ + int iCol; + if( p->bInsert ){ + sessionAppendByte(&buf, SQLITE_INSERT, &rc); sessionAppendByte(&buf, p->bIndirect, &rc); - sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_reset(pSel); + for(iCol=0; iColbInsert ){ + /* A DELETE change */ + sessionAppendByte(&buf, SQLITE_DELETE, &rc); + sessionAppendByte(&buf, p->bIndirect, &rc); + sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_reset(pSel); } } } @@ -1425,6 +1422,7 @@ int sqlite3session_changeset( sqlite3_free(buf.aBuf); } + sqlite3_exec(db, "RELEASE changeset", 0, 0, 0); sqlite3_mutex_leave(sqlite3_db_mutex(db)); return rc; } diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 4befd0fe68..a8b73824a0 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -85,7 +85,7 @@ static int test_session_cmd( case 3: { /* enable */ int val; - if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &val) ) return TCL_ERROR; val = sqlite3session_enable(pSession, val); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val)); break; @@ -436,6 +436,7 @@ static int test_sqlite3session_foreach( while( SQLITE_ROW==sqlite3changeset_next(pIter) ){ int nCol; /* Number of columns in table */ + int nCol2; /* Number of columns in table */ int op; /* SQLITE_INSERT, UPDATE or DELETE */ const char *zTab; /* Name of table change applies to */ Tcl_Obj *pVar; /* Tcl value to set $VARNAME to */ @@ -460,7 +461,8 @@ static int test_sqlite3session_foreach( zPK = ckalloc(nCol+1); memset(zPK, 0, nCol+1); - sqlite3changeset_pk(pIter, &abPK, 0); + sqlite3changeset_pk(pIter, &abPK, &nCol2); + assert( nCol==nCol2 ); for(i=0; i Date: Wed, 30 Mar 2011 17:07:47 +0000 Subject: [PATCH 040/570] Add documentation to the sqlite3_preupdate_hook() interface and its relatives. FossilOrigin-Name: 8180f2881fa970429e28d4f3258a56cfaabbcabd --- manifest | 12 ++++---- manifest.uuid | 2 +- src/sqlite.h.in | 81 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 81 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index b427fcf551..35fb6c6035 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sin\sall\sthe\slatest\schanges\sfrom\strunk. -D 2011-03-30T02:03:12.567 +C Add\sdocumentation\sto\sthe\ssqlite3_preupdate_hook()\sinterface\sand\sits\srelatives. +D 2011-03-30T17:07:47.319 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -187,7 +187,7 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 9dc0b4bb59290c0a35256d278cab0f314987ad6a -F src/sqlite.h.in 73512de44f0d3563dd24be2e701542e52c7efe25 +F src/sqlite.h.in 3fef17a4201b068291da874b42599b9e61c0cf68 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 F src/sqliteInt.h 7c11f9a648cf82e87330fd2185fcaa1f7c46dfba F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 @@ -929,7 +929,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 4255a9f609c4fd43582a0874143eabe211199726 3d2de011814002e2e25b7645f94ff8fc7aab9cdd -R 48b479c7a408c0c8015c6f938b7e92a4 +P b11d941e92897663da46160185e6e305d4e28fe6 +R e37cfb6574f4ec186f2c67ceafeda97a U drh -Z 1cd943e96dc4b8cfc7720b21a63156f8 +Z ede135d544f338afa66b4a4b2184647f diff --git a/manifest.uuid b/manifest.uuid index c6b7c703a4..9a70869e00 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b11d941e92897663da46160185e6e305d4e28fe6 \ No newline at end of file +8180f2881fa970429e28d4f3258a56cfaabbcabd \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 42ce94be21..c3dc70168f 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -1129,7 +1129,7 @@ int sqlite3_config(int, ...); ** [database connection] (specified in the first argument). ** ** The second argument to sqlite3_db_config(D,V,...) is the -** [SQLITE_DBCONIG_LOOKASIDE | configuration verb] - an integer code +** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code ** that indicates what aspect of the [database connection] is being configured. ** Subsequent arguments vary depending on the configuration verb. ** @@ -4263,8 +4263,8 @@ void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); ** on the same [database connection] D, or NULL for ** the first call on D. ** -** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] -** interfaces. +** See also the [sqlite3_commit_hook()], [sqlite3_rollback_hook()], +** and [sqlite3_preupdate_hook()] interfaces. */ void *sqlite3_update_hook( sqlite3*, @@ -6390,10 +6390,77 @@ int sqlite3_wal_checkpoint_v2( /* ** CAPI3REF: The pre-update hook. -** -** The preupdate_old() API may only be used from within an SQLITE_UPDATE or -** SQLITE_DELETE pre-update callback. The preupdate_modified() API may only -** be used from within an SQLITE_UPDATE pre-update callback. +** EXPERIMENTAL +** +** ^The [sqlite3_preupdate_hook()] interface registers a callback function +** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation. +** ^At most one preupdate hook may be registered at a time on a single +** [database connection]; each call to [sqlite3_preupdate_hook()] overrides +** the previous setting. +** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()] +** with a NULL pointer as the second parameter. +** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as +** the first parameter to callbacks. +** +** ^The preupdate hook only fires for changes to real tables; the preupdate +** hook is not invoked for changes to virtual tables. +** +** ^The second parameter to the preupdate callback is a pointer to +** the [database connection] that registered the preupdate hook. +** ^The third parameter to the preupdate callback is one of the constants +** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to indentify the +** kind of update operation that is about to occur. +** ^(The fourth parameter to the preupdate callback is the name of the +** database within the database connection that is being modified. This +** will be "main" for the main database or "temp" for TEMP tables or +** the name given after the AS keyword in the [ATTACH] statement for attached +** databases.)^ +** ^The fifth parameter to the preupdate callback is the name of the +** table that is being modified. +** ^The sixth parameter to the preupdate callback is the initial [rowid] of the +** row being changes for SQLITE_UPDATE and SQLITE_DELETE changes and is +** undefined for SQLITE_INSERT changes. +** ^The seventh parameter to the preupdate callback is the final [rowid] of +** the row being changed for SQLITE_UPDATE and SQLITE_INSERT changes and is +** undefined for SQLITE_DELETE changes. +** +** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()], +** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces +** provide additional information about a preupdate event. These routines +** may only be called from within a preupdate callback. Invoking any of +** these routines from outside of a preupdate callback or with a +** [database connection] pointer that is different from the one supplied +** to the preupdate callback results in undefined and probably undesirable +** behavior. +** +** ^The [sqlite3_preupdate_count(D)] interface returns the number of columns +** in the row that is being inserted, updated, or deleted. +** +** ^The [sqlite3_preupdate_old(D,N,P)] interface writes into P a pointer to +** a [protected sqlite3_value] that contains the value of the Nth column of +** the table row before it is updated. The N parameter must be between 0 +** and one less than the number of columns or the behavior will be +** undefined. This must only be used within SQLITE_UPDATE and SQLITE_DELETE +** preupdate callbacks; if it is used by an SQLITE_INSERT callback then the +** behavior is undefined. The [sqlite3_value] that P points to +** will be destroyed when the preupdate callback returns. +** +** ^The [sqlite3_preupdate_new(D,N,P)] interface writes into P a pointer to +** a [protected sqlite3_value] that contains the value of the Nth column of +** the table row after it is updated. The N parameter must be between 0 +** and one less than the number of columns or the behavior will be +** undefined. This must only be used within SQLITE_INSERT and SQLITE_UPDATE +** preupdate callbacks; if it is used by an SQLITE_DELETE callback then the +** behavior is undefined. The [sqlite3_value] that P points to +** will be destroyed when the preupdate callback returns. +** +** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate +** callback was invoked as a result of a direct insert, update, or delete +** operation; or 1 for inserts, updates, or deletes invoked by top-level +** triggers; or 2 for changes resulting from triggers called by top-level +** triggers; and so forth. +** +** See also: [sqlite3_update_hook()] */ SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook( sqlite3 *db, From 67c495ac207665a2ac0becee02f067487bf75918 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 30 Mar 2011 17:25:35 +0000 Subject: [PATCH 041/570] Disable the truncate optimization if there is a preupdate hook. FossilOrigin-Name: d051694e024c590e4687cae1368f900799b7442d --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/delete.c | 9 +++++++-- test/hook.test | 9 ++++----- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 35fb6c6035..6ebb88896d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sdocumentation\sto\sthe\ssqlite3_preupdate_hook()\sinterface\sand\sits\srelatives. -D 2011-03-30T17:07:47.319 +C Disable\sthe\struncate\soptimization\sif\sthere\sis\sa\spreupdate\shook. +D 2011-03-30T17:25:35.303 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -138,7 +138,7 @@ F src/callback.c 5069f224882cbdccd559f591271d28d7f37745bc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01 F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b -F src/delete.c c55748a1628b54c8785de0ff4bd9cbe27fe111cb +F src/delete.c 4aebb9ccea435701c137bf25e07fe93ad8e9346d F src/expr.c 00817c672af554321fd67c44325afd7cef0e4648 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 418b840007c873975fd0d071746d952f8bca20ce @@ -485,7 +485,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c -F test/hook.test 14b2439b878c9aae03a3684cba717be4bfdcc1c1 +F test/hook.test 29a0b6a18111835bdca827f62a7975a8e30a1dd5 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 @@ -929,7 +929,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P b11d941e92897663da46160185e6e305d4e28fe6 -R e37cfb6574f4ec186f2c67ceafeda97a +P 8180f2881fa970429e28d4f3258a56cfaabbcabd +R 7bdc0a7971e68baabbe152ea44f74530 U drh -Z ede135d544f338afa66b4a4b2184647f +Z a923e72061e5acce879b548f79bb9c49 diff --git a/manifest.uuid b/manifest.uuid index 9a70869e00..15b385f496 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8180f2881fa970429e28d4f3258a56cfaabbcabd \ No newline at end of file +d051694e024c590e4687cae1368f900799b7442d \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index a5d00263b5..71a243d5a6 100644 --- a/src/delete.c +++ b/src/delete.c @@ -338,8 +338,13 @@ void sqlite3DeleteFrom( /* Special case: A DELETE without a WHERE clause deletes everything. ** It is easier just to erase the whole table. Prior to version 3.6.5, ** this optimization caused the row change count (the value returned by - ** API function sqlite3_count_changes) to be set incorrectly. */ - if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) + ** API function sqlite3_count_changes) to be set incorrectly. + */ + if( rcauth==SQLITE_OK + && pWhere==0 + && !pTrigger + && !IsVirtual(pTab) + && db->xPreUpdateCallback==0 && 0==sqlite3FkRequired(pParse, pTab, 0, 0) ){ assert( !isView ); diff --git a/test/hook.test b/test/hook.test index 016569f0ae..5cceaf9abf 100644 --- a/test/hook.test +++ b/test/hook.test @@ -481,10 +481,10 @@ do_preupdate_test 7.2.1 { do_preupdate_test 7.2.2 { DELETE FROM t1 } { - DELETE main t3 1 1 1 1 - DELETE main t3 2 2 b a - DELETE main t3 4 4 a b - DELETE main t3 5 5 c d + DELETE main t1 1 1 1 1 + DELETE main t1 2 2 b a + DELETE main t1 4 4 a b + DELETE main t1 5 5 c d } do_execsql_test 7.3.0 { @@ -765,4 +765,3 @@ do_preupdate_test 7.6.4 { } finish_test - From 9b1c62d4166694136cd472e4498e2c77045a881c Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 30 Mar 2011 21:04:43 +0000 Subject: [PATCH 042/570] Add the SQLITE_ENABLE_PREUPDATE_HOOK compile-time option. FossilOrigin-Name: 6634521461e6acff7cc778590e62d57831f9230d --- ext/session/session1.test | 2 +- ext/session/session2.test | 1 + ext/session/session3.test | 2 +- ext/session/session4.test | 1 + ext/session/sqlite3session.c | 4 ++-- ext/session/test_session.c | 6 ++--- manifest | 46 ++++++++++++++++++------------------ manifest.uuid | 2 +- src/delete.c | 2 ++ src/insert.c | 2 ++ src/main.c | 2 ++ src/sqlite.h.in | 3 +++ src/sqliteInt.h | 2 ++ src/tclsqlite.c | 14 ++++++++--- src/test_config.c | 6 +++++ src/update.c | 4 ++-- src/vdbe.c | 18 ++++++++++++-- src/vdbeapi.c | 8 +++++++ src/vdbeaux.c | 4 +++- test/hook.test | 5 ++++ 20 files changed, 95 insertions(+), 39 deletions(-) diff --git a/ext/session/session1.test b/ext/session/session1.test index 4a2b50e6c6..067432affa 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -16,6 +16,7 @@ if {![info exists testdir]} { } source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl +ifcapable !session {finish_test; return} set testprefix session1 @@ -444,4 +445,3 @@ do_db2_test 6.3 "SELECT * FROM t2" {a b A B} catch { db2 close } finish_test - diff --git a/ext/session/session2.test b/ext/session/session2.test index 7adbfd5b6f..5c7ea47d5f 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -17,6 +17,7 @@ if {![info exists testdir]} { } source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl +ifcapable !session {finish_test; return} set testprefix session2 diff --git a/ext/session/session3.test b/ext/session/session3.test index c7046d9c8f..c0fcebff66 100644 --- a/ext/session/session3.test +++ b/ext/session/session3.test @@ -18,6 +18,7 @@ if {![info exists testdir]} { } source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl +ifcapable !session {finish_test; return} set testprefix session3 @@ -177,4 +178,3 @@ test_sqlite3_log sqlite3_initialize finish_test - diff --git a/ext/session/session4.test b/ext/session/session4.test index f695c2e467..8e179baf6d 100644 --- a/ext/session/session4.test +++ b/ext/session/session4.test @@ -16,6 +16,7 @@ if {![info exists testdir]} { } source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl +ifcapable !session {finish_test; return} set testprefix session4 diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 75385e5f2e..70acb76056 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1,5 +1,5 @@ -#ifdef SQLITE_ENABLE_SESSION +#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK) #include "sqlite3session.h" #include @@ -2533,4 +2533,4 @@ int sqlite3changeset_apply( return rc; } -#endif /* #ifdef SQLITE_ENABLE_SESSION */ +#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ diff --git a/ext/session/test_session.c b/ext/session/test_session.c index a8b73824a0..6af1892150 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -1,5 +1,6 @@ -#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_SESSION) +#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_SESSION) \ + && defined(SQLITE_ENABLE_PREUPDATE_HOOK) #include "sqlite3session.h" #include @@ -519,5 +520,4 @@ int TestSession_Init(Tcl_Interp *interp){ return TCL_OK; } -#endif - +#endif /* SQLITE_TEST && SQLITE_SESSION && SQLITE_PREUPDATE_HOOK */ diff --git a/manifest b/manifest index 6ebb88896d..dddc79360d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Disable\sthe\struncate\soptimization\sif\sthere\sis\sa\spreupdate\shook. -D 2011-03-30T17:25:35.303 +C Add\sthe\sSQLITE_ENABLE_PREUPDATE_HOOK\scompile-time\soption. +D 2011-03-30T21:04:43.055 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -99,15 +99,15 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/session1.test b2da15b9d727d7f4e5fe95599b32b92d93b5a970 -F ext/session/session2.test e36222e1f48bc9b1d80eacd001994d307c107e73 -F ext/session/session3.test 919f7e2e07fa5a166a0ea5d8ac3fbe7f38f7e447 -F ext/session/session4.test a37bc9d8891ea1f3e120056c978f66c925f040b9 +F ext/session/session1.test 7a92a2a6f531aef1e9764ffb7f983fb8b315376d +F ext/session/session2.test c3e5f78d5eb988e35cc2ba9ce3678f706283cfdb +F ext/session/session3.test bfa2376db7cbb2ac69496f84d93a8d81b13110d3 +F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 F ext/session/sessionfault.test 2544a2e2ecad56e3c07a32c09799871d243c114c -F ext/session/sqlite3session.c 9be8ccee4248681700659b89a81ae5c6cb8afacc +F ext/session/sqlite3session.c eaf093c81f076301cfd04f794d047cf7beffd290 F ext/session/sqlite3session.h f284bac51c12de0e0096fc986e61f5ae6b9e5be5 -F ext/session/test_session.c f8fdf5c110898b2bbc20c475fca879664c77fb5a +F ext/session/test_session.c 82e3fd7d94f485ea63bcfb15d636c95a01db97a9 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk e283752f215b7055cdc48399da82033b67024e42 @@ -138,7 +138,7 @@ F src/callback.c 5069f224882cbdccd559f591271d28d7f37745bc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01 F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b -F src/delete.c 4aebb9ccea435701c137bf25e07fe93ad8e9346d +F src/delete.c 44800af91a90f9d9445a266129313f27487614d8 F src/expr.c 00817c672af554321fd67c44325afd7cef0e4648 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 418b840007c873975fd0d071746d952f8bca20ce @@ -147,12 +147,12 @@ F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c c46747b4bdde2ae4c2815526a151fefb66ba64a6 +F src/insert.c e354eadb2ca3e8d939ba928f229e2268974f380c F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e F src/loadext.c 8af9fcc75708d60b88636ccba38b4a7b3c155c3e -F src/main.c 2563bd9ca8430c7677d375c566b54b890aaf508f +F src/main.c bed41512fabb19492b61d37fd988d79f6225e624 F src/malloc.c 92d59a007d7a42857d4e9454aa25b6b703286be1 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206 @@ -187,13 +187,13 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 9dc0b4bb59290c0a35256d278cab0f314987ad6a -F src/sqlite.h.in 3fef17a4201b068291da874b42599b9e61c0cf68 +F src/sqlite.h.in 235300cdca517ce148385d3ab816e7e8cf9e1ff3 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h 7c11f9a648cf82e87330fd2185fcaa1f7c46dfba +F src/sqliteInt.h 14325fe41ee564f064adacda02ab64837fa905c4 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e -F src/tclsqlite.c c233c25153b6fa3b511bc65df352cb8f97a0f81d +F src/tclsqlite.c 8376ae45f7e28d521ad708a0086771fab3c96475 F src/test1.c 9020310c7617234b33fd1c3064f89524db25f290 F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc @@ -207,7 +207,7 @@ F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2 -F src/test_config.c e9a4ce02dec5bcced1c13e0cf8b72edfd5903d74 +F src/test_config.c 3050df9faf023fb52937f7e9998004c2415d4122 F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5 @@ -237,15 +237,15 @@ F src/test_vfstrace.c 2265c9895f350c8d3c39b079998fbe7481505cc1 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080 F src/trigger.c ec4813709e990a169b6923293e839fa5dfd64282 -F src/update.c f81e9b326cafba3fbe493141e396f3bbfba1d99b +F src/update.c 3f3f3bb734a0da1dffd0ed33e504642b35ed3605 F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60 F src/util.c cd997077bad039efc0597eb027c929658f93c018 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c 175a42d0f12b92093a7335402dbb46bfe7e360b0 +F src/vdbe.c 4784ded3d2c97f8084a17cacbeea490a0dccf75e F src/vdbe.h edef9c4f0be83e1f1dccd049da37b40e021b63d9 F src/vdbeInt.h b6748a8ac9be169d83585a0f5daf747863c6b8db -F src/vdbeapi.c e472b3e5985175e948e70025cb3bffa8a2e185c8 -F src/vdbeaux.c 051a1609e578418d1bfc6d2420b8eb412a7aea97 +F src/vdbeapi.c 7ef519083e3420bf7793d8b4eae2961d894d98ab +F src/vdbeaux.c b526e30d7a5d5b8b18408b2ec077e7286df2f6dc F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -485,7 +485,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c -F test/hook.test 29a0b6a18111835bdca827f62a7975a8e30a1dd5 +F test/hook.test 040cf2ca263f192c66b358e095138dad0a9d75bb F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 @@ -929,7 +929,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 8180f2881fa970429e28d4f3258a56cfaabbcabd -R 7bdc0a7971e68baabbe152ea44f74530 +P d051694e024c590e4687cae1368f900799b7442d +R c057f780dc1cba178107219ab6b28dc8 U drh -Z a923e72061e5acce879b548f79bb9c49 +Z 598e11d1b0eff48f657d073c9eb1f2dc diff --git a/manifest.uuid b/manifest.uuid index 15b385f496..c3c451f694 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d051694e024c590e4687cae1368f900799b7442d \ No newline at end of file +6634521461e6acff7cc778590e62d57831f9230d \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index 71a243d5a6..8a44d12247 100644 --- a/src/delete.c +++ b/src/delete.c @@ -344,7 +344,9 @@ void sqlite3DeleteFrom( && pWhere==0 && !pTrigger && !IsVirtual(pTab) +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK && db->xPreUpdateCallback==0 +#endif && 0==sqlite3FkRequired(pParse, pTab, 0, 0) ){ assert( !isView ); diff --git a/src/insert.c b/src/insert.c index cf48d0ffe7..364e68460f 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1286,12 +1286,14 @@ void sqlite3GenerateConstraintChecks( pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace ); }else{ +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* This OP_Delete opcode fires the pre-update-hook only. It does ** not modify the b-tree. It is more efficient to let the coming ** OP_Insert replace the existing entry than it is to delete the ** existing entry and then insert a new one. */ sqlite3VdbeAddOp2(v, OP_Delete, baseCur, OPFLAG_ISNOOP); sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE); +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ if( pTab->pIndex ){ sqlite3MultiWrite(pParse); sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0); diff --git a/src/main.c b/src/main.c index 9ccd657e79..21991c558f 100644 --- a/src/main.c +++ b/src/main.c @@ -1306,6 +1306,7 @@ void *sqlite3_rollback_hook( return pRet; } +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** Register a callback to be invoked each time a row is updated, ** inserted or deleted using this database connection. @@ -1324,6 +1325,7 @@ void *sqlite3_preupdate_hook( sqlite3_mutex_leave(db->mutex); return pRet; } +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ #ifndef SQLITE_OMIT_WAL /* diff --git a/src/sqlite.h.in b/src/sqlite.h.in index c3dc70168f..3daf72cd36 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6392,6 +6392,9 @@ int sqlite3_wal_checkpoint_v2( ** CAPI3REF: The pre-update hook. ** EXPERIMENTAL ** +** ^These interfaces are only available if SQLite is compiled using the +** [SQLITE_ENABLE_UPDATE_HOOK] compile-time option. +** ** ^The [sqlite3_preupdate_hook()] interface registers a callback function ** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation. ** ^At most one preupdate hook may be registered at a time on a single diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a15b8bff1c..d31ed4ae6f 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -829,11 +829,13 @@ struct sqlite3 { void (*xRollbackCallback)(void*); /* Invoked at every commit. */ void *pUpdateArg; void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK void *pPreUpdateArg; /* First argument to xPreUpdateCallback */ void (*xPreUpdateCallback)( /* Registered using sqlite3_preupdate_hook() */ void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64 ); PreUpdate *pPreUpdate; /* Context for active pre-update callback */ +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ #ifndef SQLITE_OMIT_WAL int (*xWalCallback)(void *, sqlite3 *, const char *, int); void *pWalArg; diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 93c5118372..de0e992bd4 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -653,6 +653,7 @@ static void DbUnlockNotify(void **apArg, int nArg){ } #endif +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** Pre-update hook callback. */ @@ -686,6 +687,7 @@ static void DbPreUpdateHandler( Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT); Tcl_DecrRefCount(pCmd); } +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ static void DbUpdateHandler( void *p, @@ -1624,7 +1626,9 @@ static void DbHookCmd( } } +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK sqlite3_preupdate_hook(db, (pDb->pPreUpdateHook?DbPreUpdateHandler:0), pDb); +#endif sqlite3_update_hook(db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb); sqlite3_rollback_hook(db, (pDb->pRollbackHook?DbRollbackHandler:0), pDb); sqlite3_wal_hook(db, (pDb->pWalHook?DbWalHandler:0), pDb); @@ -2851,6 +2855,10 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ ** $db preupdate_hook old INDEX */ case DB_PREUPDATE: { +#ifndef SQLITE_ENABLE_PREUPDATE_HOOK + Tcl_AppendResult(interp, "preupdate_hook was omitted at compile-time"); + rc = TCL_ERROR; +#else static const char *azSub[] = {"count", "depth", "hook", "new", "old", 0}; enum DbPreupdateSubCmd { PRE_COUNT, PRE_DEPTH, PRE_HOOK, PRE_NEW, PRE_OLD @@ -2920,7 +2928,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ } } } - +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ break; } @@ -3720,7 +3728,7 @@ static void init_all(Tcl_Interp *interp){ extern int Sqlitemultiplex_Init(Tcl_Interp*); extern int SqliteSuperlock_Init(Tcl_Interp*); extern int SqlitetestSyscall_Init(Tcl_Interp*); -#ifdef SQLITE_ENABLE_SESSION +#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK) extern int TestSession_Init(Tcl_Interp*); #endif #ifdef SQLITE_ENABLE_ZIPVFS @@ -3760,7 +3768,7 @@ static void init_all(Tcl_Interp *interp){ Sqlitemultiplex_Init(interp); SqliteSuperlock_Init(interp); SqlitetestSyscall_Init(interp); -#ifdef SQLITE_ENABLE_SESSION +#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK) TestSession_Init(interp); #endif diff --git a/src/test_config.c b/src/test_config.c index 24ddbaa027..2bf7af5729 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -85,6 +85,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "mem5", "0", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + Tcl_SetVar2(interp, "sqlite_options", "preupdate", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "preupdate", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_MUTEX_OMIT Tcl_SetVar2(interp, "sqlite_options", "mutex", "0", TCL_GLOBAL_ONLY); #else diff --git a/src/update.c b/src/update.c index fd310fb307..d702cba570 100644 --- a/src/update.c +++ b/src/update.c @@ -487,13 +487,13 @@ void sqlite3Update( /* Delete the index entries associated with the current record. */ j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid); sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx); - + /* If changing the rowid value, or if there are foreign key constraints ** to process, delete the old record. Otherwise, add a noop OP_Delete ** to invoke the pre-update hook. ** ** That (regNew==regnewRowid+1) is true is also important for the - ** pre-update hook. If hte caller invokes preupdate_new(), the returned + ** pre-update hook. If the caller invokes preupdate_new(), the returned ** value is copied from memory cell (regNewRowid+1+iCol), where iCol ** is the column index supplied by the user. */ diff --git a/src/vdbe.c b/src/vdbe.c index cd8c1ec69b..e85dc85f69 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -107,6 +107,16 @@ static void updateMaxBlobsize(Mem *p){ } #endif +/* +** This macro evaluates to true if either the update hook or the preupdate +** hook are enabled for database connect DB. +*/ +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK +# define HAS_UPDATE_HOOK(DB) ((DB)->xPreUpdateCallback||(DB)->xUpdateCallback) +#else +# define HAS_UPDATE_HOOK(DB) ((DB)->xUpdateCallback) +#endif + /* ** The next global variable is incremented each type the OP_Found opcode ** is executed. This is used to test whether or not the foreign key @@ -3890,7 +3900,7 @@ case OP_InsertInt: { iKey = pOp->p3; } - if( pOp->p4type==P4_TABLE && (db->xPreUpdateCallback||db->xUpdateCallback) ){ + if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ assert( pC->isTable ); assert( pC->iDb>=0 ); zDb = db->aDb[pC->iDb].zName; @@ -3898,6 +3908,7 @@ case OP_InsertInt: { op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); } +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* Invoke the pre-update hook, if any */ if( db->xPreUpdateCallback && pOp->p4type==P4_TABLE @@ -3905,6 +3916,7 @@ case OP_InsertInt: { ){ sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, iKey, pOp->p2); } +#endif if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = iKey; @@ -3991,7 +4003,7 @@ case OP_Delete: { /* If the update-hook or pre-update-hook will be invoked, set iKey to ** the rowid of the row being deleted. Set zDb and zTab as well. */ - if( pOp->p4.z && (db->xPreUpdateCallback || db->xUpdateCallback) ){ + if( pOp->p4.z && HAS_UPDATE_HOOK(db) ){ assert( pC->iDb>=0 ); assert( pC->isTable ); assert( pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */ @@ -4000,6 +4012,7 @@ case OP_Delete: { pTab = pOp->p4.pTab; } +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* Invoke the pre-update-hook if required. */ if( db->xPreUpdateCallback && pOp->p4.z ){ assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) ); @@ -4009,6 +4022,7 @@ case OP_Delete: { pOp->p3 ); } +#endif if( opflags & OPFLAG_ISNOOP ) break; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index b485aa7483..8af16e9ee3 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -1327,6 +1327,7 @@ int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ return v; } +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** This function is called from within a pre-update callback to retrieve ** a field of the row currently being updated or deleted. @@ -1381,7 +1382,9 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ sqlite3Error(db, rc, 0); return sqlite3ApiExit(db, rc); } +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** This function is called from within a pre-update callback to retrieve ** the number of columns in the row being updated, deleted or inserted. @@ -1390,7 +1393,9 @@ int sqlite3_preupdate_count(sqlite3 *db){ PreUpdate *p = db->pPreUpdate; return (p ? p->pCsr->nField : 0); } +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** This function is designed to be called from within a pre-update callback ** only. It returns zero if the change that caused the callback was made @@ -1406,7 +1411,9 @@ int sqlite3_preupdate_depth(sqlite3 *db){ PreUpdate *p = db->pPreUpdate; return (p ? p->v->nFrame : 0); } +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** This function is called from within a pre-update callback to retrieve ** a field of the row currently being updated or inserted. @@ -1481,3 +1488,4 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ sqlite3Error(db, rc, 0); return sqlite3ApiExit(db, rc); } +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 839feb905b..6dab72c369 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2812,7 +2812,7 @@ UnpackedRecord *sqlite3VdbeRecordUnpack( pMem->enc = pKeyInfo->enc; pMem->db = pKeyInfo->db; pMem->flags = 0; - pMem->zMalloc = pMem->z = 0; + pMem->zMalloc = 0; pMem->z = 0; d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); pMem++; @@ -3171,6 +3171,7 @@ void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ } } +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** Invoke the pre-update hook. If this is an UPDATE or DELETE pre-update call, ** then cursor passed as the second argument should point to the row about @@ -3228,3 +3229,4 @@ void sqlite3VdbePreUpdateHook( sqlite3DbFree(db, preupdate.aNew); } } +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ diff --git a/test/hook.test b/test/hook.test index 5cceaf9abf..58a6fed8bf 100644 --- a/test/hook.test +++ b/test/hook.test @@ -365,6 +365,11 @@ unset ::hooks #---------------------------------------------------------------------------- # The following tests - hook-7.* - test the pre-update hook. # +ifcapable !preupdate { + finish_test + return +} +# # 7.1.1 - INSERT statement. # 7.1.2 - INSERT INTO ... SELECT statement. # 7.1.3 - REPLACE INTO ... (rowid conflict) From 5d8a298495a021026c32d79714a8630170edaaa6 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 1 Apr 2011 15:30:39 +0000 Subject: [PATCH 043/570] If the sessions module is being built as part of the amalgamation, do not try to include sqliteInt.h and vdbeInt.h. FossilOrigin-Name: f87bfe6e12093e5958b658a49d3766fb29562cbb --- ext/session/sqlite3session.c | 6 ++++-- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 70acb76056..8c1b8f64a8 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -5,8 +5,10 @@ #include #include -#include "sqliteInt.h" -#include "vdbeInt.h" +#ifndef SQLITE_AMALGAMATION +# include "sqliteInt.h" +# include "vdbeInt.h" +#endif typedef struct SessionTable SessionTable; typedef struct SessionChange SessionChange; diff --git a/manifest b/manifest index dddc79360d..8e4d946b71 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_ENABLE_PREUPDATE_HOOK\scompile-time\soption. -D 2011-03-30T21:04:43.055 +C If\sthe\ssessions\smodule\sis\sbeing\sbuilt\sas\spart\sof\sthe\samalgamation,\sdo\snot\stry\sto\sinclude\ssqliteInt.h\sand\svdbeInt.h. +D 2011-04-01T15:30:39.770 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -105,7 +105,7 @@ F ext/session/session3.test bfa2376db7cbb2ac69496f84d93a8d81b13110d3 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 F ext/session/sessionfault.test 2544a2e2ecad56e3c07a32c09799871d243c114c -F ext/session/sqlite3session.c eaf093c81f076301cfd04f794d047cf7beffd290 +F ext/session/sqlite3session.c 2b2936b5188776b33bba1263f93267f3ec9d0d84 F ext/session/sqlite3session.h f284bac51c12de0e0096fc986e61f5ae6b9e5be5 F ext/session/test_session.c 82e3fd7d94f485ea63bcfb15d636c95a01db97a9 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -929,7 +929,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P d051694e024c590e4687cae1368f900799b7442d -R c057f780dc1cba178107219ab6b28dc8 -U drh -Z 598e11d1b0eff48f657d073c9eb1f2dc +P 6634521461e6acff7cc778590e62d57831f9230d +R 7a473314ef2d0233cdf9f16418e4fb53 +U dan +Z 1c0b7044d6d9a7b111c49878de940801 diff --git a/manifest.uuid b/manifest.uuid index c3c451f694..7f5424aa62 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6634521461e6acff7cc778590e62d57831f9230d \ No newline at end of file +f87bfe6e12093e5958b658a49d3766fb29562cbb \ No newline at end of file From cfdbde214b222cfaf67296bc6b5fa9a9da6f2a81 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 6 Apr 2011 23:39:28 +0000 Subject: [PATCH 044/570] Fix VC++ compiler warnings. FossilOrigin-Name: 7b7c8d366c51e89aefc6efc9dcffe3f62c7e1d25 --- ext/session/sqlite3session.c | 42 ++++++++++++++++++------------------ manifest | 14 ++++++------ manifest.uuid | 2 +- src/vdbetrace.c | 2 +- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 8c1b8f64a8..7b77e170e8 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -564,7 +564,7 @@ static int sessionTableInfo( assert( pazCol && pabPK ); - nThis = strlen(zThis); + nThis = sqlite3Strlen30(zThis); zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis); if( !zPragma ) return SQLITE_NOMEM; @@ -778,8 +778,8 @@ static void xPreUpdate( sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ ){ sqlite3_session *pSession; - int nDb = strlen(zDb); - int nName = strlen(zDb); + int nDb = sqlite3Strlen30(zDb); + int nName = sqlite3Strlen30(zName); assert( sqlite3_mutex_held(db->mutex) ); @@ -825,7 +825,7 @@ int sqlite3session_create( ){ sqlite3_session *pNew; /* Newly allocated session object */ sqlite3_session *pOld; /* Session object already attached to db */ - int nDb = strlen(zDb); /* Length of zDb in bytes */ + int nDb = sqlite3Strlen30(zDb); /* Length of zDb in bytes */ /* Zero the output value in case an error occurs. */ *ppSession = 0; @@ -882,7 +882,7 @@ void sqlite3session_delete(sqlite3_session *pSession){ sqlite3_free(p); } } - sqlite3_free(pTab->azCol); + sqlite3_free((char*)pTab->azCol); /* cast works around VC++ bug */ sqlite3_free(pTab->apChange); sqlite3_free(pTab); } @@ -914,7 +914,7 @@ int sqlite3session_attach( /* First search for an existing entry. If one is found, this call is ** a no-op. Return early. */ - nName = strlen(zName); + nName = sqlite3Strlen30(zName); for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){ if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ) break; } @@ -985,7 +985,7 @@ static void sessionAppendByte(SessionBuffer *p, u8 v, int *pRc){ ** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before ** returning. */ -static void sessionAppendVarint(SessionBuffer *p, sqlite3_int64 v, int *pRc){ +static void sessionAppendVarint(SessionBuffer *p, int v, int *pRc){ if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, 9, pRc) ){ p->nBuf += sessionVarintPut(&p->aBuf[p->nBuf], v); } @@ -1023,7 +1023,7 @@ static void sessionAppendStr( const char *zStr, int *pRc ){ - int nStr = strlen(zStr); + int nStr = sqlite3Strlen30(zStr); if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, nStr, pRc) ){ memcpy(&p->aBuf[p->nBuf], zStr, nStr); p->nBuf += nStr; @@ -1062,7 +1062,7 @@ static void sessionAppendIdent( const char *zStr, /* String to quote, escape and append */ int *pRc /* IN/OUT: Error code */ ){ - int nStr = strlen(zStr)*2 + 2 + 1; + int nStr = sqlite3Strlen30(zStr)*2 + 2 + 1; if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, nStr, pRc) ){ char *zOut = (char *)&p->aBuf[p->nBuf]; const char *zIn = zStr; @@ -1072,7 +1072,7 @@ static void sessionAppendIdent( *zOut++ = *(zIn++); } *zOut++ = '"'; - p->nBuf = ((u8 *)zOut - p->aBuf); + p->nBuf = (int)((u8 *)zOut - p->aBuf); } } @@ -1372,7 +1372,7 @@ int sqlite3session_changeset( sessionAppendByte(&buf, 'T', &rc); sessionAppendVarint(&buf, nCol, &rc); sessionAppendBlob(&buf, pTab->abPK, nCol, &rc); - sessionAppendBlob(&buf, (u8 *)zName, strlen(zName)+1, &rc); + sessionAppendBlob(&buf, (u8 *)zName, sqlite3Strlen30(zName)+1, &rc); /* Build and compile a statement to execute: */ if( rc==SQLITE_OK ){ @@ -1413,7 +1413,7 @@ int sqlite3session_changeset( if( buf.nBuf==nNoop ){ buf.nBuf = nRewind; } - sqlite3_free(azCol); + sqlite3_free((char*)azCol); /* cast works around VC++ bug */ } } @@ -1589,7 +1589,7 @@ int sqlite3changeset_next(sqlite3_changeset_iter *p){ p->abPK = (u8 *)aChange; aChange += p->nCol; p->zTab = (char *)aChange; - aChange += (strlen((char *)aChange) + 1); + aChange += (sqlite3Strlen30((char *)aChange) + 1); p->op = *(aChange++); p->bIndirect = *(aChange++); sqlite3_free(p->apValue); @@ -1796,7 +1796,7 @@ int sqlite3changeset_invert( */ int nByte = 1 + sessionVarintGet(&aIn[i+1], &nCol); nByte += nCol; - nByte += 1 + strlen((char *)&aIn[i+nByte]); + nByte += 1 + sqlite3Strlen30((char *)&aIn[i+nByte]); memcpy(&aOut[i], &aIn[i], nByte); i += nByte; break; @@ -1810,7 +1810,7 @@ int sqlite3changeset_invert( sessionReadRecord(&aEnd, nCol, 0); aOut[i] = (eType==SQLITE_DELETE ? SQLITE_INSERT : SQLITE_DELETE); aOut[i+1] = aIn[i+1]; - nByte = aEnd - &aIn[i+2]; + nByte = (int)(aEnd - &aIn[i+2]); memcpy(&aOut[i+2], &aIn[i+2], nByte); i += 2 + nByte; break; @@ -1822,9 +1822,9 @@ int sqlite3changeset_invert( u8 *aEnd = &aIn[i+2]; sessionReadRecord(&aEnd, nCol, 0); - nByte1 = aEnd - &aIn[i+2]; + nByte1 = (int)(aEnd - &aIn[i+2]); sessionReadRecord(&aEnd, nCol, 0); - nByte2 = aEnd - &aIn[i+2] - nByte1; + nByte2 = (int)(aEnd - &aIn[i+2]) - nByte1; aOut[i] = SQLITE_UPDATE; aOut[i+1] = aIn[i+1]; @@ -2416,7 +2416,7 @@ int sqlite3changeset_apply( sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ int rc; /* Return code */ const char *zTab = 0; /* Name of current table */ - int nTab = 0; /* Result of strlen(zTab) */ + int nTab = 0; /* Result of sqlite3Strlen30(zTab) */ SessionApplyCtx sApply; /* changeset_apply() context object */ memset(&sApply, 0, sizeof(sApply)); @@ -2438,7 +2438,7 @@ int sqlite3changeset_apply( u8 *abPK; schemaMismatch = 0; - sqlite3_free(sApply.azCol); + sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ sqlite3_finalize(sApply.pDelete); sqlite3_finalize(sApply.pUpdate); sqlite3_finalize(sApply.pInsert); @@ -2479,7 +2479,7 @@ int sqlite3changeset_apply( ){ break; } - nTab = strlen(zTab); + nTab = sqlite3Strlen30(zTab); } /* If there is a schema mismatch on the current table, proceed to the @@ -2530,7 +2530,7 @@ int sqlite3changeset_apply( sqlite3_finalize(sApply.pDelete); sqlite3_finalize(sApply.pUpdate); sqlite3_finalize(sApply.pSelect); - sqlite3_free(sApply.azCol); + sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ sqlite3_mutex_leave(sqlite3_db_mutex(db)); return rc; } diff --git a/manifest b/manifest index a2bcb079d9..0b5de163b9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sin\sthe\slatest\schanges\sfrom\sthe\strunk. -D 2011-04-06T22:33:50.737 +C Fix\sVC++\scompiler\swarnings. +D 2011-04-06T23:39:28.224 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -105,7 +105,7 @@ F ext/session/session3.test bfa2376db7cbb2ac69496f84d93a8d81b13110d3 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 F ext/session/sessionfault.test 2544a2e2ecad56e3c07a32c09799871d243c114c -F ext/session/sqlite3session.c 2b2936b5188776b33bba1263f93267f3ec9d0d84 +F ext/session/sqlite3session.c bc6fc77d70d4d9994598b1daf0a43d48965b2155 F ext/session/sqlite3session.h f284bac51c12de0e0096fc986e61f5ae6b9e5be5 F ext/session/test_session.c 82e3fd7d94f485ea63bcfb15d636c95a01db97a9 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -251,7 +251,7 @@ F src/vdbeapi.c 8051038f7674c708f4515ab189fc3ea929e09a4c F src/vdbeaux.c b0a2a184a25380f7eb9d07e9336034ec38d1b213 F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b -F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 +F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114 F src/vtab.c b0abc931f95af94c9ffdf9f747eb191cda953123 F src/wal.c 7334009b396285b658a95a3b6bc6d2b016a1f794 F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840 @@ -937,7 +937,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 45f20261720dcd73eb887f7e3df100723000418b 614de91a504d2231009a9de1305e31fce1b1c5a6 -R 502dde3bb5feee985b14f915e41e9858 +P 435b57dc2be7b071270a6cddece297758b8153aa +R 430b240dcc83276815f3990defb9cdf0 U drh -Z 9b010756d90228476ef26682d9d1164b +Z 063f7a6f50976dabf014f8516d936514 diff --git a/manifest.uuid b/manifest.uuid index 6bf7c439fb..e28e83255d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -435b57dc2be7b071270a6cddece297758b8153aa \ No newline at end of file +7b7c8d366c51e89aefc6efc9dcffe3f62c7e1d25 \ No newline at end of file diff --git a/src/vdbetrace.c b/src/vdbetrace.c index b422fa9eb1..de123b550f 100644 --- a/src/vdbetrace.c +++ b/src/vdbetrace.c @@ -85,7 +85,7 @@ char *sqlite3VdbeExpandSql( const char *zStart = zRawSql; while( *(zRawSql++)!='\n' && *zRawSql ); sqlite3StrAccumAppend(&out, "-- ", 3); - sqlite3StrAccumAppend(&out, zStart, zRawSql-zStart); + sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); } }else{ while( zRawSql[0] ){ From 36828bd9bb6305485019912edc6a55a52bc5144e Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 6 Apr 2011 23:40:28 +0000 Subject: [PATCH 045/570] Add a missing "extern C" terminator to the end of sqlite3session.h. FossilOrigin-Name: 29090b695a95feaba1b74f9894997083a060263a --- ext/session/sqlite3session.h | 6 ++++++ manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index bcb901667c..eb4e114e37 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -737,5 +737,11 @@ int sqlite3changeset_apply( #define SQLITE_CHANGESET_REPLACE 1 #define SQLITE_CHANGESET_ABORT 2 +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +} #endif +#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ diff --git a/manifest b/manifest index 0b5de163b9..aaad18cb5b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sVC++\scompiler\swarnings. -D 2011-04-06T23:39:28.224 +C Add\sa\smissing\s"extern\sC"\sterminator\sto\sthe\send\sof\ssqlite3session.h. +D 2011-04-06T23:40:28.737 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -106,7 +106,7 @@ F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 F ext/session/sessionfault.test 2544a2e2ecad56e3c07a32c09799871d243c114c F ext/session/sqlite3session.c bc6fc77d70d4d9994598b1daf0a43d48965b2155 -F ext/session/sqlite3session.h f284bac51c12de0e0096fc986e61f5ae6b9e5be5 +F ext/session/sqlite3session.h 9b91addc5bd1777137d4f1c0252da9fbe2d4618e F ext/session/test_session.c 82e3fd7d94f485ea63bcfb15d636c95a01db97a9 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -937,7 +937,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 435b57dc2be7b071270a6cddece297758b8153aa -R 430b240dcc83276815f3990defb9cdf0 +P 7b7c8d366c51e89aefc6efc9dcffe3f62c7e1d25 +R 35a03a7ffb44f2b52e4ebaca11ffd944 U drh -Z 063f7a6f50976dabf014f8516d936514 +Z efe884ab8aaf8c7e1eec316d7a2437f1 diff --git a/manifest.uuid b/manifest.uuid index e28e83255d..cf1a04a1ea 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7b7c8d366c51e89aefc6efc9dcffe3f62c7e1d25 \ No newline at end of file +29090b695a95feaba1b74f9894997083a060263a \ No newline at end of file From 5d607a6e062a0b5f79b62091edd63967ea792edd Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 14 Apr 2011 11:16:21 +0000 Subject: [PATCH 046/570] Start adding the sqlite3changeset_concat() function to the session module. FossilOrigin-Name: 8927b2260b8d84f53776cb29e1d2fa41b6b0de0e --- ext/session/session5.test | 124 ++++++++ ext/session/sqlite3session.c | 539 +++++++++++++++++++++++++++++++---- ext/session/sqlite3session.h | 6 + ext/session/test_session.c | 36 +++ manifest | 19 +- manifest.uuid | 2 +- 6 files changed, 660 insertions(+), 66 deletions(-) create mode 100644 ext/session/session5.test diff --git a/ext/session/session5.test b/ext/session/session5.test new file mode 100644 index 0000000000..440a44c08b --- /dev/null +++ b/ext/session/session5.test @@ -0,0 +1,124 @@ +# 2011 April 13 +# +# 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 the session module. +# Specifically, for the sqlite3changeset_concat() command. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} + +set testprefix session5 + +proc do_concat_test {tn sql1 sql2} { + sqlite3session S1 db main ; S1 attach * + sqlite3session S2 db main ; S2 attach * + + execsql $sql1 + set C1 [S1 changeset] + S1 delete + + sqlite3session S1 db main ; S1 attach * + + execsql $sql2 + set C2 [S1 changeset] + S1 delete + + set C3 [S2 changeset] + S2 delete + + set C4 [sqlite3changeset_concat $C1 $C2] + + set c3 [list] + set c4 [list] + sqlite3session_foreach c $C3 { lappend c3 $c } + sqlite3session_foreach c $C4 { lappend c4 $c } + set c3 [lsort $c3] + set c4 [lsort $c4] + + do_test $tn [list set {} $c4] $c3 +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a PRIMARY KEY, b); +} + +do_concat_test 1.1.1 { + INSERT INTO t1 VALUES(1, 'one'); +} { + INSERT INTO t1 VALUES(2, 'two'); +} + +do_concat_test 1.1.2 { + UPDATE t1 SET b = 'five' WHERE a = 1; +} { + UPDATE t1 SET b = 'six' WHERE a = 2; +} + +do_concat_test 1.1.3 { + DELETE FROM t1 WHERE a = 1; +} { + DELETE FROM t1 WHERE a = 2; +} + + +# 1.2.1: INSERT + DELETE -> (none) +# 1.2.2: INSERT + UPDATE -> INSERT +# +# 1.2.3: DELETE + INSERT (matching data) -> (none) +# 1.2.4: DELETE + INSERT (non-matching data) -> UPDATE +# +# 1.2.5: UPDATE + UPDATE (matching data) -> (none) +# 1.2.6: UPDATE + UPDATE (non-matching data) -> UPDATE +# 1.2.7: UPDATE + DELETE -> DELETE +# +do_concat_test 1.2.1 { + INSERT INTO t1 VALUES('x', 'y'); +} { + DELETE FROM t1 WHERE a = 'x'; +} +do_concat_test 1.2.2 { + INSERT INTO t1 VALUES(5.0, 'five'); +} { + UPDATE t1 SET b = 'six' WHERE a = 5.0; +} + +do_execsql_test 1.2.3.1 "INSERT INTO t1 VALUES('I', 'one')" +do_concat_test 1.2.3.2 { + DELETE FROM t1 WHERE a = 'I'; +} { + INSERT INTO t1 VALUES('I', 'one'); +} +do_concat_test 1.2.4 { + DELETE FROM t1 WHERE a = 'I'; +} { + INSERT INTO t1 VALUES('I', 'two'); +} +do_concat_test 1.2.5 { + UPDATE t1 SET b = 'five' WHERE a = 'I'; +} { + UPDATE t1 SET b = 'two' WHERE a = 'I'; +} +do_concat_test 1.2.6 { + UPDATE t1 SET b = 'six' WHERE a = 'I'; +} { + UPDATE t1 SET b = 'seven' WHERE a = 'I'; +} +do_concat_test 1.2.7 { + UPDATE t1 SET b = 'eight' WHERE a = 'I'; +} { + DELETE FROM t1 WHERE a = 'I'; +} + +finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 7b77e170e8..770fc13e30 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -126,6 +126,7 @@ struct SessionTable { ** Followed by one or more changes to the table. ** ** 1 byte: Either SQLITE_INSERT, UPDATE or DELETE. +** 1 byte: The "indirect-change" flag. ** old.* record: (delete and update only) ** new.* record: (insert and update only) */ @@ -353,20 +354,19 @@ static unsigned int sessionPreupdateHash( } /* -** Based on the primary key values stored in change pChange, calculate a +** Based on the primary key values stored in change aRecord, calculate a ** hash key, assuming the has table has nBucket buckets. The hash keys ** calculated by this function are compatible with those calculated by ** sessionPreupdateHash(). */ static unsigned int sessionChangeHash( - sqlite3 *db, /* Database handle */ SessionTable *pTab, /* Table handle */ - SessionChange *pChange, /* Change handle */ + u8 *aRecord, /* Change record */ int nBucket /* Assume this many buckets in hash table */ ){ unsigned int h = 0; /* Value to return */ int i; /* Used to iterate through columns */ - u8 *a = pChange->aRecord; /* Used to iterate through change record */ + u8 *a = aRecord; /* Used to iterate through change record */ for(i=0; inCol; i++){ int eType = *a++; @@ -393,6 +393,160 @@ static unsigned int sessionChangeHash( return (h % nBucket); } +static int sessionSerialLen(u8 *a){ + int e = *a; + int n; + if( e==0 ) return 1; + if( e==SQLITE_NULL ) return 1; + if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; + return sessionVarintGet(&a[1], &n) + 1 + n; +} + +static int sessionChangeEqual( + SessionTable *pTab, + u8 *aLeft, /* Change record */ + u8 *aRight /* Change record */ +){ + u8 *a1 = aLeft; + u8 *a2 = aRight; + int i; + + for(i=0; inCol; i++){ + int n1 = sessionSerialLen(a1); + int n2 = sessionSerialLen(a2); + + if( pTab->abPK[i] && (n1!=n2 || memcmp(a1, a2, n1)) ){ + return 0; + } + a1 += n1; + a2 += n1; + } + + return 1; +} + +static void sessionMergeRecord( + u8 **paOut, + SessionTable *pTab, + u8 *aLeft, + u8 *aRight +){ + u8 *a1 = aLeft; + u8 *a2 = aRight; + u8 *aOut = *paOut; + int i; + + for(i=0; inCol; i++){ + int n1 = sessionSerialLen(a1); + int n2 = sessionSerialLen(a2); + if( *a2 ){ + memcpy(aOut, a2, n2); + aOut += n2; + }else{ + memcpy(aOut, a1, n1); + aOut += n1; + } + a1 += n1; + a2 += n2; + } + + *paOut = aOut; +} + +static u8 *sessionMergeValue( + u8 **paOne, + u8 **paTwo, + int *pnVal +){ + u8 *a1 = *paOne; + u8 *a2 = *paTwo; + u8 *pRet = 0; + int n1; + + assert( a1 ); + if( a2 ){ + int n2 = sessionSerialLen(a2); + if( *a2 ){ + *pnVal = n2; + pRet = a2; + } + *paTwo = &a2[n2]; + } + + n1 = sessionSerialLen(a1); + if( pRet==0 ){ + *pnVal = n1; + pRet = a1; + } + *paOne = &a1[n1]; + + return pRet; +} + +static int sessionMergeUpdate( + u8 **paOut, + SessionTable *pTab, + u8 *aOldRecord1, + u8 *aOldRecord2, + u8 *aNewRecord1, + u8 *aNewRecord2 +){ + u8 *aOld1 = aOldRecord1; + u8 *aOld2 = aOldRecord2; + u8 *aNew1 = aNewRecord1; + u8 *aNew2 = aNewRecord2; + + u8 *aOut = *paOut; + int i; + int bRequired = 0; + + assert( aOldRecord1 && aNewRecord1 ); + + /* Write the old.* vector first. */ + for(i=0; inCol; i++){ + int nOld; + u8 *aOld; + int nNew; + u8 *aNew; + + aOld = sessionMergeValue(&aOld1, &aOld2, &nOld); + aNew = sessionMergeValue(&aNew1, &aNew2, &nNew); + if( pTab->abPK[i] || nOld!=nNew || memcmp(aOld, aNew, nNew) ){ + if( pTab->abPK[i]==0 ) bRequired = 1; + memcpy(aOut, aOld, nOld); + aOut += nOld; + }else{ + *(aOut++) = '\0'; + } + } + + if( !bRequired ) return 0; + + /* Write the new.* vector */ + aOld1 = aOldRecord1; + aOld2 = aOldRecord2; + aNew1 = aNewRecord1; + aNew2 = aNewRecord2; + for(i=0; inCol; i++){ + int nOld; + u8 *aOld; + int nNew; + u8 *aNew; + + aOld = sessionMergeValue(&aOld1, &aOld2, &nOld); + aNew = sessionMergeValue(&aNew1, &aNew2, &nNew); + if( pTab->abPK[i] || (nOld==nNew && 0==memcmp(aOld, aNew, nNew)) ){ + *(aOut++) = '\0'; + }else{ + memcpy(aOut, aNew, nNew); + aOut += nNew; + } + } + + *paOut = aOut; + return 1; +} + static int sessionPreupdateEqual( sqlite3 *db, SessionTable *pTab, @@ -480,7 +634,7 @@ static int sessionPreupdateEqual( ** Growing the hash table in this case is a performance optimization only, ** it is not required for correct operation. */ -static int sessionGrowHash(sqlite3_session *pSession, SessionTable *pTab){ +static int sessionGrowHash(SessionTable *pTab){ if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){ int i; SessionChange **apNew; @@ -489,7 +643,6 @@ static int sessionGrowHash(sqlite3_session *pSession, SessionTable *pTab){ apNew = (SessionChange **)sqlite3_malloc(sizeof(SessionChange *) * nNew); if( apNew==0 ){ if( pTab->nChange==0 ){ - pSession->rc = SQLITE_NOMEM; return SQLITE_ERROR; } return SQLITE_OK; @@ -500,7 +653,7 @@ static int sessionGrowHash(sqlite3_session *pSession, SessionTable *pTab){ SessionChange *p; SessionChange *pNext; for(p=pTab->apChange[i]; p; p=pNext){ - int iHash = sessionChangeHash(pSession->db, pTab, p, nNew); + int iHash = sessionChangeHash(pTab, p->aRecord, nNew); pNext = p->pNext; p->pNext = apNew[iHash]; apNew[iHash] = p; @@ -677,7 +830,10 @@ static void sessionPreupdateOneChange( if( sessionInitTable(pSession, pTab) ) return; /* Grow the hash table if required */ - if( sessionGrowHash(pSession, pTab) ) return; + if( sessionGrowHash(pTab) ){ + pSession->rc = SQLITE_NOMEM; + return; + } /* Search the hash table for an existing entry for rowid=iKey2. If ** one is found, store a pointer to it in pChange and unlink it from @@ -693,8 +849,8 @@ static void sessionPreupdateOneChange( } if( pC==0 ){ /* Create a new change object containing all the old values (if - ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK - ** values (if this is an INSERT). */ + ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK + ** values (if this is an INSERT). */ SessionChange *pChange; /* New change object */ int nByte; /* Number of bytes to allocate */ int i; /* Used to iterate through columns */ @@ -851,6 +1007,27 @@ int sqlite3session_create( return SQLITE_OK; } +void sessionDeleteTable(SessionTable *pList){ + SessionTable *pNext; + SessionTable *pTab; + + for(pTab=pList; pTab; pTab=pNext){ + int i; + pNext = pTab->pNext; + for(i=0; inChange; i++){ + SessionChange *p; + SessionChange *pNext; + for(p=pTab->apChange[i]; p; p=pNext){ + pNext = p->pNext; + sqlite3_free(p); + } + } + sqlite3_free((char*)pTab->azCol); /* cast works around VC++ bug */ + sqlite3_free(pTab->apChange); + sqlite3_free(pTab); + } +} + /* ** Delete a session object previously allocated using sqlite3session_create(). */ @@ -870,22 +1047,7 @@ void sqlite3session_delete(sqlite3_session *pSession){ /* Delete all attached table objects. And the contents of their ** associated hash-tables. */ - while( pSession->pTable ){ - int i; - SessionTable *pTab = pSession->pTable; - pSession->pTable = pTab->pNext; - for(i=0; inChange; i++){ - SessionChange *p; - SessionChange *pNext; - for(p=pTab->apChange[i]; p; p=pNext){ - pNext = p->pNext; - sqlite3_free(p); - } - } - sqlite3_free((char*)pTab->azCol); /* cast works around VC++ bug */ - sqlite3_free(pTab->apChange); - sqlite3_free(pTab); - } + sessionDeleteTable(pSession->pTable); /* Free the session object itself. */ sqlite3_free(pSession); @@ -1322,6 +1484,18 @@ static int sessionSelectBind( return rc; } +static void sessionAppendTableHdr( + SessionBuffer *pBuf, + SessionTable *pTab, + int *pRc +){ + /* Write a table header */ + sessionAppendByte(pBuf, 'T', pRc); + sessionAppendVarint(pBuf, pTab->nCol, pRc); + sessionAppendBlob(pBuf, pTab->abPK, pTab->nCol, pRc); + sessionAppendBlob(pBuf, (u8 *)pTab->zName, strlen(pTab->zName)+1, pRc); +} + /* ** Obtain a changeset object containing all changes recorded by the ** session object passed as the first argument. @@ -1369,10 +1543,7 @@ int sqlite3session_changeset( } /* Write a table header */ - sessionAppendByte(&buf, 'T', &rc); - sessionAppendVarint(&buf, nCol, &rc); - sessionAppendBlob(&buf, pTab->abPK, nCol, &rc); - sessionAppendBlob(&buf, (u8 *)zName, sqlite3Strlen30(zName)+1, &rc); + sessionAppendTableHdr(&buf, pTab, &rc); /* Build and compile a statement to execute: */ if( rc==SQLITE_OK ){ @@ -1525,9 +1696,9 @@ static int sessionReadRecord( if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ int nByte; - int enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); aRec += sessionVarintGet(aRec, &nByte); if( apOut ){ + int enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); sqlite3ValueSetStr(apOut[i], nByte, aRec, enc, SQLITE_STATIC); } aRec += nByte; @@ -1552,23 +1723,21 @@ static int sessionReadRecord( return SQLITE_OK; } -/* -** Advance an iterator created by sqlite3changeset_start() to the next -** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE -** or SQLITE_CORRUPT. -** -** This function may not be called on iterators passed to a conflict handler -** callback by changeset_apply(). -*/ -int sqlite3changeset_next(sqlite3_changeset_iter *p){ +static int sessionChangesetNext( + sqlite3_changeset_iter *p, + u8 **paRec, + int *pnRec +){ u8 *aChange; int i; u8 c; + assert( (paRec==0 && pnRec==0) || (paRec && pnRec) ); + /* If the iterator is in the error-state, return immediately. */ if( p->rc!=SQLITE_OK ) return p->rc; - /* Free the current contents of p->apValue[]. */ + /* Free the current contents of p->apValue[], if any. */ if( p->apValue ){ for(i=0; inCol*2; i++){ sqlite3ValueFree(p->apValue[i]); @@ -1582,47 +1751,64 @@ int sqlite3changeset_next(sqlite3_changeset_iter *p){ } aChange = p->pNext; - c = *(aChange++); - if( c=='T' ){ + if( aChange[0]=='T' ){ int nByte; /* Bytes to allocate for apValue */ + aChange++; aChange += sessionVarintGet(aChange, &p->nCol); p->abPK = (u8 *)aChange; aChange += p->nCol; p->zTab = (char *)aChange; aChange += (sqlite3Strlen30((char *)aChange) + 1); - p->op = *(aChange++); - p->bIndirect = *(aChange++); - sqlite3_free(p->apValue); - nByte = sizeof(sqlite3_value *) * p->nCol * 2; - p->apValue = (sqlite3_value **)sqlite3_malloc(nByte); - if( !p->apValue ){ - return (p->rc = SQLITE_NOMEM); + + if( paRec==0 ){ + sqlite3_free(p->apValue); + nByte = sizeof(sqlite3_value *) * p->nCol * 2; + p->apValue = (sqlite3_value **)sqlite3_malloc(nByte); + if( !p->apValue ){ + return (p->rc = SQLITE_NOMEM); + } + memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2); } - memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2); - }else{ - p->op = c; - p->bIndirect = *(aChange++); } + + p->op = *(aChange++); + p->bIndirect = *(aChange++); if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){ return (p->rc = SQLITE_CORRUPT); } + if( paRec ){ *paRec = aChange; } + /* If this is an UPDATE or DELETE, read the old.* record. */ if( p->op!=SQLITE_INSERT ){ - p->rc = sessionReadRecord(&aChange, p->nCol, p->apValue); + p->rc = sessionReadRecord(&aChange, p->nCol, paRec?0:p->apValue); if( p->rc!=SQLITE_OK ) return p->rc; } /* If this is an INSERT or UPDATE, read the new.* record. */ if( p->op!=SQLITE_DELETE ){ - p->rc = sessionReadRecord(&aChange, p->nCol, &p->apValue[p->nCol]); + p->rc = sessionReadRecord(&aChange, p->nCol, paRec?0:&p->apValue[p->nCol]); if( p->rc!=SQLITE_OK ) return p->rc; } + if( pnRec ){ *pnRec = aChange - *paRec; } p->pNext = aChange; return SQLITE_ROW; } +/* +** Advance an iterator created by sqlite3changeset_start() to the next +** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE +** or SQLITE_CORRUPT. +** +** This function may not be called on iterators passed to a conflict handler +** callback by changeset_apply(). +*/ +int sqlite3changeset_next(sqlite3_changeset_iter *p){ + return sessionChangesetNext(p, 0, 0); + +} + /* ** The following function extracts information on the current change ** from a changeset iterator. They may only be called after changeset_next() @@ -2535,4 +2721,245 @@ int sqlite3changeset_apply( return rc; } +static int sessionChangeMerge( + SessionTable *pTab, + SessionChange *pExist, + int op2, + int bIndirect, + u8 *aRec, + int nRec, + SessionChange **ppNew +){ + SessionChange *pNew = 0; + + if( !pExist ){ + pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange)); + if( !pNew ){ + return SQLITE_NOMEM; + } + memset(pNew, 0, sizeof(SessionChange)); + pNew->bInsert = op2; + pNew->bIndirect = bIndirect; + pNew->nRecord = nRec; + pNew->aRecord = aRec; + }else{ + int op1 = pExist->bInsert; + + /* + ** op1=INSERT, op2=INSERT -> Unsupported. Discard op2. + ** op1=INSERT, op2=UPDATE -> INSERT. + ** op1=INSERT, op2=DELETE -> (none) + ** + ** op1=UPDATE, op2=INSERT -> Unsupported. Discard op2. + ** op1=UPDATE, op2=UPDATE -> UPDATE. + ** op1=UPDATE, op2=DELETE -> DELETE. + ** + ** op1=DELETE, op2=INSERT -> UPDATE. + ** op1=DELETE, op2=UPDATE -> Unsupported. Discard op2. + ** op1=DELETE, op2=DELETE -> Unsupported. Discard op2. + */ + if( (op1==SQLITE_INSERT && op2==SQLITE_INSERT) + || (op1==SQLITE_UPDATE && op2==SQLITE_INSERT) + || (op1==SQLITE_DELETE && op2==SQLITE_UPDATE) + || (op1==SQLITE_DELETE && op2==SQLITE_DELETE) + ){ + pNew = pExist; + }else if( op1==SQLITE_INSERT && op2==SQLITE_DELETE ){ + sqlite3_free(pExist); + assert( pNew==0 ); + }else{ + int nByte; + u8 *aCsr; + + nByte = sizeof(SessionChange) + pExist->nRecord + nRec; + pNew = (SessionChange *)sqlite3_malloc(nByte); + if( !pNew ){ + return SQLITE_NOMEM; + } + memset(pNew, 0, sizeof(SessionChange)); + pNew->bIndirect = (bIndirect && pExist->bIndirect); + aCsr = pNew->aRecord = (u8 *)&pNew[1]; + + if( op1==SQLITE_INSERT && op2==SQLITE_UPDATE ){ + u8 *a1 = aRec; + pNew->bInsert = SQLITE_INSERT; + sessionReadRecord(&a1, pTab->nCol, 0); + sessionMergeRecord(&aCsr, pTab, pExist->aRecord, a1); + } + else if( op1==SQLITE_UPDATE && op2==SQLITE_UPDATE ){ + u8 *a1 = pExist->aRecord; + u8 *a2 = aRec; + sessionReadRecord(&a1, pTab->nCol, 0); + sessionReadRecord(&a2, pTab->nCol, 0); + pNew->bInsert = SQLITE_UPDATE; + if( 0==sessionMergeUpdate(&aCsr, pTab, aRec, pExist->aRecord, a1, a2) ){ + sqlite3_free(pNew); + pNew = 0; + } + } + else if( op1==SQLITE_UPDATE && op2==SQLITE_DELETE ){ + pNew->bInsert = SQLITE_DELETE; + sessionMergeRecord(&aCsr, pTab, aRec, pExist->aRecord); + } + else if( op1==SQLITE_DELETE && op2==SQLITE_INSERT ){ + pNew->bInsert = SQLITE_UPDATE; + if( 0==sessionMergeUpdate(&aCsr, pTab, pExist->aRecord, 0, aRec, 0) ){ + sqlite3_free(pNew); + pNew = 0; + } + } + + if( pNew ){ + pNew->nRecord = (aCsr - pNew->aRecord); + } + sqlite3_free(pExist); + } + } + + *ppNew = pNew; + return SQLITE_OK; +} + +int sessionConcatChangeset( + int nChangeset, + void *pChangeset, + SessionTable **ppTabList +){ + u8 *aRec; + int nRec; + sqlite3_changeset_iter *pIter; + int rc; + SessionTable *pTab = 0; + + rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + if( rc!=SQLITE_OK ) return rc; + + while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec) ){ + const char *zNew; + int nCol; + int op; + int iHash; + int bIndirect; + SessionChange *pChange; + SessionChange *pExist = 0; + SessionChange **pp; + + assert( pIter->apValue==0 ); + sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect); + + if( !pTab || zNew!=pTab->zName ){ + /* Search the list for a matching table */ + int nNew = strlen(zNew); + for(pTab = *ppTabList; pTab; pTab=pTab->pNext){ + if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break; + } + if( !pTab ){ + pTab = sqlite3_malloc(sizeof(SessionTable)); + if( !pTab ) break; + memset(pTab, 0, sizeof(SessionTable)); + pTab->pNext = *ppTabList; + *ppTabList = pTab; + } + pTab->zName = (char *)zNew; + pTab->nCol = nCol; + sqlite3changeset_pk(pIter, &pTab->abPK, 0); + } + + if( sessionGrowHash(pTab) ) break; + iHash = sessionChangeHash(pTab, aRec, pTab->nChange); + + /* Search for existing entry. If found, remove it from the hash table. + ** Code below may link it back in. + */ + for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){ + if( sessionChangeEqual(pTab, (*pp)->aRecord, aRec) ){ + pExist = *pp; + *pp = (*pp)->pNext; + pTab->nEntry--; + break; + } + } + + rc = sessionChangeMerge(pTab, pExist, op, bIndirect, aRec, nRec, &pChange); + if( rc ) break; + if( pChange ){ + pChange->pNext = pTab->apChange[iHash]; + pTab->apChange[iHash] = pChange; + pTab->nEntry++; + } + } + + if( rc==SQLITE_OK ){ + rc = sqlite3changeset_finalize(pIter); + }else{ + sqlite3changeset_finalize(pIter); + } + return rc; +} + + +/* +** 1. Iterate through the left-hand changeset. Add an entry to a table +** specific hash table for each change in the changeset. The hash table +** key is the PK of the row affected by the change. +** +** 2. Then interate through the right-hand changeset. Attempt to add an +** entry to a hash table for each component change. If a change already +** exists with the same PK values, combine the two into a single change. +** +** 3. Write an output changeset based on the contents of the hash table. +*/ +int sqlite3changeset_concat( + int nLeft, /* Number of bytes in lhs input */ + void *pLeft, /* Lhs input changeset */ + int nRight /* Number of bytes in rhs input */, + void *pRight, /* Rhs input changeset */ + int *pnOut, /* OUT: Number of bytes in output changeset */ + void **ppOut /* OUT: changeset (left right) */ +){ + SessionTable *pList = 0; /* List of SessionTable objects */ + int rc; /* Return code */ + + *pnOut = 0; + *ppOut = 0; + + rc = sessionConcatChangeset(nLeft, pLeft, &pList); + if( rc==SQLITE_OK ){ + rc = sessionConcatChangeset(nRight, pRight, &pList); + } + + /* Create the serialized output changeset based on the contents of the + ** hash tables attached to the SessionTable objects in list pList. + */ + if( rc==SQLITE_OK ){ + SessionTable *pTab; + SessionBuffer buf = {0, 0, 0}; + for(pTab=pList; pTab; pTab=pTab->pNext){ + int i; + if( pTab->nEntry==0 ) continue; + + sessionAppendTableHdr(&buf, pTab, &rc); + for(i=0; inChange; i++){ + SessionChange *p; + for(p=pTab->apChange[i]; p; p=p->pNext){ + sessionAppendByte(&buf, p->bInsert, &rc); + sessionAppendByte(&buf, p->bIndirect, &rc); + sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); + } + } + } + + if( rc==SQLITE_OK ){ + *ppOut = buf.aBuf; + *pnOut = buf.nBuf; + }else{ + sqlite3_free(buf.aBuf); + } + } + + concat_out: + sessionDeleteTable(pList); + return rc; +} + #endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index eb4e114e37..10a94b927b 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -522,6 +522,12 @@ int sqlite3changeset_invert( int *pnOut, void **ppOut /* OUT: Inverse of input */ ); +int sqlite3changeset_concat( + int nLeft, void *pLeft, /* Input changeset */ + int nRight, void *Right, /* Input changeset */ + int *pnOut, void **ppOut /* OUT: Inverse of input */ +); + /* ** CAPI3REF: Apply A Changeset To A Database ** diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 6af1892150..05eb732d6d 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -410,6 +410,39 @@ static int test_sqlite3changeset_invert( return TCL_OK; } +/* +** sqlite3changeset_concat LEFT RIGHT +*/ +static int test_sqlite3changeset_concat( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc; /* Return code from changeset_invert() */ + void *aLeft; /* Input changeset */ + int nLeft; /* Size of buffer aChangeset in bytes */ + void *aRight; /* Input changeset */ + int nRight; /* Size of buffer aChangeset in bytes */ + void *aOut; /* Output changeset */ + int nOut; /* Size of buffer aOut in bytes */ + + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "LEFT RIGHT"); + return TCL_ERROR; + } + aLeft = (void *)Tcl_GetByteArrayFromObj(objv[1], &nLeft); + aRight = (void *)Tcl_GetByteArrayFromObj(objv[2], &nRight); + + rc = sqlite3changeset_concat(nLeft, aLeft, nRight, aRight, &nOut, &aOut); + if( rc!=SQLITE_OK ){ + return test_session_error(interp, rc); + } + Tcl_SetObjResult(interp, Tcl_NewByteArrayObj((unsigned char *)aOut, nOut)); + sqlite3_free(aOut); + return TCL_OK; +} + /* ** sqlite3session_foreach VARNAME CHANGESET SCRIPT */ @@ -514,6 +547,9 @@ int TestSession_Init(Tcl_Interp *interp){ Tcl_CreateObjCommand( interp, "sqlite3changeset_invert", test_sqlite3changeset_invert, 0, 0 ); + Tcl_CreateObjCommand( + interp, "sqlite3changeset_concat", test_sqlite3changeset_concat, 0, 0 + ); Tcl_CreateObjCommand( interp, "sqlite3changeset_apply", test_sqlite3changeset_apply, 0, 0 ); diff --git a/manifest b/manifest index 336c603f40..4dcb9b0bb0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\slatest\strunk\schanges\sinto\sthe\ssessions\sbranch. -D 2011-04-09T18:07:51.034 +C Start\sadding\sthe\ssqlite3changeset_concat()\sfunction\sto\sthe\ssession\smodule. +D 2011-04-14T11:16:21.630 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -103,11 +103,12 @@ F ext/session/session1.test 7a92a2a6f531aef1e9764ffb7f983fb8b315376d F ext/session/session2.test c3e5f78d5eb988e35cc2ba9ce3678f706283cfdb F ext/session/session3.test bfa2376db7cbb2ac69496f84d93a8d81b13110d3 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 +F ext/session/session5.test ed5025c96693d406fb13bcf330d1a962dcb68c24 F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 F ext/session/sessionfault.test 2544a2e2ecad56e3c07a32c09799871d243c114c -F ext/session/sqlite3session.c bc6fc77d70d4d9994598b1daf0a43d48965b2155 -F ext/session/sqlite3session.h 9b91addc5bd1777137d4f1c0252da9fbe2d4618e -F ext/session/test_session.c 82e3fd7d94f485ea63bcfb15d636c95a01db97a9 +F ext/session/sqlite3session.c 124ac6d43ac5820add2e736b25432c3f6b5a733a +F ext/session/sqlite3session.h dc7c85fd27fa3a9a17b34e0951ed36cdced1bc67 +F ext/session/test_session.c f4d1dca94db71ec2177ee61eab51e718e58476d7 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk f942406cb7df55d1aec40a88a7ae399b730cd94f @@ -937,7 +938,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 29090b695a95feaba1b74f9894997083a060263a 1c2f0f8477bcf251fe874a2cfae4d7a403cb88ff -R a40e5f171b5b8b5d469c7b8e3eba3790 -U drh -Z 7e220d1108384435c7d9af48b2056273 +P 83705e90a54bad462a5b7fbca70cc129998f871c +R 2d3308935368f3ab85a5bea7204d6f97 +U dan +Z 4aed6546b387a7c5d8dbcb80467675b2 diff --git a/manifest.uuid b/manifest.uuid index 1c2583a835..4733d7436b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -83705e90a54bad462a5b7fbca70cc129998f871c \ No newline at end of file +8927b2260b8d84f53776cb29e1d2fa41b6b0de0e \ No newline at end of file From 6cda207f5f00357b712d06bb2f89dd93312decbe Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 14 Apr 2011 18:01:41 +0000 Subject: [PATCH 047/570] Add further tests for the sqlite3changeset_concat() function. Also fixes. FossilOrigin-Name: 1fc3f15d88c160b45642b46d1d54c591af058ba2 --- ext/session/session5.test | 104 ++++++++++++++++++++++++++++------- ext/session/sqlite3session.c | 50 ++++++++++------- ext/session/sqlite3session.h | 9 ++- manifest | 16 +++--- manifest.uuid | 2 +- 5 files changed, 130 insertions(+), 51 deletions(-) diff --git a/ext/session/session5.test b/ext/session/session5.test index 440a44c08b..676b2c718f 100644 --- a/ext/session/session5.test +++ b/ext/session/session5.test @@ -21,33 +21,46 @@ ifcapable !session {finish_test; return} set testprefix session5 -proc do_concat_test {tn sql1 sql2} { - sqlite3session S1 db main ; S1 attach * - sqlite3session S2 db main ; S2 attach * +# Organization of tests: +# +# session5-1.*: Simple tests to check the concat() function produces +# correct results. +# +# session5-2.*: More complicated tests. +# +# session5-3.*: Schema mismatch errors. +# - execsql $sql1 - set C1 [S1 changeset] - S1 delete +proc changeset_to_list {c} { + set list [list] + sqlite3session_foreach elem $c { lappend list $elem } + lsort $list +} - sqlite3session S1 db main ; S1 attach * +proc do_concat_test {tn args} { - execsql $sql2 - set C2 [S1 changeset] - S1 delete + set subtest 0 + foreach sql $args { + incr subtest + sqlite3session S db main ; S attach * + execsql $sql - set C3 [S2 changeset] - S2 delete + set c [S changeset] + if {[info commands s_prev] != ""} { + set c_concat [sqlite3changeset_concat $c_prev $c] + set c_two [s_prev changeset] + s_prev delete - set C4 [sqlite3changeset_concat $C1 $C2] + set h_concat [changeset_to_list $c_concat] + set h_two [changeset_to_list $c_two] - set c3 [list] - set c4 [list] - sqlite3session_foreach c $C3 { lappend c3 $c } - sqlite3session_foreach c $C4 { lappend c4 $c } - set c3 [lsort $c3] - set c4 [lsort $c4] + do_test $tn.$subtest [list set {} $h_concat] $h_two + } + set c_prev $c + rename S s_prev + } - do_test $tn [list set {} $c4] $c3 + catch { s_prev delete } } do_execsql_test 1.0 { @@ -121,4 +134,55 @@ do_concat_test 1.2.7 { DELETE FROM t1 WHERE a = 'I'; } +db function indirect indirect +proc indirect {{x -1}} { + S indirect $x + s_prev indirect $x +} + +do_concat_test 2.1 { + CREATE TABLE abc(a, b, c PRIMARY KEY); + INSERT INTO abc VALUES(NULL, NULL, 1); + INSERT INTO abc VALUES('abcdefghijkl', NULL, 2); +} { + DELETE FROM abc WHERE c = 1; + UPDATE abc SET c = 1 WHERE c = 2; +} { + INSERT INTO abc VALUES('abcdefghijkl', NULL, 2); + INSERT INTO abc VALUES(1.0, 2.0, 3); +} { + UPDATE abc SET a = a-1; +} { + CREATE TABLE def(d, e, f, PRIMARY KEY(e, f)); + INSERT INTO def VALUES('x', randomblob(11000), 67); + INSERT INTO def SELECT d, e, f+1 FROM def; + INSERT INTO def SELECT d, e, f+2 FROM def; + INSERT INTO def SELECT d, e, f+4 FROM def; +} { + DELETE FROM def WHERE rowid>4; +} { + INSERT INTO def SELECT d, e, f+4 FROM def; +} { + INSERT INTO abc VALUES(22, 44, -1); +} { + UPDATE abc SET c=-2 WHERE c=-1; + UPDATE abc SET c=-3 WHERE c=-2; +} { + UPDATE abc SET c=-4 WHERE c=-3; +} { + UPDATE abc SET a=a+1 WHERE c=-3; + UPDATE abc SET a=a+1 WHERE c=-3; +} { + UPDATE abc SET a=a+1 WHERE c=-3; + UPDATE abc SET a=a+1 WHERE c=-3; +} { + INSERT INTO abc VALUES('one', 'two', 'three'); +} { + SELECT indirect(1); + UPDATE abc SET a='one point five' WHERE c = 'three'; +} { + SELECT indirect(0); + UPDATE abc SET a='one point six' WHERE c = 'three'; +} + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 770fc13e30..f22fafa5dc 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -353,6 +353,20 @@ static unsigned int sessionPreupdateHash( return SQLITE_OK; } +/* +** The buffer that the argument points to contains a serialized SQL value. +** Return the number of bytes of space occupied by the value (including +** the type byte). +*/ +static int sessionSerialLen(u8 *a){ + int e = *a; + int n; + if( e==0 ) return 1; + if( e==SQLITE_NULL ) return 1; + if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; + return sessionVarintGet(&a[1], &n) + 1 + n; +} + /* ** Based on the primary key values stored in change aRecord, calculate a ** hash key, assuming the has table has nBucket buckets. The hash keys @@ -369,7 +383,7 @@ static unsigned int sessionChangeHash( u8 *a = aRecord; /* Used to iterate through change record */ for(i=0; inCol; i++){ - int eType = *a++; + int eType = *a; int isPK = pTab->abPK[i]; /* It is not possible for eType to be SQLITE_NULL here. The session @@ -377,31 +391,29 @@ static unsigned int sessionChangeHash( ** primary key columns. */ assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT || eType==SQLITE_TEXT || eType==SQLITE_BLOB + || eType==SQLITE_NULL || eType==0 ); + assert( !isPK || (eType!=0 && eType!=SQLITE_NULL) ); - if( isPK ) h = HASH_APPEND(h, eType); - if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ - if( isPK ) h = sessionHashAppendI64(h, sessionGetI64(a)); - a += 8; + if( isPK ){ + a++; + h = HASH_APPEND(h, eType); + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + if( isPK ) h = sessionHashAppendI64(h, sessionGetI64(a)); + a += 8; + }else{ + int n; + a += sessionVarintGet(a, &n); + if( isPK ) h = sessionHashAppendBlob(h, n, a); + a += n; + } }else{ - int n; - a += sessionVarintGet(a, &n); - if( isPK ) h = sessionHashAppendBlob(h, n, a); - a += n; + a += sessionSerialLen(a); } } return (h % nBucket); } -static int sessionSerialLen(u8 *a){ - int e = *a; - int n; - if( e==0 ) return 1; - if( e==SQLITE_NULL ) return 1; - if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; - return sessionVarintGet(&a[1], &n) + 1 + n; -} - static int sessionChangeEqual( SessionTable *pTab, u8 *aLeft, /* Change record */ @@ -419,7 +431,7 @@ static int sessionChangeEqual( return 0; } a1 += n1; - a2 += n1; + a2 += n2; } return 1; diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 10a94b927b..fcde98f842 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -522,10 +522,13 @@ int sqlite3changeset_invert( int *pnOut, void **ppOut /* OUT: Inverse of input */ ); +/* +** CAPI3REF: Combine Two Changeset Objects +*/ int sqlite3changeset_concat( - int nLeft, void *pLeft, /* Input changeset */ - int nRight, void *Right, /* Input changeset */ - int *pnOut, void **ppOut /* OUT: Inverse of input */ + int nLeft, void *pLeft, /* First input changeset */ + int nRight, void *Right, /* Second input changeset */ + int *pnOut, void **ppOut /* OUT: Output changeset */ ); /* diff --git a/manifest b/manifest index 4dcb9b0bb0..7b1c552c55 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Start\sadding\sthe\ssqlite3changeset_concat()\sfunction\sto\sthe\ssession\smodule. -D 2011-04-14T11:16:21.630 +C Add\sfurther\stests\sfor\sthe\ssqlite3changeset_concat()\sfunction.\sAlso\sfixes. +D 2011-04-14T18:01:41.789 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -103,11 +103,11 @@ F ext/session/session1.test 7a92a2a6f531aef1e9764ffb7f983fb8b315376d F ext/session/session2.test c3e5f78d5eb988e35cc2ba9ce3678f706283cfdb F ext/session/session3.test bfa2376db7cbb2ac69496f84d93a8d81b13110d3 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 -F ext/session/session5.test ed5025c96693d406fb13bcf330d1a962dcb68c24 +F ext/session/session5.test 9dff891440dc3a424daea914b7e08e9f137272ed F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 F ext/session/sessionfault.test 2544a2e2ecad56e3c07a32c09799871d243c114c -F ext/session/sqlite3session.c 124ac6d43ac5820add2e736b25432c3f6b5a733a -F ext/session/sqlite3session.h dc7c85fd27fa3a9a17b34e0951ed36cdced1bc67 +F ext/session/sqlite3session.c abf9846341847c5b81040683b143b511ee828f2e +F ext/session/sqlite3session.h e64876b299dcd1f8c9d043d59bfe14a94ee6b2ba F ext/session/test_session.c f4d1dca94db71ec2177ee61eab51e718e58476d7 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -938,7 +938,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 83705e90a54bad462a5b7fbca70cc129998f871c -R 2d3308935368f3ab85a5bea7204d6f97 +P 8927b2260b8d84f53776cb29e1d2fa41b6b0de0e +R f3f9539d9ce74ceea388d1aad2d1949b U dan -Z 4aed6546b387a7c5d8dbcb80467675b2 +Z 58678ea87adc6f0684f4c0fc5f0a6d31 diff --git a/manifest.uuid b/manifest.uuid index 4733d7436b..d6d4737a85 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8927b2260b8d84f53776cb29e1d2fa41b6b0de0e \ No newline at end of file +1fc3f15d88c160b45642b46d1d54c591af058ba2 \ No newline at end of file From 29e03e977c3acad3ad250c05c37e7a2e8ce11e54 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 15 Apr 2011 12:04:50 +0000 Subject: [PATCH 048/570] Add documentation for sqlite3changeset_concat() to sqlite3session.h. FossilOrigin-Name: ada9efa53a6ea55f89d237cfd530f1d180343e19 --- ext/session/sqlite3session.h | 80 ++++++++++++++++++++++++++++++++++-- manifest | 12 +++--- manifest.uuid | 2 +- 3 files changed, 83 insertions(+), 11 deletions(-) diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index fcde98f842..38164401f4 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -523,12 +523,84 @@ int sqlite3changeset_invert( ); /* -** CAPI3REF: Combine Two Changeset Objects +** CAPI3REF: Concatenate Two Changeset Objects +** +** This function is used to concatenate two changesets, A and B, into a +** single changeset. The result is a changeset equivalent to applying +** changeset A followed by changeset B. +** +** Rows are identified by the values in their PRIMARY KEY columns. A change +** in changeset A is considered to apply to the same row as a change in +** changeset B if the two rows have the same primary key. +** +** Changes to rows that appear only in changeset A or B are copied into the +** output changeset. Or, if both changeset A and B contain a change that +** applies to a single row, the output depends on the type of each change, +** as follows: +** +** +** +** +**
Change A Change B Output Change +**
INSERT INSERT +** Change A is copied into the output changeset. Change B is discarded. +** This case does not occur if changeset B is recorded immediately after +** changeset A. +**
INSERT UPDATE +** An INSERT change is copied into the output changeset. The values in +** the INSERT change are as if the row was inserted by change A and then +** updated according to change B. +**
INSERT DELETE +** No change at all is copied into the output changeset. +**
UPDATE INSERT +** Change A is copied into the output changeset. Change B is discarded. +** This case does not occur if changeset B is recorded immediately after +** changeset A. +**
UPDATE UPDATE +** A single UPDATE is copied into the output changeset. The accompanying +** values are as if the row was updated once by change A and then again +** by change B. +**
UPDATE DELETE +** A single DELETE is copied into the output changeset. +**
DELETE INSERT +** If one or more of the column values in the row inserted by change +** B differ from those in the row deleted by change A, an UPDATE +** change is added to the output changeset. Otherwise, if the inserted +** row is exactly the same as the deleted row, no change is added to +** the output changeset. +**
DELETE UPDATE +** Change A is copied into the output changeset. Change B is discarded. +** This case does not occur if changeset B is recorded immediately after +** changeset A. +**
DELETE DELETE +** Change A is copied into the output changeset. Change B is discarded. +** This case does not occur if changeset B is recorded immediately after +** changeset A. +**
+** +** If the two changesets contain changes to the same table, then the number +** of columns and the position of the primary key columns for the table must +** be the same in each changeset. If this is not the case, attempting to +** concatenate the two changesets together fails and this function returns +** SQLITE_SCHEMA. If either of the two input changesets appear to be corrupt, +** and the corruption is detected, SQLITE_CORRUPT is returned. Or, if an +** out-of-memory condition occurs during processing, this function returns +** SQLITE_NOMEM. +** +** If none of the above errors occur, SQLITE_OK is returned and *ppOut set +** to point to a buffer containing the output changeset. It is the +** responsibility of the caller to eventually call sqlite3_free() on *ppOut +** to release memory allocated for the buffer. *pnOut is set to the number +** of bytes in the output changeset. If an error does occur, both *ppOut and +** *pnOut are set to zero before returning. */ int sqlite3changeset_concat( - int nLeft, void *pLeft, /* First input changeset */ - int nRight, void *Right, /* Second input changeset */ - int *pnOut, void **ppOut /* OUT: Output changeset */ + int nA, /* Number of bytes in buffer pA */ + void *pA, /* Pointer to buffer containing changeset A */ + int nB, /* Number of bytes in buffer pB */ + void *pB, /* Pointer to buffer containing changeset B */ + int *pnOut, /* OUT: Number of bytes in output changeset */ + void **ppOut /* OUT: Buffer containing output changeset */ ); /* diff --git a/manifest b/manifest index 7b1c552c55..be42cd3f25 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sfurther\stests\sfor\sthe\ssqlite3changeset_concat()\sfunction.\sAlso\sfixes. -D 2011-04-14T18:01:41.789 +C Add\sdocumentation\sfor\ssqlite3changeset_concat()\sto\ssqlite3session.h. +D 2011-04-15T12:04:50.155 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -107,7 +107,7 @@ F ext/session/session5.test 9dff891440dc3a424daea914b7e08e9f137272ed F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 F ext/session/sessionfault.test 2544a2e2ecad56e3c07a32c09799871d243c114c F ext/session/sqlite3session.c abf9846341847c5b81040683b143b511ee828f2e -F ext/session/sqlite3session.h e64876b299dcd1f8c9d043d59bfe14a94ee6b2ba +F ext/session/sqlite3session.h 665f5591562e3c71eb3d0da26f1a1efae26f7bcf F ext/session/test_session.c f4d1dca94db71ec2177ee61eab51e718e58476d7 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -938,7 +938,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 8927b2260b8d84f53776cb29e1d2fa41b6b0de0e -R f3f9539d9ce74ceea388d1aad2d1949b +P 1fc3f15d88c160b45642b46d1d54c591af058ba2 +R 5b10e49a76b6665385d53106c727e888 U dan -Z 58678ea87adc6f0684f4c0fc5f0a6d31 +Z 6bd794c4ce6596f42844ff8d0a6b8d50 diff --git a/manifest.uuid b/manifest.uuid index d6d4737a85..7b35dd9932 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1fc3f15d88c160b45642b46d1d54c591af058ba2 \ No newline at end of file +ada9efa53a6ea55f89d237cfd530f1d180343e19 \ No newline at end of file From f29123b5725a9b3a385045a4847788be2d88642c Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 15 Apr 2011 15:04:31 +0000 Subject: [PATCH 049/570] Have sqlite3changeset_concat() return SQLITE_SCHEMA if an attempt is made to concatenate changesets based on incompatible database schemas. FossilOrigin-Name: 343b64517d244b75097e38342dc273eb5a52915b --- ext/session/session5.test | 56 +++++++++++++++++++++++++++++++++++- ext/session/sqlite3session.c | 15 ++++++++-- manifest | 14 ++++----- manifest.uuid | 2 +- 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/ext/session/session5.test b/ext/session/session5.test index 676b2c718f..d2761b3218 100644 --- a/ext/session/session5.test +++ b/ext/session/session5.test @@ -63,6 +63,9 @@ proc do_concat_test {tn args} { catch { s_prev delete } } +#------------------------------------------------------------------------- +# Test cases session5-1.* - simple tests. +# do_execsql_test 1.0 { CREATE TABLE t1(a PRIMARY KEY, b); } @@ -134,12 +137,15 @@ do_concat_test 1.2.7 { DELETE FROM t1 WHERE a = 'I'; } + +#------------------------------------------------------------------------- +# Test cases session5-2.* - more complex tests. +# db function indirect indirect proc indirect {{x -1}} { S indirect $x s_prev indirect $x } - do_concat_test 2.1 { CREATE TABLE abc(a, b, c PRIMARY KEY); INSERT INTO abc VALUES(NULL, NULL, 1); @@ -185,4 +191,52 @@ do_concat_test 2.1 { UPDATE abc SET a='one point six' WHERE c = 'three'; } +#------------------------------------------------------------------------- +# Test that schema incompatibilities are detected correctly. +# +# session5-3.1: Incompatible number of columns. +# session5-3.2: Incompatible PK definition. +# +proc sql_to_changeset {sql} { + sqlite3session S db main + S attach * + execsql $sql + set c [S changeset] + S delete + return $c +} + +do_test 3.1 { + db close + forcedelete test.db + sqlite3 db test.db + + execsql { CREATE TABLE t1(a PRIMARY KEY, b) } + set c1 [sql_to_changeset { INSERT INTO t1 VALUES(1, 2) }] + execsql { + DROP TABLE t1; + CREATE TABLE t1(a PRIMARY KEY, b, c); + } + set c2 [sql_to_changeset { INSERT INTO t1 VALUES(2, 3, 4) }] + + list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg +} {1 SQLITE_SCHEMA} + +do_test 3.2 { + db close + forcedelete test.db + sqlite3 db test.db + + execsql { CREATE TABLE t1(a PRIMARY KEY, b) } + set c1 [sql_to_changeset { INSERT INTO t1 VALUES(1, 2) }] + execsql { + DROP TABLE t1; + CREATE TABLE t1(a, b PRIMARY KEY); + } + set c2 [sql_to_changeset { INSERT INTO t1 VALUES(2, 3) }] + + list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg +} {1 SQLITE_SCHEMA} + + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index f22fafa5dc..b37b1b33f7 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2862,19 +2862,28 @@ int sessionConcatChangeset( if( !pTab || zNew!=pTab->zName ){ /* Search the list for a matching table */ int nNew = strlen(zNew); + u8 *abPK; + + sqlite3changeset_pk(pIter, &abPK, 0); for(pTab = *ppTabList; pTab; pTab=pTab->pNext){ if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break; } if( !pTab ){ pTab = sqlite3_malloc(sizeof(SessionTable)); - if( !pTab ) break; + if( !pTab ){ + rc = SQLITE_NOMEM; + break; + } memset(pTab, 0, sizeof(SessionTable)); pTab->pNext = *ppTabList; + pTab->abPK = abPK; + pTab->nCol = nCol; *ppTabList = pTab; + }else if( pTab->nCol!=nCol || memcmp(pTab->abPK, abPK, nCol) ){ + rc = SQLITE_SCHEMA; + break; } pTab->zName = (char *)zNew; - pTab->nCol = nCol; - sqlite3changeset_pk(pIter, &pTab->abPK, 0); } if( sessionGrowHash(pTab) ) break; diff --git a/manifest b/manifest index be42cd3f25..8e07b45dbd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sdocumentation\sfor\ssqlite3changeset_concat()\sto\ssqlite3session.h. -D 2011-04-15T12:04:50.155 +C Have\ssqlite3changeset_concat()\sreturn\sSQLITE_SCHEMA\sif\san\sattempt\sis\smade\sto\sconcatenate\schangesets\sbased\son\sincompatible\sdatabase\sschemas. +D 2011-04-15T15:04:31.042 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -103,10 +103,10 @@ F ext/session/session1.test 7a92a2a6f531aef1e9764ffb7f983fb8b315376d F ext/session/session2.test c3e5f78d5eb988e35cc2ba9ce3678f706283cfdb F ext/session/session3.test bfa2376db7cbb2ac69496f84d93a8d81b13110d3 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 -F ext/session/session5.test 9dff891440dc3a424daea914b7e08e9f137272ed +F ext/session/session5.test cbb011a1b2f487d2fe4b014fb6ae3a67e5f7f767 F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 F ext/session/sessionfault.test 2544a2e2ecad56e3c07a32c09799871d243c114c -F ext/session/sqlite3session.c abf9846341847c5b81040683b143b511ee828f2e +F ext/session/sqlite3session.c b5293510224e42c50d69a509e6bfaca45defec76 F ext/session/sqlite3session.h 665f5591562e3c71eb3d0da26f1a1efae26f7bcf F ext/session/test_session.c f4d1dca94db71ec2177ee61eab51e718e58476d7 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -938,7 +938,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 1fc3f15d88c160b45642b46d1d54c591af058ba2 -R 5b10e49a76b6665385d53106c727e888 +P ada9efa53a6ea55f89d237cfd530f1d180343e19 +R bdb9eba45cd97b77f78325d72d96c5f4 U dan -Z 6bd794c4ce6596f42844ff8d0a6b8d50 +Z 570068f4f013ca36918b632f2a36093d diff --git a/manifest.uuid b/manifest.uuid index 7b35dd9932..6943cc86d4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ada9efa53a6ea55f89d237cfd530f1d180343e19 \ No newline at end of file +343b64517d244b75097e38342dc273eb5a52915b \ No newline at end of file From 1756ae10e16dd7a7892d9f4be98fef51b7193183 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 15 Apr 2011 16:03:32 +0000 Subject: [PATCH 050/570] Add tests and fixes for OOM handling in sqlite3changeset_concat(). FossilOrigin-Name: df0b2d21dcd81679e55b24866f97568019932983 --- ext/session/session5.test | 41 ++++++++++++++++++-------------- ext/session/session_common.tcl | 6 ++++- ext/session/sessionfault.test | 43 ++++++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 6 ++++- manifest | 18 +++++++------- manifest.uuid | 2 +- 6 files changed, 86 insertions(+), 30 deletions(-) diff --git a/ext/session/session5.test b/ext/session/session5.test index d2761b3218..9cce67dcc1 100644 --- a/ext/session/session5.test +++ b/ext/session/session5.test @@ -31,12 +31,6 @@ set testprefix session5 # session5-3.*: Schema mismatch errors. # -proc changeset_to_list {c} { - set list [list] - sqlite3session_foreach elem $c { lappend list $elem } - lsort $list -} - proc do_concat_test {tn args} { set subtest 0 @@ -191,20 +185,31 @@ do_concat_test 2.1 { UPDATE abc SET a='one point six' WHERE c = 'three'; } +catch {db close} +forcedelete test.db +sqlite3 db test.db +do_concat_test 2.2 { + CREATE TABLE t1(a, b, PRIMARY KEY(b)); + CREATE TABLE t2(a PRIMARY KEY, b); + INSERT INTO t1 VALUES('string', 1); + INSERT INTO t1 VALUES(4, 2); + INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3); +} { + INSERT INTO t2 VALUES('one', 'two'); + INSERT INTO t2 VALUES(1, NULL); + UPDATE t1 SET a = 5 WHERE a = 2; +} { + DELETE FROM t2 WHERE a = 1; + UPDATE t1 SET a = 4 WHERE a = 2; + INSERT INTO t2 VALUES('x', 'y'); +} + #------------------------------------------------------------------------- # Test that schema incompatibilities are detected correctly. # # session5-3.1: Incompatible number of columns. # session5-3.2: Incompatible PK definition. # -proc sql_to_changeset {sql} { - sqlite3session S db main - S attach * - execsql $sql - set c [S changeset] - S delete - return $c -} do_test 3.1 { db close @@ -212,12 +217,12 @@ do_test 3.1 { sqlite3 db test.db execsql { CREATE TABLE t1(a PRIMARY KEY, b) } - set c1 [sql_to_changeset { INSERT INTO t1 VALUES(1, 2) }] + set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }] execsql { DROP TABLE t1; CREATE TABLE t1(a PRIMARY KEY, b, c); } - set c2 [sql_to_changeset { INSERT INTO t1 VALUES(2, 3, 4) }] + set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3, 4) }] list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg } {1 SQLITE_SCHEMA} @@ -228,12 +233,12 @@ do_test 3.2 { sqlite3 db test.db execsql { CREATE TABLE t1(a PRIMARY KEY, b) } - set c1 [sql_to_changeset { INSERT INTO t1 VALUES(1, 2) }] + set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }] execsql { DROP TABLE t1; CREATE TABLE t1(a, b PRIMARY KEY); } - set c2 [sql_to_changeset { INSERT INTO t1 VALUES(2, 3) }] + set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3) }] list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg } {1 SQLITE_SCHEMA} diff --git a/ext/session/session_common.tcl b/ext/session/session_common.tcl index d5c74fba5c..53870c4027 100644 --- a/ext/session/session_common.tcl +++ b/ext/session/session_common.tcl @@ -128,5 +128,9 @@ proc compare_db {db1 db2} { return "" } - +proc changeset_to_list {c} { + set list [list] + sqlite3session_foreach elem $c { lappend list $elem } + lsort $list +} diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index cf155f4f3d..c21d72fb81 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -251,4 +251,47 @@ do_faultsim_test 5 -faults oom* -body { } } +#------------------------------------------------------------------------- +# Test that OOM errors in sqlite3changeset_concat() are handled correctly. +# +catch {db close} +forcedelete test.db +sqlite3 db test.db +do_execsql_test 5.prep1 { + CREATE TABLE t1(a, b, PRIMARY KEY(b)); + CREATE TABLE t2(a PRIMARY KEY, b); + INSERT INTO t1 VALUES('string', 1); + INSERT INTO t1 VALUES(4, 2); + INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3); +} + +do_test 5.prep2 { + sqlite3session M db main + M attach * + set ::c2 [changeset_from_sql { + INSERT INTO t2 VALUES(randomblob(1000), randomblob(1000)); + INSERT INTO t2 VALUES('one', 'two'); + INSERT INTO t2 VALUES(1, NULL); + UPDATE t1 SET a = 5 WHERE a = 2; + }] + set ::c1 [changeset_from_sql { + DELETE FROM t2 WHERE a = 1; + UPDATE t1 SET a = 4 WHERE a = 2; + INSERT INTO t2 VALUES('x', 'y'); + }] + set ::total [changeset_to_list [M changeset]] + M delete +} {} + +do_faultsim_test 6 -faults oom-* -body { + set ::result [sqlite3changeset_concat $::c1 $::c2] + set {} {} +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + if {$testrc==0} { + set v [changeset_to_list $::result] + if {$v != $::total} { error "result no good" } + } +} + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index b37b1b33f7..41665ce9e9 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2786,6 +2786,7 @@ static int sessionChangeMerge( nByte = sizeof(SessionChange) + pExist->nRecord + nRec; pNew = (SessionChange *)sqlite3_malloc(nByte); if( !pNew ){ + sqlite3_free(pExist); return SQLITE_NOMEM; } memset(pNew, 0, sizeof(SessionChange)); @@ -2886,7 +2887,10 @@ int sessionConcatChangeset( pTab->zName = (char *)zNew; } - if( sessionGrowHash(pTab) ) break; + if( sessionGrowHash(pTab) ){ + rc = SQLITE_NOMEM; + break; + } iHash = sessionChangeHash(pTab, aRec, pTab->nChange); /* Search for existing entry. If found, remove it from the hash table. diff --git a/manifest b/manifest index 8e07b45dbd..b165b9433c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Have\ssqlite3changeset_concat()\sreturn\sSQLITE_SCHEMA\sif\san\sattempt\sis\smade\sto\sconcatenate\schangesets\sbased\son\sincompatible\sdatabase\sschemas. -D 2011-04-15T15:04:31.042 +C Add\stests\sand\sfixes\sfor\sOOM\shandling\sin\ssqlite3changeset_concat(). +D 2011-04-15T16:03:32.057 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -103,10 +103,10 @@ F ext/session/session1.test 7a92a2a6f531aef1e9764ffb7f983fb8b315376d F ext/session/session2.test c3e5f78d5eb988e35cc2ba9ce3678f706283cfdb F ext/session/session3.test bfa2376db7cbb2ac69496f84d93a8d81b13110d3 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 -F ext/session/session5.test cbb011a1b2f487d2fe4b014fb6ae3a67e5f7f767 -F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 -F ext/session/sessionfault.test 2544a2e2ecad56e3c07a32c09799871d243c114c -F ext/session/sqlite3session.c b5293510224e42c50d69a509e6bfaca45defec76 +F ext/session/session5.test 940d77c748808769cac50fb62bb674aa84e472f2 +F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 +F ext/session/sessionfault.test 2766cd620f1793f0e54f1e3859a184bcea55bad4 +F ext/session/sqlite3session.c 08573805932a9db4158f36663e01747d0ff69342 F ext/session/sqlite3session.h 665f5591562e3c71eb3d0da26f1a1efae26f7bcf F ext/session/test_session.c f4d1dca94db71ec2177ee61eab51e718e58476d7 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -938,7 +938,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P ada9efa53a6ea55f89d237cfd530f1d180343e19 -R bdb9eba45cd97b77f78325d72d96c5f4 +P 343b64517d244b75097e38342dc273eb5a52915b +R c818789c65113df118a04c3a29f3e5ba U dan -Z 570068f4f013ca36918b632f2a36093d +Z 7081c2709375635b8446c7ef8a86300e diff --git a/manifest.uuid b/manifest.uuid index 6943cc86d4..72289d19b5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -343b64517d244b75097e38342dc273eb5a52915b \ No newline at end of file +df0b2d21dcd81679e55b24866f97568019932983 \ No newline at end of file From b08a1efae52f0252fcde355fffaad4aa4cf3cdfd Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 15 Apr 2011 19:18:57 +0000 Subject: [PATCH 051/570] Improve coverage of session module. FossilOrigin-Name: 3dfd1d63bddfa9bd9018eb00bee1d496379630b5 --- ext/session/session5.test | 51 ++++++++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 29 +++++++++++--------- manifest | 14 +++++----- manifest.uuid | 2 +- 4 files changed, 76 insertions(+), 20 deletions(-) diff --git a/ext/session/session5.test b/ext/session/session5.test index 9cce67dcc1..1e67e1d325 100644 --- a/ext/session/session5.test +++ b/ext/session/session5.test @@ -183,6 +183,13 @@ do_concat_test 2.1 { } { SELECT indirect(0); UPDATE abc SET a='one point six' WHERE c = 'three'; +} { + CREATE TABLE x1(a, b, PRIMARY KEY(a)); + SELECT indirect(1); + INSERT INTO x1 VALUES(1, 2); +} { + SELECT indirect(1); + UPDATE x1 SET b = 3 WHERE a = 1; } catch {db close} @@ -204,6 +211,50 @@ do_concat_test 2.2 { INSERT INTO t2 VALUES('x', 'y'); } +do_test 2.3.0 { + catch {db close} + forcedelete test.db + sqlite3 db test.db + + set sql1 "" + set sql2 "" + for {set i 1} {$i < 120} {incr i} { + append sql1 "INSERT INTO x1 VALUES($i*4, $i);" + } + for {set i 1} {$i < 120} {incr i} { + append sql2 "DELETE FROM x1 WHERE a = $i*4;" + } + + set {} {} +} {} +do_concat_test 2.3 { + CREATE TABLE x1(a PRIMARY KEY, b) +} $sql1 $sql2 $sql1 $sql2 + +do_concat_test 2.4 { + CREATE TABLE x2(a PRIMARY KEY, b); + CREATE TABLE x3(a PRIMARY KEY, b); + + INSERT INTO x2 VALUES('a', 'b'); + INSERT INTO x2 VALUES('x', 'y'); + INSERT INTO x3 VALUES('a', 'b'); +} { + INSERT INTO x2 VALUES('c', 'd'); + INSERT INTO x3 VALUES('e', 'f'); + INSERT INTO x3 VALUES('x', 'y'); +} + +do_concat_test 2.5 { + UPDATE x3 SET b = 'Y' WHERE a = 'x' +} { + DELETE FROM x3 WHERE a = 'x' +} { + DELETE FROM x2 WHERE a = 'a' +} { + INSERT INTO x2 VALUES('a', 'B'); +} + + #------------------------------------------------------------------------- # Test that schema incompatibilities are detected correctly. # diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 41665ce9e9..bad6240a1f 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2793,13 +2793,21 @@ static int sessionChangeMerge( pNew->bIndirect = (bIndirect && pExist->bIndirect); aCsr = pNew->aRecord = (u8 *)&pNew[1]; - if( op1==SQLITE_INSERT && op2==SQLITE_UPDATE ){ + if( op1==SQLITE_INSERT ){ /* INSERT + UPDATE */ u8 *a1 = aRec; + assert( op2==SQLITE_UPDATE ); pNew->bInsert = SQLITE_INSERT; sessionReadRecord(&a1, pTab->nCol, 0); sessionMergeRecord(&aCsr, pTab, pExist->aRecord, a1); - } - else if( op1==SQLITE_UPDATE && op2==SQLITE_UPDATE ){ + }else if( op1==SQLITE_DELETE ){ /* DELETE + INSERT */ + assert( op2==SQLITE_INSERT ); + pNew->bInsert = SQLITE_UPDATE; + if( 0==sessionMergeUpdate(&aCsr, pTab, pExist->aRecord, 0, aRec, 0) ){ + sqlite3_free(pNew); + pNew = 0; + } + }else if( op2==SQLITE_UPDATE ){ /* UPDATE + UPDATE */ + assert( op1==SQLITE_UPDATE ); u8 *a1 = pExist->aRecord; u8 *a2 = aRec; sessionReadRecord(&a1, pTab->nCol, 0); @@ -2809,18 +2817,11 @@ static int sessionChangeMerge( sqlite3_free(pNew); pNew = 0; } - } - else if( op1==SQLITE_UPDATE && op2==SQLITE_DELETE ){ + }else{ /* UPDATE + DELETE */ + assert( op1==SQLITE_UPDATE && op2==SQLITE_DELETE ); pNew->bInsert = SQLITE_DELETE; sessionMergeRecord(&aCsr, pTab, aRec, pExist->aRecord); } - else if( op1==SQLITE_DELETE && op2==SQLITE_INSERT ){ - pNew->bInsert = SQLITE_UPDATE; - if( 0==sessionMergeUpdate(&aCsr, pTab, pExist->aRecord, 0, aRec, 0) ){ - sqlite3_free(pNew); - pNew = 0; - } - } if( pNew ){ pNew->nRecord = (aCsr - pNew->aRecord); @@ -2860,6 +2861,10 @@ int sessionConcatChangeset( assert( pIter->apValue==0 ); sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect); + assert( zNew>=(char *)pChangeset && zNew-nChangeset<((char *)pChangeset) ); + assert( !pTab || pTab->zName-nChangeset<(char *)pChangeset ); + assert( !pTab || zNew>=pTab->zName ); + if( !pTab || zNew!=pTab->zName ){ /* Search the list for a matching table */ int nNew = strlen(zNew); diff --git a/manifest b/manifest index b165b9433c..bc49322d17 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sand\sfixes\sfor\sOOM\shandling\sin\ssqlite3changeset_concat(). -D 2011-04-15T16:03:32.057 +C Improve\scoverage\sof\ssession\smodule. +D 2011-04-15T19:18:57.799 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -103,10 +103,10 @@ F ext/session/session1.test 7a92a2a6f531aef1e9764ffb7f983fb8b315376d F ext/session/session2.test c3e5f78d5eb988e35cc2ba9ce3678f706283cfdb F ext/session/session3.test bfa2376db7cbb2ac69496f84d93a8d81b13110d3 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 -F ext/session/session5.test 940d77c748808769cac50fb62bb674aa84e472f2 +F ext/session/session5.test 525503799d56124a31bedbd7895c1e668d18420d F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 2766cd620f1793f0e54f1e3859a184bcea55bad4 -F ext/session/sqlite3session.c 08573805932a9db4158f36663e01747d0ff69342 +F ext/session/sqlite3session.c 4c44da92750d4b31bcbed25428be7167cddccf84 F ext/session/sqlite3session.h 665f5591562e3c71eb3d0da26f1a1efae26f7bcf F ext/session/test_session.c f4d1dca94db71ec2177ee61eab51e718e58476d7 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -938,7 +938,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 343b64517d244b75097e38342dc273eb5a52915b -R c818789c65113df118a04c3a29f3e5ba +P df0b2d21dcd81679e55b24866f97568019932983 +R b4d7dfa6bf40d53e75863a5a6b9fd8ce U dan -Z 7081c2709375635b8446c7ef8a86300e +Z 2d321dbf5ee44d87c34feecb146a5235 diff --git a/manifest.uuid b/manifest.uuid index 72289d19b5..8ae1676306 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -df0b2d21dcd81679e55b24866f97568019932983 \ No newline at end of file +3dfd1d63bddfa9bd9018eb00bee1d496379630b5 \ No newline at end of file From 6734007d75cfd1785843aea9b8c3b6b568662c74 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 16 Apr 2011 19:23:10 +0000 Subject: [PATCH 052/570] Improve test coverage of session module. FossilOrigin-Name: f46d4b641d613c39a80b12106e6a6ac0efc8be83 --- ext/session/session1.test | 22 +++++++ ext/session/session3.test | 33 +++++++++- ext/session/session5.test | 113 +++++++++++++++++++++++++++++++++- ext/session/sessionfault.test | 101 +++++++++++++++++++++++++++++- ext/session/sqlite3session.c | 108 +++++++++++++++++--------------- ext/session/test_session.c | 31 ++++++++-- manifest | 24 ++++---- manifest.uuid | 2 +- test/tester.tcl | 8 ++- 9 files changed, 369 insertions(+), 73 deletions(-) diff --git a/ext/session/session1.test b/ext/session/session1.test index 067432affa..5e0fbc52a0 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -443,5 +443,27 @@ do_conflict_test 6.1 -tables {t1 t2} -sql { do_db2_test 6.2 "SELECT * FROM t1" {a b 1 2} do_db2_test 6.3 "SELECT * FROM t2" {a b A B} +#------------------------------------------------------------------------- +# Test that session objects are not confused by changes to table in +# other databases. +# +catch { db2 close } +drop_all_tables +forcedelete test.db2 +do_iterator_test 7.1 * { + ATTACH 'test.db2' AS aux; + CREATE TABLE main.t1(x PRIMARY KEY, y); + CREATE TABLE aux.t1(x PRIMARY KEY, y); + + INSERT INTO main.t1 VALUES('one', 1); + INSERT INTO main.t1 VALUES('two', 2); + INSERT INTO aux.t1 VALUES('three', 3); + INSERT INTO aux.t1 VALUES('four', 4); +} { + {INSERT t1 0 X. {} {t two i 2}} + {INSERT t1 0 X. {} {t one i 1}} +} + + catch { db2 close } finish_test diff --git a/ext/session/session3.test b/ext/session/session3.test index c0fcebff66..e15407c2eb 100644 --- a/ext/session/session3.test +++ b/ext/session/session3.test @@ -119,7 +119,6 @@ do_test 2.2.1 { } list [catch { S changeset } msg] $msg } {1 SQLITE_SCHEMA} - do_test 2.2.2 { S delete sqlite3session S db main @@ -135,6 +134,38 @@ do_test 2.2.2 { } list [catch { S changeset } msg] $msg } {1 SQLITE_SCHEMA} +do_test 2.2.3 { + S delete + sqlite3session S db main + execsql { + DROP TABLE t2; + CREATE TABLE t2(a, b PRIMARY KEY, c); + } + S attach t2 + execsql { + INSERT INTO t2 VALUES(1, 2, 3); + DROP TABLE t2; + CREATE TABLE t2(a, b PRIMARY KEY); + INSERT INTO t2 VALUES(4, 5); + } + list [catch { S changeset } msg] $msg +} {1 SQLITE_SCHEMA} +do_test 2.2.4 { + S delete + sqlite3session S db main + execsql { + DROP TABLE t2; + CREATE TABLE t2(a, b PRIMARY KEY, c); + } + S attach t2 + execsql { + INSERT INTO t2 VALUES(1, 2, 3); + DROP TABLE t2; + CREATE TABLE t2(a, b PRIMARY KEY, c, d); + INSERT INTO t2 VALUES(4, 5, 6, 7); + } + list [catch { S changeset } msg] $msg +} {1 SQLITE_SCHEMA} do_test 2.3 { S delete diff --git a/ext/session/session5.test b/ext/session/session5.test index 1e67e1d325..88430057d0 100644 --- a/ext/session/session5.test +++ b/ext/session/session5.test @@ -30,6 +30,11 @@ set testprefix session5 # # session5-3.*: Schema mismatch errors. # +# session5-4.*: Test the concat cases that indicate that the database +# was modified in between recording of the two changesets +# being concatenated (i.e. two changesets that INSERT rows +# with the same PK values). +# proc do_concat_test {tn args} { @@ -224,7 +229,6 @@ do_test 2.3.0 { for {set i 1} {$i < 120} {incr i} { append sql2 "DELETE FROM x1 WHERE a = $i*4;" } - set {} {} } {} do_concat_test 2.3 { @@ -254,6 +258,47 @@ do_concat_test 2.5 { INSERT INTO x2 VALUES('a', 'B'); } +for {set k 1} {$k <=10} {incr k} { + do_test 2.6.$k.1 { + drop_all_tables + set sql1 "" + set sql2 "" + for {set i 1} {$i < 120} {incr i} { + append sql1 "INSERT INTO x1 VALUES(randomblob(20+(random()%10)), $i);" + } + for {set i 1} {$i < 120} {incr i} { + append sql2 "DELETE FROM x1 WHERE rowid = $i;" + } + set {} {} + } {} + do_concat_test 2.6.$k { + CREATE TABLE x1(a PRIMARY KEY, b) + } $sql1 $sql2 $sql1 $sql2 +} + +for {set k 1} {$k <=10} {incr k} { + do_test 2.7.$k.1 { + drop_all_tables + set sql1 "" + set sql2 "" + for {set i 1} {$i < 120} {incr i} { + append sql1 { + INSERT INTO x1 VALUES( + CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END, + CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END + ); + } + } + for {set i 1} {$i < 120} {incr i} { + append sql2 "DELETE FROM x1 WHERE rowid = $i;" + } + set {} {} + } {} + do_concat_test 2.7.$k { + CREATE TABLE x1(a PRIMARY KEY, b) + } $sql1 $sql2 $sql1 $sql2 +} + #------------------------------------------------------------------------- # Test that schema incompatibilities are detected correctly. @@ -294,5 +339,71 @@ do_test 3.2 { list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg } {1 SQLITE_SCHEMA} +#------------------------------------------------------------------------- +# Test that concat() handles these properly: +# +# session5-4.1: INSERT + INSERT +# session5-4.2: UPDATE + INSERT +# session5-4.3: DELETE + UPDATE +# session5-4.4: DELETE + DELETE +# + +proc do_concat_test2 {tn sql1 sqlX sql2 expected} { + sqlite3session S db main ; S attach * + execsql $sql1 + set ::c1 [S changeset] + S delete + + execsql $sqlX + + sqlite3session S db main ; S attach * + execsql $sql2 + set ::c2 [S changeset] + S delete + + uplevel do_test $tn [list { + changeset_to_list [sqlite3changeset_concat $::c1 $::c2] + }] [list [normalize_list $expected]] +} + +drop_all_tables db +do_concat_test2 4.1 { + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES('key', 'value'); +} { + DELETE FROM t1 WHERE a = 'key'; +} { + INSERT INTO t1 VALUES('key', 'xxx'); +} { + {INSERT t1 0 X. {} {t key t value}} +} +do_concat_test2 4.2 { + UPDATE t1 SET b = 'yyy'; +} { + DELETE FROM t1 WHERE a = 'key'; +} { + INSERT INTO t1 VALUES('key', 'value'); +} { + {UPDATE t1 0 X. {t key t xxx} {{} {} t yyy}} +} +do_concat_test2 4.3 { + DELETE FROM t1 WHERE a = 'key'; +} { + INSERT INTO t1 VALUES('key', 'www'); +} { + UPDATE t1 SET b = 'valueX' WHERE a = 'key'; +} { + {DELETE t1 0 X. {t key t value} {}} +} +do_concat_test2 4.4 { + DELETE FROM t1 WHERE a = 'key'; +} { + INSERT INTO t1 VALUES('key', 'ttt'); +} { + DELETE FROM t1 WHERE a = 'key'; +} { + {DELETE t1 0 X. {t key t valueX} {}} +} finish_test + diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index c21d72fb81..b9800e1f46 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -265,7 +265,7 @@ do_execsql_test 5.prep1 { INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3); } -do_test 5.prep2 { +do_test 6.prep2 { sqlite3session M db main M attach * set ::c2 [changeset_from_sql { @@ -294,4 +294,103 @@ do_faultsim_test 6 -faults oom-* -body { } } +faultsim_delete_and_reopen +do_execsql_test 5.prep1 { + CREATE TABLE t1(a, b, PRIMARY KEY(a)); +} +faultsim_save_and_close + +set res [list] +for {set ::i 0} {$::i < 480} {incr ::i 4} { + lappend res "INSERT t1 0 X. {} {i $::i i $::i}" +} +set res [lsort $res] +do_faultsim_test 7 -faults oom-transient -prep { + faultsim_restore_and_reopen + sqlite3session S db main + S attach * +} -body { + for {set ::i 0} {$::i < 480} {incr ::i 4} { + execsql {INSERT INTO t1 VALUES($::i, $::i)} + } +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + if {$testrc==0} { + set cres [list [catch {changeset_to_list [S changeset]} msg] $msg] + S delete + if {$cres != "1 SQLITE_NOMEM" && $cres != "0 {$::res}"} { + error "Expected {0 $::res} Got {$cres}" + } + } else { + S changeset + S delete + } +} + +faultsim_delete_and_reopen +do_test 8.prep { + sqlite3session S db main + S attach * + execsql { + CREATE TABLE t1(a, b, PRIMARY KEY(a)); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(3, 4); + INSERT INTO t1 VALUES(5, 6); + } + set ::changeset [S changeset] + S delete +} {} + +set expected [normalize_list { + {INSERT t1 0 X. {} {i 1 i 2}} + {INSERT t1 0 X. {} {i 3 i 4}} + {INSERT t1 0 X. {} {i 5 i 6}} +}] +do_faultsim_test 8.1 -faults oom* -body { + set ::res [list] + sqlite3session_foreach -next v $::changeset { lappend ::res $v } + normalize_list $::res +} -test { + faultsim_test_result [list 0 $::expected] {1 SQLITE_NOMEM} +} +do_faultsim_test 8.2 -faults oom* -body { + set ::res [list] + sqlite3session_foreach v $::changeset { lappend ::res $v } + normalize_list $::res +} -test { + faultsim_test_result [list 0 $::expected] {1 SQLITE_NOMEM} +} + +faultsim_delete_and_reopen +do_test 9.prep { + execsql { + PRAGMA encoding = 'utf16'; + CREATE TABLE t1(a PRIMARY KEY, b); + } +} {} +faultsim_save_and_close + +do_faultsim_test 9 -faults oom-transient -prep { + catch { unset ::c } + faultsim_restore_and_reopen + sqlite3session S db main + S attach * +} -body { + execsql { + INSERT INTO t1 VALUES('abcdefghijklmnopqrstuv', 'ABCDEFGHIJKLMNOPQRSTUV'); + } + set ::c [S changeset] + set {} {} +} -test { + S delete + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} {1 {callback requested query abort}} + if {[info exists ::c]} { + set expected "{INSERT t1 0 X. {} {t abcdefghijklmnopqrstuv t ABCDEFGHIJKLMNOPQRSTUV}}" + if { [changeset_to_list $::c] != $expected } { + error "changeset mismatch" + } + } +} + + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index bad6240a1f..4f81170621 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -317,34 +317,29 @@ static unsigned int sessionPreupdateHash( eType = sqlite3_value_type(pVal); h = HASH_APPEND(h, eType); - switch( eType ){ - case SQLITE_INTEGER: - case SQLITE_FLOAT: { - i64 iVal; - if( eType==SQLITE_INTEGER ){ - iVal = sqlite3_value_int64(pVal); - }else{ - double rVal = sqlite3_value_double(pVal); - assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); - memcpy(&iVal, &rVal, 8); - } - h = sessionHashAppendI64(h, iVal); - break; + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + i64 iVal; + if( eType==SQLITE_INTEGER ){ + iVal = sqlite3_value_int64(pVal); + }else{ + double rVal = sqlite3_value_double(pVal); + assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); + memcpy(&iVal, &rVal, 8); } - - case SQLITE_TEXT: - case SQLITE_BLOB: { - int n = sqlite3_value_bytes(pVal); - const u8 *z = eType==SQLITE_TEXT ? - sqlite3_value_text(pVal) : sqlite3_value_blob(pVal); - h = sessionHashAppendBlob(h, n, z); - break; + h = sessionHashAppendI64(h, iVal); + }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ + const u8 *z; + if( eType==SQLITE_TEXT ){ + z = (const u8 *)sqlite3_value_text(pVal); + }else{ + z = (const u8 *)sqlite3_value_blob(pVal); } - - default: - assert( eType==SQLITE_NULL ); - *pbNullPK = 1; - return SQLITE_OK; + if( !z ) return SQLITE_NOMEM; + h = sessionHashAppendBlob(h, sqlite3_value_bytes(pVal), z); + }else{ + assert( eType==SQLITE_NULL ); + *pbNullPK = 1; + return SQLITE_OK; } } } @@ -399,12 +394,12 @@ static unsigned int sessionChangeHash( a++; h = HASH_APPEND(h, eType); if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ - if( isPK ) h = sessionHashAppendI64(h, sessionGetI64(a)); + h = sessionHashAppendI64(h, sessionGetI64(a)); a += 8; }else{ int n; a += sessionVarintGet(a, &n); - if( isPK ) h = sessionHashAppendBlob(h, n, a); + h = sessionHashAppendBlob(h, n, a); a += n; } }else{ @@ -559,7 +554,7 @@ static int sessionMergeUpdate( return 1; } -static int sessionPreupdateEqual( +static void sessionPreupdateEqual( sqlite3 *db, SessionTable *pTab, SessionChange *pChange, @@ -589,14 +584,23 @@ static int sessionPreupdateEqual( } } }else{ - sqlite3_value *pVal; - int rc; + sqlite3_value *pVal; /* Value returned by preupdate_new/old */ + int rc; /* Error code from preupdate_new/old */ + + /* The following calls to preupdate_new() and preupdate_old() can not + ** fail. This is because they cache their return values, and by the + ** time control flows to here they have already been called once from + ** within sessionPreupdateHash(). The first two asserts below verify + ** this (that the method has already been called). */ if( bNew ){ + assert( db->pPreUpdate->pNewUnpacked || db->pPreUpdate->aNew ); rc = sqlite3_preupdate_new(db, i, &pVal); }else{ + assert( db->pPreUpdate->pUnpacked ); rc = sqlite3_preupdate_old(db, i, &pVal); } - if( rc!=SQLITE_OK || sqlite3_value_type(pVal)!=eType ) return rc; + assert( rc==SQLITE_OK ); + if( sqlite3_value_type(pVal)!=eType ) return; /* A SessionChange object never has a NULL value in a PK column */ assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT @@ -607,24 +611,24 @@ static int sessionPreupdateEqual( i64 iVal = sessionGetI64(a); a += 8; if( eType==SQLITE_INTEGER ){ - if( sqlite3_value_int64(pVal)!=iVal ) return SQLITE_OK; + if( sqlite3_value_int64(pVal)!=iVal ) return; }else{ double rVal; assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); memcpy(&rVal, &iVal, 8); - if( sqlite3_value_double(pVal)!=rVal ) return SQLITE_OK; + if( sqlite3_value_double(pVal)!=rVal ) return; } }else{ int n; const u8 *z; a += sessionVarintGet(a, &n); - if( sqlite3_value_bytes(pVal)!=n ) return SQLITE_OK; + if( sqlite3_value_bytes(pVal)!=n ) return; if( eType==SQLITE_TEXT ){ z = sqlite3_value_text(pVal); }else{ z = sqlite3_value_blob(pVal); } - if( memcmp(a, z, n) ) return SQLITE_OK; + if( memcmp(a, z, n) ) return; a += n; break; } @@ -632,7 +636,7 @@ static int sessionPreupdateEqual( } *pbEqual = 1; - return SQLITE_OK; + return; } /* @@ -854,9 +858,9 @@ static void sessionPreupdateOneChange( rc = sessionPreupdateHash(db, pTab, op==SQLITE_INSERT, &iHash, &bNullPk); if( rc==SQLITE_OK && bNullPk==0 ){ SessionChange *pC; - for(pC=pTab->apChange[iHash]; rc==SQLITE_OK && pC; pC=pC->pNext){ + for(pC=pTab->apChange[iHash]; pC; pC=pC->pNext){ int bEqual; - rc = sessionPreupdateEqual(db, pTab, pC, op==SQLITE_INSERT, &bEqual); + sessionPreupdateEqual(db, pTab, pC, op==SQLITE_INSERT, &bEqual); if( bEqual ) break; } if( pC==0 ){ @@ -1278,12 +1282,19 @@ static void sessionAppendCol( sessionAppendBlob(p, aBuf, 8, pRc); } if( eType==SQLITE_BLOB || eType==SQLITE_TEXT ){ - int nByte = sqlite3_column_bytes(pStmt, iCol); - sessionAppendVarint(p, nByte, pRc); - sessionAppendBlob(p, eType==SQLITE_BLOB ? - sqlite3_column_blob(pStmt, iCol) : sqlite3_column_text(pStmt, iCol), - nByte, pRc - ); + u8 *z; + if( eType==SQLITE_BLOB ){ + z = (u8 *)sqlite3_column_blob(pStmt, iCol); + }else{ + z = (u8 *)sqlite3_column_text(pStmt, iCol); + } + if( z ){ + int nByte = sqlite3_column_bytes(pStmt, iCol); + sessionAppendVarint(p, nByte, pRc); + sessionAppendBlob(p, z, nByte, pRc); + }else{ + *pRc = SQLITE_NOMEM; + } } } } @@ -1710,8 +1721,8 @@ static int sessionReadRecord( int nByte; aRec += sessionVarintGet(aRec, &nByte); if( apOut ){ - int enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); - sqlite3ValueSetStr(apOut[i], nByte, aRec, enc, SQLITE_STATIC); + u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); + sqlite3ValueSetStr(apOut[i], nByte, (char *)aRec, enc, SQLITE_STATIC); } aRec += nByte; } @@ -1742,7 +1753,6 @@ static int sessionChangesetNext( ){ u8 *aChange; int i; - u8 c; assert( (paRec==0 && pnRec==0) || (paRec && pnRec) ); @@ -1818,7 +1828,6 @@ static int sessionChangesetNext( */ int sqlite3changeset_next(sqlite3_changeset_iter *p){ return sessionChangesetNext(p, 0, 0); - } /* @@ -2987,7 +2996,6 @@ int sqlite3changeset_concat( } } - concat_out: sessionDeleteTable(pList); return rc; } diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 05eb732d6d..0993073328 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -456,13 +456,25 @@ static int test_sqlite3session_foreach( int nChangeSet; sqlite3_changeset_iter *pIter; int rc; + Tcl_Obj *pVarname; + Tcl_Obj *pCS; + Tcl_Obj *pScript; + int isCheckNext = 0; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "VARNAME CHANGESET SCRIPT"); + if( objc>1 ){ + char *zOpt = Tcl_GetString(objv[1]); + isCheckNext = (strcmp(zOpt, "-next")==0); + } + if( objc!=4+isCheckNext ){ + Tcl_WrongNumArgs(interp, 1, objv, "?-next? VARNAME CHANGESET SCRIPT"); return TCL_ERROR; } - pChangeSet = (void *)Tcl_GetByteArrayFromObj(objv[2], &nChangeSet); + pVarname = objv[1+isCheckNext]; + pCS = objv[2+isCheckNext]; + pScript = objv[3+isCheckNext]; + + pChangeSet = (void *)Tcl_GetByteArrayFromObj(pCS, &nChangeSet); rc = sqlite3changeset_start(&pIter, nChangeSet, pChangeSet); if( rc!=SQLITE_OK ){ return test_session_error(interp, rc); @@ -524,14 +536,21 @@ static int test_sqlite3session_foreach( Tcl_ListObjAppendElement(0, pVar, pOld); Tcl_ListObjAppendElement(0, pVar, pNew); - Tcl_ObjSetVar2(interp, objv[1], 0, pVar, 0); - rc = Tcl_EvalObjEx(interp, objv[3], 0); + Tcl_ObjSetVar2(interp, pVarname, 0, pVar, 0); + rc = Tcl_EvalObjEx(interp, pScript, 0); if( rc!=TCL_OK && rc!=TCL_CONTINUE ){ sqlite3changeset_finalize(pIter); return rc==TCL_BREAK ? TCL_OK : rc; } } - rc = sqlite3changeset_finalize(pIter); + + if( isCheckNext ){ + int rc2 = sqlite3changeset_next(pIter); + rc = sqlite3changeset_finalize(pIter); + assert( (rc2==SQLITE_DONE && rc==SQLITE_OK) || rc2==rc ); + }else{ + rc = sqlite3changeset_finalize(pIter); + } if( rc!=SQLITE_OK ){ return test_session_error(interp, rc); } diff --git a/manifest b/manifest index bc49322d17..1938e24d5e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\scoverage\sof\ssession\smodule. -D 2011-04-15T19:18:57.799 +C Improve\stest\scoverage\sof\ssession\smodule. +D 2011-04-16T19:23:10.456 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -99,16 +99,16 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/session1.test 7a92a2a6f531aef1e9764ffb7f983fb8b315376d +F ext/session/session1.test f5d9f2e362abe2563181389509822bda956516ee F ext/session/session2.test c3e5f78d5eb988e35cc2ba9ce3678f706283cfdb -F ext/session/session3.test bfa2376db7cbb2ac69496f84d93a8d81b13110d3 +F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 -F ext/session/session5.test 525503799d56124a31bedbd7895c1e668d18420d +F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 -F ext/session/sessionfault.test 2766cd620f1793f0e54f1e3859a184bcea55bad4 -F ext/session/sqlite3session.c 4c44da92750d4b31bcbed25428be7167cddccf84 +F ext/session/sessionfault.test 759060c36ef424919e3900b885b22aa15caf7f39 +F ext/session/sqlite3session.c 3475df4021c5260f795cf66f67233449795c06ea F ext/session/sqlite3session.h 665f5591562e3c71eb3d0da26f1a1efae26f7bcf -F ext/session/test_session.c f4d1dca94db71ec2177ee61eab51e718e58476d7 +F ext/session/test_session.c 311e5b9228374d0b5780448f289847ff1cf7d388 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk f942406cb7df55d1aec40a88a7ae399b730cd94f @@ -697,7 +697,7 @@ F test/tclsqlite.test 1ce9b6340d6d412420634e129a2e3722c651056a F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05 -F test/tester.tcl 6fa3d2f581b479a3a088b1b5b0d145e548ebe662 +F test/tester.tcl fc2e27b3a782c5c5b03f7cded15cf498cad9bfef F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca @@ -938,7 +938,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P df0b2d21dcd81679e55b24866f97568019932983 -R b4d7dfa6bf40d53e75863a5a6b9fd8ce +P 3dfd1d63bddfa9bd9018eb00bee1d496379630b5 +R 57f77b8ed5537ccfd8e7f64bd8d648b6 U dan -Z 2d321dbf5ee44d87c34feecb146a5235 +Z 35862238c72a43b8ebb72adec800f600 diff --git a/manifest.uuid b/manifest.uuid index 8ae1676306..387cde32ce 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3dfd1d63bddfa9bd9018eb00bee1d496379630b5 \ No newline at end of file +f46d4b641d613c39a80b12106e6a6ac0efc8be83 \ No newline at end of file diff --git a/test/tester.tcl b/test/tester.tcl index bae10530c6..bd6a00a17f 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -20,7 +20,7 @@ # Commands to manipulate the db and the file-system at a high level: # # copy_file FROM TO -# drop_all_table ?DB? +# drop_all_tables ?DB? # forcedelete FILENAME # # Test the capability of the SQLite version built into the interpreter to @@ -362,6 +362,12 @@ proc fix_testname {varname} { set testname "${::testprefix}-$testname" } } + +proc normalize_list {L} { + set L2 [list] + foreach l $L {lappend L2 $l} + set L2 +} proc do_execsql_test {testname sql {result {}}} { fix_testname testname From 80fe2d931071b6378969e26fedcc92bf0ff19ef3 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 18 Apr 2011 07:36:27 +0000 Subject: [PATCH 053/570] Further coverage tests for the session module. FossilOrigin-Name: 69a01c708bf044eacf21a8951fe9e7d9fb4332c5 --- ext/session/session2.test | 17 ++ ext/session/sessionfault.test | 51 ++++- ext/session/sqlite3session.c | 337 ++++++++++++++++++---------------- manifest | 16 +- manifest.uuid | 2 +- 5 files changed, 254 insertions(+), 169 deletions(-) diff --git a/ext/session/session2.test b/ext/session/session2.test index 5c7ea47d5f..04be5f0917 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -390,6 +390,23 @@ do_iterator_test 6.1.7 * { {UPDATE t2 0 X. {i 4 t y} {{} {} t new}} } +do_iterator_test 6.1.8 * { + CREATE TABLE t3(a, b PRIMARY KEY); + CREATE TABLE t4(a, b PRIMARY KEY); + CREATE TRIGGER t4t AFTER UPDATE ON t4 BEGIN + UPDATE t3 SET a = new.a WHERE b = new.b; + END; + + SELECT indirect(1); + INSERT INTO t3 VALUES('one', 1); + INSERT INTO t4 VALUES('one', 1); + SELECT indirect(0); + UPDATE t4 SET a = 'two' WHERE b = 1; +} { + {INSERT t4 0 .X {} {t two i 1}} + {INSERT t3 1 .X {} {t two i 1}} +} + sqlite3session S db main do_execsql_test 6.2.1 { SELECT indirect(0); diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index b9800e1f46..1444a46b36 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -20,6 +20,8 @@ source $testdir/tester.tcl set testprefix sessionfault +if 1 { + forcedelete test.db2 sqlite3 db2 test.db2 do_common_sql { @@ -362,7 +364,7 @@ do_faultsim_test 8.2 -faults oom* -body { } faultsim_delete_and_reopen -do_test 9.prep { +do_test 9.1.prep { execsql { PRAGMA encoding = 'utf16'; CREATE TABLE t1(a PRIMARY KEY, b); @@ -370,7 +372,8 @@ do_test 9.prep { } {} faultsim_save_and_close -do_faultsim_test 9 -faults oom-transient -prep { +set answers [list {0 {}} {1 SQLITE_NOMEM} {1 {callback requested query abort}}] +do_faultsim_test 9.1 -faults oom-transient -prep { catch { unset ::c } faultsim_restore_and_reopen sqlite3session S db main @@ -383,9 +386,48 @@ do_faultsim_test 9 -faults oom-transient -prep { set {} {} } -test { S delete - faultsim_test_result {0 {}} {1 SQLITE_NOMEM} {1 {callback requested query abort}} + eval faultsim_test_result $::answers if {[info exists ::c]} { - set expected "{INSERT t1 0 X. {} {t abcdefghijklmnopqrstuv t ABCDEFGHIJKLMNOPQRSTUV}}" + set expected [normalize_list { + {INSERT t1 0 X. {} {t abcdefghijklmnopqrstuv t ABCDEFGHIJKLMNOPQRSTUV}} + }] + if { [changeset_to_list $::c] != $expected } { + error "changeset mismatch" + } + } +} + +} + +faultsim_delete_and_reopen +do_test 9.2.prep { + execsql { + PRAGMA encoding = 'utf16'; + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES('abcdefghij', 'ABCDEFGHIJKLMNOPQRSTUV'); + } +} {} +faultsim_save_and_close + +set answers [list {0 {}} {1 SQLITE_NOMEM} {1 {callback requested query abort}}] +do_faultsim_test 9.2 -faults oom-transient -prep { + catch { unset ::c } + faultsim_restore_and_reopen + sqlite3session S db main + S attach * +} -body { + execsql { + UPDATE t1 SET b = 'xyz'; + } + set ::c [S changeset] + set {} {} +} -test { + S delete + eval faultsim_test_result $::answers + if {[info exists ::c]} { + set expected [normalize_list { + {UPDATE t1 0 X. {t abcdefghij t ABCDEFGHIJKLMNOPQRSTUV} {{} {} t xyz}} + }] if { [changeset_to_list $::c] != $expected } { error "changeset mismatch" } @@ -393,4 +435,5 @@ do_faultsim_test 9 -faults oom-transient -prep { } + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 4f81170621..2232d21938 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -222,51 +222,68 @@ static int sessionSerializeValue( sqlite3_value *pValue, /* Value to serialize */ int *pnWrite /* IN/OUT: Increment by bytes written */ ){ - int eType; /* Value type (SQLITE_NULL, TEXT etc.) */ int nByte; /* Size of serialized value in bytes */ - eType = sqlite3_value_type(pValue); - if( aBuf ) aBuf[0] = eType; - - switch( eType ){ - case SQLITE_NULL: - nByte = 1; - break; - - case SQLITE_INTEGER: - case SQLITE_FLOAT: - if( aBuf ){ - /* TODO: SQLite does something special to deal with mixed-endian - ** floating point values (e.g. ARM7). This code probably should - ** too. */ - u64 i; - if( eType==SQLITE_INTEGER ){ - i = (u64)sqlite3_value_int64(pValue); - }else{ - double r; - assert( sizeof(double)==8 && sizeof(u64)==8 ); - r = sqlite3_value_double(pValue); - memcpy(&i, &r, 8); + if( pValue ){ + int eType; /* Value type (SQLITE_NULL, TEXT etc.) */ + + eType = sqlite3_value_type(pValue); + if( aBuf ) aBuf[0] = eType; + + switch( eType ){ + case SQLITE_NULL: + nByte = 1; + break; + + case SQLITE_INTEGER: + case SQLITE_FLOAT: + if( aBuf ){ + /* TODO: SQLite does something special to deal with mixed-endian + ** floating point values (e.g. ARM7). This code probably should + ** too. */ + u64 i; + if( eType==SQLITE_INTEGER ){ + i = (u64)sqlite3_value_int64(pValue); + }else{ + double r; + assert( sizeof(double)==8 && sizeof(u64)==8 ); + r = sqlite3_value_double(pValue); + memcpy(&i, &r, 8); + } + sessionPutI64(&aBuf[1], i); } - sessionPutI64(&aBuf[1], i); + nByte = 9; + break; + + default: { + u8 *z; + int n; + int nVarint; + + assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); + if( eType==SQLITE_TEXT ){ + z = (u8 *)sqlite3_value_text(pValue); + }else{ + z = (u8 *)sqlite3_value_blob(pValue); + } + if( z==0 ) return SQLITE_NOMEM; + n = sqlite3_value_bytes(pValue); + nVarint = sessionVarintLen(n); + + if( aBuf ){ + sessionVarintPut(&aBuf[1], n); + memcpy(&aBuf[nVarint + 1], eType==SQLITE_TEXT ? + sqlite3_value_text(pValue) : sqlite3_value_blob(pValue), n + ); + } + + nByte = 1 + nVarint + n; + break; } - nByte = 9; - break; - - default: { - int n = sqlite3_value_bytes(pValue); - int nVarint = sessionVarintLen(n); - assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); - if( aBuf ){ - sessionVarintPut(&aBuf[1], n); - memcpy(&aBuf[nVarint + 1], eType==SQLITE_TEXT ? - sqlite3_value_text(pValue) : sqlite3_value_blob(pValue), n - ); - } - - nByte = 1 + nVarint + n; - break; } + }else{ + nByte = 1; + if( aBuf ) aBuf[0] = '\0'; } *pnWrite += nByte; @@ -851,18 +868,21 @@ static void sessionPreupdateOneChange( return; } - /* Search the hash table for an existing entry for rowid=iKey2. If - ** one is found, store a pointer to it in pChange and unlink it from - ** the hash table. Otherwise, set pChange to NULL. - */ + /* Calculate the hash-key for this change. If the primary key of the row + ** includes a NULL value, exit early. Such changes are ignored by the + ** session module. */ rc = sessionPreupdateHash(db, pTab, op==SQLITE_INSERT, &iHash, &bNullPk); - if( rc==SQLITE_OK && bNullPk==0 ){ + if( rc!=SQLITE_OK ) goto error_out; + + if( bNullPk==0 ){ + /* Search the hash table for an existing record for this row. */ SessionChange *pC; for(pC=pTab->apChange[iHash]; pC; pC=pC->pNext){ int bEqual; sessionPreupdateEqual(db, pTab, pC, op==SQLITE_INSERT, &bEqual); if( bEqual ) break; } + if( pC==0 ){ /* Create a new change object containing all the old values (if ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK @@ -876,53 +896,57 @@ static void sessionPreupdateOneChange( /* Figure out how large an allocation is required */ nByte = sizeof(SessionChange); - for(i=0; inCol && rc==SQLITE_OK; i++){ + for(i=0; inCol; i++){ sqlite3_value *p = 0; if( op!=SQLITE_INSERT ){ - rc = sqlite3_preupdate_old(pSession->db, i, &p); - }else if( 1 || pTab->abPK[i] ){ - rc = sqlite3_preupdate_new(pSession->db, i, &p); - } - if( p && rc==SQLITE_OK ){ - rc = sessionSerializeValue(0, p, &nByte); + TESTONLY(int trc = ) sqlite3_preupdate_old(pSession->db, i, &p); + assert( trc==SQLITE_OK ); + }else if( pTab->abPK[i] ){ + TESTONLY(int trc = ) sqlite3_preupdate_new(pSession->db, i, &p); + assert( trc==SQLITE_OK ); } + + /* This may fail if SQLite value p contains a utf-16 string that must + ** be converted to utf-8 and an OOM error occurs while doing so. */ + rc = sessionSerializeValue(0, p, &nByte); + if( rc!=SQLITE_OK ) goto error_out; } /* Allocate the change object */ pChange = (SessionChange *)sqlite3_malloc(nByte); if( !pChange ){ rc = SQLITE_NOMEM; + goto error_out; }else{ memset(pChange, 0, sizeof(SessionChange)); pChange->aRecord = (u8 *)&pChange[1]; } - /* Populate the change object */ + /* Populate the change object. None of the preupdate_old(), + ** preupdate_new() or SerializeValue() calls below may fail as all + ** required values and encodings have already been cached in memory. + ** It is not possible for an OOM to occur in this block. */ nByte = 0; - for(i=0; inCol && rc==SQLITE_OK; i++){ + for(i=0; inCol; i++){ sqlite3_value *p = 0; if( op!=SQLITE_INSERT ){ - rc = sqlite3_preupdate_old(pSession->db, i, &p); - }else if( 1 || pTab->abPK[i] ){ - rc = sqlite3_preupdate_new(pSession->db, i, &p); - } - if( p && rc==SQLITE_OK ){ - rc = sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte); + sqlite3_preupdate_old(pSession->db, i, &p); + }else if( pTab->abPK[i] ){ + sqlite3_preupdate_new(pSession->db, i, &p); } + sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte); } - if( rc==SQLITE_OK ){ - /* Add the change back to the hash-table */ - if( pSession->bIndirect || sqlite3_preupdate_depth(pSession->db) ){ - pChange->bIndirect = 1; - } - pChange->nRecord = nByte; - pChange->bInsert = (op==SQLITE_INSERT); - pChange->pNext = pTab->apChange[iHash]; - pTab->apChange[iHash] = pChange; - }else{ - sqlite3_free(pChange); + + /* Add the change to the hash-table */ + if( pSession->bIndirect || sqlite3_preupdate_depth(pSession->db) ){ + pChange->bIndirect = 1; } - }else if( rc==SQLITE_OK && pC->bIndirect ){ + pChange->nRecord = nByte; + pChange->bInsert = (op==SQLITE_INSERT); + pChange->pNext = pTab->apChange[iHash]; + pTab->apChange[iHash] = pChange; + + }else if( pC->bIndirect ){ /* If the existing change is considered "indirect", but this current ** change is "direct", mark the change object as direct. */ if( sqlite3_preupdate_depth(pSession->db)==0 && pSession->bIndirect==0 ){ @@ -932,6 +956,7 @@ static void sessionPreupdateOneChange( } /* If an error has occurred, mark the session object as failed. */ + error_out: if( rc!=SQLITE_OK ){ pSession->rc = rc; } @@ -1125,7 +1150,7 @@ int sqlite3session_attach( ** set *pRc to SQLITE_NOMEM and return non-zero. */ static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ - if( p->nAlloc-p->nBufnAlloc-p->nBufnAlloc ? p->nAlloc : 128; do { @@ -1135,12 +1160,12 @@ static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ aNew = (u8 *)sqlite3_realloc(p->aBuf, nNew); if( 0==aNew ){ *pRc = SQLITE_NOMEM; - return 1; + }else{ + p->aBuf = aNew; + p->nAlloc = nNew; } - p->aBuf = aNew; - p->nAlloc = nNew; } - return 0; + return (*pRc!=SQLITE_OK); } /* @@ -1151,7 +1176,7 @@ static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ ** returning. */ static void sessionAppendByte(SessionBuffer *p, u8 v, int *pRc){ - if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, 1, pRc) ){ + if( 0==sessionBufferGrow(p, 1, pRc) ){ p->aBuf[p->nBuf++] = v; } } @@ -1164,7 +1189,7 @@ static void sessionAppendByte(SessionBuffer *p, u8 v, int *pRc){ ** returning. */ static void sessionAppendVarint(SessionBuffer *p, int v, int *pRc){ - if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, 9, pRc) ){ + if( 0==sessionBufferGrow(p, 9, pRc) ){ p->nBuf += sessionVarintPut(&p->aBuf[p->nBuf], v); } } @@ -1182,7 +1207,7 @@ static void sessionAppendBlob( int nBlob, int *pRc ){ - if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, nBlob, pRc) ){ + if( 0==sessionBufferGrow(p, nBlob, pRc) ){ memcpy(&p->aBuf[p->nBuf], aBlob, nBlob); p->nBuf += nBlob; } @@ -1202,7 +1227,7 @@ static void sessionAppendStr( int *pRc ){ int nStr = sqlite3Strlen30(zStr); - if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, nStr, pRc) ){ + if( 0==sessionBufferGrow(p, nStr, pRc) ){ memcpy(&p->aBuf[p->nBuf], zStr, nStr); p->nBuf += nStr; } @@ -1241,7 +1266,7 @@ static void sessionAppendIdent( int *pRc /* IN/OUT: Error code */ ){ int nStr = sqlite3Strlen30(zStr)*2 + 2 + 1; - if( *pRc==SQLITE_OK && 0==sessionBufferGrow(p, nStr, pRc) ){ + if( 0==sessionBufferGrow(p, nStr, pRc) ){ char *zOut = (char *)&p->aBuf[p->nBuf]; const char *zIn = zStr; *zOut++ = '"'; @@ -1300,12 +1325,10 @@ static void sessionAppendCol( } /* -** This function is a no-op if *pRc is other than SQLITE_OK when it is -** called. ** -** Otherwse, if *pRc is SQLITE_OK, then it appends an update change to -** the buffer (see the comments under "CHANGESET FORMAT" at the top of the -** file). An update change consists of: +** This function appends an update change to the buffer (see the comments +** under "CHANGESET FORMAT" at the top of the file). An update change +** consists of: ** ** 1 byte: SQLITE_UPDATE (0x17) ** n bytes: old.* record (see RECORD FORMAT) @@ -1323,89 +1346,89 @@ static void sessionAppendCol( ** original values of any fields that have been modified. The new.* record ** contains the new values of only those fields that have been modified. */ -static void sessionAppendUpdate( +static int sessionAppendUpdate( SessionBuffer *pBuf, /* Buffer to append to */ sqlite3_stmt *pStmt, /* Statement handle pointing at new row */ SessionChange *p, /* Object containing old values */ - u8 *abPK, /* Boolean array - true for PK columns */ - int *pRc /* IN/OUT: Error code */ + u8 *abPK /* Boolean array - true for PK columns */ ){ - if( *pRc==SQLITE_OK ){ - SessionBuffer buf2 = {0,0,0}; /* Buffer to accumulate new.* record in */ - int bNoop = 1; /* Set to zero if any values are modified */ - int nRewind = pBuf->nBuf; /* Set to zero if any values are modified */ - int i; /* Used to iterate through columns */ - u8 *pCsr = p->aRecord; /* Used to iterate through old.* values */ + int rc = SQLITE_OK; + SessionBuffer buf2 = {0,0,0}; /* Buffer to accumulate new.* record in */ + int bNoop = 1; /* Set to zero if any values are modified */ + int nRewind = pBuf->nBuf; /* Set to zero if any values are modified */ + int i; /* Used to iterate through columns */ + u8 *pCsr = p->aRecord; /* Used to iterate through old.* values */ - sessionAppendByte(pBuf, SQLITE_UPDATE, pRc); - sessionAppendByte(pBuf, p->bIndirect, pRc); - for(i=0; ibIndirect, &rc); + for(i=0; inBuf = nRewind; + if( bChanged || abPK[i] ){ + sessionAppendBlob(pBuf, pCsr, nAdvance, &rc); }else{ - sessionAppendBlob(pBuf, buf2.aBuf, buf2.nBuf, pRc); + sessionAppendByte(pBuf, 0, &rc); } - sqlite3_free(buf2.aBuf); + + if( bChanged ){ + sessionAppendCol(&buf2, pStmt, i, &rc); + bNoop = 0; + }else{ + sessionAppendByte(&buf2, 0, &rc); + } + + pCsr += nAdvance; } + + if( bNoop ){ + pBuf->nBuf = nRewind; + }else{ + sessionAppendBlob(pBuf, buf2.aBuf, buf2.nBuf, &rc); + } + sqlite3_free(buf2.aBuf); + + return rc; } static int sessionSelectStmt( @@ -1457,6 +1480,7 @@ static int sessionSelectBind( int eType = *a++; switch( eType ){ + case 0: case SQLITE_NULL: assert( abPK[i]==0 ); break; @@ -1580,6 +1604,7 @@ int sqlite3session_changeset( for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ rc = sessionSelectBind(pSel, nCol, abPK, p); + if( rc!=SQLITE_OK ) continue; if( sqlite3_step(pSel)==SQLITE_ROW ){ int iCol; if( p->bInsert ){ @@ -1589,7 +1614,7 @@ int sqlite3session_changeset( sessionAppendCol(&buf, pSel, iCol, &rc); } }else{ - sessionAppendUpdate(&buf, pSel, p, abPK, &rc); + rc = sessionAppendUpdate(&buf, pSel, p, abPK); } }else if( !p->bInsert ){ /* A DELETE change */ diff --git a/manifest b/manifest index 1938e24d5e..c0ef6b6a13 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\stest\scoverage\sof\ssession\smodule. -D 2011-04-16T19:23:10.456 +C Further\scoverage\stests\sfor\sthe\ssession\smodule. +D 2011-04-18T07:36:27.686 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -100,13 +100,13 @@ F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test f5d9f2e362abe2563181389509822bda956516ee -F ext/session/session2.test c3e5f78d5eb988e35cc2ba9ce3678f706283cfdb +F ext/session/session2.test 99ca0da7ddb617d42bafd83adccf99f18ae0384b F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 -F ext/session/sessionfault.test 759060c36ef424919e3900b885b22aa15caf7f39 -F ext/session/sqlite3session.c 3475df4021c5260f795cf66f67233449795c06ea +F ext/session/sessionfault.test 401045278298a242cbc2e4bc986c102f01ff2180 +F ext/session/sqlite3session.c fd43b8cb35d8112fa77a9e9101f9efe7005e5e23 F ext/session/sqlite3session.h 665f5591562e3c71eb3d0da26f1a1efae26f7bcf F ext/session/test_session.c 311e5b9228374d0b5780448f289847ff1cf7d388 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -938,7 +938,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 3dfd1d63bddfa9bd9018eb00bee1d496379630b5 -R 57f77b8ed5537ccfd8e7f64bd8d648b6 +P f46d4b641d613c39a80b12106e6a6ac0efc8be83 +R bc07f4a1348864ef3dbdf87527d99ed2 U dan -Z 35862238c72a43b8ebb72adec800f600 +Z fcc600b67a0d6c899a275e81c6cbea0f diff --git a/manifest.uuid b/manifest.uuid index 387cde32ce..4c438b56bb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f46d4b641d613c39a80b12106e6a6ac0efc8be83 \ No newline at end of file +69a01c708bf044eacf21a8951fe9e7d9fb4332c5 \ No newline at end of file From 798693b2b1952827f95dd1a3ed9e2d1f0ce34cf1 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 18 Apr 2011 12:05:03 +0000 Subject: [PATCH 054/570] Fix some missing comments and other issues with session module code. FossilOrigin-Name: 20d7c280235201e519f296372f269e7cecda24da --- ext/session/sqlite3session.c | 177 +++++++++++++++++++++++------------ manifest | 12 +-- manifest.uuid | 2 +- 3 files changed, 126 insertions(+), 65 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 2232d21938..5a31a204f5 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -136,7 +136,7 @@ struct SessionTable { ** this structure stored in a SessionTable.aChange[] hash table. */ struct SessionChange { - int bInsert; /* True if row was inserted this session */ + int op; /* One of UPDATE, DELETE, INSERT */ int bIndirect; /* True if this change is "indirect" */ int nRecord; /* Number of bytes in buffer aRecord[] */ u8 *aRecord; /* Buffer containing old.* record */ @@ -290,29 +290,67 @@ static int sessionSerializeValue( return SQLITE_OK; } +/* +** This macro is used to calculate hash key values for data structures. In +** order to use this macro, the entire data structure must be represented +** as a series of unsigned integers. In order to calculate a hash-key value +** for a data structure represented as three such integers, the macro may +** then be used as follows: +** +** int hash_key_value; +** hash_key_value = HASH_APPEND(0, ); +** hash_key_value = HASH_APPEND(hash_key_value, ); +** hash_key_value = HASH_APPEND(hash_key_value, ); +** +** In practice, the data structures this macro is used for are the primary +** key values of modified rows. +*/ #define HASH_APPEND(hash, add) ((hash) << 3) ^ (hash) ^ (unsigned int)(add) + +/* +** Append the hash of the 64-bit integer passed as the second argument to the +** hash-key value passed as the first. Return the new hash-key value. +*/ static unsigned int sessionHashAppendI64(unsigned int h, i64 i){ h = HASH_APPEND(h, i & 0xFFFFFFFF); return HASH_APPEND(h, (i>>32)&0xFFFFFFFF); } + +/* +** Append the hash of the blob passed via the second and third arguments to +** the hash-key value passed as the first. Return the new hash-key value. +*/ static unsigned int sessionHashAppendBlob(unsigned int h, int n, const u8 *z){ int i; for(i=0; inBucket. +** new.* row currently available and, assuming no error occurs, writes it to +** *piHash before returning. If the primary key contains one or more NULL +** values, *pbNullPK is set to true before returning. +** +** If an error occurs, an SQLite error code is returned and the final values +** of *piHash asn *pbNullPK are undefined. Otherwise, SQLITE_OK is returned +** and the output variables are set as described above. */ -static unsigned int sessionPreupdateHash( +static int sessionPreupdateHash( sqlite3 *db, /* Database handle */ SessionTable *pTab, /* Session table handle */ int bNew, /* True to hash the new.* PK */ int *piHash, /* OUT: Hash value */ - int *pbNullPK + int *pbNullPK /* OUT: True if there are NULL values in PK */ ){ unsigned int h = 0; /* Hash value to return */ int i; /* Used to iterate through columns */ @@ -333,7 +371,7 @@ static unsigned int sessionPreupdateHash( if( rc!=SQLITE_OK ) return rc; eType = sqlite3_value_type(pVal); - h = HASH_APPEND(h, eType); + h = sessionHashAppendType(h, eType); if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ i64 iVal; if( eType==SQLITE_INTEGER ){ @@ -356,7 +394,6 @@ static unsigned int sessionPreupdateHash( }else{ assert( eType==SQLITE_NULL ); *pbNullPK = 1; - return SQLITE_OK; } } } @@ -381,7 +418,7 @@ static int sessionSerialLen(u8 *a){ /* ** Based on the primary key values stored in change aRecord, calculate a -** hash key, assuming the has table has nBucket buckets. The hash keys +** hash key. Assume the has table has nBucket buckets. The hash keys ** calculated by this function are compatible with those calculated by ** sessionPreupdateHash(). */ @@ -409,7 +446,7 @@ static unsigned int sessionChangeHash( if( isPK ){ a++; - h = HASH_APPEND(h, eType); + h = sessionHashAppendType(h, eType); if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ h = sessionHashAppendI64(h, sessionGetI64(a)); a += 8; @@ -426,20 +463,26 @@ static unsigned int sessionChangeHash( return (h % nBucket); } +/* +** Arguments aLeft and aRight are pointers to change records for table pTab. +** This function returns true if the two records apply to the same row (i.e. +** have the same values stored in the primary key columns), or false +** otherwise. +*/ static int sessionChangeEqual( - SessionTable *pTab, + SessionTable *pTab, /* Table used for PK definition */ u8 *aLeft, /* Change record */ u8 *aRight /* Change record */ ){ - u8 *a1 = aLeft; - u8 *a2 = aRight; - int i; + u8 *a1 = aLeft; /* Cursor to iterate through aLeft */ + u8 *a2 = aRight; /* Cursor to iterate through aRight */ + int iCol; /* Used to iterate through table columns */ - for(i=0; inCol; i++){ + for(iCol=0; iColnCol; iCol++){ int n1 = sessionSerialLen(a1); int n2 = sessionSerialLen(a2); - if( pTab->abPK[i] && (n1!=n2 || memcmp(a1, a2, n1)) ){ + if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){ return 0; } a1 += n1; @@ -449,18 +492,31 @@ static int sessionChangeEqual( return 1; } +/* +** Arguments aLeft and aRight both point to buffers containing change +** records with nCol columns. This function "merges" the two records into +** a single records which is written to the buffer at *paOut. *paOut is +** then set to point to one byte after the last byte written before +** returning. +** +** The merging of records is done as follows: For each column, if the +** aRight record contains a value for the column, copy the value from +** their. Otherwise, if aLeft contains a value, copy it. If neither +** record contains a value for a given column, then neither does the +** output record. +*/ static void sessionMergeRecord( u8 **paOut, - SessionTable *pTab, + int nCol, u8 *aLeft, u8 *aRight ){ - u8 *a1 = aLeft; - u8 *a2 = aRight; - u8 *aOut = *paOut; - int i; + u8 *a1 = aLeft; /* Cursor used to iterate through aLeft */ + u8 *a2 = aRight; /* Cursor used to iterate through aRight */ + u8 *aOut = *paOut; /* Output cursor */ + int iCol; /* Used to iterate from 0 to nCol */ - for(i=0; inCol; i++){ + for(iCol=0; iColnCol; i++){ - int eType = *a++; if( !pTab->abPK[i] ){ - switch( eType ){ - case SQLITE_INTEGER: - case SQLITE_FLOAT: - a += 8; - break; - - case SQLITE_TEXT: - case SQLITE_BLOB: { - int n; - a += sessionVarintGet(a, &n); - a += n; - break; - } - } + a += sessionSerialLen(a); }else{ sqlite3_value *pVal; /* Value returned by preupdate_new/old */ int rc; /* Error code from preupdate_new/old */ + int eType = *a++; /* Type of value from change record */ /* The following calls to preupdate_new() and preupdate_old() can not ** fail. This is because they cache their return values, and by the @@ -942,7 +1003,7 @@ static void sessionPreupdateOneChange( pChange->bIndirect = 1; } pChange->nRecord = nByte; - pChange->bInsert = (op==SQLITE_INSERT); + pChange->op = op; pChange->pNext = pTab->apChange[iHash]; pTab->apChange[iHash] = pChange; @@ -1606,8 +1667,8 @@ int sqlite3session_changeset( rc = sessionSelectBind(pSel, nCol, abPK, p); if( rc!=SQLITE_OK ) continue; if( sqlite3_step(pSel)==SQLITE_ROW ){ - int iCol; - if( p->bInsert ){ + if( p->op==SQLITE_INSERT ){ + int iCol; sessionAppendByte(&buf, SQLITE_INSERT, &rc); sessionAppendByte(&buf, p->bIndirect, &rc); for(iCol=0; iColbInsert ){ + }else if( p->op!=SQLITE_INSERT ){ /* A DELETE change */ sessionAppendByte(&buf, SQLITE_DELETE, &rc); sessionAppendByte(&buf, p->bIndirect, &rc); @@ -2784,12 +2845,12 @@ static int sessionChangeMerge( return SQLITE_NOMEM; } memset(pNew, 0, sizeof(SessionChange)); - pNew->bInsert = op2; + pNew->op = op2; pNew->bIndirect = bIndirect; pNew->nRecord = nRec; pNew->aRecord = aRec; }else{ - int op1 = pExist->bInsert; + int op1 = pExist->op; /* ** op1=INSERT, op2=INSERT -> Unsupported. Discard op2. @@ -2830,12 +2891,12 @@ static int sessionChangeMerge( if( op1==SQLITE_INSERT ){ /* INSERT + UPDATE */ u8 *a1 = aRec; assert( op2==SQLITE_UPDATE ); - pNew->bInsert = SQLITE_INSERT; + pNew->op = SQLITE_INSERT; sessionReadRecord(&a1, pTab->nCol, 0); - sessionMergeRecord(&aCsr, pTab, pExist->aRecord, a1); + sessionMergeRecord(&aCsr, pTab->nCol, pExist->aRecord, a1); }else if( op1==SQLITE_DELETE ){ /* DELETE + INSERT */ assert( op2==SQLITE_INSERT ); - pNew->bInsert = SQLITE_UPDATE; + pNew->op = SQLITE_UPDATE; if( 0==sessionMergeUpdate(&aCsr, pTab, pExist->aRecord, 0, aRec, 0) ){ sqlite3_free(pNew); pNew = 0; @@ -2846,15 +2907,15 @@ static int sessionChangeMerge( u8 *a2 = aRec; sessionReadRecord(&a1, pTab->nCol, 0); sessionReadRecord(&a2, pTab->nCol, 0); - pNew->bInsert = SQLITE_UPDATE; + pNew->op = SQLITE_UPDATE; if( 0==sessionMergeUpdate(&aCsr, pTab, aRec, pExist->aRecord, a1, a2) ){ sqlite3_free(pNew); pNew = 0; } }else{ /* UPDATE + DELETE */ assert( op1==SQLITE_UPDATE && op2==SQLITE_DELETE ); - pNew->bInsert = SQLITE_DELETE; - sessionMergeRecord(&aCsr, pTab, aRec, pExist->aRecord); + pNew->op = SQLITE_DELETE; + sessionMergeRecord(&aCsr, pTab->nCol, aRec, pExist->aRecord); } if( pNew ){ @@ -3006,7 +3067,7 @@ int sqlite3changeset_concat( for(i=0; inChange; i++){ SessionChange *p; for(p=pTab->apChange[i]; p; p=p->pNext){ - sessionAppendByte(&buf, p->bInsert, &rc); + sessionAppendByte(&buf, p->op, &rc); sessionAppendByte(&buf, p->bIndirect, &rc); sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); } diff --git a/manifest b/manifest index c0ef6b6a13..5d77f78c46 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\scoverage\stests\sfor\sthe\ssession\smodule. -D 2011-04-18T07:36:27.686 +C Fix\ssome\smissing\scomments\sand\sother\sissues\swith\ssession\smodule\scode. +D 2011-04-18T12:05:03.122 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -106,7 +106,7 @@ F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 401045278298a242cbc2e4bc986c102f01ff2180 -F ext/session/sqlite3session.c fd43b8cb35d8112fa77a9e9101f9efe7005e5e23 +F ext/session/sqlite3session.c 04a5065d5b64f43f120113df170e96bb8db8e229 F ext/session/sqlite3session.h 665f5591562e3c71eb3d0da26f1a1efae26f7bcf F ext/session/test_session.c 311e5b9228374d0b5780448f289847ff1cf7d388 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -938,7 +938,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P f46d4b641d613c39a80b12106e6a6ac0efc8be83 -R bc07f4a1348864ef3dbdf87527d99ed2 +P 69a01c708bf044eacf21a8951fe9e7d9fb4332c5 +R b92955ca865aafd93c0b967b180f7cc1 U dan -Z fcc600b67a0d6c899a275e81c6cbea0f +Z 3095f8afd486ad0b7645eeb6cb4cbdcc diff --git a/manifest.uuid b/manifest.uuid index 4c438b56bb..521c05b9db 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -69a01c708bf044eacf21a8951fe9e7d9fb4332c5 \ No newline at end of file +20d7c280235201e519f296372f269e7cecda24da \ No newline at end of file From 77fc1d5bb4ffe5e423ae17b02b7f9dd66c4c41da Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 18 Apr 2011 15:47:08 +0000 Subject: [PATCH 055/570] Fix further missing comments and other minor issues in the session module code. FossilOrigin-Name: 99f0f35092b0b78b7016b21c242da263ab64b77b --- ext/session/sqlite3session.c | 171 ++++++++++++++++++++++++----------- manifest | 12 +-- manifest.uuid | 2 +- 3 files changed, 126 insertions(+), 59 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 5a31a204f5..50c436b8c4 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -645,20 +645,25 @@ static int sessionMergeUpdate( return 1; } -static void sessionPreupdateEqual( - sqlite3 *db, - SessionTable *pTab, - SessionChange *pChange, - int bNew, - int *pbEqual +/* +** This function is only called from within a pre-update-hook callback. +** It determines if the current pre-update-hook change affects the same row +** as the change stored in argument pChange. If so, it returns true. Otherwise +** if the pre-update-hook does not affect the same row as pChange, it returns +** false. +*/ +static int sessionPreupdateEqual( + sqlite3 *db, /* Database handle */ + SessionTable *pTab, /* Table associated with change */ + SessionChange *pChange, /* Change to compare to */ + int op /* Current pre-update operation */ ){ - int i; - u8 *a = pChange->aRecord; + int iCol; /* Used to iterate through columns */ + u8 *a = pChange->aRecord; /* Cursor used to scan change record */ - *pbEqual = 0; - - for(i=0; inCol; i++){ - if( !pTab->abPK[i] ){ + assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE ); + for(iCol=0; iColnCol; iCol++){ + if( !pTab->abPK[iCol] ){ a += sessionSerialLen(a); }else{ sqlite3_value *pVal; /* Value returned by preupdate_new/old */ @@ -670,15 +675,15 @@ static void sessionPreupdateEqual( ** time control flows to here they have already been called once from ** within sessionPreupdateHash(). The first two asserts below verify ** this (that the method has already been called). */ - if( bNew ){ + if( op==SQLITE_INSERT ){ assert( db->pPreUpdate->pNewUnpacked || db->pPreUpdate->aNew ); - rc = sqlite3_preupdate_new(db, i, &pVal); + rc = sqlite3_preupdate_new(db, iCol, &pVal); }else{ assert( db->pPreUpdate->pUnpacked ); - rc = sqlite3_preupdate_old(db, i, &pVal); + rc = sqlite3_preupdate_old(db, iCol, &pVal); } assert( rc==SQLITE_OK ); - if( sqlite3_value_type(pVal)!=eType ) return; + if( sqlite3_value_type(pVal)!=eType ) return 0; /* A SessionChange object never has a NULL value in a PK column */ assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT @@ -689,32 +694,31 @@ static void sessionPreupdateEqual( i64 iVal = sessionGetI64(a); a += 8; if( eType==SQLITE_INTEGER ){ - if( sqlite3_value_int64(pVal)!=iVal ) return; + if( sqlite3_value_int64(pVal)!=iVal ) return 0; }else{ double rVal; assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); memcpy(&rVal, &iVal, 8); - if( sqlite3_value_double(pVal)!=rVal ) return; + if( sqlite3_value_double(pVal)!=rVal ) return 0; } }else{ int n; const u8 *z; a += sessionVarintGet(a, &n); - if( sqlite3_value_bytes(pVal)!=n ) return; + if( sqlite3_value_bytes(pVal)!=n ) return 0; if( eType==SQLITE_TEXT ){ z = sqlite3_value_text(pVal); }else{ z = sqlite3_value_blob(pVal); } - if( memcmp(a, z, n) ) return; + if( memcmp(a, z, n) ) return 0; a += n; break; } } } - *pbEqual = 1; - return; + return 1; } /* @@ -768,7 +772,8 @@ static int sessionGrowHash(SessionTable *pTab){ ** not, SQLITE_SCHEMA is returned and none of the output variables are ** populated. ** -** Otherwise, if it is not NULL, variable *pzTab is set to point to a +** Otherwise, if they are not NULL, variable *pnCol is set to the number +** of columns in the database table and variable *pzTab is set to point to a ** nul-terminated copy of the table name. *pazCol (if not NULL) is set to ** point to an array of pointers to column names. And *pabPK (again, if not ** NULL) is set to point to an array of booleans - true if the corresponding @@ -778,8 +783,9 @@ static int sessionGrowHash(SessionTable *pTab){ ** ** CREATE TABLE tbl1(w, x, y, z, PRIMARY KEY(w, z)); ** -** Then the three output variables are populated as follows: +** Then the four output variables are populated as follows: ** +** *pnCol = 4 ** *pzTab = "tbl1" ** *pazCol = {"w", "x", "y", "z"} ** *pabPK = {1, 0, 0, 1} @@ -908,10 +914,18 @@ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ return pSession->rc; } +/* +** This function is only called from with a pre-update-hook reporting a +** change on table pTab (attached to session pSession). The type of change +** (UPDATE, INSERT, DELETE) is specified by the first argument. +** +** Unless one is already present or an error occurs, an entry is added +** to the changed-rows hash table associated with table pTab. +*/ static void sessionPreupdateOneChange( - int op, - sqlite3_session *pSession, - SessionTable *pTab + int op, /* One of SQLITE_UPDATE, INSERT, DELETE */ + sqlite3_session *pSession, /* Session object pTab is attached to */ + SessionTable *pTab /* Table that change applies to */ ){ sqlite3 *db = pSession->db; int iHash; @@ -939,9 +953,7 @@ static void sessionPreupdateOneChange( /* Search the hash table for an existing record for this row. */ SessionChange *pC; for(pC=pTab->apChange[iHash]; pC; pC=pC->pNext){ - int bEqual; - sessionPreupdateEqual(db, pTab, pC, op==SQLITE_INSERT, &bEqual); - if( bEqual ) break; + if( sessionPreupdateEqual(db, pTab, pC, op) ) break; } if( pC==0 ){ @@ -1109,6 +1121,10 @@ int sqlite3session_create( return SQLITE_OK; } +/* +** Free the list of table objects passed as the first argument. The contents +** of the changed-rows hash tables are also deleted. +*/ void sessionDeleteTable(SessionTable *pList){ SessionTable *pNext; SessionTable *pTab; @@ -1492,14 +1508,20 @@ static int sessionAppendUpdate( return rc; } +/* +** Formulate and prepare a SELECT statement to retrieve a row from table +** zTab in database zDb based on its primary key. i.e. +** +** SELECT * FROM zDb.zTab WHERE pk1 = ? AND pk2 = ? AND ... +*/ static int sessionSelectStmt( sqlite3 *db, /* Database handle */ const char *zDb, /* Database name */ const char *zTab, /* Table name */ - int nCol, - const char **azCol, - u8 *abPK, - sqlite3_stmt **ppStmt + int nCol, /* Number of columns in table */ + const char **azCol, /* Names of table columns */ + u8 *abPK, /* PRIMARY KEY array */ + sqlite3_stmt **ppStmt /* OUT: Prepared SELECT statement */ ){ int rc = SQLITE_OK; int i; @@ -1527,11 +1549,19 @@ static int sessionSelectStmt( return rc; } +/* +** Bind the PRIMARY KEY values from the change passed in argument pChange +** to the SELECT statement passed as the first argument. The SELECT statement +** is as prepared by function sessionSelectStmt(). +** +** Return SQLITE_OK if all PK values are successfully bound, or an SQLite +** error code (e.g. SQLITE_NOMEM) otherwise. +*/ static int sessionSelectBind( - sqlite3_stmt *pSelect, - int nCol, - u8 *abPK, - SessionChange *pChange + sqlite3_stmt *pSelect, /* SELECT from sessionSelectStmt() */ + int nCol, /* Number of columns in table */ + u8 *abPK, /* PRIMARY KEY array */ + SessionChange *pChange /* Change structure */ ){ int i; int rc = SQLITE_OK; @@ -1592,6 +1622,12 @@ static int sessionSelectBind( return rc; } +/* +** This function is a no-op if *pRc is set to other than SQLITE_OK when it +** is called. Otherwise, append a serialized table header (part of the binary +** changeset format) to buffer *pBuf. If an error occurs, set *pRc to an +** SQLite error code before returning. +*/ static void sessionAppendTableHdr( SessionBuffer *pBuf, SessionTable *pTab, @@ -1832,10 +1868,26 @@ static int sessionReadRecord( return SQLITE_OK; } +/* +** Advance the changeset iterator to the next change. +** +** If both paRec and pnRec are NULL, then this function works like the public +** API sqlite3changeset_next(). If SQLITE_ROW is returned, then the +** sqlite3changeset_new() and old() APIs may be used to query for values. +** +** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change +** record is written to *paRec before returning and the number of bytes in +** the record to *pnRec. +** +** Either way, this function returns SQLITE_ROW if the iterator is +** successfully advanced to the next change in the changeset, an SQLite +** error code if an error occurs, or SQLITE_DONE if there are no further +** changes in the changeset. +*/ static int sessionChangesetNext( - sqlite3_changeset_iter *p, - u8 **paRec, - int *pnRec + sqlite3_changeset_iter *p, /* Changeset iterator */ + u8 **paRec, /* If non-NULL, store record pointer here */ + int *pnRec /* If non-NULL, store size of record here */ ){ u8 *aChange; int i; @@ -1918,7 +1970,7 @@ int sqlite3changeset_next(sqlite3_changeset_iter *p){ /* ** The following function extracts information on the current change -** from a changeset iterator. They may only be called after changeset_next() +** from a changeset iterator. It may only be called after changeset_next() ** has returned SQLITE_ROW. */ int sqlite3changeset_op( @@ -1935,6 +1987,12 @@ int sqlite3changeset_op( return SQLITE_OK; } +/* +** Return information regarding the PRIMARY KEY and number of columns in +** the database table affected by the change that pIter currently points +** to. This function may only be called after changeset_next() returns +** SQLITE_ROW. +*/ int sqlite3changeset_pk( sqlite3_changeset_iter *pIter, /* Iterator object */ unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */ @@ -2828,14 +2886,19 @@ int sqlite3changeset_apply( return rc; } +/* +** This function is called to merge two changes to the same row together as +** part of an sqlite3changeset_concat() operation. A new change object is +** allocated and a pointer to it stored in *ppNew. +*/ static int sessionChangeMerge( - SessionTable *pTab, - SessionChange *pExist, - int op2, - int bIndirect, - u8 *aRec, - int nRec, - SessionChange **ppNew + SessionTable *pTab, /* Table structure */ + SessionChange *pExist, /* Existing change */ + int op2, /* Second change operation */ + int bIndirect, /* True if second change is indirect */ + u8 *aRec, /* Second change record */ + int nRec, /* Number of bytes in aRec */ + SessionChange **ppNew /* OUT: Merged change */ ){ SessionChange *pNew = 0; @@ -2929,10 +2992,14 @@ static int sessionChangeMerge( return SQLITE_OK; } +/* +** Add all changes in the changeset passed via the first two arguments to +** hash tables. +*/ int sessionConcatChangeset( - int nChangeset, - void *pChangeset, - SessionTable **ppTabList + int nChangeset, /* Number of bytes in pChangeset */ + void *pChangeset, /* Changeset buffer */ + SessionTable **ppTabList /* IN/OUT: List of table objects */ ){ u8 *aRec; int nRec; diff --git a/manifest b/manifest index 5d77f78c46..f38f5e51b4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\smissing\scomments\sand\sother\sissues\swith\ssession\smodule\scode. -D 2011-04-18T12:05:03.122 +C Fix\sfurther\smissing\scomments\sand\sother\sminor\sissues\sin\sthe\ssession\smodule\scode. +D 2011-04-18T15:47:08.694 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -106,7 +106,7 @@ F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 401045278298a242cbc2e4bc986c102f01ff2180 -F ext/session/sqlite3session.c 04a5065d5b64f43f120113df170e96bb8db8e229 +F ext/session/sqlite3session.c 26de50c3e34d89ae62e97024ad07e772e1c52db2 F ext/session/sqlite3session.h 665f5591562e3c71eb3d0da26f1a1efae26f7bcf F ext/session/test_session.c 311e5b9228374d0b5780448f289847ff1cf7d388 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -938,7 +938,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 69a01c708bf044eacf21a8951fe9e7d9fb4332c5 -R b92955ca865aafd93c0b967b180f7cc1 +P 20d7c280235201e519f296372f269e7cecda24da +R 22fa2c52781f892ef560f2c8f63b1707 U dan -Z 3095f8afd486ad0b7645eeb6cb4cbdcc +Z e6f0d0d675f579cb5b46b0fe2c73f457 diff --git a/manifest.uuid b/manifest.uuid index 521c05b9db..240a76a7a9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -20d7c280235201e519f296372f269e7cecda24da \ No newline at end of file +99f0f35092b0b78b7016b21c242da263ab64b77b \ No newline at end of file From e437ca5ec0af264b3f299409d18c381800414082 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 11 Jul 2011 19:45:38 +0000 Subject: [PATCH 056/570] Modifications so that the sessions extension works with blob handles. FossilOrigin-Name: 82ac16c4f873d3bd7c22f36ba7b974b4903a2d50 --- ext/session/session6.test | 90 +++++++++++++++++++++++++++++++++++++++ manifest | 19 +++++---- manifest.uuid | 2 +- src/vdbeapi.c | 2 +- src/vdbeaux.c | 6 ++- src/vdbeblob.c | 28 ++++++++++++ 6 files changed, 135 insertions(+), 12 deletions(-) create mode 100644 ext/session/session6.test diff --git a/ext/session/session6.test b/ext/session/session6.test new file mode 100644 index 0000000000..8a1f172cde --- /dev/null +++ b/ext/session/session6.test @@ -0,0 +1,90 @@ +# 2011 July 11 +# +# 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 sessions extension. +# Specifically, it tests that sessions work when the database is modified +# using incremental blob handles. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} + +set testprefix session6 + +proc do_then_apply_tcl {tcl {dbname main}} { + proc xConflict args { return "OMIT" } + set rc [catch { + sqlite3session S db $dbname + db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" { + S attach $name + } + eval $tcl + sqlite3changeset_apply db2 [S changeset] xConflict + } msg] + + catch { S delete } + if {$rc} {error $msg} +} + +test_sqlite3_log x +proc x {args} {puts $args} + +forcedelete test.db2 +sqlite3 db2 test.db2 + +do_common_sql { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(c PRIMARY KEY, d); +} + +# Test a blob update. +# +do_test 1.1 { + do_then_apply_tcl { + db eval { INSERT INTO t1 VALUES(1, 'helloworld') } + db eval { INSERT INTO t2 VALUES(2, 'onetwothree') } + } + compare_db db db2 +} {} +do_test 1.2 { + do_then_apply_tcl { + set fd [db incrblob t1 b 1] + puts -nonewline $fd 1234567890 + close $fd + } + compare_db db db2 +} {} + +# Test an attached database. +# +do_test 2.1 { + forcedelete test.db3 + file copy test.db2 test.db3 + execsql { ATTACH 'test.db3' AS aux; } + + do_then_apply_tcl { + set fd [db incrblob aux t2 d 1] + puts -nonewline $fd fourfivesix + close $fd + } aux + + sqlite3 db3 test.db3 + compare_db db2 db3 +} {} + + +db3 close +db2 close + +finish_test diff --git a/manifest b/manifest index 8bdd0ba57a..31ce25fa38 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Pull\sthe\slatest\sversion\s3.7.7\srelease-candidate\schanges\sinto\sthe\nsessions\sbranch. -D 2011-06-23T17:40:15.467 +C Modifications\sso\sthat\sthe\ssessions\sextension\sworks\swith\sblob\shandles. +D 2011-07-11T19:45:38.954 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -107,6 +107,7 @@ F ext/session/session2.test 99ca0da7ddb617d42bafd83adccf99f18ae0384b F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 +F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 401045278298a242cbc2e4bc986c102f01ff2180 F ext/session/sqlite3session.c 26de50c3e34d89ae62e97024ad07e772e1c52db2 @@ -251,9 +252,9 @@ F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e F src/vdbe.c df52db6162fd94767b76bb4e9a7cb9207e83086f F src/vdbe.h 322af148cceef120bb1ec9cff7f122e76abf94da F src/vdbeInt.h 3de6588b36c833969aebab202e1766d586c37ec2 -F src/vdbeapi.c 1d947da083c24e8bf61823f02f619a1f4a682100 -F src/vdbeaux.c db3d4eedccea5add714dfb8b10f70d0f8d692db5 -F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3 +F src/vdbeapi.c 432a8a194accb9fe9fae45338f210174c6c961b4 +F src/vdbeaux.c bb86d48ce99c288d17e8d79711713399c21f0a8d +F src/vdbeblob.c a547f286b651641bdb43a567af66d0e776a39ea2 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114 F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582 @@ -960,7 +961,7 @@ F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d -P 5d95b42946b5cf0346164aebe0a8c4f37527bc31 b61a76a53af04f731fe7617f7b6b4fb2aef6587b -R 5b9118bd8782ff0e4b99f3cb89f8be24 -U drh -Z 3edc7355d0a27e1ff60419d5d75c34a3 +P 840bf9c2d92192ee3cc2aa7c0e9bdb805a066fd4 +R c823c2479e73fc426d6fab6fb150638b +U dan +Z 6339a08530525dea9c6675e0fc9a27f5 diff --git a/manifest.uuid b/manifest.uuid index 6c62bceba4..fecbc08bba 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -840bf9c2d92192ee3cc2aa7c0e9bdb805a066fd4 \ No newline at end of file +82ac16c4f873d3bd7c22f36ba7b974b4903a2d50 \ No newline at end of file diff --git a/src/vdbeapi.c b/src/vdbeapi.c index f7b3b41623..136a8cd168 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -1389,7 +1389,7 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ */ int sqlite3_preupdate_count(sqlite3 *db){ PreUpdate *p = db->pPreUpdate; - return (p ? p->pCsr->nField : 0); + return (p ? p->keyinfo.nField : 0); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index a45f7a2892..8c442fce51 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3274,13 +3274,17 @@ void sqlite3VdbePreUpdateHook( iKey2 = iKey1; } + assert( pCsr->nField==pTab->nCol + || (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1) + ); + preupdate.v = v; preupdate.pCsr = pCsr; preupdate.op = op; preupdate.iNewReg = iReg; preupdate.keyinfo.db = db; preupdate.keyinfo.enc = ENC(db); - preupdate.keyinfo.nField = pCsr->nField; + preupdate.keyinfo.nField = pTab->nCol; preupdate.iKey1 = iKey1; preupdate.iKey2 = iKey2; preupdate.iPKey = pTab->iPKey; diff --git a/src/vdbeblob.c b/src/vdbeblob.c index a8728e6d25..4dc9ef4fff 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -30,6 +30,8 @@ struct Incrblob { BtCursor *pCsr; /* Cursor pointing at blob row */ sqlite3_stmt *pStmt; /* Statement holding cursor open */ sqlite3 *db; /* The associated database */ + char *zDb; /* Database name */ + Table *pTab; /* Table object */ }; @@ -194,6 +196,8 @@ int sqlite3_blob_open( sqlite3BtreeLeaveAll(db); goto blob_open_out; } + pBlob->pTab = pTab; + pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zName; /* Now search pTab for the exact column. */ for(iCol=0; iColnCol; iCol++) { @@ -386,6 +390,30 @@ static int blobReadWrite( */ assert( db == v->db ); sqlite3BtreeEnterCursor(p->pCsr); + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + if( xCall==sqlite3BtreePutData ){ + /* If a pre-update hook is registered and this is a write cursor, + ** invoke it here. + ** + ** TODO: The preupdate-hook is passed SQLITE_DELETE, even though this + ** operation should really be an SQLITE_UPDATE. This is probably + ** incorrect, but is convenient because at this point the new.* values + ** are not easily obtainable. And for the sessions module, an + ** SQLITE_UPDATE where the PK columns do not change is handled in the + ** same way as an SQLITE_DELETE (the SQLITE_DELETE code is actually + ** slightly more efficient). Since you cannot write to a PK column + ** using the incremental-blob API, this works. For the sessions module + ** anyhow. + */ + sqlite3_int64 iKey; + sqlite3BtreeKeySize(p->pCsr, &iKey); + sqlite3VdbePreUpdateHook( + v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1 + ); + } +#endif + rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); sqlite3BtreeLeaveCursor(p->pCsr); if( rc==SQLITE_ABORT ){ From 40368988da8bd6125a459e98fe6af1f5ecece54c Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 13 Jul 2011 15:21:02 +0000 Subject: [PATCH 057/570] Add the xFilter callback to the sqlite3changeset_apply() function. This callback allows the application to accept or reject changes on a per-table basis when applying a changeset. FossilOrigin-Name: 282474c42f24f0e66c69b576b72ef8ce764d49e2 --- ext/session/sqlite3session.c | 79 +++++++++++++++++++++--------------- ext/session/sqlite3session.h | 42 ++++++++++++------- ext/session/test_session.c | 43 ++++++++++++++++---- manifest | 16 ++++---- manifest.uuid | 2 +- 5 files changed, 118 insertions(+), 64 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 50c436b8c4..78d2b6d86c 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2756,6 +2756,10 @@ int sqlite3changeset_apply( sqlite3 *db, /* Apply change to "main" db of this handle */ int nChangeset, /* Size of changeset in bytes */ void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), int(*xConflict)( void *pCtx, /* Copy of fifth arg to _apply() */ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ @@ -2788,7 +2792,6 @@ int sqlite3changeset_apply( if( zTab==0 || sqlite3_strnicmp(zNew, zTab, nTab+1) ){ u8 *abPK; - schemaMismatch = 0; sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ sqlite3_finalize(sApply.pDelete); sqlite3_finalize(sApply.pUpdate); @@ -2797,40 +2800,50 @@ int sqlite3changeset_apply( memset(&sApply, 0, sizeof(sApply)); sApply.db = db; - sqlite3changeset_pk(pIter, &abPK, 0); - rc = sessionTableInfo( - db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK - ); - if( rc!=SQLITE_OK ) break; - - if( sApply.nCol==0 ){ - schemaMismatch = 1; - sqlite3_log(SQLITE_SCHEMA, - "sqlite3changeset_apply(): no such table: %s", zTab + /* If an xFilter() callback was specified, invoke it now. If the + ** xFilter callback returns zero, skip this table. If it returns + ** non-zero, proceed. */ + schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew))); + if( schemaMismatch ){ + zTab = sqlite3_mprintf("%s", zNew); + nTab = strlen(zTab); + sApply.azCol = (const char **)zTab; + }else{ + sqlite3changeset_pk(pIter, &abPK, 0); + rc = sessionTableInfo( + db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK ); + if( rc!=SQLITE_OK ) break; + + if( sApply.nCol==0 ){ + schemaMismatch = 1; + sqlite3_log(SQLITE_SCHEMA, + "sqlite3changeset_apply(): no such table: %s", zTab + ); + } + else if( sApply.nCol!=nCol ){ + schemaMismatch = 1; + sqlite3_log(SQLITE_SCHEMA, + "sqlite3changeset_apply(): table %s has %d columns, expected %d", + zTab, sApply.nCol, nCol + ); + } + else if( memcmp(sApply.abPK, abPK, nCol)!=0 ){ + schemaMismatch = 1; + sqlite3_log(SQLITE_SCHEMA, "sqlite3changeset_apply(): " + "primary key mismatch for table %s", zTab + ); + } + else if( + (rc = sessionSelectRow(db, zTab, &sApply)) + || (rc = sessionUpdateRow(db, zTab, &sApply)) + || (rc = sessionDeleteRow(db, zTab, &sApply)) + || (rc = sessionInsertRow(db, zTab, &sApply)) + ){ + break; + } + nTab = sqlite3Strlen30(zTab); } - else if( sApply.nCol!=nCol ){ - schemaMismatch = 1; - sqlite3_log(SQLITE_SCHEMA, - "sqlite3changeset_apply(): table %s has %d columns, expected %d", - zTab, sApply.nCol, nCol - ); - } - else if( memcmp(sApply.abPK, abPK, nCol)!=0 ){ - schemaMismatch = 1; - sqlite3_log(SQLITE_SCHEMA, - "sqlite3changeset_apply(): primary key mismatch for table %s", zTab - ); - } - else if( - (rc = sessionSelectRow(db, zTab, &sApply)) - || (rc = sessionUpdateRow(db, zTab, &sApply)) - || (rc = sessionDeleteRow(db, zTab, &sApply)) - || (rc = sessionInsertRow(db, zTab, &sApply)) - ){ - break; - } - nTab = sqlite3Strlen30(zTab); } /* If there is a schema mismatch on the current table, proceed to the diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 38164401f4..d8db1d6137 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -610,9 +610,19 @@ int sqlite3changeset_concat( ** "main" database attached to handle db with the changes found in the ** changeset passed via the second and third arguments. ** -** For each change in the changeset, this function tests that the target -** database contains a compatible table. A table is considered compatible -** if all of the following are true: +** The fourth argument (xFilter) passed to this function is the "filter +** callback". If it is not NULL, then for each table affected by at least one +** change in the changeset, the filter callback is invoked with +** the table name as the second argument, and a copy of the context pointer +** passed as the sixth argument to this function as the first. If the "filter +** callback" returns zero, then no attempt is made to apply any changes to +** the table. Otherwise, if the return value is non-zero or the xFilter +** argument to this function is NULL, all changes related to the table are +** attempted. +** +** For each table that is not excluded by the filter callback, this function +** tests that the target database contains a compatible table. A table is +** considered compatible if all of the following are true: ** **
    **
  • The table has the same name as the name recorded in the @@ -623,17 +633,17 @@ int sqlite3changeset_concat( ** recorded in the changeset. **
** -** If there is no compatible table, it is not an error, but the change is -** not applied. A warning message is issued via the sqlite3_log() mechanism -** with the error code SQLITE_SCHEMA. At most one such warning is issued for -** each table in the changeset. +** If there is no compatible table, it is not an error, but none of the +** changes associated with the table are applied. A warning message is issued +** via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most +** one such warning is issued for each table in the changeset. ** -** Otherwise, if there is a compatible table, an attempt is made to modify -** the table contents according to the UPDATE, INSERT or DELETE change. -** If a change cannot be applied cleanly, the conflict handler function -** passed as the fourth argument to sqlite3changeset_apply() may be invoked. -** A description of exactly when the conflict handler is invoked for each -** type of change is below. +** For each change for which there is a compatible table, an attempt is made +** to modify the table contents according to the UPDATE, INSERT or DELETE +** change. If a change cannot be applied cleanly, the conflict handler +** function passed as the fifth argument to sqlite3changeset_apply() may be +** invoked. A description of exactly when the conflict handler is invoked for +** each type of change is below. ** ** Each time the conflict handler function is invoked, it must return one ** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or @@ -729,8 +739,12 @@ int sqlite3changeset_apply( sqlite3 *db, /* Apply change to "main" db of this handle */ int nChangeset, /* Size of changeset in bytes */ void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), int(*xConflict)( - void *pCtx, /* Copy of fifth arg to _apply() */ + void *pCtx, /* Copy of sixth arg to _apply() */ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 0993073328..9817b3c2f4 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -185,7 +185,8 @@ static void test_append_value(Tcl_Obj *pList, sqlite3_value *pVal){ typedef struct TestConflictHandler TestConflictHandler; struct TestConflictHandler { Tcl_Interp *interp; - Tcl_Obj *pScript; + Tcl_Obj *pConflictScript; + Tcl_Obj *pFilterScript; }; static int test_obj_eq_string(Tcl_Obj *p, const char *z){ @@ -199,6 +200,29 @@ static int test_obj_eq_string(Tcl_Obj *p, const char *z){ return (nObj==n && (n==0 || 0==memcmp(zObj, z, n))); } +static int test_filter_handler( + void *pCtx, /* Pointer to TestConflictHandler structure */ + const char *zTab /* Table name */ +){ + TestConflictHandler *p = (TestConflictHandler *)pCtx; + int res = 1; + Tcl_Obj *pEval; + Tcl_Interp *interp = p->interp; + + pEval = Tcl_DuplicateObj(p->pFilterScript); + Tcl_IncrRefCount(pEval); + + if( TCL_OK!=Tcl_ListObjAppendElement(0, pEval, Tcl_NewStringObj(zTab, -1)) + || TCL_OK!=Tcl_EvalObjEx(interp, pEval, TCL_EVAL_GLOBAL) + || TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &res) + ){ + Tcl_BackgroundError(interp); + } + + Tcl_DecrRefCount(pEval); + return res; +} + static int test_conflict_handler( void *pCtx, /* Pointer to TestConflictHandler structure */ int eConf, /* DATA, MISSING, CONFLICT, CONSTRAINT */ @@ -213,7 +237,7 @@ static int test_conflict_handler( const char *zTab; /* Name of table conflict is on */ int nCol; /* Number of columns in table zTab */ - pEval = Tcl_DuplicateObj(p->pScript); + pEval = Tcl_DuplicateObj(p->pConflictScript); Tcl_IncrRefCount(pEval); sqlite3changeset_op(pIter, &zTab, &nCol, &op, 0); @@ -342,7 +366,7 @@ static int test_conflict_handler( } /* -** sqlite3changeset_apply DB CHANGESET SCRIPT +** sqlite3changeset_apply DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT? */ static int test_sqlite3changeset_apply( void * clientData, @@ -357,8 +381,10 @@ static int test_sqlite3changeset_apply( int nChangeset; /* Size of buffer aChangeset in bytes */ TestConflictHandler ctx; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB CHANGESET SCRIPT"); + if( objc!=4 && objc!=5 ){ + Tcl_WrongNumArgs(interp, 1, objv, + "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?" + ); return TCL_ERROR; } if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &info) ){ @@ -367,11 +393,12 @@ static int test_sqlite3changeset_apply( } db = *(sqlite3 **)info.objClientData; pChangeset = (void *)Tcl_GetByteArrayFromObj(objv[2], &nChangeset); - ctx.pScript = objv[3]; + ctx.pConflictScript = objv[3]; + ctx.pFilterScript = objc==5 ? objv[4] : 0; ctx.interp = interp; - rc = sqlite3changeset_apply( - db, nChangeset, pChangeset, test_conflict_handler, (void *)&ctx + rc = sqlite3changeset_apply(db, nChangeset, pChangeset, + (objc==5) ? test_filter_handler : 0, test_conflict_handler, (void *)&ctx ); if( rc!=SQLITE_OK ){ return test_session_error(interp, rc); diff --git a/manifest b/manifest index 31ce25fa38..f77afa1ffe 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modifications\sso\sthat\sthe\ssessions\sextension\sworks\swith\sblob\shandles. -D 2011-07-11T19:45:38.954 +C Add\sthe\sxFilter\scallback\sto\sthe\ssqlite3changeset_apply()\sfunction.\sThis\scallback\sallows\sthe\sapplication\sto\saccept\sor\sreject\schanges\son\sa\sper-table\sbasis\swhen\sapplying\sa\schangeset. +D 2011-07-13T15:21:02.741 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -110,9 +110,9 @@ F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 401045278298a242cbc2e4bc986c102f01ff2180 -F ext/session/sqlite3session.c 26de50c3e34d89ae62e97024ad07e772e1c52db2 -F ext/session/sqlite3session.h 665f5591562e3c71eb3d0da26f1a1efae26f7bcf -F ext/session/test_session.c 311e5b9228374d0b5780448f289847ff1cf7d388 +F ext/session/sqlite3session.c c05d28332fcdd66c82de85f5459d71554e2259d7 +F ext/session/sqlite3session.h f34905c818569779ddaea1bbef43469177614c69 +F ext/session/test_session.c 209f13fa8f4a597ffcc15fd0f8a3f27ed079c5e5 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk f56d9895882f5cdd9f9f9ba8f8a679e9202288c1 @@ -961,7 +961,7 @@ F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d -P 840bf9c2d92192ee3cc2aa7c0e9bdb805a066fd4 -R c823c2479e73fc426d6fab6fb150638b +P 82ac16c4f873d3bd7c22f36ba7b974b4903a2d50 +R c22fa4ebad64b5fe1347a3f0a2dcb7e8 U dan -Z 6339a08530525dea9c6675e0fc9a27f5 +Z 6a509799e9e665bc4a33861bc6dba39f diff --git a/manifest.uuid b/manifest.uuid index fecbc08bba..527039d08d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -82ac16c4f873d3bd7c22f36ba7b974b4903a2d50 \ No newline at end of file +282474c42f24f0e66c69b576b72ef8ce764d49e2 \ No newline at end of file From 4f52804206ab97c057f7f0a6a9e078a5c9555867 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 15 Jul 2011 19:11:32 +0000 Subject: [PATCH 058/570] Add a few casts required by 64-bit VS2010 to the sessions code. FossilOrigin-Name: 5ac4a06111b5fad5f58c20ef5d2b65aeb23e105a --- ext/session/sqlite3session.c | 10 +++++----- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 78d2b6d86c..577556ee92 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1637,7 +1637,7 @@ static void sessionAppendTableHdr( sessionAppendByte(pBuf, 'T', pRc); sessionAppendVarint(pBuf, pTab->nCol, pRc); sessionAppendBlob(pBuf, pTab->abPK, pTab->nCol, pRc); - sessionAppendBlob(pBuf, (u8 *)pTab->zName, strlen(pTab->zName)+1, pRc); + sessionAppendBlob(pBuf, (u8 *)pTab->zName, (int)strlen(pTab->zName)+1, pRc); } /* @@ -1951,7 +1951,7 @@ static int sessionChangesetNext( if( p->rc!=SQLITE_OK ) return p->rc; } - if( pnRec ){ *pnRec = aChange - *paRec; } + if( pnRec ){ *pnRec = (int)(aChange - *paRec); } p->pNext = aChange; return SQLITE_ROW; } @@ -2806,7 +2806,7 @@ int sqlite3changeset_apply( schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew))); if( schemaMismatch ){ zTab = sqlite3_mprintf("%s", zNew); - nTab = strlen(zTab); + nTab = (int)strlen(zTab); sApply.azCol = (const char **)zTab; }else{ sqlite3changeset_pk(pIter, &abPK, 0); @@ -2995,7 +2995,7 @@ static int sessionChangeMerge( } if( pNew ){ - pNew->nRecord = (aCsr - pNew->aRecord); + pNew->nRecord = (int)(aCsr - pNew->aRecord); } sqlite3_free(pExist); } @@ -3042,7 +3042,7 @@ int sessionConcatChangeset( if( !pTab || zNew!=pTab->zName ){ /* Search the list for a matching table */ - int nNew = strlen(zNew); + int nNew = (int)strlen(zNew); u8 *abPK; sqlite3changeset_pk(pIter, &abPK, 0); diff --git a/manifest b/manifest index f77afa1ffe..02f04f5c40 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sxFilter\scallback\sto\sthe\ssqlite3changeset_apply()\sfunction.\sThis\scallback\sallows\sthe\sapplication\sto\saccept\sor\sreject\schanges\son\sa\sper-table\sbasis\swhen\sapplying\sa\schangeset. -D 2011-07-13T15:21:02.741 +C Add\sa\sfew\scasts\srequired\sby\s64-bit\sVS2010\sto\sthe\ssessions\scode. +D 2011-07-15T19:11:32.763 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -110,7 +110,7 @@ F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 401045278298a242cbc2e4bc986c102f01ff2180 -F ext/session/sqlite3session.c c05d28332fcdd66c82de85f5459d71554e2259d7 +F ext/session/sqlite3session.c b31221e6e068476f736e8aaf5c7b66895d1b16f4 F ext/session/sqlite3session.h f34905c818569779ddaea1bbef43469177614c69 F ext/session/test_session.c 209f13fa8f4a597ffcc15fd0f8a3f27ed079c5e5 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -961,7 +961,7 @@ F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d -P 82ac16c4f873d3bd7c22f36ba7b974b4903a2d50 -R c22fa4ebad64b5fe1347a3f0a2dcb7e8 +P 282474c42f24f0e66c69b576b72ef8ce764d49e2 +R dce52d6dc32cededac0b5cc1823e4002 U dan -Z 6a509799e9e665bc4a33861bc6dba39f +Z 91f64262d00fcd067a4fb1a130723392 diff --git a/manifest.uuid b/manifest.uuid index 527039d08d..1a2b253550 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -282474c42f24f0e66c69b576b72ef8ce764d49e2 \ No newline at end of file +5ac4a06111b5fad5f58c20ef5d2b65aeb23e105a \ No newline at end of file From b69ec3482a760d6d74e1386c524f7de51d622b92 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 16 Jul 2011 18:05:07 +0000 Subject: [PATCH 059/570] Note in the documentation that when iterating through a changeset, all changes to a single table are grouped together. Also add the sqlite3session_isempty() function. FossilOrigin-Name: 364f3b820a26f9b15cf74a0222ed5e302becc54f --- ext/session/session1.test | 27 +++++++++++++++++++++++++++ ext/session/sqlite3session.c | 17 +++++++++++++++++ ext/session/sqlite3session.h | 26 ++++++++++++++++++++++++++ ext/session/test_session.c | 8 ++++++++ manifest | 18 +++++++++--------- manifest.uuid | 2 +- 6 files changed, 88 insertions(+), 10 deletions(-) diff --git a/ext/session/session1.test b/ext/session/session1.test index 5e0fbc52a0..3ffe893a0d 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -464,6 +464,33 @@ do_iterator_test 7.1 * { {INSERT t1 0 X. {} {t one i 1}} } +#------------------------------------------------------------------------- +# Test the sqlite3session_isempty() function. +# +do_test 8.1 { + execsql { + CREATE TABLE t5(x PRIMARY KEY, y); + CREATE TABLE t6(x PRIMARY KEY, y); + INSERT INTO t5 VALUES('a', 'b'); + INSERT INTO t6 VALUES('a', 'b'); + } + sqlite3session S db main + S attach * + + S isempty +} {0} +do_test 8.2 { + execsql { DELETE FROM t5 } + S isempty +} {1} +do_test 8.3 { + S delete + sqlite3session S db main + S attach t5 + execsql { DELETE FROM t5 } + S isempty +} {0} +do_test 8.4 { S delete } {} catch { db2 close } finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 577556ee92..2e21f2800f 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1773,6 +1773,23 @@ int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect){ return ret; } +/* +** Return true if there have been no changes to monitored tables recorded +** by the session object passed as the only argument. +*/ +int sqlite3session_isempty(sqlite3_session *pSession){ + int ret = 0; + SessionTable *pTab; + + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); + for(pTab=pSession->pTable; pTab && ret==0; pTab=pTab->pNext){ + ret = (pTab->nEntry>0); + } + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); + + return ret; +} + /* ** Create an iterator used to iterate through the contents of a changeset. */ diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index d8db1d6137..3c27d22ff8 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -254,6 +254,23 @@ int sqlite3session_changeset( void **ppChangeset /* OUT: Buffer containing changeset */ ); +/* +** CAPI3REF: Test if a changeset has recorded any changes. +** +** Return non-zero if no changes to attached tables have been recorded by +** the session object passed as the first argument. Otherwise, if one or +** more changes have been recorded, return zero. +** +** Even if this function returns zero, it is possible that calling +** [sqlite3session_changeset()] on the session handle may still return a +** changeset that contains no changes. This can happen when a row in +** an attached table is modified and then later on the original values +** are restored. However, if this function returns non-zero, then it is +** guaranteed that a call to sqlite3session_changeset() will return a +** changeset containing zero changes. +*/ +int sqlite3session_isempty(sqlite3_session *pSession); + /* ** CAPI3REF: Create An Iterator To Traverse A Changeset ** @@ -276,6 +293,15 @@ int sqlite3session_changeset( ** by passing it to [sqlite3changeset_finalize()]. The buffer containing the ** changeset (pChangeset) must remain valid until after the iterator is ** destroyed. +** +** Assuming the changeset blob was created by one of the +** [sqlite3session_changeset()], [sqlite3changeset_concat()] or +** [sqlite3changest_invert()], all changes within the changeset that apply +** to a single table are grouped together. This means that when an application +** iterates through a changeset using an iterator created by this function, +** all changes that relate to a single table are visted consecutively. There +** is no chance that the iterator will visit a change the applies to table X, +** then one for table Y, and then later on visit another change for table X. */ int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 9817b3c2f4..4bf2766c9c 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -38,6 +38,7 @@ static int test_session_cmd( { "delete", 0, "", }, /* 2 */ { "enable", 1, "BOOL", }, /* 3 */ { "indirect", 1, "BOOL", }, /* 4 */ + { "isempty", 0, "", }, /* 5 */ { 0 } }; int iSub; @@ -99,6 +100,13 @@ static int test_session_cmd( Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val)); break; } + + case 5: { /* isempty */ + int val; + val = sqlite3session_isempty(pSession); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val)); + break; + } } return TCL_OK; diff --git a/manifest b/manifest index 02f04f5c40..c0d06c4548 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\sfew\scasts\srequired\sby\s64-bit\sVS2010\sto\sthe\ssessions\scode. -D 2011-07-15T19:11:32.763 +C Note\sin\sthe\sdocumentation\sthat\swhen\siterating\sthrough\sa\schangeset,\sall\schanges\sto\sa\ssingle\stable\sare\sgrouped\stogether.\sAlso\sadd\sthe\ssqlite3session_isempty()\sfunction. +D 2011-07-16T18:05:07.557 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -102,7 +102,7 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/session1.test f5d9f2e362abe2563181389509822bda956516ee +F ext/session/session1.test 6ad289a19648890cb138e4d2c9d2f5c1f714e505 F ext/session/session2.test 99ca0da7ddb617d42bafd83adccf99f18ae0384b F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 @@ -110,9 +110,9 @@ F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 401045278298a242cbc2e4bc986c102f01ff2180 -F ext/session/sqlite3session.c b31221e6e068476f736e8aaf5c7b66895d1b16f4 -F ext/session/sqlite3session.h f34905c818569779ddaea1bbef43469177614c69 -F ext/session/test_session.c 209f13fa8f4a597ffcc15fd0f8a3f27ed079c5e5 +F ext/session/sqlite3session.c b35e70924598794e157325eb7176523293f1d48c +F ext/session/sqlite3session.h b977d0bae338918c64f4f18f03f4648ad91df407 +F ext/session/test_session.c ea4dc9b4a1895c8e6bddcbfe3838d7eb57df2d99 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk f56d9895882f5cdd9f9f9ba8f8a679e9202288c1 @@ -961,7 +961,7 @@ F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d -P 282474c42f24f0e66c69b576b72ef8ce764d49e2 -R dce52d6dc32cededac0b5cc1823e4002 +P 5ac4a06111b5fad5f58c20ef5d2b65aeb23e105a +R 3578d3e546ebd39820e5a49b01cb2c15 U dan -Z 91f64262d00fcd067a4fb1a130723392 +Z 84bc1b5f26e12cf6f38c5104884f25b6 diff --git a/manifest.uuid b/manifest.uuid index 1a2b253550..06c7707950 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5ac4a06111b5fad5f58c20ef5d2b65aeb23e105a \ No newline at end of file +364f3b820a26f9b15cf74a0222ed5e302becc54f \ No newline at end of file From a93166e030d00e81f471b3863dc3f8396955597b Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 16 Jul 2011 18:35:53 +0000 Subject: [PATCH 060/570] Fix error in a comment in sqlite3session.h. No changes to code. FossilOrigin-Name: 70c84e50209722a61d66fd737e42d49275745b62 --- ext/session/sqlite3session.h | 13 +++++++------ manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 3c27d22ff8..3a1c470ca8 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -296,12 +296,13 @@ int sqlite3session_isempty(sqlite3_session *pSession); ** ** Assuming the changeset blob was created by one of the ** [sqlite3session_changeset()], [sqlite3changeset_concat()] or -** [sqlite3changest_invert()], all changes within the changeset that apply -** to a single table are grouped together. This means that when an application -** iterates through a changeset using an iterator created by this function, -** all changes that relate to a single table are visted consecutively. There -** is no chance that the iterator will visit a change the applies to table X, -** then one for table Y, and then later on visit another change for table X. +** [sqlite3changeset_invert()] functions, all changes within the changeset +** that apply to a single table are grouped together. This means that when +** an application iterates through a changeset using an iterator created by +** this function, all changes that relate to a single table are visted +** consecutively. There is no chance that the iterator will visit a change +** the applies to table X, then one for table Y, and then later on visit +** another change for table X. */ int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ diff --git a/manifest b/manifest index c0d06c4548..141967fdc4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Note\sin\sthe\sdocumentation\sthat\swhen\siterating\sthrough\sa\schangeset,\sall\schanges\sto\sa\ssingle\stable\sare\sgrouped\stogether.\sAlso\sadd\sthe\ssqlite3session_isempty()\sfunction. -D 2011-07-16T18:05:07.557 +C Fix\serror\sin\sa\scomment\sin\ssqlite3session.h.\sNo\schanges\sto\scode. +D 2011-07-16T18:35:53.645 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -111,7 +111,7 @@ F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 401045278298a242cbc2e4bc986c102f01ff2180 F ext/session/sqlite3session.c b35e70924598794e157325eb7176523293f1d48c -F ext/session/sqlite3session.h b977d0bae338918c64f4f18f03f4648ad91df407 +F ext/session/sqlite3session.h 8dec372049532017d71c992609ca5450de7c5520 F ext/session/test_session.c ea4dc9b4a1895c8e6bddcbfe3838d7eb57df2d99 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -961,7 +961,7 @@ F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d -P 5ac4a06111b5fad5f58c20ef5d2b65aeb23e105a -R 3578d3e546ebd39820e5a49b01cb2c15 +P 364f3b820a26f9b15cf74a0222ed5e302becc54f +R 7e574e123b2972c02a13eb4ef0e5a00a U dan -Z 84bc1b5f26e12cf6f38c5104884f25b6 +Z 6474c382418a7e49b9385e31f9ee66e8 diff --git a/manifest.uuid b/manifest.uuid index 06c7707950..03dc0faed6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -364f3b820a26f9b15cf74a0222ed5e302becc54f \ No newline at end of file +70c84e50209722a61d66fd737e42d49275745b62 \ No newline at end of file From ff53032641c6a9e01b3e9c8425c3a101fd7f7546 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 18 Jul 2011 15:22:56 +0000 Subject: [PATCH 061/570] Fix the sqlite3session_isempty() method so that it returns, as documented, non-zero when no changes have been recorded by the session object. FossilOrigin-Name: d04e0fd82a15aee963e35830caf8159b4b6ccd87 --- ext/session/session1.test | 6 +++--- ext/session/sqlite3session.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ext/session/session1.test b/ext/session/session1.test index 3ffe893a0d..91ccab21aa 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -478,18 +478,18 @@ do_test 8.1 { S attach * S isempty -} {0} +} {1} do_test 8.2 { execsql { DELETE FROM t5 } S isempty -} {1} +} {0} do_test 8.3 { S delete sqlite3session S db main S attach t5 execsql { DELETE FROM t5 } S isempty -} {0} +} {1} do_test 8.4 { S delete } {} catch { db2 close } diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 2e21f2800f..817954034f 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1787,7 +1787,7 @@ int sqlite3session_isempty(sqlite3_session *pSession){ } sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); - return ret; + return (ret==0); } /* diff --git a/manifest b/manifest index 141967fdc4..a3d6a2cab4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\serror\sin\sa\scomment\sin\ssqlite3session.h.\sNo\schanges\sto\scode. -D 2011-07-16T18:35:53.645 +C Fix\sthe\ssqlite3session_isempty()\smethod\sso\sthat\sit\sreturns,\sas\sdocumented,\snon-zero\swhen\sno\schanges\shave\sbeen\srecorded\sby\sthe\ssession\sobject. +D 2011-07-18T15:22:56.414 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -102,7 +102,7 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/session1.test 6ad289a19648890cb138e4d2c9d2f5c1f714e505 +F ext/session/session1.test 98691eec553390d61114b6214d2397f399dc1198 F ext/session/session2.test 99ca0da7ddb617d42bafd83adccf99f18ae0384b F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 @@ -110,7 +110,7 @@ F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 401045278298a242cbc2e4bc986c102f01ff2180 -F ext/session/sqlite3session.c b35e70924598794e157325eb7176523293f1d48c +F ext/session/sqlite3session.c 97295e187eade25398f52ed8b13fea68e0ee1e02 F ext/session/sqlite3session.h 8dec372049532017d71c992609ca5450de7c5520 F ext/session/test_session.c ea4dc9b4a1895c8e6bddcbfe3838d7eb57df2d99 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -961,7 +961,7 @@ F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d -P 364f3b820a26f9b15cf74a0222ed5e302becc54f -R 7e574e123b2972c02a13eb4ef0e5a00a +P 70c84e50209722a61d66fd737e42d49275745b62 +R 7d529af0ae98dc5a31387a39a49b9017 U dan -Z 6474c382418a7e49b9385e31f9ee66e8 +Z 3511ba374807e0034b8197f50cf80466 diff --git a/manifest.uuid b/manifest.uuid index 03dc0faed6..7c4bfbd3cf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -70c84e50209722a61d66fd737e42d49275745b62 \ No newline at end of file +d04e0fd82a15aee963e35830caf8159b4b6ccd87 \ No newline at end of file From cfec7eee203411e30cf3c55d975b562dc8f2c16e Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 26 Jul 2011 15:50:36 +0000 Subject: [PATCH 062/570] Fix a problem causing sqlite3changeset_invert() to effectively drop UPDATE changes. FossilOrigin-Name: bb3e65d9724dcecdc54b4c9fb0448f95d14495ff --- ext/session/session1.test | 15 +++++- ext/session/session8.test | 92 ++++++++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 82 +++++++++++++++++++++++++------- ext/session/sqlite3session.h | 2 +- manifest | 19 ++++---- manifest.uuid | 2 +- 6 files changed, 183 insertions(+), 29 deletions(-) create mode 100644 ext/session/session8.test diff --git a/ext/session/session1.test b/ext/session/session1.test index 91ccab21aa..7ef33e7fce 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -142,7 +142,7 @@ do_changeset_test 2.3.2 S { do_changeset_invert_test 2.3.3 S { {DELETE t1 0 X. {i 10 t Sukhothai} {}} {INSERT t1 0 X. {} {i 1 t Sukhothai}} - {UPDATE t1 0 X. {{} {} t Surin} {i 2 t Ayutthaya}} + {UPDATE t1 0 X. {i 2 t Surin} {{} {} t Ayutthaya}} {INSERT t1 0 X. {} {i 3 t Thonburi}} {DELETE t1 0 X. {i 20 t Thapae} {}} } @@ -492,5 +492,18 @@ do_test 8.3 { } {1} do_test 8.4 { S delete } {} +#------------------------------------------------------------------------- +# +do_execsql_test 9.1 { + CREATE TABLE t7(a, b, c, d, e PRIMARY KEY, f, g); + INSERT INTO t7 VALUES(1, 1, 1, 1, 1, 1, 1); +} +do_test 9.2 { + sqlite3session S db main + S attach * + execsql { UPDATE t7 SET b=2, d=2 } +} {} +do_changeset_test 9.2 S {{UPDATE t7 0 ....X.. {{} {} i 1 {} {} i 1 i 1 {} {} {} {}} {{} {} i 2 {} {} i 2 {} {} {} {} {} {}}}} +S delete catch { db2 close } finish_test diff --git a/ext/session/session8.test b/ext/session/session8.test new file mode 100644 index 0000000000..93bd4e06c3 --- /dev/null +++ b/ext/session/session8.test @@ -0,0 +1,92 @@ +# 2011 July 13 +# +# 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. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} + +set testprefix session8 + +proc noop {args} {} + +# Like [dbcksum] in tester.tcl. Except this version is not sensitive +# to changes in the value of implicit IPK columns. +# +proc udbcksum {db dbname} { + if {$dbname=="temp"} { + set master sqlite_temp_master + } else { + set master $dbname.sqlite_master + } + set alltab [$db eval "SELECT name FROM $master WHERE type='table'"] + set txt [$db eval "SELECT * FROM $master"]\n + foreach tab $alltab { + append txt [lsort [$db eval "SELECT * FROM $dbname.$tab"]]\n + } + return [md5 $txt] +} + +proc do_then_undo {tn sql} { + set ck1 [udbcksum db main] + + sqlite3session S db main + S attach * + db eval $sql + + set ck2 [udbcksum db main] + + set invert [sqlite3changeset_invert [S changeset]] + S delete + sqlite3changeset_apply db $invert noop + + set ck3 [udbcksum db main] + + set a [expr {$ck1==$ck2}] + set b [expr {$ck1==$ck3}] + uplevel [list do_test $tn.1 "set {} $a" 0] + uplevel [list do_test $tn.2 "set {} $b" 1] +} + +do_execsql_test 1.1 { + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES("abc", "xyz"); +} +do_then_undo 1.2 { INSERT INTO t1 VALUES(3, 4); } +do_then_undo 1.3 { DELETE FROM t1 WHERE b=2; } +do_then_undo 1.4 { UPDATE t1 SET b = 3 WHERE a = 1; } + +do_execsql_test 2.1 { + CREATE TABLE t2(a, b PRIMARY KEY); + INSERT INTO t2 VALUES(1, 2); + INSERT INTO t2 VALUES('abc', 'xyz'); +} +do_then_undo 1.2 { INSERT INTO t2 VALUES(3, 4); } +do_then_undo 1.3 { DELETE FROM t2 WHERE b=2; } +do_then_undo 1.4 { UPDATE t1 SET a = '123' WHERE b = 'xyz'; } + +do_execsql_test 3.1 { + CREATE TABLE t3(a, b, c, d, e, PRIMARY KEY(c, e)); + INSERT INTO t3 VALUES('x', 45, 0.0, 'abcdef', 12); + INSERT INTO t3 VALUES(45, 0.0, 'abcdef', 12, 'x'); + INSERT INTO t3 VALUES(0.0, 'abcdef', 12, 'x', 45); +} + +do_then_undo 3.2 { UPDATE t3 SET b=b||b WHERE e!='x' } +do_then_undo 3.3 { UPDATE t3 SET a = 46 } + +finish_test + diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 817954034f..b8bcc9b286 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2132,14 +2132,17 @@ int sqlite3changeset_finalize(sqlite3_changeset_iter *p){ */ int sqlite3changeset_invert( int nChangeset, /* Number of bytes in input */ - void *pChangeset, /* Input changeset */ + const void *pChangeset, /* Input changeset */ int *pnInverted, /* OUT: Number of bytes in output changeset */ void **ppInverted /* OUT: Inverse of pChangeset */ ){ + int rc = SQLITE_OK; /* Return value */ u8 *aOut; u8 *aIn; int i; - int nCol = 0; + int nCol = 0; /* Number of cols in current table */ + u8 *abPK = 0; /* PK array for current table */ + sqlite3_value **apVal = 0; /* Space for values for UPDATE inversion */ /* Zero the output variables in case an error occurs. */ *ppInverted = 0; @@ -2163,10 +2166,13 @@ int sqlite3changeset_invert( ** * A nul-terminated table name. */ int nByte = 1 + sessionVarintGet(&aIn[i+1], &nCol); + abPK = &aIn[i+nByte]; nByte += nCol; nByte += 1 + sqlite3Strlen30((char *)&aIn[i+nByte]); memcpy(&aOut[i], &aIn[i], nByte); i += nByte; + sqlite3_free(apVal); + apVal = 0; break; } @@ -2185,40 +2191,82 @@ int sqlite3changeset_invert( } case SQLITE_UPDATE: { - int nByte1; /* Size of old.* record in bytes */ - int nByte2; /* Size of new.* record in bytes */ - u8 *aEnd = &aIn[i+2]; + int iCol; + int nWrite = 0; + u8 *aEnd = &aIn[i+2]; - sessionReadRecord(&aEnd, nCol, 0); - nByte1 = (int)(aEnd - &aIn[i+2]); - sessionReadRecord(&aEnd, nCol, 0); - nByte2 = (int)(aEnd - &aIn[i+2]) - nByte1; + if( 0==apVal ){ + apVal = (sqlite3_value **)sqlite3_malloc(sizeof(apVal[0])*nCol*2); + if( 0==apVal ){ + rc = SQLITE_NOMEM; + goto finished_invert; + } + memset(apVal, 0, sizeof(apVal[0])*nCol*2); + } + /* Read the old.* and new.* records for the update change. */ + rc = sessionReadRecord(&aEnd, nCol, &apVal[0]); + if( rc==SQLITE_OK ){ + rc = sessionReadRecord(&aEnd, nCol, &apVal[nCol]); + } + + /* Write the header for the new UPDATE change. Same as the original. */ aOut[i] = SQLITE_UPDATE; aOut[i+1] = aIn[i+1]; - memcpy(&aOut[i+2], &aIn[i+2+nByte1], nByte2); - memcpy(&aOut[i+2+nByte2], &aIn[i+2], nByte1); + nWrite = 2; - i += 2 + nByte1 + nByte2; + /* Write the new old.* record. Consists of the PK columns from the + ** original old.* record, and the other values from the original + ** new.* record. */ + for(iCol=0; rc==SQLITE_OK && iColaRecord; u8 *a2 = aRec; + assert( op1==SQLITE_UPDATE ); sessionReadRecord(&a1, pTab->nCol, 0); sessionReadRecord(&a2, pTab->nCol, 0); pNew->op = SQLITE_UPDATE; diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 3a1c470ca8..a1ab1e9645 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -545,7 +545,7 @@ int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); ** changeset. If it is not, the results are undefined. */ int sqlite3changeset_invert( - int nIn, void *pIn, /* Input changeset */ + int nIn, const void *pIn, /* Input changeset */ int *pnOut, void **ppOut /* OUT: Inverse of input */ ); diff --git a/manifest b/manifest index 4e10bb5947..996459f395 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\slatest\strunk\schanges\sinto\sthe\ssessions\sbranch. -D 2011-07-22T12:49:27.667 +C Fix\sa\sproblem\scausing\ssqlite3changeset_invert()\sto\seffectively\sdrop\sUPDATE\schanges. +D 2011-07-26T15:50:36.271 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 1e6988b3c11dee9bd5edc0c804bd4468d74a9cdc F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -102,16 +102,17 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/session1.test 98691eec553390d61114b6214d2397f399dc1198 +F ext/session/session1.test 502086908e4144dfaccb1baa77bc29d75a9daace F ext/session/session2.test 99ca0da7ddb617d42bafd83adccf99f18ae0384b F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 +F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 401045278298a242cbc2e4bc986c102f01ff2180 -F ext/session/sqlite3session.c 97295e187eade25398f52ed8b13fea68e0ee1e02 -F ext/session/sqlite3session.h 8dec372049532017d71c992609ca5450de7c5520 +F ext/session/sqlite3session.c 5a50e28759187440805fca653029946311593da6 +F ext/session/sqlite3session.h f374c9c4c96e08f67ac418871c29d423245c7673 F ext/session/test_session.c ea4dc9b4a1895c8e6bddcbfe3838d7eb57df2d99 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -964,7 +965,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262 -P d04e0fd82a15aee963e35830caf8159b4b6ccd87 8ce2b74a82264550b0e19da3e0e1a145db940a1c -R a5737ded89a8c66dbf565b51f6981ff8 -U drh -Z 81f45685ad26c120405ad7cb74da4306 +P 110cfd6920cf3011aeaf7e586f8db867bfc69fbb +R 95b1f91b4b1f21686c1d16002cdc06fd +U dan +Z 326ddfa62484f9d6c6538d0373ca9236 diff --git a/manifest.uuid b/manifest.uuid index cd26a2668c..94d44ce8ae 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -110cfd6920cf3011aeaf7e586f8db867bfc69fbb \ No newline at end of file +bb3e65d9724dcecdc54b4c9fb0448f95d14495ff \ No newline at end of file From 1e556c3fe51cdf565c6bf05ba0406ce51872e3d5 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 26 Jul 2011 15:57:56 +0000 Subject: [PATCH 063/570] Fix a test case in sessionfault.test. No changes to code. FossilOrigin-Name: dc6ecacd7724089a0387e69a0fd5cdbfdd2023f8 --- ext/session/sessionfault.test | 2 +- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index 1444a46b36..d0556ce33f 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -247,7 +247,7 @@ do_faultsim_test 5 -faults oom* -body { foreach c { {DELETE t1 0 .X {t xxx t yyy} {}} {INSERT t1 0 .X {} {t string i 1}} - {UPDATE t1 0 .X {i 20 {} {}} {i 4 i 2}} + {UPDATE t1 0 .X {i 20 i 2} {i 4 {} {}}} } { lappend y $c } if {$x != $y} { error "changeset no good" } } diff --git a/manifest b/manifest index 996459f395..51775aa388 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\scausing\ssqlite3changeset_invert()\sto\seffectively\sdrop\sUPDATE\schanges. -D 2011-07-26T15:50:36.271 +C Fix\sa\stest\scase\sin\ssessionfault.test.\sNo\schanges\sto\scode. +D 2011-07-26T15:57:56.891 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 1e6988b3c11dee9bd5edc0c804bd4468d74a9cdc F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -110,7 +110,7 @@ F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 -F ext/session/sessionfault.test 401045278298a242cbc2e4bc986c102f01ff2180 +F ext/session/sessionfault.test 891453e96630ee2915081487fc4b7226f0aa252f F ext/session/sqlite3session.c 5a50e28759187440805fca653029946311593da6 F ext/session/sqlite3session.h f374c9c4c96e08f67ac418871c29d423245c7673 F ext/session/test_session.c ea4dc9b4a1895c8e6bddcbfe3838d7eb57df2d99 @@ -965,7 +965,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262 -P 110cfd6920cf3011aeaf7e586f8db867bfc69fbb -R 95b1f91b4b1f21686c1d16002cdc06fd +P bb3e65d9724dcecdc54b4c9fb0448f95d14495ff +R 9792f6e7ba4296e8c713a87df4ad910e U dan -Z 326ddfa62484f9d6c6538d0373ca9236 +Z 85a557af61ebafc7cfd33bb00bd9108a diff --git a/manifest.uuid b/manifest.uuid index 94d44ce8ae..6b93cf17ff 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bb3e65d9724dcecdc54b4c9fb0448f95d14495ff \ No newline at end of file +dc6ecacd7724089a0387e69a0fd5cdbfdd2023f8 \ No newline at end of file From 964cbd469beab81aec2c8283ef593f2d36faaf14 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 26 Jul 2011 17:53:53 +0000 Subject: [PATCH 064/570] Fix errors in a comment in sqlite3session.c. No changes to code. FossilOrigin-Name: d5f4c4c0bf0d488db11c6ab0d26ca3554a57d0ff --- ext/session/sqlite3session.c | 8 ++++---- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index b8bcc9b286..778caad591 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2353,11 +2353,11 @@ static int sessionDeleteRow( ** ** UPDATE x SET ** a = CASE WHEN ?2 THEN ?3 ELSE a END, -** b = CASE WHEN ?5 THEN ?6 ELSE a END, -** c = CASE WHEN ?8 THEN ?9 ELSE a END, -** d = CASE WHEN ?11 THEN ?12 ELSE a END +** b = CASE WHEN ?5 THEN ?6 ELSE b END, +** c = CASE WHEN ?8 THEN ?9 ELSE c END, +** d = CASE WHEN ?11 THEN ?12 ELSE d END ** WHERE a = ?1 AND c = ?7 AND (?13 OR -** (?5==0 OR b IS ?4) AND (?11==0 OR b IS ?10) AND +** (?5==0 OR b IS ?4) AND (?11==0 OR d IS ?10) AND ** ) ** ** For each column in the table, there are three variables to bind: diff --git a/manifest b/manifest index 51775aa388..468757b49e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stest\scase\sin\ssessionfault.test.\sNo\schanges\sto\scode. -D 2011-07-26T15:57:56.891 +C Fix\serrors\sin\sa\scomment\sin\ssqlite3session.c.\sNo\schanges\sto\scode. +D 2011-07-26T17:53:53.311 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 1e6988b3c11dee9bd5edc0c804bd4468d74a9cdc F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -111,7 +111,7 @@ F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 891453e96630ee2915081487fc4b7226f0aa252f -F ext/session/sqlite3session.c 5a50e28759187440805fca653029946311593da6 +F ext/session/sqlite3session.c 57d04e1d6a3579e673e61dea29f214fb4e0fc505 F ext/session/sqlite3session.h f374c9c4c96e08f67ac418871c29d423245c7673 F ext/session/test_session.c ea4dc9b4a1895c8e6bddcbfe3838d7eb57df2d99 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -965,7 +965,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262 -P bb3e65d9724dcecdc54b4c9fb0448f95d14495ff -R 9792f6e7ba4296e8c713a87df4ad910e +P dc6ecacd7724089a0387e69a0fd5cdbfdd2023f8 +R 243487bed84c57b1cd5a32970f8d4775 U dan -Z 85a557af61ebafc7cfd33bb00bd9108a +Z 2c93411bbe8d90a5b2b924f24cbf2370 diff --git a/manifest.uuid b/manifest.uuid index 6b93cf17ff..8a22590c14 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dc6ecacd7724089a0387e69a0fd5cdbfdd2023f8 \ No newline at end of file +d5f4c4c0bf0d488db11c6ab0d26ca3554a57d0ff \ No newline at end of file From 7f197bb7b05a5cdd0ec5aa68447266b495d03818 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Aug 2011 21:32:11 +0000 Subject: [PATCH 065/570] Avoid segfaulting on an incremental blob write if SQLITE_ENABLE_PREUPDATE_HOOK set but no pre-update hooks are defined. FossilOrigin-Name: 62c446340475b52b843c0345eda32ebe86fa9159 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbeblob.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 468757b49e..a887475f95 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\serrors\sin\sa\scomment\sin\ssqlite3session.c.\sNo\schanges\sto\scode. -D 2011-07-26T17:53:53.311 +C Avoid\ssegfaulting\son\san\sincremental\sblob\swrite\sif\sSQLITE_ENABLE_PREUPDATE_HOOK\nset\sbut\sno\spre-update\shooks\sare\sdefined. +D 2011-08-03T21:32:11.649 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 1e6988b3c11dee9bd5edc0c804bd4468d74a9cdc F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -255,7 +255,7 @@ F src/vdbe.h 322af148cceef120bb1ec9cff7f122e76abf94da F src/vdbeInt.h 3de6588b36c833969aebab202e1766d586c37ec2 F src/vdbeapi.c ddd061183e2c3015f676e53ee85fcaf306617e8e F src/vdbeaux.c 7d0b75a04ac466d25a90fefd1df83361a2ab0ad7 -F src/vdbeblob.c a547f286b651641bdb43a567af66d0e776a39ea2 +F src/vdbeblob.c fde0374afb0c512614aed191ac2683f6772d2b8f F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114 F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582 @@ -965,7 +965,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262 -P dc6ecacd7724089a0387e69a0fd5cdbfdd2023f8 -R 243487bed84c57b1cd5a32970f8d4775 -U dan -Z 2c93411bbe8d90a5b2b924f24cbf2370 +P d5f4c4c0bf0d488db11c6ab0d26ca3554a57d0ff +R dc4862fa4ca184e0298413704bde1899 +U drh +Z abe606476a76771b05a5d0a0f3902dc5 diff --git a/manifest.uuid b/manifest.uuid index 8a22590c14..492ab34ae1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d5f4c4c0bf0d488db11c6ab0d26ca3554a57d0ff \ No newline at end of file +62c446340475b52b843c0345eda32ebe86fa9159 \ No newline at end of file diff --git a/src/vdbeblob.c b/src/vdbeblob.c index 4dc9ef4fff..2f37ad933b 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -392,7 +392,7 @@ static int blobReadWrite( sqlite3BtreeEnterCursor(p->pCsr); #ifdef SQLITE_ENABLE_PREUPDATE_HOOK - if( xCall==sqlite3BtreePutData ){ + if( xCall==sqlite3BtreePutData && db->xPreUpdateCallback ){ /* If a pre-update hook is registered and this is a write cursor, ** invoke it here. ** From adb96a62e5b03ec4203bee7050cdf71e6b2830df Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 16 Jan 2012 12:33:36 +0000 Subject: [PATCH 066/570] Support building with SQLITE_ENABLE_SESSION under MSVC. FossilOrigin-Name: 2845654d425164de143e82b9fdb255d81a01af56 --- Makefile.msc | 22 +++++++++++++++++++--- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index f40936d915..3c14cc2087 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -178,6 +178,8 @@ TCC = $(TCC) -DSQLITE_TEMP_STORE=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1 # END standard options # BEGIN required Windows option @@ -412,6 +414,9 @@ SRC = $(SRC) \ SRC = $(SRC) \ $(TOP)\ext\rtree\rtree.h \ $(TOP)\ext\rtree\rtree.c +SRC = $(SRC) \ + $(TOP)\ext\session\sqlite3session.h \ + $(TOP)\ext\session\sqlite3session.c # Generated source code files @@ -468,9 +473,11 @@ TESTSRC = \ $(TOP)\src\test_wholenumber.c \ $(TOP)\src\test_wsd.c \ $(TOP)\ext\fts3\fts3_term.c \ - $(TOP)\ext\fts3\fts3_test.c + $(TOP)\ext\fts3\fts3_test.c \ + $(TOP)\ext\session\test_session.c # Source code to the library files needed by the test fixture +# (non-amalgamation) # TESTSRC2 = \ $(TOP)\src\attach.c \ @@ -513,7 +520,14 @@ TESTSRC2 = \ $(TOP)\ext\fts3\fts3_expr.c \ $(TOP)\ext\fts3\fts3_tokenizer.c \ $(TOP)\ext\fts3\fts3_write.c \ - $(TOP)\ext\async\sqlite3async.c + $(TOP)\ext\async\sqlite3async.c \ + $(TOP)\ext\session\sqlite3session.c + +# Source code to the library files needed by the test fixture +# (amalgamation) +# +TESTSRC3 = \ + $(TOP)\ext\session\sqlite3session.c # Header files used by all library source files. # @@ -558,6 +572,8 @@ EXTHDR = $(EXTHDR) \ $(TOP)\ext\icu\sqliteicu.h EXTHDR = $(EXTHDR) \ $(TOP)\ext\rtree\sqlite3rtree.h +EXTHDR = $(EXTHDR) \ + $(TOP)\ext\session\sqlite3session.h # This is the default Makefile target. The objects listed here # are what get build when you type just "make" with no arguments. @@ -944,7 +960,7 @@ TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.lib -TESTFIXTURE_SRC1 = sqlite3.c +TESTFIXTURE_SRC1 = $(TESTSRC3) sqlite3.c !IF $(USE_AMALGAMATION)==0 TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0) !ELSE diff --git a/manifest b/manifest index d6154d7b08..3561babe89 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Update\ssessions\sbranch\swith\slatest\schanges\sfrom\strunk. -D 2012-01-14T13:50:12.463 +C Support\sbuilding\swith\sSQLITE_ENABLE_SESSION\sunder\sMSVC. +D 2012-01-16T12:33:36.900 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 3f79a373e57c3b92dabf76f40b065e719d31ac34 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc dcad80fa69f17d46fe6778ba873fc108ca16298d +F Makefile.msc 340b6d1bb4553c389d6837aa437d7c25dc03f980 F Makefile.vxworks 1deb39c8bb047296c30161ffa10c1b5423e632f9 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 F VERSION af03cd6400f9d71d38bdb7a9d66a1aefdc2f3e0d @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P a9bcb432f58b96f079a73c456efd4851c582221e 88ad2f23c5036cbb4a69b73ce5792bd5c33a9177 -R 30723a7c24a6752d8bfb2c322e9b8748 -U dan -Z 241182607d7d4efdfae3b5115d25b877 +P 01c84fd391a0ca1f5245c7eff0644d0cc6cff86b +R 88d7ca9f3f2aa524ac3a66d4c2e7567b +U mistachkin +Z 171e4d9c94c739b476f164aff1375bac diff --git a/manifest.uuid b/manifest.uuid index 62957ac731..6308588f15 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -01c84fd391a0ca1f5245c7eff0644d0cc6cff86b \ No newline at end of file +2845654d425164de143e82b9fdb255d81a01af56 \ No newline at end of file From 40eaa08620a75a29f4849cd3572e64feaafce5ec Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 28 Sep 2012 12:55:56 +0000 Subject: [PATCH 067/570] Update the sessionfault-9.1 and -9.2 tests to account for the change in version 3.7.11 in which a pending statement no longer blocks ROLLBACK but instead causes the next call on that statement to return SQLITE_ABORT. FossilOrigin-Name: fae9eb197fcef726fd2c7c701afe6805fc008cf9 --- ext/session/sessionfault.test | 8 ++++++-- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index d0556ce33f..f17daccfc7 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -372,7 +372,9 @@ do_test 9.1.prep { } {} faultsim_save_and_close -set answers [list {0 {}} {1 SQLITE_NOMEM} {1 {callback requested query abort}}] +set answers [list {0 {}} {1 SQLITE_NOMEM} \ + {1 {callback requested query abort}} \ + {1 {abort due to ROLLBACK}}] do_faultsim_test 9.1 -faults oom-transient -prep { catch { unset ::c } faultsim_restore_and_reopen @@ -409,7 +411,9 @@ do_test 9.2.prep { } {} faultsim_save_and_close -set answers [list {0 {}} {1 SQLITE_NOMEM} {1 {callback requested query abort}}] +set answers [list {0 {}} {1 SQLITE_NOMEM} \ + {1 {callback requested query abort}} \ + {1 {abort due to ROLLBACK}}] do_faultsim_test 9.2 -faults oom-transient -prep { catch { unset ::c } faultsim_restore_and_reopen diff --git a/manifest b/manifest index e332fe6cdf..2217d6a1bb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\swith\slatest\strunk\schanges. -D 2012-08-31T14:23:16.346 +C Update\sthe\ssessionfault-9.1\sand\s-9.2\stests\sto\saccount\sfor\sthe\schange\sin\nversion\s3.7.11\sin\swhich\sa\spending\sstatement\sno\slonger\sblocks\sROLLBACK\sbut\ninstead\scauses\sthe\snext\scall\son\sthat\sstatement\sto\sreturn\sSQLITE_ABORT. +D 2012-09-28T12:55:56.421 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in abd5c10d21d1395f140d9e50ea999df8fa4d6376 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -109,7 +109,7 @@ F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 -F ext/session/sessionfault.test 891453e96630ee2915081487fc4b7226f0aa252f +F ext/session/sessionfault.test 496291b287ba3c0b14ca2e074425e29cc92a64a6 F ext/session/sqlite3session.c 57d04e1d6a3579e673e61dea29f214fb4e0fc505 F ext/session/sqlite3session.h f374c9c4c96e08f67ac418871c29d423245c7673 F ext/session/test_session.c ea4dc9b4a1895c8e6bddcbfe3838d7eb57df2d99 @@ -1026,7 +1026,7 @@ F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 67d8a99aceb56384a81b3f30d6c71743146d2cc9 -P aa62d6881b5aae64e15dbae70ce8e77bcc2a9f0b 527340abff18aedbcb0f82ac1296a9f548e24ac4 -R ce445dd99f7d73f4997bfaaffd71f58e -U dan -Z b7fa6fd6ef1ab9dd566a694a77a1f165 +P 87995dc9409482f0a7a367bfc51d78ac0f63b8c3 +R 0ffae7a510db2af1076692fe90154443 +U drh +Z a5785b316a6ee7492de59cea784cd09f diff --git a/manifest.uuid b/manifest.uuid index 56b257152a..5fdf4c7f29 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -87995dc9409482f0a7a367bfc51d78ac0f63b8c3 \ No newline at end of file +fae9eb197fcef726fd2c7c701afe6805fc008cf9 \ No newline at end of file From 498dcae0f0fbed1716c822c1abca02bf0eb4d0c0 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 13 Mar 2013 11:42:00 +0000 Subject: [PATCH 068/570] Fix a compiler warning in sqlite3VdbePreUpdateHook(). Add sqlite3session.c to the amalgamation. Fix the Makefile.in to work with sessions. FossilOrigin-Name: e54b0225f226a163ec874df7d4b738efba12b3a7 --- Makefile.in | 20 ++++++++++++++++---- Makefile.msc | 7 ++++++- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/vdbeaux.c | 2 +- tool/mksqlite3c.tcl | 3 +++ 6 files changed, 37 insertions(+), 17 deletions(-) diff --git a/Makefile.in b/Makefile.in index 652928b8cc..634c7a3654 100644 --- a/Makefile.in +++ b/Makefile.in @@ -26,7 +26,8 @@ BCC = @BUILD_CC@ @BUILD_CFLAGS@ # will run on the target platform. (BCC and TCC are usually the # same unless your are cross-compiling.) # -TCC = @CC@ @CPPFLAGS@ @CFLAGS@ -I. -I${TOP}/src -I${TOP}/ext/rtree +TCC = @CC@ @CPPFLAGS@ @CFLAGS@ -I. -I${TOP}/src -I${TOP}/ext/rtree -I${TOP}/ext/icu +TCC += -I${TOP}/ext/fts3 -I${TOP}/ext/async -I${TOP}/ext/session # Define this for the autoconf-based build, so that the code knows it can # include the generated config.h @@ -76,6 +77,7 @@ TEMP_STORE = -DSQLITE_TEMP_STORE=@TEMP_STORE@ # The same set of OMIT and ENABLE flags should be passed to the # LEMON parser generator and the mkkeywordhash tool as well. OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@ +OPT_FEATURE_FLAGS += -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK TCC += $(OPT_FEATURE_FLAGS) @@ -175,7 +177,8 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ - random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \ + random.lo resolve.lo rowset.lo rtree.lo \ + sqlite3session.lo select.lo status.lo \ table.lo tokenize.lo trigger.lo \ update.lo util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ @@ -325,6 +328,10 @@ SRC += \ SRC += \ $(TOP)/ext/rtree/rtree.h \ $(TOP)/ext/rtree/rtree.c +SRC += \ + $(TOP)/ext/session/sqlite3session.c \ + $(TOP)/ext/session/sqlite3session.h + # Generated source code files @@ -384,7 +391,8 @@ TESTSRC = \ $(TOP)/src/test_wholenumber.c \ $(TOP)/src/test_wsd.c \ $(TOP)/ext/fts3/fts3_term.c \ - $(TOP)/ext/fts3/fts3_test.c + $(TOP)/ext/fts3/fts3_test.c \ + $(TOP)/ext/session/test_session.c # Source code to the library files needed by the test fixture # @@ -428,7 +436,8 @@ TESTSRC2 = \ $(TOP)/ext/fts3/fts3_term.c \ $(TOP)/ext/fts3/fts3_tokenizer.c \ $(TOP)/ext/fts3/fts3_write.c \ - $(TOP)/ext/async/sqlite3async.c + $(TOP)/ext/async/sqlite3async.c \ + $(TOP)/ext/session/sqlite3session.c # Header files used by all library source files. # @@ -864,6 +873,9 @@ fts3_write.lo: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR) rtree.lo: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR) $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c +sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR) + $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c + # Rules to build the 'testfixture' application. # diff --git a/Makefile.msc b/Makefile.msc index cc726ae959..a15c755d2e 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -232,6 +232,7 @@ TCC = $(TCC) -I$(TOP)\ext\fts3 RCC = $(RCC) -I$(TOP)\ext\fts3 TCC = $(TCC) -I$(TOP)\ext\rtree RCC = $(RCC) -I$(TOP)\ext\rtree +TCC = $(TCC) -I$(TOP)\ext\session !ENDIF # Define -DNDEBUG to compile without debugging (i.e., for production usage) @@ -488,7 +489,8 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ - random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \ + random.lo resolve.lo rowset.lo rtree.lo \ + sqlite3session.lo select.lo status.lo \ table.lo tokenize.lo trigger.lo \ update.lo util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ @@ -1198,6 +1200,9 @@ fts3_write.lo: $(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR) rtree.lo: $(TOP)\ext\rtree\rtree.c $(HDR) $(EXTHDR) $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\rtree\rtree.c +rtree.lo: $(TOP)\ext\session\sqlite3sesion.c $(HDR) $(EXTHDR) + $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\session\sqlite3session.c + # Rules to build the 'testfixture' application. # diff --git a/manifest b/manifest index 53fce838c5..10fc165232 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Merge\slatest\strunk\schanges\sinto\sthis\sbranch. -D 2013-03-13T06:34:51.061 +C Fix\sa\scompiler\swarning\sin\ssqlite3VdbePreUpdateHook().\nAdd\ssqlite3session.c\sto\sthe\samalgamation.\nFix\sthe\sMakefile.in\sto\swork\swith\ssessions. +D 2013-03-13T11:42:00.694 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f -F Makefile.in 9a804abbd3cae82d196e4d33aba13239e32522a5 +F Makefile.in f33fad60e6fa3cc15f6a39609a256b340a1c12d9 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc 5de508f802789aae3e96d86261c5cf633d67ce00 +F Makefile.msc 29bce8fa86dc10ffeb5ac11537c0e12c3a3e6887 F Makefile.vxworks b18ad88e9a8c6a001f5cf4a389116a4f1a7ab45f F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 F VERSION 6d4f66eaebabc42ef8c2a4d2d0caf4ce7ee81137 @@ -255,7 +255,7 @@ F src/vdbe.c 9e4164ac85aa01e1a563e6c7f565b106ff0bf67b F src/vdbe.h 1223e2548e0970cf96f573ff6b99f804a36ad683 F src/vdbeInt.h 0112cab1c820a599005c6bcc9504bdb17f5dbcdb F src/vdbeapi.c b816227ece97354aee7a741c1fc3c5445202d8bb -F src/vdbeaux.c 684c159170453c8a118786b9c174627ece825f3a +F src/vdbeaux.c b49b277bcac5ac1e14165f13b7cd320b5333f420 F src/vdbeblob.c 11248c6362389569764682eb0f59ce910f3cc381 F src/vdbemem.c 833005f1cbbf447289f1973dba2a0c2228c7b8ab F src/vdbesort.c c61ca318681c0e7267da8be3abfca8469652a7e9 @@ -1022,7 +1022,7 @@ F tool/mkkeywordhash.c bb52064aa614e1426445e4b2b9b00eeecd23cc79 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02 -F tool/mksqlite3c.tcl 589c7f44e990be1b8443cfe4808dce392b0327fa +F tool/mksqlite3c.tcl bb8afe0948d88d5d9e6f80d75f2b89face94af08 F tool/mksqlite3h.tcl 78013ad79a5e492e5f764f3c7a8ef834255061f8 F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795 F tool/mkvsix.tcl 0be7f7a591f1e83f9199cb82911b66668ca484c9 @@ -1051,7 +1051,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 62adb0e0d70e619becb68ffd2625d979bcc777cd 839aa91faf1db7025d90fa3c65e50efb829b053b -R f971c8bcbe5e7e01d3f1960cb48792c9 -U dan -Z 72580c54b4ef9e18ca4a1b86983b9c48 +P d6cd3c780c6bc718d37e0f0b884e3e9a423d57be +R 8d8bef3ec05b88293bab641b3f53c396 +U drh +Z 2a31f3327a39b82b184325a96aea6d38 diff --git a/manifest.uuid b/manifest.uuid index 5a3c033a66..cad3cf8107 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d6cd3c780c6bc718d37e0f0b884e3e9a423d57be \ No newline at end of file +e54b0225f226a163ec874df7d4b738efba12b3a7 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 7a676a2e39..b54d6b918f 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3313,7 +3313,7 @@ void sqlite3VdbePreUpdateHook( preupdate.keyinfo.db = db; preupdate.keyinfo.enc = ENC(db); preupdate.keyinfo.nField = pTab->nCol; - preupdate.keyinfo.aSortOrder = &fakeSortOrder; + preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; preupdate.iKey1 = iKey1; preupdate.iKey2 = iKey2; preupdate.iPKey = pTab->iPKey; diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl index 2c569d7a4e..d08d9d2f1b 100644 --- a/tool/mksqlite3c.tcl +++ b/tool/mksqlite3c.tcl @@ -108,6 +108,7 @@ foreach hdr { parse.h pcache.h rtree.h + sqlite3session.h sqlite3ext.h sqlite3.h sqliteicu.h @@ -319,6 +320,8 @@ foreach file { rtree.c icu.c fts3_icu.c + + sqlite3session.c } { copy_file tsrc/$file } From 8ce2b0956abf53d952ef30c7339095930a707fff Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 13 Mar 2013 12:20:15 +0000 Subject: [PATCH 069/570] Fix main.mk so that it builds the amalgamation correctly. FossilOrigin-Name: 0b84e277245f10f928c010ea5958923681c6d582 --- main.mk | 9 +++++++-- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/main.mk b/main.mk index d5b8d69811..dbd29d0ac7 100644 --- a/main.mk +++ b/main.mk @@ -207,6 +207,9 @@ SRC += \ SRC += \ $(TOP)/ext/rtree/rtree.h \ $(TOP)/ext/rtree/rtree.c +SRC += \ + $(TOP)/ext/session/sqlite3session.c \ + $(TOP)/ext/session/sqlite3session.h # Generated source code files @@ -533,7 +536,8 @@ tclsqlite3: $(TOP)/src/tclsqlite.c libsqlite3.a $(TCCX) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite3 \ $(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB) -sqlite3_analyzer.c: sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl +sqlite3_analyzer.c: sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c \ + $(TOP)/tool/spaceanal.tcl echo "#define TCLSH 2" > $@ cat sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c >> $@ echo "static const char *tclsh_main_loop(void){" >> $@ @@ -581,7 +585,8 @@ test: testfixture$(EXE) sqlite3$(EXE) # threadtest runs a few thread-safety tests that are implemented in C. This # target is invoked by the releasetest.tcl script. # -threadtest3$(EXE): sqlite3.o $(TOP)/test/threadtest3.c $(TOP)/test/tt3_checkpoint.c +threadtest3$(EXE): sqlite3.o $(TOP)/test/threadtest3.c \ + $(TOP)/test/tt3_checkpoint.c $(TCCX) -O2 sqlite3.o $(TOP)/test/threadtest3.c \ -o threadtest3$(EXE) $(THREADLIB) diff --git a/manifest b/manifest index 10fc165232..82a4228fcd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scompiler\swarning\sin\ssqlite3VdbePreUpdateHook().\nAdd\ssqlite3session.c\sto\sthe\samalgamation.\nFix\sthe\sMakefile.in\sto\swork\swith\ssessions. -D 2013-03-13T11:42:00.694 +C Fix\smain.mk\sso\sthat\sit\sbuilds\sthe\samalgamation\scorrectly. +D 2013-03-13T12:20:15.110 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in f33fad60e6fa3cc15f6a39609a256b340a1c12d9 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -115,7 +115,7 @@ F ext/session/sqlite3session.h f374c9c4c96e08f67ac418871c29d423245c7673 F ext/session/test_session.c ea4dc9b4a1895c8e6bddcbfe3838d7eb57df2d99 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 -F main.mk 787401c56823d6cf0d2fa01540d04bd438b11ee5 +F main.mk 9422cb87866650146b89d742c666e8abd5e1ab6a F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac @@ -1051,7 +1051,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P d6cd3c780c6bc718d37e0f0b884e3e9a423d57be -R 8d8bef3ec05b88293bab641b3f53c396 +P e54b0225f226a163ec874df7d4b738efba12b3a7 +R df3120294f1b47f95d03bbfec72e5f33 U drh -Z 2a31f3327a39b82b184325a96aea6d38 +Z 1665add974d8ea78c75d5773b499e48a diff --git a/manifest.uuid b/manifest.uuid index cad3cf8107..6803c7b87d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e54b0225f226a163ec874df7d4b738efba12b3a7 \ No newline at end of file +0b84e277245f10f928c010ea5958923681c6d582 \ No newline at end of file From 38b4daa12227b0628302945f07b8faaf9dafafca Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 13 Mar 2013 19:02:39 +0000 Subject: [PATCH 070/570] Fix typos in MSVC makefile. FossilOrigin-Name: 2d15c2685750b930c5b7e2f06cb056b24a037967 --- Makefile.msc | 3 ++- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index a15c755d2e..dea8ee8cd6 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -233,6 +233,7 @@ RCC = $(RCC) -I$(TOP)\ext\fts3 TCC = $(TCC) -I$(TOP)\ext\rtree RCC = $(RCC) -I$(TOP)\ext\rtree TCC = $(TCC) -I$(TOP)\ext\session +RCC = $(RCC) -I$(TOP)\ext\session !ENDIF # Define -DNDEBUG to compile without debugging (i.e., for production usage) @@ -1200,7 +1201,7 @@ fts3_write.lo: $(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR) rtree.lo: $(TOP)\ext\rtree\rtree.c $(HDR) $(EXTHDR) $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\rtree\rtree.c -rtree.lo: $(TOP)\ext\session\sqlite3sesion.c $(HDR) $(EXTHDR) +sqlite3session.lo: $(TOP)\ext\session\sqlite3sesion.c $(HDR) $(EXTHDR) $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\session\sqlite3session.c diff --git a/manifest b/manifest index 82a4228fcd..d5d4db2ad3 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Fix\smain.mk\sso\sthat\sit\sbuilds\sthe\samalgamation\scorrectly. -D 2013-03-13T12:20:15.110 +C Fix\stypos\sin\sMSVC\smakefile. +D 2013-03-13T19:02:39.185 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in f33fad60e6fa3cc15f6a39609a256b340a1c12d9 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc 29bce8fa86dc10ffeb5ac11537c0e12c3a3e6887 +F Makefile.msc 50121cf9f55dd2bd06ed70007c9c48d89f2c230b F Makefile.vxworks b18ad88e9a8c6a001f5cf4a389116a4f1a7ab45f F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 F VERSION 6d4f66eaebabc42ef8c2a4d2d0caf4ce7ee81137 @@ -1051,7 +1051,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P e54b0225f226a163ec874df7d4b738efba12b3a7 -R df3120294f1b47f95d03bbfec72e5f33 -U drh -Z 1665add974d8ea78c75d5773b499e48a +P 0b84e277245f10f928c010ea5958923681c6d582 +R 8936b43e7cb6239a57717295926fbe09 +U mistachkin +Z 90881652b49d2ff478c663d912137eaa diff --git a/manifest.uuid b/manifest.uuid index 6803c7b87d..c29d8d46f9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0b84e277245f10f928c010ea5958923681c6d582 \ No newline at end of file +2d15c2685750b930c5b7e2f06cb056b24a037967 \ No newline at end of file From e191e2c6d0cbc85e07f57b4dbd10e3a2b94c470e Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 19 Mar 2013 15:23:18 +0000 Subject: [PATCH 071/570] Include the sqlite3session.h header file in with sqlite3.h. Make sure the session APIs are all public. FossilOrigin-Name: ec490336bc6629d3910667ece1bbc4685a199546 --- Makefile.in | 5 ++++- Makefile.msc | 3 +++ main.mk | 6 +++++- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- tool/mksqlite3c.tcl | 5 +++-- tool/mksqlite3h.tcl | 10 ++++++++-- 7 files changed, 34 insertions(+), 17 deletions(-) diff --git a/Makefile.in b/Makefile.in index 634c7a3654..0ea9498be0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -528,6 +528,8 @@ sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl + cp tsrc/shell.c tsrc/sqlite3ext.h . + cp $(TOP)/ext/session/sqlite3session.h . tclsqlite3.c: sqlite3.c echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c @@ -890,7 +892,8 @@ TESTFIXTURE_FLAGS += -DBUILD_sqlite TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la TESTFIXTURE_SRC1 = sqlite3.c -TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c $(TESTFIXTURE_SRC$(USE_AMALGAMATION)) +TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c +TESTFIXTURE_SRC += $(TESTFIXTURE_SRC$(USE_AMALGAMATION)) testfixture$(TEXE): $(TESTFIXTURE_SRC) $(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \ diff --git a/Makefile.msc b/Makefile.msc index 00e4ffbe8d..8f34c6cc2d 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -849,6 +849,9 @@ sqlite3.exe: $(TOP)\src\shell.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h sqlite3.c: .target_source $(TOP)\tool\mksqlite3c.tcl $(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl + copy tsrc\shell.c . + copy tsrc\sqlite3ext.h . + copy $(TOP)\ext\session\sqlite3session.h . sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl $(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl diff --git a/main.mk b/main.mk index dbd29d0ac7..5faf2fb8e9 100644 --- a/main.mk +++ b/main.mk @@ -391,6 +391,8 @@ target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl tclsh $(TOP)/tool/mksqlite3c.tcl + cp tsrc/shell.c tsrc/sqlite3ext.h . + cp $(TOP)/ext/session/sqlite3session.h . echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c cat sqlite3.c >>tclsqlite3.c echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c @@ -558,9 +560,11 @@ testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c $(TESTSRC) $(TESTSRC2) $(TOP)/src/tclsqlite.c \ -o testfixture$(EXE) $(LIBTCL) libsqlite3.a $(THREADLIB) -amalgamation-testfixture$(EXE): sqlite3.c $(TESTSRC) $(TOP)/src/tclsqlite.c +amalgamation-testfixture$(EXE): sqlite3.c $(TESTSRC) $(TOP)/src/tclsqlite.c \ + $(TOP)/ext/session/test_session.c $(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \ $(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c \ + $(TOP)/ext/session/test_session.c \ -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c diff --git a/manifest b/manifest index 60723169d4..7c7192ad81 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Adjust\sthe\sMSVC\smakefile\sso\sthat\sit\scorrectly\shandles\sthe\ssessions\nextension\sbeing\sincluded\sin\sthe\samalgamation.\s\sImport\sthe\stest\scase\nchanges\sthat\sappeared\sin\s3.7.16\sfinal. -D 2013-03-18T16:24:33.543 +C Include\sthe\ssqlite3session.h\sheader\sfile\sin\swith\ssqlite3.h.\s\sMake\ssure\nthe\ssession\sAPIs\sare\sall\spublic. +D 2013-03-19T15:23:18.846 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f -F Makefile.in f33fad60e6fa3cc15f6a39609a256b340a1c12d9 +F Makefile.in 174bfca74e57f38699e3412a984f6b38106750fa F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc c56c19e93d5de6dde495d68d28d8455a5bab9917 +F Makefile.msc 0ad7d4278a3b7e0c56d3ca7cc607b34acc1df516 F Makefile.vxworks b18ad88e9a8c6a001f5cf4a389116a4f1a7ab45f F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 F VERSION 6d4f66eaebabc42ef8c2a4d2d0caf4ce7ee81137 @@ -115,7 +115,7 @@ F ext/session/sqlite3session.h f374c9c4c96e08f67ac418871c29d423245c7673 F ext/session/test_session.c ea4dc9b4a1895c8e6bddcbfe3838d7eb57df2d99 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 -F main.mk 9422cb87866650146b89d742c666e8abd5e1ab6a +F main.mk 01f02b625cc1b8609690aaddb00e2fbb1edbeec5 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac @@ -1022,8 +1022,8 @@ F tool/mkkeywordhash.c bb52064aa614e1426445e4b2b9b00eeecd23cc79 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02 -F tool/mksqlite3c.tcl bb8afe0948d88d5d9e6f80d75f2b89face94af08 -F tool/mksqlite3h.tcl 78013ad79a5e492e5f764f3c7a8ef834255061f8 +F tool/mksqlite3c.tcl aa76553fe5f5fc93772f3bb1d1626421b454e7e5 +F tool/mksqlite3h.tcl 280a819542c2a001c342e4bfe829974a76cb449e F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795 F tool/mkvsix.tcl 0be7f7a591f1e83f9199cb82911b66668ca484c9 F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091 @@ -1051,7 +1051,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 2d15c2685750b930c5b7e2f06cb056b24a037967 66d5f2b76750f3520eb7a495f6247206758f5b90 -R 2176dc6cddaef86d42b3729c5996485e +P 9bac09a99aef5f18386037b409869d760c520d53 +R f21fcc9e1243effe28692f83a9850041 U drh -Z 1f183a91c30c6bc258b1a36f7025012a +Z b7b8384c096e1370a180493dde9bfbdb diff --git a/manifest.uuid b/manifest.uuid index 742ad126ba..590d021b04 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9bac09a99aef5f18386037b409869d760c520d53 \ No newline at end of file +ec490336bc6629d3910667ece1bbc4685a199546 \ No newline at end of file diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl index d08d9d2f1b..81bcf07bcf 100644 --- a/tool/mksqlite3c.tcl +++ b/tool/mksqlite3c.tcl @@ -23,7 +23,7 @@ # # Begin by reading the "sqlite3.h" header file. Extract the version number -# from in this file. The versioon number is needed to generate the header +# from in this file. The version number is needed to generate the header # comment of the amalgamation. # if {[lsearch $argv --nostatic]>=0} { @@ -121,6 +121,7 @@ foreach hdr { set available_hdr($hdr) 1 } set available_hdr(sqliteInt.h) 0 +set available_hdr(sqlite3session.h) 0 # 78 stars used for comment formatting. set s78 \ @@ -182,7 +183,7 @@ proc copy_file {filename} { if {[regexp $declpattern $line all funcname]} { # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions. # so that linkage can be modified at compile-time. - if {[regexp {^sqlite3_} $funcname]} { + if {[regexp {^sqlite3(session)?_} $funcname]} { puts $out "SQLITE_API $line" } else { puts $out "SQLITE_PRIVATE $line" diff --git a/tool/mksqlite3h.tcl b/tool/mksqlite3h.tcl index f68f61a368..5241f8dc00 100644 --- a/tool/mksqlite3h.tcl +++ b/tool/mksqlite3h.tcl @@ -68,9 +68,15 @@ set declpattern {^ *[a-zA-Z][a-zA-Z_0-9 ]+ \**sqlite3_[_a-zA-Z0-9]+\(} # Force the output to use unix line endings, even on Windows. fconfigure stdout -translation lf -# Process the src/sqlite.h.in ext/rtree/sqlite3rtree.h files. +set filelist [subst { + $TOP/src/sqlite.h.in + $TOP/ext/rtree/sqlite3rtree.h + $TOP/ext/session/sqlite3session.h +}] + +# Process the source files. # -foreach file [list $TOP/src/sqlite.h.in $TOP/ext/rtree/sqlite3rtree.h] { +foreach file $filelist { set in [open $file] while {![eof $in]} { From 1ffe7c7fab56b93f291abfe474a6a1995421e5fb Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 19 Mar 2013 17:10:10 +0000 Subject: [PATCH 072/570] Also export the sqlite3changeset interfaces in the amalgamated version of the sessions extension. FossilOrigin-Name: 5b399f2bc43612c52ea2289001d852d7ba6f9750 --- ext/session/sqlite3session.c | 4 ++-- manifest | 16 ++++++++-------- manifest.uuid | 2 +- tool/mksqlite3c.tcl | 2 +- tool/symbols.sh | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 778caad591..15865e6b90 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1125,7 +1125,7 @@ int sqlite3session_create( ** Free the list of table objects passed as the first argument. The contents ** of the changed-rows hash tables are also deleted. */ -void sessionDeleteTable(SessionTable *pList){ +static void sessionDeleteTable(SessionTable *pList){ SessionTable *pNext; SessionTable *pTab; @@ -3074,7 +3074,7 @@ static int sessionChangeMerge( ** Add all changes in the changeset passed via the first two arguments to ** hash tables. */ -int sessionConcatChangeset( +static int sessionConcatChangeset( int nChangeset, /* Number of bytes in pChangeset */ void *pChangeset, /* Changeset buffer */ SessionTable **ppTabList /* IN/OUT: List of table objects */ diff --git a/manifest b/manifest index 7c7192ad81..d3b33519de 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Include\sthe\ssqlite3session.h\sheader\sfile\sin\swith\ssqlite3.h.\s\sMake\ssure\nthe\ssession\sAPIs\sare\sall\spublic. -D 2013-03-19T15:23:18.846 +C Also\sexport\sthe\ssqlite3changeset\sinterfaces\sin\sthe\samalgamated\sversion\sof\nthe\ssessions\sextension. +D 2013-03-19T17:10:10.376 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 174bfca74e57f38699e3412a984f6b38106750fa F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -110,7 +110,7 @@ F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 496291b287ba3c0b14ca2e074425e29cc92a64a6 -F ext/session/sqlite3session.c 57d04e1d6a3579e673e61dea29f214fb4e0fc505 +F ext/session/sqlite3session.c 7d7ca693bd581243835ee47b41b491bd909a26f4 F ext/session/sqlite3session.h f374c9c4c96e08f67ac418871c29d423245c7673 F ext/session/test_session.c ea4dc9b4a1895c8e6bddcbfe3838d7eb57df2d99 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -1022,7 +1022,7 @@ F tool/mkkeywordhash.c bb52064aa614e1426445e4b2b9b00eeecd23cc79 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02 -F tool/mksqlite3c.tcl aa76553fe5f5fc93772f3bb1d1626421b454e7e5 +F tool/mksqlite3c.tcl 521b39c2d2987c4257919b97a3cfb3bd4a394bf1 F tool/mksqlite3h.tcl 280a819542c2a001c342e4bfe829974a76cb449e F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795 F tool/mkvsix.tcl 0be7f7a591f1e83f9199cb82911b66668ca484c9 @@ -1045,13 +1045,13 @@ F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d -F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f +F tool/symbols.sh c5a617b8c61a0926747a56c65f5671ef8ac0e148 F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 9bac09a99aef5f18386037b409869d760c520d53 -R f21fcc9e1243effe28692f83a9850041 +P ec490336bc6629d3910667ece1bbc4685a199546 +R feb292609e6100e1f2edd6a494c7d523 U drh -Z b7b8384c096e1370a180493dde9bfbdb +Z 6c74b8c2b0cc569ec1ecb44db9287f05 diff --git a/manifest.uuid b/manifest.uuid index 590d021b04..69c2acc8d3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ec490336bc6629d3910667ece1bbc4685a199546 \ No newline at end of file +5b399f2bc43612c52ea2289001d852d7ba6f9750 \ No newline at end of file diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl index 81bcf07bcf..4058631bbf 100644 --- a/tool/mksqlite3c.tcl +++ b/tool/mksqlite3c.tcl @@ -183,7 +183,7 @@ proc copy_file {filename} { if {[regexp $declpattern $line all funcname]} { # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions. # so that linkage can be modified at compile-time. - if {[regexp {^sqlite3(session)?_} $funcname]} { + if {[regexp {^sqlite3[a-z]*_} $funcname]} { puts $out "SQLITE_API $line" } else { puts $out "SQLITE_PRIVATE $line" diff --git a/tool/symbols.sh b/tool/symbols.sh index befffce5c4..5e80078fa3 100644 --- a/tool/symbols.sh +++ b/tool/symbols.sh @@ -10,7 +10,7 @@ gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \ -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \ -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \ -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \ - -DSQLITE_ENABLE_ICU \ + -DSQLITE_ENABLE_ICU -DSQLITE_ENABLE_PREUPDATE_HOOK -DSQLITE_ENABLE_SESSION \ sqlite3.c nm sqlite3.o | grep ' [TD] ' | sort -k 3 From eeeee7f55d25594f8025f637aa343a449e8b6bb9 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 10 Apr 2013 15:01:36 +0000 Subject: [PATCH 073/570] Designate the beginning and the end of the sqlite3session.h file in the constructed sqlite3.h file. FossilOrigin-Name: 53f5be74327162a2bd25a91eaf7c91b126294727 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/mksqlite3h.tcl | 6 ++++++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 0c1f9bd6b6..59b640372d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\schanges\sfor\sthe\s3.7.16.1\srelease\scandidate\sinto\sthe\ssessions\sbranch. -D 2013-03-28T01:19:26.359 +C Designate\sthe\sbeginning\sand\sthe\send\sof\sthe\ssqlite3session.h\sfile\sin\sthe\nconstructed\ssqlite3.h\sfile. +D 2013-04-10T15:01:36.565 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 174bfca74e57f38699e3412a984f6b38106750fa F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1026,7 +1026,7 @@ F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02 F tool/mksqlite3c.tcl 521b39c2d2987c4257919b97a3cfb3bd4a394bf1 -F tool/mksqlite3h.tcl 280a819542c2a001c342e4bfe829974a76cb449e +F tool/mksqlite3h.tcl c26c2c00f6402dff490b9d088b35022a65079f9b F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795 F tool/mkvsix.tcl 0be7f7a591f1e83f9199cb82911b66668ca484c9 F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091 @@ -1054,7 +1054,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 5b399f2bc43612c52ea2289001d852d7ba6f9750 274d2a22660c7b34b8bbd85f3c29cbafbcb1b4e7 -R b02a4b1d8d4060ecab7247b46b1af3cb +P ee35a89712b8ea9f4e70d61a29150348896b519f +R 100e7ec13abd2ea8455e764a279a1723 U drh -Z 8200523e839d9fbff750764d761a16eb +Z 4925298600da5fcf8376b1bdce3109e3 diff --git a/manifest.uuid b/manifest.uuid index 1cd07d6476..1c9ae4b351 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ee35a89712b8ea9f4e70d61a29150348896b519f \ No newline at end of file +53f5be74327162a2bd25a91eaf7c91b126294727 \ No newline at end of file diff --git a/tool/mksqlite3h.tcl b/tool/mksqlite3h.tcl index 5241f8dc00..55e7ad287e 100644 --- a/tool/mksqlite3h.tcl +++ b/tool/mksqlite3h.tcl @@ -78,6 +78,9 @@ set filelist [subst { # foreach file $filelist { set in [open $file] + if {![regexp {sqlite.h.in} $file]} { + puts "/******** Begin file [file tail $file] *********/" + } while {![eof $in]} { set line [gets $in] @@ -109,4 +112,7 @@ foreach file $filelist { puts $line } close $in + if {![regexp {sqlite.h.in} $file]} { + puts "/******** End of [file tail $file] *********/" + } } From 73c4041b4303308b607179d917411941f74e9d1f Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 11 Apr 2013 00:45:28 +0000 Subject: [PATCH 074/570] Correct minor typo in two regular expressions. FossilOrigin-Name: f1eed92b7b0ef4ee22a11d8bb4f9a572b56ce019 --- manifest | 14 +++++++------- manifest.uuid | 2 +- tool/mksqlite3h.tcl | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 59b640372d..97541883c8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Designate\sthe\sbeginning\sand\sthe\send\sof\sthe\ssqlite3session.h\sfile\sin\sthe\nconstructed\ssqlite3.h\sfile. -D 2013-04-10T15:01:36.565 +C Correct\sminor\stypo\sin\stwo\sregular\sexpressions. +D 2013-04-11T00:45:28.510 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 174bfca74e57f38699e3412a984f6b38106750fa F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1026,7 +1026,7 @@ F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02 F tool/mksqlite3c.tcl 521b39c2d2987c4257919b97a3cfb3bd4a394bf1 -F tool/mksqlite3h.tcl c26c2c00f6402dff490b9d088b35022a65079f9b +F tool/mksqlite3h.tcl 2d0f1b3768f8d000b7881217d5fd4c776eb27467 F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795 F tool/mkvsix.tcl 0be7f7a591f1e83f9199cb82911b66668ca484c9 F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091 @@ -1054,7 +1054,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P ee35a89712b8ea9f4e70d61a29150348896b519f -R 100e7ec13abd2ea8455e764a279a1723 -U drh -Z 4925298600da5fcf8376b1bdce3109e3 +P 53f5be74327162a2bd25a91eaf7c91b126294727 +R 135af717c2fd2e17b5a8c6896e5cb14f +U mistachkin +Z b1ea33e149cde9618b3874273f57fbc4 diff --git a/manifest.uuid b/manifest.uuid index 1c9ae4b351..642c124c19 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -53f5be74327162a2bd25a91eaf7c91b126294727 \ No newline at end of file +f1eed92b7b0ef4ee22a11d8bb4f9a572b56ce019 \ No newline at end of file diff --git a/tool/mksqlite3h.tcl b/tool/mksqlite3h.tcl index 55e7ad287e..323111bb30 100644 --- a/tool/mksqlite3h.tcl +++ b/tool/mksqlite3h.tcl @@ -78,7 +78,7 @@ set filelist [subst { # foreach file $filelist { set in [open $file] - if {![regexp {sqlite.h.in} $file]} { + if {![regexp {sqlite\.h\.in} $file]} { puts "/******** Begin file [file tail $file] *********/" } while {![eof $in]} { @@ -112,7 +112,7 @@ foreach file $filelist { puts $line } close $in - if {![regexp {sqlite.h.in} $file]} { + if {![regexp {sqlite\.h\.in} $file]} { puts "/******** End of [file tail $file] *********/" } } From 7f6e147a5105607c07a229433fae3a33588be247 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 11 Apr 2013 19:04:20 +0000 Subject: [PATCH 075/570] Increase the version number to 3.7.16.2 and cherrypick the fix for ticket [7ff3120e4fa54abb55]. This check-in is a release candidate. FossilOrigin-Name: 86f26f9152988e47d7e1cfcca9eedf5e6265a225 --- VERSION | 2 +- configure | 18 +++++++++--------- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- src/os_win.c | 2 +- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/VERSION b/VERSION index 9efca4c4be..d225ed60b2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.7.16.1 +3.7.16.2 diff --git a/configure b/configure index ddd6364831..88939d6087 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.62 for sqlite 3.7.16.1. +# Generated by GNU Autoconf 2.62 for sqlite 3.7.16.2. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. @@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' -PACKAGE_VERSION='3.7.16.1' -PACKAGE_STRING='sqlite 3.7.16.1' +PACKAGE_VERSION='3.7.16.2' +PACKAGE_STRING='sqlite 3.7.16.2' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. @@ -1484,7 +1484,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sqlite 3.7.16.1 to adapt to many kinds of systems. +\`configure' configures sqlite 3.7.16.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1549,7 +1549,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.7.16.1:";; + short | recursive ) echo "Configuration of sqlite 3.7.16.2:";; esac cat <<\_ACEOF @@ -1665,7 +1665,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.7.16.1 +sqlite configure 3.7.16.2 generated by GNU Autoconf 2.62 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1679,7 +1679,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sqlite $as_me 3.7.16.1, which was +It was created by sqlite $as_me 3.7.16.2, which was generated by GNU Autoconf 2.62. Invocation command line was $ $0 $@ @@ -14032,7 +14032,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sqlite $as_me 3.7.16.1, which was +This file was extended by sqlite $as_me 3.7.16.2, which was generated by GNU Autoconf 2.62. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14085,7 +14085,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ -sqlite config.status 3.7.16.1 +sqlite config.status 3.7.16.2 configured by $0, generated by GNU Autoconf 2.62, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/manifest b/manifest index 5cf11cc2fb..96c0f8867c 100644 --- a/manifest +++ b/manifest @@ -1,12 +1,12 @@ -C Version\s3.7.16.1 -D 2013-03-29T13:44:34.265 +C Increase\sthe\sversion\snumber\sto\s3.7.16.2\sand\scherrypick\sthe\nfix\sfor\sticket\s[7ff3120e4fa54abb55].\s\sThis\scheck-in\sis\sa\srelease\ncandidate. +D 2013-04-11T19:04:20.543 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in df3e48659d80e1b7765785d8d66c86b320f72cc7 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.msc 0c1abc21c8deefc88e8a32ad6a07e5f96e158761 F Makefile.vxworks b18ad88e9a8c6a001f5cf4a389116a4f1a7ab45f F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 -F VERSION 05604ccde96fe1b37f922eddbdcb5654308261db +F VERSION 0dee4d2e0c64791ff0085277424fb5c07d79fc9a F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F addopcodes.awk 17dc593f791f874d2c23a0f9360850ded0286531 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 @@ -15,7 +15,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.h.in 0921066a13130082764ab4ab6456f7b5bebe56de F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 -F configure 2f9994fd2e2005753809a2246c7a0816c80b2d2f x +F configure 1a5f411b3c5053495a161609c274393281db12cc x F configure.ac 81c43d151d0b0e406be056394cc9ff4cb3fd0444 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1 @@ -161,7 +161,7 @@ F src/os.c e1acdc09ff3ac2412945cca9766e2dcf4675f31c F src/os.h 027491c77d2404c0a678bb3fb06286f331eb9b57 F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_unix.c 21a36fa0b3753609b6606b30d9338d4bb6b24696 -F src/os_win.c 9fe5356f943425ab8431237bd3a4297044928b70 +F src/os_win.c c96990935e7fd799b43a7f0ee74798f45f06e21a F src/pager.c 3e9a15939684b0af441325f05335331b15979c9d F src/pager.h 1109a06578ec5574dc2c74cf8d9f69daf36fe3e0 F src/parse.y 5d5e12772845805fdfeb889163516b84fbb9ae95 @@ -1041,10 +1041,10 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 39534b4baa53b9360696a9d5ee8cc2108af34592 -R e8e4e98970281a95c0de62c6e5f4d562 -T +bgcolor * #d0c0ff -T +sym-release * -T +sym-version-3.7.16.1 * +P 527231bc67285f01fb18d4451b28f61da3c4e39d +R c66fa2b9be1b92880a65bec11685cd9d +T *branch * branch-3.7.16 +T *sym-branch-3.7.16 * +T -sym-trunk * U drh -Z 17d1076ce5eb9d83e75734278cd22a73 +Z 2720d0b49f6dbe5c13feb9b59916963e diff --git a/manifest.uuid b/manifest.uuid index 68abab9466..8bc1952ae9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -527231bc67285f01fb18d4451b28f61da3c4e39d \ No newline at end of file +86f26f9152988e47d7e1cfcca9eedf5e6265a225 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index 58ba25f302..4fb6b02a86 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -2641,7 +2641,7 @@ static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ rc = 1; OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc)); }else{ - rc = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0); + rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0); if( rc ){ winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); } From 226fb534ddaaf97e22cbe3ef429adf14000900b5 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 12 Apr 2013 11:52:43 +0000 Subject: [PATCH 076/570] Version 3.7.16.2 FossilOrigin-Name: cbea02d93865ce0e06789db95fd9168ebac970c7 --- manifest | 14 +++++++------- manifest.uuid | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 96c0f8867c..86f1645ca1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Increase\sthe\sversion\snumber\sto\s3.7.16.2\sand\scherrypick\sthe\nfix\sfor\sticket\s[7ff3120e4fa54abb55].\s\sThis\scheck-in\sis\sa\srelease\ncandidate. -D 2013-04-11T19:04:20.543 +C Version\s3.7.16.2 +D 2013-04-12T11:52:43.886 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in df3e48659d80e1b7765785d8d66c86b320f72cc7 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1041,10 +1041,10 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 527231bc67285f01fb18d4451b28f61da3c4e39d +P 86f26f9152988e47d7e1cfcca9eedf5e6265a225 R c66fa2b9be1b92880a65bec11685cd9d -T *branch * branch-3.7.16 -T *sym-branch-3.7.16 * -T -sym-trunk * +T +bgcolor * #d0c0ff +T +sym-release * +T +sym-version-3.7.16.2 * U drh -Z 2720d0b49f6dbe5c13feb9b59916963e +Z daf56eb23d2f90e92e4839bc9c04cfb7 diff --git a/manifest.uuid b/manifest.uuid index 8bc1952ae9..af054d5354 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -86f26f9152988e47d7e1cfcca9eedf5e6265a225 \ No newline at end of file +cbea02d93865ce0e06789db95fd9168ebac970c7 \ No newline at end of file From 35e2858e980a5c45d37eadc8ec3cb341ff1ed363 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 2 Jul 2013 20:23:40 +0000 Subject: [PATCH 077/570] Fixes for the sessions module so that it works with sqlite3_extended_error_codes() set. FossilOrigin-Name: c2972b6aed23f6c76a289534de9ea4732a48f40e --- ext/session/sqlite3session.c | 6 +++--- manifest | 18 +++++++++--------- manifest.uuid | 2 +- test/permutations.test | 8 ++++++++ test/session.test | 3 +++ 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 15865e6b90..aa0c4b59db 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2749,7 +2749,7 @@ static int sessionApplyOneOp( rc = sessionConflictHandler( SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry ); - }else if( rc==SQLITE_CONSTRAINT ){ + }else if( (rc&0xff)==SQLITE_CONSTRAINT ){ rc = sessionConflictHandler( SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0 ); @@ -2788,7 +2788,7 @@ static int sessionApplyOneOp( SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry ); - }else if( rc==SQLITE_CONSTRAINT ){ + }else if( (rc&0xff)==SQLITE_CONSTRAINT ){ /* This is always a CONSTRAINT conflict. */ rc = sessionConflictHandler( SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0 @@ -2802,7 +2802,7 @@ static int sessionApplyOneOp( sqlite3_step(p->pInsert); rc = sqlite3_reset(p->pInsert); - if( rc==SQLITE_CONSTRAINT ){ + if( (rc&0xff)==SQLITE_CONSTRAINT ){ rc = sessionConflictHandler( SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, pbReplace ); diff --git a/manifest b/manifest index cb4dedd666..20f746c129 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Bring\sthe\ssessions\sbranch\sup-to-date\swith\sall\sthe\slatest\strunk\schanges. -D 2013-06-26T13:31:50.503 +C Fixes\sfor\sthe\ssessions\smodule\sso\sthat\sit\sworks\swith\ssqlite3_extended_error_codes()\sset. +D 2013-07-02T20:23:40.233 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in aff38bc64c582dd147f18739532198372587b0f0 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -144,7 +144,7 @@ F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 496291b287ba3c0b14ca2e074425e29cc92a64a6 -F ext/session/sqlite3session.c 7d7ca693bd581243835ee47b41b491bd909a26f4 +F ext/session/sqlite3session.c c0867804cc86b219c3905c0cd313408d11f7a409 F ext/session/sqlite3session.h f374c9c4c96e08f67ac418871c29d423245c7673 F ext/session/test_session.c 23eddaf713708ae063d278ec6297652e3672dc38 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -721,7 +721,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0 F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16 F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/percentile.test 4614301e38398df7fdd5f28f4ed8f272b328251b -F test/permutations.test 17f03ab6fc174c910c6eb86761d5ba60b93ad3b5 +F test/permutations.test 742b8005bb3c782797a20beccdbe213ef52531fb F test/pragma.test 5e7de6c32a5d764f09437d2025f07e4917b9e178 F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 @@ -773,7 +773,7 @@ F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977 F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394 F test/selectE.test fc02a1eb04c8eb537091482644b7d778ae8759b7 F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118 -F test/session.test c1a17c11ef7d01c24fe2b9f7871190d949a8e718 +F test/session.test 082dea459efc76e2a527b8ee9ff74d76e63ea7b6 F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746 F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879 F test/shared3.test ebf77f023f4bdaa8f74f65822b559e86ce5c6257 @@ -1110,7 +1110,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P fc88f7311ba888015634b89b5909890208f543f5 bd4267f17bbf5d01fb3f12a5a06e94fcbcbd785c -R fbcf046d813fd5b4194215d3a88e6121 -U drh -Z 65f93ab590b102a4bb6eff5ef529fe8b +P 086a127236ee99d67513490fb7b5549e8b752c44 +R 2763382f3d6cfe76b83308c186ebd5fb +U dan +Z 3d139fb0da074f52216dcf16de48044b diff --git a/manifest.uuid b/manifest.uuid index bb570b6c5d..728ff221c4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -086a127236ee99d67513490fb7b5549e8b752c44 \ No newline at end of file +c2972b6aed23f6c76a289534de9ea4732a48f40e \ No newline at end of file diff --git a/test/permutations.test b/test/permutations.test index bb72596af4..cd55406fa7 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -878,6 +878,14 @@ test_suite "session" -description { All session module related tests. } -files [glob -nocomplain $::testdir/../ext/session/*.test] +test_suite "session_eec" -description { + All session module related tests with sqlite3_extended_result_codes() set. +} -files [ + glob -nocomplain $::testdir/../ext/session/*.test +] -dbconfig { + sqlite3_extended_result_codes $::dbhandle 1 +} + test_suite "no_optimization" -description { Run test scripts with optimizations disabled using the sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS) interface. diff --git a/test/session.test b/test/session.test index bf159c3b22..85ac056cdd 100644 --- a/test/session.test +++ b/test/session.test @@ -12,6 +12,9 @@ set testdir [file dirname $argv0] source $testdir/permutations.test ifcapable session { + # First run tests with sqlite3_extended_error_codes() set, then + # again with it clear. + run_test_suite session_eec run_test_suite session } From cb3e4b797ed2144ec3af50113833f597006b1ed8 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 3 Jul 2013 19:53:05 +0000 Subject: [PATCH 078/570] Experimental change to the handling of foreign key constraint violations when applying a changeset: all foreign keys, immediate and deferred, are deferred until the end of the transaction (or sub-transaction) opened by the sqlite3changeset_apply(). A single call to the conflict-handler (if any) is made if any FK constraint violations are still present in the database at this point. The conflict-handler may choose to rollback the changeset, or to apply it, constraint violations and all. FossilOrigin-Name: 1d44e5d3c2b1dc958442f9114a960b256e002ed3 --- ext/session/session1.test | 4 +- ext/session/session9.test | 134 ++++++++++++++++++++++ ext/session/sqlite3session.c | 41 ++++++- ext/session/sqlite3session.h | 42 ++++++- ext/session/test_session.c | 212 ++++++++++++++++++----------------- manifest | 37 +++--- manifest.uuid | 2 +- src/fkey.c | 6 +- src/main.c | 2 + src/pragma.c | 15 +++ src/sqlite.h.in | 2 + src/sqliteInt.h | 3 + src/vdbe.c | 13 ++- src/vdbeInt.h | 1 + src/vdbeapi.c | 6 +- src/vdbeaux.c | 7 +- 16 files changed, 391 insertions(+), 136 deletions(-) create mode 100644 ext/session/session9.test diff --git a/ext/session/session1.test b/ext/session/session1.test index 7ef33e7fce..e47fb3e845 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -264,12 +264,12 @@ do_conflict_test 3.2.3 -tables t2 -sql { DELETE FROM t2 WHERE a = 3; DELETE FROM t2 WHERE a = 4; } -conflicts { - {DELETE t2 CONSTRAINT {i 1 t one}} {DELETE t2 NOTFOUND {i 3 t three}} {DELETE t2 DATA {i 4 t four} {i 4 t five}} + {FOREIGN_KEY 1} } do_execsql_test 3.2.4 "SELECT * FROM t2" {} -do_db2_test 3.2.5 "SELECT * FROM t2" {1 one 4 five} +do_db2_test 3.2.5 "SELECT * FROM t2" {4 five} # Test UPDATE changesets. # diff --git a/ext/session/session9.test b/ext/session/session9.test new file mode 100644 index 0000000000..35d8e876c9 --- /dev/null +++ b/ext/session/session9.test @@ -0,0 +1,134 @@ +# 2013 July 04 +# +# 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 tests that the sessions module handles foreign key constraint +# violations when applying changesets as required. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} +set testprefix session9 + + +#-------------------------------------------------------------------- +# + +proc populate_db {} { + drop_all_tables + execsql { + PRAGMA foreign_keys = 1; + CREATE TABLE p1(a PRIMARY KEY, b); + CREATE TABLE c1(a PRIMARY KEY, b REFERENCES p1); + CREATE TABLE c2(a PRIMARY KEY, + b REFERENCES p1 DEFERRABLE INITIALLY DEFERRED + ); + + INSERT INTO p1 VALUES(1, 'one'); + INSERT INTO p1 VALUES(2, 'two'); + INSERT INTO p1 VALUES(3, 'three'); + INSERT INTO p1 VALUES(4, 'four'); + } +} + +proc capture_changeset {sql} { + sqlite3session S db main + + foreach t [db eval {SELECT name FROM sqlite_master WHERE type='table'}] { + S attach $t + } + execsql $sql + set ret [S changeset] + S delete + + return $ret +} + +do_test 1.1 { + populate_db + set cc [capture_changeset { + INSERT INTO c1 VALUES('ii', 2); + INSERT INTO c2 VALUES('iii', 3); + }] + set {} {} +} {} + +proc xConflict {args} { + lappend ::xConflict {*}$args + return $::conflictret +} + +foreach {tn delrow trans conflictargs conflictret} { + 1 2 0 {FOREIGN_KEY 1} OMIT + 2 3 0 {FOREIGN_KEY 1} OMIT + 3 2 1 {FOREIGN_KEY 1} OMIT + 4 3 1 {FOREIGN_KEY 1} OMIT + 5 2 0 {FOREIGN_KEY 1} ABORT + 6 3 0 {FOREIGN_KEY 1} ABORT + 7 2 1 {FOREIGN_KEY 1} ABORT + 8 3 1 {FOREIGN_KEY 1} ABORT +} { + + set A(OMIT) {0 {}} + set A(ABORT) {1 SQLITE_CONSTRAINT} + do_test 1.2.$tn.1 { + populate_db + execsql { DELETE FROM p1 WHERE a=($delrow+0) } + if {$trans} { execsql BEGIN } + + set ::xConflict [list] + list [catch {sqlite3changeset_apply db $::cc xConflict} msg] $msg + } $A($conflictret) + + do_test 1.2.$tn.2 { set ::xConflict } $conflictargs + + set A(OMIT) {1 1} + set A(ABORT) {0 0} + do_test 1.2.$tn.3 { + execsql { SELECT count(*) FROM c1 UNION ALL SELECT count(*) FROM c2 } + } $A($conflictret) + + do_test 1.2.$tn.4 { expr ![sqlite3_get_autocommit db] } $trans + do_test 1.2.$tn.5 { + if { $trans } { execsql COMMIT } + } {} +} + +#-------------------------------------------------------------------- +# Test that closing a transaction clears the defer_foreign_keys flag. +# +foreach {tn open noclose close} { + 1 BEGIN {} COMMIT + 2 BEGIN {} ROLLBACK + + 3 {SAVEPOINT one} {} {RELEASE one} + 4 {SAVEPOINT one} {ROLLBACK TO one} {RELEASE one} +} { + execsql $open + do_execsql_test 2.$tn.1 { PRAGMA defer_foreign_keys } {0} + + do_execsql_test 2.$tn.2 { + PRAGMA defer_foreign_keys = 1; + PRAGMA defer_foreign_keys; + } {1} + + execsql $noclose + do_execsql_test 2.$tn.3 { PRAGMA defer_foreign_keys } {1} + + execsql $close + do_execsql_test 2.$tn.4 { PRAGMA defer_foreign_keys } {0} +} + +finish_test + diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index aa0c4b59db..31e0300eb2 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1,6 +1,5 @@ #if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK) - #include "sqlite3session.h" #include #include @@ -2110,6 +2109,26 @@ int sqlite3changeset_conflict( return SQLITE_OK; } +/* +** This function may only be called with an iterator passed to an +** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case +** it sets the output variable to the total number of known foreign key +** violations in the destination database and returns SQLITE_OK. +** +** In all other cases this function returns SQLITE_MISUSE. +*/ +int sqlite3changeset_fk_conflicts( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int *pnOut /* OUT: Number of FK violations */ +){ + if( pIter->pConflict || pIter->apValue ){ + return SQLITE_MISUSE; + } + *pnOut = pIter->nCol; + return SQLITE_OK; +} + + /* ** Finalize an iterator allocated with sqlite3changeset_start(). ** @@ -2845,6 +2864,9 @@ int sqlite3changeset_apply( sqlite3_mutex_enter(sqlite3_db_mutex(db)); rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 1", 0, 0, 0); + } while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){ int nCol; int op; @@ -2948,6 +2970,23 @@ int sqlite3changeset_apply( sqlite3changeset_finalize(pIter); } + if( rc==SQLITE_OK ){ + int nFk = sqlite3_foreign_key_check(db); + if( nFk>0 ){ + int res = SQLITE_CHANGESET_ABORT; + if( xConflict ){ + sqlite3_changeset_iter sIter; + memset(&sIter, 0, sizeof(sIter)); + sIter.nCol = nFk; + res = xConflict(pCtx, SQLITE_CHANGESET_FOREIGN_KEY, &sIter); + } + if( res!=SQLITE_CHANGESET_OMIT ){ + rc = SQLITE_CONSTRAINT; + } + } + } + sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0); + if( rc==SQLITE_OK ){ rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); }else{ diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index a1ab1e9645..f1a7052bcd 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -489,6 +489,21 @@ int sqlite3changeset_conflict( sqlite3_value **ppValue /* OUT: Value from conflicting row */ ); +/* +** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations +** +** This function may only be called with an iterator passed to an +** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case +** it sets the output variable to the total number of known foreign key +** violations in the destination database and returns SQLITE_OK. +** +** In all other cases this function returns SQLITE_MISUSE. +*/ +int sqlite3changeset_fk_conflicts( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int *pnOut /* OUT: Number of FK violations */ +); + /* ** CAPI3REF: Finalize A Changeset Iterator @@ -809,20 +824,35 @@ int sqlite3changeset_apply( ** ** The conflicting row in this case is the database row with the matching ** primary key. +** +**
SQLITE_CHANGESET_FOREIGN_KEY
+** If foreign key handling is enabled, and applying a changeset leaves the +** database in a state containing foreign key violations, the conflict +** handler is invoked with CHANGESET_FOREIGN_KEY as the second argument +** exactly once before the changeset is committed. If the conflict handler +** returns CHANGESET_OMIT, the changes, including those that caused the +** foreign key constraint violation, are committed. Or, if it returns +** CHANGESET_ABORT, the changeset is rolled back. +** +** No current or conflicting row information is provided. The only function +** it is possible to call on the supplied sqlite3_changeset_iter handle +** is sqlite3changeset_fk_conflicts(). ** **
SQLITE_CHANGESET_CONSTRAINT
** If any other constraint violation occurs while applying a change (i.e. -** a FOREIGN KEY, UNIQUE, CHECK or NOT NULL constraint), the conflict -** handler is invoked with CHANGESET_CONSTRAINT as the second argument. +** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is +** invoked with CHANGESET_CONSTRAINT as the second argument. ** ** There is no conflicting row in this case. The results of invoking the ** sqlite3changeset_conflict() API are undefined. +** **
*/ -#define SQLITE_CHANGESET_DATA 1 -#define SQLITE_CHANGESET_NOTFOUND 2 -#define SQLITE_CHANGESET_CONFLICT 3 -#define SQLITE_CHANGESET_CONSTRAINT 4 +#define SQLITE_CHANGESET_DATA 1 +#define SQLITE_CHANGESET_NOTFOUND 2 +#define SQLITE_CHANGESET_CONFLICT 3 +#define SQLITE_CHANGESET_CONSTRAINT 4 +#define SQLITE_CHANGESET_FOREIGN_KEY 5 /* ** CAPI3REF: Constants Returned By The Conflict Handler diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 82e2c64ba5..49e45c5fb3 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -250,109 +250,119 @@ static int test_conflict_handler( sqlite3changeset_op(pIter, &zTab, &nCol, &op, 0); - /* Append the operation type. */ - Tcl_ListObjAppendElement(0, pEval, Tcl_NewStringObj( - op==SQLITE_INSERT ? "INSERT" : - op==SQLITE_UPDATE ? "UPDATE" : - "DELETE", -1 - )); - - /* Append the table name. */ - Tcl_ListObjAppendElement(0, pEval, Tcl_NewStringObj(zTab, -1)); - - /* Append the conflict type. */ - switch( eConf ){ - case SQLITE_CHANGESET_DATA: - Tcl_ListObjAppendElement(interp, pEval,Tcl_NewStringObj("DATA",-1)); - break; - case SQLITE_CHANGESET_NOTFOUND: - Tcl_ListObjAppendElement(interp, pEval,Tcl_NewStringObj("NOTFOUND",-1)); - break; - case SQLITE_CHANGESET_CONFLICT: - Tcl_ListObjAppendElement(interp, pEval,Tcl_NewStringObj("CONFLICT",-1)); - break; - case SQLITE_CHANGESET_CONSTRAINT: - Tcl_ListObjAppendElement(interp, pEval,Tcl_NewStringObj("CONSTRAINT",-1)); - break; - } - - /* If this is not an INSERT, append the old row */ - if( op!=SQLITE_INSERT ){ - int i; - Tcl_Obj *pOld = Tcl_NewObj(); - for(i=0; iisDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ + if( !pFKey->isDeferred + && !pParse->pToplevel + && !pParse->isMultiWrite + && !(pParse->db->flags & SQLITE_DeferForeignKeys) + ){ /* Special case: If this is an INSERT statement that will insert exactly ** one row into the table, raise a constraint immediately instead of ** incrementing a counter. This is necessary as the VM code is being diff --git a/src/main.c b/src/main.c index 6d3798dcbf..df158b9186 100644 --- a/src/main.c +++ b/src/main.c @@ -1037,6 +1037,8 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){ /* Any deferred constraint violations have now been resolved. */ db->nDeferredCons = 0; + db->nDeferredImmCons = 0; + db->flags &= ~SQLITE_DeferForeignKeys; /* If one has been configured, invoke the rollback-hook callback */ if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ diff --git a/src/pragma.c b/src/pragma.c index 5803f6c4a5..9a288b977c 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1169,6 +1169,21 @@ void sqlite3Pragma( } } }else + + if( sqlite3StrICmp(zLeft, "defer_foreign_keys")==0 ){ + if( zRight ){ + if( sqlite3GetBoolean(zRight, 0) ){ + db->flags |= SQLITE_DeferForeignKeys; + }else{ + db->flags &= ~SQLITE_DeferForeignKeys; + db->nDeferredImmCons = 0; + } + sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); + }else{ + int bVal = !!(db->flags & SQLITE_DeferForeignKeys); + returnSingleInt(pParse, "defer_foreign_keys", bVal); + } + } #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ #ifndef SQLITE_OMIT_FOREIGN_KEY diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 3894e56abb..f02e568f38 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7280,6 +7280,8 @@ SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *); SQLITE_EXPERIMENTAL int sqlite3_preupdate_depth(sqlite3 *); SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); +int sqlite3_foreign_key_check(sqlite3 *db); + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 8ee07a13ff..dd65c51d90 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -961,6 +961,7 @@ struct sqlite3 { int nSavepoint; /* Number of non-transaction savepoints */ int nStatement; /* Number of nested statement-transactions */ i64 nDeferredCons; /* Net deferred constraints this transaction. */ + i64 nDeferredImmCons; /* Net deferred immediate constraints */ int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY @@ -1016,6 +1017,7 @@ struct sqlite3 { #define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ #define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ #define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ +#define SQLITE_DeferForeignKeys 0x00800000 /* ** Bits of the sqlite3.dbOptFlags field that are used by the @@ -1161,6 +1163,7 @@ struct FuncDestructor { struct Savepoint { char *zName; /* Savepoint name (nul-terminated) */ i64 nDeferredCons; /* Number of deferred fk violations */ + i64 nDeferredImmCons; /* Number of deferred imm fk. */ Savepoint *pNext; /* Parent savepoint (if any) */ }; diff --git a/src/vdbe.c b/src/vdbe.c index c5e6cfcc3e..5330c48b5f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -878,7 +878,7 @@ case OP_Halt: { p->rc = rc = SQLITE_BUSY; }else{ assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ); - assert( rc==SQLITE_OK || db->nDeferredCons>0 ); + assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 ); rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; } goto vdbe_return; @@ -2737,6 +2737,7 @@ case OP_Savepoint: { pNew->pNext = db->pSavepoint; db->pSavepoint = pNew; pNew->nDeferredCons = db->nDeferredCons; + pNew->nDeferredImmCons = db->nDeferredImmCons; } } }else{ @@ -2824,6 +2825,7 @@ case OP_Savepoint: { } }else{ db->nDeferredCons = pSavepoint->nDeferredCons; + db->nDeferredImmCons = pSavepoint->nDeferredImmCons; } if( !isTransaction ){ @@ -2978,6 +2980,7 @@ case OP_Transaction: { ** counter. If the statement transaction needs to be rolled back, ** the value of this counter needs to be restored too. */ p->nStmtDefCons = db->nDeferredCons; + p->nStmtDefImmCons = db->nDeferredImmCons; } } break; @@ -5319,7 +5322,9 @@ case OP_Param: { /* out2-prerelease */ ** statement counter is incremented (immediate foreign key constraints). */ case OP_FkCounter: { - if( pOp->p1 ){ + if( db->flags & SQLITE_DeferForeignKeys ){ + db->nDeferredImmCons += pOp->p2; + }else if( pOp->p1 ){ db->nDeferredCons += pOp->p2; }else{ p->nFkConstraint += pOp->p2; @@ -5340,9 +5345,9 @@ case OP_FkCounter: { */ case OP_FkIfZero: { /* jump */ if( pOp->p1 ){ - if( db->nDeferredCons==0 ) pc = pOp->p2-1; + if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; }else{ - if( p->nFkConstraint==0 ) pc = pOp->p2-1; + if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; } break; } diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 1f9358a232..aec4b422b6 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -350,6 +350,7 @@ struct Vdbe { #endif i64 nFkConstraint; /* Number of imm. FK constraints this VM */ i64 nStmtDefCons; /* Number of def. constraints when stmt started */ + i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ char *zSql; /* Text of the SQL statement that generated this */ void *pFree; /* Free this when deleting the vdbe */ #ifdef SQLITE_DEBUG diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 8be71383ba..6fb45edb84 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -386,7 +386,9 @@ static int sqlite3Step(Vdbe *p){ db->u1.isInterrupted = 0; } - assert( db->writeVdbeCnt>0 || db->autoCommit==0 || db->nDeferredCons==0 ); + assert( db->writeVdbeCnt>0 || db->autoCommit==0 + || (db->nDeferredCons==0 && db->nDeferredImmCons==0) + ); #ifndef SQLITE_OMIT_TRACE if( db->xProfile && !db->init.busy ){ @@ -1496,3 +1498,5 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ return sqlite3ApiExit(db, rc); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + +int sqlite3_foreign_key_check(sqlite3 *db){ return db->nDeferredImmCons; } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 7897116fb8..88561ecb06 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2051,6 +2051,7 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ ** the statement transaction was opened. */ if( eOp==SAVEPOINT_ROLLBACK ){ db->nDeferredCons = p->nStmtDefCons; + db->nDeferredImmCons = p->nStmtDefImmCons; } } return rc; @@ -2069,7 +2070,9 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ #ifndef SQLITE_OMIT_FOREIGN_KEY int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ sqlite3 *db = p->db; - if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){ + if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0) + || (!deferred && p->nFkConstraint>0) + ){ p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; p->errorAction = OE_Abort; sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed"); @@ -2201,6 +2204,8 @@ int sqlite3VdbeHalt(Vdbe *p){ sqlite3RollbackAll(db, SQLITE_OK); }else{ db->nDeferredCons = 0; + db->nDeferredImmCons = 0; + db->flags &= ~SQLITE_DeferForeignKeys; sqlite3CommitInternalChanges(db); } }else{ From bded90b4873a5e4e6d513f36dd0edc181004dfaa Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 4 Jul 2013 15:22:53 +0000 Subject: [PATCH 079/570] Fix a bug preventing some FK constraint checking from being deferred until the end of changeset application. FossilOrigin-Name: 1452defb8cfcc489230314dd1e0425feba46c49d --- ext/session/session9.test | 124 +++++++++++++++++++++++++++++++++++++- manifest | 14 ++--- manifest.uuid | 2 +- src/fkey.c | 7 ++- 4 files changed, 135 insertions(+), 12 deletions(-) diff --git a/ext/session/session9.test b/ext/session/session9.test index 35d8e876c9..b6ead68991 100644 --- a/ext/session/session9.test +++ b/ext/session/session9.test @@ -23,8 +23,8 @@ set testprefix session9 #-------------------------------------------------------------------- +# Basic tests. # - proc populate_db {} { drop_all_tables execsql { @@ -130,5 +130,127 @@ foreach {tn open noclose close} { do_execsql_test 2.$tn.4 { PRAGMA defer_foreign_keys } {0} } +#-------------------------------------------------------------------- +# Test that a cyclic relationship can be inserted and deleted. +# +# This situation does not come up in practice, but testing it serves to +# show that it does not matter which order parent and child keys +# are processed in internally when applying a changeset. +# +drop_all_tables + +do_execsql_test 3.1 { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(x PRIMARY KEY, y); +} + +# Create changesets as follows: +# +# $cc1 - Insert a row into t1. +# $cc2 - Insert a row into t2. +# $cc - Combination of $cc1 and $cc2. +# +# $ccdel1 - Delete the row from t1. +# $ccdel2 - Delete the row from t2. +# $ccdel - Combination of $cc1 and $cc2. +# +do_test 3.2 { + set cc1 [capture_changeset { + INSERT INTO t1 VALUES('one', 'value one'); + }] + set ccdel1 [capture_changeset { DELETE FROM t1; }] + set cc2 [capture_changeset { + INSERT INTO t2 VALUES('value one', 'one'); + }] + set ccdel2 [capture_changeset { DELETE FROM t2; }] + set cc [capture_changeset { + INSERT INTO t1 VALUES('one', 'value one'); + INSERT INTO t2 VALUES('value one', 'one'); + }] + set ccdel [capture_changeset { + DELETE FROM t1; + DELETE FROM t2; + }] + set {} {} +} {} + +# Now modify the database schema to create a cyclic foreign key dependency +# between tables t1 and t2. This means that although changesets $cc and +# $ccdel can be applied, none of the others may without violating the +# foreign key constraints. +# +do_test 3.3 { + + drop_all_tables + execsql { + CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t2); + CREATE TABLE t2(x PRIMARY KEY, y REFERENCES t1); + } + + + proc conflict_handler {args} { return "ABORT" } + sqlite3changeset_apply db $cc conflict_handler + + execsql { + SELECT * FROM t1; + SELECT * FROM t2; + } +} {one {value one} {value one} one} + +do_test 3.3.1 { + list [catch {sqlite3changeset_apply db $::ccdel1 conflict_handler} msg] $msg +} {1 SQLITE_CONSTRAINT} +do_test 3.3.2 { + list [catch {sqlite3changeset_apply db $::ccdel2 conflict_handler} msg] $msg +} {1 SQLITE_CONSTRAINT} + +do_test 3.3.4.1 { + list [catch {sqlite3changeset_apply db $::ccdel conflict_handler} msg] $msg +} {0 {}} +do_execsql_test 3.3.4.2 { + SELECT * FROM t1; + SELECT * FROM t2; +} {} + +do_test 3.5.1 { + list [catch {sqlite3changeset_apply db $::cc1 conflict_handler} msg] $msg +} {1 SQLITE_CONSTRAINT} +do_test 3.5.2 { + list [catch {sqlite3changeset_apply db $::cc2 conflict_handler} msg] $msg +} {1 SQLITE_CONSTRAINT} + +#-------------------------------------------------------------------- +# Test that if a change that affects FK processing is not applied +# due to a separate constraint, SQLite does not get confused and +# increment FK counters anyway. +# +drop_all_tables +do_execsql_test 4.1 { + CREATE TABLE p1(x PRIMARY KEY, y); + CREATE TABLE c1(a PRIMARY KEY, b REFERENCES p1); + INSERT INTO p1 VALUES(1,1); +} + +do_execsql_test 4.2.1 { + BEGIN; + PRAGMA defer_foreign_keys = 1; + INSERT INTO c1 VALUES('x', 'x'); +} +do_catchsql_test 4.2.2 { COMMIT } {1 {foreign key constraint failed}} +do_catchsql_test 4.2.3 { ROLLBACK } {0 {}} + +do_execsql_test 4.3.1 { + BEGIN; + PRAGMA defer_foreign_keys = 1; + INSERT INTO c1 VALUES(1, 1); +} +do_catchsql_test 4.3.2 { + INSERT INTO c1 VALUES(1, 'x') +} {1 {column a is not unique}} + +do_catchsql_test 4.3.3 { COMMIT } {0 {}} +do_catchsql_test 4.3.4 { BEGIN ; COMMIT } {0 {}} + finish_test + diff --git a/manifest b/manifest index cbf96b3093..05a751b481 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Experimental\schange\sto\sthe\shandling\sof\sforeign\skey\sconstraint\sviolations\swhen\sapplying\sa\schangeset:\sall\sforeign\skeys,\simmediate\sand\sdeferred,\sare\sdeferred\suntil\sthe\send\sof\sthe\stransaction\s(or\ssub-transaction)\sopened\sby\sthe\ssqlite3changeset_apply().\sA\ssingle\scall\sto\sthe\sconflict-handler\s(if\sany)\sis\smade\sif\sany\sFK\sconstraint\sviolations\sare\sstill\spresent\sin\sthe\sdatabase\sat\sthis\spoint.\sThe\sconflict-handler\smay\schoose\sto\srollback\sthe\schangeset,\sor\sto\sapply\sit,\sconstraint\sviolations\sand\sall. -D 2013-07-03T19:53:05.693 +C Fix\sa\sbug\spreventing\ssome\sFK\sconstraint\schecking\sfrom\sbeing\sdeferred\suntil\sthe\send\sof\schangeset\sapplication. +D 2013-07-04T15:22:53.953 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in aff38bc64c582dd147f18739532198372587b0f0 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -142,7 +142,7 @@ F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 -F ext/session/session9.test 3378ceace4e291dda8512b83d256be51aac5344e +F ext/session/session9.test 43acfdc57647c2ce4b36dbd0769112520ea6af14 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 496291b287ba3c0b14ca2e074425e29cc92a64a6 F ext/session/sqlite3session.c 80903fe2c24c8a9e7ccacebca1855a31ebebbbc3 @@ -186,7 +186,7 @@ F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 F src/delete.c 39a770e9729b1acd2de347f8f614584841d0083e F src/expr.c 2b47ae9da6c9f34eff6736962ea2e102c6c4a755 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c ddd160ce0b81f092165f72d84c356d49c903a3ad +F src/fkey.c 87619fc3a9b6ab6877388bbcc05cdb136503786e F src/func.c 5c50c1ea31fd864b0fe921fe1a8d4c55acd609ef F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 @@ -1111,7 +1111,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P c2972b6aed23f6c76a289534de9ea4732a48f40e -R 1e1bb18e922bc4e9bb6b2e837b9cd1c8 +P 1d44e5d3c2b1dc958442f9114a960b256e002ed3 +R 28f75ac347bd281672cb0a8d27d3f6b3 U dan -Z 8c44f70721e5b391cc002040c9d1eb51 +Z 01296a7a6fdc241a613ea24758428ad2 diff --git a/manifest.uuid b/manifest.uuid index f8240dd8be..44d88b34c0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1d44e5d3c2b1dc958442f9114a960b256e002ed3 \ No newline at end of file +1452defb8cfcc489230314dd1e0425feba46c49d \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index 0369bbc6f0..3f3c5d8ad6 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -422,10 +422,9 @@ static void fkLookupParent( } } - if( !pFKey->isDeferred + if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferForeignKeys) && !pParse->pToplevel && !pParse->isMultiWrite - && !(pParse->db->flags & SQLITE_DeferForeignKeys) ){ /* Special case: If this is an INSERT statement that will insert exactly ** one row into the table, raise a constraint immediately instead of @@ -817,7 +816,9 @@ void sqlite3FkCheck( SrcList *pSrc; int *aiCol = 0; - if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ + if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferForeignKeys) + && !pParse->pToplevel && !pParse->isMultiWrite + ){ assert( regOld==0 && regNew!=0 ); /* Inserting a single row into a parent table cannot cause an immediate ** foreign key violation. So do nothing in this case. */ From 963c74df5988fa4bf5dd6dda9fb15a9b09a0d6a4 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 11 Jul 2013 12:19:12 +0000 Subject: [PATCH 080/570] Rename the SQLITE_DeferForeignKeys macro to shorter SQLITE_DeferFKs. Move the "defer_foreign_keys" pragma into the flagPragma() routine. FossilOrigin-Name: 3a2ab74c85a40e0e7ef2d6aef6ec23837cb788e6 --- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- src/fkey.c | 4 ++-- src/main.c | 2 +- src/pragma.c | 21 ++++----------------- src/sqliteInt.h | 2 +- src/vdbe.c | 2 +- src/vdbeaux.c | 2 +- 8 files changed, 22 insertions(+), 35 deletions(-) diff --git a/manifest b/manifest index 66bca82b2d..8d6c35f1b7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Pull\sin\sall\sthe\slatest\schanges\sfrom\strunk. -D 2013-07-09T13:05:49.248 +C Rename\sthe\sSQLITE_DeferForeignKeys\smacro\sto\sshorter\sSQLITE_DeferFKs.\s\sMove\nthe\s"defer_foreign_keys"\spragma\sinto\sthe\sflagPragma()\sroutine. +D 2013-07-11T12:19:12.495 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in aff38bc64c582dd147f18739532198372587b0f0 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -187,7 +187,7 @@ F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 F src/delete.c 39a770e9729b1acd2de347f8f614584841d0083e F src/expr.c 2b47ae9da6c9f34eff6736962ea2e102c6c4a755 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c 87619fc3a9b6ab6877388bbcc05cdb136503786e +F src/fkey.c 914a6bbd987d857c41ac9d244efa6641f36faadb F src/func.c 5c50c1ea31fd864b0fe921fe1a8d4c55acd609ef F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 @@ -198,7 +198,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c c48f7f3f170e502fe0cc20748e03c6e0b5a016c2 -F src/main.c a27560235a8e0e3f1a94aaca30189431bf61e776 +F src/main.c 93407bb51024f962ed9cf1c3e525e63484ebbdb9 F src/malloc.c fe085aa851b666b7c375c1ff957643dc20a04bf6 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 437c7c4af964895d4650f29881df63535caaa1fa @@ -223,7 +223,7 @@ F src/parse.y 9acfcc83ddbf0cf82f0ed9582ccf0ad6c366ff37 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c d23d07716de96c7c0c2503ec5051a4384c3fb938 -F src/pragma.c 057f5b1343c9a79e3e6c0c542a3a08b85849ee61 +F src/pragma.c c87581d93a7518cba656b7919e32ded5d331b76a F src/prepare.c 2306be166bbeddf454e18bf8b21dba8388d05328 F src/printf.c 41c49dac366a3a411190001a8ab495fa8887974e F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 @@ -234,7 +234,7 @@ F src/shell.c c8cd06e6b66250a3ea0149c4edec30de14f57b6f F src/sqlite.h.in fb8adf7852fb92e410de422b5569923327bf8a2c F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h a83b0cef30022c46a19e6ace1f668b7833935eed +F src/sqliteInt.h 62b11aa829ab51446a52dfea93f14b8e1e5d5862 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -290,11 +290,11 @@ F src/update.c 19daebf6a0a67af5524913e93498d08388792128 F src/utf.c 8d819e2e5104a430fc2005f018db14347c95a38f F src/util.c f566b5138099a2df8533b190d0dcc74b7dfbe0c9 F src/vacuum.c d9c5759f4c5a438bb43c2086f72c5d2edabc36c8 -F src/vdbe.c 7e1654d4ac01f017aad8088a1225e514b2aef5cf +F src/vdbe.c 26f19a439806efdd9fb93b1874a4a7029a885142 F src/vdbe.h 1223e2548e0970cf96f573ff6b99f804a36ad683 F src/vdbeInt.h 11feb11eb49d8b312741011d30d91c9c50b59de0 F src/vdbeapi.c bb28ee14bae43579b33d88e0d916a1657255a866 -F src/vdbeaux.c 84f5fb7cb2f62fd8b8a37b96ac929221cc77d317 +F src/vdbeaux.c 35846cedd64e90b83f498786775c69c2c6b6c8b1 F src/vdbeblob.c 1268e0bcb8e21fa32520b0fc376e1bcdfaa0c642 F src/vdbemem.c 833005f1cbbf447289f1973dba2a0c2228c7b8ab F src/vdbesort.c 3937e06b2a0e354500e17dc206ef4c35770a5017 @@ -1115,7 +1115,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 1452defb8cfcc489230314dd1e0425feba46c49d 1e39f85077f1f2b96c3a656c5b6334bafb005908 -R 996effd12b4e262519df6f6e538dae74 +P af3ca4c6e557e6bc92584586b5a97d9be41b0b82 +R 5801e485f633968bff3b48e71da6671c U drh -Z 08707dac307041af534ddfd35863fca1 +Z 2dfee648a27ba78793a28310983bc733 diff --git a/manifest.uuid b/manifest.uuid index d864f435a3..ae79df7faa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -af3ca4c6e557e6bc92584586b5a97d9be41b0b82 \ No newline at end of file +3a2ab74c85a40e0e7ef2d6aef6ec23837cb788e6 \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index 3f3c5d8ad6..bb59c656f6 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -422,7 +422,7 @@ static void fkLookupParent( } } - if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferForeignKeys) + if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs) && !pParse->pToplevel && !pParse->isMultiWrite ){ @@ -816,7 +816,7 @@ void sqlite3FkCheck( SrcList *pSrc; int *aiCol = 0; - if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferForeignKeys) + if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) && !pParse->pToplevel && !pParse->isMultiWrite ){ assert( regOld==0 && regNew!=0 ); diff --git a/src/main.c b/src/main.c index ad9422b486..b25c43be3d 100644 --- a/src/main.c +++ b/src/main.c @@ -1038,7 +1038,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){ /* Any deferred constraint violations have now been resolved. */ db->nDeferredCons = 0; db->nDeferredImmCons = 0; - db->flags &= ~SQLITE_DeferForeignKeys; + db->flags &= ~SQLITE_DeferFKs; /* If one has been configured, invoke the rollback-hook callback */ if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ diff --git a/src/pragma.c b/src/pragma.c index 9a288b977c..fd0ebc727c 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -197,12 +197,13 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted ** flag if there are any active statements. */ { "read_uncommitted", SQLITE_ReadUncommitted }, - { "recursive_triggers", SQLITE_RecTriggers }, + { "recursive_triggers", SQLITE_RecTriggers }, /* This flag may only be set if both foreign-key and trigger support ** are present in the build. */ #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - { "foreign_keys", SQLITE_ForeignKeys }, + { "foreign_keys", SQLITE_ForeignKeys }, + { "defer_foreign_keys", SQLITE_DeferFKs }, #endif }; int i; @@ -228,6 +229,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ db->flags |= mask; }else{ db->flags &= ~mask; + if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0; } /* Many of the flag-pragmas modify the code generated by the SQL @@ -1169,21 +1171,6 @@ void sqlite3Pragma( } } }else - - if( sqlite3StrICmp(zLeft, "defer_foreign_keys")==0 ){ - if( zRight ){ - if( sqlite3GetBoolean(zRight, 0) ){ - db->flags |= SQLITE_DeferForeignKeys; - }else{ - db->flags &= ~SQLITE_DeferForeignKeys; - db->nDeferredImmCons = 0; - } - sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); - }else{ - int bVal = !!(db->flags & SQLITE_DeferForeignKeys); - returnSingleInt(pParse, "defer_foreign_keys", bVal); - } - } #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ #ifndef SQLITE_OMIT_FOREIGN_KEY diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 228d34fc59..f989c3a30b 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1018,7 +1018,7 @@ struct sqlite3 { #define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ #define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ #define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ -#define SQLITE_DeferForeignKeys 0x00800000 +#define SQLITE_DeferFKs 0x00800000 /* Defer all FK constraints */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the diff --git a/src/vdbe.c b/src/vdbe.c index e5a40b7993..b957212e34 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5338,7 +5338,7 @@ case OP_Param: { /* out2-prerelease */ ** statement counter is incremented (immediate foreign key constraints). */ case OP_FkCounter: { - if( db->flags & SQLITE_DeferForeignKeys ){ + if( db->flags & SQLITE_DeferFKs ){ db->nDeferredImmCons += pOp->p2; }else if( pOp->p1 ){ db->nDeferredCons += pOp->p2; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 5ba51dce60..654230dfa9 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2221,7 +2221,7 @@ int sqlite3VdbeHalt(Vdbe *p){ }else{ db->nDeferredCons = 0; db->nDeferredImmCons = 0; - db->flags &= ~SQLITE_DeferForeignKeys; + db->flags &= ~SQLITE_DeferFKs; sqlite3CommitInternalChanges(db); } }else{ From 07001c45a1cfe57cab888ddee16288d23f5fd344 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 11 Jul 2013 13:49:59 +0000 Subject: [PATCH 081/570] Remove the undocumented sqlite3_foreign_key_check() API and replace it with sqlite3_db_status(db, SQLITE_DBSTATUS_DEFERRED_FKS, ...). Add test cases for the new functionality. FossilOrigin-Name: d39e65fe702a2e11477f2d996f77404f45763368 --- ext/session/sqlite3session.c | 5 +- manifest | 23 ++++---- manifest.uuid | 2 +- src/sqlite.h.in | 11 +++- src/status.c | 10 ++++ src/test_malloc.c | 3 +- src/vdbeapi.c | 2 - test/fkey1.test | 3 + test/fkey6.test | 103 +++++++++++++++++++++++++++++++++++ 9 files changed, 142 insertions(+), 20 deletions(-) create mode 100644 test/fkey6.test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 31e0300eb2..6fa8107408 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2971,8 +2971,9 @@ int sqlite3changeset_apply( } if( rc==SQLITE_OK ){ - int nFk = sqlite3_foreign_key_check(db); - if( nFk>0 ){ + int nFk, notUsed; + sqlite3_db_status(db, SQLITE_DBSTATUS_DEFERRED_FKS, &nFk, ¬Used, 0); + if( nFk!=0 ){ int res = SQLITE_CHANGESET_ABORT; if( xConflict ){ sqlite3_changeset_iter sIter; diff --git a/manifest b/manifest index 8d6c35f1b7..d549fe0174 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Rename\sthe\sSQLITE_DeferForeignKeys\smacro\sto\sshorter\sSQLITE_DeferFKs.\s\sMove\nthe\s"defer_foreign_keys"\spragma\sinto\sthe\sflagPragma()\sroutine. -D 2013-07-11T12:19:12.495 +C Remove\sthe\sundocumented\ssqlite3_foreign_key_check()\sAPI\sand\sreplace\sit\swith\nsqlite3_db_status(db,\sSQLITE_DBSTATUS_DEFERRED_FKS,\s...).\s\sAdd\stest\scases\nfor\sthe\snew\sfunctionality. +D 2013-07-11T13:49:59.348 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in aff38bc64c582dd147f18739532198372587b0f0 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -146,7 +146,7 @@ F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 F ext/session/session9.test 43acfdc57647c2ce4b36dbd0769112520ea6af14 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 496291b287ba3c0b14ca2e074425e29cc92a64a6 -F ext/session/sqlite3session.c 80903fe2c24c8a9e7ccacebca1855a31ebebbbc3 +F ext/session/sqlite3session.c e0345e8425a36fb8ac107175ebae46b4af8873e4 F ext/session/sqlite3session.h c7db3d8515eba7f41eeb8698a25e58d24cd384bf F ext/session/test_session.c 12053e9190653164fa624427cf90d1f46ca7f179 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -231,12 +231,12 @@ F src/resolve.c 89f9003e8316ee3a172795459efc2a0274e1d5a8 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 91b62654caf8dfe292fb8882715e575d34ad3874 F src/shell.c c8cd06e6b66250a3ea0149c4edec30de14f57b6f -F src/sqlite.h.in fb8adf7852fb92e410de422b5569923327bf8a2c +F src/sqlite.h.in 17c84f6a2296a33a16141f4cff4b176278f3d1cc F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc F src/sqliteInt.h 62b11aa829ab51446a52dfea93f14b8e1e5d5862 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d -F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9 +F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/tclsqlite.c e0eaf3a78eca2ef650abb67b6571cc86abcb5f87 F src/test1.c 870fc648a48cb6d6808393174f7ebe82b8c840fa @@ -263,7 +263,7 @@ F src/test_intarray.c 87847c71c3c36889c0bcc9c4baf9d31881665d61 F src/test_intarray.h b999bb18d090b8d9d9c49d36ec37ef8f341fe169 F src/test_journal.c f5c0a05b7b3d5930db769b5ee6c3766dc2221a64 F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e -F src/test_malloc.c 2855429b8232107b3296409be2a8eb68345290c2 +F src/test_malloc.c a105801222c0514f8befa2a1712a95505cce099a F src/test_multiplex.c 5d691eeb6cb6aa7888da28eba5e62a9a857d3c0f F src/test_multiplex.h 9b63b95f07acedee425fdfe49a47197c9bf5f9d8 F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f @@ -293,7 +293,7 @@ F src/vacuum.c d9c5759f4c5a438bb43c2086f72c5d2edabc36c8 F src/vdbe.c 26f19a439806efdd9fb93b1874a4a7029a885142 F src/vdbe.h 1223e2548e0970cf96f573ff6b99f804a36ad683 F src/vdbeInt.h 11feb11eb49d8b312741011d30d91c9c50b59de0 -F src/vdbeapi.c bb28ee14bae43579b33d88e0d916a1657255a866 +F src/vdbeapi.c bca51b6ea254af3a1bbfd2a58522f6d6db214334 F src/vdbeaux.c 35846cedd64e90b83f498786775c69c2c6b6c8b1 F src/vdbeblob.c 1268e0bcb8e21fa32520b0fc376e1bcdfaa0c642 F src/vdbemem.c 833005f1cbbf447289f1973dba2a0c2228c7b8ab @@ -465,11 +465,12 @@ F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7 F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146 -F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da +F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b F test/fkey2.test 06e0b4cc9e1b3271ae2ae6feeb19755468432111 F test/fkey3.test 5ec899d12b13bcf1e9ef40eff7fb692fdb91392e F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d F test/fkey5.test 0bf64f2d19ad80433ca0b24edbf604a18b353d5f +F test/fkey6.test 2d76497c54db0e5bfbecee0acf00bb8a706b37db F test/fkey_malloc.test bb74c9cb8f8fceed03b58f8a7ef2df98520bbd51 F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c @@ -1115,7 +1116,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P af3ca4c6e557e6bc92584586b5a97d9be41b0b82 -R 5801e485f633968bff3b48e71da6671c +P 3a2ab74c85a40e0e7ef2d6aef6ec23837cb788e6 +R 4b05e08ec28ee8fbe45f517a6910194e U drh -Z 2dfee648a27ba78793a28310983bc733 +Z 8f1a9fcd771ae153ffef09cc214c7392 diff --git a/manifest.uuid b/manifest.uuid index ae79df7faa..89b033640c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3a2ab74c85a40e0e7ef2d6aef6ec23837cb788e6 \ No newline at end of file +d39e65fe702a2e11477f2d996f77404f45763368 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 24ccb8d39d..6e51fadc70 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6239,6 +6239,12 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined). ^The ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. **
+** +** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(
SQLITE_DBSTATUS_DEFERRED_FKS
+**
This parameter returns the zero for the current value if and only if +** there all foreign key constraints (deferred or immediate) have been +** resolved. The highwater mark is always 0. +**
** */ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 @@ -6251,7 +6257,8 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_CACHE_WRITE 9 -#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_DEFERRED_FKS 10 +#define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */ /* @@ -7282,8 +7289,6 @@ SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *); SQLITE_EXPERIMENTAL int sqlite3_preupdate_depth(sqlite3 *); SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); -int sqlite3_foreign_key_check(sqlite3 *db); - /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. diff --git a/src/status.c b/src/status.c index 28349e6d3d..5fcb68ddc3 100644 --- a/src/status.c +++ b/src/status.c @@ -243,6 +243,16 @@ int sqlite3_db_status( break; } + /* Set *pCurrent to non-zero if there are unresolved deferred foreign + ** key constraints. Set *pCurrent to zero if all foreign key constraints + ** have been satisfied. The *pHighwater is always set to zero. + */ + case SQLITE_DBSTATUS_DEFERRED_FKS: { + *pHighwater = 0; + *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0; + break; + } + default: { rc = SQLITE_ERROR; } diff --git a/src/test_malloc.c b/src/test_malloc.c index cf98a8fb21..2e31f0833d 100644 --- a/src/test_malloc.c +++ b/src/test_malloc.c @@ -1349,7 +1349,8 @@ static int test_db_status( { "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL }, { "CACHE_HIT", SQLITE_DBSTATUS_CACHE_HIT }, { "CACHE_MISS", SQLITE_DBSTATUS_CACHE_MISS }, - { "CACHE_WRITE", SQLITE_DBSTATUS_CACHE_WRITE } + { "CACHE_WRITE", SQLITE_DBSTATUS_CACHE_WRITE }, + { "DEFERRED_FKS", SQLITE_DBSTATUS_DEFERRED_FKS } }; Tcl_Obj *pResult; if( objc!=4 ){ diff --git a/src/vdbeapi.c b/src/vdbeapi.c index b97faaf404..854396a379 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -1499,5 +1499,3 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ return sqlite3ApiExit(db, rc); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ - -int sqlite3_foreign_key_check(sqlite3 *db){ return db->nDeferredImmCons; } diff --git a/test/fkey1.test b/test/fkey1.test index e7c00d16d4..90a4c44409 100644 --- a/test/fkey1.test +++ b/test/fkey1.test @@ -117,5 +117,8 @@ do_test fkey1-3.4 { {0 0 t5 d {} {SET DEFAULT} CASCADE NONE} \ {0 1 t5 e {} {SET DEFAULT} CASCADE NONE} \ ] +do_test fkey1-3.5 { + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 0 0} finish_test diff --git a/test/fkey6.test b/test/fkey6.test new file mode 100644 index 0000000000..66286b43ec --- /dev/null +++ b/test/fkey6.test @@ -0,0 +1,103 @@ +# 2012 December 17 +# +# 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 tests the PRAGMA defer_foreign_keys and +# SQLITE_DBSTATUS_DEFERRED_FKS +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +ifcapable {!foreignkey} { + finish_test + return +} + +do_execsql_test fkey6-1.1 { + PRAGMA foreign_keys=ON; + CREATE TABLE t1(x INTEGER PRIMARY KEY); + CREATE TABLE t2(y INTEGER PRIMARY KEY, + z INTEGER REFERENCES t1(x) DEFERRABLE INITIALLY DEFERRED); + CREATE INDEX t2z ON t2(z); + CREATE TABLE t3(u INTEGER PRIMARY KEY, v INTEGER REFERENCES t1(x)); + CREATE INDEX t3v ON t3(v); + INSERT INTO t1 VALUES(1),(2),(3),(4),(5); + INSERT INTO t2 VALUES(1,1),(2,2); + INSERT INTO t3 VALUES(3,3),(4,4); +} {} +do_test fkey6-1.2 { + catchsql {DELETE FROM t1 WHERE x=2;} +} {1 {foreign key constraint failed}} +do_test fkey6-1.3 { + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 0 0} +do_test fkey6-1.4 { + execsql { + BEGIN; + DELETE FROM t1 WHERE x=1; + } +} {} +do_test fkey6-1.5.1 { + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 1 +} {0 1 0} +do_test fkey6-1.5.2 { + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 1 0} +do_test fkey6-1.6 { + execsql { + ROLLBACK; + } +} {} +do_test fkey6-1.7 { + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 0 0} +do_test fkey6-1.8 { + execsql { + PRAGMA defer_foreign_keys=ON; + BEGIN; + DELETE FROM t1 WHERE x=3; + } +} {} +do_test fkey6-1.9 { + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 1 0} +do_test fkey6-1.10 { + execsql { + ROLLBACK; + PRAGMA defer_foreign_keys=OFF; + BEGIN; + } + catchsql {DELETE FROM t1 WHERE x=3} +} {1 {foreign key constraint failed}} +db eval {ROLLBACK} + +do_test fkey6-1.20 { + execsql { + BEGIN; + DELETE FROM t1 WHERE x=1; + } + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 1 0} +do_test fkey6-1.21 { + execsql { + DELETE FROM t2 WHERE y=1; + } + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 0 0} +do_test fkey6-1.22 { + execsql { + COMMIT; + } +} {} + + +finish_test From 7531a5a37840f18cdb39407c69bd200e0b349569 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 23 Aug 2013 17:43:32 +0000 Subject: [PATCH 082/570] Add the sqlite3session_table_filter API to the sessions extension. FossilOrigin-Name: b7e4dd889d37c8f57c2d3c7900e802f644aac3ea --- ext/session/sessionA.test | 69 +++++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 25 ++++++++++++ ext/session/sqlite3session.h | 19 +++++++++ ext/session/test_session.c | 74 +++++++++++++++++++++++++++++------- manifest | 19 ++++----- manifest.uuid | 2 +- 6 files changed, 185 insertions(+), 23 deletions(-) create mode 100644 ext/session/sessionA.test diff --git a/ext/session/sessionA.test b/ext/session/sessionA.test new file mode 100644 index 0000000000..1ca0f13709 --- /dev/null +++ b/ext/session/sessionA.test @@ -0,0 +1,69 @@ +# 2013 July 04 +# +# 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 tests that the sessions module handles foreign key constraint +# violations when applying changesets as required. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} +set testprefix sessionA + + +forcedelete test.db2 +sqlite3 db2 test.db2 +foreach {tn db} {1 db 2 db2} { + do_test 1.$tn.1 { + execsql { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(a PRIMARY KEY, b); + CREATE TABLE t3(a PRIMARY KEY, b); + } $db + } {} +} + +proc tbl_filter {zTbl} { + return $::table_filter($zTbl) +} + +do_test 2.1 { + set ::table_filter(t1) 1 + set ::table_filter(t2) 0 + set ::table_filter(t3) 1 + + sqlite3session S db main + S table_filter tbl_filter + + execsql { + INSERT INTO t1 VALUES('a', 'b'); + INSERT INTO t2 VALUES('c', 'd'); + INSERT INTO t3 VALUES('e', 'f'); + } + + set changeset [S changeset] + S delete + sqlite3changeset_apply db2 $changeset xConflict + + execsql { + SELECT * FROM t1; + SELECT * FROM t2; + SELECT * FROM t3; + } db2 +} {a b e f} + + +finish_test + + diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 6fa8107408..801ea60717 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -23,6 +23,8 @@ struct sqlite3_session { int bIndirect; /* True if all changes are indirect */ int bAutoAttach; /* True to auto-attach tables */ int rc; /* Non-zero if an error has occurred */ + void *pFilterCtx; /* First argument to pass to xTableFilter */ + int (*xTableFilter)(void *pCtx, const char *zTab); sqlite3_session *pNext; /* Next session object on same db. */ SessionTable *pTable; /* List of attached tables */ }; @@ -1066,6 +1068,16 @@ static void xPreUpdate( if( !pTab ){ /* This branch is taken if table zName has not yet been attached to ** this session and the auto-attach flag is set. */ + + /* If there is a table-filter configured, invoke it. If it returns 0, + ** this change will not be recorded. Break out of the loop early in + ** this case. */ + if( pSession->xTableFilter + && pSession->xTableFilter(pSession->pFilterCtx, zName)==0 + ){ + break; + } + pSession->rc = sqlite3session_attach(pSession,zName); if( pSession->rc ) break; pTab = pSession->pTable; @@ -1170,6 +1182,19 @@ void sqlite3session_delete(sqlite3_session *pSession){ sqlite3_free(pSession); } +/* +** Set a table filter on a Session Object. +*/ +void sqlite3session_table_filter( + sqlite3_session *pSession, + int(*xFilter)(void*, const char*), + void *pCtx /* First argument passed to xFilter */ +){ + pSession->bAutoAttach = 1; + pSession->pFilterCtx = pCtx; + pSession->xTableFilter = xFilter; +} + /* ** Attach a table to a session. All subsequent changes made to the table ** while the session object is enabled will be recorded. diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index f1a7052bcd..974a770c7b 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -71,6 +71,7 @@ int sqlite3session_create( */ void sqlite3session_delete(sqlite3_session *pSession); + /* ** CAPI3REF: Enable Or Disable A Session Object ** @@ -152,6 +153,24 @@ int sqlite3session_attach( const char *zTab /* Table name */ ); +/* +** CAPI3REF: Set a table filter on a Session Object. +** +** The second argument (xFilter) is the "filter callback". For changes to rows +** in tables that are not attached to the Session oject, the filter is called +** to determine whether changes to the table's rows should be tracked or not. +** If xFilter returns 0, changes is not tracked. Note that once a table is +** attached, xFilter will not be called again. +*/ +void sqlite3session_table_filter( + sqlite3_session *pSession, /* Session object */ + int(*xFilter)( + void *pCtx, /* Copy of third arg to _filter_table() */ + const char *zTab /* Table name */ + ), + void *pCtx /* First argument passed to xFilter */ +); + /* ** CAPI3REF: Generate A Changeset From A Session Object ** diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 49e45c5fb3..4340921a67 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -7,18 +7,50 @@ #include #include +typedef struct TestSession TestSession; +struct TestSession { + sqlite3_session *pSession; + Tcl_Interp *interp; + Tcl_Obj *pFilterScript; +}; + static int test_session_error(Tcl_Interp *interp, int rc){ extern const char *sqlite3ErrName(int); Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); return TCL_ERROR; } +static int test_table_filter(void *pCtx, const char *zTbl){ + TestSession *p = (TestSession*)pCtx; + Tcl_Obj *pEval; + int rc; + int bRes = 0; + + pEval = Tcl_DuplicateObj(p->pFilterScript); + Tcl_IncrRefCount(pEval); + rc = Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zTbl, -1)); + if( rc==TCL_OK ){ + rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL); + } + if( rc==TCL_OK ){ + rc = Tcl_GetBooleanFromObj(p->interp, Tcl_GetObjResult(p->interp), &bRes); + } + if( rc!=TCL_OK ){ + /* printf("error: %s\n", Tcl_GetStringResult(p->interp)); */ + Tcl_BackgroundError(p->interp); + } + Tcl_DecrRefCount(pEval); + + return bRes; +} + /* ** Tclcmd: $session attach TABLE ** $session changeset ** $session delete ** $session enable BOOL ** $session indirect INTEGER +** $session table_filter SCRIPT */ static int test_session_cmd( void *clientData, @@ -26,19 +58,21 @@ static int test_session_cmd( int objc, Tcl_Obj *CONST objv[] ){ - sqlite3_session *pSession = (sqlite3_session *)clientData; + TestSession *p = (TestSession*)clientData; + sqlite3_session *pSession = p->pSession; struct SessionSubcmd { const char *zSub; int nArg; const char *zMsg; int iSub; } aSub[] = { - { "attach", 1, "TABLE", }, /* 0 */ - { "changeset", 0, "", }, /* 1 */ - { "delete", 0, "", }, /* 2 */ - { "enable", 1, "BOOL", }, /* 3 */ - { "indirect", 1, "BOOL", }, /* 4 */ - { "isempty", 0, "", }, /* 5 */ + { "attach", 1, "TABLE", }, /* 0 */ + { "changeset", 0, "", }, /* 1 */ + { "delete", 0, "", }, /* 2 */ + { "enable", 1, "BOOL", }, /* 3 */ + { "indirect", 1, "BOOL", }, /* 4 */ + { "isempty", 0, "", }, /* 5 */ + { "table_filter", 1, "SCRIPT", }, /* 6 */ { 0 } }; int iSub; @@ -65,8 +99,8 @@ static int test_session_cmd( if( rc!=SQLITE_OK ){ return test_session_error(interp, rc); } - } break; + } case 1: { /* changeset */ int nChange; @@ -107,14 +141,25 @@ static int test_session_cmd( Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val)); break; } + + case 6: { /* table_filter */ + if( p->pFilterScript ) Tcl_DecrRefCount(p->pFilterScript); + p->interp = interp; + p->pFilterScript = Tcl_DuplicateObj(objv[2]); + Tcl_IncrRefCount(p->pFilterScript); + sqlite3session_table_filter(pSession, test_table_filter, clientData); + break; + } } return TCL_OK; } static void test_session_del(void *clientData){ - sqlite3_session *pSession = (sqlite3_session *)clientData; - sqlite3session_delete(pSession); + TestSession *p = (TestSession*)clientData; + if( p->pFilterScript ) Tcl_DecrRefCount(p->pFilterScript); + sqlite3session_delete(p->pSession); + ckfree(p); } /* @@ -129,7 +174,7 @@ static int test_sqlite3session( sqlite3 *db; Tcl_CmdInfo info; int rc; /* sqlite3session_create() return code */ - sqlite3_session *pSession; /* New session object */ + TestSession *p; /* New wrapper object */ if( objc!=4 ){ Tcl_WrongNumArgs(interp, 1, objv, "CMD DB-HANDLE DB-NAME"); @@ -142,13 +187,16 @@ static int test_sqlite3session( } db = *(sqlite3 **)info.objClientData; - rc = sqlite3session_create(db, Tcl_GetString(objv[3]), &pSession); + p = (TestSession*)ckalloc(sizeof(TestSession)); + memset(p, 0, sizeof(TestSession)); + rc = sqlite3session_create(db, Tcl_GetString(objv[3]), &p->pSession); if( rc!=SQLITE_OK ){ + ckfree(p); return test_session_error(interp, rc); } Tcl_CreateObjCommand( - interp, Tcl_GetString(objv[1]), test_session_cmd, (ClientData)pSession, + interp, Tcl_GetString(objv[1]), test_session_cmd, (ClientData)p, test_session_del ); Tcl_SetObjResult(interp, objv[1]); diff --git a/manifest b/manifest index eeb634ab67..11155359af 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sin\sminor\sbug\sfixes\sand\sperformance\stweaks\sfrom\strunk\sleading\sup\sto\nthe\sversion\s3.8.0\srelease. -D 2013-08-22T15:07:08.266 +C Add\sthe\ssqlite3session_table_filter\sAPI\sto\sthe\ssessions\sextension. +D 2013-08-23T17:43:32.715 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in aff38bc64c582dd147f18739532198372587b0f0 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -144,11 +144,12 @@ F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 F ext/session/session9.test 43acfdc57647c2ce4b36dbd0769112520ea6af14 +F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 496291b287ba3c0b14ca2e074425e29cc92a64a6 -F ext/session/sqlite3session.c e0345e8425a36fb8ac107175ebae46b4af8873e4 -F ext/session/sqlite3session.h c7db3d8515eba7f41eeb8698a25e58d24cd384bf -F ext/session/test_session.c 12053e9190653164fa624427cf90d1f46ca7f179 +F ext/session/sqlite3session.c 63eea3741e8ac1574d4c183fd92a6a50b1415357 +F ext/session/sqlite3session.h 6c35057241567ed6319f750ee504a81c459225e1 +F ext/session/test_session.c d38968307c05229cc8cd603722cf305d6f768832 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt f2b23a6bde8f1c6e86b957e4d94eab0add520b0d @@ -1119,7 +1120,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 3e4033285deb417bd72c008917729dbf3bf4e90d 0775501acf152dcbf4dd039f4511f3d8c4330d85 -R f6e422c39c44105817eb40d9d54618de -U drh -Z f9597afebde4efa08f5ab31e24bede7f +P 831492dca8bcfb1a1f83a8bb15de9cc94f29f07e +R cbce615b433685cc6c1cb9210155f0f8 +U dan +Z 2d1cb3afe326cb66267c2981ea353dde diff --git a/manifest.uuid b/manifest.uuid index 8fadc4e3f6..023cc42f5d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -831492dca8bcfb1a1f83a8bb15de9cc94f29f07e \ No newline at end of file +b7e4dd889d37c8f57c2d3c7900e802f644aac3ea \ No newline at end of file From fba5765b578cb65c52440af2079b951139fbfe55 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 11 Nov 2013 23:02:10 +0000 Subject: [PATCH 083/570] Fix two test cases (due to changes in the formatting of constraint errors) so that all tests now pass. FossilOrigin-Name: 129e2b69178147d04ee27fce66c17b39f8654da3 --- ext/session/session9.test | 6 ++---- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/ext/session/session9.test b/ext/session/session9.test index b6ead68991..3b42c31061 100644 --- a/ext/session/session9.test +++ b/ext/session/session9.test @@ -236,7 +236,7 @@ do_execsql_test 4.2.1 { PRAGMA defer_foreign_keys = 1; INSERT INTO c1 VALUES('x', 'x'); } -do_catchsql_test 4.2.2 { COMMIT } {1 {foreign key constraint failed}} +do_catchsql_test 4.2.2 { COMMIT } {1 {FOREIGN KEY constraint failed}} do_catchsql_test 4.2.3 { ROLLBACK } {0 {}} do_execsql_test 4.3.1 { @@ -246,11 +246,9 @@ do_execsql_test 4.3.1 { } do_catchsql_test 4.3.2 { INSERT INTO c1 VALUES(1, 'x') -} {1 {column a is not unique}} +} {1 {UNIQUE constraint failed: c1.a}} do_catchsql_test 4.3.3 { COMMIT } {0 {}} do_catchsql_test 4.3.4 { BEGIN ; COMMIT } {0 {}} finish_test - - diff --git a/manifest b/manifest index fcac3f7230..d26953124e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sin\sthe\sWITHOUT\sROWID\schanges.\s\sA\sfew\stests\sare\sfailing\snow.\s\sThey\swill\nbe\sfixed\sin\sa\sfollow-on\scheck-in. -D 2013-11-11T22:55:26.153 +C Fix\stwo\stest\scases\s(due\sto\schanges\sin\sthe\sformatting\sof\sconstraint\serrors)\nso\sthat\sall\stests\snow\spass. +D 2013-11-11T23:02:10.499 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in bb787d5227c6aa95915ff04e9634a0a469297ea4 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -146,7 +146,7 @@ F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 -F ext/session/session9.test 43acfdc57647c2ce4b36dbd0769112520ea6af14 +F ext/session/session9.test 776e46785c29c11cda01f5205d0f1e8f8f9a46bf F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 496291b287ba3c0b14ca2e074425e29cc92a64a6 @@ -1151,7 +1151,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P aa72ea8a004de7fe744fc13baef19d05aea607d5 f58d57017199421167dae8ebc67db2f19be45082 -R 3b17341d4c625bc46e3586e654b8390b +P 5addd1234ded59ce60fb633b76ac87d483377edd +R 7497a574757ea7847d650e9a557949cb U drh -Z 1cdf9fac9d6e4efb5a645c5741312eca +Z 55c6c2c9062609ee78397175c9785a12 diff --git a/manifest.uuid b/manifest.uuid index e437b594ea..767d2dcc1b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5addd1234ded59ce60fb633b76ac87d483377edd \ No newline at end of file +129e2b69178147d04ee27fce66c17b39f8654da3 \ No newline at end of file From b7bc8c984917c7ef714d4f1bfbea2916a35f1e3f Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 6 Mar 2014 14:53:25 +0000 Subject: [PATCH 084/570] Enhance the test harness for the sessions interface so that it does not use SQLite operations that can encounter an OOM error in places where it is unable to report an OOM error back up to the test script. FossilOrigin-Name: bc0e661033b78f27866932244e6204985ae39000 --- ext/session/test_session.c | 11 +++++++---- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 4340921a67..022cbc6679 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -159,7 +159,7 @@ static void test_session_del(void *clientData){ TestSession *p = (TestSession*)clientData; if( p->pFilterScript ) Tcl_DecrRefCount(p->pFilterScript); sqlite3session_delete(p->pSession); - ckfree(p); + ckfree((char*)p); } /* @@ -191,7 +191,7 @@ static int test_sqlite3session( memset(p, 0, sizeof(TestSession)); rc = sqlite3session_create(db, Tcl_GetString(objv[3]), &p->pSession); if( rc!=SQLITE_OK ){ - ckfree(p); + ckfree((char*)p); return test_session_error(interp, rc); } @@ -222,10 +222,13 @@ static void test_append_value(Tcl_Obj *pList, sqlite3_value *pVal){ Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("f", 1)); pObj = Tcl_NewDoubleObj(sqlite3_value_double(pVal)); break; - case SQLITE_TEXT: + case SQLITE_TEXT: { + const char *z = (char*)sqlite3_value_blob(pVal); + int n = sqlite3_value_bytes(pVal); Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("t", 1)); - pObj = Tcl_NewStringObj((char *)sqlite3_value_text(pVal), -1); + pObj = Tcl_NewStringObj(z, n); break; + } case SQLITE_BLOB: Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("b", 1)); pObj = Tcl_NewByteArrayObj( diff --git a/manifest b/manifest index 60f4a66dd8..3d8c760b5d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\slatest\s3.8.4\stweaks\sfrom\strunk. -D 2014-03-06T13:48:31.335 +C Enhance\sthe\stest\sharness\sfor\sthe\ssessions\sinterface\sso\sthat\sit\sdoes\snot\nuse\sSQLite\soperations\sthat\scan\sencounter\san\sOOM\serror\sin\splaces\swhere\sit\nis\sunable\sto\sreport\san\sOOM\serror\sback\sup\sto\sthe\stest\sscript. +D 2014-03-06T14:53:25.586 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -152,7 +152,7 @@ F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 496291b287ba3c0b14ca2e074425e29cc92a64a6 F ext/session/sqlite3session.c 34e19186d05d534e5a37a4f5a8a3c3e24e3fa88a F ext/session/sqlite3session.h 6c35057241567ed6319f750ee504a81c459225e1 -F ext/session/test_session.c d38968307c05229cc8cd603722cf305d6f768832 +F ext/session/test_session.c b74ddeb47ef034618af1e7e7f7d70dadfd61e13c F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt f439556c5ce01ced70987e5ee86549a45165d9ff @@ -1170,7 +1170,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P a1f2b0428518ec18af74a0e01deb4e40cd95a78f 0a4200f95cf46ad620b9fd91f4444114a0c74730 -R 6b398dedc2e443426b8d1ae4a040c589 +P 1ed463d91866182fbc884fb88770717ee5bf33ce +R 96958e98af456557b41c042e55a4957f U drh -Z 5e939e72ef6a3efe23540b139841828b +Z 0502c27f4f3e5bf50ee9c481e253dd89 diff --git a/manifest.uuid b/manifest.uuid index 732285ae0a..76378d0acd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1ed463d91866182fbc884fb88770717ee5bf33ce \ No newline at end of file +bc0e661033b78f27866932244e6204985ae39000 \ No newline at end of file From 87778c7f9692542c7be393ece73fab30366b6e75 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 6 Mar 2014 15:01:11 +0000 Subject: [PATCH 085/570] Fix a harmless compiler warning in the sessions test harness. FossilOrigin-Name: d389e20ab07a76d0c4be3801265977fa977a4394 --- ext/session/test_session.c | 2 +- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 022cbc6679..f1c2fbe9a3 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -253,7 +253,7 @@ static int test_obj_eq_string(Tcl_Obj *p, const char *z){ int nObj; char *zObj; - n = strlen(z); + n = (int)strlen(z); zObj = Tcl_GetStringFromObj(p, &nObj); return (nObj==n && (n==0 || 0==memcmp(zObj, z, n))); diff --git a/manifest b/manifest index 3d8c760b5d..8f664024a5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\stest\sharness\sfor\sthe\ssessions\sinterface\sso\sthat\sit\sdoes\snot\nuse\sSQLite\soperations\sthat\scan\sencounter\san\sOOM\serror\sin\splaces\swhere\sit\nis\sunable\sto\sreport\san\sOOM\serror\sback\sup\sto\sthe\stest\sscript. -D 2014-03-06T14:53:25.586 +C Fix\sa\sharmless\scompiler\swarning\sin\sthe\ssessions\stest\sharness. +D 2014-03-06T15:01:11.376 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -152,7 +152,7 @@ F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 496291b287ba3c0b14ca2e074425e29cc92a64a6 F ext/session/sqlite3session.c 34e19186d05d534e5a37a4f5a8a3c3e24e3fa88a F ext/session/sqlite3session.h 6c35057241567ed6319f750ee504a81c459225e1 -F ext/session/test_session.c b74ddeb47ef034618af1e7e7f7d70dadfd61e13c +F ext/session/test_session.c 7878ac0e2fe9675e8ec24d54f6a538ccc105977f F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt f439556c5ce01ced70987e5ee86549a45165d9ff @@ -1170,7 +1170,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 1ed463d91866182fbc884fb88770717ee5bf33ce -R 96958e98af456557b41c042e55a4957f +P bc0e661033b78f27866932244e6204985ae39000 +R 973bedbe61265104f3741c995c452b29 U drh -Z 0502c27f4f3e5bf50ee9c481e253dd89 +Z 1571e450ec5231b885fc926309559de1 diff --git a/manifest.uuid b/manifest.uuid index 76378d0acd..04ddcd160e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bc0e661033b78f27866932244e6204985ae39000 \ No newline at end of file +d389e20ab07a76d0c4be3801265977fa977a4394 \ No newline at end of file From dcc5c7b2fcdfbc89bea36650cdbaf454217783bb Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 11 Apr 2014 16:14:54 +0000 Subject: [PATCH 086/570] Update comments in the R-Tree module in preparation for some big changes. Add an "rtree" performance test to speedtest1. FossilOrigin-Name: 20a73ec0b2f56609a4504052e198e32803d30207 --- ext/rtree/rtree.c | 102 +++++++++++++++++++++++----------------------- manifest | 17 ++++---- manifest.uuid | 2 +- test/speedtest1.c | 97 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 158 insertions(+), 60 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index cefb9a8b2a..2034ff693f 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -110,6 +110,7 @@ #include "sqlite3rtree.h" typedef sqlite3_int64 i64; typedef unsigned char u8; +typedef unsigned short u16; typedef unsigned int u32; #endif @@ -135,7 +136,7 @@ typedef union RtreeCoord RtreeCoord; ** ever contain very many entries, so a fixed number of buckets is ** used. */ -#define HASHSIZE 128 +#define HASHSIZE 97 /* The xBestIndex method of this virtual table requires an estimate of ** the number of rows in the virtual table to calculate the costs of @@ -151,15 +152,15 @@ typedef union RtreeCoord RtreeCoord; ** An rtree virtual-table object. */ struct Rtree { - sqlite3_vtab base; + sqlite3_vtab base; /* Base class. Must be first */ sqlite3 *db; /* Host database connection */ int iNodeSize; /* Size in bytes of each node in the node table */ - int nDim; /* Number of dimensions */ - int nBytesPerCell; /* Bytes consumed per cell */ + u8 nDim; /* Number of dimensions */ + u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */ + u8 nBytesPerCell; /* Bytes consumed per cell */ int iDepth; /* Current depth of the r-tree structure */ char *zDb; /* Name of database containing r-tree table */ char *zName; /* Name of r-tree table */ - RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */ int nBusy; /* Current number of users of this structure */ i64 nRowEst; /* Estimated number of rows in this table */ @@ -186,10 +187,10 @@ struct Rtree { sqlite3_stmt *pWriteParent; sqlite3_stmt *pDeleteParent; - int eCoordType; + RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */ }; -/* Possible values for eCoordType: */ +/* Possible values for Rtree.eCoordType: */ #define RTREE_COORD_REAL32 0 #define RTREE_COORD_INT32 1 @@ -232,7 +233,7 @@ struct Rtree { ** An rtree cursor object. */ struct RtreeCursor { - sqlite3_vtab_cursor base; + sqlite3_vtab_cursor base; /* Base class. Must be first */ RtreeNode *pNode; /* Node cursor is currently pointing at */ int iCell; /* Index of current cell in pNode */ int iStrategy; /* Copy of idxNum search parameter */ @@ -240,9 +241,13 @@ struct RtreeCursor { RtreeConstraint *aConstraint; /* Search constraints. */ }; +/* +** A coordinate can be either a floating point number or a integer. All +** coordinates within a single R-Tree are always of the same time. +*/ union RtreeCoord { - RtreeValue f; - int i; + RtreeValue f; /* Floating point value */ + int i; /* Integer value */ }; /* @@ -284,21 +289,23 @@ struct RtreeConstraint { ** An rtree structure node. */ struct RtreeNode { - RtreeNode *pParent; /* Parent node */ - i64 iNode; - int nRef; - int isDirty; - u8 *zData; - RtreeNode *pNext; /* Next node in this hash chain */ + RtreeNode *pParent; /* Parent node */ + i64 iNode; /* The node number */ + int nRef; /* Number of references to this node */ + int isDirty; /* True if the node needs to be written to disk */ + u8 *zData; /* Content of the node, as should be on disk */ + RtreeNode *pNext; /* Next node in this hash collision chain */ }; + +/* Return the number of cells in a node */ #define NCELL(pNode) readInt16(&(pNode)->zData[2]) /* -** Structure to store a deserialized rtree record. +** A single cell from a node, deserialized */ struct RtreeCell { - i64 iRowid; - RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2]; + i64 iRowid; /* Node or entry ID */ + RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2]; /* Bounding box coordinates */ }; @@ -426,10 +433,7 @@ static void nodeZero(Rtree *pRtree, RtreeNode *p){ ** in the Rtree.aHash table. */ static int nodeHash(i64 iNode){ - return ( - (iNode>>56) ^ (iNode>>48) ^ (iNode>>40) ^ (iNode>>32) ^ - (iNode>>24) ^ (iNode>>16) ^ (iNode>> 8) ^ (iNode>> 0) - ) % HASHSIZE; + return iNode % HASHSIZE; } /* @@ -489,8 +493,7 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){ /* ** Obtain a reference to an r-tree node. */ -static int -nodeAcquire( +static int nodeAcquire( Rtree *pRtree, /* R-tree structure */ i64 iNode, /* Node number to load */ RtreeNode *pParent, /* Either the parent node or NULL */ @@ -579,10 +582,10 @@ nodeAcquire( ** Overwrite cell iCell of node pNode with the contents of pCell. */ static void nodeOverwriteCell( - Rtree *pRtree, - RtreeNode *pNode, - RtreeCell *pCell, - int iCell + Rtree *pRtree, /* The overall R-Tree */ + RtreeNode *pNode, /* The node into which the cell is to be written */ + RtreeCell *pCell, /* The cell to write */ + int iCell /* Index into pNode into which pCell is written */ ){ int ii; u8 *p = &pNode->zData[4 + pRtree->nBytesPerCell*iCell]; @@ -594,7 +597,7 @@ static void nodeOverwriteCell( } /* -** Remove cell the cell with index iCell from node pNode. +** Remove the cell with index iCell from node pNode. */ static void nodeDeleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell){ u8 *pDst = &pNode->zData[4 + pRtree->nBytesPerCell*iCell]; @@ -611,11 +614,10 @@ static void nodeDeleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell){ ** ** If there is not enough free space in pNode, return SQLITE_FULL. */ -static int -nodeInsertCell( - Rtree *pRtree, - RtreeNode *pNode, - RtreeCell *pCell +static int nodeInsertCell( + Rtree *pRtree, /* The overall R-Tree */ + RtreeNode *pNode, /* Write new cell into this node */ + RtreeCell *pCell /* The cell to be inserted */ ){ int nCell; /* Current number of cells in pNode */ int nMaxCell; /* Maximum number of cells for pNode */ @@ -636,8 +638,7 @@ nodeInsertCell( /* ** If the node is dirty, write it out to the database. */ -static int -nodeWrite(Rtree *pRtree, RtreeNode *pNode){ +static int nodeWrite(Rtree *pRtree, RtreeNode *pNode){ int rc = SQLITE_OK; if( pNode->isDirty ){ sqlite3_stmt *p = pRtree->pWriteNode; @@ -662,8 +663,7 @@ nodeWrite(Rtree *pRtree, RtreeNode *pNode){ ** Release a reference to a node. If the node is dirty and the reference ** count drops to zero, the node data is written to the database. */ -static int -nodeRelease(Rtree *pRtree, RtreeNode *pNode){ +static int nodeRelease(Rtree *pRtree, RtreeNode *pNode){ int rc = SQLITE_OK; if( pNode ){ assert( pNode->nRef>0 ); @@ -691,9 +691,9 @@ nodeRelease(Rtree *pRtree, RtreeNode *pNode){ ** an internal node, then the 64-bit integer is a child page number. */ static i64 nodeGetRowid( - Rtree *pRtree, - RtreeNode *pNode, - int iCell + Rtree *pRtree, /* The overall R-Tree */ + RtreeNode *pNode, /* The node from which to extract the ID */ + int iCell /* The cell index from which to extract the ID */ ){ assert( iCellzData[4 + pRtree->nBytesPerCell*iCell]); @@ -703,11 +703,11 @@ static i64 nodeGetRowid( ** Return coordinate iCoord from cell iCell in node pNode. */ static void nodeGetCoord( - Rtree *pRtree, - RtreeNode *pNode, - int iCell, - int iCoord, - RtreeCoord *pCoord /* Space to write result to */ + Rtree *pRtree, /* The overall R-Tree */ + RtreeNode *pNode, /* The node from which to extract a coordinate */ + int iCell, /* The index of the cell within the node */ + int iCoord, /* Which coordinate to extract */ + RtreeCoord *pCoord /* OUT: Space to write result to */ ){ readCoord(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord); } @@ -717,10 +717,10 @@ static void nodeGetCoord( ** to by pCell with the results. */ static void nodeGetCell( - Rtree *pRtree, - RtreeNode *pNode, - int iCell, - RtreeCell *pCell + Rtree *pRtree, /* The overall R-Tree */ + RtreeNode *pNode, /* The node containing the cell to be read */ + int iCell, /* Index of the cell within the node */ + RtreeCell *pCell /* OUT: Write the cell contents here */ ){ int ii; pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell); diff --git a/manifest b/manifest index 0602716bed..1a7e491bc3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sall\srecent\schanges\sfrom\strunk,\nincluding\sthe\sfix\sfor\sthe\sOP_SCopy-vs-OP_Copy\sproblem. -D 2014-04-03T16:35:33.203 +C Update\scomments\sin\sthe\sR-Tree\smodule\sin\spreparation\sfor\ssome\sbig\schanges.\nAdd\san\s"rtree"\sperformance\stest\sto\sspeedtest1. +D 2014-04-11T16:14:54.092 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 2d9f95da404d850474e628c720c5ce15d29b47de +F ext/rtree/rtree.c 043f16a6c3f823c760657b975f2ff1de7fe5c197 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -840,7 +840,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523 F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b -F test/speedtest1.c 90446861e566a9965a8d005381a3c964ff333646 +F test/speedtest1.c 3e06b48e8c578eaa61a01e8c7c4d8734c9dd3776 F test/spellfix.test 61309f5efbec53603b3f86457d34a504f80abafe F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298 F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de @@ -1174,7 +1174,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P fc8ca1a87e7127bd28f32fd809aec3e24355fbfa d5513dfa23baa0b0a095aaf17d19aacd30dcef61 -R 507e4fb477cf51261d2563e52f7cfa77 +P 9515c8344a6743bbb0c6a6e49fb79fb3139090df +R 57f2249bba89c44cd5839664eafe6658 +T *branch * rtree-enhancements +T *sym-rtree-enhancements * +T -sym-sessions * U drh -Z a91c37323943563a6d3bfb60a104e003 +Z bdd5cbefa0a4dcc9a9cc6ed610b85f71 diff --git a/manifest.uuid b/manifest.uuid index 7a0e457ea7..d8135897dd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9515c8344a6743bbb0c6a6e49fb79fb3139090df \ No newline at end of file +20a73ec0b2f56609a4504052e198e32803d30207 \ No newline at end of file diff --git a/test/speedtest1.c b/test/speedtest1.c index 28c24e0885..a32f12f923 100644 --- a/test/speedtest1.c +++ b/test/speedtest1.c @@ -931,6 +931,98 @@ void testset_cte(void){ } +/* Generate two numbers between 1 and mx. The first number is less than +** the second. Usually the numbers are near each other but can sometimes +** be far apart. +*/ +static void twoCoords( + unsigned mx, /* Range of 1..mx */ + unsigned *pX0, unsigned *pX1 /* OUT: write results here */ +){ + unsigned d, x0, x1, span; + + span = mx/100 + 1; + if( speedtest1_random()%3==0 ) span *= 3; + if( speedtest1_random()%17==0 ) span = mx - 5; + d = speedtest1_random()%span + 1; + x0 = speedtest1_random()%(mx-d) + 1; + x1 = x0 + d; + *pX0 = x0; + *pX1 = x1; +} + +/* +** A testset for the R-Tree virtual table +*/ +void testset_rtree(void){ + unsigned i, n; + unsigned mxCoord; + unsigned x0, x1, y0, y1, z0, z1; + + mxCoord = g.szTest*600; + n = g.szTest*100; + speedtest1_begin_test(100, "%d INSERTs into an r-tree", n); + speedtest1_exec("BEGIN"); + speedtest1_exec("CREATE VIRTUAL TABLE rt1 USING rtree(id,x0,x1,y0,y1,z0,z1)"); + speedtest1_prepare("INSERT INTO rt1(id,x0,x1,y0,y1,z0,z1)" + "VALUES(?1,?2,?3,?4,?5,?6,?7)"); + for(i=1; i<=n; i++){ + twoCoords(mxCoord, &x0, &x1); + twoCoords(mxCoord, &y0, &y1); + twoCoords(mxCoord, &z0, &z1); + sqlite3_bind_int(g.pStmt, 1, i); + sqlite3_bind_int(g.pStmt, 2, x0); + sqlite3_bind_int(g.pStmt, 3, x1); + sqlite3_bind_int(g.pStmt, 4, y0); + sqlite3_bind_int(g.pStmt, 5, y1); + sqlite3_bind_int(g.pStmt, 6, z0); + sqlite3_bind_int(g.pStmt, 7, z1); + speedtest1_run(); + } + speedtest1_exec("COMMIT"); + speedtest1_end_test(); + + n = g.szTest*20; + speedtest1_begin_test(110, "%d one-dimensional intersect slice queries", n); + speedtest1_prepare("SELECT count(*) FROM rt1 WHERE x0>=?1 AND x1<=?2"); + for(i=0; i=?1 AND y0<=?2"); + for(i=0; i=?1 AND x0<=?2" + " AND y1>=?1 AND y0<=?2 AND z1>=?1 AND z0<=?2"); + for(i=0; i Date: Fri, 11 Apr 2014 17:41:08 +0000 Subject: [PATCH 087/570] Add the --verify option to speedtest1. Add verification test cases to the "rtree" testset and a case that uses a custom geometry callback. FossilOrigin-Name: 9d485c4207a81f32334857d4a608c5c511dd2b83 --- manifest | 15 +++--- manifest.uuid | 2 +- test/speedtest1.c | 116 ++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 109 insertions(+), 24 deletions(-) diff --git a/manifest b/manifest index 1a7e491bc3..12cad8c970 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\scomments\sin\sthe\sR-Tree\smodule\sin\spreparation\sfor\ssome\sbig\schanges.\nAdd\san\s"rtree"\sperformance\stest\sto\sspeedtest1. -D 2014-04-11T16:14:54.092 +C Add\sthe\s--verify\soption\sto\sspeedtest1.\s\sAdd\sverification\stest\scases\sto\nthe\s"rtree"\stestset\sand\sa\scase\sthat\suses\sa\scustom\sgeometry\scallback. +D 2014-04-11T17:41:08.614 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -840,7 +840,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523 F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b -F test/speedtest1.c 3e06b48e8c578eaa61a01e8c7c4d8734c9dd3776 +F test/speedtest1.c 017473605f9df5f4770dd60ddb4038e6d6829916 F test/spellfix.test 61309f5efbec53603b3f86457d34a504f80abafe F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298 F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de @@ -1174,10 +1174,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 9515c8344a6743bbb0c6a6e49fb79fb3139090df -R 57f2249bba89c44cd5839664eafe6658 -T *branch * rtree-enhancements -T *sym-rtree-enhancements * -T -sym-sessions * +P 20a73ec0b2f56609a4504052e198e32803d30207 +R 47999e8bbddb67bbaef79a4f5741e58b U drh -Z bdd5cbefa0a4dcc9a9cc6ed610b85f71 +Z 73dffdddfd99e7f86f5cf9f646a8ff0c diff --git a/manifest.uuid b/manifest.uuid index d8135897dd..0d054cdd30 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -20a73ec0b2f56609a4504052e198e32803d30207 \ No newline at end of file +9d485c4207a81f32334857d4a608c5c511dd2b83 \ No newline at end of file diff --git a/test/speedtest1.c b/test/speedtest1.c index a32f12f923..0680e9599f 100644 --- a/test/speedtest1.c +++ b/test/speedtest1.c @@ -29,6 +29,7 @@ static const char zHelp[] = " --trace Turn on SQL tracing\n" " --utf16be Set text encoding to UTF-16BE\n" " --utf16le Set text encoding to UTF-16LE\n" + " --verify Run additional verification steps.\n" " --without-rowid Use WITHOUT ROWID where appropriate\n" ; @@ -51,6 +52,7 @@ static struct Global { int bReprepare; /* True to reprepare the SQL on each rerun */ int bSqlOnly; /* True to print the SQL once only */ int bExplain; /* Print SQL with EXPLAIN prefix */ + int bVerify; /* Try to verify that results are correct */ int szTest; /* Scale factor for test iterations */ const char *zWR; /* Might be WITHOUT ROWID */ const char *zNN; /* Might be NOT NULL */ @@ -951,6 +953,26 @@ static void twoCoords( *pX1 = x1; } +/* The following routine is an R-Tree geometry callback. It returns +** true if the object overlaps a slice on the Y coordinate between the +** two values given as arguments. In other words +** +** SELECT count(*) FROM rt1 WHERE id MATCH xslice(10,20); +** +** Is the same as saying: +** +** SELECT count(*) FROM rt1 WHERE y1>=10 AND y0<=20; +*/ +static int xsliceGeometryCallback( + sqlite3_rtree_geometry *p, + int nCoord, + double *aCoord, + int *pRes +){ + *pRes = aCoord[3]>=p->aParam[0] && aCoord[2]<=p->aParam[1]; + return SQLITE_OK; +} + /* ** A testset for the R-Tree virtual table */ @@ -958,6 +980,8 @@ void testset_rtree(void){ unsigned i, n; unsigned mxCoord; unsigned x0, x1, y0, y1, z0, z1; + unsigned iStep; + int *aCheck = sqlite3_malloc( sizeof(int)*g.szTest*100 ); mxCoord = g.szTest*600; n = g.szTest*100; @@ -982,23 +1006,83 @@ void testset_rtree(void){ speedtest1_exec("COMMIT"); speedtest1_end_test(); - n = g.szTest*20; - speedtest1_begin_test(110, "%d one-dimensional intersect slice queries", n); - speedtest1_prepare("SELECT count(*) FROM rt1 WHERE x0>=?1 AND x1<=?2"); - for(i=0; i=?1 AND x1<=?2"); + iStep = mxCoord/n; + for(i=0; i=?1 AND x1<=?2"); + iStep = mxCoord/n; + for(i=0; i=?1 AND y0<=?2"); - for(i=0; i=?1 AND y0<=?2"); + iStep = mxCoord/n; + for(i=0; i=?1 AND x0<=?2" " AND y1>=?1 AND y0<=?2 AND z1>=?1 AND z0<=?2"); - for(i=0; i Date: Fri, 11 Apr 2014 23:14:48 +0000 Subject: [PATCH 088/570] Add the new interfaces to rtree, though they do not yet work. Add the "show_speedtest1_rtree.tcl" script for showing the test data used for the R-Tree tests of speedtest1. Change speedtest1 to generate better R-Tree test data. FossilOrigin-Name: 0b70275972c7a6a533566c1e50bffbf3ac531e95 --- ext/rtree/rtree.c | 68 +++++++++++++++++++++++++--------- ext/rtree/sqlite3rtree.h | 61 +++++++++++++++++++++++++++--- main.mk | 2 +- manifest | 19 +++++----- manifest.uuid | 2 +- test/show_speedtest1_rtree.tcl | 57 ++++++++++++++++++++++++++++ test/speedtest1.c | 17 +++++---- 7 files changed, 184 insertions(+), 42 deletions(-) create mode 100644 test/show_speedtest1_rtree.tcl diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 2034ff693f..ddfc3d79a1 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -324,21 +324,24 @@ struct RtreeCell { struct RtreeMatchArg { u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue*, int *); + int (*xQueryFunc)(sqlite3_rtree_query_info*); void *pContext; int nParam; RtreeDValue aParam[1]; }; /* -** When a geometry callback is created (see sqlite3_rtree_geometry_callback), +** When a geometry callback is created using either +** sqlite3_rtree_geometry_callback() or sqlite3_rtree_query_callback(), ** a single instance of the following structure is allocated. It is used -** as the context for the user-function created by by s_r_g_c(). The object -** is eventually deleted by the destructor mechanism provided by -** sqlite3_create_function_v2() (which is called by s_r_g_c() to create -** the geometry callback function). +** as the context for the user-function created by sqlite3_rtree_*_callback(). +** The object is eventually deleted by the destructor mechanism provided by +** sqlite3_create_function_v2(). */ struct RtreeGeomCallback { int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); + int (*xQueryFunc)(sqlite3_rtree_query_info*); + void (*xDestructor)(void*); void *pContext; }; @@ -3352,22 +3355,23 @@ int sqlite3RtreeInit(sqlite3 *db){ } /* -** A version of sqlite3_free() that can be used as a callback. This is used -** in two places - as the destructor for the blob value returned by the -** invocation of a geometry function, and as the destructor for the geometry -** functions themselves. +** This routine is called when a custom geometry function or custom query +** function is cancelled. The pointer is to a RtreeGeomCallback object +** that needs to be freed. */ -static void doSqlite3Free(void *p){ +static void rtreeFreeCallback(void *p){ + RtreeGeomCallback *pGeom = (RtreeGeomCallback*)p; + if( pGeom->xDestructor ) pGeom->xDestructor(pGeom->pContext); sqlite3_free(p); } /* -** Each call to sqlite3_rtree_geometry_callback() creates an ordinary SQLite -** scalar user function. This C function is the callback used for all such -** registered SQL functions. +** Each call to sqlite3_rtree_geometry_callback() or +** sqlite3_rtree_query_callback() creates an ordinary SQLite +** scalar user function that is implemented by this routine. ** -** The scalar user functions return a blob that is interpreted by r-tree -** table MATCH operators. +** This function returns a blob that is interpreted by r-tree +** table MATCH operator. */ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); @@ -3391,7 +3395,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ pBlob->aParam[i] = sqlite3_value_double(aArg[i]); #endif } - sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free); + sqlite3_result_blob(ctx, pBlob, nBlob, sqlite3_free); } } @@ -3410,12 +3414,42 @@ int sqlite3_rtree_geometry_callback( pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback)); if( !pGeomCtx ) return SQLITE_NOMEM; pGeomCtx->xGeom = xGeom; + pGeomCtx->xQueryFunc = 0; + pGeomCtx->xDestructor = 0; pGeomCtx->pContext = pContext; /* Create the new user-function. Register a destructor function to delete ** the context object when it is no longer required. */ return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY, - (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free + (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback + ); +} + +/* +** Register a new 2nd-generation geometry function for use with the +** r-tree MATCH operator. +*/ +int sqlite3_rtree_query_callback( + sqlite3 *db, + const char *zQueryFunc, + int (*xQueryFunc)(sqlite3_rtree_query_info*), + void *pContext, + void (*xDestructor)(void*) +){ + RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ + + /* Allocate and populate the context object. */ + pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback)); + if( !pGeomCtx ) return SQLITE_NOMEM; + pGeomCtx->xGeom = 0; + pGeomCtx->xQueryFunc = xQueryFunc; + pGeomCtx->xDestructor = xDestructor; + pGeomCtx->pContext = pContext; + + /* Create the new user-function. Register a destructor function to delete + ** the context object when it is no longer required. */ + return sqlite3_create_function_v2(db, zQueryFunc, -1, SQLITE_ANY, + (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback ); } diff --git a/ext/rtree/sqlite3rtree.h b/ext/rtree/sqlite3rtree.h index c849091f29..79d1ffeede 100644 --- a/ext/rtree/sqlite3rtree.h +++ b/ext/rtree/sqlite3rtree.h @@ -21,6 +21,16 @@ extern "C" { #endif typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; +typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info; + +/* The double-precision datatype used by RTree depends on the +** SQLITE_RTREE_INT_ONLY compile-time option. +*/ +#ifdef SQLITE_RTREE_INT_ONLY + typedef sqlite3_int64 sqlite3_rtree_dbl; +#else + typedef double sqlite3_rtree_dbl; +#endif /* ** Register a geometry callback named zGeom that can be used as part of an @@ -31,11 +41,7 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, -#ifdef SQLITE_RTREE_INT_ONLY - int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes), -#else - int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes), -#endif + int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), void *pContext ); @@ -47,11 +53,54 @@ int sqlite3_rtree_geometry_callback( struct sqlite3_rtree_geometry { void *pContext; /* Copy of pContext passed to s_r_g_c() */ int nParam; /* Size of array aParam[] */ - double *aParam; /* Parameters passed to SQL geom function */ + sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */ void *pUser; /* Callback implementation user data */ void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ }; +/* +** Register a 2nd-generation geometry callback named zScore that can be +** used as part of an R-Tree geometry query as follows: +** +** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) +*/ +int sqlite3_rtree_query_callback( + sqlite3 *db, + const char *zQueryFunc, + int (*xQueryFunc)(sqlite3_rtree_query_info*), + void *pContext, + void (*xDestructor)(void*) +); + + +/* +** A pointer to a structure of the following type is passed as the +** argument to scored geometry callback registered using +** sqlite3_rtree_query_callback(). +*/ +struct sqlite3_rtree_query_info { + void *pContext; /* pContext from when function registered */ + int nParam; /* Number of function parameters */ + sqlite3_rtree_dbl *aParam; /* value of function parameters */ + void *pUser; /* callback can use this, if desired */ + void (*xDelUser)(void*); /* function to free pUser */ + sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */ + int nCoord; /* Number of coordinates */ + int iLevel; /* Level of current node or entry */ + sqlite3_int64 iRowid; /* Rowid for current entry */ + sqlite3_rtree_dbl rParentScore; /* Score of parent node */ + int eParentWithin; /* Visibility of parent node */ + int eWithin; /* OUT: Visiblity */ + sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ +}; + +/* +** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin. +*/ +#define NOT_WITHIN 0 /* Object completely outside of query region */ +#define PARTLY_WITHIN 1 /* Object partially overlaps query region */ +#define FULLY_WITHIN 2 /* Object fully contained within query region */ + #ifdef __cplusplus } /* end of the 'extern "C"' block */ diff --git a/main.mk b/main.mk index d7f8aaa3dd..57757ccc6a 100644 --- a/main.mk +++ b/main.mk @@ -483,7 +483,7 @@ parse.c: $(TOP)/src/parse.y lemon $(TOP)/addopcodes.awk mv parse.h parse.h.temp $(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h -sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION +sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION $(TOP)/ext/rtree/sqlite3rtree.h tclsh $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h keywordhash.h: $(TOP)/tool/mkkeywordhash.c diff --git a/manifest b/manifest index 12cad8c970..af46986305 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s--verify\soption\sto\sspeedtest1.\s\sAdd\sverification\stest\scases\sto\nthe\s"rtree"\stestset\sand\sa\scase\sthat\suses\sa\scustom\sgeometry\scallback. -D 2014-04-11T17:41:08.614 +C Add\sthe\snew\sinterfaces\sto\srtree,\sthough\sthey\sdo\snot\syet\swork.\s\sAdd\sthe\n"show_speedtest1_rtree.tcl"\sscript\sfor\sshowing\sthe\stest\sdata\sused\sfor\sthe\nR-Tree\stests\sof\sspeedtest1.\s\sChange\sspeedtest1\sto\sgenerate\sbetter\sR-Tree\ntest\sdata. +D 2014-04-11T23:14:48.914 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 043f16a6c3f823c760657b975f2ff1de7fe5c197 +F ext/rtree/rtree.c 541016f8a53bbedda4dc2deb0067f6955b0accb9 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -137,7 +137,7 @@ F ext/rtree/rtreeC.test 16d7aa86ecb6a876d2a38cf590a1471a41b3a46d F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea -F ext/rtree/sqlite3rtree.h c34c1e41d1ab80bb8ad09aae402c9c956871a765 +F ext/rtree/sqlite3rtree.h f93a466456ed25a9dadf90ad050e2945a2c49cff F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test 894e3bc9f497c4fa07a2aa3271e3911f3670c3d8 @@ -157,7 +157,7 @@ F ext/session/test_session.c 7878ac0e2fe9675e8ec24d54f6a538ccc105977f F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt f439556c5ce01ced70987e5ee86549a45165d9ff -F main.mk a3028a846754a96c8841d1a7227890c471c65ec2 +F main.mk 82b154dd823b75c2f1247f1bb98893bf94a5af57 F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 @@ -825,6 +825,7 @@ F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29 F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9 F test/shell5.test bb755ea9144b8078a752fc56223582627070b5f1 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 +F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5 F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868 F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329 F test/skipscan1.test bed8cbe9d554c8c27afb6c88500f704c86a9196f @@ -840,7 +841,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523 F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b -F test/speedtest1.c 017473605f9df5f4770dd60ddb4038e6d6829916 +F test/speedtest1.c d29c8048beb7ea9254191f3fde9414709166a920 F test/spellfix.test 61309f5efbec53603b3f86457d34a504f80abafe F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298 F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de @@ -1174,7 +1175,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 20a73ec0b2f56609a4504052e198e32803d30207 -R 47999e8bbddb67bbaef79a4f5741e58b +P 9d485c4207a81f32334857d4a608c5c511dd2b83 +R 0017d933bc77106350e8e33449b1c08c U drh -Z 73dffdddfd99e7f86f5cf9f646a8ff0c +Z 0d8113e9fad970081c8175cf29f2569d diff --git a/manifest.uuid b/manifest.uuid index 0d054cdd30..1c530a4dc8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9d485c4207a81f32334857d4a608c5c511dd2b83 \ No newline at end of file +0b70275972c7a6a533566c1e50bffbf3ac531e95 \ No newline at end of file diff --git a/test/show_speedtest1_rtree.tcl b/test/show_speedtest1_rtree.tcl new file mode 100644 index 0000000000..3faa168146 --- /dev/null +++ b/test/show_speedtest1_rtree.tcl @@ -0,0 +1,57 @@ +#!/usr/bin/tclsh +# +# This script displays the field of rectangles used by --testset rtree +# of speedtest1. Run this script as follows: +# +# rm test.db +# ./speedtest1 --testset rtree --size 25 test.db +# sqlite3 --separator ' ' test.db 'SELECT * FROM rt1' >data.txt +# wish show_speedtest1_rtree.tcl +# +# The filename "data.txt" is hard coded into this script and so that name +# must be used on lines 3 and 4 above. Elsewhere, different filenames can +# be used. The --size N parameter can be adjusted as desired. +# +package require Tk +set f [open data.txt rb] +set data [read $f] +close $f +canvas .c +frame .b +button .b.b1 -text X-Y -command refill-xy +button .b.b2 -text X-Z -command refill-xz +button .b.b3 -text Y-Z -command refill-yz +pack .b.b1 .b.b2 .b.b3 -side left +pack .c -side top -fill both -expand 1 +pack .b -side top +proc resize_canvas_to_fit {} { + foreach {x0 y0 x1 y1} [.c bbox all] break + set w [expr {$x1-$x0}] + set h [expr {$y1-$y0}] + .c config -width $w -height $h +} +proc refill-xy {} { + .c delete all + foreach {id x0 x1 y0 y1 z0 z1} $::data { + .c create rectangle $x0 $y0 $x1 $y1 + } + .c scale all 0 0 0.05 0.05 + resize_canvas_to_fit +} +proc refill-xz {} { + .c delete all + foreach {id x0 x1 y0 y1 z0 z1} $::data { + .c create rectangle $x0 $z0 $x1 $z1 + } + .c scale all 0 0 0.05 0.05 + resize_canvas_to_fit +} +proc refill-yz {} { + .c delete all + foreach {id x0 x1 y0 y1 z0 z1} $::data { + .c create rectangle $y0 $z0 $y1 $z1 + } + .c scale all 0 0 0.05 0.05 + resize_canvas_to_fit +} +refill-xy diff --git a/test/speedtest1.c b/test/speedtest1.c index 0680e9599f..383f5809a9 100644 --- a/test/speedtest1.c +++ b/test/speedtest1.c @@ -938,14 +938,15 @@ void testset_cte(void){ ** be far apart. */ static void twoCoords( + int p1, int p2, /* Parameters adjusting sizes */ unsigned mx, /* Range of 1..mx */ unsigned *pX0, unsigned *pX1 /* OUT: write results here */ ){ unsigned d, x0, x1, span; span = mx/100 + 1; - if( speedtest1_random()%3==0 ) span *= 3; - if( speedtest1_random()%17==0 ) span = mx - 5; + if( speedtest1_random()%3==0 ) span *= p1; + if( speedtest1_random()%p2==0 ) span = mx/2; d = speedtest1_random()%span + 1; x0 = speedtest1_random()%(mx-d) + 1; x1 = x0 + d; @@ -976,14 +977,14 @@ static int xsliceGeometryCallback( /* ** A testset for the R-Tree virtual table */ -void testset_rtree(void){ +void testset_rtree(int p1, int p2){ unsigned i, n; unsigned mxCoord; unsigned x0, x1, y0, y1, z0, z1; unsigned iStep; int *aCheck = sqlite3_malloc( sizeof(int)*g.szTest*100 ); - mxCoord = g.szTest*600; + mxCoord = 15000; n = g.szTest*100; speedtest1_begin_test(100, "%d INSERTs into an r-tree", n); speedtest1_exec("BEGIN"); @@ -991,9 +992,9 @@ void testset_rtree(void){ speedtest1_prepare("INSERT INTO rt1(id,x0,x1,y0,y1,z0,z1)" "VALUES(?1,?2,?3,?4,?5,?6,?7)"); for(i=1; i<=n; i++){ - twoCoords(mxCoord, &x0, &x1); - twoCoords(mxCoord, &y0, &y1); - twoCoords(mxCoord, &z0, &z1); + twoCoords(p1, p2, mxCoord, &x0, &x1); + twoCoords(p1, p2, mxCoord, &y0, &y1); + twoCoords(p1, p2, mxCoord, &z0, &z1); sqlite3_bind_int(g.pStmt, 1, i); sqlite3_bind_int(g.pStmt, 2, x0); sqlite3_bind_int(g.pStmt, 3, x1); @@ -1322,7 +1323,7 @@ int main(int argc, char **argv){ }else if( strcmp(zTSet,"cte")==0 ){ testset_cte(); }else if( strcmp(zTSet,"rtree")==0 ){ - testset_rtree(); + testset_rtree(6, 147); }else{ fatal_error("unknown testset: \"%s\"\nChoices: main debug1 cte rtree\n", zTSet); From 0ccb6cdc874181048268ecafbbc90725a0056118 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 12 Apr 2014 17:44:00 +0000 Subject: [PATCH 089/570] Continuing clean-up of the R-Tree module in preparation for cutting in the new generalized query mechanism. FossilOrigin-Name: 66c858f20586424e15d0bfa3d7b56643bde66226 --- ext/rtree/rtree.c | 121 ++++++++++++++++++++++++--------------------- manifest | 14 +++--- manifest.uuid | 2 +- src/test_rtree.c | 123 ++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 185 insertions(+), 75 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index ddfc3d79a1..e85fe4449d 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -289,12 +289,12 @@ struct RtreeConstraint { ** An rtree structure node. */ struct RtreeNode { - RtreeNode *pParent; /* Parent node */ - i64 iNode; /* The node number */ - int nRef; /* Number of references to this node */ - int isDirty; /* True if the node needs to be written to disk */ - u8 *zData; /* Content of the node, as should be on disk */ - RtreeNode *pNext; /* Next node in this hash collision chain */ + RtreeNode *pParent; /* Parent node */ + i64 iNode; /* The node number */ + int nRef; /* Number of references to this node */ + int isDirty; /* True if the node needs to be written to disk */ + u8 *zData; /* Content of the node, as should be on disk */ + RtreeNode *pNext; /* Next node in this hash collision chain */ }; /* Return the number of cells in a node */ @@ -310,32 +310,17 @@ struct RtreeCell { /* -** Value for the first field of every RtreeMatchArg object. The MATCH -** operator tests that the first field of a blob operand matches this -** value to avoid operating on invalid blobs (which could cause a segfault). -*/ -#define RTREE_GEOMETRY_MAGIC 0x891245AB - -/* -** An instance of this structure must be supplied as a blob argument to -** the right-hand-side of an SQL MATCH operator used to constrain an -** r-tree query. -*/ -struct RtreeMatchArg { - u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ - int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue*, int *); - int (*xQueryFunc)(sqlite3_rtree_query_info*); - void *pContext; - int nParam; - RtreeDValue aParam[1]; -}; - -/* -** When a geometry callback is created using either -** sqlite3_rtree_geometry_callback() or sqlite3_rtree_query_callback(), -** a single instance of the following structure is allocated. It is used -** as the context for the user-function created by sqlite3_rtree_*_callback(). -** The object is eventually deleted by the destructor mechanism provided by +** This object becomes the sqlite3_user_data() for the SQL functions +** that are created by sqlite3_rtree_geometry_callback() and +** sqlite3_rtree_query_callback() and which appear on the right of MATCH +** operators in order to constrain a search. +** +** xGeom and xQueryFunc are the callback functions. Exactly one of +** xGeom and xQueryFunc fields is non-NULL, depending on whether the +** SQL function was created using sqlite3_rtree_geometry_callback() or +** sqlite3_rtree_query_callback(). +** +** This object is deleted automatically by the destructor mechanism in ** sqlite3_create_function_v2(). */ struct RtreeGeomCallback { @@ -345,6 +330,27 @@ struct RtreeGeomCallback { void *pContext; }; + +/* +** Value for the first field of every RtreeMatchArg object. The MATCH +** operator tests that the first field of a blob operand matches this +** value to avoid operating on invalid blobs (which could cause a segfault). +*/ +#define RTREE_GEOMETRY_MAGIC 0x891245AB + +/* +** An instance of this structure (in the form of a BLOB) is returned by +** the SQL functions that sqlite3_rtree_geometry_callback() and +** sqlite3_rtree_query_callback() create, and is read as the right-hand +** operand to the MATCH operator of an R-Tree. +*/ +struct RtreeMatchArg { + u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ + RtreeGeomCallback cb; /* Info about the callback functions */ + int nParam; /* Number of parameters to the SQL function */ + RtreeDValue aParam[1]; /* Values for parameters to the SQL function */ +}; + #ifndef MAX # define MAX(x,y) ((x) < (y) ? (y) : (x)) #endif @@ -1253,11 +1259,11 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ return SQLITE_ERROR; } - pGeom->pContext = p->pContext; + pGeom->pContext = p->cb.pContext; pGeom->nParam = p->nParam; pGeom->aParam = p->aParam; - pCons->xGeom = p->xGeom; + pCons->xGeom = p->cb.xGeom; pCons->pGeom = pGeom; return SQLITE_OK; } @@ -3355,9 +3361,11 @@ int sqlite3RtreeInit(sqlite3 *db){ } /* -** This routine is called when a custom geometry function or custom query -** function is cancelled. The pointer is to a RtreeGeomCallback object -** that needs to be freed. +** This routine deletes the RtreeGeomCallback object that was attached +** one of the SQL functions create by sqlite3_rtree_geometry_callback() +** or sqlite3_rtree_query_callback(). In other words, this routine is the +** destructor for an RtreeGeomCallback objecct. This routine is called when +** the corresponding SQL function is deleted. */ static void rtreeFreeCallback(void *p){ RtreeGeomCallback *pGeom = (RtreeGeomCallback*)p; @@ -3368,10 +3376,16 @@ static void rtreeFreeCallback(void *p){ /* ** Each call to sqlite3_rtree_geometry_callback() or ** sqlite3_rtree_query_callback() creates an ordinary SQLite -** scalar user function that is implemented by this routine. +** scalar function that is implemented by this routine. ** -** This function returns a blob that is interpreted by r-tree -** table MATCH operator. +** All this function does is construct an RtreeMatchArg object that +** contains the geometry-checking callback routines and a list of +** parameters to this function, then return that RtreeMatchArg object +** as a BLOB. +** +** The R-Tree MATCH operator will read the returned BLOB, deserialize +** the RtreeMatchArg object, and use the RtreeMatchArg object to figure +** out which elements of the R-Tree should be returned by the query. */ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); @@ -3385,8 +3399,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ }else{ int i; pBlob->magic = RTREE_GEOMETRY_MAGIC; - pBlob->xGeom = pGeomCtx->xGeom; - pBlob->pContext = pGeomCtx->pContext; + pBlob->cb = pGeomCtx[0]; pBlob->nParam = nArg; for(i=0; ixQueryFunc = 0; pGeomCtx->xDestructor = 0; pGeomCtx->pContext = pContext; - - /* Create the new user-function. Register a destructor function to delete - ** the context object when it is no longer required. */ return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY, (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback ); @@ -3430,11 +3440,11 @@ int sqlite3_rtree_geometry_callback( ** r-tree MATCH operator. */ int sqlite3_rtree_query_callback( - sqlite3 *db, - const char *zQueryFunc, - int (*xQueryFunc)(sqlite3_rtree_query_info*), - void *pContext, - void (*xDestructor)(void*) + sqlite3 *db, /* Register SQL function on this connection */ + const char *zQueryFunc, /* Name of new SQL function */ + int (*xQueryFunc)(sqlite3_rtree_query_info*), /* Callback */ + void *pContext, /* Extra data passed into the callback */ + void (*xDestructor)(void*) /* Destructor for the extra data */ ){ RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ @@ -3445,9 +3455,6 @@ int sqlite3_rtree_query_callback( pGeomCtx->xQueryFunc = xQueryFunc; pGeomCtx->xDestructor = xDestructor; pGeomCtx->pContext = pContext; - - /* Create the new user-function. Register a destructor function to delete - ** the context object when it is no longer required. */ return sqlite3_create_function_v2(db, zQueryFunc, -1, SQLITE_ANY, (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback ); diff --git a/manifest b/manifest index af46986305..0f929e7155 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\snew\sinterfaces\sto\srtree,\sthough\sthey\sdo\snot\syet\swork.\s\sAdd\sthe\n"show_speedtest1_rtree.tcl"\sscript\sfor\sshowing\sthe\stest\sdata\sused\sfor\sthe\nR-Tree\stests\sof\sspeedtest1.\s\sChange\sspeedtest1\sto\sgenerate\sbetter\sR-Tree\ntest\sdata. -D 2014-04-11T23:14:48.914 +C Continuing\sclean-up\sof\sthe\sR-Tree\smodule\sin\spreparation\sfor\scutting\sin\sthe\nnew\sgeneralized\squery\smechanism. +D 2014-04-12T17:44:00.241 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 541016f8a53bbedda4dc2deb0067f6955b0accb9 +F ext/rtree/rtree.c 8778f55ece9016ab3b17969f19f9656a06f6e100 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -274,7 +274,7 @@ F src/test_osinst.c 90a845c8183013d80eccb1f29e8805608516edba F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00 F src/test_quota.c 30c64f0ef84734f2231a686df41ed882b0c59bc0 F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb -F src/test_rtree.c f3d1d12538dccb75fd916e3fa58f250edbdd3b47 +F src/test_rtree.c cd35d54c0b847c0c373d66f91616c49697ab4edf F src/test_schema.c cd12a2223c3a394f4d07bb93bdf6d344c5c121b6 F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe F src/test_sqllog.c c1c1bbedbcaf82b93d83e4f9dd990e62476a680e @@ -1175,7 +1175,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 9d485c4207a81f32334857d4a608c5c511dd2b83 -R 0017d933bc77106350e8e33449b1c08c +P 0b70275972c7a6a533566c1e50bffbf3ac531e95 +R 958d8acaf66c9f2ba2d270349d1218f7 U drh -Z 0d8113e9fad970081c8175cf29f2569d +Z 02617e452696d44ca40af16d5a687407 diff --git a/manifest.uuid b/manifest.uuid index 1c530a4dc8..866d285af2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0b70275972c7a6a533566c1e50bffbf3ac531e95 \ No newline at end of file +66c858f20586424e15d0bfa3d7b56643bde66226 \ No newline at end of file diff --git a/src/test_rtree.c b/src/test_rtree.c index e1966c2437..3b4c205879 100644 --- a/src/test_rtree.c +++ b/src/test_rtree.c @@ -50,11 +50,7 @@ static void circle_del(void *p){ static int circle_geom( sqlite3_rtree_geometry *p, int nCoord, -#ifdef SQLITE_RTREE_INT_ONLY - sqlite3_int64 *aCoord, -#else - double *aCoord, -#endif + sqlite3_rtree_dbl *aCoord, int *pRes ){ int i; /* Iterator variable */ @@ -154,6 +150,113 @@ static int circle_geom( return SQLITE_OK; } +/* +** Implementation of "circle" r-tree geometry callback using the +** 2nd-generation interface that allows scoring. +*/ +static int circle_query_func(sqlite3_rtree_query_info *p){ + int i; /* Iterator variable */ + Circle *pCircle; /* Structure defining circular region */ + double xmin, xmax; /* X dimensions of box being tested */ + double ymin, ymax; /* X dimensions of box being tested */ + int nWithin = 0; /* Number of corners inside the circle */ + + if( p->pUser==0 ){ + /* If pUser is still 0, then the parameter values have not been tested + ** for correctness or stored into a Circle structure yet. Do this now. */ + + /* This geometry callback is for use with a 2-dimensional r-tree table. + ** Return an error if the table does not have exactly 2 dimensions. */ + if( p->nCoord!=4 ) return SQLITE_ERROR; + + /* Test that the correct number of parameters (3) have been supplied, + ** and that the parameters are in range (that the radius of the circle + ** radius is greater than zero). */ + if( p->nParam!=3 || p->aParam[2]<0.0 ) return SQLITE_ERROR; + + /* Allocate a structure to cache parameter data in. Return SQLITE_NOMEM + ** if the allocation fails. */ + pCircle = (Circle *)(p->pUser = sqlite3_malloc(sizeof(Circle))); + if( !pCircle ) return SQLITE_NOMEM; + p->xDelUser = circle_del; + + /* Record the center and radius of the circular region. One way that + ** tested bounding boxes that intersect the circular region are detected + ** is by testing if each corner of the bounding box lies within radius + ** units of the center of the circle. */ + pCircle->centerx = p->aParam[0]; + pCircle->centery = p->aParam[1]; + pCircle->radius = p->aParam[2]; + + /* Define two bounding box regions. The first, aBox[0], extends to + ** infinity in the X dimension. It covers the same range of the Y dimension + ** as the circular region. The second, aBox[1], extends to infinity in + ** the Y dimension and is constrained to the range of the circle in the + ** X dimension. + ** + ** Then imagine each box is split in half along its short axis by a line + ** that intersects the center of the circular region. A bounding box + ** being tested can be said to intersect the circular region if it contains + ** points from each half of either of the two infinite bounding boxes. + */ + pCircle->aBox[0].xmin = pCircle->centerx; + pCircle->aBox[0].xmax = pCircle->centerx; + pCircle->aBox[0].ymin = pCircle->centery + pCircle->radius; + pCircle->aBox[0].ymax = pCircle->centery - pCircle->radius; + pCircle->aBox[1].xmin = pCircle->centerx + pCircle->radius; + pCircle->aBox[1].xmax = pCircle->centerx - pCircle->radius; + pCircle->aBox[1].ymin = pCircle->centery; + pCircle->aBox[1].ymax = pCircle->centery; + } + + pCircle = (Circle *)p->pUser; + xmin = p->aCoord[0]; + xmax = p->aCoord[1]; + ymin = p->aCoord[2]; + ymax = p->aCoord[3]; + + /* Check if any of the 4 corners of the bounding-box being tested lie + ** inside the circular region. If they do, then the bounding-box does + ** intersect the region of interest. Set the output variable to true and + ** return SQLITE_OK in this case. */ + for(i=0; i<4; i++){ + double x = (i&0x01) ? xmax : xmin; + double y = (i&0x02) ? ymax : ymin; + double d2; + + d2 = (x-pCircle->centerx)*(x-pCircle->centerx); + d2 += (y-pCircle->centery)*(y-pCircle->centery); + if( d2<(pCircle->radius*pCircle->radius) ) nWithin++; + } + + /* Check if the bounding box covers any other part of the circular region. + ** See comments above for a description of how this test works. If it does + ** cover part of the circular region, set the output variable to true + ** and return SQLITE_OK. */ + if( nWithin==0 ){ + for(i=0; i<2; i++){ + if( xmin<=pCircle->aBox[i].xmin + && xmax>=pCircle->aBox[i].xmax + && ymin<=pCircle->aBox[i].ymin + && ymax>=pCircle->aBox[i].ymax + ){ + nWithin = 1; + break; + } + } + } + + p->rScore = p->iLevel; + if( nWithin==0 ){ + p->eWithin = NOT_WITHIN; + }else if( nWithin>=4 ){ + p->eWithin = FULLY_WITHIN; + }else{ + p->eWithin = PARTLY_WITHIN; + } + return SQLITE_OK; +} + /* END of implementation of "circle" geometry callback. ************************************************************************** *************************************************************************/ @@ -194,11 +297,7 @@ static int gHere = 42; static int cube_geom( sqlite3_rtree_geometry *p, int nCoord, -#ifdef SQLITE_RTREE_INT_ONLY - sqlite3_int64 *aCoord, -#else - double *aCoord, -#endif + sqlite3_rtree_dbl *aCoord, int *piRes ){ Cube *pCube = (Cube *)p->pUser; @@ -293,6 +392,10 @@ static int register_circle_geom( } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; rc = sqlite3_rtree_geometry_callback(db, "circle", circle_geom, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_rtree_query_callback(db, "Qcircle", + circle_query_func, 0, 0); + } Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); #endif return TCL_OK; From 8ae04b53c9a6d8e221ae4ecbe7eabd0c032fdee7 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 13 Apr 2014 16:10:09 +0000 Subject: [PATCH 090/570] Continuing work on the new custom query mechanism for r-tree. FossilOrigin-Name: ca7357e66ca60f59477b1db000c2cdaeb8082ae1 --- ext/rtree/rtree.c | 49 +++++++++++++++++++++------------------- ext/rtree/sqlite3rtree.h | 4 ++++ manifest | 14 ++++++------ manifest.uuid | 2 +- 4 files changed, 38 insertions(+), 31 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index e85fe4449d..aa57791cc5 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -272,9 +272,12 @@ union RtreeCoord { struct RtreeConstraint { int iCoord; /* Index of constrained coordinate */ int op; /* Constraining operation */ - RtreeDValue rValue; /* Constraint value. */ - int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); - sqlite3_rtree_geometry *pGeom; /* Constraint callback argument for a MATCH */ + union { + RtreeDValue rValue; /* Constraint value. */ + int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*); + int (*xQueryFunc)(sqlite3_rtree_query_info*); + } u; + sqlite3_rtree_query_info *pGeom; /* xGeom and xQueryFunc argument */ }; /* Possible values for RtreeConstraint.op */ @@ -283,7 +286,8 @@ struct RtreeConstraint { #define RTREE_LT 0x43 #define RTREE_GE 0x44 #define RTREE_GT 0x45 -#define RTREE_MATCH 0x46 +#define RTREE_MATCH 0x46 /* Old-style sqlite3_rtree_geometry_callback() */ +#define RTREE_QUERY 0x47 /* New-style sqlite3_rtree_query_callback() */ /* ** An rtree structure node. @@ -860,7 +864,7 @@ static void freeCursorConstraints(RtreeCursor *pCsr){ if( pCsr->aConstraint ){ int i; /* Used to iterate through constraint array */ for(i=0; inConstraint; i++){ - sqlite3_rtree_geometry *pGeom = pCsr->aConstraint[i].pGeom; + sqlite3_rtree_query_info *pGeom = pCsr->aConstraint[i].pGeom; if( pGeom ){ if( pGeom->xDelUser ) pGeom->xDelUser(pGeom->pUser); sqlite3_free(pGeom); @@ -915,7 +919,8 @@ static int testRtreeGeom( for(i=0; iaCoord[i]); } - return pConstraint->xGeom(pConstraint->pGeom, nCoord, aCoord, pbRes); + return pConstraint->u.xGeom((sqlite3_rtree_geometry*)pConstraint->pGeom, + nCoord, aCoord, pbRes); } /* @@ -945,15 +950,15 @@ static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ switch( p->op ){ case RTREE_LE: case RTREE_LT: - bRes = p->rValueu.rValuerValue>cell_max; + bRes = p->u.rValue>cell_max; break; case RTREE_EQ: - bRes = (p->rValue>cell_max || p->rValueu.rValue>cell_max || p->u.rValueop==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH ); switch( p->op ){ - case RTREE_LE: res = (coord<=p->rValue); break; - case RTREE_LT: res = (coordrValue); break; - case RTREE_GE: res = (coord>=p->rValue); break; - case RTREE_GT: res = (coord>p->rValue); break; - case RTREE_EQ: res = (coord==p->rValue); break; + case RTREE_LE: res = (coord<=p->u.rValue); break; + case RTREE_LT: res = (coordu.rValue); break; + case RTREE_GE: res = (coord>=p->u.rValue); break; + case RTREE_GT: res = (coord>p->u.rValue); break; + case RTREE_EQ: res = (coord==p->u.rValue); break; default: { int rc; assert( p->op==RTREE_MATCH ); @@ -1230,7 +1235,7 @@ static int findLeafNode(Rtree *pRtree, i64 iRowid, RtreeNode **ppLeaf){ */ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ RtreeMatchArg *p; - sqlite3_rtree_geometry *pGeom; + sqlite3_rtree_query_info *pGeom; int nBlob; /* Check that value is actually a blob. */ @@ -1244,12 +1249,10 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ return SQLITE_ERROR; } - pGeom = (sqlite3_rtree_geometry *)sqlite3_malloc( - sizeof(sqlite3_rtree_geometry) + nBlob - ); + pGeom = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pGeom)+nBlob ); if( !pGeom ) return SQLITE_NOMEM; - memset(pGeom, 0, sizeof(sqlite3_rtree_geometry)); - p = (RtreeMatchArg *)&pGeom[1]; + memset(pGeom, 0, sizeof(*pGeom)); + p = (RtreeMatchArg*)&pGeom[1]; memcpy(p, sqlite3_value_blob(pValue), nBlob); if( p->magic!=RTREE_GEOMETRY_MAGIC @@ -1263,7 +1266,7 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ pGeom->nParam = p->nParam; pGeom->aParam = p->aParam; - pCons->xGeom = p->cb.xGeom; + pCons->u.xGeom = p->cb.xGeom; pCons->pGeom = pGeom; return SQLITE_OK; } @@ -1326,9 +1329,9 @@ static int rtreeFilter( } }else{ #ifdef SQLITE_RTREE_INT_ONLY - p->rValue = sqlite3_value_int64(argv[ii]); + p->u.rValue = sqlite3_value_int64(argv[ii]); #else - p->rValue = sqlite3_value_double(argv[ii]); + p->u.rValue = sqlite3_value_double(argv[ii]); #endif } } diff --git a/ext/rtree/sqlite3rtree.h b/ext/rtree/sqlite3rtree.h index 79d1ffeede..3f4df4ed89 100644 --- a/ext/rtree/sqlite3rtree.h +++ b/ext/rtree/sqlite3rtree.h @@ -77,6 +77,10 @@ int sqlite3_rtree_query_callback( ** A pointer to a structure of the following type is passed as the ** argument to scored geometry callback registered using ** sqlite3_rtree_query_callback(). +** +** Note that the first 5 fields of this structure are identical to +** sqlite3_rtree_geometry. This structure is a subclass of +** sqlite3_rtree_geometry. */ struct sqlite3_rtree_query_info { void *pContext; /* pContext from when function registered */ diff --git a/manifest b/manifest index 0f929e7155..29fa91b96a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Continuing\sclean-up\sof\sthe\sR-Tree\smodule\sin\spreparation\sfor\scutting\sin\sthe\nnew\sgeneralized\squery\smechanism. -D 2014-04-12T17:44:00.241 +C Continuing\swork\son\sthe\snew\scustom\squery\smechanism\sfor\sr-tree. +D 2014-04-13T16:10:09.443 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 8778f55ece9016ab3b17969f19f9656a06f6e100 +F ext/rtree/rtree.c 527490ab54b8f1bb88bece47037f0d947534cece F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -137,7 +137,7 @@ F ext/rtree/rtreeC.test 16d7aa86ecb6a876d2a38cf590a1471a41b3a46d F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea -F ext/rtree/sqlite3rtree.h f93a466456ed25a9dadf90ad050e2945a2c49cff +F ext/rtree/sqlite3rtree.h 488cf8834d2012b913d33683157d3cf5f1327a69 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test 894e3bc9f497c4fa07a2aa3271e3911f3670c3d8 @@ -1175,7 +1175,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 0b70275972c7a6a533566c1e50bffbf3ac531e95 -R 958d8acaf66c9f2ba2d270349d1218f7 +P 66c858f20586424e15d0bfa3d7b56643bde66226 +R c2e5d1b590c0114514efc7f22a499336 U drh -Z 02617e452696d44ca40af16d5a687407 +Z 7b1f11ecd50995d28149a37777f2c7ae diff --git a/manifest.uuid b/manifest.uuid index 866d285af2..77fbfcc83e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -66c858f20586424e15d0bfa3d7b56643bde66226 \ No newline at end of file +ca7357e66ca60f59477b1db000c2cdaeb8082ae1 \ No newline at end of file From b6c3aeac904db2de7be1d4c366afa74c0e00c0c4 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 14 Apr 2014 12:18:17 +0000 Subject: [PATCH 091/570] Remove over 300 lines of unused code, code that implemented the older Guttman insertion algorithms that are no longer used. FossilOrigin-Name: 3ba5f295c709faebf5505e61f6dc5266b811b086 --- ext/rtree/rtree.c | 349 ++-------------------------------------------- manifest | 12 +- manifest.uuid | 2 +- 3 files changed, 22 insertions(+), 341 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index aa57791cc5..5fff43529e 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -54,48 +54,6 @@ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) -/* -** This file contains an implementation of a couple of different variants -** of the r-tree algorithm. See the README file for further details. The -** same data-structure is used for all, but the algorithms for insert and -** delete operations vary. The variants used are selected at compile time -** by defining the following symbols: -*/ - -/* Either, both or none of the following may be set to activate -** r*tree variant algorithms. -*/ -#define VARIANT_RSTARTREE_CHOOSESUBTREE 0 -#define VARIANT_RSTARTREE_REINSERT 1 - -/* -** Exactly one of the following must be set to 1. -*/ -#define VARIANT_GUTTMAN_QUADRATIC_SPLIT 0 -#define VARIANT_GUTTMAN_LINEAR_SPLIT 0 -#define VARIANT_RSTARTREE_SPLIT 1 - -#define VARIANT_GUTTMAN_SPLIT \ - (VARIANT_GUTTMAN_LINEAR_SPLIT||VARIANT_GUTTMAN_QUADRATIC_SPLIT) - -#if VARIANT_GUTTMAN_QUADRATIC_SPLIT - #define PickNext QuadraticPickNext - #define PickSeeds QuadraticPickSeeds - #define AssignCells splitNodeGuttman -#endif -#if VARIANT_GUTTMAN_LINEAR_SPLIT - #define PickNext LinearPickNext - #define PickSeeds LinearPickSeeds - #define AssignCells splitNodeGuttman -#endif -#if VARIANT_RSTARTREE_SPLIT - #define AssignCells splitNodeStartree -#endif - -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif - #ifndef SQLITE_CORE #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 @@ -1556,62 +1514,32 @@ static RtreeDValue cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ return (cellArea(pRtree, &cell)-area); } -#if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLIT static RtreeDValue cellOverlap( Rtree *pRtree, RtreeCell *p, RtreeCell *aCell, - int nCell, - int iExclude + int nCell ){ int ii; RtreeDValue overlap = 0.0; for(ii=0; iinDim*2); jj+=2){ - RtreeDValue x1, x2; - - x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); - x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); - - if( x2nDim*2); jj+=2){ + RtreeDValue x1, x2; + x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); + x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); + if( x2iDepth-1) ){ - int jj; - aCell = sqlite3_malloc(sizeof(RtreeCell)*nCell); - if( !aCell ){ - rc = SQLITE_NOMEM; - nodeRelease(pRtree, pNode); - pNode = 0; - continue; - } - for(jj=0; jjiDepth-1) ){ - overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell); - }else{ - overlap = 0.0; - } - if( (iCell==0) - || (overlapnDim; i++){ - RtreeDValue x1 = DCOORD(aCell[0].aCoord[i*2]); - RtreeDValue x2 = DCOORD(aCell[0].aCoord[i*2+1]); - RtreeDValue x3 = x1; - RtreeDValue x4 = x2; - int jj; - - int iCellLeft = 0; - int iCellRight = 0; - - for(jj=1; jjx4 ) x4 = right; - if( left>x3 ){ - x3 = left; - iCellRight = jj; - } - if( rightmaxNormalInnerWidth ){ - iLeftSeed = iCellLeft; - iRightSeed = iCellRight; - } - } - } - - *piLeftSeed = iLeftSeed; - *piRightSeed = iRightSeed; -} -#endif /* VARIANT_GUTTMAN_LINEAR_SPLIT */ - -#if VARIANT_GUTTMAN_QUADRATIC_SPLIT -/* -** Implementation of the quadratic variant of the PickNext() function from -** Guttman[84]. -*/ -static RtreeCell *QuadraticPickNext( - Rtree *pRtree, - RtreeCell *aCell, - int nCell, - RtreeCell *pLeftBox, - RtreeCell *pRightBox, - int *aiUsed -){ - #define FABS(a) ((a)<0.0?-1.0*(a):(a)) - - int iSelect = -1; - RtreeDValue fDiff; - int ii; - for(ii=0; iifDiff ){ - fDiff = diff; - iSelect = ii; - } - } - } - aiUsed[iSelect] = 1; - return &aCell[iSelect]; -} - -/* -** Implementation of the quadratic variant of the PickSeeds() function from -** Guttman[84]. -*/ -static void QuadraticPickSeeds( - Rtree *pRtree, - RtreeCell *aCell, - int nCell, - int *piLeftSeed, - int *piRightSeed -){ - int ii; - int jj; - - int iLeftSeed = 0; - int iRightSeed = 1; - RtreeDValue fWaste = 0.0; - - for(ii=0; iifWaste ){ - iLeftSeed = ii; - iRightSeed = jj; - fWaste = waste; - } - } - } - - *piLeftSeed = iLeftSeed; - *piRightSeed = iRightSeed; -} -#endif /* VARIANT_GUTTMAN_QUADRATIC_SPLIT */ /* ** Arguments aIdx, aDistance and aSpare all point to arrays of size @@ -2052,7 +1794,6 @@ static void SortByDimension( } } -#if VARIANT_RSTARTREE_SPLIT /* ** Implementation of the R*-tree variant of SplitNode from Beckman[1990]. */ @@ -2120,7 +1861,7 @@ static int splitNodeStartree( } margin += cellMargin(pRtree, &left); margin += cellMargin(pRtree, &right); - overlap = cellOverlap(pRtree, &left, &right, 1, -1); + overlap = cellOverlap(pRtree, &left, &right, 1); area = cellArea(pRtree, &left) + cellArea(pRtree, &right); if( (nLeft==RTREE_MINCELLS(pRtree)) || (overlap0; i--){ - RtreeCell *pNext; - pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed); - RtreeDValue diff = - cellGrowth(pRtree, pBboxLeft, pNext) - - cellGrowth(pRtree, pBboxRight, pNext) - ; - if( (RTREE_MINCELLS(pRtree)-NCELL(pRight)==i) - || (diff>0.0 && (RTREE_MINCELLS(pRtree)-NCELL(pLeft)!=i)) - ){ - nodeInsertCell(pRtree, pRight, pNext); - cellUnion(pRtree, pBboxRight, pNext); - }else{ - nodeInsertCell(pRtree, pLeft, pNext); - cellUnion(pRtree, pBboxLeft, pNext); - } - } - - sqlite3_free(aiUsed); - return SQLITE_OK; -} -#endif static int updateMapping( Rtree *pRtree, @@ -2286,7 +1971,7 @@ static int SplitNode( memset(pLeft->zData, 0, pRtree->iNodeSize); memset(pRight->zData, 0, pRtree->iNodeSize); - rc = AssignCells(pRtree, aCell, nCell, pLeft, pRight, &leftbbox, &rightbbox); + rc = splitNodeStartree(pRtree, aCell, nCell, pLeft, pRight,&leftbbox,&rightbbox); if( rc!=SQLITE_OK ){ goto splitnode_out; } @@ -2635,16 +2320,12 @@ static int rtreeInsertCell( } } if( nodeInsertCell(pRtree, pNode, pCell) ){ -#if VARIANT_RSTARTREE_REINSERT if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1){ rc = SplitNode(pRtree, pNode, pCell, iHeight); }else{ pRtree->iReinsertHeight = iHeight; rc = Reinsert(pRtree, pNode, pCell, iHeight); } -#else - rc = SplitNode(pRtree, pNode, pCell, iHeight); -#endif }else{ rc = AdjustTree(pRtree, pNode, pCell); if( rc==SQLITE_OK ){ diff --git a/manifest b/manifest index 29fa91b96a..9126cb413e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Continuing\swork\son\sthe\snew\scustom\squery\smechanism\sfor\sr-tree. -D 2014-04-13T16:10:09.443 +C Remove\sover\s300\slines\sof\sunused\scode,\scode\sthat\simplemented\sthe\solder\s\nGuttman\sinsertion\salgorithms\sthat\sare\sno\slonger\sused. +D 2014-04-14T12:18:17.185 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 527490ab54b8f1bb88bece47037f0d947534cece +F ext/rtree/rtree.c d7fbe473260cc53463c372c9cf7303495a40fbc8 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -1175,7 +1175,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 66c858f20586424e15d0bfa3d7b56643bde66226 -R c2e5d1b590c0114514efc7f22a499336 +P ca7357e66ca60f59477b1db000c2cdaeb8082ae1 +R cf842e59d29c59dde99b1f71fa55bf0f U drh -Z 7b1f11ecd50995d28149a37777f2c7ae +Z e4f991d8b5489d1278b0a7eb150a81ec diff --git a/manifest.uuid b/manifest.uuid index 77fbfcc83e..512a941529 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ca7357e66ca60f59477b1db000c2cdaeb8082ae1 \ No newline at end of file +3ba5f295c709faebf5505e61f6dc5266b811b086 \ No newline at end of file From de8c279b28defed9ca99483bdc22eb3959f63fd9 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 14 Apr 2014 14:43:09 +0000 Subject: [PATCH 092/570] Fix comments on the rtreenode() and rtreedepth() test function in the R-Tree module. FossilOrigin-Name: ade5b986e8baab9df7bdaf7ccfaee2d6ba55fa3c --- ext/rtree/rtree.c | 17 +++++++++++++---- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 5fff43529e..17375718e9 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -2946,10 +2946,10 @@ static int rtreeInit( ** Implementation of a scalar function that decodes r-tree nodes to ** human readable strings. This can be used for debugging and analysis. ** -** The scalar function takes two arguments, a blob of data containing -** an r-tree node, and the number of dimensions the r-tree indexes. -** For a two-dimensional r-tree structure called "rt", to deserialize -** all nodes, a statement like: +** The scalar function takes two arguments: (1) the number of dimensions +** to the rtree (between 1 and 5, inclusive) and (2) a blob of data containing +** an r-tree node. For a two-dimensional r-tree structure called "rt", to +** deserialize all nodes, a statement like: ** ** SELECT rtreenode(2, data) FROM rt_node; ** @@ -3003,6 +3003,15 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ sqlite3_result_text(ctx, zText, -1, sqlite3_free); } +/* This routine implements an SQL function that returns the "depth" parameter +** from the front of a blob that is an r-tree node. For example: +** +** SELECT rtreedepth(data) FROM rt_node WHERE nodeno=1; +** +** The depth value is 0 for all nodes other than the root node, and the root +** node always has nodeno=1, so the example above is the primary use for this +** routine. This routine is intended for testing and analysis only. +*/ static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ UNUSED_PARAMETER(nArg); if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB diff --git a/manifest b/manifest index 9126cb413e..89c7e30ee7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sover\s300\slines\sof\sunused\scode,\scode\sthat\simplemented\sthe\solder\s\nGuttman\sinsertion\salgorithms\sthat\sare\sno\slonger\sused. -D 2014-04-14T12:18:17.185 +C Fix\scomments\son\sthe\srtreenode()\sand\srtreedepth()\stest\sfunction\sin\sthe\sR-Tree\nmodule. +D 2014-04-14T14:43:09.474 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c d7fbe473260cc53463c372c9cf7303495a40fbc8 +F ext/rtree/rtree.c 07630c252ce0ba63d2d0e6922847eff6eec64fbc F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -1175,7 +1175,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P ca7357e66ca60f59477b1db000c2cdaeb8082ae1 -R cf842e59d29c59dde99b1f71fa55bf0f +P 3ba5f295c709faebf5505e61f6dc5266b811b086 +R e7b36f9b46b38d0d4d4bc75aff5d0712 U drh -Z e4f991d8b5489d1278b0a7eb150a81ec +Z 1c3694849e99525baeaeac92e41be917 diff --git a/manifest.uuid b/manifest.uuid index 512a941529..0a6c215cd0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3ba5f295c709faebf5505e61f6dc5266b811b086 \ No newline at end of file +ade5b986e8baab9df7bdaf7ccfaee2d6ba55fa3c \ No newline at end of file From 96ce1b36aa7709d0aeffbf1c464bd0aad096afb9 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 15 Apr 2014 21:06:14 +0000 Subject: [PATCH 093/570] Initial attempt at getting R-Tree queries to work using a priority queue. This check-in compiles, but R-Trees do not work well. And there are debugging printf()s left in the code. This is an incremental check-in. FossilOrigin-Name: 53688a25c23c394278a357829793889970aa4157 --- ext/rtree/rtree.c | 547 +++++++++++++++++++++++++++++++--------------- manifest | 15 +- manifest.uuid | 2 +- 3 files changed, 381 insertions(+), 183 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 17375718e9..9f41da3534 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -63,6 +63,7 @@ #include #include +#include #ifndef SQLITE_AMALGAMATION #include "sqlite3rtree.h" @@ -86,6 +87,7 @@ typedef struct RtreeConstraint RtreeConstraint; typedef struct RtreeMatchArg RtreeMatchArg; typedef struct RtreeGeomCallback RtreeGeomCallback; typedef union RtreeCoord RtreeCoord; +typedef struct RtreeSearchPoint RtreeSearchPoint; /* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */ #define RTREE_MAX_DIMENSIONS 5 @@ -165,6 +167,23 @@ struct Rtree { typedef float RtreeValue; /* Low accuracy coordinate */ #endif +/* +** When doing a search of an r-tree, instances of the following structure +** record intermediate results from the tree walk. +** +** The id is always a node-id. For iLevel>=1 the id is the node-id of +** the node that the RtreeSearchPoint represents. When iLevel==0, however, +** the id is of the parent node and the cell that RtreeSearchPoint +** represents is the iCell-th entry in the parent node. +*/ +struct RtreeSearchPoint { + RtreeDValue rScore; /* The score for this node. Smallest goes first. */ + sqlite3_int64 id; /* Node ID */ + u8 iLevel; /* 0=entries. 1=leaf node. 2+ for higher */ + u8 eWithin; /* PARTLY_WITHIN or FULLY_WITHIN */ + u8 iCell; /* Cell index within the node */ +}; + /* ** The minimum number of cells allowed for a node is a third of the ** maximum. In Gutman's notation: @@ -187,18 +206,34 @@ struct Rtree { */ #define RTREE_MAX_DEPTH 40 + +/* +** Number of entries in the cursor RtreeNode cache. The first entry is +** used to cache the RtreeNode for RtreeCursor.sPoint. The remaining +** entries cache the RtreeNode for the first elements of the priority queue. +*/ +#define RTREE_CACHE_SZ 5 + /* ** An rtree cursor object. */ struct RtreeCursor { sqlite3_vtab_cursor base; /* Base class. Must be first */ - RtreeNode *pNode; /* Node cursor is currently pointing at */ - int iCell; /* Index of current cell in pNode */ + u8 atEOF; /* True if at end of search */ + u8 bPoint; /* True if sPoint is valid */ int iStrategy; /* Copy of idxNum search parameter */ int nConstraint; /* Number of entries in aConstraint */ RtreeConstraint *aConstraint; /* Search constraints. */ + int nPointAlloc; /* Number of slots allocated for aPoint[] */ + int nPoint; /* Number of slots used in aPoint[] */ + RtreeSearchPoint *aPoint; /* Priority queue for search points */ + RtreeSearchPoint sPoint; /* Cached next search point */ + RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */ }; +/* Return the Rtree of a RtreeCursor */ +#define RTREE_OF_CURSOR(X) ((Rtree*)((X)->base.pVtab)) + /* ** A coordinate can be either a floating point number or a integer. All ** coordinates within a single R-Tree are always of the same time. @@ -247,6 +282,7 @@ struct RtreeConstraint { #define RTREE_MATCH 0x46 /* Old-style sqlite3_rtree_geometry_callback() */ #define RTREE_QUERY 0x47 /* New-style sqlite3_rtree_query_callback() */ + /* ** An rtree structure node. */ @@ -838,12 +874,13 @@ static void freeCursorConstraints(RtreeCursor *pCsr){ */ static int rtreeClose(sqlite3_vtab_cursor *cur){ Rtree *pRtree = (Rtree *)(cur->pVtab); - int rc; + int ii; RtreeCursor *pCsr = (RtreeCursor *)cur; freeCursorConstraints(pCsr); - rc = nodeRelease(pRtree, pCsr->pNode); + sqlite3_free(pCsr->aPoint); + for(ii=0; iiaNode[ii]); sqlite3_free(pCsr); - return rc; + return SQLITE_OK; } /* @@ -854,14 +891,14 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){ */ static int rtreeEof(sqlite3_vtab_cursor *cur){ RtreeCursor *pCsr = (RtreeCursor *)cur; - return (pCsr->pNode==0); + return pCsr->atEOF; } /* ** The r-tree constraint passed as the second argument to this function is ** guaranteed to be a MATCH constraint. */ -static int testRtreeGeom( +static int rtreeTestGeom( Rtree *pRtree, /* R-Tree object */ RtreeConstraint *pConstraint, /* MATCH constraint to test */ RtreeCell *pCell, /* Cell to test */ @@ -883,24 +920,39 @@ static int testRtreeGeom( /* ** Cursor pCursor currently points to a cell in a non-leaf page. -** Set *pbEof to true if the sub-tree headed by the cell is filtered -** (excluded) by the constraints in the pCursor->aConstraint[] -** array, or false otherwise. +** Set *peWithin to NOT_WITHIN if the constraints in pCursor->aConstraint[] +** are guaranteed to never be satisfied by any subelement under the +** current cell. If some subelement of the cell might satisfy all +** constraints, then set *peWithin to PARTLY_WITHIN. If all subelements +** of the cell are guaranteed to fully satisfy all constraints, then +** set *peWithin to FULLY_WITHIN. +** +** In other words, set *peWithin to NOT_WITHIN, PARTLY_WITHIN, or +** FULLY_WITHIN if the cell is completely outside of the field-of-view, +** overlaps the field of view, or is completely contained within the +** field of view, respectively. +** +** It is not an error to set *peWithin to PARTLY_WITHIN when FULLY_WITHIN +** would be correct. Doing so is suboptimal, but will still give the +** correct answer. ** ** Return SQLITE_OK if successful or an SQLite error code if an error -** occurs within a geometry callback. +** occurs. Errors can only possible if there is a geometry callback. */ -static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ - RtreeCell cell; +static int rtreeTestCell( + RtreeCursor *pCursor, /* The cursor to check */ + RtreeCell *pCell, /* The cell to check */ + int *peWithin /* Set true if element is out-of-bounds */ +){ int ii; - int bRes = 0; + int bOutOfBounds = 0; int rc = SQLITE_OK; + Rtree *pRtree = RTREE_OF_CURSOR(pCursor); - nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); - for(ii=0; bRes==0 && iinConstraint; ii++){ + for(ii=0; bOutOfBounds==0 && iinConstraint; ii++){ RtreeConstraint *p = &pCursor->aConstraint[ii]; - RtreeDValue cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); - RtreeDValue cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); + RtreeDValue cell_min = DCOORD(pCell->aCoord[(p->iCoord>>1)*2]); + RtreeDValue cell_max = DCOORD(pCell->aCoord[(p->iCoord>>1)*2+1]); assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH @@ -908,52 +960,61 @@ static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ switch( p->op ){ case RTREE_LE: case RTREE_LT: - bRes = p->u.rValueu.rValueu.rValue>cell_max; + bOutOfBounds = p->u.rValue>cell_max; break; case RTREE_EQ: - bRes = (p->u.rValue>cell_max || p->u.rValueu.rValue>cell_max || p->u.rValueop==RTREE_MATCH ); - rc = testRtreeGeom(pRtree, p, &cell, &bRes); - bRes = !bRes; + rc = rtreeTestGeom(pRtree, p, pCell, &bOutOfBounds); + bOutOfBounds = !bOutOfBounds; break; } } } - *pbEof = bRes; + *peWithin = bOutOfBounds ? NOT_WITHIN : PARTLY_WITHIN; return rc; } /* -** Test if the cell that cursor pCursor currently points to -** would be filtered (excluded) by the constraints in the -** pCursor->aConstraint[] array. If so, set *pbEof to true before -** returning. If the cell is not filtered (excluded) by the constraints, -** set pbEof to zero. +** pCursor points to a leaf r-tree entry which is a candidate for output. +** This routine sets *peWithin to one of NOT_WITHIN, PARTLY_WITHIN, or +** FULLY_WITHIN depending on whether or not the leaf entry is completely +** outside the region defined by pCursor->aConstraints[], or overlaps the +** region, or is completely within the region, respectively. +** +** This routine is more selective than rtreeTestCell(). rtreeTestCell() +** will return PARTLY_WITHIN or FULLY_WITHIN if the constraints are such +** that a subelement of the cell to be included in the result set. This +** routine is is only called for leaf r-tree entries and does not need +** to concern itself with subelements. Hence it only sets *peWithin to +** PARTLY_WITHIN or FULLY_WITHIN if the cell itself meets the requirements. ** ** Return SQLITE_OK if successful or an SQLite error code if an error ** occurs within a geometry callback. ** ** This function assumes that the cell is part of a leaf node. */ -static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ - RtreeCell cell; +static int rtreeTestEntry( + RtreeCursor *pCursor, /* Cursor pointing to the leaf element */ + RtreeCell *pCell, /* The cell to check */ + int *peWithin /* OUT: NOT_WITHIN, PARTLY_WITHIN, or FULLY_WITHIN */ +){ + Rtree *pRtree = RTREE_OF_CURSOR(pCursor); int ii; - *pbEof = 0; + int res = 1; /* Innocent until proven guilty */ - nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); - for(ii=0; iinConstraint; ii++){ + for(ii=0; res && iinConstraint; ii++){ RtreeConstraint *p = &pCursor->aConstraint[ii]; - RtreeDValue coord = DCOORD(cell.aCoord[p->iCoord]); - int res; + RtreeDValue coord = DCOORD(pCell->aCoord[p->iCoord]); assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH ); @@ -966,85 +1027,19 @@ static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ default: { int rc; assert( p->op==RTREE_MATCH ); - rc = testRtreeGeom(pRtree, p, &cell, &res); + rc = rtreeTestGeom(pRtree, p, pCell, &res); if( rc!=SQLITE_OK ){ return rc; } break; } } - - if( !res ){ - *pbEof = 1; - return SQLITE_OK; - } } + *peWithin = res ? FULLY_WITHIN : NOT_WITHIN; return SQLITE_OK; } -/* -** Cursor pCursor currently points at a node that heads a sub-tree of -** height iHeight (if iHeight==0, then the node is a leaf). Descend -** to point to the left-most cell of the sub-tree that matches the -** configured constraints. -*/ -static int descendToCell( - Rtree *pRtree, - RtreeCursor *pCursor, - int iHeight, - int *pEof /* OUT: Set to true if cannot descend */ -){ - int isEof; - int rc; - int ii; - RtreeNode *pChild; - sqlite3_int64 iRowid; - - RtreeNode *pSavedNode = pCursor->pNode; - int iSavedCell = pCursor->iCell; - - assert( iHeight>=0 ); - - if( iHeight==0 ){ - rc = testRtreeEntry(pRtree, pCursor, &isEof); - }else{ - rc = testRtreeCell(pRtree, pCursor, &isEof); - } - if( rc!=SQLITE_OK || isEof || iHeight==0 ){ - goto descend_to_cell_out; - } - - iRowid = nodeGetRowid(pRtree, pCursor->pNode, pCursor->iCell); - rc = nodeAcquire(pRtree, iRowid, pCursor->pNode, &pChild); - if( rc!=SQLITE_OK ){ - goto descend_to_cell_out; - } - - nodeRelease(pRtree, pCursor->pNode); - pCursor->pNode = pChild; - isEof = 1; - for(ii=0; isEof && iiiCell = ii; - rc = descendToCell(pRtree, pCursor, iHeight-1, &isEof); - if( rc!=SQLITE_OK ){ - goto descend_to_cell_out; - } - } - - if( isEof ){ - assert( pCursor->pNode==pChild ); - nodeReference(pSavedNode); - nodeRelease(pRtree, pChild); - pCursor->pNode = pSavedNode; - pCursor->iCell = iSavedCell; - } - -descend_to_cell_out: - *pEof = isEof; - return rc; -} - /* ** One of the cells in node pNode is guaranteed to have a 64-bit ** integer value equal to iRowid. Return the index of this cell. @@ -1057,6 +1052,7 @@ static int nodeRowidIndex( ){ int ii; int nCell = NCELL(pNode); + assert( nCell<200 ); for(ii=0; iirScorerScore ) return -1; + if( pA->rScore>pB->rScore ) return +1; + if( pA->iLeveliLevel ) return -1; + if( pA->iLevel>pB->iLevel ) return +1; + return 0; +} + +/* +** Interchange to search points in a cursor. +*/ +static void rtreeSearchPointSwap(RtreeCursor *p, int i, int j){ + RtreeSearchPoint t = p->aPoint[i]; + assert( iaPoint[i] = p->aPoint[j]; + p->aPoint[j] = t; + if( i=RTREE_CACHE_SZ-1 ){ + nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i+1]); + p->aNode[i+1] = 0; + }else{ + RtreeNode *pTemp = p->aNode[i+i]; + p->aNode[i+1] = p->aNode[j+1]; + p->aNode[j+1] = pTemp; + } + } +} + +/* +** Return the search point with the lowest current score. +*/ +static RtreeSearchPoint *rtreeSearchPointFirst(RtreeCursor *pCur){ + return pCur->bPoint ? &pCur->sPoint : pCur->nPoint ? pCur->aPoint : 0; +} + +/* +** Get the RtreeNode for the search point with the lowest score. +*/ +static RtreeNode *rtreeNodeOfFirstSearchPoint(RtreeCursor *pCur, int *pRC){ + sqlite3_int64 id; + int ii = 1 - pCur->bPoint; + assert( ii==0 || ii==1 ); + assert( pCur->bPoint || pCur->nPoint ); + if( pCur->aNode[ii]==0 ){ + assert( pRC!=0 ); + id = ii ? pCur->aPoint[0].id : pCur->sPoint.id; + *pRC = nodeAcquire(RTREE_OF_CURSOR(pCur), id, 0, &pCur->aNode[ii]); + } + return pCur->aNode[ii]; +} + +/* +** Push a new element onto the priority queue +*/ +static RtreeSearchPoint *rtreeEnqueue( + RtreeCursor *pCur, /* The cursor */ + RtreeDValue rScore, /* Score for the new search point */ + u8 iLevel /* Level for the new search point */ +){ + int i, j; + RtreeSearchPoint *pNew; + if( pCur->nPoint>=pCur->nPointAlloc ){ + int nNew = pCur->nPointAlloc*2 + 8; + pNew = sqlite3_realloc(pCur->aPoint, nNew*sizeof(pCur->aPoint[0])); + if( pNew==0 ) return 0; + pCur->aPoint = pNew; + pCur->nPointAlloc = nNew; + } + i = pCur->nPoint++; + pNew = pCur->aPoint + i; + pNew->rScore = rScore; + pNew->iLevel = iLevel; + while( i>0 ){ + RtreeSearchPoint *pParent; + j = (i-1)/2; + pParent = pCur->aPoint + j; + if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break; + rtreeSearchPointSwap(pCur, j, i); + i = j; + pNew = pParent; + } + return pNew; +} + +/* +** Allocate a new RtreeSearchPoint and return a pointer to it. Return +** NULL if malloc fails. +*/ +static RtreeSearchPoint *rtreeSearchPointNew( + RtreeCursor *pCur, /* The cursor */ + RtreeDValue rScore, /* Score for the new search point */ + u8 iLevel /* Level for the new search point */ +){ + RtreeSearchPoint *pNew, *pFirst; + pFirst = rtreeSearchPointFirst(pCur); + if( pFirst==0 + || pFirst->rScore>rScore + || (pFirst->rScore==rScore && pFirst->iLevel>iLevel) + ){ + if( pCur->bPoint ){ + pNew = rtreeEnqueue(pCur, rScore, iLevel); + if( pNew==0 ) return 0; + assert( pCur->aNode[1]==0 ); + pCur->aNode[1] = pCur->aNode[0]; + pCur->aNode[0] = 0; + *pNew = pCur->sPoint; + } + pCur->sPoint.rScore = rScore; + pCur->sPoint.iLevel = iLevel; + pCur->bPoint = 1; + return &pCur->sPoint; + }else{ + return rtreeEnqueue(pCur, rScore, iLevel); + } +} + +static void traceTop(RtreeCursor *pCur, const char *zPrefix){ + RtreeSearchPoint *p = rtreeSearchPointFirst(pCur); + if( p ){ + printf("=== %6s id=%lld lvl=%d iCell=%d rScore=%g eWithin=%d\n", + zPrefix, p->id, p->iLevel, p->iCell, p->rScore, p->eWithin); + } +} + +/* Remove the search point with the lowest current score. +*/ +static void rtreeSearchPointPop(RtreeCursor *p){ + int i, j, k, n; + i = p->bPoint; + assert( i==0 || i==1 ); + if( p->aNode[i] ){ + nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]); + p->aNode[i] = 0; + } + if( p->bPoint ){ + p->bPoint = 0; + }else if( p->nPoint ){ + n = --p->nPoint; + p->aPoint[0] = p->aPoint[n]; + i = 0; + while( (j = i*2+1)aPoint[k], &p->aPoint[j])<0 ){ + if( rtreeSearchPointCompare(&p->aPoint[k], &p->aPoint[i])<0 ){ + rtreeSearchPointSwap(p, i, k); + i = k; + }else{ + break; + } + }else{ + if( rtreeSearchPointCompare(&p->aPoint[j], &p->aPoint[i])<0 ){ + rtreeSearchPointSwap(p, i, j); + i = j; + }else{ + break; + } + } + } + } +} + + +/* +** Continue the search on cursor pCur until the front of the queue +** contains an entry suitable for returning as a result-set row, +** or until the RtreeSearchPoint queue is empty, indicating that the +** query has completed. +*/ +static int rtreeStepToLeaf(RtreeCursor *pCur){ + RtreeSearchPoint *p; + RtreeSearchPoint *pNew; + Rtree *pRtree = RTREE_OF_CURSOR(pCur); + RtreeNode *pNode; + int eWithin; + int rc = SQLITE_OK; + int nCell; + RtreeCell cell; + RtreeSearchPoint x; + + while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){ + pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc); + if( rc ) return rc; + nCell = NCELL(pNode); + assert( nCell<200 ); + while( p->iCelliCell, &cell); + if( p->iLevel==1 ){ + rc = rtreeTestEntry(pCur, &cell, &eWithin); + }else{ + rc = rtreeTestCell(pCur, &cell, &eWithin); + } + if( rc ) return rc; + x = *p; + p->iCell++; + if( p->iCell>=nCell ){ +traceTop(pCur, "POP:"); + rtreeSearchPointPop(pCur); + } + if( eWithin==NOT_WITHIN ) continue; + pNew = rtreeSearchPointNew(pCur, /*rScore*/0.0, x.iLevel-1); + if( pNew==0 ) return SQLITE_NOMEM; + pNew->eWithin = eWithin; + if( pNew->iLevel ){ + pNew->id = cell.iRowid; + pNew->iCell = 0; + }else{ + pNew->id = x.id; + pNew->iCell = x.iCell; + } +traceTop(pCur, "PUSH:"); + break; + } + } + pCur->atEOF = p==0; + return SQLITE_OK; +} + /* ** Rtree virtual table module xNext method. */ static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){ - Rtree *pRtree = (Rtree *)(pVtabCursor->pVtab); RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; int rc = SQLITE_OK; - /* RtreeCursor.pNode must not be NULL. If is is NULL, then this cursor is - ** already at EOF. It is against the rules to call the xNext() method of - ** a cursor that has already reached EOF. - */ - assert( pCsr->pNode ); - - if( pCsr->iStrategy==1 ){ - /* This "scan" is a direct lookup by rowid. There is no next entry. */ - nodeRelease(pRtree, pCsr->pNode); - pCsr->pNode = 0; - }else{ - /* Move to the next entry that matches the configured constraints. */ - int iHeight = 0; - while( pCsr->pNode ){ - RtreeNode *pNode = pCsr->pNode; - int nCell = NCELL(pNode); - for(pCsr->iCell++; pCsr->iCelliCell++){ - int isEof; - rc = descendToCell(pRtree, pCsr, iHeight, &isEof); - if( rc!=SQLITE_OK || !isEof ){ - return rc; - } - } - pCsr->pNode = pNode->pParent; - rc = nodeParentIndex(pRtree, pNode, &pCsr->iCell); - if( rc!=SQLITE_OK ){ - return rc; - } - nodeReference(pCsr->pNode); - nodeRelease(pRtree, pNode); - iHeight++; - } - } - + /* Move to the next entry that matches the configured constraints. */ +traceTop(pCsr, "POP:"); + rtreeSearchPointPop(pCsr); + rtreeStepToLeaf(pCsr); return rc; } @@ -1128,13 +1317,14 @@ static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){ ** Rtree virtual table module xRowid method. */ static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){ - Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; - - assert(pCsr->pNode); - *pRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell); - - return SQLITE_OK; + RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); + int rc = SQLITE_OK; + RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); + if( rc==SQLITE_OK && p ){ + *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell); + } + return rc; } /* @@ -1143,13 +1333,18 @@ static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ Rtree *pRtree = (Rtree *)cur->pVtab; RtreeCursor *pCsr = (RtreeCursor *)cur; + RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); + RtreeCoord c; + int rc = SQLITE_OK; + RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); + if( rc ) return rc; + if( p==0 ) return SQLITE_OK; if( i==0 ){ - i64 iRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell); - sqlite3_result_int64(ctx, iRowid); + sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell)); }else{ - RtreeCoord c; - nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c); + if( rc ) return rc; + nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c); #ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ sqlite3_result_double(ctx, c.f); @@ -1160,7 +1355,6 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ sqlite3_result_int(ctx, c.i); } } - return SQLITE_OK; } @@ -1171,12 +1365,18 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ ** *ppLeaf to 0 and return SQLITE_OK. If an error occurs, set *ppLeaf ** to zero and return an SQLite error code. */ -static int findLeafNode(Rtree *pRtree, i64 iRowid, RtreeNode **ppLeaf){ +static int findLeafNode( + Rtree *pRtree, /* RTree to search */ + i64 iRowid, /* The rowid searching for */ + RtreeNode **ppLeaf, /* Write the node here */ + sqlite3_int64 *piNode /* Write the node-id here */ +){ int rc; *ppLeaf = 0; sqlite3_bind_int64(pRtree->pReadRowid, 1, iRowid); if( sqlite3_step(pRtree->pReadRowid)==SQLITE_ROW ){ i64 iNode = sqlite3_column_int64(pRtree->pReadRowid, 0); + if( piNode ) *piNode = iNode; rc = nodeAcquire(pRtree, iNode, 0, ppLeaf); sqlite3_reset(pRtree->pReadRowid); }else{ @@ -1239,10 +1439,10 @@ static int rtreeFilter( ){ Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; - RtreeNode *pRoot = 0; int ii; int rc = SQLITE_OK; + int iCell = 0; rtreeReference(pRtree); @@ -1252,13 +1452,16 @@ static int rtreeFilter( if( idxNum==1 ){ /* Special case - lookup by rowid. */ RtreeNode *pLeaf; /* Leaf on which the required cell resides */ + RtreeSearchPoint *p; /* Search point for the the leaf */ i64 iRowid = sqlite3_value_int64(argv[0]); - rc = findLeafNode(pRtree, iRowid, &pLeaf); - pCsr->pNode = pLeaf; - if( pLeaf ){ - assert( rc==SQLITE_OK ); - rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &pCsr->iCell); - } + p = rtreeSearchPointNew(pCsr, 0.0, 0); + if( p==0 ) return SQLITE_NOMEM; + rc = findLeafNode(pRtree, iRowid, &pLeaf, &p->id); + pCsr->aNode[0] = pLeaf; + p->eWithin = PARTLY_WITHIN; + if( rc ) rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); + p->iCell = iCell; +traceTop(pCsr, "PUSH:"); }else{ /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array ** with the configured constraints. @@ -1297,26 +1500,18 @@ static int rtreeFilter( } if( rc==SQLITE_OK ){ - pCsr->pNode = 0; rc = nodeAcquire(pRtree, 1, 0, &pRoot); } if( rc==SQLITE_OK ){ - int isEof = 1; - int nCell = NCELL(pRoot); - pCsr->pNode = pRoot; - for(pCsr->iCell=0; rc==SQLITE_OK && pCsr->iCelliCell++){ - assert( pCsr->pNode==pRoot ); - rc = descendToCell(pRtree, pCsr, pRtree->iDepth, &isEof); - if( !isEof ){ - break; - } - } - if( rc==SQLITE_OK && isEof ){ - assert( pCsr->pNode==pRoot ); - nodeRelease(pRtree, pRoot); - pCsr->pNode = 0; - } - assert( rc!=SQLITE_OK || !pCsr->pNode || pCsr->iCellpNode) ); + RtreeSearchPoint *pNew = rtreeSearchPointNew(pCsr, 0.0, pRtree->iDepth+1); + if( pNew==0 ) return SQLITE_NOMEM; + pNew->id = 1; + pNew->iCell = 0; + pNew->eWithin = PARTLY_WITHIN; + assert( pCsr->bPoint==1 ); + pCsr->aNode[0] = pRoot; +traceTop(pCsr, "PUSH:"); + rc = rtreeStepToLeaf(pCsr); } } @@ -2395,7 +2590,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){ ** about to be deleted. */ if( rc==SQLITE_OK ){ - rc = findLeafNode(pRtree, iDelete, &pLeaf); + rc = findLeafNode(pRtree, iDelete, &pLeaf, 0); } /* Delete the cell in question from the leaf node. */ diff --git a/manifest b/manifest index 89c7e30ee7..7acb80fc79 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scomments\son\sthe\srtreenode()\sand\srtreedepth()\stest\sfunction\sin\sthe\sR-Tree\nmodule. -D 2014-04-14T14:43:09.474 +C Initial\sattempt\sat\sgetting\sR-Tree\squeries\sto\swork\susing\sa\spriority\squeue.\nThis\scheck-in\scompiles,\sbut\sR-Trees\sdo\snot\swork\swell.\s\sAnd\sthere\sare\ndebugging\sprintf()s\sleft\sin\sthe\scode.\s\sThis\sis\san\sincremental\scheck-in. +D 2014-04-15T21:06:14.359 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 07630c252ce0ba63d2d0e6922847eff6eec64fbc +F ext/rtree/rtree.c 2f4d35a0689d588698cd0dd7d513761dff20c8fa F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -1175,7 +1175,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 3ba5f295c709faebf5505e61f6dc5266b811b086 -R e7b36f9b46b38d0d4d4bc75aff5d0712 +P ade5b986e8baab9df7bdaf7ccfaee2d6ba55fa3c +R 52e87385ec75daf64fa5f31a0250db29 +T *branch * rtree-queue +T *sym-rtree-queue * +T -sym-rtree-enhancements * U drh -Z 1c3694849e99525baeaeac92e41be917 +Z d0176a391caa75c92333b568fa6cbbbf diff --git a/manifest.uuid b/manifest.uuid index 0a6c215cd0..ddde4e0525 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ade5b986e8baab9df7bdaf7ccfaee2d6ba55fa3c \ No newline at end of file +53688a25c23c394278a357829793889970aa4157 \ No newline at end of file From f247982e37aa5b5f1d8b50ab96ba8f7238d2dab9 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 16 Apr 2014 13:00:08 +0000 Subject: [PATCH 094/570] Bug fixes to the priority-queue implementation for R-Trees. Improved tracing capability. Some queries work now, but still many problems. FossilOrigin-Name: a439ddd629c6bb5ea2e7e274673fee4f5c207acf --- ext/rtree/rtree.c | 79 ++++++++++++++++++++++++++++++++++------------- manifest | 15 ++++----- manifest.uuid | 2 +- 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 9f41da3534..3754655bb0 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -1098,14 +1098,15 @@ static void rtreeSearchPointSwap(RtreeCursor *p, int i, int j){ assert( iaPoint[i] = p->aPoint[j]; p->aPoint[j] = t; - if( i=RTREE_CACHE_SZ-1 ){ - nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i+1]); - p->aNode[i+1] = 0; + i++; j++; + if( i=RTREE_CACHE_SZ ){ + nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]); + p->aNode[i] = 0; }else{ - RtreeNode *pTemp = p->aNode[i+i]; - p->aNode[i+1] = p->aNode[j+1]; - p->aNode[j+1] = pTemp; + RtreeNode *pTemp = p->aNode[i]; + p->aNode[i] = p->aNode[j]; + p->aNode[j] = pTemp; } } } @@ -1182,10 +1183,16 @@ static RtreeSearchPoint *rtreeSearchPointNew( || (pFirst->rScore==rScore && pFirst->iLevel>iLevel) ){ if( pCur->bPoint ){ + int ii; pNew = rtreeEnqueue(pCur, rScore, iLevel); if( pNew==0 ) return 0; - assert( pCur->aNode[1]==0 ); - pCur->aNode[1] = pCur->aNode[0]; + ii = (int)(pNew - pCur->aPoint) + 1; + if( iiaNode[ii]==0 ); + pCur->aNode[ii] = pCur->aNode[0]; + }else{ + nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]); + } pCur->aNode[0] = 0; *pNew = pCur->sPoint; } @@ -1198,13 +1205,34 @@ static RtreeSearchPoint *rtreeSearchPointNew( } } -static void traceTop(RtreeCursor *pCur, const char *zPrefix){ - RtreeSearchPoint *p = rtreeSearchPointFirst(pCur); - if( p ){ - printf("=== %6s id=%lld lvl=%d iCell=%d rScore=%g eWithin=%d\n", - zPrefix, p->id, p->iLevel, p->iCell, p->rScore, p->eWithin); +#if 0 +/* Tracing routines for the RtreeSearchPoint queue */ +static void tracePoint(RtreeSearchPoint *p, int idx, RtreeCursor *pCur){ + if( idx<0 ){ printf(" s"); }else{ printf("%2d", idx); } + printf(" %d.%05lld.%02d %g %d", + p->iLevel, p->id, p->iCell, p->rScore, p->eWithin + ); + idx++; + if( idxaNode[idx]); + }else{ + printf("\n"); } } +static void traceQueue(RtreeCursor *pCur, const char *zPrefix){ + int ii; + printf("=== %9s ", zPrefix); + if( pCur->bPoint ){ + tracePoint(&pCur->sPoint, -1, pCur); + } + for(ii=0; iinPoint; ii++){ + if( ii>0 || pCur->bPoint ) printf(" "); + tracePoint(&pCur->aPoint[ii], ii, pCur); + } +} +#else +# define RTREE_QUEUE_TRACE(A,B) /* no-op */ +#endif /* Remove the search point with the lowest current score. */ @@ -1221,6 +1249,10 @@ static void rtreeSearchPointPop(RtreeCursor *p){ }else if( p->nPoint ){ n = --p->nPoint; p->aPoint[0] = p->aPoint[n]; + if( naNode[1] = p->aNode[n+1]; + p->aNode[n+1] = 0; + } i = 0; while( (j = i*2+1)iCell++; + if( eWithin==NOT_WITHIN ) continue; if( p->iCell>=nCell ){ -traceTop(pCur, "POP:"); + RTREE_QUEUE_TRACE(pCur, "POP-S:"); rtreeSearchPointPop(pCur); } - if( eWithin==NOT_WITHIN ) continue; pNew = rtreeSearchPointNew(pCur, /*rScore*/0.0, x.iLevel-1); if( pNew==0 ) return SQLITE_NOMEM; pNew->eWithin = eWithin; @@ -1291,9 +1323,14 @@ traceTop(pCur, "POP:"); pNew->id = x.id; pNew->iCell = x.iCell; } -traceTop(pCur, "PUSH:"); + p = pNew; + RTREE_QUEUE_TRACE(pCur, "PUSH-S:"); break; } + if( p->iCell>=nCell ){ + RTREE_QUEUE_TRACE(pCur, "POP-Se:"); + rtreeSearchPointPop(pCur); + } } pCur->atEOF = p==0; return SQLITE_OK; @@ -1307,7 +1344,7 @@ static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){ int rc = SQLITE_OK; /* Move to the next entry that matches the configured constraints. */ -traceTop(pCsr, "POP:"); + RTREE_QUEUE_TRACE(pCsr, "POP-Nx:"); rtreeSearchPointPop(pCsr); rtreeStepToLeaf(pCsr); return rc; @@ -1461,7 +1498,7 @@ static int rtreeFilter( p->eWithin = PARTLY_WITHIN; if( rc ) rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); p->iCell = iCell; -traceTop(pCsr, "PUSH:"); + RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); }else{ /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array ** with the configured constraints. @@ -1510,7 +1547,7 @@ traceTop(pCsr, "PUSH:"); pNew->eWithin = PARTLY_WITHIN; assert( pCsr->bPoint==1 ); pCsr->aNode[0] = pRoot; -traceTop(pCsr, "PUSH:"); + RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:"); rc = rtreeStepToLeaf(pCsr); } } @@ -3177,7 +3214,7 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ nCell = (int)strlen(zCell); for(jj=0; jj Date: Wed, 16 Apr 2014 14:45:11 +0000 Subject: [PATCH 095/570] =?UTF-8?q?Fix=20a=20bug=20in=20rowid=3D=3F=20quer?= =?UTF-8?q?y=20handling.=20=20More=20problems=20remain.?= FossilOrigin-Name: 5b0e6ba4a5050cf81cf41b977b28d714163569e0 --- ext/rtree/rtree.c | 23 ++++++++++++----------- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 3754655bb0..26082ff511 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -1230,6 +1230,7 @@ static void traceQueue(RtreeCursor *pCur, const char *zPrefix){ tracePoint(&pCur->aPoint[ii], ii, pCur); } } +# define RTREE_QUEUE_TRACE(A,B) traceQueue(A,B) #else # define RTREE_QUEUE_TRACE(A,B) /* no-op */ #endif @@ -1284,7 +1285,6 @@ static void rtreeSearchPointPop(RtreeCursor *p){ */ static int rtreeStepToLeaf(RtreeCursor *pCur){ RtreeSearchPoint *p; - RtreeSearchPoint *pNew; Rtree *pRtree = RTREE_OF_CURSOR(pCur); RtreeNode *pNode; int eWithin; @@ -1313,17 +1313,16 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){ RTREE_QUEUE_TRACE(pCur, "POP-S:"); rtreeSearchPointPop(pCur); } - pNew = rtreeSearchPointNew(pCur, /*rScore*/0.0, x.iLevel-1); - if( pNew==0 ) return SQLITE_NOMEM; - pNew->eWithin = eWithin; - if( pNew->iLevel ){ - pNew->id = cell.iRowid; - pNew->iCell = 0; + p = rtreeSearchPointNew(pCur, /*rScore*/0.0, x.iLevel-1); + if( p==0 ) return SQLITE_NOMEM; + p->eWithin = eWithin; + if( p->iLevel ){ + p->id = cell.iRowid; + p->iCell = 0; }else{ - pNew->id = x.id; - pNew->iCell = x.iCell; + p->id = x.id; + p->iCell = x.iCell; } - p = pNew; RTREE_QUEUE_TRACE(pCur, "PUSH-S:"); break; } @@ -1496,7 +1495,9 @@ static int rtreeFilter( rc = findLeafNode(pRtree, iRowid, &pLeaf, &p->id); pCsr->aNode[0] = pLeaf; p->eWithin = PARTLY_WITHIN; - if( rc ) rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); + if( rc==SQLITE_OK ){ + rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); + } p->iCell = iCell; RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); }else{ diff --git a/manifest b/manifest index 83f2beda77..df0b85687e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Bug\sfixes\sto\sthe\spriority-queue\simplementation\sfor\sR-Trees.\s\sImproved\stracing\ncapability.\s\sSome\squeries\swork\snow,\sbut\sstill\smany\sproblems. -D 2014-04-16T13:00:08.915 +C Fix\sa\sbug\sin\srowid=?\squery\shandling.\s\sMore\sproblems\sremain. +D 2014-04-16T14:45:11.945 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 3105c5514d6dbf99c39aceac84c4c0f9e00f90ea +F ext/rtree/rtree.c 4702eae330e9803ac51208ec0e26c5aceb0cd20b F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -1175,7 +1175,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 53688a25c23c394278a357829793889970aa4157 -R 67a30187386908beb1eb82f50c3b2dfd +P a439ddd629c6bb5ea2e7e274673fee4f5c207acf +R 759346bdeaafb6dce8a9cda8463bc2de U drh -Z ba82d149b9f56c655f1e6f2a959cfc71 +Z 100295249b6d7d7223775c8a6bd7cd19 diff --git a/manifest.uuid b/manifest.uuid index b2db9c77b5..8106164958 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a439ddd629c6bb5ea2e7e274673fee4f5c207acf \ No newline at end of file +5b0e6ba4a5050cf81cf41b977b28d714163569e0 \ No newline at end of file From 933a5ff2d4389b5a9007f7b43b1084d16950aad5 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 16 Apr 2014 17:15:14 +0000 Subject: [PATCH 096/570] TCL tests now all pass. FossilOrigin-Name: f864baccd3fe0ee939ac1ec20069792f649cddc0 --- ext/rtree/rtree.c | 24 ++++++++++++++---------- ext/rtree/rtreeB.test | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 26082ff511..9c62576612 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -1239,7 +1239,7 @@ static void traceQueue(RtreeCursor *pCur, const char *zPrefix){ */ static void rtreeSearchPointPop(RtreeCursor *p){ int i, j, k, n; - i = p->bPoint; + i = 1 - p->bPoint; assert( i==0 || i==1 ); if( p->aNode[i] ){ nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]); @@ -1345,7 +1345,7 @@ static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){ /* Move to the next entry that matches the configured constraints. */ RTREE_QUEUE_TRACE(pCsr, "POP-Nx:"); rtreeSearchPointPop(pCsr); - rtreeStepToLeaf(pCsr); + rc = rtreeStepToLeaf(pCsr); return rc; } @@ -1490,16 +1490,20 @@ static int rtreeFilter( RtreeNode *pLeaf; /* Leaf on which the required cell resides */ RtreeSearchPoint *p; /* Search point for the the leaf */ i64 iRowid = sqlite3_value_int64(argv[0]); - p = rtreeSearchPointNew(pCsr, 0.0, 0); - if( p==0 ) return SQLITE_NOMEM; - rc = findLeafNode(pRtree, iRowid, &pLeaf, &p->id); - pCsr->aNode[0] = pLeaf; - p->eWithin = PARTLY_WITHIN; - if( rc==SQLITE_OK ){ + i64 iNode = 0; + rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); + if( rc==SQLITE_OK && pLeaf!=0 ){ + p = rtreeSearchPointNew(pCsr, 0.0, 0); + assert( p!=0 ); /* Always returns pCsr->sPoint */ + pCsr->aNode[0] = pLeaf; + p->id = iNode; + p->eWithin = PARTLY_WITHIN; rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); + p->iCell = iCell; + RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); + }else{ + pCsr->atEOF = 1; } - p->iCell = iCell; - RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); }else{ /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array ** with the configured constraints. diff --git a/ext/rtree/rtreeB.test b/ext/rtree/rtreeB.test index 7cb445cc4f..aeb308eca7 100644 --- a/ext/rtree/rtreeB.test +++ b/ext/rtree/rtreeB.test @@ -41,7 +41,7 @@ ifcapable rtree_int_only { INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400); SELECT rtreenode(2, data) FROM t1_node; } - } {{{1073741824 0.000000 0.000000 100.000000 100.000000} {2147483646 0.000000 0.000000 200.000000 200.000000} {4294967296 0.000000 0.000000 300.000000 300.000000} {8589934592 20.000000 20.000000 150.000000 150.000000} {9223372036854775807 150.000000 150.000000 400.000000 400.000000}}} + } {{{1073741824 0 0 100 100} {2147483646 0 0 200 200} {4294967296 0 0 300 300} {8589934592 20 20 150 150} {9223372036854775807 150 150 400 400}}} } finish_test diff --git a/manifest b/manifest index df0b85687e..1061ef3307 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sbug\sin\srowid=?\squery\shandling.\s\sMore\sproblems\sremain. -D 2014-04-16T14:45:11.945 +C TCL\stests\snow\sall\spass. +D 2014-04-16T17:15:14.114 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 4702eae330e9803ac51208ec0e26c5aceb0cd20b +F ext/rtree/rtree.c 142d70dc3bb8db1caf6c0e94b88ec0e8047d36ee F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -132,7 +132,7 @@ F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971 F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34 F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf -F ext/rtree/rtreeB.test 983e567b49b5dca165940f66b87e161aa30e82b2 +F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e F ext/rtree/rtreeC.test 16d7aa86ecb6a876d2a38cf590a1471a41b3a46d F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 @@ -1175,7 +1175,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P a439ddd629c6bb5ea2e7e274673fee4f5c207acf -R 759346bdeaafb6dce8a9cda8463bc2de +P 5b0e6ba4a5050cf81cf41b977b28d714163569e0 +R f6b681e4a8814b2c282cb2ca3c357703 U drh -Z 100295249b6d7d7223775c8a6bd7cd19 +Z 3d7f5774712bc082940f713cae866e31 diff --git a/manifest.uuid b/manifest.uuid index 8106164958..cd8f7f474f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5b0e6ba4a5050cf81cf41b977b28d714163569e0 \ No newline at end of file +f864baccd3fe0ee939ac1ec20069792f649cddc0 \ No newline at end of file From 18b5142b29d7fe828f17dd816c55b9fb5925ea85 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 16 Apr 2014 21:02:28 +0000 Subject: [PATCH 097/570] Performance optimization on nodeGetCell() in R-Tree. FossilOrigin-Name: 5d20ff9ec837ad35bc44d6c25d13764b350e81dd --- ext/rtree/rtree.c | 11 ++++++++--- manifest | 13 ++++++------- manifest.uuid | 2 +- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 9c62576612..6bf1db11c4 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -729,10 +729,15 @@ static void nodeGetCell( int iCell, /* Index of the cell within the node */ RtreeCell *pCell /* OUT: Write the cell contents here */ ){ - int ii; + u8 *pData; + u8 *pEnd; + RtreeCoord *pCoord; pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell); - for(ii=0; iinDim*2; ii++){ - nodeGetCoord(pRtree, pNode, iCell, ii, &pCell->aCoord[ii]); + pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell); + pEnd = pData + pRtree->nDim*8; + pCoord = pCell->aCoord; + for(; pData Date: Thu, 17 Apr 2014 13:15:33 +0000 Subject: [PATCH 098/570] Refactor the constraint checking logic in RTree. The new-style constraint callbacks created by sqlite3_rtree_query_callback() are now hooked up from end to end, though still untested. FossilOrigin-Name: 32a13870175a1dd1d33af3572dde09ff607a04b6 --- ext/rtree/rtree.c | 300 +++++++++++++++++++++--------------------- ext/rtree/rtree6.test | 18 +-- ext/rtree/rtreeC.test | 13 +- manifest | 16 +-- manifest.uuid | 2 +- 5 files changed, 172 insertions(+), 177 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 6bf1db11c4..3c9a8daba9 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -274,13 +274,13 @@ struct RtreeConstraint { }; /* Possible values for RtreeConstraint.op */ -#define RTREE_EQ 0x41 -#define RTREE_LE 0x42 -#define RTREE_LT 0x43 -#define RTREE_GE 0x44 -#define RTREE_GT 0x45 -#define RTREE_MATCH 0x46 /* Old-style sqlite3_rtree_geometry_callback() */ -#define RTREE_QUERY 0x47 /* New-style sqlite3_rtree_query_callback() */ +#define RTREE_EQ 0x41 /* A */ +#define RTREE_LE 0x42 /* B */ +#define RTREE_LT 0x43 /* C */ +#define RTREE_GE 0x44 /* D */ +#define RTREE_GT 0x45 /* E */ +#define RTREE_MATCH 0x46 /* F: Old-style sqlite3_rtree_geometry_callback() */ +#define RTREE_QUERY 0x47 /* G: New-style sqlite3_rtree_query_callback() */ /* @@ -900,149 +900,131 @@ static int rtreeEof(sqlite3_vtab_cursor *cur){ } /* -** The r-tree constraint passed as the second argument to this function is -** guaranteed to be a MATCH constraint. +** Convert raw bits from the on-disk RTree record into a coordinate value +** The on-disk record stores integer coordinates if eInt is true and it +** stores 32-bit floating point records if eInt is false. a[] is the four +** bytes of the on-disk record to be decoded. Store the results in "r". */ -static int rtreeTestGeom( - Rtree *pRtree, /* R-Tree object */ - RtreeConstraint *pConstraint, /* MATCH constraint to test */ - RtreeCell *pCell, /* Cell to test */ - int *pbRes /* OUT: Test result */ -){ - int i; - RtreeDValue aCoord[RTREE_MAX_DIMENSIONS*2]; - int nCoord = pRtree->nDim*2; - - assert( pConstraint->op==RTREE_MATCH ); - assert( pConstraint->pGeom ); - - for(i=0; iaCoord[i]); - } - return pConstraint->u.xGeom((sqlite3_rtree_geometry*)pConstraint->pGeom, - nCoord, aCoord, pbRes); +#define RTREE_DECODE_COORD(eInt, a, r) { \ + u32 x; /* Raw bits of the coordinate value */ \ + RtreeCoord c; /* Coordinate decoded */ \ + x = ((u32)a[0]<<24) + ((u32)a[1]<<16) \ + +((u32)a[2]<<8) + a[3]; \ + c.i = *(int*)&x; \ + r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ } + -/* -** Cursor pCursor currently points to a cell in a non-leaf page. -** Set *peWithin to NOT_WITHIN if the constraints in pCursor->aConstraint[] -** are guaranteed to never be satisfied by any subelement under the -** current cell. If some subelement of the cell might satisfy all -** constraints, then set *peWithin to PARTLY_WITHIN. If all subelements -** of the cell are guaranteed to fully satisfy all constraints, then -** set *peWithin to FULLY_WITHIN. -** -** In other words, set *peWithin to NOT_WITHIN, PARTLY_WITHIN, or -** FULLY_WITHIN if the cell is completely outside of the field-of-view, -** overlaps the field of view, or is completely contained within the -** field of view, respectively. -** -** It is not an error to set *peWithin to PARTLY_WITHIN when FULLY_WITHIN -** would be correct. Doing so is suboptimal, but will still give the -** correct answer. -** -** Return SQLITE_OK if successful or an SQLite error code if an error -** occurs. Errors can only possible if there is a geometry callback. +/* +** Check the RTree node or entry given by pCellData and p against the MATCH +** constraint pConstraint. */ -static int rtreeTestCell( - RtreeCursor *pCursor, /* The cursor to check */ - RtreeCell *pCell, /* The cell to check */ - int *peWithin /* Set true if element is out-of-bounds */ +static int rtreeCallbackConstraint( + RtreeConstraint *pConstraint, /* The constraint to test */ + int eInt, /* True if RTree holding integer coordinates */ + u8 *pCellData, /* Raw cell content */ + RtreeSearchPoint *pSearch, /* Container of this cell */ + sqlite3_rtree_dbl *prScore, /* OUT: score for the cell */ + int *peWithin /* OUT: visibility of the cell */ ){ - int ii; - int bOutOfBounds = 0; - int rc = SQLITE_OK; - Rtree *pRtree = RTREE_OF_CURSOR(pCursor); + int i; /* Loop counter */ + sqlite3_rtree_query_info *pGeom = pConstraint->pGeom; /* Callback info */ + int nCoord = pGeom->nCoord; /* No. of coordinates */ + int rc; /* Callback return code */ + sqlite3_rtree_dbl aCoord[RTREE_MAX_DIMENSIONS*2]; /* Decoded coordinates */ - for(ii=0; bOutOfBounds==0 && iinConstraint; ii++){ - RtreeConstraint *p = &pCursor->aConstraint[ii]; - RtreeDValue cell_min = DCOORD(pCell->aCoord[(p->iCoord>>1)*2]); - RtreeDValue cell_max = DCOORD(pCell->aCoord[(p->iCoord>>1)*2+1]); + assert( pConstraint->op==RTREE_MATCH || pConstraint->op==RTREE_QUERY ); + assert( nCoord==2 || nCoord==4 || nCoord==6 || nCoord==8 || nCoord==10 ); - assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE - || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH - ); - - switch( p->op ){ - case RTREE_LE: case RTREE_LT: - bOutOfBounds = p->u.rValueu.rValue>cell_max; - break; - - case RTREE_EQ: - bOutOfBounds = (p->u.rValue>cell_max || p->u.rValueop==RTREE_MATCH ); - rc = rtreeTestGeom(pRtree, p, pCell, &bOutOfBounds); - bOutOfBounds = !bOutOfBounds; - break; - } - } + pCellData += 8; + for(i=0; iop==RTREE_MATCH ){ + rc = pConstraint->u.xGeom((sqlite3_rtree_geometry*)pGeom, + nCoord, aCoord, &i); + if( i==0 ) *peWithin = NOT_WITHIN; + }else{ + pGeom->aCoord = aCoord; + pGeom->iLevel = pSearch->iLevel; + pGeom->rScore = pGeom->rParentScore = pSearch->rScore; + pGeom->eWithin = pGeom->eParentWithin = pSearch->eWithin; + rc = pConstraint->u.xQueryFunc(pGeom); + if( pGeom->eWithin<*peWithin ) *peWithin = pGeom->eWithin; + if( pGeom->rScore<*prScore ) *prScore = pGeom->rScore; } - - *peWithin = bOutOfBounds ? NOT_WITHIN : PARTLY_WITHIN; return rc; } /* -** pCursor points to a leaf r-tree entry which is a candidate for output. -** This routine sets *peWithin to one of NOT_WITHIN, PARTLY_WITHIN, or -** FULLY_WITHIN depending on whether or not the leaf entry is completely -** outside the region defined by pCursor->aConstraints[], or overlaps the -** region, or is completely within the region, respectively. -** -** This routine is more selective than rtreeTestCell(). rtreeTestCell() -** will return PARTLY_WITHIN or FULLY_WITHIN if the constraints are such -** that a subelement of the cell to be included in the result set. This -** routine is is only called for leaf r-tree entries and does not need -** to concern itself with subelements. Hence it only sets *peWithin to -** PARTLY_WITHIN or FULLY_WITHIN if the cell itself meets the requirements. -** -** Return SQLITE_OK if successful or an SQLite error code if an error -** occurs within a geometry callback. -** -** This function assumes that the cell is part of a leaf node. +** Check the internal RTree node given by pCellData against constraint p. +** If this constraint cannot be satisfied by any child within the node, +** set *peWithin to NOT_WITHIN. */ -static int rtreeTestEntry( - RtreeCursor *pCursor, /* Cursor pointing to the leaf element */ - RtreeCell *pCell, /* The cell to check */ - int *peWithin /* OUT: NOT_WITHIN, PARTLY_WITHIN, or FULLY_WITHIN */ +static void rtreeNonleafConstraint( + RtreeConstraint *p, /* The constraint to test */ + int eInt, /* True if RTree holds integer coordinates */ + u8 *pCellData, /* Raw cell content as appears on disk */ + int *peWithin /* Adjust downward, as appropriate */ ){ - Rtree *pRtree = RTREE_OF_CURSOR(pCursor); - int ii; - int res = 1; /* Innocent until proven guilty */ + sqlite3_rtree_dbl val; /* Coordinate value convert to a double */ - for(ii=0; res && iinConstraint; ii++){ - RtreeConstraint *p = &pCursor->aConstraint[ii]; - RtreeDValue coord = DCOORD(pCell->aCoord[p->iCoord]); - assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE - || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH - ); - switch( p->op ){ - case RTREE_LE: res = (coord<=p->u.rValue); break; - case RTREE_LT: res = (coordu.rValue); break; - case RTREE_GE: res = (coord>=p->u.rValue); break; - case RTREE_GT: res = (coord>p->u.rValue); break; - case RTREE_EQ: res = (coord==p->u.rValue); break; - default: { - int rc; - assert( p->op==RTREE_MATCH ); - rc = rtreeTestGeom(pRtree, p, pCell, &res); - if( rc!=SQLITE_OK ){ - return rc; - } - break; - } - } + /* p->iCoord might point to either a lower or upper bound coordinate + ** in a coordinate pair. But make pCellData point to the lower bound. + */ + pCellData += 8 + 4*(p->iCoord&0xfe); + + assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE + || p->op==RTREE_GT || p->op==RTREE_EQ ); + switch( p->op ){ + case RTREE_LE: + case RTREE_LT: + case RTREE_EQ: + RTREE_DECODE_COORD(eInt, pCellData, val); + /* val now holds the lower bound of the coordinate pair */ + if( p->u.rValue>=val ) return; + if( p->op!=RTREE_EQ ) break; /* RTREE_LE and RTREE_LT end here */ + /* Fall through for the RTREE_EQ case */ + + default: /* RTREE_GT or RTREE_GE, or fallthrough of RTREE_EQ */ + pCellData += 4; + RTREE_DECODE_COORD(eInt, pCellData, val); + /* val now holds the upper bound of the coordinate pair */ + if( p->u.rValue<=val ) return; } + *peWithin = NOT_WITHIN; +} - *peWithin = res ? FULLY_WITHIN : NOT_WITHIN; - return SQLITE_OK; +/* +** Check the leaf RTree cell given by pCellData against constraint p. +** If this constraint is not satisfied, set *peWithin to NOT_WITHIN. +** If the constraint is satisfied, leave *peWithin unchanged. +** +** The constraint is of the form: xN op $val +** +** The op is given by p->op. The xN is p->iCoord-th coordinate in +** pCellData. $val is given by p->u.rValue. +*/ +static void rtreeLeafConstraint( + RtreeConstraint *p, /* The constraint to test */ + int eInt, /* True if RTree holds integer coordinates */ + u8 *pCellData, /* Raw cell content as appears on disk */ + int *peWithin /* Adjust downward, as appropriate */ +){ + RtreeDValue xN; /* Coordinate value converted to a double */ + + assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE + || p->op==RTREE_GT || p->op==RTREE_EQ ); + pCellData += 8 + p->iCoord*4; + RTREE_DECODE_COORD(eInt, pCellData, xN); + switch( p->op ){ + case RTREE_LE: if( xN <= p->u.rValue ) return; break; + case RTREE_LT: if( xN < p->u.rValue ) return; break; + case RTREE_GE: if( xN >= p->u.rValue ) return; break; + case RTREE_GT: if( xN > p->u.rValue ) return; break; + default: if( xN == p->u.rValue ) return; break; + } + *peWithin = NOT_WITHIN; } /* @@ -1295,39 +1277,53 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){ int eWithin; int rc = SQLITE_OK; int nCell; - RtreeCell cell; + int nConstraint = pCur->nConstraint; + int ii; + int eInt; RtreeSearchPoint x; + eInt = pRtree->eCoordType==RTREE_COORD_INT32; while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){ pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc); if( rc ) return rc; nCell = NCELL(pNode); assert( nCell<200 ); while( p->iCelliCell, &cell); - if( p->iLevel==1 ){ - rc = rtreeTestEntry(pCur, &cell, &eWithin); - }else{ - rc = rtreeTestCell(pCur, &cell, &eWithin); + sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)0; + u8 *pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell); + eWithin = FULLY_WITHIN; + for(ii=0; iiaConstraint + ii; + if( pConstraint->op>=RTREE_MATCH ){ + rc = rtreeCallbackConstraint(pConstraint, eInt, pCellData, p, + &rScore, &eWithin); + if( rc ) return rc; + }else if( p->iLevel==1 ){ + rtreeLeafConstraint(pConstraint, eInt, pCellData, &eWithin); + }else{ + rtreeNonleafConstraint(pConstraint, eInt, pCellData, &eWithin); + } + if( eWithin==NOT_WITHIN ) break; } - if( rc ) return rc; - x = *p; p->iCell++; if( eWithin==NOT_WITHIN ) continue; + x.iLevel = p->iLevel - 1; + if( x.iLevel ){ + x.id = readInt64(pCellData); + x.iCell = 0; + }else{ + x.id = p->id; + x.iCell = p->iCell - 1; + } if( p->iCell>=nCell ){ RTREE_QUEUE_TRACE(pCur, "POP-S:"); rtreeSearchPointPop(pCur); } - p = rtreeSearchPointNew(pCur, /*rScore*/0.0, x.iLevel-1); + p = rtreeSearchPointNew(pCur, rScore, x.iLevel); if( p==0 ) return SQLITE_NOMEM; p->eWithin = eWithin; - if( p->iLevel ){ - p->id = cell.iRowid; - p->iCell = 0; - }else{ - p->id = x.id; - p->iCell = x.iCell; - } + p->id = x.id; + p->iCell = x.iCell; RTREE_QUEUE_TRACE(pCur, "PUSH-S:"); break; } @@ -1460,7 +1456,6 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ sqlite3_free(pGeom); return SQLITE_ERROR; } - pGeom->pContext = p->cb.pContext; pGeom->nParam = p->nParam; pGeom->aParam = p->aParam; @@ -1525,7 +1520,7 @@ static int rtreeFilter( for(ii=0; iiaConstraint[ii]; p->op = idxStr[ii*2]; - p->iCoord = idxStr[ii*2+1]-'a'; + p->iCoord = idxStr[ii*2+1]-'0'; if( p->op==RTREE_MATCH ){ /* A MATCH operator. The right-hand-side must be a blob that ** can be cast into an RtreeMatchArg object. One created using @@ -1535,6 +1530,7 @@ static int rtreeFilter( if( rc!=SQLITE_OK ){ break; } + p->pGeom->nCoord = pRtree->nDim*2; }else{ #ifdef SQLITE_RTREE_INT_ONLY p->u.rValue = sqlite3_value_int64(argv[ii]); @@ -1663,7 +1659,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ break; } zIdxStr[iIdx++] = op; - zIdxStr[iIdx++] = p->iColumn - 1 + 'a'; + zIdxStr[iIdx++] = p->iColumn - 1 + '0'; pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); pIdxInfo->aConstraintUsage[ii].omit = 1; } diff --git a/ext/rtree/rtree6.test b/ext/rtree/rtree6.test index bdc9bb4146..c5a78bb3e3 100644 --- a/ext/rtree/rtree6.test +++ b/ext/rtree/rtree6.test @@ -57,31 +57,31 @@ do_test rtree6-1.1 { do_test rtree6-1.2 { rtree_strategy {SELECT * FROM t1 WHERE x1>10} -} {Ea} +} {E0} do_test rtree6-1.3 { rtree_strategy {SELECT * FROM t1 WHERE x1<10} -} {Ca} +} {C0} do_test rtree6-1.4 { rtree_strategy {SELECT * FROM t1,t2 WHERE k=ii AND x1<10} -} {Ca} +} {C0} do_test rtree6-1.5 { rtree_strategy {SELECT * FROM t1,t2 WHERE k=+ii AND x1<10} -} {Ca} +} {C0} do_eqp_test rtree6.2.1 { SELECT * FROM t1,t2 WHERE k=+ii AND x1<10 } { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:Ca} + 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0} 0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)} } do_eqp_test rtree6.2.2 { SELECT * FROM t1,t2 WHERE k=ii AND x1<10 } { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:Ca} + 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0} 0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)} } @@ -95,7 +95,7 @@ do_eqp_test rtree6.2.3 { do_eqp_test rtree6.2.4 { SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10 } { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:CaEb} + 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1} 0 1 1 {SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)} } @@ -126,7 +126,7 @@ do_test rtree6.3.2 { x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 } -} {EaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEa} +} {E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0} do_test rtree6.3.3 { rtree_strategy { SELECT * FROM t3 WHERE @@ -137,7 +137,7 @@ do_test rtree6.3.3 { x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 } -} {EaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEa} +} {E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0} do_execsql_test rtree6-3.4 { SELECT * FROM t3 WHERE x1>0.5 AND x1>0.8 AND x1>1.1 diff --git a/ext/rtree/rtreeC.test b/ext/rtree/rtreeC.test index 23dc607841..94db05a4d1 100644 --- a/ext/rtree/rtreeC.test +++ b/ext/rtree/rtreeC.test @@ -29,7 +29,7 @@ do_eqp_test 1.1 { WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y } { 0 0 1 {SCAN TABLE t} - 0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa} + 0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0} } do_eqp_test 1.2 { @@ -37,7 +37,7 @@ do_eqp_test 1.2 { WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y } { 0 0 0 {SCAN TABLE t} - 0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa} + 0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0} } do_eqp_test 1.3 { @@ -45,7 +45,7 @@ do_eqp_test 1.3 { WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y } { 0 0 0 {SCAN TABLE t} - 0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa} + 0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0} } do_eqp_test 1.5 { @@ -82,7 +82,7 @@ do_eqp_test 2.1 { WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y } { 0 0 1 {SCAN TABLE t} - 0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa} + 0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0} } do_eqp_test 2.2 { @@ -90,7 +90,7 @@ do_eqp_test 2.2 { WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y } { 0 0 0 {SCAN TABLE t} - 0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa} + 0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0} } do_eqp_test 2.3 { @@ -98,7 +98,7 @@ do_eqp_test 2.3 { WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y } { 0 0 0 {SCAN TABLE t} - 0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa} + 0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0} } do_eqp_test 2.5 { @@ -271,4 +271,3 @@ ifcapable rtree { finish_test - diff --git a/manifest b/manifest index 336104aca0..d10804afcb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\soptimization\son\snodeGetCell()\sin\sR-Tree. -D 2014-04-16T21:02:28.844 +C Refactor\sthe\sconstraint\schecking\slogic\sin\sRTree.\s\sThe\snew-style\sconstraint\ncallbacks\screated\sby\ssqlite3_rtree_query_callback()\sare\snow\shooked\sup\sfrom\nend\sto\send,\sthough\sstill\suntested. +D 2014-04-17T13:15:33.281 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,20 +120,20 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 1a59db351a8dfaa46c59b3105865a1aaa5192a61 +F ext/rtree/rtree.c 117aaebed87a7c1e5d3e03afbad83c3700aa5ab8 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba F ext/rtree/rtree3.test a494da55c30ee0bc9b01a91c80c81b387b22d2dc F ext/rtree/rtree4.test c8fe384f60ebd49540a5fecc990041bf452eb6e0 F ext/rtree/rtree5.test 6a510494f12454bf57ef28f45bc7764ea279431e -F ext/rtree/rtree6.test fe0bd377a21c68ce2826129d14354c884cb1f354 +F ext/rtree/rtree6.test 756585abc51727fec97c77852476445c10c0ee95 F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971 F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34 F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e -F ext/rtree/rtreeC.test 16d7aa86ecb6a876d2a38cf590a1471a41b3a46d +F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06 F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea @@ -1175,7 +1175,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P f26936f71a16ab25590540f7feb273514dfb69ff -R b2b62cbe51f5e73202ce646c31659a05 +P 5d20ff9ec837ad35bc44d6c25d13764b350e81dd +R 9ddd572c495f4e9fca0e8e969ae19d88 U drh -Z 74eaec9038e9087250153055260f329f +Z 43698a2882be63e69b530e3c48875378 diff --git a/manifest.uuid b/manifest.uuid index a27b70bb21..5fbbb6cae9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5d20ff9ec837ad35bc44d6c25d13764b350e81dd \ No newline at end of file +32a13870175a1dd1d33af3572dde09ff607a04b6 \ No newline at end of file From b640595f97b7f55e619fd895becb7bf7ad5d6cf3 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 17 Apr 2014 14:52:20 +0000 Subject: [PATCH 099/570] Test cases and bug fixes for the sqlite3_rtree_query_callback() mechanism. FossilOrigin-Name: 1ccaaed6b516ec2ce953c1b31025a82ba76d00e7 --- ext/rtree/rtree.c | 113 ++++++++++++++++++++++++------------------ ext/rtree/rtreeE.test | 72 +++++++++++++++++++++++++++ manifest | 15 +++--- manifest.uuid | 2 +- src/test_rtree.c | 36 ++++++++------ 5 files changed, 168 insertions(+), 70 deletions(-) create mode 100644 ext/rtree/rtreeE.test diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 3c9a8daba9..53414af7ee 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -162,9 +162,11 @@ struct Rtree { #ifdef SQLITE_RTREE_INT_ONLY typedef sqlite3_int64 RtreeDValue; /* High accuracy coordinate */ typedef int RtreeValue; /* Low accuracy coordinate */ +# define RTREE_ZERO 0 #else typedef double RtreeDValue; /* High accuracy coordinate */ typedef float RtreeValue; /* Low accuracy coordinate */ +# define RTREE_ZERO 0.0 #endif /* @@ -270,7 +272,7 @@ struct RtreeConstraint { int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*); int (*xQueryFunc)(sqlite3_rtree_query_info*); } u; - sqlite3_rtree_query_info *pGeom; /* xGeom and xQueryFunc argument */ + sqlite3_rtree_query_info *pInfo; /* xGeom and xQueryFunc argument */ }; /* Possible values for RtreeConstraint.op */ @@ -863,10 +865,10 @@ static void freeCursorConstraints(RtreeCursor *pCsr){ if( pCsr->aConstraint ){ int i; /* Used to iterate through constraint array */ for(i=0; inConstraint; i++){ - sqlite3_rtree_query_info *pGeom = pCsr->aConstraint[i].pGeom; - if( pGeom ){ - if( pGeom->xDelUser ) pGeom->xDelUser(pGeom->pUser); - sqlite3_free(pGeom); + sqlite3_rtree_query_info *pInfo = pCsr->aConstraint[i].pInfo; + if( pInfo ){ + if( pInfo->xDelUser ) pInfo->xDelUser(pInfo->pUser); + sqlite3_free(pInfo); } } sqlite3_free(pCsr->aConstraint); @@ -928,8 +930,8 @@ static int rtreeCallbackConstraint( int *peWithin /* OUT: visibility of the cell */ ){ int i; /* Loop counter */ - sqlite3_rtree_query_info *pGeom = pConstraint->pGeom; /* Callback info */ - int nCoord = pGeom->nCoord; /* No. of coordinates */ + sqlite3_rtree_query_info *pInfo = pConstraint->pInfo; /* Callback info */ + int nCoord = pInfo->nCoord; /* No. of coordinates */ int rc; /* Callback return code */ sqlite3_rtree_dbl aCoord[RTREE_MAX_DIMENSIONS*2]; /* Decoded coordinates */ @@ -941,17 +943,20 @@ static int rtreeCallbackConstraint( RTREE_DECODE_COORD(eInt, pCellData, aCoord[i]); } if( pConstraint->op==RTREE_MATCH ){ - rc = pConstraint->u.xGeom((sqlite3_rtree_geometry*)pGeom, + rc = pConstraint->u.xGeom((sqlite3_rtree_geometry*)pInfo, nCoord, aCoord, &i); if( i==0 ) *peWithin = NOT_WITHIN; + *prScore = RTREE_ZERO; }else{ - pGeom->aCoord = aCoord; - pGeom->iLevel = pSearch->iLevel; - pGeom->rScore = pGeom->rParentScore = pSearch->rScore; - pGeom->eWithin = pGeom->eParentWithin = pSearch->eWithin; - rc = pConstraint->u.xQueryFunc(pGeom); - if( pGeom->eWithin<*peWithin ) *peWithin = pGeom->eWithin; - if( pGeom->rScore<*prScore ) *prScore = pGeom->rScore; + pInfo->aCoord = aCoord; + pInfo->iLevel = pSearch->iLevel; + pInfo->rScore = pInfo->rParentScore = pSearch->rScore; + pInfo->eWithin = pInfo->eParentWithin = pSearch->eWithin; + rc = pConstraint->u.xQueryFunc(pInfo); + if( pInfo->eWithin<*peWithin ) *peWithin = pInfo->eWithin; + if( pInfo->rScore<*prScore || *prScorerScore; + } } return rc; } @@ -1065,6 +1070,12 @@ static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){ /* ** Compare two search points. Return negative, zero, or positive if the first ** is less than, equal to, or greater than the second. +** +** The rScore is the primary key. Smaller rScore values come first. +** If the rScore is a tie, then use iLevel as the tie breaker with smaller +** iLevel values coming first. In this way, if rScore is the same for all +** SearchPoints, then iLevel becomes the deciding factor and the result +** is a depth-first search, which is the desired default behavior. */ static int rtreeSearchPointCompare( const RtreeSearchPoint *pA, @@ -1289,7 +1300,7 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){ nCell = NCELL(pNode); assert( nCell<200 ); while( p->iCellzData + (4+pRtree->nBytesPerCell*p->iCell); eWithin = FULLY_WITHIN; for(ii=0; iieWithin = eWithin; @@ -1429,9 +1441,10 @@ static int findLeafNode( ** operator. */ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ - RtreeMatchArg *p; - sqlite3_rtree_query_info *pGeom; - int nBlob; + RtreeMatchArg *pBlob; /* BLOB returned by geometry function */ + sqlite3_rtree_query_info *pInfo; /* Callback information */ + int nBlob; /* Size of the geometry function blob */ + int nExpected; /* Expected size of the BLOB */ /* Check that value is actually a blob. */ if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR; @@ -1444,24 +1457,29 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ return SQLITE_ERROR; } - pGeom = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pGeom)+nBlob ); - if( !pGeom ) return SQLITE_NOMEM; - memset(pGeom, 0, sizeof(*pGeom)); - p = (RtreeMatchArg*)&pGeom[1]; + pInfo = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pInfo)+nBlob ); + if( !pInfo ) return SQLITE_NOMEM; + memset(pInfo, 0, sizeof(*pInfo)); + pBlob = (RtreeMatchArg*)&pInfo[1]; - memcpy(p, sqlite3_value_blob(pValue), nBlob); - if( p->magic!=RTREE_GEOMETRY_MAGIC - || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(RtreeDValue)) - ){ - sqlite3_free(pGeom); + memcpy(pBlob, sqlite3_value_blob(pValue), nBlob); + nExpected = (int)(sizeof(RtreeMatchArg) + + (pBlob->nParam-1)*sizeof(RtreeDValue)); + if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){ + sqlite3_free(pInfo); return SQLITE_ERROR; } - pGeom->pContext = p->cb.pContext; - pGeom->nParam = p->nParam; - pGeom->aParam = p->aParam; + pInfo->pContext = pBlob->cb.pContext; + pInfo->nParam = pBlob->nParam; + pInfo->aParam = pBlob->aParam; - pCons->u.xGeom = p->cb.xGeom; - pCons->pGeom = pGeom; + if( pBlob->cb.xGeom ){ + pCons->u.xGeom = pBlob->cb.xGeom; + }else{ + pCons->op = RTREE_QUERY; + pCons->u.xQueryFunc = pBlob->cb.xQueryFunc; + } + pCons->pInfo = pInfo; return SQLITE_OK; } @@ -1493,7 +1511,7 @@ static int rtreeFilter( i64 iNode = 0; rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); if( rc==SQLITE_OK && pLeaf!=0 ){ - p = rtreeSearchPointNew(pCsr, 0.0, 0); + p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0); assert( p!=0 ); /* Always returns pCsr->sPoint */ pCsr->aNode[0] = pLeaf; p->id = iNode; @@ -1521,7 +1539,7 @@ static int rtreeFilter( RtreeConstraint *p = &pCsr->aConstraint[ii]; p->op = idxStr[ii*2]; p->iCoord = idxStr[ii*2+1]-'0'; - if( p->op==RTREE_MATCH ){ + if( p->op>=RTREE_MATCH ){ /* A MATCH operator. The right-hand-side must be a blob that ** can be cast into an RtreeMatchArg object. One created using ** an sqlite3_rtree_geometry_callback() SQL user function. @@ -1530,7 +1548,7 @@ static int rtreeFilter( if( rc!=SQLITE_OK ){ break; } - p->pGeom->nCoord = pRtree->nDim*2; + p->pInfo->nCoord = pRtree->nDim*2; }else{ #ifdef SQLITE_RTREE_INT_ONLY p->u.rValue = sqlite3_value_int64(argv[ii]); @@ -1546,7 +1564,8 @@ static int rtreeFilter( rc = nodeAcquire(pRtree, 1, 0, &pRoot); } if( rc==SQLITE_OK ){ - RtreeSearchPoint *pNew = rtreeSearchPointNew(pCsr, 0.0, pRtree->iDepth+1); + RtreeSearchPoint *pNew; + pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, pRtree->iDepth+1); if( pNew==0 ) return SQLITE_NOMEM; pNew->id = 1; pNew->iCell = 0; @@ -1759,7 +1778,7 @@ static RtreeDValue cellOverlap( int nCell ){ int ii; - RtreeDValue overlap = 0.0; + RtreeDValue overlap = RTREE_ZERO; for(ii=0; iinDim+1)*(sizeof(int*)+nCell*sizeof(int)); @@ -2071,9 +2090,9 @@ static int splitNodeStartree( } for(ii=0; iinDim; ii++){ - RtreeDValue margin = 0.0; - RtreeDValue fBestOverlap = 0.0; - RtreeDValue fBestArea = 0.0; + RtreeDValue margin = RTREE_ZERO; + RtreeDValue fBestOverlap = RTREE_ZERO; + RtreeDValue fBestArea = RTREE_ZERO; int iBestLeft = 0; int nLeft; @@ -2492,7 +2511,7 @@ static int Reinsert( } for(ii=0; iinDim; iDim++){ RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) - DCOORD(aCell[ii].aCoord[iDim*2])); @@ -3299,8 +3318,8 @@ int sqlite3RtreeInit(sqlite3 *db){ ** the corresponding SQL function is deleted. */ static void rtreeFreeCallback(void *p){ - RtreeGeomCallback *pGeom = (RtreeGeomCallback*)p; - if( pGeom->xDestructor ) pGeom->xDestructor(pGeom->pContext); + RtreeGeomCallback *pInfo = (RtreeGeomCallback*)p; + if( pInfo->xDestructor ) pInfo->xDestructor(pInfo->pContext); sqlite3_free(p); } diff --git a/ext/rtree/rtreeE.test b/ext/rtree/rtreeE.test new file mode 100644 index 0000000000..14f5c332ca --- /dev/null +++ b/ext/rtree/rtreeE.test @@ -0,0 +1,72 @@ +# 2010 August 28 +# +# 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 contains tests for the r-tree module. Specifically, it tests +# that new-style custom r-tree queries (geometry callbacks) work. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source $testdir/tester.tcl +ifcapable !rtree { finish_test ; return } +ifcapable rtree_int_only { finish_test; return } + + +#------------------------------------------------------------------------- +# Test the example 2d "circle" geometry callback. +# +register_circle_geom db + +do_execsql_test rtreeE-1.1 { + PRAGMA page_size=512; + CREATE VIRTUAL TABLE rt2 USING rtree(id,x0,x1,y0,y1); + + /* A tight pattern of small boxes near 0,0 */ + WITH RECURSIVE + x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4), + y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4) + INSERT INTO rt2 SELECT x+5*y, x, x+2, y, y+2 FROM x, y; + + /* A looser pattern of small boxes near 100, 0 */ + WITH RECURSIVE + x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4), + y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4) + INSERT INTO rt2 SELECT 100+x+5*y, x*3+100, x*3+102, y*3, y*3+2 FROM x, y; + + /* A looser pattern of larger boxes near 0, 200 */ + WITH RECURSIVE + x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4), + y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4) + INSERT INTO rt2 SELECT 200+x+5*y, x*7, x*7+15, y*7+200, y*7+215 FROM x, y; +} {} + +if 0 { +# Queries against each of the three clusters */ +do_execsql_test rtreeE-1.1 { + SELECT id FROM rt2 WHERE id MATCH Qcircle(0.0, 0.0, 50.0) ORDER BY id; +} {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24} +do_execsql_test rtreeE-1.2 { + SELECT id FROM rt2 WHERE id MATCH Qcircle(100.0, 0.0, 50.0) ORDER BY id; +} {100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124} +do_execsql_test rtreeE-1.3 { + SELECT id FROM rt2 WHERE id MATCH Qcircle(0.0, 200.0, 50.0) ORDER BY id; +} {200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224} +} + +# The Qcircle geometry function gives a lower score to larger leaf-nodes. +# This causes the 200s to sort before the 100s and the 0s to sort before +# last. +# +do_execsql_test rtreeE-1.4 { + SELECT id FROM rt2 WHERE id MATCH Qcircle(0,0,1000) AND id%100==0 +} {200 100 0} + +finish_test diff --git a/manifest b/manifest index d10804afcb..63a2d6b9ce 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Refactor\sthe\sconstraint\schecking\slogic\sin\sRTree.\s\sThe\snew-style\sconstraint\ncallbacks\screated\sby\ssqlite3_rtree_query_callback()\sare\snow\shooked\sup\sfrom\nend\sto\send,\sthough\sstill\suntested. -D 2014-04-17T13:15:33.281 +C Test\scases\sand\sbug\sfixes\sfor\sthe\ssqlite3_rtree_query_callback()\nmechanism. +D 2014-04-17T14:52:20.025 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 117aaebed87a7c1e5d3e03afbad83c3700aa5ab8 +F ext/rtree/rtree.c 6a47918e44697dd32f5bba8a79d3490e56bd76c9 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -135,6 +135,7 @@ F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06 F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca +F ext/rtree/rtreeE.test c8c951df54fd556d30eb621ecc2acd8771970a5e F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 488cf8834d2012b913d33683157d3cf5f1327a69 @@ -274,7 +275,7 @@ F src/test_osinst.c 90a845c8183013d80eccb1f29e8805608516edba F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00 F src/test_quota.c 30c64f0ef84734f2231a686df41ed882b0c59bc0 F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb -F src/test_rtree.c cd35d54c0b847c0c373d66f91616c49697ab4edf +F src/test_rtree.c 636d2a5bc9ded2fa1df4e7d4c575eb0d3f13b334 F src/test_schema.c cd12a2223c3a394f4d07bb93bdf6d344c5c121b6 F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe F src/test_sqllog.c c1c1bbedbcaf82b93d83e4f9dd990e62476a680e @@ -1175,7 +1176,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 5d20ff9ec837ad35bc44d6c25d13764b350e81dd -R 9ddd572c495f4e9fca0e8e969ae19d88 +P 32a13870175a1dd1d33af3572dde09ff607a04b6 +R 1f38906450e19fda5c27a4543b70f18c U drh -Z 43698a2882be63e69b530e3c48875378 +Z 26a5b86beaa061e155488cf6e80f8d30 diff --git a/manifest.uuid b/manifest.uuid index 5fbbb6cae9..07ccb10268 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -32a13870175a1dd1d33af3572dde09ff607a04b6 \ No newline at end of file +1ccaaed6b516ec2ce953c1b31025a82ba76d00e7 \ No newline at end of file diff --git a/src/test_rtree.c b/src/test_rtree.c index 3b4c205879..c1951a896b 100644 --- a/src/test_rtree.c +++ b/src/test_rtree.c @@ -35,6 +35,7 @@ struct Circle { double centerx; double centery; double radius; + double mxArea; }; /* @@ -58,7 +59,12 @@ static int circle_geom( double xmin, xmax; /* X dimensions of box being tested */ double ymin, ymax; /* X dimensions of box being tested */ - if( p->pUser==0 ){ + xmin = aCoord[0]; + xmax = aCoord[1]; + ymin = aCoord[2]; + ymax = aCoord[3]; + pCircle = (Circle *)p->pUser; + if( pCircle==0 ){ /* If pUser is still 0, then the parameter values have not been tested ** for correctness or stored into a Circle structure yet. Do this now. */ @@ -104,14 +110,9 @@ static int circle_geom( pCircle->aBox[1].xmax = pCircle->centerx - pCircle->radius; pCircle->aBox[1].ymin = pCircle->centery; pCircle->aBox[1].ymax = pCircle->centery; + pCircle->mxArea = (xmax - xmin)*(ymax - ymin) + 1.0; } - pCircle = (Circle *)p->pUser; - xmin = aCoord[0]; - xmax = aCoord[1]; - ymin = aCoord[2]; - ymax = aCoord[3]; - /* Check if any of the 4 corners of the bounding-box being tested lie ** inside the circular region. If they do, then the bounding-box does ** intersect the region of interest. Set the output variable to true and @@ -161,7 +162,12 @@ static int circle_query_func(sqlite3_rtree_query_info *p){ double ymin, ymax; /* X dimensions of box being tested */ int nWithin = 0; /* Number of corners inside the circle */ - if( p->pUser==0 ){ + xmin = p->aCoord[0]; + xmax = p->aCoord[1]; + ymin = p->aCoord[2]; + ymax = p->aCoord[3]; + pCircle = (Circle *)p->pUser; + if( pCircle==0 ){ /* If pUser is still 0, then the parameter values have not been tested ** for correctness or stored into a Circle structure yet. Do this now. */ @@ -207,14 +213,9 @@ static int circle_query_func(sqlite3_rtree_query_info *p){ pCircle->aBox[1].xmax = pCircle->centerx - pCircle->radius; pCircle->aBox[1].ymin = pCircle->centery; pCircle->aBox[1].ymax = pCircle->centery; + pCircle->mxArea = 200.0*200.0; } - pCircle = (Circle *)p->pUser; - xmin = p->aCoord[0]; - xmax = p->aCoord[1]; - ymin = p->aCoord[2]; - ymax = p->aCoord[3]; - /* Check if any of the 4 corners of the bounding-box being tested lie ** inside the circular region. If they do, then the bounding-box does ** intersect the region of interest. Set the output variable to true and @@ -246,7 +247,12 @@ static int circle_query_func(sqlite3_rtree_query_info *p){ } } - p->rScore = p->iLevel; + if( p->iLevel==2 ){ + p->rScore = 1.0 - (xmax-xmin)*(ymax-ymin)/pCircle->mxArea; + if( p->rScore<0.01 ) p->rScore = 0.01; + }else{ + p->rScore = 0.0; + } if( nWithin==0 ){ p->eWithin = NOT_WITHIN; }else if( nWithin>=4 ){ From 1821cbacf15e813af181b594a6b28af2c6fb0da6 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 17 Apr 2014 15:34:58 +0000 Subject: [PATCH 100/570] More test cases with very long priority queues. FossilOrigin-Name: 71692aa97c78676f0ba80eaeec0ad9ac225f4427 --- ext/rtree/rtreeE.test | 67 ++++++++++++++++++++++++++++++++++++------- manifest | 14 ++++----- manifest.uuid | 2 +- src/test_rtree.c | 61 +++++++++++++++++++++++++++++++++++---- 4 files changed, 120 insertions(+), 24 deletions(-) diff --git a/ext/rtree/rtreeE.test b/ext/rtree/rtreeE.test index 14f5c332ca..bc97943dcb 100644 --- a/ext/rtree/rtreeE.test +++ b/ext/rtree/rtreeE.test @@ -27,46 +27,93 @@ register_circle_geom db do_execsql_test rtreeE-1.1 { PRAGMA page_size=512; - CREATE VIRTUAL TABLE rt2 USING rtree(id,x0,x1,y0,y1); + CREATE VIRTUAL TABLE rt1 USING rtree(id,x0,x1,y0,y1); /* A tight pattern of small boxes near 0,0 */ WITH RECURSIVE x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4), y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4) - INSERT INTO rt2 SELECT x+5*y, x, x+2, y, y+2 FROM x, y; + INSERT INTO rt1 SELECT x+5*y, x, x+2, y, y+2 FROM x, y; /* A looser pattern of small boxes near 100, 0 */ WITH RECURSIVE x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4), y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4) - INSERT INTO rt2 SELECT 100+x+5*y, x*3+100, x*3+102, y*3, y*3+2 FROM x, y; + INSERT INTO rt1 SELECT 100+x+5*y, x*3+100, x*3+102, y*3, y*3+2 FROM x, y; /* A looser pattern of larger boxes near 0, 200 */ WITH RECURSIVE x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4), y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4) - INSERT INTO rt2 SELECT 200+x+5*y, x*7, x*7+15, y*7+200, y*7+215 FROM x, y; + INSERT INTO rt1 SELECT 200+x+5*y, x*7, x*7+15, y*7+200, y*7+215 FROM x, y; } {} -if 0 { # Queries against each of the three clusters */ do_execsql_test rtreeE-1.1 { - SELECT id FROM rt2 WHERE id MATCH Qcircle(0.0, 0.0, 50.0) ORDER BY id; + SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 0.0, 50.0, 3) ORDER BY id; } {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24} do_execsql_test rtreeE-1.2 { - SELECT id FROM rt2 WHERE id MATCH Qcircle(100.0, 0.0, 50.0) ORDER BY id; + SELECT id FROM rt1 WHERE id MATCH Qcircle(100.0, 0.0, 50.0, 3) ORDER BY id; } {100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124} do_execsql_test rtreeE-1.3 { - SELECT id FROM rt2 WHERE id MATCH Qcircle(0.0, 200.0, 50.0) ORDER BY id; + SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 200.0, 50.0, 3) ORDER BY id; } {200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224} -} # The Qcircle geometry function gives a lower score to larger leaf-nodes. # This causes the 200s to sort before the 100s and the 0s to sort before # last. # do_execsql_test rtreeE-1.4 { - SELECT id FROM rt2 WHERE id MATCH Qcircle(0,0,1000) AND id%100==0 + SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,3) AND id%100==0 } {200 100 0} +# Construct a large 2-D RTree with thousands of random entries. +# +do_test rtreeE-2.1 { + db eval { + CREATE TABLE t2(id,x0,x1,y0,y1); + CREATE VIRTUAL TABLE rt2 USING rtree(id,x0,x1,y0,y1); + BEGIN; + } + expr srand(0) + for {set i 1} {$i<=10000} {incr i} { + set dx [expr {int(rand()*40)+1}] + set dy [expr {int(rand()*40)+1}] + set x0 [expr {int(rand()*(10000 - $dx))}] + set x1 [expr {$x0+$dx}] + set y0 [expr {int(rand()*(10000 - $dy))}] + set y1 [expr {$y0+$dy}] + set id [expr {$i+10000}] + db eval {INSERT INTO t2 VALUES($id,$x0,$x1,$y0,$y1)} + } + db eval { + INSERT INTO rt2 SELECT * FROM t2; + COMMIT; + } +} {} + +for {set i 1} {$i<=200} {incr i} { + set dx [expr {int(rand()*100)}] + set dy [expr {int(rand()*100)}] + set x0 [expr {int(rand()*(10000 - $dx))}] + set x1 [expr {$x0+$dx}] + set y0 [expr {int(rand()*(10000 - $dy))}] + set y1 [expr {$y0+$dy}] + set ans [db eval {SELECT id FROM t2 WHERE x1>=$x0 AND x0<=$x1 AND y1>=$y0 AND y0<=$y1 ORDER BY id}] + do_execsql_test rtreeE-2.2.$i { + SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch($x0,$x1,$y0,$y1) ORDER BY id + } $ans +} + +# Run query that have very deep priority queues +# +set ans [db eval {SELECT id FROM t2 WHERE x1>=0 AND x0<=5000 AND y1>=0 AND y0<=5000 ORDER BY id}] +do_execsql_test rtreeE-2.3 { + SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,5000,0,5000) ORDER BY id +} $ans +set ans [db eval {SELECT id FROM t2 WHERE x1>=0 AND x0<=10000 AND y1>=0 AND y0<=10000 ORDER BY id}] +do_execsql_test rtreeE-2.4 { + SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,10000,0,10000) ORDER BY id +} $ans + finish_test diff --git a/manifest b/manifest index 63a2d6b9ce..6eb3fbb265 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Test\scases\sand\sbug\sfixes\sfor\sthe\ssqlite3_rtree_query_callback()\nmechanism. -D 2014-04-17T14:52:20.025 +C More\stest\scases\swith\svery\slong\spriority\squeues. +D 2014-04-17T15:34:58.372 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -135,7 +135,7 @@ F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06 F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca -F ext/rtree/rtreeE.test c8c951df54fd556d30eb621ecc2acd8771970a5e +F ext/rtree/rtreeE.test 0878fd6bce3a62ac980e6f67ba14cc86c8f4f2b3 F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 488cf8834d2012b913d33683157d3cf5f1327a69 @@ -275,7 +275,7 @@ F src/test_osinst.c 90a845c8183013d80eccb1f29e8805608516edba F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00 F src/test_quota.c 30c64f0ef84734f2231a686df41ed882b0c59bc0 F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb -F src/test_rtree.c 636d2a5bc9ded2fa1df4e7d4c575eb0d3f13b334 +F src/test_rtree.c 38cdb28581d07503c9135ef73692ec8192b876b0 F src/test_schema.c cd12a2223c3a394f4d07bb93bdf6d344c5c121b6 F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe F src/test_sqllog.c c1c1bbedbcaf82b93d83e4f9dd990e62476a680e @@ -1176,7 +1176,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 32a13870175a1dd1d33af3572dde09ff607a04b6 -R 1f38906450e19fda5c27a4543b70f18c +P 1ccaaed6b516ec2ce953c1b31025a82ba76d00e7 +R 449eb9a5ce303ca34184a4306bd9d328 U drh -Z 26a5b86beaa061e155488cf6e80f8d30 +Z 39039e877d4cb95ab625ec95bd5cc650 diff --git a/manifest.uuid b/manifest.uuid index 07ccb10268..f923c4ba43 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1ccaaed6b516ec2ce953c1b31025a82ba76d00e7 \ No newline at end of file +71692aa97c78676f0ba80eaeec0ad9ac225f4427 \ No newline at end of file diff --git a/src/test_rtree.c b/src/test_rtree.c index c1951a896b..51e991949c 100644 --- a/src/test_rtree.c +++ b/src/test_rtree.c @@ -36,6 +36,7 @@ struct Circle { double centery; double radius; double mxArea; + int eScoreType; }; /* @@ -175,10 +176,10 @@ static int circle_query_func(sqlite3_rtree_query_info *p){ ** Return an error if the table does not have exactly 2 dimensions. */ if( p->nCoord!=4 ) return SQLITE_ERROR; - /* Test that the correct number of parameters (3) have been supplied, + /* Test that the correct number of parameters (4) have been supplied, ** and that the parameters are in range (that the radius of the circle ** radius is greater than zero). */ - if( p->nParam!=3 || p->aParam[2]<0.0 ) return SQLITE_ERROR; + if( p->nParam!=4 || p->aParam[2]<0.0 ) return SQLITE_ERROR; /* Allocate a structure to cache parameter data in. Return SQLITE_NOMEM ** if the allocation fails. */ @@ -193,6 +194,7 @@ static int circle_query_func(sqlite3_rtree_query_info *p){ pCircle->centerx = p->aParam[0]; pCircle->centery = p->aParam[1]; pCircle->radius = p->aParam[2]; + pCircle->eScoreType = (int)p->aParam[3]; /* Define two bounding box regions. The first, aBox[0], extends to ** infinity in the X dimension. It covers the same range of the Y dimension @@ -247,11 +249,21 @@ static int circle_query_func(sqlite3_rtree_query_info *p){ } } - if( p->iLevel==2 ){ - p->rScore = 1.0 - (xmax-xmin)*(ymax-ymin)/pCircle->mxArea; - if( p->rScore<0.01 ) p->rScore = 0.01; + if( pCircle->eScoreType==1 ){ + /* Depth first search */ + p->rScore = p->iLevel; + }else if( pCircle->eScoreType==2 ){ + /* Breadth first search */ + p->rScore = 100 - p->iLevel; }else{ - p->rScore = 0.0; + /* Depth-first search, except sort the leaf nodes by area with + ** the largest area first */ + if( p->iLevel==2 ){ + p->rScore = 1.0 - (xmax-xmin)*(ymax-ymin)/pCircle->mxArea; + if( p->rScore<0.01 ) p->rScore = 0.01; + }else{ + p->rScore = 0.0; + } } if( nWithin==0 ){ p->eWithin = NOT_WITHIN; @@ -262,6 +274,39 @@ static int circle_query_func(sqlite3_rtree_query_info *p){ } return SQLITE_OK; } +/* +** Implementation of "breadthfirstsearch" r-tree geometry callback using the +** 2nd-generation interface that allows scoring. +** +** ... WHERE id MATCH breadthfirstsearch($x0,$x1,$y0,$y1) ... +** +** It returns all entries whose bounding boxes overlap with $x0,$x1,$y0,$y1. +*/ +static int bfs_query_func(sqlite3_rtree_query_info *p){ + double x0,x1,y0,y1; /* Dimensions of box being tested */ + double bx0,bx1,by0,by1; /* Boundary of the query function */ + + if( p->nParam!=4 ) return SQLITE_ERROR; + x0 = p->aCoord[0]; + x1 = p->aCoord[1]; + y0 = p->aCoord[2]; + y1 = p->aCoord[3]; + bx0 = p->aParam[0]; + bx1 = p->aParam[1]; + by0 = p->aParam[2]; + by1 = p->aParam[3]; + p->rScore = 100 - p->iLevel; + if( p->eParentWithin==FULLY_WITHIN ){ + p->eWithin = FULLY_WITHIN; + }else if( x0>=bx0 && x1<=bx1 && y0>=by0 && y1<=by1 ){ + p->eWithin = FULLY_WITHIN; + }else if( x1>=bx0 && x0<=bx1 && y1>=by0 && y0<=by1 ){ + p->eWithin = PARTLY_WITHIN; + }else{ + p->eWithin = NOT_WITHIN; + } + return SQLITE_OK; +} /* END of implementation of "circle" geometry callback. ************************************************************************** @@ -402,6 +447,10 @@ static int register_circle_geom( rc = sqlite3_rtree_query_callback(db, "Qcircle", circle_query_func, 0, 0); } + if( rc==SQLITE_OK ){ + rc = sqlite3_rtree_query_callback(db, "breadthfirstsearch", + bfs_query_func, 0, 0); + } Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); #endif return TCL_OK; From a5db90fc8ee2e7dfdd1093f9a6ed4dc27ad7f1c4 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 17 Apr 2014 23:23:29 +0000 Subject: [PATCH 101/570] Performance optimization on byte-swapping in R-Tree. FossilOrigin-Name: 444084fd620fc3f45cfb87b83f532d76bd2744e7 --- ext/rtree/rtree.c | 28 +++++++++++++++++++++------- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 53414af7ee..620c158288 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -243,6 +243,7 @@ struct RtreeCursor { union RtreeCoord { RtreeValue f; /* Floating point value */ int i; /* Integer value */ + u32 u; /* Unsigned for byte-order conversions */ }; /* @@ -902,19 +903,32 @@ static int rtreeEof(sqlite3_vtab_cursor *cur){ } /* -** Convert raw bits from the on-disk RTree record into a coordinate value -** The on-disk record stores integer coordinates if eInt is true and it -** stores 32-bit floating point records if eInt is false. a[] is the four +** Convert raw bits from the on-disk RTree record into a coordinate value. +** The on-disk format is big-endian and needs to be converted for little-endian +** platforms. The on-disk record stores integer coordinates if eInt is true +** and it stores 32-bit floating point records if eInt is false. a[] is the four ** bytes of the on-disk record to be decoded. Store the results in "r". +** +** The first version of this macro is fast on x86, x86_64 and ARM, all of which +** are little-endian. The second version of this macro is cross-platform but +** takes twice as long, according to valgrind on linux x64. */ +#if defined(__x86) || defined(__x86_64) || defined(__arm__) || defined(_MSC_VER) #define RTREE_DECODE_COORD(eInt, a, r) { \ - u32 x; /* Raw bits of the coordinate value */ \ RtreeCoord c; /* Coordinate decoded */ \ - x = ((u32)a[0]<<24) + ((u32)a[1]<<16) \ - +((u32)a[2]<<8) + a[3]; \ - c.i = *(int*)&x; \ + memcpy(&c.u,a,4); \ + c.u = ((c.u>>24)&0xff)|((c.u>>8)&0xff00)| \ + ((c.u&0xff)<<24)|((c.u&0xff00)<<8); \ r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ } +#else +#define RTREE_DECODE_COORD(eInt, a, r) { \ + RtreeCoord c; /* Coordinate decoded */ \ + c.u = ((u32)a[0]<<24) + ((u32)a[1]<<16) \ + +((u32)a[2]<<8) + a[3]; \ + r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ +} +#endif /* diff --git a/manifest b/manifest index 6eb3fbb265..f00e6668a6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C More\stest\scases\swith\svery\slong\spriority\squeues. -D 2014-04-17T15:34:58.372 +C Performance\soptimization\son\sbyte-swapping\sin\sR-Tree. +D 2014-04-17T23:23:29.676 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 6a47918e44697dd32f5bba8a79d3490e56bd76c9 +F ext/rtree/rtree.c 5cf5ae21ca1742be863f025ce64e4262fc6def4c F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -1176,7 +1176,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 1ccaaed6b516ec2ce953c1b31025a82ba76d00e7 -R 449eb9a5ce303ca34184a4306bd9d328 +P 71692aa97c78676f0ba80eaeec0ad9ac225f4427 +R f1ebd50a7930430ccdb2dd222ebc5021 U drh -Z 39039e877d4cb95ab625ec95bd5cc650 +Z 8e204d3bb697cd291df3586d6cea66ab diff --git a/manifest.uuid b/manifest.uuid index f923c4ba43..41369a2d98 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -71692aa97c78676f0ba80eaeec0ad9ac225f4427 \ No newline at end of file +444084fd620fc3f45cfb87b83f532d76bd2744e7 \ No newline at end of file From ec7c03a08ba8fa274c38dca3d00c83ea0b518286 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 Apr 2014 01:37:08 +0000 Subject: [PATCH 102/570] Further improvements to the RTREE_DECODE_COORD() method, to take advantage of known processor byte orders when available. This makes the code 3% faster, according to valgrind. Also add test cases to make sure the on-disk representation is correct. FossilOrigin-Name: 6f3e94f4b1b403cd7bfc5e8e0ffbd61b5174d3a4 --- ext/rtree/rtree.c | 34 +++++++++++++++++++++++----------- ext/rtree/rtree1.test | 19 +++++++++++-------- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 620c158288..bcaa4d635a 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -904,16 +904,21 @@ static int rtreeEof(sqlite3_vtab_cursor *cur){ /* ** Convert raw bits from the on-disk RTree record into a coordinate value. -** The on-disk format is big-endian and needs to be converted for little-endian -** platforms. The on-disk record stores integer coordinates if eInt is true -** and it stores 32-bit floating point records if eInt is false. a[] is the four -** bytes of the on-disk record to be decoded. Store the results in "r". +** The on-disk format is big-endian and needs to be converted for little- +** endian platforms. The on-disk record stores integer coordinates if +** eInt is true and it stores 32-bit floating point records if eInt is +** false. a[] is the four bytes of the on-disk record to be decoded. +** Store the results in "r". ** -** The first version of this macro is fast on x86, x86_64 and ARM, all of which -** are little-endian. The second version of this macro is cross-platform but -** takes twice as long, according to valgrind on linux x64. +** There are three versions of this macro, one each for little-endian and +** big-endian processors and a third generic implementation. The endian- +** specific implementations are much faster and are preferred if the +** processor endianness is known at compile-time. The SQLITE_BYTEORDER +** macro is part of sqliteInt.h and hence the endian-specific +** implementation will only be used if this module is compiled as part +** of the amalgamation. */ -#if defined(__x86) || defined(__x86_64) || defined(__arm__) || defined(_MSC_VER) +#if defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==1234 #define RTREE_DECODE_COORD(eInt, a, r) { \ RtreeCoord c; /* Coordinate decoded */ \ memcpy(&c.u,a,4); \ @@ -921,6 +926,12 @@ static int rtreeEof(sqlite3_vtab_cursor *cur){ ((c.u&0xff)<<24)|((c.u&0xff00)<<8); \ r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ } +#elif defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==4321 +#define RTREE_DECODE_COORD(eInt, a, r) { \ + RtreeCoord c; /* Coordinate decoded */ \ + memcpy(&c.u,a,4); \ + r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ +} #else #define RTREE_DECODE_COORD(eInt, a, r) { \ RtreeCoord c; /* Coordinate decoded */ \ @@ -929,7 +940,6 @@ static int rtreeEof(sqlite3_vtab_cursor *cur){ r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ } #endif - /* ** Check the RTree node or entry given by pCellData and p against the MATCH @@ -2242,7 +2252,8 @@ static int SplitNode( memset(pLeft->zData, 0, pRtree->iNodeSize); memset(pRight->zData, 0, pRtree->iNodeSize); - rc = splitNodeStartree(pRtree, aCell, nCell, pLeft, pRight,&leftbbox,&rightbbox); + rc = splitNodeStartree(pRtree, aCell, nCell, pLeft, pRight, + &leftbbox, &rightbbox); if( rc!=SQLITE_OK ){ goto splitnode_out; } @@ -3003,7 +3014,8 @@ static int rtreeSqlInit( char *zCreate = sqlite3_mprintf( "CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY, data BLOB);" "CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY, nodeno INTEGER);" -"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY, parentnode INTEGER);" +"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY," + " parentnode INTEGER);" "INSERT INTO '%q'.'%q_node' VALUES(1, zeroblob(%d))", zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, pRtree->iNodeSize ); diff --git a/ext/rtree/rtree1.test b/ext/rtree/rtree1.test index 275b13264f..9de5362781 100644 --- a/ext/rtree/rtree1.test +++ b/ext/rtree/rtree1.test @@ -120,12 +120,13 @@ proc execsql_intout {sql} { # Test that it is possible to open an existing database that contains # r-tree tables. # -do_test rtree-1.4.1 { - execsql { - CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2); - INSERT INTO t1 VALUES(1, 5.0, 10.0); - INSERT INTO t1 VALUES(2, 15.0, 20.0); - } +do_execsql_test rtree-1.4.1a { + CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2); + INSERT INTO t1 VALUES(1, 5.0, 10.0); + SELECT substr(hex(data),1,40) FROM t1_node; +} {00000001000000000000000140A0000041200000} +do_execsql_test rtree-1.4.1b { + INSERT INTO t1 VALUES(2, 15.0, 20.0); } {} do_test rtree-1.4.2 { db close @@ -435,16 +436,18 @@ do_test rtree-11.2 { # Test on-conflict clause handling. # db_delete_and_reopen -do_execsql_test 12.0 { +do_execsql_test 12.0.1 { CREATE VIRTUAL TABLE t1 USING rtree_i32(idx, x1, x2, y1, y2); INSERT INTO t1 VALUES(1, 1, 2, 3, 4); + SELECT substr(hex(data),1,56) FROM t1_node; +} {00000001000000000000000100000001000000020000000300000004} +do_execsql_test 12.0.2 { INSERT INTO t1 VALUES(2, 2, 3, 4, 5); INSERT INTO t1 VALUES(3, 3, 4, 5, 6); CREATE TABLE source(idx, x1, x2, y1, y2); INSERT INTO source VALUES(5, 8, 8, 8, 8); INSERT INTO source VALUES(2, 7, 7, 7, 7); - } db_save_and_close foreach {tn sql_template testdata} { diff --git a/manifest b/manifest index 967e3767a3..760724c749 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\slatest\schanges\sfrom\ssessions. -D 2014-04-18T01:14:46.009 +C Further\simprovements\sto\sthe\sRTREE_DECODE_COORD()\smethod,\sto\stake\sadvantage\nof\sknown\sprocessor\sbyte\sorders\swhen\savailable.\s\sThis\smakes\sthe\scode\s3%\sfaster,\naccording\sto\svalgrind.\s\sAlso\sadd\stest\scases\sto\smake\ssure\sthe\son-disk\nrepresentation\sis\scorrect. +D 2014-04-18T01:37:08.946 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,9 +120,9 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 5cf5ae21ca1742be863f025ce64e4262fc6def4c +F ext/rtree/rtree.c b8357523ca0aa01ec8efffdec0868909e3744257 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e -F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290 +F ext/rtree/rtree1.test e2da4aaa426918d27122d1a1066c6ecf8409a514 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba F ext/rtree/rtree3.test a494da55c30ee0bc9b01a91c80c81b387b22d2dc F ext/rtree/rtree4.test c8fe384f60ebd49540a5fecc990041bf452eb6e0 @@ -1177,7 +1177,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 444084fd620fc3f45cfb87b83f532d76bd2744e7 95e77efe076ab421bd246119c47dba5dacf9d087 -R e9845f4b2c71a18e1d378888de7ae7a2 +P d9eef5b03c7c4bb69c11eda41152ee81aed1cac7 +R fd5f15a432e8499b9e125ee6ec5ed14e U drh -Z 0c4fc380d884463ecab3c74420a85e5e +Z 4e8eac956a9a7b7e58efbf89636dab07 diff --git a/manifest.uuid b/manifest.uuid index 2112ab381a..ddcb25049d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d9eef5b03c7c4bb69c11eda41152ee81aed1cac7 \ No newline at end of file +6f3e94f4b1b403cd7bfc5e8e0ffbd61b5174d3a4 \ No newline at end of file From a6ca7f2c1bb27886702423d9217c6ab9d63edd0a Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 21 Apr 2014 15:21:19 +0000 Subject: [PATCH 103/570] Fix an off-by-one error in setting the "iLevel" field of the sqlite3_rtree_query_info structure passed into the RTree query callback. FossilOrigin-Name: d708f159abfb3b87e2844463088d4fb7f8da9c97 --- ext/rtree/rtree.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- src/test_rtree.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index bcaa4d635a..4f843a3d46 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -973,7 +973,7 @@ static int rtreeCallbackConstraint( *prScore = RTREE_ZERO; }else{ pInfo->aCoord = aCoord; - pInfo->iLevel = pSearch->iLevel; + pInfo->iLevel = pSearch->iLevel - 1; pInfo->rScore = pInfo->rParentScore = pSearch->rScore; pInfo->eWithin = pInfo->eParentWithin = pSearch->eWithin; rc = pConstraint->u.xQueryFunc(pInfo); diff --git a/manifest b/manifest index 760724c749..dd1b8e9de2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\simprovements\sto\sthe\sRTREE_DECODE_COORD()\smethod,\sto\stake\sadvantage\nof\sknown\sprocessor\sbyte\sorders\swhen\savailable.\s\sThis\smakes\sthe\scode\s3%\sfaster,\naccording\sto\svalgrind.\s\sAlso\sadd\stest\scases\sto\smake\ssure\sthe\son-disk\nrepresentation\sis\scorrect. -D 2014-04-18T01:37:08.946 +C Fix\san\soff-by-one\serror\sin\ssetting\sthe\s"iLevel"\sfield\sof\sthe\nsqlite3_rtree_query_info\sstructure\spassed\sinto\sthe\sRTree\squery\scallback. +D 2014-04-21T15:21:19.367 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c b8357523ca0aa01ec8efffdec0868909e3744257 +F ext/rtree/rtree.c 09000d72086c21979960426bc9b592a6007bfb8d F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test e2da4aaa426918d27122d1a1066c6ecf8409a514 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -275,7 +275,7 @@ F src/test_osinst.c 90a845c8183013d80eccb1f29e8805608516edba F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00 F src/test_quota.c 30c64f0ef84734f2231a686df41ed882b0c59bc0 F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb -F src/test_rtree.c 38cdb28581d07503c9135ef73692ec8192b876b0 +F src/test_rtree.c 4c1ff96a2d3a84e6a12fe8643e6d46dae0ef11de F src/test_schema.c cd12a2223c3a394f4d07bb93bdf6d344c5c121b6 F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe F src/test_sqllog.c c1c1bbedbcaf82b93d83e4f9dd990e62476a680e @@ -1177,7 +1177,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P d9eef5b03c7c4bb69c11eda41152ee81aed1cac7 -R fd5f15a432e8499b9e125ee6ec5ed14e +P 6f3e94f4b1b403cd7bfc5e8e0ffbd61b5174d3a4 +R 9cd9b8456e5c8aff94fe9550b50b870a U drh -Z 4e8eac956a9a7b7e58efbf89636dab07 +Z 1f57c8fdc97d1a8a65988c09a5e9a0f3 diff --git a/manifest.uuid b/manifest.uuid index ddcb25049d..89bf0fdeca 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6f3e94f4b1b403cd7bfc5e8e0ffbd61b5174d3a4 \ No newline at end of file +d708f159abfb3b87e2844463088d4fb7f8da9c97 \ No newline at end of file diff --git a/src/test_rtree.c b/src/test_rtree.c index 51e991949c..eb918ac5fd 100644 --- a/src/test_rtree.c +++ b/src/test_rtree.c @@ -258,7 +258,7 @@ static int circle_query_func(sqlite3_rtree_query_info *p){ }else{ /* Depth-first search, except sort the leaf nodes by area with ** the largest area first */ - if( p->iLevel==2 ){ + if( p->iLevel==1 ){ p->rScore = 1.0 - (xmax-xmin)*(ymax-ymin)/pCircle->mxArea; if( p->rScore<0.01 ) p->rScore = 0.01; }else{ From 74188329ce6084e428e3fa9ddc9d1c5419819718 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 21 Apr 2014 15:53:45 +0000 Subject: [PATCH 104/570] Be sure to initialize the sqlite3_rtree_query_info.iRowid field for the leaves of the R-Tree when doing a query callback search. FossilOrigin-Name: 4394693882c04c19ebe87ef7547c57e679554397 --- ext/rtree/rtree.c | 3 +++ manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 4f843a3d46..a471514c53 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -962,6 +962,9 @@ static int rtreeCallbackConstraint( assert( pConstraint->op==RTREE_MATCH || pConstraint->op==RTREE_QUERY ); assert( nCoord==2 || nCoord==4 || nCoord==6 || nCoord==8 || nCoord==10 ); + if( pConstraint->op==RTREE_MATCH && pSearch->iLevel==1 ){ + pInfo->iRowid = readInt64(pCellData); + } pCellData += 8; for(i=0; i Date: Mon, 21 Apr 2014 18:13:37 +0000 Subject: [PATCH 105/570] Fix the generation of sqlite3_rtree_query_info.iRowid and add test cases to verify that it is fixed. FossilOrigin-Name: eba95ead49f8f8ce45d400186562ff0066537c5c --- ext/rtree/rtree.c | 2 +- ext/rtree/rtreeE.test | 10 ++++++++++ manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/test_rtree.c | 10 +++++++++- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index a471514c53..a6c99cb9ee 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -962,7 +962,7 @@ static int rtreeCallbackConstraint( assert( pConstraint->op==RTREE_MATCH || pConstraint->op==RTREE_QUERY ); assert( nCoord==2 || nCoord==4 || nCoord==6 || nCoord==8 || nCoord==10 ); - if( pConstraint->op==RTREE_MATCH && pSearch->iLevel==1 ){ + if( pConstraint->op==RTREE_QUERY && pSearch->iLevel==1 ){ pInfo->iRowid = readInt64(pCellData); } pCellData += 8; diff --git a/ext/rtree/rtreeE.test b/ext/rtree/rtreeE.test index bc97943dcb..c450623790 100644 --- a/ext/rtree/rtreeE.test +++ b/ext/rtree/rtreeE.test @@ -67,6 +67,16 @@ do_execsql_test rtreeE-1.4 { SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,3) AND id%100==0 } {200 100 0} +# Exclude odd rowids on a depth-first search +do_execsql_test rtreeE-1.5 { + SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,4) ORDER BY +id +} {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224} + +# Exclude odd rowids on a breadth-first search. +do_execsql_test rtreeE-1.6 { + SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,5) ORDER BY +id +} {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224} + # Construct a large 2-D RTree with thousands of random entries. # do_test rtreeE-2.1 { diff --git a/manifest b/manifest index 992786f329..a115e0886e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Be\ssure\sto\sinitialize\sthe\ssqlite3_rtree_query_info.iRowid\sfield\sfor\sthe\nleaves\sof\sthe\sR-Tree\swhen\sdoing\sa\squery\scallback\ssearch. -D 2014-04-21T15:53:45.432 +C Fix\sthe\sgeneration\sof\ssqlite3_rtree_query_info.iRowid\sand\sadd\stest\scases\nto\sverify\sthat\sit\sis\sfixed. +D 2014-04-21T18:13:37.363 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 2474c438614edfc171bd9a85e3374f732511d962 +F ext/rtree/rtree.c 77fdd459e7edf78a385a83930e2b072b2f0131b5 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test e2da4aaa426918d27122d1a1066c6ecf8409a514 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -135,7 +135,7 @@ F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06 F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca -F ext/rtree/rtreeE.test 0878fd6bce3a62ac980e6f67ba14cc86c8f4f2b3 +F ext/rtree/rtreeE.test 388c1c8602c3ce55c15f03b509e9cf545fb7c41f F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 488cf8834d2012b913d33683157d3cf5f1327a69 @@ -275,7 +275,7 @@ F src/test_osinst.c 90a845c8183013d80eccb1f29e8805608516edba F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00 F src/test_quota.c 30c64f0ef84734f2231a686df41ed882b0c59bc0 F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb -F src/test_rtree.c 4c1ff96a2d3a84e6a12fe8643e6d46dae0ef11de +F src/test_rtree.c fdd8d29ca5165c7857987a2ba263fac5c69e231f F src/test_schema.c cd12a2223c3a394f4d07bb93bdf6d344c5c121b6 F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe F src/test_sqllog.c c1c1bbedbcaf82b93d83e4f9dd990e62476a680e @@ -1177,7 +1177,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P d708f159abfb3b87e2844463088d4fb7f8da9c97 -R b6276022832016ce4c25e5317a578a57 +P 4394693882c04c19ebe87ef7547c57e679554397 +R 9a6527f0d42b13ef1dcd87b1f989aba6 U drh -Z 8b38b422713df2439dae120af50d35b5 +Z 8819b772d7d2f245af8d8a9675d9c9d8 diff --git a/manifest.uuid b/manifest.uuid index ceffd746e2..d92fc37198 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4394693882c04c19ebe87ef7547c57e679554397 \ No newline at end of file +eba95ead49f8f8ce45d400186562ff0066537c5c \ No newline at end of file diff --git a/src/test_rtree.c b/src/test_rtree.c index eb918ac5fd..9d19fa0e2c 100644 --- a/src/test_rtree.c +++ b/src/test_rtree.c @@ -255,7 +255,7 @@ static int circle_query_func(sqlite3_rtree_query_info *p){ }else if( pCircle->eScoreType==2 ){ /* Breadth first search */ p->rScore = 100 - p->iLevel; - }else{ + }else if( pCircle->eScoreType==3 ){ /* Depth-first search, except sort the leaf nodes by area with ** the largest area first */ if( p->iLevel==1 ){ @@ -264,6 +264,14 @@ static int circle_query_func(sqlite3_rtree_query_info *p){ }else{ p->rScore = 0.0; } + }else if( pCircle->eScoreType==4 ){ + /* Depth-first search, except exclude odd rowids */ + p->rScore = p->iLevel; + if( p->iRowid&1 ) nWithin = 0; + }else{ + /* Breadth-first search, except exclude odd rowids */ + p->rScore = 100 - p->iLevel; + if( p->iRowid&1 ) nWithin = 0; } if( nWithin==0 ){ p->eWithin = NOT_WITHIN; From c686929914188d138527dcf460c025ef4b3638e9 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 25 Apr 2014 16:29:03 +0000 Subject: [PATCH 106/570] Enhance the sqlite3_rtree_query_info object to report on the number of elements in the priority queue at each level. FossilOrigin-Name: f7dad408dd46a1e3612b6142a3afb1d0d4fcda00 --- ext/rtree/rtree.c | 20 ++++++++++++++------ ext/rtree/sqlite3rtree.h | 2 ++ manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index a6c99cb9ee..7b540b4be1 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -228,9 +228,11 @@ struct RtreeCursor { RtreeConstraint *aConstraint; /* Search constraints. */ int nPointAlloc; /* Number of slots allocated for aPoint[] */ int nPoint; /* Number of slots used in aPoint[] */ + int mxLevel; /* iLevel value for root of the tree */ RtreeSearchPoint *aPoint; /* Priority queue for search points */ RtreeSearchPoint sPoint; /* Cached next search point */ RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */ + u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */ }; /* Return the Rtree of a RtreeCursor */ @@ -1179,7 +1181,8 @@ static RtreeSearchPoint *rtreeEnqueue( i = pCur->nPoint++; pNew = pCur->aPoint + i; pNew->rScore = rScore; - pNew->iLevel = iLevel; + pNew->iLevel = iLevel; + assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH ); while( i>0 ){ RtreeSearchPoint *pParent; j = (i-1)/2; @@ -1203,6 +1206,7 @@ static RtreeSearchPoint *rtreeSearchPointNew( ){ RtreeSearchPoint *pNew, *pFirst; pFirst = rtreeSearchPointFirst(pCur); + pCur->anQueue[iLevel]++; if( pFirst==0 || pFirst->rScore>rScore || (pFirst->rScore==rScore && pFirst->iLevel>iLevel) @@ -1271,8 +1275,10 @@ static void rtreeSearchPointPop(RtreeCursor *p){ p->aNode[i] = 0; } if( p->bPoint ){ + p->anQueue[p->sPoint.iLevel]--; p->bPoint = 0; }else if( p->nPoint ){ + p->anQueue[p->aPoint[0].iLevel]--; n = --p->nPoint; p->aPoint[0] = p->aPoint[n]; if( n0 ){ + rc = nodeAcquire(pRtree, 1, 0, &pRoot); + if( rc==SQLITE_OK && argc>0 ){ pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc); pCsr->nConstraint = argc; if( !pCsr->aConstraint ){ rc = SQLITE_NOMEM; }else{ memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc); + memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1)); assert( (idxStr==0 && argc==0) || (idxStr && (int)strlen(idxStr)==argc*2) ); for(ii=0; iipInfo->nCoord = pRtree->nDim*2; + p->pInfo->anQueue = pCsr->anQueue; + p->pInfo->mxLevel = pRtree->iDepth + 1; }else{ #ifdef SQLITE_RTREE_INT_ONLY p->u.rValue = sqlite3_value_int64(argv[ii]); @@ -1586,10 +1596,6 @@ static int rtreeFilter( } } } - - if( rc==SQLITE_OK ){ - rc = nodeAcquire(pRtree, 1, 0, &pRoot); - } if( rc==SQLITE_OK ){ RtreeSearchPoint *pNew; pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, pRtree->iDepth+1); @@ -1599,11 +1605,13 @@ static int rtreeFilter( pNew->eWithin = PARTLY_WITHIN; assert( pCsr->bPoint==1 ); pCsr->aNode[0] = pRoot; + pRoot = 0; RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:"); rc = rtreeStepToLeaf(pCsr); } } + nodeRelease(pRtree, pRoot); rtreeRelease(pRtree); return rc; } diff --git a/ext/rtree/sqlite3rtree.h b/ext/rtree/sqlite3rtree.h index 3f4df4ed89..5de0508d00 100644 --- a/ext/rtree/sqlite3rtree.h +++ b/ext/rtree/sqlite3rtree.h @@ -89,8 +89,10 @@ struct sqlite3_rtree_query_info { void *pUser; /* callback can use this, if desired */ void (*xDelUser)(void*); /* function to free pUser */ sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */ + unsigned int *anQueue; /* Number of pending entries in the queue */ int nCoord; /* Number of coordinates */ int iLevel; /* Level of current node or entry */ + int mxLevel; /* The largest iLevel value in the tree */ sqlite3_int64 iRowid; /* Rowid for current entry */ sqlite3_rtree_dbl rParentScore; /* Score of parent node */ int eParentWithin; /* Visibility of parent node */ diff --git a/manifest b/manifest index a115e0886e..707f14a0a3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\sgeneration\sof\ssqlite3_rtree_query_info.iRowid\sand\sadd\stest\scases\nto\sverify\sthat\sit\sis\sfixed. -D 2014-04-21T18:13:37.363 +C Enhance\sthe\ssqlite3_rtree_query_info\sobject\sto\sreport\son\sthe\snumber\sof\s\nelements\sin\sthe\spriority\squeue\sat\seach\slevel. +D 2014-04-25T16:29:03.796 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 77fdd459e7edf78a385a83930e2b072b2f0131b5 +F ext/rtree/rtree.c 6f70db93e0e42c369325c5cddcf2024c5a87ca43 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test e2da4aaa426918d27122d1a1066c6ecf8409a514 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -138,7 +138,7 @@ F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca F ext/rtree/rtreeE.test 388c1c8602c3ce55c15f03b509e9cf545fb7c41f F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea -F ext/rtree/sqlite3rtree.h 488cf8834d2012b913d33683157d3cf5f1327a69 +F ext/rtree/sqlite3rtree.h 83349d519fe5f518b3ea025d18dd1fe51b1684bd F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/session1.test 894e3bc9f497c4fa07a2aa3271e3911f3670c3d8 @@ -1177,7 +1177,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 4394693882c04c19ebe87ef7547c57e679554397 -R 9a6527f0d42b13ef1dcd87b1f989aba6 +P eba95ead49f8f8ce45d400186562ff0066537c5c +R efef19137bd31aa6c6fdc7dea3b8daf2 U drh -Z 8819b772d7d2f245af8d8a9675d9c9d8 +Z ded30c2c8b9ed7281fad6af13254832e diff --git a/manifest.uuid b/manifest.uuid index d92fc37198..8909227722 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -eba95ead49f8f8ce45d400186562ff0066537c5c \ No newline at end of file +f7dad408dd46a1e3612b6142a3afb1d0d4fcda00 \ No newline at end of file From 0894993e888cccd60c4b6698dce17ce000bfb27d Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 6 Aug 2014 11:49:31 +0000 Subject: [PATCH 107/570] Fix an obsolete comment in the func.c source file. No changes to code. FossilOrigin-Name: 7a145c9409e70b92946534eb44c2e205f7309897 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/func.c | 9 +++------ 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 25d96a1c40..80a3330a4d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sin\sthe\sfix\sfor\sthe\sInterlockedCompareExchange()\sbuild\sissue. -D 2014-08-06T03:16:56.688 +C Fix\san\sobsolete\scomment\sin\sthe\sfunc.c\ssource\sfile.\s\sNo\schanges\sto\scode. +D 2014-08-06T11:49:31.740 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 639859a6f81bd15921ccd56ddbd6dfd335278377 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -193,7 +193,7 @@ F src/delete.c 50b74c1dde25d1ebcb4fa5c870762e6470ee46f1 F src/expr.c f749009cf4a8534efb5e0d5cd7c9fb1fb0f2836c F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 8545f3b36da47473e10800ea4fb0810fd4062514 -F src/func.c 3bc223ea36cd29a91c481485343d0ee4257ab8dc +F src/func.c bbb724b74ed96ca42675a7274646a71dd52bcda7 F src/global.c 1e4bd956dc2f608f87d2a929abc4a20db65f30e4 F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 @@ -1200,7 +1200,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 68a6d5e2f43702c78057ae2f2a7345c981d24e17 7be244ce129d6502f3a3e3f3e8a1dd61ef71d878 -R 895a81415e1d620e3196223591337e06 +P 091aa5f1047f0ec984a69ab1f356c1960813b77b +R f8322f66146340bee955eb1bc05e0bbb U drh -Z 282de6283138a0396ca3a1a5b524cbe0 +Z 2907f648c6e2ceca10c49409542f13ae diff --git a/manifest.uuid b/manifest.uuid index 96790e8187..374a6b101e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -091aa5f1047f0ec984a69ab1f356c1960813b77b \ No newline at end of file +7a145c9409e70b92946534eb44c2e205f7309897 \ No newline at end of file diff --git a/src/func.c b/src/func.c index efbb3efbb7..dbc8375541 100644 --- a/src/func.c +++ b/src/func.c @@ -9,12 +9,9 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** This file contains the C functions that implement various SQL -** functions of SQLite. -** -** There is only one exported symbol in this file - the function -** sqliteRegisterBuildinFunctions() found at the bottom of the file. -** All other code has file scope. +** This file contains the C-language implementions for many of the SQL +** functions of SQLite. (Some function, and in particular the date and +** time functions, are implemented separately.) */ #include "sqliteInt.h" #include From 73b3c055904e82ad4e4f1081ee42413a31c8efc9 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 15 Aug 2014 20:15:49 +0000 Subject: [PATCH 108/570] Begin adding the sqlite3session_patchset() API to the sessions extension. This is an interim commit. FossilOrigin-Name: 60a4565a8c44762a002cd02979317df5ca47e899 --- ext/session/sessionB.test | 233 +++++++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 213 ++++++++++++++++++++++++++------ ext/session/sqlite3session.h | 9 ++ ext/session/test_session.c | 8 +- manifest | 19 +-- manifest.uuid | 2 +- 6 files changed, 435 insertions(+), 49 deletions(-) create mode 100644 ext/session/sessionB.test diff --git a/ext/session/sessionB.test b/ext/session/sessionB.test new file mode 100644 index 0000000000..76213d8ab2 --- /dev/null +++ b/ext/session/sessionB.test @@ -0,0 +1,233 @@ +# 2014 August 16 +# +# 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 sessions SQLite extension. +# Specifically, this file contains tests for "patchset" changes. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} + +set testprefix sessionB + +# +# 1.*: Test that the blobs returned by the session_patchset() API are +# as expected. Also the sqlite3_changeset_iter functions. +# +# 2.*: Test that patchset blobs are handled by sqlite3changeset_apply(). +# +# 3.*: Test that sqlite3changeset_invert() works with patchset blobs. +# Correct behaviour is to return SQLITE_CORRUPT. + +proc do_patchset_test {tn session res} { + set r [list] + foreach x $res {lappend r $x} + uplevel do_test $tn [list [subst -nocommands { + set x [list] + sqlite3session_foreach c [$session patchset] { lappend x [set c] } + set x + }]] [list $r] +} + +proc do_sql2patchset_test {tn sql res} { + sqlite3session S db main + S attach * + execsql $sql + uplevel [list do_patchset_test $tn S $res] + S delete +} + +#------------------------------------------------------------------------- +# Run simple tests of the _patchset() API. +# +do_execsql_test 1.0 { + CREATE TABLE t1(a, b, c, d, PRIMARY KEY(d, a)); + INSERT INTO t1 VALUES(1, 2, 3, 4); + INSERT INTO t1 VALUES(5, 6, 7, 8); + INSERT INTO t1 VALUES(9, 10, 11, 12); +} + +do_test 1.1 { + sqlite3session S db main + S attach t1 + execsql { + INSERT INTO t1 VALUES('w', 'x', 'y', 'z'); + DELETE FROM t1 WHERE d=4; + UPDATE t1 SET c = 14 WHERE a=5; + } +} {} + +do_patchset_test 1.2 S { + {UPDATE t1 0 X..X {i 5 {} {} {} {} i 8} {{} {} {} {} i 14 {} {}}} + {INSERT t1 0 X..X {} {t w t x t y t z}} + {DELETE t1 0 X..X {i 1 {} {} {} {} i 4} {}} +} + +do_test 1.3 { + S delete +} {} + +do_sql2patchset_test 1.4 { + DELETE FROM t1; +} { + {DELETE t1 0 X..X {i 5 {} {} {} {} i 8} {}} + {DELETE t1 0 X..X {t w {} {} {} {} t z} {}} + {DELETE t1 0 X..X {i 9 {} {} {} {} i 12} {}} +} + +do_sql2patchset_test 1.5 { + INSERT INTO t1 VALUES(X'61626364', NULL, NULL, 4.2); + INSERT INTO t1 VALUES(4.2, NULL, NULL, X'61626364'); +} { + {INSERT t1 0 X..X {} {f 4.2 n {} n {} b abcd}} + {INSERT t1 0 X..X {} {b abcd n {} n {} f 4.2}} +} + +do_sql2patchset_test 1.6 { + UPDATE t1 SET b=45 WHERE typeof(a)=='blob'; + UPDATE t1 SET c='zzzz' WHERE typeof(a)!='blob'; +} { + {UPDATE t1 0 X..X {f 4.2 {} {} {} {} b abcd} {{} {} {} {} t zzzz {} {}}} + {UPDATE t1 0 X..X {b abcd {} {} {} {} f 4.2} {{} {} i 45 {} {} {} {}}} +} + +do_sql2patchset_test 1.7 { + UPDATE t1 SET b='xyz' WHERE typeof(a)=='blob'; + UPDATE t1 SET c='xyz' WHERE typeof(a)!='blob'; + UPDATE t1 SET b=45 WHERE typeof(a)=='blob'; + UPDATE t1 SET c='zzzz' WHERE typeof(a)!='blob'; +} { +} + +do_sql2patchset_test 1.8 { + DELETE FROM t1; +} { + {DELETE t1 0 X..X {f 4.2 {} {} {} {} b abcd} {}} + {DELETE t1 0 X..X {b abcd {} {} {} {} f 4.2} {}} +} + +#------------------------------------------------------------------------- +# Run simple tests of _apply() with patchset objects. +# +reset_db + +proc noop {args} { error $args } +proc exec_rollback_replay {sql} { + sqlite3session S db main + S attach * + execsql BEGIN + execsql $sql + set patchset [S patchset] + S delete + execsql ROLLBACK + sqlite3changeset_apply db $patchset noop +} + +do_execsql_test 2.0 { + CREATE TABLE t2(a, b, c, d, PRIMARY KEY(b,c)); + CREATE TABLE t3(w, x, y, z, PRIMARY KEY(w)); +} + +do_test 2.1 { + exec_rollback_replay { + INSERT INTO t2 VALUES(1, 2, 3, 4); + INSERT INTO t2 VALUES('w', 'x', 'y', 'z'); + } + execsql { SELECT * FROM t2 } +} {1 2 3 4 w x y z} + +do_test 2.2 { + exec_rollback_replay { + DELETE FROM t2 WHERE a=1; + UPDATE t2 SET d = 'a'; + } + execsql { SELECT * FROM t2 } +} {w x y a} + +#------------------------------------------------------------------------- +# sqlite3changeset_invert() +# +reset_db + +do_execsql_test 3.1 { CREATE TABLE t1(x PRIMARY KEY, y) } +do_test 3.2 { + sqlite3session S db main + S attach * + execsql { INSERT INTO t1 VALUES(1, 2) } + set patchset [S patchset] + S delete + list [catch { sqlite3changeset_invert $patchset } msg] [set msg] +} {1 SQLITE_CORRUPT} + + +#------------------------------------------------------------------------- +# sqlite3changeset_concat() +# +reset_db + +proc do_patchconcat_test {tn args} { + set nSql [expr [llength $args]-1] + set res [lindex $args $nSql] + set patchlist [list] + + execsql BEGIN + foreach sql [lrange $args 0 end-1] { + sqlite3session S db main + S attach * + execsql $sql + lappend patchlist [S patchset] + S delete + } + execsql ROLLBACK + + set patch [lindex $patchlist 0] + foreach p [lrange $patchlist 1 end] { + set patch [sqlite3changeset_concat $patch $p] + } + + set x [list] + sqlite3session_foreach c $patch { lappend x $c } + + uplevel [list do_test $tn [list set {} $x] [list {*}$res]] +} + +do_execsql_test 4.1.1 { + CREATE TABLE t1(x PRIMARY KEY, y, z); +} +do_patchconcat_test 4.1.2 { + INSERT INTO t1 VALUES(1, 2, 3); +} { + INSERT INTO t1 VALUES(4, 5, 6); +} { + {INSERT t1 0 X.. {} {i 1 i 2 i 3}} + {INSERT t1 0 X.. {} {i 4 i 5 i 6}} +} + +if 0 { +do_execsql_test 4.2.1 { + INSERT INTO t1 VALUES(1, 2, 3); + INSERT INTO t1 VALUES(4, 5, 6); +} +do_patchconcat_test 4.2.2 { + UPDATE t1 SET z = 'abc' WHERE x=1 +} { + UPDATE t1 SET z = 'def' WHERE x=4 +} { +} +} + +finish_test + + diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 256d5f089c..62adb8de25 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -35,6 +35,7 @@ struct sqlite3_session { struct sqlite3_changeset_iter { u8 *aChangeset; /* Pointer to buffer containing changeset */ int nChangeset; /* Number of bytes in aChangeset */ + int bPatchset; /* True if this is a patchset */ u8 *pNext; /* Pointer to next change within aChangeset */ int rc; /* Iterator error code */ sqlite3_stmt *pConflict; /* Points to conflicting row, if any */ @@ -122,6 +123,7 @@ struct SessionTable { ** ** 1 byte: Constant 0x54 (capital 'T') ** Varint: Big-endian integer set to the number of columns in the table. +** nCol bytes: 0x01 for PK columns, 0x00 otherwise. ** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. ** ** Followed by one or more changes to the table. @@ -130,6 +132,25 @@ struct SessionTable { ** 1 byte: The "indirect-change" flag. ** old.* record: (delete and update only) ** new.* record: (insert and update only) +** +** PATCHSET FORMAT: +** +** A patchset is also a collection of changes. It is similar to a changeset, +** but omits those fields that are not useful if no conflict resolution +** is required when applying the changeset. +** +** Each group of changes begins with a table header: +** +** 1 byte: Constant 0x50 (capital 'P') +** Varint: Big-endian integer set to the number of columns in the table. +** nCol bytes: 0x01 for PK columns, 0x00 otherwise. +** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. +** +** Followed by one or more changes to the table. +** +** 1 byte: Either SQLITE_INSERT, UPDATE or DELETE. +** 1 byte: The "indirect-change" flag. +** single record: (PK fields for DELETE, or full record for INSERT/UPDATE). */ /* @@ -1449,6 +1470,7 @@ static void sessionAppendCol( */ static int sessionAppendUpdate( SessionBuffer *pBuf, /* Buffer to append to */ + int bPatchset, /* True for "patchset", 0 for "changeset" */ sqlite3_stmt *pStmt, /* Statement handle pointing at new row */ SessionChange *p, /* Object containing old values */ u8 *abPK /* Boolean array - true for PK columns */ @@ -1506,15 +1528,23 @@ static int sessionAppendUpdate( } } - if( bChanged || abPK[i] ){ - sessionAppendBlob(pBuf, pCsr, nAdvance, &rc); - }else{ - sessionAppendByte(pBuf, 0, &rc); + /* If at least one field has been modified, this is not a no-op. */ + if( bChanged ) bNoop = 0; + + /* Add a field to the old.* record. This is omitted if this modules is + ** currently generating a patchset. */ + if( bPatchset==0 ){ + if( bChanged || abPK[i] ){ + sessionAppendBlob(pBuf, pCsr, nAdvance, &rc); + }else{ + sessionAppendByte(pBuf, 0, &rc); + } } - if( bChanged ){ + /* Add a field to the new.* record. Or the only record if currently + ** generating a patchset. */ + if( bChanged || (bPatchset && abPK[i]) ){ sessionAppendCol(&buf2, pStmt, i, &rc); - bNoop = 0; }else{ sessionAppendByte(&buf2, 0, &rc); } @@ -1532,6 +1562,56 @@ static int sessionAppendUpdate( return rc; } +static int sessionAppendDelete( + SessionBuffer *pBuf, /* Buffer to append to */ + int bPatchset, /* True for "patchset", 0 for "changeset" */ + sqlite3_stmt *pStmt, /* Statement handle pointing at new row */ + SessionChange *p, /* Object containing old values */ + u8 *abPK /* Boolean array - true for PK columns */ +){ + int rc = SQLITE_OK; + + sessionAppendByte(pBuf, SQLITE_DELETE, &rc); + sessionAppendByte(pBuf, p->bIndirect, &rc); + + if( bPatchset==0 ){ + sessionAppendBlob(pBuf, p->aRecord, p->nRecord, &rc); + }else{ + int nCol = sqlite3_column_count(pStmt); + int i; + u8 *a = p->aRecord; + for(i=0; iaRecord)==p->nRecord ); + } + + return rc; +} + /* ** Formulate and prepare a SELECT statement to retrieve a row from table ** zTab in database zDb based on its primary key. i.e. @@ -1654,25 +1734,20 @@ static int sessionSelectBind( */ static void sessionAppendTableHdr( SessionBuffer *pBuf, + int bPatchset, SessionTable *pTab, int *pRc ){ /* Write a table header */ - sessionAppendByte(pBuf, 'T', pRc); + sessionAppendByte(pBuf, (bPatchset ? 'P' : 'T'), pRc); sessionAppendVarint(pBuf, pTab->nCol, pRc); sessionAppendBlob(pBuf, pTab->abPK, pTab->nCol, pRc); sessionAppendBlob(pBuf, (u8 *)pTab->zName, (int)strlen(pTab->zName)+1, pRc); } -/* -** Obtain a changeset object containing all changes recorded by the -** session object passed as the first argument. -** -** It is the responsibility of the caller to eventually free the buffer -** using sqlite3_free(). -*/ -int sqlite3session_changeset( +int sessionGenerateChangeset( sqlite3_session *pSession, /* Session object */ + int bPatchset, /* True for patchset, false for changeset */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ){ @@ -1711,7 +1786,7 @@ int sqlite3session_changeset( } /* Write a table header */ - sessionAppendTableHdr(&buf, pTab, &rc); + sessionAppendTableHdr(&buf, bPatchset, pTab, &rc); /* Build and compile a statement to execute: */ if( rc==SQLITE_OK ){ @@ -1735,13 +1810,10 @@ int sqlite3session_changeset( sessionAppendCol(&buf, pSel, iCol, &rc); } }else{ - rc = sessionAppendUpdate(&buf, pSel, p, abPK); + rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, abPK); } }else if( p->op!=SQLITE_INSERT ){ - /* A DELETE change */ - sessionAppendByte(&buf, SQLITE_DELETE, &rc); - sessionAppendByte(&buf, p->bIndirect, &rc); - sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); + rc = sessionAppendDelete(&buf, bPatchset, pSel, p, abPK); } if( rc==SQLITE_OK ){ rc = sqlite3_reset(pSel); @@ -1769,6 +1841,36 @@ int sqlite3session_changeset( return rc; } +/* +** Obtain a changeset object containing all changes recorded by the +** session object passed as the first argument. +** +** It is the responsibility of the caller to eventually free the buffer +** using sqlite3_free(). +*/ +int sqlite3session_changeset( + sqlite3_session *pSession, /* Session object */ + int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ + void **ppChangeset /* OUT: Buffer containing changeset */ +){ + return sessionGenerateChangeset(pSession, 0, pnChangeset, ppChangeset); +} + +/* +** Obtain a patchset object containing all changes recorded by the +** session object passed as the first argument. +** +** It is the responsibility of the caller to eventually free the buffer +** using sqlite3_free(). +*/ +int sqlite3session_patchset( + sqlite3_session *pSession, /* Session object */ + int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ + void **ppPatchset /* OUT: Buffer containing changeset */ +){ + return sessionGenerateChangeset(pSession, 1, pnPatchset, ppPatchset); +} + /* ** Enable or disable the session object passed as the first argument. */ @@ -1866,13 +1968,16 @@ int sqlite3changeset_start( static int sessionReadRecord( u8 **paChange, /* IN/OUT: Pointer to binary record */ int nCol, /* Number of values in record */ + u8 *abPK, /* Array of primary key flags, or NULL */ sqlite3_value **apOut /* Write values to this array */ ){ int i; /* Used to iterate through columns */ u8 *aRec = *paChange; /* Cursor for the serialized record */ for(i=0; ipNext; - if( aChange[0]=='T' ){ + if( aChange[0]=='T' || aChange[0]=='P' ){ int nByte; /* Bytes to allocate for apValue */ + p->bPatchset = (aChange[0]=='P'); aChange++; aChange += sessionVarintGet(aChange, &p->nCol); p->abPK = (u8 *)aChange; @@ -1981,18 +2087,36 @@ static int sessionChangesetNext( if( paRec ){ *paRec = aChange; } /* If this is an UPDATE or DELETE, read the old.* record. */ - if( p->op!=SQLITE_INSERT ){ - p->rc = sessionReadRecord(&aChange, p->nCol, paRec?0:p->apValue); + if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){ + u8 *abPK = p->bPatchset ? p->abPK : 0; + p->rc = sessionReadRecord(&aChange, p->nCol, abPK, paRec?0:p->apValue); if( p->rc!=SQLITE_OK ) return p->rc; } /* If this is an INSERT or UPDATE, read the new.* record. */ if( p->op!=SQLITE_DELETE ){ - p->rc = sessionReadRecord(&aChange, p->nCol, paRec?0:&p->apValue[p->nCol]); + sqlite3_value **apOut = (paRec ? 0 : &p->apValue[p->nCol]); + p->rc = sessionReadRecord(&aChange, p->nCol, 0, apOut); if( p->rc!=SQLITE_OK ) return p->rc; } - if( pnRec ){ *pnRec = (int)(aChange - *paRec); } + if( pnRec ){ + *pnRec = (int)(aChange - *paRec); + }else if( p->bPatchset && p->op==SQLITE_UPDATE ){ + /* If this is an UPDATE that is part of a patchset, then all PK and + ** modified fields are present in the new.* record. The old.* record + ** is currently completely empty. This block shifts the PK fields from + ** new.* to old.*, to accommodate the code that reads these arrays. */ + int i; + for(i=0; inCol; i++){ + assert( p->apValue[i]==0 ); + assert( p->abPK[i]==0 || p->apValue[i+p->nCol] ); + if( p->abPK[i] ){ + p->apValue[i] = p->apValue[i+p->nCol]; + p->apValue[i+p->nCol] = 0; + } + } + } p->pNext = aChange; return SQLITE_ROW; } @@ -2225,7 +2349,7 @@ int sqlite3changeset_invert( int nByte; u8 *aEnd = &aIn[i+2]; - sessionReadRecord(&aEnd, nCol, 0); + sessionReadRecord(&aEnd, nCol, 0, 0); aOut[i] = (eType==SQLITE_DELETE ? SQLITE_INSERT : SQLITE_DELETE); aOut[i+1] = aIn[i+1]; nByte = (int)(aEnd - &aIn[i+2]); @@ -2249,9 +2373,9 @@ int sqlite3changeset_invert( } /* Read the old.* and new.* records for the update change. */ - rc = sessionReadRecord(&aEnd, nCol, &apVal[0]); + rc = sessionReadRecord(&aEnd, nCol, 0, &apVal[0]); if( rc==SQLITE_OK ){ - rc = sessionReadRecord(&aEnd, nCol, &apVal[nCol]); + rc = sessionReadRecord(&aEnd, nCol, 0, &apVal[nCol]); } /* Write the header for the new UPDATE change. Same as the original. */ @@ -2781,10 +2905,21 @@ static int sessionApplyOneOp( if( op==SQLITE_DELETE ){ - /* Bind values to the DELETE statement. */ - rc = sessionBindRow(pIter, sqlite3changeset_old, nCol, 0, p->pDelete); + /* Bind values to the DELETE statement. If conflict handling is required, + ** bind values for all columns and set bound variable (nCol+1) to true. + ** Or, if conflict handling is not required, bind just the PK column + ** values and, if it exists, set (nCol+1) to false. Conflict handling + ** is not required if: + ** + ** * this is a patchset, or + ** * (pbRetry==0), or + ** * all columns of the table are PK columns (in this case there is + ** no (nCol+1) variable to bind to). + */ + u8 *abPK = (pIter->bPatchset ? p->abPK : 0); + rc = sessionBindRow(pIter, sqlite3changeset_old, nCol, abPK, p->pDelete); if( rc==SQLITE_OK && sqlite3_bind_parameter_count(p->pDelete)>nCol ){ - rc = sqlite3_bind_int(p->pDelete, nCol+1, pbRetry==0); + rc = sqlite3_bind_int(p->pDelete, nCol+1, (pbRetry==0 || abPK)); } if( rc!=SQLITE_OK ) return rc; @@ -2816,7 +2951,9 @@ static int sessionApplyOneOp( rc = sessionBindValue(p->pUpdate, i*3+3, pNew); } } - if( rc==SQLITE_OK ) sqlite3_bind_int(p->pUpdate, nCol*3+1, pbRetry==0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int(p->pUpdate, nCol*3+1, pbRetry==0 || pIter->bPatchset); + } if( rc!=SQLITE_OK ) return rc; /* Attempt the UPDATE. In the case of a NOTFOUND or DATA conflict, @@ -3099,7 +3236,7 @@ static int sessionChangeMerge( u8 *a1 = aRec; assert( op2==SQLITE_UPDATE ); pNew->op = SQLITE_INSERT; - sessionReadRecord(&a1, pTab->nCol, 0); + sessionReadRecord(&a1, pTab->nCol, 0, 0); sessionMergeRecord(&aCsr, pTab->nCol, pExist->aRecord, a1); }else if( op1==SQLITE_DELETE ){ /* DELETE + INSERT */ assert( op2==SQLITE_INSERT ); @@ -3112,8 +3249,8 @@ static int sessionChangeMerge( u8 *a1 = pExist->aRecord; u8 *a2 = aRec; assert( op1==SQLITE_UPDATE ); - sessionReadRecord(&a1, pTab->nCol, 0); - sessionReadRecord(&a2, pTab->nCol, 0); + sessionReadRecord(&a1, pTab->nCol, 0, 0); + sessionReadRecord(&a2, pTab->nCol, 0, 0); pNew->op = SQLITE_UPDATE; if( 0==sessionMergeUpdate(&aCsr, pTab, aRec, pExist->aRecord, a1, a2) ){ sqlite3_free(pNew); @@ -3274,7 +3411,7 @@ int sqlite3changeset_concat( int i; if( pTab->nEntry==0 ) continue; - sessionAppendTableHdr(&buf, pTab, &rc); + sessionAppendTableHdr(&buf, 0, pTab, &rc); for(i=0; inChange; i++){ SessionChange *p; for(p=pTab->apChange[i]; p; p=p->pNext){ diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 974a770c7b..de4ee77b94 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -273,6 +273,15 @@ int sqlite3session_changeset( void **ppChangeset /* OUT: Buffer containing changeset */ ); +/* +** CAPI3REF: Generate A Patchset From A Session Object +*/ +int sqlite3session_patchset( + sqlite3_session *pSession, /* Session object */ + int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ + void **ppPatchset /* OUT: Buffer containing changeset */ +); + /* ** CAPI3REF: Test if a changeset has recorded any changes. ** diff --git a/ext/session/test_session.c b/ext/session/test_session.c index f1c2fbe9a3..fa99f56786 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -73,6 +73,7 @@ static int test_session_cmd( { "indirect", 1, "BOOL", }, /* 4 */ { "isempty", 0, "", }, /* 5 */ { "table_filter", 1, "SCRIPT", }, /* 6 */ + { "patchset", 0, "", }, /* 7 */ { 0 } }; int iSub; @@ -102,10 +103,15 @@ static int test_session_cmd( break; } + case 7: /* patchset */ case 1: { /* changeset */ int nChange; void *pChange; - rc = sqlite3session_changeset(pSession, &nChange, &pChange); + if( iSub==7 ){ + rc = sqlite3session_patchset(pSession, &nChange, &pChange); + }else{ + rc = sqlite3session_changeset(pSession, &nChange, &pChange); + } if( rc==SQLITE_OK ){ Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pChange, nChange)); sqlite3_free(pChange); diff --git a/manifest b/manifest index b52178bb67..833a47196f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\ssessions\sbranch\sfor\sversion\s3.8.6. -D 2014-08-15T15:10:46.167 +C Begin\sadding\sthe\ssqlite3session_patchset()\sAPI\sto\sthe\ssessions\sextension.\sThis\sis\san\sinterim\scommit. +D 2014-08-15T20:15:49.367 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 639859a6f81bd15921ccd56ddbd6dfd335278377 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -152,11 +152,12 @@ F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 F ext/session/session9.test 776e46785c29c11cda01f5205d0f1e8f8f9a46bf F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 +F ext/session/sessionB.test dbabf40e7580f2dc245ea6b37b94fd1ec0b25fc3 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 496291b287ba3c0b14ca2e074425e29cc92a64a6 -F ext/session/sqlite3session.c 34e19186d05d534e5a37a4f5a8a3c3e24e3fa88a -F ext/session/sqlite3session.h 6c35057241567ed6319f750ee504a81c459225e1 -F ext/session/test_session.c 7878ac0e2fe9675e8ec24d54f6a538ccc105977f +F ext/session/sqlite3session.c e0d8101afc5df85495c401eadf2cb288c3d53adc +F ext/session/sqlite3session.h c99445ea9918343d3e62acafdf82bc5502cfba29 +F ext/session/test_session.c 920ccb6d6e1df263cd9099563328094c230b2925 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 @@ -1201,7 +1202,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P d49455d9a972fc2224d9beb97165a998ca56e838 9491ba7d738528f168657adb43a198238abde19e -R f94212c9f19d7229cfd6e84a8137e8b7 -U drh -Z 80e27e19ffdd26307df7b50bec8606de +P 2acbeac1fd9b9feb26e1c24d4ae50ce79f17a3f8 +R 3c0b82c93c7620c8b999c9243f48a749 +U dan +Z a8da13936a56069d46e167f9c70b2c2a diff --git a/manifest.uuid b/manifest.uuid index 79ed17684c..ccaf220a3e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2acbeac1fd9b9feb26e1c24d4ae50ce79f17a3f8 \ No newline at end of file +60a4565a8c44762a002cd02979317df5ca47e899 \ No newline at end of file From 64277f4a7054909abe1cd8fdedb1e2ad21b4b853 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 16 Aug 2014 16:47:55 +0000 Subject: [PATCH 109/570] Fixes for the sqlite3changeset_concat() API regarding patchsets. FossilOrigin-Name: dccb34859508eac8146ae5b19c447673d04be3b0 --- ext/session/sessionB.test | 101 +++++++++++++++++++++++++++- ext/session/sqlite3session.c | 124 ++++++++++++++++++++++++----------- manifest | 14 ++-- manifest.uuid | 2 +- 4 files changed, 193 insertions(+), 48 deletions(-) diff --git a/ext/session/sessionB.test b/ext/session/sessionB.test index 76213d8ab2..8791272f8e 100644 --- a/ext/session/sessionB.test +++ b/ext/session/sessionB.test @@ -178,17 +178,24 @@ do_test 3.2 { reset_db proc do_patchconcat_test {tn args} { + set bRevert 0 + if {[lindex $args 0] == "-revert"} { + set bRevert 1 + set args [lrange $args 1 end] + } set nSql [expr [llength $args]-1] set res [lindex $args $nSql] set patchlist [list] execsql BEGIN + if {$bRevert} { execsql { SAVEPOINT x } } foreach sql [lrange $args 0 end-1] { sqlite3session S db main S attach * execsql $sql lappend patchlist [S patchset] S delete + if {$bRevert} { execsql { ROLLBACK TO x } } } execsql ROLLBACK @@ -215,17 +222,109 @@ do_patchconcat_test 4.1.2 { {INSERT t1 0 X.. {} {i 4 i 5 i 6}} } -if 0 { do_execsql_test 4.2.1 { INSERT INTO t1 VALUES(1, 2, 3); INSERT INTO t1 VALUES(4, 5, 6); } + do_patchconcat_test 4.2.2 { UPDATE t1 SET z = 'abc' WHERE x=1 } { UPDATE t1 SET z = 'def' WHERE x=4 } { + {UPDATE t1 0 X.. {i 1 {} {} {} {}} {{} {} {} {} t abc}} + {UPDATE t1 0 X.. {i 4 {} {} {} {}} {{} {} {} {} t def}} } + +do_patchconcat_test 4.2.3 { + DELETE FROM t1 WHERE x=1; +} { + DELETE FROM t1 WHERE x=4; +} { + {DELETE t1 0 X.. {i 1 {} {} {} {}} {}} + {DELETE t1 0 X.. {i 4 {} {} {} {}} {}} +} + + +do_execsql_test 4.3.1 { + CREATE TABLE t2(a, b, c, d, PRIMARY KEY(c, b)); + INSERT INTO t2 VALUES('.', 1, 1, '.'); + INSERT INTO t2 VALUES('.', 1, 2, '.'); + INSERT INTO t2 VALUES('.', 2, 1, '.'); + INSERT INTO t2 VALUES('.', 2, 2, '.'); +} + +# INSERT + INSERT +do_patchconcat_test 4.3.2 -revert { + INSERT INTO t2 VALUES('a', 'a', 'a', 'a'); +} { + INSERT INTO t2 VALUES('b', 'a', 'a', 'b'); +} { + {INSERT t2 0 .XX. {} {t a t a t a t a}} +} + +# INSERT + DELETE +do_patchconcat_test 4.3.3 { + INSERT INTO t2 VALUES('a', 'a', 'a', 'a'); +} { + DELETE FROM t2 WHERE c = 'a'; +} { +} + +# INSERT + UPDATE +do_patchconcat_test 4.3.4 { + INSERT INTO t2 VALUES('a', 'a', 'a', 'a'); +} { + UPDATE t2 SET d = 'b' WHERE c='a'; +} { + {INSERT t2 0 .XX. {} {t a t a t a t b}} +} + +# UPDATE + UPDATE +do_patchconcat_test 4.3.5 { + UPDATE t2 SET a = 'a' WHERE c=1 AND b=2; +} { + UPDATE t2 SET d = 'd' WHERE c=1 AND b=2; +} { + {UPDATE t2 0 .XX. {{} {} i 2 i 1 {} {}} {t a {} {} {} {} t d}} +} + +# UPDATE + DELETE +do_patchconcat_test 4.3.6 { + UPDATE t2 SET a = 'a' WHERE c=1 AND b=2; +} { + DELETE FROM t2 WHERE c=1 AND b=2; +} { + {DELETE t2 0 .XX. {{} {} i 2 i 1 {} {}} {}} +} + +# DELETE + INSERT +do_patchconcat_test 4.3.7 { + DELETE FROM t2 WHERE b=1; +} { + INSERT INTO t2 VALUES('x', 1, 2, '.'); +} { + {DELETE t2 0 .XX. {{} {} i 1 i 1 {} {}} {}} + {UPDATE t2 0 .XX. {{} {} i 1 i 2 {} {}} {t x {} {} {} {} t .}} +} + +# DELETE + UPDATE +do_patchconcat_test 4.3.8 -revert { + DELETE FROM t2 WHERE b=1 AND c=2; +} { + UPDATE t2 SET a=5 WHERE b=1 AND c=2; +} { + {DELETE t2 0 .XX. {{} {} i 1 i 2 {} {}} {}} +} + +# DELETE + UPDATE +do_patchconcat_test 4.3.9 -revert { + DELETE FROM t2 WHERE b=1 AND c=2; +} { + DELETE FROM t2 WHERE b=1; +} { + {DELETE t2 0 .XX. {{} {} i 1 i 1 {} {}} {}} + {DELETE t2 0 .XX. {{} {} i 1 i 2 {} {}} {}} } finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 62adb8de25..b86c635ed1 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -443,9 +443,13 @@ static int sessionSerialLen(u8 *a){ ** hash key. Assume the has table has nBucket buckets. The hash keys ** calculated by this function are compatible with those calculated by ** sessionPreupdateHash(). +** +** The bPkOnly argument is non-zero if the record at aRecord[] is from +** a patchset DELETE. In this case the non-PK fields are omitted entirely. */ static unsigned int sessionChangeHash( SessionTable *pTab, /* Table handle */ + int bPkOnly, /* Record consists of PK fields only */ u8 *aRecord, /* Change record */ int nBucket /* Assume this many buckets in hash table */ ){ @@ -456,6 +460,7 @@ static unsigned int sessionChangeHash( for(i=0; inCol; i++){ int eType = *a; int isPK = pTab->abPK[i]; + if( bPkOnly && isPK==0 ) continue; /* It is not possible for eType to be SQLITE_NULL here. The session ** module does not record changes for rows with NULL values stored in @@ -493,7 +498,9 @@ static unsigned int sessionChangeHash( */ static int sessionChangeEqual( SessionTable *pTab, /* Table used for PK definition */ + int bLeftPkOnly, u8 *aLeft, /* Change record */ + int bRightPkOnly, u8 *aRight /* Change record */ ){ u8 *a1 = aLeft; /* Cursor to iterate through aLeft */ @@ -507,8 +514,8 @@ static int sessionChangeEqual( if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){ return 0; } - a1 += n1; - a2 += n2; + if( pTab->abPK[iCol] || bLeftPkOnly==0 ) a1 += n1; + if( pTab->abPK[iCol] || bRightPkOnly==0 ) a2 += n2; } return 1; @@ -606,6 +613,7 @@ static u8 *sessionMergeValue( static int sessionMergeUpdate( u8 **paOut, /* IN/OUT: Pointer to output buffer */ SessionTable *pTab, /* Table change pertains to */ + int bPatchset, u8 *aOldRecord1, /* old.* record for first change */ u8 *aOldRecord2, /* old.* record for second change */ u8 *aNewRecord1, /* new.* record for first change */ @@ -618,29 +626,32 @@ static int sessionMergeUpdate( u8 *aOut = *paOut; int i; - int bRequired = 0; - assert( aOldRecord1 && aNewRecord1 ); + if( bPatchset==0 ){ + int bRequired = 0; - /* Write the old.* vector first. */ - for(i=0; inCol; i++){ - int nOld; - u8 *aOld; - int nNew; - u8 *aNew; + assert( aOldRecord1 && aNewRecord1 ); - aOld = sessionMergeValue(&aOld1, &aOld2, &nOld); - aNew = sessionMergeValue(&aNew1, &aNew2, &nNew); - if( pTab->abPK[i] || nOld!=nNew || memcmp(aOld, aNew, nNew) ){ - if( pTab->abPK[i]==0 ) bRequired = 1; - memcpy(aOut, aOld, nOld); - aOut += nOld; - }else{ - *(aOut++) = '\0'; + /* Write the old.* vector first. */ + for(i=0; inCol; i++){ + int nOld; + u8 *aOld; + int nNew; + u8 *aNew; + + aOld = sessionMergeValue(&aOld1, &aOld2, &nOld); + aNew = sessionMergeValue(&aNew1, &aNew2, &nNew); + if( pTab->abPK[i] || nOld!=nNew || memcmp(aOld, aNew, nNew) ){ + if( pTab->abPK[i]==0 ) bRequired = 1; + memcpy(aOut, aOld, nOld); + aOut += nOld; + }else{ + *(aOut++) = '\0'; + } } - } - if( !bRequired ) return 0; + if( !bRequired ) return 0; + } /* Write the new.* vector */ aOld1 = aOldRecord1; @@ -655,7 +666,9 @@ static int sessionMergeUpdate( aOld = sessionMergeValue(&aOld1, &aOld2, &nOld); aNew = sessionMergeValue(&aNew1, &aNew2, &nNew); - if( pTab->abPK[i] || (nOld==nNew && 0==memcmp(aOld, aNew, nNew)) ){ + if( bPatchset==0 + && (pTab->abPK[i] || (nOld==nNew && 0==memcmp(aOld, aNew, nNew))) + ){ *(aOut++) = '\0'; }else{ memcpy(aOut, aNew, nNew); @@ -754,7 +767,7 @@ static int sessionPreupdateEqual( ** Growing the hash table in this case is a performance optimization only, ** it is not required for correct operation. */ -static int sessionGrowHash(SessionTable *pTab){ +static int sessionGrowHash(int bPatchset, SessionTable *pTab){ if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){ int i; SessionChange **apNew; @@ -773,7 +786,8 @@ static int sessionGrowHash(SessionTable *pTab){ SessionChange *p; SessionChange *pNext; for(p=pTab->apChange[i]; p; p=pNext){ - int iHash = sessionChangeHash(pTab, p->aRecord, nNew); + int bPkOnly = (p->op==SQLITE_DELETE && bPatchset); + int iHash = sessionChangeHash(pTab, bPkOnly, p->aRecord, nNew); pNext = p->pNext; p->pNext = apNew[iHash]; apNew[iHash] = p; @@ -960,7 +974,7 @@ static void sessionPreupdateOneChange( if( sessionInitTable(pSession, pTab) ) return; /* Grow the hash table if required */ - if( sessionGrowHash(pTab) ){ + if( sessionGrowHash(0, pTab) ){ pSession->rc = SQLITE_NOMEM; return; } @@ -3174,6 +3188,7 @@ int sqlite3changeset_apply( */ static int sessionChangeMerge( SessionTable *pTab, /* Table structure */ + int bPatchset, /* True for patchsets */ SessionChange *pExist, /* Existing change */ int op2, /* Second change operation */ int bIndirect, /* True if second change is indirect */ @@ -3219,9 +3234,13 @@ static int sessionChangeMerge( sqlite3_free(pExist); assert( pNew==0 ); }else{ + u8 *aExist = pExist->aRecord; int nByte; u8 *aCsr; + /* Allocate a new SessionChange object. Ensure that the aRecord[] + ** buffer of the new object is large enough to hold any record that + ** may be generated by combining the input records. */ nByte = sizeof(SessionChange) + pExist->nRecord + nRec; pNew = (SessionChange *)sqlite3_malloc(nByte); if( !pNew ){ @@ -3236,30 +3255,37 @@ static int sessionChangeMerge( u8 *a1 = aRec; assert( op2==SQLITE_UPDATE ); pNew->op = SQLITE_INSERT; - sessionReadRecord(&a1, pTab->nCol, 0, 0); - sessionMergeRecord(&aCsr, pTab->nCol, pExist->aRecord, a1); + if( bPatchset==0 ) sessionReadRecord(&a1, pTab->nCol, 0, 0); + sessionMergeRecord(&aCsr, pTab->nCol, aExist, a1); }else if( op1==SQLITE_DELETE ){ /* DELETE + INSERT */ assert( op2==SQLITE_INSERT ); pNew->op = SQLITE_UPDATE; - if( 0==sessionMergeUpdate(&aCsr, pTab, pExist->aRecord, 0, aRec, 0) ){ + if( 0==sessionMergeUpdate(&aCsr, pTab, bPatchset, aExist, 0, aRec, 0) ){ sqlite3_free(pNew); pNew = 0; } }else if( op2==SQLITE_UPDATE ){ /* UPDATE + UPDATE */ - u8 *a1 = pExist->aRecord; + u8 *a1 = aExist; u8 *a2 = aRec; assert( op1==SQLITE_UPDATE ); - sessionReadRecord(&a1, pTab->nCol, 0, 0); - sessionReadRecord(&a2, pTab->nCol, 0, 0); + if( bPatchset==0 ){ + sessionReadRecord(&a1, pTab->nCol, 0, 0); + sessionReadRecord(&a2, pTab->nCol, 0, 0); + } pNew->op = SQLITE_UPDATE; - if( 0==sessionMergeUpdate(&aCsr, pTab, aRec, pExist->aRecord, a1, a2) ){ + if( 0==sessionMergeUpdate(&aCsr, pTab, bPatchset, aRec, aExist,a1,a2) ){ sqlite3_free(pNew); pNew = 0; } }else{ /* UPDATE + DELETE */ assert( op1==SQLITE_UPDATE && op2==SQLITE_DELETE ); pNew->op = SQLITE_DELETE; - sessionMergeRecord(&aCsr, pTab->nCol, aRec, pExist->aRecord); + if( bPatchset ){ + memcpy(aCsr, aRec, nRec); + aCsr += nRec; + }else{ + sessionMergeRecord(&aCsr, pTab->nCol, aRec, aExist); + } } if( pNew ){ @@ -3278,6 +3304,7 @@ static int sessionChangeMerge( ** hash tables. */ static int sessionConcatChangeset( + int bPatchset, /* True to expect patchsets */ int nChangeset, /* Number of bytes in pChangeset */ void *pChangeset, /* Changeset buffer */ SessionTable **ppTabList /* IN/OUT: List of table objects */ @@ -3301,6 +3328,13 @@ static int sessionConcatChangeset( SessionChange *pExist = 0; SessionChange **pp; + assert( bPatchset==0 || bPatchset==1 ); + assert( pIter->bPatchset==0 || pIter->bPatchset==1 ); + if( pIter->bPatchset!=bPatchset ){ + rc = SQLITE_ERROR; + break; + } + assert( pIter->apValue==0 ); sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect); @@ -3335,17 +3369,25 @@ static int sessionConcatChangeset( pTab->zName = (char *)zNew; } - if( sessionGrowHash(pTab) ){ + if( sessionGrowHash(bPatchset, pTab) ){ rc = SQLITE_NOMEM; break; } - iHash = sessionChangeHash(pTab, aRec, pTab->nChange); + iHash = sessionChangeHash( + pTab, (bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange + ); /* Search for existing entry. If found, remove it from the hash table. ** Code below may link it back in. */ for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){ - if( sessionChangeEqual(pTab, (*pp)->aRecord, aRec) ){ + int bPkOnly1 = 0; + int bPkOnly2 = 0; + if( bPatchset ){ + bPkOnly1 = (*pp)->op==SQLITE_DELETE; + bPkOnly2 = op==SQLITE_DELETE; + } + if( sessionChangeEqual(pTab, bPkOnly1, (*pp)->aRecord, bPkOnly2, aRec) ){ pExist = *pp; *pp = (*pp)->pNext; pTab->nEntry--; @@ -3353,7 +3395,9 @@ static int sessionConcatChangeset( } } - rc = sessionChangeMerge(pTab, pExist, op, bIndirect, aRec, nRec, &pChange); + rc = sessionChangeMerge(pTab, + bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange + ); if( rc ) break; if( pChange ){ pChange->pNext = pTab->apChange[iHash]; @@ -3392,13 +3436,15 @@ int sqlite3changeset_concat( ){ SessionTable *pList = 0; /* List of SessionTable objects */ int rc; /* Return code */ + int bPatch; /* True for a patchset */ *pnOut = 0; *ppOut = 0; + bPatch = (nLeft>0 && *(char*)pLeft=='P') || (nRight>0 && *(char*)pRight=='P'); - rc = sessionConcatChangeset(nLeft, pLeft, &pList); + rc = sessionConcatChangeset(bPatch, nLeft, pLeft, &pList); if( rc==SQLITE_OK ){ - rc = sessionConcatChangeset(nRight, pRight, &pList); + rc = sessionConcatChangeset(bPatch, nRight, pRight, &pList); } /* Create the serialized output changeset based on the contents of the @@ -3411,7 +3457,7 @@ int sqlite3changeset_concat( int i; if( pTab->nEntry==0 ) continue; - sessionAppendTableHdr(&buf, 0, pTab, &rc); + sessionAppendTableHdr(&buf, bPatch, pTab, &rc); for(i=0; inChange; i++){ SessionChange *p; for(p=pTab->apChange[i]; p; p=p->pNext){ diff --git a/manifest b/manifest index 833a47196f..2e5dc07be7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Begin\sadding\sthe\ssqlite3session_patchset()\sAPI\sto\sthe\ssessions\sextension.\sThis\sis\san\sinterim\scommit. -D 2014-08-15T20:15:49.367 +C Fixes\sfor\sthe\ssqlite3changeset_concat()\sAPI\sregarding\spatchsets. +D 2014-08-16T16:47:55.133 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 639859a6f81bd15921ccd56ddbd6dfd335278377 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -152,10 +152,10 @@ F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 F ext/session/session9.test 776e46785c29c11cda01f5205d0f1e8f8f9a46bf F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 -F ext/session/sessionB.test dbabf40e7580f2dc245ea6b37b94fd1ec0b25fc3 +F ext/session/sessionB.test 51c70394bc04ac72d72f54bd0879614b9c34240c F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 496291b287ba3c0b14ca2e074425e29cc92a64a6 -F ext/session/sqlite3session.c e0d8101afc5df85495c401eadf2cb288c3d53adc +F ext/session/sqlite3session.c eed0f0510859e564f9f8c886d22a299579b5c6c1 F ext/session/sqlite3session.h c99445ea9918343d3e62acafdf82bc5502cfba29 F ext/session/test_session.c 920ccb6d6e1df263cd9099563328094c230b2925 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -1202,7 +1202,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2acbeac1fd9b9feb26e1c24d4ae50ce79f17a3f8 -R 3c0b82c93c7620c8b999c9243f48a749 +P 60a4565a8c44762a002cd02979317df5ca47e899 +R 1bd074b437e8898f047cce1541823103 U dan -Z a8da13936a56069d46e167f9c70b2c2a +Z 66bd65019d7460afe376babf330097ba diff --git a/manifest.uuid b/manifest.uuid index ccaf220a3e..9786ee73ae 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -60a4565a8c44762a002cd02979317df5ca47e899 \ No newline at end of file +dccb34859508eac8146ae5b19c447673d04be3b0 \ No newline at end of file From a71d2371d0ff9e73b3ba99bee09a4eef204e22fb Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 16 Aug 2014 19:01:00 +0000 Subject: [PATCH 110/570] Fix some missing and out-of-date comments in the sessions module. FossilOrigin-Name: 05c1d9149b27c68e2654ed28491722927d2176f5 --- ext/session/sqlite3session.c | 37 ++++++++++++++++++++++++++---------- ext/session/sqlite3session.h | 20 +++++++++++++++++++ manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index b86c635ed1..69d67817bf 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -498,9 +498,9 @@ static unsigned int sessionChangeHash( */ static int sessionChangeEqual( SessionTable *pTab, /* Table used for PK definition */ - int bLeftPkOnly, + int bLeftPkOnly, /* True if aLeft[] contains PK fields only */ u8 *aLeft, /* Change record */ - int bRightPkOnly, + int bRightPkOnly, /* True if aRight[] contains PK fields only */ u8 *aRight /* Change record */ ){ u8 *a1 = aLeft; /* Cursor to iterate through aLeft */ @@ -613,7 +613,7 @@ static u8 *sessionMergeValue( static int sessionMergeUpdate( u8 **paOut, /* IN/OUT: Pointer to output buffer */ SessionTable *pTab, /* Table change pertains to */ - int bPatchset, + int bPatchset, /* True if records are patchset records */ u8 *aOldRecord1, /* old.* record for first change */ u8 *aOldRecord2, /* old.* record for second change */ u8 *aNewRecord1, /* new.* record for first change */ @@ -1576,11 +1576,16 @@ static int sessionAppendUpdate( return rc; } +/* +** Append a DELETE change to the buffer passed as the first argument. Use +** the changeset format if argument bPatchset is zero, or the patchset +** format otherwise. +*/ static int sessionAppendDelete( SessionBuffer *pBuf, /* Buffer to append to */ int bPatchset, /* True for "patchset", 0 for "changeset" */ - sqlite3_stmt *pStmt, /* Statement handle pointing at new row */ SessionChange *p, /* Object containing old values */ + int nCol, /* Number of columns in table */ u8 *abPK /* Boolean array - true for PK columns */ ){ int rc = SQLITE_OK; @@ -1591,7 +1596,6 @@ static int sessionAppendDelete( if( bPatchset==0 ){ sessionAppendBlob(pBuf, p->aRecord, p->nRecord, &rc); }else{ - int nCol = sqlite3_column_count(pStmt); int i; u8 *a = p->aRecord; for(i=0; izName, (int)strlen(pTab->zName)+1, pRc); } +/* +** Generate either a changeset (if argument bPatchset is zero) or a patchset +** (if it is non-zero) based on the current contents of the session object +** passed as the first argument. +** +** If no error occurs, SQLITE_OK is returned and the new changeset/patchset +** stored in output variables *pnChangeset and *ppChangeset. Or, if an error +** occurs, an SQLite error code is returned and both output variables set +** to 0. +*/ int sessionGenerateChangeset( sqlite3_session *pSession, /* Session object */ int bPatchset, /* True for patchset, false for changeset */ @@ -1827,7 +1841,7 @@ int sessionGenerateChangeset( rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, abPK); } }else if( p->op!=SQLITE_INSERT ){ - rc = sessionAppendDelete(&buf, bPatchset, pSel, p, abPK); + rc = sessionAppendDelete(&buf, bPatchset, p, nCol, abPK); } if( rc==SQLITE_OK ){ rc = sqlite3_reset(pSel); @@ -1965,6 +1979,9 @@ int sqlite3changeset_start( ** When this function is called, *paChange points to the start of the record ** to deserialize. Assuming no error occurs, *paChange is set to point to ** one byte after the end of the same record before this function returns. +** If the argument abPK is NULL, then the record contains nCol values. Or, +** if abPK is other than NULL, then the record contains only the PK fields +** (in other words, it is a patchset DELETE record). ** ** If successful, each element of the apOut[] array (allocated by the caller) ** is set to point to an sqlite3_value object containing the value read diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index de4ee77b94..a6af9aca57 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -275,6 +275,26 @@ int sqlite3session_changeset( /* ** CAPI3REF: Generate A Patchset From A Session Object +** +** The differences between a patchset and a changeset are that: +** +**
    +**
  • DELETE records consist of the primary key fields only. The +** original values of other fields are omitted. +**
  • The original values of any modified fields are omitted from +** UPDATE records. +**
+** +** A patchset blob may be used with up to date versions of all +** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(), +** which returns SQLITE_CORRUPT if it is passed a patchset. Similarly, +** attempting to use a patchset blob with old versions of the +** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error. +** +** Because the non-primary key "old.*" fields are omitted, no +** SQLITE_CHANGESET_DATA conflicts can be detected or reported if a patchset +** is passed to the sqlite3changeset_apply() API. Other conflict types work +** in the same way as for changesets. */ int sqlite3session_patchset( sqlite3_session *pSession, /* Session object */ diff --git a/manifest b/manifest index 2e5dc07be7..feade027e6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fixes\sfor\sthe\ssqlite3changeset_concat()\sAPI\sregarding\spatchsets. -D 2014-08-16T16:47:55.133 +C Fix\ssome\smissing\sand\sout-of-date\scomments\sin\sthe\ssessions\smodule. +D 2014-08-16T19:01:00.672 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 639859a6f81bd15921ccd56ddbd6dfd335278377 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -155,8 +155,8 @@ F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 F ext/session/sessionB.test 51c70394bc04ac72d72f54bd0879614b9c34240c F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 496291b287ba3c0b14ca2e074425e29cc92a64a6 -F ext/session/sqlite3session.c eed0f0510859e564f9f8c886d22a299579b5c6c1 -F ext/session/sqlite3session.h c99445ea9918343d3e62acafdf82bc5502cfba29 +F ext/session/sqlite3session.c f2385ab5ebac94d8e54cc3aa8dc9ca77f8cdf0d9 +F ext/session/sqlite3session.h ef0dbcd599ab8b83e3f3f2e9912e1734519a3ef4 F ext/session/test_session.c 920ccb6d6e1df263cd9099563328094c230b2925 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -1202,7 +1202,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 60a4565a8c44762a002cd02979317df5ca47e899 -R 1bd074b437e8898f047cce1541823103 +P dccb34859508eac8146ae5b19c447673d04be3b0 +R 7605cd9723f946167ef7a988888841f4 U dan -Z 66bd65019d7460afe376babf330097ba +Z 7c34f49d718669db325837ce5da84317 diff --git a/manifest.uuid b/manifest.uuid index 9786ee73ae..19c7a76bfc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dccb34859508eac8146ae5b19c447673d04be3b0 \ No newline at end of file +05c1d9149b27c68e2654ed28491722927d2176f5 \ No newline at end of file From 2e934cd40c24e85562bf767ecdab2bcc19d10c08 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 18 Aug 2014 08:42:36 +0000 Subject: [PATCH 111/570] Add tests for sessions module. FossilOrigin-Name: 82fdb1975f5b29a751089a8582713372999ae56e --- ext/session/sessionB.test | 176 +++++++++++++++++++++++++++++++++++++- manifest | 12 +-- manifest.uuid | 2 +- 3 files changed, 182 insertions(+), 8 deletions(-) diff --git a/ext/session/sessionB.test b/ext/session/sessionB.test index 8791272f8e..d61cada98f 100644 --- a/ext/session/sessionB.test +++ b/ext/session/sessionB.test @@ -327,6 +327,180 @@ do_patchconcat_test 4.3.9 -revert { {DELETE t2 0 .XX. {{} {} i 1 i 2 {} {}} {}} } +#------------------------------------------------------------------------- +# More rigorous testing of the _patchset(), _apply and _concat() APIs. +# +# The inputs to each test are a populate database and a list of DML +# statements. This test determines that the final database is the same +# if: +# +# 1) the statements are executed directly on the database. +# +# 2) a single patchset is collected while executing the statements and +# then applied to a copy of the original database file. +# +# 3) individual patchsets are collected for statement while executing +# them and concatenated together before being applied to a copy of +# the original database. The concatenation is done in a couple of +# different ways - linear, pairwise etc. +# +# All tests, as it happens, are run with both changesets and patchsets. +# But the focus is on patchset capabilities. +# + +# Return a checksum of the contents of the database file. Implicit IPK +# columns are not included in the checksum - just modifying rowids does +# not change the database checksum. +# +proc databasecksum {db} { + set alltab [$db eval {SELECT name FROM sqlite_master WHERE type='table'}] + foreach tab $alltab { + $db eval "SELECT * FROM $tab LIMIT 1" res { } + set slist [list] + foreach col [lsort $res(*)] { + lappend slist "quote($col)" + } + set sql "SELECT [join $slist ,] FROM $tab" + append txt "[lsort [$db eval $sql]]\n" + } + return [md5 $txt] +} + +proc do_patchset_test {tn tstcmd lSql} { + if {$tstcmd != "patchset" && $tstcmd != "changeset"} { + error "have $tstcmd: must be patchset or changeset" + } + + foreach fname {test.db2 test.db3 test.db4 test.db5} { + forcedelete $fname + forcecopy test.db $fname + } + + # Execute the SQL statements on [db]. Collect a patchset for each + # individual statement, as well as a single patchset for the entire + # operation. + sqlite3session S db main + S attach * + foreach sql $lSql { + sqlite3session T db main + T attach * + db eval $sql + lappend lPatch [T patchset] + T delete + } + set patchset [S patchset] + S delete + + # Calculate a checksum for the final database. + set cksum [databasecksum db] + + # 1. Apply the single large patchset to test.db2 + sqlite3 db2 test.db2 + sqlite3changeset_apply db2 $patchset noop + uplevel [list do_test $tn.1 { databasecksum db2 } $cksum ] + db2 close + + # 2. Apply each of the single-statement patchsets to test.db3 + sqlite3 db2 test.db3 + foreach p $lPatch { + sqlite3changeset_apply db2 $p noop + } + uplevel [list do_test $tn.2 { databasecksum db2 } $cksum ] + db2 close + + # 3. Concatenate all single-statement patchsets into a single large + # patchset, then apply it to test.db4. + # + sqlite3 db2 test.db4 + set big "" + foreach p $lPatch { + set big [sqlite3changeset_concat $big $p] + } + sqlite3changeset_apply db2 $big noop + uplevel [list do_test $tn.3 { databasecksum db2 } $cksum ] + db2 close + + # 4. Concatenate all single-statement patchsets pairwise into a single + # large patchset, then apply it to test.db5. Pairwise concatenation: + # + # a b c d e f g h i j k + # -> {a b} {c d} {e f} {g h} {i j} k + # -> {a b c d} {e f g h} {i j k} + # -> {a b c d e f g h} {i j k} + # -> {a b c d e f g h i j k} + # -> APPLY! + # + sqlite3 db2 test.db5 + set L $lPatch + while {[llength $L] > 1} { + set O [list] + for {set i 0} {$i < [llength $L]} {incr i 2} { + if {$i==[llength $L]-1} { + lappend O [lindex $L $i] + } else { + set i1 [expr $i+1] + lappend O [sqlite3changeset_concat [lindex $L $i] [lindex $L $i1]] + } + } + set L $O + } + sqlite3changeset_apply db2 [lindex $L 0] noop + uplevel [list do_test $tn.4 { databasecksum db2 } $cksum ] + db2 close +} + +proc do_patchset_changeset_test {tn initsql args} { + foreach tstcmd {patchset changeset} { + reset_db + execsql $initsql + foreach sql $args { + set lSql [split $sql ";"] + uplevel [list do_patchset_test $tn.$tstcmd $tstcmd $lSql] + } + } +} + +do_patchset_changeset_test 5.1 { + CREATE TABLE t1(a PRIMARY KEY, b, c); + INSERT INTO t1 VALUES(1, 2, 3); +} { + INSERT INTO t1 VALUES(4, 5, 6); + DELETE FROM t1 WHERE a=1; +} { + INSERT INTO t1 VALUES(7, 8, 9); + UPDATE t1 SET c = 5; + INSERT INTO t1 VALUES(10, 11, 12); + UPDATE t1 SET c = 6; + INSERT INTO t1 VALUES(13, 14, 15); +} { + UPDATE t1 SET c=c+1; + DELETE FROM t1 WHERE (a%2); +} + +do_patchset_changeset_test 5.2 { + CREATE TABLE t1(a PRIMARY KEY, b, c); + CREATE TABLE t2(a, b, c, d, PRIMARY KEY(c, b)); +} { + INSERT INTO t1 VALUES(x'00', 0, 'zero'); + INSERT INTO t1 VALUES(x'01', 1, 'one'); + INSERT INTO t1 VALUES(x'02', 4, 'four'); + INSERT INTO t1 VALUES(x'03', 9, 'nine'); + INSERT INTO t1 VALUES(x'04', 16, 'sixteen'); + INSERT INTO t1 VALUES(x'05', 25, 'twenty-five'); +} { + UPDATE t1 SET a = b WHERE b<=4; + INSERT INTO t2 SELECT NULL, * FROM t1; + DELETE FROM t1 WHERE b=25; +} { + DELETE FROM t2; + INSERT INTO t2 SELECT NULL, * FROM t1; + DELETE FROM t1; + INSERT INTO t1 SELECT b, c, d FROM t2; + UPDATE t1 SET b = b+1; + UPDATE t1 SET b = b+1; + UPDATE t1 SET b = b+1; +} + + finish_test - diff --git a/manifest b/manifest index feade027e6..6060acbd59 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\smissing\sand\sout-of-date\scomments\sin\sthe\ssessions\smodule. -D 2014-08-16T19:01:00.672 +C Add\stests\sfor\ssessions\smodule. +D 2014-08-18T08:42:36.985 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 639859a6f81bd15921ccd56ddbd6dfd335278377 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -152,7 +152,7 @@ F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 F ext/session/session9.test 776e46785c29c11cda01f5205d0f1e8f8f9a46bf F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 -F ext/session/sessionB.test 51c70394bc04ac72d72f54bd0879614b9c34240c +F ext/session/sessionB.test 77fca512719c136b8e1f4cb77b77e4c62b9d09ad F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test 496291b287ba3c0b14ca2e074425e29cc92a64a6 F ext/session/sqlite3session.c f2385ab5ebac94d8e54cc3aa8dc9ca77f8cdf0d9 @@ -1202,7 +1202,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P dccb34859508eac8146ae5b19c447673d04be3b0 -R 7605cd9723f946167ef7a988888841f4 +P 05c1d9149b27c68e2654ed28491722927d2176f5 +R 03b8d5b2540614bccade3685e83e41dc U dan -Z 7c34f49d718669db325837ce5da84317 +Z cda8ef5f85a6d704893f36da729451e0 diff --git a/manifest.uuid b/manifest.uuid index 19c7a76bfc..01d5ecc3e5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -05c1d9149b27c68e2654ed28491722927d2176f5 \ No newline at end of file +82fdb1975f5b29a751089a8582713372999ae56e \ No newline at end of file From e62296100f7f32a53b3c6cea88ef4618057b503f Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 18 Aug 2014 15:08:26 +0000 Subject: [PATCH 112/570] Begin adding commands to the command-line interface for interacting with the sessions extension. This is the first check-in of a work-in-progress. FossilOrigin-Name: c2fcf0b9f4bdc48dfc6530bda4f531b94a833207 --- main.mk | 5 ++ manifest | 17 +++--- manifest.uuid | 2 +- src/shell.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 167 insertions(+), 8 deletions(-) diff --git a/main.mk b/main.mk index 73c9847408..24e599ca5b 100644 --- a/main.mk +++ b/main.mk @@ -72,6 +72,8 @@ LIBOBJ+= vdbe.o parse.o \ vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \ vdbetrace.o wal.o walker.o where.o utf.o vtab.o +LIBOBJ += sqlite3session.o + # All of the source code files. @@ -563,6 +565,9 @@ fts3_write.o: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR) rtree.o: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR) $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c +sqlite3session.o: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR) + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c + # Rules for building test programs and for running tests # diff --git a/manifest b/manifest index 84f92a5c48..3a3abec595 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\slatest\strunk\schanges,\sand\sin\sparticular\sthe\srefactoring\sof\sthe\nobject\snames\sin\sthe\scommand-line\sshell. -D 2014-08-18T13:48:41.625 +C Begin\sadding\scommands\sto\sthe\scommand-line\sinterface\sfor\sinteracting\swith\nthe\ssessions\sextension.\s\sThis\sis\sthe\sfirst\scheck-in\sof\sa\swork-in-progress. +D 2014-08-18T15:08:26.073 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 639859a6f81bd15921ccd56ddbd6dfd335278377 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -161,7 +161,7 @@ F ext/session/test_session.c 920ccb6d6e1df263cd9099563328094c230b2925 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 152593de5d19eeab0fdaacfdedd5eafdfdd83d5a +F main.mk eb6742eba7ebb8dc18401220e7ce21788d41aaef F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 @@ -238,7 +238,7 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 0ea356d32a5e884add23d1b9b4e8736681dd5697 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be F src/select.c ea48e891406ccdf748f3eb02893e056d134a0fea -F src/shell.c 41df1103617331e023301d943977f8c06bd1486f +F src/shell.c 6378fc281ab6c2c5ee46cf13f2657e8a187c3ce7 F src/sqlite.h.in 021a1f5c50e83060675d994a6014fd409e611d9e F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -1202,7 +1202,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 82fdb1975f5b29a751089a8582713372999ae56e 11a70e1ae7f05d06e4e09c9d20db0444b8881584 -R 9eb07c2c47c345635567e1ec3d8ef22d +P 419d286a2fc465f6e0f9662909d0cc52a18eefa4 +R 23a3bfb6cd8e3a34baca1f6d98151d23 +T *branch * sessions_from_cli +T *sym-sessions_from_cli * +T -sym-sessions * U drh -Z 44d5fceffc6c6ae323a3b362c9fccbd4 +Z dbfbe7f80e47f8918e41f67c20d63911 diff --git a/manifest.uuid b/manifest.uuid index 3f8761cf9d..c0786ba14f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -419d286a2fc465f6e0f9662909d0cc52a18eefa4 \ No newline at end of file +c2fcf0b9f4bdc48dfc6530bda4f531b94a833207 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 87b335fbb1..66f073a9a8 100644 --- a/src/shell.c +++ b/src/shell.c @@ -432,6 +432,19 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){ return zResult; } +#if defined(SQLITE_ENABLE_SESSION) +/* +** State information for a single open session +*/ +typedef struct OpenSession OpenSession; +struct OpenSession { + char *zName; /* Symbolic name for this session */ + int nFilter; /* Number of xFilter rejection GLOB patterns */ + char **azFilter; /* Array of xFilter rejection GLOB patterns */ + sqlite3_session *p; /* The open session */ +}; +#endif + /* ** Shell output mode information from before ".explain on", ** saved so that it can be restored by ".explain off" @@ -479,6 +492,10 @@ struct ShellState { int *aiIndent; /* Array of indents used in MODE_Explain */ int nIndent; /* Size of array aiIndent[] */ int iIndent; /* Index of current op in aiIndent[] */ +#if defined(SQLITE_ENABLE_SESSION) + int nSession; /* Number of active sessions */ + OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */ +#endif }; /* @@ -1636,6 +1653,9 @@ static char zHelp[] = " LIKE pattern TABLE.\n" ".separator STRING ?NL? Change separator used by output mode and .import\n" " NL is the end-of-line mark for CSV\n" +#if defined(SQLITE_ENABLE_SESSION) + ".session CMD ... Create or control sessions\n" +#endif ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" ".show Show the current values for various settings\n" ".stats on|off Turn stats on or off\n" @@ -1651,6 +1671,30 @@ static char zHelp[] = " Negative values right-justify\n" ; +#if defined(SQLITE_ENABLE_SESSION) +/* +** Print help information for the ".sessions" command +*/ +void session_help(ShellState *p){ + fprintf(p->out, + ".session ?NAME? SUBCOMMAND ?ARGS...?\n" + "If ?NAME? is omitted, the first defined session is used.\n" + "Subcommands:\n" + " attach TABLE Attach TABLE\n" + " changeset FILE Write a changeset into FILE\n" + " close Close one session\n" + " enable ?BOOLEAN? Set or query the enable bit\n" + " filter GLOB... Reject tables matching GLOBs\n" + " indirect ?BOOLEAN? Mark or query the indirect status\n" + " isempty Query whether the session is empty\n" + " list List currently open session names\n" + " open DB NAME Open a new session on DB\n" + " patchset FILE Write a patchset into FILE\n" + ); +} +#endif + + /* Forward reference */ static int process_input(ShellState *p, FILE *in); /* @@ -1714,6 +1758,36 @@ static void writefileFunc( sqlite3_result_int64(context, rc); } +#if defined(SQLITE_ENABLE_SESSION) +/* +** Close a single OpenSession object and release all of its associated +** resources. +*/ +static void session_close(OpenSession *pSession){ + int i; + sqlite3session_delete(pSession->p); + sqlite3_free(pSession->zName); + for(i=0; inFilter; i++){ + sqlite3_free(pSession->azFilter[i]); + } + sqlite3_free(pSession->azFilter); + memset(pSession, 0, sizeof(OpenSession)); +} +#endif + +/* +** Close all OpenSession objects and release all assocaited resources. +*/ +static void session_close_all(ShellState *p){ +#if defined(SQLITE_ENABLE_SESSION) + int i; + for(i=0; inSession; i++){ + session_close(&p->aSession[i]); + } + p->nSession = 0; +#endif +} + /* ** Make sure the database is open. If it is not, then open it. If ** the database fails to open, print an error message and exit. @@ -2865,6 +2939,7 @@ static int do_meta_command(char *zLine, ShellState *p){ } open_db(p, 1); if( p->db!=0 ){ + session_close_all(p); sqlite3_close(savedDb); sqlite3_free(p->zFreeOnClose); p->zFreeOnClose = zNewFilename; @@ -3086,6 +3161,81 @@ static int do_meta_command(char *zLine, ShellState *p){ } }else +#if defined(SQLITE_ENABLE_SESSION) + if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){ + OpenSession *pSession = &p->aSession[0]; + char **azCmd = &azArg[1]; + int iSes = 0; + int nCmd = nArg - 1; + int i; + if( nArg<=1 ) goto session_syntax_error; + if( nArg>=3 ){ + for(iSes=0; iSesnSession; iSes++){ + if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break; + } + if( iSesnSession ){ + pSession = &p->aSession[iSes]; + azCmd++; + nCmd--; + }else{ + pSession = &p->aSession[0]; + iSes = 0; + } + } + + /* .session close + ** Close the identified session + */ + if( strcmp(azCmd[0], "close")==0 ){ + if( p->nSession ){ + session_close(pSession); + p->aSession[iSes] = p->aSession[--p->nSession]; + } + }else + + /* .session list + ** List all currently open sessions + */ + if( strcmp(azCmd[0],"list")==0 ){ + for(i=0; inSession; i++){ + fprintf(p->out, "%d %s\n", i, p->aSession[i].zName); + } + }else + + /* .session open DB NAME + ** Open a new session called NAME on the attached database DB. + ** DB is normally "main". + */ + if( strcmp(azCmd[0],"open")==0 ){ + char *zName; + if( nCmd!=3 ) goto session_syntax_error; + zName = azCmd[2]; + if( zName[0]==0 ) goto session_syntax_error; + for(i=0; inSession; i++){ + if( strcmp(p->aSession[i].zName,zName)==0 ){ + fprintf(stderr, "Session \"%s\" already exists\n", zName); + goto meta_command_exit; + } + } + if( p->nSession>=ArraySize(p->aSession) ){ + fprintf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession)); + goto meta_command_exit; + } + pSession = &p->aSession[p->nSession]; + rc = sqlite3session_create(p->db, azCmd[1], &pSession->p); + if( rc ){ + fprintf(stderr, "Cannot open session: error code=%d\n", rc); + goto meta_command_exit; + } + p->nSession++; + pSession->zName = sqlite3_mprintf("%s", zName); + }else + /* If no command name matches, show a syntax error */ + session_syntax_error: + session_help(p); + }else +#endif + #ifdef SQLITE_DEBUG /* Undocumented commands for internal testing. Subject to change ** without notice. */ @@ -4134,6 +4284,7 @@ int main(int argc, char **argv){ } set_table_name(&data, 0); if( data.db ){ + session_close_all(&data); sqlite3_close(data.db); } sqlite3_free(data.zFreeOnClose); From 082c96dffa373ed10d000001edce62ae757f13ec Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 18 Aug 2014 16:03:46 +0000 Subject: [PATCH 113/570] Add miscellaneous test cases to improve coverage of sessions module. FossilOrigin-Name: 0fac6cfffe628ea02c78ebad065307309ec9eaa1 --- ext/session/session1.test | 18 +++++++ ext/session/sessionB.test | 15 +++++- ext/session/sessionfault.test | 52 ++++++++++++++++-- ext/session/sqlite3session.c | 18 ++++--- ext/session/sqlite3session.h | 4 ++ ext/session/test_session.c | 99 +++++++++++++++++++++++++++++++++++ manifest | 24 ++++----- manifest.uuid | 2 +- 8 files changed, 207 insertions(+), 25 deletions(-) diff --git a/ext/session/session1.test b/ext/session/session1.test index e47fb3e845..e6f9c8fd7f 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -492,6 +492,24 @@ do_test 8.3 { } {1} do_test 8.4 { S delete } {} +do_test 8.5 { + sqlite3session S db main + S attach t5 + S attach t6 + execsql { INSERT INTO t5 VALUES(1, 2) } + S isempty +} {0} + +do_test 8.6 { + S delete + sqlite3session S db main + S attach t5 + S attach t6 + execsql { INSERT INTO t6 VALUES(1, 2) } + S isempty +} {0} +do_test 8.7 { S delete } {} + #------------------------------------------------------------------------- # do_execsql_test 9.1 { diff --git a/ext/session/sessionB.test b/ext/session/sessionB.test index d61cada98f..9798cabfee 100644 --- a/ext/session/sessionB.test +++ b/ext/session/sessionB.test @@ -453,9 +453,11 @@ proc do_patchset_changeset_test {tn initsql args} { foreach tstcmd {patchset changeset} { reset_db execsql $initsql + set x 0 foreach sql $args { + incr x set lSql [split $sql ";"] - uplevel [list do_patchset_test $tn.$tstcmd $tstcmd $lSql] + uplevel [list do_patchset_test $tn.$tstcmd.$x $tstcmd $lSql] } } } @@ -501,6 +503,17 @@ do_patchset_changeset_test 5.2 { UPDATE t1 SET b = b+1; } +set initsql { CREATE TABLE t1(a, b, c, PRIMARY KEY(c, b)); } +for {set i 0} {$i < 1000} {incr i} { + append insert "INSERT INTO t1 VALUES($i, $i, $i);" + append delete "DELETE FROM t1 WHERE b=$i;" +} +do_patchset_changeset_test 5.3 \ + $initsql $insert $delete \ + $insert $delete \ + "$insert $delete" \ + $delete + finish_test diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index f17daccfc7..4b278098a9 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -20,8 +20,6 @@ source $testdir/tester.tcl set testprefix sessionfault -if 1 { - forcedelete test.db2 sqlite3 db2 test.db2 do_common_sql { @@ -399,8 +397,6 @@ do_faultsim_test 9.1 -faults oom-transient -prep { } } -} - faultsim_delete_and_reopen do_test 9.2.prep { execsql { @@ -438,6 +434,54 @@ do_faultsim_test 9.2 -faults oom-transient -prep { } } +#------------------------------------------------------------------------- +# Test that if a conflict-handler encounters an OOM in +# sqlite3_value_text() but goes on to return SQLITE_CHANGESET_REPLACE +# anyway, the OOM is picked up by the sessions module. +set bigstr [string repeat abcdefghij 100] +faultsim_delete_and_reopen +do_test 10.prep.1 { + execsql { + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES($bigstr, $bigstr); + } + + sqlite3session S db main + S attach * + execsql { UPDATE t1 SET b = b||'x' } + set C [S changeset] + S delete + execsql { UPDATE t1 SET b = b||'xyz' } +} {} +faultsim_save_and_close + +faultsim_restore_and_reopen +do_test 10.prep.2 { + proc xConflict {args} { return "ABORT" } + list [catch { sqlite3changeset_apply db $C xConflict } msg] $msg +} {1 SQLITE_ABORT} +do_execsql_test 10.prep.3 { SELECT b=$bigstr||'x' FROM t1 } 0 +do_test 10.prep.4 { + proc xConflict {args} { return "REPLACE" } + list [catch { sqlite3changeset_apply db $C xConflict } msg] $msg +} {0 {}} +do_execsql_test 10.prep.5 { SELECT b=$bigstr||'x' FROM t1 } 1 +db close + +do_faultsim_test 10 -faults oom-tra* -prep { + faultsim_restore_and_reopen +} -body { + sqlite3changeset_apply_replace_all db $::C +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + if {$testrc==0} { + if {[db one {SELECT b=$bigstr||'x' FROM t1}]==0} { + error "data does not look right" + } + } +} + + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 69d67817bf..18dba064ec 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2703,10 +2703,14 @@ static int sessionBindValue( sqlite3_value *pVal /* Value to bind */ ){ int eType = sqlite3_value_type(pVal); + /* COVERAGE: The (pVal->z==0) branch is never true using current versions + ** of SQLite. If a malloc fails in an sqlite3_value_xxx() function, either + ** the (pVal->z) variable remains as it was or the type of the value is + ** set to SQLITE_NULL. */ if( (eType==SQLITE_TEXT || eType==SQLITE_BLOB) && pVal->z==0 ){ /* This condition occurs when an earlier OOM in a call to ** sqlite3_value_text() or sqlite3_value_blob() (perhaps from within - ** a conflict-hanler) has zeroed the pVal->z pointer. Return NOMEM. */ + ** a conflict-handler) has zeroed the pVal->z pointer. Return NOMEM. */ return SQLITE_NOMEM; } return sqlite3_bind_value(pStmt, i, pVal); @@ -3052,6 +3056,8 @@ int sqlite3changeset_apply( int nTab = 0; /* Result of sqlite3Strlen30(zTab) */ SessionApplyCtx sApply; /* changeset_apply() context object */ + assert( xConflict!=0 ); + memset(&sApply, 0, sizeof(sApply)); rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); if( rc!=SQLITE_OK ) return rc; @@ -3169,12 +3175,10 @@ int sqlite3changeset_apply( sqlite3_db_status(db, SQLITE_DBSTATUS_DEFERRED_FKS, &nFk, ¬Used, 0); if( nFk!=0 ){ int res = SQLITE_CHANGESET_ABORT; - if( xConflict ){ - sqlite3_changeset_iter sIter; - memset(&sIter, 0, sizeof(sIter)); - sIter.nCol = nFk; - res = xConflict(pCtx, SQLITE_CHANGESET_FOREIGN_KEY, &sIter); - } + sqlite3_changeset_iter sIter; + memset(&sIter, 0, sizeof(sIter)); + sIter.nCol = nFk; + res = xConflict(pCtx, SQLITE_CHANGESET_FOREIGN_KEY, &sIter); if( res!=SQLITE_CHANGESET_OMIT ){ rc = SQLITE_CONSTRAINT; } diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index a6af9aca57..ced984ecbe 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -735,6 +735,10 @@ int sqlite3changeset_concat( ** invoked. A description of exactly when the conflict handler is invoked for ** each type of change is below. ** +** Unlike the xFilter argument, xConflict may not be passed NULL. The results +** of passing anything other than a valid function pointer as the xConflict +** argument are undefined. +** ** Each time the conflict handler function is invoked, it must return one ** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or ** [SQLITE_CHANGESET_REPLACE]. SQLITE_CHANGESET_REPLACE may only be returned diff --git a/ext/session/test_session.c b/ext/session/test_session.c index fa99f56786..38e4be1481 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -417,6 +417,13 @@ static int test_conflict_handler( rc = sqlite3changeset_old(pIter, nCol, &pVal); assert( rc==SQLITE_RANGE ); } + if( eConf!=SQLITE_CHANGESET_FOREIGN_KEY ){ + /* eConf!=FOREIGN_KEY is always true at this point. The condition is + ** just there to make it clearer what is being tested. */ + int nDummy; + int rc = sqlite3changeset_fk_conflicts(pIter, &nDummy); + assert( rc==SQLITE_MISUSE ); + } /* End of testing block ***********************************************************************/ } @@ -440,6 +447,51 @@ static int test_conflict_handler( return ret; } +/* +** The conflict handler used by sqlite3changeset_apply_replace_all(). +** This conflict handler calls sqlite3_value_text16() on all available +** sqlite3_value objects and then returns CHANGESET_REPLACE, or +** CHANGESET_OMIT if REPLACE is not applicable. This is used to test the +** effect of a malloc failure within an sqlite3_value_xxx() function +** invoked by a conflict-handler callback. +*/ +static int replace_handler( + void *pCtx, /* Pointer to TestConflictHandler structure */ + int eConf, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *pIter /* Handle describing change and conflict */ +){ + int op; /* SQLITE_UPDATE, DELETE or INSERT */ + const char *zTab; /* Name of table conflict is on */ + int nCol; /* Number of columns in table zTab */ + int i; + int x = 0; + + sqlite3changeset_op(pIter, &zTab, &nCol, &op, 0); + + if( op!=SQLITE_INSERT ){ + for(i=0; i Date: Mon, 18 Aug 2014 17:56:31 +0000 Subject: [PATCH 114/570] Add the "changeset" command-line utility for getting an ASCII dump of change sets. FossilOrigin-Name: 55bb3544a6b474c04853270067a35ca4b0079f52 --- ext/session/changeset.c | 314 ++++++++++++++++++++++++++++++++++++++++ main.mk | 4 + manifest | 18 +-- manifest.uuid | 2 +- src/shell.c | 49 +++++++ 5 files changed, 376 insertions(+), 11 deletions(-) create mode 100644 ext/session/changeset.c diff --git a/ext/session/changeset.c b/ext/session/changeset.c new file mode 100644 index 0000000000..62817a64e5 --- /dev/null +++ b/ext/session/changeset.c @@ -0,0 +1,314 @@ +/* +** 2014-08-18 +** +** 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 contains code to implement the "changeset" command line +** utility for displaying and transforming changesets generated by +** the Sessions extension. +*/ +#include "sqlite3.h" +#include +#include +#include +#include +#include + + +/* +** Show a usage message on stderr then quit. +*/ +static void usage(const char *argv0){ + fprintf(stderr, "Usage: %s FILENAME COMMAND ...\n", argv0); + fprintf(stderr, + "COMMANDs:\n" + " apply DB Apply the changeset to database file DB\n" + " concat FILE2 OUT Concatenate FILENAME and FILE2 into OUT\n" + " dump Show the complete content of the changeset\n" + " invert OUT Write an inverted changeset into file OUT\n" + " sql Give a pseudo-SQL rendering of the changeset\n" + ); + exit(1); +} + +/* +** Read the content of a disk file into an in-memory buffer +*/ +static void readFile(const char *zFilename, int *pSz, void **ppBuf){ + FILE *f; + int sz; + void *pBuf; + f = fopen(zFilename, "rb"); + if( f==0 ){ + fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename); + exit(1); + } + fseek(f, 0, SEEK_END); + sz = (int)ftell(f); + rewind(f); + pBuf = sqlite3_malloc( sz ? sz : 1 ); + if( pBuf==0 ){ + fprintf(stderr, "cannot allocate %d to hold content of \"%s\"\n", + sz, zFilename); + exit(1); + } + if( sz>0 ){ + if( fread(pBuf, sz, 1, f)!=1 ){ + fprintf(stderr, "cannot read all %d bytes of \"%s\"\n", sz, zFilename); + exit(1); + } + fclose(f); + } + *pSz = sz; + *ppBuf = pBuf; +} + +/* Array for converting from half-bytes (nybbles) into ASCII hex +** digits. */ +static const char hexdigits[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + +/* +** Render an sqlite3_value as an SQL string. +*/ +static void renderValue(sqlite3_value *pVal){ + switch( sqlite3_value_type(pVal) ){ + case SQLITE_FLOAT: { + double r1; + char zBuf[50]; + r1 = sqlite3_value_double(pVal); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1); + printf("%s", zBuf); + break; + } + case SQLITE_INTEGER: { + printf("%lld", sqlite3_value_int64(pVal)); + break; + } + case SQLITE_BLOB: { + char const *zBlob = sqlite3_value_blob(pVal); + int nBlob = sqlite3_value_bytes(pVal); + int i; + printf("x'"); + for(i=0; i>4)&0x0F]); + putchar(hexdigits[(zBlob[i])&0x0F]); + } + putchar('\''); + break; + } + case SQLITE_TEXT: { + const unsigned char *zArg = sqlite3_value_text(pVal); + putchar('\''); + while( zArg[0] ){ + putchar(zArg[0]); + if( zArg[0]=='\'' ) putchar(zArg[0]); + zArg++; + } + putchar('\''); + break; + } + default: { + assert( sqlite3_value_type(pVal)==SQLITE_NULL ); + printf("NULL"); + break; + } + } +} + +int main(int argc, char **argv){ + int sz, rc; + void *pBuf = 0; + if( argc<3 ) usage(argv[0]); + readFile(argv[1], &sz, &pBuf); + + /* changeset FILENAME apply DB + ** Apply the changeset in FILENAME to the database file DB + */ + if( strcmp(argv[2],"apply")==0 ){ + fprintf(stderr, "not yet implemented\n"); + }else + + /* changeset FILENAME concat FILE2 OUT + ** Add changeset FILE2 onto the end of the changeset in FILENAME + ** and write the result into OUT. + */ + if( strcmp(argv[2],"concat")==0 ){ + fprintf(stderr, "not yet implemented\n"); + }else + + /* changeset FILENAME dump + ** Show the complete content of the changeset in FILENAME + */ + if( strcmp(argv[2],"dump")==0 ){ + int cnt = 0; + int i; + sqlite3_changeset_iter *pIter; + rc = sqlite3changeset_start(&pIter, sz, pBuf); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "sqlite3changeset_start() returns %d\n", rc); + exit(1); + } + while( sqlite3changeset_next(pIter)==SQLITE_ROW ){ + int op, bIndirect, nCol; + const char *zTab; + unsigned char *abPK; + sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect); + cnt++; + printf("%d: %s table=[%s] indirect=%d nColumn=%d\n", + cnt, op==SQLITE_INSERT ? "INSERT" : + op==SQLITE_UPDATE ? "UPDATE" : "DELETE", + zTab, bIndirect, nCol); + sqlite3changeset_pk(pIter, &abPK, 0); + for(i=0; i=3 ){ for(iSes=0; iSesnSession; iSes++){ if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break; @@ -3183,6 +3184,53 @@ static int do_meta_command(char *zLine, ShellState *p){ } } + /* .session attach TABLE + ** Invoke the sqlite3session_attach() interface to attach a particular + ** table so that it is never filtered. + */ + if( strcmp(azCmd[0],"attach")==0 ){ + if( nCmd!=2 ) goto session_syntax_error; + if( pSession->p==0 ){ + session_not_open: + fprintf(stderr, "ERROR: No sessions are open\n"); + }else{ + rc = sqlite3session_attach(pSession->p, azCmd[1]); + if( rc ){ + fprintf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc); + rc = 0; + } + } + }else + + /* .session changeset FILE + ** .session patchset FILE + ** Write a changeset or patchset into a file. The file is overwritten. + */ + if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){ + FILE *out = 0; + if( nCmd!=2 ) goto session_syntax_error; + if( pSession->p==0 ) goto session_not_open; + out = fopen(azCmd[1], "wb"); + if( out==0 ){ + fprintf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]); + }else{ + int szChng; + void *pChng; + if( azCmd[0][0]=='c' ){ + sqlite3session_changeset(pSession->p, &szChng, &pChng); + }else{ + sqlite3session_patchset(pSession->p, &szChng, &pChng); + } + if( pChng + && fwrite(pChng, szChng, 1, out)!=1 ){ + fprintf(stderr, "ERROR: Failed to write entire %d-byte output\n", + szChng); + } + sqlite3_free(pChng); + fclose(out); + } + }else + /* .session close ** Close the identified session */ @@ -3225,6 +3273,7 @@ static int do_meta_command(char *zLine, ShellState *p){ rc = sqlite3session_create(p->db, azCmd[1], &pSession->p); if( rc ){ fprintf(stderr, "Cannot open session: error code=%d\n", rc); + rc = 0; goto meta_command_exit; } p->nSession++; From 03168cacd5c139471e651cf825501a953e0fcd4c Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 18 Aug 2014 20:01:31 +0000 Subject: [PATCH 115/570] A reasonably complete implementation of the "changeset" command-line tool and the ".sessions" command in the command-line shell. FossilOrigin-Name: 7b12f1f9c012f33d376242920583807b014b3287 --- ext/session/changeset.c | 108 ++++++++++++++++++++++++++++++++++++++-- manifest | 14 +++--- manifest.uuid | 2 +- src/shell.c | 80 +++++++++++++++++++++++++++++ 4 files changed, 191 insertions(+), 13 deletions(-) diff --git a/ext/session/changeset.c b/ext/session/changeset.c index 62817a64e5..1ff5cde87d 100644 --- a/ext/session/changeset.c +++ b/ext/session/changeset.c @@ -124,6 +124,58 @@ static void renderValue(sqlite3_value *pVal){ } } +/* +** Number of conflicts seen +*/ +static int nConflict = 0; + +/* +** The conflict callback +*/ +static int conflictCallback( + void *pCtx, + int eConflict, + sqlite3_changeset_iter *pIter +){ + int op, bIndirect, nCol, i; + const char *zTab; + unsigned char *abPK; + const char *zType = ""; + const char *zOp = ""; + const char *zSep = " "; + + nConflict++; + sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect); + sqlite3changeset_pk(pIter, &abPK, 0); + switch( eConflict ){ + case SQLITE_CHANGESET_DATA: zType = "DATA"; break; + case SQLITE_CHANGESET_NOTFOUND: zType = "NOTFOUND"; break; + case SQLITE_CHANGESET_CONFLICT: zType = "PRIMARY KEY"; break; + case SQLITE_CHANGESET_FOREIGN_KEY: zType = "FOREIGN KEY"; break; + case SQLITE_CHANGESET_CONSTRAINT: zType = "CONSTRAINT"; break; + } + switch( op ){ + case SQLITE_UPDATE: zOp = "UPDATE of"; break; + case SQLITE_INSERT: zOp = "INSERT into"; break; + case SQLITE_DELETE: zOp = "DELETE from"; break; + } + printf("%s conflict on %s table %s with primary key", zType, zOp, zTab); + for(i=0; inFilter; i++){ + if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0; + } + return 1; +} +#endif + /* ** Make sure the database is open. If it is not, then open it. If ** the database fails to open, print an error message and exit. @@ -3235,12 +3250,75 @@ static int do_meta_command(char *zLine, ShellState *p){ ** Close the identified session */ if( strcmp(azCmd[0], "close")==0 ){ + if( nCmd!=1 ) goto session_syntax_error; if( p->nSession ){ session_close(pSession); p->aSession[iSes] = p->aSession[--p->nSession]; } }else + /* .session enable ?BOOLEAN? + ** Query or set the enable flag + */ + if( strcmp(azCmd[0], "enable")==0 ){ + int ii; + if( nCmd>2 ) goto session_syntax_error; + ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); + if( p->nSession ){ + ii = sqlite3session_enable(pSession->p, ii); + fprintf(p->out, "session %s enable flag = %d\n", pSession->zName, ii); + } + }else + + /* .session filter GLOB .... + ** Set a list of GLOB patterns of table names to be excluded. + */ + if( strcmp(azCmd[0], "filter")==0 ){ + int ii, nByte; + if( nCmd<2 ) goto session_syntax_error; + if( p->nSession ){ + for(ii=0; iinFilter; ii++){ + sqlite3_free(pSession->azFilter[ii]); + } + sqlite3_free(pSession->azFilter); + nByte = sizeof(pSession->azFilter[0])*(nCmd-1); + pSession->azFilter = sqlite3_malloc( nByte ); + if( pSession->azFilter==0 ){ + fprintf(stderr, "Error: out or memory\n"); + exit(1); + } + for(ii=1; iiazFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]); + } + pSession->nFilter = ii-1; + } + }else + + /* .session indirect ?BOOLEAN? + ** Query or set the indirect flag + */ + if( strcmp(azCmd[0], "indirect")==0 ){ + int ii; + if( nCmd>2 ) goto session_syntax_error; + ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); + if( p->nSession ){ + ii = sqlite3session_indirect(pSession->p, ii); + fprintf(p->out, "session %s indirect flag = %d\n", pSession->zName,ii); + } + }else + + /* .session isempty + ** Determine if the session is empty + */ + if( strcmp(azCmd[0], "isempty")==0 ){ + int ii; + if( nCmd!=1 ) goto session_syntax_error; + if( p->nSession ){ + ii = sqlite3session_isempty(pSession->p); + fprintf(p->out, "session %s isempty flag = %d\n", pSession->zName, ii); + } + }else + /* .session list ** List all currently open sessions */ @@ -3276,6 +3354,8 @@ static int do_meta_command(char *zLine, ShellState *p){ rc = 0; goto meta_command_exit; } + pSession->nFilter = 0; + sqlite3session_table_filter(pSession->p, session_filter, pSession); p->nSession++; pSession->zName = sqlite3_mprintf("%s", zName); }else From f5ab08c77903a3c2dfa0a68c3c243ce1ab047686 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 18 Aug 2014 20:14:30 +0000 Subject: [PATCH 116/570] Fix a harmless compiler warning in the sessionAppendDelete() function. FossilOrigin-Name: 1324d08d0c639378cf1b03bd6410db81947747ac --- ext/session/sqlite3session.c | 2 +- manifest | 13 ++++++------- manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 18dba064ec..4617e6a3c2 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1621,7 +1621,7 @@ static int sessionAppendDelete( } } if( abPK[i] ){ - sessionAppendBlob(pBuf, pStart, a-pStart, &rc); + sessionAppendBlob(pBuf, pStart, (int)(a-pStart), &rc); } } assert( (a - p->aRecord)==p->nRecord ); diff --git a/manifest b/manifest index 3199c22597..eba81a57c4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s"changeset"\scommand-line\stool\sfor\sanalyzing\sand\smanipulating\nchangesets\sin\sfiles\son\sdisk.\s\sAdd\sthe\s".session"\scommand\sto\sthe\scommand-line\ntool. -D 2014-08-18T20:08:25.748 +C Fix\sa\sharmless\scompiler\swarning\sin\sthe\ssessionAppendDelete()\sfunction. +D 2014-08-18T20:14:30.667 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 639859a6f81bd15921ccd56ddbd6dfd335278377 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -156,7 +156,7 @@ F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 F ext/session/sessionB.test 276267cd7fc37c2e2dd03f1e2ed9ada336a8bdb4 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test e7965159a73d385c1a4af12d82c3a039ebdd71a6 -F ext/session/sqlite3session.c b7cc5645ee3de77c650cf7e05161f320ebaa997f +F ext/session/sqlite3session.c 4c7689bd8286147f7d9bf5d4b6ca5e7e7ee588ab F ext/session/sqlite3session.h 66c14a2f6193c47773770307636e88c43db6f839 F ext/session/test_session.c a252fb669d3a1b3552ee7b87fe610debc0afeb7b F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -1203,8 +1203,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0fac6cfffe628ea02c78ebad065307309ec9eaa1 7b12f1f9c012f33d376242920583807b014b3287 -R 7a7a7eda9e9e796cac11d47296a11e68 -T +closed 7b12f1f9c012f33d376242920583807b014b3287 +P 31addb627fdbaeb908e0611ad82f6db7537428ea +R 0c1b981f1387fdad5168bd8925d76ab9 U drh -Z bd91644aa3e055b27f4fc846b7cc054f +Z 34dce636dabda531b1c7f9aae0a417c1 diff --git a/manifest.uuid b/manifest.uuid index af042500c5..c5348ad8bf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -31addb627fdbaeb908e0611ad82f6db7537428ea \ No newline at end of file +1324d08d0c639378cf1b03bd6410db81947747ac \ No newline at end of file From 9f674f2600e7009328fbeb8d5c1614875439bb8d Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 18 Aug 2014 20:23:29 +0000 Subject: [PATCH 117/570] Fix the autoconf and MSVC makefiles so that they construct the changeset command-line utility upon request. Delete that utility program when "make clean" is run. FossilOrigin-Name: 4dc15fe066f079ff31c89a5e0242dd5b3c851d29 --- Makefile.in | 5 ++++- Makefile.msc | 6 +++++- main.mk | 1 + manifest | 16 ++++++++-------- manifest.uuid | 2 +- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Makefile.in b/Makefile.in index 7814529c21..3292da7741 100644 --- a/Makefile.in +++ b/Makefile.in @@ -964,6 +964,9 @@ showjournal$(TEXE): $(TOP)/tool/showjournal.c sqlite3.lo showwal$(TEXE): $(TOP)/tool/showwal.c sqlite3.lo $(LTLINK) -o $@ $(TOP)/tool/showwal.c sqlite3.lo $(TLIBS) +changeset$(TEXE): $(TOP)/ext/session/changeset.c sqlite3.lo + $(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS) + rollback-test$(TEXE): $(TOP)/tool/rollback-test.c sqlite3.lo $(LTLINK) -o $@ $(TOP)/tool/rollback-test.c sqlite3.lo $(TLIBS) @@ -1012,7 +1015,7 @@ clean: rm -f testfixture$(TEXE) test.db rm -f LogEst$(TEXE) fts3view$(TEXE) rollback-test$(TEXE) showdb$(TEXE) rm -f showjournal$(TEXE) showstat4$(TEXE) showwal$(TEXE) speedtest1$(TEXE) - rm -f wordcount$(TEXE) + rm -f wordcount$(TEXE) changeset$(TEXE) rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def rm -f sqlite3.c rm -f sqlite3rc.h diff --git a/Makefile.msc b/Makefile.msc index 38ea41ffba..d246cf03c3 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1476,6 +1476,10 @@ showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(TOP)\tool\showwal.c $(SQLITE3C) +changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) + $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ + $(TOP)\ext\session\changeset.c $(SQLITE3C) + fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) @@ -1512,7 +1516,7 @@ clean: del /Q tclsqlite3.exe tclsqlite3.exp del /Q testloadext.dll testloadext.exp del /Q testfixture.exe testfixture.exp test.db - del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe + del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe changeset.exe del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe del /Q wordcount.exe del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def diff --git a/main.mk b/main.mk index 13798354cb..4d376a805b 100644 --- a/main.mk +++ b/main.mk @@ -722,6 +722,7 @@ clean: rm -f showjournal showjournal.exe rm -f showstat4 showstat4.exe rm -f showwal showwal.exe + rm -f changeset changeset.exe rm -f speedtest1 speedtest1.exe rm -f wordcount wordcount.exe rm -f sqlite3.c sqlite3-*.c fts?amal.c tclsqlite3.c diff --git a/manifest b/manifest index eba81a57c4..d2986aafb7 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Fix\sa\sharmless\scompiler\swarning\sin\sthe\ssessionAppendDelete()\sfunction. -D 2014-08-18T20:14:30.667 +C Fix\sthe\sautoconf\sand\sMSVC\smakefiles\sso\sthat\sthey\sconstruct\sthe\schangeset\ncommand-line\sutility\supon\srequest.\s\sDelete\sthat\sutility\sprogram\swhen\n"make\sclean"\sis\srun. +D 2014-08-18T20:23:29.435 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f -F Makefile.in 639859a6f81bd15921ccd56ddbd6dfd335278377 +F Makefile.in d5ad373b7a23525414b8843b3084cf90c560d92f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc d389ce1d436d21a93a9f5f6211dc45e4b8860962 +F Makefile.msc f1bbf555916b6e60887d86cea62f27e6a26cdb24 F Makefile.vxworks 034289efa9d591b04b1a73598623119c306cbba0 F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8 F VERSION 1c877615a9db323e3cd301e3d57d853f9d5c4a07 @@ -162,7 +162,7 @@ F ext/session/test_session.c a252fb669d3a1b3552ee7b87fe610debc0afeb7b F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 95de2e32fbe62b10e28bd7a131e2b003b923a8b3 +F main.mk a9987b6655610e663e9f055e0f1646227f45cddd F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 @@ -1203,7 +1203,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 31addb627fdbaeb908e0611ad82f6db7537428ea -R 0c1b981f1387fdad5168bd8925d76ab9 +P 1324d08d0c639378cf1b03bd6410db81947747ac +R fdaf7ebc782210d979a62294e31e9051 U drh -Z 34dce636dabda531b1c7f9aae0a417c1 +Z e19e0e50f2717082ee6e33a1c9b88ce5 diff --git a/manifest.uuid b/manifest.uuid index c5348ad8bf..2e186914d2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1324d08d0c639378cf1b03bd6410db81947747ac \ No newline at end of file +4dc15fe066f079ff31c89a5e0242dd5b3c851d29 \ No newline at end of file From 2967e0cc9c1c21a8ab06a294ee9470d558e3b6a9 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 19 Aug 2014 00:26:17 +0000 Subject: [PATCH 118/570] Improved response to error conditions in the ".session" shell command and in the "changeset" command-line program. FossilOrigin-Name: b69f7dd1f35846c3bb9f4f160d50c4f03796f887 --- ext/session/changeset.c | 12 ++++++++---- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c | 8 ++++++-- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/ext/session/changeset.c b/ext/session/changeset.c index 1ff5cde87d..edb43ff8e5 100644 --- a/ext/session/changeset.c +++ b/ext/session/changeset.c @@ -232,8 +232,10 @@ int main(int argc, char **argv){ exit(1); } readFile(argv[3], &szB, &pB); - sqlite3changeset_concat(sz, pBuf, szB, pB, &szOut, &pOutBuf); - if( fwrite(pOutBuf, szOut, 1, out)!=1 ){ + rc = sqlite3changeset_concat(sz, pBuf, szB, pB, &szOut, &pOutBuf); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "sqlite3changeset_concat() returns %d\n", rc); + }else if( szOut>0 && fwrite(pOutBuf, szOut, 1, out)!=1 ){ fprintf(stderr, "unable to write all %d bytes of output to \"%s\"\n", szOut, zOut); } @@ -300,8 +302,10 @@ int main(int argc, char **argv){ fprintf(stderr, "cannot open \"%s\" for writing\n", zOut); exit(1); } - sqlite3changeset_invert(sz, pBuf, &szOut, &pOutBuf); - if( fwrite(pOutBuf, szOut, 1, out)!=1 ){ + rc = sqlite3changeset_invert(sz, pBuf, &szOut, &pOutBuf); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "sqlite3changeset_invert() returns %d\n", rc); + }else if( szOut>0 && fwrite(pOutBuf, szOut, 1, out)!=1 ){ fprintf(stderr, "unable to write all %d bytes of output to \"%s\"\n", szOut, zOut); } diff --git a/manifest b/manifest index d2986aafb7..8526781f17 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\sautoconf\sand\sMSVC\smakefiles\sso\sthat\sthey\sconstruct\sthe\schangeset\ncommand-line\sutility\supon\srequest.\s\sDelete\sthat\sutility\sprogram\swhen\n"make\sclean"\sis\srun. -D 2014-08-18T20:23:29.435 +C Improved\sresponse\sto\serror\sconditions\sin\sthe\s".session"\sshell\scommand\sand\nin\sthe\s"changeset"\scommand-line\sprogram. +D 2014-08-19T00:26:17.830 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in d5ad373b7a23525414b8843b3084cf90c560d92f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -143,7 +143,7 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 83349d519fe5f518b3ea025d18dd1fe51b1684bd F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/session/changeset.c 9be709cea346d65c6d0cc8bf03569956af125462 +F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a F ext/session/session1.test 3733d71eb9a99b14d51fa5219d5b8a82407c3be8 F ext/session/session2.test 99ca0da7ddb617d42bafd83adccf99f18ae0384b F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 @@ -239,7 +239,7 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 0ea356d32a5e884add23d1b9b4e8736681dd5697 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be F src/select.c ea48e891406ccdf748f3eb02893e056d134a0fea -F src/shell.c 1761e117dd58e2383a2d30319c49d0fca00f8bf0 +F src/shell.c 220564b70a2115e2157688f8faa6bb751ffe019a F src/sqlite.h.in 021a1f5c50e83060675d994a6014fd409e611d9e F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -1203,7 +1203,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1324d08d0c639378cf1b03bd6410db81947747ac -R fdaf7ebc782210d979a62294e31e9051 +P 4dc15fe066f079ff31c89a5e0242dd5b3c851d29 +R d85ccd3884f4a5cc5341a67dd8277838 U drh -Z e19e0e50f2717082ee6e33a1c9b88ce5 +Z edfba13e974f0e2f2be5cef97fba91ac diff --git a/manifest.uuid b/manifest.uuid index 2e186914d2..fc1bfdae69 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4dc15fe066f079ff31c89a5e0242dd5b3c851d29 \ No newline at end of file +b69f7dd1f35846c3bb9f4f160d50c4f03796f887 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index d45e59166e..ac42909582 100644 --- a/src/shell.c +++ b/src/shell.c @@ -3232,9 +3232,13 @@ static int do_meta_command(char *zLine, ShellState *p){ int szChng; void *pChng; if( azCmd[0][0]=='c' ){ - sqlite3session_changeset(pSession->p, &szChng, &pChng); + rc = sqlite3session_changeset(pSession->p, &szChng, &pChng); }else{ - sqlite3session_patchset(pSession->p, &szChng, &pChng); + rc = sqlite3session_patchset(pSession->p, &szChng, &pChng); + } + if( rc ){ + printf("Error: error code %d\n", rc); + rc = 0; } if( pChng && fwrite(pChng, szChng, 1, out)!=1 ){ From 3a432b0b475fa5ae550a1ab35279c2647344138c Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 19 Aug 2014 00:33:22 +0000 Subject: [PATCH 119/570] Disable the hook-7.5.2 tests when using sessions, since that are not correct in that case. FossilOrigin-Name: 6d5b9332e8d8bb572ac98b0f4e47e59ad12aac26 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/hook.test | 28 +++++++++++++++------------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/manifest b/manifest index 8526781f17..05bbcc7219 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sresponse\sto\serror\sconditions\sin\sthe\s".session"\sshell\scommand\sand\nin\sthe\s"changeset"\scommand-line\sprogram. -D 2014-08-19T00:26:17.830 +C Disable\sthe\shook-7.5.2\stests\swhen\susing\ssessions,\ssince\sthat\sare\snot\scorrect\nin\sthat\scase. +D 2014-08-19T00:33:22.234 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in d5ad373b7a23525414b8843b3084cf90c560d92f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -618,7 +618,7 @@ F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536 F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98 F test/hexlit.test f9ecde8145bfc2341573473256c74ae37a200497 -F test/hook.test 5429d34d6e59086175d8efbcd7e14d891375bdfb +F test/hook.test 76201cfcba801d02d13600700f26ab64313d1826 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 @@ -1203,7 +1203,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4dc15fe066f079ff31c89a5e0242dd5b3c851d29 -R d85ccd3884f4a5cc5341a67dd8277838 +P b69f7dd1f35846c3bb9f4f160d50c4f03796f887 +R 8c550f2382b76c35956caff857ef2faa U drh -Z edfba13e974f0e2f2be5cef97fba91ac +Z 2eb508c95168b21e7a389265ba7bb22f diff --git a/manifest.uuid b/manifest.uuid index fc1bfdae69..795c3d44c4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b69f7dd1f35846c3bb9f4f160d50c4f03796f887 \ No newline at end of file +6d5b9332e8d8bb572ac98b0f4e47e59ad12aac26 \ No newline at end of file diff --git a/test/hook.test b/test/hook.test index 28f0a66681..e6bb9ae2d0 100644 --- a/test/hook.test +++ b/test/hook.test @@ -705,19 +705,21 @@ do_execsql_test 7.5.2.0 { ALTER TABLE t8 ADD COLUMN c DEFAULT 'xxx'; } -# At time of writing, these two are broken. They demonstrate that the -# sqlite3_preupdate_old() method does not handle the case where ALTER TABLE -# has been used to add a column with a default value other than NULL. -# -do_preupdate_test 7.5.2.1 { - DELETE FROM t8 WHERE a = 'one' -} { - DELETE main t8 1 1 one two xxx -} -do_preupdate_test 7.5.2.2 { - UPDATE t8 SET b = 'five' -} { - UPDATE main t8 2 2 three four xxx three five xxx +ifcapable !session { + # At time of writing, these two are broken. They demonstrate that the + # sqlite3_preupdate_old() method does not handle the case where ALTER TABLE + # has been used to add a column with a default value other than NULL. + # + do_preupdate_test 7.5.2.1 { + DELETE FROM t8 WHERE a = 'one' + } { + DELETE main t8 1 1 one two xxx + } + do_preupdate_test 7.5.2.2 { + UPDATE t8 SET b = 'five' + } { + UPDATE main t8 2 2 three four xxx three five xxx + } } # This block of tests verifies that IPK values are correctly reported From ef7a6304961a4f323e3ceb10227777be7293c73a Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 23 Sep 2014 20:39:55 +0000 Subject: [PATCH 120/570] Begin adding 'streaming' APIs to sessions module. This is a work in progress. FossilOrigin-Name: 3c7d3d950bbf5f5ed3696ebc61c77ca48bafe2b5 --- ext/session/sqlite3session.c | 436 ++++++++++++++++++++++++++--------- ext/session/sqlite3session.h | 58 +++++ ext/session/test_session.c | 68 +++++- manifest | 20 +- manifest.uuid | 2 +- test/permutations.test | 8 + 6 files changed, 467 insertions(+), 125 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 4617e6a3c2..ec0387e775 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -12,6 +12,12 @@ typedef struct SessionTable SessionTable; typedef struct SessionChange SessionChange; typedef struct SessionBuffer SessionBuffer; +typedef struct SessionInput SessionInput; + +/* +** Minimum chunk size used by streaming versions of functions. +*/ +#define SESSIONS_STR_CHUNK_SIZE 1024 /* ** Session handle structure. @@ -29,14 +35,38 @@ struct sqlite3_session { SessionTable *pTable; /* List of attached tables */ }; +/* +** Instances of this structure are used to build strings or binary records. +*/ +struct SessionBuffer { + u8 *aBuf; /* Pointer to changeset buffer */ + int nBuf; /* Size of buffer aBuf */ + int nAlloc; /* Size of allocation containing aBuf */ +}; + +/* +** An object of this type is used internally as an abstraction for the +** input data read by changeset iterators. Input data may be supplied +** either as a single large buffer (sqlite3changeset_start()) or using +** a stream function (sqlite3changeset_start_str()). +*/ +struct SessionInput { + int iNext; /* Offset in aChangeset[] of next change */ + u8 *aChangeset; /* Pointer to buffer containing changeset */ + int nChangeset; /* Number of bytes in aChangeset */ + SessionBuffer buf; /* Current read buffer */ + int (*xInput)(void*, void*, int*); /* Input stream call (or NULL) */ + void *pIn; /* First argument to xInput */ + int bEof; /* Set to true after xInput finished */ +}; + /* ** Structure for changeset iterators. */ struct sqlite3_changeset_iter { - u8 *aChangeset; /* Pointer to buffer containing changeset */ - int nChangeset; /* Number of bytes in aChangeset */ + SessionInput in; /* Input buffer or stream */ + SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */ int bPatchset; /* True if this is a patchset */ - u8 *pNext; /* Pointer to next change within aChangeset */ int rc; /* Iterator error code */ sqlite3_stmt *pConflict; /* Points to conflicting row, if any */ char *zTab; /* Current table */ @@ -165,15 +195,6 @@ struct SessionChange { SessionChange *pNext; /* For hash-table collisions */ }; -/* -** Instances of this structure are used to build strings or binary records. -*/ -struct SessionBuffer { - u8 *aBuf; /* Pointer to changeset buffer */ - int nBuf; /* Size of buffer aBuf */ - int nAlloc; /* Size of allocation containing aBuf */ -}; - /* ** Write a varint with value iVal into the buffer at aBuf. Return the ** number of bytes written. @@ -1291,7 +1312,7 @@ static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ int nNew = p->nAlloc ? p->nAlloc : 128; do { nNew = nNew*2; - }while( nNew<(p->nAlloc+nByte) ); + }while( nNew<(p->nBuf+nByte) ); aNew = (u8 *)sqlite3_realloc(p->aBuf, nNew); if( 0==aNew ){ @@ -1776,6 +1797,8 @@ static void sessionAppendTableHdr( int sessionGenerateChangeset( sqlite3_session *pSession, /* Session object */ int bPatchset, /* True for patchset, false for changeset */ + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut, /* First argument for xOutput */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ){ @@ -1784,11 +1807,15 @@ int sessionGenerateChangeset( SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */ int rc; /* Return code */ + assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0 ) ); + /* Zero the output variables in case an error occurs. If this session ** object is already in the error state (sqlite3_session.rc != SQLITE_OK), ** this call will be a no-op. */ - *pnChangeset = 0; - *ppChangeset = 0; + if( xOutput==0 ){ + *pnChangeset = 0; + *ppChangeset = 0; + } if( pSession->rc ) return pSession->rc; rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0); @@ -1846,6 +1873,19 @@ int sessionGenerateChangeset( if( rc==SQLITE_OK ){ rc = sqlite3_reset(pSel); } + + /* If the buffer is now larger than SESSIONS_STR_CHUNK_SIZE, pass + ** its contents to the xOutput() callback. */ + if( xOutput + && rc==SQLITE_OK + && buf.nBuf>nNoop + && buf.nBuf>SESSIONS_STR_CHUNK_SIZE + ){ + rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf); + nNoop = -1; + buf.nBuf = 0; + } + } } @@ -1858,12 +1898,16 @@ int sessionGenerateChangeset( } if( rc==SQLITE_OK ){ - *pnChangeset = buf.nBuf; - *ppChangeset = buf.aBuf; - }else{ - sqlite3_free(buf.aBuf); + if( xOutput==0 ){ + *pnChangeset = buf.nBuf; + *ppChangeset = buf.aBuf; + buf.aBuf = 0; + }else if( buf.nBuf>0 ){ + rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf); + } } + sqlite3_free(buf.aBuf); sqlite3_exec(db, "RELEASE changeset", 0, 0, 0); sqlite3_mutex_leave(sqlite3_db_mutex(db)); return rc; @@ -1881,7 +1925,29 @@ int sqlite3session_changeset( int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ){ - return sessionGenerateChangeset(pSession, 0, pnChangeset, ppChangeset); + return sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset, ppChangeset); +} + +/* +** Streaming version of sqlite3session_changeset(). +*/ +int sqlite3session_changeset_str( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +){ + return sessionGenerateChangeset(pSession, 0, xOutput, pOut, 0, 0); +} + +/* +** Streaming version of sqlite3session_patchset(). +*/ +int sqlite3session_patchset_str( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +){ + return sessionGenerateChangeset(pSession, 1, xOutput, pOut, 0, 0); } /* @@ -1896,7 +1962,7 @@ int sqlite3session_patchset( int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ void **ppPatchset /* OUT: Buffer containing changeset */ ){ - return sessionGenerateChangeset(pSession, 1, pnPatchset, ppPatchset); + return sessionGenerateChangeset(pSession, 1, 0, 0, pnPatchset, ppPatchset); } /* @@ -1945,16 +2011,20 @@ int sqlite3session_isempty(sqlite3_session *pSession){ } /* -** Create an iterator used to iterate through the contents of a changeset. +** Do the work for either sqlite3changeset_start() or start_str(). */ -int sqlite3changeset_start( +int sessionChangesetStart( sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, int nChangeset, /* Size of buffer pChangeset in bytes */ void *pChangeset /* Pointer to buffer containing changeset */ ){ sqlite3_changeset_iter *pRet; /* Iterator to return */ int nByte; /* Number of bytes to allocate for iterator */ + assert( xInput==0 || (pChangeset==0 && nChangeset==0) ); + /* Zero the output variable in case an error occurs. */ *pp = 0; @@ -1963,15 +2033,80 @@ int sqlite3changeset_start( pRet = (sqlite3_changeset_iter *)sqlite3_malloc(nByte); if( !pRet ) return SQLITE_NOMEM; memset(pRet, 0, sizeof(sqlite3_changeset_iter)); - pRet->aChangeset = (u8 *)pChangeset; - pRet->nChangeset = nChangeset; - pRet->pNext = pRet->aChangeset; + pRet->in.aChangeset = (u8 *)pChangeset; + pRet->in.nChangeset = nChangeset; + pRet->in.xInput = xInput; + pRet->in.pIn = pIn; + pRet->in.iNext = 0; + pRet->in.bEof = (xInput ? 0 : 1); /* Populate the output variable and return success. */ *pp = pRet; return SQLITE_OK; } +/* +** Create an iterator used to iterate through the contents of a changeset. +*/ +int sqlite3changeset_start( + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ + int nChangeset, /* Size of buffer pChangeset in bytes */ + void *pChangeset /* Pointer to buffer containing changeset */ +){ + return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset); +} + +/* +** Streaming version of sqlite3changeset_start(). +*/ +int sqlite3changeset_start_str( + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn +){ + return sessionChangesetStart(pp, xInput, pIn, 0, 0); +} + +/* +** Ensure that there are at least nByte bytes available in the buffer. Or, +** if there are not nByte bytes remaining in the input, that all available +** data is in the buffer. +** +** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise. +*/ +static int sessionInputBuffer(SessionInput *pInput, int nByte){ + int rc = SQLITE_OK; + if( pInput->xInput && !pInput->bEof ){ + assert( 0 ); + } + return rc; +} + +/* +** When this function is called, *ppRec points to the start of a record +** that contains nCol values. This function advances the pointer *ppRec +** until it points to the byte immediately following that record. +*/ +static void sessionSkipRecord( + u8 **ppRec, /* IN/OUT: Record pointer */ + int nCol /* Number of values in record */ +){ + u8 *aRec = *ppRec; + int i; + for(i=0; iaChangeset[pIn->iNext++]; + } + assert( !apOut || apOut[i]==0 ); if( eType ){ if( apOut ){ apOut[i] = sqlite3ValueNew(0); - if( !apOut[i] ) return SQLITE_NOMEM; + if( !apOut[i] ) rc = SQLITE_NOMEM; } + } + if( rc==SQLITE_OK ){ + u8 *aVal = &pIn->aChangeset[pIn->iNext]; if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ int nByte; - aRec += sessionVarintGet(aRec, &nByte); - if( apOut ){ + pIn->iNext += sessionVarintGet(aVal, &nByte); + rc = sessionInputBuffer(pIn, nByte); + if( apOut && rc==SQLITE_OK ){ + u8 *aRec = &pIn->aChangeset[pIn->iNext]; u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); sqlite3ValueSetStr(apOut[i], nByte, (char *)aRec, enc, SQLITE_STATIC); } - aRec += nByte; + pIn->iNext += nByte; } if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ if( apOut ){ - sqlite3_int64 v = sessionGetI64(aRec); + sqlite3_int64 v = sessionGetI64(aVal); if( eType==SQLITE_INTEGER ){ sqlite3VdbeMemSetInt64(apOut[i], v); }else{ @@ -2036,13 +2180,83 @@ static int sessionReadRecord( sqlite3VdbeMemSetDouble(apOut[i], d); } } - aRec += 8; + pIn->iNext += 8; } } } - *paChange = aRec; - return SQLITE_OK; + return rc; +} + +/* +** The input pointer currently points to the second byte of a table-header. +** Specifically, to the following: +** +** + number of columns in table (varint) +** + array of PK flags (1 byte per column), +** + table name (nul terminated). +** +** This function ensures that all of the above is present in the input +** buffer (i.e. that it can be accessed without any calls to xInput()). +** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. +** The input pointer is not moved. +*/ +static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ + int rc = SQLITE_OK; + int nCol = 0; + int iIn = pIn->iNext; + + rc = sessionInputBuffer(pIn, 9); + if( rc==SQLITE_OK ){ + iIn += sessionVarintGet(&pIn->aChangeset[iIn], &nCol); + rc = sessionInputBuffer(pIn, nCol+100); + iIn += nCol; + } + while( rc==SQLITE_OK ){ + while( iInnChangeset && pIn->aChangeset[iIn] ) iIn++; + if( pIn->aChangeset[iIn]==0 ) break; + rc = sessionInputBuffer(pIn, 100); + } + if( pnByte ) *pnByte = (iIn+1 - pIn->iNext); + return rc; +} + +/* +** The input pointer currently points to the second byte of a table-header. +** Specifically, to the following: +** +** + number of columns in table (varint) +** + array of PK flags (1 byte per column), +** + table name (nul terminated). +*/ +static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){ + int rc; + int nCopy; + assert( p->rc==SQLITE_OK ); + + rc = sessionChangesetBufferTblhdr(&p->in, &nCopy); + if( rc==SQLITE_OK ){ + int nByte; + int nVarint; + nVarint = sessionVarintGet(&p->in.aChangeset[p->in.iNext], &p->nCol); + nCopy -= nVarint; + p->in.iNext += nVarint; + nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy; + p->tblhdr.nBuf = 0; + sessionBufferGrow(&p->tblhdr, nByte, &rc); + } + + if( rc==SQLITE_OK ){ + int iPK = sizeof(sqlite3_value*)*p->nCol*2; + memset(p->tblhdr.aBuf, 0, iPK); + memcpy(&p->tblhdr.aBuf[iPK], &p->in.aChangeset[p->in.iNext], nCopy); + p->in.iNext += nCopy; + } + + p->apValue = (sqlite3_value**)p->tblhdr.aBuf; + p->abPK = (u8*)&p->apValue[p->nCol*2]; + p->zTab = (char*)&p->abPK[p->nCol]; + return (p->rc = rc); } /* @@ -2066,9 +2280,10 @@ static int sessionChangesetNext( u8 **paRec, /* If non-NULL, store record pointer here */ int *pnRec /* If non-NULL, store size of record here */ ){ - u8 *aChange; int i; + u8 op; + assert( paRec==0 || p->in.xInput==0 ); /* fixme! */ assert( (paRec==0 && pnRec==0) || (paRec && pnRec) ); /* If the iterator is in the error-state, return immediately. */ @@ -2082,57 +2297,50 @@ static int sessionChangesetNext( memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2); } + /* Make sure the buffer contains at least 10 bytes of input data, or all + ** remaining data if there are less than 10 bytes available. This is + ** sufficient either for the 'T' or 'P' byte and the varint that follows + ** it, or for the two single byte values otherwise. */ + p->rc = sessionInputBuffer(&p->in, 2); + if( p->rc!=SQLITE_OK ) return p->rc; + /* If the iterator is already at the end of the changeset, return DONE. */ - if( p->pNext>=&p->aChangeset[p->nChangeset] ){ + if( p->in.iNext>=p->in.nChangeset ){ return SQLITE_DONE; } - aChange = p->pNext; - if( aChange[0]=='T' || aChange[0]=='P' ){ - int nByte; /* Bytes to allocate for apValue */ - p->bPatchset = (aChange[0]=='P'); - aChange++; - aChange += sessionVarintGet(aChange, &p->nCol); - p->abPK = (u8 *)aChange; - aChange += p->nCol; - p->zTab = (char *)aChange; - aChange += (sqlite3Strlen30((char *)aChange) + 1); - - if( paRec==0 ){ - sqlite3_free(p->apValue); - nByte = sizeof(sqlite3_value *) * p->nCol * 2; - p->apValue = (sqlite3_value **)sqlite3_malloc(nByte); - if( !p->apValue ){ - return (p->rc = SQLITE_NOMEM); - } - memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2); - } + op = p->in.aChangeset[p->in.iNext++]; + if( op=='T' || op=='P' ){ + p->bPatchset = (op=='P'); + if( sessionChangesetReadTblhdr(p) ) return p->rc; + if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc; + op = p->in.aChangeset[p->in.iNext++]; } - p->op = *(aChange++); - p->bIndirect = *(aChange++); + p->op = op; + p->bIndirect = p->in.aChangeset[p->in.iNext++]; if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){ return (p->rc = SQLITE_CORRUPT); } - if( paRec ){ *paRec = aChange; } + if( paRec ){ *paRec = &p->in.aChangeset[p->in.iNext]; } /* If this is an UPDATE or DELETE, read the old.* record. */ if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){ u8 *abPK = p->bPatchset ? p->abPK : 0; - p->rc = sessionReadRecord(&aChange, p->nCol, abPK, paRec?0:p->apValue); + p->rc = sessionReadRecord(&p->in, p->nCol, abPK, paRec?0:p->apValue); if( p->rc!=SQLITE_OK ) return p->rc; } /* If this is an INSERT or UPDATE, read the new.* record. */ if( p->op!=SQLITE_DELETE ){ sqlite3_value **apOut = (paRec ? 0 : &p->apValue[p->nCol]); - p->rc = sessionReadRecord(&aChange, p->nCol, 0, apOut); + p->rc = sessionReadRecord(&p->in, p->nCol, 0, apOut); if( p->rc!=SQLITE_OK ) return p->rc; } - if( pnRec ){ - *pnRec = (int)(aChange - *paRec); + if( pnRec ){ + *pnRec = (int)(&p->in.aChangeset[p->in.iNext] - *paRec); }else if( p->bPatchset && p->op==SQLITE_UPDATE ){ /* If this is an UPDATE that is part of a patchset, then all PK and ** modified fields are present in the new.* record. The old.* record @@ -2148,7 +2356,7 @@ static int sessionChangesetNext( } } } - p->pNext = aChange; + return SQLITE_ROW; } @@ -2321,7 +2529,7 @@ int sqlite3changeset_finalize(sqlite3_changeset_iter *p){ if( p->apValue ){ for(i=0; inCol*2; i++) sqlite3ValueFree(p->apValue[i]); } - sqlite3_free(p->apValue); + sqlite3_free(p->tblhdr.aBuf); sqlite3_free(p); return rc; } @@ -2339,52 +2547,71 @@ int sqlite3changeset_invert( u8 *aOut; u8 *aIn; int i; + SessionInput sInput; int nCol = 0; /* Number of cols in current table */ u8 *abPK = 0; /* PK array for current table */ sqlite3_value **apVal = 0; /* Space for values for UPDATE inversion */ + SessionBuffer sPK = {0, 0, 0}; /* PK array for current table */ /* Zero the output variables in case an error occurs. */ *ppInverted = 0; *pnInverted = 0; if( nChangeset==0 ) return SQLITE_OK; + /* Set up the input stream */ + memset(&sInput, 0, sizeof(SessionInput)); + sInput.nChangeset = nChangeset; + sInput.aChangeset = (u8*)pChangeset; + aOut = (u8 *)sqlite3_malloc(nChangeset); if( !aOut ) return SQLITE_NOMEM; aIn = (u8 *)pChangeset; i = 0; while( iop = SQLITE_INSERT; - if( bPatchset==0 ) sessionReadRecord(&a1, pTab->nCol, 0, 0); + if( bPatchset==0 ) sessionSkipRecord(&a1, pTab->nCol); sessionMergeRecord(&aCsr, pTab->nCol, aExist, a1); }else if( op1==SQLITE_DELETE ){ /* DELETE + INSERT */ assert( op2==SQLITE_INSERT ); @@ -3290,8 +3518,8 @@ static int sessionChangeMerge( u8 *a2 = aRec; assert( op1==SQLITE_UPDATE ); if( bPatchset==0 ){ - sessionReadRecord(&a1, pTab->nCol, 0, 0); - sessionReadRecord(&a2, pTab->nCol, 0, 0); + sessionSkipRecord(&a1, pTab->nCol); + sessionSkipRecord(&a2, pTab->nCol); } pNew->op = SQLITE_UPDATE; if( 0==sessionMergeUpdate(&aCsr, pTab, bPatchset, aRec, aExist,a1,a2) ){ @@ -3356,14 +3584,8 @@ static int sessionConcatChangeset( break; } - assert( pIter->apValue==0 ); sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect); - - assert( zNew>=(char *)pChangeset && zNew-nChangeset<((char *)pChangeset) ); - assert( !pTab || pTab->zName-nChangeset<(char *)pChangeset ); - assert( !pTab || zNew>=pTab->zName ); - - if( !pTab || zNew!=pTab->zName ){ + if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){ /* Search the list for a matching table */ int nNew = (int)strlen(zNew); u8 *abPK; @@ -3373,21 +3595,23 @@ static int sessionConcatChangeset( if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break; } if( !pTab ){ - pTab = sqlite3_malloc(sizeof(SessionTable)); + pTab = sqlite3_malloc(sizeof(SessionTable) + nCol + nNew+1); if( !pTab ){ rc = SQLITE_NOMEM; break; } memset(pTab, 0, sizeof(SessionTable)); pTab->pNext = *ppTabList; - pTab->abPK = abPK; pTab->nCol = nCol; + pTab->abPK = (u8*)&pTab[1]; + memcpy(pTab->abPK, abPK, nCol); + pTab->zName = (char*)&pTab->abPK[nCol]; + memcpy(pTab->zName, zNew, nNew+1); *ppTabList = pTab; }else if( pTab->nCol!=nCol || memcmp(pTab->abPK, abPK, nCol) ){ rc = SQLITE_SCHEMA; break; } - pTab->zName = (char *)zNew; } if( sessionGrowHash(bPatchset, pTab) ){ diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index ced984ecbe..4737bd953f 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -273,6 +273,31 @@ int sqlite3session_changeset( void **ppChangeset /* OUT: Buffer containing changeset */ ); + +/* +** This function is similar to sqlite3session_changeset(), except that instead +** of storing the output changeset in a buffer obtained from sqlite3_malloc() +** it invokes the supplied xOutput() callback zero or more times to stream the +** changeset to the application. This is useful in order to avoid large memory +** allocations when working with very large changesets. +** +** The first parameter passed to each call to the xOutput callback is a copy +** of the pOut parameter passed to this function. The following two parameters +** are a pointer to the buffer containing the next chunk of the output changeset +** and the size of that buffer in bytes. +** +** If the data is successfully processed by the xOutput callback, it should +** return SQLITE_OK. Or, if an error occurs, some other SQLite error code. In +** this case the sqlite3session_changeset_str() call is abandoned immediately +** and returns a copy of the xOutput return code. +*/ +int sqlite3session_changeset_str( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); + + /* ** CAPI3REF: Generate A Patchset From A Session Object ** @@ -302,6 +327,15 @@ int sqlite3session_patchset( void **ppPatchset /* OUT: Buffer containing changeset */ ); +/* +** Streaming version of sqlite3session_patchset(). +*/ +int sqlite3session_patchset_str( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); + /* ** CAPI3REF: Test if a changeset has recorded any changes. ** @@ -358,6 +392,30 @@ int sqlite3changeset_start( void *pChangeset /* Pointer to blob containing changeset */ ); + +/* +** This function is similar to sqlite3changeset_start(), except that instead +** of reading data from a single buffer, it requests it one chunk at a time +** from the application by invoking the supplied xInput() callback. The xInput() +** callback may be invoked at any time during the lifetime of the iterator. +** +** Each time the xInput callback is invoked, the first argument passed is a +** copy of the third parameter passed to this function. The second argument, +** pData, points to a buffer (*pnData) bytes in size. Assuming no error occurs +** the xInput method should copy up to (*pnData) bytes of data into the buffer +** and set (*pnData) to the actual number of bytes copied before returning +** SQLITE_OK. If the input is completely exhausted, (*pnData) should be set +** to zero to indicate this. Or, if an error occurs, an SQLite error code +** should be returned. In this case the iterator is put into an error state and +** all subsequent calls to iterator methods return a copy of the xInput error +** code. +*/ +int sqlite3changeset_start_str( + sqlite3_changeset_iter **pp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn +); + /* ** CAPI3REF: Advance A Changeset Iterator ** diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 38e4be1481..bf4bde39a4 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -14,6 +14,23 @@ struct TestSession { Tcl_Obj *pFilterScript; }; +#define SESSION_STREAM_TCL_VAR "sqlite3session_streams" + +/* +** Attempt to find the global variable zVar within interpreter interp +** and extract a boolean value from it. Return this value. +** +** If the named variable cannot be found, or if it cannot be interpreted +** as a boolean, return 0. +*/ +static int test_tcl_boolean(Tcl_Interp *interp, const char *zVar){ + Tcl_Obj *pObj; + int bVal = 0; + pObj = Tcl_ObjGetVar2(interp, Tcl_NewStringObj(zVar, -1), 0, TCL_GLOBAL_ONLY); + if( pObj ) Tcl_GetBooleanFromObj(0, pObj, &bVal); + return bVal; +} + static int test_session_error(Tcl_Interp *interp, int rc){ extern const char *sqlite3ErrName(int); Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); @@ -44,12 +61,38 @@ static int test_table_filter(void *pCtx, const char *zTbl){ return bRes; } +struct TestSessionsBlob { + void *p; + int n; +}; +typedef struct TestSessionsBlob TestSessionsBlob; + +static int testSessionsOutput( + void *pCtx, + const void *pData, + int nData +){ + TestSessionsBlob *pBlob = (TestSessionsBlob*)pCtx; + char *pNew; + + assert( nData>0 ); + pNew = (char*)sqlite3_realloc(pBlob->p, pBlob->n + nData); + if( pNew==0 ){ + return SQLITE_NOMEM; + } + pBlob->p = (void*)pNew; + memcpy(&pNew[pBlob->n], pData, nData); + pBlob->n += nData; + return SQLITE_OK; +} + /* ** Tclcmd: $session attach TABLE ** $session changeset ** $session delete ** $session enable BOOL ** $session indirect INTEGER +** $session patchset ** $session table_filter SCRIPT */ static int test_session_cmd( @@ -105,17 +148,26 @@ static int test_session_cmd( case 7: /* patchset */ case 1: { /* changeset */ - int nChange; - void *pChange; - if( iSub==7 ){ - rc = sqlite3session_patchset(pSession, &nChange, &pChange); + TestSessionsBlob o = {0, 0}; + if( test_tcl_boolean(interp, SESSION_STREAM_TCL_VAR) ){ + void *pCtx = (void*)&o; + if( iSub==7 ){ + rc = sqlite3session_patchset_str(pSession, testSessionsOutput, pCtx); + }else{ + rc = sqlite3session_changeset_str(pSession, testSessionsOutput, pCtx); + } }else{ - rc = sqlite3session_changeset(pSession, &nChange, &pChange); + if( iSub==7 ){ + rc = sqlite3session_patchset(pSession, &o.n, &o.p); + }else{ + rc = sqlite3session_changeset(pSession, &o.n, &o.p); + } } if( rc==SQLITE_OK ){ - Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pChange, nChange)); - sqlite3_free(pChange); - }else{ + Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(o.p, o.n)); + } + sqlite3_free(o.p); + if( rc!=SQLITE_OK ){ return test_session_error(interp, rc); } break; diff --git a/manifest b/manifest index ffe55892fc..753640048a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sall\srecent\strunk\schanges\sinto\sthe\ssessions\sbranch. -D 2014-09-21T22:49:20.257 +C Begin\sadding\s'streaming'\sAPIs\sto\ssessions\smodule.\sThis\sis\sa\swork\sin\sprogress. +D 2014-09-23T20:39:55.903 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -158,9 +158,9 @@ F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 F ext/session/sessionB.test 276267cd7fc37c2e2dd03f1e2ed9ada336a8bdb4 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test e7965159a73d385c1a4af12d82c3a039ebdd71a6 -F ext/session/sqlite3session.c 4c7689bd8286147f7d9bf5d4b6ca5e7e7ee588ab -F ext/session/sqlite3session.h 66c14a2f6193c47773770307636e88c43db6f839 -F ext/session/test_session.c a252fb669d3a1b3552ee7b87fe610debc0afeb7b +F ext/session/sqlite3session.c ead909b1b0976aa6d08dcb7b487a902e358f7e4c +F ext/session/sqlite3session.h d074a929d368b438d32c15af8f8fe2afa80afe3f +F ext/session/test_session.c e39119c8554fe1b0925a038423ca137ddf6f6bd9 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e @@ -776,7 +776,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0 F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54 -F test/permutations.test 89f594fdba922586d46c3e0a7ab4990b5a7f8da7 +F test/permutations.test b8ca6c9ecec6f360485a8cb61ef1b8734b31797b F test/pragma.test 19d0241a007bcdd77fc2606ec60fc60357e7fc8b F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 @@ -1216,7 +1216,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c2885c6bb24cc55178467e57e77bf71df58b3b13 d5880abd63c83c88e135257373afa0a3fd88297e -R 9d7f30c83131a55806d3c1dd053387df -U drh -Z c53e54ee2e290caf615c330d235d140a +P 6406b77f2c447751a2fbb16f01c61cdcfd6af59e +R 67d8884fcab24bc7ffc4823662b37f4a +U dan +Z 2bbe541c87040990ceab83529c1e7e80 diff --git a/manifest.uuid b/manifest.uuid index a34006bb05..424c64b57a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6406b77f2c447751a2fbb16f01c61cdcfd6af59e \ No newline at end of file +3c7d3d950bbf5f5ed3696ebc61c77ca48bafe2b5 \ No newline at end of file diff --git a/test/permutations.test b/test/permutations.test index 7bea39eb7a..44f571793c 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -938,6 +938,14 @@ test_suite "session_eec" -description { sqlite3_extended_result_codes $::dbhandle 1 } +test_suite "session_str" -description { + All session module related tests using the streaming APIs. +} -files [ + glob -nocomplain $::testdir/../ext/session/*.test +] -dbconfig { + set ::sqlite3session_streams 1 +} + test_suite "no_optimization" -description { Run test scripts with optimizations disabled using the sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS) interface. From 4757c65866180484e56b35d8d8c21748fef149b6 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 24 Sep 2014 17:13:20 +0000 Subject: [PATCH 121/570] Add streaming version of sqlite3changeset_apply(). Tests and fixes for the same and sqlite3changeset_start_str(). FossilOrigin-Name: b917fc146876f764442de08d5ec36e5b4cf5ab52 --- ext/session/sqlite3session.c | 197 ++++++++++++++++++++++++++--------- ext/session/sqlite3session.h | 24 +++++ ext/session/test_session.c | 89 +++++++++++++--- manifest | 18 ++-- manifest.uuid | 2 +- test/session.test | 1 + 6 files changed, 256 insertions(+), 75 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index ec0387e775..ceea8268c6 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -17,7 +17,11 @@ typedef struct SessionInput SessionInput; /* ** Minimum chunk size used by streaming versions of functions. */ +#ifdef SQLITE_TEST +#define SESSIONS_STR_CHUNK_SIZE 1 +#else #define SESSIONS_STR_CHUNK_SIZE 1024 +#endif /* ** Session handle structure. @@ -51,9 +55,10 @@ struct SessionBuffer { ** a stream function (sqlite3changeset_start_str()). */ struct SessionInput { - int iNext; /* Offset in aChangeset[] of next change */ - u8 *aChangeset; /* Pointer to buffer containing changeset */ - int nChangeset; /* Number of bytes in aChangeset */ + int iNext; /* Offset in aData[] of next change */ + u8 *aData; /* Pointer to buffer containing changeset */ + int nData; /* Number of bytes in aData */ + SessionBuffer buf; /* Current read buffer */ int (*xInput)(void*, void*, int*); /* Input stream call (or NULL) */ void *pIn; /* First argument to xInput */ @@ -2033,8 +2038,8 @@ int sessionChangesetStart( pRet = (sqlite3_changeset_iter *)sqlite3_malloc(nByte); if( !pRet ) return SQLITE_NOMEM; memset(pRet, 0, sizeof(sqlite3_changeset_iter)); - pRet->in.aChangeset = (u8 *)pChangeset; - pRet->in.nChangeset = nChangeset; + pRet->in.aData = (u8 *)pChangeset; + pRet->in.nData = nChangeset; pRet->in.xInput = xInput; pRet->in.pIn = pIn; pRet->in.iNext = 0; @@ -2074,10 +2079,31 @@ int sqlite3changeset_start_str( ** ** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise. */ -static int sessionInputBuffer(SessionInput *pInput, int nByte){ +static int sessionInputBuffer(SessionInput *pIn, int nByte){ int rc = SQLITE_OK; - if( pInput->xInput && !pInput->bEof ){ - assert( 0 ); + if( pIn->xInput ){ + while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){ + int nNew = SESSIONS_STR_CHUNK_SIZE; + + if( pIn->iNext>=SESSIONS_STR_CHUNK_SIZE ){ + int nMove = pIn->buf.nBuf - pIn->iNext; + memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove); + pIn->buf.nBuf -= pIn->iNext; + pIn->iNext = 0; + } + + if( SQLITE_OK==sessionBufferGrow(&pIn->buf, nNew, &rc) ){ + rc = pIn->xInput(pIn->pIn, &pIn->buf.aBuf[pIn->buf.nBuf], &nNew); + if( nNew==0 ){ + pIn->bEof = 1; + }else{ + pIn->buf.nBuf += nNew; + } + } + + pIn->aData = pIn->buf.aBuf; + pIn->nData = pIn->buf.nBuf; + } } return rc; } @@ -2107,6 +2133,25 @@ static void sessionSkipRecord( *ppRec = aRec; } +/* +** This function sets the value of the sqlite3_value object passed as the +** first argument to a copy of the string or blob held in the aData[] +** buffer. SQLITE_OK is returned if successful, or SQLITE_NOMEM if an OOM +** error occurs. +*/ +static int sessionValueSetStr( + sqlite3_value *pVal, /* Set the value of this object */ + u8 *aData, /* Buffer containing string or blob data */ + int nData, /* Size of buffer aData[] in bytes */ + u8 enc /* String encoding (0 for blobs) */ +){ + u8 *aCopy = sqlite3_malloc(nData); + if( aCopy==0 ) return SQLITE_NOMEM; + memcpy(aCopy, aData, nData); + sqlite3ValueSetStr(pVal, nData, (char*)aCopy, enc, sqlite3_free); + return SQLITE_OK; +} + /* ** Deserialize a single record from a buffer in memory. See "RECORD FORMAT" ** for details. @@ -2145,7 +2190,7 @@ static int sessionReadRecord( if( abPK && abPK[i]==0 ) continue; rc = sessionInputBuffer(pIn, 9); if( rc==SQLITE_OK ){ - eType = pIn->aChangeset[pIn->iNext++]; + eType = pIn->aData[pIn->iNext++]; } assert( !apOut || apOut[i]==0 ); @@ -2157,15 +2202,14 @@ static int sessionReadRecord( } if( rc==SQLITE_OK ){ - u8 *aVal = &pIn->aChangeset[pIn->iNext]; + u8 *aVal = &pIn->aData[pIn->iNext]; if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ int nByte; pIn->iNext += sessionVarintGet(aVal, &nByte); rc = sessionInputBuffer(pIn, nByte); if( apOut && rc==SQLITE_OK ){ - u8 *aRec = &pIn->aChangeset[pIn->iNext]; u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); - sqlite3ValueSetStr(apOut[i], nByte, (char *)aRec, enc, SQLITE_STATIC); + rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc); } pIn->iNext += nByte; } @@ -2204,20 +2248,23 @@ static int sessionReadRecord( static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ int rc = SQLITE_OK; int nCol = 0; - int iIn = pIn->iNext; + int nRead = 0; rc = sessionInputBuffer(pIn, 9); if( rc==SQLITE_OK ){ - iIn += sessionVarintGet(&pIn->aChangeset[iIn], &nCol); - rc = sessionInputBuffer(pIn, nCol+100); - iIn += nCol; + nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol); + rc = sessionInputBuffer(pIn, nRead+nCol+100); + nRead += nCol; } + while( rc==SQLITE_OK ){ - while( iInnChangeset && pIn->aChangeset[iIn] ) iIn++; - if( pIn->aChangeset[iIn]==0 ) break; - rc = sessionInputBuffer(pIn, 100); + while( (pIn->iNext + nRead)nData && pIn->aData[pIn->iNext + nRead] ){ + nRead++; + } + if( pIn->aData[pIn->iNext + nRead]==0 ) break; + rc = sessionInputBuffer(pIn, nRead + 100); } - if( pnByte ) *pnByte = (iIn+1 - pIn->iNext); + if( pnByte ) *pnByte = nRead+1; return rc; } @@ -2238,7 +2285,7 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){ if( rc==SQLITE_OK ){ int nByte; int nVarint; - nVarint = sessionVarintGet(&p->in.aChangeset[p->in.iNext], &p->nCol); + nVarint = sessionVarintGet(&p->in.aData[p->in.iNext], &p->nCol); nCopy -= nVarint; p->in.iNext += nVarint; nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy; @@ -2249,7 +2296,7 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){ if( rc==SQLITE_OK ){ int iPK = sizeof(sqlite3_value*)*p->nCol*2; memset(p->tblhdr.aBuf, 0, iPK); - memcpy(&p->tblhdr.aBuf[iPK], &p->in.aChangeset[p->in.iNext], nCopy); + memcpy(&p->tblhdr.aBuf[iPK], &p->in.aData[p->in.iNext], nCopy); p->in.iNext += nCopy; } @@ -2305,25 +2352,25 @@ static int sessionChangesetNext( if( p->rc!=SQLITE_OK ) return p->rc; /* If the iterator is already at the end of the changeset, return DONE. */ - if( p->in.iNext>=p->in.nChangeset ){ + if( p->in.iNext>=p->in.nData ){ return SQLITE_DONE; } - op = p->in.aChangeset[p->in.iNext++]; + op = p->in.aData[p->in.iNext++]; if( op=='T' || op=='P' ){ p->bPatchset = (op=='P'); if( sessionChangesetReadTblhdr(p) ) return p->rc; if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc; - op = p->in.aChangeset[p->in.iNext++]; + op = p->in.aData[p->in.iNext++]; } p->op = op; - p->bIndirect = p->in.aChangeset[p->in.iNext++]; + p->bIndirect = p->in.aData[p->in.iNext++]; if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){ - return (p->rc = SQLITE_CORRUPT); + return (p->rc = SQLITE_CORRUPT_BKPT); } - if( paRec ){ *paRec = &p->in.aChangeset[p->in.iNext]; } + if( paRec ){ *paRec = &p->in.aData[p->in.iNext]; } /* If this is an UPDATE or DELETE, read the old.* record. */ if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){ @@ -2340,7 +2387,7 @@ static int sessionChangesetNext( } if( pnRec ){ - *pnRec = (int)(&p->in.aChangeset[p->in.iNext] - *paRec); + *pnRec = (int)(&p->in.aData[p->in.iNext] - *paRec); }else if( p->bPatchset && p->op==SQLITE_UPDATE ){ /* If this is an UPDATE that is part of a patchset, then all PK and ** modified fields are present in the new.* record. The old.* record @@ -2530,6 +2577,7 @@ int sqlite3changeset_finalize(sqlite3_changeset_iter *p){ for(i=0; inCol*2; i++) sqlite3ValueFree(p->apValue[i]); } sqlite3_free(p->tblhdr.aBuf); + sqlite3_free(p->in.buf.aBuf); sqlite3_free(p); return rc; } @@ -2560,8 +2608,8 @@ int sqlite3changeset_invert( /* Set up the input stream */ memset(&sInput, 0, sizeof(SessionInput)); - sInput.nChangeset = nChangeset; - sInput.aChangeset = (u8*)pChangeset; + sInput.nData = nChangeset; + sInput.aData = (u8*)pChangeset; aOut = (u8 *)sqlite3_malloc(nChangeset); if( !aOut ) return SQLITE_NOMEM; @@ -2571,7 +2619,7 @@ int sqlite3changeset_invert( while( inData - p->iData; /* Bytes of data available */ + int nRet = p->nStream; /* Bytes actually returned */ + + if( nRet>nReq ) nRet = nReq; + if( nRet>nRem ) nRet = nRem; + + assert( nRet>=0 ); + if( nRet>0 ){ + memcpy(pData, &p->aData[p->iData], nRet); + p->iData += nRet; + } + + *pnData = nRet; + return SQLITE_OK; +} + + /* ** sqlite3changeset_apply DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT? */ @@ -559,6 +591,10 @@ static int test_sqlite3changeset_apply( void *pChangeset; /* Buffer containing changeset */ int nChangeset; /* Size of buffer aChangeset in bytes */ TestConflictHandler ctx; + TestStreamInput sStr; + + memset(&sStr, 0, sizeof(sStr)); + sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR); if( objc!=4 && objc!=5 ){ Tcl_WrongNumArgs(interp, 1, objv, @@ -576,9 +612,18 @@ static int test_sqlite3changeset_apply( ctx.pFilterScript = objc==5 ? objv[4] : 0; ctx.interp = interp; - rc = sqlite3changeset_apply(db, nChangeset, pChangeset, - (objc==5) ? test_filter_handler : 0, test_conflict_handler, (void *)&ctx - ); + if( sStr.nStream==0 ){ + rc = sqlite3changeset_apply(db, nChangeset, pChangeset, + (objc==5) ? test_filter_handler : 0, test_conflict_handler, (void *)&ctx + ); + }else{ + sStr.aData = (unsigned char*)pChangeset; + sStr.nData = nChangeset; + rc = sqlite3changeset_apply_str(db, testStreamInput, (void*)&sStr, + (objc==5) ? test_filter_handler : 0, test_conflict_handler, (void *)&ctx + ); + } + if( rc!=SQLITE_OK ){ return test_session_error(interp, rc); } @@ -632,7 +677,7 @@ static int test_sqlite3changeset_invert( ){ int rc; /* Return code from changeset_invert() */ void *aChangeset; /* Input changeset */ - int nChangeSet; /* Size of buffer aChangeset in bytes */ + int nChangeset; /* Size of buffer aChangeset in bytes */ void *aOut; /* Output changeset */ int nOut; /* Size of buffer aOut in bytes */ @@ -640,9 +685,9 @@ static int test_sqlite3changeset_invert( Tcl_WrongNumArgs(interp, 1, objv, "CHANGESET"); return TCL_ERROR; } - aChangeset = (void *)Tcl_GetByteArrayFromObj(objv[1], &nChangeSet); + aChangeset = (void *)Tcl_GetByteArrayFromObj(objv[1], &nChangeset); - rc = sqlite3changeset_invert(nChangeSet, aChangeset, &nOut, &aOut); + rc = sqlite3changeset_invert(nChangeset, aChangeset, &nOut, &aOut); if( rc!=SQLITE_OK ){ return test_session_error(interp, rc); } @@ -693,8 +738,8 @@ static int test_sqlite3session_foreach( int objc, Tcl_Obj *CONST objv[] ){ - void *pChangeSet; - int nChangeSet; + void *pChangeset; + int nChangeset; sqlite3_changeset_iter *pIter; int rc; Tcl_Obj *pVarname; @@ -702,6 +747,9 @@ static int test_sqlite3session_foreach( Tcl_Obj *pScript; int isCheckNext = 0; + TestStreamInput sStr; + memset(&sStr, 0, sizeof(sStr)); + if( objc>1 ){ char *zOpt = Tcl_GetString(objv[1]); isCheckNext = (strcmp(zOpt, "-next")==0); @@ -715,8 +763,15 @@ static int test_sqlite3session_foreach( pCS = objv[2+isCheckNext]; pScript = objv[3+isCheckNext]; - pChangeSet = (void *)Tcl_GetByteArrayFromObj(pCS, &nChangeSet); - rc = sqlite3changeset_start(&pIter, nChangeSet, pChangeSet); + pChangeset = (void *)Tcl_GetByteArrayFromObj(pCS, &nChangeset); + sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR); + if( sStr.nStream==0 ){ + rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + }else{ + sStr.aData = (unsigned char*)pChangeset; + sStr.nData = nChangeset; + rc = sqlite3changeset_start_str(&pIter, testStreamInput, (void*)&sStr); + } if( rc!=SQLITE_OK ){ return test_session_error(interp, rc); } diff --git a/manifest b/manifest index 753640048a..e7faacba4f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Begin\sadding\s'streaming'\sAPIs\sto\ssessions\smodule.\sThis\sis\sa\swork\sin\sprogress. -D 2014-09-23T20:39:55.903 +C Add\sstreaming\sversion\sof\ssqlite3changeset_apply().\sTests\sand\sfixes\sfor\sthe\ssame\sand\ssqlite3changeset_start_str(). +D 2014-09-24T17:13:20.331 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -158,9 +158,9 @@ F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 F ext/session/sessionB.test 276267cd7fc37c2e2dd03f1e2ed9ada336a8bdb4 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test e7965159a73d385c1a4af12d82c3a039ebdd71a6 -F ext/session/sqlite3session.c ead909b1b0976aa6d08dcb7b487a902e358f7e4c -F ext/session/sqlite3session.h d074a929d368b438d32c15af8f8fe2afa80afe3f -F ext/session/test_session.c e39119c8554fe1b0925a038423ca137ddf6f6bd9 +F ext/session/sqlite3session.c 1c653844900de41e175f77f22fe1af7abb05e798 +F ext/session/sqlite3session.h 7e7a31ad1992f6678a20654c9751dacd10384292 +F ext/session/test_session.c 77f1e7a269daeb60f82441ff859c812d686ef79d F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e @@ -832,7 +832,7 @@ F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394 F test/selectE.test fc02a1eb04c8eb537091482644b7d778ae8759b7 F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3 F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118 -F test/session.test 082dea459efc76e2a527b8ee9ff74d76e63ea7b6 +F test/session.test 35f9c76809c26bee45d86891c7620b692ef9b8a8 F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746 F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879 F test/shared3.test fcd65cb11d189eff5f5c85cc4fad246fb0933108 @@ -1216,7 +1216,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 6406b77f2c447751a2fbb16f01c61cdcfd6af59e -R 67d8884fcab24bc7ffc4823662b37f4a +P 3c7d3d950bbf5f5ed3696ebc61c77ca48bafe2b5 +R bba1026624291c9ce371985c2bc9cae0 U dan -Z 2bbe541c87040990ceab83529c1e7e80 +Z 40a11f75418a19b3b02aba54325bf64c diff --git a/manifest.uuid b/manifest.uuid index 424c64b57a..4b63e2e10a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3c7d3d950bbf5f5ed3696ebc61c77ca48bafe2b5 \ No newline at end of file +b917fc146876f764442de08d5ec36e5b4cf5ab52 \ No newline at end of file diff --git a/test/session.test b/test/session.test index 85ac056cdd..da04ac45c5 100644 --- a/test/session.test +++ b/test/session.test @@ -16,6 +16,7 @@ ifcapable session { # again with it clear. run_test_suite session_eec run_test_suite session + run_test_suite session_str } finish_test From fa122adac1d0b19fef73945db4f061225bf922f6 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 25 Sep 2014 14:54:20 +0000 Subject: [PATCH 122/570] Add streaming version of sqlite3changeset_invert() to sessions module. FossilOrigin-Name: 8ded6a46794c7bff1c8b790c662ba7e92f576380 --- ext/session/sqlite3session.c | 220 +++++++++++++++++++++++++---------- ext/session/sqlite3session.h | 10 ++ ext/session/test_session.c | 31 +++-- manifest | 16 +-- manifest.uuid | 2 +- 5 files changed, 198 insertions(+), 81 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index ceea8268c6..b62f039943 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -334,10 +334,11 @@ static int sessionSerializeValue( if( aBuf ) aBuf[0] = '\0'; } - *pnWrite += nByte; + if( pnWrite ) *pnWrite += nByte; return SQLITE_OK; } + /* ** This macro is used to calculate hash key values for data structures. In ** order to use this macro, the entire data structure must be represented @@ -1330,6 +1331,29 @@ static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ return (*pRc!=SQLITE_OK); } +/* +** Append the value passed as the second argument to the buffer passed +** as the first. +** +** This function is a no-op if *pRc is non-zero when it is called. +** Otherwise, if an error occurs, *pRc is set to an SQLite error code +** before returning. +*/ +static void sessionAppendValue(SessionBuffer *p, sqlite3_value *pVal, int *pRc){ + int rc = *pRc; + if( rc==SQLITE_OK ){ + int nByte = 0; + sessionSerializeValue(0, pVal, &nByte); + sessionBufferGrow(p, nByte, &rc); + if( rc==SQLITE_OK ){ + rc = sessionSerializeValue(&p->aBuf[p->nBuf], pVal, 0); + p->nBuf += nByte; + }else{ + *pRc = rc; + } + } +} + /* ** This function is a no-op if *pRc is other than SQLITE_OK when it is ** called. Otherwise, append a single byte to the buffer. @@ -2268,6 +2292,38 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ return rc; } +/* +** The input pointer currently points to the first byte of the first field +** of a record consisting of nCol columns. This function ensures the entire +** record is buffered. +*/ +static int sessionChangesetBufferRecord( + SessionInput *pIn, + int nCol, + int *pnByte +){ + int rc = SQLITE_OK; + int nByte = 0; + int i; + for(i=0; rc==SQLITE_OK && iaData[pIn->iNext + nByte++]; + if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ + int n; + nByte += sessionVarintGet(&pIn->aData[pIn->iNext+nByte], &n); + nByte += n; + rc = sessionInputBuffer(pIn, nByte); + }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + nByte += 8; + } + } + } + *pnByte = nByte; + return rc; +} + /* ** The input pointer currently points to the second byte of a table-header. ** Specifically, to the following: @@ -2582,44 +2638,37 @@ int sqlite3changeset_finalize(sqlite3_changeset_iter *p){ return rc; } -/* -** Invert a changeset object. -*/ -int sqlite3changeset_invert( - int nChangeset, /* Number of bytes in input */ - const void *pChangeset, /* Input changeset */ +static int sessionChangesetInvert( + SessionInput *pInput, /* Input changeset */ + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut, int *pnInverted, /* OUT: Number of bytes in output changeset */ void **ppInverted /* OUT: Inverse of pChangeset */ ){ int rc = SQLITE_OK; /* Return value */ - u8 *aOut; - u8 *aIn; - int i; - SessionInput sInput; + SessionBuffer sOut; /* Output buffer */ int nCol = 0; /* Number of cols in current table */ u8 *abPK = 0; /* PK array for current table */ sqlite3_value **apVal = 0; /* Space for values for UPDATE inversion */ SessionBuffer sPK = {0, 0, 0}; /* PK array for current table */ + /* Initialize the output buffer */ + memset(&sOut, 0, sizeof(SessionBuffer)); + /* Zero the output variables in case an error occurs. */ - *ppInverted = 0; - *pnInverted = 0; - if( nChangeset==0 ) return SQLITE_OK; + if( ppInverted ){ + *ppInverted = 0; + *pnInverted = 0; + } - /* Set up the input stream */ - memset(&sInput, 0, sizeof(SessionInput)); - sInput.nData = nChangeset; - sInput.aData = (u8*)pChangeset; - - aOut = (u8 *)sqlite3_malloc(nChangeset); - if( !aOut ) return SQLITE_NOMEM; - aIn = (u8 *)pChangeset; - - i = 0; - while( iiNext>=pInput->nData ) break; + eType = pInput->aData[pInput->iNext]; + switch( eType ){ case 'T': { /* A 'table' record consists of: @@ -2630,19 +2679,19 @@ int sqlite3changeset_invert( ** * A nul-terminated table name. */ int nByte; - int nVarint; - int iNext = sInput.iNext; - sInput.iNext++; - if( (rc = sessionChangesetBufferTblhdr(&sInput, &nByte)) ){ + int nVar; + pInput->iNext++; + if( (rc = sessionChangesetBufferTblhdr(pInput, &nByte)) ){ goto finished_invert; } - nVarint = sessionVarintGet(&sInput.aData[iNext+1], &nCol); + nVar = sessionVarintGet(&pInput->aData[pInput->iNext], &nCol); sPK.nBuf = 0; - sessionAppendBlob(&sPK, &sInput.aData[iNext+1+nVarint], nCol, &rc); + sessionAppendBlob(&sPK, &pInput->aData[pInput->iNext+nVar], nCol, &rc); + sessionAppendByte(&sOut, eType, &rc); + sessionAppendBlob(&sOut, &pInput->aData[pInput->iNext], nByte, &rc); if( rc ) goto finished_invert; - sInput.iNext += nByte; - memcpy(&aOut[i], &sInput.aData[iNext], nByte+1); - i += nByte+1; + + pInput->iNext += nByte; sqlite3_free(apVal); apVal = 0; abPK = sPK.aBuf; @@ -2651,22 +2700,22 @@ int sqlite3changeset_invert( case SQLITE_INSERT: case SQLITE_DELETE: { - int iStart; int nByte; - sInput.iNext += 2; - iStart = sInput.iNext; - sessionReadRecord(&sInput, nCol, 0, 0); - aOut[i] = (eType==SQLITE_DELETE ? SQLITE_INSERT : SQLITE_DELETE); - aOut[i+1] = aIn[i+1]; /* indirect-flag */ - nByte = sInput.iNext - iStart; - memcpy(&aOut[i+2], &sInput.aData[iStart], nByte); - i += 2 + nByte; + int bIndirect = pInput->aData[pInput->iNext+1]; + int eType2 = (eType==SQLITE_DELETE ? SQLITE_INSERT : SQLITE_DELETE); + pInput->iNext += 2; + assert( rc==SQLITE_OK ); + rc = sessionChangesetBufferRecord(pInput, nCol, &nByte); + sessionAppendByte(&sOut, eType2, &rc); + sessionAppendByte(&sOut, bIndirect, &rc); + sessionAppendBlob(&sOut, &pInput->aData[pInput->iNext], nByte, &rc); + pInput->iNext += nByte; + if( rc ) goto finished_invert; break; } case SQLITE_UPDATE: { int iCol; - int nWrite = 0; if( 0==apVal ){ apVal = (sqlite3_value **)sqlite3_malloc(sizeof(apVal[0])*nCol*2); @@ -2678,15 +2727,14 @@ int sqlite3changeset_invert( } /* Write the header for the new UPDATE change. Same as the original. */ - aOut[i] = SQLITE_UPDATE; - aOut[i+1] = sInput.aData[sInput.iNext+1]; - nWrite = 2; + sessionAppendByte(&sOut, eType, &rc); + sessionAppendByte(&sOut, pInput->aData[pInput->iNext+1], &rc); /* Read the old.* and new.* records for the update change. */ - sInput.iNext += 2; - rc = sessionReadRecord(&sInput, nCol, 0, &apVal[0]); + pInput->iNext += 2; + rc = sessionReadRecord(pInput, nCol, 0, &apVal[0]); if( rc==SQLITE_OK ){ - rc = sessionReadRecord(&sInput, nCol, 0, &apVal[nCol]); + rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol]); } /* Write the new old.* record. Consists of the PK columns from the @@ -2694,7 +2742,7 @@ int sqlite3changeset_invert( ** new.* record. */ for(iCol=0; rc==SQLITE_OK && iCol=SESSIONS_STR_CHUNK_SIZE ){ + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); + sOut.nBuf = 0; + if( rc!=SQLITE_OK ) goto finished_invert; + } } assert( rc==SQLITE_OK ); - *pnInverted = nChangeset; - *ppInverted = (void *)aOut; + if( pnInverted ){ + *pnInverted = sOut.nBuf; + *ppInverted = sOut.aBuf; + sOut.aBuf = 0; + }else if( sOut.nBuf>0 ){ + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); + } finished_invert: - if( rc!=SQLITE_OK ){ - sqlite3_free(aOut); - } + sqlite3_free(sOut.aBuf); sqlite3_free(apVal); sqlite3_free(sPK.aBuf); return rc; } + +/* +** Invert a changeset object. +*/ +int sqlite3changeset_invert( + int nChangeset, /* Number of bytes in input */ + const void *pChangeset, /* Input changeset */ + int *pnInverted, /* OUT: Number of bytes in output changeset */ + void **ppInverted /* OUT: Inverse of pChangeset */ +){ + SessionInput sInput; + + /* Set up the input stream */ + memset(&sInput, 0, sizeof(SessionInput)); + sInput.nData = nChangeset; + sInput.aData = (u8*)pChangeset; + + return sessionChangesetInvert(&sInput, 0, 0, pnInverted, ppInverted); +} + +/* +** Streaming version of sqlite3changeset_invert(). +*/ +int sqlite3changeset_invert_str( + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +){ + SessionInput sInput; + int rc; + + /* Set up the input stream */ + memset(&sInput, 0, sizeof(SessionInput)); + sInput.xInput = xInput; + sInput.pIn = pIn; + + rc = sessionChangesetInvert(&sInput, xOutput, pOut, 0, 0); + sqlite3_free(sInput.buf.aBuf); + return rc; +} + typedef struct SessionApplyCtx SessionApplyCtx; struct SessionApplyCtx { sqlite3 *db; diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 28623391d4..ce91cb68f1 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -670,6 +670,16 @@ int sqlite3changeset_invert( int *pnOut, void **ppOut /* OUT: Inverse of input */ ); +/* +** Streaming version of sqlite3changeset_invert(). +*/ +int sqlite3changeset_invert_str( + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); + /* ** CAPI3REF: Concatenate Two Changeset Objects ** diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 444519c98b..edd508d0e3 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -676,24 +676,33 @@ static int test_sqlite3changeset_invert( Tcl_Obj *CONST objv[] ){ int rc; /* Return code from changeset_invert() */ - void *aChangeset; /* Input changeset */ - int nChangeset; /* Size of buffer aChangeset in bytes */ - void *aOut; /* Output changeset */ - int nOut; /* Size of buffer aOut in bytes */ + TestStreamInput sIn; /* Input stream */ + TestSessionsBlob sOut; /* Output blob */ if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "CHANGESET"); return TCL_ERROR; } - aChangeset = (void *)Tcl_GetByteArrayFromObj(objv[1], &nChangeset); - rc = sqlite3changeset_invert(nChangeset, aChangeset, &nOut, &aOut); - if( rc!=SQLITE_OK ){ - return test_session_error(interp, rc); + memset(&sIn, 0, sizeof(sIn)); + memset(&sOut, 0, sizeof(sOut)); + sIn.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR); + sIn.aData = Tcl_GetByteArrayFromObj(objv[1], &sIn.nData); + + if( sIn.nStream ){ + rc = sqlite3changeset_invert_str( + testStreamInput, (void*)&sIn, testSessionsOutput, (void*)&sOut + ); + }else{ + rc = sqlite3changeset_invert(sIn.nData, sIn.aData, &sOut.n, &sOut.p); } - Tcl_SetObjResult(interp, Tcl_NewByteArrayObj((unsigned char *)aOut, nOut)); - sqlite3_free(aOut); - return TCL_OK; + if( rc!=SQLITE_OK ){ + rc = test_session_error(interp, rc); + }else{ + Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n)); + } + sqlite3_free(sOut.p); + return rc; } /* diff --git a/manifest b/manifest index e7faacba4f..3a15e079e7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sstreaming\sversion\sof\ssqlite3changeset_apply().\sTests\sand\sfixes\sfor\sthe\ssame\sand\ssqlite3changeset_start_str(). -D 2014-09-24T17:13:20.331 +C Add\sstreaming\sversion\sof\ssqlite3changeset_invert()\sto\ssessions\smodule. +D 2014-09-25T14:54:20.019 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -158,9 +158,9 @@ F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 F ext/session/sessionB.test 276267cd7fc37c2e2dd03f1e2ed9ada336a8bdb4 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test e7965159a73d385c1a4af12d82c3a039ebdd71a6 -F ext/session/sqlite3session.c 1c653844900de41e175f77f22fe1af7abb05e798 -F ext/session/sqlite3session.h 7e7a31ad1992f6678a20654c9751dacd10384292 -F ext/session/test_session.c 77f1e7a269daeb60f82441ff859c812d686ef79d +F ext/session/sqlite3session.c 9edf9273280c804c45e7508be9644cf96f278c63 +F ext/session/sqlite3session.h 944d7b2c3e87b5598a2c34afe8dd032d51d09818 +F ext/session/test_session.c 4449ef150e52baad844aa08c29569f3ec10902d8 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e @@ -1216,7 +1216,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 3c7d3d950bbf5f5ed3696ebc61c77ca48bafe2b5 -R bba1026624291c9ce371985c2bc9cae0 +P b917fc146876f764442de08d5ec36e5b4cf5ab52 +R b1265a84c7bae5ddb87cac377b4def7e U dan -Z 40a11f75418a19b3b02aba54325bf64c +Z 0bbb9bee98e102db876d83b2977969a7 diff --git a/manifest.uuid b/manifest.uuid index 4b63e2e10a..49b0c2f888 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b917fc146876f764442de08d5ec36e5b4cf5ab52 \ No newline at end of file +8ded6a46794c7bff1c8b790c662ba7e92f576380 \ No newline at end of file From cbf6d2d2aa7fdceffd755dbe92954e4cca0dbfc5 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 25 Sep 2014 20:43:28 +0000 Subject: [PATCH 123/570] Add streaming version of sqlite3changeset_concat(). FossilOrigin-Name: 88eb6656bdb047a104837a2e15e7fe18c0a7a159 --- ext/session/sessionB.test | 9 +- ext/session/sqlite3session.c | 218 +++++++++++++++++++++++------------ ext/session/sqlite3session.h | 12 ++ ext/session/test_session.c | 43 ++++--- manifest | 18 +-- manifest.uuid | 2 +- 6 files changed, 203 insertions(+), 99 deletions(-) diff --git a/ext/session/sessionB.test b/ext/session/sessionB.test index 9798cabfee..2fc061f4e6 100644 --- a/ext/session/sessionB.test +++ b/ext/session/sessionB.test @@ -22,6 +22,11 @@ ifcapable !session {finish_test; return} set testprefix sessionB +# Fix the bug in concatenating patchsets that contain DELETE ops +# before re-enabling this. +finish_test +return + # # 1.*: Test that the blobs returned by the session_patchset() API are # as expected. Also the sqlite3_changeset_iter functions. @@ -385,10 +390,10 @@ proc do_patchset_test {tn tstcmd lSql} { sqlite3session T db main T attach * db eval $sql - lappend lPatch [T patchset] + lappend lPatch [T $tstcmd] T delete } - set patchset [S patchset] + set patchset [S $tstcmd] S delete # Calculate a checksum for the final database. diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index b62f039943..8c6cacd1a4 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2386,7 +2386,6 @@ static int sessionChangesetNext( int i; u8 op; - assert( paRec==0 || p->in.xInput==0 ); /* fixme! */ assert( (paRec==0 && pnRec==0) || (paRec && pnRec) ); /* If the iterator is in the error-state, return immediately. */ @@ -2426,36 +2425,48 @@ static int sessionChangesetNext( return (p->rc = SQLITE_CORRUPT_BKPT); } - if( paRec ){ *paRec = &p->in.aData[p->in.iNext]; } - - /* If this is an UPDATE or DELETE, read the old.* record. */ - if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){ - u8 *abPK = p->bPatchset ? p->abPK : 0; - p->rc = sessionReadRecord(&p->in, p->nCol, abPK, paRec?0:p->apValue); + if( paRec ){ + int nVal; /* Number of values to buffer */ + if( p->bPatchset==0 && op==SQLITE_UPDATE ){ + nVal = p->nCol * 2; + }else if( p->bPatchset && op==SQLITE_DELETE ){ + nVal = 0; + for(i=0; inCol; i++) if( p->abPK[i] ) nVal++; + }else{ + nVal = p->nCol; + } + p->rc = sessionChangesetBufferRecord(&p->in, nVal, pnRec); if( p->rc!=SQLITE_OK ) return p->rc; - } + *paRec = &p->in.aData[p->in.iNext]; + p->in.iNext += *pnRec; + }else{ - /* If this is an INSERT or UPDATE, read the new.* record. */ - if( p->op!=SQLITE_DELETE ){ - sqlite3_value **apOut = (paRec ? 0 : &p->apValue[p->nCol]); - p->rc = sessionReadRecord(&p->in, p->nCol, 0, apOut); - if( p->rc!=SQLITE_OK ) return p->rc; - } + /* If this is an UPDATE or DELETE, read the old.* record. */ + if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){ + u8 *abPK = p->bPatchset ? p->abPK : 0; + p->rc = sessionReadRecord(&p->in, p->nCol, abPK, p->apValue); + if( p->rc!=SQLITE_OK ) return p->rc; + } - if( pnRec ){ - *pnRec = (int)(&p->in.aData[p->in.iNext] - *paRec); - }else if( p->bPatchset && p->op==SQLITE_UPDATE ){ - /* If this is an UPDATE that is part of a patchset, then all PK and - ** modified fields are present in the new.* record. The old.* record - ** is currently completely empty. This block shifts the PK fields from - ** new.* to old.*, to accommodate the code that reads these arrays. */ - int i; - for(i=0; inCol; i++){ - assert( p->apValue[i]==0 ); - assert( p->abPK[i]==0 || p->apValue[i+p->nCol] ); - if( p->abPK[i] ){ - p->apValue[i] = p->apValue[i+p->nCol]; - p->apValue[i+p->nCol] = 0; + /* If this is an INSERT or UPDATE, read the new.* record. */ + if( p->op!=SQLITE_DELETE ){ + p->rc = sessionReadRecord(&p->in, p->nCol, 0, &p->apValue[p->nCol]); + if( p->rc!=SQLITE_OK ) return p->rc; + } + + if( p->bPatchset && p->op==SQLITE_UPDATE ){ + /* If this is an UPDATE that is part of a patchset, then all PK and + ** modified fields are present in the new.* record. The old.* record + ** is currently completely empty. This block shifts the PK fields from + ** new.* to old.*, to accommodate the code that reads these arrays. */ + int i; + for(i=0; inCol; i++){ + assert( p->apValue[i]==0 ); + assert( p->abPK[i]==0 || p->apValue[i+p->nCol] ); + if( p->abPK[i] ){ + p->apValue[i] = p->apValue[i+p->nCol]; + p->apValue[i+p->nCol] = 0; + } } } } @@ -2627,14 +2638,17 @@ int sqlite3changeset_fk_conflicts( ** callback by changeset_apply(). */ int sqlite3changeset_finalize(sqlite3_changeset_iter *p){ - int i; /* Used to iterate through p->apValue[] */ - int rc = p->rc; /* Return code */ - if( p->apValue ){ - for(i=0; inCol*2; i++) sqlite3ValueFree(p->apValue[i]); + int rc = SQLITE_OK; + if( p ){ + int i; /* Used to iterate through p->apValue[] */ + rc = p->rc; + if( p->apValue ){ + for(i=0; inCol*2; i++) sqlite3ValueFree(p->apValue[i]); + } + sqlite3_free(p->tblhdr.aBuf); + sqlite3_free(p->in.buf.aBuf); + sqlite3_free(p); } - sqlite3_free(p->tblhdr.aBuf); - sqlite3_free(p->in.buf.aBuf); - sqlite3_free(p); return rc; } @@ -3647,7 +3661,7 @@ static int sessionChangeMerge( SessionChange *pNew = 0; if( !pExist ){ - pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange)); + pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec); if( !pNew ){ return SQLITE_NOMEM; } @@ -3655,7 +3669,8 @@ static int sessionChangeMerge( pNew->op = op2; pNew->bIndirect = bIndirect; pNew->nRecord = nRec; - pNew->aRecord = aRec; + pNew->aRecord = (u8*)&pNew[1]; + memcpy(pNew->aRecord, aRec, nRec); }else{ int op1 = pExist->op; @@ -3751,21 +3766,15 @@ static int sessionChangeMerge( ** Add all changes in the changeset passed via the first two arguments to ** hash tables. */ -static int sessionConcatChangeset( - int bPatchset, /* True to expect patchsets */ - int nChangeset, /* Number of bytes in pChangeset */ - void *pChangeset, /* Changeset buffer */ +static int sessionAddChangeset( + sqlite3_changeset_iter *pIter, /* Iterator to read from */ SessionTable **ppTabList /* IN/OUT: List of table objects */ ){ u8 *aRec; int nRec; - sqlite3_changeset_iter *pIter; - int rc; + int rc = SQLITE_OK; SessionTable *pTab = 0; - rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); - if( rc!=SQLITE_OK ) return rc; - while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec) ){ const char *zNew; int nCol; @@ -3776,12 +3785,14 @@ static int sessionConcatChangeset( SessionChange *pExist = 0; SessionChange **pp; +#if 0 assert( bPatchset==0 || bPatchset==1 ); assert( pIter->bPatchset==0 || pIter->bPatchset==1 ); if( pIter->bPatchset!=bPatchset ){ rc = SQLITE_ERROR; break; } +#endif sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect); if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){ @@ -3813,12 +3824,12 @@ static int sessionConcatChangeset( } } - if( sessionGrowHash(bPatchset, pTab) ){ + if( sessionGrowHash(pIter->bPatchset, pTab) ){ rc = SQLITE_NOMEM; break; } iHash = sessionChangeHash( - pTab, (bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange + pTab, (pIter->bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange ); /* Search for existing entry. If found, remove it from the hash table. @@ -3827,7 +3838,7 @@ static int sessionConcatChangeset( for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){ int bPkOnly1 = 0; int bPkOnly2 = 0; - if( bPatchset ){ + if( pIter->bPatchset ){ bPkOnly1 = (*pp)->op==SQLITE_DELETE; bPkOnly2 = op==SQLITE_DELETE; } @@ -3840,7 +3851,7 @@ static int sessionConcatChangeset( } rc = sessionChangeMerge(pTab, - bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange + pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange ); if( rc ) break; if( pChange ){ @@ -3850,15 +3861,10 @@ static int sessionConcatChangeset( } } - if( rc==SQLITE_OK ){ - rc = sqlite3changeset_finalize(pIter); - }else{ - sqlite3changeset_finalize(pIter); - } + if( rc==SQLITE_OK ) rc = pIter->rc; return rc; } - /* ** 1. Iterate through the left-hand changeset. Add an entry to a table ** specific hash table for each change in the changeset. The hash table @@ -3870,26 +3876,25 @@ static int sessionConcatChangeset( ** ** 3. Write an output changeset based on the contents of the hash table. */ -int sqlite3changeset_concat( - int nLeft, /* Number of bytes in lhs input */ - void *pLeft, /* Lhs input changeset */ - int nRight /* Number of bytes in rhs input */, - void *pRight, /* Rhs input changeset */ - int *pnOut, /* OUT: Number of bytes in output changeset */ - void **ppOut /* OUT: changeset (left right) */ +int sessionChangesetConcat( + sqlite3_changeset_iter *pLeft, + sqlite3_changeset_iter *pRight, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut, + int *pnOut, + void **ppOut ){ SessionTable *pList = 0; /* List of SessionTable objects */ int rc; /* Return code */ int bPatch; /* True for a patchset */ - *pnOut = 0; - *ppOut = 0; - bPatch = (nLeft>0 && *(char*)pLeft=='P') || (nRight>0 && *(char*)pRight=='P'); + assert( xOutput==0 || (ppOut==0 && pnOut==0) ); - rc = sessionConcatChangeset(bPatch, nLeft, pLeft, &pList); + rc = sessionAddChangeset(pLeft, &pList); if( rc==SQLITE_OK ){ - rc = sessionConcatChangeset(bPatch, nRight, pRight, &pList); + rc = sessionAddChangeset(pRight, &pList); } + bPatch = pLeft->bPatchset || pRight->bPatchset; /* Create the serialized output changeset based on the contents of the ** hash tables attached to the SessionTable objects in list pList. @@ -3897,7 +3902,7 @@ int sqlite3changeset_concat( if( rc==SQLITE_OK ){ SessionTable *pTab; SessionBuffer buf = {0, 0, 0}; - for(pTab=pList; pTab; pTab=pTab->pNext){ + for(pTab=pList; pTab && rc==SQLITE_OK; pTab=pTab->pNext){ int i; if( pTab->nEntry==0 ) continue; @@ -3910,18 +3915,85 @@ int sqlite3changeset_concat( sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); } } + + if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STR_CHUNK_SIZE ){ + rc = xOutput(pOut, buf.aBuf, buf.nBuf); + buf.nBuf = 0; + } } if( rc==SQLITE_OK ){ - *ppOut = buf.aBuf; - *pnOut = buf.nBuf; - }else{ - sqlite3_free(buf.aBuf); + if( xOutput ){ + if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf); + }else{ + *ppOut = buf.aBuf; + *pnOut = buf.nBuf; + buf.aBuf = 0; + } } + sqlite3_free(buf.aBuf); } sessionDeleteTable(pList); return rc; } +/* +** Combine two changesets together. +*/ +int sqlite3changeset_concat( + int nLeft, /* Number of bytes in lhs input */ + void *pLeft, /* Lhs input changeset */ + int nRight /* Number of bytes in rhs input */, + void *pRight, /* Rhs input changeset */ + int *pnOut, /* OUT: Number of bytes in output changeset */ + void **ppOut /* OUT: changeset (left right) */ +){ + sqlite3_changeset_iter *pIter1 = 0; + sqlite3_changeset_iter *pIter2 = 0; + int rc; + + *pnOut = 0; + *ppOut = 0; + rc = sqlite3changeset_start(&pIter1, nLeft, pLeft); + if( rc==SQLITE_OK ){ + rc = sqlite3changeset_start(&pIter2, nRight, pRight); + } + if( rc==SQLITE_OK ){ + rc = sessionChangesetConcat(pIter1, pIter2, 0, 0, pnOut, ppOut); + } + + sqlite3changeset_finalize(pIter1); + sqlite3changeset_finalize(pIter2); + return rc; +} + +/* +** Streaming version of sqlite3changeset_concat(). +*/ +int sqlite3changeset_concat_str( + int (*xInputA)(void *pIn, void *pData, int *pnData), + void *pInA, + int (*xInputB)(void *pIn, void *pData, int *pnData), + void *pInB, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +){ + sqlite3_changeset_iter *pIter1 = 0; + sqlite3_changeset_iter *pIter2 = 0; + int rc; + + rc = sqlite3changeset_start_str(&pIter1, xInputA, pInA); + if( rc==SQLITE_OK ){ + rc = sqlite3changeset_start_str(&pIter2, xInputB, pInB); + } + if( rc==SQLITE_OK ){ + rc = sessionChangesetConcat(pIter1, pIter2, xOutput, pOut, 0, 0); + } + + sqlite3changeset_finalize(pIter1); + sqlite3changeset_finalize(pIter2); + return rc; +} + #endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index ce91cb68f1..ad58c0d772 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -761,6 +761,18 @@ int sqlite3changeset_concat( void **ppOut /* OUT: Buffer containing output changeset */ ); +/* +** Streaming verson of sqlite3changeset_concat(). +*/ +int sqlite3changeset_concat_str( + int (*xInputA)(void *pIn, void *pData, int *pnData), + void *pInA, + int (*xInputB)(void *pIn, void *pData, int *pnData), + void *pInB, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); + /* ** CAPI3REF: Apply A Changeset To A Database ** diff --git a/ext/session/test_session.c b/ext/session/test_session.c index edd508d0e3..df690d44ad 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -715,27 +715,42 @@ static int test_sqlite3changeset_concat( Tcl_Obj *CONST objv[] ){ int rc; /* Return code from changeset_invert() */ - void *aLeft; /* Input changeset */ - int nLeft; /* Size of buffer aChangeset in bytes */ - void *aRight; /* Input changeset */ - int nRight; /* Size of buffer aChangeset in bytes */ - void *aOut; /* Output changeset */ - int nOut; /* Size of buffer aOut in bytes */ + + TestStreamInput sLeft; /* Input stream */ + TestStreamInput sRight; /* Input stream */ + TestSessionsBlob sOut = {0,0}; /* Output blob */ if( objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "LEFT RIGHT"); return TCL_ERROR; } - aLeft = (void *)Tcl_GetByteArrayFromObj(objv[1], &nLeft); - aRight = (void *)Tcl_GetByteArrayFromObj(objv[2], &nRight); - rc = sqlite3changeset_concat(nLeft, aLeft, nRight, aRight, &nOut, &aOut); - if( rc!=SQLITE_OK ){ - return test_session_error(interp, rc); + memset(&sLeft, 0, sizeof(sLeft)); + memset(&sRight, 0, sizeof(sRight)); + sLeft.aData = Tcl_GetByteArrayFromObj(objv[1], &sLeft.nData); + sRight.aData = Tcl_GetByteArrayFromObj(objv[2], &sRight.nData); + sLeft.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR); + sRight.nStream = sLeft.nStream; + + if( sLeft.nStream>0 ){ + rc = sqlite3changeset_concat_str( + testStreamInput, (void*)&sLeft, + testStreamInput, (void*)&sRight, + testSessionsOutput, (void*)&sOut + ); + }else{ + rc = sqlite3changeset_concat( + sLeft.nData, sLeft.aData, sRight.nData, sRight.aData, &sOut.n, &sOut.p + ); } - Tcl_SetObjResult(interp, Tcl_NewByteArrayObj((unsigned char *)aOut, nOut)); - sqlite3_free(aOut); - return TCL_OK; + + if( rc!=SQLITE_OK ){ + rc = test_session_error(interp, rc); + }else{ + Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n)); + } + sqlite3_free(sOut.p); + return rc; } /* diff --git a/manifest b/manifest index 3a15e079e7..ddf1638203 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sstreaming\sversion\sof\ssqlite3changeset_invert()\sto\ssessions\smodule. -D 2014-09-25T14:54:20.019 +C Add\sstreaming\sversion\sof\ssqlite3changeset_concat(). +D 2014-09-25T20:43:28.741 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -155,12 +155,12 @@ F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 F ext/session/session9.test 776e46785c29c11cda01f5205d0f1e8f8f9a46bf F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 -F ext/session/sessionB.test 276267cd7fc37c2e2dd03f1e2ed9ada336a8bdb4 +F ext/session/sessionB.test c414583719a6a1b430bbb4b32cdffc6089d2b139 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test e7965159a73d385c1a4af12d82c3a039ebdd71a6 -F ext/session/sqlite3session.c 9edf9273280c804c45e7508be9644cf96f278c63 -F ext/session/sqlite3session.h 944d7b2c3e87b5598a2c34afe8dd032d51d09818 -F ext/session/test_session.c 4449ef150e52baad844aa08c29569f3ec10902d8 +F ext/session/sqlite3session.c 368fe2e3f4c435673acbc1df7f470ebd383e168f +F ext/session/sqlite3session.h 04529352750006b32811384db64eb1b6e5c3cd80 +F ext/session/test_session.c 194083ee1f0f6f38404f662fe9b50849abd3b7ee F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e @@ -1216,7 +1216,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b917fc146876f764442de08d5ec36e5b4cf5ab52 -R b1265a84c7bae5ddb87cac377b4def7e +P 8ded6a46794c7bff1c8b790c662ba7e92f576380 +R ee60d24169659791aff86861c22f5852 U dan -Z 0bbb9bee98e102db876d83b2977969a7 +Z 192d45bf138dc22ddb0bc36d2880342f diff --git a/manifest.uuid b/manifest.uuid index 49b0c2f888..a34e37dfb6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8ded6a46794c7bff1c8b790c662ba7e92f576380 \ No newline at end of file +88eb6656bdb047a104837a2e15e7fe18c0a7a159 \ No newline at end of file From fa29ecc4ed5b09b157b6270097ebbc7c2e951632 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 26 Sep 2014 10:52:21 +0000 Subject: [PATCH 124/570] Fix a problem with concatenating patchsets containing DELETE and INSERT operations on the same row. FossilOrigin-Name: 4d8537eafb40e3687abc057ba26a1f7014f2c2d9 --- ext/session/sessionB.test | 5 ----- ext/session/sqlite3session.c | 19 ++++++++++++++----- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/ext/session/sessionB.test b/ext/session/sessionB.test index 2fc061f4e6..b11c3110a1 100644 --- a/ext/session/sessionB.test +++ b/ext/session/sessionB.test @@ -22,11 +22,6 @@ ifcapable !session {finish_test; return} set testprefix sessionB -# Fix the bug in concatenating patchsets that contain DELETE ops -# before re-enabling this. -finish_test -return - # # 1.*: Test that the blobs returned by the session_patchset() API are # as expected. Also the sqlite3_changeset_iter functions. diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 8c6cacd1a4..a0e0697ee3 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -597,11 +597,15 @@ static void sessionMergeRecord( ** as to point to the next value in the record. ** ** If, when this function is called, *paTwo points to a valid value (i.e. -** *paTwo[0] is not 0x00 - the "no value" placeholder), a copy of the *paOne +** *paTwo[0] is not 0x00 - the "no value" placeholder), a copy of the *paTwo ** pointer is returned and *pnVal is set to the number of bytes in the ** serialized value. Otherwise, a copy of *paOne is returned and *pnVal ** set to the number of bytes in the value at *paOne. If *paOne points -** to the "no value" placeholder, *pnVal is set to 1. +** to the "no value" placeholder, *pnVal is set to 1. In other words: +** +** if( *paTwo is valid ) return *paTwo; +** return *paOne; +** */ static u8 *sessionMergeValue( u8 **paOne, /* IN/OUT: Left-hand buffer pointer */ @@ -3723,9 +3727,14 @@ static int sessionChangeMerge( }else if( op1==SQLITE_DELETE ){ /* DELETE + INSERT */ assert( op2==SQLITE_INSERT ); pNew->op = SQLITE_UPDATE; - if( 0==sessionMergeUpdate(&aCsr, pTab, bPatchset, aExist, 0, aRec, 0) ){ - sqlite3_free(pNew); - pNew = 0; + if( bPatchset ){ + memcpy(aCsr, aRec, nRec); + aCsr += nRec; + }else{ + if( 0==sessionMergeUpdate(&aCsr, pTab, bPatchset, aExist, 0,aRec,0) ){ + sqlite3_free(pNew); + pNew = 0; + } } }else if( op2==SQLITE_UPDATE ){ /* UPDATE + UPDATE */ u8 *a1 = aExist; diff --git a/manifest b/manifest index ddf1638203..07a4e34a3b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sstreaming\sversion\sof\ssqlite3changeset_concat(). -D 2014-09-25T20:43:28.741 +C Fix\sa\sproblem\swith\sconcatenating\spatchsets\scontaining\sDELETE\sand\sINSERT\soperations\son\sthe\ssame\srow. +D 2014-09-26T10:52:21.193 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -155,10 +155,10 @@ F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 F ext/session/session9.test 776e46785c29c11cda01f5205d0f1e8f8f9a46bf F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 -F ext/session/sessionB.test c414583719a6a1b430bbb4b32cdffc6089d2b139 +F ext/session/sessionB.test d4ac901b43d4922a17dff08bbaa2f5354487ce4d F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test e7965159a73d385c1a4af12d82c3a039ebdd71a6 -F ext/session/sqlite3session.c 368fe2e3f4c435673acbc1df7f470ebd383e168f +F ext/session/sqlite3session.c ade9fa2f7341b822dddaa865115ec964a030df94 F ext/session/sqlite3session.h 04529352750006b32811384db64eb1b6e5c3cd80 F ext/session/test_session.c 194083ee1f0f6f38404f662fe9b50849abd3b7ee F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1216,7 +1216,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 8ded6a46794c7bff1c8b790c662ba7e92f576380 -R ee60d24169659791aff86861c22f5852 +P 88eb6656bdb047a104837a2e15e7fe18c0a7a159 +R 81a0c7112c65d31bc1808253eb2f372f U dan -Z 192d45bf138dc22ddb0bc36d2880342f +Z a169087f5f6ea34184b5d5b4868830f7 diff --git a/manifest.uuid b/manifest.uuid index a34e37dfb6..c388e5763a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -88eb6656bdb047a104837a2e15e7fe18c0a7a159 \ No newline at end of file +4d8537eafb40e3687abc057ba26a1f7014f2c2d9 \ No newline at end of file From 16228167c24b757214d2f8485d8b79c1bc0dc16f Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 27 Sep 2014 12:26:18 +0000 Subject: [PATCH 125/570] Improve sessions module documentation and comments. Fix some other code issues. FossilOrigin-Name: bfc8bd80f8b225cebc66478448510ce84223ae7d --- ext/session/sqlite3session.c | 48 ++++--- ext/session/sqlite3session.h | 237 ++++++++++++++++++++--------------- manifest | 14 +-- manifest.uuid | 2 +- 4 files changed, 171 insertions(+), 130 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index a0e0697ee3..eb1ff1e774 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -49,10 +49,10 @@ struct SessionBuffer { }; /* -** An object of this type is used internally as an abstraction for the -** input data read by changeset iterators. Input data may be supplied -** either as a single large buffer (sqlite3changeset_start()) or using -** a stream function (sqlite3changeset_start_str()). +** An object of this type is used internally as an abstraction for +** input data. Input data may be supplied either as a single large buffer +** (e.g. sqlite3changeset_start()) or using a stream function (e.g. +** sqlite3changeset_start_str()). */ struct SessionInput { int iNext; /* Offset in aData[] of next change */ @@ -2173,6 +2173,10 @@ static int sessionValueSetStr( int nData, /* Size of buffer aData[] in bytes */ u8 enc /* String encoding (0 for blobs) */ ){ + /* In theory this code could just pass SQLITE_TRANSIENT as the final + ** argument to sqlite3ValueSetStr() and have the copy created + ** automatically. But doing so makes it difficult to detect any OOM + ** error. Hence the code to create the copy externally. */ u8 *aCopy = sqlite3_malloc(nData); if( aCopy==0 ) return SQLITE_NOMEM; memcpy(aCopy, aData, nData); @@ -2299,12 +2303,16 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ /* ** The input pointer currently points to the first byte of the first field ** of a record consisting of nCol columns. This function ensures the entire -** record is buffered. +** record is buffered. It does not move the input pointer. +** +** If successful, SQLITE_OK is returned and *pnByte is set to the size of +** the record in bytes. Otherwise, an SQLite error code is returned. The +** final value of *pnByte is undefined in this case. */ static int sessionChangesetBufferRecord( - SessionInput *pIn, - int nCol, - int *pnByte + SessionInput *pIn, /* Input data */ + int nCol, /* Number of columns in record */ + int *pnByte /* OUT: Size of record in bytes */ ){ int rc = SQLITE_OK; int nByte = 0; @@ -2335,6 +2343,15 @@ static int sessionChangesetBufferRecord( ** + number of columns in table (varint) ** + array of PK flags (1 byte per column), ** + table name (nul terminated). +** +** This function decodes the table-header and populates the p->nCol, +** p->zTab and p->abPK[] variables accordingly. The p->apValue[] array is +** also allocated or resized according to the new value of p->nCol. The +** input pointer is left pointing to the byte following the table header. +** +** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code +** is returned and the final values of the various fields enumerated above +** are undefined. */ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){ int rc; @@ -3775,7 +3792,7 @@ static int sessionChangeMerge( ** Add all changes in the changeset passed via the first two arguments to ** hash tables. */ -static int sessionAddChangeset( +static int sessionChangesetToHash( sqlite3_changeset_iter *pIter, /* Iterator to read from */ SessionTable **ppTabList /* IN/OUT: List of table objects */ ){ @@ -3794,15 +3811,6 @@ static int sessionAddChangeset( SessionChange *pExist = 0; SessionChange **pp; -#if 0 - assert( bPatchset==0 || bPatchset==1 ); - assert( pIter->bPatchset==0 || pIter->bPatchset==1 ); - if( pIter->bPatchset!=bPatchset ){ - rc = SQLITE_ERROR; - break; - } -#endif - sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect); if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){ /* Search the list for a matching table */ @@ -3899,9 +3907,9 @@ int sessionChangesetConcat( assert( xOutput==0 || (ppOut==0 && pnOut==0) ); - rc = sessionAddChangeset(pLeft, &pList); + rc = sessionChangesetToHash(pLeft, &pList); if( rc==SQLITE_OK ){ - rc = sessionAddChangeset(pRight, &pList); + rc = sessionChangesetToHash(pRight, &pList); } bPatch = pLeft->bPatchset || pRight->bPatchset; diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index ad58c0d772..0dd03067ed 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -274,30 +274,6 @@ int sqlite3session_changeset( ); -/* -** This function is similar to sqlite3session_changeset(), except that instead -** of storing the output changeset in a buffer obtained from sqlite3_malloc() -** it invokes the supplied xOutput() callback zero or more times to stream the -** changeset to the application. This is useful in order to avoid large memory -** allocations when working with very large changesets. -** -** The first parameter passed to each call to the xOutput callback is a copy -** of the pOut parameter passed to this function. The following two parameters -** are a pointer to the buffer containing the next chunk of the output changeset -** and the size of that buffer in bytes. -** -** If the data is successfully processed by the xOutput callback, it should -** return SQLITE_OK. Or, if an error occurs, some other SQLite error code. In -** this case the sqlite3session_changeset_str() call is abandoned immediately -** and returns a copy of the xOutput return code. -*/ -int sqlite3session_changeset_str( - sqlite3_session *pSession, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); - - /* ** CAPI3REF: Generate A Patchset From A Session Object ** @@ -327,15 +303,6 @@ int sqlite3session_patchset( void **ppPatchset /* OUT: Buffer containing changeset */ ); -/* -** Streaming version of sqlite3session_patchset(). -*/ -int sqlite3session_patchset_str( - sqlite3_session *pSession, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); - /* ** CAPI3REF: Test if a changeset has recorded any changes. ** @@ -393,29 +360,6 @@ int sqlite3changeset_start( ); -/* -** This function is similar to sqlite3changeset_start(), except that instead -** of reading data from a single buffer, it requests it one chunk at a time -** from the application by invoking the supplied xInput() callback. The xInput() -** callback may be invoked at any time during the lifetime of the iterator. -** -** Each time the xInput callback is invoked, the first argument passed is a -** copy of the third parameter passed to this function. The second argument, -** pData, points to a buffer (*pnData) bytes in size. Assuming no error occurs -** the xInput method should copy up to (*pnData) bytes of data into the buffer -** and set (*pnData) to the actual number of bytes copied before returning -** SQLITE_OK. If the input is completely exhausted, (*pnData) should be set -** to zero to indicate this. Or, if an error occurs, an SQLite error code -** should be returned. In this case the iterator is put into an error state and -** all subsequent calls to iterator methods return a copy of the xInput error -** code. -*/ -int sqlite3changeset_start_str( - sqlite3_changeset_iter **pp, - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn -); - /* ** CAPI3REF: Advance A Changeset Iterator ** @@ -670,16 +614,6 @@ int sqlite3changeset_invert( int *pnOut, void **ppOut /* OUT: Inverse of input */ ); -/* -** Streaming version of sqlite3changeset_invert(). -*/ -int sqlite3changeset_invert_str( - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); - /* ** CAPI3REF: Concatenate Two Changeset Objects ** @@ -761,18 +695,6 @@ int sqlite3changeset_concat( void **ppOut /* OUT: Buffer containing output changeset */ ); -/* -** Streaming verson of sqlite3changeset_concat(). -*/ -int sqlite3changeset_concat_str( - int (*xInputA)(void *pIn, void *pData, int *pnData), - void *pInA, - int (*xInputB)(void *pIn, void *pData, int *pnData), - void *pInB, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); - /* ** CAPI3REF: Apply A Changeset To A Database ** @@ -925,30 +847,6 @@ int sqlite3changeset_apply( void *pCtx /* First argument passed to xConflict */ ); -/* -** This function is similar to sqlite3changeset_apply(), except that instead -** of reading data from a single buffer, it requests it one chunk at a time -** from the application by invoking the supplied xInput() callback. -** -** See the documentation for sqlite3changeset_start_str() for a description -** of how the xInput callback should be implemented. -*/ -int sqlite3changeset_apply_str( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ - void *pIn, /* First arg for xInput */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx /* First argument passed to xConflict */ -); - /* ** CAPI3REF: Constants Passed To The Conflict Handler ** @@ -1045,6 +943,141 @@ int sqlite3changeset_apply_str( #define SQLITE_CHANGESET_REPLACE 1 #define SQLITE_CHANGESET_ABORT 2 +/* +** CAPI3REF: Streaming Versions of API functions. +** +** The six streaming API xxx_str() functions serve similar purposes to the +** corresponding non-streaming API functions: +** +** +** +**
Streaming functionNon-streaming equivalent
sqlite3changeset_apply_str[sqlite3changeset_apply] +**
sqlite3changeset_concat_str[sqlite3changeset_concat] +**
sqlite3changeset_invert_str[sqlite3changeset_invert] +**
sqlite3changeset_start_str[sqlite3changeset_start] +**
sqlite3session_changeset_str[sqlite3session_changeset] +**
sqlite3session_patchset_str[sqlite3session_patchset] +**
+** +** Non-streaming functions that accept changesets (or patchsets) as input +** require that the entire changeset be stored in a single buffer in memory. +** Similarly, those that return a changeset or patchset do so by returning +** a pointer to a single large buffer allocated using sqlite3_malloc(). +** Normally this is convenient. However, if an application running in a +** low-memory environment is required to handle very large changesets, the +** large contiguous memory allocations required can become onerous. +** +** In order to avoid this problem, instead of a single large buffer, input +** is passed to a streaming API functions by way of a callback function that +** the sessions module invokes to incrementally request input data as it is +** required. In all cases, a pair of API function parameters such as +** +**
+**        int nChangeset,
+**        void *pChangeset,
+**  
+** +** Is replaced by: +** +**
+**        int (*xInput)(void *pIn, void *pData, int *pnData),
+**        void *pIn,
+**  
+** +** Each time the xInput callback is invoked by the sessions module, the first +** argument passed is a copy of the supplied pIn context pointer. The second +** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no +** error occurs the xInput method should copy up to (*pnData) bytes of data +** into the buffer and set (*pnData) to the actual number of bytes copied +** before returning SQLITE_OK. If the input is completely exhausted, (*pnData) +** should be set to zero to indicate this. Or, if an error occurs, an SQLite +** error code should be returned. In all cases, if an xInput callback returns +** an error, all processing is abandoned and the streaming API function +** returns a copy of the error code to the caller. +** +** In the case of sqlite3changeset_start_str(), the xInput callback may be +** invoked by the sessions module at any point during the lifetime of the +** iterator. If such an xInput callback returns an error, the iterator enters +** an error state, whereby all subsequent calls to iterator functions +** immediately fail with the same error code as returned by xInput. +** +** Similarly, streaming API functions that return changesets (or patchsets) +** return them in chunks by way of a callback function instead of via a +** pointer to a single large buffer. In this case, a pair of parameters such +** as: +** +**
+**        int *pnChangeset,
+**        void **ppChangeset,
+**  
+** +** Is replaced by: +** +**
+**        int (*xOutput)(void *pOut, const void *pData, int nData),
+**        void *pOut
+**  
+** +** The xOutput callback is invoked zero or more times to return data to +** the application. The first parameter passed to each call is a copy of the +** pOut pointer supplied by the application. The second parameter, pData, +** points to a buffer nData bytes in size containing the chunk of output +** data being returned. If the xOutput callback successfully processes the +** supplied data, it should return SQLITE_OK to indicate success. Otherwise, +** it should return some other SQLite error code. In this case processing +** is immediately abandoned and the streaming API function returns a copy +** of the xOutput error code to the application. +** +** The sessions module never invokes an xOutput callback with the third +** parameter set to a value less than or equal to zero. Other than this, +** no guarantees are made as to the size of the chunks of data returned. +*/ +int sqlite3changeset_apply_str( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ + void *pIn, /* First arg for xInput */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx /* First argument passed to xConflict */ +); +int sqlite3changeset_concat_str( + int (*xInputA)(void *pIn, void *pData, int *pnData), + void *pInA, + int (*xInputB)(void *pIn, void *pData, int *pnData), + void *pInB, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +int sqlite3changeset_invert_str( + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +int sqlite3changeset_start_str( + sqlite3_changeset_iter **pp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn +); +int sqlite3session_changeset_str( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +int sqlite3session_patchset_str( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); + + /* ** Make sure we can call this stuff from C++. */ diff --git a/manifest b/manifest index 07a4e34a3b..258fb598ba 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\sconcatenating\spatchsets\scontaining\sDELETE\sand\sINSERT\soperations\son\sthe\ssame\srow. -D 2014-09-26T10:52:21.193 +C Improve\ssessions\smodule\sdocumentation\sand\scomments.\sFix\ssome\sother\scode\sissues. +D 2014-09-27T12:26:18.848 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -158,8 +158,8 @@ F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 F ext/session/sessionB.test d4ac901b43d4922a17dff08bbaa2f5354487ce4d F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/sessionfault.test e7965159a73d385c1a4af12d82c3a039ebdd71a6 -F ext/session/sqlite3session.c ade9fa2f7341b822dddaa865115ec964a030df94 -F ext/session/sqlite3session.h 04529352750006b32811384db64eb1b6e5c3cd80 +F ext/session/sqlite3session.c 9ce77f4752cd5d8982e7b64f665ae66754dda723 +F ext/session/sqlite3session.h b57009fb88835cc4684376bd3eae0d6ab364968a F ext/session/test_session.c 194083ee1f0f6f38404f662fe9b50849abd3b7ee F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 @@ -1216,7 +1216,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 88eb6656bdb047a104837a2e15e7fe18c0a7a159 -R 81a0c7112c65d31bc1808253eb2f372f +P 4d8537eafb40e3687abc057ba26a1f7014f2c2d9 +R c2c5a501f3f294cbca1bcb47eb806551 U dan -Z a169087f5f6ea34184b5d5b4868830f7 +Z c7ab4f2784fbdfc318b000ddf7671e24 diff --git a/manifest.uuid b/manifest.uuid index c388e5763a..31da46d10b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4d8537eafb40e3687abc057ba26a1f7014f2c2d9 \ No newline at end of file +bfc8bd80f8b225cebc66478448510ce84223ae7d \ No newline at end of file From e8fa8c9649b16bd8d0f7acdfd92d4762d07e004e Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 27 Sep 2014 16:33:09 +0000 Subject: [PATCH 126/570] Fix a segfault in the streaming API functions triggered by a very long table name. FossilOrigin-Name: d2642543eed54da1ac0f757d43dd4d72482eb752 --- ext/session/session1.test | 26 ++++++++++ ext/session/sessionfault.test | 38 ++++++++++++++- ext/session/sqlite3session.c | 92 ++++++++++++++++------------------- ext/session/test_session.c | 17 +++++-- manifest | 18 +++---- manifest.uuid | 2 +- 6 files changed, 127 insertions(+), 66 deletions(-) diff --git a/ext/session/session1.test b/ext/session/session1.test index e6f9c8fd7f..1c853a97a1 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -524,4 +524,30 @@ do_test 9.2 { do_changeset_test 9.2 S {{UPDATE t7 0 ....X.. {{} {} i 1 {} {} i 1 i 1 {} {} {} {}} {{} {} i 2 {} {} i 2 {} {} {} {} {} {}}}} S delete catch { db2 close } + +#------------------------------------------------------------------------- +# Test a really long table name. +# +reset_db +set tblname [string repeat tblname123 100] +do_test 10.1.1 { + execsql " + CREATE TABLE $tblname (a PRIMARY KEY, b); + INSERT INTO $tblname VALUES('xyz', 'def'); + " + sqlite3session S db main + S attach $tblname + execsql " + INSERT INTO $tblname VALUES('uvw', 'abc'); + DELETE FROM $tblname WHERE a = 'xyz'; + " +} {} +breakpoint +do_changeset_test 10.1.2 S " + {INSERT $tblname 0 X. {} {t uvw t abc}} + {DELETE $tblname 0 X. {t xyz t def} {}} +" +do_test 10.1.4 { S delete } {} + + finish_test diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index 4b278098a9..c94589e372 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -30,7 +30,6 @@ do_common_sql { faultsim_save_and_close db2 close - #------------------------------------------------------------------------- # Test OOM error handling when collecting and applying a simple changeset. # @@ -234,7 +233,7 @@ set changeset [changeset_from_sql { }] db close -do_faultsim_test 5 -faults oom* -body { +do_faultsim_test 5.1 -faults oom* -body { set ::inverse [sqlite3changeset_invert $::changeset] set {} {} } -test { @@ -251,6 +250,41 @@ do_faultsim_test 5 -faults oom* -body { } } +catch {db close} +catch {db2 close} +forcedelete test.db +sqlite3 db test.db +execsql { + CREATE TABLE t2(a PRIMARY KEY, b); + INSERT INTO t2 VALUES(1, 'abc'); + INSERT INTO t2 VALUES(2, 'def'); +} +set changeset [changeset_from_sql { + UPDATE t2 SET b = (b || b || b || b); + UPDATE t2 SET b = (b || b || b || b); + UPDATE t2 SET b = (b || b || b || b); + UPDATE t2 SET b = (b || b || b || b); +}] +db close +set abc [string repeat abc 256] +set def [string repeat def 256] + +do_faultsim_test 5.2 -faults oom-tra* -body { + set ::inverse [sqlite3changeset_invert $::changeset] + set {} {} +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + if {$testrc==0} { + set x [list] + sqlite3session_foreach c $::inverse { lappend x $c } + foreach c " + {UPDATE t2 0 X. {i 1 t $::abc} {{} {} t abc}} + {UPDATE t2 0 X. {i 2 t $::def} {{} {} t def}} + " { lappend y $c } + if {$x != $y} { error "changeset no good" } + } +} + #------------------------------------------------------------------------- # Test that OOM errors in sqlite3changeset_concat() are handled correctly. # diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index eb1ff1e774..7e69be4cc4 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -18,7 +18,7 @@ typedef struct SessionInput SessionInput; ** Minimum chunk size used by streaming versions of functions. */ #ifdef SQLITE_TEST -#define SESSIONS_STR_CHUNK_SIZE 1 +#define SESSIONS_STR_CHUNK_SIZE 64 #else #define SESSIONS_STR_CHUNK_SIZE 1024 #endif @@ -1347,7 +1347,7 @@ static void sessionAppendValue(SessionBuffer *p, sqlite3_value *pVal, int *pRc){ int rc = *pRc; if( rc==SQLITE_OK ){ int nByte = 0; - sessionSerializeValue(0, pVal, &nByte); + rc = sessionSerializeValue(0, pVal, &nByte); sessionBufferGrow(p, nByte, &rc); if( rc==SQLITE_OK ){ rc = sessionSerializeValue(&p->aBuf[p->nBuf], pVal, 0); @@ -2225,12 +2225,10 @@ static int sessionReadRecord( eType = pIn->aData[pIn->iNext++]; } - assert( !apOut || apOut[i]==0 ); + assert( apOut[i]==0 ); if( eType ){ - if( apOut ){ - apOut[i] = sqlite3ValueNew(0); - if( !apOut[i] ) rc = SQLITE_NOMEM; - } + apOut[i] = sqlite3ValueNew(0); + if( !apOut[i] ) rc = SQLITE_NOMEM; } if( rc==SQLITE_OK ){ @@ -2239,22 +2237,20 @@ static int sessionReadRecord( int nByte; pIn->iNext += sessionVarintGet(aVal, &nByte); rc = sessionInputBuffer(pIn, nByte); - if( apOut && rc==SQLITE_OK ){ + if( rc==SQLITE_OK ){ u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc); } pIn->iNext += nByte; } if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ - if( apOut ){ - sqlite3_int64 v = sessionGetI64(aVal); - if( eType==SQLITE_INTEGER ){ - sqlite3VdbeMemSetInt64(apOut[i], v); - }else{ - double d; - memcpy(&d, &v, 8); - sqlite3VdbeMemSetDouble(apOut[i], d); - } + sqlite3_int64 v = sessionGetI64(aVal); + if( eType==SQLITE_INTEGER ){ + sqlite3VdbeMemSetInt64(apOut[i], v); + }else{ + double d; + memcpy(&d, &v, 8); + sqlite3VdbeMemSetDouble(apOut[i], d); } pIn->iNext += 8; } @@ -2293,10 +2289,10 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ while( (pIn->iNext + nRead)nData && pIn->aData[pIn->iNext + nRead] ){ nRead++; } - if( pIn->aData[pIn->iNext + nRead]==0 ) break; + if( (pIn->iNext + nRead)nData ) break; rc = sessionInputBuffer(pIn, nRead + 100); } - if( pnByte ) *pnByte = nRead+1; + *pnByte = nRead+1; return rc; } @@ -2775,7 +2771,7 @@ static int sessionChangesetInvert( /* Write the new old.* record. Consists of the PK columns from the ** original old.* record, and the other values from the original ** new.* record. */ - for(iCol=0; rc==SQLITE_OK && iColpNext){ - int i; - if( pTab->nEntry==0 ) continue; + for(pTab=pList; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ + int i; + if( pTab->nEntry==0 ) continue; - sessionAppendTableHdr(&buf, bPatch, pTab, &rc); - for(i=0; inChange; i++){ - SessionChange *p; - for(p=pTab->apChange[i]; p; p=p->pNext){ - sessionAppendByte(&buf, p->op, &rc); - sessionAppendByte(&buf, p->bIndirect, &rc); - sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); - } - } - - if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STR_CHUNK_SIZE ){ - rc = xOutput(pOut, buf.aBuf, buf.nBuf); - buf.nBuf = 0; + sessionAppendTableHdr(&buf, bPatch, pTab, &rc); + for(i=0; inChange; i++){ + SessionChange *p; + for(p=pTab->apChange[i]; p; p=p->pNext){ + sessionAppendByte(&buf, p->op, &rc); + sessionAppendByte(&buf, p->bIndirect, &rc); + sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); } } - if( rc==SQLITE_OK ){ - if( xOutput ){ - if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf); - }else{ - *ppOut = buf.aBuf; - *pnOut = buf.nBuf; - buf.aBuf = 0; - } + if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STR_CHUNK_SIZE ){ + rc = xOutput(pOut, buf.aBuf, buf.nBuf); + buf.nBuf = 0; } - sqlite3_free(buf.aBuf); } + if( rc==SQLITE_OK ){ + if( xOutput ){ + if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf); + }else{ + *ppOut = buf.aBuf; + *pnOut = buf.nBuf; + buf.aBuf = 0; + } + } + sqlite3_free(buf.aBuf); + sessionDeleteTable(pList); return rc; } diff --git a/ext/session/test_session.c b/ext/session/test_session.c index df690d44ad..7e366ef3bb 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -75,7 +75,7 @@ struct TestSessionsBlob { }; typedef struct TestSessionsBlob TestSessionsBlob; -static int testSessionsOutput( +static int testStreamOutput( void *pCtx, const void *pData, int nData @@ -160,9 +160,9 @@ static int test_session_cmd( if( test_tcl_integer(interp, SESSION_STREAM_TCL_VAR) ){ void *pCtx = (void*)&o; if( iSub==7 ){ - rc = sqlite3session_patchset_str(pSession, testSessionsOutput, pCtx); + rc = sqlite3session_patchset_str(pSession, testStreamOutput, pCtx); }else{ - rc = sqlite3session_changeset_str(pSession, testSessionsOutput, pCtx); + rc = sqlite3session_changeset_str(pSession, testStreamOutput, pCtx); } }else{ if( iSub==7 ){ @@ -562,6 +562,13 @@ static int testStreamInput( int nRem = p->nData - p->iData; /* Bytes of data available */ int nRet = p->nStream; /* Bytes actually returned */ + /* Allocate and free some space. There is no point to this, other than + ** that it allows the regular OOM fault-injection tests to cause an error + ** in this function. */ + void *pAlloc = sqlite3_malloc(10); + if( pAlloc==0 ) return SQLITE_NOMEM; + sqlite3_free(pAlloc); + if( nRet>nReq ) nRet = nReq; if( nRet>nRem ) nRet = nRem; @@ -691,7 +698,7 @@ static int test_sqlite3changeset_invert( if( sIn.nStream ){ rc = sqlite3changeset_invert_str( - testStreamInput, (void*)&sIn, testSessionsOutput, (void*)&sOut + testStreamInput, (void*)&sIn, testStreamOutput, (void*)&sOut ); }else{ rc = sqlite3changeset_invert(sIn.nData, sIn.aData, &sOut.n, &sOut.p); @@ -736,7 +743,7 @@ static int test_sqlite3changeset_concat( rc = sqlite3changeset_concat_str( testStreamInput, (void*)&sLeft, testStreamInput, (void*)&sRight, - testSessionsOutput, (void*)&sOut + testStreamOutput, (void*)&sOut ); }else{ rc = sqlite3changeset_concat( diff --git a/manifest b/manifest index 258fb598ba..4cb1bee75c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\ssessions\smodule\sdocumentation\sand\scomments.\sFix\ssome\sother\scode\sissues. -D 2014-09-27T12:26:18.848 +C Fix\sa\ssegfault\sin\sthe\sstreaming\sAPI\sfunctions\striggered\sby\sa\svery\slong\stable\sname. +D 2014-09-27T16:33:09.345 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -146,7 +146,7 @@ F ext/rtree/sqlite3rtree.h 83349d519fe5f518b3ea025d18dd1fe51b1684bd F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a -F ext/session/session1.test 3733d71eb9a99b14d51fa5219d5b8a82407c3be8 +F ext/session/session1.test 4653867f32a98ce4bbb4a181aac6debe51ca4dfb F ext/session/session2.test 99ca0da7ddb617d42bafd83adccf99f18ae0384b F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 @@ -157,10 +157,10 @@ F ext/session/session9.test 776e46785c29c11cda01f5205d0f1e8f8f9a46bf F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 F ext/session/sessionB.test d4ac901b43d4922a17dff08bbaa2f5354487ce4d F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 -F ext/session/sessionfault.test e7965159a73d385c1a4af12d82c3a039ebdd71a6 -F ext/session/sqlite3session.c 9ce77f4752cd5d8982e7b64f665ae66754dda723 +F ext/session/sessionfault.test cf9758bfb6ccd5db5f09f170667a8cea1ac8afa7 +F ext/session/sqlite3session.c 228cca8fdb6fd07942be097c516f22e39ec39e3c F ext/session/sqlite3session.h b57009fb88835cc4684376bd3eae0d6ab364968a -F ext/session/test_session.c 194083ee1f0f6f38404f662fe9b50849abd3b7ee +F ext/session/test_session.c 56a4ddd443b571c8d365b03197c032bdaed1443a F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e @@ -1216,7 +1216,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4d8537eafb40e3687abc057ba26a1f7014f2c2d9 -R c2c5a501f3f294cbca1bcb47eb806551 +P bfc8bd80f8b225cebc66478448510ce84223ae7d +R 9ca53892e63f9c31475266a6b3e34d34 U dan -Z c7ab4f2784fbdfc318b000ddf7671e24 +Z f7759b84adfee5a6c178fa61db492ce5 diff --git a/manifest.uuid b/manifest.uuid index 31da46d10b..903686ec1f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bfc8bd80f8b225cebc66478448510ce84223ae7d \ No newline at end of file +d2642543eed54da1ac0f757d43dd4d72482eb752 \ No newline at end of file From f05ac11214c082d4a849742f3e5c6246c4bf5106 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 27 Sep 2014 18:18:32 +0000 Subject: [PATCH 127/570] Fix a segfault in the sessions module that could follow an OOM. FossilOrigin-Name: 09985fa6b60a0bf38e23bbccd4d8e1d1cbf66124 --- ext/session/session9.test | 34 ++++++++++++++++++ ext/session/sessionA.test | 43 +++++++++++++++++++++-- ext/session/sessionfault.test | 66 +++++++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 4 +++ manifest | 18 +++++----- manifest.uuid | 2 +- 6 files changed, 155 insertions(+), 12 deletions(-) diff --git a/ext/session/session9.test b/ext/session/session9.test index 3b42c31061..a9f61c872f 100644 --- a/ext/session/session9.test +++ b/ext/session/session9.test @@ -200,6 +200,7 @@ do_test 3.3 { do_test 3.3.1 { list [catch {sqlite3changeset_apply db $::ccdel1 conflict_handler} msg] $msg } {1 SQLITE_CONSTRAINT} + do_test 3.3.2 { list [catch {sqlite3changeset_apply db $::ccdel2 conflict_handler} msg] $msg } {1 SQLITE_CONSTRAINT} @@ -251,4 +252,37 @@ do_catchsql_test 4.3.2 { do_catchsql_test 4.3.3 { COMMIT } {0 {}} do_catchsql_test 4.3.4 { BEGIN ; COMMIT } {0 {}} +#-------------------------------------------------------------------- +# Test that if a DELETE change cannot be applied due to an +# SQLITE_CONSTRAINT error thrown by a trigger program, things do not +# go awry. + +drop_all_tables +reset_db +do_execsql_test 5.1 { + CREATE TABLE x1(x PRIMARY KEY, y); + CREATE TABLE x2(x PRIMARY KEY, y); + INSERT INTO x2 VALUES(1, 1); + INSERT INTO x1 VALUES(1, 1); +} + +set ::cc [changeset_from_sql { DELETE FROM x1; }] + +do_execsql_test 5.2 { + INSERT INTO x1 VALUES(1, 1); + CREATE TRIGGER tr1 AFTER DELETE ON x1 BEGIN + INSERT INTO x2 VALUES(old.x, old.y); + END; +} {} + +proc conflict_handler {args} { return "ABORT" } +do_test 5.3 { + list [catch {sqlite3changeset_apply db $::cc conflict_handler} msg] $msg +} {1 SQLITE_ABORT} + +do_execsql_test 5.4 { + SELECT * FROM X1; +} {1 1} + finish_test + diff --git a/ext/session/sessionA.test b/ext/session/sessionA.test index 1ca0f13709..8ee2046519 100644 --- a/ext/session/sessionA.test +++ b/ext/session/sessionA.test @@ -9,8 +9,7 @@ # #*********************************************************************** # -# This file tests that the sessions module handles foreign key constraint -# violations when applying changesets as required. +# This file tests that filter callbacks work as required. # if {![info exists testdir]} { @@ -63,6 +62,46 @@ do_test 2.1 { } db2 } {a b e f} +#------------------------------------------------------------------------- +# Test that filter callbacks passed to sqlite3changeset_apply() are +# invoked correctly. +# +reset_db +do_execsql_test 3.1 { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(x PRIMARY KEY, y); +} + +do_test 3.2 { + execsql BEGIN + set ::cs [changeset_from_sql { + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t2 VALUES('x', 'y'); + }] + execsql ROLLBACK + set {} {} +} {} + +proc filter {x y} { + return [string equal $x $y] +} + +do_test 3.3 { + sqlite3changeset_apply db $::cs {} [list filter t1] + execsql { + SELECT * FROM t1; + SELECT * FROM t2; + } +} {1 2} + +do_test 3.4 { + execsql { DELETE FROM t1 } + sqlite3changeset_apply db $::cs {} [list filter t2] + execsql { + SELECT * FROM t1; + SELECT * FROM t2; + } +} {x y} finish_test diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index c94589e372..39f27bfe6d 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -285,6 +285,38 @@ do_faultsim_test 5.2 -faults oom-tra* -body { } } +catch {db close} +catch {db2 close} +forcedelete test.db +sqlite3 db test.db +set abc [string repeat abc 256] +set def [string repeat def 256] +execsql " + CREATE TABLE t2(a PRIMARY KEY, b); + INSERT INTO t2 VALUES(1, '$abc'); +" +set changeset [changeset_from_sql " + INSERT INTO t2 VALUES(2, '$def'); + DELETE FROM t2 WHERE a = 1; +"] +db close + +do_faultsim_test 5.3 -faults oom-tra* -body { + set ::inverse [sqlite3changeset_invert $::changeset] + set {} {} +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + if {$testrc==0} { + set x [list] + sqlite3session_foreach c $::inverse { lappend x $c } + foreach c " + {INSERT t2 0 X. {} {i 1 t $::abc}} + {DELETE t2 0 X. {i 2 t $::def} {}} + " { lappend y $c } + if {$x != $y} { error "changeset no good" } + } +} + #------------------------------------------------------------------------- # Test that OOM errors in sqlite3changeset_concat() are handled correctly. # @@ -515,7 +547,41 @@ do_faultsim_test 10 -faults oom-tra* -prep { } } +#------------------------------------------------------------------------- +# Test an OOM with an sqlite3changeset_apply() filter callback. +# +reset_db +do_test 11.prep { + execsql { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(x PRIMARY KEY, y); + BEGIN; + } + set ::cs [changeset_from_sql { + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t2 VALUES('x', 'y'); + }] + + execsql ROLLBACK + set {} {} +} {} + +proc filter {x} { return [string equal t1 $x] } +faultsim_save_and_close + +do_faultsim_test 11 -faults oom-tra* -prep { + faultsim_restore_and_reopen +} -body { + sqlite3changeset_apply db $::cs {} filter +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + if {$testrc==0} { + if {[db eval {SELECT * FROM t1 UNION ALL SELECT * FROM t2}] != "1 2"} { + error "data does not look right" + } + } +} finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 7e69be4cc4..ed8d851083 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -3495,6 +3495,10 @@ static int sessionChangesetApply( schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew))); if( schemaMismatch ){ zTab = sqlite3_mprintf("%s", zNew); + if( zTab==0 ){ + rc = SQLITE_NOMEM; + break; + } nTab = (int)strlen(zTab); sApply.azCol = (const char **)zTab; }else{ diff --git a/manifest b/manifest index 4cb1bee75c..0d58beec13 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\ssegfault\sin\sthe\sstreaming\sAPI\sfunctions\striggered\sby\sa\svery\slong\stable\sname. -D 2014-09-27T16:33:09.345 +C Fix\sa\ssegfault\sin\sthe\ssessions\smodule\sthat\scould\sfollow\san\sOOM. +D 2014-09-27T18:18:32.969 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -153,12 +153,12 @@ F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 -F ext/session/session9.test 776e46785c29c11cda01f5205d0f1e8f8f9a46bf -F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 +F ext/session/session9.test b6dd1086de8c59b6f129923425487791f51c689c +F ext/session/sessionA.test 5543846eb9ca045217262f5d8c9376ce812e1ba5 F ext/session/sessionB.test d4ac901b43d4922a17dff08bbaa2f5354487ce4d F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 -F ext/session/sessionfault.test cf9758bfb6ccd5db5f09f170667a8cea1ac8afa7 -F ext/session/sqlite3session.c 228cca8fdb6fd07942be097c516f22e39ec39e3c +F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc +F ext/session/sqlite3session.c 0691b8d7434edb07166828778540bb418a7a68e3 F ext/session/sqlite3session.h b57009fb88835cc4684376bd3eae0d6ab364968a F ext/session/test_session.c 56a4ddd443b571c8d365b03197c032bdaed1443a F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1216,7 +1216,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P bfc8bd80f8b225cebc66478448510ce84223ae7d -R 9ca53892e63f9c31475266a6b3e34d34 +P d2642543eed54da1ac0f757d43dd4d72482eb752 +R 7328e4de54076fa7989cf4f3b00a08d8 U dan -Z f7759b84adfee5a6c178fa61db492ce5 +Z 371024a806f6988dfc33105901bfbbae diff --git a/manifest.uuid b/manifest.uuid index 903686ec1f..d5a74ccbec 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d2642543eed54da1ac0f757d43dd4d72482eb752 \ No newline at end of file +09985fa6b60a0bf38e23bbccd4d8e1d1cbf66124 \ No newline at end of file From f1a08ad88ded911534463a7ffa2c298612452f7f Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 27 Sep 2014 20:45:48 +0000 Subject: [PATCH 128/570] Change the names of the stream interface APIs to be of the form "_strm" instead of "_str". In other words, added an "m" to the end, to try to make it clear that we are talking about a "stream" and not a "string. FossilOrigin-Name: 1f44bfdc237ee6304f4aa56e5c5d1c0d74fcc944 --- ext/session/session5.test | 1 - ext/session/session8.test | 1 - ext/session/session9.test | 1 - ext/session/sessionA.test | 2 -- ext/session/sessionB.test | 1 - ext/session/session_common.tcl | 1 - ext/session/sqlite3session.c | 44 ++++++++++++++++++---------------- ext/session/sqlite3session.h | 16 ++++++------- ext/session/test_session.c | 12 +++++----- manifest | 32 ++++++++++++------------- manifest.uuid | 2 +- test/permutations.test | 2 +- test/session.test | 2 +- 13 files changed, 56 insertions(+), 61 deletions(-) diff --git a/ext/session/session5.test b/ext/session/session5.test index 88430057d0..9b8f9ffe12 100644 --- a/ext/session/session5.test +++ b/ext/session/session5.test @@ -406,4 +406,3 @@ do_concat_test2 4.4 { } finish_test - diff --git a/ext/session/session8.test b/ext/session/session8.test index 93bd4e06c3..9f70fe2829 100644 --- a/ext/session/session8.test +++ b/ext/session/session8.test @@ -89,4 +89,3 @@ do_then_undo 3.2 { UPDATE t3 SET b=b||b WHERE e!='x' } do_then_undo 3.3 { UPDATE t3 SET a = 46 } finish_test - diff --git a/ext/session/session9.test b/ext/session/session9.test index a9f61c872f..ebb88ffade 100644 --- a/ext/session/session9.test +++ b/ext/session/session9.test @@ -285,4 +285,3 @@ do_execsql_test 5.4 { } {1 1} finish_test - diff --git a/ext/session/sessionA.test b/ext/session/sessionA.test index 8ee2046519..0e0a14e38a 100644 --- a/ext/session/sessionA.test +++ b/ext/session/sessionA.test @@ -104,5 +104,3 @@ do_test 3.4 { } {x y} finish_test - - diff --git a/ext/session/sessionB.test b/ext/session/sessionB.test index b11c3110a1..f1af5d213c 100644 --- a/ext/session/sessionB.test +++ b/ext/session/sessionB.test @@ -516,4 +516,3 @@ do_patchset_changeset_test 5.3 \ finish_test - diff --git a/ext/session/session_common.tcl b/ext/session/session_common.tcl index 53870c4027..d6ce27a850 100644 --- a/ext/session/session_common.tcl +++ b/ext/session/session_common.tcl @@ -133,4 +133,3 @@ proc changeset_to_list {c} { sqlite3session_foreach elem $c { lappend list $elem } lsort $list } - diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index ed8d851083..fe7d6e5a21 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -17,10 +17,12 @@ typedef struct SessionInput SessionInput; /* ** Minimum chunk size used by streaming versions of functions. */ -#ifdef SQLITE_TEST -#define SESSIONS_STR_CHUNK_SIZE 64 -#else -#define SESSIONS_STR_CHUNK_SIZE 1024 +#ifndef SESSIONS_STRM_CHUNK_SIZE +# ifdef SQLITE_TEST +# define SESSIONS_STRM_CHUNK_SIZE 64 +# else +# define SESSIONS_STRM_CHUNK_SIZE 1024 +# endif #endif /* @@ -52,7 +54,7 @@ struct SessionBuffer { ** An object of this type is used internally as an abstraction for ** input data. Input data may be supplied either as a single large buffer ** (e.g. sqlite3changeset_start()) or using a stream function (e.g. -** sqlite3changeset_start_str()). +** sqlite3changeset_start_strm()). */ struct SessionInput { int iNext; /* Offset in aData[] of next change */ @@ -1907,12 +1909,12 @@ int sessionGenerateChangeset( rc = sqlite3_reset(pSel); } - /* If the buffer is now larger than SESSIONS_STR_CHUNK_SIZE, pass + /* If the buffer is now larger than SESSIONS_STRM_CHUNK_SIZE, pass ** its contents to the xOutput() callback. */ if( xOutput && rc==SQLITE_OK && buf.nBuf>nNoop - && buf.nBuf>SESSIONS_STR_CHUNK_SIZE + && buf.nBuf>SESSIONS_STRM_CHUNK_SIZE ){ rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf); nNoop = -1; @@ -1964,7 +1966,7 @@ int sqlite3session_changeset( /* ** Streaming version of sqlite3session_changeset(). */ -int sqlite3session_changeset_str( +int sqlite3session_changeset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut @@ -1975,7 +1977,7 @@ int sqlite3session_changeset_str( /* ** Streaming version of sqlite3session_patchset(). */ -int sqlite3session_patchset_str( +int sqlite3session_patchset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut @@ -2044,7 +2046,7 @@ int sqlite3session_isempty(sqlite3_session *pSession){ } /* -** Do the work for either sqlite3changeset_start() or start_str(). +** Do the work for either sqlite3changeset_start() or start_strm(). */ int sessionChangesetStart( sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ @@ -2092,7 +2094,7 @@ int sqlite3changeset_start( /* ** Streaming version of sqlite3changeset_start(). */ -int sqlite3changeset_start_str( +int sqlite3changeset_start_strm( sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn @@ -2111,9 +2113,9 @@ static int sessionInputBuffer(SessionInput *pIn, int nByte){ int rc = SQLITE_OK; if( pIn->xInput ){ while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){ - int nNew = SESSIONS_STR_CHUNK_SIZE; + int nNew = SESSIONS_STRM_CHUNK_SIZE; - if( pIn->iNext>=SESSIONS_STR_CHUNK_SIZE ){ + if( pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ int nMove = pIn->buf.nBuf - pIn->iNext; memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove); pIn->buf.nBuf -= pIn->iNext; @@ -2801,7 +2803,7 @@ static int sessionChangesetInvert( } assert( rc==SQLITE_OK ); - if( xOutput && sOut.nBuf>=SESSIONS_STR_CHUNK_SIZE ){ + if( xOutput && sOut.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); sOut.nBuf = 0; if( rc!=SQLITE_OK ) goto finished_invert; @@ -2847,7 +2849,7 @@ int sqlite3changeset_invert( /* ** Streaming version of sqlite3changeset_invert(). */ -int sqlite3changeset_invert_str( +int sqlite3changeset_invert_strm( int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int (*xOutput)(void *pOut, const void *pData, int nData), @@ -3641,7 +3643,7 @@ int sqlite3changeset_apply( ** attached to handle "db". Invoke the supplied conflict handler callback ** to resolve any conflicts encountered while applying the change. */ -int sqlite3changeset_apply_str( +int sqlite3changeset_apply_strm( sqlite3 *db, /* Apply change to "main" db of this handle */ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ void *pIn, /* First arg for xInput */ @@ -3657,7 +3659,7 @@ int sqlite3changeset_apply_str( void *pCtx /* First argument passed to xConflict */ ){ sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int rc = sqlite3changeset_start_str(&pIter, xInput, pIn); + int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); if( rc==SQLITE_OK ){ rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); } @@ -3932,7 +3934,7 @@ int sessionChangesetConcat( } } - if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STR_CHUNK_SIZE ){ + if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ rc = xOutput(pOut, buf.aBuf, buf.nBuf); buf.nBuf = 0; } @@ -3986,7 +3988,7 @@ int sqlite3changeset_concat( /* ** Streaming version of sqlite3changeset_concat(). */ -int sqlite3changeset_concat_str( +int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, int (*xInputB)(void *pIn, void *pData, int *pnData), @@ -3998,9 +4000,9 @@ int sqlite3changeset_concat_str( sqlite3_changeset_iter *pIter2 = 0; int rc; - rc = sqlite3changeset_start_str(&pIter1, xInputA, pInA); + rc = sqlite3changeset_start_strm(&pIter1, xInputA, pInA); if( rc==SQLITE_OK ){ - rc = sqlite3changeset_start_str(&pIter2, xInputB, pInB); + rc = sqlite3changeset_start_strm(&pIter2, xInputB, pInB); } if( rc==SQLITE_OK ){ rc = sessionChangesetConcat(pIter1, pIter2, xOutput, pOut, 0, 0); diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 0dd03067ed..e768d66324 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -946,7 +946,7 @@ int sqlite3changeset_apply( /* ** CAPI3REF: Streaming Versions of API functions. ** -** The six streaming API xxx_str() functions serve similar purposes to the +** The six streaming API xxx_strm() functions serve similar purposes to the ** corresponding non-streaming API functions: ** ** @@ -995,7 +995,7 @@ int sqlite3changeset_apply( ** an error, all processing is abandoned and the streaming API function ** returns a copy of the error code to the caller. ** -** In the case of sqlite3changeset_start_str(), the xInput callback may be +** In the case of sqlite3changeset_start_strm(), the xInput callback may be ** invoked by the sessions module at any point during the lifetime of the ** iterator. If such an xInput callback returns an error, the iterator enters ** an error state, whereby all subsequent calls to iterator functions @@ -1032,7 +1032,7 @@ int sqlite3changeset_apply( ** parameter set to a value less than or equal to zero. Other than this, ** no guarantees are made as to the size of the chunks of data returned. */ -int sqlite3changeset_apply_str( +int sqlite3changeset_apply_strm( sqlite3 *db, /* Apply change to "main" db of this handle */ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ void *pIn, /* First arg for xInput */ @@ -1047,7 +1047,7 @@ int sqlite3changeset_apply_str( ), void *pCtx /* First argument passed to xConflict */ ); -int sqlite3changeset_concat_str( +int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, int (*xInputB)(void *pIn, void *pData, int *pnData), @@ -1055,23 +1055,23 @@ int sqlite3changeset_concat_str( int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); -int sqlite3changeset_invert_str( +int sqlite3changeset_invert_strm( int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); -int sqlite3changeset_start_str( +int sqlite3changeset_start_strm( sqlite3_changeset_iter **pp, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); -int sqlite3session_changeset_str( +int sqlite3session_changeset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); -int sqlite3session_patchset_str( +int sqlite3session_patchset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 7e366ef3bb..6c538bcec1 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -160,9 +160,9 @@ static int test_session_cmd( if( test_tcl_integer(interp, SESSION_STREAM_TCL_VAR) ){ void *pCtx = (void*)&o; if( iSub==7 ){ - rc = sqlite3session_patchset_str(pSession, testStreamOutput, pCtx); + rc = sqlite3session_patchset_strm(pSession, testStreamOutput, pCtx); }else{ - rc = sqlite3session_changeset_str(pSession, testStreamOutput, pCtx); + rc = sqlite3session_changeset_strm(pSession, testStreamOutput, pCtx); } }else{ if( iSub==7 ){ @@ -626,7 +626,7 @@ static int test_sqlite3changeset_apply( }else{ sStr.aData = (unsigned char*)pChangeset; sStr.nData = nChangeset; - rc = sqlite3changeset_apply_str(db, testStreamInput, (void*)&sStr, + rc = sqlite3changeset_apply_strm(db, testStreamInput, (void*)&sStr, (objc==5) ? test_filter_handler : 0, test_conflict_handler, (void *)&ctx ); } @@ -697,7 +697,7 @@ static int test_sqlite3changeset_invert( sIn.aData = Tcl_GetByteArrayFromObj(objv[1], &sIn.nData); if( sIn.nStream ){ - rc = sqlite3changeset_invert_str( + rc = sqlite3changeset_invert_strm( testStreamInput, (void*)&sIn, testStreamOutput, (void*)&sOut ); }else{ @@ -740,7 +740,7 @@ static int test_sqlite3changeset_concat( sRight.nStream = sLeft.nStream; if( sLeft.nStream>0 ){ - rc = sqlite3changeset_concat_str( + rc = sqlite3changeset_concat_strm( testStreamInput, (void*)&sLeft, testStreamInput, (void*)&sRight, testStreamOutput, (void*)&sOut @@ -801,7 +801,7 @@ static int test_sqlite3session_foreach( }else{ sStr.aData = (unsigned char*)pChangeset; sStr.nData = nChangeset; - rc = sqlite3changeset_start_str(&pIter, testStreamInput, (void*)&sStr); + rc = sqlite3changeset_start_strm(&pIter, testStreamInput, (void*)&sStr); } if( rc!=SQLITE_OK ){ return test_session_error(interp, rc); diff --git a/manifest b/manifest index da8cd912d5..36205b94dd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\srecent\strunk\schanges\s(performance\senhancements)\sinto\sthe\ssessions\nbranch. -D 2014-09-27T19:51:50.438 +C Change\sthe\snames\sof\sthe\sstream\sinterface\sAPIs\sto\sbe\sof\sthe\sform\n"_strm"\sinstead\sof\s"_str".\s\sIn\sother\swords,\sadded\san\s"m"\sto\sthe\send,\sto\ntry\sto\smake\sit\sclear\sthat\swe\sare\stalking\sabout\sa\s"stream"\sand\snot\sa\s"string. +D 2014-09-27T20:45:48.295 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -150,17 +150,17 @@ F ext/session/session1.test 4653867f32a98ce4bbb4a181aac6debe51ca4dfb F ext/session/session2.test 99ca0da7ddb617d42bafd83adccf99f18ae0384b F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 -F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 +F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 -F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 -F ext/session/session9.test b6dd1086de8c59b6f129923425487791f51c689c -F ext/session/sessionA.test 5543846eb9ca045217262f5d8c9376ce812e1ba5 -F ext/session/sessionB.test d4ac901b43d4922a17dff08bbaa2f5354487ce4d -F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 +F ext/session/session8.test 8e194b3f655d861ca36de5d4de53f702751bab3b +F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069 +F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f +F ext/session/sessionB.test 06961b7c3641151f5d23088250ecad132501113c +F ext/session/session_common.tcl 9de0451b6a47218fc16b9ed8876b6238a0a3d88d F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c 0691b8d7434edb07166828778540bb418a7a68e3 -F ext/session/sqlite3session.h b57009fb88835cc4684376bd3eae0d6ab364968a -F ext/session/test_session.c 56a4ddd443b571c8d365b03197c032bdaed1443a +F ext/session/sqlite3session.c 67b8aee718cf34e267f4040d9b945a7a6407b0b2 +F ext/session/sqlite3session.h 16608d29879a0ed3c6be6b7fb18dcdb5c707aaef +F ext/session/test_session.c a28352e99bc6a83b94e4cce99a7bf25c73d6d489 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e @@ -777,7 +777,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0 F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54 -F test/permutations.test b8ca6c9ecec6f360485a8cb61ef1b8734b31797b +F test/permutations.test a33230010a3d4ce0c57d586672ccef10a7d1af29 F test/pragma.test 19d0241a007bcdd77fc2606ec60fc60357e7fc8b F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 @@ -833,7 +833,7 @@ F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394 F test/selectE.test fc02a1eb04c8eb537091482644b7d778ae8759b7 F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3 F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118 -F test/session.test 35f9c76809c26bee45d86891c7620b692ef9b8a8 +F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746 F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879 F test/shared3.test fcd65cb11d189eff5f5c85cc4fad246fb0933108 @@ -1217,7 +1217,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 09985fa6b60a0bf38e23bbccd4d8e1d1cbf66124 d026f0c944ce812732d3595eaa3c5d432a86c7dd -R 6b80dc3719dfaf6510fd0fc97f44558f +P 497367cb57345dd37793e5f369b34d12be56172e +R cc11bbbd763a56bfdd0667ee0dcdded3 U drh -Z 29718882bdf5b938c85c12503154fa25 +Z 9e5912d3733f34c1f4a27e9b30386e30 diff --git a/manifest.uuid b/manifest.uuid index 8ff815c08d..55c0eb0873 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -497367cb57345dd37793e5f369b34d12be56172e \ No newline at end of file +1f44bfdc237ee6304f4aa56e5c5d1c0d74fcc944 \ No newline at end of file diff --git a/test/permutations.test b/test/permutations.test index 44f571793c..5fd50cc2d5 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -938,7 +938,7 @@ test_suite "session_eec" -description { sqlite3_extended_result_codes $::dbhandle 1 } -test_suite "session_str" -description { +test_suite "session_strm" -description { All session module related tests using the streaming APIs. } -files [ glob -nocomplain $::testdir/../ext/session/*.test diff --git a/test/session.test b/test/session.test index da04ac45c5..4fd1ec0184 100644 --- a/test/session.test +++ b/test/session.test @@ -16,7 +16,7 @@ ifcapable session { # again with it clear. run_test_suite session_eec run_test_suite session - run_test_suite session_str + run_test_suite session_strm } finish_test From abae0c4f1d3b9ce7a9d6342b61ec000117df1d63 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 15 Oct 2014 20:02:21 +0000 Subject: [PATCH 129/570] Fix a problem causing sqlite3changeset_concat() to fail to detect attempts to concatenate patchsets which changesets. FossilOrigin-Name: 236704a9d1551a50a55bd6e0b6473191a7a7dd21 --- ext/session/sessionC.test | 190 +++++++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 6 ++ manifest | 13 +-- manifest.uuid | 2 +- 4 files changed, 204 insertions(+), 7 deletions(-) create mode 100644 ext/session/sessionC.test diff --git a/ext/session/sessionC.test b/ext/session/sessionC.test new file mode 100644 index 0000000000..81cc53f5a6 --- /dev/null +++ b/ext/session/sessionC.test @@ -0,0 +1,190 @@ +# 2014 August 16 +# +# 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. +# +#*********************************************************************** +# +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} + +set testprefix sessionC + +#------------------------------------------------------------------------- +# Test the outcome of a DELETE operation made as part of applying a +# changeset failing with SQLITE_CONSTRAINT. This may happen if an +# ON DELETE RESTRICT foreign key action is triggered, or if a trigger +# program raises a constraint somehow. +# +do_execsql_test 1.0 { + PRAGMA foreign_keys = 1; + + CREATE TABLE p(a PRIMARY KEY, b, c); + CREATE TABLE c(d PRIMARY KEY, e REFERENCES p ON DELETE RESTRICT); + + INSERT INTO p VALUES('one', 1, 1); + INSERT INTO p VALUES('two', 2, 2); + INSERT INTO p VALUES('three', 3, 3); + + INSERT INTO c VALUES(1, 'one'); + INSERT INTO c VALUES(3, 'three'); +} + +do_test 1.1 { + execsql BEGIN + set C [changeset_from_sql { + INSERT INTO c VALUES(4, 'one'); + DELETE FROM p WHERE a='two'; + }] + execsql ROLLBACK + execsql { + INSERT INTO c VALUES(2, 'two'); + } +} {} + +do_test 1.2.1 { + proc xConflict {args} { return "ABORT" } + catch { sqlite3changeset_apply db $C xConflict } msg + set msg +} {SQLITE_ABORT} +do_execsql_test 1.2.2 { SELECT * FROM c } {1 one 3 three 2 two} + +do_test 1.3.1 { + proc xConflict {args} { return "OMIT" } + catch { sqlite3changeset_apply db $C xConflict } msg + set msg +} {} +do_execsql_test 1.3.2 { SELECT * FROM c } {1 one 3 three 2 two 4 one} +do_execsql_test 1.3.3 { + SELECT * FROM p; +} {one 1 1 two 2 2 three 3 3} + + +#------------------------------------------------------------------------- +# Test that concatenating a changeset with a patchset does not work. +# Any attempt to do so returns SQLITE_ERROR. +# +reset_db +do_execsql_test 2.0 { + CREATE TABLE x1(t, v PRIMARY KEY); + INSERT INTO x1 VALUES(12, 55); + INSERT INTO x1 VALUES(55, 14); +} + +do_test 2.1 { + execsql BEGIN + + sqlite3session S1 db main + S1 attach * + execsql { + UPDATE x1 SET t=13 WHERE v=55; + INSERT INTO x1 VALUES(99, 123); + } + set patchset [S1 patchset] + S1 delete + + sqlite3session S1 db main + S1 attach * + execsql { + UPDATE x1 SET t=56 WHERE v=14; + INSERT INTO x1 VALUES(22, 998); + } + set changeset [S1 changeset] + S1 delete + + execsql ROLLBACK +} {} + +do_test 2.2 { + set rc [catch { sqlite3changeset_concat $patchset $changeset } msg] + list $rc $msg +} {1 SQLITE_ERROR} + +do_test 2.3 { + set rc [catch { sqlite3changeset_concat $changeset $patchset } msg] + list $rc $msg +} {1 SQLITE_ERROR} + +do_test 2.4 { + set rc [catch { sqlite3changeset_concat {} $patchset } msg] + list $rc $msg +} [list 0 $patchset] + +do_test 2.5 { + set rc [catch { sqlite3changeset_concat $patchset {} } msg] + list $rc $msg +} [list 0 $patchset] + +do_test 2.6 { + set rc [catch { sqlite3changeset_concat {} $changeset } msg] + list $rc $msg +} [list 0 $changeset] + +do_test 2.7 { + set rc [catch { sqlite3changeset_concat $changeset {} } msg] + list $rc $msg +} [list 0 $changeset] + +do_test 2.8 { + set rc [catch { sqlite3changeset_concat {} {} } msg] + list $rc $msg +} [list 0 {}] + + +#------------------------------------------------------------------------- +# Test that the xFilter argument to sqlite3changeset_apply() works. +# +reset_db +do_execsql_test 3.0 { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(a PRIMARY KEY, b); + CREATE TABLE t3(a PRIMARY KEY, b); +} +do_test 3.1 { + execsql BEGIN + set changeset [changeset_from_sql { + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t2 VALUES(2, 2); + INSERT INTO t3 VALUES(3, 3); + }] + execsql ROLLBACK +} {} +do_test 3.2 { + proc xFilter {zName} { + if {$zName == "t1"} { return 1 } + return 0 + } + sqlite3changeset_apply db $changeset noop xFilter + execsql { + SELECT * FROM t1; + SELECT * FROM t2; + SELECT * FROM t3; + } +} {1 1} +do_test 3.3 { + proc xFilter {zName} { + if {$zName == "t3"} { return 1 } + return 0 + } + sqlite3changeset_apply db $changeset noop xFilter + execsql { + SELECT * FROM t1; + SELECT * FROM t2; + SELECT * FROM t3; + } +} {1 1 3 3} + + + +finish_test + diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index fe7d6e5a21..f861bd1ec6 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -3911,12 +3911,18 @@ int sessionChangesetConcat( assert( xOutput==0 || (ppOut==0 && pnOut==0) ); + assert( pLeft->zTab==0 && pRight->zTab==0 ); rc = sessionChangesetToHash(pLeft, &pList); + assert( pLeft->zTab || pList==0 ); if( rc==SQLITE_OK ){ rc = sessionChangesetToHash(pRight, &pList); } bPatch = pLeft->bPatchset || pRight->bPatchset; + if( pLeft->zTab && pRight->zTab && pLeft->bPatchset!=pRight->bPatchset ){ + rc = SQLITE_ERROR; + } + /* Create the serialized output changeset based on the contents of the ** hash tables attached to the SessionTable objects in list pList. */ diff --git a/manifest b/manifest index 9b98ed7c5f..193e5f6c38 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\slatest\strunk\schanges\swith\sthis\sbranch. -D 2014-10-15T19:37:13.299 +C Fix\sa\sproblem\scausing\ssqlite3changeset_concat()\sto\sfail\sto\sdetect\sattempts\sto\sconcatenate\spatchsets\swhich\schangesets. +D 2014-10-15T20:02:21.265 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -156,9 +156,10 @@ F ext/session/session8.test 8e194b3f655d861ca36de5d4de53f702751bab3b F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069 F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f F ext/session/sessionB.test 06961b7c3641151f5d23088250ecad132501113c +F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4 F ext/session/session_common.tcl 9de0451b6a47218fc16b9ed8876b6238a0a3d88d F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c 67b8aee718cf34e267f4040d9b945a7a6407b0b2 +F ext/session/sqlite3session.c 838050c4c217d2843e4705b14be25d8f0457f155 F ext/session/sqlite3session.h 16608d29879a0ed3c6be6b7fb18dcdb5c707aaef F ext/session/test_session.c a28352e99bc6a83b94e4cce99a7bf25c73d6d489 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1221,7 +1222,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 83d4114f2aa404e670ced33511183baacd813a01 3c1e70f4d55bc009ed9ed4cf6d756d7061985851 -R 573bb7e03bcfc05e0f889e571f4f3aa7 +P 1b2824f1d11ac336779372e322aecfb36fb2a31d +R fa664b8794125d09d3da5d2babd6e792 U dan -Z d7531a3919881ed86fbddd665aff411c +Z 8d94920cff847cf3f9fcffe7f6436f08 diff --git a/manifest.uuid b/manifest.uuid index 1d5dadfa49..4a7ff9ad2f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1b2824f1d11ac336779372e322aecfb36fb2a31d \ No newline at end of file +236704a9d1551a50a55bd6e0b6473191a7a7dd21 \ No newline at end of file From cf8e91442d4b66812f8080cf3e916523ad858b11 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 8 Apr 2015 16:01:12 +0000 Subject: [PATCH 130/570] Add experimental API sqlite3session_diff(). FossilOrigin-Name: c4340b2ea2115ad97dcac036f9034e132ab789e5 --- ext/session/session2.test | 10 + ext/session/sessionD.test | 150 ++++++++++++ ext/session/sqlite3session.c | 431 ++++++++++++++++++++++++++++++----- ext/session/sqlite3session.h | 57 +++++ ext/session/test_session.c | 35 ++- manifest | 24 +- manifest.uuid | 2 +- 7 files changed, 636 insertions(+), 73 deletions(-) create mode 100644 ext/session/sessionD.test diff --git a/ext/session/session2.test b/ext/session/session2.test index 04be5f0917..0035e39dbf 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -169,7 +169,17 @@ set set_of_tests { INSERT INTO %T4% VALUES('def', 'abc'); } 17 { UPDATE %T4% SET b = 1 } + 18 { DELETE FROM %T4% WHERE 1 } + + 19 { + INSERT INTO t1 VALUES('', ''); + INSERT INTO t1 VALUES(X'', X''); + } + 20 { + DELETE FROM t1; + INSERT INTO t1 VALUES('', NULL); + } } test_reset diff --git a/ext/session/sessionD.test b/ext/session/sessionD.test new file mode 100644 index 0000000000..c26728742a --- /dev/null +++ b/ext/session/sessionD.test @@ -0,0 +1,150 @@ +# 2014 August 16 +# +# 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 focuses on the sqlite3session_diff() function. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} + +set testprefix sessionD + +proc scksum {db dbname} { + + if {$dbname=="temp"} { + set master sqlite_temp_master + } else { + set master $dbname.sqlite_master + } + + set alltab [$db eval "SELECT name FROM $master WHERE type='table'"] + set txt [$db eval "SELECT * FROM $master ORDER BY type,name,sql"] + foreach tab $alltab { + set cols [list] + db eval "PRAGMA $dbname.table_info = $tab" x { + lappend cols "quote($x(name))" + } + set cols [join $cols ,] + append txt [db eval "SELECT $cols FROM $tab ORDER BY $cols"] + } + return [md5 $txt] +} + +proc do_diff_test {tn setup} { + reset_db + forcedelete test.db2 + execsql { ATTACH 'test.db2' AS aux } + execsql $setup + + sqlite3session S db main + foreach tbl [db eval {SELECT name FROM sqlite_master WHERE type='table'}] { + S attach $tbl + S diff aux $tbl + } + + set C [S changeset] + S delete + + sqlite3 db2 test.db2 + sqlite3changeset_apply db2 $C "" + uplevel do_test $tn.1 [list {execsql { PRAGMA integrity_check } db2}] ok + db2 close + + set cksum [scksum db main] + uplevel do_test $tn.2 [list {scksum db aux}] [list $cksum] +} + + +forcedelete test.db2 +do_execsql_test 1.0 { + CREATE TABLE t2(a PRIMARY KEY, b); + INSERT INTO t2 VALUES(1, 'one'); + INSERT INTO t2 VALUES(2, 'two'); + + ATTACH 'test.db2' AS aux; + CREATE TABLE aux.t2(a PRIMARY KEY, b); +} + +do_test 1.1 { + sqlite3session S db main + S attach t2 + S diff aux t2 + set C [S changeset] + S delete +} {} + +do_test 1.2 { + sqlite3 db2 test.db2 + sqlite3changeset_apply db2 $C "" + db2 close + db eval { SELECT * FROM aux.t2 } +} {1 one 2 two} + +do_diff_test 2.1 { + CREATE TABLE aux.t1(x, y, PRIMARY KEY(y)); + CREATE TABLE t1(x, y, PRIMARY KEY(y)); + + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(NULL, 'xyz'); + INSERT INTO t1 VALUES(4.5, 5.5); +} + +do_diff_test 2.2 { + CREATE TABLE aux.t1(x, y, PRIMARY KEY(y)); + CREATE TABLE t1(x, y, PRIMARY KEY(y)); + + INSERT INTO aux.t1 VALUES(1, 2); + INSERT INTO aux.t1 VALUES(NULL, 'xyz'); + INSERT INTO aux.t1 VALUES(4.5, 5.5); +} + +do_diff_test 2.3 { + CREATE TABLE aux.t1(a PRIMARY KEY, b TEXT); + CREATE TABLE t1(a PRIMARY KEY, b TEXT); + + INSERT INTO aux.t1 VALUES(1, 'one'); + INSERT INTO aux.t1 VALUES(2, 'two'); + INSERT INTO aux.t1 VALUES(3, 'three'); + + INSERT INTO t1 VALUES(1, 'I'); + INSERT INTO t1 VALUES(2, 'two'); + INSERT INTO t1 VALUES(3, 'III'); +} + +do_diff_test 2.4 { + CREATE TABLE aux.t1(a, b, c, d, PRIMARY KEY(c, b, a)); + CREATE TABLE t1(a, b, c, d, PRIMARY KEY(c, b, a)); + + INSERT INTO t1 VALUES('hvkzyipambwdqlvwv','',-458331.50,X'DA51ED5E84'); + INSERT INTO t1 VALUES(X'C5C6B5DD','jjxrath',40917,830244); + INSERT INTO t1 VALUES(-204877.54,X'1704C253D5F3AFA8',155120.88,NULL); + INSERT INTO t1 + VALUES('ckmqmzoeuvxisxqy',X'EB5A5D3A1DD22FD1','tidhjcbvbppdt',-642987.37); + INSERT INTO t1 VALUES(-851726,-161992,-469943,-159541); + INSERT INTO t1 VALUES(X'4A6A667F858938',185083,X'7A',NULL); + + INSERT INTO aux.t1 VALUES(415075.74,'auawczkb',X'',X'57B4FAAF2595'); + INSERT INTO aux.t1 VALUES(727637,711560,-181340,'hphuo'); + INSERT INTO aux.t1 + VALUES(-921322.81,662959,'lvlgwdgxaurr','ajjrzrbhqflsutnymgc'); + INSERT INTO aux.t1 VALUES(-146061,-377892,X'4E','gepvpvvuhszpxabbb'); + INSERT INTO aux.t1 VALUES(-851726,-161992,-469943,-159541); + INSERT INTO aux.t1 VALUES(X'4A6A667F858938',185083,X'7A',NULL); + INSERT INTO aux.t1 VALUES(-204877.54,X'1704C253D5F3AFA8',155120.88, 4); + INSERT INTO aux.t1 + VALUES('ckmqmzoeuvxisxqy',X'EB5A5D3A1DD22FD1','tidgtsplhjcbvbppdt',-642987.3); +} + +finish_test + diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index f861bd1ec6..5966947820 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -25,6 +25,15 @@ typedef struct SessionInput SessionInput; # endif #endif +typedef struct SessionHook SessionHook; +struct SessionHook { + void *pCtx; + int (*xOld)(void*,int,sqlite3_value**); + int (*xNew)(void*,int,sqlite3_value**); + int (*xCount)(void*); + int (*xDepth)(void*); +}; + /* ** Session handle structure. */ @@ -39,6 +48,7 @@ struct sqlite3_session { int (*xTableFilter)(void *pCtx, const char *zTab); sqlite3_session *pNext; /* Next session object on same db. */ SessionTable *pTable; /* List of attached tables */ + SessionHook hook; /* APIs to grab new and old data with */ }; /* @@ -316,8 +326,8 @@ static int sessionSerializeValue( }else{ z = (u8 *)sqlite3_value_blob(pValue); } - if( z==0 ) return SQLITE_NOMEM; n = sqlite3_value_bytes(pValue); + if( z==0 && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM; nVarint = sessionVarintLen(n); if( aBuf ){ @@ -397,7 +407,7 @@ static unsigned int sessionHashAppendType(unsigned int h, int eType){ ** and the output variables are set as described above. */ static int sessionPreupdateHash( - sqlite3 *db, /* Database handle */ + sqlite3_session *pSession, /* Session object that owns pTab */ SessionTable *pTab, /* Session table handle */ int bNew, /* True to hash the new.* PK */ int *piHash, /* OUT: Hash value */ @@ -407,7 +417,7 @@ static int sessionPreupdateHash( int i; /* Used to iterate through columns */ assert( *pbNullPK==0 ); - assert( pTab->nCol==sqlite3_preupdate_count(db) ); + assert( pTab->nCol==pSession->hook.xCount(pSession->hook.pCtx) ); for(i=0; inCol; i++){ if( pTab->abPK[i] ){ int rc; @@ -415,9 +425,9 @@ static int sessionPreupdateHash( sqlite3_value *pVal; if( bNew ){ - rc = sqlite3_preupdate_new(db, i, &pVal); + rc = pSession->hook.xNew(pSession->hook.pCtx, i, &pVal); }else{ - rc = sqlite3_preupdate_old(db, i, &pVal); + rc = pSession->hook.xOld(pSession->hook.pCtx, i, &pVal); } if( rc!=SQLITE_OK ) return rc; @@ -435,13 +445,15 @@ static int sessionPreupdateHash( h = sessionHashAppendI64(h, iVal); }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ const u8 *z; + int n; if( eType==SQLITE_TEXT ){ z = (const u8 *)sqlite3_value_text(pVal); }else{ z = (const u8 *)sqlite3_value_blob(pVal); } - if( !z ) return SQLITE_NOMEM; - h = sessionHashAppendBlob(h, sqlite3_value_bytes(pVal), z); + n = sqlite3_value_bytes(pVal); + if( !z && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM; + h = sessionHashAppendBlob(h, n, z); }else{ assert( eType==SQLITE_NULL ); *pbNullPK = 1; @@ -721,11 +733,12 @@ static int sessionMergeUpdate( ** false. */ static int sessionPreupdateEqual( - sqlite3 *db, /* Database handle */ + sqlite3_session *pSession, /* Session object that owns SessionTable */ SessionTable *pTab, /* Table associated with change */ SessionChange *pChange, /* Change to compare to */ int op /* Current pre-update operation */ ){ + sqlite3 *db = pSession->db; int iCol; /* Used to iterate through columns */ u8 *a = pChange->aRecord; /* Cursor used to scan change record */ @@ -744,11 +757,11 @@ static int sessionPreupdateEqual( ** within sessionPreupdateHash(). The first two asserts below verify ** this (that the method has already been called). */ if( op==SQLITE_INSERT ){ - assert( db->pPreUpdate->pNewUnpacked || db->pPreUpdate->aNew ); - rc = sqlite3_preupdate_new(db, iCol, &pVal); + /* assert( db->pPreUpdate->pNewUnpacked || db->pPreUpdate->aNew ); */ + rc = pSession->hook.xNew(pSession->hook.pCtx, iCol, &pVal); }else{ - assert( db->pPreUpdate->pUnpacked ); - rc = sqlite3_preupdate_old(db, iCol, &pVal); + /* assert( db->pPreUpdate->pUnpacked ); */ + rc = pSession->hook.xOld(pSession->hook.pCtx, iCol, &pVal); } assert( rc==SQLITE_OK ); if( sqlite3_value_type(pVal)!=eType ) return 0; @@ -976,7 +989,7 @@ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ ); } if( pSession->rc==SQLITE_OK - && pTab->nCol!=sqlite3_preupdate_count(pSession->db) + && pTab->nCol!=pSession->hook.xCount(pSession->hook.pCtx) ){ pSession->rc = SQLITE_SCHEMA; } @@ -996,9 +1009,8 @@ static void sessionPreupdateOneChange( sqlite3_session *pSession, /* Session object pTab is attached to */ SessionTable *pTab /* Table that change applies to */ ){ - sqlite3 *db = pSession->db; int iHash; - int bNullPk = 0; + int bNull = 0; int rc = SQLITE_OK; if( pSession->rc ) return; @@ -1015,14 +1027,14 @@ static void sessionPreupdateOneChange( /* Calculate the hash-key for this change. If the primary key of the row ** includes a NULL value, exit early. Such changes are ignored by the ** session module. */ - rc = sessionPreupdateHash(db, pTab, op==SQLITE_INSERT, &iHash, &bNullPk); + rc = sessionPreupdateHash(pSession, pTab, op==SQLITE_INSERT, &iHash, &bNull); if( rc!=SQLITE_OK ) goto error_out; - if( bNullPk==0 ){ + if( bNull==0 ){ /* Search the hash table for an existing record for this row. */ SessionChange *pC; for(pC=pTab->apChange[iHash]; pC; pC=pC->pNext){ - if( sessionPreupdateEqual(db, pTab, pC, op) ) break; + if( sessionPreupdateEqual(pSession, pTab, pC, op) ) break; } if( pC==0 ){ @@ -1041,10 +1053,10 @@ static void sessionPreupdateOneChange( for(i=0; inCol; i++){ sqlite3_value *p = 0; if( op!=SQLITE_INSERT ){ - TESTONLY(int trc = ) sqlite3_preupdate_old(pSession->db, i, &p); + TESTONLY(int trc = ) pSession->hook.xOld(pSession->hook.pCtx, i, &p); assert( trc==SQLITE_OK ); }else if( pTab->abPK[i] ){ - TESTONLY(int trc = ) sqlite3_preupdate_new(pSession->db, i, &p); + TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx, i, &p); assert( trc==SQLITE_OK ); } @@ -1072,15 +1084,15 @@ static void sessionPreupdateOneChange( for(i=0; inCol; i++){ sqlite3_value *p = 0; if( op!=SQLITE_INSERT ){ - sqlite3_preupdate_old(pSession->db, i, &p); + pSession->hook.xOld(pSession->hook.pCtx, i, &p); }else if( pTab->abPK[i] ){ - sqlite3_preupdate_new(pSession->db, i, &p); + pSession->hook.xNew(pSession->hook.pCtx, i, &p); } sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte); } /* Add the change to the hash-table */ - if( pSession->bIndirect || sqlite3_preupdate_depth(pSession->db) ){ + if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){ pChange->bIndirect = 1; } pChange->nRecord = nByte; @@ -1091,7 +1103,9 @@ static void sessionPreupdateOneChange( }else if( pC->bIndirect ){ /* If the existing change is considered "indirect", but this current ** change is "direct", mark the change object as direct. */ - if( sqlite3_preupdate_depth(pSession->db)==0 && pSession->bIndirect==0 ){ + if( pSession->hook.xDepth(pSession->hook.pCtx)==0 + && pSession->bIndirect==0 + ){ pC->bIndirect = 0; } } @@ -1104,6 +1118,39 @@ static void sessionPreupdateOneChange( } } +static int sessionFindTable( + sqlite3_session *pSession, + const char *zName, + SessionTable **ppTab +){ + int rc = SQLITE_OK; + int nName = sqlite3Strlen30(zName); + SessionTable *pRet; + + /* Search for an existing table */ + for(pRet=pSession->pTable; pRet; pRet=pRet->pNext){ + if( 0==sqlite3_strnicmp(pRet->zName, zName, nName+1) ) break; + } + + if( pRet==0 && pSession->bAutoAttach ){ + /* If there is a table-filter configured, invoke it. If it returns 0, + ** do not automatically add the new table. */ + if( pSession->xTableFilter==0 + || pSession->xTableFilter(pSession->pFilterCtx, zName) + ){ + rc = sqlite3session_attach(pSession, zName); + if( rc==SQLITE_OK ){ + pRet = pSession->pTable; + assert( 0==sqlite3_strnicmp(pRet->zName, zName, nName+1) ); + } + } + } + + assert( rc==SQLITE_OK || pRet==0 ); + *ppTab = pRet; + return rc; +} + /* ** The 'pre-update' hook registered by this module with SQLite databases. */ @@ -1118,7 +1165,6 @@ static void xPreUpdate( ){ sqlite3_session *pSession; int nDb = sqlite3Strlen30(zDb); - int nName = sqlite3Strlen30(zName); assert( sqlite3_mutex_held(db->mutex) ); @@ -1132,37 +1178,312 @@ static void xPreUpdate( if( pSession->rc ) continue; if( sqlite3_strnicmp(zDb, pSession->zDb, nDb+1) ) continue; - for(pTab=pSession->pTable; pTab || pSession->bAutoAttach; pTab=pTab->pNext){ - if( !pTab ){ - /* This branch is taken if table zName has not yet been attached to - ** this session and the auto-attach flag is set. */ - - /* If there is a table-filter configured, invoke it. If it returns 0, - ** this change will not be recorded. Break out of the loop early in - ** this case. */ - if( pSession->xTableFilter - && pSession->xTableFilter(pSession->pFilterCtx, zName)==0 - ){ - break; - } - - pSession->rc = sqlite3session_attach(pSession,zName); - if( pSession->rc ) break; - pTab = pSession->pTable; - assert( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ); - } - - if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ){ - sessionPreupdateOneChange(op, pSession, pTab); - if( op==SQLITE_UPDATE ){ - sessionPreupdateOneChange(SQLITE_INSERT, pSession, pTab); - } - break; + pSession->rc = sessionFindTable(pSession, zName, &pTab); + if( pTab ){ + assert( pSession->rc==SQLITE_OK ); + sessionPreupdateOneChange(op, pSession, pTab); + if( op==SQLITE_UPDATE ){ + sessionPreupdateOneChange(SQLITE_INSERT, pSession, pTab); } } } } +/* +** The pre-update hook implementations. +*/ +static int sessionPreupdateOld(void *pCtx, int iVal, sqlite3_value **ppVal){ + return sqlite3_preupdate_old((sqlite3*)pCtx, iVal, ppVal); +} +static int sessionPreupdateNew(void *pCtx, int iVal, sqlite3_value **ppVal){ + return sqlite3_preupdate_new((sqlite3*)pCtx, iVal, ppVal); +} +static int sessionPreupdateCount(void *pCtx){ + return sqlite3_preupdate_count((sqlite3*)pCtx); +} +static int sessionPreupdateDepth(void *pCtx){ + return sqlite3_preupdate_depth((sqlite3*)pCtx); +} + +/* +** Install the pre-update hooks on the session object passed as the only +** argument. +*/ +static void sessionPreupdateHooks( + sqlite3_session *pSession +){ + pSession->hook.pCtx = (void*)pSession->db; + pSession->hook.xOld = sessionPreupdateOld; + pSession->hook.xNew = sessionPreupdateNew; + pSession->hook.xCount = sessionPreupdateCount; + pSession->hook.xDepth = sessionPreupdateDepth; +} + +typedef struct SessionDiffCtx SessionDiffCtx; +struct SessionDiffCtx { + sqlite3_stmt *pStmt; + int nOldOff; +}; + +/* +** The diff hook implementations. +*/ +static int sessionDiffOld(void *pCtx, int iVal, sqlite3_value **ppVal){ + SessionDiffCtx *p = (SessionDiffCtx*)pCtx; + *ppVal = sqlite3_column_value(p->pStmt, iVal+p->nOldOff); + return SQLITE_OK; +} +static int sessionDiffNew(void *pCtx, int iVal, sqlite3_value **ppVal){ + SessionDiffCtx *p = (SessionDiffCtx*)pCtx; + *ppVal = sqlite3_column_value(p->pStmt, iVal); + return SQLITE_OK; +} +static int sessionDiffCount(void *pCtx){ + SessionDiffCtx *p = (SessionDiffCtx*)pCtx; + return p->nOldOff ? p->nOldOff : sqlite3_column_count(p->pStmt); +} +static int sessionDiffDepth(void *pCtx){ + return 0; +} + +/* +** Install the diff hooks on the session object passed as the only +** argument. +*/ +static void sessionDiffHooks( + sqlite3_session *pSession, + SessionDiffCtx *pDiffCtx +){ + pSession->hook.pCtx = (void*)pDiffCtx; + pSession->hook.xOld = sessionDiffOld; + pSession->hook.xNew = sessionDiffNew; + pSession->hook.xCount = sessionDiffCount; + pSession->hook.xDepth = sessionDiffDepth; +} + +static char *sessionExprComparePK( + int nCol, + const char *zDb1, const char *zDb2, + const char *zTab, + const char **azCol, u8 *abPK +){ + int i; + const char *zSep = ""; + char *zRet = 0; + + for(i=0; inCol, zDb1, zDb2, pTab->zName,zExpr); + + if( zStmt==0 ){ + rc = SQLITE_NOMEM; + }else{ + sqlite3_stmt *pStmt; + rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0); + if( rc==SQLITE_OK ){ + SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx; + pDiffCtx->pStmt = pStmt; + pDiffCtx->nOldOff = 0; + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + sessionPreupdateOneChange(op, pSession, pTab); + } + rc = sqlite3_finalize(pStmt); + } + sqlite3_free(zStmt); + } + + return rc; +} + +static int sessionDiffFindModified( + sqlite3_session *pSession, + SessionTable *pTab, + const char *zFrom, + const char *zExpr +){ + int rc = SQLITE_OK; + + char *zExpr2 = sessionExprCompareOther(pTab->nCol, + pSession->zDb, zFrom, pTab->zName, pTab->azCol, pTab->abPK + ); + if( zExpr2==0 ){ + rc = SQLITE_NOMEM; + }else{ + char *zStmt = sqlite3_mprintf( + "SELECT * FROM \"%w\".\"%w\", \"%w\".\"\%w\" WHERE %s AND %z", + pSession->zDb, pTab->zName, zFrom, pTab->zName, zExpr, zExpr2 + ); + if( zStmt==0 ){ + rc = SQLITE_NOMEM; + }else{ + sqlite3_stmt *pStmt; + rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0); + + if( rc==SQLITE_OK ){ + SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx; + pDiffCtx->pStmt = pStmt; + pDiffCtx->nOldOff = pTab->nCol; + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + sessionPreupdateOneChange(SQLITE_UPDATE, pSession, pTab); + } + rc = sqlite3_finalize(pStmt); + } + sqlite3_free(zStmt); + } + } + + return rc; +} + +int sqlite3session_diff( + sqlite3_session *pSession, + const char *zFrom, + const char *zTbl, + char **pzErrMsg +){ + const char *zDb = pSession->zDb; + int rc = pSession->rc; + SessionDiffCtx d; + + memset(&d, 0, sizeof(d)); + sessionDiffHooks(pSession, &d); + + if( pzErrMsg ) *pzErrMsg = 0; + if( rc==SQLITE_OK ){ + char *zExpr = 0; + sqlite3 *db = pSession->db; + SessionTable *pTo; /* Table zTbl */ + + /* Locate and if necessary initialize the target table object */ + rc = sessionFindTable(pSession, zTbl, &pTo); + if( pTo==0 ) goto diff_out; + if( pTo->nCol==0 ){ + rc = pSession->rc = sessionTableInfo(db, zDb, + pTo->zName, &pTo->nCol, 0, &pTo->azCol, &pTo->abPK + ); + } + + /* Check the table schemas match */ + if( rc==SQLITE_OK ){ + int nCol; /* Columns in zFrom.zTbl */ + u8 *abPK; + const char **azCol = 0; + rc = sessionTableInfo(db, zFrom, zTbl, &nCol, 0, &azCol, &abPK); + if( rc==SQLITE_OK ){ + int bMismatch = 0; + if( pTo->nCol!=nCol || memcmp(pTo->abPK, abPK, nCol) ){ + bMismatch = 1; + }else{ + int i; + for(i=0; iazCol[i]) ) bMismatch = 1; + } + } + + if( bMismatch ){ + *pzErrMsg = sqlite3_mprintf("table schemas do not match"); + rc = SQLITE_ERROR; + } + } + sqlite3_free(azCol); + } + + if( rc==SQLITE_OK ){ + zExpr = sessionExprComparePK(pTo->nCol, + zDb, zFrom, pTo->zName, pTo->azCol, pTo->abPK + ); + } + + /* Find new rows */ + if( rc==SQLITE_OK ){ + rc = sessionDiffFindNew(SQLITE_INSERT, pSession, pTo, zDb, zFrom, zExpr); + } + + /* Find old rows */ + if( rc==SQLITE_OK ){ + rc = sessionDiffFindNew(SQLITE_DELETE, pSession, pTo, zFrom, zDb, zExpr); + } + + /* Find modified rows */ + if( rc==SQLITE_OK ){ + rc = sessionDiffFindModified(pSession, pTo, zFrom, zExpr); + } + + sqlite3_free(zExpr); + } + + diff_out: + sessionPreupdateHooks(pSession); + return rc; +} + /* ** Create a session object. This session object will record changes to ** database zDb attached to connection db. @@ -1187,6 +1508,7 @@ int sqlite3session_create( pNew->zDb = (char *)&pNew[1]; pNew->bEnable = 1; memcpy(pNew->zDb, zDb, nDb+1); + sessionPreupdateHooks(pNew); /* Add the new session object to the linked list of session objects ** attached to database handle $db. Do this under the cover of the db @@ -1500,13 +1822,14 @@ static void sessionAppendCol( } if( eType==SQLITE_BLOB || eType==SQLITE_TEXT ){ u8 *z; + int nByte; if( eType==SQLITE_BLOB ){ z = (u8 *)sqlite3_column_blob(pStmt, iCol); }else{ z = (u8 *)sqlite3_column_text(pStmt, iCol); } - if( z ){ - int nByte = sqlite3_column_bytes(pStmt, iCol); + nByte = sqlite3_column_bytes(pStmt, iCol); + if( z || (eType==SQLITE_BLOB && nByte==0) ){ sessionAppendVarint(p, nByte, pRc); sessionAppendBlob(p, z, nByte, pRc); }else{ @@ -2179,7 +2502,7 @@ static int sessionValueSetStr( ** argument to sqlite3ValueSetStr() and have the copy created ** automatically. But doing so makes it difficult to detect any OOM ** error. Hence the code to create the copy externally. */ - u8 *aCopy = sqlite3_malloc(nData); + u8 *aCopy = sqlite3_malloc(nData+1); if( aCopy==0 ) return SQLITE_NOMEM; memcpy(aCopy, aData, nData); sqlite3ValueSetStr(pVal, nData, (char*)aCopy, enc, sqlite3_free); diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index e768d66324..ed1c5d917c 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -273,6 +273,63 @@ int sqlite3session_changeset( void **ppChangeset /* OUT: Buffer containing changeset */ ); +/* +** CAPI3REF: Load The Difference Between Tables Into A Session +** +** If it is not already attached to the session object passed as the first +** argument, this function attaches table zTbl in the same manner as the +** [sqlite3session_attach()] function. If zTbl does not exist, or if it +** does not have a primary key, this function is a no-op (but does not return +** an error). +** +** Argument zFromDb must be the name of a database ("main", "temp" etc.) +** attached to the same database handle as the session object that contains +** a table compatible with the table attached to the session by this function. +** A table is considered compatible if it: +** +**
    +**
  • Has the same name, +**
  • Has the same set of columns declared in the same order, and +**
  • Has the same PRIMARY KEY definition. +**
+** +** This function adds a set of changes to the session object that could be +** used to update the table in database zFrom (call this the "from-table") +** so that its content is the same as the table attached to the session +** object (call this the "to-table"). Specifically: +** +**
    +**
  • For each row (primary key) that exists in the to-table but not in +** the from-table, an INSERT record is added to the session object. +** +**
  • For each row (primary key) that exists in the to-table but not in +** the from-table, a DELETE record is added to the session object. +** +**
  • For each row (primary key) that exists in both tables, but features +** different in each, an UPDATE record is added to the session. +**
+** +** To clarify, if this function is called and then a changeset constructed +** using [sqlite3session_changeset()], then after applying that changeset to +** database zFrom the contents of the two compatible tables would be +** identical. +** +** It an error if database zFrom does not exist or does not contain the +** required compatible table. +** +** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite +** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg +** may be set to point to a buffer containing an English language error +** message. It is the responsibility of the caller to free this buffer using +** sqlite3_free(). +*/ +int sqlite3session_diff( + sqlite3_session *pSession, + const char *zFromDb, + const char *zTbl, + char **pzErrMsg +); + /* ** CAPI3REF: Generate A Patchset From A Session Object diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 6c538bcec1..3dc24fc69e 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -117,14 +117,15 @@ static int test_session_cmd( const char *zMsg; int iSub; } aSub[] = { - { "attach", 1, "TABLE", }, /* 0 */ - { "changeset", 0, "", }, /* 1 */ - { "delete", 0, "", }, /* 2 */ - { "enable", 1, "BOOL", }, /* 3 */ - { "indirect", 1, "BOOL", }, /* 4 */ - { "isempty", 0, "", }, /* 5 */ - { "table_filter", 1, "SCRIPT", }, /* 6 */ - { "patchset", 0, "", }, /* 7 */ + { "attach", 1, "TABLE", }, /* 0 */ + { "changeset", 0, "", }, /* 1 */ + { "delete", 0, "", }, /* 2 */ + { "enable", 1, "BOOL", }, /* 3 */ + { "indirect", 1, "BOOL", }, /* 4 */ + { "isempty", 0, "", }, /* 5 */ + { "table_filter", 1, "SCRIPT", }, /* 6 */ + { "patchset", 0, "", }, /* 7 */ + { "diff", 2, "FROMDB TBL", }, /* 8 */ { 0 } }; int iSub; @@ -216,6 +217,24 @@ static int test_session_cmd( sqlite3session_table_filter(pSession, test_table_filter, clientData); break; } + + case 8: { /* diff */ + char *zErr = 0; + rc = sqlite3session_diff(pSession, + Tcl_GetString(objv[2]), + Tcl_GetString(objv[3]), + &zErr + ); + assert( rc!=SQLITE_OK || zErr==0 ); + if( zErr ){ + Tcl_AppendResult(interp, zErr, 0); + return TCL_ERROR; + } + if( rc ){ + return test_session_error(interp, rc); + } + break; + } } return TCL_OK; diff --git a/manifest b/manifest index 42a45e41f3..b4d0667b70 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sprintf()\swidth\sand\sprecision\soverflow\sfixes\sfrom\strunk. -D 2015-04-07T23:10:44.364 +C Add\sexperimental\sAPI\ssqlite3session_diff(). +D 2015-04-08T16:01:12.482 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 3083cf0c2bc6618e532b9478ce735bb512322985 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -148,7 +148,7 @@ F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a F ext/session/session1.test 4653867f32a98ce4bbb4a181aac6debe51ca4dfb -F ext/session/session2.test 99ca0da7ddb617d42bafd83adccf99f18ae0384b +F ext/session/session2.test a95a2d270b32638c1acba7cb9c81856712d469ac F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169 @@ -158,11 +158,12 @@ F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069 F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f F ext/session/sessionB.test 06961b7c3641151f5d23088250ecad132501113c F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4 +F ext/session/sessionD.test 95903bd6a23dadbda7e192f730dd7dedd2d369ef F ext/session/session_common.tcl 9de0451b6a47218fc16b9ed8876b6238a0a3d88d F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c 838050c4c217d2843e4705b14be25d8f0457f155 -F ext/session/sqlite3session.h 16608d29879a0ed3c6be6b7fb18dcdb5c707aaef -F ext/session/test_session.c a28352e99bc6a83b94e4cce99a7bf25c73d6d489 +F ext/session/sqlite3session.c 3fcf2efe81c90602db76b1da33538895034eef66 +F ext/session/sqlite3session.h d9ebd8d4c5791aafdf18165575c7f2223c09279b +F ext/session/test_session.c 037fc25340a918eb2195972fed439d7adf7b5db9 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e @@ -1267,7 +1268,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 271c110bcf5bf2ea7e113dd01dec876a08e3c047 8e4ac2ce24415926247961b00a62425ae85d6ffb -R e52a83cd9a76eb22e0a9f49afec82395 -U drh -Z 65d91c87ac07196da2d7921b7b9389b5 +P aeca95ac77f6f320a916f7e3c5a7a588ef4a20c8 +R 5c3cbffcff665bc16c7e835a4d990399 +T *branch * sessions-diff +T *sym-sessions-diff * +T -sym-sessions * +U dan +Z b513e16008d3799dcac5a3d5f415d7d8 diff --git a/manifest.uuid b/manifest.uuid index e451de8f37..8b03fb6fb8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -aeca95ac77f6f320a916f7e3c5a7a588ef4a20c8 \ No newline at end of file +c4340b2ea2115ad97dcac036f9034e132ab789e5 \ No newline at end of file From 3cc89d9567bb0e247c8d7de93c851febf22a363c Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 8 Apr 2015 16:43:31 +0000 Subject: [PATCH 131/570] Fix problems in the sessions module causing it to produce spurious SQLITE_NOMEM errors when handling SQL text or blob values zero bytes in size. FossilOrigin-Name: b9459d5980c6249a5c1bc5ea72cb4f3b1ba0e433 --- ext/session/session2.test | 10 ++++++++++ ext/session/sqlite3session.c | 15 +++++++++------ manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/ext/session/session2.test b/ext/session/session2.test index 04be5f0917..0035e39dbf 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -169,7 +169,17 @@ set set_of_tests { INSERT INTO %T4% VALUES('def', 'abc'); } 17 { UPDATE %T4% SET b = 1 } + 18 { DELETE FROM %T4% WHERE 1 } + + 19 { + INSERT INTO t1 VALUES('', ''); + INSERT INTO t1 VALUES(X'', X''); + } + 20 { + DELETE FROM t1; + INSERT INTO t1 VALUES('', NULL); + } } test_reset diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index f861bd1ec6..946681a4b3 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -316,8 +316,8 @@ static int sessionSerializeValue( }else{ z = (u8 *)sqlite3_value_blob(pValue); } - if( z==0 ) return SQLITE_NOMEM; n = sqlite3_value_bytes(pValue); + if( z==0 && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM; nVarint = sessionVarintLen(n); if( aBuf ){ @@ -435,13 +435,15 @@ static int sessionPreupdateHash( h = sessionHashAppendI64(h, iVal); }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ const u8 *z; + int n; if( eType==SQLITE_TEXT ){ z = (const u8 *)sqlite3_value_text(pVal); }else{ z = (const u8 *)sqlite3_value_blob(pVal); } - if( !z ) return SQLITE_NOMEM; - h = sessionHashAppendBlob(h, sqlite3_value_bytes(pVal), z); + n = sqlite3_value_bytes(pVal); + if( !z && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM; + h = sessionHashAppendBlob(h, n, z); }else{ assert( eType==SQLITE_NULL ); *pbNullPK = 1; @@ -1500,13 +1502,14 @@ static void sessionAppendCol( } if( eType==SQLITE_BLOB || eType==SQLITE_TEXT ){ u8 *z; + int nByte; if( eType==SQLITE_BLOB ){ z = (u8 *)sqlite3_column_blob(pStmt, iCol); }else{ z = (u8 *)sqlite3_column_text(pStmt, iCol); } - if( z ){ - int nByte = sqlite3_column_bytes(pStmt, iCol); + nByte = sqlite3_column_bytes(pStmt, iCol); + if( z || (eType==SQLITE_BLOB && nByte==0) ){ sessionAppendVarint(p, nByte, pRc); sessionAppendBlob(p, z, nByte, pRc); }else{ @@ -2179,7 +2182,7 @@ static int sessionValueSetStr( ** argument to sqlite3ValueSetStr() and have the copy created ** automatically. But doing so makes it difficult to detect any OOM ** error. Hence the code to create the copy externally. */ - u8 *aCopy = sqlite3_malloc(nData); + u8 *aCopy = sqlite3_malloc(nData+1); if( aCopy==0 ) return SQLITE_NOMEM; memcpy(aCopy, aData, nData); sqlite3ValueSetStr(pVal, nData, (char*)aCopy, enc, sqlite3_free); diff --git a/manifest b/manifest index 42a45e41f3..b53ebc56fc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sprintf()\swidth\sand\sprecision\soverflow\sfixes\sfrom\strunk. -D 2015-04-07T23:10:44.364 +C Fix\sproblems\sin\sthe\ssessions\smodule\scausing\sit\sto\sproduce\sspurious\sSQLITE_NOMEM\serrors\swhen\shandling\sSQL\stext\sor\sblob\svalues\szero\sbytes\sin\ssize. +D 2015-04-08T16:43:31.690 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 3083cf0c2bc6618e532b9478ce735bb512322985 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -148,7 +148,7 @@ F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a F ext/session/session1.test 4653867f32a98ce4bbb4a181aac6debe51ca4dfb -F ext/session/session2.test 99ca0da7ddb617d42bafd83adccf99f18ae0384b +F ext/session/session2.test a95a2d270b32638c1acba7cb9c81856712d469ac F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169 @@ -160,7 +160,7 @@ F ext/session/sessionB.test 06961b7c3641151f5d23088250ecad132501113c F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4 F ext/session/session_common.tcl 9de0451b6a47218fc16b9ed8876b6238a0a3d88d F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c 838050c4c217d2843e4705b14be25d8f0457f155 +F ext/session/sqlite3session.c 7c6516f0342772441bcd2d845760902cfc0b39b8 F ext/session/sqlite3session.h 16608d29879a0ed3c6be6b7fb18dcdb5c707aaef F ext/session/test_session.c a28352e99bc6a83b94e4cce99a7bf25c73d6d489 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1267,7 +1267,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 271c110bcf5bf2ea7e113dd01dec876a08e3c047 8e4ac2ce24415926247961b00a62425ae85d6ffb -R e52a83cd9a76eb22e0a9f49afec82395 -U drh -Z 65d91c87ac07196da2d7921b7b9389b5 +P aeca95ac77f6f320a916f7e3c5a7a588ef4a20c8 +R 2b6c500da0e9b0a3fd57accc4dad1058 +U dan +Z aded3edd721aa55f05087866d9fe12cb diff --git a/manifest.uuid b/manifest.uuid index e451de8f37..27eccb5ef6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -aeca95ac77f6f320a916f7e3c5a7a588ef4a20c8 \ No newline at end of file +b9459d5980c6249a5c1bc5ea72cb4f3b1ba0e433 \ No newline at end of file From 730bb805a84cb3b08f7b99d5db2eb8c5ef5d9106 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 9 Apr 2015 19:19:22 +0000 Subject: [PATCH 132/570] Updates to comments describing the changeset and patchset formats. FossilOrigin-Name: 5342f721e878b52f207731ea57411f3669ae3f3f --- ext/session/sqlite3session.c | 51 ++++++++++++++++++++++++++++++++---- manifest | 12 ++++----- manifest.uuid | 2 +- 3 files changed, 53 insertions(+), 12 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 946681a4b3..aa71f32081 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -159,7 +159,7 @@ struct SessionTable { ** Each group of changes begins with a table header: ** ** 1 byte: Constant 0x54 (capital 'T') -** Varint: Big-endian integer set to the number of columns in the table. +** Varint: Number of columns in the table. ** nCol bytes: 0x01 for PK columns, 0x00 otherwise. ** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. ** @@ -170,16 +170,38 @@ struct SessionTable { ** old.* record: (delete and update only) ** new.* record: (insert and update only) ** +** The "old.*" and "new.*" records, if present, are N field records in the +** format described above under "RECORD FORMAT", where N is the number of +** columns in the table. The i'th field of each record is associated with +** the i'th column of the table, counting from left to right in the order +** in which columns were declared in the CREATE TABLE statement. +** +** The new.* record that is part of each INSERT change contains the values +** that make up the new row. Similarly, the old.* record that is part of each +** DELETE change contains the values that made up the row that was deleted +** from the database. In the changeset format, the records that are part +** of INSERT or DELETE changes never contain any undefined (type byte 0x00) +** fields. +** +** Within the old.* record associated with an UPDATE change, all fields +** associated with table columns that are not PRIMARY KEY columns and are +** not modified by the UPDATE change are set to "undefined". Other fields +** are set to the values that made up the row before the UPDATE that the +** change records took place. Within the new.* record, fields associated +** with table columns modified by the UPDATE change contain the new +** values. Fields associated with table columns that are not modified +** are set to "undefined". +** ** PATCHSET FORMAT: ** ** A patchset is also a collection of changes. It is similar to a changeset, -** but omits those fields that are not useful if no conflict resolution -** is required when applying the changeset. +** but leaves undefined those fields that are not useful if no conflict +** resolution is required when applying the changeset. ** ** Each group of changes begins with a table header: ** ** 1 byte: Constant 0x50 (capital 'P') -** Varint: Big-endian integer set to the number of columns in the table. +** Varint: Number of columns in the table. ** nCol bytes: 0x01 for PK columns, 0x00 otherwise. ** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. ** @@ -187,7 +209,26 @@ struct SessionTable { ** ** 1 byte: Either SQLITE_INSERT, UPDATE or DELETE. ** 1 byte: The "indirect-change" flag. -** single record: (PK fields for DELETE, or full record for INSERT/UPDATE). +** single record: (PK fields for DELETE, PK and modified fields for UPDATE, +** full record for INSERT). +** +** As in the changeset format, each field of the single record that is part +** of a patchset change is associated with the correspondingly positioned +** table column, counting from left to right within the CREATE TABLE +** statement. +** +** For a DELETE change, all fields within the record except those associated +** with PRIMARY KEY columns are set to "undefined". The PRIMARY KEY fields +** contain the values identifying the row to delete. +** +** For an UPDATE change, all fields except those associated with PRIMARY KEY +** columns and columns that are modified by the UPDATE are set to "undefined". +** PRIMARY KEY fields contain the values identifying the table row to update, +** and fields associated with modified columns contain the new column values. +** +** The records associated with INSERT changes are in the same format as for +** changesets. It is not possible for a record associated with an INSERT +** change to contain a field set to "undefined". */ /* diff --git a/manifest b/manifest index b53ebc56fc..a9ab76b4a8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sproblems\sin\sthe\ssessions\smodule\scausing\sit\sto\sproduce\sspurious\sSQLITE_NOMEM\serrors\swhen\shandling\sSQL\stext\sor\sblob\svalues\szero\sbytes\sin\ssize. -D 2015-04-08T16:43:31.690 +C Updates\sto\scomments\sdescribing\sthe\schangeset\sand\spatchset\sformats. +D 2015-04-09T19:19:22.574 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 3083cf0c2bc6618e532b9478ce735bb512322985 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -160,7 +160,7 @@ F ext/session/sessionB.test 06961b7c3641151f5d23088250ecad132501113c F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4 F ext/session/session_common.tcl 9de0451b6a47218fc16b9ed8876b6238a0a3d88d F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c 7c6516f0342772441bcd2d845760902cfc0b39b8 +F ext/session/sqlite3session.c 27eb71e164a8e05d344c6254e8f906f093dfd4d1 F ext/session/sqlite3session.h 16608d29879a0ed3c6be6b7fb18dcdb5c707aaef F ext/session/test_session.c a28352e99bc6a83b94e4cce99a7bf25c73d6d489 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1267,7 +1267,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P aeca95ac77f6f320a916f7e3c5a7a588ef4a20c8 -R 2b6c500da0e9b0a3fd57accc4dad1058 +P b9459d5980c6249a5c1bc5ea72cb4f3b1ba0e433 +R a602d0c91e77a7e6222a205b1b755ccf U dan -Z aded3edd721aa55f05087866d9fe12cb +Z 08fe7407f1e8070b595e48c16318a0a6 diff --git a/manifest.uuid b/manifest.uuid index 27eccb5ef6..7812248cad 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b9459d5980c6249a5c1bc5ea72cb4f3b1ba0e433 \ No newline at end of file +5342f721e878b52f207731ea57411f3669ae3f3f \ No newline at end of file From 92f283c0d4d4f9bf552e168c845cae5ef6ad98e0 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 16 Apr 2015 13:52:03 +0000 Subject: [PATCH 133/570] Fix a stray backslash character in a printf format string in sessionDiffFindModified() FossilOrigin-Name: abb192a1d79388d4717f459b91e34f9c035935f2 --- ext/session/sqlite3session.c | 2 +- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 28b3af9d87..9a367cfb1c 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1417,7 +1417,7 @@ static int sessionDiffFindModified( rc = SQLITE_NOMEM; }else{ char *zStmt = sqlite3_mprintf( - "SELECT * FROM \"%w\".\"%w\", \"%w\".\"\%w\" WHERE %s AND %z", + "SELECT * FROM \"%w\".\"%w\", \"%w\".\"%w\" WHERE %s AND %z", pSession->zDb, pTab->zName, zFrom, pTab->zName, zExpr, zExpr2 ); if( zStmt==0 ){ diff --git a/manifest b/manifest index f673b417e6..2e4c25c168 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sall\srecent\strunk\sfixes\sand\senhancements\sinto\sthe\ssessions\sbranch. -D 2015-04-15T14:14:38.449 +C Fix\sa\sstray\sbackslash\scharacter\sin\sa\sprintf\sformat\sstring\sin\nsessionDiffFindModified() +D 2015-04-16T13:52:03.882 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7e23076b9c9dd5c1901c78cf6cdd64d616e5a539 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -161,7 +161,7 @@ F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4 F ext/session/sessionD.test 95903bd6a23dadbda7e192f730dd7dedd2d369ef F ext/session/session_common.tcl 9de0451b6a47218fc16b9ed8876b6238a0a3d88d F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c 2266fca2cb730f3c88423725453bb31c7e820583 +F ext/session/sqlite3session.c 7c82934f4cff05cfbb58bde7562de0964bb7fb32 F ext/session/sqlite3session.h d9ebd8d4c5791aafdf18165575c7f2223c09279b F ext/session/test_session.c 037fc25340a918eb2195972fed439d7adf7b5db9 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1269,7 +1269,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 5f14f34f072921e229bc20a5185c0cdb3f464c04 bd06eeb8d06237dc2d54d8a03e8bf525cb811c9e -R 9a2dfdee602d304934edbae48280a16c +P e65e65f9bc9b4bf5c9dd6e3a77a0d5f03c40e006 +R 25456e7e52fcd9fbd64c7561e09a3c2d U drh -Z 3665d5b1b05a141bd80e3d7f627d8145 +Z 6d1f041621c8223ff5e5a995b79f05ad diff --git a/manifest.uuid b/manifest.uuid index bcb504ccb4..02efefc93d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e65e65f9bc9b4bf5c9dd6e3a77a0d5f03c40e006 \ No newline at end of file +abb192a1d79388d4717f459b91e34f9c035935f2 \ No newline at end of file From 10dc553c13ae43064717f173ebd7717c97fbf63b Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 17 Apr 2015 11:31:08 +0000 Subject: [PATCH 134/570] Hold the database mutex for the duration of sqlite3session_diff(). FossilOrigin-Name: 6f33050115562833c43da3c99dd37aeb0bf966b6 --- ext/session/sqlite3session.c | 2 ++ manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 9a367cfb1c..a07e1e84d6 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1455,6 +1455,7 @@ int sqlite3session_diff( memset(&d, 0, sizeof(d)); sessionDiffHooks(pSession, &d); + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); if( pzErrMsg ) *pzErrMsg = 0; if( rc==SQLITE_OK ){ char *zExpr = 0; @@ -1521,6 +1522,7 @@ int sqlite3session_diff( diff_out: sessionPreupdateHooks(pSession); + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); return rc; } diff --git a/manifest b/manifest index 2e4c25c168..ee05b48b56 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sstray\sbackslash\scharacter\sin\sa\sprintf\sformat\sstring\sin\nsessionDiffFindModified() -D 2015-04-16T13:52:03.882 +C Hold\sthe\sdatabase\smutex\sfor\sthe\sduration\sof\ssqlite3session_diff(). +D 2015-04-17T11:31:08.304 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7e23076b9c9dd5c1901c78cf6cdd64d616e5a539 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -161,7 +161,7 @@ F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4 F ext/session/sessionD.test 95903bd6a23dadbda7e192f730dd7dedd2d369ef F ext/session/session_common.tcl 9de0451b6a47218fc16b9ed8876b6238a0a3d88d F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c 7c82934f4cff05cfbb58bde7562de0964bb7fb32 +F ext/session/sqlite3session.c 2ad7285103457129c636a2367d40f3b9c459b256 F ext/session/sqlite3session.h d9ebd8d4c5791aafdf18165575c7f2223c09279b F ext/session/test_session.c 037fc25340a918eb2195972fed439d7adf7b5db9 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1269,7 +1269,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e65e65f9bc9b4bf5c9dd6e3a77a0d5f03c40e006 -R 25456e7e52fcd9fbd64c7561e09a3c2d -U drh -Z 6d1f041621c8223ff5e5a995b79f05ad +P abb192a1d79388d4717f459b91e34f9c035935f2 +R 39574ad38832f7643b0bd124d608871c +U dan +Z 2a1b149e99da178a1dea33510073d75a diff --git a/manifest.uuid b/manifest.uuid index 02efefc93d..db862f34a6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -abb192a1d79388d4717f459b91e34f9c035935f2 \ No newline at end of file +6f33050115562833c43da3c99dd37aeb0bf966b6 \ No newline at end of file From dd009f839c988874c3cfd83acc1969ac57df9fe1 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 23 Apr 2015 14:40:17 +0000 Subject: [PATCH 135/570] Fix a performance problem in sqlite3session_diff(). FossilOrigin-Name: ea400eca314d81761fe5c0e329b906c045f0dfe4 --- ext/session/sessionD.test | 38 ++++++++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 2 +- manifest | 16 +++++++-------- manifest.uuid | 2 +- 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/ext/session/sessionD.test b/ext/session/sessionD.test index c26728742a..aab9fdaea8 100644 --- a/ext/session/sessionD.test +++ b/ext/session/sessionD.test @@ -65,6 +65,25 @@ proc do_diff_test {tn setup} { uplevel do_test $tn.2 [list {scksum db aux}] [list $cksum] } +# Ensure that the diff produced by comparing the current contents of [db] +# with itself is empty. +proc do_empty_diff_test {tn} { + forcedelete test.db2 + forcecopy test.db test.db2 + + execsql { ATTACH 'test.db2' AS aux } + sqlite3session S db main + foreach tbl [db eval {SELECT name FROM sqlite_master WHERE type='table'}] { + S attach $tbl + S diff aux $tbl + } + + set ::C [S changeset] + S delete + + uplevel [list do_test $tn {string length $::C} 0] +} + forcedelete test.db2 do_execsql_test 1.0 { @@ -146,5 +165,24 @@ do_diff_test 2.4 { VALUES('ckmqmzoeuvxisxqy',X'EB5A5D3A1DD22FD1','tidgtsplhjcbvbppdt',-642987.3); } +reset_db +do_execsql_test 3.0 { + CREATE TABLE t1(a, b, c, PRIMARY KEY(a)); + INSERT INTO t1 VALUES(1, 2, 3); + INSERT INTO t1 VALUES(4, 5, 6); + INSERT INTO t1 VALUES(7, 8, 9); + + CREATE TABLE t2(a, b, c, PRIMARY KEY(a, b)); + INSERT INTO t2 VALUES(1, 2, 3); + INSERT INTO t2 VALUES(4, 5, 6); + INSERT INTO t2 VALUES(7, 8, 9); + + CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b, c)); + INSERT INTO t3 VALUES(1, 2, 3); + INSERT INTO t3 VALUES(4, 5, 6); + INSERT INTO t3 VALUES(7, 8, 9); +} +do_empty_diff_test 3.1 + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index a07e1e84d6..70bd250e34 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1417,7 +1417,7 @@ static int sessionDiffFindModified( rc = SQLITE_NOMEM; }else{ char *zStmt = sqlite3_mprintf( - "SELECT * FROM \"%w\".\"%w\", \"%w\".\"%w\" WHERE %s AND %z", + "SELECT * FROM \"%w\".\"%w\", \"%w\".\"%w\" WHERE %s AND (%z)", pSession->zDb, pTab->zName, zFrom, pTab->zName, zExpr, zExpr2 ); if( zStmt==0 ){ diff --git a/manifest b/manifest index 3a0b76390b..d6c7250535 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\slatest\strunk\senhancements\sand\sfixes\sinto\sthe\ssessions\sbranch. -D 2015-04-23T13:49:53.138 +C Fix\sa\sperformance\sproblem\sin\ssqlite3session_diff(). +D 2015-04-23T14:40:17.627 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7599f0c96df628cd543884b1b2f2a2fbffd00079 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -158,10 +158,10 @@ F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069 F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f F ext/session/sessionB.test 06961b7c3641151f5d23088250ecad132501113c F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4 -F ext/session/sessionD.test 95903bd6a23dadbda7e192f730dd7dedd2d369ef +F ext/session/sessionD.test 197781b4823fbf0003a21da0e4360b37d0e0a81f F ext/session/session_common.tcl 9de0451b6a47218fc16b9ed8876b6238a0a3d88d F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c 2ad7285103457129c636a2367d40f3b9c459b256 +F ext/session/sqlite3session.c de11ba62d7bf5b9a5d732411550771d4ee6b412a F ext/session/sqlite3session.h d9ebd8d4c5791aafdf18165575c7f2223c09279b F ext/session/test_session.c 037fc25340a918eb2195972fed439d7adf7b5db9 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1271,7 +1271,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b8ef1cdee307441e8d97b4bfc21f8547692eea9f b5e43602833249aa4b73337bf85b7f308450dab6 -R 21546caf070f5228972b31b0602e8636 -U drh -Z 47f4cbb84ecfe918df05ce03c5e0cd26 +P 4e5f17d189eb0578a544c21fc150f9e2ee3428e3 +R bb0c0c482394af2863743ccd1d1a9362 +U dan +Z ee0bd6bc3557d1b9872d331b62e53091 diff --git a/manifest.uuid b/manifest.uuid index f5eb052979..e79db0245b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4e5f17d189eb0578a544c21fc150f9e2ee3428e3 \ No newline at end of file +ea400eca314d81761fe5c0e329b906c045f0dfe4 \ No newline at end of file From 4cc923e3e3cb6dd54779c8b74cbbfbbcea979754 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 23 Apr 2015 15:03:14 +0000 Subject: [PATCH 136/570] Fix the error message returned by sqlite3session_diff() for tables with no PRIMARY KEY. FossilOrigin-Name: 4d34a3d40da210bebb2a2e6dff094f9a39c92798 --- ext/session/sessionD.test | 31 +++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 9 ++++++++- ext/session/test_session.c | 1 + manifest | 16 ++++++++-------- manifest.uuid | 2 +- 5 files changed, 49 insertions(+), 10 deletions(-) diff --git a/ext/session/sessionD.test b/ext/session/sessionD.test index aab9fdaea8..6fc47075d5 100644 --- a/ext/session/sessionD.test +++ b/ext/session/sessionD.test @@ -184,5 +184,36 @@ do_execsql_test 3.0 { } do_empty_diff_test 3.1 + +#------------------------------------------------------------------------- +# Test some error cases: +# +# 1) schema mismatches between the two dbs, and +# 2) tables with no primary keys. +# +reset_db +forcedelete test.db2 +do_execsql_test 4.0 { + ATTACH 'test.db2' AS ixua; + CREATE TABLE ixua.t1(a, b, c); + CREATE TABLE main.t1(a, b, c); + + CREATE TABLE ixua.t2(a PRIMARY KEY, b, c); + CREATE TABLE main.t2(a PRIMARY KEY, b, x); +} + +do_test 4.1 { + sqlite3session S db main + S attach t1 + list [catch { S diff ixua t1 } msg] $msg +} {1 {table has no primary key}} + +do_test 4.2 { + S attach t2 + list [catch { S diff ixua t2 } msg] $msg +} {1 {table schemas do not match}} + +S delete + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 70bd250e34..f5a6096611 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1473,18 +1473,21 @@ int sqlite3session_diff( /* Check the table schemas match */ if( rc==SQLITE_OK ){ + int bHasPk = 0; int nCol; /* Columns in zFrom.zTbl */ u8 *abPK; const char **azCol = 0; rc = sessionTableInfo(db, zFrom, zTbl, &nCol, 0, &azCol, &abPK); if( rc==SQLITE_OK ){ int bMismatch = 0; - if( pTo->nCol!=nCol || memcmp(pTo->abPK, abPK, nCol) ){ + if( pTo->nCol!=nCol ){ bMismatch = 1; }else{ int i; for(i=0; iabPK[i]!=abPK[i] ) bMismatch = 1; if( sqlite3_stricmp(azCol[i], pTo->azCol[i]) ) bMismatch = 1; + if( abPK[i] ) bHasPk = 1; } } @@ -1492,6 +1495,10 @@ int sqlite3session_diff( *pzErrMsg = sqlite3_mprintf("table schemas do not match"); rc = SQLITE_ERROR; } + if( bHasPk==0 ){ + *pzErrMsg = sqlite3_mprintf("table has no primary key"); + rc = SQLITE_ERROR; + } } sqlite3_free(azCol); } diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 3dc24fc69e..b3f2533ff5 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -228,6 +228,7 @@ static int test_session_cmd( assert( rc!=SQLITE_OK || zErr==0 ); if( zErr ){ Tcl_AppendResult(interp, zErr, 0); + sqlite3_free(zErr); return TCL_ERROR; } if( rc ){ diff --git a/manifest b/manifest index d6c7250535..5b54ca3c2e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sperformance\sproblem\sin\ssqlite3session_diff(). -D 2015-04-23T14:40:17.627 +C Fix\sthe\serror\smessage\sreturned\sby\ssqlite3session_diff()\sfor\stables\swith\sno\sPRIMARY\sKEY. +D 2015-04-23T15:03:14.997 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7599f0c96df628cd543884b1b2f2a2fbffd00079 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -158,12 +158,12 @@ F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069 F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f F ext/session/sessionB.test 06961b7c3641151f5d23088250ecad132501113c F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4 -F ext/session/sessionD.test 197781b4823fbf0003a21da0e4360b37d0e0a81f +F ext/session/sessionD.test bdc20e2384bf92b5719b9e41ad3b18cd9188cf26 F ext/session/session_common.tcl 9de0451b6a47218fc16b9ed8876b6238a0a3d88d F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c de11ba62d7bf5b9a5d732411550771d4ee6b412a +F ext/session/sqlite3session.c 0b26c45c0c3c0b2afaae9bd69ae1e80a6b8e9b5a F ext/session/sqlite3session.h d9ebd8d4c5791aafdf18165575c7f2223c09279b -F ext/session/test_session.c 037fc25340a918eb2195972fed439d7adf7b5db9 +F ext/session/test_session.c 67a049635d910c55917f23d067575ab5432d4546 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e @@ -1271,7 +1271,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4e5f17d189eb0578a544c21fc150f9e2ee3428e3 -R bb0c0c482394af2863743ccd1d1a9362 +P ea400eca314d81761fe5c0e329b906c045f0dfe4 +R 57c462c26b9985ec1f9daf86d6b971a1 U dan -Z ee0bd6bc3557d1b9872d331b62e53091 +Z dd15ced7dcdddbd36a44e0c8439b0673 diff --git a/manifest.uuid b/manifest.uuid index e79db0245b..9d7404abb8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ea400eca314d81761fe5c0e329b906c045f0dfe4 \ No newline at end of file +4d34a3d40da210bebb2a2e6dff094f9a39c92798 \ No newline at end of file From b9db90995254891621c116039cef50b5c3606db1 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 23 Apr 2015 17:22:49 +0000 Subject: [PATCH 137/570] Modify the sqlite3session_diff() API so that tables with no PRIMARY KEYs are ignored. This matches the other sessions APIs. Also change sqlite3session_diff() so that it returns SQLITE_SCHEMA, instead of SQLITE_ERROR, if the tables being compared do not have compatible schemas. FossilOrigin-Name: aada0ad08e3baa10d14d1f3393183110289e068e --- ext/session/sessionD.test | 18 ++++++++++++------ ext/session/sqlite3session.c | 18 +++++++++--------- ext/session/sqlite3session.h | 5 +++++ ext/session/test_session.c | 31 +++++++++++++++---------------- manifest | 18 +++++++++--------- manifest.uuid | 2 +- 6 files changed, 51 insertions(+), 41 deletions(-) diff --git a/ext/session/sessionD.test b/ext/session/sessionD.test index 6fc47075d5..b8572782e2 100644 --- a/ext/session/sessionD.test +++ b/ext/session/sessionD.test @@ -189,7 +189,8 @@ do_empty_diff_test 3.1 # Test some error cases: # # 1) schema mismatches between the two dbs, and -# 2) tables with no primary keys. +# 2) tables with no primary keys. This is not actually an error, but +# should not add any changes to the session object. # reset_db forcedelete test.db2 @@ -197,22 +198,27 @@ do_execsql_test 4.0 { ATTACH 'test.db2' AS ixua; CREATE TABLE ixua.t1(a, b, c); CREATE TABLE main.t1(a, b, c); + INSERT INTO main.t1 VALUES(1, 2, 3); CREATE TABLE ixua.t2(a PRIMARY KEY, b, c); CREATE TABLE main.t2(a PRIMARY KEY, b, x); } -do_test 4.1 { +do_test 4.1.1 { sqlite3session S db main S attach t1 list [catch { S diff ixua t1 } msg] $msg -} {1 {table has no primary key}} +} {0 {}} +do_test 4.1.2 { + string length [S changeset] +} {0} +S delete -do_test 4.2 { +do_test 4.2.2 { + sqlite3session S db main S attach t2 list [catch { S diff ixua t2 } msg] $msg -} {1 {table schemas do not match}} - +} {1 {SQLITE_SCHEMA - table schemas do not match}} S delete finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index f5a6096611..b5a1b9dfa3 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1474,12 +1474,12 @@ int sqlite3session_diff( /* Check the table schemas match */ if( rc==SQLITE_OK ){ int bHasPk = 0; + int bMismatch = 0; int nCol; /* Columns in zFrom.zTbl */ u8 *abPK; const char **azCol = 0; rc = sessionTableInfo(db, zFrom, zTbl, &nCol, 0, &azCol, &abPK); if( rc==SQLITE_OK ){ - int bMismatch = 0; if( pTo->nCol!=nCol ){ bMismatch = 1; }else{ @@ -1491,16 +1491,16 @@ int sqlite3session_diff( } } - if( bMismatch ){ - *pzErrMsg = sqlite3_mprintf("table schemas do not match"); - rc = SQLITE_ERROR; - } - if( bHasPk==0 ){ - *pzErrMsg = sqlite3_mprintf("table has no primary key"); - rc = SQLITE_ERROR; - } } sqlite3_free(azCol); + if( bMismatch ){ + *pzErrMsg = sqlite3_mprintf("table schemas do not match"); + rc = SQLITE_SCHEMA; + } + if( bHasPk==0 ){ + /* Ignore tables with no primary keys */ + goto diff_out; + } } if( rc==SQLITE_OK ){ diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index ed1c5d917c..c8ce488ba7 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -293,6 +293,11 @@ int sqlite3session_changeset( **
  • Has the same PRIMARY KEY definition. ** ** +** If the tables are not compatible, SQLITE_SCHEMA is returned. If the tables +** are compatible but do not have any PRIMARY KEY columns, it is not an error +** but no changes are added to the session object. As with other session +** APIs, tables without PRIMARY KEYs are simply ignored. +** ** This function adds a set of changes to the session object that could be ** used to update the table in database zFrom (call this the "from-table") ** so that its content is the same as the table attached to the session diff --git a/ext/session/test_session.c b/ext/session/test_session.c index b3f2533ff5..15f7b6f575 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -39,9 +39,13 @@ static int test_tcl_integer(Tcl_Interp *interp, const char *zVar){ return iVal; } -static int test_session_error(Tcl_Interp *interp, int rc){ +static int test_session_error(Tcl_Interp *interp, int rc, char *zErr){ extern const char *sqlite3ErrName(int); Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); + if( zErr ){ + Tcl_AppendResult(interp, " - ", zErr, 0); + sqlite3_free(zErr); + } return TCL_ERROR; } @@ -150,7 +154,7 @@ static int test_session_cmd( if( zArg[0]=='*' && zArg[1]=='\0' ) zArg = 0; rc = sqlite3session_attach(pSession, zArg); if( rc!=SQLITE_OK ){ - return test_session_error(interp, rc); + return test_session_error(interp, rc, 0); } break; } @@ -177,7 +181,7 @@ static int test_session_cmd( } sqlite3_free(o.p); if( rc!=SQLITE_OK ){ - return test_session_error(interp, rc); + return test_session_error(interp, rc, 0); } break; } @@ -226,13 +230,8 @@ static int test_session_cmd( &zErr ); assert( rc!=SQLITE_OK || zErr==0 ); - if( zErr ){ - Tcl_AppendResult(interp, zErr, 0); - sqlite3_free(zErr); - return TCL_ERROR; - } if( rc ){ - return test_session_error(interp, rc); + return test_session_error(interp, rc, zErr); } break; } @@ -278,7 +277,7 @@ static int test_sqlite3session( rc = sqlite3session_create(db, Tcl_GetString(objv[3]), &p->pSession); if( rc!=SQLITE_OK ){ ckfree((char*)p); - return test_session_error(interp, rc); + return test_session_error(interp, rc, 0); } Tcl_CreateObjCommand( @@ -652,7 +651,7 @@ static int test_sqlite3changeset_apply( } if( rc!=SQLITE_OK ){ - return test_session_error(interp, rc); + return test_session_error(interp, rc, 0); } Tcl_ResetResult(interp); return TCL_OK; @@ -686,7 +685,7 @@ static int test_sqlite3changeset_apply_replace_all( rc = sqlite3changeset_apply(db, nChangeset, pChangeset, 0, replace_handler,0); if( rc!=SQLITE_OK ){ - return test_session_error(interp, rc); + return test_session_error(interp, rc, 0); } Tcl_ResetResult(interp); return TCL_OK; @@ -724,7 +723,7 @@ static int test_sqlite3changeset_invert( rc = sqlite3changeset_invert(sIn.nData, sIn.aData, &sOut.n, &sOut.p); } if( rc!=SQLITE_OK ){ - rc = test_session_error(interp, rc); + rc = test_session_error(interp, rc, 0); }else{ Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n)); } @@ -772,7 +771,7 @@ static int test_sqlite3changeset_concat( } if( rc!=SQLITE_OK ){ - rc = test_session_error(interp, rc); + rc = test_session_error(interp, rc, 0); }else{ Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n)); } @@ -824,7 +823,7 @@ static int test_sqlite3session_foreach( rc = sqlite3changeset_start_strm(&pIter, testStreamInput, (void*)&sStr); } if( rc!=SQLITE_OK ){ - return test_session_error(interp, rc); + return test_session_error(interp, rc, 0); } while( SQLITE_ROW==sqlite3changeset_next(pIter) ){ @@ -907,7 +906,7 @@ static int test_sqlite3session_foreach( rc = sqlite3changeset_finalize(pIter); } if( rc!=SQLITE_OK ){ - return test_session_error(interp, rc); + return test_session_error(interp, rc, 0); } return TCL_OK; diff --git a/manifest b/manifest index 5b54ca3c2e..cc09519aa2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\serror\smessage\sreturned\sby\ssqlite3session_diff()\sfor\stables\swith\sno\sPRIMARY\sKEY. -D 2015-04-23T15:03:14.997 +C Modify\sthe\ssqlite3session_diff()\sAPI\sso\sthat\stables\swith\sno\sPRIMARY\sKEYs\sare\signored.\sThis\smatches\sthe\sother\ssessions\sAPIs.\sAlso\schange\ssqlite3session_diff()\sso\sthat\sit\sreturns\sSQLITE_SCHEMA,\sinstead\sof\sSQLITE_ERROR,\sif\sthe\stables\sbeing\scompared\sdo\snot\shave\scompatible\sschemas. +D 2015-04-23T17:22:50.000 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7599f0c96df628cd543884b1b2f2a2fbffd00079 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -158,12 +158,12 @@ F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069 F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f F ext/session/sessionB.test 06961b7c3641151f5d23088250ecad132501113c F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4 -F ext/session/sessionD.test bdc20e2384bf92b5719b9e41ad3b18cd9188cf26 +F ext/session/sessionD.test d4744c78334162851d2a2f285c7e603e31b49aa2 F ext/session/session_common.tcl 9de0451b6a47218fc16b9ed8876b6238a0a3d88d F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c 0b26c45c0c3c0b2afaae9bd69ae1e80a6b8e9b5a -F ext/session/sqlite3session.h d9ebd8d4c5791aafdf18165575c7f2223c09279b -F ext/session/test_session.c 67a049635d910c55917f23d067575ab5432d4546 +F ext/session/sqlite3session.c d22a8996f44202a13d0b1ad18757cd509729a23c +F ext/session/sqlite3session.h 8e86f9eec3ed71f1f30eefbe810cbe5bc10b5aa9 +F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e @@ -1271,7 +1271,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ea400eca314d81761fe5c0e329b906c045f0dfe4 -R 57c462c26b9985ec1f9daf86d6b971a1 +P 4d34a3d40da210bebb2a2e6dff094f9a39c92798 +R 77fdc1b8d856af82047ddfafb467bba9 U dan -Z dd15ced7dcdddbd36a44e0c8439b0673 +Z c001be8d13359c151923937b5aa6a277 diff --git a/manifest.uuid b/manifest.uuid index 9d7404abb8..ef8da808c5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4d34a3d40da210bebb2a2e6dff094f9a39c92798 \ No newline at end of file +aada0ad08e3baa10d14d1f3393183110289e068e \ No newline at end of file From 6dc29e60c813032d8bbdd98a14f42e1c9c5ed018 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 2 Jun 2015 09:19:22 +0000 Subject: [PATCH 138/570] Modify the sessions module to ignore all operations on tables with no primary keys as documented. FossilOrigin-Name: bdaf9575cd9ebb33dc5da4062a84bca79e7b0fec --- ext/session/session1.test | 51 ++++++++++++--- ext/session/sessionE.test | 116 +++++++++++++++++++++++++++++++++ ext/session/session_common.tcl | 10 +++ ext/session/sqlite3session.c | 51 ++++++++------- manifest | 19 +++--- manifest.uuid | 2 +- 6 files changed, 207 insertions(+), 42 deletions(-) create mode 100644 ext/session/sessionE.test diff --git a/ext/session/session1.test b/ext/session/session1.test index 1c853a97a1..fc74a1e84e 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -20,16 +20,6 @@ ifcapable !session {finish_test; return} set testprefix session1 -proc do_changeset_test {tn session res} { - set r [list] - foreach x $res {lappend r $x} - uplevel do_test $tn [list [subst -nocommands { - set x [list] - sqlite3session_foreach c [$session changeset] { lappend x [set c] } - set x - }]] [list $r] -} - proc do_changeset_invert_test {tn session res} { set r [list] foreach x $res {lappend r $x} @@ -525,6 +515,47 @@ do_changeset_test 9.2 S {{UPDATE t7 0 ....X.. {{} {} i 1 {} {} i 1 i 1 {} {} {} S delete catch { db2 close } +#------------------------------------------------------------------------- +# Test a really long table name. +# +reset_db +set tblname [string repeat tblname123 100] +do_test 10.1.1 { + execsql " + CREATE TABLE $tblname (a PRIMARY KEY, b); + INSERT INTO $tblname VALUES('xyz', 'def'); + " + sqlite3session S db main + S attach $tblname + execsql " + INSERT INTO $tblname VALUES('uvw', 'abc'); + DELETE FROM $tblname WHERE a = 'xyz'; + " +} {} +breakpoint +do_changeset_test 10.1.2 S " + {INSERT $tblname 0 X. {} {t uvw t abc}} + {DELETE $tblname 0 X. {t xyz t def} {}} +" +do_test 10.1.4 { S delete } {} + +#--------------------------------------------------------------- +reset_db +do_execsql_test 11.1 { + CREATE TABLE t1(a, b); +} +do_test 11.2 { + sqlite3session S db main + S attach t1 + execsql { + INSERT INTO t1 VALUES(1, 2); + } + S changeset +} {} + +S delete + + #------------------------------------------------------------------------- # Test a really long table name. # diff --git a/ext/session/sessionE.test b/ext/session/sessionE.test new file mode 100644 index 0000000000..57962eb6ba --- /dev/null +++ b/ext/session/sessionE.test @@ -0,0 +1,116 @@ +# 2015 June 02 +# +# 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 the sessions module. +# Specifically, it tests that operations on tables without primary keys +# are ignored. +# + + + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} +set testprefix sessionE + +# +# Test plan: +# +# 1.*: Test that non-PK tables are not auto-attached. +# 2.*: Test that explicitly attaching a non-PK table is a no-op. +# 3.*: Test that sqlite3session_diff() on a non-PK table is a no-op. +# + + +#-------------------------------------------------------------------------- +reset_db +do_execsql_test 1.0 { + CREATE TABLE t1(a, b); + CREATE TABLE t2(a PRIMARY KEY, b); +} +do_test 1.1 { + sqlite3session S db main + S attach * + breakpoint + execsql { + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t2 VALUES(1, 2); + } +} {} +do_changeset_test 1.2 S { + {INSERT t2 0 X. {} {i 1 i 2}} +} +S delete + +reset_db +do_execsql_test 2.0 { + CREATE TABLE t1(a, b); + CREATE TABLE t2(a PRIMARY KEY, b); +} +do_test 2.1 { + sqlite3session S db main + S attach t1 + S attach t2 + breakpoint + execsql { + INSERT INTO t1 VALUES(3, 4); + INSERT INTO t2 VALUES(3, 4); + INSERT INTO t1 VALUES(5, 6); + INSERT INTO t2 VALUES(5, 6); + } +} {} +do_changeset_test 2.2 S { + {INSERT t2 0 X. {} {i 3 i 4}} + {INSERT t2 0 X. {} {i 5 i 6}} +} +S delete + +reset_db +forcedelete test.db2 +do_execsql_test 3.0 { + ATTACH 'test.db2' AS aux; + CREATE TABLE aux.t1(a, b); + CREATE TABLE aux.t2(a PRIMARY KEY, b); + + CREATE TABLE t1(a, b); + CREATE TABLE t2(a PRIMARY KEY, b); + + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t2 VALUES(3, 4); +} +do_test 3.1 { + sqlite3session S db main + S attach t1 + S diff aux t1 + + S attach t2 + S diff aux t2 +} {} +do_changeset_test 3.2 S { + {INSERT t2 0 X. {} {i 3 i 4}} +} +do_execsql_test 3.3 { + INSERT INTO t1 VALUES(5, 6); + INSERT INTO t2 VALUES(7, 8); +} +do_changeset_test 3.4 S { + {INSERT t2 0 X. {} {i 3 i 4}} + {INSERT t2 0 X. {} {i 7 i 8}} +} + + +S delete + + + diff --git a/ext/session/session_common.tcl b/ext/session/session_common.tcl index d6ce27a850..f27ad11dc0 100644 --- a/ext/session/session_common.tcl +++ b/ext/session/session_common.tcl @@ -1,4 +1,14 @@ +proc do_changeset_test {tn session res} { + set r [list] + foreach x $res {lappend r $x} + uplevel do_test $tn [list [subst -nocommands { + set x [list] + sqlite3session_foreach c [$session changeset] { lappend x [set c] } + set x + }]] [list $r] +} + proc do_conflict_test {tn args} { proc xConflict {args} { diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 287c5929c1..39923ee779 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1008,32 +1008,33 @@ static int sessionTableInfo( /* ** This function is only called from within a pre-update handler for a ** write to table pTab, part of session pSession. If this is the first -** write to this table, set the SessionTable.nCol variable to the number -** of columns in the table. +** write to this table, initalize the SessionTable.nCol, azCol[] and +** abPK[] arrays accordingly. ** -** Otherwise, if this is not the first time this table has been written -** to, check that the number of columns in the table has not changed. If -** it has not, return zero. -** -** If the number of columns in the table has changed since the last write -** was recorded, set the session error-code to SQLITE_SCHEMA and return -** non-zero. Users are not allowed to change the number of columns in a table -** for which changes are being recorded by the session module. If they do so, -** it is an error. +** If an error occurs, an error code is stored in sqlite3_session.rc and +** non-zero returned. Or, if no error occurs but the table has no primary +** key, sqlite3_session.rc is left set to SQLITE_OK and non-zero returned to +** indicate that updates on this table should be ignored. SessionTable.abPK +** is set to NULL in this case. */ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ if( pTab->nCol==0 ){ + u8 *abPK; assert( pTab->azCol==0 || pTab->abPK==0 ); pSession->rc = sessionTableInfo(pSession->db, pSession->zDb, - pTab->zName, &pTab->nCol, 0, &pTab->azCol, &pTab->abPK + pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK ); + if( pSession->rc==SQLITE_OK ){ + int i; + for(i=0; inCol; i++){ + if( abPK[i] ){ + pTab->abPK = abPK; + break; + } + } + } } - if( pSession->rc==SQLITE_OK - && pTab->nCol!=pSession->hook.xCount(pSession->hook.pCtx) - ){ - pSession->rc = SQLITE_SCHEMA; - } - return pSession->rc; + return (pSession->rc || pTab->abPK==0); } /* @@ -1058,6 +1059,13 @@ static void sessionPreupdateOneChange( /* Load table details if required */ if( sessionInitTable(pSession, pTab) ) return; + /* Check the number of columns in this xPreUpdate call matches the + ** number of columns in the table. */ + if( pTab->nCol!=pSession->hook.xCount(pSession->hook.pCtx) ){ + pSession->rc = SQLITE_SCHEMA; + return; + } + /* Grow the hash table if required */ if( sessionGrowHash(0, pTab) ){ pSession->rc = SQLITE_NOMEM; @@ -1465,10 +1473,9 @@ int sqlite3session_diff( /* Locate and if necessary initialize the target table object */ rc = sessionFindTable(pSession, zTbl, &pTo); if( pTo==0 ) goto diff_out; - if( pTo->nCol==0 ){ - rc = pSession->rc = sessionTableInfo(db, zDb, - pTo->zName, &pTo->nCol, 0, &pTo->azCol, &pTo->abPK - ); + if( sessionInitTable(pSession, pTo) ){ + rc = pSession->rc; + goto diff_out; } /* Check the table schemas match */ diff --git a/manifest b/manifest index 25dfe229ee..434493b0a8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Import\srecent\senhancements\sfrom\strunk. -D 2015-05-29T19:04:58.908 +C Modify\sthe\ssessions\smodule\sto\signore\sall\soperations\son\stables\swith\sno\sprimary\skeys\sas\sdocumented. +D 2015-06-02T09:19:22.231 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 58c16cc8cd876ed112902e70cf33d33f3270b5aa F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -166,7 +166,7 @@ F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a -F ext/session/session1.test 4653867f32a98ce4bbb4a181aac6debe51ca4dfb +F ext/session/session1.test d4f53b9b5add7eeb358e535d6e18552142092429 F ext/session/session2.test a95a2d270b32638c1acba7cb9c81856712d469ac F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 @@ -178,9 +178,10 @@ F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f F ext/session/sessionB.test 06961b7c3641151f5d23088250ecad132501113c F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4 F ext/session/sessionD.test d4744c78334162851d2a2f285c7e603e31b49aa2 -F ext/session/session_common.tcl 9de0451b6a47218fc16b9ed8876b6238a0a3d88d +F ext/session/sessionE.test 9ebeae9918f0a07fafc2b5f4a1636fd8bc940804 +F ext/session/session_common.tcl f4b7b59c617edf0c9b00d94cd93498d225d43837 F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c 9ccf68d542f4afc5dc14295d984bf37a7db6b936 +F ext/session/sqlite3session.c d630293057fcf4274451edec24c2745953ca042c F ext/session/sqlite3session.h 8e86f9eec3ed71f1f30eefbe810cbe5bc10b5aa9 F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1300,7 +1301,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 519054bb72e8f8977b11161c81b0e96ba7bca589 09a38bf665902834936d39341627ded88142e6ae -R 8892830f1d56f04b6b2e14d9642ea36b -U drh -Z 5694d275e23a4dea203ff0f897ed1e57 +P 54bec164ebeaf62d783352b3c4d0de8845394091 +R f80d0c3771ea18894e499ba6e9adad71 +U dan +Z e52febd1b018cb0f724ad3d4cfe4ef9d diff --git a/manifest.uuid b/manifest.uuid index 70a7baacb5..d8666bb556 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -54bec164ebeaf62d783352b3c4d0de8845394091 \ No newline at end of file +bdaf9575cd9ebb33dc5da4062a84bca79e7b0fec \ No newline at end of file From 807547038d78f05597ca6e4e578741a21c9ff95c Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 2 Jun 2015 09:20:46 +0000 Subject: [PATCH 139/570] Add the "finish_test" command to the end of new test script sessionE.test. FossilOrigin-Name: fb3914070791c84b5f323b7359ac845246d8a844 --- ext/session/sessionE.test | 1 + manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ext/session/sessionE.test b/ext/session/sessionE.test index 57962eb6ba..27e530ec7f 100644 --- a/ext/session/sessionE.test +++ b/ext/session/sessionE.test @@ -112,5 +112,6 @@ do_changeset_test 3.4 S { S delete +finish_test diff --git a/manifest b/manifest index 434493b0a8..2204ad1cdc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modify\sthe\ssessions\smodule\sto\signore\sall\soperations\son\stables\swith\sno\sprimary\skeys\sas\sdocumented. -D 2015-06-02T09:19:22.231 +C Add\sthe\s"finish_test"\scommand\sto\sthe\send\sof\snew\stest\sscript\ssessionE.test. +D 2015-06-02T09:20:46.301 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 58c16cc8cd876ed112902e70cf33d33f3270b5aa F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -178,7 +178,7 @@ F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f F ext/session/sessionB.test 06961b7c3641151f5d23088250ecad132501113c F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4 F ext/session/sessionD.test d4744c78334162851d2a2f285c7e603e31b49aa2 -F ext/session/sessionE.test 9ebeae9918f0a07fafc2b5f4a1636fd8bc940804 +F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26 F ext/session/session_common.tcl f4b7b59c617edf0c9b00d94cd93498d225d43837 F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc F ext/session/sqlite3session.c d630293057fcf4274451edec24c2745953ca042c @@ -1301,7 +1301,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 54bec164ebeaf62d783352b3c4d0de8845394091 -R f80d0c3771ea18894e499ba6e9adad71 +P bdaf9575cd9ebb33dc5da4062a84bca79e7b0fec +R dbe1b57e21e93824d104fb3b930d73e6 U dan -Z e52febd1b018cb0f724ad3d4cfe4ef9d +Z cd8fea501989560b39f7780ac3d3b3f9 diff --git a/manifest.uuid b/manifest.uuid index d8666bb556..5f700eaf36 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bdaf9575cd9ebb33dc5da4062a84bca79e7b0fec \ No newline at end of file +fb3914070791c84b5f323b7359ac845246d8a844 \ No newline at end of file From 5898ad69543124bd762d91b341401c704cfd1099 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 11 Jun 2015 17:26:10 +0000 Subject: [PATCH 140/570] Add the sqlite3changegroup_xxx() APIs to the sessions module. For combining multiple changesets or patchsets. FossilOrigin-Name: 0c1a901cd60e557fc676b97625243163dfe9be9d --- ext/session/sqlite3session.c | 201 ++++++++++++++++++++++--------- ext/session/sqlite3session.h | 226 +++++++++++++++++++++++++---------- manifest | 14 +-- manifest.uuid | 2 +- 4 files changed, 318 insertions(+), 125 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 39923ee779..0937c9bb32 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -4045,6 +4045,15 @@ int sqlite3changeset_apply_strm( return rc; } +/* +** sqlite3_changegroup handle. +*/ +struct sqlite3_changegroup { + int rc; /* Error code */ + int bPatch; /* True to accumulate patchsets */ + SessionTable *pList; /* List of tables in current patch */ +}; + /* ** This function is called to merge two changes to the same row together as ** part of an sqlite3changeset_concat() operation. A new change object is @@ -4170,18 +4179,19 @@ static int sessionChangeMerge( } /* -** Add all changes in the changeset passed via the first two arguments to -** hash tables. +** Add all changes in the changeset traversed by the iterator passed as +** the first argument to the changegroup hash tables. */ static int sessionChangesetToHash( sqlite3_changeset_iter *pIter, /* Iterator to read from */ - SessionTable **ppTabList /* IN/OUT: List of table objects */ + sqlite3_changegroup *pGrp /* Changegroup object to add changeset to */ ){ u8 *aRec; int nRec; int rc = SQLITE_OK; SessionTable *pTab = 0; + while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec) ){ const char *zNew; int nCol; @@ -4192,6 +4202,13 @@ static int sessionChangesetToHash( SessionChange *pExist = 0; SessionChange **pp; + if( pGrp->pList==0 ){ + pGrp->bPatch = pIter->bPatchset; + }else if( pIter->bPatchset!=pGrp->bPatch ){ + rc = SQLITE_ERROR; + break; + } + sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect); if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){ /* Search the list for a matching table */ @@ -4199,7 +4216,7 @@ static int sessionChangesetToHash( u8 *abPK; sqlite3changeset_pk(pIter, &abPK, 0); - for(pTab = *ppTabList; pTab; pTab=pTab->pNext){ + for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){ if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break; } if( !pTab ){ @@ -4209,13 +4226,13 @@ static int sessionChangesetToHash( break; } memset(pTab, 0, sizeof(SessionTable)); - pTab->pNext = *ppTabList; + pTab->pNext = pGrp->pList; pTab->nCol = nCol; pTab->abPK = (u8*)&pTab[1]; memcpy(pTab->abPK, abPK, nCol); pTab->zName = (char*)&pTab->abPK[nCol]; memcpy(pTab->zName, zNew, nNew+1); - *ppTabList = pTab; + pGrp->pList = pTab; }else if( pTab->nCol!=nCol || memcmp(pTab->abPK, abPK, nCol) ){ rc = SQLITE_SCHEMA; break; @@ -4262,54 +4279,45 @@ static int sessionChangesetToHash( if( rc==SQLITE_OK ) rc = pIter->rc; return rc; } - -/* -** 1. Iterate through the left-hand changeset. Add an entry to a table -** specific hash table for each change in the changeset. The hash table -** key is the PK of the row affected by the change. + +/* +** Serialize a changeset (or patchset) based on all changesets (or patchsets) +** added to the changegroup object passed as the first argument. ** -** 2. Then interate through the right-hand changeset. Attempt to add an -** entry to a hash table for each component change. If a change already -** exists with the same PK values, combine the two into a single change. +** If xOutput is not NULL, then the changeset/patchset is returned to the +** user via one or more calls to xOutput, as with the other streaming +** interfaces. ** -** 3. Write an output changeset based on the contents of the hash table. +** Or, if xOutput is NULL, then (*ppOut) is populated with a pointer to a +** buffer containing the output changeset before this function returns. In +** this case (*pnOut) is set to the size of the output buffer in bytes. It +** is the responsibility of the caller to free the output buffer using +** sqlite3_free() when it is no longer required. +** +** If successful, SQLITE_OK is returned. Or, if an error occurs, an SQLite +** error code. If an error occurs and xOutput is NULL, (*ppOut) and (*pnOut) +** are both set to 0 before returning. */ -static int sessionChangesetConcat( - sqlite3_changeset_iter *pLeft, - sqlite3_changeset_iter *pRight, +static int sessionChangegroupOutput( + sqlite3_changegroup *pGrp, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut, int *pnOut, void **ppOut ){ - SessionTable *pList = 0; /* List of SessionTable objects */ - int rc; /* Return code */ - int bPatch; /* True for a patchset */ - SessionTable *pTab; + int rc = SQLITE_OK; SessionBuffer buf = {0, 0, 0}; - + SessionTable *pTab; assert( xOutput==0 || (ppOut==0 && pnOut==0) ); - assert( pLeft->zTab==0 && pRight->zTab==0 ); - rc = sessionChangesetToHash(pLeft, &pList); - assert( pLeft->zTab || pList==0 ); - if( rc==SQLITE_OK ){ - rc = sessionChangesetToHash(pRight, &pList); - } - bPatch = pLeft->bPatchset || pRight->bPatchset; - - if( pLeft->zTab && pRight->zTab && pLeft->bPatchset!=pRight->bPatchset ){ - rc = SQLITE_ERROR; - } - /* Create the serialized output changeset based on the contents of the - ** hash tables attached to the SessionTable objects in list pList. + ** hash tables attached to the SessionTable objects in list p->pList. */ - for(pTab=pList; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ + for(pTab=pGrp->pList; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ int i; if( pTab->nEntry==0 ) continue; - sessionAppendTableHdr(&buf, bPatch, pTab, &rc); + sessionAppendTableHdr(&buf, pGrp->bPatch, pTab, &rc); for(i=0; inChange; i++){ SessionChange *p; for(p=pTab->apChange[i]; p; p=p->pNext){ @@ -4336,10 +4344,93 @@ static int sessionChangesetConcat( } sqlite3_free(buf.aBuf); - sessionDeleteTable(pList); return rc; } +/* +** Allocate a new, empty, sqlite3_changegroup. +*/ +int sqlite3changegroup_new(sqlite3_changegroup **pp){ + int rc = SQLITE_OK; /* Return code */ + sqlite3_changegroup *p; /* New object */ + p = (sqlite3_changegroup*)sqlite3_malloc(sizeof(sqlite3_changegroup)); + if( p==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(p, 0, sizeof(sqlite3_changegroup)); + } + *pp = p; + return rc; +} + +/* +** Add the changeset currently stored in buffer pData, size nData bytes, +** to changeset-group p. +*/ +int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void *pData){ + sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ + int rc; /* Return code */ + + rc = sqlite3changeset_start(&pIter, nData, pData); + if( rc==SQLITE_OK ){ + rc = sessionChangesetToHash(pIter, pGrp); + } + sqlite3changeset_finalize(pIter); + return rc; +} + +/* +** Obtain a buffer containing a changeset representing the concatenation +** of all changesets added to the group so far. +*/ +int sqlite3changegroup_output( + sqlite3_changegroup *pGrp, + int *pnData, + void **ppData +){ + return sessionChangegroupOutput(pGrp, 0, 0, pnData, ppData); +} + +/* +** Streaming versions of changegroup_add(). +*/ +int sqlite3changegroup_add_strm( + sqlite3_changegroup *pGrp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn +){ + sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ + int rc; /* Return code */ + + rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); + if( rc==SQLITE_OK ){ + rc = sessionChangesetToHash(pIter, pGrp); + } + sqlite3changeset_finalize(pIter); + return rc; +} + +/* +** Streaming versions of changegroup_output(). +*/ +int sqlite3changegroup_output_strm( + sqlite3_changegroup *pGrp, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +){ + return sessionChangegroupOutput(pGrp, xOutput, pOut, 0, 0); +} + +/* +** Delete a changegroup object. +*/ +void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){ + if( pGrp ){ + sessionDeleteTable(pGrp->pList); + sqlite3_free(pGrp); + } +} + /* ** Combine two changesets together. */ @@ -4351,22 +4442,21 @@ int sqlite3changeset_concat( int *pnOut, /* OUT: Number of bytes in output changeset */ void **ppOut /* OUT: changeset (left right) */ ){ - sqlite3_changeset_iter *pIter1 = 0; - sqlite3_changeset_iter *pIter2 = 0; + sqlite3_changegroup *pGrp; int rc; - *pnOut = 0; - *ppOut = 0; - rc = sqlite3changeset_start(&pIter1, nLeft, pLeft); + rc = sqlite3changegroup_new(&pGrp); if( rc==SQLITE_OK ){ - rc = sqlite3changeset_start(&pIter2, nRight, pRight); + rc = sqlite3changegroup_add(pGrp, nLeft, pLeft); } if( rc==SQLITE_OK ){ - rc = sessionChangesetConcat(pIter1, pIter2, 0, 0, pnOut, ppOut); + rc = sqlite3changegroup_add(pGrp, nRight, pRight); } + if( rc==SQLITE_OK ){ + rc = sqlite3changegroup_output(pGrp, pnOut, ppOut); + } + sqlite3changegroup_delete(pGrp); - sqlite3changeset_finalize(pIter1); - sqlite3changeset_finalize(pIter2); return rc; } @@ -4381,20 +4471,21 @@ int sqlite3changeset_concat_strm( int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ){ - sqlite3_changeset_iter *pIter1 = 0; - sqlite3_changeset_iter *pIter2 = 0; + sqlite3_changegroup *pGrp; int rc; - rc = sqlite3changeset_start_strm(&pIter1, xInputA, pInA); + rc = sqlite3changegroup_new(&pGrp); if( rc==SQLITE_OK ){ - rc = sqlite3changeset_start_strm(&pIter2, xInputB, pInB); + rc = sqlite3changegroup_add_strm(pGrp, xInputA, pInA); } if( rc==SQLITE_OK ){ - rc = sessionChangesetConcat(pIter1, pIter2, xOutput, pOut, 0, 0); + rc = sqlite3changegroup_add_strm(pGrp, xInputB, pInB); } + if( rc==SQLITE_OK ){ + rc = sqlite3changegroup_output_strm(pGrp, xOutput, pOut); + } + sqlite3changegroup_delete(pGrp); - sqlite3changeset_finalize(pIter1); - sqlite3changeset_finalize(pIter2); return rc; } diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index c8ce488ba7..f2df143e1a 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -683,70 +683,22 @@ int sqlite3changeset_invert( ** single changeset. The result is a changeset equivalent to applying ** changeset A followed by changeset B. ** -** Rows are identified by the values in their PRIMARY KEY columns. A change -** in changeset A is considered to apply to the same row as a change in -** changeset B if the two rows have the same primary key. +** This function combines the two input changesets using an +** sqlite3_changegroup object. Calling it produces similar results as the +** following code fragment: ** -** Changes to rows that appear only in changeset A or B are copied into the -** output changeset. Or, if both changeset A and B contain a change that -** applies to a single row, the output depends on the type of each change, -** as follows: +** sqlite3_changegroup *pGrp; +** rc = sqlite3_changegroup_new(&pGrp); +** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA); +** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nB, pB); +** if( rc==SQLITE_OK ){ +** rc = sqlite3changegroup_output(pGrp, pnOut, ppOut); +** }else{ +** *ppOut = 0; +** *pnOut = 0; +** } ** -**
  • -** -** -**
    Change A Change B Output Change -**
    INSERT INSERT -** Change A is copied into the output changeset. Change B is discarded. -** This case does not occur if changeset B is recorded immediately after -** changeset A. -**
    INSERT UPDATE -** An INSERT change is copied into the output changeset. The values in -** the INSERT change are as if the row was inserted by change A and then -** updated according to change B. -**
    INSERT DELETE -** No change at all is copied into the output changeset. -**
    UPDATE INSERT -** Change A is copied into the output changeset. Change B is discarded. -** This case does not occur if changeset B is recorded immediately after -** changeset A. -**
    UPDATE UPDATE -** A single UPDATE is copied into the output changeset. The accompanying -** values are as if the row was updated once by change A and then again -** by change B. -**
    UPDATE DELETE -** A single DELETE is copied into the output changeset. -**
    DELETE INSERT -** If one or more of the column values in the row inserted by change -** B differ from those in the row deleted by change A, an UPDATE -** change is added to the output changeset. Otherwise, if the inserted -** row is exactly the same as the deleted row, no change is added to -** the output changeset. -**
    DELETE UPDATE -** Change A is copied into the output changeset. Change B is discarded. -** This case does not occur if changeset B is recorded immediately after -** changeset A. -**
    DELETE DELETE -** Change A is copied into the output changeset. Change B is discarded. -** This case does not occur if changeset B is recorded immediately after -** changeset A. -**
    -** -** If the two changesets contain changes to the same table, then the number -** of columns and the position of the primary key columns for the table must -** be the same in each changeset. If this is not the case, attempting to -** concatenate the two changesets together fails and this function returns -** SQLITE_SCHEMA. If either of the two input changesets appear to be corrupt, -** and the corruption is detected, SQLITE_CORRUPT is returned. Or, if an -** out-of-memory condition occurs during processing, this function returns -** SQLITE_NOMEM. -** -** If none of the above errors occur, SQLITE_OK is returned and *ppOut set -** to point to a buffer containing the output changeset. It is the -** responsibility of the caller to eventually call sqlite3_free() on *ppOut -** to release memory allocated for the buffer. *pnOut is set to the number -** of bytes in the output changeset. If an error does occur, both *ppOut and -** *pnOut are set to zero before returning. +** Refer to the sqlite3_changegroup documentation below for details. */ int sqlite3changeset_concat( int nA, /* Number of bytes in buffer pA */ @@ -757,6 +709,148 @@ int sqlite3changeset_concat( void **ppOut /* OUT: Buffer containing output changeset */ ); + +/* +** Changegroup handle. +*/ +typedef struct sqlite3_changegroup sqlite3_changegroup; + +/* +** CAPI3REF: Combine two or more changesets into a single changeset. +** +** An sqlite3_changegroup object is used to combine two or more changesets +** (or patchsets) into a single changeset (or patchset). A single changegroup +** object may combine changesets or patchsets, but not both. The output is +** always in the same format as the input. +** +** If successful, this function returns SQLITE_OK and populates (*pp) with +** a pointer to a new sqlite3_changegroup object before returning. The caller +** should eventually free the returned object using a call to +** sqlite3changegroup_delete(). If an error occurs, an SQLite error code +** (i.e. SQLITE_NOMEM) is returned and *pp is set to NULL. +** +** The usual usage pattern for an sqlite3_changegroup object is as follows: +** +**
      +**
    • It is created using a call to sqlite3changegroup_new(). +** +**
    • Zero or more changesets (or patchsets) are added to the object +** by calling sqlite3changegroup_add(). +** +**
    • The result of combining all input changesets together is obtained +** by the application via a call to sqlite3changegroup_output(). +** +**
    • The object is deleted using a call to sqlite3changegroup_delete(). +**
    +** +** Any number of calls to add() and output() may be made between the calls to +** new() and delete(), and in any order. +** +** As well as the regular sqlite3changegroup_add() and +** sqlite3changegroup_output() functions, also available are the streaming +** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm(). +*/ +int sqlite3changegroup_new(sqlite3_changegroup **pp); + +/* +** Add all changes within the changeset (or patchset) in buffer pData (size +** nData bytes) to the changegroup. +** +** If the buffer contains a patchset, then all prior calls to this function +** on the same changegroup object must also have specified patchsets. Or, if +** the buffer contains a changeset, so must have the earlier calls to this +** function. Otherwise, SQLITE_ERROR is returned and no changes are added +** to the changegroup. +** +** Rows within the changeset and changegroup are identified by the values in +** their PRIMARY KEY columns. A change in the changeset is considered to +** apply to the same row as a change already present in the changegroup if +** the two rows have the same primary key. +** +** Changes to rows that that do not already appear in the changegroup are +** simply copied into it. Or, if both the new changeset and the changegroup +** contain changes that apply to a single row, the final contents of the +** changegroup depends on the type of each change, as follows: +** +** +** +** +**
    Existing Change New Change Output Change +**
    INSERT INSERT +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    INSERT UPDATE +** The INSERT change remains in the changegroup. The values in the +** INSERT change are modified as if the row was inserted by the +** existing change and then updated according to the new change. +**
    INSERT DELETE +** The existing INSERT is removed from the changegroup. The DELETE is +** not added. +**
    UPDATE INSERT +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    UPDATE UPDATE +** The existing UPDATE remains within the changegroup. It is amended +** so that the accompanying values are as if the row was updated once +** by the existing change and then again by the new change. +**
    UPDATE DELETE +** The existing UPDATE is replaced by the new DELETE within the +** changegroup. +**
    DELETE INSERT +** If one or more of the column values in the row inserted by the +** new change differ from those in the row deleted by the existing +** change, the existing DELETE is replaced by an UPDATE within the +** changegroup. Otherwise, if the inserted row is exactly the same +** as the deleted row, the existing DELETE is simply discarded. +**
    DELETE UPDATE +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    DELETE DELETE +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    +** +** If the new changeset contains changes to a table that is already present +** in the changegroup, then the number of columns and the position of the +** primary key columns for the table must be consistent. If this is not the +** case, this function fails with SQLITE_SCHEMA. If the input changeset +** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is +** returned. Or, if an out-of-memory condition occurs during processing, this +** function returns SQLITE_NOMEM. In all cases, if an error occurs the +** final contents of the changegroup is undefined. +** +** If no error occurs, SQLITE_OK is returned. +*/ +int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); + +/* +** Obtain a buffer containing a changeset (or patchset) representing the +** current contents of the changegroup. If the inputs to the changegroup +** were themselves changesets, the output is a changeset. Or, if the +** inputs were patchsets, the output is also a patchset. +** +** If an error occurs, an SQLite error code is returned and the output +** variables (*pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK +** is returned and the output variables are set to the size of and a +** pointer to the output buffer, respectively. In this case it is the +** responsibility of the caller to eventually free the buffer using a +** call to sqlite3_free(). +*/ +int sqlite3changegroup_output( + sqlite3_changegroup*, + int *pnData, /* OUT: Size of output buffer in bytes */ + void **ppData /* OUT: Pointer to output buffer */ +); + +/* +** Delete a changegroup object. +*/ +void sqlite3changegroup_delete(sqlite3_changegroup*); + /* ** CAPI3REF: Apply A Changeset To A Database ** @@ -1138,6 +1232,14 @@ int sqlite3session_patchset_strm( int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); +int sqlite3changegroup_add_strm(sqlite3_changegroup*, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn +); +int sqlite3changegroup_output_strm(sqlite3_changegroup*, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); /* diff --git a/manifest b/manifest index 2204ad1cdc..c7877d9297 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s"finish_test"\scommand\sto\sthe\send\sof\snew\stest\sscript\ssessionE.test. -D 2015-06-02T09:20:46.301 +C Add\sthe\ssqlite3changegroup_xxx()\sAPIs\sto\sthe\ssessions\smodule.\sFor\scombining\smultiple\schangesets\sor\spatchsets. +D 2015-06-11T17:26:10.939 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 58c16cc8cd876ed112902e70cf33d33f3270b5aa F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -181,8 +181,8 @@ F ext/session/sessionD.test d4744c78334162851d2a2f285c7e603e31b49aa2 F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26 F ext/session/session_common.tcl f4b7b59c617edf0c9b00d94cd93498d225d43837 F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c d630293057fcf4274451edec24c2745953ca042c -F ext/session/sqlite3session.h 8e86f9eec3ed71f1f30eefbe810cbe5bc10b5aa9 +F ext/session/sqlite3session.c 78e5b310cd6e655e9166f40dc8a319c0c866cfdc +F ext/session/sqlite3session.h 772cffe38f11bd62f434eabf080157eabf3d553e F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 @@ -1301,7 +1301,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P bdaf9575cd9ebb33dc5da4062a84bca79e7b0fec -R dbe1b57e21e93824d104fb3b930d73e6 +P fb3914070791c84b5f323b7359ac845246d8a844 +R 8257ada0208a724be61180fd75fdecb0 U dan -Z cd8fea501989560b39f7780ac3d3b3f9 +Z fef5e9795fb303b4eab93bd557fcafaf diff --git a/manifest.uuid b/manifest.uuid index 5f700eaf36..c7a49060eb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fb3914070791c84b5f323b7359ac845246d8a844 \ No newline at end of file +0c1a901cd60e557fc676b97625243163dfe9be9d \ No newline at end of file From 6c39e6a80008610147fda192405472c88578bf73 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 1 Oct 2015 16:35:57 +0000 Subject: [PATCH 141/570] Changes to the sesssions module ensure that tables appear within changesets and patchsets in the same order that they were attached to the sessions object. FossilOrigin-Name: 7695890230dc1e0c6db9b7aa509db2039c7f7239 --- ext/session/session1.test | 11 -- ext/session/session2.test | 4 +- ext/session/sessionB.test | 10 -- ext/session/sessionF.test | 295 +++++++++++++++++++++++++++++++++ ext/session/session_common.tcl | 22 +++ ext/session/sqlite3session.c | 24 ++- ext/session/sqlite3session.h | 25 +++ manifest | 25 +-- manifest.uuid | 2 +- 9 files changed, 376 insertions(+), 42 deletions(-) create mode 100644 ext/session/sessionF.test diff --git a/ext/session/session1.test b/ext/session/session1.test index fc74a1e84e..7aebe8c000 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -20,17 +20,6 @@ ifcapable !session {finish_test; return} set testprefix session1 -proc do_changeset_invert_test {tn session res} { - set r [list] - foreach x $res {lappend r $x} - uplevel do_test $tn [list [subst -nocommands { - set x [list] - set changeset [sqlite3changeset_invert [$session changeset]] - sqlite3session_foreach c [set changeset] { lappend x [set c] } - set x - }]] [list $r] -} - do_execsql_test 1.0 { CREATE TABLE t1(x PRIMARY KEY, y); INSERT INTO t1 VALUES('abc', 'def'); diff --git a/ext/session/session2.test b/ext/session/session2.test index 0035e39dbf..cd8c2869e7 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -298,8 +298,8 @@ foreach {tn sql changeset} { DELETE FROM t1 WHERE 1; UPDATE t2 SET x = 34; } { - {UPDATE t2 0 .X {i 36 i 37} {i 34 {} {}}} {DELETE t1 0 X {i 35} {}} + {UPDATE t2 0 .X {i 36 i 37} {i 34 {} {}}} } } { do_iterator_test 5.$tn * $sql $changeset @@ -413,8 +413,8 @@ do_iterator_test 6.1.8 * { SELECT indirect(0); UPDATE t4 SET a = 'two' WHERE b = 1; } { - {INSERT t4 0 .X {} {t two i 1}} {INSERT t3 1 .X {} {t two i 1}} + {INSERT t4 0 .X {} {t two i 1}} } sqlite3session S db main diff --git a/ext/session/sessionB.test b/ext/session/sessionB.test index f1af5d213c..eae41f76ad 100644 --- a/ext/session/sessionB.test +++ b/ext/session/sessionB.test @@ -31,16 +31,6 @@ set testprefix sessionB # 3.*: Test that sqlite3changeset_invert() works with patchset blobs. # Correct behaviour is to return SQLITE_CORRUPT. -proc do_patchset_test {tn session res} { - set r [list] - foreach x $res {lappend r $x} - uplevel do_test $tn [list [subst -nocommands { - set x [list] - sqlite3session_foreach c [$session patchset] { lappend x [set c] } - set x - }]] [list $r] -} - proc do_sql2patchset_test {tn sql res} { sqlite3session S db main S attach * diff --git a/ext/session/sessionF.test b/ext/session/sessionF.test new file mode 100644 index 0000000000..ba57bf85ec --- /dev/null +++ b/ext/session/sessionF.test @@ -0,0 +1,295 @@ +# 2015 June 02 +# +# 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 the sessions module. +# Specifically, it tests that tables appear in the correct order +# within changesets and patchsets. +# + + + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} +set testprefix sessionF + +# +# Test plan: +# +# 1.*: Test that sqlite3session_changeset() and sqlite3session_patchset() +# output tables in the right order. +# +# 2.*: Test that sqlite3session_invert() does not modify the order of +# tables within a changeset. +# +# 3.*: Test that sqlite3session_concat outputs tables in the right order. +# + +# Create a db schema to use. +# +do_execsql_test 1.0 { + CREATE TABLE t3(e PRIMARY KEY, f); + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(c PRIMARY KEY, d); +} + +#----------------------------------------------------------------------- +# 1.* - changeset() and patchset(). +# + +foreach {tn setup result} { + 1 { + S attach * + } { + {INSERT t2 0 X. {} {i 2 t two}} + {INSERT t1 0 X. {} {i 1 t one}} + {INSERT t3 0 X. {} {i 3 t three}} + } + + 2 { + S attach t1 + S attach * + } { + {INSERT t1 0 X. {} {i 1 t one}} + {INSERT t2 0 X. {} {i 2 t two}} + {INSERT t3 0 X. {} {i 3 t three}} + } + + 3 { + S attach t3 + S attach t2 + S attach t1 + } { + {INSERT t3 0 X. {} {i 3 t three}} + {INSERT t2 0 X. {} {i 2 t two}} + {INSERT t1 0 X. {} {i 1 t one}} + } +} { + execsql { + DELETE FROM t1; + DELETE FROM t2; + DELETE FROM t3; + } + sqlite3session S db main + eval $setup + + do_execsql_test 1.$tn.1 { + INSERT INTO t2 VALUES(2, 'two'); + INSERT INTO t1 VALUES(1, 'one'); + INSERT INTO t3 VALUES(3, 'three'); + } + + do_changeset_test 1.1.$tn.2 S $result + do_patchset_test 1.1.$tn.3 S $result + + S delete +} + +foreach {tn setup result} { + 1 { + S attach * + } { + {INSERT t2 0 X. {} {i 4 t four}} + {INSERT t2 0 X. {} {i 5 t five}} + {INSERT t1 0 X. {} {i 1 t one}} + {INSERT t3 0 X. {} {i 6 t six}} + } + + 2 { + S attach t1 + S attach * + } { + {INSERT t1 0 X. {} {i 1 t one}} + {INSERT t2 0 X. {} {i 4 t four}} + {INSERT t2 0 X. {} {i 5 t five}} + {INSERT t3 0 X. {} {i 6 t six}} + } + + 3 { + S attach t3 + S attach t2 + S attach t1 + } { + {INSERT t3 0 X. {} {i 6 t six}} + {INSERT t2 0 X. {} {i 4 t four}} + {INSERT t2 0 X. {} {i 5 t five}} + {INSERT t1 0 X. {} {i 1 t one}} + } +} { + execsql { + DELETE FROM t1; + DELETE FROM t2; + DELETE FROM t3; + } + sqlite3session S db main + eval $setup + + do_execsql_test 1.$tn.1 { + INSERT INTO t2 VALUES(2, 'two'); + INSERT INTO t1 VALUES(1, 'one'); + DELETE FROM t2; + INSERT INTO t2 VALUES(4, 'four'); + INSERT INTO t2 VALUES(5, 'five'); + INSERT INTO t3 VALUES(6, 'six'); + } + + do_changeset_test 1.2.$tn.2 S $result + do_patchset_test 1.2.$tn.2 S $result + + S delete +} + +#------------------------------------------------------------------------- +# 2.* - invert() +# + +foreach {tn setup result} { + 1 { + S attach * + } { + {DELETE t2 0 X. {i 4 t four} {}} + {DELETE t2 0 X. {i 5 t five} {}} + {DELETE t1 0 X. {i 1 t one} {}} + {DELETE t3 0 X. {i 6 t six} {}} + } + + 2 { + S attach t1 + S attach * + } { + {DELETE t1 0 X. {i 1 t one} {}} + {DELETE t2 0 X. {i 4 t four} {}} + {DELETE t2 0 X. {i 5 t five} {}} + {DELETE t3 0 X. {i 6 t six} {}} + } + + 3 { + S attach t3 + S attach t2 + S attach t1 + } { + {DELETE t3 0 X. {i 6 t six} {}} + {DELETE t2 0 X. {i 4 t four} {}} + {DELETE t2 0 X. {i 5 t five} {}} + {DELETE t1 0 X. {i 1 t one} {}} + } +} { + execsql { + DELETE FROM t1; + DELETE FROM t2; + DELETE FROM t3; + } + sqlite3session S db main + eval $setup + + do_execsql_test 1.$tn.1 { + INSERT INTO t2 VALUES(2, 'two'); + INSERT INTO t1 VALUES(1, 'one'); + DELETE FROM t2; + INSERT INTO t2 VALUES(4, 'four'); + INSERT INTO t2 VALUES(5, 'five'); + INSERT INTO t3 VALUES(6, 'six'); + } + + do_changeset_invert_test 2.$tn.2 S $result + + S delete +} + +#------------------------------------------------------------------------- +# 3.* - concat() +# +foreach {tn setup1 sql1 setup2 sql2 result} { + 1 { + S attach * + } { + INSERT INTO t1 VALUES(1, 'one'); + INSERT INTO t2 VALUES(2, 'two'); + } { + S attach t2 + S attach t1 + } { + INSERT INTO t1 VALUES(3, 'three'); + INSERT INTO t2 VALUES(4, 'four'); + } { + {INSERT t1 0 X. {} {i 1 t one}} + {INSERT t1 0 X. {} {i 3 t three}} + {INSERT t2 0 X. {} {i 2 t two}} + {INSERT t2 0 X. {} {i 4 t four}} + } + + 1 { + S attach t2 + S attach t1 + } { + INSERT INTO t1 VALUES(1, 'one'); + INSERT INTO t2 VALUES(2, 'two'); + } { + S attach * + } { + INSERT INTO t1 VALUES(3, 'three'); + INSERT INTO t2 VALUES(4, 'four'); + } { + {INSERT t2 0 X. {} {i 2 t two}} + {INSERT t2 0 X. {} {i 4 t four}} + {INSERT t1 0 X. {} {i 1 t one}} + {INSERT t1 0 X. {} {i 3 t three}} + } + + 1 { + S attach * + } { + INSERT INTO t2 VALUES(2, 'two'); + } { + S attach * + } { + INSERT INTO t1 VALUES(3, 'three'); + INSERT INTO t2 VALUES(4, 'four'); + INSERT INTO t3 VALUES(5, 'five'); + } { + {INSERT t2 0 X. {} {i 2 t two}} + {INSERT t2 0 X. {} {i 4 t four}} + {INSERT t1 0 X. {} {i 3 t three}} + {INSERT t3 0 X. {} {i 5 t five}} + } + +} { + execsql { + DELETE FROM t1; + DELETE FROM t2; + DELETE FROM t3; + } + sqlite3session S db main + eval $setup1 + execsql $sql1 + set c1 [S changeset] + S delete + + sqlite3session S db main + eval $setup2 + execsql $sql2 + set c2 [S changeset] + S delete + + set res [list] + sqlite3session_foreach x [sqlite3changeset_concat $c1 $c2] { + lappend res $x + } + + do_test 3.$tn { set res } [list {*}$result] +} + + +finish_test + diff --git a/ext/session/session_common.tcl b/ext/session/session_common.tcl index f27ad11dc0..38eebec0a0 100644 --- a/ext/session/session_common.tcl +++ b/ext/session/session_common.tcl @@ -9,6 +9,28 @@ proc do_changeset_test {tn session res} { }]] [list $r] } +proc do_patchset_test {tn session res} { + set r [list] + foreach x $res {lappend r $x} + uplevel do_test $tn [list [subst -nocommands { + set x [list] + sqlite3session_foreach c [$session patchset] { lappend x [set c] } + set x + }]] [list $r] +} + + +proc do_changeset_invert_test {tn session res} { + set r [list] + foreach x $res {lappend r $x} + uplevel do_test $tn [list [subst -nocommands { + set x [list] + set changeset [sqlite3changeset_invert [$session changeset]] + sqlite3session_foreach c [set changeset] { lappend x [set c] } + set x + }]] [list $r] +} + proc do_conflict_test {tn args} { proc xConflict {args} { diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 0937c9bb32..546a22a072 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1188,7 +1188,7 @@ static int sessionFindTable( ){ rc = sqlite3session_attach(pSession, zName); if( rc==SQLITE_OK ){ - pRet = pSession->pTable; + for(pRet=pSession->pTable; pRet->pNext; pRet=pRet->pNext); assert( 0==sqlite3_strnicmp(pRet->zName, zName, nName+1) ); } } @@ -1675,12 +1675,17 @@ int sqlite3session_attach( if( !pTab ){ rc = SQLITE_NOMEM; }else{ - /* Populate the new SessionTable object and link it into the list. */ + /* Populate the new SessionTable object and link it into the list. + ** The new object must be linked onto the end of the list, not + ** simply added to the start of it in order to ensure that tables + ** appear in the correct order when a changeset or patchset is + ** eventually generated. */ + SessionTable **ppTab; memset(pTab, 0, sizeof(SessionTable)); pTab->zName = (char *)&pTab[1]; memcpy(pTab->zName, zName, nName+1); - pTab->pNext = pSession->pTable; - pSession->pTable = pTab; + for(ppTab=&pSession->pTable; *ppTab; ppTab=&(*ppTab)->pNext); + *ppTab = pTab; } } } @@ -4220,19 +4225,26 @@ static int sessionChangesetToHash( if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break; } if( !pTab ){ + SessionTable **ppTab; + pTab = sqlite3_malloc(sizeof(SessionTable) + nCol + nNew+1); if( !pTab ){ rc = SQLITE_NOMEM; break; } memset(pTab, 0, sizeof(SessionTable)); - pTab->pNext = pGrp->pList; pTab->nCol = nCol; pTab->abPK = (u8*)&pTab[1]; memcpy(pTab->abPK, abPK, nCol); pTab->zName = (char*)&pTab->abPK[nCol]; memcpy(pTab->zName, zNew, nNew+1); - pGrp->pList = pTab; + + /* The new object must be linked on to the end of the list, not + ** simply added to the start of it. This is to ensure that the + ** tables within the output of sqlite3changegroup_output() are in + ** the right order. */ + for(ppTab=&pGrp->pList; *ppTab; ppTab=&(*ppTab)->pNext); + *ppTab = pTab; }else if( pTab->nCol!=nCol || memcmp(pTab->abPK, abPK, nCol) ){ rc = SQLITE_SCHEMA; break; diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index f2df143e1a..71f02159cf 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -206,6 +206,14 @@ void sqlite3session_table_filter( ** a database with a compatible schema using the [sqlite3changeset_apply()] ** API. ** +** Within a changeset generated by this function, all changes related to a +** single table are grouped together. In other words, when iterating through +** a changeset or when applying a changeset to a database, all changes related +** to a single table are processed before moving on to the next table. Tables +** are sorted in the same order in which they were attached (or auto-attached) +** to the sqlite3_session object. The order in which the changes related to +** a single table are stored is undefined. +** ** Following a successful call to this function, it is the responsibility of ** the caller to eventually free the buffer that *ppChangeset points to using ** [sqlite3_free()]. @@ -358,6 +366,11 @@ int sqlite3session_diff( ** SQLITE_CHANGESET_DATA conflicts can be detected or reported if a patchset ** is passed to the sqlite3changeset_apply() API. Other conflict types work ** in the same way as for changesets. +** +** Changes within a patchset are ordered in the same way as for changesets +** generated by the sqlite3session_changeset() function (i.e. all changes for +** a single table are grouped together, tables appear in the order in which +** they were attached to the session object). */ int sqlite3session_patchset( sqlite3_session *pSession, /* Session object */ @@ -659,6 +672,9 @@ int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); **
  • For each UPDATE change, the old.* and new.* values are exchanged. ** ** +** This function does not change the order in which changes appear within +** the changeset. It merely reverses the sense of each individual change. +** ** If successful, a pointer to a buffer containing the inverted changeset ** is stored in *ppOut, the size of the same buffer is stored in *pnOut, and ** SQLITE_OK is returned. If an error occurs, both *pnOut and *ppOut are @@ -833,6 +849,15 @@ int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); ** were themselves changesets, the output is a changeset. Or, if the ** inputs were patchsets, the output is also a patchset. ** +** As with the output of the sqlite3session_changeset() and +** sqlite3session_patchset() functions, all changes related to a single +** table are grouped together in the output of this function. Tables appear +** in the same order as for the very first changeset added to the changegroup. +** If the second or subsequent changesets added to the changegroup contain +** changes for tables that do not appear in the first changeset, they are +** appended onto the end of the output changeset, again in the order in +** which they are first encountered. +** ** If an error occurs, an SQLite error code is returned and the output ** variables (*pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK ** is returned and the output variables are set to the size of and a diff --git a/manifest b/manifest index bcf5b0db01..794f881303 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\srecent\senhancements\sfrom\strunk,\sand\sespecially\sthe\sfix\sfor\nticket\s[1b266395d6bc10]. -D 2015-09-30T14:50:39.955 +C Changes\sto\sthe\ssesssions\smodule\sensure\sthat\stables\sappear\swithin\schangesets\sand\spatchsets\sin\sthe\ssame\sorder\sthat\sthey\swere\sattached\sto\sthe\ssessions\sobject. +D 2015-10-01T16:35:57.175 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in fdcfdc361f0a3723da9b48b967f259f7aaff3ad5 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -256,8 +256,8 @@ F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a -F ext/session/session1.test d4f53b9b5add7eeb358e535d6e18552142092429 -F ext/session/session2.test a95a2d270b32638c1acba7cb9c81856712d469ac +F ext/session/session1.test 5dab50ce55c859e829bae24f0787013f51775fc5 +F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0 F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169 @@ -265,14 +265,15 @@ F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 8e194b3f655d861ca36de5d4de53f702751bab3b F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069 F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f -F ext/session/sessionB.test 06961b7c3641151f5d23088250ecad132501113c +F ext/session/sessionB.test 886252dcb7e692e62ef7e357456200912e367823 F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4 F ext/session/sessionD.test d4744c78334162851d2a2f285c7e603e31b49aa2 F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26 -F ext/session/session_common.tcl f4b7b59c617edf0c9b00d94cd93498d225d43837 +F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce +F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596 F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c 78e5b310cd6e655e9166f40dc8a319c0c866cfdc -F ext/session/sqlite3session.h 772cffe38f11bd62f434eabf080157eabf3d553e +F ext/session/sqlite3session.c 1ace1d1e4cb32cf60ca6e8ed1ae8d4c9f99ca458 +F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 @@ -1409,7 +1410,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c91065f8edb1e54076791716fc20d3fcfe3070dc e796c0efb6cf17444b53af75046daf7d8fa82f78 -R 0237333bf6dc63bf0c4f4c66d7918366 -U drh -Z 5f6cedfd7517312f688a69652091b608 +P b2face9aa95ade96a5666c70b6b31064c1ad0977 +R 67f4bc03b9ceb2707f867778f6790d70 +U dan +Z c3622f418cca20fcda99ae888e36e276 diff --git a/manifest.uuid b/manifest.uuid index 75c74a20e2..5274d2fafa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b2face9aa95ade96a5666c70b6b31064c1ad0977 \ No newline at end of file +7695890230dc1e0c6db9b7aa509db2039c7f7239 \ No newline at end of file From 86151e8905a6767e3c5173dba111ead43ec865ca Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Dec 2015 14:37:16 +0000 Subject: [PATCH 142/570] Avoid unnecessary work inside of verifyDbFile() in the unix VFS. FossilOrigin-Name: f3c0579e931799088e9a83757e25bae229120697 --- manifest | 15 +++++++++------ manifest.uuid | 2 +- src/os_unix.c | 8 +++++--- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index d584f281f3..11df61697b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\stest\scase\sof\sthe\sform\s"WHERE\sa<2\sOR\sa<3"\susing\sPRAGMA\scount_changes.\nThis\stest\scase\swas\sfailing\sbefore\sthe\s3.9.0\srelease. -D 2015-12-08T04:18:33.696 +C Avoid\sunnecessary\swork\sinside\sof\sverifyDbFile()\sin\sthe\sunix\sVFS. +D 2015-12-08T14:37:16.738 F Makefile.in 28bcd6149e050dff35d4dcfd97e890cd387a499d F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e8fdca1cb89a1b58b5f4d3a130ea9a3d28cb314d @@ -323,7 +323,7 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c 0ca6d8710366fbb01a275160f018334cd347cbda +F src/os_unix.c 2f3bb1da50782128edf31fb17d22dc46f14c6eae F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c f92aacd5216d8815136c9e0190041783c602641a @@ -1408,7 +1408,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 07e5199c6f868cc02a0b708865254056c4f3daf3 -R 17b34bcad46ec764b462c91813dd5909 +P 177862c1d50ba899d890fbc35f35e7423bc6aed5 +R cc3c3a45cf6a02d31e382067a458ce71 +T *branch * unix-vfs-optimization +T *sym-unix-vfs-optimization * +T -sym-trunk * U drh -Z 86e126efc794a5aaf900005c30a5cf69 +Z fcbe6020f6a9bf3f613adea5032fb70c diff --git a/manifest.uuid b/manifest.uuid index d39829dc75..12ed6b4bd9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -177862c1d50ba899d890fbc35f35e7423bc6aed5 \ No newline at end of file +f3c0579e931799088e9a83757e25bae229120697 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 791ba5d8d9..25f769fa50 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1315,6 +1315,10 @@ static int fileHasMoved(unixFile *pFile){ static void verifyDbFile(unixFile *pFile){ struct stat buf; int rc; + + /* These verifications occurs for the main database only */ + if( pFile->ctrlFlags & UNIXFILE_NOLOCK ) return; + rc = osFstat(pFile->h, &buf); if( rc!=0 ){ sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath); @@ -5761,9 +5765,6 @@ static int unixOpen( p->openFlags = openFlags; } #endif - - noLock = eType!=SQLITE_OPEN_MAIN_DB; - #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE if( fstatfs(fd, &fsInfo) == -1 ){ @@ -5782,6 +5783,7 @@ static int unixOpen( /* Set up appropriate ctrlFlags */ if( isDelete ) ctrlFlags |= UNIXFILE_DELETE; if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY; + noLock = eType!=SQLITE_OPEN_MAIN_DB; if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK; if( syncDir ) ctrlFlags |= UNIXFILE_DIRSYNC; if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI; From 710b33b9992285bf53d50182c0543b8d8030f4b1 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sun, 3 Jan 2016 18:59:28 +0000 Subject: [PATCH 143/570] Alternative to [76f5efa6], move definition of utf8_printf up. FossilOrigin-Name: 54c5522dda239cb9775709495ed7eb56a5dd8e11 --- manifest | 17 +++++++------ manifest.uuid | 2 +- src/shell.c | 68 +++++++++++++++++++++++++-------------------------- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/manifest b/manifest index 584914720e..6efc1e7e97 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Bug\sfix:\sthe\sconflict\sresolution\sbehavior\sfor\sthe\simplied\sNOT\sNULL\sconstraint\non\sthe\sPRIMARY\sKEY\sof\sa\sWITHOUT\sROWID\stable\sshould\sbe\sABORT. -D 2016-01-03T18:07:57.631 +C Alternative\sto\s[76f5efa6],\smove\sdefinition\sof\sutf8_printf\sup. +D 2016-01-03T18:59:28.715 F Makefile.in 28bcd6149e050dff35d4dcfd97e890cd387a499d F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 5fff077fcc46de7714ed6eebb6159a4c00eab751 @@ -334,7 +334,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c a83b41104e6ff69855d03cd0aaa09e93927ec39f F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c f8fded11fc443a9f5a73cc5db069d06b34460e2f -F src/shell.c ed71dc7679e6f087a3f1ea3f9dae4b0fae7209c3 +F src/shell.c 3ecb7a857c4595fef9ae4141fc8bb8dc53021be2 F src/sqlite.h.in 7d87d71b9a4689c51fa092f48f16590ff71558e3 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d @@ -1406,7 +1406,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 76f5efa68728d899a63a74f2528dfd0c497aa5f0 -R 478df71a9631f4b73fcefbae5de2f355 -U drh -Z 2ce3cb02ff6782c368c437352328d0d1 +P e30062e9f6cae980150dda7df440b36dfdcb7bbe +R ebd31578448110e2087f3d6a13f40257 +T *branch * altShellFix +T *sym-altShellFix * +T -sym-trunk * +U mistachkin +Z f75cb2b820513d79cf30ddfb170e4e99 diff --git a/manifest.uuid b/manifest.uuid index c0ad5b411d..2bb8fd855c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e30062e9f6cae980150dda7df440b36dfdcb7bbe \ No newline at end of file +54c5522dda239cb9775709495ed7eb56a5dd8e11 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index b7a7abcd33..47c1b07759 100644 --- a/src/shell.c +++ b/src/shell.c @@ -361,6 +361,39 @@ static char *Argv0; static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ +/* +** Render output like fprintf(). Except, if the output is going to the +** console and if this is running on a Windows machine, translate the +** output from UTF-8 into MBCS. +*/ +#if defined(_WIN32) || defined(WIN32) +void utf8_printf(FILE *out, const char *zFormat, ...){ + va_list ap; + va_start(ap, zFormat); + if( stdout_is_console && (out==stdout || out==stderr) ){ + extern char *sqlite3_win32_utf8_to_mbcs(const char*); + char *z1 = sqlite3_vmprintf(zFormat, ap); + char *z2 = sqlite3_win32_utf8_to_mbcs(z1); + sqlite3_free(z1); + fputs(z2, out); + sqlite3_free(z2); + }else{ + vfprintf(out, zFormat, ap); + } + va_end(ap); +} +#elif !defined(utf8_printf) +# define utf8_printf fprintf +#endif + +/* +** Render output like fprintf(). This should not be used on anything that +** includes string formatting (e.g. "%s"). +*/ +#if !defined(raw_printf) +# define raw_printf fprintf +#endif + /* ** Write I/O traces to the following stream. */ @@ -382,7 +415,7 @@ static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){ va_start(ap, zFormat); z = sqlite3_vmprintf(zFormat, ap); va_end(ap); - fprintf(iotrace, "%s", z); + utf8_printf(iotrace, "%s", z); sqlite3_free(z); } #endif @@ -539,39 +572,6 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){ return zResult; } -/* -** Render output like fprintf(). Except, if the output is going to the -** console and if this is running on a Windows machine, translate the -** output from UTF-8 into MBCS. -*/ -#if defined(_WIN32) || defined(WIN32) -void utf8_printf(FILE *out, const char *zFormat, ...){ - va_list ap; - va_start(ap, zFormat); - if( stdout_is_console && (out==stdout || out==stderr) ){ - extern char *sqlite3_win32_utf8_to_mbcs(const char*); - char *z1 = sqlite3_vmprintf(zFormat, ap); - char *z2 = sqlite3_win32_utf8_to_mbcs(z1); - sqlite3_free(z1); - fputs(z2, out); - sqlite3_free(z2); - }else{ - vfprintf(out, zFormat, ap); - } - va_end(ap); -} -#elif !defined(utf8_printf) -# define utf8_printf fprintf -#endif - -/* -** Render output like fprintf(). This should not be used on anything that -** includes string formatting (e.g. "%s"). -*/ -#if !defined(raw_printf) -# define raw_printf fprintf -#endif - /* ** Shell output mode information from before ".explain on", ** saved so that it can be restored by ".explain off" From e807bdba86b39f5996683c14842c705e3f6e25d6 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 21 Jan 2016 17:06:33 +0000 Subject: [PATCH 144/570] Add a new hint bit on the flags parameter of sqlite3BtreeDelete(). The new BTREE_IDXDELETE bit indicates that the call is to delete an index entry corresponding to a table row that has already been deleted. FossilOrigin-Name: ac2cbadd8000947c097da5b00c00090fe58fdcff --- manifest | 23 +++++++++++++---------- manifest.uuid | 2 +- src/btree.c | 41 +++++++++++++++++++++++++++++------------ src/btree.h | 7 ++++++- src/delete.c | 5 ++++- src/sqliteInt.h | 5 ++++- src/vdbe.c | 23 ++++++++++++++++------- 7 files changed, 73 insertions(+), 33 deletions(-) diff --git a/manifest b/manifest index d459ef1f26..084be630fe 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\scomments\son\sthe\sFORDELETE\shint.\s\sNo\slogic\schanges. -D 2016-01-21T15:55:37.704 +C Add\sa\snew\shint\sbit\son\sthe\sflags\sparameter\sof\ssqlite3BtreeDelete().\s\sThe\snew\nBTREE_IDXDELETE\sbit\sindicates\sthat\sthe\scall\sis\sto\sdelete\san\sindex\sentry\s\ncorresponding\sto\sa\stable\srow\sthat\shas\salready\sbeen\sdeleted. +D 2016-01-21T17:06:33.267 F Makefile.in 7be88f5b473891e3a8c07245ed60535fcda4f9ee F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc c5ead4aa22ff6f528c755b07ed1e31184ac5b3d2 @@ -288,8 +288,8 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c f224ae877fde69d1a9d430f502edaf8502752dbe -F src/btree.h 526137361963e746949ab966a910c7f455ac6b04 +F src/btree.c 97cf881292e085ee71faf44f7167b6312965b562 +F src/btree.h c5dfbbc59226fa5fcc2b03befa85fe10ef23c1b5 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 31af80bba31ac159967951ef58f3144cc7db9d70 F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261 @@ -297,7 +297,7 @@ F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 997651e3ee6c2818fbf7fcdb7156cef9eb3ece20 F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78 -F src/delete.c 00af9f08a15ddc5cba5962d3d3e5bf2d67b2e7da +F src/delete.c f02e46234c5fc86f6c03ae34dc0ba48e93cd5029 F src/expr.c df0d7c3230d59abd679da22ff5ce4cfd0e3a0e63 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c e18b3dff7d47c7bcac5ac4fc178a89b9fd322b44 @@ -350,7 +350,7 @@ F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/sqlite.h.in 214476a62012e578f42133a9a3b4f97a9aa421a3 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 0403328581127bc8ad2f9cc7af2c3bb23d5316da +F src/sqliteInt.h 46e0bac7a3cdab96e8b5afd1436accc25d2c3d6a F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -410,7 +410,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c e802e8e311a0d6c48cd1b3e89db164f6f0248d70 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c b90d9d38e5e0260c2eafa3cb4c2274d8ea94da27 +F src/vdbe.c e21a506d17a7397cba16c162d8c9c96e9769c68e F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e @@ -1419,7 +1419,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f60f025027ab3acdbc97701f81ff9c11c8463022 -R 58c662ebb54c7087fe70ba0b9b653627 +P a3cec529f0238e4ca1196fec420f2de80d28db78 +R 76198b2176fddd32b1fb9b7a5f18b4c8 +T *branch * btree-fordelete-flag +T *sym-btree-fordelete-flag * +T -sym-trunk * U drh -Z 656e64b9ebb4ed29ac85ca9fad2e65b0 +Z c987d8ca8053309611f1f75e6c6acde5 diff --git a/manifest.uuid b/manifest.uuid index 80d0db3e83..57018fb84b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a3cec529f0238e4ca1196fec420f2de80d28db78 \ No newline at end of file +ac2cbadd8000947c097da5b00c00090fe58fdcff \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 4e6f6478af..89144e7a84 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4049,13 +4049,13 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){ ** on the database already. If a write-cursor is requested, then ** the caller is assumed to have an open write transaction. ** -** If wrFlag==0, then the cursor can only be used for reading. -** If wrFlag==1, then the cursor can be used for reading or for -** writing if other conditions for writing are also met. These -** are the conditions that must be met in order for writing to -** be allowed: +** If the BTREE_WRCSR bit of wrFlag is clear, then the cursor can only +** be used for reading. If the BTREE_WRCSR bit is set, then the cursor +** can be used for reading or for writing if other conditions for writing +** are also met. These are the conditions that must be met in order +** for writing to be allowed: ** -** 1: The cursor must have been opened with wrFlag==1 +** 1: The cursor must have been opened with wrFlag containing BTREE_WRCSR ** ** 2: Other database connections that share the same pager cache ** but which are not in the READ_UNCOMMITTED state may not have @@ -4067,6 +4067,16 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){ ** ** 4: There must be an active transaction. ** +** The BTREE_FORDELETE bit of wrFlag may optionally be set if BTREE_WRCSR +** is set. If FORDELETE is set, that is a hint to the implementation that +** this cursor will only be used to seek to and delete entries of an index +** as part of a larger DELETE statement. The FORDELETE hint is not used by +** this implementation. But in a hypothetical alternative storage engine +** in which index entries are automatically deleted when corresponding table +** rows are deleted, the FORDELETE flag is a hint that all SEEK and DELETE +** operations on this cursor can be no-ops and all READ operations can +** return a null row (2-bytes: 0x01 0x00). +** ** No checking is done to make sure that page iTable really is the ** root page of a b-tree. If it is not, then the cursor acquired ** will not work correctly. @@ -8082,13 +8092,18 @@ end_insert: /* ** Delete the entry that the cursor is pointing to. ** -** If the second parameter is zero, then the cursor is left pointing at an -** arbitrary location after the delete. If it is non-zero, then the cursor -** is left in a state such that the next call to BtreeNext() or BtreePrev() -** moves it to the same row as it would if the call to BtreeDelete() had -** been omitted. +** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then +** the cursor is left pointing at an arbitrary location after the delete. +** But if that bit is set, then the cursor is left in a state such that +** the next call to BtreeNext() or BtreePrev() moves it to the same row +** as it would have been on if the call to BtreeDelete() had been omitted. +** +** The BTREE_IDXDELETE bit of flags indicates that this is a delete of +** an index entry where the corresponding table row has already been deleted. +** The BTREE_IDXDELETE bit is a hint that is not used by this implementation, +** but which might be used by alternative storage engines. */ -int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ +int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; int rc; /* Return code */ @@ -8098,6 +8113,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ int iCellDepth; /* Depth of node containing pCell */ u16 szCell; /* Size of the cell being deleted */ int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */ + u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */ assert( cursorOwnsBtShared(pCur) ); assert( pBt->inTransaction==TRANS_WRITE ); @@ -8107,6 +8123,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ assert( !hasReadConflicts(p, pCur->pgnoRoot) ); assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); assert( pCur->eState==CURSOR_VALID ); + assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_IDXDELETE))==0 ); iCellDepth = pCur->iPage; iCellIdx = pCur->aiIdx[iCellDepth]; diff --git a/src/btree.h b/src/btree.h index 37a9915eda..416faca651 100644 --- a/src/btree.h +++ b/src/btree.h @@ -245,7 +245,12 @@ int sqlite3BtreeMovetoUnpacked( ); int sqlite3BtreeCursorHasMoved(BtCursor*); int sqlite3BtreeCursorRestore(BtCursor*, int*); -int sqlite3BtreeDelete(BtCursor*, int); +int sqlite3BtreeDelete(BtCursor*, u8 flags); + +/* Allowed flags for the 2nd argument to sqlite3BtreeDelete() */ +#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */ +#define BTREE_IDXDELETE 0x04 /* this is index, table row already deleted */ + int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, const void *pData, int nData, int nZero, int bias, int seekResult); diff --git a/src/delete.c b/src/delete.c index ed273bde81..98c49c9930 100644 --- a/src/delete.c +++ b/src/delete.c @@ -718,6 +718,7 @@ void sqlite3GenerateRowDelete( ** a view (in which case the only effect of the DELETE statement is to ** fire the INSTEAD OF triggers). */ if( pTab->pSelect==0 ){ + u8 p5 = 0; sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); if( count ){ @@ -725,8 +726,10 @@ void sqlite3GenerateRowDelete( } if( iIdxNoSeek>=0 ){ sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); + if( eMode!=ONEPASS_OFF ) p5 = OPFLAG_IDXDELETE; } - sqlite3VdbeChangeP5(v, eMode==ONEPASS_MULTI); + if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; + sqlite3VdbeChangeP5(v, p5); } /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b536b8ab28..25aff00151 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2847,7 +2847,8 @@ struct AuthContext { /* ** Bitfield flags for P5 value in various opcodes. */ -#define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */ +#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */ + /* Also used in P2 (not P5) of OP_Delete */ #define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ #define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */ #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ @@ -2860,6 +2861,8 @@ struct AuthContext { #define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */ #define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */ #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ +#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete: keep cursor position */ +#define OPFLAG_IDXDELETE 0x04 /* OP_Delete: index in a DELETE op */ /* * Each trigger present in the database schema is stored as an instance of diff --git a/src/vdbe.c b/src/vdbe.c index c6d5f7b0cc..c290097da2 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4341,14 +4341,20 @@ case OP_InsertInt: { ** ** Delete the record at which the P1 cursor is currently pointing. ** -** If the P5 parameter is non-zero, the cursor will be left pointing at -** either the next or the previous record in the table. If it is left -** pointing at the next record, then the next Next instruction will be a -** no-op. As a result, in this case it is OK to delete a record from within a -** Next loop. If P5 is zero, then the cursor is left in an undefined state. +** If the OPFLAG_SAVEPOSITION bit of the P5 parameter is set, then +** the cursor will be left pointing at either the next or the previous +** record in the table. If it is left pointing at the next record, then +** the next Next instruction will be a no-op. As a result, in this case +** it is ok to delete a record from within a Next loop. If +** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be +** left in an undefined state. ** -** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is -** incremented (otherwise not). +** If the OPFLAG_IDXDELETE bit is set on P5, that indicates that this +** delete is on an index cursor where the corresponding table row has +** already been deleted. +** +** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row +** change count is incremented (otherwise not). ** ** P1 must not be pseudo-table. It has to be a real table with ** multiple rows. @@ -4385,6 +4391,9 @@ case OP_Delete: { } #endif + assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_IDXDELETE))==0 ); + assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); + assert( OPFLAG_IDXDELETE==BTREE_IDXDELETE ); rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); pC->cacheStatus = CACHE_STALE; From 2beb2c390bc7e25996f44b847ef1e080909d6b10 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 21 Jan 2016 17:25:56 +0000 Subject: [PATCH 145/570] Disable the RESTRICT foreign key action if "PRAGMA defer_foreign_keys" is set. FossilOrigin-Name: 82470d1c3a41221c78bcdd402b2219c4c21c43af --- manifest | 19 +++++++++-------- manifest.uuid | 2 +- src/fkey.c | 3 +++ test/fkey6.test | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 5649e90988..66d0b52411 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\sLIKE-operator\sbug\sfix\sfrom\strunk. -D 2016-01-20T16:02:48.763 +C Disable\sthe\sRESTRICT\sforeign\skey\saction\sif\s"PRAGMA\sdefer_foreign_keys"\sis\sset. +D 2016-01-21T17:25:56.966 F Makefile.in a47ec69daac0cdfe3413e50ceea6dc8da3dc4ecb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc b4d0270955b3f102214b2242f2a1b802c22ee21b @@ -320,7 +320,7 @@ F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78 F src/delete.c 86e3940d07fe69a40270c2aaf6ca6c7adf19246c F src/expr.c df0d7c3230d59abd679da22ff5ce4cfd0e3a0e63 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c e18b3dff7d47c7bcac5ac4fc178a89b9fd322b44 +F src/fkey.c 3fd2e17526d8586fdeafa376672c9303b7e35e7f F src/func.c ba6c03f9e440f5693086c08ee88e6e60212b3504 F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 @@ -656,7 +656,7 @@ F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9 F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d F test/fkey5.test 5a373303f201ac03c22ba1ef17a733d3f56e611a -F test/fkey6.test 6697550baa38505c9952eff130ab26a2d156c0cc +F test/fkey6.test d078a1e323a740062bed38df32b8a736fd320dc0 F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13 F test/fkey8.test 8f08203458321e6c19a263829de4cfc936274ab0 F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749 @@ -1440,7 +1440,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 327af5f644a49b2f41d5456958f9d61a2b704e1c e8adeb64d4e463772feb58dbd6f00715b92e735c -R ed9d6c66302fd811ae6a8e53c4d95620 -U drh -Z 8662dc0834e686268b7ae44f172fcd73 +P 36cb3d6e274a06a78693ca506feaad0b14bde11d +R f0ee48a1a8d6b1b8328a4821e1589857 +T *branch * disable-restrict +T *sym-disable-restrict * +T -sym-sessions * +U dan +Z 284a240298ca9699332d11236aa182a9 diff --git a/manifest.uuid b/manifest.uuid index df02854c57..f82434f679 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -36cb3d6e274a06a78693ca506feaad0b14bde11d \ No newline at end of file +82470d1c3a41221c78bcdd402b2219c4c21c43af \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index 2abd06c693..8ad6cfbe78 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -1163,6 +1163,9 @@ static Trigger *fkActionTrigger( action = pFKey->aAction[iAction]; pTrigger = pFKey->apTrigger[iAction]; + if( (db->flags & SQLITE_DeferFKs) && action==OE_Restrict ){ + return 0; + } if( action!=OE_None && !pTrigger ){ u8 enableLookaside; /* Copy of db->lookaside.bEnabled */ diff --git a/test/fkey6.test b/test/fkey6.test index 7c24704e03..b658f20fea 100644 --- a/test/fkey6.test +++ b/test/fkey6.test @@ -23,6 +23,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix fkey6 ifcapable {!foreignkey} { finish_test @@ -171,5 +172,58 @@ do_execsql_test fkey6-2.6 { PRAGMA defer_foreign_keys; } {0} +#-------------------------------------------------------------------------- +# Test that defer_foreign_keys disables RESTRICT. +# +do_execsql_test 3.1 { + CREATE TABLE p2(a PRIMARY KEY, b); + CREATE TABLE c2(x, y REFERENCES p2 ON DELETE RESTRICT ON UPDATE RESTRICT); + INSERT INTO p2 VALUES(1, 'one'); + INSERT INTO p2 VALUES(2, 'two'); + INSERT INTO c2 VALUES('i', 1); +} + +do_catchsql_test 3.2.1 { + BEGIN; + UPDATE p2 SET a=a-1; +} {1 {FOREIGN KEY constraint failed}} +do_execsql_test 3.2.2 { COMMIT } + +do_execsql_test 3.2.3 { + BEGIN; + PRAGMA defer_foreign_keys = 1; + UPDATE p2 SET a=a-1; + COMMIT; +} + +do_execsql_test 3.2.4 { + BEGIN; + PRAGMA defer_foreign_keys = 1; + UPDATE p2 SET a=a-1; +} +do_catchsql_test 3.2.5 { + COMMIT; +} {1 {FOREIGN KEY constraint failed}} +do_execsql_test 3.2.6 { ROLLBACK } + +do_execsql_test 3.3.1 { + CREATE TRIGGER p2t AFTER DELETE ON p2 BEGIN + INSERT INTO p2 VALUES(old.a, 'deleted!'); + END; +} +do_catchsql_test 3.3.2 { + BEGIN; + DELETE FROM p2 WHERE a=1; +} {1 {FOREIGN KEY constraint failed}} +do_execsql_test 3.3.3 { COMMIT } + +do_execsql_test 3.3.4 { + BEGIN; + PRAGMA defer_foreign_keys = 1; + DELETE FROM p2 WHERE a=1; + COMMIT; + SELECT * FROM p2; +} {0 one 1 deleted!} + finish_test From 795502d26c770c06b1d8d586fd316a6e374ed1d6 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 22 Jan 2016 19:48:34 +0000 Subject: [PATCH 146/570] Experimental performance enhancements for fts5. FossilOrigin-Name: b5a57b812fd6a734cf2a342bf0b730ae18912d73 --- ext/fts5/fts5Int.h | 10 +- ext/fts5/fts5_expr.c | 42 ++-- ext/fts5/fts5_index.c | 389 +++++++++++++++++++++++++++----------- ext/fts5/fts5_vocab.c | 56 +++--- ext/fts5/test/fts5ac.test | 1 - manifest | 25 +-- manifest.uuid | 2 +- 7 files changed, 355 insertions(+), 170 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index b2f0d6c34e..7c50da9656 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -315,6 +315,12 @@ void sqlite3Fts5TermsetFree(Fts5Termset*); typedef struct Fts5Index Fts5Index; typedef struct Fts5IndexIter Fts5IndexIter; +struct Fts5IndexIter { + i64 iRowid; + const u8 *pData; + int nData; +}; + /* ** Values used as part of the flags argument passed to IndexQuery(). */ @@ -396,6 +402,8 @@ void sqlite3Fts5IterClose(Fts5IndexIter*); const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*); int sqlite3Fts5IterNextScan(Fts5IndexIter*); +int sqlite3Fts5IterCollist(Fts5IndexIter*, const u8 **, int*); + /* ** Insert or remove data to or from the index. Each time a document is @@ -469,8 +477,6 @@ int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge); int sqlite3Fts5IndexLoadConfig(Fts5Index *p); -int sqlite3Fts5IterCollist(Fts5IndexIter*, const u8 **, int*); - /* ** End of interface to code in fts5_index.c. **************************************************************************/ diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index c51ed7939c..290baf4e2c 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -323,11 +323,15 @@ static int fts5ExprSynonymList( const u8 *a; int n; - if( bCollist ){ + if( 0 && bCollist ){ rc = sqlite3Fts5IterCollist(pIter, &a, &n); }else{ i64 dummy; +#if 0 rc = sqlite3Fts5IterPoslist(pIter, pColset, &a, &n, &dummy); +#endif + a = pIter->pData; + n = pIter->nData; } if( rc!=SQLITE_OK ) goto synonym_poslist_out; @@ -436,7 +440,12 @@ static int fts5ExprPhraseIsMatch( pTerm, 0, pColset, pNode->iRowid, &bFlag, (u8**)&a, &n ); }else{ + Fts5IndexIter *pIter = pTerm->pIter; +#if 0 rc = sqlite3Fts5IterPoslist(pTerm->pIter, pColset, &a, &n, &dummy); +#endif + a = pIter->pData; + n = pIter->nData; } if( rc!=SQLITE_OK ) goto ismatch_out; sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]); @@ -775,6 +784,7 @@ static int fts5ExprNearTest( for(pTerm=&pPhrase->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){ Fts5IndexIter *pIter = pTerm->pIter; if( sqlite3Fts5IterEof(pIter)==0 ){ +#if 0 int n; i64 iRowid; rc = sqlite3Fts5IterPoslist(pIter, pNear->pColset, 0, &n, &iRowid); @@ -784,6 +794,10 @@ static int fts5ExprNearTest( }else if( iRowid==pNode->iRowid && n>0 ){ pPhrase->poslist.n = 1; } +#endif + if( pIter->iRowid==pNode->iRowid && pIter->nData>0 ){ + pPhrase->poslist.n = 1; + } } } return pPhrase->poslist.n; @@ -800,9 +814,13 @@ static int fts5ExprNearTest( rc = fts5ExprPhraseIsMatch(pNode, pNear->pColset, pPhrase, &bMatch); if( bMatch==0 ) break; }else{ + Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; + fts5BufferSet(&rc, &pPhrase->poslist, pIter->nData, pIter->pData); +#if 0 rc = sqlite3Fts5IterPoslistBuffer( pPhrase->aTerm[0].pIter, &pPhrase->poslist ); +#endif } } @@ -823,21 +841,20 @@ static int fts5ExprTokenTest( ** fts5_index.c iterator object. This is much faster than synthesizing ** a new poslist the way we have to for more complicated phrase or NEAR ** expressions. */ - Fts5ExprNearset *pNear = pNode->pNear; - Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; + Fts5ExprPhrase *pPhrase = pNode->pNear->apPhrase[0]; Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; - Fts5Colset *pColset = pNear->pColset; - int rc; assert( pNode->eType==FTS5_TERM ); - assert( pNear->nPhrase==1 && pPhrase->nTerm==1 ); + assert( pNode->pNear->nPhrase==1 && pPhrase->nTerm==1 ); assert( pPhrase->aTerm[0].pSynonym==0 ); - rc = sqlite3Fts5IterPoslist(pIter, pColset, - (const u8**)&pPhrase->poslist.p, (int*)&pPhrase->poslist.n, &pNode->iRowid - ); + pPhrase->poslist.n = pIter->nData; + if( pExpr->pConfig->eDetail==FTS5_DETAIL_FULL ){ + pPhrase->poslist.p = (u8*)pIter->pData; + } + pNode->iRowid = pIter->iRowid; pNode->bNomatch = (pPhrase->poslist.n==0); - return rc; + return SQLITE_OK; } /* @@ -2484,6 +2501,8 @@ int sqlite3Fts5ExprPhraseCollist( int rc = SQLITE_OK; assert( iPhrase>=0 && iPhrasenPhrase ); + assert( pExpr->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); + if( pNode->bEof==0 && pNode->iRowid==pExpr->pRoot->iRowid && pPhrase->poslist.n>0 @@ -2503,7 +2522,8 @@ int sqlite3Fts5ExprPhraseCollist( *ppCollist = a; } }else{ - sqlite3Fts5IterCollist(pPhrase->aTerm[0].pIter, ppCollist, pnCollist); + *ppCollist = pPhrase->aTerm[0].pIter->pData; + *pnCollist = pPhrase->aTerm[0].pIter->nData; } }else{ *ppCollist = 0; diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index fc11a23413..2ea57b04f9 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -261,6 +261,7 @@ typedef struct Fts5Data Fts5Data; typedef struct Fts5DlidxIter Fts5DlidxIter; typedef struct Fts5DlidxLvl Fts5DlidxLvl; typedef struct Fts5DlidxWriter Fts5DlidxWriter; +typedef struct Fts5Iter Fts5Iter; typedef struct Fts5PageWriter Fts5PageWriter; typedef struct Fts5SegIter Fts5SegIter; typedef struct Fts5DoclistIter Fts5DoclistIter; @@ -503,10 +504,16 @@ struct Fts5SegIter { ** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered. ** There is no way to tell if this is populated or not. */ -struct Fts5IndexIter { +struct Fts5Iter { + Fts5IndexIter base; /* Base class containing output vars */ + Fts5Index *pIndex; /* Index that owns this iterator */ Fts5Structure *pStruct; /* Database structure for this iterator */ Fts5Buffer poslist; /* Buffer containing current poslist */ + Fts5Colset *pColset; /* Restrict matches to these columns */ + + /* Invoked to set output variables. */ + void (*xSetOutputs)(Fts5Iter*, Fts5SegIter*); int nSeg; /* Size of aSeg[] array */ int bRev; /* True to iterate in reverse order */ @@ -1752,7 +1759,7 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){ ** points to a delete marker. A delete marker is an entry with a 0 byte ** position-list. */ -static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5IndexIter *pIter){ +static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5Iter *pIter){ Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; return (p->rc==SQLITE_OK && pSeg->pLeaf && pSeg->nPos==0); } @@ -2406,7 +2413,7 @@ static void fts5SegIterClear(Fts5SegIter *pIter){ ** two iterators. */ static void fts5AssertComparisonResult( - Fts5IndexIter *pIter, + Fts5Iter *pIter, Fts5SegIter *p1, Fts5SegIter *p2, Fts5CResult *pRes @@ -2447,7 +2454,7 @@ static void fts5AssertComparisonResult( ** statement used to verify that the contents of the pIter->aFirst[] array ** are correct. */ -static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5IndexIter *pIter){ +static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5Iter *pIter){ if( p->rc==SQLITE_OK ){ Fts5SegIter *pFirst = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; int i; @@ -2492,7 +2499,7 @@ static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5IndexIter *pIter){ ** to a key that is a duplicate of another, higher priority, ** segment-iterator in the pSeg->aSeg[] array. */ -static int fts5MultiIterDoCompare(Fts5IndexIter *pIter, int iOut){ +static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){ int i1; /* Index of left-hand Fts5SegIter */ int i2; /* Index of right-hand Fts5SegIter */ int iRes; @@ -2638,7 +2645,7 @@ static void fts5SegIterNextFrom( /* ** Free the iterator object passed as the second argument. */ -static void fts5MultiIterFree(Fts5Index *p, Fts5IndexIter *pIter){ +static void fts5MultiIterFree(Fts5Index *p, Fts5Iter *pIter){ if( pIter ){ int i; for(i=0; inSeg; i++){ @@ -2652,7 +2659,7 @@ static void fts5MultiIterFree(Fts5Index *p, Fts5IndexIter *pIter){ static void fts5MultiIterAdvanced( Fts5Index *p, /* FTS5 backend to iterate within */ - Fts5IndexIter *pIter, /* Iterator to update aFirst[] array for */ + Fts5Iter *pIter, /* Iterator to update aFirst[] array for */ int iChanged, /* Index of sub-iterator just advanced */ int iMinset /* Minimum entry in aFirst[] to set */ ){ @@ -2680,8 +2687,9 @@ static void fts5MultiIterAdvanced( */ static int fts5MultiIterAdvanceRowid( Fts5Index *p, /* FTS5 backend to iterate within */ - Fts5IndexIter *pIter, /* Iterator to update aFirst[] array for */ - int iChanged /* Index of sub-iterator just advanced */ + Fts5Iter *pIter, /* Iterator to update aFirst[] array for */ + int iChanged, /* Index of sub-iterator just advanced */ + Fts5SegIter **ppFirst ){ Fts5SegIter *pNew = &pIter->aSeg[iChanged]; @@ -2714,13 +2722,14 @@ static int fts5MultiIterAdvanceRowid( } } + *ppFirst = pNew; return 0; } /* ** Set the pIter->bEof variable based on the state of the sub-iterators. */ -static void fts5MultiIterSetEof(Fts5IndexIter *pIter){ +static void fts5MultiIterSetEof(Fts5Iter *pIter){ Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; pIter->bEof = pSeg->pLeaf==0; pIter->iSwitchRowid = pSeg->iRowid; @@ -2735,39 +2744,44 @@ static void fts5MultiIterSetEof(Fts5IndexIter *pIter){ */ static void fts5MultiIterNext( Fts5Index *p, - Fts5IndexIter *pIter, + Fts5Iter *pIter, int bFrom, /* True if argument iFrom is valid */ i64 iFrom /* Advance at least as far as this */ ){ - if( p->rc==SQLITE_OK ){ - int bUseFrom = bFrom; - do { - int iFirst = pIter->aFirst[1].iFirst; - int bNewTerm = 0; - Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; - assert( p->rc==SQLITE_OK ); - if( bUseFrom && pSeg->pDlidx ){ - fts5SegIterNextFrom(p, pSeg, iFrom); - }else{ - pSeg->xNext(p, pSeg, &bNewTerm); - } + int bUseFrom = bFrom; + while( p->rc==SQLITE_OK ){ + int iFirst = pIter->aFirst[1].iFirst; + int bNewTerm = 0; + Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; + assert( p->rc==SQLITE_OK ); + if( bUseFrom && pSeg->pDlidx ){ + fts5SegIterNextFrom(p, pSeg, iFrom); + }else{ + pSeg->xNext(p, pSeg, &bNewTerm); + } - if( pSeg->pLeaf==0 || bNewTerm - || fts5MultiIterAdvanceRowid(p, pIter, iFirst) - ){ - fts5MultiIterAdvanced(p, pIter, iFirst, 1); - fts5MultiIterSetEof(pIter); - } - fts5AssertMultiIterSetup(p, pIter); + if( pSeg->pLeaf==0 || bNewTerm + || fts5MultiIterAdvanceRowid(p, pIter, iFirst, &pSeg) + ){ + fts5MultiIterAdvanced(p, pIter, iFirst, 1); + fts5MultiIterSetEof(pIter); + pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; + if( pSeg->pLeaf==0 ) return; + } - bUseFrom = 0; - }while( pIter->bSkipEmpty && fts5MultiIterIsEmpty(p, pIter) ); + fts5AssertMultiIterSetup(p, pIter); + assert( pSeg==&pIter->aSeg[pIter->aFirst[1].iFirst] && pSeg->pLeaf ); + if( pIter->bSkipEmpty==0 || pSeg->nPos ){ + pIter->xSetOutputs(pIter, pSeg); + return; + } + bUseFrom = 0; } } static void fts5MultiIterNext2( Fts5Index *p, - Fts5IndexIter *pIter, + Fts5Iter *pIter, int *pbNewTerm /* OUT: True if *might* be new term */ ){ assert( pIter->bSkipEmpty ); @@ -2780,7 +2794,7 @@ static void fts5MultiIterNext2( assert( p->rc==SQLITE_OK ); pSeg->xNext(p, pSeg, &bNewTerm); if( pSeg->pLeaf==0 || bNewTerm - || fts5MultiIterAdvanceRowid(p, pIter, iFirst) + || fts5MultiIterAdvanceRowid(p, pIter, iFirst, &pSeg) ){ fts5MultiIterAdvanced(p, pIter, iFirst, 1); fts5MultiIterSetEof(pIter); @@ -2794,17 +2808,19 @@ static void fts5MultiIterNext2( } } +static void fts5IterSetOutputs_Noop(Fts5Iter *pIter, Fts5SegIter *pSeg){ +} -static Fts5IndexIter *fts5MultiIterAlloc( +static Fts5Iter *fts5MultiIterAlloc( Fts5Index *p, /* FTS5 backend to iterate within */ int nSeg ){ - Fts5IndexIter *pNew; + Fts5Iter *pNew; int nSlot; /* Power of two >= nSeg */ for(nSlot=2; nSlotaSeg[] */ sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */ ); @@ -2812,12 +2828,13 @@ static Fts5IndexIter *fts5MultiIterAlloc( pNew->nSeg = nSlot; pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot]; pNew->pIndex = p; + pNew->xSetOutputs = fts5IterSetOutputs_Noop; } return pNew; } /* -** Allocate a new Fts5IndexIter object. +** Allocate a new Fts5Iter object. ** ** The new object will be used to iterate through data in structure pStruct. ** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel @@ -2835,14 +2852,14 @@ static void fts5MultiIterNew( const u8 *pTerm, int nTerm, /* Term to seek to (or NULL/0) */ int iLevel, /* Level to iterate (-1 for all) */ int nSegment, /* Number of segments to merge (iLevel>=0) */ - Fts5IndexIter **ppOut /* New object */ + Fts5Iter **ppOut /* New object */ ){ int nSeg = 0; /* Number of segment-iters in use */ int iIter = 0; /* */ int iSeg; /* Used to iterate through segments */ Fts5Buffer buf = {0,0,0}; /* Buffer used by fts5SegIterSeekInit() */ Fts5StructureLevel *pLvl; - Fts5IndexIter *pNew; + Fts5Iter *pNew; assert( (pTerm==0 && nTerm==0) || iLevel<0 ); @@ -2917,16 +2934,16 @@ static void fts5MultiIterNew( } /* -** Create an Fts5IndexIter that iterates through the doclist provided +** Create an Fts5Iter that iterates through the doclist provided ** as the second argument. */ static void fts5MultiIterNew2( Fts5Index *p, /* FTS5 backend to iterate within */ Fts5Data *pData, /* Doclist to iterate through */ int bDesc, /* True for descending rowid order */ - Fts5IndexIter **ppOut /* New object */ + Fts5Iter **ppOut /* New object */ ){ - Fts5IndexIter *pNew; + Fts5Iter *pNew; pNew = fts5MultiIterAlloc(p, 2); if( pNew ){ Fts5SegIter *pIter = &pNew->aSeg[1]; @@ -2961,7 +2978,7 @@ static void fts5MultiIterNew2( ** Return true if the iterator is at EOF or if an error has occurred. ** False otherwise. */ -static int fts5MultiIterEof(Fts5Index *p, Fts5IndexIter *pIter){ +static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){ assert( p->rc || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->bEof ); @@ -2973,7 +2990,7 @@ static int fts5MultiIterEof(Fts5Index *p, Fts5IndexIter *pIter){ ** to. If the iterator points to EOF when this function is called the ** results are undefined. */ -static i64 fts5MultiIterRowid(Fts5IndexIter *pIter){ +static i64 fts5MultiIterRowid(Fts5Iter *pIter){ assert( pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf ); return pIter->aSeg[ pIter->aFirst[1].iFirst ].iRowid; } @@ -2983,7 +3000,7 @@ static i64 fts5MultiIterRowid(Fts5IndexIter *pIter){ */ static void fts5MultiIterNextFrom( Fts5Index *p, - Fts5IndexIter *pIter, + Fts5Iter *pIter, i64 iMatch ){ while( 1 ){ @@ -3000,7 +3017,7 @@ static void fts5MultiIterNextFrom( ** Return a pointer to a buffer containing the term associated with the ** entry that the iterator currently points to. */ -static const u8 *fts5MultiIterTerm(Fts5IndexIter *pIter, int *pn){ +static const u8 *fts5MultiIterTerm(Fts5Iter *pIter, int *pn){ Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; *pn = p->term.n; return p->term.p; @@ -3582,7 +3599,7 @@ static void fts5WriteInit( ** incremental merge operation. This function is called if the incremental ** merge step has finished but the input has not been completely exhausted. */ -static void fts5TrimSegments(Fts5Index *p, Fts5IndexIter *pIter){ +static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){ int i; Fts5Buffer buf; memset(&buf, 0, sizeof(Fts5Buffer)); @@ -3660,7 +3677,7 @@ static void fts5IndexMergeLevel( Fts5Structure *pStruct = *ppStruct; Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl]; Fts5StructureLevel *pLvlOut; - Fts5IndexIter *pIter = 0; /* Iterator to read input data */ + Fts5Iter *pIter = 0; /* Iterator to read input data */ int nRem = pnRem ? *pnRem : 0; /* Output leaf pages left to write */ int nInput; /* Number of input segments */ Fts5SegWriter writer; /* Writer object */ @@ -4342,7 +4359,7 @@ static int fts5IndexExtractCol( static int fts5AppendRowid( Fts5Index *p, i64 iDelta, - Fts5IndexIter *pMulti, + Fts5Iter *pMulti, Fts5Colset *pColset, Fts5Buffer *pBuf ){ @@ -4367,7 +4384,7 @@ static int fts5AppendRowid( static int fts5AppendPoslist( Fts5Index *p, i64 iDelta, - Fts5IndexIter *pMulti, + Fts5Iter *pMulti, Fts5Colset *pColset, Fts5Buffer *pBuf ){ @@ -4645,14 +4662,14 @@ static void fts5SetupPrefixIter( const u8 *pToken, /* Buffer containing prefix to match */ int nToken, /* Size of buffer pToken in bytes */ Fts5Colset *pColset, /* Restrict matches to these columns */ - Fts5IndexIter **ppIter /* OUT: New iterator */ + Fts5Iter **ppIter /* OUT: New iterator */ ){ Fts5Structure *pStruct; Fts5Buffer *aBuf; const int nBuf = 32; void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*); - int (*xAppend)(Fts5Index*, i64, Fts5IndexIter*, Fts5Colset*, Fts5Buffer*); + int (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Colset*, Fts5Buffer*); if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){ xMerge = fts5MergeRowidLists; xAppend = fts5AppendRowid; @@ -4668,7 +4685,7 @@ static void fts5SetupPrefixIter( const int flags = FTS5INDEX_QUERY_SCAN; int i; i64 iLastRowid = 0; - Fts5IndexIter *p1 = 0; /* Iterator used to gather data from index */ + Fts5Iter *p1 = 0; /* Iterator used to gather data from index */ Fts5Data *pData; Fts5Buffer doclist; int bNewTerm = 1; @@ -4932,6 +4949,154 @@ int sqlite3Fts5IndexWrite( return rc; } + +static int fts5IndexExtractColset ( + Fts5Colset *pColset, /* Colset to filter on */ + const u8 *pPos, int nPos, /* Position list */ + Fts5Buffer *pBuf /* Output buffer */ +){ + int rc = SQLITE_OK; + int i; + + fts5BufferZero(pBuf); + for(i=0; inCol; i++){ + const u8 *pSub = pPos; + int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]); + if( nSub ){ + fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); + } + } + return rc; +} + +/* +** xSetOutputs callback used by detail=none tables. +*/ +static void fts5IterSetOutputs_None(Fts5Iter *pIter, Fts5SegIter *pSeg){ + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_NONE ); + pIter->base.iRowid = pSeg->iRowid; + pIter->base.nData = pSeg->nPos; +} + +/* +** xSetOutputs callback used by detail=full and detail=col tables when no +** column filters are specified. +*/ +static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){ + pIter->base.iRowid = pSeg->iRowid; + pIter->base.nData = pSeg->nPos; + + assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE ); + assert( pIter->pColset==0 || pIter->bFiltered ); + + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ + /* All data is stored on the current page. Populate the output + ** variables to point into the body of the page object. */ + pIter->base.pData = &pSeg->pLeaf->p[pSeg->iLeafOffset]; + }else{ + /* The data is distributed over two or more pages. Copy it into the + ** Fts5Iter.poslist buffer and then set the output pointer to point + ** to this buffer. */ + fts5BufferZero(&pIter->poslist); + fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist); + pIter->base.pData = pIter->poslist.p; + } +} + +/* +** xSetOutputs callback used by detail=col when there is a column filter. +*/ +static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){ + Fts5Colset *pColset = pIter->pColset; + pIter->base.iRowid = pSeg->iRowid; + + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); + assert( pColset ); + + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf && 0 ){ + /* All data is stored on the current page. Populate the output + ** variables to point into the body of the page object. */ + Fts5PoslistWriter writer = {0}; + const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset]; + int n = pSeg->nPos; + int iCol = 0; + i64 iPos = 0; + int iOff = 0; + + fts5BufferZero(&pIter->poslist); + while( 0==sqlite3Fts5PoslistNext64(a, n, &iOff, &iPos) ){ + if( iPos==pColset->aiCol[iCol] ){ + sqlite3Fts5PoslistWriterAppend(&pIter->poslist, &writer, iPos); + if( ++iCol>=pColset->nCol ) break; + } + } + + }else{ + /* The data is distributed over two or more pages. Copy it into the + ** Fts5Iter.poslist buffer and then set the output pointer to point + ** to this buffer. */ + fts5BufferZero(&pIter->poslist); + fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); + } + + pIter->base.pData = pIter->poslist.p; + pIter->base.nData = pIter->poslist.n; +} + +/* +** xSetOutputs callback used by detail=full when there is a column filter. +*/ +static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){ + Fts5Colset *pColset = pIter->pColset; + pIter->base.iRowid = pSeg->iRowid; + + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL ); + assert( pColset ); + + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ + /* All data is stored on the current page. Populate the output + ** variables to point into the body of the page object. */ + const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset]; + if( pColset->nCol==1 ){ + pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]); + pIter->base.pData = a; + }else{ + fts5BufferZero(&pIter->poslist); + fts5IndexExtractColset(pColset, a, pSeg->nPos, &pIter->poslist); + pIter->base.pData = pIter->poslist.p; + pIter->base.nData = pIter->poslist.n; + } + }else{ + /* The data is distributed over two or more pages. Copy it into the + ** Fts5Iter.poslist buffer and then set the output pointer to point + ** to this buffer. */ + fts5BufferZero(&pIter->poslist); + fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); + pIter->base.pData = pIter->poslist.p; + pIter->base.nData = pIter->poslist.n; + } +} + +static void fts5IterSetOutputCb(Fts5Iter *pIter){ + int eDetail = pIter->pIndex->pConfig->eDetail; + if( eDetail==FTS5_DETAIL_NONE ){ + pIter->xSetOutputs = fts5IterSetOutputs_None; + } + + else if( pIter->pColset==0 || pIter->bFiltered ){ + pIter->xSetOutputs = fts5IterSetOutputs_Nocolset; + } + + else if( eDetail==FTS5_DETAIL_FULL ){ + pIter->xSetOutputs = fts5IterSetOutputs_Full; + } + + else{ + assert( eDetail==FTS5_DETAIL_COLUMNS ); + pIter->xSetOutputs = fts5IterSetOutputs_Col; + } +} + /* ** Open a new iterator to iterate though all rowid that match the ** specified token or token prefix. @@ -4944,22 +5109,27 @@ int sqlite3Fts5IndexQuery( Fts5IndexIter **ppIter /* OUT: New iterator object */ ){ Fts5Config *pConfig = p->pConfig; - Fts5IndexIter *pRet = 0; - int iIdx = 0; + Fts5Iter *pRet = 0; Fts5Buffer buf = {0, 0, 0}; /* If the QUERY_SCAN flag is set, all other flags must be clear. */ assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN ); if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){ + int iIdx = 0; /* Index to search */ memcpy(&buf.p[1], pToken, nToken); -#ifdef SQLITE_DEBUG - /* If the QUERY_TEST_NOIDX flag was specified, then this must be a + /* Figure out which index to search and set iIdx accordingly. If this + ** is a prefix query for which there is no prefix index, set iIdx to + ** greater than pConfig->nPrefix to indicate that the query will be + ** satisfied by scanning multiple terms in the main index. + ** + ** If the QUERY_TEST_NOIDX flag was specified, then this must be a ** prefix-query. Instead of using a prefix-index (if one exists), ** evaluate the prefix query using the main FTS index. This is used ** for internal sanity checking by the integrity-check in debug ** mode only. */ +#ifdef SQLITE_DEBUG if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){ assert( flags & FTS5INDEX_QUERY_PREFIX ); iIdx = 1+pConfig->nPrefix; @@ -4973,6 +5143,7 @@ int sqlite3Fts5IndexQuery( } if( iIdx<=pConfig->nPrefix ){ + /* Straight index lookup */ Fts5Structure *pStruct = fts5StructureRead(p); buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx); if( pStruct ){ @@ -4980,17 +5151,25 @@ int sqlite3Fts5IndexQuery( fts5StructureRelease(pStruct); } }else{ + /* Scan multiple terms in the main index */ int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0; buf.p[0] = FTS5_MAIN_PREFIX; fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet); } + if( p->rc==SQLITE_OK ){ + Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst]; + pRet->pColset = pColset; + fts5IterSetOutputCb(pRet); + if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); + } if( p->rc ){ - sqlite3Fts5IterClose(pRet); + sqlite3Fts5IterClose(&pRet->base); pRet = 0; fts5CloseReader(p); } - *ppIter = pRet; + + *ppIter = &pRet->base; sqlite3Fts5BufferFree(&buf); } return fts5IndexReturn(p); @@ -5000,14 +5179,15 @@ int sqlite3Fts5IndexQuery( ** Return true if the iterator passed as the only argument is at EOF. */ int sqlite3Fts5IterEof(Fts5IndexIter *pIter){ - assert( pIter->pIndex->rc==SQLITE_OK ); - return pIter->bEof; + assert( ((Fts5Iter*)pIter)->pIndex->rc==SQLITE_OK ); + return ((Fts5Iter*)pIter)->bEof; } /* ** Move to the next matching rowid. */ -int sqlite3Fts5IterNext(Fts5IndexIter *pIter){ +int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; assert( pIter->pIndex->rc==SQLITE_OK ); fts5MultiIterNext(pIter->pIndex, pIter, 0, 0); return fts5IndexReturn(pIter->pIndex); @@ -5016,7 +5196,8 @@ int sqlite3Fts5IterNext(Fts5IndexIter *pIter){ /* ** Move to the next matching term/rowid. Used by the fts5vocab module. */ -int sqlite3Fts5IterNextScan(Fts5IndexIter *pIter){ +int sqlite3Fts5IterNextScan(Fts5IndexIter *pIndexIter){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; Fts5Index *p = pIter->pIndex; assert( pIter->pIndex->rc==SQLITE_OK ); @@ -5039,7 +5220,8 @@ int sqlite3Fts5IterNextScan(Fts5IndexIter *pIter){ ** definition of "at or after" depends on whether this iterator iterates ** in ascending or descending rowid order. */ -int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIter, i64 iMatch){ +int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch); return fts5IndexReturn(pIter->pIndex); } @@ -5047,41 +5229,21 @@ int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIter, i64 iMatch){ /* ** Return the current rowid. */ -i64 sqlite3Fts5IterRowid(Fts5IndexIter *pIter){ - return fts5MultiIterRowid(pIter); +i64 sqlite3Fts5IterRowid(Fts5IndexIter *pIndexIter){ + return fts5MultiIterRowid((Fts5Iter*)pIndexIter); } /* ** Return the current term. */ -const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIter, int *pn){ +const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){ int n; - const char *z = (const char*)fts5MultiIterTerm(pIter, &n); + const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n); *pn = n-1; return &z[1]; } -static int fts5IndexExtractColset ( - Fts5Colset *pColset, /* Colset to filter on */ - const u8 *pPos, int nPos, /* Position list */ - Fts5Buffer *pBuf /* Output buffer */ -){ - int rc = SQLITE_OK; - int i; - - fts5BufferZero(pBuf); - for(i=0; inCol; i++){ - const u8 *pSub = pPos; - int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]); - if( nSub ){ - fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); - } - } - return rc; -} - - /* ** Return a pointer to a buffer containing a copy of the position list for ** the current entry. Output variable *pn is set to the size of the buffer @@ -5091,12 +5253,13 @@ static int fts5IndexExtractColset ( ** field that starts the position list on disk. */ int sqlite3Fts5IterPoslist( - Fts5IndexIter *pIter, + Fts5IndexIter *pIndexIter, Fts5Colset *pColset, /* Column filter (or NULL) */ const u8 **pp, /* OUT: Pointer to position-list data */ int *pn, /* OUT: Size of position-list in bytes */ i64 *piRowid /* OUT: Current rowid */ ){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; int eDetail = pIter->pIndex->pConfig->eDetail; @@ -5133,10 +5296,11 @@ int sqlite3Fts5IterPoslist( } int sqlite3Fts5IterCollist( - Fts5IndexIter *pIter, + Fts5IndexIter *pIndexIter, const u8 **pp, /* OUT: Pointer to position-list data */ int *pn /* OUT: Size of position-list in bytes */ ){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); *pp = pIter->poslist.p; *pn = pIter->poslist.n; @@ -5148,7 +5312,8 @@ int sqlite3Fts5IterCollist( ** copies the position list into the buffer supplied as the second ** argument. */ -int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf){ +int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIndexIter, Fts5Buffer *pBuf){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; Fts5Index *p = pIter->pIndex; Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; assert( p->rc==SQLITE_OK ); @@ -5160,8 +5325,9 @@ int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf){ /* ** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery(). */ -void sqlite3Fts5IterClose(Fts5IndexIter *pIter){ - if( pIter ){ +void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){ + if( pIndexIter ){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; Fts5Index *pIndex = pIter->pIndex; fts5MultiIterFree(pIter->pIndex, pIter); fts5CloseReader(pIndex); @@ -5328,35 +5494,30 @@ static int fts5QueryCksum( ){ int eDetail = p->pConfig->eDetail; u64 cksum = *pCksum; - Fts5IndexIter *pIdxIter = 0; - Fts5Buffer buf = {0, 0, 0}; - int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIdxIter); + Fts5IndexIter *pIter = 0; + int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter); - while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIdxIter) ){ - i64 rowid = sqlite3Fts5IterRowid(pIdxIter); + while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIter) ){ + i64 rowid = sqlite3Fts5IterRowid(pIter); if( eDetail==FTS5_DETAIL_NONE ){ cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n); }else{ - rc = sqlite3Fts5IterPoslistBuffer(pIdxIter, &buf); - if( rc==SQLITE_OK ){ - Fts5PoslistReader sReader; - for(sqlite3Fts5PoslistReaderInit(buf.p, buf.n, &sReader); - sReader.bEof==0; - sqlite3Fts5PoslistReaderNext(&sReader) - ){ - int iCol = FTS5_POS2COLUMN(sReader.iPos); - int iOff = FTS5_POS2OFFSET(sReader.iPos); - cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n); - } + Fts5PoslistReader sReader; + for(sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &sReader); + sReader.bEof==0; + sqlite3Fts5PoslistReaderNext(&sReader) + ){ + int iCol = FTS5_POS2COLUMN(sReader.iPos); + int iOff = FTS5_POS2OFFSET(sReader.iPos); + cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n); } } if( rc==SQLITE_OK ){ - rc = sqlite3Fts5IterNext(pIdxIter); + rc = sqlite3Fts5IterNext(pIter); } } - sqlite3Fts5IterClose(pIdxIter); - fts5BufferFree(&buf); + sqlite3Fts5IterClose(pIter); *pCksum = cksum; return rc; @@ -5661,7 +5822,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){ int eDetail = p->pConfig->eDetail; u64 cksum2 = 0; /* Checksum based on contents of indexes */ Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */ - Fts5IndexIter *pIter; /* Used to iterate through entire index */ + Fts5Iter *pIter; /* Used to iterate through entire index */ Fts5Structure *pStruct; /* Index structure */ #ifdef SQLITE_DEBUG diff --git a/ext/fts5/fts5_vocab.c b/ext/fts5/fts5_vocab.c index ddc5576c5d..17aa5816c4 100644 --- a/ext/fts5/fts5_vocab.c +++ b/ext/fts5/fts5_vocab.c @@ -412,28 +412,29 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ i64 iPos = 0; /* 64-bit position read from poslist */ int iOff = 0; /* Current offset within position list */ + pPos = pCsr->pIter->pData; + nPos = pCsr->pIter->nData; switch( pCsr->pConfig->eDetail ){ case FTS5_DETAIL_FULL: - rc = sqlite3Fts5IterPoslist(pCsr->pIter, 0, &pPos, &nPos, &dummy); - if( rc==SQLITE_OK ){ - if( pTab->eType==FTS5_VOCAB_ROW ){ - while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ - pCsr->aCnt[0]++; - } - pCsr->aDoc[0]++; - }else{ - int iCol = -1; - while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ - int ii = FTS5_POS2COLUMN(iPos); - pCsr->aCnt[ii]++; - if( iCol!=ii ){ - if( ii>=nCol ){ - rc = FTS5_CORRUPT; - break; - } - pCsr->aDoc[ii]++; - iCol = ii; + pPos = pCsr->pIter->pData; + nPos = pCsr->pIter->nData; + if( pTab->eType==FTS5_VOCAB_ROW ){ + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ + pCsr->aCnt[0]++; + } + pCsr->aDoc[0]++; + }else{ + int iCol = -1; + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ + int ii = FTS5_POS2COLUMN(iPos); + pCsr->aCnt[ii]++; + if( iCol!=ii ){ + if( ii>=nCol ){ + rc = FTS5_CORRUPT; + break; } + pCsr->aDoc[ii]++; + iCol = ii; } } } @@ -443,19 +444,14 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ if( pTab->eType==FTS5_VOCAB_ROW ){ pCsr->aDoc[0]++; }else{ - Fts5Buffer buf = {0, 0, 0}; - rc = sqlite3Fts5IterPoslistBuffer(pCsr->pIter, &buf); - if( rc==SQLITE_OK ){ - while( 0==sqlite3Fts5PoslistNext64(buf.p, buf.n, &iOff,&iPos) ){ - assert_nc( iPos>=0 && iPos=nCol ){ - rc = FTS5_CORRUPT; - break; - } - pCsr->aDoc[iPos]++; + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){ + assert_nc( iPos>=0 && iPos=nCol ){ + rc = FTS5_CORRUPT; + break; } + pCsr->aDoc[iPos]++; } - sqlite3Fts5BufferFree(&buf); } break; diff --git a/ext/fts5/test/fts5ac.test b/ext/fts5/test/fts5ac.test index 00b1328867..a5a522a466 100644 --- a/ext/fts5/test/fts5ac.test +++ b/ext/fts5/test/fts5ac.test @@ -250,7 +250,6 @@ foreach {tn2 sql} { FROM xx WHERE xx match $expr } $res - set res [fts5_query_data $expr xx DESC] do_execsql_test 1.$tn2.$tn.[llength $res].desc { SELECT rowid, fts5_test_poslist(xx), fts5_test_collist(xx) diff --git a/manifest b/manifest index 6c3814c3d9..99a9a8b139 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssqlite3TokenInit()\sutility\sfunction. -D 2016-01-22T17:48:09.470 +C Experimental\sperformance\senhancements\sfor\sfts5. +D 2016-01-22T19:48:34.825 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc d2b93511a969c0c8fcf52aeb5e426571e8c610d2 @@ -97,13 +97,13 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 -F ext/fts5/fts5Int.h 5599703af9c13512900a9f22fec39d48078d619d +F ext/fts5/fts5Int.h f93aed3d05d1b3686c4dccf70544bcfc7aa117f1 F ext/fts5/fts5_aux.c 2dafc3aee0c70d643140c77d8d70daffa51a9e9e F ext/fts5/fts5_buffer.c 7d3f6f01f8fdc45204e6a33925ef8478a67d28dd F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 -F ext/fts5/fts5_expr.c 4ab4504c54bbe24689c83411d8588f4ec99136e9 +F ext/fts5/fts5_expr.c 48b9131b74c8d3b8c12ba0f7995e2d60eecce9f2 F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c 716c301835a122ba36910b4f821c87d26ae9a5d9 +F ext/fts5/fts5_index.c 19062d1f40ba6d88d786a986d1c20f9d741799d0 F ext/fts5/fts5_main.c 833db0a3df10ab26e0221a9baa40cf871c450df3 F ext/fts5/fts5_storage.c fb2eaec3aa954b680d43096dc539f8270bd6390e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -112,13 +112,13 @@ F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be F ext/fts5/fts5_tokenize.c 504984ac6993323247221eebe3cd55bead01b5f8 F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1 -F ext/fts5/fts5_vocab.c ee6df1a3be103414d7b7af833ae1885c7b83a9d0 +F ext/fts5/fts5_vocab.c f1b4308b9b7ec8e659d0c9b39ddc8f1aeee47a1a F ext/fts5/fts5parse.y 1647eba089b9b3fc058b4dc989d9da87d15b9580 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba F ext/fts5/test/fts5_common.tcl 6d0d74b695c4be055a8ba1dd807f22a2abc95b5e F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b -F ext/fts5/test/fts5ac.test d5073ca7bd2d9fe8aab0c82c6c75a7e4b0d70ced +F ext/fts5/test/fts5ac.test dec95549e007dd9be52aa435cdcd0f08e14e64d0 F ext/fts5/test/fts5ad.test 0ddaa5b692ff220100ee396228838f4331399eaa F ext/fts5/test/fts5ae.test 612dcb51f4069226791ff14c17dbfb3138c56f20 F ext/fts5/test/fts5af.test be858a96b1f5de66ba6d64f0021bd8b2408e126c @@ -1419,7 +1419,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e60461e984b8df09256bb0d733dbfae52568a145 -R 03ab6310cefadc63b5c7c7da966c2348 -U drh -Z 0c42ba520d71deaa3e0a21b23ff67f9d +P 7323175337b7ba85ac932ca892b28860f6a5b688 +R bc65520844365f59e43048a22901b688 +T *branch * fts5-perf +T *sym-fts5-perf * +T -sym-trunk * +U dan +Z 20f25a74d681d80924173ee060583d9e diff --git a/manifest.uuid b/manifest.uuid index e9fd60917b..fc3a1227d6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7323175337b7ba85ac932ca892b28860f6a5b688 \ No newline at end of file +b5a57b812fd6a734cf2a342bf0b730ae18912d73 \ No newline at end of file From 3e7860938b58cae4388007a2bc6506679f13ddff Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sat, 23 Jan 2016 07:53:04 +0000 Subject: [PATCH 147/570] Add tooling to create an MSVC Makefile capable of building the core library and shell only, using a pre-built amalgamation. FossilOrigin-Name: c46f1a13cb00264d1164399059250884c7be4ea0 --- Makefile.min.msc | 885 +++++++++++++++++++++++++++++++++++++++++++++ Makefile.msc | 38 ++ manifest | 17 +- manifest.uuid | 2 +- tool/mkmsvcmin.tcl | 88 +++++ 5 files changed, 1023 insertions(+), 7 deletions(-) create mode 100644 Makefile.min.msc create mode 100644 tool/mkmsvcmin.tcl diff --git a/Makefile.min.msc b/Makefile.min.msc new file mode 100644 index 0000000000..2ec986fa4b --- /dev/null +++ b/Makefile.min.msc @@ -0,0 +1,885 @@ +# +# nmake Makefile for SQLite +# +############################################################################### +############################## START OF OPTIONS ############################### +############################################################################### + +# The toplevel directory of the source tree. This is the directory +# that contains this "Makefile.msc". +# +TOP = . + + +# Set this non-0 to enable full warnings (-W4, etc) when compiling. +# +!IFNDEF USE_FULLWARN +USE_FULLWARN = 0 +!ENDIF + +# Set this non-0 to use "stdcall" calling convention for the core library +# and shell executable. +# +!IFNDEF USE_STDCALL +USE_STDCALL = 0 +!ENDIF + +# Set this non-0 to have the shell executable link against the core dynamic +# link library. +# +!IFNDEF DYNAMIC_SHELL +DYNAMIC_SHELL = 0 +!ENDIF + +# Set this non-0 to enable extra code that attempts to detect misuse of the +# SQLite API. +# +!IFNDEF API_ARMOR +API_ARMOR = 0 +!ENDIF + +# If necessary, create a list of harmless compiler warnings to disable when +# compiling the various tools. For the SQLite source code itself, warnings, +# if any, will be disabled from within it. +# +!IFNDEF NO_WARN +!IF $(USE_FULLWARN)!=0 +NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206 +NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706 +!ENDIF +!ENDIF + +# Set this non-0 to use the library paths and other options necessary for +# Windows Phone 8.1. +# +!IFNDEF USE_WP81_OPTS +USE_WP81_OPTS = 0 +!ENDIF + +# Set this non-0 to split the SQLite amalgamation file into chunks to +# be used for debugging with Visual Studio. +# +!IFNDEF SPLIT_AMALGAMATION +SPLIT_AMALGAMATION = 0 +!ENDIF + + +# Set this non-0 to dynamically link to the MSVC runtime library. +# +!IFNDEF USE_CRT_DLL +USE_CRT_DLL = 0 +!ENDIF + +# Set this non-0 to link to the RPCRT4 library. +# +!IFNDEF USE_RPCRT4_LIB +USE_RPCRT4_LIB = 0 +!ENDIF + +# Set this non-0 to generate assembly code listings for the source code +# files. +# +!IFNDEF USE_LISTINGS +USE_LISTINGS = 0 +!ENDIF + +# Set this non-0 to attempt setting the native compiler automatically +# for cross-compiling the command line tools needed during the compilation +# process. +# +!IFNDEF XCOMPILE +XCOMPILE = 0 +!ENDIF + +# Set this non-0 to use the native libraries paths for cross-compiling +# the command line tools needed during the compilation process. +# +!IFNDEF USE_NATIVE_LIBPATHS +USE_NATIVE_LIBPATHS = 0 +!ENDIF + +# Set this 0 to skip the compiling and embedding of version resources. +# +!IFNDEF USE_RC +USE_RC = 1 +!ENDIF + +# Set this non-0 to compile binaries suitable for the WinRT environment. +# This setting does not apply to any binaries that require Tcl to operate +# properly (i.e. the text fixture, etc). +# +!IFNDEF FOR_WINRT +FOR_WINRT = 0 +!ENDIF + +# Set this non-0 to compile binaries suitable for the UAP environment. +# This setting does not apply to any binaries that require Tcl to operate +# properly (i.e. the text fixture, etc). +# +!IFNDEF FOR_UAP +FOR_UAP = 0 +!ENDIF + +# Set this non-0 to compile binaries suitable for the Windows 10 platform. +# +!IFNDEF FOR_WIN10 +FOR_WIN10 = 0 +!ENDIF + + +# Set this to non-0 to create and use PDBs. +# +!IFNDEF SYMBOLS +SYMBOLS = 1 +!ENDIF + +# Set this to non-0 to use the SQLite debugging heap subsystem. +# +!IFNDEF MEMDEBUG +MEMDEBUG = 0 +!ENDIF + +# Set this to non-0 to use the Win32 native heap subsystem. +# +!IFNDEF WIN32HEAP +WIN32HEAP = 0 +!ENDIF + +# Set this to non-0 to enable OSTRACE() macros, which can be useful when +# debugging. +# +!IFNDEF OSTRACE +OSTRACE = 0 +!ENDIF + +# Set this to one of the following values to enable various debugging +# features. Each level includes the debugging options from the previous +# levels. Currently, the recognized values for DEBUG are: +# +# 0 == NDEBUG: Disables assert() and other runtime diagnostics. +# 1 == SQLITE_ENABLE_API_ARMOR: extra attempts to detect misuse of the API. +# 2 == Disables NDEBUG and all optimizations and then enables PDBs. +# 3 == SQLITE_DEBUG: Enables various diagnostics messages and code. +# 4 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call. +# 5 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros. +# 6 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros. +# +!IFNDEF DEBUG +DEBUG = 0 +!ENDIF + +# Enable use of available compiler optimizations? Normally, this should be +# non-zero. Setting this to zero, thus disabling all compiler optimizations, +# can be useful for testing. +# +!IFNDEF OPTIMIZATIONS +OPTIMIZATIONS = 2 +!ENDIF + +# Set the source code file to be used by executables and libraries when +# they need the amalgamation. +# +!IFNDEF SQLITE3C +!IF $(SPLIT_AMALGAMATION)!=0 +SQLITE3C = sqlite3-all.c +!ELSE +SQLITE3C = sqlite3.c +!ENDIF +!ENDIF + +# Set the include code file to be used by executables and libraries when +# they need SQLite. +# +!IFNDEF SQLITE3H +SQLITE3H = sqlite3.h +!ENDIF + +# This is the name to use for the SQLite dynamic link library (DLL). +# +!IFNDEF SQLITE3DLL +SQLITE3DLL = sqlite3.dll +!ENDIF + +# This is the name to use for the SQLite import library (LIB). +# +!IFNDEF SQLITE3LIB +SQLITE3LIB = sqlite3.lib +!ENDIF + +# This is the name to use for the SQLite shell executable (EXE). +# +!IFNDEF SQLITE3EXE +SQLITE3EXE = sqlite3.exe +!ENDIF + +# This is the argument used to set the program database (PDB) file for the +# SQLite shell executable (EXE). +# +!IFNDEF SQLITE3EXEPDB +SQLITE3EXEPDB = /pdb:sqlite3sh.pdb +!ENDIF + +# These are the "standard" SQLite compilation options used when compiling for +# the Windows platform. +# +!IFNDEF OPT_FEATURE_FLAGS +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 +!ENDIF + +# These are the "extended" SQLite compilation options used when compiling for +# the Windows 10 platform. +# +!IFNDEF EXT_FEATURE_FLAGS +!IF $(FOR_WIN10)!=0 +EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4=1 +EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_SYSTEM_MALLOC=1 +EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_OMIT_LOCALTIME=1 +!ELSE +EXT_FEATURE_FLAGS = +!ENDIF +!ENDIF + +############################################################################### +############################### END OF OPTIONS ################################ +############################################################################### + +# This assumes that MSVC is always installed in 32-bit Program Files directory +# and sets the variable for use in locating other 32-bit installs accordingly. +# +PROGRAMFILES_X86 = $(VCINSTALLDIR)\..\.. +PROGRAMFILES_X86 = $(PROGRAMFILES_X86:\\=\) + +# Check for the predefined command macro CC. This should point to the compiler +# binary for the target platform. If it is not defined, simply define it to +# the legacy default value 'cl.exe'. +# +!IFNDEF CC +CC = cl.exe +!ENDIF + +# Check for the command macro LD. This should point to the linker binary for +# the target platform. If it is not defined, simply define it to the legacy +# default value 'link.exe'. +# +!IFNDEF LD +LD = link.exe +!ENDIF + +# Check for the predefined command macro RC. This should point to the resource +# compiler binary for the target platform. If it is not defined, simply define +# it to the legacy default value 'rc.exe'. +# +!IFNDEF RC +RC = rc.exe +!ENDIF + +# Check for the MSVC runtime library path macro. Othertise, this value will +# default to the 'lib' directory underneath the MSVC installation directory. +# +!IFNDEF CRTLIBPATH +CRTLIBPATH = $(VCINSTALLDIR)\lib +!ENDIF + +CRTLIBPATH = $(CRTLIBPATH:\\=\) + +# Check for the command macro NCC. This should point to the compiler binary +# for the platform the compilation process is taking place on. If it is not +# defined, simply define it to have the same value as the CC macro. When +# cross-compiling, it is suggested that this macro be modified via the command +# line (since nmake itself does not provide a built-in method to guess it). +# For example, to use the x86 compiler when cross-compiling for x64, a command +# line similar to the following could be used (all on one line): +# +# nmake /f Makefile.msc sqlite3.dll +# XCOMPILE=1 USE_NATIVE_LIBPATHS=1 +# +# Alternatively, the full path and file name to the compiler binary for the +# platform the compilation process is taking place may be specified (all on +# one line): +# +# nmake /f Makefile.msc sqlite3.dll +# "NCC=""%VCINSTALLDIR%\bin\cl.exe""" +# USE_NATIVE_LIBPATHS=1 +# +!IFDEF NCC +NCC = $(NCC:\\=\) +!ELSEIF $(XCOMPILE)!=0 +NCC = "$(VCINSTALLDIR)\bin\$(CC)" +NCC = $(NCC:\\=\) +!ELSE +NCC = $(CC) +!ENDIF + +# Check for the MSVC native runtime library path macro. Othertise, +# this value will default to the 'lib' directory underneath the MSVC +# installation directory. +# +!IFNDEF NCRTLIBPATH +NCRTLIBPATH = $(VCINSTALLDIR)\lib +!ENDIF + +NCRTLIBPATH = $(NCRTLIBPATH:\\=\) + +# Check for the Platform SDK library path macro. Othertise, this +# value will default to the 'lib' directory underneath the Windows +# SDK installation directory (the environment variable used appears +# to be available when using Visual C++ 2008 or later via the +# command line). +# +!IFNDEF NSDKLIBPATH +NSDKLIBPATH = $(WINDOWSSDKDIR)\lib +!ENDIF + +NSDKLIBPATH = $(NSDKLIBPATH:\\=\) + +# C compiler and options for use in building executables that +# will run on the platform that is doing the build. +# +!IF $(USE_FULLWARN)!=0 +BCC = $(NCC) -nologo -W4 $(CCOPTS) $(BCCOPTS) +!ELSE +BCC = $(NCC) -nologo -W3 $(CCOPTS) $(BCCOPTS) +!ENDIF + +# Check if assembly code listings should be generated for the source +# code files to be compiled. +# +!IF $(USE_LISTINGS)!=0 +BCC = $(BCC) -FAcs +!ENDIF + +# Check if the native library paths should be used when compiling +# the command line tools used during the compilation process. If +# so, set the necessary macro now. +# +!IF $(USE_NATIVE_LIBPATHS)!=0 +NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)" + +!IFDEF NUCRTLIBPATH +NUCRTLIBPATH = $(NUCRTLIBPATH:\\=\) +NLTLIBPATHS = $(NLTLIBPATHS) "/LIBPATH:$(NUCRTLIBPATH)" +!ENDIF +!ENDIF + +# C compiler and options for use in building executables that +# will run on the target platform. (BCC and TCC are usually the +# same unless your are cross-compiling.) +# +!IF $(USE_FULLWARN)!=0 +TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS) +!ELSE +TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS) +!ENDIF + +TCC = $(TCC) -DSQLITE_OS_WIN=1 -I$(TOP) -fp:precise +RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) $(RCOPTS) $(RCCOPTS) + +# Adjust the names of the primary targets for use with Windows 10. +# +!IF $(FOR_WIN10)!=0 +SQLITE3DLL = winsqlite3.dll +SQLITE3LIB = winsqlite3.lib +SQLITE3EXE = winsqlite3shell.exe +SQLITE3EXEPDB = +!ENDIF + +# Check if we want to use the "stdcall" calling convention when compiling. +# This is not supported by the compilers for non-x86 platforms. It should +# also be noted here that building any target with these "stdcall" options +# will most likely fail if the Tcl library is also required. This is due +# to how the Tcl library functions are declared and exported (i.e. without +# an explicit calling convention, which results in "cdecl"). +# +!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0 +!IF "$(PLATFORM)"=="x86" +CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall +SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall +!ELSE +!IFNDEF PLATFORM +CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall +SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall +!ELSE +CORE_CCONV_OPTS = +SHELL_CCONV_OPTS = +!ENDIF +!ENDIF +!ELSE +CORE_CCONV_OPTS = +SHELL_CCONV_OPTS = +!ENDIF + +# These are additional compiler options used for the core library. +# +!IFNDEF CORE_COMPILE_OPTS +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) -DSQLITE_API=__declspec(dllexport) +!ELSE +CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) +!ENDIF +!ENDIF + +# These are the additional targets that the core library should depend on +# when linking. +# +!IFNDEF CORE_LINK_DEP +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +CORE_LINK_DEP = +!ELSE +CORE_LINK_DEP = +!ENDIF +!ENDIF + +# These are additional linker options used for the core library. +# +!IFNDEF CORE_LINK_OPTS +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +CORE_LINK_OPTS = +!ELSE +CORE_LINK_OPTS = +!ENDIF +!ENDIF + +# These are additional compiler options used for the shell executable. +# +!IFNDEF SHELL_COMPILE_OPTS +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport) +!ELSE +SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) +!ENDIF +!ENDIF + +# This is the source code that the shell executable should be compiled +# with. +# +!IFNDEF SHELL_CORE_SRC +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +SHELL_CORE_SRC = +!ELSE +SHELL_CORE_SRC = $(SQLITE3C) +!ENDIF +!ENDIF + +# This is the core library that the shell executable should depend on. +# +!IFNDEF SHELL_CORE_DEP +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +SHELL_CORE_DEP = $(SQLITE3DLL) +!ELSE +SHELL_CORE_DEP = +!ENDIF +!ENDIF + +# This is the core library that the shell executable should link with. +# +!IFNDEF SHELL_CORE_LIB +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +SHELL_CORE_LIB = $(SQLITE3LIB) +!ELSE +SHELL_CORE_LIB = +!ENDIF +!ENDIF + +# These are additional linker options used for the shell executable. +# +!IFNDEF SHELL_LINK_OPTS +SHELL_LINK_OPTS = $(SHELL_CORE_LIB) +!ENDIF + +# Check if assembly code listings should be generated for the source +# code files to be compiled. +# +!IF $(USE_LISTINGS)!=0 +TCC = $(TCC) -FAcs +!ENDIF + +# When compiling the library for use in the WinRT environment, +# the following compile-time options must be used as well to +# disable use of Win32 APIs that are not available and to enable +# use of Win32 APIs that are specific to Windows 8 and/or WinRT. +# +!IF $(FOR_WINRT)!=0 +TCC = $(TCC) -DSQLITE_OS_WINRT=1 +RCC = $(RCC) -DSQLITE_OS_WINRT=1 +TCC = $(TCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP +RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP +!ENDIF + +# C compiler options for the Windows 10 platform (needs MSVC 2015). +# +!IF $(FOR_WIN10)!=0 +TCC = $(TCC) /guard:cf -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE +BCC = $(BCC) /guard:cf -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE +!ENDIF + +# Also, we need to dynamically link to the correct MSVC runtime +# when compiling for WinRT (e.g. debug or release) OR if the +# USE_CRT_DLL option is set to force dynamically linking to the +# MSVC runtime library. +# +!IF $(FOR_WINRT)!=0 || $(FOR_WIN10)!=0 || $(USE_CRT_DLL)!=0 +!IF $(DEBUG)>1 +TCC = $(TCC) -MDd +BCC = $(BCC) -MDd +!ELSE +TCC = $(TCC) -MD +BCC = $(BCC) -MD +!ENDIF +!ELSE +!IF $(DEBUG)>1 +TCC = $(TCC) -MTd +BCC = $(BCC) -MTd +!ELSE +TCC = $(TCC) -MT +BCC = $(BCC) -MT +!ENDIF +!ENDIF + + +# Define -DNDEBUG to compile without debugging (i.e., for production usage) +# Omitting the define will cause extra debugging code to be inserted and +# includes extra comments when "EXPLAIN stmt" is used. +# +!IF $(DEBUG)==0 +TCC = $(TCC) -DNDEBUG +BCC = $(BCC) -DNDEBUG +RCC = $(RCC) -DNDEBUG +!ENDIF + +!IF $(DEBUG)>0 || $(API_ARMOR)!=0 || $(FOR_WIN10)!=0 +TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR=1 +RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1 +!ENDIF + +!IF $(DEBUG)>2 +TCC = $(TCC) -DSQLITE_DEBUG=1 +RCC = $(RCC) -DSQLITE_DEBUG=1 +!ENDIF + +!IF $(DEBUG)>4 || $(OSTRACE)!=0 +TCC = $(TCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1 +RCC = $(RCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1 +!ENDIF + +!IF $(DEBUG)>5 +TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE=1 +RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE=1 +!ENDIF + +# Prevent warnings about "insecure" MSVC runtime library functions +# being used. +# +TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS +BCC = $(BCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS +RCC = $(RCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS + +# Prevent warnings about "deprecated" POSIX functions being used. +# +TCC = $(TCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS +BCC = $(BCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS +RCC = $(RCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS + +# Use the SQLite debugging heap subsystem? +# +!IF $(MEMDEBUG)!=0 +TCC = $(TCC) -DSQLITE_MEMDEBUG=1 +RCC = $(RCC) -DSQLITE_MEMDEBUG=1 + +# Use native Win32 heap subsystem instead of malloc/free? +# +!ELSEIF $(WIN32HEAP)!=0 +TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1 +RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1 + +# Validate the heap on every call into the native Win32 heap subsystem? +# +!IF $(DEBUG)>3 +TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1 +RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1 +!ENDIF +!ENDIF + + +# Compiler options needed for programs that use the readline() library. +# +!IFNDEF READLINE_FLAGS +READLINE_FLAGS = -DHAVE_READLINE=0 +!ENDIF + +# The library that programs using readline() must link against. +# +!IFNDEF LIBREADLINE +LIBREADLINE = +!ENDIF + +# Should the database engine be compiled threadsafe +# +TCC = $(TCC) -DSQLITE_THREADSAFE=1 +RCC = $(RCC) -DSQLITE_THREADSAFE=1 + +# Do threads override each others locks by default (1), or do we test (-1) +# +TCC = $(TCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1 +RCC = $(RCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1 + +# Any target libraries which libsqlite must be linked against +# +!IFNDEF TLIBS +TLIBS = +!ENDIF + +# Flags controlling use of the in memory btree implementation +# +# SQLITE_TEMP_STORE is 0 to force temporary tables to be in a file, 1 to +# default to file, 2 to default to memory, and 3 to force temporary +# tables to always be in memory. +# +TCC = $(TCC) -DSQLITE_TEMP_STORE=1 +RCC = $(RCC) -DSQLITE_TEMP_STORE=1 + +# Enable/disable loadable extensions, and other optional features +# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*). +# The same set of OMIT and ENABLE flags should be passed to the +# LEMON parser generator and the mkkeywordhash tool as well. + +# These are the required SQLite compilation options used when compiling for +# the Windows platform. +# +REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100 + +# If we are linking to the RPCRT4 library, enable features that need it. +# +!IF $(USE_RPCRT4_LIB)!=0 +REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_WIN32_USE_UUID=1 +!ENDIF + +# Add the required and optional SQLite compilation options into the command +# lines used to invoke the MSVC code and resource compilers. +# +TCC = $(TCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) +RCC = $(RCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) + +# Add in any optional parameters specified on the commane line, e.g. +# nmake /f Makefile.msc all "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1" +# +TCC = $(TCC) $(OPTS) +RCC = $(RCC) $(OPTS) + +# If compiling for debugging, add some defines. +# +!IF $(DEBUG)>1 +TCC = $(TCC) -D_DEBUG +BCC = $(BCC) -D_DEBUG +RCC = $(RCC) -D_DEBUG +!ENDIF + +# If optimizations are enabled or disabled (either implicitly or +# explicitly), add the necessary flags. +# +!IF $(DEBUG)>1 || $(OPTIMIZATIONS)==0 +TCC = $(TCC) -Od +BCC = $(BCC) -Od +!ELSEIF $(OPTIMIZATIONS)>=3 +TCC = $(TCC) -Ox +BCC = $(BCC) -Ox +!ELSEIF $(OPTIMIZATIONS)==2 +TCC = $(TCC) -O2 +BCC = $(BCC) -O2 +!ELSEIF $(OPTIMIZATIONS)==1 +TCC = $(TCC) -O1 +BCC = $(BCC) -O1 +!ENDIF + +# If symbols are enabled (or compiling for debugging), enable PDBs. +# +!IF $(DEBUG)>1 || $(SYMBOLS)!=0 +TCC = $(TCC) -Zi +BCC = $(BCC) -Zi +!ENDIF + + +# Command line prefixes for compiling code, compiling resources, +# linking, etc. +# +LTCOMPILE = $(TCC) -Fo$@ +LTRCOMPILE = $(RCC) -r +LTLIB = lib.exe +LTLINK = $(TCC) -Fe$@ + +# If requested, link to the RPCRT4 library. +# +!IF $(USE_RPCRT4_LIB)!=0 +LTLINK = $(LTLINK) rpcrt4.lib +!ENDIF + +# If a platform was set, force the linker to target that. +# Note that the vcvars*.bat family of batch files typically +# set this for you. Otherwise, the linker will attempt +# to deduce the binary type based on the object files. +!IFDEF PLATFORM +LTLINKOPTS = /NOLOGO /MACHINE:$(PLATFORM) +LTLIBOPTS = /NOLOGO /MACHINE:$(PLATFORM) +!ELSE +LTLINKOPTS = /NOLOGO +LTLIBOPTS = /NOLOGO +!ENDIF + +# When compiling for use in the WinRT environment, the following +# linker option must be used to mark the executable as runnable +# only in the context of an application container. +# +!IF $(FOR_WINRT)!=0 +LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER +!IF "$(VISUALSTUDIOVERSION)"=="12.0" || "$(VISUALSTUDIOVERSION)"=="14.0" +!IFNDEF STORELIBPATH +!IF "$(PLATFORM)"=="x86" +STORELIBPATH = $(CRTLIBPATH)\store +!ELSEIF "$(PLATFORM)"=="x64" +STORELIBPATH = $(CRTLIBPATH)\store\amd64 +!ELSEIF "$(PLATFORM)"=="ARM" +STORELIBPATH = $(CRTLIBPATH)\store\arm +!ELSE +STORELIBPATH = $(CRTLIBPATH)\store +!ENDIF +!ENDIF +STORELIBPATH = $(STORELIBPATH:\\=\) +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(STORELIBPATH)" +!ENDIF +!ENDIF + +# When compiling for Windows Phone 8.1, an extra library path is +# required. +# +!IF $(USE_WP81_OPTS)!=0 +!IFNDEF WP81LIBPATH +!IF "$(PLATFORM)"=="x86" +WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86 +!ELSEIF "$(PLATFORM)"=="ARM" +WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\ARM +!ELSE +WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86 +!ENDIF +!ENDIF +!ENDIF + +# When compiling for Windows Phone 8.1, some extra linker options +# are also required. +# +!IF $(USE_WP81_OPTS)!=0 +!IFDEF WP81LIBPATH +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(WP81LIBPATH)" +!ENDIF +LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE +LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib +LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib +!ENDIF + +# When compiling for UAP, some extra linker options are also required. +# +!IF $(FOR_UAP)!=0 +LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib +LTLINKOPTS = $(LTLINKOPTS) mincore.lib +!IFDEF PSDKLIBPATH +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)" +!ENDIF +!ENDIF + +# If either debugging or symbols are enabled, enable PDBs. +# +!IF $(DEBUG)>1 || $(SYMBOLS)!=0 +LDFLAGS = /DEBUG $(LDOPTS) +!ELSE +LDFLAGS = $(LDOPTS) +!ENDIF + + +# You should not have to change anything below this line +############################################################################### + + +# Object files for the amalgamation. +# +LIBOBJS1 = sqlite3.lo + +# Determine the real value of LIBOBJ based on the 'configure' script +# +LIBOBJ = $(LIBOBJS1) + +# Determine if embedded resource compilation and usage are enabled. +# +!IF $(USE_RC)!=0 +LIBRESOBJS = sqlite3res.lo +!ELSE +LIBRESOBJS = +!ENDIF + + +# Additional compiler options for the shell. These are only effective +# when the shell is not being dynamically linked. +# +!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 +SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 +!ENDIF + + +# This is the default Makefile target. The objects listed here +# are what get build when you type just "make" with no arguments. +# +all: dll libsqlite3.lib shell + +# Dynamic link library section. +# +dll: $(SQLITE3DLL) + +# Shell executable. +# +shell: $(SQLITE3EXE) + +libsqlite3.lib: $(LIBOBJ) + $(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS) + + +$(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) + $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) + + +$(SQLITE3EXE): $(TOP)\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H) + $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\shell.c $(SHELL_CORE_SRC) \ + /link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) + + +# Rule to build the amalgamation +# +sqlite3.lo: $(SQLITE3C) + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(SQLITE3C) + + +# Rule to build the Win32 resources object file. +# +!IF $(USE_RC)!=0 +_HASHCHAR=^# +!IF ![echo !IFNDEF VERSION > rcver.vc] && \ + ![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| find "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \ + ![echo !ENDIF >> rcver.vc] +!INCLUDE rcver.vc +!ENDIF + +RESOURCE_VERSION = $(VERSION:^#=) +RESOURCE_VERSION = $(RESOURCE_VERSION:define=) +RESOURCE_VERSION = $(RESOURCE_VERSION:SQLITE_VERSION=) +RESOURCE_VERSION = $(RESOURCE_VERSION:"=) +RESOURCE_VERSION = $(RESOURCE_VERSION:.=,) + +$(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H) + echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h + echo #define SQLITE_RESOURCE_VERSION $(RESOURCE_VERSION) >> sqlite3rc.h + echo #endif >> sqlite3rc.h + $(LTRCOMPILE) -fo $(LIBRESOBJS) -DRC_VERONLY $(TOP)\sqlite3.rc +!ENDIF + + +clean: + del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL + del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL diff --git a/Makefile.msc b/Makefile.msc index 5921e9375a..ab0ba95d53 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -10,11 +10,13 @@ # TOP = . +# <> # Set this non-0 to create and use the SQLite amalgamation file. # !IFNDEF USE_AMALGAMATION USE_AMALGAMATION = 1 !ENDIF +# <> # Set this non-0 to enable full warnings (-W4, etc) when compiling. # @@ -68,11 +70,13 @@ USE_WP81_OPTS = 0 SPLIT_AMALGAMATION = 0 !ENDIF +# <> # Set this non-0 to use the International Components for Unicode (ICU). # !IFNDEF USE_ICU USE_ICU = 0 !ENDIF +# <> # Set this non-0 to dynamically link to the MSVC runtime library. # @@ -136,12 +140,14 @@ FOR_UAP = 0 FOR_WIN10 = 0 !ENDIF +# <> # Set this non-0 to skip attempting to look for and/or link with the Tcl # runtime library. # !IFNDEF NO_TCL NO_TCL = 0 !ENDIF +# <> # Set this to non-0 to create and use PDBs. # @@ -553,6 +559,7 @@ BCC = $(BCC) -MT !ENDIF !ENDIF +# <> # The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in # any extension header files by default. For non-amalgamation # builds, we need to make sure the compiler can find these. @@ -576,6 +583,7 @@ MKSQLITE3C_ARGS = --linemacros MKSQLITE3C_ARGS = !ENDIF !ENDIF +# <> # Define -DNDEBUG to compile without debugging (i.e., for production usage) # Omitting the define will cause extra debugging code to be inserted and @@ -640,6 +648,7 @@ RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1 !ENDIF !ENDIF +# <> # The locations of the Tcl header and library files. Also, the library that # non-stubs enabled programs using Tcl must link against. These variables # (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment @@ -691,6 +700,7 @@ LIBICU = icuuc.lib icuin.lib !IFNDEF TCLSH_CMD TCLSH_CMD = tclsh85 !ENDIF +# <> # Compiler options needed for programs that use the readline() library. # @@ -789,6 +799,7 @@ TCC = $(TCC) -Zi BCC = $(BCC) -Zi !ENDIF +# <> # If ICU support is enabled, add the compiler options for it. # !IF $(USE_ICU)!=0 @@ -799,6 +810,7 @@ RCC = $(RCC) -I$(TOP)\ext\icu TCC = $(TCC) -I$(ICUINCDIR) RCC = $(RCC) -I$(ICUINCDIR) !ENDIF +# <> # Command line prefixes for compiling code, compiling resources, # linking, etc. @@ -894,6 +906,7 @@ LDFLAGS = /DEBUG $(LDOPTS) LDFLAGS = $(LDOPTS) !ENDIF +# <> # Start with the Tcl related linker options. # !IF $(NO_TCL)==0 @@ -907,10 +920,12 @@ LTLIBS = $(LIBTCL) LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:$(ICULIBDIR) LTLIBS = $(LTLIBS) $(LIBICU) !ENDIF +# <> # You should not have to change anything below this line ############################################################################### +# <> # Object files for the SQLite library (non-amalgamation). # LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \ @@ -934,6 +949,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \ vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \ utf.lo vtab.lo +# <> # Object files for the amalgamation. # @@ -941,11 +957,15 @@ LIBOBJS1 = sqlite3.lo # Determine the real value of LIBOBJ based on the 'configure' script # +# <> !IF $(USE_AMALGAMATION)==0 LIBOBJ = $(LIBOBJS0) !ELSE +# <> LIBOBJ = $(LIBOBJS1) +# <> !ENDIF +# <> # Determine if embedded resource compilation and usage are enabled. # @@ -955,6 +975,7 @@ LIBRESOBJS = sqlite3res.lo LIBRESOBJS = !ENDIF +# <> # All of the source code files. # SRC1 = \ @@ -1303,6 +1324,7 @@ FUZZDATA = \ $(TOP)\test\fuzzdata2.db \ $(TOP)\test\fuzzdata3.db \ $(TOP)\test\fuzzdata4.db +# <> # Additional compiler options for the shell. These are only effective # when the shell is not being dynamically linked. @@ -1311,6 +1333,7 @@ FUZZDATA = \ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 !ENDIF +# <> # Extra compiler options for various test tools. # MPTESTER_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS5 @@ -1320,6 +1343,7 @@ FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 # Standard options to testfixture. # TESTOPTS = --verbose=file --output=test-out.txt +# <> # This is the default Makefile target. The objects listed here # are what get build when you type just "make" with no arguments. @@ -1337,22 +1361,27 @@ shell: $(SQLITE3EXE) libsqlite3.lib: $(LIBOBJ) $(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS) +# <> libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib $(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCLSTUB) $(TLIBS) +# <> $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) +# <> sqlite3.def: libsqlite3.lib echo EXPORTS > sqlite3.def dumpbin /all libsqlite3.lib \ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3_.*)$$" \1 \ | sort >> sqlite3.def +# <> $(SQLITE3EXE): $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H) $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c $(SHELL_CORE_SRC) \ /link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) +# <> sqldiff.exe: $(TOP)\tool\sqldiff.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) @@ -1406,12 +1435,14 @@ sqlite3.c: .target_source sqlite3ext.h $(TOP)\tool\mksqlite3c.tcl sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl $(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl +# <> # Rule to build the amalgamation # sqlite3.lo: $(SQLITE3C) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(SQLITE3C) +# <> # Rules to build the LEMON compiler generator # lempar.c: $(TOP)\tool\lempar.c @@ -1432,10 +1463,12 @@ parse.lo: parse.c $(HDR) opcodes.lo: opcodes.c $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c opcodes.c +# <> # Rule to build the Win32 resources object file. # !IF $(USE_RC)!=0 +# <> $(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(SQLITE3H) echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h for /F %%V in ('type "$(TOP)\VERSION"') do ( \ @@ -1444,8 +1477,10 @@ $(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(SQLITE3H) ) echo #endif >> sqlite3rc.h $(LTRCOMPILE) -fo $(LIBRESOBJS) $(TOP)\src\sqlite3.rc +# <> !ENDIF +# <> # Rules to build individual *.lo files from files in the src directory. # alter.lo: $(TOP)\src\alter.c $(HDR) @@ -1945,10 +1980,12 @@ speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C) $(SQLITE3H) rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU -Fe$@ \ $(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) +# <> clean: del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL +# <> del /Q $(SQLITE3C) $(SQLITE3H) opcodes.c opcodes.h 2>NUL del /Q lemon.* lempar.c parse.* 2>NUL del /Q mkkeywordhash.* keywordhash.h 2>NUL @@ -1974,3 +2011,4 @@ clean: del /Q sqlite-*-output.vsix 2>NUL del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe 2>NUL del /Q fts5.* fts5parse.* 2>NUL +# <> diff --git a/manifest b/manifest index 61cf5d66ed..12db615b93 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,9 @@ -C More\swork\son\sthe\sMSVC\sbuild. -D 2016-01-23T00:07:51.151 +C Add\stooling\sto\screate\san\sMSVC\sMakefile\scapable\sof\sbuilding\sthe\score\slibrary\sand\sshell\sonly,\susing\sa\spre-built\samalgamation. +D 2016-01-23T07:53:04.796 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 +F Makefile.min.msc c805e4a474fc7610d4f0cd0b6a9f56334a14c6ad +F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -1378,6 +1379,7 @@ F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh 5a5441280b509d2bb3bdc71bfb63781b0d570373 F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8 +F tool/mkmsvcmin.tcl 859737ff14668827738a3f7ca17ba643a88bcecc F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e @@ -1419,7 +1421,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a1c8116ced62d81f3f5ca26bbe0877e829d4cc56 -R b34246fa017fc0ae2e7bf7cb484e3eeb +P a79c46bc61a35edbaf6112c26e8052314b0eb16a +R bd00cfb25453f633191b5f1755909575 +T *branch * msvcMakeMin +T *sym-msvcMakeMin * +T -sym-trunk * U mistachkin -Z ba075ff448ff99fa520b3503324fe6e9 +Z 18f99743dd26f3a3f31830457ad1b4ef diff --git a/manifest.uuid b/manifest.uuid index d1ea2b33a4..06bbe8845c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a79c46bc61a35edbaf6112c26e8052314b0eb16a \ No newline at end of file +c46f1a13cb00264d1164399059250884c7be4ea0 \ No newline at end of file diff --git a/tool/mkmsvcmin.tcl b/tool/mkmsvcmin.tcl new file mode 100644 index 0000000000..56c9d52811 --- /dev/null +++ b/tool/mkmsvcmin.tcl @@ -0,0 +1,88 @@ +#!/usr/bin/tcl +# +# Removes and/or replaces specially marked sections from the Makefile +# for MSVC, writing the resulting output to another (different) file. +# In addition, some other strings are also removed and/or replaced if +# they are present in the Makefile. +# +set fromFileName [lindex $argv 0] + +if {![file exists $fromFileName]} then { + error "input file \"$fromFileName\" does not exist" +} + +set toFileName [lindex $argv 1] + +if {[file exists $toFileName]} then { + error "output file \"$toFileName\" already exists" +} + +proc readFile { fileName } { + set file_id [open $fileName RDONLY] + fconfigure $file_id -encoding binary -translation binary + set result [read $file_id] + close $file_id + return $result +} + +proc writeFile { fileName data } { + set file_id [open $fileName {WRONLY CREAT TRUNC}] + fconfigure $file_id -encoding binary -translation binary + puts -nonewline $file_id $data + close $file_id + return "" +} + +proc escapeSubSpec { data } { + regsub -all -- {&} $data {\\\&} data + regsub -all -- {\\(\d+)} $data {\\\\\1} data + return $data +} + +proc substVars { data } { + return [uplevel 1 [list subst -nocommands -nobackslashes $data]] +} + +# +# NOTE: This block is used to replace the section marked <> in +# the Makefile, if it exists. +# +set blocks(1) [string trimleft [string map [list \\\\ \\] { +_HASHCHAR=^# +!IF ![echo !IFNDEF VERSION > rcver.vc] && \\ + ![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| find "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \\ + ![echo !ENDIF >> rcver.vc] +!INCLUDE rcver.vc +!ENDIF + +RESOURCE_VERSION = $(VERSION:^#=) +RESOURCE_VERSION = $(RESOURCE_VERSION:define=) +RESOURCE_VERSION = $(RESOURCE_VERSION:SQLITE_VERSION=) +RESOURCE_VERSION = $(RESOURCE_VERSION:"=) +RESOURCE_VERSION = $(RESOURCE_VERSION:.=,) + +$(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H) + echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h + echo #define SQLITE_RESOURCE_VERSION $(RESOURCE_VERSION) >> sqlite3rc.h + echo #endif >> sqlite3rc.h + $(LTRCOMPILE) -fo $(LIBRESOBJS) -DRC_VERONLY $(TOP)\sqlite3.rc +}]] + +set data [readFile $fromFileName] + +regsub -all -- {# <>\n.*?# <>\n} \ + $data "" data + +foreach i [lsort [array names blocks]] { + regsub -all -- [substVars \ + {# <>\n.*?# <>\n}] \ + $data [escapeSubSpec $blocks($i)] data +} + +set data [string map [list " -I\$(TOP)\\src" ""] $data] +set data [string map [list " /DEF:sqlite3.def" ""] $data] +set data [string map [list " sqlite3.def" ""] $data] +set data [string map [list " libtclsqlite3.lib" ""] $data] +set data [string map [list "\$(TOP)\\src\\" "\$(TOP)\\"] $data] + +writeFile $toFileName $data From c615097d3d9140f9ea2d23faf2dd4ed58475a6ad Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Jan 2016 14:05:27 +0000 Subject: [PATCH 148/570] Remove an assert() that can be false if compiled with SQLITE_USE_ALLOCA. FossilOrigin-Name: f0a551edf87ef061deae34d88b02c3b484ae9adc --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/prepare.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 61cf5d66ed..7b54ea0ab0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C More\swork\son\sthe\sMSVC\sbuild. -D 2016-01-23T00:07:51.151 +C Remove\san\sassert()\sthat\scan\sbe\sfalse\sif\scompiled\swith\sSQLITE_USE_ALLOCA. +D 2016-01-23T14:05:27.109 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -340,7 +340,7 @@ F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 F src/pragma.c ea290193369faa0a26ae2f924e7b86289b4a7987 F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c -F src/prepare.c 74855ddbdfad6a1c4a4d5c4b0913ebb01174ba19 +F src/prepare.c 8ca7237428f372a04717d558555ea67ee1c5df93 F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a1c8116ced62d81f3f5ca26bbe0877e829d4cc56 -R b34246fa017fc0ae2e7bf7cb484e3eeb -U mistachkin -Z ba075ff448ff99fa520b3503324fe6e9 +P a79c46bc61a35edbaf6112c26e8052314b0eb16a +R 78c84a447f1adb3672b2aa032cc33ea6 +U drh +Z 2d3baf83036e6553ecd28fa4c13c4bc2 diff --git a/manifest.uuid b/manifest.uuid index d1ea2b33a4..d11f7b73ef 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a79c46bc61a35edbaf6112c26e8052314b0eb16a \ No newline at end of file +f0a551edf87ef061deae34d88b02c3b484ae9adc \ No newline at end of file diff --git a/src/prepare.c b/src/prepare.c index acc70dd2d5..acd50fcaf7 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -525,7 +525,7 @@ static int sqlite3Prepare( } pParse->pReprepare = pReprepare; assert( ppStmt && *ppStmt==0 ); - assert( !db->mallocFailed ); + /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */ assert( sqlite3_mutex_held(db->mutex) ); /* Check to verify that it is possible to get a read lock on all From 8498f387be1e02e4053c4bf5dcf4ded8a7103484 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 23 Jan 2016 14:45:36 +0000 Subject: [PATCH 149/570] Fix a problem involving detail=col and column filters. FossilOrigin-Name: 7558a0ad2276e91f2faced8ea405d9fdb4fa0c6e --- ext/fts5/fts5_index.c | 14 ++++++++++---- manifest | 15 ++++++--------- manifest.uuid | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 2ea57b04f9..8323842dc6 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -5013,21 +5013,26 @@ static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){ assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); assert( pColset ); - if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf && 0 ){ + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ /* All data is stored on the current page. Populate the output ** variables to point into the body of the page object. */ Fts5PoslistWriter writer = {0}; const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset]; int n = pSeg->nPos; int iCol = 0; + int iCVal = pColset->aiCol[0]; i64 iPos = 0; int iOff = 0; fts5BufferZero(&pIter->poslist); while( 0==sqlite3Fts5PoslistNext64(a, n, &iOff, &iPos) ){ - if( iPos==pColset->aiCol[iCol] ){ - sqlite3Fts5PoslistWriterAppend(&pIter->poslist, &writer, iPos); - if( ++iCol>=pColset->nCol ) break; + while( iPos>=iCVal ){ + if( iPos==iCVal ){ + sqlite3Fts5PoslistWriterAppend(&pIter->poslist, &writer, iPos); + } + if( ++iCol>=pColset->nCol ) goto setoutputs_col_out; + assert( pColset->aiCol[iCol]>iCVal ); + iCVal = pColset->aiCol[iCol]; } } @@ -5039,6 +5044,7 @@ static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){ fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); } +setoutputs_col_out: pIter->base.pData = pIter->poslist.p; pIter->base.nData = pIter->poslist.n; } diff --git a/manifest b/manifest index 99a9a8b139..0168850d28 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Experimental\sperformance\senhancements\sfor\sfts5. -D 2016-01-22T19:48:34.825 +C Fix\sa\sproblem\sinvolving\sdetail=col\sand\scolumn\sfilters. +D 2016-01-23T14:45:36.706 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc d2b93511a969c0c8fcf52aeb5e426571e8c610d2 @@ -103,7 +103,7 @@ F ext/fts5/fts5_buffer.c 7d3f6f01f8fdc45204e6a33925ef8478a67d28dd F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 F ext/fts5/fts5_expr.c 48b9131b74c8d3b8c12ba0f7995e2d60eecce9f2 F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c 19062d1f40ba6d88d786a986d1c20f9d741799d0 +F ext/fts5/fts5_index.c bd5476edd4d6ef37fc389794a78f47f29f521634 F ext/fts5/fts5_main.c 833db0a3df10ab26e0221a9baa40cf871c450df3 F ext/fts5/fts5_storage.c fb2eaec3aa954b680d43096dc539f8270bd6390e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -1419,10 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7323175337b7ba85ac932ca892b28860f6a5b688 -R bc65520844365f59e43048a22901b688 -T *branch * fts5-perf -T *sym-fts5-perf * -T -sym-trunk * +P b5a57b812fd6a734cf2a342bf0b730ae18912d73 +R 20bdd3799e5ba562672d44f9df7f8c2a U dan -Z 20f25a74d681d80924173ee060583d9e +Z fc938fd5a5718db0c9c10bacac344b80 diff --git a/manifest.uuid b/manifest.uuid index fc3a1227d6..7a9fdf27eb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b5a57b812fd6a734cf2a342bf0b730ae18912d73 \ No newline at end of file +7558a0ad2276e91f2faced8ea405d9fdb4fa0c6e \ No newline at end of file From c66d03f1e13e8f1746e063d642480cd951d4ca44 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 23 Jan 2016 15:57:06 +0000 Subject: [PATCH 150/570] Fix some signed/unsigned comparison compiler warnings in fts5. FossilOrigin-Name: 3be336aa893f9eb0837d7d66c83bab1489792b9a --- ext/fts5/fts5Int.h | 6 +++--- ext/fts5/fts5_buffer.c | 2 +- manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index b2f0d6c34e..5d7facc948 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -225,8 +225,8 @@ int sqlite3Fts5ConfigParseRank(const char*, char**, char**); typedef struct Fts5Buffer Fts5Buffer; struct Fts5Buffer { u8 *p; - u32 n; - u32 nSpace; + int n; + int nSpace; }; int sqlite3Fts5BufferSize(int*, Fts5Buffer*, u32); @@ -247,7 +247,7 @@ char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...); #define fts5BufferSet(a,b,c,d) sqlite3Fts5BufferSet(a,b,c,d) #define fts5BufferGrow(pRc,pBuf,nn) ( \ - (pBuf)->n + (nn) <= (pBuf)->nSpace ? 0 : \ + (u32)((pBuf)->n) + (u32)(nn) <= (u32)((pBuf)->nSpace) ? 0 : \ sqlite3Fts5BufferSize((pRc),(pBuf),(nn)+(pBuf)->n) \ ) diff --git a/ext/fts5/fts5_buffer.c b/ext/fts5/fts5_buffer.c index 94591188d3..9bd4fddb82 100644 --- a/ext/fts5/fts5_buffer.c +++ b/ext/fts5/fts5_buffer.c @@ -363,7 +363,7 @@ int sqlite3Fts5TermsetAdd( void sqlite3Fts5TermsetFree(Fts5Termset *p){ if( p ){ - int i; + u32 i; for(i=0; iapHash); i++){ Fts5TermsetEntry *pEntry = p->apHash[i]; while( pEntry ){ diff --git a/manifest b/manifest index 7b54ea0ab0..9f8ab447a0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sassert()\sthat\scan\sbe\sfalse\sif\scompiled\swith\sSQLITE_USE_ALLOCA. -D 2016-01-23T14:05:27.109 +C Fix\ssome\ssigned/unsigned\scomparison\scompiler\swarnings\sin\sfts5. +D 2016-01-23T15:57:06.186 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -97,9 +97,9 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 -F ext/fts5/fts5Int.h 5599703af9c13512900a9f22fec39d48078d619d +F ext/fts5/fts5Int.h e4c7ca41a7841f180d78a24850757e0ffcb20f27 F ext/fts5/fts5_aux.c 2dafc3aee0c70d643140c77d8d70daffa51a9e9e -F ext/fts5/fts5_buffer.c 7d3f6f01f8fdc45204e6a33925ef8478a67d28dd +F ext/fts5/fts5_buffer.c 0b8e1f84fec3ec01f7e17f8d4f17c46856b31e10 F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 F ext/fts5/fts5_expr.c 4ab4504c54bbe24689c83411d8588f4ec99136e9 F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a79c46bc61a35edbaf6112c26e8052314b0eb16a -R 78c84a447f1adb3672b2aa032cc33ea6 -U drh -Z 2d3baf83036e6553ecd28fa4c13c4bc2 +P f0a551edf87ef061deae34d88b02c3b484ae9adc +R 962289f1674397e1ac71fafb409f527f +U dan +Z 5f630552e065d9e5a5f7f6919a0222d3 diff --git a/manifest.uuid b/manifest.uuid index d11f7b73ef..e3c087f5fd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f0a551edf87ef061deae34d88b02c3b484ae9adc \ No newline at end of file +3be336aa893f9eb0837d7d66c83bab1489792b9a \ No newline at end of file From c6aab321441e0ce3eefa2a2ace0864cbca116231 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Jan 2016 18:24:52 +0000 Subject: [PATCH 151/570] Changes to spellfix to try to get it to use stack space instead of heap space in cases where that makes sense. FossilOrigin-Name: dfcebc7393a3a780ee9c4f257723c303bb633064 --- ext/misc/spellfix.c | 17 +++++++++++++---- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/ext/misc/spellfix.c b/ext/misc/spellfix.c index c0da6b339b..d17a05a3cd 100644 --- a/ext/misc/spellfix.c +++ b/ext/misc/spellfix.c @@ -365,8 +365,8 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){ int *m; /* The cost matrix */ char *cx; /* Corresponding character values */ int *toFree = 0; /* Malloced space */ - int mStack[60+15]; /* Stack space to use if not too much is needed */ int nMatch = 0; + int mStack[60+15]; /* Stack space to use if not too much is needed */ /* Early out if either input is NULL */ if( zA==0 || zB==0 ) return -1; @@ -899,15 +899,24 @@ static int editDist3Core( EditDist3FromString f = *pFrom; EditDist3To *a2; unsigned int *m; + unsigned int *pToFree; int szRow; EditDist3Cost *p; int res; + sqlite3_uint64 nByte; + unsigned int stackSpace[16*1024]; /* allocate the Wagner matrix and the aTo[] array for the TO string */ n = (f.n+1)*(n2+1); n = (n+1)&~1; - m = sqlite3_malloc( n*sizeof(m[0]) + sizeof(a2[0])*n2 ); - if( m==0 ) return -1; /* Out of memory */ + nByte = n*sizeof(m[0]) + sizeof(a2[0])*n2; + if( nByte<=sizeof(stackSpace) ){ + m = stackSpace; + pToFree = 0; + }else{ + m = pToFree = sqlite3_malloc( nByte ); + if( m==0 ) return -1; /* Out of memory */ + } a2 = (EditDist3To*)&m[n]; memset(a2, 0, sizeof(a2[0])*n2); @@ -1029,7 +1038,7 @@ static int editDist3Core( editDist3Abort: for(i2=0; i2 Date: Sat, 23 Jan 2016 18:51:59 +0000 Subject: [PATCH 152/570] Fix an fts5 problem with using both xPhraseFirst() and xPhraseFirstColumn() within a single statement in detail=col mode. FossilOrigin-Name: 72d53699bf0dcdb9d2a22e229989d7435f061399 --- ext/fts5/fts5Int.h | 6 +-- ext/fts5/fts5_aux.c | 2 +- ext/fts5/fts5_buffer.c | 4 +- ext/fts5/fts5_expr.c | 79 +++++++++++---------------------- ext/fts5/fts5_index.c | 79 --------------------------------- ext/fts5/fts5_main.c | 4 +- ext/fts5/fts5_storage.c | 2 +- ext/fts5/fts5_tokenize.c | 2 +- ext/fts5/fts5_vocab.c | 3 +- ext/fts5/test/fts5_common.tcl | 3 +- ext/fts5/test/fts5synonym2.test | 37 ++++++++++++++- manifest | 32 ++++++------- manifest.uuid | 2 +- 13 files changed, 90 insertions(+), 165 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index b8486dfdfb..48ab980921 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -29,7 +29,7 @@ typedef unsigned short u16; typedef sqlite3_int64 i64; typedef sqlite3_uint64 u64; -#define ArraySize(x) (sizeof(x) / sizeof(x[0])) +#define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) #define testcase(x) #define ALWAYS(x) 1 @@ -388,8 +388,6 @@ int sqlite3Fts5IterEof(Fts5IndexIter*); int sqlite3Fts5IterNext(Fts5IndexIter*); int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch); i64 sqlite3Fts5IterRowid(Fts5IndexIter*); -int sqlite3Fts5IterPoslist(Fts5IndexIter*,Fts5Colset*, const u8**, int*, i64*); -int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf); /* ** Close an iterator opened by sqlite3Fts5IndexQuery(). @@ -402,8 +400,6 @@ void sqlite3Fts5IterClose(Fts5IndexIter*); const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*); int sqlite3Fts5IterNextScan(Fts5IndexIter*); -int sqlite3Fts5IterCollist(Fts5IndexIter*, const u8 **, int*); - /* ** Insert or remove data to or from the index. Each time a document is diff --git a/ext/fts5/fts5_aux.c b/ext/fts5/fts5_aux.c index 011064d405..79bed1c8f7 100644 --- a/ext/fts5/fts5_aux.c +++ b/ext/fts5/fts5_aux.c @@ -544,7 +544,7 @@ int sqlite3Fts5AuxInit(fts5_api *pApi){ int rc = SQLITE_OK; /* Return code */ int i; /* To iterate through builtin functions */ - for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){ + for(i=0; rc==SQLITE_OK && ixCreateFunction(pApi, aBuiltin[i].zFunc, aBuiltin[i].pUserData, diff --git a/ext/fts5/fts5_buffer.c b/ext/fts5/fts5_buffer.c index 9bd4fddb82..d69adf7d24 100644 --- a/ext/fts5/fts5_buffer.c +++ b/ext/fts5/fts5_buffer.c @@ -322,7 +322,7 @@ int sqlite3Fts5TermsetAdd( *pbPresent = 0; if( p ){ int i; - int hash = 13; + u32 hash = 13; Fts5TermsetEntry *pEntry; /* Calculate a hash value for this term. This is the same hash checksum @@ -339,7 +339,7 @@ int sqlite3Fts5TermsetAdd( if( pEntry->iIdx==iIdx && pEntry->nTerm==nTerm && memcmp(pEntry->pTerm, pTerm, nTerm)==0 - ){ + ){ *pbPresent = 1; break; } diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index 290baf4e2c..3a1497f05d 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -306,7 +306,7 @@ static int fts5ExprSynonymList( int bCollist, Fts5Colset *pColset, i64 iRowid, - int *pbDel, /* OUT: Caller should sqlite3_free(*pa) */ + Fts5Buffer *pBuf, /* Use this buffer for space if required */ u8 **pa, int *pn ){ Fts5PoslistReader aStatic[4]; @@ -320,22 +320,7 @@ static int fts5ExprSynonymList( for(p=pTerm; p; p=p->pSynonym){ Fts5IndexIter *pIter = p->pIter; if( sqlite3Fts5IterEof(pIter)==0 && sqlite3Fts5IterRowid(pIter)==iRowid ){ - const u8 *a; - int n; - - if( 0 && bCollist ){ - rc = sqlite3Fts5IterCollist(pIter, &a, &n); - }else{ - i64 dummy; -#if 0 - rc = sqlite3Fts5IterPoslist(pIter, pColset, &a, &n, &dummy); -#endif - a = pIter->pData; - n = pIter->nData; - } - - if( rc!=SQLITE_OK ) goto synonym_poslist_out; - if( n==0 ) continue; + if( pIter->nData==0 ) continue; if( nIter==nAlloc ){ int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2; Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte); @@ -348,20 +333,19 @@ static int fts5ExprSynonymList( if( aIter!=aStatic ) sqlite3_free(aIter); aIter = aNew; } - sqlite3Fts5PoslistReaderInit(a, n, &aIter[nIter]); + sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &aIter[nIter]); assert( aIter[nIter].bEof==0 ); nIter++; } } - assert( *pbDel==0 ); if( nIter==1 ){ *pa = (u8*)aIter[0].a; *pn = aIter[0].n; }else{ Fts5PoslistWriter writer = {0}; - Fts5Buffer buf = {0,0,0}; i64 iPrev = -1; + fts5BufferZero(pBuf); while( 1 ){ int i; i64 iMin = FTS5_LARGEST_INT64; @@ -376,15 +360,12 @@ static int fts5ExprSynonymList( } } if( iMin==FTS5_LARGEST_INT64 || rc!=SQLITE_OK ) break; - rc = sqlite3Fts5PoslistWriterAppend(&buf, &writer, iMin); + rc = sqlite3Fts5PoslistWriterAppend(pBuf, &writer, iMin); iPrev = iMin; } - if( rc ){ - sqlite3_free(buf.p); - }else{ - *pa = buf.p; - *pn = buf.n; - *pbDel = 1; + if( rc==SQLITE_OK ){ + *pa = pBuf->p; + *pn = pBuf->n; } } @@ -421,7 +402,7 @@ static int fts5ExprPhraseIsMatch( /* If the aStatic[] array is not large enough, allocate a large array ** using sqlite3_malloc(). This approach could be improved upon. */ - if( pPhrase->nTerm>(int)ArraySize(aStatic) ){ + if( pPhrase->nTerm>ArraySize(aStatic) ){ int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm; aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte); if( !aIter ) return SQLITE_NOMEM; @@ -431,23 +412,23 @@ static int fts5ExprPhraseIsMatch( /* Initialize a term iterator for each term in the phrase */ for(i=0; inTerm; i++){ Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; - i64 dummy; int n = 0; int bFlag = 0; - const u8 *a = 0; + u8 *a = 0; if( pTerm->pSynonym ){ + Fts5Buffer buf = {0, 0, 0}; rc = fts5ExprSynonymList( - pTerm, 0, pColset, pNode->iRowid, &bFlag, (u8**)&a, &n + pTerm, 0, pColset, pNode->iRowid, &buf, &a, &n ); + if( rc ){ + sqlite3_free(a); + goto ismatch_out; + } + if( a==buf.p ) bFlag = 1; }else{ - Fts5IndexIter *pIter = pTerm->pIter; -#if 0 - rc = sqlite3Fts5IterPoslist(pTerm->pIter, pColset, &a, &n, &dummy); -#endif - a = pIter->pData; - n = pIter->nData; + a = (u8*)pTerm->pIter->pData; + n = pTerm->pIter->nData; } - if( rc!=SQLITE_OK ) goto ismatch_out; sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]); aIter[i].bFlag = (u8)bFlag; if( aIter[i].bEof ) goto ismatch_out; @@ -562,7 +543,7 @@ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){ /* If the aStatic[] array is not large enough, allocate a large array ** using sqlite3_malloc(). This approach could be improved upon. */ - if( pNear->nPhrase>(int)ArraySize(aStatic) ){ + if( pNear->nPhrase>ArraySize(aStatic) ){ int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase; a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte); }else{ @@ -1387,10 +1368,10 @@ static void fts5ExprPhraseFree(Fts5ExprPhrase *pPhrase){ Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; sqlite3_free(pTerm->zTerm); sqlite3Fts5IterClose(pTerm->pIter); - for(pSyn=pTerm->pSynonym; pSyn; pSyn=pNext){ pNext = pSyn->pSynonym; sqlite3Fts5IterClose(pSyn->pIter); + fts5BufferFree((Fts5Buffer*)&pSyn[1]); sqlite3_free(pSyn); } } @@ -1478,13 +1459,13 @@ static int fts5ParseTokenize( assert( pPhrase==0 || pPhrase->nTerm>0 ); if( pPhrase && (tflags & FTS5_TOKEN_COLOCATED) ){ Fts5ExprTerm *pSyn; - int nByte = sizeof(Fts5ExprTerm) + nToken+1; + int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1; pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte); if( pSyn==0 ){ rc = SQLITE_NOMEM; }else{ memset(pSyn, 0, nByte); - pSyn->zTerm = (char*)&pSyn[1]; + pSyn->zTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer); memcpy(pSyn->zTerm, pToken, nToken); pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym; pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn; @@ -2263,7 +2244,7 @@ int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){ int rc = SQLITE_OK; void *pCtx = (void*)pGlobal; - for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aFunc); i++){ + for(i=0; rc==SQLITE_OK && iz, -1, SQLITE_UTF8, pCtx, p->x, 0, 0); } @@ -2509,18 +2490,10 @@ int sqlite3Fts5ExprPhraseCollist( ){ Fts5ExprTerm *pTerm = &pPhrase->aTerm[0]; if( pTerm->pSynonym ){ - int bDel = 0; - u8 *a; + Fts5Buffer *pBuf = (Fts5Buffer*)&pTerm->pSynonym[1]; rc = fts5ExprSynonymList( - pTerm, 1, 0, pNode->iRowid, &bDel, &a, pnCollist + pTerm, 1, 0, pNode->iRowid, pBuf, (u8**)ppCollist, pnCollist ); - if( bDel ){ - sqlite3Fts5BufferSet(&rc, &pPhrase->poslist, *pnCollist, a); - *ppCollist = pPhrase->poslist.p; - sqlite3_free(a); - }else{ - *ppCollist = a; - } }else{ *ppCollist = pPhrase->aTerm[0].pIter->pData; *pnCollist = pPhrase->aTerm[0].pIter->nData; diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 8323842dc6..e147199ef8 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -5249,85 +5249,6 @@ const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){ return &z[1]; } - -/* -** Return a pointer to a buffer containing a copy of the position list for -** the current entry. Output variable *pn is set to the size of the buffer -** in bytes before returning. -** -** The returned position list does not include the "number of bytes" varint -** field that starts the position list on disk. -*/ -int sqlite3Fts5IterPoslist( - Fts5IndexIter *pIndexIter, - Fts5Colset *pColset, /* Column filter (or NULL) */ - const u8 **pp, /* OUT: Pointer to position-list data */ - int *pn, /* OUT: Size of position-list in bytes */ - i64 *piRowid /* OUT: Current rowid */ -){ - Fts5Iter *pIter = (Fts5Iter*)pIndexIter; - Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; - int eDetail = pIter->pIndex->pConfig->eDetail; - - assert( pIter->pIndex->rc==SQLITE_OK ); - *piRowid = pSeg->iRowid; - if( eDetail==FTS5_DETAIL_NONE ){ - *pn = pSeg->nPos; - }else - if( eDetail==FTS5_DETAIL_FULL - && pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf - ){ - u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset]; - if( pColset==0 || pIter->bFiltered ){ - *pn = pSeg->nPos; - *pp = pPos; - }else if( pColset->nCol==1 ){ - *pp = pPos; - *pn = fts5IndexExtractCol(pp, pSeg->nPos, pColset->aiCol[0]); - }else{ - fts5BufferZero(&pIter->poslist); - fts5IndexExtractColset(pColset, pPos, pSeg->nPos, &pIter->poslist); - *pp = pIter->poslist.p; - *pn = pIter->poslist.n; - } - }else{ - fts5BufferZero(&pIter->poslist); - fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); - if( eDetail==FTS5_DETAIL_FULL ){ - *pp = pIter->poslist.p; - } - *pn = pIter->poslist.n; - } - return fts5IndexReturn(pIter->pIndex); -} - -int sqlite3Fts5IterCollist( - Fts5IndexIter *pIndexIter, - const u8 **pp, /* OUT: Pointer to position-list data */ - int *pn /* OUT: Size of position-list in bytes */ -){ - Fts5Iter *pIter = (Fts5Iter*)pIndexIter; - assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); - *pp = pIter->poslist.p; - *pn = pIter->poslist.n; - return SQLITE_OK; -} - -/* -** This function is similar to sqlite3Fts5IterPoslist(), except that it -** copies the position list into the buffer supplied as the second -** argument. -*/ -int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIndexIter, Fts5Buffer *pBuf){ - Fts5Iter *pIter = (Fts5Iter*)pIndexIter; - Fts5Index *p = pIter->pIndex; - Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; - assert( p->rc==SQLITE_OK ); - fts5BufferZero(pBuf); - fts5SegiterPoslist(p, pSeg, 0, pBuf); - return fts5IndexReturn(p); -} - /* ** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery(). */ diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index 7447f9b5e1..ec045da6bf 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -538,7 +538,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ for(i=0; inConstraint; i++){ struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; int j; - for(j=0; j<(int)ArraySize(aConstraint); j++){ + for(j=0; jiColumn==aColMap[pC->iCol] && p->op & pC->op ){ if( p->usable ){ @@ -585,7 +585,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ /* Assign argvIndex values to each constraint in use. */ iNext = 1; - for(i=0; i<(int)ArraySize(aConstraint); i++){ + for(i=0; iiConsIndex>=0 ){ pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++; diff --git a/ext/fts5/fts5_storage.c b/ext/fts5/fts5_storage.c index 56383619d1..da9524dea3 100644 --- a/ext/fts5/fts5_storage.c +++ b/ext/fts5/fts5_storage.c @@ -338,7 +338,7 @@ int sqlite3Fts5StorageClose(Fts5Storage *p){ int i; /* Finalize all SQL statements */ - for(i=0; i<(int)ArraySize(p->aStmt); i++){ + for(i=0; iaStmt); i++){ sqlite3_finalize(p->aStmt[i]); } diff --git a/ext/fts5/fts5_tokenize.c b/ext/fts5/fts5_tokenize.c index e60183c095..790adaae47 100644 --- a/ext/fts5/fts5_tokenize.c +++ b/ext/fts5/fts5_tokenize.c @@ -1220,7 +1220,7 @@ int sqlite3Fts5TokenizerInit(fts5_api *pApi){ int rc = SQLITE_OK; /* Return code */ int i; /* To iterate through builtin functions */ - for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){ + for(i=0; rc==SQLITE_OK && ixCreateTokenizer(pApi, aBuiltin[i].zName, (void*)pApi, diff --git a/ext/fts5/fts5_vocab.c b/ext/fts5/fts5_vocab.c index 17aa5816c4..b17e8974fb 100644 --- a/ext/fts5/fts5_vocab.c +++ b/ext/fts5/fts5_vocab.c @@ -184,7 +184,7 @@ static int fts5VocabInitVtab( rc = fts5VocabTableType(zType, pzErr, &eType); if( rc==SQLITE_OK ){ - assert( eType>=0 && eType=0 && eTypeeType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); while( rc==SQLITE_OK ){ - i64 dummy; const u8 *pPos; int nPos; /* Position list */ i64 iPos = 0; /* 64-bit position read from poslist */ int iOff = 0; /* Current offset within position list */ diff --git a/ext/fts5/test/fts5_common.tcl b/ext/fts5/test/fts5_common.tcl index e7c61af00c..cf688dcc0d 100644 --- a/ext/fts5/test/fts5_common.tcl +++ b/ext/fts5/test/fts5_common.tcl @@ -48,7 +48,8 @@ proc fts5_test_poslist2 {cmd} { } } - set res + #set res + sort_poslist $res } proc fts5_test_collist {cmd} { diff --git a/ext/fts5/test/fts5synonym2.test b/ext/fts5/test/fts5synonym2.test index dddaa17af8..7e92822c33 100644 --- a/ext/fts5/test/fts5synonym2.test +++ b/ext/fts5/test/fts5synonym2.test @@ -27,6 +27,21 @@ foreach_detail_mode $testprefix { fts5_tclnum_register db fts5_aux_test_functions db +proc fts5_test_bothlist {cmd} { + + for {set i 0} {$i < [$cmd xPhraseCount]} {incr i} { + set bFirst 1 + $cmd xPhraseColumnForeach $i c { + lappend CL $i.$c + if {$bFirst} { $cmd xPhraseForeach $i c o { lappend PL $i.$c.$o } } + set bFirst 0 + } + } + + list [sort_poslist $PL] $CL +} +sqlite3_fts5_create_function db fts5_test_bothlist fts5_test_bothlist + proc fts5_rowid {cmd} { expr [$cmd xColumnText -1] } sqlite3_fts5_create_function db fts5_rowid fts5_rowid @@ -89,6 +104,8 @@ do_execsql_test 1.$tok.0.2 { } foreach {tn expr} { + 2.1 "one OR two OR three OR four" + 1.1 "one" 1.2 "two" 1.3 "three" 1.4 "four" 1.5 "v" 1.6 "vi" 1.7 "vii" 1.8 "viii" 1.9 "9" 1.10 "0" 1.11 "1" 1.12 "2" @@ -113,13 +130,31 @@ foreach {tn expr} { set res [fts5_query_data $expr ss ASC ::tclnum_syn] do_execsql_test 1.$tok.$tn.[llength $res].asc.1 { - SELECT rowid, fts5_test_poslist(ss), fts5_test_collist(ss) FROM ss($expr) + SELECT rowid, fts5_test_poslist2(ss), fts5_test_collist(ss) FROM ss($expr) } $res do_execsql_test 1.$tok.$tn.[llength $res].asc.2 { SELECT rowid, fts5_test_poslist(ss), fts5_test_collist(ss) FROM ss($expr) + } $res + + do_execsql_test 1.$tok.$tn.[llength $res].asc.2 { + SELECT rowid, fts5_test_poslist2(ss), fts5_test_collist(ss) FROM ss($expr) ORDER BY rank ASC } $res + + set res2 [list] + foreach {a b c} $res { lappend res2 $a $c $b } + do_execsql_test 1.$tok.$tn.[llength $res].asc.3 { + SELECT rowid, fts5_test_collist(ss), fts5_test_poslist2(ss) FROM ss($expr) + } $res2 + + set res3 [list] + foreach {a b c} $res { lappend res3 $a [list $b $c] } + do_execsql_test 1.$tok.$tn.[llength $res].asc.3 { + SELECT rowid, fts5_test_bothlist(ss) FROM ss($expr) + } $res3 + + } } diff --git a/manifest b/manifest index e3a6b78f3f..fbcb4d2d1b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\strunk\schanges\s(including\sfixes\sfor\swarnings\sin\sfts5)\swith\sthis\sbranch. -D 2016-01-23T16:20:16.389 +C Fix\san\sfts5\sproblem\swith\susing\sboth\sxPhraseFirst()\sand\sxPhraseFirstColumn()\swithin\sa\ssingle\sstatement\sin\sdetail=col\smode. +D 2016-01-23T18:51:59.865 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -97,25 +97,25 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 -F ext/fts5/fts5Int.h a810589cf2fedd7dcfc9ba7871d2a5a09e850ace -F ext/fts5/fts5_aux.c 2dafc3aee0c70d643140c77d8d70daffa51a9e9e -F ext/fts5/fts5_buffer.c 0b8e1f84fec3ec01f7e17f8d4f17c46856b31e10 +F ext/fts5/fts5Int.h 6e0f90eb4872654a5b98130dec16965716525c9a +F ext/fts5/fts5_aux.c b9bcce753ef5b451267b2232f0ca153ddeb3951d +F ext/fts5/fts5_buffer.c f6e0c6018ffc8e39fc0b333b5daa8b8d528ae6e4 F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 -F ext/fts5/fts5_expr.c 48b9131b74c8d3b8c12ba0f7995e2d60eecce9f2 +F ext/fts5/fts5_expr.c a66b9694519d9c336d9bdbd46ea22e7e14aef412 F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c bd5476edd4d6ef37fc389794a78f47f29f521634 -F ext/fts5/fts5_main.c 833db0a3df10ab26e0221a9baa40cf871c450df3 -F ext/fts5/fts5_storage.c fb2eaec3aa954b680d43096dc539f8270bd6390e +F ext/fts5/fts5_index.c 722d8717e3167dd05fa48af970352932052da318 +F ext/fts5/fts5_main.c 3886bbfc5ac1d9df29979823ddf2b68241e1127e +F ext/fts5/fts5_storage.c 2a1f44deae090cd711f02cec0c2af8e660360d24 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 F ext/fts5/fts5_test_mi.c 1ec66ffdf7632077fbd773b7a6df5153272ec070 F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be -F ext/fts5/fts5_tokenize.c 504984ac6993323247221eebe3cd55bead01b5f8 +F ext/fts5/fts5_tokenize.c 4d5c4f183c7d07d144bc219b92da1ea0e962fae3 F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1 -F ext/fts5/fts5_vocab.c f1b4308b9b7ec8e659d0c9b39ddc8f1aeee47a1a +F ext/fts5/fts5_vocab.c 3ef401a8d6932db56368de32f446eb9fe73aa623 F ext/fts5/fts5parse.y 1647eba089b9b3fc058b4dc989d9da87d15b9580 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba -F ext/fts5/test/fts5_common.tcl 6d0d74b695c4be055a8ba1dd807f22a2abc95b5e +F ext/fts5/test/fts5_common.tcl 61ff0d1a29d98a91c4553b20b3f410d858834ee9 F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b F ext/fts5/test/fts5ac.test dec95549e007dd9be52aa435cdcd0f08e14e64d0 @@ -177,7 +177,7 @@ F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6 F ext/fts5/test/fts5simple.test 2bc6451cbe887a9215f5b14ae307c70d850344c9 F ext/fts5/test/fts5simple2.test 98377ae1ff7749a42c21fe1a139c1ed312522c46 F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48 -F ext/fts5/test/fts5synonym2.test eadb00c73ef0653258873e756b7e9102e0687539 +F ext/fts5/test/fts5synonym2.test aa4c43bd3b691ff80f658cb064f5ab40690e834e F ext/fts5/test/fts5tok1.test beb894c6f3468f10a574302f69ebe4436b0287c7 F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2 F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89 @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7558a0ad2276e91f2faced8ea405d9fdb4fa0c6e 3be336aa893f9eb0837d7d66c83bab1489792b9a -R 27b07c29574081bf2a6f1649bb5e2393 +P ceccc9ad788fb4da9120915741995b9f088f85ff +R e7d7753020b6f70b109a92a8ac037ba7 U dan -Z 165b70c16fc218fdaf7b93acd8863bd2 +Z 648645363fb131dd10e5d7321a173b9d diff --git a/manifest.uuid b/manifest.uuid index 3e212691ce..1891619c18 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ceccc9ad788fb4da9120915741995b9f088f85ff \ No newline at end of file +72d53699bf0dcdb9d2a22e229989d7435f061399 \ No newline at end of file From 408273e722fbff04e6f02960060529cd85ba772e Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sat, 23 Jan 2016 19:24:19 +0000 Subject: [PATCH 153/570] Use the -integer option when sorting list elements. FossilOrigin-Name: 949aa614e1401f6ab61cbb2e0469c60d764e6880 --- manifest | 15 ++++++--------- manifest.uuid | 2 +- tool/mkmsvcmin.tcl | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 12db615b93..d24047ded1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stooling\sto\screate\san\sMSVC\sMakefile\scapable\sof\sbuilding\sthe\score\slibrary\sand\sshell\sonly,\susing\sa\spre-built\samalgamation. -D 2016-01-23T07:53:04.796 +C Use\sthe\s-integer\soption\swhen\ssorting\slist\selements. +D 2016-01-23T19:24:19.182 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.min.msc c805e4a474fc7610d4f0cd0b6a9f56334a14c6ad @@ -1379,7 +1379,7 @@ F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh 5a5441280b509d2bb3bdc71bfb63781b0d570373 F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8 -F tool/mkmsvcmin.tcl 859737ff14668827738a3f7ca17ba643a88bcecc +F tool/mkmsvcmin.tcl a0217f49042ec8160ff8665db638e9b5edc17964 F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e @@ -1421,10 +1421,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a79c46bc61a35edbaf6112c26e8052314b0eb16a -R bd00cfb25453f633191b5f1755909575 -T *branch * msvcMakeMin -T *sym-msvcMakeMin * -T -sym-trunk * +P c46f1a13cb00264d1164399059250884c7be4ea0 +R ce47a7131ea57ef586dba1d328c21253 U mistachkin -Z 18f99743dd26f3a3f31830457ad1b4ef +Z c9f6cfce5ff80db91258ef2b40e34be6 diff --git a/manifest.uuid b/manifest.uuid index 06bbe8845c..0c60eb81fc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c46f1a13cb00264d1164399059250884c7be4ea0 \ No newline at end of file +949aa614e1401f6ab61cbb2e0469c60d764e6880 \ No newline at end of file diff --git a/tool/mkmsvcmin.tcl b/tool/mkmsvcmin.tcl index 56c9d52811..188b73a18e 100644 --- a/tool/mkmsvcmin.tcl +++ b/tool/mkmsvcmin.tcl @@ -73,7 +73,7 @@ set data [readFile $fromFileName] regsub -all -- {# <>\n.*?# <>\n} \ $data "" data -foreach i [lsort [array names blocks]] { +foreach i [lsort -integer [array names blocks]] { regsub -all -- [substVars \ {# <>\n.*?# <>\n}] \ $data [escapeSubSpec $blocks($i)] data From 06cee48728424701260e2f3215ad75c257bace44 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Jan 2016 19:47:00 +0000 Subject: [PATCH 154/570] Improved comments on the transformation script and on the generated Makefile. FossilOrigin-Name: c6e633ab73812fe38f3e969f1652f1b5759096e4 --- Makefile.min.msc | 6 ++++++ manifest | 16 +++++++-------- manifest.uuid | 2 +- tool/mkmsvcmin.tcl | 51 +++++++++++++++++++++++++++------------------- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/Makefile.min.msc b/Makefile.min.msc index 2ec986fa4b..e2187efad3 100644 --- a/Makefile.min.msc +++ b/Makefile.min.msc @@ -1,3 +1,9 @@ +#### DO NOT EDIT #### +# This makefile is automatically generated from the Makefile.msc at +# the root of the canonical SQLite source tree using the +# tool/mkmsvcmin.tcl script. +# + # # nmake Makefile for SQLite # diff --git a/manifest b/manifest index d24047ded1..504f2ebbaf 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Use\sthe\s-integer\soption\swhen\ssorting\slist\selements. -D 2016-01-23T19:24:19.182 +C Improved\scomments\son\sthe\stransformation\sscript\sand\son\sthe\sgenerated\sMakefile. +D 2016-01-23T19:47:00.459 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.min.msc c805e4a474fc7610d4f0cd0b6a9f56334a14c6ad +F Makefile.min.msc cbbc5e37bfe74583cce7c2585319620b7516e6ed F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 @@ -1379,7 +1379,7 @@ F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh 5a5441280b509d2bb3bdc71bfb63781b0d570373 F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8 -F tool/mkmsvcmin.tcl a0217f49042ec8160ff8665db638e9b5edc17964 +F tool/mkmsvcmin.tcl a62d398d1304b36dd41b69e655d875728fd9d509 F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e @@ -1421,7 +1421,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c46f1a13cb00264d1164399059250884c7be4ea0 -R ce47a7131ea57ef586dba1d328c21253 -U mistachkin -Z c9f6cfce5ff80db91258ef2b40e34be6 +P 949aa614e1401f6ab61cbb2e0469c60d764e6880 +R 52e20c37d886e0ca572199fede1eb984 +U drh +Z 5f79d302a18d7c201b23ed73e75ff6ef diff --git a/manifest.uuid b/manifest.uuid index 0c60eb81fc..876d304c70 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -949aa614e1401f6ab61cbb2e0469c60d764e6880 \ No newline at end of file +c6e633ab73812fe38f3e969f1652f1b5759096e4 \ No newline at end of file diff --git a/tool/mkmsvcmin.tcl b/tool/mkmsvcmin.tcl index 188b73a18e..7414f53000 100644 --- a/tool/mkmsvcmin.tcl +++ b/tool/mkmsvcmin.tcl @@ -1,22 +1,26 @@ #!/usr/bin/tcl # -# Removes and/or replaces specially marked sections from the Makefile -# for MSVC, writing the resulting output to another (different) file. -# In addition, some other strings are also removed and/or replaced if -# they are present in the Makefile. -# -set fromFileName [lindex $argv 0] - -if {![file exists $fromFileName]} then { - error "input file \"$fromFileName\" does not exist" +# This script reads the regular MSVC makefile (../Makefile.msc) and outputs +# a revised version of that Makefile that is "minimal" in the sense that +# it uses the sqlite3.c amalgamation as input and does not require tclsh. +# The resulting "../Makefile.min.msc" is suitable for use in the amalgamation +# tarballs. +# +if {$argc==0} { + set basedir [file dir [file dir [file normalize $argv0]]] + set fromFileName [file join $basedir Makefile.msc] + set toFileName [file join $basedir Makefile.min.msc] +} else { + set fromFileName [lindex $argv 0] + if {![file exists $fromFileName]} then { + error "input file \"$fromFileName\" does not exist" + } + set toFileName [lindex $argv 1] + if {[file exists $toFileName]} then { + error "output file \"$toFileName\" already exists" + } } - -set toFileName [lindex $argv 1] -if {[file exists $toFileName]} then { - error "output file \"$toFileName\" already exists" -} - proc readFile { fileName } { set file_id [open $fileName RDONLY] fconfigure $file_id -encoding binary -translation binary @@ -24,7 +28,7 @@ proc readFile { fileName } { close $file_id return $result } - + proc writeFile { fileName data } { set file_id [open $fileName {WRONLY CREAT TRUNC}] fconfigure $file_id -encoding binary -translation binary @@ -32,17 +36,17 @@ proc writeFile { fileName data } { close $file_id return "" } - + proc escapeSubSpec { data } { regsub -all -- {&} $data {\\\&} data regsub -all -- {\\(\d+)} $data {\\\\\1} data return $data } - + proc substVars { data } { return [uplevel 1 [list subst -nocommands -nobackslashes $data]] } - + # # NOTE: This block is used to replace the section marked <> in # the Makefile, if it exists. @@ -67,8 +71,13 @@ $(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H) echo #endif >> sqlite3rc.h $(LTRCOMPILE) -fo $(LIBRESOBJS) -DRC_VERONLY $(TOP)\sqlite3.rc }]] - -set data [readFile $fromFileName] + +set data "#### DO NOT EDIT ####\n" +append data "# This makefile is automatically " +append data "generated from the [file tail $fromFileName] at\n" +append data "# the root of the canonical SQLite source tree using the\n" +append data "# tool/[file tail $argv0] script.\n#\n\n" +append data [readFile $fromFileName] regsub -all -- {# <>\n.*?# <>\n} \ $data "" data From ac779bcbe964611322cc9ad4e056e8220784b84a Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Jan 2016 20:09:30 +0000 Subject: [PATCH 155/570] Adjust the amalgamation-tarball build process so that it includes the MSVC makefile and the sqlite3.rc resource file. FossilOrigin-Name: e420f3dc93a0e3364f0773950b7a125f5221a109 --- autoconf/Makefile.am | 2 +- autoconf/{README => README.txt} | 5 ++++- manifest | 16 ++++++++-------- manifest.uuid | 2 +- tool/mkautoconfamal.sh | 17 +++++++++-------- 5 files changed, 23 insertions(+), 19 deletions(-) rename autoconf/{README => README.txt} (88%) diff --git a/autoconf/Makefile.am b/autoconf/Makefile.am index eed3ba41cb..03424a606b 100644 --- a/autoconf/Makefile.am +++ b/autoconf/Makefile.am @@ -14,7 +14,7 @@ sqlite3_CFLAGS = $(AM_CFLAGS) include_HEADERS = sqlite3.h sqlite3ext.h -EXTRA_DIST = sqlite3.1 tea +EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt pkgconfigdir = ${libdir}/pkgconfig pkgconfig_DATA = sqlite3.pc diff --git a/autoconf/README b/autoconf/README.txt similarity index 88% rename from autoconf/README rename to autoconf/README.txt index dd8cca24bd..731158a883 100644 --- a/autoconf/README +++ b/autoconf/README.txt @@ -1,4 +1,3 @@ - This package contains: * the SQLite library amalgamation (single file) source code distribution, @@ -6,6 +5,7 @@ This package contains: * the sqlite3.h and sqlite3ext.h header files required to link programs and sqlite extensions against the installed libary. * autoconf/automake installation infrastucture. + * a Makefile.msc and sqlite3.rc for Microsoft Visual C++ The generic installation instructions for autoconf/automake are found in the INSTALL file. @@ -30,3 +30,6 @@ example: $ CFLAGS="-Os -DSQLITE_OMIT_TRIGGERS" ./configure +To compile for Windows using Microsoft Visual C++: + + $ nmake /f Makefile.msc FOR_WIN10=1 diff --git a/manifest b/manifest index 504f2ebbaf..a6797b77e5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\scomments\son\sthe\stransformation\sscript\sand\son\sthe\sgenerated\sMakefile. -D 2016-01-23T19:47:00.459 +C Adjust\sthe\samalgamation-tarball\sbuild\sprocess\sso\sthat\sit\sincludes\sthe\nMSVC\smakefile\sand\sthe\ssqlite3.rc\sresource\sfile. +D 2016-01-23T20:09:30.205 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.min.msc cbbc5e37bfe74583cce7c2585319620b7516e6ed @@ -11,9 +11,9 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 -F autoconf/Makefile.am 089e5ecdb5761e64ea1013ded02feb4d8b29927d -F autoconf/README 14458f1046c118efa721aadec5f227e876d3cd38 +F autoconf/Makefile.am 1c1657650775960804945dc392e14d9e43c5ed84 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 +F autoconf/README.txt c9265657b6ca8c4de1e148e8c0c4c29d60ec860c w autoconf/README F autoconf/configure.ac 7b1ea0dcaf49fafba262ce4b0ee8cb3281b555d1 F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 @@ -1377,7 +1377,7 @@ F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 -F tool/mkautoconfamal.sh 5a5441280b509d2bb3bdc71bfb63781b0d570373 +F tool/mkautoconfamal.sh add1d703074e7edb2d8423441c7e245271c5c8cb F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8 F tool/mkmsvcmin.tcl a62d398d1304b36dd41b69e655d875728fd9d509 F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b @@ -1421,7 +1421,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 949aa614e1401f6ab61cbb2e0469c60d764e6880 -R 52e20c37d886e0ca572199fede1eb984 +P c6e633ab73812fe38f3e969f1652f1b5759096e4 +R d5543de9eede26dd90664aa004eef406 U drh -Z 5f79d302a18d7c201b23ed73e75ff6ef +Z 98c1051b769380596fbf89ccef90cc39 diff --git a/manifest.uuid b/manifest.uuid index 876d304c70..c32f479829 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c6e633ab73812fe38f3e969f1652f1b5759096e4 \ No newline at end of file +e420f3dc93a0e3364f0773950b7a125f5221a109 \ No newline at end of file diff --git a/tool/mkautoconfamal.sh b/tool/mkautoconfamal.sh index 9f44152e36..d368cd226b 100644 --- a/tool/mkautoconfamal.sh +++ b/tool/mkautoconfamal.sh @@ -34,14 +34,15 @@ set -e ARTIFACT=`printf "3%.2d%.2d%.2d" $xx $yy $zz` rm -rf $TMPSPACE -cp -R $TOP/autoconf $TMPSPACE - -cp sqlite3.c $TMPSPACE -cp sqlite3.h $TMPSPACE -cp sqlite3ext.h $TMPSPACE -cp $TOP/sqlite3.1 $TMPSPACE -cp $TOP/sqlite3.pc.in $TMPSPACE -cp $TOP/src/shell.c $TMPSPACE +cp -R $TOP/autoconf $TMPSPACE +cp sqlite3.c $TMPSPACE +cp sqlite3.h $TMPSPACE +cp sqlite3ext.h $TMPSPACE +cp $TOP/sqlite3.1 $TMPSPACE +cp $TOP/sqlite3.pc.in $TMPSPACE +cp $TOP/src/shell.c $TMPSPACE +cp $TOP/Makefile.min.msc $TMPSPACE/Makefile.msc +cp $TOP/src/sqlite3.rc $TMPSPACE cat $TMPSPACE/configure.ac | sed "s/--SQLITE-VERSION--/$VERSION/" > $TMPSPACE/tmp From 4a25549b087bd576ac413f88f5e2d654cd59e0b4 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sat, 23 Jan 2016 20:16:40 +0000 Subject: [PATCH 156/570] Minor coding style tweaks for the mkmsvcmin tool. FossilOrigin-Name: c15e0fc4be08b92547bea1f1cac65581ef497409 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- tool/mkmsvcmin.tcl | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index a6797b77e5..2076ff35e1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Adjust\sthe\samalgamation-tarball\sbuild\sprocess\sso\sthat\sit\sincludes\sthe\nMSVC\smakefile\sand\sthe\ssqlite3.rc\sresource\sfile. -D 2016-01-23T20:09:30.205 +C Minor\scoding\sstyle\stweaks\sfor\sthe\smkmsvcmin\stool. +D 2016-01-23T20:16:40.624 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.min.msc cbbc5e37bfe74583cce7c2585319620b7516e6ed @@ -13,7 +13,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 1c1657650775960804945dc392e14d9e43c5ed84 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 -F autoconf/README.txt c9265657b6ca8c4de1e148e8c0c4c29d60ec860c w autoconf/README +F autoconf/README.txt c9265657b6ca8c4de1e148e8c0c4c29d60ec860c F autoconf/configure.ac 7b1ea0dcaf49fafba262ce4b0ee8cb3281b555d1 F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 @@ -1379,7 +1379,7 @@ F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh add1d703074e7edb2d8423441c7e245271c5c8cb F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8 -F tool/mkmsvcmin.tcl a62d398d1304b36dd41b69e655d875728fd9d509 +F tool/mkmsvcmin.tcl c1f92b52505fe4a026e7b57fffe49b439b11b71b F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e @@ -1421,7 +1421,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c6e633ab73812fe38f3e969f1652f1b5759096e4 -R d5543de9eede26dd90664aa004eef406 -U drh -Z 98c1051b769380596fbf89ccef90cc39 +P e420f3dc93a0e3364f0773950b7a125f5221a109 +R 0e64448b1af0ccd7100284f6f222657e +U mistachkin +Z 38e3fbc9582e760d49d364916a96f186 diff --git a/manifest.uuid b/manifest.uuid index c32f479829..6bcba645b0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e420f3dc93a0e3364f0773950b7a125f5221a109 \ No newline at end of file +c15e0fc4be08b92547bea1f1cac65581ef497409 \ No newline at end of file diff --git a/tool/mkmsvcmin.tcl b/tool/mkmsvcmin.tcl index 7414f53000..d0143ddd86 100644 --- a/tool/mkmsvcmin.tcl +++ b/tool/mkmsvcmin.tcl @@ -5,18 +5,18 @@ # it uses the sqlite3.c amalgamation as input and does not require tclsh. # The resulting "../Makefile.min.msc" is suitable for use in the amalgamation # tarballs. -# +# if {$argc==0} { set basedir [file dir [file dir [file normalize $argv0]]] set fromFileName [file join $basedir Makefile.msc] set toFileName [file join $basedir Makefile.min.msc] } else { set fromFileName [lindex $argv 0] - if {![file exists $fromFileName]} then { + if {![file exists $fromFileName]} { error "input file \"$fromFileName\" does not exist" } set toFileName [lindex $argv 1] - if {[file exists $toFileName]} then { + if {[file exists $toFileName]} { error "output file \"$toFileName\" already exists" } } From 021f9a6605c2c1af96db9fd144c64749c5224751 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Jan 2016 20:34:27 +0000 Subject: [PATCH 157/570] Move Makefile.min.msc into the autoconf subdir where it belongs and change its name to Makefile.msc. Adjust build scripts accordingly. FossilOrigin-Name: 12eb8db79697ef55228c78011d275f36f58271e1 --- Makefile.min.msc => autoconf/Makefile.msc | 5 +++-- manifest | 18 +++++++++--------- manifest.uuid | 2 +- tool/mkautoconfamal.sh | 1 - tool/mkmsvcmin.tcl | 7 ++++--- 5 files changed, 17 insertions(+), 16 deletions(-) rename Makefile.min.msc => autoconf/Makefile.msc (99%) diff --git a/Makefile.min.msc b/autoconf/Makefile.msc similarity index 99% rename from Makefile.min.msc rename to autoconf/Makefile.msc index e2187efad3..fce62b2b8a 100644 --- a/Makefile.min.msc +++ b/autoconf/Makefile.msc @@ -1,7 +1,8 @@ #### DO NOT EDIT #### # This makefile is automatically generated from the Makefile.msc at -# the root of the canonical SQLite source tree using the -# tool/mkmsvcmin.tcl script. +# the root of the canonical SQLite source tree (not the +# amalgamation tarball) using the tool/mkmsvcmin.tcl +# script. # # diff --git a/manifest b/manifest index 2076ff35e1..9a914fa3d3 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,7 @@ -C Minor\scoding\sstyle\stweaks\sfor\sthe\smkmsvcmin\stool. -D 2016-01-23T20:16:40.624 +C Move\sMakefile.min.msc\sinto\sthe\sautoconf\ssubdir\swhere\sit\sbelongs\sand\schange\nits\sname\sto\sMakefile.msc.\s\sAdjust\sbuild\sscripts\saccordingly. +D 2016-01-23T20:34:27.088 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.min.msc cbbc5e37bfe74583cce7c2585319620b7516e6ed F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 @@ -12,6 +11,7 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 1c1657650775960804945dc392e14d9e43c5ed84 +F autoconf/Makefile.msc 68ed752a809b611d97b95d8572a34fe6fd1196f1 w Makefile.min.msc F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt c9265657b6ca8c4de1e148e8c0c4c29d60ec860c F autoconf/configure.ac 7b1ea0dcaf49fafba262ce4b0ee8cb3281b555d1 @@ -1377,9 +1377,9 @@ F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 -F tool/mkautoconfamal.sh add1d703074e7edb2d8423441c7e245271c5c8cb +F tool/mkautoconfamal.sh a29b14d54302b33fd892958f6895582ea90e4a45 F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8 -F tool/mkmsvcmin.tcl c1f92b52505fe4a026e7b57fffe49b439b11b71b +F tool/mkmsvcmin.tcl 93167a9e73383465b5716aa8dfa407409fccef1d F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e @@ -1421,7 +1421,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e420f3dc93a0e3364f0773950b7a125f5221a109 -R 0e64448b1af0ccd7100284f6f222657e -U mistachkin -Z 38e3fbc9582e760d49d364916a96f186 +P c15e0fc4be08b92547bea1f1cac65581ef497409 +R ffa1a98b2b7806021300568489ac1126 +U drh +Z ba6195ff75ad05f3ae39571f4a1714e5 diff --git a/manifest.uuid b/manifest.uuid index 6bcba645b0..e3e08e4e7c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c15e0fc4be08b92547bea1f1cac65581ef497409 \ No newline at end of file +12eb8db79697ef55228c78011d275f36f58271e1 \ No newline at end of file diff --git a/tool/mkautoconfamal.sh b/tool/mkautoconfamal.sh index d368cd226b..6081a7b0ec 100644 --- a/tool/mkautoconfamal.sh +++ b/tool/mkautoconfamal.sh @@ -41,7 +41,6 @@ cp sqlite3ext.h $TMPSPACE cp $TOP/sqlite3.1 $TMPSPACE cp $TOP/sqlite3.pc.in $TMPSPACE cp $TOP/src/shell.c $TMPSPACE -cp $TOP/Makefile.min.msc $TMPSPACE/Makefile.msc cp $TOP/src/sqlite3.rc $TMPSPACE cat $TMPSPACE/configure.ac | diff --git a/tool/mkmsvcmin.tcl b/tool/mkmsvcmin.tcl index d0143ddd86..de01490c97 100644 --- a/tool/mkmsvcmin.tcl +++ b/tool/mkmsvcmin.tcl @@ -9,7 +9,7 @@ if {$argc==0} { set basedir [file dir [file dir [file normalize $argv0]]] set fromFileName [file join $basedir Makefile.msc] - set toFileName [file join $basedir Makefile.min.msc] + set toFileName [file join $basedir autoconf Makefile.msc] } else { set fromFileName [lindex $argv 0] if {![file exists $fromFileName]} { @@ -75,8 +75,9 @@ $(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H) set data "#### DO NOT EDIT ####\n" append data "# This makefile is automatically " append data "generated from the [file tail $fromFileName] at\n" -append data "# the root of the canonical SQLite source tree using the\n" -append data "# tool/[file tail $argv0] script.\n#\n\n" +append data "# the root of the canonical SQLite source tree (not the\n" +append data "# amalgamation tarball) using the tool/[file tail $argv0]\n" +append data "# script.\n#\n\n" append data [readFile $fromFileName] regsub -all -- {# <>\n.*?# <>\n} \ From 74f6e6ccf877fd3154eff2fabaa0c55e188bb019 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Jan 2016 20:43:48 +0000 Subject: [PATCH 158/570] Updates to the autoconf README file. FossilOrigin-Name: 4ce60fa42d8486d219d40d25d785d7f2cabe5e06 --- autoconf/README.txt | 11 +++++++++-- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/autoconf/README.txt b/autoconf/README.txt index 731158a883..575e0a8dd8 100644 --- a/autoconf/README.txt +++ b/autoconf/README.txt @@ -4,8 +4,11 @@ This package contains: * the shell.c file used to build the sqlite3 shell too, and * the sqlite3.h and sqlite3ext.h header files required to link programs and sqlite extensions against the installed libary. - * autoconf/automake installation infrastucture. - * a Makefile.msc and sqlite3.rc for Microsoft Visual C++ + * autoconf/automake installation infrastucture for building on posix systems. + * a Makefile.msc and sqlite3.rc for building with Microsoft Visual C++ + +BUILDING ON POSIX +================= The generic installation instructions for autoconf/automake are found in the INSTALL file. @@ -30,6 +33,10 @@ example: $ CFLAGS="-Os -DSQLITE_OMIT_TRIGGERS" ./configure + +BUILDING WITH MICROSOFT VISUAL C++: +=================================== + To compile for Windows using Microsoft Visual C++: $ nmake /f Makefile.msc FOR_WIN10=1 diff --git a/manifest b/manifest index 9a914fa3d3..e41fae053e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Move\sMakefile.min.msc\sinto\sthe\sautoconf\ssubdir\swhere\sit\sbelongs\sand\schange\nits\sname\sto\sMakefile.msc.\s\sAdjust\sbuild\sscripts\saccordingly. -D 2016-01-23T20:34:27.088 +C Updates\sto\sthe\sautoconf\sREADME\sfile. +D 2016-01-23T20:43:48.995 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -11,9 +11,9 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 1c1657650775960804945dc392e14d9e43c5ed84 -F autoconf/Makefile.msc 68ed752a809b611d97b95d8572a34fe6fd1196f1 w Makefile.min.msc +F autoconf/Makefile.msc 68ed752a809b611d97b95d8572a34fe6fd1196f1 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 -F autoconf/README.txt c9265657b6ca8c4de1e148e8c0c4c29d60ec860c +F autoconf/README.txt ebf930270b2d6258f4d2c62c8c5a5dcc7cff5293 F autoconf/configure.ac 7b1ea0dcaf49fafba262ce4b0ee8cb3281b555d1 F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 @@ -1421,7 +1421,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c15e0fc4be08b92547bea1f1cac65581ef497409 -R ffa1a98b2b7806021300568489ac1126 +P 12eb8db79697ef55228c78011d275f36f58271e1 +R f077ea8ac49bb767871086d72cc4aac2 U drh -Z ba6195ff75ad05f3ae39571f4a1714e5 +Z 47e598e0236f733ea03c00ba7b81ee9b diff --git a/manifest.uuid b/manifest.uuid index e3e08e4e7c..ea84af834d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -12eb8db79697ef55228c78011d275f36f58271e1 \ No newline at end of file +4ce60fa42d8486d219d40d25d785d7f2cabe5e06 \ No newline at end of file From 76d4b1b835be68f6164042e34efb4c31e3dc11c3 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sat, 23 Jan 2016 21:57:46 +0000 Subject: [PATCH 159/570] More updates to the README. FossilOrigin-Name: 9f02868df71d902a2b9118d0b06df18ee92b666b --- autoconf/README.txt | 77 +++++++++++++++++++++++++++++++++++++++++---- manifest | 14 ++++----- manifest.uuid | 2 +- 3 files changed, 79 insertions(+), 14 deletions(-) diff --git a/autoconf/README.txt b/autoconf/README.txt index 575e0a8dd8..a581c39dea 100644 --- a/autoconf/README.txt +++ b/autoconf/README.txt @@ -4,8 +4,10 @@ This package contains: * the shell.c file used to build the sqlite3 shell too, and * the sqlite3.h and sqlite3ext.h header files required to link programs and sqlite extensions against the installed libary. - * autoconf/automake installation infrastucture for building on posix systems. - * a Makefile.msc and sqlite3.rc for building with Microsoft Visual C++ + * autoconf/automake installation infrastucture for building on POSIX + compliant systems. + * a Makefile.msc and sqlite3.rc for building with Microsoft Visual C++ on + Windows. BUILDING ON POSIX ================= @@ -19,7 +21,7 @@ The following SQLite specific boolean options are supported: --enable-threadsafe build a thread-safe library [default=yes] --enable-dynamic-extensions support loadable extensions [default=yes] -The default value for the CFLAGS variable (options passed to the C +The default value for the CFLAGS variable (options passed to the C compiler) includes debugging symbols in the build, resulting in larger binaries than are necessary. Override it on the configure command line like this: @@ -34,9 +36,72 @@ example: $ CFLAGS="-Os -DSQLITE_OMIT_TRIGGERS" ./configure -BUILDING WITH MICROSOFT VISUAL C++: -=================================== +BUILDING WITH MICROSOFT VISUAL C++ +================================== To compile for Windows using Microsoft Visual C++: - $ nmake /f Makefile.msc FOR_WIN10=1 + $ nmake /f Makefile.msc + +Using Microsoft Visual C++ 2005 (or later) is recommended. Several Windows +platform variants may be built by adding additional macros to the NMAKE +command line. + +BUILDING FOR WINRT 8.0 +---------------------- + + FOR_WINRT=1 + +Using Microsoft Visual C++ 2012 (or later) is required. When using the +above, something like the following macro will need to be added to the +NMAKE command line as well: + + "NSDKLIBPATH=%WindowsSdkDir%\..\8.0\lib\win8\um\x86" + +BUILDING FOR WINRT 8.1 +---------------------- + + FOR_WINRT=1 + +Using Microsoft Visual C++ 2013 (or later) is required. When using the +above, something like the following macro will need to be added to the +NMAKE command line as well: + + "NSDKLIBPATH=%WindowsSdkDir%\..\8.1\lib\winv6.3\um\x86" + +BUILDING FOR UAP 10.0 +--------------------- + + FOR_WINRT=1 FOR_UAP=1 + +Using Microsoft Visual C++ 2015 (or later) is required. When using the +above, something like the following macros will need to be added to the +NMAKE command line as well: + + "NSDKLIBPATH=%WindowsSdkDir%\..\10\lib\10.0.10586.0\um\x86" + "PSDKLIBPATH=%WindowsSdkDir%\..\10\lib\10.0.10586.0\um\x86" + "NUCRTLIBPATH=%UniversalCRTSdkDir%\..\10\lib\10.0.10586.0\ucrt\x86" + +BUILDING FOR THE WINDOWS 10 SDK +------------------------------- + + FOR_WIN10=1 + +Using Microsoft Visual C++ 2015 (or later) is required. When using the +above, no other macros should be needed on the NMAKE command line. + +USING PREPROCESSOR DEFINES +-------------------------- + +Additionally, preprocessor defines may be specified by using the OPTS macro +on the NMAKE command line. However, not all possible preprocessor defines +may be specified in this manner as some require the amalgamation to be built +with them enabled (see http://www.sqlite.org/compile.html). For example, the +following will work: + + "OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_ENABLE_JSON1=1" + +However, the following will not compile unless the amalgamation was built +with it enabled: + + "OPTS=-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1" diff --git a/manifest b/manifest index e41fae053e..0f3e8b7b8d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Updates\sto\sthe\sautoconf\sREADME\sfile. -D 2016-01-23T20:43:48.995 +C More\supdates\sto\sthe\sREADME. +D 2016-01-23T21:57:46.170 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -13,7 +13,7 @@ F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 1c1657650775960804945dc392e14d9e43c5ed84 F autoconf/Makefile.msc 68ed752a809b611d97b95d8572a34fe6fd1196f1 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 -F autoconf/README.txt ebf930270b2d6258f4d2c62c8c5a5dcc7cff5293 +F autoconf/README.txt fc86867528c500dfd691620e623bfe6799c98d14 F autoconf/configure.ac 7b1ea0dcaf49fafba262ce4b0ee8cb3281b555d1 F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 @@ -1421,7 +1421,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 12eb8db79697ef55228c78011d275f36f58271e1 -R f077ea8ac49bb767871086d72cc4aac2 -U drh -Z 47e598e0236f733ea03c00ba7b81ee9b +P 4ce60fa42d8486d219d40d25d785d7f2cabe5e06 +R 9ddb76e24748b77caceaf34a8b255b23 +U mistachkin +Z 8a8dd4db0d2ee1de0599573a5cb1355c diff --git a/manifest.uuid b/manifest.uuid index ea84af834d..c53057578b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4ce60fa42d8486d219d40d25d785d7f2cabe5e06 \ No newline at end of file +9f02868df71d902a2b9118d0b06df18ee92b666b \ No newline at end of file From 9084ec1d962388a219d32fbed684f15e44de11d8 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Jan 2016 22:55:53 +0000 Subject: [PATCH 160/570] Add the SQLITE_SPELLFIX_STACKALLOC_SZ compile-time option to control how much stack space is available for use as the Wagner matrix in editDest3 of the spellfix extension. FossilOrigin-Name: dd0100dd87e2c7c70fabb2d3188f0906e605583d --- ext/misc/spellfix.c | 13 ++++++++++++- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/ext/misc/spellfix.c b/ext/misc/spellfix.c index d17a05a3cd..68bd2afbb2 100644 --- a/ext/misc/spellfix.c +++ b/ext/misc/spellfix.c @@ -875,6 +875,17 @@ static void updateCost( } } +/* +** How much stack space (int bytes) to use for Wagner matrix in +** editDist3Core(). If more space than this is required, the entire +** matrix is taken from the heap. To reduce the load on the memory +** allocator, make this value as large as practical for the +** architecture in use. +*/ +#ifndef SQLITE_SPELLFIX_STACKALLOC_SZ +# define SQLITE_SPELLFIX_STACKALLOC_SZ (1024) +#endif + /* Compute the edit distance between two strings. ** ** If an error occurs, return a negative number which is the error code. @@ -904,7 +915,7 @@ static int editDist3Core( EditDist3Cost *p; int res; sqlite3_uint64 nByte; - unsigned int stackSpace[16*1024]; + unsigned int stackSpace[SQLITE_SPELLFIX_STACKALLOC_SZ/sizeof(unsigned int)]; /* allocate the Wagner matrix and the aTo[] array for the TO string */ n = (f.n+1)*(n2+1); diff --git a/manifest b/manifest index 8a5302c683..d6adb98190 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Changes\sto\sspellfix\sto\stry\sto\sget\sit\sto\suse\sstack\sspace\sinstead\sof\sheap\sspace\nin\scases\swhere\sthat\smakes\ssense. -D 2016-01-23T18:24:52.238 +C Add\sthe\sSQLITE_SPELLFIX_STACKALLOC_SZ\scompile-time\soption\sto\scontrol\show\smuch\nstack\sspace\sis\savailable\sfor\suse\sas\sthe\sWagner\smatrix\sin\seditDest3\sof\sthe\nspellfix\sextension. +D 2016-01-23T22:55:53.451 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -210,7 +210,7 @@ F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a F ext/misc/series.c b8fb7befd85b3a9b4a10e701b30b2b79ca92b6d4 F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 -F ext/misc/spellfix.c 5850a0e05ae1eacd48a3d80991c63b58d41e2d27 +F ext/misc/spellfix.c db4cc4b7aa12384e6c19a289a39cd232d355413d F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 3be336aa893f9eb0837d7d66c83bab1489792b9a -R e0cc5654cf9d372268674d3acd0d1178 +P dfcebc7393a3a780ee9c4f257723c303bb633064 +R f2b384711e45db4261b5ef34d3e09d67 U drh -Z 5f4045218ee81aac454594c9cbaf4e94 +Z 57efa8447e9c944d8afed12c4b4dd5da diff --git a/manifest.uuid b/manifest.uuid index ff35bf94f1..dfbb1735b4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dfcebc7393a3a780ee9c4f257723c303bb633064 \ No newline at end of file +dd0100dd87e2c7c70fabb2d3188f0906e605583d \ No newline at end of file From d0d0f8dc67725287d31be219314e839594a4278f Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Jan 2016 01:07:59 +0000 Subject: [PATCH 161/570] Small simplification and performance improvement in memsys5Free(). FossilOrigin-Name: 0a9cff5c4822874b74e90bfca3963bc7e5c753a5 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/mem5.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index d6adb98190..1cbb37b406 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_SPELLFIX_STACKALLOC_SZ\scompile-time\soption\sto\scontrol\show\smuch\nstack\sspace\sis\savailable\sfor\suse\sas\sthe\sWagner\smatrix\sin\seditDest3\sof\sthe\nspellfix\sextension. -D 2016-01-23T22:55:53.451 +C Small\ssimplification\sand\sperformance\simprovement\sin\smemsys5Free(). +D 2016-01-25T01:07:59.493 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -316,7 +316,7 @@ F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a -F src/mem5.c 71f81a11fc5e29a57428761ab38a7bf2ef4ee19d +F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85 F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P dfcebc7393a3a780ee9c4f257723c303bb633064 -R f2b384711e45db4261b5ef34d3e09d67 +P dd0100dd87e2c7c70fabb2d3188f0906e605583d +R a179bcf25d5e17fae98e7434f7b5c754 U drh -Z 57efa8447e9c944d8afed12c4b4dd5da +Z 6a3ae2a8bc97ab052cdf4e5d8140159f diff --git a/manifest.uuid b/manifest.uuid index dfbb1735b4..fed0f2a557 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dd0100dd87e2c7c70fabb2d3188f0906e605583d \ No newline at end of file +0a9cff5c4822874b74e90bfca3963bc7e5c753a5 \ No newline at end of file diff --git a/src/mem5.c b/src/mem5.c index 7316a630a6..c194a6b778 100644 --- a/src/mem5.c +++ b/src/mem5.c @@ -322,11 +322,11 @@ static void memsys5FreeUnsafe(void *pOld){ int iBuddy; if( (iBlock>>iLogsize) & 1 ){ iBuddy = iBlock - size; + assert( iBuddy>=0 ); }else{ iBuddy = iBlock + size; + if( iBuddy>=mem5.nBlock ) break; } - assert( iBuddy>=0 ); - if( (iBuddy+(1<mem5.nBlock ) break; if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break; memsys5Unlink(iBuddy, iLogsize); iLogsize++; From a7dc4a321d8f537d9257b20634f93dccfabd03cd Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Jan 2016 02:15:02 +0000 Subject: [PATCH 162/570] Small simplification to the prepare statement opcode memory reuse logic. Easier to read, and slightly smaller and faster. FossilOrigin-Name: 8a1deae497edf3fa43fa96152d140405398c5ed6 --- manifest | 12 ++--- manifest.uuid | 2 +- src/vdbeaux.c | 119 ++++++++++++++++++++++++-------------------------- 3 files changed, 64 insertions(+), 69 deletions(-) diff --git a/manifest b/manifest index 1cbb37b406..e1fe265cc4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Small\ssimplification\sand\sperformance\simprovement\sin\smemsys5Free(). -D 2016-01-25T01:07:59.493 +C Small\ssimplification\sto\sthe\sprepare\sstatement\sopcode\smemory\sreuse\slogic.\nEasier\sto\sread,\sand\sslightly\ssmaller\sand\sfaster. +D 2016-01-25T02:15:02.255 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -414,7 +414,7 @@ F src/vdbe.c b90d9d38e5e0260c2eafa3cb4c2274d8ea94da27 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e -F src/vdbeaux.c 07f8f485a6cbc0a62da660f14e303061d45d5cb6 +F src/vdbeaux.c 757f86e6fef8efb3dd4226cb31e2e82b9c44c883 F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 F src/vdbesort.c 0971557e5d3c289e46f56a52aed2197c13251de7 @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P dd0100dd87e2c7c70fabb2d3188f0906e605583d -R a179bcf25d5e17fae98e7434f7b5c754 +P 0a9cff5c4822874b74e90bfca3963bc7e5c753a5 +R 5ad29c29cc49b0c7f9cd0947deba5a80 U drh -Z 6a3ae2a8bc97ab052cdf4e5d8140159f +Z 5c673e5ee459b55b04084dc37cebc110 diff --git a/manifest.uuid b/manifest.uuid index fed0f2a557..f04ce16d0b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0a9cff5c4822874b74e90bfca3963bc7e5c753a5 \ No newline at end of file +8a1deae497edf3fa43fa96152d140405398c5ed6 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 17f1cb7dc4..e9be081a20 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1721,41 +1721,43 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){ } #endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */ -/* -** Allocate space from a fixed size buffer and return a pointer to -** that space. If insufficient space is available, return NULL. +/* An instance of this object describes bulk memory available for use +** by subcomponents of a prepared statement. Space is allocated out +** of a ReusableSpace object by the allocSpace() routine below. +*/ +struct ReusableSpace { + u8 *pSpace; /* Available memory */ + int nFree; /* Bytes of available memory */ + int nNeeded; /* Total bytes that could not be allocated */ +}; + +/* Try to allocate nByte bytes of 8-byte aligned bulk memory for pBuf +** from the ReusableSpace object. Return a pointer to the allocated +** memory on success. If insufficient memory is available in the +** ReusableSpace object, increase the ReusableSpace.nNeeded +** value by the amount needed and return NULL. ** -** The pBuf parameter is the initial value of a pointer which will -** receive the new memory. pBuf is normally NULL. If pBuf is not -** NULL, it means that memory space has already been allocated and that -** this routine should not allocate any new memory. When pBuf is not -** NULL simply return pBuf. Only allocate new memory space when pBuf -** is NULL. +** If pBuf is not initially NULL, that means that the memory has already +** been allocated by a prior call to this routine, so just return a copy +** of pBuf and leave ReusableSpace unchanged. ** -** nByte is the number of bytes of space needed. -** -** pFrom points to *pnFrom bytes of available space. New space is allocated -** from the end of the pFrom buffer and *pnFrom is decremented. -** -** *pnNeeded is a counter of the number of bytes of space that have failed -** to allocate. If there is insufficient space in pFrom to satisfy the -** request, then increment *pnNeeded by the amount of the request. +** This allocator is employed to repurpose unused slots at the end of the +** opcode array of prepared state for other memory needs of the prepared +** statement. */ static void *allocSpace( - void *pBuf, /* Where return pointer will be stored */ - int nByte, /* Number of bytes to allocate */ - u8 *pFrom, /* Memory available for allocation */ - int *pnFrom, /* IN/OUT: Space available at pFrom */ - int *pnNeeded /* If allocation cannot be made, increment *pnByte */ + struct ReusableSpace *p, /* Bulk memory available for allocation */ + void *pBuf, /* Pointer to a prior allocation */ + int nByte /* Bytes of memory needed */ ){ - assert( EIGHT_BYTE_ALIGNMENT(pFrom) ); + assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) ); if( pBuf==0 ){ nByte = ROUND8(nByte); - if( nByte <= *pnFrom ){ - *pnFrom -= nByte; - pBuf = &pFrom[*pnFrom]; + if( nByte <= p->nFree ){ + p->nFree -= nByte; + pBuf = &p->pSpace[p->nFree]; }else{ - *pnNeeded += nByte; + p->nNeeded += nByte; } } assert( EIGHT_BYTE_ALIGNMENT(pBuf) ); @@ -1831,9 +1833,7 @@ void sqlite3VdbeMakeReady( int nArg; /* Number of arguments in subprograms */ int nOnce; /* Number of OP_Once instructions */ int n; /* Loop counter */ - int nFree; /* Available free space */ - u8 *zCsr; /* Memory available for allocation */ - int nByte; /* How much extra memory is needed */ + struct ReusableSpace x; /* Reusable bulk memory */ assert( p!=0 ); assert( p->nOp>0 ); @@ -1851,7 +1851,7 @@ void sqlite3VdbeMakeReady( /* For each cursor required, also allocate a memory cell. Memory ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by - ** the vdbe program. Instead they are used to allocate space for + ** the vdbe program. Instead they are used to allocate memory for ** VdbeCursor/BtCursor structures. The blob of memory associated with ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1) ** stores the blob of memory associated with cursor 1, etc. @@ -1860,20 +1860,18 @@ void sqlite3VdbeMakeReady( */ nMem += nCursor; - /* zCsr will initially point to nFree bytes of unused space at the - ** end of the opcode array, p->aOp. The computation of nFree is - ** conservative - it might be smaller than the true number of free - ** bytes, but never larger. nFree must be a multiple of 8 - it is - ** rounded down if is not. + /* Figure out how much reusable memory is available at the end of the + ** opcode array. This extra memory will be reallocated for other elements + ** of the prepared statement. */ - n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode space used */ - zCsr = &((u8*)p->aOp)[n]; /* Unused opcode space */ - assert( EIGHT_BYTE_ALIGNMENT(zCsr) ); - nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused space */ - assert( nFree>=0 ); - if( nFree>0 ){ - memset(zCsr, 0, nFree); - assert( EIGHT_BYTE_ALIGNMENT(&zCsr[nFree]) ); + n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ + x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ + assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); + x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ + assert( x.nFree>=0 ); + if( x.nFree>0 ){ + memset(x.pSpace, 0, x.nFree); + assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); } resolveP2Values(p, &nArg); @@ -1883,33 +1881,30 @@ void sqlite3VdbeMakeReady( } p->expired = 0; - /* Memory for registers, parameters, cursor, etc, is allocated in two - ** passes. On the first pass, we try to reuse unused space at the + /* Memory for registers, parameters, cursor, etc, is allocated in one or two + ** passes. On the first pass, we try to reuse unused memory at the ** end of the opcode array. If we are unable to satisfy all memory ** requirements by reusing the opcode array tail, then the second - ** pass will fill in the rest using a fresh allocation. + ** pass will fill in the remainder using a fresh memory allocation. ** ** This two-pass approach that reuses as much memory as possible from - ** the leftover space at the end of the opcode array can significantly + ** the leftover memory at the end of the opcode array. This can significantly ** reduce the amount of memory held by a prepared statement. */ do { - nByte = 0; - p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), zCsr, &nFree, &nByte); - p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), zCsr, &nFree, &nByte); - p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), zCsr, &nFree, &nByte); - p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*), - zCsr, &nFree, &nByte); - p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, zCsr, &nFree, &nByte); + x.nNeeded = 0; + p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem)); + p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem)); + p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*)); + p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*)); + p->aOnceFlag = allocSpace(&x, p->aOnceFlag, nOnce); #ifdef SQLITE_ENABLE_STMT_SCANSTATUS - p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), zCsr, &nFree, &nByte); + p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64)); #endif - if( nByte ){ - p->pFree = sqlite3DbMallocZero(db, nByte); - } - zCsr = p->pFree; - nFree = nByte; - }while( nByte && !db->mallocFailed ); + if( x.nNeeded==0 ) break; + x.pSpace = p->pFree = sqlite3DbMallocZero(db, x.nNeeded); + x.nFree = x.nNeeded; + }while( !db->mallocFailed ); p->nCursor = nCursor; p->nOnceFlag = nOnce; From 164c957b091ed8fb0b875481556e9e7d882d11a2 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Jan 2016 13:55:47 +0000 Subject: [PATCH 163/570] Add the SQLITE_EXTRA_DURABLE compile-time option. FossilOrigin-Name: 30671345b1c1ee55a2d1aa17273213f1849efd81 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/pager.c | 17 ++++++++++++++++- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index e1fe265cc4..69e58459fa 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Small\ssimplification\sto\sthe\sprepare\sstatement\sopcode\smemory\sreuse\slogic.\nEasier\sto\sread,\sand\sslightly\ssmaller\sand\sfaster. -D 2016-01-25T02:15:02.255 +C Add\sthe\sSQLITE_EXTRA_DURABLE\scompile-time\soption. +D 2016-01-25T13:55:47.049 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -332,7 +332,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 0eb7f469fcd4e1fbedf30060438e26b839ec5486 F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c f4e9ac39fbb1e0fde97af85c0f4e00eb90764b67 +F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 F src/pager.h 1c2a49143dfba9e69cc8159ef019f472ed8d260b F src/parse.y caad1e98edeca6960493d0c60d31b76820dd7776 F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23 @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0a9cff5c4822874b74e90bfca3963bc7e5c753a5 -R 5ad29c29cc49b0c7f9cd0947deba5a80 +P 8a1deae497edf3fa43fa96152d140405398c5ed6 +R ae4ccddaf3c593cdf1ed2beb484cfd15 U drh -Z 5c673e5ee459b55b04084dc37cebc110 +Z 297086babbdf85e61ae58e42a437c1ec diff --git a/manifest.uuid b/manifest.uuid index f04ce16d0b..439be2e5fa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8a1deae497edf3fa43fa96152d140405398c5ed6 \ No newline at end of file +30671345b1c1ee55a2d1aa17273213f1849efd81 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 2c904d2df1..0afbe215c6 100644 --- a/src/pager.c +++ b/src/pager.c @@ -428,6 +428,20 @@ int sqlite3PagerTrace=1; /* True to enable tracing */ */ #define MAX_SECTOR_SIZE 0x10000 +/* +** If the option SQLITE_EXTRA_DURABLE option is set at compile-time, then +** SQLite will do extra fsync() operations when synchronous==FULL to help +** ensure that transactions are durable across a power failure. Most +** applications are happy as long as transactions are consistent across +** a power failure, and are perfectly willing to lose the last transaction +** in exchange for the extra performance of avoiding directory syncs. +** And so the default SQLITE_EXTRA_DURABLE setting is off. +*/ +#ifndef SQLITE_EXTRA_DURABLE +# define SQLITE_EXTRA_DURABLE 0 +#endif + + /* ** An instance of the following structure is allocated for each active ** savepoint and statement transaction in the system. All such structures @@ -1983,7 +1997,8 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ ); sqlite3OsClose(pPager->jfd); if( bDelete ){ - rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); + rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, + pPager->fullSync && SQLITE_EXTRA_DURABLE); } } } From cc2fa4cf5599637bdb8f5a2cc64f0805243e04e4 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Jan 2016 15:57:29 +0000 Subject: [PATCH 164/570] Replace the OP_SetIfNotPos operator with OP_OffsetLimit in the VDBE, for simpler and smaller code. FossilOrigin-Name: 7ac017a498b6fb28343eef2d24e400c7800660d6 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/select.c | 9 +++------ src/vdbe.c | 33 ++++++++++++++++++++++----------- 4 files changed, 33 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index 69e58459fa..827a3d5126 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_EXTRA_DURABLE\scompile-time\soption. -D 2016-01-25T13:55:47.049 +C Replace\sthe\sOP_SetIfNotPos\soperator\swith\sOP_OffsetLimit\sin\sthe\sVDBE,\sfor\nsimpler\sand\ssmaller\scode. +D 2016-01-25T15:57:29.060 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -345,7 +345,7 @@ F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c 1db9a902e89201a0ae3ff5243a7a3f37842a3937 +F src/select.c c34292c8ce7fe69c7cf890d933834a22572bd301 F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/sqlite.h.in 214476a62012e578f42133a9a3b4f97a9aa421a3 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -410,7 +410,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c b90d9d38e5e0260c2eafa3cb4c2274d8ea94da27 +F src/vdbe.c 3ffbcc413bf793e3f0b95b79ef2f4bd449a5b5a3 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 8a1deae497edf3fa43fa96152d140405398c5ed6 -R ae4ccddaf3c593cdf1ed2beb484cfd15 +P 30671345b1c1ee55a2d1aa17273213f1849efd81 +R f342889ba3409bd63b1cf54d88bfe0e2 U drh -Z 297086babbdf85e61ae58e42a437c1ec +Z e7c5fc86067d4269675714897cec0b51 diff --git a/manifest.uuid b/manifest.uuid index 439be2e5fa..276ef7a03f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -30671345b1c1ee55a2d1aa17273213f1849efd81 \ No newline at end of file +7ac017a498b6fb28343eef2d24e400c7800660d6 \ No newline at end of file diff --git a/src/select.c b/src/select.c index ffc0ec2415..ea4298e677 100644 --- a/src/select.c +++ b/src/select.c @@ -1860,10 +1860,8 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ sqlite3ExprCode(pParse, p->pOffset, iOffset); sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); VdbeComment((v, "OFFSET counter")); - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iOffset, iOffset, 0); - sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1); + sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset); VdbeComment((v, "LIMIT+OFFSET")); - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iLimit, iOffset+1, -1); } } } @@ -2280,9 +2278,8 @@ static int multiSelect( addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); VdbeComment((v, "Jump ahead if LIMIT reached")); if( p->iOffset ){ - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iOffset, p->iOffset, 0); - sqlite3VdbeAddOp3(v, OP_Add, p->iLimit, p->iOffset, p->iOffset+1); - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iLimit, p->iOffset+1, -1); + sqlite3VdbeAddOp3(v, OP_OffsetLimit, + p->iLimit, p->iOffset+1, p->iOffset); } } explainSetInteger(iSub2, pParse->iNextSelectId); diff --git a/src/vdbe.c b/src/vdbe.c index c6d5f7b0cc..cfff895c30 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5757,20 +5757,31 @@ case OP_IfPos: { /* jump, in1 */ break; } -/* Opcode: SetIfNotPos P1 P2 P3 * * -** Synopsis: if r[P1]<=0 then r[P2]=P3 +/* Opcode: OffsetLimit P1 P2 P3 * * +** Synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) ** -** Register P1 must contain an integer. -** If the value of register P1 is not positive (if it is less than 1) then -** set the value of register P2 to be the integer P3. +** This opcode performs a commonly used computation associated with +** LIMIT and OFFSET process. r[P1] holds the limit counter. r[P3] +** holds the offset counter. The opcode computes the combined value +** of the LIMIT and OFFSET and stores that value in r[P2]. The r[P2] +** value computed is the total number of rows that will need to be +** visited in order to complete the query. +** +** If r[P3] is zero or negative, that means there is no OFFSET +** and r[P2] is set to be the value of the LIMIT, r[P1]. +** +** if r[P1] is zero or negative, that means there is no LIMIT +** and r[P2] is set to -1. +** +** Otherwise, r[P2] is set to the sum of r[P1] and r[P3]. */ -case OP_SetIfNotPos: { /* in1, in2 */ +case OP_OffsetLimit: { /* in1, out2, in3 */ pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags&MEM_Int ); - if( pIn1->u.i<=0 ){ - pOut = out2Prerelease(p, pOp); - pOut->u.i = pOp->p3; - } + pIn3 = &aMem[pOp->p3]; + pOut = out2Prerelease(p, pOp); + assert( pIn1->flags & MEM_Int ); + assert( pIn3->flags & MEM_Int ); + pOut->u.i = pIn1->u.i<=0 ? -1 : pIn1->u.i+(pIn3->u.i>0?pIn3->u.i:0); break; } From e88ec187cdd590f7b9155cef3ee276c268a4a522 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 25 Jan 2016 17:04:48 +0000 Subject: [PATCH 165/570] Fix issues on unix with opening database files via symlinks that are not in the current working directory. And with nested symlinks. FossilOrigin-Name: 80398fd44fb232193450103808e1854e0eba5652 --- manifest | 19 +++--- manifest.uuid | 2 +- src/os_unix.c | 154 +++++++++++++++++++++++++++++++++------------- test/symlink.test | 119 ++++++++++++++++++++++++++--------- 4 files changed, 215 insertions(+), 79 deletions(-) diff --git a/manifest b/manifest index 827a3d5126..0b395a1661 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Replace\sthe\sOP_SetIfNotPos\soperator\swith\sOP_OffsetLimit\sin\sthe\sVDBE,\sfor\nsimpler\sand\ssmaller\scode. -D 2016-01-25T15:57:29.060 +C Fix\sissues\son\sunix\swith\sopening\sdatabase\sfiles\svia\ssymlinks\sthat\sare\snot\sin\sthe\scurrent\sworking\sdirectory.\sAnd\swith\snested\ssymlinks. +D 2016-01-25T17:04:48.546 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -329,7 +329,7 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c 0eb7f469fcd4e1fbedf30060438e26b839ec5486 +F src/os_unix.c cf524029242b4f878d6b97bad25cc2c0b66c2b31 F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 @@ -1061,7 +1061,7 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2 -F test/symlink.test cbf6cb8c6c4b63a39e9f0f6b0d5c99e249dbc102 +F test/symlink.test 511db82662446bb0d3619002422760ef8e4b1122 F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85 F test/syscall.test 2aa9e111b79fb385681ff8940124def6f8faab87 F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 @@ -1419,7 +1419,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 30671345b1c1ee55a2d1aa17273213f1849efd81 -R f342889ba3409bd63b1cf54d88bfe0e2 -U drh -Z e7c5fc86067d4269675714897cec0b51 +P 7ac017a498b6fb28343eef2d24e400c7800660d6 +R 0289127606d03bb3b649ecbd39bb14a5 +T *branch * follow-symlinks +T *sym-follow-symlinks * +T -sym-trunk * +U dan +Z 3e18b3d01ba737d3635110839e378935 diff --git a/manifest.uuid b/manifest.uuid index 276ef7a03f..6dda1af216 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7ac017a498b6fb28343eef2d24e400c7800660d6 \ No newline at end of file +80398fd44fb232193450103808e1854e0eba5652 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index ee9b55674b..9cd1fa19ad 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -149,6 +149,11 @@ */ #define MAX_PATHNAME 512 +/* +** Maximum supported symbolic links +*/ +#define SQLITE_MAX_SYMLINKS 100 + /* Always cast the getpid() return type for compatibility with ** kernel modules in VxWorks. */ #define osGetpid(X) (pid_t)getpid() @@ -5927,52 +5932,22 @@ static int unixAccess( return SQLITE_OK; } - /* -** Turn a relative pathname into a full pathname. The relative path -** is stored as a nul-terminated string in the buffer pointed to by -** zPath. +** Buffer zOut contains a (possibly) relative pathname. Overwrite it with +** the corresponding full pathname. ** -** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes -** (in this case, MAX_PATHNAME bytes). The full-path is written to -** this buffer before returning. +** Parameter nOut is the allocated size of buffer zOut. nByte is the number +** of bytes in the nul-terminated string that it contains (not including +** the nul-terminator itself). +** +** Return SQLITE_OK if successful, or an SQLite error code otherwise. */ -static int unixFullPathname( - sqlite3_vfs *pVfs, /* Pointer to vfs object */ - const char *zPath, /* Possibly relative input path */ - int nOut, /* Size of output buffer in bytes */ - char *zOut /* Output buffer */ +static int mkFullPathname( + const char *zPath, /* Use this path to log any errors */ + char *zOut, /* IN/OUT: Buffer to modify */ + int nByte, /* size of nul-terminated zOut in bytes */ + int nOut /* Allocated size of buffer zOut */ ){ - int nByte; - - /* It's odd to simulate an io-error here, but really this is just - ** using the io-error infrastructure to test that SQLite handles this - ** function failing. This function could fail if, for example, the - ** current working directory has been unlinked. - */ - SimulateIOError( return SQLITE_ERROR ); - - assert( pVfs->mxPathname==MAX_PATHNAME ); - UNUSED_PARAMETER(pVfs); - -#if defined(HAVE_READLINK) - /* Attempt to resolve the path as if it were a symbolic link. If it is - ** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if - ** the identified file is not a symbolic link or does not exist, then - ** zPath is copied directly into zOut. Either way, nByte is left set to - ** the size of the string copied into zOut[] in bytes. */ - nByte = osReadlink(zPath, zOut, nOut-1); - if( nByte<0 ){ - if( errno!=EINVAL && errno!=ENOENT ){ - return unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath); - } - sqlite3_snprintf(nOut, zOut, "%s", zPath); - nByte = sqlite3Strlen30(zOut); - }else{ - zOut[nByte] = '\0'; - } -#endif - /* If buffer zOut[] now contains an absolute path there is nothing more ** to do. If it contains a relative path, do the following: ** @@ -5989,6 +5964,7 @@ static int unixFullPathname( ** truncated to make it fit. This is Ok, as SQLite refuses to open any ** file for which this function returns a full path larger than (nOut-8) ** bytes in size. */ + assert( nBytemxPathname==MAX_PATHNAME ); + UNUSED_PARAMETER(pVfs); + + /* It's odd to simulate an io-error here, but really this is just + ** using the io-error infrastructure to test that SQLite handles this + ** function failing. This function could fail if, for example, the + ** current working directory has been unlinked. + */ + SimulateIOError( return SQLITE_ERROR ); + + do { + + /* Attempt to resolve the path as if it were a symbolic link. If it is + ** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if + ** the identified file is not a symbolic link or does not exist, then + ** zPath is copied directly into zOut. Either way, nByte is left set to + ** the size of the string copied into zOut[] in bytes. */ + assert( (zDel==0 && zIn==zPath) || (zDel!=0 && zIn==zDel) ); + if( zDel ){ + assert( zIn==zDel ); + sqlite3_snprintf(nOut, zDel, "%s", zOut); + } + nByte = osReadlink(zIn, zOut, nOut-1); + if( nByte<0 ){ + if( errno!=EINVAL && errno!=ENOENT ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath); + }else{ + sqlite3_snprintf(nOut, zOut, "%s", zIn); + nByte = sqlite3Strlen30(zOut); + } + bLink = 0; + }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ + sqlite3_log(SQLITE_CANTOPEN, + "too many symbolic links (max=%d)", SQLITE_MAX_SYMLINKS + ); + rc = SQLITE_CANTOPEN_BKPT; + }else{ + zOut[nByte] = '\0'; + if( zOut[0]!='/' ){ + int n; + for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); + if( nByte+n+1>nOut ){ + rc = SQLITE_CANTOPEN_BKPT; + }else{ + memmove(&zOut[n], zOut, nByte+1); + memcpy(zOut, zIn, n); + nByte += n; + } + } + if( zDel==0 ){ + zDel = sqlite3_malloc(nOut); + if( zDel==0 ) rc = SQLITE_NOMEM; + zIn = (const char*)zDel; + } + bLink = 1; + } + + if( rc==SQLITE_OK ){ + rc = mkFullPathname(zPath, zOut, nByte, nOut); + } + }while( bLink && rc==SQLITE_OK ); + + sqlite3_free(zDel); + return rc; +#endif /* HAVE_READLINK */ +} + #ifndef SQLITE_OMIT_LOAD_EXTENSION /* diff --git a/test/symlink.test b/test/symlink.test index 790624161f..e9e5f3c305 100644 --- a/test/symlink.test +++ b/test/symlink.test @@ -83,38 +83,49 @@ do_test 1.5 { do_test 2.0 { catch { db close } catch { db2 close } - forcedelete test.db test.db2 + forcedelete test.db test.db2 test.db3 sqlite3 db test.db execsql { CREATE TABLE t1(x) } file link test.db2 test.db - sqlite3 db2 test.db2 - file exists test.db-journal -} 0 + file link test.db3 test.db2 + set {} {} +} {} -do_test 2.1 { - execsql { - BEGIN; - INSERT INTO t1 VALUES(1); - } db2 - file exists test.db-journal -} 1 -do_test 2.2 { - file exists test.db2-journal -} 0 -do_test 2.3 { - execsql { - COMMIT; - PRAGMA journal_mode = wal; - INSERT INTO t1 VALUES(2); - } db2 - file exists test.db-wal -} 1 -do_test 2.4 { - file exists test.db2-wal -} 0 -do_execsql_test 2.5 { - SELECT * FROM t1; -} {1 2} +foreach {tn f} {1 test.db2 2 test.db3} { + do_test 2.$tn.1 { + sqlite3 db2 $f + file exists test.db-journal + } 0 + do_test 2.$tn.2 { + execsql { + BEGIN; + INSERT INTO t1 VALUES(1); + } db2 + file exists test.db-journal + } 1 + do_test 2.$tn.3 { + list [file exists test2.db-journal] [file exists test3.db-journal] + } {0 0} + do_test 2.$tn.4 { + execsql { + COMMIT; + PRAGMA journal_mode = wal; + INSERT INTO t1 VALUES(2); + } db2 + file exists test.db-wal + } 1 + do_test 2.$tn.5 { + list [file exists test2.db-wal] [file exists test3.db-wal] + } {0 0} + do_execsql_test 2.$tn.6 { + SELECT * FROM t1; + } {1 2} + db2 close + do_execsql_test 2.$tn.7 { + DELETE FROM t1; + PRAGMA journal_mode = delete; + } delete +} # Try to open a ridiculously long pathname. Bug found by # Kostya Serebryany using libFuzzer on 2015-11-30. @@ -125,5 +136,57 @@ do_test 3.1 { set res } {unable to open database file} +#------------------------------------------------------------------------- +# Test that relative symlinks that are not located in the cwd work. +# +do_test 4.1 { + forcedelete x y z + file mkdir x + file mkdir y + file mkdir z + sqlite3 db x/test.db + file link y/test.db ../x/test.db + file link z/test.db ../y/test.db + execsql { + PRAGMA journal_mode = wal; + CREATE TABLE t1(x, y); + INSERT INTO t1 VALUES('hello', 'world'); + } +} {wal} + +do_test 4.2.1 { + db close + sqlite3 db y/test.db + db eval { SELECT * FROM t1 } +} {hello world} +do_test 4.2.2 { + list [file exists x/test.db-wal] [file exists y/test.db-wal] +} {1 0} + +do_test 4.3.1 { + db close + sqlite3 db z/test.db + db eval { SELECT * FROM t1 } +} {hello world} +do_test 4.3.2 { + list [file exists x/test.db-wal] [file exists y/test.db-wal] \ + [file exists z/test.db-wal] +} {1 0 0} + +do_test 4.4.0 { + forcedelete w + file mkdir w + file link w/test.db [file join [pwd] x/test.db] + set {} {} +} {} +do_test 4.4.1 { + db close + breakpoint + sqlite3 db w/test.db + db eval { SELECT * FROM t1 } +} {hello world} +do_test 4.4.2 { + list [file exists x/test.db-wal] [file exists w/test.db-wal] +} {1 0} finish_test From caf6b150a1077f2d4293b4091247c7e932da3927 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 25 Jan 2016 18:05:49 +0000 Subject: [PATCH 166/570] Simplify the unixFullpathname() function. This adds a dependency on lstat(). FossilOrigin-Name: f71249d3db9242b8f38955db51a7a5789d002803 --- manifest | 15 +++--- manifest.uuid | 2 +- src/os_unix.c | 137 +++++++++++++++++++------------------------------- 3 files changed, 60 insertions(+), 94 deletions(-) diff --git a/manifest b/manifest index 0b395a1661..27188d419f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sissues\son\sunix\swith\sopening\sdatabase\sfiles\svia\ssymlinks\sthat\sare\snot\sin\sthe\scurrent\sworking\sdirectory.\sAnd\swith\snested\ssymlinks. -D 2016-01-25T17:04:48.546 +C Simplify\sthe\sunixFullpathname()\sfunction.\sThis\sadds\sa\sdependency\son\slstat(). +D 2016-01-25T18:05:49.964 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -329,7 +329,7 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c cf524029242b4f878d6b97bad25cc2c0b66c2b31 +F src/os_unix.c 6604e7f9e5298b615f729b6bb3c22bd3545cdca6 F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 @@ -1419,10 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7ac017a498b6fb28343eef2d24e400c7800660d6 -R 0289127606d03bb3b649ecbd39bb14a5 -T *branch * follow-symlinks -T *sym-follow-symlinks * -T -sym-trunk * +P 80398fd44fb232193450103808e1854e0eba5652 +R 084dee05e1353887f6af0d88670b22d0 U dan -Z 3e18b3d01ba737d3635110839e378935 +Z 72572e009a3ce3b7747f3257ebf7dfc7 diff --git a/manifest.uuid b/manifest.uuid index 6dda1af216..b66c39a6ae 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -80398fd44fb232193450103808e1854e0eba5652 \ No newline at end of file +f71249d3db9242b8f38955db51a7a5789d002803 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 9cd1fa19ad..3d113301b8 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -480,6 +480,8 @@ static struct unix_syscall { #endif #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent) + { "lstat", (sqlite3_syscall_ptr)lstat, 0 }, +#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) }; /* End of the overrideable system calls */ @@ -5933,54 +5935,24 @@ static int unixAccess( } /* -** Buffer zOut contains a (possibly) relative pathname. Overwrite it with -** the corresponding full pathname. ** -** Parameter nOut is the allocated size of buffer zOut. nByte is the number -** of bytes in the nul-terminated string that it contains (not including -** the nul-terminator itself). -** -** Return SQLITE_OK if successful, or an SQLite error code otherwise. */ static int mkFullPathname( - const char *zPath, /* Use this path to log any errors */ - char *zOut, /* IN/OUT: Buffer to modify */ - int nByte, /* size of nul-terminated zOut in bytes */ + const char *zPath, /* Input path */ + char *zOut, /* Output buffer */ int nOut /* Allocated size of buffer zOut */ ){ - /* If buffer zOut[] now contains an absolute path there is nothing more - ** to do. If it contains a relative path, do the following: - ** - ** * move the relative path string so that it is at the end of th - ** zOut[] buffer. - ** * Call getcwd() to read the path of the current working directory - ** into the start of the zOut[] buffer. - ** * Append a '/' character to the cwd string and move the - ** relative path back within the buffer so that it immediately - ** follows the '/'. - ** - ** This code is written so that if the combination of the CWD and relative - ** path are larger than the allocated size of zOut[] the CWD is silently - ** truncated to make it fit. This is Ok, as SQLite refuses to open any - ** file for which this function returns a full path larger than (nOut-8) - ** bytes in size. */ - assert( nBytenOut ) return SQLITE_CANTOPEN_BKPT; + sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath); return SQLITE_OK; } @@ -6000,13 +5972,11 @@ static int unixFullPathname( char *zOut /* Output buffer */ ){ #if !defined(HAVE_READLINK) - sqlite3_snprintf(nOut, zOut, "%s", zIn); - nByte = sqlite3Strlen30(zOut); - return mkFullPathname(zPath, zOut, sqlite3Strlen30(zOut), nOut); + return mkFullPathname(zPath, zOut, nOut); #else int rc = SQLITE_OK; int nByte; - int nLink = 0; /* Number of symbolic links followed so far */ + int nLink = 1; /* Number of symbolic links followed so far */ int bLink; /* True for a symbolic link */ const char *zIn = zPath; /* Input path for each iteration of loop */ char *zDel = 0; @@ -6023,55 +5993,54 @@ static int unixFullPathname( do { - /* Attempt to resolve the path as if it were a symbolic link. If it is - ** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if - ** the identified file is not a symbolic link or does not exist, then - ** zPath is copied directly into zOut. Either way, nByte is left set to - ** the size of the string copied into zOut[] in bytes. */ - assert( (zDel==0 && zIn==zPath) || (zDel!=0 && zIn==zDel) ); - if( zDel ){ - assert( zIn==zDel ); - sqlite3_snprintf(nOut, zDel, "%s", zOut); - } - nByte = osReadlink(zIn, zOut, nOut-1); - if( nByte<0 ){ - if( errno!=EINVAL && errno!=ENOENT ){ - rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath); - }else{ - sqlite3_snprintf(nOut, zOut, "%s", zIn); - nByte = sqlite3Strlen30(zOut); + /* Call stat() on path zIn. Set bLink to true if the path is a symbolic + ** link, or false otherwise. */ + int bLink = 0; + struct stat buf; + if( osLstat(zIn, &buf)!=0 ){ + if( errno!=ENOENT ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "stat", zIn); } - bLink = 0; - }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ - sqlite3_log(SQLITE_CANTOPEN, - "too many symbolic links (max=%d)", SQLITE_MAX_SYMLINKS - ); - rc = SQLITE_CANTOPEN_BKPT; }else{ - zOut[nByte] = '\0'; - if( zOut[0]!='/' ){ - int n; - for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); - if( nByte+n+1>nOut ){ - rc = SQLITE_CANTOPEN_BKPT; - }else{ - memmove(&zOut[n], zOut, nByte+1); - memcpy(zOut, zIn, n); - nByte += n; - } - } + bLink = S_ISLNK(buf.st_mode); + } + + if( bLink ){ if( zDel==0 ){ zDel = sqlite3_malloc(nOut); if( zDel==0 ) rc = SQLITE_NOMEM; - zIn = (const char*)zDel; + }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ + rc = SQLITE_CANTOPEN_BKPT; } - bLink = 1; + + if( rc==SQLITE_OK ){ + nByte = osReadlink(zIn, zDel, nOut-1); + if( nByte<0 ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn); + }else if( zDel[0]!='/' ){ + int n; + for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); + if( nByte+n+1>nOut ){ + rc = SQLITE_CANTOPEN_BKPT; + }else{ + memmove(&zDel[n], zDel, nByte+1); + memcpy(zDel, zIn, n); + nByte += n; + } + zDel[nByte] = '\0'; + } + } + + zIn = zDel; } if( rc==SQLITE_OK ){ - rc = mkFullPathname(zPath, zOut, nByte, nOut); + assert( zIn!=zOut || zIn[0]=='/' ); + rc = mkFullPathname(zIn, zOut, nOut); } - }while( bLink && rc==SQLITE_OK ); + if( bLink==0 ) break; + zIn = zOut; + }while( rc==SQLITE_OK ); sqlite3_free(zDel); return rc; @@ -7574,7 +7543,7 @@ int sqlite3_os_init(void){ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==27 ); + assert( ArraySize(aSyscall)==28 ); /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ From af1b36b1df592aa8ecf1fd8799db7e415688ed6e Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 25 Jan 2016 18:43:05 +0000 Subject: [PATCH 167/570] Only use lstat() if the HAVE_LSTAT macro is defined. Fix some test file issues. FossilOrigin-Name: 8a6e4147a680ad6c5fdd588468b6daac82349d2c --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/os_unix.c | 12 ++++++++---- src/vxworks.h | 1 + test/oserror.test | 2 +- test/syscall.test | 2 +- 6 files changed, 21 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 27188d419f..33b8dc8b5c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplify\sthe\sunixFullpathname()\sfunction.\sThis\sadds\sa\sdependency\son\slstat(). -D 2016-01-25T18:05:49.964 +C Only\suse\slstat()\sif\sthe\sHAVE_LSTAT\smacro\sis\sdefined.\sFix\ssome\stest\sfile\sissues. +D 2016-01-25T18:43:05.007 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -329,7 +329,7 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c 6604e7f9e5298b615f729b6bb3c22bd3545cdca6 +F src/os_unix.c 4c217111d7bdebbd7a9b47cf11f434420da432e7 F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 @@ -420,7 +420,7 @@ F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 F src/vdbesort.c 0971557e5d3c289e46f56a52aed2197c13251de7 F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 F src/vtab.c 320682cca733115b4cbe71320b5c5eeb1074ebde -F src/vxworks.h 974e7d9a98f602d6310d563e1dc4e08f9fc48e47 +F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c d21b99fd1458159d0b1ecdccc8ee6ada4fdc4c54 F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 @@ -924,7 +924,7 @@ F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859 F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3 -F test/oserror.test 361346396ae18462c7393c1ac5c3f17237bd89b2 +F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799 F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71 @@ -1063,7 +1063,7 @@ F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2 F test/symlink.test 511db82662446bb0d3619002422760ef8e4b1122 F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85 -F test/syscall.test 2aa9e111b79fb385681ff8940124def6f8faab87 +F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 F test/tabfunc01.test cc33684f9480fcf1fd5ce287ac28d22971cad1cc F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 80398fd44fb232193450103808e1854e0eba5652 -R 084dee05e1353887f6af0d88670b22d0 +P f71249d3db9242b8f38955db51a7a5789d002803 +R 31817b68212f6684c4e9fbfebdae658d U dan -Z 72572e009a3ce3b7747f3257ebf7dfc7 +Z 17d90a7cade21886dca3e4bdfc08ed4c diff --git a/manifest.uuid b/manifest.uuid index b66c39a6ae..35202dd686 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f71249d3db9242b8f38955db51a7a5789d002803 \ No newline at end of file +8a6e4147a680ad6c5fdd588468b6daac82349d2c \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 3d113301b8..a3bb45bdb9 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -480,7 +480,11 @@ static struct unix_syscall { #endif #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent) - { "lstat", (sqlite3_syscall_ptr)lstat, 0 }, +#if defined(HAVE_LSTAT) + { "lstat", (sqlite3_syscall_ptr)lstat, 0 }, +#else + { "lstat", (sqlite3_syscall_ptr)0, 0 }, +#endif #define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) }; /* End of the overrideable system calls */ @@ -5971,7 +5975,7 @@ static int unixFullPathname( int nOut, /* Size of output buffer in bytes */ char *zOut /* Output buffer */ ){ -#if !defined(HAVE_READLINK) +#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT) return mkFullPathname(zPath, zOut, nOut); #else int rc = SQLITE_OK; @@ -5999,7 +6003,7 @@ static int unixFullPathname( struct stat buf; if( osLstat(zIn, &buf)!=0 ){ if( errno!=ENOENT ){ - rc = unixLogError(SQLITE_CANTOPEN_BKPT, "stat", zIn); + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn); } }else{ bLink = S_ISLNK(buf.st_mode); @@ -6044,7 +6048,7 @@ static int unixFullPathname( sqlite3_free(zDel); return rc; -#endif /* HAVE_READLINK */ +#endif /* HAVE_READLINK && HAVE_LSTAT */ } diff --git a/src/vxworks.h b/src/vxworks.h index 60c41a19b8..e7013c3f66 100644 --- a/src/vxworks.h +++ b/src/vxworks.h @@ -28,4 +28,5 @@ #define OS_VXWORKS 0 #define HAVE_FCHOWN 1 #define HAVE_READLINK 1 +#define HAVE_LSTAT 1 #endif /* defined(_WRS_KERNEL) */ diff --git a/test/oserror.test b/test/oserror.test index 5fa7f98eb5..246a9d4023 100644 --- a/test/oserror.test +++ b/test/oserror.test @@ -95,7 +95,7 @@ do_test 1.4.1 { do_re_test 1.4.2 { lindex $::log 0 -} {^os_unix.c:\d*: \(\d+\) (open|readlink)\(.*test.db\) - } +} {^os_unix.c:\d*: \(\d+\) (open|readlink|lstat)\(.*test.db\) - } #-------------------------------------------------------------------------- # Tests oserror-1.* test failures in the unlink() system call. diff --git a/test/syscall.test b/test/syscall.test index a935957d39..5716b35a6e 100644 --- a/test/syscall.test +++ b/test/syscall.test @@ -61,7 +61,7 @@ foreach s { fcntl read pread write pwrite fchmod fallocate pread64 pwrite64 unlink openDirectory mkdir rmdir statvfs fchown geteuid umask mmap munmap mremap - getpagesize readlink + getpagesize readlink lstat } { if {[test_syscall exists $s]} {lappend syscall_list $s} } From 2aac8c7ba1e84a90b36906926336a4558360a02e Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Jan 2016 22:08:11 +0000 Subject: [PATCH 168/570] Fix a compiler warning about doing pointer arithmetic involving a NULL pointer even though the result of computation is never used. FossilOrigin-Name: 7c49a9478bd36564e81d33458ca1f4063ddaca83 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbesort.c | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 827a3d5126..5a7fe0a637 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Replace\sthe\sOP_SetIfNotPos\soperator\swith\sOP_OffsetLimit\sin\sthe\sVDBE,\sfor\nsimpler\sand\ssmaller\scode. -D 2016-01-25T15:57:29.060 +C Fix\sa\scompiler\swarning\sabout\sdoing\spointer\sarithmetic\sinvolving\sa\sNULL\spointer\neven\sthough\sthe\sresult\sof\scomputation\sis\snever\sused. +D 2016-01-25T22:08:11.961 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -417,7 +417,7 @@ F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e F src/vdbeaux.c 757f86e6fef8efb3dd4226cb31e2e82b9c44c883 F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 -F src/vdbesort.c 0971557e5d3c289e46f56a52aed2197c13251de7 +F src/vdbesort.c 3bb1f1f03162e6d223da623714d8e93fcaeac658 F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 F src/vtab.c 320682cca733115b4cbe71320b5c5eeb1074ebde F src/vxworks.h 974e7d9a98f602d6310d563e1dc4e08f9fc48e47 @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 30671345b1c1ee55a2d1aa17273213f1849efd81 -R f342889ba3409bd63b1cf54d88bfe0e2 +P 7ac017a498b6fb28343eef2d24e400c7800660d6 +R aa5d51a793ca6d0a7613986a1affa54a U drh -Z e7c5fc86067d4269675714897cec0b51 +Z 142832d114ade2d8f5ff5fab3faed40b diff --git a/manifest.uuid b/manifest.uuid index 276ef7a03f..d34f9b48c8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7ac017a498b6fb28343eef2d24e400c7800660d6 \ No newline at end of file +7c49a9478bd36564e81d33458ca1f4063ddaca83 \ No newline at end of file diff --git a/src/vdbesort.c b/src/vdbesort.c index e095f80912..22029aa6bf 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -1837,7 +1837,9 @@ int sqlite3VdbeSorterWrite( pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory]; pSorter->iMemory += ROUND8(nReq); - pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory); + if( pSorter->list.pList ){ + pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory); + } }else{ pNew = (SorterRecord *)sqlite3Malloc(nReq); if( pNew==0 ){ From a72d15b5f0bbc0d67eb117624df7f005ad89c443 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Jan 2016 23:19:58 +0000 Subject: [PATCH 169/570] Minor changes to the autoconf/README.txt file. FossilOrigin-Name: 6df8a9c00a9d067f67d492da7a4617908070c6c0 --- autoconf/README.txt | 16 +++++++++++----- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/autoconf/README.txt b/autoconf/README.txt index a581c39dea..114831ec5e 100644 --- a/autoconf/README.txt +++ b/autoconf/README.txt @@ -9,6 +9,12 @@ This package contains: * a Makefile.msc and sqlite3.rc for building with Microsoft Visual C++ on Windows. +SUMMARY OF HOW TO BUILD +======================= + + unix: ./configure; make + windows: nmake /f Makefile.msc + BUILDING ON POSIX ================= @@ -47,7 +53,7 @@ Using Microsoft Visual C++ 2005 (or later) is recommended. Several Windows platform variants may be built by adding additional macros to the NMAKE command line. -BUILDING FOR WINRT 8.0 +Building for WinRT 8.0 ---------------------- FOR_WINRT=1 @@ -58,7 +64,7 @@ NMAKE command line as well: "NSDKLIBPATH=%WindowsSdkDir%\..\8.0\lib\win8\um\x86" -BUILDING FOR WINRT 8.1 +Building for WinRT 8.1 ---------------------- FOR_WINRT=1 @@ -69,7 +75,7 @@ NMAKE command line as well: "NSDKLIBPATH=%WindowsSdkDir%\..\8.1\lib\winv6.3\um\x86" -BUILDING FOR UAP 10.0 +Building for UAP 10.0 --------------------- FOR_WINRT=1 FOR_UAP=1 @@ -82,7 +88,7 @@ NMAKE command line as well: "PSDKLIBPATH=%WindowsSdkDir%\..\10\lib\10.0.10586.0\um\x86" "NUCRTLIBPATH=%UniversalCRTSdkDir%\..\10\lib\10.0.10586.0\ucrt\x86" -BUILDING FOR THE WINDOWS 10 SDK +Building for the Windows 10 SDK ------------------------------- FOR_WIN10=1 @@ -90,7 +96,7 @@ BUILDING FOR THE WINDOWS 10 SDK Using Microsoft Visual C++ 2015 (or later) is required. When using the above, no other macros should be needed on the NMAKE command line. -USING PREPROCESSOR DEFINES +Other preprocessor defines -------------------------- Additionally, preprocessor defines may be specified by using the OPTS macro diff --git a/manifest b/manifest index 0f3e8b7b8d..48622ea281 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C More\supdates\sto\sthe\sREADME. -D 2016-01-23T21:57:46.170 +C Minor\schanges\sto\sthe\sautoconf/README.txt\sfile. +D 2016-01-25T23:19:58.651 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -13,7 +13,7 @@ F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 1c1657650775960804945dc392e14d9e43c5ed84 F autoconf/Makefile.msc 68ed752a809b611d97b95d8572a34fe6fd1196f1 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 -F autoconf/README.txt fc86867528c500dfd691620e623bfe6799c98d14 +F autoconf/README.txt e3a5cf0ba2d8944c71ca1eb7c06c15f52bfca131 F autoconf/configure.ac 7b1ea0dcaf49fafba262ce4b0ee8cb3281b555d1 F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 @@ -1421,7 +1421,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4ce60fa42d8486d219d40d25d785d7f2cabe5e06 -R 9ddb76e24748b77caceaf34a8b255b23 -U mistachkin -Z 8a8dd4db0d2ee1de0599573a5cb1355c +P 9f02868df71d902a2b9118d0b06df18ee92b666b +R 9aeab9bcdca09d2b8e9198ca7dec65cb +U drh +Z 1be43b84d3a6e7c2425c5f0806c1fce0 diff --git a/manifest.uuid b/manifest.uuid index c53057578b..4cab521d6d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9f02868df71d902a2b9118d0b06df18ee92b666b \ No newline at end of file +6df8a9c00a9d067f67d492da7a4617908070c6c0 \ No newline at end of file From f0fc9929369cda0c7416174d43a299188b8beabf Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 26 Jan 2016 00:12:42 +0000 Subject: [PATCH 170/570] Remove an unused variable. FossilOrigin-Name: 1c2656c1d37906230edc142d3a4253b16b6e925f --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/os_unix.c | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 33b8dc8b5c..ea40dd333f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Only\suse\slstat()\sif\sthe\sHAVE_LSTAT\smacro\sis\sdefined.\sFix\ssome\stest\sfile\sissues. -D 2016-01-25T18:43:05.007 +C Remove\san\sunused\svariable. +D 2016-01-26T00:12:42.634 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -329,7 +329,7 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c 4c217111d7bdebbd7a9b47cf11f434420da432e7 +F src/os_unix.c e9e1e6a49892a76fe1fd167b1d475eeddaf1ccb3 F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f71249d3db9242b8f38955db51a7a5789d002803 -R 31817b68212f6684c4e9fbfebdae658d -U dan -Z 17d90a7cade21886dca3e4bdfc08ed4c +P 8a6e4147a680ad6c5fdd588468b6daac82349d2c +R d2cf53f7b50c768b631d5f18bba143b9 +U drh +Z 592370e14c792642f017f87ac074cb77 diff --git a/manifest.uuid b/manifest.uuid index 35202dd686..78b51cd18f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8a6e4147a680ad6c5fdd588468b6daac82349d2c \ No newline at end of file +1c2656c1d37906230edc142d3a4253b16b6e925f \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index a3bb45bdb9..cdbcd2c8e0 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -5981,7 +5981,6 @@ static int unixFullPathname( int rc = SQLITE_OK; int nByte; int nLink = 1; /* Number of symbolic links followed so far */ - int bLink; /* True for a symbolic link */ const char *zIn = zPath; /* Input path for each iteration of loop */ char *zDel = 0; From 23496702622549d23f22639b7e2f5c47cfeba9a6 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 26 Jan 2016 13:56:42 +0000 Subject: [PATCH 171/570] Ensure that unixFullpathname() always nul-terminates its output buffer, even when returning an error. FossilOrigin-Name: 4a4385564dd3887a7953820b60c99d6ce289f96a --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/os_unix.c | 31 +++++++++++++++++++------------ test/symlink.test | 1 - 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/manifest b/manifest index ea40dd333f..2765e104fb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunused\svariable. -D 2016-01-26T00:12:42.634 +C Ensure\sthat\sunixFullpathname()\salways\snul-terminates\sits\soutput\sbuffer,\seven\swhen\sreturning\san\serror. +D 2016-01-26T13:56:42.494 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -329,7 +329,7 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c e9e1e6a49892a76fe1fd167b1d475eeddaf1ccb3 +F src/os_unix.c 5bb20172d0c9a6afcfa829a88c406970593c848d F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 @@ -1061,7 +1061,7 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2 -F test/symlink.test 511db82662446bb0d3619002422760ef8e4b1122 +F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849 F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85 F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 8a6e4147a680ad6c5fdd588468b6daac82349d2c -R d2cf53f7b50c768b631d5f18bba143b9 -U drh -Z 592370e14c792642f017f87ac074cb77 +P 1c2656c1d37906230edc142d3a4253b16b6e925f +R 6c0824142ba46339a29c32338146479b +U dan +Z e95289d1bfc22539e02b85ec76fd69c7 diff --git a/manifest.uuid b/manifest.uuid index 78b51cd18f..72144560be 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1c2656c1d37906230edc142d3a4253b16b6e925f \ No newline at end of file +4a4385564dd3887a7953820b60c99d6ce289f96a \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index cdbcd2c8e0..81422f215d 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -5955,7 +5955,12 @@ static int mkFullPathname( iOff = sqlite3Strlen30(zOut); zOut[iOff++] = '/'; } - if( (iOff+nPath+1)>nOut ) return SQLITE_CANTOPEN_BKPT; + if( (iOff+nPath+1)>nOut ){ + /* SQLite assumes that xFullPathname() nul-terminates the output buffer + ** even if it returns an error. */ + zOut[iOff] = '\0'; + return SQLITE_CANTOPEN_BKPT; + } sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath); return SQLITE_OK; } @@ -6020,15 +6025,17 @@ static int unixFullPathname( nByte = osReadlink(zIn, zDel, nOut-1); if( nByte<0 ){ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn); - }else if( zDel[0]!='/' ){ - int n; - for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); - if( nByte+n+1>nOut ){ - rc = SQLITE_CANTOPEN_BKPT; - }else{ - memmove(&zDel[n], zDel, nByte+1); - memcpy(zDel, zIn, n); - nByte += n; + }else{ + if( zDel[0]!='/' ){ + int n; + for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); + if( nByte+n+1>nOut ){ + rc = SQLITE_CANTOPEN_BKPT; + }else{ + memmove(&zDel[n], zDel, nByte+1); + memcpy(zDel, zIn, n); + nByte += n; + } } zDel[nByte] = '\0'; } @@ -6037,8 +6044,8 @@ static int unixFullPathname( zIn = zDel; } - if( rc==SQLITE_OK ){ - assert( zIn!=zOut || zIn[0]=='/' ); + assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' ); + if( rc==SQLITE_OK && zIn!=zOut ){ rc = mkFullPathname(zIn, zOut, nOut); } if( bLink==0 ) break; diff --git a/test/symlink.test b/test/symlink.test index e9e5f3c305..949102cf8a 100644 --- a/test/symlink.test +++ b/test/symlink.test @@ -181,7 +181,6 @@ do_test 4.4.0 { } {} do_test 4.4.1 { db close - breakpoint sqlite3 db w/test.db db eval { SELECT * FROM t1 } } {hello world} From fee981e5b97a79b26308c2dc3f946264e4ee8028 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 26 Jan 2016 17:08:22 +0000 Subject: [PATCH 172/570] Enhance fts5txt2db.tcl, a script used to generate fts5/fts4 databases for performance testing. FossilOrigin-Name: c646e40350e5aa91abcf52de61fb31275bad38f9 --- ext/fts5/tool/fts5txt2db.tcl | 200 +++++++++++++++++++++++++---------- manifest | 12 +-- manifest.uuid | 2 +- 3 files changed, 152 insertions(+), 62 deletions(-) diff --git a/ext/fts5/tool/fts5txt2db.tcl b/ext/fts5/tool/fts5txt2db.tcl index c22c5dae72..c6a58e6edd 100644 --- a/ext/fts5/tool/fts5txt2db.tcl +++ b/ext/fts5/tool/fts5txt2db.tcl @@ -1,13 +1,127 @@ -proc usage {} { - puts stderr "$::argv0 ?OPTIONS? DATABASE FILE1..." +#------------------------------------------------------------------------- +# Command line options processor. +# +proc command_line_error {O E {msg ""}} { + if {$msg != ""} { + puts stderr "Error: $msg" + puts stderr "" + } + + set L [list] + foreach o $O { + if {[llength $o]==1} { + lappend L [string toupper $o] + } + } + + puts stderr "Usage: $::argv0 ?SWITCHES? $L" puts stderr "" - puts stderr "Options are" - puts stderr " -fts5" - puts stderr " -fts4" - puts stderr " -colsize " - puts stderr { + puts stderr "Switches are:" + foreach o $O { + if {[llength $o]==3} { + foreach {a b c} $o {} + puts stderr [format " -%-15s %s (default \"%s\")" "$a VAL" $c $b] + } elseif {[llength $o]==2} { + foreach {a b} $o {} + puts stderr [format " -%-15s %s" $a $b] + } + } + puts stderr "" + puts stderr $E + exit -1 +} + +proc process_command_line {avar lArgs O E} { + + upvar $avar A + set zTrailing "" ;# True if ... is present in $O + set lPosargs [list] + + # Populate A() with default values. Also, for each switch in the command + # line spec, set an entry in the idx() array as follows: + # + # {tblname t1 "table name to use"} + # -> [set idx(-tblname) {tblname t1 "table name to use"} + # + # For each position parameter, append its name to $lPosargs. If the ... + # specifier is present, set $zTrailing to the name of the prefix. + # + foreach o $O { + set nm [lindex $o 0] + set nArg [llength $o] + switch -- $nArg { + 1 { + if {[string range $nm end-2 end]=="..."} { + set zTrailing [string range $nm 0 end-3] + } else { + lappend lPosargs $nm + } + } + 2 { + set A($nm) 0 + set idx(-$nm) $o + } + 3 { + set A($nm) [lindex $o 1] + set idx(-$nm) $o + } + default { + error "Error in command line specification" + } + } + } + + # Set explicitly specified option values + # + set nArg [llength $lArgs] + for {set i 0} {$i < $nArg} {incr i} { + set opt [lindex $lArgs $i] + if {[string range $opt 0 0]!="-" || $opt=="--"} break + set c [array names idx "${opt}*"] + if {[llength $c]==0} { command_line_error $O $E "Unrecognized option: $opt"} + if {[llength $c]>1} { command_line_error $O $E "Ambiguous option: $opt"} + + if {[llength $idx($c)]==3} { + if {$i==[llength $lArgs]-1} { + command_line_error $O $E "Option requires argument: $c" + } + incr i + set A([lindex $idx($c) 0]) [lindex $lArgs $i] + } else { + set A([lindex $idx($c) 0]) 1 + } + } + + # Deal with position arguments. + # + set nPosarg [llength $lPosargs] + set nRem [expr $nArg - $i] + if {$nRem < $nPosarg || ($zTrailing=="" && $nRem > $nPosarg)} { + command_line_error $O $E + } + for {set j 0} {$j < $nPosarg} {incr j} { + set A([lindex $lPosargs $j]) [lindex $lArgs [expr $j+$i]] + } + if {$zTrailing!=""} { + set A($zTrailing) [lrange $lArgs [expr $j+$i] end] + } +} +# End of command line options processor. +#------------------------------------------------------------------------- + + +process_command_line A $argv { + {fts5 "use fts5"} + {fts4 "use fts4"} + {colsize "10 10 10" "list of column sizes"} + {tblname "t1" "table name to create"} + {detail "full" "Fts5 detail mode to use"} + {repeat 1 "Load each file this many times"} + database + file... +} { This script is designed to create fts4/5 tables with more than one column. The -colsize option should be set to a Tcl list of integer values, one for each column in the table. Each value is the number of tokens that will be @@ -22,59 +136,27 @@ of the -colsize list. The next N2 are used for the second column of the first row, and so on. Rows are added to the table until the entire list of tokens is exhausted. } - exit -1 + +if {$A(fts4)} { + set A(fts) fts4 +} else { + set A(fts) fts5 } -set O(aColSize) [list 10 10 10] -set O(tblname) t1 -set O(fts) fts5 - - -set options_with_values {-colsize} - -for {set i 0} {$i < [llength $argv]} {incr i} { - set opt [lindex $argv $i] - if {[string range $opt 0 0]!="-"} break - - if {[lsearch $options_with_values $opt]>=0} { - incr i - if {$i==[llength $argv]} usage - set val [lindex $argv $i] - } - - switch -- $opt { - -colsize { - set O(aColSize) $val - } - - -fts4 { - set O(fts) fts4 - } - - -fts5 { - set O(fts) fts5 - } - } -} - -if {$i > [llength $argv]-2} usage -set O(db) [lindex $argv $i] -set O(files) [lrange $argv [expr $i+1] end] - -sqlite3 db $O(db) +sqlite3 db $A(database) # Create the FTS table in the db. Return a list of the table columns. # proc create_table {} { - global O + global A set cols [list 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 z] - set nCol [llength $O(aColSize)] + set nCol [llength $A(colsize)] set cols [lrange $cols 0 [expr $nCol-1]] - set sql "CREATE VIRTUAL TABLE IF NOT EXISTS $O(tblname) USING $O(fts) (" + set sql "CREATE VIRTUAL TABLE IF NOT EXISTS $A(tblname) USING $A(fts) (" append sql [join $cols ,] - append sql ");" + if {$A(fts)=="fts5"} { append sql ",detail=$A(detail));" } db eval $sql return $cols @@ -89,27 +171,35 @@ proc readfile {file} { split $data } +proc repeat {L n} { + set res [list] + for {set i 0} {$i < $n} {incr i} { + set res [concat $res $L] + } + set res +} + # Load all the data into a big list of tokens. # set tokens [list] -foreach f $O(files) { - set tokens [concat $tokens [readfile $f]] +foreach f $A(file) { + set tokens [concat $tokens [repeat [readfile $f] $A(repeat)]] } set N [llength $tokens] set i 0 set cols [create_table] -set sql "INSERT INTO $O(tblname) VALUES(\$[lindex $cols 0]" +set sql "INSERT INTO $A(tblname) VALUES(\$R([lindex $cols 0])" foreach c [lrange $cols 1 end] { - append sql ", \$A($c)" + append sql ", \$R($c)" } append sql ")" db eval BEGIN while {$i < $N} { - foreach c $cols s $O(aColSize) { - set A($c) [lrange $tokens $i [expr $i+$s-1]] + foreach c $cols s $A(colsize) { + set R($c) [lrange $tokens $i [expr $i+$s-1]] incr i $s } db eval $sql diff --git a/manifest b/manifest index fbcb4d2d1b..32c610bbaf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sfts5\sproblem\swith\susing\sboth\sxPhraseFirst()\sand\sxPhraseFirstColumn()\swithin\sa\ssingle\sstatement\sin\sdetail=col\smode. -D 2016-01-23T18:51:59.865 +C Enhance\sfts5txt2db.tcl,\sa\sscript\sused\sto\sgenerate\sfts5/fts4\sdatabases\sfor\sperformance\stesting. +D 2016-01-26T17:08:22.193 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -189,7 +189,7 @@ F ext/fts5/test/fts5update.test 57c7012a7919889048947addae10e0613df45529 F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e F ext/fts5/test/fts5vocab.test 480d780aa6b699816c5066225fbd86f3a0239477 F ext/fts5/tool/fts5speed.tcl aaee41894b552df8fbf8616aad003b2ea9ba3221 -F ext/fts5/tool/fts5txt2db.tcl c374c4c4797e8cdfadabdfaeeb5412dcd6686e84 +F ext/fts5/tool/fts5txt2db.tcl ae308338b2da1646dea456ab66706acdde8c714e F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093 F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45 F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ceccc9ad788fb4da9120915741995b9f088f85ff -R e7d7753020b6f70b109a92a8ac037ba7 +P 72d53699bf0dcdb9d2a22e229989d7435f061399 +R e572f7330a1bdca73a606e620f2735b9 U dan -Z 648645363fb131dd10e5d7321a173b9d +Z 9f71d918f9bd09bf4fa550347b1ed369 diff --git a/manifest.uuid b/manifest.uuid index 1891619c18..0db14bcc12 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -72d53699bf0dcdb9d2a22e229989d7435f061399 \ No newline at end of file +c646e40350e5aa91abcf52de61fb31275bad38f9 \ No newline at end of file From 1c16bccb79888f775b4e1fbdca00d8f272afed17 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 26 Jan 2016 19:30:49 +0000 Subject: [PATCH 173/570] Improve the performance of fts5 column filters on detail=col tables. FossilOrigin-Name: 249a2d070c34bf884a04cb248b9691e239f2871c --- ext/fts5/fts5_index.c | 68 ++++++++++++++++++++++++++++++---- ext/fts5/test/fts5ac.test | 2 +- ext/fts5/test/fts5simple3.test | 44 ++++++++++++++++++++++ ext/fts5/tool/fts5speed.tcl | 2 + manifest | 17 +++++---- manifest.uuid | 2 +- 6 files changed, 117 insertions(+), 18 deletions(-) create mode 100644 ext/fts5/test/fts5simple3.test diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index e147199ef8..6d442de799 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -5003,6 +5003,53 @@ static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){ } } +/* +** xSetOutputs callback used when: detail=col when there is a column filter. +** +** * detail=col, +** * there is a column filter, and +** * the table contains 32 or fewer columns. +*/ +static void fts5IterSetOutputs_Col32(Fts5Iter *pIter, Fts5SegIter *pSeg){ + Fts5Colset *pColset = pIter->pColset; + pIter->base.iRowid = pSeg->iRowid; + + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); + assert( pColset ); + + fts5BufferZero(&pIter->poslist); + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ + int i; + int iPrev = 0; + u32 m = 0; + u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset]; + u8 *pEnd = (u8*)&a[pSeg->nPos]; + + while( aposlist.p; + for(i=0; inCol; i++){ + int iCol = pColset->aiCol[i]; + if( m & (1 << iCol) ){ + *a++ = (iCol - iPrev) + 2; + iPrev = iCol; + } + } + pIter->poslist.n = a - pIter->poslist.p; + + }else{ + fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); + } + + pIter->base.pData = pIter->poslist.p; + pIter->base.nData = pIter->poslist.n; +} + /* ** xSetOutputs callback used by detail=col when there is a column filter. */ @@ -5083,9 +5130,9 @@ static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){ } } -static void fts5IterSetOutputCb(Fts5Iter *pIter){ - int eDetail = pIter->pIndex->pConfig->eDetail; - if( eDetail==FTS5_DETAIL_NONE ){ +static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){ + Fts5Config *pConfig = pIter->pIndex->pConfig; + if( pConfig->eDetail==FTS5_DETAIL_NONE ){ pIter->xSetOutputs = fts5IterSetOutputs_None; } @@ -5093,13 +5140,18 @@ static void fts5IterSetOutputCb(Fts5Iter *pIter){ pIter->xSetOutputs = fts5IterSetOutputs_Nocolset; } - else if( eDetail==FTS5_DETAIL_FULL ){ + else if( pConfig->eDetail==FTS5_DETAIL_FULL ){ pIter->xSetOutputs = fts5IterSetOutputs_Full; } else{ - assert( eDetail==FTS5_DETAIL_COLUMNS ); - pIter->xSetOutputs = fts5IterSetOutputs_Col; + assert( pConfig->eDetail==FTS5_DETAIL_COLUMNS ); + if( pConfig->nCol<=32 ){ + pIter->xSetOutputs = fts5IterSetOutputs_Col32; + sqlite3Fts5BufferSize(pRc, &pIter->poslist, pConfig->nCol); + }else{ + pIter->xSetOutputs = fts5IterSetOutputs_Col; + } } } @@ -5166,8 +5218,8 @@ int sqlite3Fts5IndexQuery( if( p->rc==SQLITE_OK ){ Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst]; pRet->pColset = pColset; - fts5IterSetOutputCb(pRet); - if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); + fts5IterSetOutputCb(&p->rc, pRet); + if( p->rc==SQLITE_OK && pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); } if( p->rc ){ sqlite3Fts5IterClose(&pRet->base); diff --git a/ext/fts5/test/fts5ac.test b/ext/fts5/test/fts5ac.test index a5a522a466..61b3230772 100644 --- a/ext/fts5/test/fts5ac.test +++ b/ext/fts5/test/fts5ac.test @@ -158,8 +158,8 @@ foreach {tn2 sql} { #------------------------------------------------------------------------- # foreach {tn expr} { - 1.2 "a OR b" 1.1 "a AND b" + 1.2 "a OR b" 1.3 "o" 1.4 "b q" 1.5 "e a e" diff --git a/ext/fts5/test/fts5simple3.test b/ext/fts5/test/fts5simple3.test new file mode 100644 index 0000000000..b84a3e56dd --- /dev/null +++ b/ext/fts5/test/fts5simple3.test @@ -0,0 +1,44 @@ +# 2015 September 05 +# +# 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. +# +#************************************************************************* +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5simple3 + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +fts5_aux_test_functions db + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, c, detail=col); + INSERT INTO t1 VALUES('a', 'b', 'c'); + INSERT INTO t1 VALUES('x', 'x', 'x'); +} + +do_execsql_test 1.1 { + SELECT rowid, fts5_test_collist(t1) FROM t1('a:a'); +} {1 0.0} + +do_execsql_test 1.2 { + SELECT rowid, fts5_test_collist(t1) FROM t1('b:x'); +} {2 0.1} + +do_execsql_test 1.3 { + SELECT rowid, fts5_test_collist(t1) FROM t1('b:a'); +} {} + + +finish_test + diff --git a/ext/fts5/tool/fts5speed.tcl b/ext/fts5/tool/fts5speed.tcl index 1b060ea759..8e1c7f3899 100644 --- a/ext/fts5/tool/fts5speed.tcl +++ b/ext/fts5/tool/fts5speed.tcl @@ -11,6 +11,8 @@ set Q { {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'c:t*'"} {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t* OR b:t* OR c:t* OR d:t* OR e:t* OR f:t* OR g:t*'"} {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t*'"} + + {2 "SELECT count(*) FROM t1 WHERE t1 MATCH 'c:the'"} } proc usage {} { diff --git a/manifest b/manifest index 32c610bbaf..2e90cb8536 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sfts5txt2db.tcl,\sa\sscript\sused\sto\sgenerate\sfts5/fts4\sdatabases\sfor\sperformance\stesting. -D 2016-01-26T17:08:22.193 +C Improve\sthe\sperformance\sof\sfts5\scolumn\sfilters\son\sdetail=col\stables. +D 2016-01-26T19:30:49.768 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -103,7 +103,7 @@ F ext/fts5/fts5_buffer.c f6e0c6018ffc8e39fc0b333b5daa8b8d528ae6e4 F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 F ext/fts5/fts5_expr.c a66b9694519d9c336d9bdbd46ea22e7e14aef412 F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c 722d8717e3167dd05fa48af970352932052da318 +F ext/fts5/fts5_index.c b34b7257f73929dc1b25c420aad2453dcbe36128 F ext/fts5/fts5_main.c 3886bbfc5ac1d9df29979823ddf2b68241e1127e F ext/fts5/fts5_storage.c 2a1f44deae090cd711f02cec0c2af8e660360d24 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -118,7 +118,7 @@ F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba F ext/fts5/test/fts5_common.tcl 61ff0d1a29d98a91c4553b20b3f410d858834ee9 F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b -F ext/fts5/test/fts5ac.test dec95549e007dd9be52aa435cdcd0f08e14e64d0 +F ext/fts5/test/fts5ac.test 55cad4275a1f5acabfe14d8442a8046b47e49e5f F ext/fts5/test/fts5ad.test 0ddaa5b692ff220100ee396228838f4331399eaa F ext/fts5/test/fts5ae.test 612dcb51f4069226791ff14c17dbfb3138c56f20 F ext/fts5/test/fts5af.test be858a96b1f5de66ba6d64f0021bd8b2408e126c @@ -176,6 +176,7 @@ F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17 F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6 F ext/fts5/test/fts5simple.test 2bc6451cbe887a9215f5b14ae307c70d850344c9 F ext/fts5/test/fts5simple2.test 98377ae1ff7749a42c21fe1a139c1ed312522c46 +F ext/fts5/test/fts5simple3.test e671b36bc4dbd4f5095e66cb04473cba9f680f53 F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48 F ext/fts5/test/fts5synonym2.test aa4c43bd3b691ff80f658cb064f5ab40690e834e F ext/fts5/test/fts5tok1.test beb894c6f3468f10a574302f69ebe4436b0287c7 @@ -188,7 +189,7 @@ F ext/fts5/test/fts5unindexed.test e9539d5b78c677315e7ed8ea911d4fd25437c680 F ext/fts5/test/fts5update.test 57c7012a7919889048947addae10e0613df45529 F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e F ext/fts5/test/fts5vocab.test 480d780aa6b699816c5066225fbd86f3a0239477 -F ext/fts5/tool/fts5speed.tcl aaee41894b552df8fbf8616aad003b2ea9ba3221 +F ext/fts5/tool/fts5speed.tcl 47f0031e6ac564964f4f4805e439ea665e848df2 F ext/fts5/tool/fts5txt2db.tcl ae308338b2da1646dea456ab66706acdde8c714e F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093 F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45 @@ -1419,7 +1420,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 72d53699bf0dcdb9d2a22e229989d7435f061399 -R e572f7330a1bdca73a606e620f2735b9 +P c646e40350e5aa91abcf52de61fb31275bad38f9 +R a44979856d96ea38951595ad6e15598a U dan -Z 9f71d918f9bd09bf4fa550347b1ed369 +Z a6d46df0ea079f8f36131bee8e2cf5b7 diff --git a/manifest.uuid b/manifest.uuid index 0db14bcc12..54ccb7acb1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c646e40350e5aa91abcf52de61fb31275bad38f9 \ No newline at end of file +249a2d070c34bf884a04cb248b9691e239f2871c \ No newline at end of file From 18205c781d4bb15d5a26801844212f231a4aed9d Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 26 Jan 2016 20:08:50 +0000 Subject: [PATCH 174/570] Further minor performance improvements and code-size reductions related to fts5 column filters on detail=col tables. FossilOrigin-Name: b4ac61aeee976296e7719949cd4fb496147a29e8 --- ext/fts5/fts5_index.c | 119 +++++++++++++++--------------------------- manifest | 12 ++--- manifest.uuid | 2 +- 3 files changed, 50 insertions(+), 83 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 6d442de799..ca3feb86f7 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -5004,96 +5004,63 @@ static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){ } /* -** xSetOutputs callback used when: detail=col when there is a column filter. -** -** * detail=col, -** * there is a column filter, and -** * the table contains 32 or fewer columns. +** xSetOutputs callback used by detail=col when there is a column filter +** and there are 100 or more columns. Also called as a fallback from +** fts5IterSetOutputs_Col100 if the column-list spans more than one page. */ -static void fts5IterSetOutputs_Col32(Fts5Iter *pIter, Fts5SegIter *pSeg){ - Fts5Colset *pColset = pIter->pColset; - pIter->base.iRowid = pSeg->iRowid; - - assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); - assert( pColset ); - +static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){ fts5BufferZero(&pIter->poslist); - if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ - int i; - int iPrev = 0; - u32 m = 0; - u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset]; - u8 *pEnd = (u8*)&a[pSeg->nPos]; - - while( aposlist.p; - for(i=0; inCol; i++){ - int iCol = pColset->aiCol[i]; - if( m & (1 << iCol) ){ - *a++ = (iCol - iPrev) + 2; - iPrev = iCol; - } - } - pIter->poslist.n = a - pIter->poslist.p; - - }else{ - fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); - } - + fts5SegiterPoslist(pIter->pIndex, pSeg, pIter->pColset, &pIter->poslist); + pIter->base.iRowid = pSeg->iRowid; pIter->base.pData = pIter->poslist.p; pIter->base.nData = pIter->poslist.n; } /* -** xSetOutputs callback used by detail=col when there is a column filter. +** xSetOutputs callback used when: +** +** * detail=col, +** * there is a column filter, and +** * the table contains 100 or fewer columns. +** +** The last point is to ensure all column numbers are stored as +** single-byte varints. */ -static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){ - Fts5Colset *pColset = pIter->pColset; - pIter->base.iRowid = pSeg->iRowid; +static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){ assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); - assert( pColset ); + assert( pIter->pColset ); - if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ - /* All data is stored on the current page. Populate the output - ** variables to point into the body of the page object. */ - Fts5PoslistWriter writer = {0}; - const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset]; - int n = pSeg->nPos; - int iCol = 0; - int iCVal = pColset->aiCol[0]; - i64 iPos = 0; - int iOff = 0; + if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){ + fts5IterSetOutputs_Col(pIter, pSeg); + }else{ + u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset]; + u8 *pEnd = (u8*)&a[pSeg->nPos]; + int iPrev = 0; + int *aiCol = pIter->pColset->aiCol; + int *aiColEnd = &aiCol[pIter->pColset->nCol]; - fts5BufferZero(&pIter->poslist); - while( 0==sqlite3Fts5PoslistNext64(a, n, &iOff, &iPos) ){ - while( iPos>=iCVal ){ - if( iPos==iCVal ){ - sqlite3Fts5PoslistWriterAppend(&pIter->poslist, &writer, iPos); - } - if( ++iCol>=pColset->nCol ) goto setoutputs_col_out; - assert( pColset->aiCol[iCol]>iCVal ); - iCVal = pColset->aiCol[iCol]; + u8 *aOut = pIter->poslist.p; + int iPrevOut = 0; + + pIter->base.iRowid = pSeg->iRowid; + + while( aposlist); - fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); - } - setoutputs_col_out: - pIter->base.pData = pIter->poslist.p; - pIter->base.nData = pIter->poslist.n; + pIter->base.pData = pIter->poslist.p; + pIter->base.nData = aOut - pIter->poslist.p; + } } /* @@ -5146,8 +5113,8 @@ static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){ else{ assert( pConfig->eDetail==FTS5_DETAIL_COLUMNS ); - if( pConfig->nCol<=32 ){ - pIter->xSetOutputs = fts5IterSetOutputs_Col32; + if( pConfig->nCol<=100 ){ + pIter->xSetOutputs = fts5IterSetOutputs_Col100; sqlite3Fts5BufferSize(pRc, &pIter->poslist, pConfig->nCol); }else{ pIter->xSetOutputs = fts5IterSetOutputs_Col; diff --git a/manifest b/manifest index 2e90cb8536..173bd3a03a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\sthe\sperformance\sof\sfts5\scolumn\sfilters\son\sdetail=col\stables. -D 2016-01-26T19:30:49.768 +C Further\sminor\sperformance\simprovements\sand\scode-size\sreductions\srelated\sto\sfts5\scolumn\sfilters\son\sdetail=col\stables. +D 2016-01-26T20:08:50.348 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -103,7 +103,7 @@ F ext/fts5/fts5_buffer.c f6e0c6018ffc8e39fc0b333b5daa8b8d528ae6e4 F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 F ext/fts5/fts5_expr.c a66b9694519d9c336d9bdbd46ea22e7e14aef412 F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c b34b7257f73929dc1b25c420aad2453dcbe36128 +F ext/fts5/fts5_index.c 5558bfbeaf364cc67f937e25753ceed8757cb6d1 F ext/fts5/fts5_main.c 3886bbfc5ac1d9df29979823ddf2b68241e1127e F ext/fts5/fts5_storage.c 2a1f44deae090cd711f02cec0c2af8e660360d24 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -1420,7 +1420,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c646e40350e5aa91abcf52de61fb31275bad38f9 -R a44979856d96ea38951595ad6e15598a +P 249a2d070c34bf884a04cb248b9691e239f2871c +R a28f5f4bedd812396ab85ff0aefd35c4 U dan -Z a6d46df0ea079f8f36131bee8e2cf5b7 +Z 56fb7a3fddaab518f0c4eb551a124662 diff --git a/manifest.uuid b/manifest.uuid index 54ccb7acb1..708359e9ec 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -249a2d070c34bf884a04cb248b9691e239f2871c \ No newline at end of file +b4ac61aeee976296e7719949cd4fb496147a29e8 \ No newline at end of file From d5be6f01cd7aa0aaa10334c6df01fd8118126d42 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 27 Jan 2016 07:28:33 +0000 Subject: [PATCH 175/570] Support building for Windows 10 desktop using 'MinCore.lib'. FossilOrigin-Name: 4bf89891fbb076364dc45a6bf3246efa6bc33d5d --- Makefile.msc | 12 ++++++++++-- autoconf/Makefile.msc | 2 +- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/os_win.c | 35 ++++++++++++++++++++++++++--------- tool/mkmsvcmin.tcl | 2 +- 6 files changed, 49 insertions(+), 24 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index ab0ba95d53..3427b8177a 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -890,7 +890,7 @@ LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib # When compiling for UAP, some extra linker options are also required. # -!IF $(FOR_UAP)!=0 +!IF $(FOR_UAP)!=0 || $(FOR_WIN10)!=0 LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib LTLINKOPTS = $(LTLINKOPTS) mincore.lib !IFDEF PSDKLIBPATH @@ -1343,12 +1343,20 @@ FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 # Standard options to testfixture. # TESTOPTS = --verbose=file --output=test-out.txt + +# Extra targets for the "all" target that require Tcl. +# +!IF $(NO_TCL)==0 +ALL_TCL_TARGETS = libtclsqlite3.lib +!ELSE +ALL_TCL_TARGETS = +!ENDIF # <> # This is the default Makefile target. The objects listed here # are what get build when you type just "make" with no arguments. # -all: dll libsqlite3.lib shell libtclsqlite3.lib +all: dll libsqlite3.lib shell $(ALL_TCL_TARGETS) # Dynamic link library section. # diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index fce62b2b8a..598e6517ae 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -785,7 +785,7 @@ LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib # When compiling for UAP, some extra linker options are also required. # -!IF $(FOR_UAP)!=0 +!IF $(FOR_UAP)!=0 || $(FOR_WIN10)!=0 LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib LTLINKOPTS = $(LTLINKOPTS) mincore.lib !IFDEF PSDKLIBPATH diff --git a/manifest b/manifest index a5a0c52194..07acca6779 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Performance\simprovements\sfor\sfts5,\sparticularly\sdetail=col\smode. -D 2016-01-26T20:19:55.225 +C Support\sbuilding\sfor\sWindows\s10\sdesktop\susing\s'MinCore.lib'. +D 2016-01-27T07:28:33.525 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 +F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -11,7 +11,7 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 1c1657650775960804945dc392e14d9e43c5ed84 -F autoconf/Makefile.msc 68ed752a809b611d97b95d8572a34fe6fd1196f1 +F autoconf/Makefile.msc 2ce3b1565a52d7083a1dbf57a1706fd14cc1ee0c F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt e9757a381e5ce2553dbaa6247bb8ad00eb8d87aa F autoconf/configure.ac 7b1ea0dcaf49fafba262ce4b0ee8cb3281b555d1 @@ -332,7 +332,7 @@ F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 5bb20172d0c9a6afcfa829a88c406970593c848d -F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 +F src/os_win.c ccf29ddded3e41e506b6bd98c1171aa0963b23f2 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 F src/pager.h 1c2a49143dfba9e69cc8159ef019f472ed8d260b @@ -1380,7 +1380,7 @@ F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh a29b14d54302b33fd892958f6895582ea90e4a45 F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8 -F tool/mkmsvcmin.tcl 93167a9e73383465b5716aa8dfa407409fccef1d +F tool/mkmsvcmin.tcl d57e6efc9428605f5418d0b235721ddf7b5d9c0b F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4003db4a49c6b623750e56f626fa492c8402067f b4ac61aeee976296e7719949cd4fb496147a29e8 -R 3b6b6d60ef77e3cea10b7a0c2c39f1b3 -U dan -Z 0416f9e7e1e3c46e17637bea5d350927 +P a3d7b8ac53f94d29a11362f193fd1967f30583df +R 626d84a8bdebb7b947f7c1e376ac97c5 +U mistachkin +Z 136b0599f548728406750a73608ec6f4 diff --git a/manifest.uuid b/manifest.uuid index 915fae58ae..20f348c1ae 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a3d7b8ac53f94d29a11362f193fd1967f30583df \ No newline at end of file +4bf89891fbb076364dc45a6bf3246efa6bc33d5d \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index c54bfd6a90..eda6cf59fb 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -76,6 +76,10 @@ # define NTDDI_WINBLUE 0x06030000 #endif +#ifndef NTDDI_WINTHRESHOLD +# define NTDDI_WINTHRESHOLD 0x06040000 +#endif + /* ** Check to see if the GetVersionEx[AW] functions are deprecated on the ** target system. GetVersionEx was first deprecated in Win8.1. @@ -88,6 +92,19 @@ # endif #endif +/* +** Check to see if the CreateFileMappingA function is supported on the +** target system. It is unavailable when using "mincore.lib" on Win10. +** When compiling for Windows 10, always assume "mincore.lib" is in use. +*/ +#ifndef SQLITE_WIN32_CREATEFILEMAPPINGA +# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINTHRESHOLD +# define SQLITE_WIN32_CREATEFILEMAPPINGA 0 +# else +# define SQLITE_WIN32_CREATEFILEMAPPINGA 1 +# endif +#endif + /* ** This constant should already be defined (in the "WinDef.h" SDK file). */ @@ -494,8 +511,9 @@ static struct win_syscall { #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) -#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ + (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) && \ + SQLITE_WIN32_CREATEFILEMAPPINGA { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, #else { "CreateFileMappingA", (SYSCALL)0, 0 }, @@ -725,8 +743,7 @@ static struct win_syscall { #define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent) -#if defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_GETVERSIONEX) && \ - SQLITE_WIN32_GETVERSIONEX +#if defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_GETVERSIONEX { "GetVersionExA", (SYSCALL)GetVersionExA, 0 }, #else { "GetVersionExA", (SYSCALL)0, 0 }, @@ -736,7 +753,7 @@ static struct win_syscall { LPOSVERSIONINFOA))aSyscall[34].pCurrent) #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ - defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX + SQLITE_WIN32_GETVERSIONEX { "GetVersionExW", (SYSCALL)GetVersionExW, 0 }, #else { "GetVersionExW", (SYSCALL)0, 0 }, @@ -1347,7 +1364,7 @@ DWORD sqlite3Win32Wait(HANDLE hObject){ ** the LockFileEx() API. */ -#if !defined(SQLITE_WIN32_GETVERSIONEX) || !SQLITE_WIN32_GETVERSIONEX +#if !SQLITE_WIN32_GETVERSIONEX # define osIsNT() (1) #elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI) # define osIsNT() (1) @@ -1368,7 +1385,7 @@ int sqlite3_win32_is_nt(void){ ** kernel. */ return 1; -#elif defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX +#elif SQLITE_WIN32_GETVERSIONEX if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){ #if defined(SQLITE_WIN32_HAS_ANSI) OSVERSIONINFOA sInfo; @@ -3952,7 +3969,7 @@ static int winShmMap( hMap = osCreateFileMappingW(pShmNode->hFile.h, NULL, PAGE_READWRITE, 0, nByte, NULL ); -#elif defined(SQLITE_WIN32_HAS_ANSI) +#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA hMap = osCreateFileMappingA(pShmNode->hFile.h, NULL, PAGE_READWRITE, 0, nByte, NULL ); @@ -4108,7 +4125,7 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){ pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect, (DWORD)((nMap>>32) & 0xffffffff), (DWORD)(nMap & 0xffffffff), NULL); -#elif defined(SQLITE_WIN32_HAS_ANSI) +#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect, (DWORD)((nMap>>32) & 0xffffffff), (DWORD)(nMap & 0xffffffff), NULL); diff --git a/tool/mkmsvcmin.tcl b/tool/mkmsvcmin.tcl index de01490c97..da0cd6283c 100644 --- a/tool/mkmsvcmin.tcl +++ b/tool/mkmsvcmin.tcl @@ -92,7 +92,7 @@ foreach i [lsort -integer [array names blocks]] { set data [string map [list " -I\$(TOP)\\src" ""] $data] set data [string map [list " /DEF:sqlite3.def" ""] $data] set data [string map [list " sqlite3.def" ""] $data] -set data [string map [list " libtclsqlite3.lib" ""] $data] +set data [string map [list " \$(ALL_TCL_TARGETS)" ""] $data] set data [string map [list "\$(TOP)\\src\\" "\$(TOP)\\"] $data] writeFile $toFileName $data From b89aeb6aa2cacdb57ef4bd73f980eb4f16ec52e4 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 27 Jan 2016 15:49:32 +0000 Subject: [PATCH 176/570] Add assert() statements on the nExtraDelete variable in vdbe.c to try to verify that the FORDELETE and IDXDELETE flags are being generated correctly. Those flags are not currently generated correctly, and so the assert()s trip on this check-in. FossilOrigin-Name: dde1db0dd2e2cf04706117629756c352b178ebb8 --- manifest | 25 ++++++++++++++----------- manifest.uuid | 2 +- src/delete.c | 11 +++++++---- src/insert.c | 11 ++++++----- src/vdbe.c | 34 ++++++++++++++++++++++++++++++++-- src/vdbeInt.h | 1 + test/e_changes.test | 1 + 7 files changed, 62 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 101db20db8..bf4b14906c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sall\srecent\strunk\senhancements. -D 2016-01-26T23:32:55.750 +C Add\sassert()\sstatements\son\sthe\snExtraDelete\svariable\sin\svdbe.c\sto\stry\sto\sverify\nthat\sthe\sFORDELETE\sand\sIDXDELETE\sflags\sare\sbeing\sgenerated\scorrectly.\s\sThose\nflags\sare\snot\scurrently\sgenerated\scorrectly,\sand\sso\sthe\sassert()s\strip\son\sthis\ncheck-in. +D 2016-01-27T15:49:32.327 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -13,7 +13,7 @@ F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 1c1657650775960804945dc392e14d9e43c5ed84 F autoconf/Makefile.msc 68ed752a809b611d97b95d8572a34fe6fd1196f1 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 -F autoconf/README.txt e9757a381e5ce2553dbaa6247bb8ad00eb8d87aa w autoconf/README +F autoconf/README.txt e9757a381e5ce2553dbaa6247bb8ad00eb8d87aa F autoconf/configure.ac 7b1ea0dcaf49fafba262ce4b0ee8cb3281b555d1 F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 @@ -299,7 +299,7 @@ F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 997651e3ee6c2818fbf7fcdb7156cef9eb3ece20 F src/dbstat.c b2ec6793eef97aebb4d171d490a4ffdfa9f2475c -F src/delete.c f02e46234c5fc86f6c03ae34dc0ba48e93cd5029 +F src/delete.c db231a9895681efed007c0887e38b49f4d1291a5 F src/expr.c d10c1cdef5810cdbf73adc9f9b383684230b360a F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c c66d3e5b35d4d95b5c1e2ee6c12f5df13a7f9ad6 @@ -308,7 +308,7 @@ F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c a00e6d8a843dc22e2c136df04e6300c4528d9b9f +F src/insert.c 410f52b9ef4603dc0aebb169b7cb6b3c60eda07e F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b @@ -412,9 +412,9 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 6039096edea4ed25f7b1e28aa5d46b0ee3ba73ef +F src/vdbe.c a27a3fdc65f5728c6e9bff49b6753fbf9d73c8c0 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 -F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189 +F src/vdbeInt.h 40c728712a2975855a2ac6aac44bf02dfd4a4c30 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e F src/vdbeaux.c 757f86e6fef8efb3dd4226cb31e2e82b9c44c883 F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 @@ -595,7 +595,7 @@ F test/e_blobbytes.test 9bea1d3e2b20f3010b04abba58f6ba172301f49f F test/e_blobclose.test df756753f571bc30e42e3a6cba2807576e49e716 F test/e_blobopen.test 234f960d90235a9b51ec3ca1e062e8541dd558d8 F test/e_blobwrite.test 615b405f29feb2cfb5a1f03dab7933258294fa26 -F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579 +F test/e_changes.test d66e8c1e33f5ec61af32eda729c8a2475404e49b F test/e_createtable.test d4c6059d44dcd4b636de9aae322766062b471844 F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412 @@ -1422,7 +1422,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ac2cbadd8000947c097da5b00c00090fe58fdcff a3d7b8ac53f94d29a11362f193fd1967f30583df -R 7855243eb7d1aae3e5a98345ca05c333 +P 9a71d56dcea953cb965f1fdda9a8b8f158cdeff6 +R 3af2d64e2a860c6e0d1b5193b911b983 +T *branch * fordelete-assert +T *sym-fordelete-assert * +T -sym-btree-fordelete-flag * U drh -Z 6eda54656ca87ef44dc31ff7472a92ee +Z f5e1f3160ce620e13f32c1dda67a1107 diff --git a/manifest.uuid b/manifest.uuid index 7255a707a7..beafd3f9d6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9a71d56dcea953cb965f1fdda9a8b8f158cdeff6 \ No newline at end of file +dde1db0dd2e2cf04706117629756c352b178ebb8 \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index 98c49c9930..b3143c5f72 100644 --- a/src/delete.c +++ b/src/delete.c @@ -479,13 +479,12 @@ void sqlite3DeleteFrom( */ if( !isView ){ int iAddrOnce = 0; - u8 p5 = (eOnePass==ONEPASS_OFF ? 0 : OPFLAG_FORDELETE); if( eOnePass==ONEPASS_MULTI ){ iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); } testcase( IsVirtual(pTab) ); - sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, p5, iTabCur, - aToOpen, &iDataCur, &iIdxCur); + sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE, + iTabCur, aToOpen, &iDataCur, &iIdxCur); assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce); @@ -724,9 +723,13 @@ void sqlite3GenerateRowDelete( if( count ){ sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); } + if( eMode!=ONEPASS_OFF ){ + sqlite3VdbeChangeP5(v, OPFLAG_IDXDELETE); + p5 = OPFLAG_IDXDELETE; + } if( iIdxNoSeek>=0 ){ sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); - if( eMode!=ONEPASS_OFF ) p5 = OPFLAG_IDXDELETE; + p5 = 0; } if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; sqlite3VdbeChangeP5(v, p5); diff --git a/src/insert.c b/src/insert.c index 8082bcb459..cbe933c221 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1647,7 +1647,7 @@ int sqlite3OpenTableAndIndices( Parse *pParse, /* Parsing context */ Table *pTab, /* Table to be opened */ int op, /* OP_OpenRead or OP_OpenWrite */ - u8 p5, /* P5 value for OP_Open* instructions */ + u8 p5, /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */ int iBase, /* Use this for the table cursor, if there is one */ u8 *aToOpen, /* If not NULL: boolean for each table and index */ int *piDataCur, /* Write the database source cursor number here */ @@ -1682,15 +1682,16 @@ int sqlite3OpenTableAndIndices( for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ int iIdxCur = iBase++; assert( pIdx->pSchema==pTab->pSchema ); - if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) && piDataCur ){ - *piDataCur = iIdxCur; - } if( aToOpen==0 || aToOpen[i+1] ){ sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - sqlite3VdbeChangeP5(v, p5); VdbeComment((v, "%s", pIdx->zName)); } + if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ + if( piDataCur ) *piDataCur = iIdxCur; + }else{ + sqlite3VdbeChangeP5(v, p5); + } } if( iBase>pParse->nTab ) pParse->nTab = iBase; return i; diff --git a/src/vdbe.c b/src/vdbe.c index adbdab0652..8583bcd4ba 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -551,6 +551,9 @@ int sqlite3VdbeExec( Op *pOp = aOp; /* Current operation */ #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) Op *pOrigOp; /* Value of pOp at the top of the loop */ +#endif +#ifdef SQLITE_DEBUG + int nExtraDelete = 0; /* Verifies FORDELETE and IDXDELETE flags */ #endif int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ @@ -3392,6 +3395,9 @@ case OP_OpenWrite: pCur->nullRow = 1; pCur->isOrdered = 1; pCur->pgnoRoot = p2; +#ifdef SQLITE_DEBUG + pCur->wrFlag = wrFlag; +#endif rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor); pCur->pKeyInfo = pKeyInfo; /* Set the VdbeCursor.isTable variable. Previous versions of @@ -4390,10 +4396,24 @@ case OP_Delete: { assert( pC->movetoTarget==iKey ); } #endif - + + /* Only flags that can be set are SAVEPOISTION and IDXDELETE */ assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_IDXDELETE))==0 ); assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); assert( OPFLAG_IDXDELETE==BTREE_IDXDELETE ); + +#ifdef SQLITE_DEBUG + if( pC->isEphemeral==0 + && (pOp->p5 & OPFLAG_IDXDELETE)==0 + && (pC->wrFlag & OPFLAG_FORDELETE)==0 + ){ + nExtraDelete++; + } + if( pOp->p2 & OPFLAG_NCHANGE ){ + nExtraDelete--; + } +#endif + rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); pC->cacheStatus = CACHE_STALE; @@ -4939,7 +4959,16 @@ case OP_IdxDelete: { r.default_rc = 0; r.aMem = &aMem[pOp->p2]; #ifdef SQLITE_DEBUG - { int i; for(i=0; iisEphemeral==0 + && (pOp->p5 & OPFLAG_IDXDELETE)==0 + && (pC->wrFlag & OPFLAG_FORDELETE)==0 + ){ + nExtraDelete++; + } + } #endif rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); if( rc==SQLITE_OK && res==0 ){ @@ -6762,6 +6791,7 @@ vdbe_return: testcase( nVmStep>0 ); p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; sqlite3VdbeLeave(p); + assert( nExtraDelete==0 || sqlite3_strlike("DELETE%",p->zSql,0)!=0 ); return rc; /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH diff --git a/src/vdbeInt.h b/src/vdbeInt.h index b231cf908e..646cf31fed 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -82,6 +82,7 @@ struct VdbeCursor { u8 isTable; /* True for rowid tables. False for indexes */ #ifdef SQLITE_DEBUG u8 seekOp; /* Most recent seek operation on this cursor */ + u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ #endif Bool isEphemeral:1; /* True for an ephemeral table */ Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ diff --git a/test/e_changes.test b/test/e_changes.test index a77e22a2ee..c4b4406f7b 100644 --- a/test/e_changes.test +++ b/test/e_changes.test @@ -65,6 +65,7 @@ foreach {tn schema} { UPDATE t1 SET b=b+1 WHERE a<5; } 5 +exit # Delete 4 rows do_changes_test 1.$tn.4 { DELETE FROM t1 WHERE a>6 From 127f720240d07433276e0ce98cb8426a23266467 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 27 Jan 2016 16:17:41 +0000 Subject: [PATCH 177/570] Fix tests in fordelete.test to test for the BTREE_AUXDELETE flag. FossilOrigin-Name: bbd25cf179df5bda1fe729928d6746248f06e46f --- manifest | 17 ++++++------- manifest.uuid | 2 +- test/fordelete.test | 58 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/manifest b/manifest index bf4b14906c..dfebd3f6ae 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sassert()\sstatements\son\sthe\snExtraDelete\svariable\sin\svdbe.c\sto\stry\sto\sverify\nthat\sthe\sFORDELETE\sand\sIDXDELETE\sflags\sare\sbeing\sgenerated\scorrectly.\s\sThose\nflags\sare\snot\scurrently\sgenerated\scorrectly,\sand\sso\sthe\sassert()s\strip\son\sthis\ncheck-in. -D 2016-01-27T15:49:32.327 +C Fix\stests\sin\sfordelete.test\sto\stest\sfor\sthe\sBTREE_AUXDELETE\sflag. +D 2016-01-27T16:17:41.726 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -642,7 +642,7 @@ F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48 F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13 F test/fkey8.test 8f08203458321e6c19a263829de4cfc936274ab0 F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749 -F test/fordelete.test ba12ec1d27cc34a4c23db4446029126d773f3849 +F test/fordelete.test f794392f1768584609fa439f7528484dc04d3a03 F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7 @@ -1422,10 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9a71d56dcea953cb965f1fdda9a8b8f158cdeff6 -R 3af2d64e2a860c6e0d1b5193b911b983 -T *branch * fordelete-assert -T *sym-fordelete-assert * -T -sym-btree-fordelete-flag * -U drh -Z f5e1f3160ce620e13f32c1dda67a1107 +P dde1db0dd2e2cf04706117629756c352b178ebb8 +R 112344660260002964aa8c335bb07305 +U dan +Z e0043c886092534757bb67db359c02f9 diff --git a/manifest.uuid b/manifest.uuid index beafd3f9d6..2b4460a277 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dde1db0dd2e2cf04706117629756c352b178ebb8 \ No newline at end of file +bbd25cf179df5bda1fe729928d6746248f06e46f \ No newline at end of file diff --git a/test/fordelete.test b/test/fordelete.test index 1e860e8867..7a49b5cbfd 100644 --- a/test/fordelete.test +++ b/test/fordelete.test @@ -30,17 +30,49 @@ proc analyze_delete_program {sql} { } { set T($rootpage) $name } - - # Calculate the results. - set res [list] + + # For each OpenWrite instruction generated for the proposed DELETE + # statement, add the following array entries: + # + # $M() -> + # $O() -> "*" | "" + # + # The O() entry is set to "*" if the BTREE_FORDELETE flag is specified, + # or "" otherwise. + # db eval "EXPLAIN $sql" R { - if {$R(opcode) == "OpenWrite"} { - set obj $T($R(p2)) - if {"0x$R(p5)" & 0x08} { append obj *} - lappend res $obj + if {$R(opcode)=="OpenWrite"} { + set root $R(p2) + set csr $R(p1) + if {[info exists T($root)]} { set M($csr) $T($root) } + + set obj $T($root) + set O($obj) "" + if {"0x$R(p5)" & 0x08} { + set O($obj) * + } else { + set O($obj) "" + } } } + db eval "EXPLAIN $sql" R { + if {$R(opcode) == "Delete"} { + set csr $R(p1) + if {[info exists M($csr)]} { + set idxdelete [expr {("0x$R(p5)" & 0x04) ? 1 : 0}] + if {$idxdelete} { + append O($M($csr)) "+" + } + } + } + } + + set res [list] + foreach {k v} [array get O] { + lappend res "${k}${v}" + } + lsort $res } @@ -53,10 +85,10 @@ do_execsql_test 1.0 { } foreach {tn sql res} { - 1 { DELETE FROM t1 WHERE a=?} { sqlite_autoindex_t1_1 t1* } - 2 { DELETE FROM t1 WHERE a=? AND b=? } { sqlite_autoindex_t1_1 t1 } - 3 { DELETE FROM t1 WHERE a>? } { sqlite_autoindex_t1_1 t1* } - 4 { DELETE FROM t1 WHERE rowid=? } { sqlite_autoindex_t1_1* t1 } + 1 { DELETE FROM t1 WHERE a=?} { sqlite_autoindex_t1_1 t1*+ } + 2 { DELETE FROM t1 WHERE a=? AND b=? } { sqlite_autoindex_t1_1 t1+ } + 3 { DELETE FROM t1 WHERE a>? } { sqlite_autoindex_t1_1 t1*+ } + 4 { DELETE FROM t1 WHERE rowid=? } { sqlite_autoindex_t1_1* t1 } } { do_adp_test 1.$tn $sql $res } @@ -68,8 +100,8 @@ do_execsql_test 2.0 { CREATE INDEX t2c ON t2(c); } foreach {tn sql res} { - 1 { DELETE FROM t2 WHERE a=?} { t2* t2a t2b* t2c* } - 2 { DELETE FROM t2 WHERE a=? AND +b=?} { t2 t2a t2b* t2c* } + 1 { DELETE FROM t2 WHERE a=?} { t2*+ t2a t2b* t2c* } + 2 { DELETE FROM t2 WHERE a=? AND +b=?} { t2+ t2a t2b* t2c* } 3 { DELETE FROM t2 WHERE a=? OR b=?} { t2 t2a* t2b* t2c* } 4 { DELETE FROM t2 WHERE +a=? } { t2 t2a* t2b* t2c* } 5 { DELETE FROM t2 WHERE rowid=? } { t2 t2a* t2b* t2c* } From def19e3b48c4064f38e6c701469f5365962f1481 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 27 Jan 2016 16:26:25 +0000 Subject: [PATCH 178/570] Change the name of the BTREE_IDXDELETE flag to BTREE_AUXDELETE, to better reflect its purpose. FossilOrigin-Name: 1d3bf6bebdda9f96734bc139601e9b05344ea0b4 --- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- src/btree.c | 11 +++++++---- src/btree.h | 2 +- src/delete.c | 4 +--- src/sqliteInt.h | 2 +- src/vdbe.c | 20 +++++++++++--------- 7 files changed, 33 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index dfebd3f6ae..9790c25453 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stests\sin\sfordelete.test\sto\stest\sfor\sthe\sBTREE_AUXDELETE\sflag. -D 2016-01-27T16:17:41.726 +C Change\sthe\sname\sof\sthe\sBTREE_IDXDELETE\sflag\sto\sBTREE_AUXDELETE,\sto\sbetter\nreflect\sits\spurpose. +D 2016-01-27T16:26:25.226 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -290,8 +290,8 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 97cf881292e085ee71faf44f7167b6312965b562 -F src/btree.h c5dfbbc59226fa5fcc2b03befa85fe10ef23c1b5 +F src/btree.c 16edaf415a54a2fc9058e3bc47d0c894cd59635e +F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c b4eba1e84752ec9cae7ff3dacd5a8b6d1ab8deb9 F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261 @@ -299,7 +299,7 @@ F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 997651e3ee6c2818fbf7fcdb7156cef9eb3ece20 F src/dbstat.c b2ec6793eef97aebb4d171d490a4ffdfa9f2475c -F src/delete.c db231a9895681efed007c0887e38b49f4d1291a5 +F src/delete.c 33ed87dc0746b1f8ce186f62b608bf40801af9c0 F src/expr.c d10c1cdef5810cdbf73adc9f9b383684230b360a F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c c66d3e5b35d4d95b5c1e2ee6c12f5df13a7f9ad6 @@ -352,7 +352,7 @@ F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/sqlite.h.in 214476a62012e578f42133a9a3b4f97a9aa421a3 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 0faffdeed20201bedb202cf6ec07f14b29158c66 +F src/sqliteInt.h 12ec54454fc0f1c25f5c7057423ada1a363b6db0 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -412,7 +412,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c a27a3fdc65f5728c6e9bff49b6753fbf9d73c8c0 +F src/vdbe.c c367615fecb5fae8a39113ee2b6ecbab94e4bcd3 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 40c728712a2975855a2ac6aac44bf02dfd4a4c30 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P dde1db0dd2e2cf04706117629756c352b178ebb8 -R 112344660260002964aa8c335bb07305 -U dan -Z e0043c886092534757bb67db359c02f9 +P bbd25cf179df5bda1fe729928d6746248f06e46f +R 21474325914b9893f106ce3a1694990c +U drh +Z 6ce2f1bf15f4f84bace517d6cc10a5ac diff --git a/manifest.uuid b/manifest.uuid index 2b4460a277..d16254398c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bbd25cf179df5bda1fe729928d6746248f06e46f \ No newline at end of file +1d3bf6bebdda9f96734bc139601e9b05344ea0b4 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 89144e7a84..04748e1b37 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8098,9 +8098,12 @@ end_insert: ** the next call to BtreeNext() or BtreePrev() moves it to the same row ** as it would have been on if the call to BtreeDelete() had been omitted. ** -** The BTREE_IDXDELETE bit of flags indicates that this is a delete of -** an index entry where the corresponding table row has already been deleted. -** The BTREE_IDXDELETE bit is a hint that is not used by this implementation, +** The BTREE_AUXDELETE bit of flags indicates that is one of several deletes +** associated with a single table entry and its indexes. Only one of those +** deletes is considered the "primary" delete. The primary delete occurs +** on a cursor that is not a BTREE_FORDELETE cursor. All but one delete +** operation on non-FORDELETE cursors is tagged with the AUXDELETE flag. +** The BTREE_AUXDELETE bit is a hint that is not used by this implementation, ** but which might be used by alternative storage engines. */ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ @@ -8123,7 +8126,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ assert( !hasReadConflicts(p, pCur->pgnoRoot) ); assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); assert( pCur->eState==CURSOR_VALID ); - assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_IDXDELETE))==0 ); + assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 ); iCellDepth = pCur->iPage; iCellIdx = pCur->aiIdx[iCellDepth]; diff --git a/src/btree.h b/src/btree.h index 416faca651..30522e99e1 100644 --- a/src/btree.h +++ b/src/btree.h @@ -249,7 +249,7 @@ int sqlite3BtreeDelete(BtCursor*, u8 flags); /* Allowed flags for the 2nd argument to sqlite3BtreeDelete() */ #define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */ -#define BTREE_IDXDELETE 0x04 /* this is index, table row already deleted */ +#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */ int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, const void *pData, int nData, diff --git a/src/delete.c b/src/delete.c index b3143c5f72..5b5a5e3cb1 100644 --- a/src/delete.c +++ b/src/delete.c @@ -724,12 +724,10 @@ void sqlite3GenerateRowDelete( sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); } if( eMode!=ONEPASS_OFF ){ - sqlite3VdbeChangeP5(v, OPFLAG_IDXDELETE); - p5 = OPFLAG_IDXDELETE; + sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); } if( iIdxNoSeek>=0 ){ sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); - p5 = 0; } if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; sqlite3VdbeChangeP5(v, p5); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 9aeffe216c..364b7a352e 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2862,7 +2862,7 @@ struct AuthContext { #define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */ #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ #define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete: keep cursor position */ -#define OPFLAG_IDXDELETE 0x04 /* OP_Delete: index in a DELETE op */ +#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */ /* * Each trigger present in the database schema is stored as an instance of diff --git a/src/vdbe.c b/src/vdbe.c index 8583bcd4ba..f6a7946e6f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -553,7 +553,7 @@ int sqlite3VdbeExec( Op *pOrigOp; /* Value of pOp at the top of the loop */ #endif #ifdef SQLITE_DEBUG - int nExtraDelete = 0; /* Verifies FORDELETE and IDXDELETE flags */ + int nExtraDelete = 0; /* Verifies FORDELETE and AUXDELETE flags */ #endif int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ @@ -4355,9 +4355,11 @@ case OP_InsertInt: { ** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be ** left in an undefined state. ** -** If the OPFLAG_IDXDELETE bit is set on P5, that indicates that this -** delete is on an index cursor where the corresponding table row has -** already been deleted. +** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this +** delete one of several associated with deleting a table row and all its +** associated index entries. Exactly one of those deletes is the "primary" +** delete. The others are all on OPFLAG_FORDELETE cursors or else are +** marked with the AUXDELETE flag. ** ** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row ** change count is incremented (otherwise not). @@ -4397,14 +4399,14 @@ case OP_Delete: { } #endif - /* Only flags that can be set are SAVEPOISTION and IDXDELETE */ - assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_IDXDELETE))==0 ); + /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ + assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 ); assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); - assert( OPFLAG_IDXDELETE==BTREE_IDXDELETE ); + assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE ); #ifdef SQLITE_DEBUG if( pC->isEphemeral==0 - && (pOp->p5 & OPFLAG_IDXDELETE)==0 + && (pOp->p5 & OPFLAG_AUXDELETE)==0 && (pC->wrFlag & OPFLAG_FORDELETE)==0 ){ nExtraDelete++; @@ -4963,7 +4965,7 @@ case OP_IdxDelete: { int i; for(i=0; iisEphemeral==0 - && (pOp->p5 & OPFLAG_IDXDELETE)==0 + && (pOp->p5 & OPFLAG_AUXDELETE)==0 && (pC->wrFlag & OPFLAG_FORDELETE)==0 ){ nExtraDelete++; From 5a2412f418bf96767fb5bc9979ca678811f8d94d Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 27 Jan 2016 23:50:14 +0000 Subject: [PATCH 179/570] Match the MSVC batch build tool sub-routine 'fn_UnsetVariable' a bit more robust. FossilOrigin-Name: 1edd5f31b9e6f91bb5434055a539428c000f1084 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/build-all-msvc.bat | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 07acca6779..7bd8b070a6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Support\sbuilding\sfor\sWindows\s10\sdesktop\susing\s'MinCore.lib'. -D 2016-01-27T07:28:33.525 +C Match\sthe\sMSVC\sbatch\sbuild\stool\ssub-routine\s'fn_UnsetVariable'\sa\sbit\smore\srobust. +D 2016-01-27T23:50:14.931 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -1363,7 +1363,7 @@ F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372 F tool/addopcodes.tcl 4ca9c3ef196f08da30add5d07ce0c9458dc8c633 -F tool/build-all-msvc.bat 204a039f985d5a4f4f9df3a3aa594fd17848c37e x +F tool/build-all-msvc.bat 6def0b5cebba36db69da8a92a9a31daf92714b4f x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a3d7b8ac53f94d29a11362f193fd1967f30583df -R 626d84a8bdebb7b947f7c1e376ac97c5 +P 4bf89891fbb076364dc45a6bf3246efa6bc33d5d +R 9e8aa43303c9d43f019b8eceec782e78 U mistachkin -Z 136b0599f548728406750a73608ec6f4 +Z 8662626dcb0cb6b59115e089abf15292 diff --git a/manifest.uuid b/manifest.uuid index 20f348c1ae..60bd1f672e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4bf89891fbb076364dc45a6bf3246efa6bc33d5d \ No newline at end of file +1edd5f31b9e6f91bb5434055a539428c000f1084 \ No newline at end of file diff --git a/tool/build-all-msvc.bat b/tool/build-all-msvc.bat index 87794132b6..30371177db 100755 --- a/tool/build-all-msvc.bat +++ b/tool/build-all-msvc.bat @@ -729,8 +729,9 @@ GOTO no_errors GOTO :EOF :fn_UnsetVariable - IF NOT "%1" == "" ( - SET %1= + SET VALUE=%1 + IF DEFINED VALUE ( + SET %VALUE%= CALL :fn_ResetErrorLevel ) GOTO :EOF From 00029a1add0f6e19b134b585bade4cbfefe1afa4 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 28 Jan 2016 00:04:32 +0000 Subject: [PATCH 180/570] Minor correction to the batch tool changes in the previous check-in. FossilOrigin-Name: 7c89d75de1e8d44d7ebd8eac1320b50dd6c221a8 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/build-all-msvc.bat | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 7bd8b070a6..8dd79dc815 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Match\sthe\sMSVC\sbatch\sbuild\stool\ssub-routine\s'fn_UnsetVariable'\sa\sbit\smore\srobust. -D 2016-01-27T23:50:14.931 +C Minor\scorrection\sto\sthe\sbatch\stool\schanges\sin\sthe\sprevious\scheck-in. +D 2016-01-28T00:04:32.165 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -1363,7 +1363,7 @@ F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372 F tool/addopcodes.tcl 4ca9c3ef196f08da30add5d07ce0c9458dc8c633 -F tool/build-all-msvc.bat 6def0b5cebba36db69da8a92a9a31daf92714b4f x +F tool/build-all-msvc.bat 77f85f4268c2711d637c629610d0cf3df5338638 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4bf89891fbb076364dc45a6bf3246efa6bc33d5d -R 9e8aa43303c9d43f019b8eceec782e78 +P 1edd5f31b9e6f91bb5434055a539428c000f1084 +R dd88757d0a47522dcabe5cdbe4d1c234 U mistachkin -Z 8662626dcb0cb6b59115e089abf15292 +Z b852cd61a6ae9681850058c67e7066b1 diff --git a/manifest.uuid b/manifest.uuid index 60bd1f672e..3c05b7f8a9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1edd5f31b9e6f91bb5434055a539428c000f1084 \ No newline at end of file +7c89d75de1e8d44d7ebd8eac1320b50dd6c221a8 \ No newline at end of file diff --git a/tool/build-all-msvc.bat b/tool/build-all-msvc.bat index 30371177db..2dd01004d5 100755 --- a/tool/build-all-msvc.bat +++ b/tool/build-all-msvc.bat @@ -732,6 +732,7 @@ GOTO no_errors SET VALUE=%1 IF DEFINED VALUE ( SET %VALUE%= + SET VALUE= CALL :fn_ResetErrorLevel ) GOTO :EOF From ba60fbb6216f1b0dd5625429b8c8d12de965c65a Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 28 Jan 2016 02:47:32 +0000 Subject: [PATCH 181/570] Fix for pthread detection in the configure scripts. FossilOrigin-Name: 47633ffdbfead3ce7b1f6560660df99f950d24f8 --- autoconf/configure.ac | 1 + configure | 56 +++++++++++++++++++++++++++++++++++++++++++ configure.ac | 1 + manifest | 18 +++++++------- manifest.uuid | 2 +- 5 files changed, 68 insertions(+), 10 deletions(-) diff --git a/autoconf/configure.ac b/autoconf/configure.ac index fcca148aea..9492530680 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -75,6 +75,7 @@ AC_ARG_ENABLE(threadsafe, [AS_HELP_STRING( THREADSAFE_FLAGS=-DSQLITE_THREADSAFE=0 if test x"$enable_threadsafe" != "xno"; then THREADSAFE_FLAGS="-D_REENTRANT=1 -DSQLITE_THREADSAFE=1" + AC_SEARCH_LIBS(pthread_create, pthread) AC_SEARCH_LIBS(pthread_mutexattr_init, pthread) fi AC_SUBST(THREADSAFE_FLAGS) diff --git a/configure b/configure index 951b719ed5..b2cb4d1308 100755 --- a/configure +++ b/configure @@ -10464,6 +10464,62 @@ fi if test "$SQLITE_THREADSAFE" = "1"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5 +$as_echo_n "checking for library containing pthread_create... " >&6; } +if ${ac_cv_search_pthread_create+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_create (); +int +main () +{ +return pthread_create (); + ; + return 0; +} +_ACEOF +for ac_lib in '' pthread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_pthread_create=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_pthread_create+:} false; then : + break +fi +done +if ${ac_cv_search_pthread_create+:} false; then : + +else + ac_cv_search_pthread_create=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create" >&5 +$as_echo "$ac_cv_search_pthread_create" >&6; } +ac_res=$ac_cv_search_pthread_create +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_mutexattr_init" >&5 $as_echo_n "checking for library containing pthread_mutexattr_init... " >&6; } if ${ac_cv_search_pthread_mutexattr_init+:} false; then : diff --git a/configure.ac b/configure.ac index 26a60147dd..19f85dc875 100644 --- a/configure.ac +++ b/configure.ac @@ -194,6 +194,7 @@ fi AC_SUBST(SQLITE_THREADSAFE) if test "$SQLITE_THREADSAFE" = "1"; then + AC_SEARCH_LIBS(pthread_create, pthread) AC_SEARCH_LIBS(pthread_mutexattr_init, pthread) fi diff --git a/manifest b/manifest index 8dd79dc815..c2a27c575e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\scorrection\sto\sthe\sbatch\stool\schanges\sin\sthe\sprevious\scheck-in. -D 2016-01-28T00:04:32.165 +C Fix\sfor\spthread\sdetection\sin\sthe\sconfigure\sscripts. +D 2016-01-28T02:47:32.836 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -14,7 +14,7 @@ F autoconf/Makefile.am 1c1657650775960804945dc392e14d9e43c5ed84 F autoconf/Makefile.msc 2ce3b1565a52d7083a1dbf57a1706fd14cc1ee0c F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt e9757a381e5ce2553dbaa6247bb8ad00eb8d87aa -F autoconf/configure.ac 7b1ea0dcaf49fafba262ce4b0ee8cb3281b555d1 +F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8 F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43 @@ -30,8 +30,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0 F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 -F configure d57d3b9d5c66549e54a4a2960de9813142d30a5a x -F configure.ac c59513d560b3107995c73b9cc1e55bfd086c4764 +F configure 12d96e3798e612e0ffa53a7a8c4d7fb1090df80e x +F configure.ac a2224b1162f79848982d3618ac1deffcd94e88ec F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1 F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1edd5f31b9e6f91bb5434055a539428c000f1084 -R dd88757d0a47522dcabe5cdbe4d1c234 -U mistachkin -Z b852cd61a6ae9681850058c67e7066b1 +P 7c89d75de1e8d44d7ebd8eac1320b50dd6c221a8 +R aa8b5eab35ce807961f68c0e84ef93a7 +U drh +Z c7a8f0aff80d4c386e53fd4da40e1b68 diff --git a/manifest.uuid b/manifest.uuid index 3c05b7f8a9..a8cb6444e4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7c89d75de1e8d44d7ebd8eac1320b50dd6c221a8 \ No newline at end of file +47633ffdbfead3ce7b1f6560660df99f950d24f8 \ No newline at end of file From d5cafb380e588ac0b2f18bfaa2008c9a90fb5996 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 28 Jan 2016 08:58:45 +0000 Subject: [PATCH 182/570] Remove a duplicate "p->magic = VDBE_MAGIC_RUN;" line from vdbeaux.c. FossilOrigin-Name: 688eb3b400a3f2f8005c341e8259f4c1485cb0ed --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbeaux.c | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index c2a27c575e..2864c79773 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sfor\spthread\sdetection\sin\sthe\sconfigure\sscripts. -D 2016-01-28T02:47:32.836 +C Remove\sa\sduplicate\s"p->magic\s=\sVDBE_MAGIC_RUN;"\sline\sfrom\svdbeaux.c. +D 2016-01-28T08:58:45.702 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -416,7 +416,7 @@ F src/vdbe.c 3ffbcc413bf793e3f0b95b79ef2f4bd449a5b5a3 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e -F src/vdbeaux.c 757f86e6fef8efb3dd4226cb31e2e82b9c44c883 +F src/vdbeaux.c fc8926c4232cd5c982f36197b1443212f265d927 F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 F src/vdbesort.c 3bb1f1f03162e6d223da623714d8e93fcaeac658 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7c89d75de1e8d44d7ebd8eac1320b50dd6c221a8 -R aa8b5eab35ce807961f68c0e84ef93a7 -U drh -Z c7a8f0aff80d4c386e53fd4da40e1b68 +P 47633ffdbfead3ce7b1f6560660df99f950d24f8 +R cfc22f0fb66c12a8ff66ff6486e44028 +U dan +Z 6ad2591078bc40cf96572d242da40773 diff --git a/manifest.uuid b/manifest.uuid index a8cb6444e4..a99478065f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -47633ffdbfead3ce7b1f6560660df99f950d24f8 \ No newline at end of file +688eb3b400a3f2f8005c341e8259f4c1485cb0ed \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index e9be081a20..3bbc5aad53 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1790,7 +1790,6 @@ void sqlite3VdbeRewind(Vdbe *p){ p->pc = -1; p->rc = SQLITE_OK; p->errorAction = OE_Abort; - p->magic = VDBE_MAGIC_RUN; p->nChange = 0; p->cacheCtr = 1; p->minWriteFileFormat = 255; From e61bbf441746d6129c9bfb09ab70ccdd6bfc421f Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 28 Jan 2016 17:06:17 +0000 Subject: [PATCH 183/570] Modifications to ensure the nExtraDelete-related assert() statement does not fail. FossilOrigin-Name: f43ff8f82d6c1239e6f9a32e7716421c1180ac74 --- manifest | 16 +++++++-------- manifest.uuid | 2 +- src/vdbe.c | 32 +++++++++++------------------- test/fordelete.test | 48 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index 9790c25453..dc719b86ce 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sname\sof\sthe\sBTREE_IDXDELETE\sflag\sto\sBTREE_AUXDELETE,\sto\sbetter\nreflect\sits\spurpose. -D 2016-01-27T16:26:25.226 +C Modifications\sto\sensure\sthe\snExtraDelete-related\sassert()\sstatement\sdoes\snot\sfail. +D 2016-01-28T17:06:17.501 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -412,7 +412,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c c367615fecb5fae8a39113ee2b6ecbab94e4bcd3 +F src/vdbe.c 66c429896ce44ebcbe199f1c7a592c12095158f0 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 40c728712a2975855a2ac6aac44bf02dfd4a4c30 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e @@ -642,7 +642,7 @@ F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48 F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13 F test/fkey8.test 8f08203458321e6c19a263829de4cfc936274ab0 F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749 -F test/fordelete.test f794392f1768584609fa439f7528484dc04d3a03 +F test/fordelete.test 57ed9b953eeace09dd2eac3251b40bf9d6990aec F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P bbd25cf179df5bda1fe729928d6746248f06e46f -R 21474325914b9893f106ce3a1694990c -U drh -Z 6ce2f1bf15f4f84bace517d6cc10a5ac +P 1d3bf6bebdda9f96734bc139601e9b05344ea0b4 +R 8c4c31e27c8a082a17d0a49af9f3ce1b +U dan +Z 9dc5d2517a8a4fb456754e0a3cfe77cf diff --git a/manifest.uuid b/manifest.uuid index d16254398c..b83d35e772 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1d3bf6bebdda9f96734bc139601e9b05344ea0b4 \ No newline at end of file +f43ff8f82d6c1239e6f9a32e7716421c1180ac74 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index f6a7946e6f..c2e70ea8b2 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4405,14 +4405,16 @@ case OP_Delete: { assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE ); #ifdef SQLITE_DEBUG - if( pC->isEphemeral==0 - && (pOp->p5 & OPFLAG_AUXDELETE)==0 - && (pC->wrFlag & OPFLAG_FORDELETE)==0 - ){ - nExtraDelete++; - } - if( pOp->p2 & OPFLAG_NCHANGE ){ - nExtraDelete--; + if( p->pFrame==0 ){ + if( pC->isEphemeral==0 + && (pOp->p5 & OPFLAG_AUXDELETE)==0 + && (pC->wrFlag & OPFLAG_FORDELETE)==0 + ){ + nExtraDelete++; + } + if( pOp->p2 & OPFLAG_NCHANGE ){ + nExtraDelete--; + } } #endif @@ -4960,21 +4962,9 @@ case OP_IdxDelete: { r.nField = (u16)pOp->p3; r.default_rc = 0; r.aMem = &aMem[pOp->p2]; -#ifdef SQLITE_DEBUG - { - int i; - for(i=0; iisEphemeral==0 - && (pOp->p5 & OPFLAG_AUXDELETE)==0 - && (pC->wrFlag & OPFLAG_FORDELETE)==0 - ){ - nExtraDelete++; - } - } -#endif rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); if( rc==SQLITE_OK && res==0 ){ - rc = sqlite3BtreeDelete(pCrsr, 0); + rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); } assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; diff --git a/test/fordelete.test b/test/fordelete.test index 7a49b5cbfd..bc38a4c5e3 100644 --- a/test/fordelete.test +++ b/test/fordelete.test @@ -158,5 +158,53 @@ do_test 3.2 { } } {6 {} {} {}} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 4.0 { + CREATE TABLE log(x); + CREATE TABLE p1(one PRIMARY KEY, two); + + CREATE TRIGGER tr_bd BEFORE DELETE ON p1 BEGIN + INSERT INTO log VALUES('delete'); + END; + INSERT INTO p1 VALUES('a', 'A'), ('b', 'B'), ('c', 'C'); + DELETE FROM p1 WHERE one = 'a'; +} + +reset_db +do_execsql_test 4.1 { + BEGIN TRANSACTION; + CREATE TABLE tbl(a PRIMARY KEY, b, c); + CREATE TABLE log(a, b, c); + INSERT INTO "tbl" VALUES(1,2,3); + CREATE TRIGGER the_trigger BEFORE DELETE ON tbl BEGIN + INSERT INTO log VALUES(1, 2,3); + END; + COMMIT; + DELETE FROM tbl WHERE a=1; +} + +reset_db +do_execsql_test 5.1 { + PRAGMA foreign_keys = 1; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + CREATE TABLE t2( + c INTEGER PRIMARY KEY, + d INTEGER DEFAULT 1 REFERENCES t1 ON DELETE SET DEFAULT + ); +} {} +do_execsql_test 5.2 { + INSERT INTO t1 VALUES(1, 'one'); + INSERT INTO t1 VALUES(2, 'two'); + INSERT INTO t2 VALUES(1, 2); + SELECT * FROM t2; +} {1 2} +do_execsql_test 5.3 { + DELETE FROM t1 WHERE a = 2; +} {} + + finish_test From 895c00e16a0308b0e0fc9fb49c1c6fdc8713af46 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 28 Jan 2016 18:22:46 +0000 Subject: [PATCH 184/570] Modify the order of terms in an "if" condition to avoid implicitly comparing a dangling pointer to NULL following an OOM error. FossilOrigin-Name: 5372f800835da61736a64dcee8b476bbe7ee2e46 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/parse.y | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 2864c79773..771dba7fa8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sa\sduplicate\s"p->magic\s=\sVDBE_MAGIC_RUN;"\sline\sfrom\svdbeaux.c. -D 2016-01-28T08:58:45.702 +C Modify\sthe\sorder\sof\sterms\sin\san\s"if"\scondition\sto\savoid\simplicitly\scomparing\sa\sdangling\spointer\sto\sNULL\sfollowing\san\sOOM\serror. +D 2016-01-28T18:22:46.091 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -336,7 +336,7 @@ F src/os_win.c ccf29ddded3e41e506b6bd98c1171aa0963b23f2 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 F src/pager.h 1c2a49143dfba9e69cc8159ef019f472ed8d260b -F src/parse.y caad1e98edeca6960493d0c60d31b76820dd7776 +F src/parse.y 426a91fbbbf7cdde3fd4b8798de7317a8782bec5 F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23 F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 47633ffdbfead3ce7b1f6560660df99f950d24f8 -R cfc22f0fb66c12a8ff66ff6486e44028 +P 688eb3b400a3f2f8005c341e8259f4c1485cb0ed +R e0b38fbf138d8fe5067019d9b4797980 U dan -Z 6ad2591078bc40cf96572d242da40773 +Z 338551eead62c92e7c871564cd38e428 diff --git a/manifest.uuid b/manifest.uuid index a99478065f..9de4b4f3bf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -688eb3b400a3f2f8005c341e8259f4c1485cb0ed \ No newline at end of file +5372f800835da61736a64dcee8b476bbe7ee2e46 \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index d6a587a2c8..846c2504b7 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1010,7 +1010,7 @@ expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);} ** unary TK_ISNULL or TK_NOTNULL expression. */ static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ sqlite3 *db = pParse->db; - if( pY && pA && pY->op==TK_NULL ){ + if( pA && pY && pY->op==TK_NULL ){ pA->op = (u8)op; sqlite3ExprDelete(db, pA->pRight); pA->pRight = 0; From 98a4d5a7fa997ddabe04c1352acedfb080d0b506 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 29 Jan 2016 08:38:35 +0000 Subject: [PATCH 185/570] Avoid two more instances of pointer arithmetic on freed pointers. FossilOrigin-Name: 2910ef64097b890c9f8929bf609ea2827db7ac97 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/prepare.c | 2 +- src/vdbesort.c | 5 ++--- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 771dba7fa8..04ba39cdd8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modify\sthe\sorder\sof\sterms\sin\san\s"if"\scondition\sto\savoid\simplicitly\scomparing\sa\sdangling\spointer\sto\sNULL\sfollowing\san\sOOM\serror. -D 2016-01-28T18:22:46.091 +C Avoid\stwo\smore\sinstances\sof\spointer\sarithmetic\son\sfreed\spointers. +D 2016-01-29T08:38:35.193 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -342,7 +342,7 @@ F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 F src/pragma.c ea290193369faa0a26ae2f924e7b86289b4a7987 F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c -F src/prepare.c 8ca7237428f372a04717d558555ea67ee1c5df93 +F src/prepare.c db85f0451ba93ecb3c1e497c279abece5cb5aead F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c @@ -419,7 +419,7 @@ F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e F src/vdbeaux.c fc8926c4232cd5c982f36197b1443212f265d927 F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 -F src/vdbesort.c 3bb1f1f03162e6d223da623714d8e93fcaeac658 +F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 F src/vtab.c 320682cca733115b4cbe71320b5c5eeb1074ebde F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 688eb3b400a3f2f8005c341e8259f4c1485cb0ed -R e0b38fbf138d8fe5067019d9b4797980 +P 5372f800835da61736a64dcee8b476bbe7ee2e46 +R 3b0a4b2b0654f088a973292429d2f71d U dan -Z 338551eead62c92e7c871564cd38e428 +Z daf578eb367bf673fc68218c1dc6fe42 diff --git a/manifest.uuid b/manifest.uuid index 9de4b4f3bf..32fa4e2607 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5372f800835da61736a64dcee8b476bbe7ee2e46 \ No newline at end of file +2910ef64097b890c9f8929bf609ea2827db7ac97 \ No newline at end of file diff --git a/src/prepare.c b/src/prepare.c index acd50fcaf7..f8ad54665a 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -582,8 +582,8 @@ static int sqlite3Prepare( zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); if( zSqlCopy ){ sqlite3RunParser(pParse, zSqlCopy, &zErrMsg); - sqlite3DbFree(db, zSqlCopy); pParse->zTail = &zSql[pParse->zTail-zSqlCopy]; + sqlite3DbFree(db, zSqlCopy); }else{ pParse->zTail = &zSql[nBytes]; } diff --git a/src/vdbesort.c b/src/vdbesort.c index 22029aa6bf..380772ee16 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -1821,6 +1821,7 @@ int sqlite3VdbeSorterWrite( if( nMin>pSorter->nMemory ){ u8 *aNew; + int iListOff = (u8*)pSorter->list.pList - pSorter->list.aMemory; int nNew = pSorter->nMemory * 2; while( nNew < nMin ) nNew = nNew*2; if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize; @@ -1828,9 +1829,7 @@ int sqlite3VdbeSorterWrite( aNew = sqlite3Realloc(pSorter->list.aMemory, nNew); if( !aNew ) return SQLITE_NOMEM; - pSorter->list.pList = (SorterRecord*)( - aNew + ((u8*)pSorter->list.pList - pSorter->list.aMemory) - ); + pSorter->list.pList = (SorterRecord*)&aNew[iListOff]; pSorter->list.aMemory = aNew; pSorter->nMemory = nNew; } From 3b83f0cd8f8525672a2631c57cea897f95a13a10 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Jan 2016 16:57:06 +0000 Subject: [PATCH 186/570] Avoid unnecessary WHERE clause term tests when coding a join where one of the tables contains a OR constraint. FossilOrigin-Name: ab94603974a0ad5342e5aee27603162652e70492 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/wherecode.c | 4 +++- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 04ba39cdd8..4caab7f68f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\stwo\smore\sinstances\sof\spointer\sarithmetic\son\sfreed\spointers. -D 2016-01-29T08:38:35.193 +C Avoid\sunnecessary\sWHERE\sclause\sterm\stests\swhen\scoding\sa\sjoin\swhere\sone\nof\sthe\stables\scontains\sa\sOR\sconstraint. +D 2016-01-29T16:57:06.008 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -428,7 +428,7 @@ F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c af9bf5dcec1a0e52726c550924aa91d837166251 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a -F src/wherecode.c 8dee26eb181ea9daa8b1a4d96f34c0860aaf99bd +F src/wherecode.c 22a7fee2360c738533ce12615f487594849adc78 F src/whereexpr.c 197a448b52073aee43eca3a2233fc113369eb2d4 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 5372f800835da61736a64dcee8b476bbe7ee2e46 -R 3b0a4b2b0654f088a973292429d2f71d -U dan -Z daf578eb367bf673fc68218c1dc6fe42 +P 2910ef64097b890c9f8929bf609ea2827db7ac97 +R a5e195d58a480f7623421e36c529b8b4 +U drh +Z 416f01dc8ffa44ad767f5afe8de92edc diff --git a/manifest.uuid b/manifest.uuid index 32fa4e2607..87b521ed65 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2910ef64097b890c9f8929bf609ea2827db7ac97 \ No newline at end of file +ab94603974a0ad5342e5aee27603162652e70492 \ No newline at end of file diff --git a/src/wherecode.c b/src/wherecode.c index 9d53a20a67..4fd7399efd 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1401,7 +1401,9 @@ Bitmask sqlite3WhereCodeOneLoopStart( Expr *pExpr = pWC->a[iTerm].pExpr; if( &pWC->a[iTerm] == pTerm ) continue; if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; - if( (pWC->a[iTerm].wtFlags & TERM_VIRTUAL)!=0 ) continue; + testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); + testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); + if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue; if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); pExpr = sqlite3ExprDup(db, pExpr, 0); From 83f0ab8087a16eadb29b74a7849a52230ac731b4 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 29 Jan 2016 18:04:31 +0000 Subject: [PATCH 187/570] Prepend "rc!=SQLITE_OK || " to the nExtraDelete assert() condition. FossilOrigin-Name: 2a055ed0afd56e8c6b17cfc31e7808debe9ec765 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index dc719b86ce..8ccd1f3c1a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modifications\sto\sensure\sthe\snExtraDelete-related\sassert()\sstatement\sdoes\snot\sfail. -D 2016-01-28T17:06:17.501 +C Prepend\s"rc!=SQLITE_OK\s||\s"\sto\sthe\snExtraDelete\sassert()\scondition. +D 2016-01-29T18:04:31.311 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -412,7 +412,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 66c429896ce44ebcbe199f1c7a592c12095158f0 +F src/vdbe.c e86e100a3f90a861f28a5bda9c9abf1bca119a54 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 40c728712a2975855a2ac6aac44bf02dfd4a4c30 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1d3bf6bebdda9f96734bc139601e9b05344ea0b4 -R 8c4c31e27c8a082a17d0a49af9f3ce1b +P f43ff8f82d6c1239e6f9a32e7716421c1180ac74 +R 089a2135f4238760de692cbeaf9edaeb U dan -Z 9dc5d2517a8a4fb456754e0a3cfe77cf +Z f28c932cf1fbf9988a116d4b713a0ec7 diff --git a/manifest.uuid b/manifest.uuid index b83d35e772..3bf3d8a23c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f43ff8f82d6c1239e6f9a32e7716421c1180ac74 \ No newline at end of file +2a055ed0afd56e8c6b17cfc31e7808debe9ec765 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index c2e70ea8b2..c36802c300 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -6783,7 +6783,9 @@ vdbe_return: testcase( nVmStep>0 ); p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; sqlite3VdbeLeave(p); - assert( nExtraDelete==0 || sqlite3_strlike("DELETE%",p->zSql,0)!=0 ); + assert( rc!=SQLITE_OK || nExtraDelete==0 + || sqlite3_strlike("DELETE%",p->zSql,0)!=0 + ); return rc; /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH From 47ab455c2bb5e8256181e46fadc53979943075c7 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Jan 2016 18:48:08 +0000 Subject: [PATCH 188/570] Remove a stray "exit" in a test script. FossilOrigin-Name: 10c88bf9f2c238abbbb54797ee2327ab72713e6f --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/e_changes.test | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 8ccd1f3c1a..26f3353966 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Prepend\s"rc!=SQLITE_OK\s||\s"\sto\sthe\snExtraDelete\sassert()\scondition. -D 2016-01-29T18:04:31.311 +C Remove\sa\sstray\s"exit"\sin\sa\stest\sscript. +D 2016-01-29T18:48:08.448 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -595,7 +595,7 @@ F test/e_blobbytes.test 9bea1d3e2b20f3010b04abba58f6ba172301f49f F test/e_blobclose.test df756753f571bc30e42e3a6cba2807576e49e716 F test/e_blobopen.test 234f960d90235a9b51ec3ca1e062e8541dd558d8 F test/e_blobwrite.test 615b405f29feb2cfb5a1f03dab7933258294fa26 -F test/e_changes.test d66e8c1e33f5ec61af32eda729c8a2475404e49b +F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579 F test/e_createtable.test d4c6059d44dcd4b636de9aae322766062b471844 F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f43ff8f82d6c1239e6f9a32e7716421c1180ac74 -R 089a2135f4238760de692cbeaf9edaeb -U dan -Z f28c932cf1fbf9988a116d4b713a0ec7 +P 2a055ed0afd56e8c6b17cfc31e7808debe9ec765 +R 4fbaa01893d53f4580e8296002d14aff +U drh +Z dbc978af0b86d437c82a817aee2df876 diff --git a/manifest.uuid b/manifest.uuid index 3bf3d8a23c..79ac026d59 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2a055ed0afd56e8c6b17cfc31e7808debe9ec765 \ No newline at end of file +10c88bf9f2c238abbbb54797ee2327ab72713e6f \ No newline at end of file diff --git a/test/e_changes.test b/test/e_changes.test index c4b4406f7b..a77e22a2ee 100644 --- a/test/e_changes.test +++ b/test/e_changes.test @@ -65,7 +65,6 @@ foreach {tn schema} { UPDATE t1 SET b=b+1 WHERE a<5; } 5 -exit # Delete 4 rows do_changes_test 1.$tn.4 { DELETE FROM t1 WHERE a>6 From de892d96604b09cf959cd317243a2176b3d9531a Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 29 Jan 2016 19:29:45 +0000 Subject: [PATCH 189/570] Experimental attempt to make better use of covering indexes within OR queries. FossilOrigin-Name: a323ac3a9d42bd5cb38d724c7e1180584b91054c --- manifest | 26 +++++++++++++------------ manifest.uuid | 2 +- src/vdbe.c | 20 +++++++++++++++---- src/vdbeInt.h | 6 ++++-- src/vdbeaux.c | 8 +++++++- src/wherecode.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++- test/whereD.test | 31 +++++++++++++++++++++++++++++- 7 files changed, 121 insertions(+), 22 deletions(-) diff --git a/manifest b/manifest index abb80cb617..4025b2f01a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\sunnecessary\sWHERE\sclause\sterm\stests\swhen\scoding\sa\sjoin\swhere\sone\sof\sthe\stables\scontains\sa\sOR\sconstraint. -D 2016-01-29T18:11:04.923 +C Experimental\sattempt\sto\smake\sbetter\suse\sof\scovering\sindexes\swithin\sOR\squeries. +D 2016-01-29T19:29:45.658 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -412,11 +412,11 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 3ffbcc413bf793e3f0b95b79ef2f4bd449a5b5a3 +F src/vdbe.c 2e0c42bba0aee55b06b636feb5ad41d77c75abe3 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 -F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189 +F src/vdbeInt.h 91f22c4d54a2540fa0da64f04dd9d96969c0f0e0 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e -F src/vdbeaux.c fc8926c4232cd5c982f36197b1443212f265d927 +F src/vdbeaux.c 657402ba7d253963e3fca323c6ad9f7b29a9efb9 F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 @@ -428,7 +428,7 @@ F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c af9bf5dcec1a0e52726c550924aa91d837166251 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a -F src/wherecode.c 22a7fee2360c738533ce12615f487594849adc78 +F src/wherecode.c 1b2a96c425048bf96eb97ba49235c71f54917b1d F src/whereexpr.c 197a448b52073aee43eca3a2233fc113369eb2d4 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1334,7 +1334,7 @@ F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2 F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5 F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6 -F test/whereD.test 9eba1f9b18e5b19a0b0bcaae5e8c037260195f2b +F test/whereD.test 4b648b4a75911474b7b4dde08a7411b165e3fa39 F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 F test/whereG.test dde4c52a97385a55be6a7cd46be8373f0cf35501 @@ -1422,8 +1422,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2910ef64097b890c9f8929bf609ea2827db7ac97 ab94603974a0ad5342e5aee27603162652e70492 -R a5e195d58a480f7623421e36c529b8b4 -T +closed ab94603974a0ad5342e5aee27603162652e70492 -U drh -Z e540fd89ce55e7aa63a8bd5d9b52b2c8 +P 512caa1ad30e6f699e2d006d5ab7674d55d2c746 +R 7c9589ab5b77780aed167682522067f5 +T *branch * covering-or +T *sym-covering-or * +T -sym-trunk * +U dan +Z 8b3097dd603cdb6f18b5a640e7f1b04b diff --git a/manifest.uuid b/manifest.uuid index ebf0893a75..afc72f756f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -512caa1ad30e6f699e2d006d5ab7674d55d2c746 \ No newline at end of file +a323ac3a9d42bd5cb38d724c7e1180584b91054c \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index cfff895c30..8ad1a17c39 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2376,12 +2376,16 @@ case OP_Column: { u32 t; /* A type code from the record header */ Mem *pReg; /* PseudoTable input register */ + pC = p->apCsr[pOp->p1]; p2 = pOp->p2; + + /* If the cursor cache is stale, bring it up-to-date */ + rc = sqlite3VdbeCursorMoveto(&pC, &p2); + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pDest = &aMem[pOp->p3]; memAboutToChange(p, pDest); assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( p2nField ); aOffset = pC->aOffset; @@ -2390,8 +2394,6 @@ case OP_Column: { assert( pC->eCurType!=CURTYPE_SORTER ); pCrsr = pC->uc.pCursor; - /* If the cursor cache is stale, bring it up-to-date */ - rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; if( pC->cacheStatus!=p->cacheCtr ){ if( pC->nullRow ){ @@ -3846,7 +3848,7 @@ seek_not_found: break; } -/* Opcode: Seek P1 P2 * * * +/* Opcode: Seek P1 P2 P3 P4 * ** Synopsis: intkey=r[P2] ** ** P1 is an open table cursor and P2 is a rowid integer. Arrange @@ -3855,6 +3857,13 @@ seek_not_found: ** This is actually a deferred seek. Nothing actually happens until ** the cursor is used to read a record. That way, if no reads ** occur, no unnecessary I/O happens. +** +** P4 may contain an array of integers (type P4_INTARRAY) containing +** one entry for each column in the table P1 is open on. If so, then +** parameter P3 is a cursor open on a database index. If array entry +** a[i] is non-zero, then reading column (a[i]-1) from cursor P3 is +** equivalent to performing the deferred seek and then reading column i +** from P1. */ case OP_Seek: { /* in2 */ VdbeCursor *pC; @@ -3869,6 +3878,9 @@ case OP_Seek: { /* in2 */ pIn2 = &aMem[pOp->p2]; pC->movetoTarget = sqlite3VdbeIntValue(pIn2); pC->deferredMoveto = 1; + assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 ); + pC->aAltMap = pOp->p4.ai; + pC->pAltCursor = p->apCsr[pOp->p3]; break; } diff --git a/src/vdbeInt.h b/src/vdbeInt.h index b231cf908e..e1c6d06567 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -74,6 +74,7 @@ typedef struct AuxData AuxData; ** * A virtual table ** * A one-row "pseudotable" stored in a single register */ +typedef struct VdbeCursor VdbeCursor; struct VdbeCursor { u8 eCurType; /* One of the CURTYPE_* values above */ i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ @@ -100,6 +101,8 @@ struct VdbeCursor { int seekResult; /* Result of previous sqlite3BtreeMoveto() */ i64 seqCount; /* Sequence counter */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ + VdbeCursor *pAltCursor; /* Set by OP_Seek */ + int *aAltMap; /* Set by OP_Seek */ #ifdef SQLITE_ENABLE_COLUMN_USED_MASK u64 maskUsed; /* Mask of columns used by this cursor */ #endif @@ -124,7 +127,6 @@ struct VdbeCursor { ** static element declared in the structure. nField total array slots for ** aType[] and nField+1 array slots for aOffset[] */ }; -typedef struct VdbeCursor VdbeCursor; /* ** When a sub-program is executed (OP_Program), a structure of this type @@ -423,7 +425,7 @@ struct Vdbe { void sqlite3VdbeError(Vdbe*, const char *, ...); void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); void sqliteVdbePopStack(Vdbe*,int); -int sqlite3VdbeCursorMoveto(VdbeCursor*); +int sqlite3VdbeCursorMoveto(VdbeCursor**, int*); int sqlite3VdbeCursorRestore(VdbeCursor*); #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) void sqlite3VdbePrintOp(FILE*, int, Op*); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 3bbc5aad53..6e368cfdbd 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3008,9 +3008,15 @@ int sqlite3VdbeCursorRestore(VdbeCursor *p){ ** If the cursor is already pointing to the correct row and that row has ** not been deleted out from under the cursor, then this routine is a no-op. */ -int sqlite3VdbeCursorMoveto(VdbeCursor *p){ +int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){ + VdbeCursor *p = *pp; if( p->eCurType==CURTYPE_BTREE ){ if( p->deferredMoveto ){ + if( p->aAltMap && p->aAltMap[*piCol] ){ + *pp = p->pAltCursor; + *piCol = p->aAltMap[*piCol] - 1; + return SQLITE_OK; + } return handleDeferredMoveto(p); } if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ diff --git a/src/wherecode.c b/src/wherecode.c index 4fd7399efd..eacd6d08d1 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -746,6 +746,54 @@ static void codeCursorHint( # define codeCursorHint(A,B,C) /* No-op */ #endif /* SQLITE_ENABLE_CURSOR_HINTS */ +/* +** Cursor iCur is open on an intkey b-tree (a table). Register iRowid contains +** a rowid value just read from cursor iIdxCur, open on index pIdx. This +** function generates code to do a deferred seek of cursor iCur to the +** rowid stored in register iRowid. +** +** Normally, this is just: +** +** OP_Seek $iCur $iRowid +** +** However, if the scan currently being coded is a branch of an OR-loop and +** the statement currently being coded is a SELECT, then P3 of the OP_Seek +** is set to iIdxCur and P4 is set to point to an array of integers +** containing one entry for each column of the table cursor iCur is open +** on. For each table column, if the column is the i'th column of the +** index, then the corresponding array entry is set to (i+1). If the column +** does not appear in the index at all, the array entry is set to 0. +*/ +static void codeDeferredSeek( + WhereInfo *pWInfo, /* Where clause context */ + Index *pIdx, /* Index scan is using */ + int iCur, /* Cursor for IPK b-tree */ + int iRowid, /* Register containing rowid to seek to */ + int iIdxCur /* Index cursor */ +){ + Parse *pParse = pWInfo->pParse; /* Parse context */ + Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */ + + assert( iIdxCur>0 ); + assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 ); + + sqlite3VdbeAddOp3(v, OP_Seek, iCur, iRowid, iIdxCur); + if( (pWInfo->wctrlFlags & WHERE_FORCE_TABLE) + && sqlite3ParseToplevel(pParse)->writeMask==0 + ){ + int i; + Table *pTab = pIdx->pTable; + int *ai = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int) * pTab->nCol); + if( ai ){ + for(i=0; inColumn-1; i++){ + assert( pIdx->aiColumn[i]nCol ); + if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]] = i+1; + } + sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY); + } + } +} + /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. @@ -1232,7 +1280,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); VdbeCoverage(v); }else{ - sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */ + codeDeferredSeek(pWInfo, pIdx, iCur, iRowidReg, iIdxCur); } }else if( iCur!=iIdxCur ){ Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); diff --git a/test/whereD.test b/test/whereD.test index 17fdac7017..1d70103a70 100644 --- a/test/whereD.test +++ b/test/whereD.test @@ -156,7 +156,7 @@ do_searchcount_test 3.4.4 { do_searchcount_test 3.5.1 { SELECT a, b FROM t3 WHERE (a=1 AND b='one') OR rowid=4 -} {1 one 2 two search 3} +} {1 one 2 two search 2} do_searchcount_test 3.5.2 { SELECT a, c FROM t3 WHERE (a=1 AND b='one') OR rowid=4 } {1 i 2 ii search 3} @@ -271,5 +271,34 @@ do_execsql_test 5.3 { c16=1 or c17=1; } {1 {} {} {} {} {} {} {} {} {} {} {} {} {} {} 1 {} {}} +#------------------------------------------------------------------------- +do_execsql_test 6.1 { + CREATE TABLE x1(a, b, c, d, e); + CREATE INDEX x1a ON x1(a); + CREATE INDEX x1bc ON x1(b, c); + CREATE INDEX x1cd ON x1(c, d); + + INSERT INTO x1 VALUES(1, 2, 3, 4, 'A'); + INSERT INTO x1 VALUES(5, 6, 7, 8, 'B'); + INSERT INTO x1 VALUES(9, 10, 11, 12, 'C'); + INSERT INTO x1 VALUES(13, 14, 15, 16, 'D'); +} + +do_searchcount_test 6.2.1 { + SELECT e FROM x1 WHERE b=2 OR c=7; +} {A B search 6} +do_searchcount_test 6.2.2 { + SELECT c FROM x1 WHERE b=2 OR c=7; +} {3 7 search 4} + +do_searchcount_test 6.3.1 { + SELECT e FROM x1 WHERE a=1 OR b=10; +} {A C search 6} +do_searchcount_test 6.3.2 { + SELECT c FROM x1 WHERE a=1 OR b=10; +} {3 11 search 5} +do_searchcount_test 6.3.3 { + SELECT rowid FROM x1 WHERE a=1 OR b=10; +} {1 3 search 4} finish_test From 945d302215abf771fd9f32e16aae6235e9663d61 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Jan 2016 20:58:40 +0000 Subject: [PATCH 190/570] Different comment on the alternative cursor fields of VdbeCursor. FossilOrigin-Name: 6e3dcb6d7d960bb513d9a4a002b6cf5ab7159686 --- manifest | 17 +++++++---------- manifest.uuid | 2 +- src/vdbeInt.h | 4 ++-- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 4025b2f01a..48234554f0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Experimental\sattempt\sto\smake\sbetter\suse\sof\scovering\sindexes\swithin\sOR\squeries. -D 2016-01-29T19:29:45.658 +C Different\scomment\son\sthe\salternative\scursor\sfields\sof\sVdbeCursor. +D 2016-01-29T20:58:40.189 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -414,7 +414,7 @@ F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 F src/vdbe.c 2e0c42bba0aee55b06b636feb5ad41d77c75abe3 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 -F src/vdbeInt.h 91f22c4d54a2540fa0da64f04dd9d96969c0f0e0 +F src/vdbeInt.h 171fdc5f6af4eeb0ff0559dbf0a71244d726a670 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e F src/vdbeaux.c 657402ba7d253963e3fca323c6ad9f7b29a9efb9 F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 @@ -1422,10 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 512caa1ad30e6f699e2d006d5ab7674d55d2c746 -R 7c9589ab5b77780aed167682522067f5 -T *branch * covering-or -T *sym-covering-or * -T -sym-trunk * -U dan -Z 8b3097dd603cdb6f18b5a640e7f1b04b +P a323ac3a9d42bd5cb38d724c7e1180584b91054c +R 2723ccd4873b2c7d653d59caf129ff2b +U drh +Z c70856a82eab5a5a2e181cbd70b2aa42 diff --git a/manifest.uuid b/manifest.uuid index afc72f756f..5612aca8d6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a323ac3a9d42bd5cb38d724c7e1180584b91054c \ No newline at end of file +6e3dcb6d7d960bb513d9a4a002b6cf5ab7159686 \ No newline at end of file diff --git a/src/vdbeInt.h b/src/vdbeInt.h index e1c6d06567..85c1a54512 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -101,8 +101,8 @@ struct VdbeCursor { int seekResult; /* Result of previous sqlite3BtreeMoveto() */ i64 seqCount; /* Sequence counter */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ - VdbeCursor *pAltCursor; /* Set by OP_Seek */ - int *aAltMap; /* Set by OP_Seek */ + VdbeCursor *pAltCursor; /* Associated index cursor from which to read */ + int *aAltMap; /* Mapping from table to index column numbers */ #ifdef SQLITE_ENABLE_COLUMN_USED_MASK u64 maskUsed; /* Mask of columns used by this cursor */ #endif From eaa6cd87e8f81fa7dfdaa7dfc3c195f86cc9f096 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 29 Jan 2016 21:16:13 +0000 Subject: [PATCH 191/570] Add tests for the change on this branch. FossilOrigin-Name: 7cb697f82932a2581af69350117a29c9c8a2544f --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/whereD.test | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 48234554f0..b6defac38e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Different\scomment\son\sthe\salternative\scursor\sfields\sof\sVdbeCursor. -D 2016-01-29T20:58:40.189 +C Add\stests\sfor\sthe\schange\son\sthis\sbranch. +D 2016-01-29T21:16:13.360 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -1334,7 +1334,7 @@ F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2 F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5 F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6 -F test/whereD.test 4b648b4a75911474b7b4dde08a7411b165e3fa39 +F test/whereD.test 51366b07cb6f546cd30cc803f7e754f063b940de F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 F test/whereG.test dde4c52a97385a55be6a7cd46be8373f0cf35501 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a323ac3a9d42bd5cb38d724c7e1180584b91054c -R 2723ccd4873b2c7d653d59caf129ff2b -U drh -Z c70856a82eab5a5a2e181cbd70b2aa42 +P 6e3dcb6d7d960bb513d9a4a002b6cf5ab7159686 +R 56d45fd4fdb64a9d12152455ff1bc2b7 +U dan +Z 8c3eb3de3f58e27647eefba9e15f6f8b diff --git a/manifest.uuid b/manifest.uuid index 5612aca8d6..c7e676919d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6e3dcb6d7d960bb513d9a4a002b6cf5ab7159686 \ No newline at end of file +7cb697f82932a2581af69350117a29c9c8a2544f \ No newline at end of file diff --git a/test/whereD.test b/test/whereD.test index 1d70103a70..de0f9618d2 100644 --- a/test/whereD.test +++ b/test/whereD.test @@ -301,4 +301,40 @@ do_searchcount_test 6.3.3 { SELECT rowid FROM x1 WHERE a=1 OR b=10; } {1 3 search 4} +do_searchcount_test 6.4.1 { + SELECT a FROM x1 WHERE b BETWEEN 1 AND 4 OR c BETWEEN 8 AND 12 +} {1 9 search 6} +do_searchcount_test 6.4.2 { + SELECT b, c FROM x1 WHERE b BETWEEN 1 AND 4 OR c BETWEEN 8 AND 12 +} {2 3 10 11 search 5} +do_searchcount_test 6.4.3 { + SELECT rowid, c FROM x1 WHERE b BETWEEN 1 AND 4 OR c BETWEEN 8 AND 12 +} {1 3 3 11 search 4} + +do_searchcount_test 6.5.1 { + SELECT a FROM x1 WHERE rowid = 2 OR c=11 +} {5 9 search 3} +do_searchcount_test 6.5.2 { + SELECT d FROM x1 WHERE rowid = 2 OR c=11 +} {8 12 search 2} +do_searchcount_test 6.5.3 { + SELECT d FROM x1 WHERE c=11 OR rowid = 2 +} {12 8 search 2} +do_searchcount_test 6.5.4 { + SELECT a FROM x1 WHERE c=11 OR rowid = 2 +} {9 5 search 3} + +do_searchcount_test 6.6.1 { + SELECT rowid FROM x1 WHERE a=1 OR b=6 OR c=11 +} {1 2 3 search 6} +do_searchcount_test 6.6.2 { + SELECT c FROM x1 WHERE a=1 OR b=6 OR c=11 +} {3 7 11 search 7} +do_searchcount_test 6.6.3 { + SELECT c FROM x1 WHERE c=11 OR a=1 OR b=6 +} {11 3 7 search 7} +do_searchcount_test 6.6.4 { + SELECT c FROM x1 WHERE b=6 OR c=11 OR a=1 +} {7 11 3 search 7} + finish_test From b17020265b4f9ff369845e0fe1adc92c5858b975 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 30 Jan 2016 00:45:18 +0000 Subject: [PATCH 192/570] Change the P4_INTARRAY so that always begins with a length integer. Print the content of the INTARRAY on EXPLAIN output. FossilOrigin-Name: 6c520d5726e80b4251338c43c405270d150ea81e --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/select.c | 5 +++-- src/vdbe.c | 5 ++++- src/vdbeaux.c | 21 ++++++++++++++++++--- src/wherecode.c | 5 +++-- 6 files changed, 39 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index b6defac38e..6b3a40d3f9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sfor\sthe\schange\son\sthis\sbranch. -D 2016-01-29T21:16:13.360 +C Change\sthe\sP4_INTARRAY\sso\sthat\salways\sbegins\swith\sa\slength\sinteger.\s\sPrint\nthe\scontent\sof\sthe\sINTARRAY\son\sEXPLAIN\soutput. +D 2016-01-30T00:45:18.967 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -347,7 +347,7 @@ F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c c34292c8ce7fe69c7cf890d933834a22572bd301 +F src/select.c ea6f3b0c279aa37eb3701792d094673a7ad1bf88 F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/sqlite.h.in 214476a62012e578f42133a9a3b4f97a9aa421a3 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -412,11 +412,11 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 2e0c42bba0aee55b06b636feb5ad41d77c75abe3 +F src/vdbe.c 0686ef5ee103935548d1aa2c0c28e52f1ae6e5a8 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 171fdc5f6af4eeb0ff0559dbf0a71244d726a670 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e -F src/vdbeaux.c 657402ba7d253963e3fca323c6ad9f7b29a9efb9 +F src/vdbeaux.c 108124021ed02fa4fc6f90a53dcaf58ac3bab941 F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 @@ -428,7 +428,7 @@ F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c af9bf5dcec1a0e52726c550924aa91d837166251 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a -F src/wherecode.c 1b2a96c425048bf96eb97ba49235c71f54917b1d +F src/wherecode.c 3c4757ae85e8237808a4ec1a25c513d83e1395e0 F src/whereexpr.c 197a448b52073aee43eca3a2233fc113369eb2d4 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 6e3dcb6d7d960bb513d9a4a002b6cf5ab7159686 -R 56d45fd4fdb64a9d12152455ff1bc2b7 -U dan -Z 8c3eb3de3f58e27647eefba9e15f6f8b +P 7cb697f82932a2581af69350117a29c9c8a2544f +R e4149e0b983ab1835709b124e27b8f90 +U drh +Z 9c9e55627bd1b33e50ca6caf5cedf1b5 diff --git a/manifest.uuid b/manifest.uuid index c7e676919d..95c87154e9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7cb697f82932a2581af69350117a29c9c8a2544f \ No newline at end of file +6c520d5726e80b4251338c43c405270d150ea81e \ No newline at end of file diff --git a/src/select.c b/src/select.c index ea4298e677..891b123543 100644 --- a/src/select.c +++ b/src/select.c @@ -2870,10 +2870,11 @@ static int multiSelectOrderBy( ** to the right and the left are evaluated, they use the correct ** collation. */ - aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy); + aPermute = sqlite3DbMallocRaw(db, sizeof(int)*(nOrderBy + 1)); if( aPermute ){ struct ExprList_item *pItem; - for(i=0, pItem=pOrderBy->a; ia; i<=nOrderBy; i++, pItem++){ assert( pItem->u.x.iOrderByCol>0 ); assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ); aPermute[i] = pItem->u.x.iOrderByCol - 1; diff --git a/src/vdbe.c b/src/vdbe.c index 8ad1a17c39..b7c0258ce6 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2067,11 +2067,14 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ ** The permutation is only valid until the next OP_Compare that has ** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should ** occur immediately prior to the OP_Compare. +** +** The first integer in the P4 integer array is the length of the array +** and does not become part of the permutation. */ case OP_Permutation: { assert( pOp->p4type==P4_INTARRAY ); assert( pOp->p4.ai ); - aPermute = pOp->p4.ai; + aPermute = pOp->p4.ai + 1; break; } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 6e368cfdbd..aaba2d3d0c 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1288,7 +1288,21 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ } #endif case P4_INTARRAY: { - sqlite3_snprintf(nTemp, zTemp, "intarray"); + int i, j; + int *ai = pOp->p4.ai; + int n = ai[0]; /* The first element of an INTARRAY is always the + ** count of the number of elements to follow */ + zTemp[0] = '['; + for(i=j=1; i1 ) zTemp[j++] = ','; + sqlite3_snprintf(nTemp-j, zTemp+j, "%d", ai[i]); + j += sqlite3Strlen30(zTemp+j); + } + if( ieCurType==CURTYPE_BTREE ){ if( p->deferredMoveto ){ - if( p->aAltMap && p->aAltMap[*piCol] ){ + int iMap; + if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){ *pp = p->pAltCursor; - *piCol = p->aAltMap[*piCol] - 1; + *piCol = iMap - 1; return SQLITE_OK; } return handleDeferredMoveto(p); diff --git a/src/wherecode.c b/src/wherecode.c index eacd6d08d1..fea397c543 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -783,11 +783,12 @@ static void codeDeferredSeek( ){ int i; Table *pTab = pIdx->pTable; - int *ai = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int) * pTab->nCol); + int *ai = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*(pTab->nCol+1)); if( ai ){ + ai[0] = pTab->nCol; for(i=0; inColumn-1; i++){ assert( pIdx->aiColumn[i]nCol ); - if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]] = i+1; + if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]+1] = i+1; } sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY); } From 5f4a686f8c5f0fa206418ab5970b61beb49aca7c Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 30 Jan 2016 12:50:25 +0000 Subject: [PATCH 193/570] Simplification and size reduction to the printf logic. Remove the bFlags parameter from sqlite3VXPrintf() and sqlite3XPrintf(). Use sqlite3XPrintf() instead of sqlite3_snprintf() for rendering P4 values in EXPLAIN output. FossilOrigin-Name: 0bdb41c45aa1cc8e5c136aaa6605d54b401483bd --- manifest | 29 +++++++------- manifest.uuid | 2 +- src/btree.c | 5 ++- src/build.c | 4 +- src/func.c | 3 +- src/printf.c | 48 +++++++++++----------- src/sqliteInt.h | 14 ++++--- src/treeview.c | 22 +++++------ src/vdbeaux.c | 103 +++++++++++++++++++----------------------------- src/vdbetrace.c | 14 +++---- src/wherecode.c | 16 ++++---- 11 files changed, 121 insertions(+), 139 deletions(-) diff --git a/manifest b/manifest index 9e56090535..d6048a60fe 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\suse\sof\scovering\sindexes\sin\sthe\sOR\soptimization. -D 2016-01-30T02:10:38.644 +C Simplification\sand\ssize\sreduction\sto\sthe\sprintf\slogic.\s\sRemove\sthe\sbFlags\nparameter\sfrom\ssqlite3VXPrintf()\sand\ssqlite3XPrintf().\s\sUse\ssqlite3XPrintf()\ninstead\sof\ssqlite3_snprintf()\sfor\srendering\sP4\svalues\sin\sEXPLAIN\soutput. +D 2016-01-30T12:50:25.204 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -290,10 +290,10 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c f224ae877fde69d1a9d430f502edaf8502752dbe +F src/btree.c 5e3435a31afbe9d839c5ee2630b8390712847415 F src/btree.h 526137361963e746949ab966a910c7f455ac6b04 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c b4eba1e84752ec9cae7ff3dacd5a8b6d1ab8deb9 +F src/build.c 0510844c48d80732aead74b5727403b493dd1cd5 F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -303,7 +303,7 @@ F src/delete.c 00af9f08a15ddc5cba5962d3d3e5bf2d67b2e7da F src/expr.c d10c1cdef5810cdbf73adc9f9b383684230b360a F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c c66d3e5b35d4d95b5c1e2ee6c12f5df13a7f9ad6 -F src/func.c ba6c03f9e440f5693086c08ee88e6e60212b3504 +F src/func.c 42b24923328f65849f52f1659efb2a0907ad78fd F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 @@ -343,7 +343,7 @@ F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 F src/pragma.c ea290193369faa0a26ae2f924e7b86289b4a7987 F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c db85f0451ba93ecb3c1e497c279abece5cb5aead -F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32 +F src/printf.c 98a5cef7fc84577ab8a3098cfa48ecfa5a70b9f8 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e @@ -352,7 +352,7 @@ F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/sqlite.h.in 214476a62012e578f42133a9a3b4f97a9aa421a3 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 74e10a74116df0aec9d4a3e134f1a86cc34c2f14 +F src/sqliteInt.h 5b552cc0eee50d519e2e020f16abbc68947b0e59 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -406,7 +406,7 @@ F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 F src/tokenize.c 5606871a377f390af7040ec3c12e0d183512d785 -F src/treeview.c 78842e90c1f71269e7a73a1d4221b6fe360bab66 +F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b F src/trigger.c 72d876b2d0c66604a112362bdae07dae9b104816 F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 @@ -416,11 +416,11 @@ F src/vdbe.c 0686ef5ee103935548d1aa2c0c28e52f1ae6e5a8 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 171fdc5f6af4eeb0ff0559dbf0a71244d726a670 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e -F src/vdbeaux.c 108124021ed02fa4fc6f90a53dcaf58ac3bab941 +F src/vdbeaux.c 221631e40111b5efa96ea557c6e2e7f62fd32b2a F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 -F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 +F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 F src/vtab.c 320682cca733115b4cbe71320b5c5eeb1074ebde F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c d21b99fd1458159d0b1ecdccc8ee6ada4fdc4c54 @@ -428,7 +428,7 @@ F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c af9bf5dcec1a0e52726c550924aa91d837166251 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a -F src/wherecode.c 3c4757ae85e8237808a4ec1a25c513d83e1395e0 +F src/wherecode.c ef0d7019029624625416cdf32cc86604c970416f F src/whereexpr.c 197a448b52073aee43eca3a2233fc113369eb2d4 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1422,8 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 512caa1ad30e6f699e2d006d5ab7674d55d2c746 6c520d5726e80b4251338c43c405270d150ea81e -R e4149e0b983ab1835709b124e27b8f90 -T +closed 6c520d5726e80b4251338c43c405270d150ea81e +P 9de3d7123007636aa97da1c70bc34344b0391078 +R 821c09620afbfbde9b9d6d9359867747 U drh -Z 625eb895cdbe3aba3d382c8d078d5321 +Z e57134af984dbdd8b3338eb2a295687a diff --git a/manifest.uuid b/manifest.uuid index a752c98cea..0454e6289a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9de3d7123007636aa97da1c70bc34344b0391078 \ No newline at end of file +0bdb41c45aa1cc8e5c136aaa6605d54b401483bd \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 4e6f6478af..481418a3dc 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8805,9 +8805,9 @@ static void checkAppendMsg( sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); } if( pCheck->zPfx ){ - sqlite3XPrintf(&pCheck->errMsg, 0, pCheck->zPfx, pCheck->v1, pCheck->v2); + sqlite3XPrintf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); } - sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap); + sqlite3VXPrintf(&pCheck->errMsg, zFormat, ap); va_end(ap); if( pCheck->errMsg.accError==STRACCUM_NOMEM ){ pCheck->mallocFailed = 1; @@ -9321,6 +9321,7 @@ char *sqlite3BtreeIntegrityCheck( sCheck.aPgRef = 0; sCheck.heap = 0; sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); + sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL; if( sCheck.nPage==0 ){ goto integrity_ck_cleanup; } diff --git a/src/build.c b/src/build.c index 06f5433e37..be320b9c5a 100644 --- a/src/build.c +++ b/src/build.c @@ -4132,14 +4132,14 @@ void sqlite3UniqueConstraint( sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200); if( pIdx->aColExpr ){ - sqlite3XPrintf(&errMsg, 0, "index '%q'", pIdx->zName); + sqlite3XPrintf(&errMsg, "index '%q'", pIdx->zName); }else{ for(j=0; jnKeyCol; j++){ char *zCol; assert( pIdx->aiColumn[j]>=0 ); zCol = pTab->aCol[pIdx->aiColumn[j]].zName; if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); - sqlite3XPrintf(&errMsg, 0, "%s.%s", pTab->zName, zCol); + sqlite3XPrintf(&errMsg, "%s.%s", pTab->zName, zCol); } } zErr = sqlite3StrAccumFinish(&errMsg); diff --git a/src/func.c b/src/func.c index b927296782..982a8c2caa 100644 --- a/src/func.c +++ b/src/func.c @@ -239,7 +239,8 @@ static void printfFunc( x.nUsed = 0; x.apArg = argv+1; sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); - sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x); + str.printfFlags = SQLITE_PRINTF_SQLFUNC; + sqlite3XPrintf(&str, zFormat, &x); n = str.nChar; sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, SQLITE_DYNAMIC); diff --git a/src/printf.c b/src/printf.c index 969950c154..946161f64c 100644 --- a/src/printf.c +++ b/src/printf.c @@ -171,7 +171,6 @@ static char *getTextArg(PrintfArguments *p){ */ void sqlite3VXPrintf( StrAccum *pAccum, /* Accumulate results here */ - u32 bFlags, /* SQLITE_PRINTF_* flags */ const char *fmt, /* Format string */ va_list ap /* arguments */ ){ @@ -211,11 +210,11 @@ void sqlite3VXPrintf( char buf[etBUFSIZE]; /* Conversion buffer */ bufpt = 0; - if( bFlags ){ - if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ + if( pAccum->printfFlags ){ + if( (bArgList = (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ pArgList = va_arg(ap, PrintfArguments*); } - useIntern = bFlags & SQLITE_PRINTF_INTERNAL; + useIntern = pAccum->printfFlags & SQLITE_PRINTF_INTERNAL; }else{ bArgList = useIntern = 0; } @@ -766,9 +765,9 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ setStrAccumError(p, STRACCUM_TOOBIG); return N; }else{ - char *zOld = p->bMalloced ? p->zText : 0; + char *zOld = isMalloced(p) ? p->zText : 0; i64 szNew = p->nChar; - assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); + assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); szNew += N + 1; if( szNew+p->nChar<=p->mxAlloc ){ /* Force exponential buffer size growth as long as it does not overflow, @@ -789,10 +788,10 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ } if( zNew ){ assert( p->zText!=0 || p->nChar==0 ); - if( !p->bMalloced && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); + if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); p->zText = zNew; p->nAlloc = sqlite3DbMallocSize(p->db, zNew); - p->bMalloced = 1; + p->printfFlags |= SQLITE_PRINTF_MALLOCED; }else{ sqlite3StrAccumReset(p); setStrAccumError(p, STRACCUM_NOMEM); @@ -810,7 +809,7 @@ void sqlite3AppendChar(StrAccum *p, int N, char c){ if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ return; } - assert( (p->zText==p->zBase)==(p->bMalloced==0) ); + assert( (p->zText==p->zBase)==!isMalloced(p) ); while( (N--)>0 ) p->zText[p->nChar++] = c; } @@ -828,7 +827,7 @@ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ memcpy(&p->zText[p->nChar], z, N); p->nChar += N; } - assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); + assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); } /* @@ -864,13 +863,13 @@ void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ */ char *sqlite3StrAccumFinish(StrAccum *p){ if( p->zText ){ - assert( (p->zText==p->zBase)==(p->bMalloced==0) ); + assert( (p->zText==p->zBase)==!isMalloced(p) ); p->zText[p->nChar] = 0; - if( p->mxAlloc>0 && p->bMalloced==0 ){ + if( p->mxAlloc>0 && !isMalloced(p) ){ p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); if( p->zText ){ memcpy(p->zText, p->zBase, p->nChar+1); - p->bMalloced = 1; + p->printfFlags |= SQLITE_PRINTF_MALLOCED; }else{ setStrAccumError(p, STRACCUM_NOMEM); } @@ -883,10 +882,10 @@ char *sqlite3StrAccumFinish(StrAccum *p){ ** Reset an StrAccum string. Reclaim all malloced memory. */ void sqlite3StrAccumReset(StrAccum *p){ - assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); - if( p->bMalloced ){ + assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); + if( isMalloced(p) ){ sqlite3DbFree(p->db, p->zText); - p->bMalloced = 0; + p->printfFlags &= ~SQLITE_PRINTF_MALLOCED; } p->zText = 0; } @@ -912,7 +911,7 @@ void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){ p->nAlloc = n; p->mxAlloc = mx; p->accError = 0; - p->bMalloced = 0; + p->printfFlags = 0; } /* @@ -926,7 +925,8 @@ char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){ assert( db!=0 ); sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); - sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap); + acc.printfFlags = SQLITE_PRINTF_INTERNAL; + sqlite3VXPrintf(&acc, zFormat, ap); z = sqlite3StrAccumFinish(&acc); if( acc.accError==STRACCUM_NOMEM ){ db->mallocFailed = 1; @@ -966,7 +966,7 @@ char *sqlite3_vmprintf(const char *zFormat, va_list ap){ if( sqlite3_initialize() ) return 0; #endif sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); - sqlite3VXPrintf(&acc, 0, zFormat, ap); + sqlite3VXPrintf(&acc, zFormat, ap); z = sqlite3StrAccumFinish(&acc); return z; } @@ -1011,7 +1011,7 @@ char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ } #endif sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); - sqlite3VXPrintf(&acc, 0, zFormat, ap); + sqlite3VXPrintf(&acc, zFormat, ap); return sqlite3StrAccumFinish(&acc); } char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ @@ -1042,7 +1042,7 @@ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); - sqlite3VXPrintf(&acc, 0, zFormat, ap); + sqlite3VXPrintf(&acc, zFormat, ap); sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, sqlite3StrAccumFinish(&acc)); } @@ -1071,7 +1071,7 @@ void sqlite3DebugPrintf(const char *zFormat, ...){ char zBuf[500]; sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); va_start(ap,zFormat); - sqlite3VXPrintf(&acc, 0, zFormat, ap); + sqlite3VXPrintf(&acc, zFormat, ap); va_end(ap); sqlite3StrAccumFinish(&acc); fprintf(stdout,"%s", zBuf); @@ -1084,9 +1084,9 @@ void sqlite3DebugPrintf(const char *zFormat, ...){ ** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument ** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. */ -void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){ +void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){ va_list ap; va_start(ap,zFormat); - sqlite3VXPrintf(p, bFlags, zFormat, ap); + sqlite3VXPrintf(p, zFormat, ap); va_end(ap); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 1a8a5d3a5b..b851399c59 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2978,10 +2978,16 @@ struct StrAccum { u32 nAlloc; /* Amount of space allocated in zText */ u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */ u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */ - u8 bMalloced; /* zText points to allocated space */ + u8 printfFlags; /* SQLITE_PRINTF flags below */ }; #define STRACCUM_NOMEM 1 #define STRACCUM_TOOBIG 2 +#define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */ +#define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */ +#define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */ + +#define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0) + /* ** A pointer to this structure is used to communicate information @@ -3298,10 +3304,8 @@ struct PrintfArguments { sqlite3_value **apArg; /* The argument values */ }; -#define SQLITE_PRINTF_INTERNAL 0x01 -#define SQLITE_PRINTF_SQLFUNC 0x02 -void sqlite3VXPrintf(StrAccum*, u32, const char*, va_list); -void sqlite3XPrintf(StrAccum*, u32, const char*, ...); +void sqlite3VXPrintf(StrAccum*, const char*, va_list); +void sqlite3XPrintf(StrAccum*, const char*, ...); char *sqlite3MPrintf(sqlite3*,const char*, ...); char *sqlite3VMPrintf(sqlite3*,const char*, va_list); #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) diff --git a/src/treeview.c b/src/treeview.c index a26e9e2b9f..2985804314 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -63,7 +63,7 @@ static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); } va_start(ap, zFormat); - sqlite3VXPrintf(&acc, 0, zFormat, ap); + sqlite3VXPrintf(&acc, zFormat, ap); va_end(ap); if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1); sqlite3StrAccumFinish(&acc); @@ -98,17 +98,17 @@ void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){ char zLine[1000]; const struct Cte *pCte = &pWith->a[i]; sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); - sqlite3XPrintf(&x, 0, "%s", pCte->zName); + sqlite3XPrintf(&x, "%s", pCte->zName); if( pCte->pCols && pCte->pCols->nExpr>0 ){ char cSep = '('; int j; for(j=0; jpCols->nExpr; j++){ - sqlite3XPrintf(&x, 0, "%c%s", cSep, pCte->pCols->a[j].zName); + sqlite3XPrintf(&x, "%c%s", cSep, pCte->pCols->a[j].zName); cSep = ','; } - sqlite3XPrintf(&x, 0, ")"); + sqlite3XPrintf(&x, ")"); } - sqlite3XPrintf(&x, 0, " AS"); + sqlite3XPrintf(&x, " AS"); sqlite3StrAccumFinish(&x); sqlite3TreeViewItem(pView, zLine, inCte-1); sqlite3TreeViewSelect(pView, pCte->pSelect, 0); @@ -159,20 +159,20 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ StrAccum x; char zLine[100]; sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); - sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor); + sqlite3XPrintf(&x, "{%d,*}", pItem->iCursor); if( pItem->zDatabase ){ - sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName); + sqlite3XPrintf(&x, " %s.%s", pItem->zDatabase, pItem->zName); }else if( pItem->zName ){ - sqlite3XPrintf(&x, 0, " %s", pItem->zName); + sqlite3XPrintf(&x, " %s", pItem->zName); } if( pItem->pTab ){ - sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName); + sqlite3XPrintf(&x, " tabname=%Q", pItem->pTab->zName); } if( pItem->zAlias ){ - sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias); + sqlite3XPrintf(&x, " (AS %s)", pItem->zAlias); } if( pItem->fg.jointype & JT_LEFT ){ - sqlite3XPrintf(&x, 0, " LEFT-JOIN"); + sqlite3XPrintf(&x, " LEFT-JOIN"); } sqlite3StrAccumFinish(&x); sqlite3TreeViewItem(pView, zLine, ipSrc->nSrc-1); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index aaba2d3d0c..619aada030 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1117,28 +1117,27 @@ static int displayComment( ** Translate the P4.pExpr value for an OP_CursorHint opcode into text ** that can be displayed in the P4 column of EXPLAIN output. */ -static int displayP4Expr(int nTemp, char *zTemp, Expr *pExpr){ +static void displayP4Expr(StrAccum *p, Expr *pExpr){ const char *zOp = 0; - int n; switch( pExpr->op ){ case TK_STRING: - sqlite3_snprintf(nTemp, zTemp, "%Q", pExpr->u.zToken); + sqlite3XPrintf(p, "%Q", pExpr->u.zToken); break; case TK_INTEGER: - sqlite3_snprintf(nTemp, zTemp, "%d", pExpr->u.iValue); + sqlite3XPrintf(p, "%d", pExpr->u.iValue); break; case TK_NULL: - sqlite3_snprintf(nTemp, zTemp, "NULL"); + sqlite3XPrintf(p, "NULL"); break; case TK_REGISTER: { - sqlite3_snprintf(nTemp, zTemp, "r[%d]", pExpr->iTable); + sqlite3XPrintf(p, "r[%d]", pExpr->iTable); break; } case TK_COLUMN: { if( pExpr->iColumn<0 ){ - sqlite3_snprintf(nTemp, zTemp, "rowid"); + sqlite3XPrintf(p, "rowid"); }else{ - sqlite3_snprintf(nTemp, zTemp, "c%d", (int)pExpr->iColumn); + sqlite3XPrintf(p, "c%d", (int)pExpr->iColumn); } break; } @@ -1170,21 +1169,19 @@ static int displayP4Expr(int nTemp, char *zTemp, Expr *pExpr){ case TK_NOTNULL: zOp = "NOTNULL"; break; default: - sqlite3_snprintf(nTemp, zTemp, "%s", "expr"); + sqlite3XPrintf(p, "%s", "expr"); break; } if( zOp ){ - sqlite3_snprintf(nTemp, zTemp, "%s(", zOp); - n = sqlite3Strlen30(zTemp); - n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pLeft); - if( npRight ){ - zTemp[n++] = ','; - n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pRight); + sqlite3XPrintf(p, "%s(", zOp); + displayP4Expr(p, pExpr->pLeft); + if( pExpr->pRight ){ + sqlite3StrAccumAppend(p, ",", 1); + displayP4Expr(p, pExpr->pRight); } - sqlite3_snprintf(nTemp-n, zTemp+n, ")"); + sqlite3StrAccumAppend(p, ")", 1); } - return sqlite3Strlen30(zTemp); } #endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */ @@ -1196,72 +1193,57 @@ static int displayP4Expr(int nTemp, char *zTemp, Expr *pExpr){ */ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ char *zP4 = zTemp; + StrAccum x; assert( nTemp>=20 ); + sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0); switch( pOp->p4type ){ case P4_KEYINFO: { - int i, j; + int j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; assert( pKeyInfo->aSortOrder!=0 ); - sqlite3_snprintf(nTemp, zTemp, "k(%d", pKeyInfo->nField); - i = sqlite3Strlen30(zTemp); + sqlite3XPrintf(&x, "k(%d", pKeyInfo->nField); for(j=0; jnField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; - const char *zColl = pColl ? pColl->zName : "nil"; - int n = sqlite3Strlen30(zColl); - if( n==6 && memcmp(zColl,"BINARY",6)==0 ){ - zColl = "B"; - n = 1; - } - if( i+n>nTemp-7 ){ - memcpy(&zTemp[i],",...",4); - i += 4; - break; - } - zTemp[i++] = ','; - if( pKeyInfo->aSortOrder[j] ){ - zTemp[i++] = '-'; - } - memcpy(&zTemp[i], zColl, n+1); - i += n; + const char *zColl = pColl ? pColl->zName : ""; + if( strcmp(zColl, "BINARY")==0 ) zColl = "B"; + sqlite3XPrintf(&x, ",%s%s", pKeyInfo->aSortOrder[j] ? "-" : "", zColl); } - zTemp[i++] = ')'; - zTemp[i] = 0; - assert( ip4.pExpr); + displayP4Expr(&x, pOp->p4.pExpr); break; } #endif case P4_COLLSEQ: { CollSeq *pColl = pOp->p4.pColl; - sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName); + sqlite3XPrintf(&x, "(%.20s)", pColl->zName); break; } case P4_FUNCDEF: { FuncDef *pDef = pOp->p4.pFunc; - sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); + sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); break; } #ifdef SQLITE_DEBUG case P4_FUNCCTX: { FuncDef *pDef = pOp->p4.pCtx->pFunc; - sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); + sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); break; } #endif case P4_INT64: { - sqlite3_snprintf(nTemp, zTemp, "%lld", *pOp->p4.pI64); + sqlite3XPrintf(&x, "%lld", *pOp->p4.pI64); break; } case P4_INT32: { - sqlite3_snprintf(nTemp, zTemp, "%d", pOp->p4.i); + sqlite3XPrintf(&x, "%d", pOp->p4.i); break; } case P4_REAL: { - sqlite3_snprintf(nTemp, zTemp, "%.16g", *pOp->p4.pReal); + sqlite3XPrintf(&x, "%.16g", *pOp->p4.pReal); break; } case P4_MEM: { @@ -1269,11 +1251,11 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ if( pMem->flags & MEM_Str ){ zP4 = pMem->z; }else if( pMem->flags & MEM_Int ){ - sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i); + sqlite3XPrintf(&x, "%lld", pMem->u.i); }else if( pMem->flags & MEM_Real ){ - sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->u.r); + sqlite3XPrintf(&x, "%.16g", pMem->u.r); }else if( pMem->flags & MEM_Null ){ - sqlite3_snprintf(nTemp, zTemp, "NULL"); + zP4 = "NULL"; }else{ assert( pMem->flags & MEM_Blob ); zP4 = "(blob)"; @@ -1283,30 +1265,24 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ #ifndef SQLITE_OMIT_VIRTUALTABLE case P4_VTAB: { sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; - sqlite3_snprintf(nTemp, zTemp, "vtab:%p", pVtab); + sqlite3XPrintf(&x, "vtab:%p", pVtab); break; } #endif case P4_INTARRAY: { - int i, j; + int i; int *ai = pOp->p4.ai; int n = ai[0]; /* The first element of an INTARRAY is always the ** count of the number of elements to follow */ + for(i=1; i1 ) zTemp[j++] = ','; - sqlite3_snprintf(nTemp-j, zTemp+j, "%d", ai[i]); - j += sqlite3Strlen30(zTemp+j); - } - if( iflags & MEM_Null ){ sqlite3StrAccumAppend(&out, "NULL", 4); }else if( pVar->flags & MEM_Int ){ - sqlite3XPrintf(&out, 0, "%lld", pVar->u.i); + sqlite3XPrintf(&out, "%lld", pVar->u.i); }else if( pVar->flags & MEM_Real ){ - sqlite3XPrintf(&out, 0, "%!.15g", pVar->u.r); + sqlite3XPrintf(&out, "%!.15g", pVar->u.r); }else if( pVar->flags & MEM_Str ){ int nOut; /* Number of bytes of the string text to include in output */ #ifndef SQLITE_OMIT_UTF16 @@ -151,17 +151,17 @@ char *sqlite3VdbeExpandSql( while( nOutn && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } } #endif - sqlite3XPrintf(&out, 0, "'%.*q'", nOut, pVar->z); + sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z); #ifdef SQLITE_TRACE_SIZE_LIMIT if( nOutn ){ - sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); + sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); } #endif #ifndef SQLITE_OMIT_UTF16 if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); #endif }else if( pVar->flags & MEM_Zero ){ - sqlite3XPrintf(&out, 0, "zeroblob(%d)", pVar->u.nZero); + sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); }else{ int nOut; /* Number of bytes of the blob to include in output */ assert( pVar->flags & MEM_Blob ); @@ -171,12 +171,12 @@ char *sqlite3VdbeExpandSql( if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; #endif for(i=0; iz[i]&0xff); + sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); } sqlite3StrAccumAppend(&out, "'", 1); #ifdef SQLITE_TRACE_SIZE_LIMIT if( nOutn ){ - sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); + sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); } #endif } diff --git a/src/wherecode.c b/src/wherecode.c index fea397c543..d590203155 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -76,7 +76,7 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){ for(i=0; i=nSkip ? "%s=?" : "ANY(%s)", z); + sqlite3XPrintf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z); } j = i; @@ -135,13 +135,13 @@ int sqlite3WhereExplainOneScan( sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); if( pItem->pSelect ){ - sqlite3XPrintf(&str, 0, " SUBQUERY %d", pItem->iSelectId); + sqlite3XPrintf(&str, " SUBQUERY %d", pItem->iSelectId); }else{ - sqlite3XPrintf(&str, 0, " TABLE %s", pItem->zName); + sqlite3XPrintf(&str, " TABLE %s", pItem->zName); } if( pItem->zAlias ){ - sqlite3XPrintf(&str, 0, " AS %s", pItem->zAlias); + sqlite3XPrintf(&str, " AS %s", pItem->zAlias); } if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ const char *zFmt = 0; @@ -165,7 +165,7 @@ int sqlite3WhereExplainOneScan( } if( zFmt ){ sqlite3StrAccumAppend(&str, " USING ", 7); - sqlite3XPrintf(&str, 0, zFmt, pIdx->zName); + sqlite3XPrintf(&str, zFmt, pIdx->zName); explainIndexRange(&str, pLoop); } }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ @@ -180,17 +180,17 @@ int sqlite3WhereExplainOneScan( assert( flags&WHERE_TOP_LIMIT); zRangeOp = "<"; } - sqlite3XPrintf(&str, 0, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); + sqlite3XPrintf(&str, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); } #ifndef SQLITE_OMIT_VIRTUALTABLE else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ - sqlite3XPrintf(&str, 0, " VIRTUAL TABLE INDEX %d:%s", + sqlite3XPrintf(&str, " VIRTUAL TABLE INDEX %d:%s", pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); } #endif #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS if( pLoop->nOut>=10 ){ - sqlite3XPrintf(&str, 0, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); + sqlite3XPrintf(&str, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); }else{ sqlite3StrAccumAppend(&str, " (~1 row)", 9); } From af30fdf6ed259cd1b32b93b571eebe2836beae18 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 30 Jan 2016 14:17:10 +0000 Subject: [PATCH 194/570] Output subtype information on register traces for PRAGMA vdbe_trace. FossilOrigin-Name: 96b780209cc95c3f3769bb880591380d94bfe38d --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/vdbe.c | 1 + 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index ee7ea0da28..c42504832e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sBTREE_FORDELETE\sand\sBTREE_AUXDELETE\sflags\sto\sthe\sb-tree\slayer\sinterface\nand\suse\sthem.\s\sAdd\sassert()\sstatement\sto\sverify\sthat\sthey\sare\scorrect. -D 2016-01-30T13:32:30.291 +C Output\ssubtype\sinformation\son\sregister\straces\sfor\sPRAGMA\svdbe_trace. +D 2016-01-30T14:17:10.486 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -412,7 +412,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c d9d2406d8a3baca537d2b05a2354afaa25e1ca84 +F src/vdbe.c bd4d2cabbafe49bd8e04d7bf57d8e480393268d9 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 716df83ac45b70ff000b515040ea606d0cb5d0f3 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e @@ -1422,8 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0bdb41c45aa1cc8e5c136aaa6605d54b401483bd 46080b0474363ca6594d2e5c249a280e2b4fc67a -R 54437ffc6525e4a6d93d7714d1fd6e2f -T +closed 46080b0474363ca6594d2e5c249a280e2b4fc67a +P 85c467041c9378cae3038756da815e9117ee8c7d +R 694b551c33162b646e920ddc57abdc60 U drh -Z 640a4b96ac8cc992fda6dcd328c886fd +Z fd54d0de297ea145965f78cad2cde9ad diff --git a/manifest.uuid b/manifest.uuid index 32d73b4945..6041e7c246 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -85c467041c9378cae3038756da815e9117ee8c7d \ No newline at end of file +96b780209cc95c3f3769bb880591380d94bfe38d \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 5ad8b11a46..ebb7e046fe 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -471,6 +471,7 @@ static void memTracePrint(Mem *p){ sqlite3VdbeMemPrettyPrint(p, zBuf); printf(" %s", zBuf); } + if( p->eSubtype ) printf(" subtype=0x%02x", p->eSubtype); } static void registerTrace(int iReg, Mem *p){ printf("REG[%d] = ", iReg); From 5b6c8e4e1d988c5e980106bb7c39aa969004de24 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 30 Jan 2016 15:46:03 +0000 Subject: [PATCH 195/570] A different way to clear the subtype on VDBE registers when the value of the register is overwritten with new content. To fix [[f45ac567eaa9f93]. FossilOrigin-Name: 2e9fb1295cd31fc29c97444c3dec82fef68e939f --- manifest | 25 ++++++++++++++----------- manifest.uuid | 2 +- src/utf.c | 2 +- src/vdbe.c | 2 +- src/vdbeInt.h | 11 ++++++++--- src/vdbeapi.c | 9 ++++++--- test/json103.test | 15 ++++++++++++++- 7 files changed, 45 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index c42504832e..16ab0b16b9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Output\ssubtype\sinformation\son\sregister\straces\sfor\sPRAGMA\svdbe_trace. -D 2016-01-30T14:17:10.486 +C A\sdifferent\sway\sto\sclear\sthe\ssubtype\son\sVDBE\sregisters\swhen\sthe\svalue\sof\sthe\sregister\sis\soverwritten\swith\snew\scontent.\sTo\sfix\s[[f45ac567eaa9f93]. +D 2016-01-30T15:46:03.527 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -409,13 +409,13 @@ F src/tokenize.c 5606871a377f390af7040ec3c12e0d183512d785 F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b F src/trigger.c 72d876b2d0c66604a112362bdae07dae9b104816 F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 -F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 +F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c bd4d2cabbafe49bd8e04d7bf57d8e480393268d9 +F src/vdbe.c 49e0a224526f4307ab80e9d3a63697b28cf0cb21 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 -F src/vdbeInt.h 716df83ac45b70ff000b515040ea606d0cb5d0f3 -F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e +F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 +F src/vdbeapi.c 9d640d5efd9a140a6bda8da53b220aa258167993 F src/vdbeaux.c 221631e40111b5efa96ea557c6e2e7f62fd32b2a F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 @@ -834,7 +834,7 @@ F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa F test/json101.test f0178422b3a2418f423fd0d3caf3571c8d1b9863 F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a -F test/json103.test 923b288a0610ec86c0951778f7db19cbcca36ad1 +F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0 F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63 F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200 @@ -1422,7 +1422,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 85c467041c9378cae3038756da815e9117ee8c7d -R 694b551c33162b646e920ddc57abdc60 -U drh -Z fd54d0de297ea145965f78cad2cde9ad +P 96b780209cc95c3f3769bb880591380d94bfe38d +R bd3d63263e82ae4209cc8f920c59f1ec +T *branch * clear-subtype-flag +T *sym-clear-subtype-flag * +T -sym-trunk * +U dan +Z b20671d59699e15a0872203a064b7cf5 diff --git a/manifest.uuid b/manifest.uuid index 6041e7c246..5e49703813 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -96b780209cc95c3f3769bb880591380d94bfe38d \ No newline at end of file +2e9fb1295cd31fc29c97444c3dec82fef68e939f \ No newline at end of file diff --git a/src/utf.c b/src/utf.c index ee367c1399..e42ab418ad 100644 --- a/src/utf.c +++ b/src/utf.c @@ -316,7 +316,7 @@ SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ c = pMem->flags; sqlite3VdbeMemRelease(pMem); - pMem->flags = MEM_Str|MEM_Term|(c&MEM_AffMask); + pMem->flags = MEM_Str|MEM_Term|(c&(MEM_AffMask|MEM_Subtype)); pMem->enc = desiredEnc; pMem->z = (char*)zOut; pMem->zMalloc = pMem->z; diff --git a/src/vdbe.c b/src/vdbe.c index ebb7e046fe..c6ae836a28 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -471,7 +471,7 @@ static void memTracePrint(Mem *p){ sqlite3VdbeMemPrettyPrint(p, zBuf); printf(" %s", zBuf); } - if( p->eSubtype ) printf(" subtype=0x%02x", p->eSubtype); + if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype); } static void registerTrace(int iReg, Mem *p){ printf("REG[%d] = ", iReg); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 497beb87d5..839c2039be 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -238,7 +238,7 @@ struct Mem { #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ #define MEM_Undefined 0x0080 /* Value is undefined */ #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ -#define MEM_TypeMask 0x01ff /* Mask of type bits */ +#define MEM_TypeMask 0x81ff /* Mask of type bits */ /* Whenever Mem contains a valid string or blob representation, one of @@ -252,11 +252,18 @@ struct Mem { #define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */ #define MEM_Agg 0x2000 /* Mem.z points to an agg function context */ #define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */ +#define MEM_Subtype 0x8000 /* Mem.eSubtype is valid */ #ifdef SQLITE_OMIT_INCRBLOB #undef MEM_Zero #define MEM_Zero 0x0000 #endif +/* Return TRUE if Mem X contains dynamically allocated content - anything +** that needs to be deallocated to avoid a leak. +*/ +#define VdbeMemDynamic(X) \ + (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) + /* ** Clear any existing type flags from a Mem and replace them with f */ @@ -472,8 +479,6 @@ int sqlite3VdbeMemNumerify(Mem*); void sqlite3VdbeMemCast(Mem*,u8,u8); int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*); void sqlite3VdbeMemRelease(Mem *p); -#define VdbeMemDynamic(X) \ - (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) int sqlite3VdbeMemFinalize(Mem*, FuncDef*); const char *sqlite3OpcodeName(int); int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 4bc912b940..0a15633ddf 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -188,7 +188,8 @@ sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal); } unsigned int sqlite3_value_subtype(sqlite3_value *pVal){ - return ((Mem*)pVal)->eSubtype; + Mem *pMem = (Mem*)pVal; + return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0); } const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); @@ -369,8 +370,10 @@ void sqlite3_result_null(sqlite3_context *pCtx){ sqlite3VdbeMemSetNull(pCtx->pOut); } void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - pCtx->pOut->eSubtype = eSubtype & 0xff; + Mem *pOut = pCtx->pOut; + assert( sqlite3_mutex_held(pOut->db->mutex) ); + pOut->eSubtype = eSubtype & 0xff; + pOut->flags |= MEM_Subtype; } void sqlite3_result_text( sqlite3_context *pCtx, diff --git a/test/json103.test b/test/json103.test index 0f0241e6fc..d7d12e3378 100644 --- a/test/json103.test +++ b/test/json103.test @@ -60,6 +60,19 @@ do_execsql_test json103-220 { WHERE rowid<7 GROUP BY b ORDER BY b; } {0 {{"n3":3,"n6":6}} 1 {{"n1":1,"n4":4}} 2 {{"n2":2,"n5":5}}} - +# ticket https://www.sqlite.org/src/info/f45ac567eaa9f93c 2016-01-30 +# Invalid JSON generated by json_group_array() +# +# The underlying problem is a failure to reset Mem.eSubtype +# +do_execsql_test json103-300 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(1),('abc'); + SELECT + json_group_array(x), + json_group_array(json_object('x',x)) + FROM t1; +} {{[1,"abc"]} {[{"x":1},{"x":"abc"}]}} finish_test From 784c1b93fbf5f206878d9fec62dd3d418b0e678d Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 30 Jan 2016 16:59:56 +0000 Subject: [PATCH 196/570] Merge the implementation of OP_IdxRowid and OP_Seek so that OP_Seek no longer requires the rowid register and a separate OP_IdxRowid call. Shorter and faster prepared statements result. FossilOrigin-Name: 9bec50a1e7796a6e038db9b1cc7cc1e7e350bf74 --- manifest | 15 ++++--- manifest.uuid | 2 +- src/vdbe.c | 103 +++++++++++++++++++++++++----------------------- src/wherecode.c | 11 +++--- 4 files changed, 66 insertions(+), 65 deletions(-) diff --git a/manifest b/manifest index df7711094d..d850d9282e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Only\shonor\sthe\sregister\ssubtype\svalue\sif\sthe\sMEM_Subtype\sflag\sis\sset.\nRevised\sand\simproved\sfix\sfor\sticket\s[f45ac567eaa9f9]. -D 2016-01-30T15:52:39.136 +C Merge\sthe\simplementation\sof\sOP_IdxRowid\sand\sOP_Seek\sso\sthat\sOP_Seek\sno\slonger\nrequires\sthe\srowid\sregister\sand\sa\sseparate\sOP_IdxRowid\scall.\s\sShorter\sand\nfaster\sprepared\sstatements\sresult. +D 2016-01-30T16:59:56.592 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -412,7 +412,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 49e0a224526f4307ab80e9d3a63697b28cf0cb21 +F src/vdbe.c 73f0f61eb5556e430487671a557d032ecac52240 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 F src/vdbeapi.c 9d640d5efd9a140a6bda8da53b220aa258167993 @@ -428,7 +428,7 @@ F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c af9bf5dcec1a0e52726c550924aa91d837166251 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a -F src/wherecode.c ef0d7019029624625416cdf32cc86604c970416f +F src/wherecode.c 7ea737b14e7a35d7f55cbad589a29aa49dfe3f7a F src/whereexpr.c 197a448b52073aee43eca3a2233fc113369eb2d4 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1422,8 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 96b780209cc95c3f3769bb880591380d94bfe38d 2e9fb1295cd31fc29c97444c3dec82fef68e939f -R bd3d63263e82ae4209cc8f920c59f1ec -T +closed 2e9fb1295cd31fc29c97444c3dec82fef68e939f +P 1f4c667f37d63fc3ef2e8f2581ecd3a66c054426 +R c807c9436e91d8aabdffdea0ecd68c4e U drh -Z 5703eae66c478a55119b68d54c8bb9ef +Z a3f05d9c2a4721d817f24f533822e83f diff --git a/manifest.uuid b/manifest.uuid index f4551f775a..01040f34b0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1f4c667f37d63fc3ef2e8f2581ecd3a66c054426 \ No newline at end of file +9bec50a1e7796a6e038db9b1cc7cc1e7e350bf74 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index c6ae836a28..a1e59e1170 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3857,42 +3857,6 @@ seek_not_found: } break; } - -/* Opcode: Seek P1 P2 P3 P4 * -** Synopsis: intkey=r[P2] -** -** P1 is an open table cursor and P2 is a rowid integer. Arrange -** for P1 to move so that it points to the rowid given by P2. -** -** This is actually a deferred seek. Nothing actually happens until -** the cursor is used to read a record. That way, if no reads -** occur, no unnecessary I/O happens. -** -** P4 may contain an array of integers (type P4_INTARRAY) containing -** one entry for each column in the table P1 is open on. If so, then -** parameter P3 is a cursor open on a database index. If array entry -** a[i] is non-zero, then reading column (a[i]-1) from cursor P3 is -** equivalent to performing the deferred seek and then reading column i -** from P1. -*/ -case OP_Seek: { /* in2 */ - VdbeCursor *pC; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->uc.pCursor!=0 ); - assert( pC->isTable ); - pC->nullRow = 0; - pIn2 = &aMem[pOp->p2]; - pC->movetoTarget = sqlite3VdbeIntValue(pIn2); - pC->deferredMoveto = 1; - assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 ); - pC->aAltMap = pOp->p4.ai; - pC->pAltCursor = p->apCsr[pOp->p3]; - break; -} /* Opcode: Found P1 P2 P3 P4 * @@ -4987,6 +4951,25 @@ case OP_IdxDelete: { break; } +/* Opcode: Seek P1 * P3 P4 * +** Synopsis: Move P3 to P1.rowid +** +** P1 is an open index cursor and P3 is a cursor on the corresponding +** table. This opcode does a deferred seek of the P3 table cursor +** to the row that corresponds to the current row of P1. +** +** This is a deferred seek. Nothing actually happens until +** the cursor is used to read a record. That way, if no reads +** occur, no unnecessary I/O happens. +** +** P4 may be an array of integers (type P4_INTARRAY) containing +** one entry for each column in the P3 table. If array entry a[i] +** is non-zero, then reading column (a[i]-1) from cursor P3 is +** equivalent to performing the deferred seek and then reading column i +** from P1. This information is stored in P3 and used to redirect +** reads against P3 over to P1, thus possibly avoiding the need to +** seek and read cursor P3. +*/ /* Opcode: IdxRowid P1 P2 * * * ** Synopsis: r[P2]=rowid ** @@ -4996,37 +4979,57 @@ case OP_IdxDelete: { ** ** See also: Rowid, MakeRecord. */ +case OP_Seek: case OP_IdxRowid: { /* out2 */ - BtCursor *pCrsr; - VdbeCursor *pC; - i64 rowid; + VdbeCursor *pC; /* The P1 index cursor */ + VdbeCursor *pTabCur; /* The P2 table cursor (OP_Seek only) */ + i64 rowid; /* Rowid that P1 current points to */ - pOut = out2Prerelease(p, pOp); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); - pCrsr = pC->uc.pCursor; - assert( pCrsr!=0 ); - pOut->flags = MEM_Null; + assert( pC->uc.pCursor!=0 ); assert( pC->isTable==0 ); assert( pC->deferredMoveto==0 ); + assert( !pC->nullRow || pOp->opcode==OP_IdxRowid ); + + /* The IdxRowid and Seek opcodes are combined because of the commonality + ** of sqlite3VdbeCursorRestore() and sqlite3VdbeIdxRowid(). */ + rc = sqlite3VdbeCursorRestore(pC); /* sqlite3VbeCursorRestore() can only fail if the record has been deleted - ** out from under the cursor. That will never happend for an IdxRowid - ** opcode, hence the NEVER() arround the check of the return value. - */ - rc = sqlite3VdbeCursorRestore(pC); + ** out from under the cursor. That will never happens for an IdxRowid + ** or Seek opcode */ if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; if( !pC->nullRow ){ rowid = 0; /* Not needed. Only used to silence a warning. */ - rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid); + rc = sqlite3VdbeIdxRowid(db, pC->uc.pCursor, &rowid); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } - pOut->u.i = rowid; - pOut->flags = MEM_Int; + if( pOp->opcode==OP_Seek ){ + assert( pOp->p3>=0 && pOp->p3nCursor ); + pTabCur = p->apCsr[pOp->p3]; + assert( pTabCur!=0 ); + assert( pTabCur->eCurType==CURTYPE_BTREE ); + assert( pTabCur->uc.pCursor!=0 ); + assert( pTabCur->isTable ); + pTabCur->nullRow = 0; + pTabCur->movetoTarget = rowid; + pTabCur->deferredMoveto = 1; + assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 ); + pTabCur->aAltMap = pOp->p4.ai; + pTabCur->pAltCursor = pC; + }else{ + pOut = out2Prerelease(p, pOp); + pOut->u.i = rowid; + pOut->flags = MEM_Int; + } + }else{ + assert( pOp->opcode==OP_IdxRowid ); + sqlite3VdbeMemSetNull(&aMem[pOp->p2]); } break; } diff --git a/src/wherecode.c b/src/wherecode.c index d590203155..3fbd198e31 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -768,7 +768,6 @@ static void codeDeferredSeek( WhereInfo *pWInfo, /* Where clause context */ Index *pIdx, /* Index scan is using */ int iCur, /* Cursor for IPK b-tree */ - int iRowid, /* Register containing rowid to seek to */ int iIdxCur /* Index cursor */ ){ Parse *pParse = pWInfo->pParse; /* Parse context */ @@ -777,7 +776,7 @@ static void codeDeferredSeek( assert( iIdxCur>0 ); assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 ); - sqlite3VdbeAddOp3(v, OP_Seek, iCur, iRowid, iIdxCur); + sqlite3VdbeAddOp3(v, OP_Seek, iIdxCur, 0, iCur); if( (pWInfo->wctrlFlags & WHERE_FORCE_TABLE) && sqlite3ParseToplevel(pParse)->writeMask==0 ){ @@ -1274,14 +1273,14 @@ Bitmask sqlite3WhereCodeOneLoopStart( if( omitTable ){ /* pIdx is a covering index. No need to access the main table. */ }else if( HasRowid(pIdx->pTable) ){ - iRowidReg = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); - sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); if( pWInfo->eOnePass!=ONEPASS_OFF ){ + iRowidReg = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); + sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); VdbeCoverage(v); }else{ - codeDeferredSeek(pWInfo, pIdx, iCur, iRowidReg, iIdxCur); + codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur); } }else if( iCur!=iIdxCur ){ Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); From 52f5d1ba6be88ca71cf8bda71ed519ebe84a93e0 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 30 Jan 2016 19:16:11 +0000 Subject: [PATCH 197/570] Performance enhancement for fts5 column filter queries on detail=full tables. FossilOrigin-Name: 13fb4aa6a87c5c6258979953da82eedc1a7bf14f --- ext/fts5/fts5_index.c | 24 ++-- ext/fts5/tool/fts5speed.tcl | 1 - ext/fts5/tool/fts5txt2db.tcl | 272 +++++++++++++++++++---------------- manifest | 18 +-- manifest.uuid | 2 +- 5 files changed, 170 insertions(+), 147 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index ca3feb86f7..f30c38d91a 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -4333,26 +4333,32 @@ static int fts5IndexExtractCol( int iCurrent = 0; /* Anything before the first 0x01 is col 0 */ const u8 *p = *pa; const u8 *pEnd = &p[n]; /* One byte past end of position list */ - u8 prev = 0; while( iCol>iCurrent ){ /* Advance pointer p until it points to pEnd or an 0x01 byte that is - ** not part of a varint */ - while( (prev & 0x80) || *p!=0x01 ){ - prev = *p++; - if( p==pEnd ) return 0; + ** not part of a varint. Note that it is not possible for a negative + ** or extremely large varint to occur within an uncorrupted position + ** list. So the last byte of each varint may be assumed to have a clear + ** 0x80 bit. */ + while( *p!=0x01 ){ + while( *p++ & 0x80 ); + if( p>=pEnd ) return 0; } *pa = p++; - p += fts5GetVarint32(p, iCurrent); + iCurrent = *p++; + if( iCurrent & 0x80 ){ + p--; + p += fts5GetVarint32(p, iCurrent); + } } if( iCol!=iCurrent ) return 0; /* Advance pointer p until it points to pEnd or an 0x01 byte that is ** not part of a varint */ - assert( (prev & 0x80)==0 ); - while( p [set idx(-tblname) {tblname t1 "table name to use"} - # - # For each position parameter, append its name to $lPosargs. If the ... - # specifier is present, set $zTrailing to the name of the prefix. - # - foreach o $O { - set nm [lindex $o 0] - set nArg [llength $o] - switch -- $nArg { - 1 { - if {[string range $nm end-2 end]=="..."} { - set zTrailing [string range $nm 0 end-3] - } else { - lappend lPosargs $nm +########################################################################### +########################################################################### +# Command line options processor. This is generic code that can be copied +# between scripts. +# +namespace eval cmdline { + proc cmdline_error {O E {msg ""}} { + if {$msg != ""} { + puts stderr "Error: $msg" + puts stderr "" + } + + set L [list] + foreach o $O { + if {[llength $o]==1} { + lappend L [string toupper $o] + } + } + + puts stderr "Usage: $::argv0 ?SWITCHES? $L" + puts stderr "" + puts stderr "Switches are:" + foreach o $O { + if {[llength $o]==3} { + foreach {a b c} $o {} + puts stderr [format " -%-15s %s (default \"%s\")" "$a VAL" $c $b] + } elseif {[llength $o]==2} { + foreach {a b} $o {} + puts stderr [format " -%-15s %s" $a $b] + } + } + puts stderr "" + puts stderr $E + exit -1 + } + + proc process {avar lArgs O E} { + upvar $avar A + set zTrailing "" ;# True if ... is present in $O + set lPosargs [list] + + # Populate A() with default values. Also, for each switch in the command + # line spec, set an entry in the idx() array as follows: + # + # {tblname t1 "table name to use"} + # -> [set idx(-tblname) {tblname t1 "table name to use"} + # + # For each position parameter, append its name to $lPosargs. If the ... + # specifier is present, set $zTrailing to the name of the prefix. + # + foreach o $O { + set nm [lindex $o 0] + set nArg [llength $o] + switch -- $nArg { + 1 { + if {[string range $nm end-2 end]=="..."} { + set zTrailing [string range $nm 0 end-3] + } else { + lappend lPosargs $nm + } + } + 2 { + set A($nm) 0 + set idx(-$nm) $o + } + 3 { + set A($nm) [lindex $o 1] + set idx(-$nm) $o + } + default { + error "Error in command line specification" } } - 2 { - set A($nm) 0 - set idx(-$nm) $o - } - 3 { - set A($nm) [lindex $o 1] - set idx(-$nm) $o - } - default { - error "Error in command line specification" + } + + # Set explicitly specified option values + # + set nArg [llength $lArgs] + for {set i 0} {$i < $nArg} {incr i} { + set opt [lindex $lArgs $i] + if {[string range $opt 0 0]!="-" || $opt=="--"} break + set c [array names idx "${opt}*"] + if {[llength $c]==0} { cmdline_error $O $E "Unrecognized option: $opt"} + if {[llength $c]>1} { cmdline_error $O $E "Ambiguous option: $opt"} + + if {[llength $idx($c)]==3} { + if {$i==[llength $lArgs]-1} { + cmdline_error $O $E "Option requires argument: $c" + } + incr i + set A([lindex $idx($c) 0]) [lindex $lArgs $i] + } else { + set A([lindex $idx($c) 0]) 1 } } - } - - # Set explicitly specified option values - # - set nArg [llength $lArgs] - for {set i 0} {$i < $nArg} {incr i} { - set opt [lindex $lArgs $i] - if {[string range $opt 0 0]!="-" || $opt=="--"} break - set c [array names idx "${opt}*"] - if {[llength $c]==0} { command_line_error $O $E "Unrecognized option: $opt"} - if {[llength $c]>1} { command_line_error $O $E "Ambiguous option: $opt"} - - if {[llength $idx($c)]==3} { - if {$i==[llength $lArgs]-1} { - command_line_error $O $E "Option requires argument: $c" - } - incr i - set A([lindex $idx($c) 0]) [lindex $lArgs $i] - } else { - set A([lindex $idx($c) 0]) 1 + + # Deal with position arguments. + # + set nPosarg [llength $lPosargs] + set nRem [expr $nArg - $i] + if {$nRem < $nPosarg || ($zTrailing=="" && $nRem > $nPosarg)} { + cmdline_error $O $E + } + for {set j 0} {$j < $nPosarg} {incr j} { + set A([lindex $lPosargs $j]) [lindex $lArgs [expr $j+$i]] + } + if {$zTrailing!=""} { + set A($zTrailing) [lrange $lArgs [expr $j+$i] end] } } - - # Deal with position arguments. - # - set nPosarg [llength $lPosargs] - set nRem [expr $nArg - $i] - if {$nRem < $nPosarg || ($zTrailing=="" && $nRem > $nPosarg)} { - command_line_error $O $E - } - for {set j 0} {$j < $nPosarg} {incr j} { - set A([lindex $lPosargs $j]) [lindex $lArgs [expr $j+$i]] - } - if {$zTrailing!=""} { - set A($zTrailing) [lrange $lArgs [expr $j+$i] end] - } -} +} ;# namespace eval cmdline # End of command line options processor. -#------------------------------------------------------------------------- +########################################################################### +########################################################################### +process_cmdline -process_command_line A $argv { - {fts5 "use fts5"} - {fts4 "use fts4"} - {colsize "10 10 10" "list of column sizes"} - {tblname "t1" "table name to create"} - {detail "full" "Fts5 detail mode to use"} - {repeat 1 "Load each file this many times"} - database - file... -} { -This script is designed to create fts4/5 tables with more than one column. -The -colsize option should be set to a Tcl list of integer values, one for -each column in the table. Each value is the number of tokens that will be -inserted into the column value for each row. For example, setting the -colsize -option to "5 10" creates an FTS table with 2 columns, with roughly 5 and 10 -tokens per row in each, respectively. - -Each "FILE" argument should be a text file. The contents of these text files is -split on whitespace characters to form a list of tokens. The first N1 tokens -are used for the first column of the first row, where N1 is the first element -of the -colsize list. The next N2 are used for the second column of the first -row, and so on. Rows are added to the table until the entire list of tokens -is exhausted. -} - +# If -fts4 was specified, use fts4. Otherwise, fts5. if {$A(fts4)} { set A(fts) fts4 } else { @@ -156,7 +173,8 @@ proc create_table {} { set sql "CREATE VIRTUAL TABLE IF NOT EXISTS $A(tblname) USING $A(fts) (" append sql [join $cols ,] - if {$A(fts)=="fts5"} { append sql ",detail=$A(detail));" } + if {$A(fts)=="fts5"} { append sql ",detail=$A(detail)" } + append sql ", prefix='$A(prefix)');" db eval $sql return $cols diff --git a/manifest b/manifest index d850d9282e..75f2023494 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\simplementation\sof\sOP_IdxRowid\sand\sOP_Seek\sso\sthat\sOP_Seek\sno\slonger\nrequires\sthe\srowid\sregister\sand\sa\sseparate\sOP_IdxRowid\scall.\s\sShorter\sand\nfaster\sprepared\sstatements\sresult. -D 2016-01-30T16:59:56.592 +C Performance\senhancement\sfor\sfts5\scolumn\sfilter\squeries\son\sdetail=full\stables. +D 2016-01-30T19:16:11.820 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c f6e0c6018ffc8e39fc0b333b5daa8b8d528ae6e4 F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 F ext/fts5/fts5_expr.c a66b9694519d9c336d9bdbd46ea22e7e14aef412 F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c 5558bfbeaf364cc67f937e25753ceed8757cb6d1 +F ext/fts5/fts5_index.c cd1e4faca8b9adc2d89b367075bf93a7f50c406b F ext/fts5/fts5_main.c 3886bbfc5ac1d9df29979823ddf2b68241e1127e F ext/fts5/fts5_storage.c 2a1f44deae090cd711f02cec0c2af8e660360d24 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -190,8 +190,8 @@ F ext/fts5/test/fts5unindexed.test e9539d5b78c677315e7ed8ea911d4fd25437c680 F ext/fts5/test/fts5update.test 57c7012a7919889048947addae10e0613df45529 F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e F ext/fts5/test/fts5vocab.test 480d780aa6b699816c5066225fbd86f3a0239477 -F ext/fts5/tool/fts5speed.tcl 47f0031e6ac564964f4f4805e439ea665e848df2 -F ext/fts5/tool/fts5txt2db.tcl ae308338b2da1646dea456ab66706acdde8c714e +F ext/fts5/tool/fts5speed.tcl f9944a9abb9b7685cfbee8101a3dd772ededca66 +F ext/fts5/tool/fts5txt2db.tcl 1343745b89ca2a1e975c23f836d0cee410052975 F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093 F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45 F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1f4c667f37d63fc3ef2e8f2581ecd3a66c054426 -R c807c9436e91d8aabdffdea0ecd68c4e -U drh -Z a3f05d9c2a4721d817f24f533822e83f +P 9bec50a1e7796a6e038db9b1cc7cc1e7e350bf74 +R bc0069e7525e32617bb065c15a24c73f +U dan +Z 0739ff39c83f4f590353add9c7d562e8 diff --git a/manifest.uuid b/manifest.uuid index 01040f34b0..6f555b4e1d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9bec50a1e7796a6e038db9b1cc7cc1e7e350bf74 \ No newline at end of file +13fb4aa6a87c5c6258979953da82eedc1a7bf14f \ No newline at end of file From 482721ab7571338de32932d6d9c221a0445bb421 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 30 Jan 2016 21:09:02 +0000 Subject: [PATCH 198/570] Fix new test cases in stat.test so that they work with -DSQLITE_DEFAULT_AUTOVACUUM=1 builds. FossilOrigin-Name: a2810cf65db13479e2ab255c37abac7841ee985d --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/stat.test | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 75f2023494..6eedebcb19 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\senhancement\sfor\sfts5\scolumn\sfilter\squeries\son\sdetail=full\stables. -D 2016-01-30T19:16:11.820 +C Fix\snew\stest\scases\sin\sstat.test\sso\sthat\sthey\swork\swith\s-DSQLITE_DEFAULT_AUTOVACUUM=1\sbuilds. +D 2016-01-30T21:09:02.039 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -1054,7 +1054,7 @@ F test/spellfix3.test f7bf7b3482971473d32b6b00f6944c5c066cff97 F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5 F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142 F test/sqllog.test a8faa2df39610a037dd372ed872d124260d32953 -F test/stat.test fafe6e82dfdb97d8c8be31cd83e36e973079ce0f +F test/stat.test acc91e80517fff447ae8adcfd953cfdaa5efc0af F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1 F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9 F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9bec50a1e7796a6e038db9b1cc7cc1e7e350bf74 -R bc0069e7525e32617bb065c15a24c73f +P 13fb4aa6a87c5c6258979953da82eedc1a7bf14f +R 47a5bd805bca8e3bfa57e533079ecc85 U dan -Z 0739ff39c83f4f590353add9c7d562e8 +Z 77da8baba44508a2b8a7ef85c127b8a0 diff --git a/manifest.uuid b/manifest.uuid index 6f555b4e1d..480ce59513 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -13fb4aa6a87c5c6258979953da82eedc1a7bf14f \ No newline at end of file +a2810cf65db13479e2ab255c37abac7841ee985d \ No newline at end of file diff --git a/test/stat.test b/test/stat.test index 14751bd6ff..288153dbb3 100644 --- a/test/stat.test +++ b/test/stat.test @@ -192,6 +192,7 @@ do_catchsql_test stat-6.1 { forcedelete test.db2 do_execsql_test 7.1 { ATTACH 'test.db2' AS '123'; + PRAGMA "123".auto_vacuum = OFF; CREATE TABLE "123".x1(a, b); INSERT INTO x1 VALUES(1, 2); } From 38bace84cdc2d654097a89ce1ffb2521eb8dbd04 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 1 Feb 2016 00:21:08 +0000 Subject: [PATCH 199/570] Fix an assert() that might fail on a corrupt database. FossilOrigin-Name: 22eaced7274764eaf7ab4b5fc52cc2fcfc285708 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/btree.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 6eedebcb19..adf078c951 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\snew\stest\scases\sin\sstat.test\sso\sthat\sthey\swork\swith\s-DSQLITE_DEFAULT_AUTOVACUUM=1\sbuilds. -D 2016-01-30T21:09:02.039 +C Fix\san\sassert()\sthat\smight\sfail\son\sa\scorrupt\sdatabase. +D 2016-02-01T00:21:08.846 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -290,7 +290,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c e3929afb9bfbaa6b39685b5e5a207036ac862a75 +F src/btree.c a2a0244ea3f0b3f57f75019c2f229c744ca5d202 F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 0510844c48d80732aead74b5727403b493dd1cd5 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 13fb4aa6a87c5c6258979953da82eedc1a7bf14f -R 47a5bd805bca8e3bfa57e533079ecc85 -U dan -Z 77da8baba44508a2b8a7ef85c127b8a0 +P a2810cf65db13479e2ab255c37abac7841ee985d +R 188fdebacf7930560dd1bef6de7f142e +U drh +Z 4925a52dc50a180b6685bbcef3b9e085 diff --git a/manifest.uuid b/manifest.uuid index 480ce59513..85c92e6bfd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a2810cf65db13479e2ab255c37abac7841ee985d \ No newline at end of file +22eaced7274764eaf7ab4b5fc52cc2fcfc285708 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index b08367cbd7..d5acaf3669 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8239,7 +8239,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ if( rc==SQLITE_OK ){ if( bSkipnext ){ assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) ); - assert( pPage==pCur->apPage[pCur->iPage] ); + assert( pPage==pCur->apPage[pCur->iPage] || CORRUPT_DB ); assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell ); pCur->eState = CURSOR_SKIPNEXT; if( iCellIdx>=pPage->nCell ){ From b0c886510f9f691ab382c5af82644ba48684a9f3 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 1 Feb 2016 13:21:13 +0000 Subject: [PATCH 200/570] Minor simplification to the OP_AutoCommit opcode. Fix some code comments related to transaction control. FossilOrigin-Name: a9b6a0672f84dd205f9333951e4c2a608d027d71 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/build.c | 11 +++++------ src/vdbe.c | 19 +++++++++---------- src/vdbeaux.c | 2 +- 5 files changed, 24 insertions(+), 26 deletions(-) diff --git a/manifest b/manifest index adf078c951..fbe4e529cf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sassert()\sthat\smight\sfail\son\sa\scorrupt\sdatabase. -D 2016-02-01T00:21:08.846 +C Minor\ssimplification\sto\sthe\sOP_AutoCommit\sopcode.\s\sFix\ssome\scode\scomments\nrelated\sto\stransaction\scontrol. +D 2016-02-01T13:21:13.072 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -293,7 +293,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c a2a0244ea3f0b3f57f75019c2f229c744ca5d202 F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 0510844c48d80732aead74b5727403b493dd1cd5 +F src/build.c c177ca703d7a3ac6ea6bba3a6c396d67ce79bc69 F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -412,11 +412,11 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 73f0f61eb5556e430487671a557d032ecac52240 +F src/vdbe.c 755b1e2117214549b768efb6e552fcd12a9d859b F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 F src/vdbeapi.c 9d640d5efd9a140a6bda8da53b220aa258167993 -F src/vdbeaux.c 221631e40111b5efa96ea557c6e2e7f62fd32b2a +F src/vdbeaux.c b8ba8e6d48732fb7a735a23e3040a01f4848498e F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a2810cf65db13479e2ab255c37abac7841ee985d -R 188fdebacf7930560dd1bef6de7f142e +P 22eaced7274764eaf7ab4b5fc52cc2fcfc285708 +R 48595a32d50edde169d3b975cd1cf3f9 U drh -Z 4925a52dc50a180b6685bbcef3b9e085 +Z 4ace4ad684d082250fc68f1cbbc590b5 diff --git a/manifest.uuid b/manifest.uuid index 85c92e6bfd..f7adbd19c9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -22eaced7274764eaf7ab4b5fc52cc2fcfc285708 \ No newline at end of file +a9b6a0672f84dd205f9333951e4c2a608d027d71 \ No newline at end of file diff --git a/src/build.c b/src/build.c index be320b9c5a..88ddf406e6 100644 --- a/src/build.c +++ b/src/build.c @@ -3892,7 +3892,7 @@ void sqlite3SrcListShiftJoinType(SrcList *p){ } /* -** Begin a transaction +** Generate VDBE code for a BEGIN statement. */ void sqlite3BeginTransaction(Parse *pParse, int type){ sqlite3 *db; @@ -3902,7 +3902,6 @@ void sqlite3BeginTransaction(Parse *pParse, int type){ assert( pParse!=0 ); db = pParse->db; assert( db!=0 ); -/* if( db->aDb[0].pBt==0 ) return; */ if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){ return; } @@ -3914,11 +3913,11 @@ void sqlite3BeginTransaction(Parse *pParse, int type){ sqlite3VdbeUsesBtree(v, i); } } - sqlite3VdbeAddOp2(v, OP_AutoCommit, 0, 0); + sqlite3VdbeAddOp0(v, OP_AutoCommit); } /* -** Commit a transaction +** Generate VDBE code for a COMMIT statement. */ void sqlite3CommitTransaction(Parse *pParse){ Vdbe *v; @@ -3930,12 +3929,12 @@ void sqlite3CommitTransaction(Parse *pParse){ } v = sqlite3GetVdbe(pParse); if( v ){ - sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 0); + sqlite3VdbeAddOp1(v, OP_AutoCommit, 1); } } /* -** Rollback a transaction +** Generate VDBE code for a ROLLBACK statement. */ void sqlite3RollbackTransaction(Parse *pParse){ Vdbe *v; diff --git a/src/vdbe.c b/src/vdbe.c index a1e59e1170..2bb39c85bf 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3008,28 +3008,27 @@ case OP_Savepoint: { case OP_AutoCommit: { int desiredAutoCommit; int iRollback; - int turnOnAC; desiredAutoCommit = pOp->p1; iRollback = pOp->p2; - turnOnAC = desiredAutoCommit && !db->autoCommit; assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); assert( desiredAutoCommit==1 || iRollback==0 ); assert( db->nVdbeActive>0 ); /* At least this one VM is active */ assert( p->bIsReader ); - if( turnOnAC && !iRollback && db->nVdbeWrite>0 ){ - /* If this instruction implements a COMMIT and other VMs are writing - ** return an error indicating that the other VMs must complete first. - */ - sqlite3VdbeError(p, "cannot commit transaction - " - "SQL statements in progress"); - rc = SQLITE_BUSY; - }else if( desiredAutoCommit!=db->autoCommit ){ + if( desiredAutoCommit!=db->autoCommit ){ if( iRollback ){ assert( desiredAutoCommit==1 ); sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); db->autoCommit = 1; + }else if( desiredAutoCommit && db->nVdbeWrite>0 ){ + /* If this instruction implements a COMMIT and other VMs are writing + ** return an error indicating that the other VMs must complete first. + */ + sqlite3VdbeError(p, "cannot commit transaction - " + "SQL statements in progress"); + rc = SQLITE_BUSY; + break; }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ goto vdbe_return; }else{ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 619aada030..d6cf451af4 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -534,7 +534,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ u8 opcode = pOp->opcode; - /* NOTE: Be sure to update mkopcodeh.awk when adding or removing + /* NOTE: Be sure to update mkopcodeh.tcl when adding or removing ** cases from this switch! */ switch( opcode ){ case OP_Transaction: { From cddb6ba03bdbe25cd0c466c3189a226adc4462ee Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 1 Feb 2016 13:58:56 +0000 Subject: [PATCH 201/570] Fix a problem causing the OR/covering-index optimization to be disabled if compile time parameter SQLITE_MAX_ATTACHED were set to greater than 30. FossilOrigin-Name: a17712bf8d98dd485560f434a5350e6381cf1411 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/wherecode.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index fbe4e529cf..ebebee2b6a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\ssimplification\sto\sthe\sOP_AutoCommit\sopcode.\s\sFix\ssome\scode\scomments\nrelated\sto\stransaction\scontrol. -D 2016-02-01T13:21:13.072 +C Fix\sa\sproblem\scausing\sthe\sOR/covering-index\soptimization\sto\sbe\sdisabled\sif\scompile\stime\sparameter\sSQLITE_MAX_ATTACHED\swere\sset\sto\sgreater\sthan\s30. +D 2016-02-01T13:58:56.691 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -428,7 +428,7 @@ F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c af9bf5dcec1a0e52726c550924aa91d837166251 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a -F src/wherecode.c 7ea737b14e7a35d7f55cbad589a29aa49dfe3f7a +F src/wherecode.c 923f5d04b379b7417bc29f3b86b5eae9d1923d72 F src/whereexpr.c 197a448b52073aee43eca3a2233fc113369eb2d4 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 22eaced7274764eaf7ab4b5fc52cc2fcfc285708 -R 48595a32d50edde169d3b975cd1cf3f9 -U drh -Z 4ace4ad684d082250fc68f1cbbc590b5 +P a9b6a0672f84dd205f9333951e4c2a608d027d71 +R 2464227ee70c33ffde6d518be2a20c9c +U dan +Z 281424deda7a5f64a5e9ae761e185dda diff --git a/manifest.uuid b/manifest.uuid index f7adbd19c9..ec7821b682 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a9b6a0672f84dd205f9333951e4c2a608d027d71 \ No newline at end of file +a17712bf8d98dd485560f434a5350e6381cf1411 \ No newline at end of file diff --git a/src/wherecode.c b/src/wherecode.c index 3fbd198e31..f5f45da397 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -778,7 +778,7 @@ static void codeDeferredSeek( sqlite3VdbeAddOp3(v, OP_Seek, iIdxCur, 0, iCur); if( (pWInfo->wctrlFlags & WHERE_FORCE_TABLE) - && sqlite3ParseToplevel(pParse)->writeMask==0 + && DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask) ){ int i; Table *pTab = pIdx->pTable; From 3b37bc4206898dd93b5280d3aae4ee3fd8293e77 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 1 Feb 2016 16:36:47 +0000 Subject: [PATCH 202/570] Update walcrash.test to ensure that, during a particular test, enough data is written to cause SQLite to sync the wal file 14 times. FossilOrigin-Name: 5d7c092869137a0ba69f93324fe4ed56a05b5985 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/walcrash.test | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index ebebee2b6a..115a4bbaf2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\scausing\sthe\sOR/covering-index\soptimization\sto\sbe\sdisabled\sif\scompile\stime\sparameter\sSQLITE_MAX_ATTACHED\swere\sset\sto\sgreater\sthan\s30. -D 2016-02-01T13:58:56.691 +C Update\swalcrash.test\sto\sensure\sthat,\sduring\sa\sparticular\stest,\senough\sdata\sis\swritten\sto\scause\sSQLite\sto\ssync\sthe\swal\sfile\s14\stimes. +D 2016-02-01T16:36:47.969 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -1308,7 +1308,7 @@ F test/walbak.test b9f68e39646375c2b877be906babcc15d38b4877 F test/walbig.test f437473a16cfb314867c6b5d1dbcd519e73e3434 F test/walblock.test be48f3a75eff0b4456209f26b3ce186c2015497d F test/walcksum.test 9afeb96240296c08c72fc524d199c912cfe34daa -F test/walcrash.test 451d79e528add5c42764cea74aa2750754171b25 +F test/walcrash.test 21038858cc552077b0522f50b0fa87e38139306a F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36 F test/walcrash3.test e426aa58122d20f2b9fbe9a507f9eb8cab85b8af F test/walfault.test 1f8389f7709877e9b4cc679033d71d6fe529056b @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a9b6a0672f84dd205f9333951e4c2a608d027d71 -R 2464227ee70c33ffde6d518be2a20c9c +P a17712bf8d98dd485560f434a5350e6381cf1411 +R 9c14b59494afeacd043f7754f1a985e1 U dan -Z 281424deda7a5f64a5e9ae761e185dda +Z ecc144871fca92cc0fc68693a6e08d49 diff --git a/manifest.uuid b/manifest.uuid index ec7821b682..af8a34f793 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a17712bf8d98dd485560f434a5350e6381cf1411 \ No newline at end of file +5d7c092869137a0ba69f93324fe4ed56a05b5985 \ No newline at end of file diff --git a/test/walcrash.test b/test/walcrash.test index 2a647188b0..b8ca7fbf34 100644 --- a/test/walcrash.test +++ b/test/walcrash.test @@ -237,12 +237,13 @@ for {set i 1} {$i < $REPEATS} {incr i} { INSERT INTO t1 VALUES(randomblob(9000)); INSERT INTO t1 VALUES(randomblob(9000)); INSERT INTO t1 VALUES(randomblob(9000)); + INSERT INTO t1 VALUES(randomblob(9000)); } } {1 {child process exited abnormally}} do_test walcrash-6.$i.2 { sqlite3 db test.db - execsql { SELECT count(*)==34 OR count(*)==35 FROM t1 WHERE x != 1 } + execsql { SELECT count(*) BETWEEN 34 AND 36 FROM t1 WHERE x != 1 } } {1} do_test walcrash-6.$i.3 { execsql { PRAGMA main.integrity_check } } {ok} do_test walcrash-6.$i.4 { execsql { PRAGMA main.journal_mode } } {wal} From ed94af5eb9b75dc1ad6f3d462a14271b5386396b Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 1 Feb 2016 17:20:08 +0000 Subject: [PATCH 203/570] Number VDBE opcodes starting with 0 instead of 1, as this obviates the lower-bound test on "switch(opcode){...}", making the code smaller and faster. FossilOrigin-Name: 4c9222f75bfac47f5422fff86b2d69a61933b3a2 --- manifest | 18 ++++++++-------- manifest.uuid | 2 +- src/vdbeaux.c | 2 +- tool/mkopcodec.tcl | 4 ++-- tool/mkopcodeh.tcl | 54 +++++++++++++++++++++++++--------------------- 5 files changed, 42 insertions(+), 38 deletions(-) diff --git a/manifest b/manifest index 115a4bbaf2..5ae7fd9d24 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\swalcrash.test\sto\sensure\sthat,\sduring\sa\sparticular\stest,\senough\sdata\sis\swritten\sto\scause\sSQLite\sto\ssync\sthe\swal\sfile\s14\stimes. -D 2016-02-01T16:36:47.969 +C Number\sVDBE\sopcodes\sstarting\swith\s0\sinstead\sof\s1,\sas\sthis\sobviates\sthe\nlower-bound\stest\son\s"switch(opcode){...}",\smaking\sthe\scode\ssmaller\sand\sfaster. +D 2016-02-01T17:20:08.707 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -416,7 +416,7 @@ F src/vdbe.c 755b1e2117214549b768efb6e552fcd12a9d859b F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 F src/vdbeapi.c 9d640d5efd9a140a6bda8da53b220aa258167993 -F src/vdbeaux.c b8ba8e6d48732fb7a735a23e3040a01f4848498e +F src/vdbeaux.c f0e7cfa04f7ac44d69866868531dbaf20659d0a2 F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 @@ -1381,8 +1381,8 @@ F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh a29b14d54302b33fd892958f6895582ea90e4a45 F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8 F tool/mkmsvcmin.tcl d57e6efc9428605f5418d0b235721ddf7b5d9c0b -F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b -F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e +F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c +F tool/mkopcodeh.tcl 385c62d78c38b2d92146dcb5abd319dbbc33506d F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkpragmatab.tcl f0d5bb266d1d388cf86fce5ba01a891e95d72d41 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a17712bf8d98dd485560f434a5350e6381cf1411 -R 9c14b59494afeacd043f7754f1a985e1 -U dan -Z ecc144871fca92cc0fc68693a6e08d49 +P 5d7c092869137a0ba69f93324fe4ed56a05b5985 +R c689c18fc524ba4b0a7bb357f3467ad8 +U drh +Z 4a66c8beaa1a93ec6bbf8e1c0f940158 diff --git a/manifest.uuid b/manifest.uuid index af8a34f793..cc32153f40 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5d7c092869137a0ba69f93324fe4ed56a05b5985 \ No newline at end of file +4c9222f75bfac47f5422fff86b2d69a61933b3a2 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index d6cf451af4..13aef0d7fd 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -171,7 +171,7 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ i = p->nOp; assert( p->magic==VDBE_MAGIC_INIT ); - assert( op>0 && op<0xff ); + assert( op>=0 && op<0xff ); if( p->pParse->nOpAlloc<=i ){ return growOp3(p, op, p1, p2, p3); } diff --git a/tool/mkopcodec.tcl b/tool/mkopcodec.tcl index 55d828b14d..abdeaaeb32 100644 --- a/tool/mkopcodec.tcl +++ b/tool/mkopcodec.tcl @@ -19,7 +19,7 @@ puts "#else" puts "# define OpHelp(X)" puts "#endif" puts "const char *sqlite3OpcodeName(int i)\173" -puts " static const char *const azName\[\] = \173 \"?\"," +puts " static const char *const azName\[\] = \173" set mx 0 set in [open [lindex $argv 0] rb] @@ -40,7 +40,7 @@ while {![eof $in]} { } close $in -for {set i 1} {$i<=$mx} {incr i} { +for {set i 0} {$i<=$mx} {incr i} { puts [format " /* %3d */ %-18s OpHelp(\"%s\")," \ $i \"$label($i)\" $synopsis($i)] } diff --git a/tool/mkopcodeh.tcl b/tool/mkopcodeh.tcl index 4c36f24ba4..053c7f8984 100644 --- a/tool/mkopcodeh.tcl +++ b/tool/mkopcodeh.tcl @@ -81,8 +81,8 @@ while {![eof $in]} { set in1($name) 0 set in2($name) 0 set in3($name) 0 - set out1($name) 0 set out2($name) 0 + set out3($name) 0 for {set i 3} {$i<[llength $line]-1} {incr i} { switch [string trim [lindex $line $i] ,] { same { @@ -112,16 +112,19 @@ while {![eof $in]} { # Assign numbers to all opcodes and output the result. # -set cnt 0 -set max 0 puts "/* Automatically generated. Do not edit */" puts "/* See the tool/mkopcodeh.tcl script for details */" -set op(OP_Noop) -1 -set order($nOp) OP_Noop -incr nOp -set op(OP_Explain) -1 -set order($nOp) OP_Explain -incr nOp +foreach name {OP_Noop OP_Explain} { + set jump($name) 0 + set in1($name) 0 + set in2($name) 0 + set in3($name) 0 + set out2($name) 0 + set out3($name) 0 + set op($name) -1 + set order($nOp) $name + incr nOp +} # The following are the opcodes that are processed by resolveP2Values() # @@ -144,7 +147,7 @@ set rp2v_ops { # Assign small values to opcodes that are processed by resolveP2Values() # to make code generation for the switch() statement smaller and faster. # -set cnt 0 +set cnt -1 for {set i 0} {$i<$nOp} {incr i} { set name $order($i) if {[lsearch $rp2v_ops $name]>=0} { @@ -169,7 +172,7 @@ for {set i 0} {$i<$nOp} {incr i} { } } set max $cnt -for {set i 1} {$i<=$nOp} {incr i} { +for {set i 0} {$i<$nOp} {incr i} { if {![info exists used($i)]} { set def($i) "OP_NotUsed_$i" } @@ -196,27 +199,28 @@ for {set i 1} {$i<=$nOp} {incr i} { # Generate the bitvectors: # set bv(0) 0 -for {set i 1} {$i<=$max} {incr i} { +for {set i 0} {$i<=$max} {incr i} { set name $def($i) - if {[info exists jump($name)] && $jump($name)} {set a0 1} {set a0 0} - if {[info exists in1($name)] && $in1($name)} {set a1 2} {set a1 0} - if {[info exists in2($name)] && $in2($name)} {set a2 4} {set a2 0} - if {[info exists in3($name)] && $in3($name)} {set a3 8} {set a3 0} - if {[info exists out2($name)] && $out2($name)} {set a4 16} {set a4 0} - if {[info exists out3($name)] && $out3($name)} {set a5 32} {set a5 0} - set bv($i) [expr {$a0+$a1+$a2+$a3+$a4+$a5}] + set x 0 + if {$jump($name)} {incr x 1} + if {$in1($name)} {incr x 2} + if {$in2($name)} {incr x 4} + if {$in3($name)} {incr x 8} + if {$out2($name)} {incr x 16} + if {$out3($name)} {incr x 32} + set bv($i) $x } puts "" puts "/* Properties such as \"out2\" or \"jump\" that are specified in" puts "** comments following the \"case\" for each opcode in the vdbe.c" puts "** are encoded into bitvectors as follows:" puts "*/" -puts "#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */" -puts "#define OPFLG_IN1 0x0002 /* in1: P1 is an input */" -puts "#define OPFLG_IN2 0x0004 /* in2: P2 is an input */" -puts "#define OPFLG_IN3 0x0008 /* in3: P3 is an input */" -puts "#define OPFLG_OUT2 0x0010 /* out2: P2 is an output */" -puts "#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */" +puts "#define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */" +puts "#define OPFLG_IN1 0x02 /* in1: P1 is an input */" +puts "#define OPFLG_IN2 0x04 /* in2: P2 is an input */" +puts "#define OPFLG_IN3 0x08 /* in3: P3 is an input */" +puts "#define OPFLG_OUT2 0x10 /* out2: P2 is an output */" +puts "#define OPFLG_OUT3 0x20 /* out3: P3 is an output */" puts "#define OPFLG_INITIALIZER \173\\" for {set i 0} {$i<=$max} {incr i} { if {$i%8==0} { From df015945e3fdca65b4bc4b7ef5f431610f405bf0 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 1 Feb 2016 20:12:41 +0000 Subject: [PATCH 204/570] Improve performance of fts5 queries. FossilOrigin-Name: 2334e88244afe6387208be5d527aba9b5ddf4e4c --- ext/fts5/fts5_expr.c | 115 +++++++++++++++++++++++++--------- ext/fts5/fts5_main.c | 16 ++--- ext/fts5/test/fts5simple.test | 23 ++++++- manifest | 18 +++--- manifest.uuid | 2 +- 5 files changed, 122 insertions(+), 52 deletions(-) diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index 3a1497f05d..7c8e3c87c1 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -62,6 +62,9 @@ struct Fts5ExprNode { int bEof; /* True at EOF */ int bNomatch; /* True if entry is not a match */ + /* Next method for this node. */ + int (*xNext)(Fts5Expr*, Fts5ExprNode*, int, i64); + i64 iRowid; /* Current rowid */ Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */ @@ -73,6 +76,12 @@ struct Fts5ExprNode { #define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING) +/* +** Invoke the xNext method of an Fts5ExprNode object. This macro should be +** used as if it has the same signature as the xNext() methods themselves. +*/ +#define fts5ExprNodeNext(a,b,c,d) (b)->xNext((a), (b), (c), (d)) + /* ** An instance of the following structure represents a single search term ** or term prefix. @@ -234,7 +243,15 @@ int sqlite3Fts5ExprNew( sParse.rc = SQLITE_NOMEM; sqlite3Fts5ParseNodeFree(sParse.pExpr); }else{ - pNew->pRoot = sParse.pExpr; + if( !sParse.pExpr ){ + const int nByte = sizeof(Fts5ExprNode); + pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&sParse.rc, nByte); + if( pNew->pRoot ){ + pNew->pRoot->bEof = 1; + } + }else{ + pNew->pRoot = sParse.pExpr; + } pNew->pIndex = 0; pNew->pConfig = pConfig; pNew->apExprPhrase = sParse.apPhrase; @@ -500,12 +517,6 @@ static int fts5LookaheadReaderInit( return fts5LookaheadReaderNext(p); } -#if 0 -static int fts5LookaheadReaderEof(Fts5LookaheadReader *p){ - return (p->iPos==FTS5_LOOKAHEAD_EOF); -} -#endif - typedef struct Fts5NearTrimmer Fts5NearTrimmer; struct Fts5NearTrimmer { Fts5LookaheadReader reader; /* Input iterator */ @@ -636,6 +647,7 @@ static int fts5ExprNearAdvanceFirst( Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0]; int rc = SQLITE_OK; + pNode->bNomatch = 0; if( pTerm->pSynonym ){ int bEof = 1; Fts5ExprTerm *p; @@ -765,17 +777,6 @@ static int fts5ExprNearTest( for(pTerm=&pPhrase->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){ Fts5IndexIter *pIter = pTerm->pIter; if( sqlite3Fts5IterEof(pIter)==0 ){ -#if 0 - int n; - i64 iRowid; - rc = sqlite3Fts5IterPoslist(pIter, pNear->pColset, 0, &n, &iRowid); - if( rc!=SQLITE_OK ){ - *pRc = rc; - return 0; - }else if( iRowid==pNode->iRowid && n>0 ){ - pPhrase->poslist.n = 1; - } -#endif if( pIter->iRowid==pNode->iRowid && pIter->nData>0 ){ pPhrase->poslist.n = 1; } @@ -797,11 +798,6 @@ static int fts5ExprNearTest( }else{ Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; fts5BufferSet(&rc, &pPhrase->poslist, pIter->nData, pIter->pData); -#if 0 - rc = sqlite3Fts5IterPoslistBuffer( - pPhrase->aTerm[0].pIter, &pPhrase->poslist - ); -#endif } } @@ -888,6 +884,7 @@ static int fts5ExprNearNextMatch( if( iRowid==iLast ) continue; bMatch = 0; if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){ + pNode->bNomatch = 0; pNode->bEof = 1; return rc; } @@ -905,7 +902,8 @@ static int fts5ExprNearNextMatch( }while( bMatch==0 ); pNode->iRowid = iLast; - pNode->bNomatch = (0==fts5ExprNearTest(&rc, pExpr, pNode)); + pNode->bNomatch = ((0==fts5ExprNearTest(&rc, pExpr, pNode)) && rc==SQLITE_OK); + assert( pNode->bEof==0 || pNode->bNomatch==0 ); return rc; } @@ -923,6 +921,7 @@ static int fts5ExprNearInitAll( int i, j; int rc = SQLITE_OK; + assert( pNode->bNomatch==0 ); for(i=0; rc==SQLITE_OK && inPhrase; i++){ Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; for(j=0; jnTerm; j++){ @@ -990,6 +989,7 @@ static int fts5RowidCmp( static void fts5ExprSetEof(Fts5ExprNode *pNode){ int i; pNode->bEof = 1; + pNode->bNomatch = 0; for(i=0; inChild; i++){ fts5ExprSetEof(pNode->apChild[i]); } @@ -1012,8 +1012,6 @@ static void fts5ExprNodeZeroPoslist(Fts5ExprNode *pNode){ } -static int fts5ExprNodeNext(Fts5Expr*, Fts5ExprNode*, int, i64); - /* ** Argument pNode is an FTS5_AND node. */ @@ -1093,6 +1091,33 @@ static int fts5NodeCompare( return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid); } +/* +** xNext() method for a node of type FTS5_TERM. +*/ +static int fts5ExprNodeNext_Term( + Fts5Expr *pExpr, + Fts5ExprNode *pNode, + int bFromValid, + i64 iFrom +){ + int rc; + Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter; + + assert( pNode->bEof==0 ); + if( bFromValid ){ + rc = sqlite3Fts5IterNextFrom(pIter, iFrom); + }else{ + rc = sqlite3Fts5IterNext(pIter); + } + if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){ + rc = fts5ExprTokenTest(pExpr, pNode); + }else{ + pNode->bEof = 1; + pNode->bNomatch = 0; + } + return rc; +} + /* ** Advance node iterator pNode, part of expression pExpr. If argument ** bFromValid is zero, then pNode is advanced exactly once. Or, if argument @@ -1100,7 +1125,7 @@ static int fts5NodeCompare( ** rowid value iFrom. Whether "past" means "less than" or "greater than" ** depends on whether this is an ASC or DESC iterator. */ -static int fts5ExprNodeNext( +static int fts5ExprNodeNext_Fallback( Fts5Expr *pExpr, Fts5ExprNode *pNode, int bFromValid, @@ -1127,6 +1152,7 @@ static int fts5ExprNodeNext( rc = fts5ExprTokenTest(pExpr, pNode); }else{ pNode->bEof = 1; + pNode->bNomatch = 0; } return rc; }; @@ -1180,6 +1206,7 @@ static int fts5ExprNodeNext( || pNode->iRowid==iFrom || pExpr->bDesc==(pNode->iRowidbNomatch==0 || rc==SQLITE_OK ); return rc; } @@ -1246,6 +1273,7 @@ static int fts5ExprNodeNextMatch( rc = fts5ExprNodeNext(pExpr, p1, 0, 0); } pNode->bEof = p1->bEof; + pNode->bNomatch = p1->bNomatch; pNode->iRowid = p1->iRowid; if( p1->bEof ){ fts5ExprNodeZeroPoslist(p2); @@ -1268,16 +1296,36 @@ static int fts5ExprNodeNextMatch( static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ int rc = SQLITE_OK; pNode->bEof = 0; + pNode->bNomatch = 0; if( Fts5NodeIsString(pNode) ){ /* Initialize all term iterators in the NEAR object. */ rc = fts5ExprNearInitAll(pExpr, pNode); }else{ int i; + int nEof = 0; for(i=0; inChild && rc==SQLITE_OK; i++){ + Fts5ExprNode *pChild = pNode->apChild[i]; rc = fts5ExprNodeFirst(pExpr, pNode->apChild[i]); + assert( pChild->bEof==0 || pChild->bEof==1 ); + nEof += pChild->bEof; } pNode->iRowid = pNode->apChild[0]->iRowid; + + switch( pNode->eType ){ + case FTS5_AND: + if( nEof>0 ) fts5ExprSetEof(pNode); + break; + + case FTS5_OR: + if( pNode->nChild==nEof ) fts5ExprSetEof(pNode); + break; + + default: + assert( pNode->eType==FTS5_NOT ); + pNode->bEof = pNode->apChild[0]->bEof; + break; + } } if( rc==SQLITE_OK ){ @@ -1305,7 +1353,7 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){ Fts5ExprNode *pRoot = p->pRoot; int rc = SQLITE_OK; - if( pRoot ){ + if( pRoot->xNext ){ p->pIndex = pIdx; p->bDesc = bDesc; rc = fts5ExprNodeFirst(p, pRoot); @@ -1333,9 +1381,11 @@ int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){ int sqlite3Fts5ExprNext(Fts5Expr *p, i64 iLast){ int rc; Fts5ExprNode *pRoot = p->pRoot; + assert( pRoot->bEof==0 && pRoot->bNomatch==0 ); do { rc = fts5ExprNodeNext(p, pRoot, 0, 0); - }while( pRoot->bNomatch && pRoot->bEof==0 && rc==SQLITE_OK ); + assert( pRoot->bNomatch==0 || (rc==SQLITE_OK && pRoot->bEof==0) ); + }while( pRoot->bNomatch ); if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){ pRoot->bEof = 1; } @@ -1343,7 +1393,7 @@ int sqlite3Fts5ExprNext(Fts5Expr *p, i64 iLast){ } int sqlite3Fts5ExprEof(Fts5Expr *p){ - return (p->pRoot==0 || p->pRoot->bEof); + return p->pRoot->bEof; } i64 sqlite3Fts5ExprRowid(Fts5Expr *p){ @@ -1640,6 +1690,7 @@ int sqlite3Fts5ExprClonePhrase( pNew->apExprPhrase[0] = sCtx.pPhrase; pNew->pRoot->pNear->apPhrase[0] = sCtx.pPhrase; pNew->pRoot->pNear->nPhrase = 1; + pNew->pRoot->xNext = fts5ExprNodeNext_Fallback; sCtx.pPhrase->pNode = pNew->pRoot; if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){ @@ -1840,6 +1891,7 @@ Fts5ExprNode *sqlite3Fts5ParseNode( pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte); if( pRet ){ + pRet->xNext = fts5ExprNodeNext_Fallback; pRet->eType = eType; pRet->pNear = pNear; if( eType==FTS5_STRING ){ @@ -1850,6 +1902,7 @@ Fts5ExprNode *sqlite3Fts5ParseNode( if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 ){ if( pNear->apPhrase[0]->aTerm[0].pSynonym==0 ){ pRet->eType = FTS5_TERM; + pRet->xNext = fts5ExprNodeNext_Term; } }else if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){ assert( pParse->rc==SQLITE_OK ); @@ -2144,7 +2197,7 @@ static void fts5ExprFunction( } if( rc==SQLITE_OK ){ char *zText; - if( pExpr->pRoot==0 ){ + if( pExpr->pRoot->xNext==0 ){ zText = sqlite3_mprintf(""); }else if( bTcl ){ zText = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pRoot); diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index ec045da6bf..9ef8d9a01a 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -220,10 +220,10 @@ struct Fts5Cursor { /* ** Values for Fts5Cursor.csrflags */ -#define FTS5CSR_REQUIRE_CONTENT 0x01 -#define FTS5CSR_REQUIRE_DOCSIZE 0x02 -#define FTS5CSR_REQUIRE_INST 0x04 -#define FTS5CSR_EOF 0x08 +#define FTS5CSR_EOF 0x01 +#define FTS5CSR_REQUIRE_CONTENT 0x02 +#define FTS5CSR_REQUIRE_DOCSIZE 0x04 +#define FTS5CSR_REQUIRE_INST 0x08 #define FTS5CSR_FREE_ZRANK 0x10 #define FTS5CSR_REQUIRE_RESEEK 0x20 #define FTS5CSR_REQUIRE_POSLIST 0x40 @@ -778,7 +778,7 @@ static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){ i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc); - if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ + if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ *pbSkip = 1; } @@ -786,6 +786,7 @@ static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){ fts5CsrNewrow(pCsr); if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ CsrFlagSet(pCsr, FTS5CSR_EOF); + *pbSkip = 1; } } return rc; @@ -807,14 +808,13 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ assert( (pCsr->ePlan<3)== (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE) ); + assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) ); if( pCsr->ePlan<3 ){ int bSkip = 0; if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc; rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid); - if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ - CsrFlagSet(pCsr, FTS5CSR_EOF); - } + CsrFlagSet(pCsr, sqlite3Fts5ExprEof(pCsr->pExpr)); fts5CsrNewrow(pCsr); }else{ switch( pCsr->ePlan ){ diff --git a/ext/fts5/test/fts5simple.test b/ext/fts5/test/fts5simple.test index e29c13117c..b6563fd9d0 100644 --- a/ext/fts5/test/fts5simple.test +++ b/ext/fts5/test/fts5simple.test @@ -19,7 +19,7 @@ ifcapable !fts5 { return } - if 1 { +if 1 { #------------------------------------------------------------------------- # @@ -363,8 +363,6 @@ do_execsql_test 15.1 { INSERT INTO x2(x2) VALUES('integrity-check'); } -} - #------------------------------------------------------------------------- foreach_detail_mode $testprefix { reset_db @@ -382,5 +380,24 @@ foreach_detail_mode $testprefix { } {{0.0.0 1.0.2}} } +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 17.0 { + CREATE VIRTUAL TABLE x3 USING fts5(x); + INSERT INTO x3 VALUES('a b c'); +} + +do_execsql_test 17.1 { + SELECT rowid FROM x3('b AND d'); +} + +#------------------------------------------------------------------------- +do_execsql_test 18.1 { + CREATE VIRTUAL TABLE x4 USING fts5(x); + SELECT rowid FROM x4('""'); +} + finish_test diff --git a/manifest b/manifest index 5ae7fd9d24..f5e3ab6b6d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Number\sVDBE\sopcodes\sstarting\swith\s0\sinstead\sof\s1,\sas\sthis\sobviates\sthe\nlower-bound\stest\son\s"switch(opcode){...}",\smaking\sthe\scode\ssmaller\sand\sfaster. -D 2016-02-01T17:20:08.707 +C Improve\sperformance\sof\sfts5\squeries. +D 2016-02-01T20:12:41.276 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -102,10 +102,10 @@ F ext/fts5/fts5Int.h 6e0f90eb4872654a5b98130dec16965716525c9a F ext/fts5/fts5_aux.c b9bcce753ef5b451267b2232f0ca153ddeb3951d F ext/fts5/fts5_buffer.c f6e0c6018ffc8e39fc0b333b5daa8b8d528ae6e4 F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 -F ext/fts5/fts5_expr.c a66b9694519d9c336d9bdbd46ea22e7e14aef412 +F ext/fts5/fts5_expr.c 768d221e592df03b26f46da56aa0a561f00fa4e0 F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 F ext/fts5/fts5_index.c cd1e4faca8b9adc2d89b367075bf93a7f50c406b -F ext/fts5/fts5_main.c 3886bbfc5ac1d9df29979823ddf2b68241e1127e +F ext/fts5/fts5_main.c 7e8a5f27d504bc04e3de7f1cba8867f0332aee9d F ext/fts5/fts5_storage.c 2a1f44deae090cd711f02cec0c2af8e660360d24 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 F ext/fts5/fts5_test_mi.c 1ec66ffdf7632077fbd773b7a6df5153272ec070 @@ -175,7 +175,7 @@ F ext/fts5/test/fts5rank.test 7e9e64eac7245637f6f2033aec4b292aaf611aab F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17 F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6 -F ext/fts5/test/fts5simple.test 2bc6451cbe887a9215f5b14ae307c70d850344c9 +F ext/fts5/test/fts5simple.test 7fcacfa473a37355af2e60096650c87b5ba8f3ba F ext/fts5/test/fts5simple2.test 98377ae1ff7749a42c21fe1a139c1ed312522c46 F ext/fts5/test/fts5simple3.test e671b36bc4dbd4f5095e66cb04473cba9f680f53 F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 5d7c092869137a0ba69f93324fe4ed56a05b5985 -R c689c18fc524ba4b0a7bb357f3467ad8 -U drh -Z 4a66c8beaa1a93ec6bbf8e1c0f940158 +P 4c9222f75bfac47f5422fff86b2d69a61933b3a2 +R 267ad0dad7a7346f85182e52086f7b51 +U dan +Z ee79d8b7c590b68c4d6e9bbdc4c83095 diff --git a/manifest.uuid b/manifest.uuid index cc32153f40..3b468df8c8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4c9222f75bfac47f5422fff86b2d69a61933b3a2 \ No newline at end of file +2334e88244afe6387208be5d527aba9b5ddf4e4c \ No newline at end of file From 1861afcdbb48d4e2cb1f6ec491aeaee51bf15774 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 1 Feb 2016 21:48:34 +0000 Subject: [PATCH 205/570] Change the OP_SetCookie instruction to write the literal P3 value, not the value in register P3. FossilOrigin-Name: 6d7d4703ebf3754bec74123d5ba7e861a705f90f --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/alter.c | 2 +- src/build.c | 12 ++++-------- src/pragma.c | 19 ++++++++----------- src/vdbe.c | 16 +++++++--------- 6 files changed, 31 insertions(+), 40 deletions(-) diff --git a/manifest b/manifest index f5e3ab6b6d..391305ff38 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\sperformance\sof\sfts5\squeries. -D 2016-02-01T20:12:41.276 +C Change\sthe\sOP_SetCookie\sinstruction\sto\swrite\sthe\sliteral\sP3\svalue,\snot\sthe\nvalue\sin\sregister\sP3. +D 2016-02-01T21:48:34.880 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -283,7 +283,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 9d649e46c780166e416fb11dbd23f8d49aab8267 +F src/alter.c 3fe13e97ab38317b092e2f3ae11267b40c9b5cbd F src/analyze.c 0043d3e501f04297fed2bb50b488bc08d5c39f36 F src/attach.c 07b3a34a1702dce92a7f1d3888c0c06222b63760 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 @@ -293,7 +293,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c a2a0244ea3f0b3f57f75019c2f229c744ca5d202 F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c c177ca703d7a3ac6ea6bba3a6c396d67ce79bc69 +F src/build.c 33dea2cef04c16a902c55f9d83b1a2065f213979 F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -340,7 +340,7 @@ F src/parse.y 426a91fbbbf7cdde3fd4b8798de7317a8782bec5 F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23 F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 -F src/pragma.c ea290193369faa0a26ae2f924e7b86289b4a7987 +F src/pragma.c 2ac26ac45eedbed3cc8a9a320ad6d2fc299e69a6 F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c db85f0451ba93ecb3c1e497c279abece5cb5aead F src/printf.c 98a5cef7fc84577ab8a3098cfa48ecfa5a70b9f8 @@ -412,7 +412,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 755b1e2117214549b768efb6e552fcd12a9d859b +F src/vdbe.c a0a0ada4b51161d3950fe30fc696b6c8235a841f F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 F src/vdbeapi.c 9d640d5efd9a140a6bda8da53b220aa258167993 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4c9222f75bfac47f5422fff86b2d69a61933b3a2 -R 267ad0dad7a7346f85182e52086f7b51 -U dan -Z ee79d8b7c590b68c4d6e9bbdc4c83095 +P 2334e88244afe6387208be5d527aba9b5ddf4e4c +R 249f75933f6fe25a197c05fa835262de +U drh +Z 56e6b1659de31a547fab736bcf3cb22f diff --git a/manifest.uuid b/manifest.uuid index 3b468df8c8..54e6aa4e9f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2334e88244afe6387208be5d527aba9b5ddf4e4c \ No newline at end of file +6d7d4703ebf3754bec74123d5ba7e861a705f90f \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 2b043ef158..c8102c55d2 100644 --- a/src/alter.c +++ b/src/alter.c @@ -608,7 +608,7 @@ void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); addr1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, minFormat); sqlite3VdbeJumpHere(v, addr1); sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); diff --git a/src/build.c b/src/build.c index 88ddf406e6..3ca4c99947 100644 --- a/src/build.c +++ b/src/build.c @@ -983,10 +983,8 @@ void sqlite3StartTable( addr1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v); fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? 1 : SQLITE_MAX_FILE_FORMAT; - sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, reg3); - sqlite3VdbeAddOp2(v, OP_Integer, ENC(db), reg3); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, reg3); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, fileFormat); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, ENC(db)); sqlite3VdbeJumpHere(v, addr1); /* This just creates a place-holder record in the sqlite_master table. @@ -1471,13 +1469,11 @@ CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){ ** 1 chance in 2^32. So we're safe enough. */ void sqlite3ChangeCookie(Parse *pParse, int iDb){ - int r1 = sqlite3GetTempReg(pParse); sqlite3 *db = pParse->db; Vdbe *v = pParse->pVdbe; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, r1); - sqlite3ReleaseTempReg(pParse, r1); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, + db->aDb[iDb].pSchema->schema_cookie+1); } /* diff --git a/src/pragma.c b/src/pragma.c index 15f0eecce3..1d827d7b70 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -444,8 +444,7 @@ void sqlite3Pragma( }else{ int size = sqlite3AbsInt32(sqlite3Atoi(zRight)); sqlite3BeginWriteOperation(pParse, 0, iDb); - sqlite3VdbeAddOp2(v, OP_Integer, size, 1); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, size); assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pDb->pSchema->cache_size = size; sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); @@ -683,8 +682,7 @@ void sqlite3Pragma( { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, { OP_If, 1, 0, 0}, /* 2 */ { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ - { OP_Integer, 0, 1, 0}, /* 4 */ - { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */ + { OP_SetCookie, 0, BTREE_INCR_VACUUM, 0}, /* 4 */ }; VdbeOp *aOp; int iAddr = sqlite3VdbeCurrentAddr(v); @@ -694,8 +692,8 @@ void sqlite3Pragma( aOp[0].p1 = iDb; aOp[1].p1 = iDb; aOp[2].p2 = iAddr+4; - aOp[4].p1 = eAuto - 1; - aOp[5].p1 = iDb; + aOp[4].p1 = iDb; + aOp[4].p3 = eAuto - 1; sqlite3VdbeUsesBtree(v, iDb); } } @@ -1728,17 +1726,16 @@ void sqlite3Pragma( /* Write the specified cookie value */ static const VdbeOpList setCookie[] = { { OP_Transaction, 0, 1, 0}, /* 0 */ - { OP_Integer, 0, 1, 0}, /* 1 */ - { OP_SetCookie, 0, 0, 1}, /* 2 */ + { OP_SetCookie, 0, 0, 0}, /* 1 */ }; VdbeOp *aOp; sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setCookie)); aOp = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0); if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; aOp[0].p1 = iDb; - aOp[1].p1 = sqlite3Atoi(zRight); - aOp[2].p1 = iDb; - aOp[2].p2 = iCookie; + aOp[1].p1 = iDb; + aOp[1].p2 = iCookie; + aOp[1].p3 = sqlite3Atoi(zRight); }else{ /* Read the specified cookie value */ static const VdbeOpList readCookie[] = { diff --git a/src/vdbe.c b/src/vdbe.c index 2bb39c85bf..1cf4cb16a7 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3213,15 +3213,15 @@ case OP_ReadCookie: { /* out2 */ /* Opcode: SetCookie P1 P2 P3 * * ** -** Write the content of register P3 (interpreted as an integer) -** into cookie number P2 of database P1. P2==1 is the schema version. -** P2==2 is the database format. P2==3 is the recommended pager cache +** Write the integer value P3 into cookie number P2 of database P1. +** P2==1 is the schema version. P2==2 is the database format. +** P2==3 is the recommended pager cache ** size, and so forth. P1==0 is the main database file and P1==1 is the ** database file used to store temporary tables. ** ** A transaction must be started before executing this opcode. */ -case OP_SetCookie: { /* in3 */ +case OP_SetCookie: { Db *pDb; assert( pOp->p2p1>=0 && pOp->p1nDb ); @@ -3230,17 +3230,15 @@ case OP_SetCookie: { /* in3 */ pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); - pIn3 = &aMem[pOp->p3]; - sqlite3VdbeMemIntegerify(pIn3); /* See note about index shifting on OP_ReadCookie */ - rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, (int)pIn3->u.i); + rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, pOp->p3); if( pOp->p2==BTREE_SCHEMA_VERSION ){ /* When the schema cookie changes, record the new cookie internally */ - pDb->pSchema->schema_cookie = (int)pIn3->u.i; + pDb->pSchema->schema_cookie = pOp->p3; db->flags |= SQLITE_InternChanges; }else if( pOp->p2==BTREE_FILE_FORMAT ){ /* Record changes in the file format */ - pDb->pSchema->file_format = (u8)pIn3->u.i; + pDb->pSchema->file_format = pOp->p3; } if( pOp->p1==1 ){ /* Invalidate all prepared statements whenever the TEMP database From b8db549832d2acc2fc30327e6fb5c0474820f122 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 2 Feb 2016 02:04:21 +0000 Subject: [PATCH 206/570] Enhance the comment on the sqlite3_index_constraint object to bring attention to the fact than iColumn field can be negative for a rowid. FossilOrigin-Name: d8b7b1996eefae7768bfcb82d4ff22c69392aa63 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqlite.h.in | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 391305ff38..3952435799 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sOP_SetCookie\sinstruction\sto\swrite\sthe\sliteral\sP3\svalue,\snot\sthe\nvalue\sin\sregister\sP3. -D 2016-02-01T21:48:34.880 +C Enhance\sthe\scomment\son\sthe\ssqlite3_index_constraint\sobject\sto\sbring\sattention\s\nto\sthe\sfact\sthan\siColumn\sfield\scan\sbe\snegative\sfor\sa\srowid. +D 2016-02-02T02:04:21.840 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -349,7 +349,7 @@ F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c ea6f3b0c279aa37eb3701792d094673a7ad1bf88 F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 -F src/sqlite.h.in 214476a62012e578f42133a9a3b4f97a9aa421a3 +F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d F src/sqliteInt.h 2f80b9b1506a8d602b2a99f3f0bfae22df3e7d70 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2334e88244afe6387208be5d527aba9b5ddf4e4c -R 249f75933f6fe25a197c05fa835262de +P 6d7d4703ebf3754bec74123d5ba7e861a705f90f +R a0fd58918162f72722cea72a597641d9 U drh -Z 56e6b1659de31a547fab736bcf3cb22f +Z 8a77cde1543981fcb216eb719b02e019 diff --git a/manifest.uuid b/manifest.uuid index 54e6aa4e9f..dae04066fb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6d7d4703ebf3754bec74123d5ba7e861a705f90f \ No newline at end of file +d8b7b1996eefae7768bfcb82d4ff22c69392aa63 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 59b30cdd3a..fce396c0f6 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -5697,7 +5697,7 @@ struct sqlite3_index_info { /* Inputs */ int nConstraint; /* Number of entries in aConstraint */ struct sqlite3_index_constraint { - int iColumn; /* Column on left-hand side of constraint */ + int iColumn; /* Column constrained. -1 for ROWID */ unsigned char op; /* Constraint operator */ unsigned char usable; /* True if this constraint is usable */ int iTermOffset; /* Used internally - xBestIndex should ignore */ From 735ff4a80947404ab8960e2b6d6d23c0b163661f Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 2 Feb 2016 17:40:41 +0000 Subject: [PATCH 207/570] Enhance the performance of fts5 AND and OR queries. FossilOrigin-Name: 62ea9e5ab8bc1a20245beebceb5ea62dcd7ec84e --- ext/fts5/fts5Int.h | 4 +- ext/fts5/fts5_expr.c | 714 ++++++++++++++++++------------------ ext/fts5/fts5_index.c | 27 +- ext/fts5/tool/fts5speed.tcl | 4 + manifest | 20 +- manifest.uuid | 2 +- 6 files changed, 384 insertions(+), 387 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index 48ab980921..9e5e52fa41 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -319,8 +319,11 @@ struct Fts5IndexIter { i64 iRowid; const u8 *pData; int nData; + u8 bEof; }; +#define sqlite3Fts5IterEof(x) ((x)->bEof) + /* ** Values used as part of the flags argument passed to IndexQuery(). */ @@ -384,7 +387,6 @@ int sqlite3Fts5IndexQuery( ** The various operations on open token or token prefix iterators opened ** using sqlite3Fts5IndexQuery(). */ -int sqlite3Fts5IterEof(Fts5IndexIter*); int sqlite3Fts5IterNext(Fts5IndexIter*); int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch); i64 sqlite3Fts5IterRowid(Fts5IndexIter*); diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index 7c8e3c87c1..1df173cfcc 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -303,7 +303,7 @@ static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){ assert( bDesc==0 || bDesc==1 ); for(p=pTerm; p; p=p->pSynonym){ if( 0==sqlite3Fts5IterEof(p->pIter) ){ - i64 iRowid = sqlite3Fts5IterRowid(p->pIter); + i64 iRowid = p->pIter->iRowid; if( bRetValid==0 || (bDesc!=(iRowidpSynonym ); for(p=pTerm; p; p=p->pSynonym){ Fts5IndexIter *pIter = p->pIter; - if( sqlite3Fts5IterEof(pIter)==0 && sqlite3Fts5IterRowid(pIter)==iRowid ){ + if( sqlite3Fts5IterEof(pIter)==0 && pIter->iRowid==iRowid ){ if( pIter->nData==0 ) continue; if( nIter==nAlloc ){ int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2; @@ -631,72 +631,6 @@ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){ } } -/* -** Advance the first term iterator in the first phrase of pNear. Set output -** variable *pbEof to true if it reaches EOF or if an error occurs. -** -** Return SQLITE_OK if successful, or an SQLite error code if an error -** occurs. -*/ -static int fts5ExprNearAdvanceFirst( - Fts5Expr *pExpr, /* Expression pPhrase belongs to */ - Fts5ExprNode *pNode, /* FTS5_STRING or FTS5_TERM node */ - int bFromValid, - i64 iFrom -){ - Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0]; - int rc = SQLITE_OK; - - pNode->bNomatch = 0; - if( pTerm->pSynonym ){ - int bEof = 1; - Fts5ExprTerm *p; - - /* Find the firstest rowid any synonym points to. */ - i64 iRowid = fts5ExprSynonymRowid(pTerm, pExpr->bDesc, 0); - - /* Advance each iterator that currently points to iRowid. Or, if iFrom - ** is valid - each iterator that points to a rowid before iFrom. */ - for(p=pTerm; p; p=p->pSynonym){ - if( sqlite3Fts5IterEof(p->pIter)==0 ){ - i64 ii = sqlite3Fts5IterRowid(p->pIter); - if( ii==iRowid - || (bFromValid && ii!=iFrom && (ii>iFrom)==pExpr->bDesc) - ){ - if( bFromValid ){ - rc = sqlite3Fts5IterNextFrom(p->pIter, iFrom); - }else{ - rc = sqlite3Fts5IterNext(p->pIter); - } - if( rc!=SQLITE_OK ) break; - if( sqlite3Fts5IterEof(p->pIter)==0 ){ - bEof = 0; - } - }else{ - bEof = 0; - } - } - } - - /* Set the EOF flag if either all synonym iterators are at EOF or an - ** error has occurred. */ - pNode->bEof = (rc || bEof); - }else{ - Fts5IndexIter *pIter = pTerm->pIter; - - assert( Fts5NodeIsString(pNode) ); - if( bFromValid ){ - rc = sqlite3Fts5IterNextFrom(pIter, iFrom); - }else{ - rc = sqlite3Fts5IterNext(pIter); - } - - pNode->bEof = (rc || sqlite3Fts5IterEof(pIter)); - } - - return rc; -} - /* ** Advance iterator pIter until it points to a value equal to or laster ** than the initial value of *piLast. If this means the iterator points @@ -716,7 +650,7 @@ static int fts5ExprAdvanceto( i64 iLast = *piLast; i64 iRowid; - iRowid = sqlite3Fts5IterRowid(pIter); + iRowid = pIter->iRowid; if( (bDesc==0 && iLast>iRowid) || (bDesc && iLastiRowid; assert( (bDesc==0 && iRowid>=iLast) || (bDesc==1 && iRowid<=iLast) ); } *piLast = iRowid; @@ -745,7 +679,7 @@ static int fts5ExprSynonymAdvanceto( for(p=pTerm; rc==SQLITE_OK && p; p=p->pSynonym){ if( sqlite3Fts5IterEof(p->pIter)==0 ){ - i64 iRowid = sqlite3Fts5IterRowid(p->pIter); + i64 iRowid = p->pIter->iRowid; if( (bDesc==0 && iLast>iRowid) || (bDesc && iLastpIter, iLast); } @@ -809,104 +743,6 @@ static int fts5ExprNearTest( } } -static int fts5ExprTokenTest( - Fts5Expr *pExpr, /* Expression that pNear is a part of */ - Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */ -){ - /* As this "NEAR" object is actually a single phrase that consists - ** of a single term only, grab pointers into the poslist managed by the - ** fts5_index.c iterator object. This is much faster than synthesizing - ** a new poslist the way we have to for more complicated phrase or NEAR - ** expressions. */ - Fts5ExprPhrase *pPhrase = pNode->pNear->apPhrase[0]; - Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; - - assert( pNode->eType==FTS5_TERM ); - assert( pNode->pNear->nPhrase==1 && pPhrase->nTerm==1 ); - assert( pPhrase->aTerm[0].pSynonym==0 ); - - pPhrase->poslist.n = pIter->nData; - if( pExpr->pConfig->eDetail==FTS5_DETAIL_FULL ){ - pPhrase->poslist.p = (u8*)pIter->pData; - } - pNode->iRowid = pIter->iRowid; - pNode->bNomatch = (pPhrase->poslist.n==0); - return SQLITE_OK; -} - -/* -** All individual term iterators in pNear are guaranteed to be valid when -** this function is called. This function checks if all term iterators -** point to the same rowid, and if not, advances them until they do. -** If an EOF is reached before this happens, *pbEof is set to true before -** returning. -** -** SQLITE_OK is returned if an error occurs, or an SQLite error code -** otherwise. It is not considered an error code if an iterator reaches -** EOF. -*/ -static int fts5ExprNearNextMatch( - Fts5Expr *pExpr, /* Expression pPhrase belongs to */ - Fts5ExprNode *pNode -){ - Fts5ExprNearset *pNear = pNode->pNear; - Fts5ExprPhrase *pLeft = pNear->apPhrase[0]; - int rc = SQLITE_OK; - i64 iLast; /* Lastest rowid any iterator points to */ - int i, j; /* Phrase and token index, respectively */ - int bMatch; /* True if all terms are at the same rowid */ - const int bDesc = pExpr->bDesc; - - /* Check that this node should not be FTS5_TERM */ - assert( pNear->nPhrase>1 - || pNear->apPhrase[0]->nTerm>1 - || pNear->apPhrase[0]->aTerm[0].pSynonym - ); - - /* Initialize iLast, the "lastest" rowid any iterator points to. If the - ** iterator skips through rowids in the default ascending order, this means - ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it - ** means the minimum rowid. */ - if( pLeft->aTerm[0].pSynonym ){ - iLast = fts5ExprSynonymRowid(&pLeft->aTerm[0], bDesc, 0); - }else{ - iLast = sqlite3Fts5IterRowid(pLeft->aTerm[0].pIter); - } - - do { - bMatch = 1; - for(i=0; inPhrase; i++){ - Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; - for(j=0; jnTerm; j++){ - Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; - if( pTerm->pSynonym ){ - i64 iRowid = fts5ExprSynonymRowid(pTerm, bDesc, 0); - if( iRowid==iLast ) continue; - bMatch = 0; - if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){ - pNode->bNomatch = 0; - pNode->bEof = 1; - return rc; - } - }else{ - Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; - i64 iRowid = sqlite3Fts5IterRowid(pIter); - if( iRowid==iLast ) continue; - bMatch = 0; - if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){ - return rc; - } - } - } - } - }while( bMatch==0 ); - - pNode->iRowid = iLast; - pNode->bNomatch = ((0==fts5ExprNearTest(&rc, pExpr, pNode)) && rc==SQLITE_OK); - assert( pNode->bEof==0 || pNode->bNomatch==0 ); - - return rc; -} /* ** Initialize all term iterators in the pNear object. If any term is found @@ -957,10 +793,6 @@ static int fts5ExprNearInitAll( return rc; } -/* fts5ExprNodeNext() calls fts5ExprNodeNextMatch(). And vice-versa. */ -static int fts5ExprNodeNextMatch(Fts5Expr*, Fts5ExprNode*); - - /* ** If pExpr is an ASC iterator, this function returns a value with the ** same sign as: @@ -1012,10 +844,275 @@ static void fts5ExprNodeZeroPoslist(Fts5ExprNode *pNode){ } + +/* +** Compare the values currently indicated by the two nodes as follows: +** +** res = (*p1) - (*p2) +** +** Nodes that point to values that come later in the iteration order are +** considered to be larger. Nodes at EOF are the largest of all. +** +** This means that if the iteration order is ASC, then numerically larger +** rowids are considered larger. Or if it is the default DESC, numerically +** smaller rowids are larger. +*/ +static int fts5NodeCompare( + Fts5Expr *pExpr, + Fts5ExprNode *p1, + Fts5ExprNode *p2 +){ + if( p2->bEof ) return -1; + if( p1->bEof ) return +1; + return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid); +} + +/* +** All individual term iterators in pNear are guaranteed to be valid when +** this function is called. This function checks if all term iterators +** point to the same rowid, and if not, advances them until they do. +** If an EOF is reached before this happens, *pbEof is set to true before +** returning. +** +** SQLITE_OK is returned if an error occurs, or an SQLite error code +** otherwise. It is not considered an error code if an iterator reaches +** EOF. +*/ +static int fts5ExprNodeTest_STRING( + Fts5Expr *pExpr, /* Expression pPhrase belongs to */ + Fts5ExprNode *pNode +){ + Fts5ExprNearset *pNear = pNode->pNear; + Fts5ExprPhrase *pLeft = pNear->apPhrase[0]; + int rc = SQLITE_OK; + i64 iLast; /* Lastest rowid any iterator points to */ + int i, j; /* Phrase and token index, respectively */ + int bMatch; /* True if all terms are at the same rowid */ + const int bDesc = pExpr->bDesc; + + /* Check that this node should not be FTS5_TERM */ + assert( pNear->nPhrase>1 + || pNear->apPhrase[0]->nTerm>1 + || pNear->apPhrase[0]->aTerm[0].pSynonym + ); + + /* Initialize iLast, the "lastest" rowid any iterator points to. If the + ** iterator skips through rowids in the default ascending order, this means + ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it + ** means the minimum rowid. */ + if( pLeft->aTerm[0].pSynonym ){ + iLast = fts5ExprSynonymRowid(&pLeft->aTerm[0], bDesc, 0); + }else{ + iLast = pLeft->aTerm[0].pIter->iRowid; + } + + do { + bMatch = 1; + for(i=0; inPhrase; i++){ + Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; + for(j=0; jnTerm; j++){ + Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; + if( pTerm->pSynonym ){ + i64 iRowid = fts5ExprSynonymRowid(pTerm, bDesc, 0); + if( iRowid==iLast ) continue; + bMatch = 0; + if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){ + pNode->bNomatch = 0; + pNode->bEof = 1; + return rc; + } + }else{ + Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; + if( pIter->iRowid==iLast ) continue; + bMatch = 0; + if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){ + return rc; + } + } + } + } + }while( bMatch==0 ); + + pNode->iRowid = iLast; + pNode->bNomatch = ((0==fts5ExprNearTest(&rc, pExpr, pNode)) && rc==SQLITE_OK); + assert( pNode->bEof==0 || pNode->bNomatch==0 ); + + return rc; +} + +/* +** Advance the first term iterator in the first phrase of pNear. Set output +** variable *pbEof to true if it reaches EOF or if an error occurs. +** +** Return SQLITE_OK if successful, or an SQLite error code if an error +** occurs. +*/ +static int fts5ExprNodeNext_STRING( + Fts5Expr *pExpr, /* Expression pPhrase belongs to */ + Fts5ExprNode *pNode, /* FTS5_STRING or FTS5_TERM node */ + int bFromValid, + i64 iFrom +){ + Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0]; + int rc = SQLITE_OK; + + pNode->bNomatch = 0; + if( pTerm->pSynonym ){ + int bEof = 1; + Fts5ExprTerm *p; + + /* Find the firstest rowid any synonym points to. */ + i64 iRowid = fts5ExprSynonymRowid(pTerm, pExpr->bDesc, 0); + + /* Advance each iterator that currently points to iRowid. Or, if iFrom + ** is valid - each iterator that points to a rowid before iFrom. */ + for(p=pTerm; p; p=p->pSynonym){ + if( sqlite3Fts5IterEof(p->pIter)==0 ){ + i64 ii = p->pIter->iRowid; + if( ii==iRowid + || (bFromValid && ii!=iFrom && (ii>iFrom)==pExpr->bDesc) + ){ + if( bFromValid ){ + rc = sqlite3Fts5IterNextFrom(p->pIter, iFrom); + }else{ + rc = sqlite3Fts5IterNext(p->pIter); + } + if( rc!=SQLITE_OK ) break; + if( sqlite3Fts5IterEof(p->pIter)==0 ){ + bEof = 0; + } + }else{ + bEof = 0; + } + } + } + + /* Set the EOF flag if either all synonym iterators are at EOF or an + ** error has occurred. */ + pNode->bEof = (rc || bEof); + }else{ + Fts5IndexIter *pIter = pTerm->pIter; + + assert( Fts5NodeIsString(pNode) ); + if( bFromValid ){ + rc = sqlite3Fts5IterNextFrom(pIter, iFrom); + }else{ + rc = sqlite3Fts5IterNext(pIter); + } + + pNode->bEof = (rc || sqlite3Fts5IterEof(pIter)); + } + + if( pNode->bEof==0 ){ + assert( rc==SQLITE_OK ); + rc = fts5ExprNodeTest_STRING(pExpr, pNode); + } + + return rc; +} + + +static int fts5ExprNodeTest_TERM( + Fts5Expr *pExpr, /* Expression that pNear is a part of */ + Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */ +){ + /* As this "NEAR" object is actually a single phrase that consists + ** of a single term only, grab pointers into the poslist managed by the + ** fts5_index.c iterator object. This is much faster than synthesizing + ** a new poslist the way we have to for more complicated phrase or NEAR + ** expressions. */ + Fts5ExprPhrase *pPhrase = pNode->pNear->apPhrase[0]; + Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; + + assert( pNode->eType==FTS5_TERM ); + assert( pNode->pNear->nPhrase==1 && pPhrase->nTerm==1 ); + assert( pPhrase->aTerm[0].pSynonym==0 ); + + pPhrase->poslist.n = pIter->nData; + if( pExpr->pConfig->eDetail==FTS5_DETAIL_FULL ){ + pPhrase->poslist.p = (u8*)pIter->pData; + } + pNode->iRowid = pIter->iRowid; + pNode->bNomatch = (pPhrase->poslist.n==0); + return SQLITE_OK; +} + +/* +** xNext() method for a node of type FTS5_TERM. +*/ +static int fts5ExprNodeNext_TERM( + Fts5Expr *pExpr, + Fts5ExprNode *pNode, + int bFromValid, + i64 iFrom +){ + int rc; + Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter; + + assert( pNode->bEof==0 ); + if( bFromValid ){ + rc = sqlite3Fts5IterNextFrom(pIter, iFrom); + }else{ + rc = sqlite3Fts5IterNext(pIter); + } + if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){ + rc = fts5ExprNodeTest_TERM(pExpr, pNode); + }else{ + pNode->bEof = 1; + pNode->bNomatch = 0; + } + return rc; +} + +static void fts5ExprNodeTest_OR( + Fts5Expr *pExpr, /* Expression of which pNode is a part */ + Fts5ExprNode *pNode /* Expression node to test */ +){ + Fts5ExprNode *pNext = pNode->apChild[0]; + int i; + + for(i=1; inChild; i++){ + Fts5ExprNode *pChild = pNode->apChild[i]; + int cmp = fts5NodeCompare(pExpr, pNext, pChild); + if( cmp>0 || (cmp==0 && pChild->bNomatch==0) ){ + pNext = pChild; + } + } + pNode->iRowid = pNext->iRowid; + pNode->bEof = pNext->bEof; + pNode->bNomatch = pNext->bNomatch; +} + +static int fts5ExprNodeNext_OR( + Fts5Expr *pExpr, + Fts5ExprNode *pNode, + int bFromValid, + i64 iFrom +){ + int i; + i64 iLast = pNode->iRowid; + + for(i=0; inChild; i++){ + Fts5ExprNode *p1 = pNode->apChild[i]; + assert( p1->bEof || fts5RowidCmp(pExpr, p1->iRowid, iLast)>=0 ); + if( p1->bEof==0 ){ + if( (p1->iRowid==iLast) + || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0) + ){ + int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); + if( rc!=SQLITE_OK ) return rc; + } + } + } + + fts5ExprNodeTest_OR(pExpr, pNode); + return SQLITE_OK; +} + /* ** Argument pNode is an FTS5_AND node. */ -static int fts5ExprAndNextRowid( +static int fts5ExprNodeTest_AND( Fts5Expr *pExpr, /* Expression pPhrase belongs to */ Fts5ExprNode *pAnd /* FTS5_AND node to advance */ ){ @@ -1030,15 +1127,11 @@ static int fts5ExprAndNextRowid( bMatch = 1; for(iChild=0; iChildnChild; iChild++){ Fts5ExprNode *pChild = pAnd->apChild[iChild]; - if( 0 && pChild->eType==FTS5_STRING ){ - /* TODO */ - }else{ - int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid); - if( cmp>0 ){ - /* Advance pChild until it points to iLast or laster */ - rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast); - if( rc!=SQLITE_OK ) return rc; - } + int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid); + if( cmp>0 ){ + /* Advance pChild until it points to iLast or laster */ + rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast); + if( rc!=SQLITE_OK ) return rc; } /* If the child node is now at EOF, so is the parent AND node. Otherwise, @@ -1068,155 +1161,66 @@ static int fts5ExprAndNextRowid( return SQLITE_OK; } - -/* -** Compare the values currently indicated by the two nodes as follows: -** -** res = (*p1) - (*p2) -** -** Nodes that point to values that come later in the iteration order are -** considered to be larger. Nodes at EOF are the largest of all. -** -** This means that if the iteration order is ASC, then numerically larger -** rowids are considered larger. Or if it is the default DESC, numerically -** smaller rowids are larger. -*/ -static int fts5NodeCompare( - Fts5Expr *pExpr, - Fts5ExprNode *p1, - Fts5ExprNode *p2 -){ - if( p2->bEof ) return -1; - if( p1->bEof ) return +1; - return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid); -} - -/* -** xNext() method for a node of type FTS5_TERM. -*/ -static int fts5ExprNodeNext_Term( +static int fts5ExprNodeNext_AND( Fts5Expr *pExpr, Fts5ExprNode *pNode, int bFromValid, i64 iFrom ){ - int rc; - Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter; - - assert( pNode->bEof==0 ); - if( bFromValid ){ - rc = sqlite3Fts5IterNextFrom(pIter, iFrom); - }else{ - rc = sqlite3Fts5IterNext(pIter); - } - if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){ - rc = fts5ExprTokenTest(pExpr, pNode); - }else{ - pNode->bEof = 1; - pNode->bNomatch = 0; + int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); + if( rc==SQLITE_OK ){ + rc = fts5ExprNodeTest_AND(pExpr, pNode); } return rc; } -/* -** Advance node iterator pNode, part of expression pExpr. If argument -** bFromValid is zero, then pNode is advanced exactly once. Or, if argument -** bFromValid is non-zero, then pNode is advanced until it is at or past -** rowid value iFrom. Whether "past" means "less than" or "greater than" -** depends on whether this is an ASC or DESC iterator. -*/ -static int fts5ExprNodeNext_Fallback( - Fts5Expr *pExpr, - Fts5ExprNode *pNode, - int bFromValid, - i64 iFrom +static int fts5ExprNodeTest_NOT( + Fts5Expr *pExpr, /* Expression pPhrase belongs to */ + Fts5ExprNode *pNode /* FTS5_NOT node to advance */ ){ int rc = SQLITE_OK; + Fts5ExprNode *p1 = pNode->apChild[0]; + Fts5ExprNode *p2 = pNode->apChild[1]; + assert( pNode->nChild==2 ); - if( pNode->bEof==0 ){ - switch( pNode->eType ){ - case FTS5_STRING: { - rc = fts5ExprNearAdvanceFirst(pExpr, pNode, bFromValid, iFrom); - break; - }; - - case FTS5_TERM: { - Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter; - if( bFromValid ){ - rc = sqlite3Fts5IterNextFrom(pIter, iFrom); - }else{ - rc = sqlite3Fts5IterNext(pIter); - } - if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){ - assert( rc==SQLITE_OK ); - rc = fts5ExprTokenTest(pExpr, pNode); - }else{ - pNode->bEof = 1; - pNode->bNomatch = 0; - } - return rc; - }; - - case FTS5_AND: { - Fts5ExprNode *pLeft = pNode->apChild[0]; - rc = fts5ExprNodeNext(pExpr, pLeft, bFromValid, iFrom); - break; - } - - case FTS5_OR: { - int i; - i64 iLast = pNode->iRowid; - - for(i=0; rc==SQLITE_OK && inChild; i++){ - Fts5ExprNode *p1 = pNode->apChild[i]; - assert( p1->bEof || fts5RowidCmp(pExpr, p1->iRowid, iLast)>=0 ); - if( p1->bEof==0 ){ - if( (p1->iRowid==iLast) - || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0) - ){ - rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); - } - } - } - - break; - } - - default: assert( pNode->eType==FTS5_NOT ); { - assert( pNode->nChild==2 ); - rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); - break; - } - } - - if( rc==SQLITE_OK ){ - rc = fts5ExprNodeNextMatch(pExpr, pNode); + while( rc==SQLITE_OK && p1->bEof==0 ){ + int cmp = fts5NodeCompare(pExpr, p1, p2); + if( cmp>0 ){ + rc = fts5ExprNodeNext(pExpr, p2, 1, p1->iRowid); + cmp = fts5NodeCompare(pExpr, p1, p2); } + assert( rc!=SQLITE_OK || cmp<=0 ); + if( cmp || p2->bNomatch ) break; + rc = fts5ExprNodeNext(pExpr, p1, 0, 0); + } + pNode->bEof = p1->bEof; + pNode->bNomatch = p1->bNomatch; + pNode->iRowid = p1->iRowid; + if( p1->bEof ){ + fts5ExprNodeZeroPoslist(p2); } - - /* Assert that if bFromValid was true, either: - ** - ** a) an error occurred, or - ** b) the node is now at EOF, or - ** c) the node is now at or past rowid iFrom. - */ - assert( bFromValid==0 - || rc!=SQLITE_OK /* a */ - || pNode->bEof /* b */ - || pNode->iRowid==iFrom || pExpr->bDesc==(pNode->iRowidbNomatch==0 || rc==SQLITE_OK ); return rc; } +static int fts5ExprNodeNext_NOT( + Fts5Expr *pExpr, + Fts5ExprNode *pNode, + int bFromValid, + i64 iFrom +){ + int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); + if( rc==SQLITE_OK ){ + rc = fts5ExprNodeTest_NOT(pExpr, pNode); + } + return rc; +} /* ** If pNode currently points to a match, this function returns SQLITE_OK ** without modifying it. Otherwise, pNode is advanced until it does point ** to a match or EOF is reached. */ -static int fts5ExprNodeNextMatch( +static int fts5ExprNodeTest( Fts5Expr *pExpr, /* Expression of which pNode is a part */ Fts5ExprNode *pNode /* Expression node to test */ ){ @@ -1225,59 +1229,27 @@ static int fts5ExprNodeNextMatch( switch( pNode->eType ){ case FTS5_STRING: { - /* Advance the iterators until they all point to the same rowid */ - rc = fts5ExprNearNextMatch(pExpr, pNode); + rc = fts5ExprNodeTest_STRING(pExpr, pNode); break; } case FTS5_TERM: { - rc = fts5ExprTokenTest(pExpr, pNode); + rc = fts5ExprNodeTest_TERM(pExpr, pNode); break; } case FTS5_AND: { - rc = fts5ExprAndNextRowid(pExpr, pNode); + rc = fts5ExprNodeTest_AND(pExpr, pNode); break; } case FTS5_OR: { - Fts5ExprNode *pNext = pNode->apChild[0]; - int i; - - for(i=1; inChild; i++){ - Fts5ExprNode *pChild = pNode->apChild[i]; - int cmp = fts5NodeCompare(pExpr, pNext, pChild); - if( cmp>0 || (cmp==0 && pChild->bNomatch==0) ){ - pNext = pChild; - } - } - pNode->iRowid = pNext->iRowid; - pNode->bEof = pNext->bEof; - pNode->bNomatch = pNext->bNomatch; + fts5ExprNodeTest_OR(pExpr, pNode); break; } default: assert( pNode->eType==FTS5_NOT ); { - Fts5ExprNode *p1 = pNode->apChild[0]; - Fts5ExprNode *p2 = pNode->apChild[1]; - assert( pNode->nChild==2 ); - - while( rc==SQLITE_OK && p1->bEof==0 ){ - int cmp = fts5NodeCompare(pExpr, p1, p2); - if( cmp>0 ){ - rc = fts5ExprNodeNext(pExpr, p2, 1, p1->iRowid); - cmp = fts5NodeCompare(pExpr, p1, p2); - } - assert( rc!=SQLITE_OK || cmp<=0 ); - if( cmp || p2->bNomatch ) break; - rc = fts5ExprNodeNext(pExpr, p1, 0, 0); - } - pNode->bEof = p1->bEof; - pNode->bNomatch = p1->bNomatch; - pNode->iRowid = p1->iRowid; - if( p1->bEof ){ - fts5ExprNodeZeroPoslist(p2); - } + rc = fts5ExprNodeTest_NOT(pExpr, pNode); break; } } @@ -1329,7 +1301,7 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ } if( rc==SQLITE_OK ){ - rc = fts5ExprNodeNextMatch(pExpr, pNode); + rc = fts5ExprNodeTest(pExpr, pNode); } return rc; } @@ -1690,13 +1662,14 @@ int sqlite3Fts5ExprClonePhrase( pNew->apExprPhrase[0] = sCtx.pPhrase; pNew->pRoot->pNear->apPhrase[0] = sCtx.pPhrase; pNew->pRoot->pNear->nPhrase = 1; - pNew->pRoot->xNext = fts5ExprNodeNext_Fallback; sCtx.pPhrase->pNode = pNew->pRoot; if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){ pNew->pRoot->eType = FTS5_TERM; + pNew->pRoot->xNext = fts5ExprNodeNext_TERM; }else{ pNew->pRoot->eType = FTS5_STRING; + pNew->pRoot->xNext = fts5ExprNodeNext_STRING; } }else{ sqlite3Fts5ExprFree(pNew); @@ -1844,6 +1817,38 @@ void sqlite3Fts5ParseSetColset( } } +static void fts5ExprAssignXNext(Fts5ExprNode *pNode){ + switch( pNode->eType ){ + case FTS5_STRING: { + Fts5ExprNearset *pNear = pNode->pNear; + if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 + && pNear->apPhrase[0]->aTerm[0].pSynonym==0 + ){ + pNode->eType = FTS5_TERM; + pNode->xNext = fts5ExprNodeNext_TERM; + }else{ + pNode->xNext = fts5ExprNodeNext_STRING; + } + break; + }; + + case FTS5_OR: { + pNode->xNext = fts5ExprNodeNext_OR; + break; + }; + + case FTS5_AND: { + pNode->xNext = fts5ExprNodeNext_AND; + break; + }; + + default: assert( pNode->eType==FTS5_NOT ); { + pNode->xNext = fts5ExprNodeNext_NOT; + break; + }; + } +} + static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){ if( p->eType!=FTS5_NOT && pSub->eType==p->eType ){ int nByte = sizeof(Fts5ExprNode*) * pSub->nChild; @@ -1891,20 +1896,18 @@ Fts5ExprNode *sqlite3Fts5ParseNode( pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte); if( pRet ){ - pRet->xNext = fts5ExprNodeNext_Fallback; pRet->eType = eType; pRet->pNear = pNear; + fts5ExprAssignXNext(pRet); if( eType==FTS5_STRING ){ int iPhrase; for(iPhrase=0; iPhrasenPhrase; iPhrase++){ pNear->apPhrase[iPhrase]->pNode = pRet; } - if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 ){ - if( pNear->apPhrase[0]->aTerm[0].pSynonym==0 ){ - pRet->eType = FTS5_TERM; - pRet->xNext = fts5ExprNodeNext_Term; - } - }else if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){ + + if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL + && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm!=1) + ){ assert( pParse->rc==SQLITE_OK ); pParse->rc = SQLITE_ERROR; assert( pParse->zErr==0 ); @@ -1915,6 +1918,7 @@ Fts5ExprNode *sqlite3Fts5ParseNode( sqlite3_free(pRet); pRet = 0; } + }else{ fts5ExprAddChildren(pRet, pLeft); fts5ExprAddChildren(pRet, pRight); diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index f30c38d91a..3b627dabad 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -518,7 +518,6 @@ struct Fts5Iter { int nSeg; /* Size of aSeg[] array */ int bRev; /* True to iterate in reverse order */ u8 bSkipEmpty; /* True to skip deleted entries */ - u8 bEof; /* True at EOF */ u8 bFiltered; /* True if column-filter already applied */ i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */ @@ -2459,7 +2458,7 @@ static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5Iter *pIter){ Fts5SegIter *pFirst = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; int i; - assert( (pFirst->pLeaf==0)==pIter->bEof ); + assert( (pFirst->pLeaf==0)==pIter->base.bEof ); /* Check that pIter->iSwitchRowid is set correctly. */ for(i=0; inSeg; i++){ @@ -2731,7 +2730,7 @@ static int fts5MultiIterAdvanceRowid( */ static void fts5MultiIterSetEof(Fts5Iter *pIter){ Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; - pIter->bEof = pSeg->pLeaf==0; + pIter->base.bEof = pSeg->pLeaf==0; pIter->iSwitchRowid = pSeg->iRowid; } @@ -2964,7 +2963,7 @@ static void fts5MultiIterNew2( } pData = 0; }else{ - pNew->bEof = 1; + pNew->base.bEof = 1; } fts5SegIterSetNext(p, pIter); @@ -2980,9 +2979,9 @@ static void fts5MultiIterNew2( */ static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){ assert( p->rc - || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->bEof + || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof ); - return (p->rc || pIter->bEof); + return (p->rc || pIter->base.bEof); } /* @@ -5209,11 +5208,6 @@ int sqlite3Fts5IndexQuery( /* ** Return true if the iterator passed as the only argument is at EOF. */ -int sqlite3Fts5IterEof(Fts5IndexIter *pIter){ - assert( ((Fts5Iter*)pIter)->pIndex->rc==SQLITE_OK ); - return ((Fts5Iter*)pIter)->bEof; -} - /* ** Move to the next matching rowid. */ @@ -5239,7 +5233,7 @@ int sqlite3Fts5IterNextScan(Fts5IndexIter *pIndexIter){ if( pSeg->pLeaf && pSeg->term.p[0]!=FTS5_MAIN_PREFIX ){ fts5DataRelease(pSeg->pLeaf); pSeg->pLeaf = 0; - pIter->bEof = 1; + pIter->base.bEof = 1; } } @@ -5257,13 +5251,6 @@ int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){ return fts5IndexReturn(pIter->pIndex); } -/* -** Return the current rowid. -*/ -i64 sqlite3Fts5IterRowid(Fts5IndexIter *pIndexIter){ - return fts5MultiIterRowid((Fts5Iter*)pIndexIter); -} - /* ** Return the current term. */ @@ -5450,7 +5437,7 @@ static int fts5QueryCksum( int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter); while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIter) ){ - i64 rowid = sqlite3Fts5IterRowid(pIter); + i64 rowid = pIter->iRowid; if( eDetail==FTS5_DETAIL_NONE ){ cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n); diff --git a/ext/fts5/tool/fts5speed.tcl b/ext/fts5/tool/fts5speed.tcl index f0e96e348d..0f38638c26 100644 --- a/ext/fts5/tool/fts5speed.tcl +++ b/ext/fts5/tool/fts5speed.tcl @@ -12,6 +12,10 @@ set Q { {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t* OR b:t* OR c:t* OR d:t* OR e:t* OR f:t* OR g:t*'"} {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t*'"} {2 "SELECT count(*) FROM t1 WHERE t1 MATCH 'c:the'"} + + {2 "SELECT count(*) FROM t1 WHERE t1 MATCH 'd:holmes OR e:holmes OR f:holmes OR g:holmes'" } + {2 "SELECT count(*) FROM t1 WHERE t1 MATCH 'd:holmes AND e:holmes AND f:holmes AND g:holmes'" } + {4 "SELECT count(*) FROM t1 WHERE t1 MATCH 'd:holmes NOT e:holmes'" } } proc usage {} { diff --git a/manifest b/manifest index 3952435799..44101197f7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\scomment\son\sthe\ssqlite3_index_constraint\sobject\sto\sbring\sattention\s\nto\sthe\sfact\sthan\siColumn\sfield\scan\sbe\snegative\sfor\sa\srowid. -D 2016-02-02T02:04:21.840 +C Enhance\sthe\sperformance\sof\sfts5\sAND\sand\sOR\squeries. +D 2016-02-02T17:40:41.411 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -98,13 +98,13 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 -F ext/fts5/fts5Int.h 6e0f90eb4872654a5b98130dec16965716525c9a +F ext/fts5/fts5Int.h 9505f3bc8d0b2ca4cd2b112e7e042e3c6a3222a7 F ext/fts5/fts5_aux.c b9bcce753ef5b451267b2232f0ca153ddeb3951d F ext/fts5/fts5_buffer.c f6e0c6018ffc8e39fc0b333b5daa8b8d528ae6e4 F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 -F ext/fts5/fts5_expr.c 768d221e592df03b26f46da56aa0a561f00fa4e0 +F ext/fts5/fts5_expr.c 304b22448ee0c3056d4177e327ed62dc80cbe23a F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c cd1e4faca8b9adc2d89b367075bf93a7f50c406b +F ext/fts5/fts5_index.c 471ff6935068a4579830474249e1046b57137103 F ext/fts5/fts5_main.c 7e8a5f27d504bc04e3de7f1cba8867f0332aee9d F ext/fts5/fts5_storage.c 2a1f44deae090cd711f02cec0c2af8e660360d24 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -190,7 +190,7 @@ F ext/fts5/test/fts5unindexed.test e9539d5b78c677315e7ed8ea911d4fd25437c680 F ext/fts5/test/fts5update.test 57c7012a7919889048947addae10e0613df45529 F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e F ext/fts5/test/fts5vocab.test 480d780aa6b699816c5066225fbd86f3a0239477 -F ext/fts5/tool/fts5speed.tcl f9944a9abb9b7685cfbee8101a3dd772ededca66 +F ext/fts5/tool/fts5speed.tcl b0056f91a55b2d1a3684ec05729de92b042e2f85 F ext/fts5/tool/fts5txt2db.tcl 1343745b89ca2a1e975c23f836d0cee410052975 F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093 F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 6d7d4703ebf3754bec74123d5ba7e861a705f90f -R a0fd58918162f72722cea72a597641d9 -U drh -Z 8a77cde1543981fcb216eb719b02e019 +P d8b7b1996eefae7768bfcb82d4ff22c69392aa63 +R e61034725c181be1c4702281e2c951bc +U dan +Z e59ee5dbb82eef632e47f5b2b9e1cde6 diff --git a/manifest.uuid b/manifest.uuid index dae04066fb..0a6e70dd4e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d8b7b1996eefae7768bfcb82d4ff22c69392aa63 \ No newline at end of file +62ea9e5ab8bc1a20245beebceb5ea62dcd7ec84e \ No newline at end of file From b06347a5dcab801ba317cbf36043f8f70df0deec Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 2 Feb 2016 21:19:21 +0000 Subject: [PATCH 208/570] Add tests to restore full coverage of fts5 code. FossilOrigin-Name: 063755c81574800e7db12a42e17d982a8c1e5181 --- ext/fts5/fts5_expr.c | 3 +- ext/fts5/test/fts5fault1.test | 3 +- ext/fts5/test/fts5fault2.test | 2 +- ext/fts5/test/fts5fault7.test | 9 ++++- ext/fts5/test/fts5fault8.test | 51 +++++++++++++++------------ ext/fts5/test/fts5faultA.test | 64 ++++++++++++++++++++++++++++++++++ ext/fts5/test/fts5simple3.test | 41 ++++++++++++++++++++++ manifest | 23 ++++++------ manifest.uuid | 2 +- 9 files changed, 159 insertions(+), 39 deletions(-) create mode 100644 ext/fts5/test/fts5faultA.test diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index 1df173cfcc..5006d88d0f 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -1337,7 +1337,8 @@ int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){ } /* If the iterator is not at a real match, skip forward until it is. */ - while( pRoot->bNomatch && rc==SQLITE_OK && pRoot->bEof==0 ){ + while( pRoot->bNomatch ){ + assert( pRoot->bEof==0 && rc==SQLITE_OK ); rc = fts5ExprNodeNext(p, pRoot, 0, 0); } } diff --git a/ext/fts5/test/fts5fault1.test b/ext/fts5/test/fts5fault1.test index 429ea39af0..9d63a1175f 100644 --- a/ext/fts5/test/fts5fault1.test +++ b/ext/fts5/test/fts5fault1.test @@ -72,7 +72,7 @@ do_faultsim_test 3 -prep { reset_db do_execsql_test 4.0 { CREATE VIRTUAL TABLE t2 USING fts5(a, b); - INSERT INTO t2 VALUES('m f a jj th q jr ar', 'hj n h h sg j i m'); + INSERT INTO t2 VALUES('m f a jj th q gi ar', 'hj n h h sg j i m'); INSERT INTO t2 VALUES('nr s t g od j kf h', 'sb h aq rg op rb n nl'); INSERT INTO t2 VALUES('do h h pb p p q fr', 'c rj qs or cr a l i'); INSERT INTO t2 VALUES('lk gp t i lq mq qm p', 'h mr g f op ld aj h'); @@ -95,6 +95,7 @@ foreach {tn expr res} { 7 { NEAR(r a, 5) } {9} 8 { m* f* } {1 4 6 8 9 10} 9 { m* + f* } {1 8} + 10 { c NOT p } {5 6 7 10} } { do_faultsim_test 4.$tn -prep { faultsim_restore_and_reopen diff --git a/ext/fts5/test/fts5fault2.test b/ext/fts5/test/fts5fault2.test index ef1df8826a..43c7c7a3dd 100644 --- a/ext/fts5/test/fts5fault2.test +++ b/ext/fts5/test/fts5fault2.test @@ -16,7 +16,7 @@ source [file join [file dirname [info script]] fts5_common.tcl] source $testdir/malloc_common.tcl set testprefix fts5fault2 -# If SQLITE_ENABLE_FTS3 is defined, omit this file. +# If SQLITE_ENABLE_FTS5 is not defined, omit this file. ifcapable !fts5 { finish_test return diff --git a/ext/fts5/test/fts5fault7.test b/ext/fts5/test/fts5fault7.test index bfe6420615..a35b19ade2 100644 --- a/ext/fts5/test/fts5fault7.test +++ b/ext/fts5/test/fts5fault7.test @@ -99,7 +99,7 @@ do_execsql_test 2.0 { } faultsim_save_and_close -do_faultsim_test 2 -faults oom-* -prep { +do_faultsim_test 2.1 -faults oom-* -prep { faultsim_restore_and_reopen } -body { db eval { UPDATE OR REPLACE xy SET rowid=3 WHERE rowid = 2 } @@ -107,6 +107,13 @@ do_faultsim_test 2 -faults oom-* -prep { faultsim_test_result {0 {}} } +# Test fault-injection when an empty expression is parsed. +# +do_faultsim_test 2.2 -faults oom-* -body { + db eval { SELECT * FROM xy('""') } +} -test { + faultsim_test_result {0 {}} +} finish_test diff --git a/ext/fts5/test/fts5fault8.test b/ext/fts5/test/fts5fault8.test index d93066c6c0..ae5849495b 100644 --- a/ext/fts5/test/fts5fault8.test +++ b/ext/fts5/test/fts5fault8.test @@ -24,32 +24,37 @@ ifcapable !fts5 { foreach_detail_mode $testprefix { -fts5_aux_test_functions db -do_execsql_test 1.0 { - CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%); - INSERT INTO t1 VALUES('a b c d', '1 2 3 4'); - INSERT INTO t1 VALUES('a b a b', NULL); - INSERT INTO t1 VALUES(NULL, '1 2 1 2'); -} - -do_faultsim_test 1 -faults oom-* -body { - execsql { - SELECT rowid, fts5_test_poslist(t1) FROM t1 WHERE t1 MATCH 'b OR 2' + fts5_aux_test_functions db + do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%); + INSERT INTO t1 VALUES('a b c d', '1 2 3 4'); + INSERT INTO t1 VALUES('a b a b', NULL); + INSERT INTO t1 VALUES(NULL, '1 2 1 2'); } -} -test { - faultsim_test_result {0 {1 {0.0.1 1.1.1} 2 {0.0.1 0.0.3} 3 {1.1.1 1.1.3}}} \ - {1 SQLITE_NOMEM} -} - -do_faultsim_test 2 -faults oom-* -body { - execsql { - INSERT INTO t1(t1) VALUES('integrity-check'); + + do_faultsim_test 1 -faults oom-* -body { + execsql { + SELECT rowid, fts5_test_poslist(t1) FROM t1 WHERE t1 MATCH 'b OR 2' + } + } -test { + faultsim_test_result {0 {1 {0.0.1 1.1.1} 2 {0.0.1 0.0.3} 3 {1.1.1 1.1.3}}} \ + {1 SQLITE_NOMEM} + } + + do_faultsim_test 2 -faults oom-* -body { + execsql { INSERT INTO t1(t1) VALUES('integrity-check') } + } -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} } -} -test { - faultsim_test_result {0 {}} {1 SQLITE_NOMEM} -} -} + if {[detail_is_none]==0} { + do_faultsim_test 3 -faults oom-* -body { + execsql { SELECT rowid FROM t1('b:2') } + } -test { + faultsim_test_result {0 {1 3}} {1 SQLITE_NOMEM} + } + } +} ;# foreach_detail_mode... finish_test diff --git a/ext/fts5/test/fts5faultA.test b/ext/fts5/test/fts5faultA.test new file mode 100644 index 0000000000..817ccb4ee8 --- /dev/null +++ b/ext/fts5/test/fts5faultA.test @@ -0,0 +1,64 @@ +# 2016 February 2 +# +# 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 is focused on OOM errors. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +source $testdir/malloc_common.tcl +set testprefix fts5faultA + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + do_execsql_test 1.0 { + CREATE VIRTUAL TABLE o1 USING fts5(a, detail=%DETAIL%); + INSERT INTO o1(o1, rank) VALUES('pgsz', 32); + + WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<300 ) + INSERT INTO o1 SELECT 'A B C' FROM s; + + INSERT INTO o1 VALUES('A X C'); + + WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<300 ) + INSERT INTO o1 SELECT 'A B C' FROM s; + } + + do_faultsim_test 1 -faults oom* -prep { + sqlite3 db test.db + } -body { + execsql { SELECT rowid FROM o1('a NOT b') } + } -test { + faultsim_test_result {0 301} + } +} + +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE o2 USING fts5(a); + + INSERT INTO o2 VALUES('A B C'); + WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<300 ) + INSERT INTO o2 SELECT group_concat('A B C ') FROM s; +} + +do_faultsim_test 2 -faults oom* -prep { + sqlite3 db test.db +} -body { + execsql { SELECT rowid FROM o2('a+b+c NOT xyz') } +} -test { + faultsim_test_result {0 {1 2}} +} +finish_test + diff --git a/ext/fts5/test/fts5simple3.test b/ext/fts5/test/fts5simple3.test index b84a3e56dd..b6922f84dd 100644 --- a/ext/fts5/test/fts5simple3.test +++ b/ext/fts5/test/fts5simple3.test @@ -39,6 +39,47 @@ do_execsql_test 1.3 { SELECT rowid, fts5_test_collist(t1) FROM t1('b:a'); } {} +#------------------------------------------------------------------------- +# Create detail=col and detail=full tables with 998 columns. +# +foreach_detail_mode $testprefix { + if {[detail_is_none]} continue + + do_test 2.1 { + execsql { DROP TABLE IF EXISTS t2 } + set cols [list] + set vals [list] + for {set i 1} {$i <= 998} {incr i} { + lappend cols "c$i" + lappend vals "'val$i'" + } + execsql "CREATE VIRTUAL TABLE t2 USING fts5(detail=%DETAIL%,[join $cols ,])" + } {} + + do_test 2.2 { + execsql "INSERT INTO t2 VALUES([join $vals ,])" + } {} + + foreach {tn q res} { + 1 { c1:val1 } 1 + 2 { c300:val300 } 1 + 3 { c300:val1 } {} + 4 { c1:val300 } {} + } { + do_execsql_test 2.3.$tn { + SELECT rowid FROM t2($q) + } $res + } +} + +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE x3 USING fts5(one); + INSERT INTO x3 VALUES('a b c'); + INSERT INTO x3 VALUES('c b a'); + INSERT INTO x3 VALUES('o t t'); + SELECT * FROM x3('x OR y OR z'); +} + finish_test diff --git a/manifest b/manifest index 44101197f7..c1cd05951c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\sperformance\sof\sfts5\sAND\sand\sOR\squeries. -D 2016-02-02T17:40:41.411 +C Add\stests\sto\srestore\sfull\scoverage\sof\sfts5\scode. +D 2016-02-02T21:19:21.156 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -102,7 +102,7 @@ F ext/fts5/fts5Int.h 9505f3bc8d0b2ca4cd2b112e7e042e3c6a3222a7 F ext/fts5/fts5_aux.c b9bcce753ef5b451267b2232f0ca153ddeb3951d F ext/fts5/fts5_buffer.c f6e0c6018ffc8e39fc0b333b5daa8b8d528ae6e4 F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 -F ext/fts5/fts5_expr.c 304b22448ee0c3056d4177e327ed62dc80cbe23a +F ext/fts5/fts5_expr.c ff5c451a6d025909639ac0f0d0af0cc595b50feb F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 F ext/fts5/fts5_index.c 471ff6935068a4579830474249e1046b57137103 F ext/fts5/fts5_main.c 7e8a5f27d504bc04e3de7f1cba8867f0332aee9d @@ -147,15 +147,16 @@ F ext/fts5/test/fts5dlidx.test 13871a14641017ae42f6f1055a8067bafd44cb3d F ext/fts5/test/fts5doclist.test 8edb5b57e5f144030ed74ec00ef6fa4294fed79b F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0 F ext/fts5/test/fts5eb.test 021aa80b7ac09b964249aa32ced9ee908703e4aa -F ext/fts5/test/fts5fault1.test 4b39c47ca3544615daa8a2f733b911fa08022c77 -F ext/fts5/test/fts5fault2.test 28c36c843bb39ae855ba79827417ecc37f114341 +F ext/fts5/test/fts5fault1.test e09040d3e17b8c0837101e8c79c8a874c4376fb7 +F ext/fts5/test/fts5fault2.test d8c6c7f916ccbdfc10b2c69530e9dd3bc8313232 F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3 F ext/fts5/test/fts5fault4.test 532b6dacb963016cbf7003196bd87fb366540277 F ext/fts5/test/fts5fault5.test 10c13a783de3f42a21e3e53e123b62ed0c3a1618 F ext/fts5/test/fts5fault6.test 9682664d679643ac6736e90c225526cc84073cda -F ext/fts5/test/fts5fault7.test 01be274bfc8d9bf22451a3bf5892e9399d044f1b -F ext/fts5/test/fts5fault8.test f2d8a2b673a5f72ca1fa0e85bdbfb2041ffd347d +F ext/fts5/test/fts5fault7.test cb14ea3c1f42394f06f2284abc58eecee6ff8080 +F ext/fts5/test/fts5fault8.test 430837fe6dd0511fd3aea52bd602ac02441bcb58 F ext/fts5/test/fts5fault9.test e10e395428a9ea0596ebe752ff7123d16ab78e08 +F ext/fts5/test/fts5faultA.test fa5d59c0ff62b7125cd14eee38ded1c46e15a7ea F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741 F ext/fts5/test/fts5hash.test 00668f6fa9b9bffbd7c1be29f408aa2bdade0451 F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d @@ -177,7 +178,7 @@ F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17 F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6 F ext/fts5/test/fts5simple.test 7fcacfa473a37355af2e60096650c87b5ba8f3ba F ext/fts5/test/fts5simple2.test 98377ae1ff7749a42c21fe1a139c1ed312522c46 -F ext/fts5/test/fts5simple3.test e671b36bc4dbd4f5095e66cb04473cba9f680f53 +F ext/fts5/test/fts5simple3.test 8e71733b3d1b0e695011d02c68ebc5ca40b6124e F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48 F ext/fts5/test/fts5synonym2.test aa4c43bd3b691ff80f658cb064f5ab40690e834e F ext/fts5/test/fts5tok1.test beb894c6f3468f10a574302f69ebe4436b0287c7 @@ -1422,7 +1423,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P d8b7b1996eefae7768bfcb82d4ff22c69392aa63 -R e61034725c181be1c4702281e2c951bc +P 62ea9e5ab8bc1a20245beebceb5ea62dcd7ec84e +R e3a290a62981c78902a14c3c2f0729a7 U dan -Z e59ee5dbb82eef632e47f5b2b9e1cde6 +Z 6792ae7332aab4430b100fd43f303a7d diff --git a/manifest.uuid b/manifest.uuid index 0a6e70dd4e..0d75e9b7c9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -62ea9e5ab8bc1a20245beebceb5ea62dcd7ec84e \ No newline at end of file +063755c81574800e7db12a42e17d982a8c1e5181 \ No newline at end of file From 1b32554b80cd84bbc93075e5b4dd803bdcf65748 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Feb 2016 01:55:44 +0000 Subject: [PATCH 209/570] Enhance the internal sqlite3VdbeAddOpList() interface to automatically update jump destinations. Use this feature to simplify the AUTOINCREMENT code generator. FossilOrigin-Name: ae8b9d2edf1b5aef6108e729754911db7682b6a3 --- manifest | 22 +++++++-------- manifest.uuid | 2 +- src/insert.c | 73 +++++++++++++++++++++++++++++++++---------------- src/pragma.c | 5 ++-- src/sqliteInt.h | 2 +- src/vdbeaux.c | 6 ++++ src/vdbeblob.c | 22 +++++++-------- 7 files changed, 80 insertions(+), 52 deletions(-) diff --git a/manifest b/manifest index c1cd05951c..1fd0c856ce 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sto\srestore\sfull\scoverage\sof\sfts5\scode. -D 2016-02-02T21:19:21.156 +C Enhance\sthe\sinternal\ssqlite3VdbeAddOpList()\sinterface\sto\sautomatically\supdate\njump\sdestinations.\s\sUse\sthis\sfeature\sto\ssimplify\sthe\sAUTOINCREMENT\scode\ngenerator. +D 2016-02-03T01:55:44.089 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -309,7 +309,7 @@ F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 410f52b9ef4603dc0aebb169b7cb6b3c60eda07e +F src/insert.c 3e2462294fc8bc6e46f377ec824ff315e79fc36d F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b @@ -341,7 +341,7 @@ F src/parse.y 426a91fbbbf7cdde3fd4b8798de7317a8782bec5 F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23 F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 -F src/pragma.c 2ac26ac45eedbed3cc8a9a320ad6d2fc299e69a6 +F src/pragma.c a973357ef2faded933725a6de2883133deb24029 F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c db85f0451ba93ecb3c1e497c279abece5cb5aead F src/printf.c 98a5cef7fc84577ab8a3098cfa48ecfa5a70b9f8 @@ -353,7 +353,7 @@ F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 2f80b9b1506a8d602b2a99f3f0bfae22df3e7d70 +F src/sqliteInt.h ed6f75088781af7cbd0a6653c2fe16340faa0dd4 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -417,8 +417,8 @@ F src/vdbe.c a0a0ada4b51161d3950fe30fc696b6c8235a841f F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 F src/vdbeapi.c 9d640d5efd9a140a6bda8da53b220aa258167993 -F src/vdbeaux.c f0e7cfa04f7ac44d69866868531dbaf20659d0a2 -F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 +F src/vdbeaux.c 23b38b447ebf5991de1d3d456003c58cf523a5da +F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 @@ -1423,7 +1423,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 62ea9e5ab8bc1a20245beebceb5ea62dcd7ec84e -R e3a290a62981c78902a14c3c2f0729a7 -U dan -Z 6792ae7332aab4430b100fd43f303a7d +P 063755c81574800e7db12a42e17d982a8c1e5181 +R 03bd7861865ae8f6fba63605b50d909b +U drh +Z 0f50d7954b5cdd37df3317e2f95eccf8 diff --git a/manifest.uuid b/manifest.uuid index 0d75e9b7c9..e0288532b8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -063755c81574800e7db12a42e17d982a8c1e5181 \ No newline at end of file +ae8b9d2edf1b5aef6108e729754911db7682b6a3 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index cbe933c221..5f36c089f6 100644 --- a/src/insert.c +++ b/src/insert.c @@ -254,7 +254,6 @@ void sqlite3AutoincrementBegin(Parse *pParse){ sqlite3 *db = pParse->db; /* The database connection */ Db *pDb; /* Database only autoinc table */ int memId; /* Register holding max rowid */ - int addr; /* A VDBE address */ Vdbe *v = pParse->pVdbe; /* VDBE under construction */ /* This routine is never called during trigger-generation. It is @@ -264,33 +263,46 @@ void sqlite3AutoincrementBegin(Parse *pParse){ assert( v ); /* We failed long ago if this is not so */ for(p = pParse->pAinc; p; p = p->pNext){ + static const int iLn = VDBE_OFFSET_LINENO(2); + static const VdbeOpList autoInc[] = { + /* 0 */ {OP_Null, 0, 0, 0}, + /* 1 */ {OP_Rewind, 0, 9, 0}, + /* 2 */ {OP_Column, 0, 0, 0}, + /* 3 */ {OP_Ne, 0, 7, 0}, + /* 4 */ {OP_Rowid, 0, 0, 0}, + /* 5 */ {OP_Column, 0, 1, 0}, + /* 6 */ {OP_Goto, 0, 9, 0}, + /* 7 */ {OP_Next, 0, 2, 0}, + /* 8 */ {OP_Integer, 0, 0, 0}, + /* 9 */ {OP_Close, 0, 0, 0} + }; + VdbeOp *aOp; pDb = &db->aDb[p->iDb]; 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); sqlite3VdbeLoadString(v, memId-1, p->pTab->zName); - sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId); - sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); VdbeCoverage(v); - sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); - sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); - sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId); - sqlite3VdbeGoto(v, addr+9); - sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Integer, 0, memId); - sqlite3VdbeAddOp0(v, OP_Close); + aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn); + if( aOp==0 ) break; + aOp[0].p2 = memId; + aOp[0].p3 = memId+1; + aOp[2].p3 = memId; + aOp[3].p1 = memId-1; + aOp[3].p3 = memId; + aOp[3].p5 = SQLITE_JUMPIFNULL; + aOp[4].p2 = memId+1; + aOp[5].p3 = memId; + aOp[8].p2 = memId; } } /* ** Update the maximum rowid for an autoincrement calculation. ** -** This routine should be called when the top of the stack holds a +** This routine should be called when the regRowid register holds a ** new rowid that is about to be inserted. If that new rowid is ** larger than the maximum rowid in the memId memory cell, then the -** memory cell is updated. The stack is unchanged. +** memory cell is updated. */ static void autoIncStep(Parse *pParse, int memId, int regRowid){ if( memId>0 ){ @@ -305,31 +317,44 @@ static void autoIncStep(Parse *pParse, int memId, int regRowid){ ** table (either directly or through triggers) needs to call this ** routine just before the "exit" code. */ -void sqlite3AutoincrementEnd(Parse *pParse){ +static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){ AutoincInfo *p; Vdbe *v = pParse->pVdbe; sqlite3 *db = pParse->db; assert( v ); for(p = pParse->pAinc; p; p = p->pNext){ + static const int iLn = VDBE_OFFSET_LINENO(2); + static const VdbeOpList autoIncEnd[] = { + /* 0 */ {OP_NotNull, 0, 2, 0}, + /* 1 */ {OP_NewRowid, 0, 0, 0}, + /* 2 */ {OP_MakeRecord, 0, 2, 0}, + /* 3 */ {OP_Insert, 0, 0, 0}, + /* 4 */ {OP_Close, 0, 0, 0} + }; + VdbeOp *aOp; Db *pDb = &db->aDb[p->iDb]; - int addr1; int iRec; int memId = p->regCtr; iRec = sqlite3GetTempReg(pParse); assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); - addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1); - sqlite3VdbeJumpHere(v, addr1); - sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec); - sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1); - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - sqlite3VdbeAddOp0(v, OP_Close); + aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn); + if( aOp==0 ) break; + aOp[0].p1 = memId+1; + aOp[1].p2 = memId+1; + aOp[2].p1 = memId-1; + aOp[2].p3 = iRec; + aOp[3].p2 = iRec; + aOp[3].p3 = memId+1; + aOp[3].p5 = OPFLAG_APPEND; sqlite3ReleaseTempReg(pParse, iRec); } } +void sqlite3AutoincrementEnd(Parse *pParse){ + if( pParse->pAinc ) autoIncrementEnd(pParse); +} #else /* ** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines diff --git a/src/pragma.c b/src/pragma.c index 1d827d7b70..c62c8d2afd 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1599,16 +1599,15 @@ void sqlite3Pragma( static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList endCode[] = { { OP_AddImm, 1, 0, 0}, /* 0 */ - { OP_If, 1, 0, 0}, /* 1 */ + { OP_If, 1, 4, 0}, /* 1 */ { OP_String8, 0, 3, 0}, /* 2 */ - { OP_ResultRow, 3, 1, 0}, + { OP_ResultRow, 3, 1, 0}, /* 3 */ }; VdbeOp *aOp; aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); if( aOp ){ aOp[0].p2 = -mxErr; - aOp[1].p2 = sqlite3VdbeCurrentAddr(v); aOp[2].p4type = P4_STATIC; aOp[2].p4.z = "ok"; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index dbe1595af9..c18e837263 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2641,7 +2641,7 @@ struct SelectDest { ** tables, the following information is attached to the Table.u.autoInc.p ** pointer of each autoincrement table to record some side information that ** the code generator needs. We have to keep per-table autoincrement -** information in case inserts are down within triggers. Triggers do not +** information in case inserts are done within triggers. Triggers do not ** normally coordinate their activities, but we do need to coordinate the ** loading and saving of autoincrement information. */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 13aef0d7fd..632c1231aa 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -646,6 +646,9 @@ VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){ /* ** Add a whole list of operations to the operation stack. Return a ** pointer to the first operation inserted. +** +** Non-zero P2 arguments to jump instructions are automatically adjusted +** so that the jump target is relative to the first operation inserted. */ VdbeOp *sqlite3VdbeAddOpList( Vdbe *p, /* Add opcodes to the prepared statement */ @@ -666,6 +669,9 @@ VdbeOp *sqlite3VdbeAddOpList( pOut->p1 = aOp->p1; pOut->p2 = aOp->p2; assert( aOp->p2>=0 ); + if( (sqlite3OpcodeProperty[aOp->opcode] & OPFLG_JUMP)!=0 && aOp->p2>0 ){ + pOut->p2 += p->nOp; + } pOut->p3 = aOp->p3; pOut->p4type = P4_NOTUSED; pOut->p4.p = 0; diff --git a/src/vdbeblob.c b/src/vdbeblob.c index f9015ad6f4..2ba5301e7a 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -249,19 +249,17 @@ int sqlite3_blob_open( ** which closes the b-tree cursor and (possibly) commits the ** transaction. */ - static const int iLn = VDBE_OFFSET_LINENO(4); + static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList openBlob[] = { - /* addr/ofst */ - /* {OP_Transaction, 0, 0, 0}, // 0/ inserted separately */ - {OP_TableLock, 0, 0, 0}, /* 1/0: Acquire a read or write lock */ - {OP_OpenRead, 0, 0, 0}, /* 2/1: Open a cursor */ - {OP_Variable, 1, 1, 0}, /* 3/2: Move ?1 into reg[1] */ - {OP_NotExists, 0, 8, 1}, /* 4/3: Seek the cursor */ - {OP_Column, 0, 0, 1}, /* 5/4 */ - {OP_ResultRow, 1, 0, 0}, /* 6/5 */ - {OP_Goto, 0, 3, 0}, /* 7/6 */ - {OP_Close, 0, 0, 0}, /* 8/7 */ - {OP_Halt, 0, 0, 0}, /* 9/8 */ + {OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */ + {OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */ + {OP_Variable, 1, 1, 0}, /* 2: Move ?1 into reg[1] */ + {OP_NotExists, 0, 7, 1}, /* 3: Seek the cursor */ + {OP_Column, 0, 0, 1}, /* 4 */ + {OP_ResultRow, 1, 0, 0}, /* 5 */ + {OP_Goto, 0, 2, 0}, /* 6 */ + {OP_Close, 0, 0, 0}, /* 7 */ + {OP_Halt, 0, 0, 0}, /* 8 */ }; Vdbe *v = (Vdbe *)pBlob->pStmt; int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); From 6841b1cb3dfd12edbc1f147bdc08887199f11cce Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Feb 2016 19:20:15 +0000 Subject: [PATCH 210/570] Add "PRAGMA synchronous=EXTRA" which syncs the directory containing the rollback journal when the rollback journal is deleted in order to commit a transaction in DELETE mode. FossilOrigin-Name: af92401826f5cf49e62c278f344ab75252a18da2 --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/pager.c | 22 +++++++++++++++++----- src/pager.h | 11 ++++++----- src/pragma.c | 23 +++++++++++++---------- src/sqliteInt.h | 8 ++++---- test/pragma.test | 20 +++++++++++++++++--- 7 files changed, 68 insertions(+), 38 deletions(-) diff --git a/manifest b/manifest index 1fd0c856ce..19dbe602f6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\sinternal\ssqlite3VdbeAddOpList()\sinterface\sto\sautomatically\supdate\njump\sdestinations.\s\sUse\sthis\sfeature\sto\ssimplify\sthe\sAUTOINCREMENT\scode\ngenerator. -D 2016-02-03T01:55:44.089 +C Add\s"PRAGMA\ssynchronous=EXTRA"\swhich\ssyncs\sthe\sdirectory\scontaining\sthe\nrollback\sjournal\swhen\sthe\srollback\sjournal\sis\sdeleted\sin\sorder\sto\scommit\sa\s\ntransaction\sin\sDELETE\smode. +D 2016-02-03T19:20:15.585 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -335,13 +335,13 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 5bb20172d0c9a6afcfa829a88c406970593c848d F src/os_win.c ccf29ddded3e41e506b6bd98c1171aa0963b23f2 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 -F src/pager.h 1c2a49143dfba9e69cc8159ef019f472ed8d260b +F src/pager.c 3e189231fc662710964b54862450bc7f69f313c2 +F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 F src/parse.y 426a91fbbbf7cdde3fd4b8798de7317a8782bec5 F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23 F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 -F src/pragma.c a973357ef2faded933725a6de2883133deb24029 +F src/pragma.c 3c4f3fadf05893e289f2adf3a20c671a842cadec F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c db85f0451ba93ecb3c1e497c279abece5cb5aead F src/printf.c 98a5cef7fc84577ab8a3098cfa48ecfa5a70b9f8 @@ -353,7 +353,7 @@ F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h ed6f75088781af7cbd0a6653c2fe16340faa0dd4 +F src/sqliteInt.h bf8c17fb55d7cd09b477111212b19d661b134989 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -943,7 +943,7 @@ F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff F test/permutations.test 4ea119731c62d2f7d0aa86dd5b184cbb61ca411b -F test/pragma.test a44253f911e7d50127d4a08f927f47c861a4c772 +F test/pragma.test 507ac7ef2ea5682241ea0ef041799ca70bb5e0bf F test/pragma2.test a9400a7289605280576098b97f5cde3f204075c0 F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc @@ -1423,7 +1423,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 063755c81574800e7db12a42e17d982a8c1e5181 -R 03bd7861865ae8f6fba63605b50d909b +P ae8b9d2edf1b5aef6108e729754911db7682b6a3 +R 1a8761ef82294be8ac021b32cc3428ab U drh -Z 0f50d7954b5cdd37df3317e2f95eccf8 +Z 47031796dc00696c427dc7b231b9f896 diff --git a/manifest.uuid b/manifest.uuid index e0288532b8..4b62d72b22 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ae8b9d2edf1b5aef6108e729754911db7682b6a3 \ No newline at end of file +af92401826f5cf49e62c278f344ab75252a18da2 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 0afbe215c6..8f1635d9ee 100644 --- a/src/pager.c +++ b/src/pager.c @@ -637,6 +637,7 @@ struct Pager { u8 useJournal; /* Use a rollback journal on this file */ u8 noSync; /* Do not sync the journal if true */ u8 fullSync; /* Do extra syncs of the journal for robustness */ + u8 extraSync; /* sync directory after journal delete */ u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */ u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ @@ -1997,8 +1998,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ ); sqlite3OsClose(pPager->jfd); if( bDelete ){ - rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, - pPager->fullSync && SQLITE_EXTRA_DURABLE); + rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, pPager->extraSync); } } } @@ -3504,9 +3504,15 @@ void sqlite3PagerSetFlags( unsigned pgFlags /* Various flags */ ){ unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK; - assert( level>=1 && level<=3 ); - pPager->noSync = (level==1 || pPager->tempFile) ?1:0; - pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0; + if( pPager->tempFile ){ + pPager->noSync = 1; + pPager->fullSync = 0; + pPager->extraSync = 0; + }else{ + pPager->noSync = level==PAGER_SYNCHRONOUS_OFF ?1:0; + pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0; + pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0; + } if( pPager->noSync ){ pPager->syncFlags = 0; pPager->ckptSyncFlags = 0; @@ -4811,11 +4817,17 @@ act_like_temp_file: pPager->noSync = pPager->tempFile; if( pPager->noSync ){ assert( pPager->fullSync==0 ); + assert( pPager->extraSync==0 ); assert( pPager->syncFlags==0 ); assert( pPager->walSyncFlags==0 ); assert( pPager->ckptSyncFlags==0 ); }else{ pPager->fullSync = 1; +#ifdef SQLITE_EXTRA_DURABLE + pPager->extraSync = 1; +#else + pPager->extraSync = 0; +#endif pPager->syncFlags = SQLITE_SYNC_NORMAL; pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS; pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; diff --git a/src/pager.h b/src/pager.h index 3552a876e7..8d9f08108d 100644 --- a/src/pager.h +++ b/src/pager.h @@ -90,11 +90,12 @@ typedef struct PgHdr DbPage; #define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */ #define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */ #define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */ -#define PAGER_SYNCHRONOUS_MASK 0x03 /* Mask for three values above */ -#define PAGER_FULLFSYNC 0x04 /* PRAGMA fullfsync=ON */ -#define PAGER_CKPT_FULLFSYNC 0x08 /* PRAGMA checkpoint_fullfsync=ON */ -#define PAGER_CACHESPILL 0x10 /* PRAGMA cache_spill=ON */ -#define PAGER_FLAGS_MASK 0x1c /* All above except SYNCHRONOUS */ +#define PAGER_SYNCHRONOUS_EXTRA 0x04 /* PRAGMA synchronous=EXTRA */ +#define PAGER_SYNCHRONOUS_MASK 0x07 /* Mask for four values above */ +#define PAGER_FULLFSYNC 0x08 /* PRAGMA fullfsync=ON */ +#define PAGER_CKPT_FULLFSYNC 0x10 /* PRAGMA checkpoint_fullfsync=ON */ +#define PAGER_CACHESPILL 0x20 /* PRAGMA cache_spill=ON */ +#define PAGER_FLAGS_MASK 0x38 /* All above except SYNCHRONOUS */ /* ** The remainder of this file contains the declarations of the functions diff --git a/src/pragma.c b/src/pragma.c index c62c8d2afd..bde17d1e86 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -32,8 +32,8 @@ /* ** Interpret the given string as a safety level. Return 0 for OFF, -** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or -** unrecognized string argument. The FULL option is disallowed +** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or +** unrecognized string argument. The FULL and EXTRA option is disallowed ** if the omitFull parameter it 1. ** ** Note that the values returned are one less that the values that @@ -42,18 +42,21 @@ ** and older scripts may have used numbers 0 for OFF and 1 for ON. */ static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){ - /* 123456789 123456789 */ - static const char zText[] = "onoffalseyestruefull"; - static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; - static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4}; - static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2}; + /* 123456789 123456789 123 */ + static const char zText[] = "onoffalseyestruextrafull"; + static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 15, 20}; + static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 5, 4}; + static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 3, 2}; + /* on no off false yes true extra full */ int i, n; if( sqlite3Isdigit(*z) ){ return (u8)sqlite3Atoi(z); } n = sqlite3Strlen30(z); - for(i=0; i Date: Wed, 3 Feb 2016 19:52:06 +0000 Subject: [PATCH 211/570] Fix markup errors in comments used to generate the documentation - specifically in the documentation on the OP_Seek opcode. FossilOrigin-Name: ef252bc4b59d272460aaebdc0d4b8e347b0d25a8 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 19dbe602f6..b7ee931a14 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\s"PRAGMA\ssynchronous=EXTRA"\swhich\ssyncs\sthe\sdirectory\scontaining\sthe\nrollback\sjournal\swhen\sthe\srollback\sjournal\sis\sdeleted\sin\sorder\sto\scommit\sa\s\ntransaction\sin\sDELETE\smode. -D 2016-02-03T19:20:15.585 +C Fix\smarkup\serrors\sin\scomments\sused\sto\sgenerate\sthe\sdocumentation\s-\sspecifically\nin\sthe\sdocumentation\son\sthe\sOP_Seek\sopcode. +D 2016-02-03T19:52:06.161 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -413,7 +413,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c a0a0ada4b51161d3950fe30fc696b6c8235a841f +F src/vdbe.c 16ca0c1e2975fac04c3ea5c62b34dc24b13fea13 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 F src/vdbeapi.c 9d640d5efd9a140a6bda8da53b220aa258167993 @@ -1423,7 +1423,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ae8b9d2edf1b5aef6108e729754911db7682b6a3 -R 1a8761ef82294be8ac021b32cc3428ab +P af92401826f5cf49e62c278f344ab75252a18da2 +R f36c5f43b820b4830c00d3f3959d5c82 U drh -Z 47031796dc00696c427dc7b231b9f896 +Z cdc17003a87221b5f2cfde36f98aed07 diff --git a/manifest.uuid b/manifest.uuid index 4b62d72b22..6563093eae 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -af92401826f5cf49e62c278f344ab75252a18da2 \ No newline at end of file +ef252bc4b59d272460aaebdc0d4b8e347b0d25a8 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 1cf4cb16a7..62ad86d4f3 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4960,8 +4960,8 @@ case OP_IdxDelete: { ** occur, no unnecessary I/O happens. ** ** P4 may be an array of integers (type P4_INTARRAY) containing -** one entry for each column in the P3 table. If array entry a[i] -** is non-zero, then reading column (a[i]-1) from cursor P3 is +** one entry for each column in the P3 table. If array entry a(i) +** is non-zero, then reading column a(i)-1 from cursor P3 is ** equivalent to performing the deferred seek and then reading column i ** from P1. This information is stored in P3 and used to redirect ** reads against P3 over to P1, thus possibly avoiding the need to From eb715c62f9367794b11cc9210a9e61a4a1943b04 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 3 Feb 2016 20:04:59 +0000 Subject: [PATCH 212/570] Improve performance of fts5 prefix queries on detail=col tables. FossilOrigin-Name: ca11f46db047e7f131cef3893f73824758a2076b --- ext/fts5/fts5Int.h | 6 + ext/fts5/fts5_index.c | 995 ++++++++++++++++++++---------------------- manifest | 16 +- manifest.uuid | 2 +- 4 files changed, 489 insertions(+), 530 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index 9e5e52fa41..fc71584909 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -332,6 +332,12 @@ struct Fts5IndexIter { #define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */ #define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */ +/* The following are used internally by the fts5_index.c module. They are +** defined here only to make it easier to avoid clashes with the flags +** above. */ +#define FTS5INDEX_QUERY_SKIPEMPTY 0x0010 +#define FTS5INDEX_QUERY_NOOUTPUT 0x0020 + /* ** Create/destroy an Fts5Index object. */ diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 3b627dabad..1a8cc63dad 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -2264,9 +2264,6 @@ static void fts5SegIterSeekInit( int bGe = (flags & FTS5INDEX_QUERY_SCAN); int bDlidx = 0; /* True if there is a doclist-index */ - static int nCall = 0; - nCall++; - assert( bGe==0 || (flags & FTS5INDEX_QUERY_DESC)==0 ); assert( pTerm && nTerm ); memset(pIter, 0, sizeof(*pIter)); @@ -2832,6 +2829,410 @@ static Fts5Iter *fts5MultiIterAlloc( return pNew; } +static void fts5PoslistCallback( + Fts5Index *p, + void *pContext, + const u8 *pChunk, int nChunk +){ + assert_nc( nChunk>=0 ); + if( nChunk>0 ){ + fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk); + } +} + +typedef struct PoslistCallbackCtx PoslistCallbackCtx; +struct PoslistCallbackCtx { + Fts5Buffer *pBuf; /* Append to this buffer */ + Fts5Colset *pColset; /* Restrict matches to this column */ + int eState; /* See above */ +}; + +typedef struct PoslistOffsetsCtx PoslistOffsetsCtx; +struct PoslistOffsetsCtx { + Fts5Buffer *pBuf; /* Append to this buffer */ + Fts5Colset *pColset; /* Restrict matches to this column */ + int iRead; + int iWrite; +}; + +/* +** TODO: Make this more efficient! +*/ +static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){ + int i; + for(i=0; inCol; i++){ + if( pColset->aiCol[i]==iCol ) return 1; + } + return 0; +} + +static void fts5PoslistOffsetsCallback( + Fts5Index *p, + void *pContext, + const u8 *pChunk, int nChunk +){ + PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext; + assert_nc( nChunk>=0 ); + if( nChunk>0 ){ + int i = 0; + while( iiRead - 2; + pCtx->iRead = iVal; + if( fts5IndexColsetTest(pCtx->pColset, iVal) ){ + fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite); + pCtx->iWrite = iVal; + } + } + } +} + +static void fts5PoslistFilterCallback( + Fts5Index *p, + void *pContext, + const u8 *pChunk, int nChunk +){ + PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext; + assert_nc( nChunk>=0 ); + if( nChunk>0 ){ + /* Search through to find the first varint with value 1. This is the + ** start of the next columns hits. */ + int i = 0; + int iStart = 0; + + if( pCtx->eState==2 ){ + int iCol; + fts5FastGetVarint32(pChunk, i, iCol); + if( fts5IndexColsetTest(pCtx->pColset, iCol) ){ + pCtx->eState = 1; + fts5BufferSafeAppendVarint(pCtx->pBuf, 1); + }else{ + pCtx->eState = 0; + } + } + + do { + while( ieState ){ + fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); + } + if( i=nChunk ){ + pCtx->eState = 2; + }else{ + fts5FastGetVarint32(pChunk, i, iCol); + pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol); + if( pCtx->eState ){ + fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); + iStart = i; + } + } + } + }while( inPos; /* Number of bytes still to come */ + Fts5Data *pData = 0; + u8 *pChunk = &pSeg->pLeaf->p[pSeg->iLeafOffset]; + int nChunk = MIN(nRem, pSeg->pLeaf->szLeaf - pSeg->iLeafOffset); + int pgno = pSeg->iLeafPgno; + int pgnoSave = 0; + + /* This function does notmwork with detail=none databases. */ + assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE ); + + if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){ + pgnoSave = pgno+1; + } + + while( 1 ){ + xChunk(p, pCtx, pChunk, nChunk); + nRem -= nChunk; + fts5DataRelease(pData); + if( nRem<=0 ){ + break; + }else{ + pgno++; + pData = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno)); + if( pData==0 ) break; + pChunk = &pData->p[4]; + nChunk = MIN(nRem, pData->szLeaf - 4); + if( pgno==pgnoSave ){ + assert( pSeg->pNextLeaf==0 ); + pSeg->pNextLeaf = pData; + pData = 0; + } + } + } +} + +/* +** Iterator pIter currently points to a valid entry (not EOF). This +** function appends the position list data for the current entry to +** buffer pBuf. It does not make a copy of the position-list size +** field. +*/ +static void fts5SegiterPoslist( + Fts5Index *p, + Fts5SegIter *pSeg, + Fts5Colset *pColset, + Fts5Buffer *pBuf +){ + if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){ + if( pColset==0 ){ + fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback); + }else{ + if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){ + PoslistCallbackCtx sCtx; + sCtx.pBuf = pBuf; + sCtx.pColset = pColset; + sCtx.eState = fts5IndexColsetTest(pColset, 0); + assert( sCtx.eState==0 || sCtx.eState==1 ); + fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback); + }else{ + PoslistOffsetsCtx sCtx; + memset(&sCtx, 0, sizeof(sCtx)); + sCtx.pBuf = pBuf; + sCtx.pColset = pColset; + fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback); + } + } + } +} + +/* +** IN/OUT parameter (*pa) points to a position list n bytes in size. If +** the position list contains entries for column iCol, then (*pa) is set +** to point to the sub-position-list for that column and the number of +** bytes in it returned. Or, if the argument position list does not +** contain any entries for column iCol, return 0. +*/ +static int fts5IndexExtractCol( + const u8 **pa, /* IN/OUT: Pointer to poslist */ + int n, /* IN: Size of poslist in bytes */ + int iCol /* Column to extract from poslist */ +){ + int iCurrent = 0; /* Anything before the first 0x01 is col 0 */ + const u8 *p = *pa; + const u8 *pEnd = &p[n]; /* One byte past end of position list */ + + while( iCol>iCurrent ){ + /* Advance pointer p until it points to pEnd or an 0x01 byte that is + ** not part of a varint. Note that it is not possible for a negative + ** or extremely large varint to occur within an uncorrupted position + ** list. So the last byte of each varint may be assumed to have a clear + ** 0x80 bit. */ + while( *p!=0x01 ){ + while( *p++ & 0x80 ); + if( p>=pEnd ) return 0; + } + *pa = p++; + iCurrent = *p++; + if( iCurrent & 0x80 ){ + p--; + p += fts5GetVarint32(p, iCurrent); + } + } + if( iCol!=iCurrent ) return 0; + + /* Advance pointer p until it points to pEnd or an 0x01 byte that is + ** not part of a varint */ + while( pnCol; i++){ + const u8 *pSub = pPos; + int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]); + if( nSub ){ + fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); + } + } + return rc; +} + +/* +** xSetOutputs callback used by detail=none tables. +*/ +static void fts5IterSetOutputs_None(Fts5Iter *pIter, Fts5SegIter *pSeg){ + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_NONE ); + pIter->base.iRowid = pSeg->iRowid; + pIter->base.nData = pSeg->nPos; +} + +/* +** xSetOutputs callback used by detail=full and detail=col tables when no +** column filters are specified. +*/ +static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){ + pIter->base.iRowid = pSeg->iRowid; + pIter->base.nData = pSeg->nPos; + + assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE ); + assert( pIter->pColset==0 || pIter->bFiltered ); + + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ + /* All data is stored on the current page. Populate the output + ** variables to point into the body of the page object. */ + pIter->base.pData = &pSeg->pLeaf->p[pSeg->iLeafOffset]; + }else{ + /* The data is distributed over two or more pages. Copy it into the + ** Fts5Iter.poslist buffer and then set the output pointer to point + ** to this buffer. */ + fts5BufferZero(&pIter->poslist); + fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist); + pIter->base.pData = pIter->poslist.p; + } +} + +/* +** xSetOutputs callback used by detail=col when there is a column filter +** and there are 100 or more columns. Also called as a fallback from +** fts5IterSetOutputs_Col100 if the column-list spans more than one page. +*/ +static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){ + fts5BufferZero(&pIter->poslist); + fts5SegiterPoslist(pIter->pIndex, pSeg, pIter->pColset, &pIter->poslist); + pIter->base.iRowid = pSeg->iRowid; + pIter->base.pData = pIter->poslist.p; + pIter->base.nData = pIter->poslist.n; +} + +/* +** xSetOutputs callback used when: +** +** * detail=col, +** * there is a column filter, and +** * the table contains 100 or fewer columns. +** +** The last point is to ensure all column numbers are stored as +** single-byte varints. +*/ +static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){ + + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); + assert( pIter->pColset ); + + if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){ + fts5IterSetOutputs_Col(pIter, pSeg); + }else{ + u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset]; + u8 *pEnd = (u8*)&a[pSeg->nPos]; + int iPrev = 0; + int *aiCol = pIter->pColset->aiCol; + int *aiColEnd = &aiCol[pIter->pColset->nCol]; + + u8 *aOut = pIter->poslist.p; + int iPrevOut = 0; + + pIter->base.iRowid = pSeg->iRowid; + + while( abase.pData = pIter->poslist.p; + pIter->base.nData = aOut - pIter->poslist.p; + } +} + +/* +** xSetOutputs callback used by detail=full when there is a column filter. +*/ +static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){ + Fts5Colset *pColset = pIter->pColset; + pIter->base.iRowid = pSeg->iRowid; + + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL ); + assert( pColset ); + + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ + /* All data is stored on the current page. Populate the output + ** variables to point into the body of the page object. */ + const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset]; + if( pColset->nCol==1 ){ + pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]); + pIter->base.pData = a; + }else{ + fts5BufferZero(&pIter->poslist); + fts5IndexExtractColset(pColset, a, pSeg->nPos, &pIter->poslist); + pIter->base.pData = pIter->poslist.p; + pIter->base.nData = pIter->poslist.n; + } + }else{ + /* The data is distributed over two or more pages. Copy it into the + ** Fts5Iter.poslist buffer and then set the output pointer to point + ** to this buffer. */ + fts5BufferZero(&pIter->poslist); + fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); + pIter->base.pData = pIter->poslist.p; + pIter->base.nData = pIter->poslist.n; + } +} + +static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){ + if( *pRc==SQLITE_OK ){ + Fts5Config *pConfig = pIter->pIndex->pConfig; + if( pConfig->eDetail==FTS5_DETAIL_NONE ){ + pIter->xSetOutputs = fts5IterSetOutputs_None; + } + + else if( pIter->pColset==0 || pIter->bFiltered ){ + pIter->xSetOutputs = fts5IterSetOutputs_Nocolset; + } + + else if( pConfig->eDetail==FTS5_DETAIL_FULL ){ + pIter->xSetOutputs = fts5IterSetOutputs_Full; + } + + else{ + assert( pConfig->eDetail==FTS5_DETAIL_COLUMNS ); + if( pConfig->nCol<=100 ){ + pIter->xSetOutputs = fts5IterSetOutputs_Col100; + sqlite3Fts5BufferSize(pRc, &pIter->poslist, pConfig->nCol); + }else{ + pIter->xSetOutputs = fts5IterSetOutputs_Col; + } + } + } +} + + /* ** Allocate a new Fts5Iter object. ** @@ -2846,8 +3247,8 @@ static Fts5Iter *fts5MultiIterAlloc( static void fts5MultiIterNew( Fts5Index *p, /* FTS5 backend to iterate within */ Fts5Structure *pStruct, /* Structure of specific index */ - int bSkipEmpty, /* True to ignore delete-keys */ int flags, /* FTS5INDEX_QUERY_XXX flags */ + Fts5Colset *pColset, /* Colset to filter on (or NULL) */ const u8 *pTerm, int nTerm, /* Term to seek to (or NULL/0) */ int iLevel, /* Level to iterate (-1 for all) */ int nSegment, /* Number of segments to merge (iLevel>=0) */ @@ -2875,36 +3276,42 @@ static void fts5MultiIterNew( *ppOut = pNew = fts5MultiIterAlloc(p, nSeg); if( pNew==0 ) return; pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC)); - pNew->bSkipEmpty = (u8)bSkipEmpty; + pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY)); pNew->pStruct = pStruct; + pNew->pColset = pColset; fts5StructureRef(pStruct); + if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){ + fts5IterSetOutputCb(&p->rc, pNew); + } /* Initialize each of the component segment iterators. */ - if( iLevel<0 ){ - Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel]; - if( p->pHash ){ - /* Add a segment iterator for the current contents of the hash table. */ - Fts5SegIter *pIter = &pNew->aSeg[iIter++]; - fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter); - } - for(pLvl=&pStruct->aLevel[0]; pLvlnSeg-1; iSeg>=0; iSeg--){ - Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; + if( p->rc==SQLITE_OK ){ + if( iLevel<0 ){ + Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel]; + if( p->pHash ){ + /* Add a segment iterator for the current contents of the hash table. */ Fts5SegIter *pIter = &pNew->aSeg[iIter++]; - if( pTerm==0 ){ - fts5SegIterInit(p, pSeg, pIter); - }else{ - fts5SegIterSeekInit(p, &buf, pTerm, nTerm, flags, pSeg, pIter); + fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter); + } + for(pLvl=&pStruct->aLevel[0]; pLvlnSeg-1; iSeg>=0; iSeg--){ + Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; + Fts5SegIter *pIter = &pNew->aSeg[iIter++]; + if( pTerm==0 ){ + fts5SegIterInit(p, pSeg, pIter); + }else{ + fts5SegIterSeekInit(p, &buf, pTerm, nTerm, flags, pSeg, pIter); + } } } + }else{ + pLvl = &pStruct->aLevel[iLevel]; + for(iSeg=nSeg-1; iSeg>=0; iSeg--){ + fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]); + } } - }else{ - pLvl = &pStruct->aLevel[iLevel]; - for(iSeg=nSeg-1; iSeg>=0; iSeg--){ - fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]); - } + assert( iIter==nSeg ); } - assert( iIter==nSeg ); /* If the above was successful, each component iterators now points ** to the first entry in its segment. In this case initialize the @@ -2924,12 +3331,17 @@ static void fts5MultiIterNew( if( pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew) ){ fts5MultiIterNext(p, pNew, 0, 0); + }else if( pNew->base.bEof==0 ){ + Fts5SegIter *pSeg = &pNew->aSeg[pNew->aFirst[1].iFirst]; + pNew->xSetOutputs(pNew, pSeg); } + }else{ fts5MultiIterFree(p, pNew); *ppOut = 0; } fts5BufferFree(&buf); + } /* @@ -3022,49 +3434,6 @@ static const u8 *fts5MultiIterTerm(Fts5Iter *pIter, int *pn){ return p->term.p; } -static void fts5ChunkIterate( - Fts5Index *p, /* Index object */ - Fts5SegIter *pSeg, /* Poslist of this iterator */ - void *pCtx, /* Context pointer for xChunk callback */ - void (*xChunk)(Fts5Index*, void*, const u8*, int) -){ - int nRem = pSeg->nPos; /* Number of bytes still to come */ - Fts5Data *pData = 0; - u8 *pChunk = &pSeg->pLeaf->p[pSeg->iLeafOffset]; - int nChunk = MIN(nRem, pSeg->pLeaf->szLeaf - pSeg->iLeafOffset); - int pgno = pSeg->iLeafPgno; - int pgnoSave = 0; - - /* This function does notmwork with detail=none databases. */ - assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE ); - - if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){ - pgnoSave = pgno+1; - } - - while( 1 ){ - xChunk(p, pCtx, pChunk, nChunk); - nRem -= nChunk; - fts5DataRelease(pData); - if( nRem<=0 ){ - break; - }else{ - pgno++; - pData = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno)); - if( pData==0 ) break; - pChunk = &pData->p[4]; - nChunk = MIN(nRem, pData->szLeaf - 4); - if( pgno==pgnoSave ){ - assert( pSeg->pNextLeaf==0 ); - pSeg->pNextLeaf = pData; - pData = 0; - } - } - } -} - - - /* ** Allocate a new segment-id for the structure pStruct. The new segment ** id must be between 1 and 65335 inclusive, and must not be used by @@ -3684,6 +4053,7 @@ static void fts5IndexMergeLevel( Fts5Buffer term; int bOldest; /* True if the output segment is the oldest */ int eDetail = p->pConfig->eDetail; + const int flags = FTS5INDEX_QUERY_NOOUTPUT; assert( iLvlnLevel ); assert( pLvl->nMerge<=pLvl->nSeg ); @@ -3728,7 +4098,7 @@ static void fts5IndexMergeLevel( bOldest = (pLvlOut->nSeg==1 && pStruct->nLevel==iLvl+2); assert( iLvl>=0 ); - for(fts5MultiIterNew(p, pStruct, 0, 0, 0, 0, iLvl, nInput, &pIter); + for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, iLvl, nInput, &pIter); fts5MultiIterEof(p, pIter)==0; fts5MultiIterNext(p, pIter, 0, 0) ){ @@ -4173,281 +4543,28 @@ int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){ return fts5IndexReturn(p); } -static void fts5PoslistCallback( - Fts5Index *p, - void *pContext, - const u8 *pChunk, int nChunk -){ - assert_nc( nChunk>=0 ); - if( nChunk>0 ){ - fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk); - } -} - -typedef struct PoslistCallbackCtx PoslistCallbackCtx; -struct PoslistCallbackCtx { - Fts5Buffer *pBuf; /* Append to this buffer */ - Fts5Colset *pColset; /* Restrict matches to this column */ - int eState; /* See above */ -}; - -typedef struct PoslistOffsetsCtx PoslistOffsetsCtx; -struct PoslistOffsetsCtx { - Fts5Buffer *pBuf; /* Append to this buffer */ - Fts5Colset *pColset; /* Restrict matches to this column */ - int iRead; - int iWrite; -}; - -/* -** TODO: Make this more efficient! -*/ -static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){ - int i; - for(i=0; inCol; i++){ - if( pColset->aiCol[i]==iCol ) return 1; - } - return 0; -} - -static void fts5PoslistOffsetsCallback( - Fts5Index *p, - void *pContext, - const u8 *pChunk, int nChunk -){ - PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext; - assert_nc( nChunk>=0 ); - if( nChunk>0 ){ - int i = 0; - while( iiRead - 2; - pCtx->iRead = iVal; - if( fts5IndexColsetTest(pCtx->pColset, iVal) ){ - fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite); - pCtx->iWrite = iVal; - } - } - } -} - -static void fts5PoslistFilterCallback( - Fts5Index *p, - void *pContext, - const u8 *pChunk, int nChunk -){ - PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext; - assert_nc( nChunk>=0 ); - if( nChunk>0 ){ - /* Search through to find the first varint with value 1. This is the - ** start of the next columns hits. */ - int i = 0; - int iStart = 0; - - if( pCtx->eState==2 ){ - int iCol; - fts5FastGetVarint32(pChunk, i, iCol); - if( fts5IndexColsetTest(pCtx->pColset, iCol) ){ - pCtx->eState = 1; - fts5BufferSafeAppendVarint(pCtx->pBuf, 1); - }else{ - pCtx->eState = 0; - } - } - - do { - while( ieState ){ - fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); - } - if( i=nChunk ){ - pCtx->eState = 2; - }else{ - fts5FastGetVarint32(pChunk, i, iCol); - pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol); - if( pCtx->eState ){ - fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); - iStart = i; - } - } - } - }while( irc, pBuf, pSeg->nPos) ){ - if( pColset==0 ){ - fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback); - }else{ - if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){ - PoslistCallbackCtx sCtx; - sCtx.pBuf = pBuf; - sCtx.pColset = pColset; - sCtx.eState = fts5IndexColsetTest(pColset, 0); - assert( sCtx.eState==0 || sCtx.eState==1 ); - fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback); - }else{ - PoslistOffsetsCtx sCtx; - memset(&sCtx, 0, sizeof(sCtx)); - sCtx.pBuf = pBuf; - sCtx.pColset = pColset; - fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback); - } - } - } -} - -/* -** IN/OUT parameter (*pa) points to a position list n bytes in size. If -** the position list contains entries for column iCol, then (*pa) is set -** to point to the sub-position-list for that column and the number of -** bytes in it returned. Or, if the argument position list does not -** contain any entries for column iCol, return 0. -*/ -static int fts5IndexExtractCol( - const u8 **pa, /* IN/OUT: Pointer to poslist */ - int n, /* IN: Size of poslist in bytes */ - int iCol /* Column to extract from poslist */ -){ - int iCurrent = 0; /* Anything before the first 0x01 is col 0 */ - const u8 *p = *pa; - const u8 *pEnd = &p[n]; /* One byte past end of position list */ - - while( iCol>iCurrent ){ - /* Advance pointer p until it points to pEnd or an 0x01 byte that is - ** not part of a varint. Note that it is not possible for a negative - ** or extremely large varint to occur within an uncorrupted position - ** list. So the last byte of each varint may be assumed to have a clear - ** 0x80 bit. */ - while( *p!=0x01 ){ - while( *p++ & 0x80 ); - if( p>=pEnd ) return 0; - } - *pa = p++; - iCurrent = *p++; - if( iCurrent & 0x80 ){ - p--; - p += fts5GetVarint32(p, iCurrent); - } - } - if( iCol!=iCurrent ) return 0; - - /* Advance pointer p until it points to pEnd or an 0x01 byte that is - ** not part of a varint */ - while( prc, pBuf, iDelta); - return 0; } -/* -** Iterator pMulti currently points to a valid entry (not EOF). This -** function appends the following to buffer pBuf: -** -** * The varint iDelta, and -** * the position list that currently points to, including the size field. -** -** If argument pColset is NULL, then the position list is filtered according -** to pColset before being appended to the buffer. If this means there are -** no entries in the position list, nothing is appended to the buffer (not -** even iDelta). -** -** If an error occurs, an error code is left in p->rc. -*/ -static int fts5AppendPoslist( +static void fts5AppendPoslist( Fts5Index *p, i64 iDelta, Fts5Iter *pMulti, - Fts5Colset *pColset, Fts5Buffer *pBuf ){ - if( p->rc==SQLITE_OK ){ - Fts5SegIter *pSeg = &pMulti->aSeg[ pMulti->aFirst[1].iFirst ]; - assert( fts5MultiIterEof(p, pMulti)==0 ); - assert( pSeg->nPos>0 ); - if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+9+9) ){ - if( p->pConfig->eDetail==FTS5_DETAIL_FULL - && pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf - && (pColset==0 || pColset->nCol==1) - ){ - const u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset]; - int nPos; - if( pColset ){ - nPos = fts5IndexExtractCol(&pPos, pSeg->nPos, pColset->aiCol[0]); - if( nPos==0 ) return 1; - }else{ - nPos = pSeg->nPos; - } - assert( nPos>0 ); - fts5BufferSafeAppendVarint(pBuf, iDelta); - fts5BufferSafeAppendVarint(pBuf, nPos*2); - fts5BufferSafeAppendBlob(pBuf, pPos, nPos); - }else{ - int iSv1; - int iSv2; - int iData; - - /* Append iDelta */ - iSv1 = pBuf->n; - fts5BufferSafeAppendVarint(pBuf, iDelta); - - /* WRITEPOSLISTSIZE */ - iSv2 = pBuf->n; - fts5BufferSafeAppendVarint(pBuf, pSeg->nPos*2); - iData = pBuf->n; - - fts5SegiterPoslist(p, pSeg, pColset, pBuf); - - if( pColset ){ - int nActual = pBuf->n - iData; - if( nActual!=pSeg->nPos ){ - if( nActual==0 ){ - pBuf->n = iSv1; - return 1; - }else{ - int nReq = sqlite3Fts5GetVarintLen((u32)(nActual*2)); - while( iSv2<(iData-nReq) ){ pBuf->p[iSv2++] = 0x80; } - sqlite3Fts5PutVarint(&pBuf->p[iSv2], nActual*2); - } - } - } - } - } + int nData = pMulti->base.nData; + assert( nData>0 ); + if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nData+9+9) ){ + fts5BufferSafeAppendVarint(pBuf, iDelta); + fts5BufferSafeAppendVarint(pBuf, nData*2); + fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData); } - - return 0; } @@ -4674,7 +4791,7 @@ static void fts5SetupPrefixIter( const int nBuf = 32; void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*); - int (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Colset*, Fts5Buffer*); + void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*); if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){ xMerge = fts5MergeRowidLists; xAppend = fts5AppendRowid; @@ -4687,7 +4804,9 @@ static void fts5SetupPrefixIter( pStruct = fts5StructureRead(p); if( aBuf && pStruct ){ - const int flags = FTS5INDEX_QUERY_SCAN; + const int flags = FTS5INDEX_QUERY_SCAN + | FTS5INDEX_QUERY_SKIPEMPTY + | FTS5INDEX_QUERY_NOOUTPUT; int i; i64 iLastRowid = 0; Fts5Iter *p1 = 0; /* Iterator used to gather data from index */ @@ -4696,19 +4815,25 @@ static void fts5SetupPrefixIter( int bNewTerm = 1; memset(&doclist, 0, sizeof(doclist)); - for(fts5MultiIterNew(p, pStruct, 1, flags, pToken, nToken, -1, 0, &p1); + fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1); + fts5IterSetOutputCb(&p->rc, p1); + for( /* no-op */ ; fts5MultiIterEof(p, p1)==0; fts5MultiIterNext2(p, p1, &bNewTerm) ){ - i64 iRowid = fts5MultiIterRowid(p1); - int nTerm; - const u8 *pTerm = fts5MultiIterTerm(p1, &nTerm); + Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ]; + int nTerm = pSeg->term.n; + const u8 *pTerm = pSeg->term.p; + p1->xSetOutputs(p1, pSeg); + assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 ); if( bNewTerm ){ if( nTerm0 && iRowid<=iLastRowid ){ + if( p1->base.nData==0 ) continue; + + if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){ for(i=0; p->rc==SQLITE_OK && doclist.n; i++){ assert( ibase.iRowid-iLastRowid, p1, &doclist); + iLastRowid = p1->base.iRowid; } for(i=0; inCol; i++){ - const u8 *pSub = pPos; - int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]); - if( nSub ){ - fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); - } - } - return rc; -} - -/* -** xSetOutputs callback used by detail=none tables. -*/ -static void fts5IterSetOutputs_None(Fts5Iter *pIter, Fts5SegIter *pSeg){ - assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_NONE ); - pIter->base.iRowid = pSeg->iRowid; - pIter->base.nData = pSeg->nPos; -} - -/* -** xSetOutputs callback used by detail=full and detail=col tables when no -** column filters are specified. -*/ -static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){ - pIter->base.iRowid = pSeg->iRowid; - pIter->base.nData = pSeg->nPos; - - assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE ); - assert( pIter->pColset==0 || pIter->bFiltered ); - - if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ - /* All data is stored on the current page. Populate the output - ** variables to point into the body of the page object. */ - pIter->base.pData = &pSeg->pLeaf->p[pSeg->iLeafOffset]; - }else{ - /* The data is distributed over two or more pages. Copy it into the - ** Fts5Iter.poslist buffer and then set the output pointer to point - ** to this buffer. */ - fts5BufferZero(&pIter->poslist); - fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist); - pIter->base.pData = pIter->poslist.p; - } -} - -/* -** xSetOutputs callback used by detail=col when there is a column filter -** and there are 100 or more columns. Also called as a fallback from -** fts5IterSetOutputs_Col100 if the column-list spans more than one page. -*/ -static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){ - fts5BufferZero(&pIter->poslist); - fts5SegiterPoslist(pIter->pIndex, pSeg, pIter->pColset, &pIter->poslist); - pIter->base.iRowid = pSeg->iRowid; - pIter->base.pData = pIter->poslist.p; - pIter->base.nData = pIter->poslist.n; -} - -/* -** xSetOutputs callback used when: -** -** * detail=col, -** * there is a column filter, and -** * the table contains 100 or fewer columns. -** -** The last point is to ensure all column numbers are stored as -** single-byte varints. -*/ -static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){ - - assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); - assert( pIter->pColset ); - - if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){ - fts5IterSetOutputs_Col(pIter, pSeg); - }else{ - u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset]; - u8 *pEnd = (u8*)&a[pSeg->nPos]; - int iPrev = 0; - int *aiCol = pIter->pColset->aiCol; - int *aiColEnd = &aiCol[pIter->pColset->nCol]; - - u8 *aOut = pIter->poslist.p; - int iPrevOut = 0; - - pIter->base.iRowid = pSeg->iRowid; - - while( abase.pData = pIter->poslist.p; - pIter->base.nData = aOut - pIter->poslist.p; - } -} - -/* -** xSetOutputs callback used by detail=full when there is a column filter. -*/ -static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){ - Fts5Colset *pColset = pIter->pColset; - pIter->base.iRowid = pSeg->iRowid; - - assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL ); - assert( pColset ); - - if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ - /* All data is stored on the current page. Populate the output - ** variables to point into the body of the page object. */ - const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset]; - if( pColset->nCol==1 ){ - pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]); - pIter->base.pData = a; - }else{ - fts5BufferZero(&pIter->poslist); - fts5IndexExtractColset(pColset, a, pSeg->nPos, &pIter->poslist); - pIter->base.pData = pIter->poslist.p; - pIter->base.nData = pIter->poslist.n; - } - }else{ - /* The data is distributed over two or more pages. Copy it into the - ** Fts5Iter.poslist buffer and then set the output pointer to point - ** to this buffer. */ - fts5BufferZero(&pIter->poslist); - fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); - pIter->base.pData = pIter->poslist.p; - pIter->base.nData = pIter->poslist.n; - } -} - -static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){ - Fts5Config *pConfig = pIter->pIndex->pConfig; - if( pConfig->eDetail==FTS5_DETAIL_NONE ){ - pIter->xSetOutputs = fts5IterSetOutputs_None; - } - - else if( pIter->pColset==0 || pIter->bFiltered ){ - pIter->xSetOutputs = fts5IterSetOutputs_Nocolset; - } - - else if( pConfig->eDetail==FTS5_DETAIL_FULL ){ - pIter->xSetOutputs = fts5IterSetOutputs_Full; - } - - else{ - assert( pConfig->eDetail==FTS5_DETAIL_COLUMNS ); - if( pConfig->nCol<=100 ){ - pIter->xSetOutputs = fts5IterSetOutputs_Col100; - sqlite3Fts5BufferSize(pRc, &pIter->poslist, pConfig->nCol); - }else{ - pIter->xSetOutputs = fts5IterSetOutputs_Col; - } - } -} - /* ** Open a new iterator to iterate though all rowid that match the ** specified token or token prefix. @@ -5177,7 +5128,9 @@ int sqlite3Fts5IndexQuery( Fts5Structure *pStruct = fts5StructureRead(p); buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx); if( pStruct ){ - fts5MultiIterNew(p, pStruct, 1, flags, buf.p, nToken+1, -1, 0, &pRet); + fts5MultiIterNew(p, pStruct, flags | FTS5INDEX_QUERY_SKIPEMPTY, + pColset, buf.p, nToken+1, -1, 0, &pRet + ); fts5StructureRelease(pStruct); } }else{ @@ -5185,14 +5138,13 @@ int sqlite3Fts5IndexQuery( int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0; buf.p[0] = FTS5_MAIN_PREFIX; fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet); + fts5IterSetOutputCb(&p->rc, pRet); + if( p->rc==SQLITE_OK ){ + Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst]; + if( p->rc==SQLITE_OK && pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); + } } - if( p->rc==SQLITE_OK ){ - Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst]; - pRet->pColset = pColset; - fts5IterSetOutputCb(&p->rc, pRet); - if( p->rc==SQLITE_OK && pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); - } if( p->rc ){ sqlite3Fts5IterClose(&pRet->base); pRet = 0; @@ -5769,6 +5721,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){ u64 cksum3 = 0; /* Checksum based on contents of indexes */ Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */ #endif + const int flags = FTS5INDEX_QUERY_NOOUTPUT; /* Load the FTS index structure */ pStruct = fts5StructureRead(p); @@ -5797,7 +5750,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){ ** same term is performed. cksum3 is calculated based on the entries ** extracted by these queries. */ - for(fts5MultiIterNew(p, pStruct, 0, 0, 0, 0, -1, 0, &pIter); + for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, -1, 0, &pIter); fts5MultiIterEof(p, pIter)==0; fts5MultiIterNext(p, pIter, 0, 0) ){ diff --git a/manifest b/manifest index b7ee931a14..0efc8787a5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\smarkup\serrors\sin\scomments\sused\sto\sgenerate\sthe\sdocumentation\s-\sspecifically\nin\sthe\sdocumentation\son\sthe\sOP_Seek\sopcode. -D 2016-02-03T19:52:06.161 +C Improve\sperformance\sof\sfts5\sprefix\squeries\son\sdetail=col\stables. +D 2016-02-03T20:04:59.805 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -98,13 +98,13 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 -F ext/fts5/fts5Int.h 9505f3bc8d0b2ca4cd2b112e7e042e3c6a3222a7 +F ext/fts5/fts5Int.h 2095cc38e776f19cc083ca90e00772ea0b204ab3 F ext/fts5/fts5_aux.c b9bcce753ef5b451267b2232f0ca153ddeb3951d F ext/fts5/fts5_buffer.c f6e0c6018ffc8e39fc0b333b5daa8b8d528ae6e4 F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 F ext/fts5/fts5_expr.c ff5c451a6d025909639ac0f0d0af0cc595b50feb F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c 471ff6935068a4579830474249e1046b57137103 +F ext/fts5/fts5_index.c e634a4a05b066f7122db93558c871148bd9893f2 F ext/fts5/fts5_main.c 7e8a5f27d504bc04e3de7f1cba8867f0332aee9d F ext/fts5/fts5_storage.c 2a1f44deae090cd711f02cec0c2af8e660360d24 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -1423,7 +1423,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P af92401826f5cf49e62c278f344ab75252a18da2 -R f36c5f43b820b4830c00d3f3959d5c82 -U drh -Z cdc17003a87221b5f2cfde36f98aed07 +P ef252bc4b59d272460aaebdc0d4b8e347b0d25a8 +R 671ea22942ad2d2bcb9568b9e59d452e +U dan +Z 34c6688fd340fcbe0aee4e43e23acf72 diff --git a/manifest.uuid b/manifest.uuid index 6563093eae..06d0c2d828 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ef252bc4b59d272460aaebdc0d4b8e347b0d25a8 \ No newline at end of file +ca11f46db047e7f131cef3893f73824758a2076b \ No newline at end of file From fabe393da8f09bee7f40781e2bae9edacebe8619 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Feb 2016 22:14:38 +0000 Subject: [PATCH 213/570] In the VDBE loop, only check for OOM errors at jumps rather than after every opcode, for about a 0.5% performance increase. FossilOrigin-Name: 632071bac5ff324a74cec9bdbba2deb60c0945e9 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbe.c | 7 ++++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 0efc8787a5..63d7f994de 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\sperformance\sof\sfts5\sprefix\squeries\son\sdetail=col\stables. -D 2016-02-03T20:04:59.805 +C In\sthe\sVDBE\sloop,\sonly\scheck\sfor\sOOM\serrors\sat\sjumps\srather\sthan\safter\severy\nopcode,\sfor\sabout\sa\s0.5%\sperformance\sincrease. +D 2016-02-03T22:14:38.812 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -413,7 +413,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 16ca0c1e2975fac04c3ea5c62b34dc24b13fea13 +F src/vdbe.c f0c2e2fb8cbff761ea8602058406c151b9325e8d F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 F src/vdbeapi.c 9d640d5efd9a140a6bda8da53b220aa258167993 @@ -1423,7 +1423,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ef252bc4b59d272460aaebdc0d4b8e347b0d25a8 -R 671ea22942ad2d2bcb9568b9e59d452e -U dan -Z 34c6688fd340fcbe0aee4e43e23acf72 +P ca11f46db047e7f131cef3893f73824758a2076b +R 59ea01ed7c88b6674116d0bfaf73cf15 +U drh +Z 96f5f7409c64154023cc6759eed6c5b3 diff --git a/manifest.uuid b/manifest.uuid index 06d0c2d828..bfccf07dec 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ca11f46db047e7f131cef3893f73824758a2076b \ No newline at end of file +632071bac5ff324a74cec9bdbba2deb60c0945e9 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 62ad86d4f3..fd90d3b0de 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -629,7 +629,6 @@ int sqlite3VdbeExec( #endif for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){ assert( pOp>=aOp && pOp<&aOp[p->nOp]); - if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE start = sqlite3Hwtime(); #endif @@ -754,14 +753,16 @@ jump_to_p2_and_check_for_interrupt: /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon ** completion. Check to see if sqlite3_interrupt() has been called - ** or if the progress callback needs to be invoked. + ** or if the progress callback needs to be invoked. Also check for + ** OOM conditions and abort if seen. ** ** This code uses unstructured "goto" statements and does not look clean. ** But that is not due to sloppy coding habits. The code is written this ** way for performance, to avoid having to run the interrupt and progress - ** checks on every opcode. This helps sqlite3_step() to run about 1.5% + ** checks on every opcode. This helps sqlite3_step() to run over 2.0% ** faster according to "valgrind --tool=cachegrind" */ check_for_interrupt: + if( db->mallocFailed ) goto no_mem; if( db->u1.isInterrupted ) goto abort_due_to_interrupt; #ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* Call the progress callback if it is configured and the required number From 6d258995e65e606f65b9189c409801c3da01f4ef Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 4 Feb 2016 09:48:12 +0000 Subject: [PATCH 214/570] Refinements to synchronous logic: (1) Use PAGER_SYNCHRONOUS_FULL rather than the corresponding magic number. (2) Honor SQLITE_NO_SYNC on xDelete calls with sync (3) Count xDelete syncs during testing (4) Fix #ifs on SQLITE_EXTRA_DURABLE so that directory syncs on journal unlink are off by default. FossilOrigin-Name: e3157cb5ad0d22758e766a95fb1463a7810f7d7f --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/attach.c | 3 ++- src/os_unix.c | 9 ++------- src/pager.c | 2 +- test/sync.test | 11 +++++------ 6 files changed, 20 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index 63d7f994de..b33b7f4352 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sVDBE\sloop,\sonly\scheck\sfor\sOOM\serrors\sat\sjumps\srather\sthan\safter\severy\nopcode,\sfor\sabout\sa\s0.5%\sperformance\sincrease. -D 2016-02-03T22:14:38.812 +C Refinements\sto\ssynchronous\slogic:\s\n(1)\sUse\sPAGER_SYNCHRONOUS_FULL\srather\sthan\sthe\scorresponding\smagic\snumber.\n(2)\sHonor\sSQLITE_NO_SYNC\son\sxDelete\scalls\swith\ssync\n(3)\sCount\sxDelete\ssyncs\sduring\stesting\n(4)\sFix\s#ifs\son\sSQLITE_EXTRA_DURABLE\sso\sthat\sdirectory\ssyncs\son\sjournal\nunlink\sare\soff\sby\sdefault. +D 2016-02-04T09:48:12.199 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -286,7 +286,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 3fe13e97ab38317b092e2f3ae11267b40c9b5cbd F src/analyze.c 0043d3e501f04297fed2bb50b488bc08d5c39f36 -F src/attach.c 07b3a34a1702dce92a7f1d3888c0c06222b63760 +F src/attach.c 27743a694df17ca468eee3956126a5d28d2a29ea F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf @@ -332,10 +332,10 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c 5bb20172d0c9a6afcfa829a88c406970593c848d +F src/os_unix.c 821ed110197175165cf2f50b0930c7ff9a24504c F src/os_win.c ccf29ddded3e41e506b6bd98c1171aa0963b23f2 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c 3e189231fc662710964b54862450bc7f69f313c2 +F src/pager.c 67cd2fbab58d0e35fed5f81432856f4f0af9fc6d F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 F src/parse.y 426a91fbbbf7cdde3fd4b8798de7317a8782bec5 F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23 @@ -1065,7 +1065,7 @@ F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2 F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849 -F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85 +F test/sync.test 2f607e1821aa3af3c5c53b58835c05e511c95899 F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 F test/tabfunc01.test cc33684f9480fcf1fd5ce287ac28d22971cad1cc @@ -1423,7 +1423,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ca11f46db047e7f131cef3893f73824758a2076b -R 59ea01ed7c88b6674116d0bfaf73cf15 +P 632071bac5ff324a74cec9bdbba2deb60c0945e9 +R 3746b9c792f29a07d873215ad89cd62c U drh -Z 96f5f7409c64154023cc6759eed6c5b3 +Z 6297b2dadaa7144af31b30e87beaeee7 diff --git a/manifest.uuid b/manifest.uuid index bfccf07dec..2921dbef8e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -632071bac5ff324a74cec9bdbba2deb60c0945e9 \ No newline at end of file +e3157cb5ad0d22758e766a95fb1463a7810f7d7f \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index fd5cc7c76c..12d3ac3ff6 100644 --- a/src/attach.c +++ b/src/attach.c @@ -156,7 +156,8 @@ static void attachFunc( sqlite3BtreeSecureDelete(aNew->pBt, sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); #ifndef SQLITE_OMIT_PAGER_PRAGMAS - sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK)); + sqlite3BtreeSetPagerFlags(aNew->pBt, + PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK)); #endif sqlite3BtreeLeave(aNew->pBt); } diff --git a/src/os_unix.c b/src/os_unix.c index 81422f215d..fe1fc6af19 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -5887,12 +5887,7 @@ static int unixDelete( int fd; rc = osOpenDirectory(zPath, &fd); if( rc==SQLITE_OK ){ -#if OS_VXWORKS - if( fsync(fd)==-1 ) -#else - if( fsync(fd) ) -#endif - { + if( full_fsync(fd,0,0) ){ rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); } robust_close(0, fd, __LINE__); @@ -6936,7 +6931,7 @@ static int proxyTakeConch(unixFile *pFile){ writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]); robust_ftruncate(conchFile->h, writeSize); rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0); - fsync(conchFile->h); + full_fsync(conchFile->h,0,0); /* If we created a new conch file (not just updated the contents of a ** valid conch file), try to match the permissions of the database */ diff --git a/src/pager.c b/src/pager.c index 8f1635d9ee..5c61968e36 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4823,7 +4823,7 @@ act_like_temp_file: assert( pPager->ckptSyncFlags==0 ); }else{ pPager->fullSync = 1; -#ifdef SQLITE_EXTRA_DURABLE +#if SQLITE_EXTRA_DURABLE pPager->extraSync = 1; #else pPager->extraSync = 0; diff --git a/test/sync.test b/test/sync.test index 14252b5c08..2ee636a266 100644 --- a/test/sync.test +++ b/test/sync.test @@ -13,7 +13,6 @@ # This file implements tests to verify that fsync is disabled when # pragma synchronous=off even for multi-database commits. # -# $Id: sync.test,v 1.6 2007/10/09 08:29:33 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -33,7 +32,7 @@ proc cond_incr_sync_count {adj} { global sqlite_sync_count if {$::tcl_platform(platform) == "windows"} { incr sqlite_sync_count $adj - } { + } else { ifcapable !dirsync { incr sqlite_sync_count $adj } @@ -64,9 +63,9 @@ ifcapable pager_pragmas { INSERT INTO t2 VALUES(3,4); COMMIT; } - cond_incr_sync_count 3 + cond_incr_sync_count 4 set sqlite_sync_count - } 8 + } 9 } do_test sync-1.3 { set sqlite_sync_count 0 @@ -78,9 +77,9 @@ do_test sync-1.3 { INSERT INTO t2 VALUES(5,6); COMMIT; } - cond_incr_sync_count 3 + cond_incr_sync_count 4 set sqlite_sync_count -} 10 +} 11 ifcapable pager_pragmas { do_test sync-1.4 { set sqlite_sync_count 0 From 3b7f9a68d5172c215fe56dc5dc60378aec268820 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 4 Feb 2016 10:28:57 +0000 Subject: [PATCH 215/570] Escape control characters in JSON. Fix for ticket [ad2559db380abf8]. FossilOrigin-Name: 4f1b5229a3bbc9d40b7433a5eb3139d59d31dcb1 --- ext/misc/json1.c | 25 ++++++++++++++++++++++++- manifest | 14 +++++++------- manifest.uuid | 2 +- test/json101.test | 15 +++++++++++++++ 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/ext/misc/json1.c b/ext/misc/json1.c index 3707516660..e4ea4fb9f0 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -276,10 +276,33 @@ static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return; p->zBuf[p->nUsed++] = '"'; for(i=0; inUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; p->zBuf[p->nUsed++] = '\\'; + }else if( c<=0x1f ){ + static const char aSpecial[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + assert( sizeof(aSpecial)==32 ); + assert( aSpecial['\b']=='b' ); + assert( aSpecial['\f']=='f' ); + assert( aSpecial['\n']=='n' ); + assert( aSpecial['\r']=='r' ); + assert( aSpecial['\t']=='t' ); + if( aSpecial[c] ){ + c = aSpecial[c]; + goto json_simple_escape; + } + if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return; + p->zBuf[p->nUsed++] = '\\'; + p->zBuf[p->nUsed++] = 'u'; + p->zBuf[p->nUsed++] = '0'; + p->zBuf[p->nUsed++] = '0'; + p->zBuf[p->nUsed++] = '0' + (c>>4); + c = "0123456789abcdef"[c&0xf]; } p->zBuf[p->nUsed++] = c; } diff --git a/manifest b/manifest index b33b7f4352..3bb584fd54 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Refinements\sto\ssynchronous\slogic:\s\n(1)\sUse\sPAGER_SYNCHRONOUS_FULL\srather\sthan\sthe\scorresponding\smagic\snumber.\n(2)\sHonor\sSQLITE_NO_SYNC\son\sxDelete\scalls\swith\ssync\n(3)\sCount\sxDelete\ssyncs\sduring\stesting\n(4)\sFix\s#ifs\son\sSQLITE_EXTRA_DURABLE\sso\sthat\sdirectory\ssyncs\son\sjournal\nunlink\sare\soff\sby\sdefault. -D 2016-02-04T09:48:12.199 +C Escape\scontrol\scharacters\sin\sJSON.\nFix\sfor\sticket\s[ad2559db380abf8]. +D 2016-02-04T10:28:57.253 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -206,7 +206,7 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2 F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c -F ext/misc/json1.c 7b1155f520d5e8ec1c005d978ac675e8a7f2688a +F ext/misc/json1.c 8698ea0ce24bda23bd8ad4a124620d758f92760b F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc @@ -833,7 +833,7 @@ F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307 F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa -F test/json101.test f0178422b3a2418f423fd0d3caf3571c8d1b9863 +F test/json101.test ef42283f0b60d8bacbc2243448e7c84988578e52 F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0 F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff @@ -1423,7 +1423,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 632071bac5ff324a74cec9bdbba2deb60c0945e9 -R 3746b9c792f29a07d873215ad89cd62c +P e3157cb5ad0d22758e766a95fb1463a7810f7d7f +R b212639d5d48b990a29409ffb71a1dde U drh -Z 6297b2dadaa7144af31b30e87beaeee7 +Z b8b1a6316f2eff8be617256b6e3556cd diff --git a/manifest.uuid b/manifest.uuid index 2921dbef8e..8bc8215408 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e3157cb5ad0d22758e766a95fb1463a7810f7d7f \ No newline at end of file +4f1b5229a3bbc9d40b7433a5eb3139d59d31dcb1 \ No newline at end of file diff --git a/test/json101.test b/test/json101.test index 8c62c8b16c..9b780a379b 100644 --- a/test/json101.test +++ b/test/json101.test @@ -342,4 +342,19 @@ foreach {tn isvalid ws} { $isvalid } +# Ticket https://www.sqlite.org/src/info/ad2559db380abf8e +# Control characters must be escaped in JSON strings. +# +do_execsql_test json-8.1 { + DROP TABLE IF EXISTS t8; + CREATE TABLE t8(a,b); + INSERT INTO t8(a) VALUES('abc' || char(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) || 'xyz'); + UPDATE t8 SET b=json_array(a); + SELECT b FROM t8; +} {{["abc\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#xyz"]}} +do_execsql_test json-8.2 { + SELECT a=json_extract(b,'$[0]') FROM t8; +} {1} + + finish_test From c4703eedab614f8b4e5e8173ac78e8507439a556 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 4 Feb 2016 11:15:57 +0000 Subject: [PATCH 216/570] Use sqlite3_malloc64() instead of sqlite3_malloc() in the spellfix extension. FossilOrigin-Name: 634d008c34bd237fc9cfb88dc291394fc5d31efa --- ext/misc/spellfix.c | 30 +++++++++++++++--------------- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/ext/misc/spellfix.c b/ext/misc/spellfix.c index 68bd2afbb2..cac1edcff8 100644 --- a/ext/misc/spellfix.c +++ b/ext/misc/spellfix.c @@ -186,7 +186,7 @@ static const unsigned char className[] = ".ABCDHLRMY9 ?"; ** Return NULL if memory allocation fails. */ static unsigned char *phoneticHash(const unsigned char *zIn, int nIn){ - unsigned char *zOut = sqlite3_malloc( nIn + 1 ); + unsigned char *zOut = sqlite3_malloc64( nIn + 1 ); int i; int nOut = 0; char cPrev = 0x77; @@ -413,7 +413,7 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){ if( nB<(sizeof(mStack)*4)/(sizeof(mStack[0])*5) ){ m = mStack; }else{ - m = toFree = sqlite3_malloc( (nB+1)*5*sizeof(m[0])/4 ); + m = toFree = sqlite3_malloc64( (nB+1)*5*sizeof(m[0])/4 ); if( m==0 ) return -3; } cx = (char*)&m[nB+1]; @@ -687,7 +687,7 @@ static int editDist3ConfigLoad( if( iCost<0 ) continue; if( pLang==0 || iLang!=iLangPrev ){ EditDist3Lang *pNew; - pNew = sqlite3_realloc(p->a, (p->nLang+1)*sizeof(p->a[0])); + pNew = sqlite3_realloc64(p->a, (p->nLang+1)*sizeof(p->a[0])); if( pNew==0 ){ rc = SQLITE_NOMEM; break; } p->a = pNew; pLang = &p->a[p->nLang]; @@ -709,7 +709,7 @@ static int editDist3ConfigLoad( EditDist3Cost *pCost; int nExtra = nFrom + nTo - 4; if( nExtra<0 ) nExtra = 0; - pCost = sqlite3_malloc( sizeof(*pCost) + nExtra ); + pCost = sqlite3_malloc64( sizeof(*pCost) + nExtra ); if( pCost==0 ){ rc = SQLITE_NOMEM; break; } pCost->nFrom = nFrom; pCost->nTo = nTo; @@ -808,7 +808,7 @@ static EditDist3FromString *editDist3FromStringNew( if( z==0 ) return 0; if( n<0 ) n = (int)strlen(z); - pStr = sqlite3_malloc( sizeof(*pStr) + sizeof(pStr->a[0])*n + n + 1 ); + pStr = sqlite3_malloc64( sizeof(*pStr) + sizeof(pStr->a[0])*n + n + 1 ); if( pStr==0 ) return 0; pStr->a = (EditDist3From*)&pStr[1]; memset(pStr->a, 0, sizeof(pStr->a[0])*n); @@ -833,13 +833,13 @@ static EditDist3FromString *editDist3FromStringNew( if( i+p->nFrom>n ) continue; if( matchFrom(p, z+i, n-i)==0 ) continue; if( p->nTo==0 ){ - apNew = sqlite3_realloc(pFrom->apDel, + apNew = sqlite3_realloc64(pFrom->apDel, sizeof(*apNew)*(pFrom->nDel+1)); if( apNew==0 ) break; pFrom->apDel = apNew; apNew[pFrom->nDel++] = p; }else{ - apNew = sqlite3_realloc(pFrom->apSubst, + apNew = sqlite3_realloc64(pFrom->apSubst, sizeof(*apNew)*(pFrom->nSubst+1)); if( apNew==0 ) break; pFrom->apSubst = apNew; @@ -925,7 +925,7 @@ static int editDist3Core( m = stackSpace; pToFree = 0; }else{ - m = pToFree = sqlite3_malloc( nByte ); + m = pToFree = sqlite3_malloc64( nByte ); if( m==0 ) return -1; /* Out of memory */ } a2 = (EditDist3To*)&m[n]; @@ -940,7 +940,7 @@ static int editDist3Core( if( i2+p->nTo>n2 ) continue; if( matchTo(p, z2+i2, n2-i2)==0 ) continue; a2[i2].nIns++; - apNew = sqlite3_realloc(a2[i2].apIns, sizeof(*apNew)*a2[i2].nIns); + apNew = sqlite3_realloc64(a2[i2].apIns, sizeof(*apNew)*a2[i2].nIns); if( apNew==0 ){ res = -1; /* Out of memory */ goto editDist3Abort; @@ -1118,7 +1118,7 @@ static void editDist3SqlFunc( */ static int editDist3Install(sqlite3 *db){ int rc; - EditDist3Config *pConfig = sqlite3_malloc( sizeof(*pConfig) ); + EditDist3Config *pConfig = sqlite3_malloc64( sizeof(*pConfig) ); if( pConfig==0 ) return SQLITE_NOMEM; memset(pConfig, 0, sizeof(*pConfig)); rc = sqlite3_create_function_v2(db, "editdist3", @@ -1607,7 +1607,7 @@ static const struct { ** should be freed by the caller. */ static unsigned char *transliterate(const unsigned char *zIn, int nIn){ - unsigned char *zOut = sqlite3_malloc( nIn*4 + 1 ); + unsigned char *zOut = sqlite3_malloc64( nIn*4 + 1 ); int c, sz, nOut; if( zOut==0 ) return 0; nOut = 0; @@ -1930,7 +1930,7 @@ static int spellfix1Init( int i; nDbName = (int)strlen(zDbName); - pNew = sqlite3_malloc( sizeof(*pNew) + nDbName + 1); + pNew = sqlite3_malloc64( sizeof(*pNew) + nDbName + 1); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ @@ -2044,7 +2044,7 @@ static void spellfix1ResetCursor(spellfix1_cursor *pCur){ static void spellfix1ResizeCursor(spellfix1_cursor *pCur, int N){ struct spellfix1_row *aNew; assert( N>=pCur->nRow ); - aNew = sqlite3_realloc(pCur->a, sizeof(pCur->a[0])*N); + aNew = sqlite3_realloc64(pCur->a, sizeof(pCur->a[0])*N); if( aNew==0 && N>0 ){ spellfix1ResetCursor(pCur); sqlite3_free(pCur->a); @@ -2203,7 +2203,7 @@ static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ static int spellfix1Open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ spellfix1_vtab *p = (spellfix1_vtab*)pVTab; spellfix1_cursor *pCur; - pCur = sqlite3_malloc( sizeof(*pCur) ); + pCur = sqlite3_malloc64( sizeof(*pCur) ); if( pCur==0 ) return SQLITE_NOMEM; memset(pCur, 0, sizeof(*pCur)); pCur->pVTab = p; @@ -2417,7 +2417,7 @@ static int spellfix1FilterForMatch( /* Load the cost table if we have not already done so */ if( p->zCostTable!=0 && p->pConfig3==0 ){ - p->pConfig3 = sqlite3_malloc( sizeof(p->pConfig3[0]) ); + p->pConfig3 = sqlite3_malloc64( sizeof(p->pConfig3[0]) ); if( p->pConfig3==0 ) return SQLITE_NOMEM; memset(p->pConfig3, 0, sizeof(p->pConfig3[0])); rc = editDist3ConfigLoad(p->pConfig3, p->db, p->zCostTable); diff --git a/manifest b/manifest index 3bb584fd54..b43bff0440 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Escape\scontrol\scharacters\sin\sJSON.\nFix\sfor\sticket\s[ad2559db380abf8]. -D 2016-02-04T10:28:57.253 +C Use\ssqlite3_malloc64()\sinstead\sof\ssqlite3_malloc()\sin\sthe\sspellfix\sextension. +D 2016-02-04T11:15:57.924 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -213,7 +213,7 @@ F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a F ext/misc/series.c b8fb7befd85b3a9b4a10e701b30b2b79ca92b6d4 F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 -F ext/misc/spellfix.c db4cc4b7aa12384e6c19a289a39cd232d355413d +F ext/misc/spellfix.c 525190484b7a9dbc6be646c4842274fff4f27d53 F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e @@ -1423,7 +1423,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e3157cb5ad0d22758e766a95fb1463a7810f7d7f -R b212639d5d48b990a29409ffb71a1dde +P 4f1b5229a3bbc9d40b7433a5eb3139d59d31dcb1 +R cd8475786d59a53ccb02d1969d7db950 U drh -Z b8b1a6316f2eff8be617256b6e3556cd +Z 726ec290d2122a80c8fe5371e8b4749b diff --git a/manifest.uuid b/manifest.uuid index 8bc8215408..c28b7cc350 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4f1b5229a3bbc9d40b7433a5eb3139d59d31dcb1 \ No newline at end of file +634d008c34bd237fc9cfb88dc291394fc5d31efa \ No newline at end of file From 4df86af329e606e8c92d5d41a8874e30ebb226cb Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 4 Feb 2016 11:48:00 +0000 Subject: [PATCH 217/570] Remove unnecessary sets of db->mallocFailed. FossilOrigin-Name: b787165b25a240fd5b4a5c7f73b395f30213a1d7 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/alter.c | 2 +- src/btree.c | 1 - src/build.c | 2 +- src/wherecode.c | 4 +--- 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index b43bff0440..194c646e6b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\ssqlite3_malloc64()\sinstead\sof\ssqlite3_malloc()\sin\sthe\sspellfix\sextension. -D 2016-02-04T11:15:57.924 +C Remove\sunnecessary\ssets\sof\sdb->mallocFailed. +D 2016-02-04T11:48:00.219 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -284,17 +284,17 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 3fe13e97ab38317b092e2f3ae11267b40c9b5cbd +F src/alter.c b6e0befc17d69b59c66f4b8a126c05b1ee7ef10a F src/analyze.c 0043d3e501f04297fed2bb50b488bc08d5c39f36 F src/attach.c 27743a694df17ca468eee3956126a5d28d2a29ea F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c a2a0244ea3f0b3f57f75019c2f229c744ca5d202 +F src/btree.c 0b359bcc2316a57acf12f583253974ad22b4654f F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 33dea2cef04c16a902c55f9d83b1a2065f213979 +F src/build.c 88ee370118ff7f081f2060ad3fb6c170f9aed7d3 F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -429,7 +429,7 @@ F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c af9bf5dcec1a0e52726c550924aa91d837166251 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a -F src/wherecode.c 923f5d04b379b7417bc29f3b86b5eae9d1923d72 +F src/wherecode.c 791a784bbf8749d560fdb0b990b607bc4f44a38d F src/whereexpr.c 197a448b52073aee43eca3a2233fc113369eb2d4 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1423,7 +1423,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4f1b5229a3bbc9d40b7433a5eb3139d59d31dcb1 -R cd8475786d59a53ccb02d1969d7db950 +P 634d008c34bd237fc9cfb88dc291394fc5d31efa +R 0723d194047e6276e554e1a515e620e8 U drh -Z 726ec290d2122a80c8fe5371e8b4749b +Z 4a87610dafa418a613875dd84903b4d5 diff --git a/manifest.uuid b/manifest.uuid index c28b7cc350..8a6b51b9d7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -634d008c34bd237fc9cfb88dc291394fc5d31efa \ No newline at end of file +b787165b25a240fd5b4a5c7f73b395f30213a1d7 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index c8102c55d2..16b7a9e192 100644 --- a/src/alter.c +++ b/src/alter.c @@ -803,7 +803,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); if( !pNew->aCol || !pNew->zName ){ - db->mallocFailed = 1; + assert( db->mallocFailed ); goto exit_begin_add_column; } memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); diff --git a/src/btree.c b/src/btree.c index d5acaf3669..b99820ddbc 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2338,7 +2338,6 @@ int sqlite3BtreeOpen( pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST); if( pBt->mutex==0 ){ rc = SQLITE_NOMEM; - db->mallocFailed = 0; goto btree_open_out; } } diff --git a/src/build.c b/src/build.c index 3ca4c99947..cea05d51c7 100644 --- a/src/build.c +++ b/src/build.c @@ -926,7 +926,7 @@ void sqlite3StartTable( pTable = sqlite3DbMallocZero(db, sizeof(Table)); if( pTable==0 ){ - db->mallocFailed = 1; + assert( db->mallocFailed ); pParse->rc = SQLITE_NOMEM; pParse->nErr++; goto begin_table_error; diff --git a/src/wherecode.c b/src/wherecode.c index f5f45da397..bb48e5dc70 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -495,9 +495,7 @@ static int codeAllEqualityTerms( pParse->nMem += nReg; zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx)); - if( !zAff ){ - pParse->db->mallocFailed = 1; - } + assert( zAff!=0 || pParse->db->mallocFailed ); if( nSkip ){ int iIdxCur = pLevel->iIdxCur; From be7721d10339d31ffd0db5eddc45c8483f1a6fba Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 4 Feb 2016 17:31:03 +0000 Subject: [PATCH 218/570] Avoid running some particularly time-consuming tests as part of veryquick.test. FossilOrigin-Name: f465944b75a800ddc6920229ad32c2f39ff91e19 --- manifest | 41 ++-- manifest.uuid | 2 +- test/fuzzer1.test | 46 ----- test/fuzzer2.test | 72 +++++++ test/mmap1.test | 65 +------ test/mmap4.test | 104 ++++++++++ test/permutations.test | 20 +- test/{savepoint3.test => savepointfault.test} | 13 +- test/sort.test | 46 ----- test/sort2.test | 28 +-- test/sort3.test | 51 ++++- test/tester.tcl | 6 + test/wal.test | 85 --------- test/wal3.test | 143 +------------- test/walcksum.test | 54 ------ test/walprotocol.test | 177 ++++++++++++++++++ test/walslow.test | 158 ++++++++++++++++ test/{where8m.test => wherefault.test} | 12 +- 18 files changed, 639 insertions(+), 484 deletions(-) create mode 100644 test/fuzzer2.test create mode 100644 test/mmap4.test rename test/{savepoint3.test => savepointfault.test} (94%) create mode 100644 test/walprotocol.test rename test/{where8m.test => wherefault.test} (84%) diff --git a/manifest b/manifest index 194c646e6b..7b935898ba 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sunnecessary\ssets\sof\sdb->mallocFailed. -D 2016-02-04T11:48:00.219 +C Avoid\srunning\ssome\sparticularly\stime-consuming\stests\sas\spart\sof\sveryquick.test. +D 2016-02-04T17:31:03.368 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -769,7 +769,8 @@ F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973 F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba F test/fuzzdata4.db 1882f0055fb63214d8407ddc7aca9b0b1c59af21 -F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36 +F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 +F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536 F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98 F test/hexlit.test d7b0a5f41123df1e43985b91b8b2e70f95282d21 @@ -897,9 +898,10 @@ F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2 F test/misc8.test fc2754d38892f7dac30c22db3616c2764f117d66 F test/misuse.test 3c34719944ba045cc6c188a4852ba04680728912 -F test/mmap1.test 1bfd611b9841eafb44f7d83c0788e146d84a33c9 +F test/mmap1.test 44a5ff1c1bcc7dcf2de50227d1f997e75a8ef1ae F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022 F test/mmap3.test c92273e16eb8d23c1d55c9815b446bb72ef0512e +F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93 F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3 F test/multiplex.test efd015ca0b5b4a57dc9535b8feb1273eebeadb60 F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a @@ -942,7 +944,7 @@ F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test 4ea119731c62d2f7d0aa86dd5b184cbb61ca411b +F test/permutations.test 382a43c49f49bafe6fddffe904ea33d6bb3ff33e F test/pragma.test 507ac7ef2ea5682241ea0ef041799ca70bb5e0bf F test/pragma2.test a9400a7289605280576098b97f5cde3f204075c0 F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c @@ -974,11 +976,11 @@ F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798 F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09 F test/savepoint.test c671fdbd34cd3bfe1518a777526ada595180cf8d F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7 -F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0 F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7 F test/savepoint7.test db3db281486c925095f305aad09fe806e5188ff3 +F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2 w test/savepoint3.test F test/scanstatus.test 5253c219e331318a437f436268e0e82345700285 F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481 F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5 @@ -1034,9 +1036,9 @@ F test/snapshot.test efc6b4edc5d571161835f9dd8552e181ad1f0ac2 F test/snapshot_fault.test 25973aeb1b86a280800e0bcf1eb5ce70e9ef57ab F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087 -F test/sort.test 3f492e5b7be1d3f756728d2ff6edf4f6091e84cb -F test/sort2.test 37afbc03f5559f2eb0f18940b55d38dfbb5172ac -F test/sort3.test 6178ade30810ac9166fcdf14b7065e49c0f534e2 +F test/sort.test c2adc635c2564241fefec0b3a68391ef6868fd3b +F test/sort2.test cc23b7c19d684657559e8a55b02f7fcee03851d0 +F test/sort3.test 1d831e95076b92985754a122e92ebc23bdf6f712 F test/sort4.test 5c34d9623a4ae5921d956dfa2b70e77ed0fc6e5c F test/sort5.test a448240a42b49239edc00f85d6d7ac7a1b261e1f F test/sortfault.test d4ccf606a0c77498e2beb542764fd9394acb4d66 @@ -1076,7 +1078,7 @@ F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054 F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl af4749cf4abf04291710c5e73f40bc8f411bae86 +F test/tester.tcl 462376b478c1429030911b4cb7c8c517ef1fbd9b F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1294,9 +1296,9 @@ F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 F test/vtab_shared.test ea8778d5b0df200adef2ca7c00c3c37d4375f772 -F test/wal.test 65bfc68f3f09dcbc62cee9f794e560428d96cec7 +F test/wal.test 0148c8b3421a25fdb4d9c160e84a681d0646371b F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada -F test/wal3.test b1d425f68a1f61d12563f0fa1ee6fca7d5afabf4 +F test/wal3.test 5dd734147f1f8f958c5261a1f2775d346d7013ce F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c F test/wal5.test 88b5d9a6a3d1532497ee9f4296f010d66f07e33c F test/wal6.test 4421cd5a2fa99d29cc91ef12fb23bed171ed3a4c @@ -1308,7 +1310,7 @@ F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe F test/walbak.test b9f68e39646375c2b877be906babcc15d38b4877 F test/walbig.test f437473a16cfb314867c6b5d1dbcd519e73e3434 F test/walblock.test be48f3a75eff0b4456209f26b3ce186c2015497d -F test/walcksum.test 9afeb96240296c08c72fc524d199c912cfe34daa +F test/walcksum.test bb234a1bb42248b3515d992b719708015c384278 F test/walcrash.test 21038858cc552077b0522f50b0fa87e38139306a F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36 F test/walcrash3.test e426aa58122d20f2b9fbe9a507f9eb8cab85b8af @@ -1318,9 +1320,10 @@ F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496 F test/waloverwrite.test a0d2ae0783187374c1e6a9571e0916152977cb81 F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6 +F test/walprotocol.test 059cb75484a1ecf6357a2c1b3324b8156749221e F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 -F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a +F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e F test/where.test 9902a3d84e9bc80357a2c54ed0e76c0d6d04a867 F test/where2.test af78c55589cbc82d793449493adba0dc3d659f23 @@ -1330,7 +1333,6 @@ F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b F test/where7.test f520bcec2c3d12dc4615623b06b2aec7c2d67e94 F test/where8.test 98eedca0d375fb400b8377269c4b4686582dfb45 -F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739 F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2 F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5 @@ -1343,6 +1345,7 @@ F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622 F test/whereJ.test 55a3221706a7ab706293f17cc8f96da563bf0767 F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b +F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864 w test/where8m.test F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c @@ -1423,7 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 634d008c34bd237fc9cfb88dc291394fc5d31efa -R 0723d194047e6276e554e1a515e620e8 -U drh -Z 4a87610dafa418a613875dd84903b4d5 +P b787165b25a240fd5b4a5c7f73b395f30213a1d7 +R 2d9511ba502b30b0a28170783af34756 +U dan +Z 9311e6c3b97d9e579dd5eb1512f82842 diff --git a/manifest.uuid b/manifest.uuid index 8a6b51b9d7..81e89adc73 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b787165b25a240fd5b4a5c7f73b395f30213a1d7 \ No newline at end of file +f465944b75a800ddc6920229ad32c2f39ff91e19 \ No newline at end of file diff --git a/test/fuzzer1.test b/test/fuzzer1.test index 4ee5730807..5e361e9df0 100644 --- a/test/fuzzer1.test +++ b/test/fuzzer1.test @@ -23,7 +23,6 @@ ifcapable !vtab { } set ::testprefix fuzzer1 - load_static_extension db fuzzer # Check configuration errors. @@ -1648,51 +1647,6 @@ do_catchsql_test 5.5.4 { CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table'); } {1 {fuzzer: ruleset must be between 0 and 2147483647}} -#------------------------------------------------------------------------- -# This test uses a fuzzer table with many rules. There is one rule to -# map each possible two character string, where characters are lower-case -# letters used in the English language, to all other possible two character -# strings. In total, (26^4)-(26^2) mappings (the subtracted term represents -# the no-op mappings discarded automatically by the fuzzer). -# -# -do_execsql_test 6.1.1 { - DROP TABLE IF EXISTS x1; - DROP TABLE IF EXISTS x1_rules; - CREATE TABLE x1_rules(ruleset, cFrom, cTo, cost); -} -puts "This test is slow - perhaps around 7 seconds on an average pc" -do_test 6.1.2 { - set LETTERS {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 z} - set cost 1 - db transaction { - foreach c1 $LETTERS { - foreach c2 $LETTERS { - foreach c3 $LETTERS { - foreach c4 $LETTERS { - db eval {INSERT INTO x1_rules VALUES(0, $c1||$c2, $c3||$c4, $cost)} - set cost [expr ($cost%1000) + 1] - } - } - } - } - db eval {UPDATE x1_rules SET cost = 20 WHERE cost<20 AND cFrom!='xx'} - } -} {} - -do_execsql_test 6.2 { - SELECT count(*) FROM x1_rules WHERE cTo!=cFrom; -} [expr 26*26*26*26 - 26*26] - -do_execsql_test 6.2.1 { - CREATE VIRTUAL TABLE x1 USING fuzzer(x1_rules); - SELECT word FROM x1 WHERE word MATCH 'xx' LIMIT 10; -} {xx hw hx hy hz ia ib ic id ie} -do_execsql_test 6.2.2 { - SELECT cTo FROM x1_rules WHERE cFrom='xx' - ORDER BY cost asc, rowid asc LIMIT 9; -} {hw hx hy hz ia ib ic id ie} - #------------------------------------------------------------------------- # Test using different types of quotes with CREATE VIRTUAL TABLE # arguments. diff --git a/test/fuzzer2.test b/test/fuzzer2.test new file mode 100644 index 0000000000..44ee9e312c --- /dev/null +++ b/test/fuzzer2.test @@ -0,0 +1,72 @@ +# 2016 February 4 +# +# 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. +# +#*********************************************************************** +# The focus of the tests is the word-fuzzer virtual table. The tests +# in this file are slower than those in fuzzer1.test. So this file does +# not run as part of veryquick.test etc. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +ifcapable !vtab { + finish_test + return +} + +set ::testprefix fuzzer2 +load_static_extension db fuzzer + +#------------------------------------------------------------------------- +# This test uses a fuzzer table with many rules. There is one rule to +# map each possible two character string, where characters are lower-case +# letters used in the English language, to all other possible two character +# strings. In total, (26^4)-(26^2) mappings (the subtracted term represents +# the no-op mappings discarded automatically by the fuzzer). +# +# +do_execsql_test 1.1.1 { + DROP TABLE IF EXISTS x1; + DROP TABLE IF EXISTS x1_rules; + CREATE TABLE x1_rules(ruleset, cFrom, cTo, cost); +} +puts "This test is slow - perhaps around 7 seconds on an average pc" +do_test 1.1.2 { + set LETTERS {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 z} + set cost 1 + db transaction { + foreach c1 $LETTERS { + foreach c2 $LETTERS { + foreach c3 $LETTERS { + foreach c4 $LETTERS { + db eval {INSERT INTO x1_rules VALUES(0, $c1||$c2, $c3||$c4, $cost)} + set cost [expr ($cost%1000) + 1] + } + } + } + } + db eval {UPDATE x1_rules SET cost = 20 WHERE cost<20 AND cFrom!='xx'} + } +} {} + +do_execsql_test 1.2 { + SELECT count(*) FROM x1_rules WHERE cTo!=cFrom; +} [expr 26*26*26*26 - 26*26] + +do_execsql_test 1.2.1 { + CREATE VIRTUAL TABLE x1 USING fuzzer(x1_rules); + SELECT word FROM x1 WHERE word MATCH 'xx' LIMIT 10; +} {xx hw hx hy hz ia ib ic id ie} +do_execsql_test 1.2.2 { + SELECT cTo FROM x1_rules WHERE cFrom='xx' + ORDER BY cost asc, rowid asc LIMIT 9; +} {hw hx hy hz ia ib ic id ie} + +finish_test diff --git a/test/mmap1.test b/test/mmap1.test index 18aec9f8fa..199a058754 100644 --- a/test/mmap1.test +++ b/test/mmap1.test @@ -28,6 +28,10 @@ proc nRead {db} { return $stats(read) } +# Return a Tcl script that registers a user-defined scalar function +# named rblob() with database handle $dbname. The function returns a +# sequence of pseudo-random blobs based on seed value $seed. +# proc register_rblob_code {dbname seed} { return [subst -nocommands { set ::rcnt $seed @@ -40,6 +44,7 @@ proc register_rblob_code {dbname seed} { }] } + # For cases 1.1 and 1.4, the number of pages read using xRead() is 4 on # unix and 9 on windows. The difference is that windows only ever maps # an integer number of OS pages (i.e. creates mappings that are a multiple @@ -269,65 +274,5 @@ do_test 5.5 { sqlite3_finalize $::STMT } SQLITE_OK -#------------------------------------------------------------------------- -# Test various mmap_size settings. -# -foreach {tn1 mmap1 mmap2} { - 1 6144 167773 - 2 18432 140399 - 3 43008 401302 - 4 92160 253899 - 5 190464 2 - 6 387072 752431 - 7 780288 291143 - 8 1566720 594306 - 9 3139584 829137 - 10 6285312 793963 - 11 12576768 1015590 -} { - do_multiclient_test tn { - sql1 { - CREATE TABLE t1(a PRIMARY KEY); - CREATE TABLE t2(x); - INSERT INTO t2 VALUES(''); - } - - code1 [register_rblob_code db 0] - code2 [register_rblob_code db2 444] - - sql1 "PRAGMA mmap_size = $mmap1" - sql2 "PRAGMA mmap_size = $mmap2" - - do_test $tn1.$tn { - for {set i 1} {$i <= 100} {incr i} { - if {$i % 2} { - set c1 sql1 - set c2 sql2 - } else { - set c1 sql2 - set c2 sql1 - } - - $c1 { - INSERT INTO t1 VALUES( rblob(5000) ); - UPDATE t2 SET x = (SELECT md5sum(a) FROM t1); - } - - set res [$c2 { - SELECT count(*) FROM t1; - SELECT x == (SELECT md5sum(a) FROM t1) FROM t2; - PRAGMA integrity_check; - }] - if {$res != [list $i 1 ok]} { - do_test $tn1.$tn.$i { - set ::res - } [list $i 1 ok] - } - } - set res 1 - } {1} - } -} - finish_test diff --git a/test/mmap4.test b/test/mmap4.test new file mode 100644 index 0000000000..97015489cc --- /dev/null +++ b/test/mmap4.test @@ -0,0 +1,104 @@ +# 2016 February 04 +# +# 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 tests the effect of the mmap() or mremap() system calls +# returning an error on the library. +# +# If either mmap() or mremap() fails, SQLite should log an error +# message, then continue accessing the database using read() and +# write() exclusively. +# +set testdir [file dirname $argv0] +source $testdir/tester.tcl +ifcapable !mmap { + finish_test + return +} +source $testdir/lock_common.tcl +set testprefix mmap4 + +# Return a Tcl script that registers a user-defined scalar function +# named rblob() with database handle $dbname. The function returns a +# sequence of pseudo-random blobs based on seed value $seed. +# +proc register_rblob_code {dbname seed} { + return [subst -nocommands { + set ::rcnt $seed + proc rblob {n} { + set ::rcnt [expr (([set ::rcnt] << 3) + [set ::rcnt] + 456) & 0xFFFFFFFF] + set str [format %.8x [expr [set ::rcnt] ^ 0xbdf20da3]] + string range [string repeat [set str] [expr [set n]/4]] 1 [set n] + } + $dbname func rblob rblob + }] +} + +#------------------------------------------------------------------------- +# Test various mmap_size settings. +# +foreach {tn1 mmap1 mmap2} { + 1 6144 167773 + 2 18432 140399 + 3 43008 401302 + 4 92160 253899 + 5 190464 2 + 6 387072 752431 + 7 780288 291143 + 8 1566720 594306 + 9 3139584 829137 + 10 6285312 793963 + 11 12576768 1015590 +} { + do_multiclient_test tn { + sql1 { + CREATE TABLE t1(a PRIMARY KEY); + CREATE TABLE t2(x); + INSERT INTO t2 VALUES(''); + } + + code1 [register_rblob_code db 0] + code2 [register_rblob_code db2 444] + + sql1 "PRAGMA mmap_size = $mmap1" + sql2 "PRAGMA mmap_size = $mmap2" + + do_test $tn1.$tn { + for {set i 1} {$i <= 100} {incr i} { + if {$i % 2} { + set c1 sql1 + set c2 sql2 + } else { + set c1 sql2 + set c2 sql1 + } + + $c1 { + INSERT INTO t1 VALUES( rblob(5000) ); + UPDATE t2 SET x = (SELECT md5sum(a) FROM t1); + } + + set res [$c2 { + SELECT count(*) FROM t1; + SELECT x == (SELECT md5sum(a) FROM t1) FROM t2; + PRAGMA integrity_check; + }] + if {$res != [list $i 1 ok]} { + do_test $tn1.$tn.$i { + set ::res + } [list $i 1 ok] + } + } + set res 1 + } {1} + } +} + +finish_test diff --git a/test/permutations.test b/test/permutations.test index 28bbd3017e..c099889067 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -113,7 +113,14 @@ set allquicktests [test_set $alltests -exclude { vtab_err.test walslow.test walcrash.test walcrash3.test walthread.test rtree3.test indexfault.test securedel2.test sort3.test sort4.test fts4growth.test fts4growth2.test - bigsort.test rbu.test + bigsort.test rbu.test walprotocol.test mmap4.test fuzzer2.test + walcrash2.test e_fkey.test backup.test + + fts4merge.test fts4merge2.test fts4merge4.test fts4check.test + fts3cov.test fts3snippet.test fts3corrupt2.test fts3an.test + fts3defer.test fts4langid.test fts3sort.test fts5unicode.test + + rtree4.test }] if {[info exists ::env(QUICKTEST_INCLUDE)]} { set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)] @@ -150,7 +157,7 @@ test_suite "veryquick" -prefix "" -description { This test suite is the same as the "quick" tests, except that some files that test malloc and IO errors are omitted. } -files [ - test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* + test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* *_err* ] test_suite "extraquick" -prefix "" -description { @@ -158,7 +165,7 @@ test_suite "extraquick" -prefix "" -description { This test suite is the same as the "veryquick" tests, except that slower tests are omitted. } -files [ - test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* \ + test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* *_err* \ wal3.test fts4merge* sort2.test mmap1.test walcrash* \ percentile.test where8m.test walcksum.test savepoint3.test \ fuzzer1.test fuzzer3.test fts3expr3.test @@ -176,7 +183,7 @@ test_suite "valgrind" -prefix "" -description { Run the "veryquick" test suite with a couple of multi-process tests (that fail under valgrind) omitted. } -files [ - test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test \ + test_set $allquicktests -exclude *malloc* *ioerr* *fault* *_err* wal.test \ shell*.test crash8.test atof1.test selectG.test \ tkt-fc62af4523.test numindex1.test ] -initialize { @@ -189,7 +196,8 @@ test_suite "valgrind-nolookaside" -prefix "" -description { Run the "veryquick" test suite with a couple of multi-process tests (that fail under valgrind) omitted. } -files [ - test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test atof1.test + test_set $allquicktests -exclude *malloc* *ioerr* *fault* *_err* \ + wal.test atof1.test ] -initialize { set ::G(valgrind) 1 catch {db close} @@ -266,7 +274,7 @@ test_suite "nofaultsim" -prefix "" -description { This test suite is the same as the "quick" tests, except that some files that test malloc and IO errors are omitted. } -files [ - test_set $allquicktests -exclude *malloc* *ioerr* *fault* + test_set $allquicktests -exclude *malloc* *ioerr* *fault* *_err* ] -initialize { catch {db close} sqlite3_shutdown diff --git a/test/savepoint3.test b/test/savepointfault.test similarity index 94% rename from test/savepoint3.test rename to test/savepointfault.test index 0dcb0aceba..0329f8caa2 100644 --- a/test/savepoint3.test +++ b/test/savepointfault.test @@ -9,14 +9,15 @@ # #*********************************************************************** # -# $Id: savepoint3.test,v 1.5 2009/06/05 17:09:12 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl -do_malloc_test savepoint3-1 -sqlprep { +set testprefix savepointfault + +do_malloc_test 1 -sqlprep { CREATE TABLE t1(a, b, c); INSERT INTO t1 VALUES(1, 2, 3); } -sqlbody { @@ -28,7 +29,7 @@ do_malloc_test savepoint3-1 -sqlprep { RELEASE one; } -do_malloc_test savepoint3-2 -sqlprep { +do_malloc_test 2 -sqlprep { PRAGMA cache_size = 10; CREATE TABLE t1(a, b, c); INSERT INTO t1 VALUES(randstr(400,400), randstr(400,400), randstr(400,400)); @@ -59,7 +60,7 @@ do_malloc_test savepoint3-2 -sqlprep { RELEASE one; } -do_ioerr_test savepoint3.3 -sqlprep { +do_ioerr_test 3 -sqlprep { CREATE TABLE t1(a, b, c); INSERT INTO t1 VALUES(1, randstr(1000,1000), randstr(1000,1000)); INSERT INTO t1 VALUES(2, randstr(1000,1000), randstr(1000,1000)); @@ -79,7 +80,7 @@ do_ioerr_test savepoint3.3 -sqlprep { # The following test does a really big savepoint rollback. One involving # more than 4000 pages. The idea is to get a specific sqlite3BitvecSet() # operation in pagerPlaybackSavepoint() to fail. -#do_malloc_test savepoint3-4 -sqlprep { +#do_malloc_test 4 -sqlprep { # BEGIN; # CREATE TABLE t1(a, b); # CREATE INDEX i1 ON t1(a); @@ -107,7 +108,7 @@ do_ioerr_test savepoint3.3 -sqlprep { # Cause a specific malloc in savepoint rollback code to fail. # -do_malloc_test savepoint3-4 -start 7 -sqlprep { +do_malloc_test 4 -start 7 -sqlprep { PRAGMA auto_vacuum = incremental; PRAGMA cache_size = 1000; diff --git a/test/sort.test b/test/sort.test index 21b11d6c88..d73ecea480 100644 --- a/test/sort.test +++ b/test/sort.test @@ -491,52 +491,6 @@ do_execsql_test sort-13.3 { SELECT a, b FROM t10 ORDER BY a; } [db eval {SELECT a, b FROM t10 ORDER BY a, b}] -#------------------------------------------------------------------------- -# Sort some large ( > 4KiB) records. -# -proc cksum {x} { - set i1 1 - set i2 2 - binary scan $x c* L - foreach {a b} $L { - set i1 [expr (($i2<<3) + $a) & 0x7FFFFFFF] - set i2 [expr (($i1<<3) + $b) & 0x7FFFFFFF] - } - list $i1 $i2 -} -db func cksum cksum - -do_execsql_test sort-14.0 { - PRAGMA cache_size = 5; - CREATE TABLE t11(a, b); - INSERT INTO t11 VALUES(randomblob(5000), NULL); - INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --2 - INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --3 - INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --4 - INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --5 - INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --6 - INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --7 - INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --8 - INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --9 - UPDATE t11 SET b = cksum(a); -} - -foreach {tn mmap_limit} { - 1 0 - 2 1000000 -} { - do_test sort-14.$tn { - sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $mmap_limit - set prev "" - db eval { SELECT * FROM t11 ORDER BY b } { - if {$b != [cksum $a]} {error "checksum failed"} - if {[string compare $b $prev] < 0} {error "sort failed"} - set prev $b - } - set {} {} - } {} -} - #------------------------------------------------------------------------- # foreach {tn mmap_limit nWorker tmpstore coremutex fakeheap softheaplimit} { diff --git a/test/sort2.test b/test/sort2.test index 890025a5d0..f686654d53 100644 --- a/test/sort2.test +++ b/test/sort2.test @@ -31,7 +31,6 @@ foreach {tn script} { catch { db eval {PRAGMA threads=7} } } } { - eval $script do_execsql_test $tn.1 { @@ -67,17 +66,22 @@ foreach {tn script} { do_execsql_test $tn.2.4 { PRAGMA integrity_check } {ok} - do_execsql_test $tn.3 { - PRAGMA cache_size = 5; - WITH r(x,y) AS ( - SELECT 1, randomblob(100) - UNION ALL - SELECT x+1, randomblob(100) FROM r - LIMIT 1000000 - ) - SELECT count(x), length(y) FROM r GROUP BY (x%5) - } { - 200000 100 200000 100 200000 100 200000 100 200000 100 + # Because it uses so much data, this test can take 12-13 seconds even on + # a modern workstation. So it is omitted from "veryquick" and other + # permutations.test tests. + if {[isquick]==0} { + do_execsql_test $tn.3 { + PRAGMA cache_size = 5; + WITH r(x,y) AS ( + SELECT 1, randomblob(100) + UNION ALL + SELECT x+1, randomblob(100) FROM r + LIMIT 1000000 + ) + SELECT count(x), length(y) FROM r GROUP BY (x%5) + } { + 200000 100 200000 100 200000 100 200000 100 200000 100 + } } } diff --git a/test/sort3.test b/test/sort3.test index 80d8bbca3f..3aa6512a4b 100644 --- a/test/sort3.test +++ b/test/sort3.test @@ -19,6 +19,53 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix sort3 +#------------------------------------------------------------------------- +# Sort some large ( > 4KiB) records. +# +proc cksum {x} { + set i1 1 + set i2 2 + binary scan $x c* L + foreach {a b} $L { + set i1 [expr (($i2<<3) + $a) & 0x7FFFFFFF] + set i2 [expr (($i1<<3) + $b) & 0x7FFFFFFF] + } + list $i1 $i2 +} +db func cksum cksum + +do_execsql_test 1.0 { + PRAGMA cache_size = 5; + CREATE TABLE t11(a, b); + INSERT INTO t11 VALUES(randomblob(5000), NULL); + INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --2 + INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --3 + INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --4 + INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --5 + INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --6 + INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --7 + INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --8 + INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --9 + UPDATE t11 SET b = cksum(a); +} + +foreach {tn mmap_limit} { + 1 0 + 2 1000000 +} { + do_test 1.$tn { + sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $mmap_limit + set prev "" + db eval { SELECT * FROM t11 ORDER BY b } { + if {$b != [cksum $a]} {error "checksum failed"} + if {[string compare $b $prev] < 0} {error "sort failed"} + set prev $b + } + set {} {} + } {} +} + + # Sort roughly 20MB of data. Once with a mmap limit of 5MB and once without. # foreach {itest limit} { @@ -26,7 +73,7 @@ foreach {itest limit} { 2 0x7FFFFFFF } { sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $limit - do_execsql_test 1.$itest { + do_execsql_test 2.$itest { WITH r(x,y) AS ( SELECT 1, randomblob(1000) UNION ALL @@ -46,7 +93,7 @@ foreach {itest limit} { # Sort more than 2GB of data. At one point this was causing a problem. # This test might take one minute or more to run. # -do_execsql_test 2 { +do_execsql_test 3 { PRAGMA cache_size = 20000; WITH r(x,y) AS ( SELECT 1, randomblob(1000) diff --git a/test/tester.tcl b/test/tester.tcl index 426808ea90..dc532c97fa 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -1905,6 +1905,12 @@ proc presql {} { set presql } +proc isquick {} { + set ret 0 + catch {set ret $::G(isquick)} + set ret +} + #------------------------------------------------------------------------- # proc slave_test_script {script} { diff --git a/test/wal.test b/test/wal.test index abd3a3ce49..92b65e66ba 100644 --- a/test/wal.test +++ b/test/wal.test @@ -824,91 +824,6 @@ do_test wal-12.6 { db2 close db close -#------------------------------------------------------------------------- -# Test large log summaries. -# -# In this case "large" usually means a log file that requires a wal-index -# mapping larger than 64KB (the default initial allocation). A 64KB wal-index -# is large enough for a log file that contains approximately 13100 frames. -# So the following tests create logs containing at least this many frames. -# -# wal-13.1.*: This test case creates a very large log file within the -# file-system (around 200MB). The log file does not contain -# any valid frames. Test that the database file can still be -# opened and queried, and that the invalid log file causes no -# problems. -# -# wal-13.2.*: Test that a process may create a large log file and query -# the database (including the log file that it itself created). -# -# wal-13.3.*: Test that if a very large log file is created, and then a -# second connection is opened on the database file, it is possible -# to query the database (and the very large log) using the -# second connection. -# -# wal-13.4.*: Same test as wal-13.3.*. Except in this case the second -# connection is opened by an external process. -# -do_test wal-13.1.1 { - list [file exists test.db] [file exists test.db-wal] -} {1 0} -do_test wal-13.1.2 { - set fd [open test.db-wal w] - seek $fd [expr 200*1024*1024] - puts $fd "" - close $fd - sqlite3 db test.db - execsql { SELECT * FROM t2 } -} {B 2} -do_test wal-13.1.3 { - db close - file exists test.db-wal -} {0} - -do_test wal-13.2.1 { - sqlite3 db test.db - execsql { SELECT count(*) FROM t2 } -} {1} -do_test wal-13.2.2 { - db function blob blob - for {set i 0} {$i < 16} {incr i} { - execsql { INSERT INTO t2 SELECT blob(400), blob(400) FROM t2 } - } - execsql { SELECT count(*) FROM t2 } -} [expr int(pow(2, 16))] -do_test wal-13.2.3 { - expr [file size test.db-wal] > [wal_file_size 33000 1024] -} 1 - -do_multiclient_test tn { - incr tn 2 - - do_test wal-13.$tn.0 { - sql1 { - PRAGMA journal_mode = WAL; - CREATE TABLE t1(x); - INSERT INTO t1 SELECT randomblob(800); - } - sql1 { SELECT count(*) FROM t1 } - } {1} - - for {set ii 1} {$ii<16} {incr ii} { - do_test wal-13.$tn.$ii.a { - sql2 { INSERT INTO t1 SELECT randomblob(800) FROM t1 } - sql2 { SELECT count(*) FROM t1 } - } [expr (1<<$ii)] - do_test wal-13.$tn.$ii.b { - sql1 { SELECT count(*) FROM t1 } - } [expr (1<<$ii)] - do_test wal-13.$tn.$ii.c { - sql1 { SELECT count(*) FROM t1 } - } [expr (1<<$ii)] - do_test wal-13.$tn.$ii.d { - sql1 { PRAGMA integrity_check } - } {ok} - } -} - #------------------------------------------------------------------------- # Check a fun corruption case has been fixed. # diff --git a/test/wal3.test b/test/wal3.test index 9ee8a99458..da3d318773 100644 --- a/test/wal3.test +++ b/test/wal3.test @@ -61,7 +61,7 @@ do_test wal3-1.0 { PRAGMA cache_size = 10; } set x [wal_frame_count test.db-wal 1024] - if {$::G(perm:name)=="memsubsys1"} { + if {[permutation]=="memsubsys1"} { if {$x==4251 || $x==4290} {set x 4056} } set x @@ -238,67 +238,6 @@ foreach {tn syncmode synccount} { T delete } -#------------------------------------------------------------------------- -# When recovering the contents of a WAL file, a process obtains the WRITER -# lock, then locks all other bytes before commencing recovery. If it fails -# to lock all other bytes (because some other process is holding a read -# lock) it should retry up to 100 times. Then return SQLITE_PROTOCOL to the -# caller. Test this (test case wal3-4.3). -# -# Also test the effect of hitting an SQLITE_BUSY while attempting to obtain -# the WRITER lock (should be the same). Test case wal3-4.4. -# -proc lock_callback {method filename handle lock} { - lappend ::locks $lock -} -do_test wal3-4.1 { - testvfs T - T filter xShmLock - T script lock_callback - set ::locks [list] - sqlite3 db test.db -vfs T - execsql { SELECT * FROM x } - lrange $::locks 0 3 -} [list {0 1 lock exclusive} {1 7 lock exclusive} \ - {1 7 unlock exclusive} {0 1 unlock exclusive} \ -] -do_test wal3-4.2 { - db close - set ::locks [list] - sqlite3 db test.db -vfs T - execsql { SELECT * FROM x } - lrange $::locks 0 3 -} [list {0 1 lock exclusive} {1 7 lock exclusive} \ - {1 7 unlock exclusive} {0 1 unlock exclusive} \ -] -proc lock_callback {method filename handle lock} { - if {$lock == "1 7 lock exclusive"} { return SQLITE_BUSY } - return SQLITE_OK -} -puts "# Warning: This next test case causes SQLite to call xSleep(1) 100 times." -puts "# Normally this equates to a 100ms delay, but if SQLite is built on unix" -puts "# without HAVE_USLEEP defined, it may be 100 seconds." -do_test wal3-4.3 { - db close - set ::locks [list] - sqlite3 db test.db -vfs T - catchsql { SELECT * FROM x } -} {1 {locking protocol}} - -puts "# Warning: Same again!" -proc lock_callback {method filename handle lock} { - if {$lock == "0 1 lock exclusive"} { return SQLITE_BUSY } - return SQLITE_OK -} -do_test wal3-4.4 { - db close - set ::locks [list] - sqlite3 db test.db -vfs T - catchsql { SELECT * FROM x } -} {1 {locking protocol}} -db close -T delete - #------------------------------------------------------------------------- # Only one client may run recovery at a time. Test this mechanism. @@ -617,86 +556,6 @@ db close db2 close T delete -#------------------------------------------------------------------------- -# -do_test wal3-8.1 { - forcedelete test.db test.db-journal test.db wal - sqlite3 db test.db - sqlite3 db2 test.db - execsql { - PRAGMA auto_vacuum = off; - PRAGMA journal_mode = WAL; - CREATE TABLE b(c); - INSERT INTO b VALUES('Tehran'); - INSERT INTO b VALUES('Qom'); - INSERT INTO b VALUES('Markazi'); - PRAGMA wal_checkpoint; - } -} {wal 0 5 5} -do_test wal3-8.2 { - execsql { SELECT * FROM b } -} {Tehran Qom Markazi} -do_test wal3-8.3 { - db eval { SELECT * FROM b } { - db eval { INSERT INTO b VALUES('Qazvin') } - set r [db2 eval { SELECT * FROM b }] - break - } - set r -} {Tehran Qom Markazi Qazvin} -do_test wal3-8.4 { - execsql { - INSERT INTO b VALUES('Gilan'); - INSERT INTO b VALUES('Ardabil'); - } -} {} -db2 close - -faultsim_save_and_close -testvfs T -default 1 -faultsim_restore_and_reopen -T filter xShmLock -T script lock_callback - -proc lock_callback {method file handle spec} { - if {$spec == "1 7 unlock exclusive"} { - T filter {} - set ::r [catchsql { SELECT * FROM b } db2] - } -} -sqlite3 db test.db -sqlite3 db2 test.db -do_test wal3-8.5 { - execsql { SELECT * FROM b } -} {Tehran Qom Markazi Qazvin Gilan Ardabil} -do_test wal3-8.6 { - set ::r -} {1 {locking protocol}} - -db close -db2 close - -faultsim_restore_and_reopen -sqlite3 db2 test.db -T filter xShmLock -T script lock_callback -proc lock_callback {method file handle spec} { - if {$spec == "1 7 unlock exclusive"} { - T filter {} - set ::r [catchsql { SELECT * FROM b } db2] - } -} -unset ::r -do_test wal3-8.5 { - execsql { SELECT * FROM b } -} {Tehran Qom Markazi Qazvin Gilan Ardabil} -do_test wal3-8.6 { - set ::r -} {1 {locking protocol}} - -db close -db2 close -T delete #------------------------------------------------------------------------- # When a connection opens a read-lock on the database, it searches for diff --git a/test/walcksum.test b/test/walcksum.test index 3005a758ac..f3fc427115 100644 --- a/test/walcksum.test +++ b/test/walcksum.test @@ -334,59 +334,5 @@ do_test walcksum-2.1 { catch { db close } catch { db2 close } -#------------------------------------------------------------------------- -# Test case walcksum-3.* tests that the checksum calculation detects single -# byte changes to frame or frame-header data and considers the frame -# invalid as a result. -# -do_test walcksum-3.1 { - forcedelete test.db test.db-wal test.db-journal - sqlite3 db test.db - - execsql { - PRAGMA synchronous = NORMAL; - PRAGMA page_size = 1024; - CREATE TABLE t1(a, b); - INSERT INTO t1 VALUES(1, randomblob(300)); - INSERT INTO t1 VALUES(2, randomblob(300)); - PRAGMA journal_mode = WAL; - INSERT INTO t1 VALUES(3, randomblob(300)); - } - - file size test.db-wal -} [wal_file_size 1 1024] -do_test walcksum-3.2 { - forcecopy test.db-wal test2.db-wal - forcecopy test.db test2.db - sqlite3 db2 test2.db - execsql { SELECT a FROM t1 } db2 -} {1 2 3} -db2 close -forcecopy test.db test2.db - - -foreach incr {1 2 3 20 40 60 80 100 120 140 160 180 200 220 240 253 254 255} { - do_test walcksum-3.3.$incr { - set FAIL 0 - for {set iOff 0} {$iOff < [wal_file_size 1 1024]} {incr iOff} { - - forcecopy test.db-wal test2.db-wal - set fd [open test2.db-wal r+] - fconfigure $fd -encoding binary - fconfigure $fd -translation binary - - seek $fd $iOff - binary scan [read $fd 1] c x - seek $fd $iOff - puts -nonewline $fd [binary format c [expr {($x+$incr)&0xFF}]] - close $fd - - sqlite3 db2 test2.db - if { [execsql { SELECT a FROM t1 } db2] != "1 2" } {set FAIL 1} - db2 close - } - set FAIL - } {0} -} finish_test diff --git a/test/walprotocol.test b/test/walprotocol.test new file mode 100644 index 0000000000..d658de9d7c --- /dev/null +++ b/test/walprotocol.test @@ -0,0 +1,177 @@ +# 2016 February 4 +# +# 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. The +# focus of this file is testing the operation of the library in +# "PRAGMA journal_mode=WAL" mode. +# +# More specifically, it tests "locking protocol" errors - errors that +# may be caused if one or more SQLite clients does not follow the expected +# locking protocol when accessing a wal-mode database. These tests take +# quite a while to run. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/lock_common.tcl +source $testdir/wal_common.tcl +ifcapable !wal {finish_test ; return } + +set testprefix walprotocol + +#------------------------------------------------------------------------- +# When recovering the contents of a WAL file, a process obtains the WRITER +# lock, then locks all other bytes before commencing recovery. If it fails +# to lock all other bytes (because some other process is holding a read +# lock) it should retry up to 100 times. Then return SQLITE_PROTOCOL to the +# caller. Test this (test case 1.3). +# +# Also test the effect of hitting an SQLITE_BUSY while attempting to obtain +# the WRITER lock (should be the same). Test case 1.4. +# +do_execsql_test 1.0 { + PRAGMA journal_mode = wal; + CREATE TABLE x(y); + INSERT INTO x VALUES('z'); +} {wal} + +proc lock_callback {method filename handle lock} { + lappend ::locks $lock +} +do_test 1.1 { + testvfs T + T filter xShmLock + T script lock_callback + set ::locks [list] + sqlite3 db test.db -vfs T + execsql { SELECT * FROM x } + lrange $::locks 0 3 +} [list {0 1 lock exclusive} {1 7 lock exclusive} \ + {1 7 unlock exclusive} {0 1 unlock exclusive} \ +] +do_test 1.2 { + db close + set ::locks [list] + sqlite3 db test.db -vfs T + execsql { SELECT * FROM x } + lrange $::locks 0 3 +} [list {0 1 lock exclusive} {1 7 lock exclusive} \ + {1 7 unlock exclusive} {0 1 unlock exclusive} \ +] +proc lock_callback {method filename handle lock} { + if {$lock == "1 7 lock exclusive"} { return SQLITE_BUSY } + return SQLITE_OK +} +puts "# Warning: This next test case causes SQLite to call xSlee(1) 100 times." +puts "# Normally this equates to a delay of roughly 10 seconds, but if SQLite" +puts "# is built on unix without HAVE_USLEEP defined, it may be much longer." +do_test 1.3 { + db close + set ::locks [list] + sqlite3 db test.db -vfs T + catchsql { SELECT * FROM x } +} {1 {locking protocol}} + +puts "# Warning: Same again!" +proc lock_callback {method filename handle lock} { + if {$lock == "0 1 lock exclusive"} { return SQLITE_BUSY } + return SQLITE_OK +} +do_test 1.4 { + db close + set ::locks [list] + sqlite3 db test.db -vfs T + catchsql { SELECT * FROM x } +} {1 {locking protocol}} +db close +T delete + +#------------------------------------------------------------------------- +# +do_test 2.1 { + forcedelete test.db test.db-journal test.db wal + sqlite3 db test.db + sqlite3 db2 test.db + execsql { + PRAGMA auto_vacuum = off; + PRAGMA journal_mode = WAL; + CREATE TABLE b(c); + INSERT INTO b VALUES('Tehran'); + INSERT INTO b VALUES('Qom'); + INSERT INTO b VALUES('Markazi'); + PRAGMA wal_checkpoint; + } +} {wal 0 5 5} +do_test 2.2 { + execsql { SELECT * FROM b } +} {Tehran Qom Markazi} +do_test 2.3 { + db eval { SELECT * FROM b } { + db eval { INSERT INTO b VALUES('Qazvin') } + set r [db2 eval { SELECT * FROM b }] + break + } + set r +} {Tehran Qom Markazi Qazvin} +do_test 2.4 { + execsql { + INSERT INTO b VALUES('Gilan'); + INSERT INTO b VALUES('Ardabil'); + } +} {} +db2 close + +faultsim_save_and_close +testvfs T -default 1 +faultsim_restore_and_reopen +T filter xShmLock +T script lock_callback + +proc lock_callback {method file handle spec} { + if {$spec == "1 7 unlock exclusive"} { + T filter {} + set ::r [catchsql { SELECT * FROM b } db2] + } +} +sqlite3 db test.db +sqlite3 db2 test.db +do_test 2.5 { + execsql { SELECT * FROM b } +} {Tehran Qom Markazi Qazvin Gilan Ardabil} +do_test 2.6 { + set ::r +} {1 {locking protocol}} + +db close +db2 close + +faultsim_restore_and_reopen +sqlite3 db2 test.db +T filter xShmLock +T script lock_callback +proc lock_callback {method file handle spec} { + if {$spec == "1 7 unlock exclusive"} { + T filter {} + set ::r [catchsql { SELECT * FROM b } db2] + } +} +unset ::r +do_test 2.7 { + execsql { SELECT * FROM b } +} {Tehran Qom Markazi Qazvin Gilan Ardabil} +do_test 2.8 { + set ::r +} {1 {locking protocol}} + +db close +db2 close +T delete + +finish_test diff --git a/test/walslow.test b/test/walslow.test index 83f292281a..2a52a225d8 100644 --- a/test/walslow.test +++ b/test/walslow.test @@ -16,9 +16,13 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +source $testdir/wal_common.tcl +source $testdir/lock_common.tcl ifcapable !wal {finish_test ; return } +set testprefix walslow + proc reopen_db {} { catch { db close } forcedelete test.db test.db-wal @@ -69,5 +73,159 @@ for {set seed 1} {$seed<10} {incr seed} { } } +#------------------------------------------------------------------------- +# Test case walslow-3.* tests that the checksum calculation detects single +# byte changes to frame or frame-header data and considers the frame +# invalid as a result. +# +reset_db +do_test 3.1 { + + execsql { + PRAGMA synchronous = NORMAL; + PRAGMA page_size = 1024; + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(1, randomblob(300)); + INSERT INTO t1 VALUES(2, randomblob(300)); + PRAGMA journal_mode = WAL; + INSERT INTO t1 VALUES(3, randomblob(300)); + } + + file size test.db-wal +} [wal_file_size 1 1024] +do_test 3.2 { + forcecopy test.db-wal test2.db-wal + forcecopy test.db test2.db + sqlite3 db2 test2.db + execsql { SELECT a FROM t1 } db2 +} {1 2 3} +db2 close +forcecopy test.db test2.db + +foreach incr {1 2 3 20 40 60 80 100 120 140 160 180 200 220 240 253 254 255} { + do_test 3.3.$incr { + set FAIL 0 + for {set iOff 0} {$iOff < [wal_file_size 1 1024]} {incr iOff} { + + forcecopy test.db-wal test2.db-wal + set fd [open test2.db-wal r+] + fconfigure $fd -encoding binary + fconfigure $fd -translation binary + + seek $fd $iOff + binary scan [read $fd 1] c x + seek $fd $iOff + puts -nonewline $fd [binary format c [expr {($x+$incr)&0xFF}]] + close $fd + + sqlite3 db2 test2.db + if { [execsql { SELECT a FROM t1 } db2] != "1 2" } {set FAIL 1} + db2 close + } + set FAIL + } {0} +} + + +#------------------------------------------------------------------------- +# Test large log summaries. +# +# In this case "large" usually means a log file that requires a wal-index +# mapping larger than 64KB (the default initial allocation). A 64KB wal-index +# is large enough for a log file that contains approximately 13100 frames. +# So the following tests create logs containing at least this many frames. +# +# 4.1.*: This test case creates a very large log file within the +# file-system (around 200MB). The log file does not contain +# any valid frames. Test that the database file can still be +# opened and queried, and that the invalid log file causes no +# problems. +# +# 4.2.*: Test that a process may create a large log file and query +# the database (including the log file that it itself created). +# +# 4.3.*: Test that if a very large log file is created, and then a +# second connection is opened on the database file, it is possible +# to query the database (and the very large log) using the +# second connection. +# +# 4.4.*: Same test as wal-13.3.*. Except in this case the second +# connection is opened by an external process. +# +set ::blobcnt 0 +proc blob {nByte} { + incr ::blobcnt + return [string range [string repeat "${::blobcnt}x" $nByte] 1 $nByte] +} + +reset_db +do_execsql_test 4.1 { + PRAGMA journal_mode = wal; + CREATE TABLE t1(x, y); + INSERT INTO "t1" VALUES('A',0); + CREATE TABLE t2(x, y); + INSERT INTO "t2" VALUES('B',2); +} {wal} +db close + +do_test 4.1.1 { + list [file exists test.db] [file exists test.db-wal] +} {1 0} +do_test 4.1.2 { + set fd [open test.db-wal w] + seek $fd [expr 200*1024*1024] + puts $fd "" + close $fd + sqlite3 db test.db + execsql { SELECT * FROM t2 } +} {B 2} +do_test 4.1.3 { + db close + file exists test.db-wal +} {0} + +do_test 4.2.1 { + sqlite3 db test.db + execsql { SELECT count(*) FROM t2 } +} {1} +do_test 4.2.2 { + db function blob blob + for {set i 0} {$i < 16} {incr i} { + execsql { INSERT INTO t2 SELECT blob(400), blob(400) FROM t2 } + } + execsql { SELECT count(*) FROM t2 } +} [expr int(pow(2, 16))] +do_test 4.2.3 { + expr [file size test.db-wal] > [wal_file_size 33000 1024] +} 1 + +do_multiclient_test tn { + incr tn 2 + + do_test 4.$tn.0 { + sql1 { + PRAGMA journal_mode = WAL; + CREATE TABLE t1(x); + INSERT INTO t1 SELECT randomblob(800); + } + sql1 { SELECT count(*) FROM t1 } + } {1} + + for {set ii 1} {$ii<16} {incr ii} { + do_test 4.$tn.$ii.a { + sql2 { INSERT INTO t1 SELECT randomblob(800) FROM t1 } + sql2 { SELECT count(*) FROM t1 } + } [expr (1<<$ii)] + do_test 4.$tn.$ii.b { + sql1 { SELECT count(*) FROM t1 } + } [expr (1<<$ii)] + do_test 4.$tn.$ii.c { + sql1 { SELECT count(*) FROM t1 } + } [expr (1<<$ii)] + do_test 4.$tn.$ii.d { + sql1 { PRAGMA integrity_check } + } {ok} + } +} finish_test diff --git a/test/where8m.test b/test/wherefault.test similarity index 84% rename from test/where8m.test rename to test/wherefault.test index 4fce3db7c3..60330a92dd 100644 --- a/test/where8m.test +++ b/test/wherefault.test @@ -9,17 +9,19 @@ # #*********************************************************************** # This file implements regression tests for SQLite library. The focus -# is testing of where.c. More specifically, the focus is the optimization -# of WHERE clauses that feature the OR operator. +# is testing of where.c. More specifically, the focus is on handling OOM +# errors within the code that optimizes WHERE clauses that feature the +# OR operator. # -# $Id: where8m.test,v 1.3 2009/06/05 17:09:12 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl -do_malloc_test where8m-1 -sqlprep { +set testprefix wherefault + +do_malloc_test 1 -sqlprep { CREATE TABLE t1(a, b, c); CREATE INDEX i1 ON t1(a); CREATE INDEX i2 ON t1(b); @@ -37,7 +39,7 @@ do_malloc_test where8m-1 -sqlprep { a BETWEEN 1 AND 3 AND b < 5 AND b > 2 AND c = 4; } -do_malloc_test where8m-2 -tclprep { +do_malloc_test 2 -tclprep { db eval { BEGIN; CREATE TABLE t1(a, b, c); From 4786cf5a20ded9637e487a9dd93ea104c8fb46ef Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 4 Feb 2016 19:45:19 +0000 Subject: [PATCH 219/570] Further improve performance of unindexed fts5 prefix queries. FossilOrigin-Name: c9c6457d8ea911f6cc63967127e58da3146fd3ef --- ext/fts5/fts5_index.c | 138 ++++++++++++++++++++++++------------------ manifest | 16 ++--- manifest.uuid | 2 +- 3 files changed, 87 insertions(+), 69 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 1a8cc63dad..0461f3a778 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -4705,76 +4705,94 @@ static void fts5MergePrefixLists( Fts5Buffer *p2 /* Second list to merge */ ){ if( p2->n ){ - i64 iLastRowid = 0; - Fts5DoclistIter i1; - Fts5DoclistIter i2; - Fts5Buffer out; - Fts5Buffer tmp; - memset(&out, 0, sizeof(out)); - memset(&tmp, 0, sizeof(tmp)); + if( p1->n==0 ){ + fts5BufferSwap(p1, p2); + }else{ + i64 iLastRowid = 0; + Fts5DoclistIter i1; + Fts5DoclistIter i2; + Fts5Buffer out = {0, 0, 0}; + Fts5Buffer tmp = {0, 0, 0}; - sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n); - fts5DoclistIterInit(p1, &i1); - fts5DoclistIterInit(p2, &i2); - while( p->rc==SQLITE_OK && (i1.aPoslist!=0 || i2.aPoslist!=0) ){ - if( i2.aPoslist==0 || (i1.aPoslist && i1.iRowidrc, &out, p1->n + p2->n) ) return; + fts5DoclistIterInit(p1, &i1); + fts5DoclistIterInit(p2, &i2); - Fts5PoslistWriter writer; - memset(&writer, 0, sizeof(writer)); + while( 1 ){ - /* Merge the two position lists. */ - fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); - fts5BufferZero(&tmp); + if( i1.iRowidrc==SQLITE_OK && (iPos1>=0 || iPos2>=0) ){ - i64 iNew; - if( iPos2<0 || (iPos1>=0 && iPos1=0 || iPos2>=0 ){ + i64 iNew; + if( iPos2<0 || (iPos1>=0 && iPos1rc = sqlite3Fts5PoslistWriterAppend(&tmp, &writer, iNew); + if( p->rc ) goto error_out; } } - if( iNew!=writer.iPrev || tmp.n==0 ){ - p->rc = sqlite3Fts5PoslistWriterAppend(&tmp, &writer, iNew); - } + + /* WRITEPOSLISTSIZE */ + fts5BufferSafeAppendVarint(&out, tmp.n * 2); + fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); + fts5DoclistIterNext(&i1); + fts5DoclistIterNext(&i2); + if( i1.aPoslist==0 || i2.aPoslist==0 ) break; } - - /* WRITEPOSLISTSIZE */ - fts5BufferSafeAppendVarint(&out, tmp.n * 2); - fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); - fts5DoclistIterNext(&i1); - fts5DoclistIterNext(&i2); } - } - fts5BufferSet(&p->rc, p1, out.n, out.p); - fts5BufferFree(&tmp); - fts5BufferFree(&out); + if( i1.aPoslist ){ + fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid); + fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist); + } + else if( i2.aPoslist ){ + fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); + fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist); + } + + error_out: + fts5BufferSet(&p->rc, p1, out.n, out.p); + fts5BufferFree(&tmp); + fts5BufferFree(&out); + } } } diff --git a/manifest b/manifest index 7b935898ba..b4349c77ff 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\srunning\ssome\sparticularly\stime-consuming\stests\sas\spart\sof\sveryquick.test. -D 2016-02-04T17:31:03.368 +C Further\simprove\sperformance\sof\sunindexed\sfts5\sprefix\squeries. +D 2016-02-04T19:45:19.673 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c f6e0c6018ffc8e39fc0b333b5daa8b8d528ae6e4 F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 F ext/fts5/fts5_expr.c ff5c451a6d025909639ac0f0d0af0cc595b50feb F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c e634a4a05b066f7122db93558c871148bd9893f2 +F ext/fts5/fts5_index.c 614c54544f844387ba6728c613a884a1aa151f06 F ext/fts5/fts5_main.c 7e8a5f27d504bc04e3de7f1cba8867f0332aee9d F ext/fts5/fts5_storage.c 2a1f44deae090cd711f02cec0c2af8e660360d24 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -980,7 +980,7 @@ F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0 F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7 F test/savepoint7.test db3db281486c925095f305aad09fe806e5188ff3 -F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2 w test/savepoint3.test +F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2 F test/scanstatus.test 5253c219e331318a437f436268e0e82345700285 F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481 F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5 @@ -1345,7 +1345,7 @@ F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622 F test/whereJ.test 55a3221706a7ab706293f17cc8f96da563bf0767 F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b -F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864 w test/where8m.test +F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864 F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c @@ -1426,7 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b787165b25a240fd5b4a5c7f73b395f30213a1d7 -R 2d9511ba502b30b0a28170783af34756 +P f465944b75a800ddc6920229ad32c2f39ff91e19 +R 50521888ffcbf123db65487e5572aad3 U dan -Z 9311e6c3b97d9e579dd5eb1512f82842 +Z 7367047abd1bd45b9cf9859d0571d183 diff --git a/manifest.uuid b/manifest.uuid index 81e89adc73..960087b4e6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f465944b75a800ddc6920229ad32c2f39ff91e19 \ No newline at end of file +c9c6457d8ea911f6cc63967127e58da3146fd3ef \ No newline at end of file From e514f651d0fb5364e6495b9d6c4dd80ca51a227f Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 4 Feb 2016 19:50:33 +0000 Subject: [PATCH 220/570] Temporarily back out the 0.5% performance improvement from check-in [632071bac5ff32]. Need a more elaborate solution that works with reentrant virtual tables and SQL functions. FossilOrigin-Name: 42736fb0adc82a0fb692850ff3dd3f9b501cbf1f --- manifest | 15 ++++++++------- manifest.uuid | 2 +- src/vdbe.c | 7 +++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index b4349c77ff..7d7eb20c87 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\simprove\sperformance\sof\sunindexed\sfts5\sprefix\squeries. -D 2016-02-04T19:45:19.673 +C Temporarily\sback\sout\sthe\s0.5%\sperformance\simprovement\sfrom\ncheck-in\s[632071bac5ff32].\s\sNeed\sa\smore\selaborate\ssolution\sthat\sworks\nwith\sreentrant\svirtual\stables\sand\sSQL\sfunctions. +D 2016-02-04T19:50:33.284 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -413,7 +413,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c f0c2e2fb8cbff761ea8602058406c151b9325e8d +F src/vdbe.c 16ca0c1e2975fac04c3ea5c62b34dc24b13fea13 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 F src/vdbeapi.c 9d640d5efd9a140a6bda8da53b220aa258167993 @@ -1426,7 +1426,8 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f465944b75a800ddc6920229ad32c2f39ff91e19 -R 50521888ffcbf123db65487e5572aad3 -U dan -Z 7367047abd1bd45b9cf9859d0571d183 +P c9c6457d8ea911f6cc63967127e58da3146fd3ef +Q -632071bac5ff324a74cec9bdbba2deb60c0945e9 +R c2fbdbab2e50abda4a6e36464c2e90a7 +U drh +Z d787da74a7d8bd75c2afcf5547eaa172 diff --git a/manifest.uuid b/manifest.uuid index 960087b4e6..902f64f567 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c9c6457d8ea911f6cc63967127e58da3146fd3ef \ No newline at end of file +42736fb0adc82a0fb692850ff3dd3f9b501cbf1f \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index fd90d3b0de..62ad86d4f3 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -629,6 +629,7 @@ int sqlite3VdbeExec( #endif for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){ assert( pOp>=aOp && pOp<&aOp[p->nOp]); + if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE start = sqlite3Hwtime(); #endif @@ -753,16 +754,14 @@ jump_to_p2_and_check_for_interrupt: /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon ** completion. Check to see if sqlite3_interrupt() has been called - ** or if the progress callback needs to be invoked. Also check for - ** OOM conditions and abort if seen. + ** or if the progress callback needs to be invoked. ** ** This code uses unstructured "goto" statements and does not look clean. ** But that is not due to sloppy coding habits. The code is written this ** way for performance, to avoid having to run the interrupt and progress - ** checks on every opcode. This helps sqlite3_step() to run over 2.0% + ** checks on every opcode. This helps sqlite3_step() to run about 1.5% ** faster according to "valgrind --tool=cachegrind" */ check_for_interrupt: - if( db->mallocFailed ) goto no_mem; if( db->u1.isInterrupted ) goto abort_due_to_interrupt; #ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* Call the progress callback if it is configured and the required number From 4a642b60607e55a2c25f663b472af3609c76b214 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 5 Feb 2016 01:55:27 +0000 Subject: [PATCH 221/570] Improvements to the way that OOM errors are processed. FossilOrigin-Name: c3ef03478a5788c855b3aef385d43ae7f494f440 --- ext/misc/json1.c | 6 ++--- manifest | 70 +++++++++++++++++++++++++----------------------- manifest.uuid | 2 +- src/alter.c | 2 +- src/analyze.c | 13 +++++---- src/attach.c | 4 +-- src/build.c | 21 +++++++-------- src/callback.c | 4 +-- src/expr.c | 5 +++- src/fkey.c | 6 ++--- src/func.c | 2 +- src/insert.c | 4 +-- src/legacy.c | 2 +- src/main.c | 8 +++--- src/malloc.c | 51 ++++++++++++++++++++++++++++------- src/parse.y | 13 +++++++-- src/pragma.c | 2 +- src/prepare.c | 18 +++++++------ src/printf.c | 2 +- src/select.c | 9 ++++--- src/sqliteInt.h | 6 ++++- src/tokenize.c | 7 +---- src/trigger.c | 2 +- src/vdbe.c | 7 +++-- src/vdbeapi.c | 4 +-- src/vdbeaux.c | 8 +++--- src/vdbemem.c | 2 +- src/vtab.c | 8 +++--- src/where.c | 2 +- src/whereexpr.c | 1 - 30 files changed, 166 insertions(+), 125 deletions(-) diff --git a/ext/misc/json1.c b/ext/misc/json1.c index e4ea4fb9f0..3c63b6e946 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -343,7 +343,7 @@ static void jsonAppendValue( default: { if( p->bErr==0 ){ sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); - p->bErr = 1; + p->bErr = 2; jsonReset(p); } break; @@ -1571,7 +1571,7 @@ static void jsonArrayFinal(sqlite3_context *ctx){ pStr->pCtx = ctx; jsonAppendChar(pStr, ']'); if( pStr->bErr ){ - sqlite3_result_error_nomem(ctx); + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); assert( pStr->bStatic ); }else{ sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, @@ -1619,7 +1619,7 @@ static void jsonObjectFinal(sqlite3_context *ctx){ if( pStr ){ jsonAppendChar(pStr, '}'); if( pStr->bErr ){ - sqlite3_result_error_nomem(ctx); + if( pStr->bErr==0 ) sqlite3_result_error_nomem(ctx); assert( pStr->bStatic ); }else{ sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, diff --git a/manifest b/manifest index 7d7eb20c87..d515b0a7f1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Temporarily\sback\sout\sthe\s0.5%\sperformance\simprovement\sfrom\ncheck-in\s[632071bac5ff32].\s\sNeed\sa\smore\selaborate\ssolution\sthat\sworks\nwith\sreentrant\svirtual\stables\sand\sSQL\sfunctions. -D 2016-02-04T19:50:33.284 +C Improvements\sto\sthe\sway\sthat\sOOM\serrors\sare\sprocessed. +D 2016-02-05T01:55:27.277 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -206,7 +206,7 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2 F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c -F ext/misc/json1.c 8698ea0ce24bda23bd8ad4a124620d758f92760b +F ext/misc/json1.c a27cf1eca6583f9b6e18abab5c2a9a82c4540ca9 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc @@ -284,9 +284,9 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c b6e0befc17d69b59c66f4b8a126c05b1ee7ef10a -F src/analyze.c 0043d3e501f04297fed2bb50b488bc08d5c39f36 -F src/attach.c 27743a694df17ca468eee3956126a5d28d2a29ea +F src/alter.c e4a5132e6264e002ab87c268108f416df3f1fb10 +F src/analyze.c 5338dbbc9f12087b38d74234de00907bdf023a92 +F src/attach.c b943546856ac657c702e1a92fb7adcf67c1dc397 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf @@ -294,27 +294,27 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 0b359bcc2316a57acf12f583253974ad22b4654f F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 88ee370118ff7f081f2060ad3fb6c170f9aed7d3 -F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261 +F src/build.c dcb55142c4c4293cbec181ef1ae1485ce0bc94d6 +F src/callback.c ed6c2a4a712eb7287ff64e20e3c23265dfb8a7ce F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 997651e3ee6c2818fbf7fcdb7156cef9eb3ece20 F src/dbstat.c b2ec6793eef97aebb4d171d490a4ffdfa9f2475c F src/delete.c 33ed87dc0746b1f8ce186f62b608bf40801af9c0 -F src/expr.c d10c1cdef5810cdbf73adc9f9b383684230b360a +F src/expr.c fddb1b19d77730d423ef2c219ae17e10087554ba F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c c66d3e5b35d4d95b5c1e2ee6c12f5df13a7f9ad6 -F src/func.c 42b24923328f65849f52f1659efb2a0907ad78fd +F src/fkey.c dc893ee37a21868fcf07e3d941c7663957807ad2 +F src/func.c 86e55fee35b9577e485f47d9dd5c1d34cd513288 F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 3e2462294fc8bc6e46f377ec824ff315e79fc36d +F src/insert.c e3e2811c69318ff62d8a764b01f5a5677d846b1e F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d -F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e +F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b -F src/main.c b686dabe9a7ece9121da87120d5c7bf402d77eb3 -F src/malloc.c b67c26c359c13836d370350b3f43d228dff5b360 +F src/main.c 62b7fe3ed245757d1ff2e6268a7ec0bc30100308 +F src/malloc.c 65168ef91884206bf3fa14a3070e79255561324b F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 @@ -337,23 +337,23 @@ F src/os_win.c ccf29ddded3e41e506b6bd98c1171aa0963b23f2 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 67cd2fbab58d0e35fed5f81432856f4f0af9fc6d F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 -F src/parse.y 426a91fbbbf7cdde3fd4b8798de7317a8782bec5 +F src/parse.y d7bff41d460f2df96fb890f36700e85cb0fc5634 F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23 F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 -F src/pragma.c 3c4f3fadf05893e289f2adf3a20c671a842cadec +F src/pragma.c 80ee77226d0008d9188356a6cbbe6010866e1bee F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c -F src/prepare.c db85f0451ba93ecb3c1e497c279abece5cb5aead -F src/printf.c 98a5cef7fc84577ab8a3098cfa48ecfa5a70b9f8 +F src/prepare.c db4ce553dd1f03909a01858a760fa293e0f32ca0 +F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c ea6f3b0c279aa37eb3701792d094673a7ad1bf88 +F src/select.c 07178f2ae1239404874492ba7e3b9a46361ebbbc F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h bf8c17fb55d7cd09b477111212b19d661b134989 +F src/sqliteInt.h e251b755c71c343434bce1e82c6593603c7af364 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -406,31 +406,31 @@ F src/test_windirent.c 8f5fada630348558d5745b334702f301da1ffc61 F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 -F src/tokenize.c 5606871a377f390af7040ec3c12e0d183512d785 +F src/tokenize.c 214b783d6138e9f9fbb6b225ce9a376db3b03d42 F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b -F src/trigger.c 72d876b2d0c66604a112362bdae07dae9b104816 +F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 16ca0c1e2975fac04c3ea5c62b34dc24b13fea13 +F src/vdbe.c 2e49c5d1b8f2f24f91ddd6c6b003d8e7fbbc4e56 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 -F src/vdbeapi.c 9d640d5efd9a140a6bda8da53b220aa258167993 -F src/vdbeaux.c 23b38b447ebf5991de1d3d456003c58cf523a5da +F src/vdbeapi.c 9324f6baee1a1b2284c6543e98f916888a81e459 +F src/vdbeaux.c 0e66330ac8ad473bdefde88278725202d0174ae5 F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db -F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 +F src/vdbemem.c 9a6736339ca581f3b9503d5a1a40b7d718ca4635 F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 -F src/vtab.c 320682cca733115b4cbe71320b5c5eeb1074ebde +F src/vtab.c 2cc0b7bb253851c8718b8850dfaed8592b6dc7f8 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c d21b99fd1458159d0b1ecdccc8ee6ada4fdc4c54 F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c af9bf5dcec1a0e52726c550924aa91d837166251 +F src/where.c 8bdb43e09d4e7f20bb371154799da39c25b51dfd F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a F src/wherecode.c 791a784bbf8749d560fdb0b990b607bc4f44a38d -F src/whereexpr.c 197a448b52073aee43eca3a2233fc113369eb2d4 +F src/whereexpr.c 85ee2de9ff0fe40a4afaf2a477bd6c9a808548b3 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1426,8 +1426,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c9c6457d8ea911f6cc63967127e58da3146fd3ef -Q -632071bac5ff324a74cec9bdbba2deb60c0945e9 -R c2fbdbab2e50abda4a6e36464c2e90a7 +P 42736fb0adc82a0fb692850ff3dd3f9b501cbf1f +R 1d34f5ef33e19e0d2d7f06ad149ac201 +T *branch * oom-handling +T *sym-oom-handling * +T -sym-trunk * U drh -Z d787da74a7d8bd75c2afcf5547eaa172 +Z a95dbad943095aee523b449d4529a303 diff --git a/manifest.uuid b/manifest.uuid index 902f64f567..a42eab21cd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -42736fb0adc82a0fb692850ff3dd3f9b501cbf1f \ No newline at end of file +c3ef03478a5788c855b3aef385d43ae7f494f440 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 16b7a9e192..3419059fa2 100644 --- a/src/alter.c +++ b/src/alter.c @@ -695,7 +695,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal); assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); if( rc!=SQLITE_OK ){ - db->mallocFailed = 1; + assert( db->mallocFailed = 1 ); return; } if( !pVal ){ diff --git a/src/analyze.c b/src/analyze.c index 4d777fa9f5..7a7d68f59a 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1523,7 +1523,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){ ** the old data with the new instead of allocating a new array. */ if( pIndex->aiRowEst==0 ){ pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol); - if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1; + if( pIndex->aiRowEst==0 ) sqlite3OomFault(pInfo->db); } aiRowEst = pIndex->aiRowEst; #endif @@ -1670,7 +1670,7 @@ static int loadStatTbl( Index *pPrevIdx = 0; /* Previous index in the loop */ IndexSample *pSample; /* A slot in pIdx->aSample[] */ - assert( db->lookaside.bEnabled==0 ); + assert( db->lookaside.bDisable ); zSql = sqlite3MPrintf(db, zSql1, zDb); if( !zSql ){ return SQLITE_NOMEM; @@ -1784,7 +1784,7 @@ static int loadStatTbl( static int loadStat4(sqlite3 *db, const char *zDb){ int rc = SQLITE_OK; /* Result codes from subroutines */ - assert( db->lookaside.bEnabled==0 ); + assert( db->lookaside.bDisable ); if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){ rc = loadStatTbl(db, 0, "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", @@ -1866,10 +1866,9 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ /* Load the statistics from the sqlite_stat4 table. */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ - int lookasideEnabled = db->lookaside.bEnabled; - db->lookaside.bEnabled = 0; + db->lookaside.bDisable++; rc = loadStat4(db, sInfo.zDatabase); - db->lookaside.bEnabled = lookasideEnabled; + db->lookaside.bDisable--; } for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); @@ -1879,7 +1878,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ #endif if( rc==SQLITE_NOMEM ){ - db->mallocFailed = 1; + sqlite3OomFault(db); } return rc; } diff --git a/src/attach.c b/src/attach.c index 12d3ac3ff6..e167951f68 100644 --- a/src/attach.c +++ b/src/attach.c @@ -127,7 +127,7 @@ static void attachFunc( flags = db->openFlags; rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; + if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); sqlite3_result_error(context, zErr, -1); sqlite3_free(zErr); return; @@ -230,7 +230,7 @@ static void attachFunc( sqlite3ResetAllSchemasOfConnection(db); db->nDb = iDb; if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - db->mallocFailed = 1; + sqlite3OomFault(db); sqlite3DbFree(db, zErrDyn); zErrDyn = sqlite3MPrintf(db, "out of memory"); }else if( zErrDyn==0 ){ diff --git a/src/build.c b/src/build.c index cea05d51c7..097149fd4f 100644 --- a/src/build.c +++ b/src/build.c @@ -78,7 +78,7 @@ void sqlite3TableLock( p->zName = zName; }else{ pToplevel->nTableLock = 0; - pToplevel->db->mallocFailed = 1; + sqlite3OomFault(pToplevel->db); } } @@ -1555,7 +1555,7 @@ static char *createTableStmt(sqlite3 *db, Table *p){ n += 35 + 6*p->nCol; zStmt = sqlite3DbMallocRaw(0, n); if( zStmt==0 ){ - db->mallocFailed = 1; + sqlite3OomFault(db); return 0; } sqlite3_snprintf(n, zStmt, "CREATE TABLE "); @@ -2038,7 +2038,7 @@ void sqlite3EndTable( pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p); if( pOld ){ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ - db->mallocFailed = 1; + sqlite3OomFault(db); return; } pParse->pNewTable = 0; @@ -2142,7 +2142,6 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ int n; /* Temporarily holds the number of cursors assigned */ sqlite3 *db = pParse->db; /* Database connection for malloc errors */ sqlite3_xauth xAuth; /* Saved xAuth pointer */ - u8 bEnabledLA; /* Saved db->lookaside.bEnabled state */ assert( pTable ); @@ -2188,18 +2187,18 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ ** statement that defines the view. */ assert( pTable->pSelect ); - bEnabledLA = db->lookaside.bEnabled; if( pTable->pCheck ){ - db->lookaside.bEnabled = 0; + db->lookaside.bDisable++; sqlite3ColumnsFromExprList(pParse, pTable->pCheck, &pTable->nCol, &pTable->aCol); + db->lookaside.bDisable--; }else{ pSel = sqlite3SelectDup(db, pTable->pSelect, 0); if( pSel ){ n = pParse->nTab; sqlite3SrcListAssignCursors(pParse, pSel->pSrc); pTable->nCol = -1; - db->lookaside.bEnabled = 0; + db->lookaside.bDisable++; #ifndef SQLITE_OMIT_AUTHORIZATION xAuth = db->xAuth; db->xAuth = 0; @@ -2208,6 +2207,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ #else pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); #endif + db->lookaside.bDisable--; pParse->nTab = n; if( pSelTab ){ assert( pTable->aCol==0 ); @@ -2226,7 +2226,6 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ nErr++; } } - db->lookaside.bEnabled = bEnabledLA; pTable->pSchema->schemaFlags |= DB_UnresetViews; #endif /* SQLITE_OMIT_VIEW */ return nErr; @@ -2692,7 +2691,7 @@ void sqlite3CreateForeignKey( pFKey->zTo, (void *)pFKey ); if( pNextTo==pFKey ){ - db->mallocFailed = 1; + sqlite3OomFault(db); goto fk_end; } if( pNextTo ){ @@ -3274,7 +3273,7 @@ Index *sqlite3CreateIndex( pIndex->zName, pIndex); if( p ){ assert( p==pIndex ); /* Malloc must have failed */ - db->mallocFailed = 1; + sqlite3OomFault(db); goto exit_create_index; } db->flags |= SQLITE_InternChanges; @@ -3992,7 +3991,7 @@ int sqlite3OpenTempDatabase(Parse *pParse){ db->aDb[1].pBt = pBt; assert( db->aDb[1].pSchema ); if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ - db->mallocFailed = 1; + sqlite3OomFault(db); return 1; } } diff --git a/src/callback.c b/src/callback.c index 2a9f5b802a..2b955fdcdb 100644 --- a/src/callback.c +++ b/src/callback.c @@ -177,7 +177,7 @@ static CollSeq *findCollSeqEntry( */ assert( pDel==0 || pDel==pColl ); if( pDel!=0 ){ - db->mallocFailed = 1; + sqlite3OomFault(db); sqlite3DbFree(db, pDel); pColl = 0; } @@ -465,7 +465,7 @@ Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema)); } if( !p ){ - db->mallocFailed = 1; + sqlite3OomFault(db); }else if ( 0==p->file_format ){ sqlite3HashInit(&p->tblHash); sqlite3HashInit(&p->idxHash); diff --git a/src/expr.c b/src/expr.c index c91db2834f..5b134d6661 100644 --- a/src/expr.c +++ b/src/expr.c @@ -699,7 +699,10 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ if( x>pParse->nzVar ){ char **a; a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0])); - if( a==0 ) return; /* Error reported through db->mallocFailed */ + if( a==0 ){ + assert( db->mallocFailed ); /* Error reported through mallocFailed */ + return; + } pParse->azVar = a; memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0])); pParse->nzVar = x; diff --git a/src/fkey.c b/src/fkey.c index 7eb188924d..fae25c4828 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -1165,7 +1165,6 @@ static Trigger *fkActionTrigger( pTrigger = pFKey->apTrigger[iAction]; if( action!=OE_None && !pTrigger ){ - u8 enableLookaside; /* Copy of db->lookaside.bEnabled */ char const *zFrom; /* Name of child table */ int nFrom; /* Length in bytes of zFrom */ Index *pIdx = 0; /* Parent key index for this FK */ @@ -1274,8 +1273,7 @@ static Trigger *fkActionTrigger( } /* Disable lookaside memory allocation */ - enableLookaside = db->lookaside.bEnabled; - db->lookaside.bEnabled = 0; + db->lookaside.bDisable++; pTrigger = (Trigger *)sqlite3DbMallocZero(db, sizeof(Trigger) + /* struct Trigger */ @@ -1297,7 +1295,7 @@ static Trigger *fkActionTrigger( } /* Re-enable the lookaside buffer, if it was disabled earlier. */ - db->lookaside.bEnabled = enableLookaside; + db->lookaside.bDisable--; sqlite3ExprDelete(db, pWhere); sqlite3ExprDelete(db, pWhen); diff --git a/src/func.c b/src/func.c index 982a8c2caa..d615cf90b1 100644 --- a/src/func.c +++ b/src/func.c @@ -1615,7 +1615,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ int rc = sqlite3_overload_function(db, "MATCH", 2); assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); if( rc==SQLITE_NOMEM ){ - db->mallocFailed = 1; + sqlite3OomFault(db); } } diff --git a/src/insert.c b/src/insert.c index 5f36c089f6..a8cde72954 100644 --- a/src/insert.c +++ b/src/insert.c @@ -83,7 +83,7 @@ const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ Table *pTab = pIdx->pTable; pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1); if( !pIdx->zColAff ){ - db->mallocFailed = 1; + sqlite3OomFault(db); return 0; } for(n=0; nnColumn; n++){ @@ -134,7 +134,7 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ sqlite3 *db = sqlite3VdbeDb(v); zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1); if( !zColAff ){ - db->mallocFailed = 1; + sqlite3OomFault(db); return; } diff --git a/src/legacy.c b/src/legacy.c index a10006e558..1b5e518d43 100644 --- a/src/legacy.c +++ b/src/legacy.c @@ -90,7 +90,7 @@ int sqlite3_exec( for(i=0; imallocFailed = 1; + sqlite3OomFault(db); goto exec_out; } } diff --git a/src/main.c b/src/main.c index 63a105c3f0..588461b48a 100644 --- a/src/main.c +++ b/src/main.c @@ -698,12 +698,12 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ p = (LookasideSlot*)&((u8*)p)[sz]; } db->lookaside.pEnd = p; - db->lookaside.bEnabled = 1; + db->lookaside.bDisable = 0; db->lookaside.bMalloced = pBuf==0 ?1:0; }else{ db->lookaside.pStart = db; db->lookaside.pEnd = db; - db->lookaside.bEnabled = 0; + db->lookaside.bDisable = 1; db->lookaside.bMalloced = 0; } #endif /* SQLITE_OMIT_LOOKASIDE */ @@ -2208,7 +2208,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){ ** be cleared before returning. Do this directly, instead of via ** sqlite3ApiExit(), to avoid setting the database handle error message. */ - db->mallocFailed = 0; + sqlite3OomClear(db); } sqlite3_mutex_leave(db->mutex); return z; @@ -2846,7 +2846,7 @@ static int openDatabase( db->openFlags = flags; rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; + if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); sqlite3_free(zErrMsg); goto opendb_out; diff --git a/src/malloc.c b/src/malloc.c index c8a04128cf..057d36a4be 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -608,10 +608,8 @@ void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ #ifndef SQLITE_OMIT_LOOKASIDE if( db ){ LookasideSlot *pBuf; - if( db->mallocFailed ){ - return 0; - } - if( db->lookaside.bEnabled ){ + if( db->lookaside.bDisable==0 ){ + assert( db->mallocFailed==0 ); if( n>db->lookaside.sz ){ db->lookaside.anStat[1]++; }else if( (pBuf = db->lookaside.pFree)==0 ){ @@ -625,7 +623,10 @@ void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ } return (void*)pBuf; } + }else if( db->mallocFailed ){ + return 0; } + } #else if( db && db->mallocFailed ){ @@ -637,10 +638,10 @@ void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){ void *p = sqlite3Malloc(n); if( !p && db ){ - db->mallocFailed = 1; + sqlite3OomFault(db); } sqlite3MemdebugSetType(p, - (db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); + (db && db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); return p; } @@ -671,10 +672,10 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ sqlite3MemdebugSetType(p, MEMTYPE_HEAP); pNew = sqlite3_realloc64(p, n); if( !pNew ){ - db->mallocFailed = 1; + sqlite3OomFault(db); } sqlite3MemdebugSetType(pNew, - (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); + (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); } } return pNew; @@ -736,11 +737,43 @@ void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ *pz = sqlite3DbStrDup(db, zNew); } +/* +** Call this routine to record the fact that an OOM (out-of-memory) error +** has happened. This routine will set db->mallocFailed, and also +** temporarily disable the lookaside memory allocator and interrupt +** any running VDBEs. +*/ +void sqlite3OomFault(sqlite3 *db){ + if( db->mallocFailed==0 && db->bBenignMalloc==0 ){ + db->mallocFailed = 1; + if( db->nVdbeExec>0 ){ + db->u1.isInterrupted = 1; + } + db->lookaside.bDisable++; + } +} + +/* +** This routine reactivates the memory allocator and clears the +** db->mallocFailed flag as necessary. +** +** The memory allocator is not restarted if there are running +** VDBEs. +*/ +void sqlite3OomClear(sqlite3 *db){ + if( db->mallocFailed && db->nVdbeExec==0 ){ + db->mallocFailed = 0; + db->u1.isInterrupted = 0; + assert( db->lookaside.bDisable>0 ); + db->lookaside.bDisable--; + } +} + /* ** Take actions at the end of an API call to indicate an OOM error */ static SQLITE_NOINLINE int apiOomError(sqlite3 *db){ - db->mallocFailed = 0; + sqlite3OomClear(db); sqlite3Error(db, SQLITE_NOMEM); return SQLITE_NOMEM; } diff --git a/src/parse.y b/src/parse.y index 846c2504b7..0bfe4e473a 100644 --- a/src/parse.y +++ b/src/parse.y @@ -106,6 +106,15 @@ struct TrigEvent { int a; IdList * b; }; */ struct AttachKey { int type; Token key; }; +/* +** Disable lookaside memory allocation for objects that might be +** shared across database connections. +*/ +static void disableLookaside(Parse *pParse){ + pParse->disableLookaside++; + pParse->db->lookaside.bDisable++; +} + } // end %include // Input is a single SQL command @@ -156,7 +165,7 @@ create_table ::= createkw temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z). { sqlite3StartTable(pParse,&Y,&Z,T,0,0,E); } createkw(A) ::= CREATE(X). { - pParse->db->lookaside.bEnabled = 0; + disableLookaside(pParse); A = X; } %type ifnotexists {int} @@ -1507,7 +1516,7 @@ cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column(Y). { sqlite3AlterFinishAddColumn(pParse, &Y); } add_column_fullname ::= fullname(X). { - pParse->db->lookaside.bEnabled = 0; + disableLookaside(pParse); sqlite3AlterBeginAddColumn(pParse, X); } kwcolumn_opt ::= . diff --git a/src/pragma.c b/src/pragma.c index bde17d1e86..c34d5421c2 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -478,7 +478,7 @@ void sqlite3Pragma( */ db->nextPagesize = sqlite3Atoi(zRight); if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){ - db->mallocFailed = 1; + sqlite3OomFault(db); } } break; diff --git a/src/prepare.c b/src/prepare.c index f8ad54665a..3fb71a770e 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -32,7 +32,7 @@ static void corruptSchema( if( z && zExtra ) z = sqlite3_mprintf("%z - %s", z, zExtra); sqlite3DbFree(db, *pData->pzErrMsg); *pData->pzErrMsg = z; - if( z==0 ) db->mallocFailed = 1; + if( z==0 ) sqlite3OomFault(db); } pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT_BKPT; } @@ -91,7 +91,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ }else{ pData->rc = rc; if( rc==SQLITE_NOMEM ){ - db->mallocFailed = 1; + sqlite3OomFault(db); }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){ corruptSchema(pData, argv[0], sqlite3_errmsg(db)); } @@ -336,7 +336,7 @@ initone_error_out: error_out: if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - db->mallocFailed = 1; + sqlite3OomFault(db); } return rc; } @@ -434,7 +434,7 @@ static void schemaIsValid(Parse *pParse){ if( !sqlite3BtreeIsInReadTrans(pBt) ){ rc = sqlite3BtreeBeginTrans(pBt, 0); if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - db->mallocFailed = 1; + sqlite3OomFault(db); } if( rc!=SQLITE_OK ) return; openedTransaction = 1; @@ -497,6 +497,11 @@ void sqlite3ParserReset(Parse *pParse){ sqlite3 *db = pParse->db; sqlite3DbFree(db, pParse->aLabel); sqlite3ExprListDelete(db, pParse->pConstExpr); + if( db ){ + assert( db->lookaside.bDisable >= pParse->disableLookaside ); + db->lookaside.bDisable -= pParse->disableLookaside; + } + pParse->disableLookaside = 0; } } @@ -592,9 +597,6 @@ static int sqlite3Prepare( } assert( 0==pParse->nQueryLoop ); - if( db->mallocFailed ){ - pParse->rc = SQLITE_NOMEM; - } if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK; if( pParse->checkSchema ){ schemaIsValid(pParse); @@ -716,7 +718,7 @@ int sqlite3Reprepare(Vdbe *p){ rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0); if( rc ){ if( rc==SQLITE_NOMEM ){ - db->mallocFailed = 1; + sqlite3OomFault(db); } assert( pNew==0 ); return rc; diff --git a/src/printf.c b/src/printf.c index 946161f64c..238997f37d 100644 --- a/src/printf.c +++ b/src/printf.c @@ -929,7 +929,7 @@ char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){ sqlite3VXPrintf(&acc, zFormat, ap); z = sqlite3StrAccumFinish(&acc); if( acc.accError==STRACCUM_NOMEM ){ - db->mallocFailed = 1; + sqlite3OomFault(db); } return z; } diff --git a/src/select.c b/src/select.c index 891b123543..84d5423de6 100644 --- a/src/select.c +++ b/src/select.c @@ -1016,7 +1016,7 @@ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ p->nRef = 1; memset(&p[1], 0, nExtra); }else{ - db->mallocFailed = 1; + sqlite3OomFault(db); } return p; } @@ -1677,7 +1677,7 @@ int sqlite3ColumnsFromExprList( pCol->zName = zName; sqlite3ColumnPropertiesFromName(0, pCol); if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){ - db->mallocFailed = 1; + sqlite3OomFault(db); } } sqlite3HashClear(&ht); @@ -1764,7 +1764,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ } /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside ** is disabled */ - assert( db->lookaside.bEnabled==0 ); + assert( db->lookaside.bDisable ); pTab->nRef = 1; pTab->zName = 0; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); @@ -5562,7 +5562,8 @@ int sqlite3Select( if( flag ){ pMinMax = sqlite3ExprListDup(db, pMinMax, 0); pDel = pMinMax; - if( pMinMax && !db->mallocFailed ){ + assert( db->mallocFailed || pMinMax!=0 ); + if( !db->mallocFailed ){ pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; pMinMax->a[0].pExpr->op = TK_COLUMN; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 16d3ea9921..70f210c0a2 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1094,8 +1094,8 @@ struct Schema { ** lookaside allocations are not used to construct the schema objects. */ struct Lookaside { + u32 bDisable; /* Only operate the lookaside when zero */ u16 sz; /* Size of each buffer in bytes */ - u8 bEnabled; /* False to disable new lookaside allocations */ u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ int nOut; /* Number of buffers currently checked out */ int mxOut; /* Highwater mark for nOut */ @@ -1178,6 +1178,7 @@ struct sqlite3 { u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ + u8 bBenignMalloc; /* Do not require OOMs if true */ u8 dfltLockMode; /* Default locking-mode for attached dbs */ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ u8 suppressErr; /* Do not issue error messages if true */ @@ -2733,6 +2734,7 @@ struct Parse { u8 mayAbort; /* True if statement may throw an ABORT exception */ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ u8 okConstFactor; /* OK to factor out constants */ + u8 disableLookaside; /* Number of times lookaside has been disabled */ int aTempReg[8]; /* Holding area for temporary registers */ int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ @@ -3777,6 +3779,8 @@ int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), FuncDestructor *pDestructor ); +void sqlite3OomFault(sqlite3*); +void sqlite3OomClear(sqlite3*); int sqlite3ApiExit(sqlite3 *db, int); int sqlite3OpenTempDatabase(Parse *); diff --git a/src/tokenize.c b/src/tokenize.c index b85e35dc10..5bee3d5a84 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -390,7 +390,6 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ void *pEngine; /* The LEMON-generated LALR(1) parser */ int tokenType; /* type of the next token */ int lastTokenParsed = -1; /* type of the previous token */ - u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ @@ -406,7 +405,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ /* sqlite3ParserTrace(stdout, "parser: "); */ pEngine = sqlite3ParserAlloc(sqlite3Malloc); if( pEngine==0 ){ - db->mallocFailed = 1; + sqlite3OomFault(db); return SQLITE_NOMEM; } assert( pParse->pNewTable==0 ); @@ -414,8 +413,6 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ assert( pParse->nVar==0 ); assert( pParse->nzVar==0 ); assert( pParse->azVar==0 ); - enableLookaside = db->lookaside.bEnabled; - if( db->lookaside.pStart ) db->lookaside.bEnabled = 1; while( zSql[i]!=0 ){ assert( i>=0 ); pParse->sLastToken.z = &zSql[i]; @@ -428,7 +425,6 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ if( tokenType>=TK_SPACE ){ assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); if( db->u1.isInterrupted ){ - sqlite3ErrorMsg(pParse, "interrupt"); pParse->rc = SQLITE_INTERRUPT; break; } @@ -463,7 +459,6 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ sqlite3_mutex_leave(sqlite3MallocMutex()); #endif /* YYDEBUG */ sqlite3ParserFree(pEngine, sqlite3_free); - db->lookaside.bEnabled = enableLookaside; if( db->mallocFailed ){ pParse->rc = SQLITE_NOMEM; } diff --git a/src/trigger.c b/src/trigger.c index 4bfb55af69..72c31eb2a3 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -323,7 +323,7 @@ void sqlite3FinishTrigger( assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pTrig = sqlite3HashInsert(pHash, zName, pTrig); if( pTrig ){ - db->mallocFailed = 1; + sqlite3OomFault(db); }else if( pLink->pSchema==pLink->pTabSchema ){ Table *pTab; pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table); diff --git a/src/vdbe.c b/src/vdbe.c index 62ad86d4f3..c0eff6a09f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -629,7 +629,6 @@ int sqlite3VdbeExec( #endif for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){ assert( pOp>=aOp && pOp<&aOp[p->nOp]); - if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE start = sqlite3Hwtime(); #endif @@ -6785,7 +6784,7 @@ vdbe_error_halt: sqlite3_log(rc, "statement aborts at %d: [%s] %s", (int)(pOp - aOp), p->zSql, p->zErrMsg); sqlite3VdbeHalt(p); - if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; + if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db); rc = SQLITE_ERROR; if( resetSchemaOnFault>0 ){ sqlite3ResetOneSchema(db, resetSchemaOnFault-1); @@ -6815,7 +6814,7 @@ too_big: /* Jump to here if a malloc() fails. */ no_mem: - db->mallocFailed = 1; + sqlite3OomFault(db); sqlite3VdbeError(p, "out of memory"); rc = SQLITE_NOMEM; goto vdbe_error_halt; @@ -6836,7 +6835,7 @@ abort_due_to_error: */ abort_due_to_interrupt: assert( db->u1.isInterrupted ); - rc = SQLITE_INTERRUPT; + rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_INTERRUPT; p->rc = rc; sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); goto vdbe_error_halt; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 0a15633ddf..fce43630e7 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -473,7 +473,7 @@ void sqlite3_result_error_nomem(sqlite3_context *pCtx){ sqlite3VdbeMemSetNull(pCtx->pOut); pCtx->isError = SQLITE_NOMEM; pCtx->fErrorOrAux = 1; - pCtx->pOut->db->mallocFailed = 1; + sqlite3OomFault(pCtx->pOut->db); } /* @@ -1101,7 +1101,7 @@ static const void *columnName( ** is the case, clear the mallocFailed flag and return NULL. */ if( db->mallocFailed ){ - db->mallocFailed = 0; + sqlite3OomClear(db); ret = 0; } sqlite3_mutex_leave(db->mutex); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 632c1231aa..7d3a8c4293 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1423,7 +1423,6 @@ static void releaseMemArray(Mem *p, int N){ if( p && N ){ Mem *pEnd = &p[N]; sqlite3 *db = p->db; - u8 malloc_failed = db->mallocFailed; if( db->pnBytesFreed ){ do{ if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); @@ -1459,7 +1458,6 @@ static void releaseMemArray(Mem *p, int N){ p->flags = MEM_Undefined; }while( (++p)mallocFailed = malloc_failed; } } @@ -1520,7 +1518,7 @@ int sqlite3VdbeList( if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ - db->mallocFailed = 1; + sqlite3OomFault(db); return SQLITE_ERROR; } @@ -2711,12 +2709,12 @@ int sqlite3VdbeTransferError(Vdbe *p){ sqlite3 *db = p->db; int rc = p->rc; if( p->zErrMsg ){ - u8 mallocFailed = db->mallocFailed; + db->bBenignMalloc++; sqlite3BeginBenignMalloc(); if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db); sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); sqlite3EndBenignMalloc(); - db->mallocFailed = mallocFailed; + db->bBenignMalloc--; db->errCode = rc; }else{ sqlite3Error(db, rc); diff --git a/src/vdbemem.c b/src/vdbemem.c index 0eeb59ef85..974b990747 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -1381,7 +1381,7 @@ static int valueFromExpr( return rc; no_mem: - db->mallocFailed = 1; + sqlite3OomFault(db); sqlite3DbFree(db, zVal); assert( *ppVal==0 ); #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 diff --git a/src/vtab.c b/src/vtab.c index ea79cd8cef..ca444944f4 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -62,7 +62,7 @@ static int createModule( pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); assert( pDel==0 || pDel==pMod ); if( pDel ){ - db->mallocFailed = 1; + sqlite3OomFault(db); sqlite3DbFree(db, pDel); } } @@ -439,7 +439,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab); if( pOld ){ - db->mallocFailed = 1; + sqlite3OomFault(db); assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ return; } @@ -530,7 +530,7 @@ static int vtabCallConstructor( db->pVtabCtx = &sCtx; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); db->pVtabCtx = sCtx.pPrior; - if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; + if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); assert( sCtx.pTab==pTab ); if( SQLITE_OK!=rc ){ @@ -1088,7 +1088,7 @@ void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ pToplevel->apVtabLock = apVtabLock; pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; }else{ - pToplevel->db->mallocFailed = 1; + sqlite3OomFault(pToplevel->db); } } diff --git a/src/where.c b/src/where.c index 8c8dfbb7b6..d3a4ab87e4 100644 --- a/src/where.c +++ b/src/where.c @@ -943,7 +943,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ){ - pParse->db->mallocFailed = 1; + sqlite3OomFault(pParse->db); }else if( !pVtab->zErrMsg ){ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); }else{ diff --git a/src/whereexpr.c b/src/whereexpr.c index e0b8bac1b7..ec244bcb46 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -563,7 +563,6 @@ static void exprAnalyzeOrTerm( sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND); sqlite3WhereExprAnalyze(pSrc, pAndWC); pAndWC->pOuter = pWC; - testcase( db->mallocFailed ); if( !db->mallocFailed ){ for(j=0, pAndTerm=pAndWC->a; jnTerm; j++, pAndTerm++){ assert( pAndTerm->pExpr ); From b84e574c8923b5bcb0b50fbb5a36f4a12b4cde0d Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 5 Feb 2016 02:42:54 +0000 Subject: [PATCH 222/570] Further performance improvements that fall out of the mallocFailed changes. FossilOrigin-Name: d94416ddca8f7ed727dd335d38155ea5945a86b7 --- manifest | 19 ++++++++----------- manifest.uuid | 2 +- src/build.c | 5 ++--- src/malloc.c | 18 +++++++++++------- src/vdbeaux.c | 4 ++-- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/manifest b/manifest index d515b0a7f1..667cb055a4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sthe\sway\sthat\sOOM\serrors\sare\sprocessed. -D 2016-02-05T01:55:27.277 +C Further\sperformance\simprovements\sthat\sfall\sout\sof\sthe\smallocFailed\schanges. +D 2016-02-05T02:42:54.123 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -294,7 +294,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 0b359bcc2316a57acf12f583253974ad22b4654f F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c dcb55142c4c4293cbec181ef1ae1485ce0bc94d6 +F src/build.c 784c61366e79092b16e116372e66930775d2e6dc F src/callback.c ed6c2a4a712eb7287ff64e20e3c23265dfb8a7ce F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -314,7 +314,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b F src/main.c 62b7fe3ed245757d1ff2e6268a7ec0bc30100308 -F src/malloc.c 65168ef91884206bf3fa14a3070e79255561324b +F src/malloc.c 92ca6e16c90fb10f97844c08061bd8381423eb89 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 @@ -417,7 +417,7 @@ F src/vdbe.c 2e49c5d1b8f2f24f91ddd6c6b003d8e7fbbc4e56 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 F src/vdbeapi.c 9324f6baee1a1b2284c6543e98f916888a81e459 -F src/vdbeaux.c 0e66330ac8ad473bdefde88278725202d0174ae5 +F src/vdbeaux.c 777461529f862623e9164eb954fc53e54ddd650a F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c 9a6736339ca581f3b9503d5a1a40b7d718ca4635 F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 @@ -1426,10 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 42736fb0adc82a0fb692850ff3dd3f9b501cbf1f -R 1d34f5ef33e19e0d2d7f06ad149ac201 -T *branch * oom-handling -T *sym-oom-handling * -T -sym-trunk * +P c3ef03478a5788c855b3aef385d43ae7f494f440 +R 84df2aaa23afa82bffc643c1855a9e65 U drh -Z a95dbad943095aee523b449d4529a303 +Z 8d53cc14407430cf1880951ea3d679f2 diff --git a/manifest.uuid b/manifest.uuid index a42eab21cd..eedb6d9e7d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c3ef03478a5788c855b3aef385d43ae7f494f440 \ No newline at end of file +d94416ddca8f7ed727dd335d38155ea5945a86b7 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 097149fd4f..4185f48e93 100644 --- a/src/build.c +++ b/src/build.c @@ -4366,10 +4366,9 @@ With *sqlite3WithAdd( }else{ pNew = sqlite3DbMallocZero(db, sizeof(*pWith)); } - assert( zName!=0 || pNew==0 ); - assert( db->mallocFailed==0 || pNew==0 ); + assert( (pNew!=0 && zName!=0) || db->mallocFailed ); - if( pNew==0 ){ + if( db->mallocFailed ){ sqlite3ExprListDelete(db, pArglist); sqlite3SelectDelete(db, pQuery); sqlite3DbFree(db, zName); diff --git a/src/malloc.c b/src/malloc.c index 057d36a4be..441b4cb67d 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -645,22 +645,26 @@ static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){ return p; } +/* Forward declaration */ +static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n); + /* ** Resize the block of memory pointed to by p to n bytes. If the ** resize fails, set the mallocFailed flag in the connection object. */ void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ + assert( db!=0 ); + if( p==0 ) return sqlite3DbMallocRaw(db, n); + assert( sqlite3_mutex_held(db->mutex) ); + if( isLookaside(db,p) && n<=db->lookaside.sz ) return p; + return dbReallocFinish(db, p, n); +} +static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){ void *pNew = 0; assert( db!=0 ); - assert( sqlite3_mutex_held(db->mutex) ); + assert( p!=0 ); if( db->mallocFailed==0 ){ - if( p==0 ){ - return sqlite3DbMallocRaw(db, n); - } if( isLookaside(db, p) ){ - if( n<=db->lookaside.sz ){ - return p; - } pNew = sqlite3DbMallocRaw(db, n); if( pNew ){ memcpy(pNew, p, db->lookaside.sz); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 7d3a8c4293..334f54e414 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2511,7 +2511,7 @@ int sqlite3VdbeHalt(Vdbe *p){ ** one, or the complete transaction if there is no statement transaction. */ - if( p->db->mallocFailed ){ + if( db->mallocFailed ){ p->rc = SQLITE_NOMEM; } if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag); @@ -2672,7 +2672,7 @@ int sqlite3VdbeHalt(Vdbe *p){ } p->magic = VDBE_MAGIC_HALT; checkActiveVdbeCnt(db); - if( p->db->mallocFailed ){ + if( db->mallocFailed ){ p->rc = SQLITE_NOMEM; } From 17a936f84a656f3fba8e108758c822ec8f7b472b Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 5 Feb 2016 02:50:11 +0000 Subject: [PATCH 223/570] Minor simplification of schema error reporting. FossilOrigin-Name: a8846aeed9992c6c9f1c8bd6e996a4cbe891751e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/prepare.c | 5 ++--- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 667cb055a4..b94b629c43 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\sperformance\simprovements\sthat\sfall\sout\sof\sthe\smallocFailed\schanges. -D 2016-02-05T02:42:54.123 +C Minor\ssimplification\sof\sschema\serror\sreporting. +D 2016-02-05T02:50:11.825 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -343,7 +343,7 @@ F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 F src/pragma.c 80ee77226d0008d9188356a6cbbe6010866e1bee F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c -F src/prepare.c db4ce553dd1f03909a01858a760fa293e0f32ca0 +F src/prepare.c c12b786713df3e8270c0f85f988c5359d8b4d87c F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c @@ -1426,7 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c3ef03478a5788c855b3aef385d43ae7f494f440 -R 84df2aaa23afa82bffc643c1855a9e65 +P d94416ddca8f7ed727dd335d38155ea5945a86b7 +R 93de80b6f41eca5b247f8cd43a03611d U drh -Z 8d53cc14407430cf1880951ea3d679f2 +Z 30d13b253cef6bc68465b8bc6d2bab02 diff --git a/manifest.uuid b/manifest.uuid index eedb6d9e7d..9d5db4dfbb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d94416ddca8f7ed727dd335d38155ea5945a86b7 \ No newline at end of file +a8846aeed9992c6c9f1c8bd6e996a4cbe891751e \ No newline at end of file diff --git a/src/prepare.c b/src/prepare.c index 3fb71a770e..f74aa52e0b 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -28,11 +28,10 @@ static void corruptSchema( if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){ char *z; if( zObj==0 ) zObj = "?"; - z = sqlite3_mprintf("malformed database schema (%s)", zObj); - if( z && zExtra ) z = sqlite3_mprintf("%z - %s", z, zExtra); + z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); + if( zExtra ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); sqlite3DbFree(db, *pData->pzErrMsg); *pData->pzErrMsg = z; - if( z==0 ) sqlite3OomFault(db); } pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT_BKPT; } From 02de84e56248309aa1c993d1e694f1ee4782c366 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 5 Feb 2016 04:39:11 +0000 Subject: [PATCH 224/570] Another small tweak to the MSVC batch build tool. FossilOrigin-Name: 76718bbce775e13a82893be519ddd98b2f3a4942 --- manifest | 15 +++++++-------- manifest.uuid | 2 +- tool/build-all-msvc.bat | 6 +++++- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 7d7eb20c87..3f7a991ee4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Temporarily\sback\sout\sthe\s0.5%\sperformance\simprovement\sfrom\ncheck-in\s[632071bac5ff32].\s\sNeed\sa\smore\selaborate\ssolution\sthat\sworks\nwith\sreentrant\svirtual\stables\sand\sSQL\sfunctions. -D 2016-02-04T19:50:33.284 +C Another\ssmall\stweak\sto\sthe\sMSVC\sbatch\sbuild\stool. +D 2016-02-05T04:39:11.238 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -1367,7 +1367,7 @@ F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372 F tool/addopcodes.tcl 4ca9c3ef196f08da30add5d07ce0c9458dc8c633 -F tool/build-all-msvc.bat 77f85f4268c2711d637c629610d0cf3df5338638 x +F tool/build-all-msvc.bat 8686ace11a70a2dcd25d8a32e594517040402f1d x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 @@ -1426,8 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c9c6457d8ea911f6cc63967127e58da3146fd3ef -Q -632071bac5ff324a74cec9bdbba2deb60c0945e9 -R c2fbdbab2e50abda4a6e36464c2e90a7 -U drh -Z d787da74a7d8bd75c2afcf5547eaa172 +P 42736fb0adc82a0fb692850ff3dd3f9b501cbf1f +R 42b9a28037cad0e47b316fe911b23a4e +U mistachkin +Z 608fd16e3704c006125d3c0da336963e diff --git a/manifest.uuid b/manifest.uuid index 902f64f567..166eb03e68 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -42736fb0adc82a0fb692850ff3dd3f9b501cbf1f \ No newline at end of file +76718bbce775e13a82893be519ddd98b2f3a4942 \ No newline at end of file diff --git a/tool/build-all-msvc.bat b/tool/build-all-msvc.bat index 2dd01004d5..059f3a1da2 100755 --- a/tool/build-all-msvc.bat +++ b/tool/build-all-msvc.bat @@ -729,11 +729,15 @@ GOTO no_errors GOTO :EOF :fn_UnsetVariable + SETLOCAL SET VALUE=%1 IF DEFINED VALUE ( - SET %VALUE%= SET VALUE= + ENDLOCAL + SET %VALUE%= CALL :fn_ResetErrorLevel + ) ELSE ( + ENDLOCAL ) GOTO :EOF From 98c7a12c003278d9332c25dc9782e491b7bb0845 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 5 Feb 2016 04:50:27 +0000 Subject: [PATCH 225/570] OOM failures on sqlite3_errmsg16() in an app-defined function are no longer benign. FossilOrigin-Name: 9efb223f4ce8ccc00515f8f016f7c494c9ae5096 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/test_func.c | 2 -- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index b94b629c43..be1bead349 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\ssimplification\sof\sschema\serror\sreporting. -D 2016-02-05T02:50:11.825 +C OOM\sfailures\son\ssqlite3_errmsg16()\sin\san\sapp-defined\sfunction\sare\sno\slonger\nbenign. +D 2016-02-05T04:50:27.680 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -376,7 +376,7 @@ F src/test_config.c 0dee90328e3dedf8ba002ee94b6a7e7ea7726fe4 F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_fs.c a61f54247fdb843761d709879c3bcd1989b2050c -F src/test_func.c 0d9c25956152adefee8881c6fadc8354793764d0 +F src/test_func.c 37453d346cfcf118774efd5bf6187f7e6a7e3254 F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32 F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5 @@ -1426,7 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P d94416ddca8f7ed727dd335d38155ea5945a86b7 -R 93de80b6f41eca5b247f8cd43a03611d +P a8846aeed9992c6c9f1c8bd6e996a4cbe891751e +R d0bf71e8097462f80d2341a6f602c53f U drh -Z 30d13b253cef6bc68465b8bc6d2bab02 +Z 1d703e36553aaf91d3187c59187314d2 diff --git a/manifest.uuid b/manifest.uuid index 9d5db4dfbb..72711c9e2c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a8846aeed9992c6c9f1c8bd6e996a4cbe891751e \ No newline at end of file +9efb223f4ce8ccc00515f8f016f7c494c9ae5096 \ No newline at end of file diff --git a/src/test_func.c b/src/test_func.c index 63cf18e3f7..579177b70c 100644 --- a/src/test_func.c +++ b/src/test_func.c @@ -166,9 +166,7 @@ static void test_agg_errmsg16_final(sqlite3_context *ctx){ const void *z; sqlite3 * db = sqlite3_context_db_handle(ctx); sqlite3_aggregate_context(ctx, 2048); - sqlite3BeginBenignMalloc(); z = sqlite3_errmsg16(db); - sqlite3EndBenignMalloc(); sqlite3_result_text16(ctx, z, -1, SQLITE_TRANSIENT); #endif } From b91d2214fe73133a320a0d63cea279d9316cf639 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 5 Feb 2016 04:55:01 +0000 Subject: [PATCH 226/570] Improve ERRORLEVEL handling in the MSVC batch build tool sub-routine 'fn_UnsetVariable'. FossilOrigin-Name: fe123ab4f17f97ba9d64a7e0589ac47fd9d43877 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/build-all-msvc.bat | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 3f7a991ee4..35946a7421 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Another\ssmall\stweak\sto\sthe\sMSVC\sbatch\sbuild\stool. -D 2016-02-05T04:39:11.238 +C Improve\sERRORLEVEL\shandling\sin\sthe\sMSVC\sbatch\sbuild\stool\ssub-routine\s'fn_UnsetVariable'. +D 2016-02-05T04:55:01.668 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -1367,7 +1367,7 @@ F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372 F tool/addopcodes.tcl 4ca9c3ef196f08da30add5d07ce0c9458dc8c633 -F tool/build-all-msvc.bat 8686ace11a70a2dcd25d8a32e594517040402f1d x +F tool/build-all-msvc.bat 31866578036cd1d962628059b0760d407c3ce4d8 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 @@ -1426,7 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 42736fb0adc82a0fb692850ff3dd3f9b501cbf1f -R 42b9a28037cad0e47b316fe911b23a4e +P 76718bbce775e13a82893be519ddd98b2f3a4942 +R 86ae75673aa5606b4c7ad2944af4b890 U mistachkin -Z 608fd16e3704c006125d3c0da336963e +Z b9861f56ee1885b232be909ed448816a diff --git a/manifest.uuid b/manifest.uuid index 166eb03e68..b114896ea4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -76718bbce775e13a82893be519ddd98b2f3a4942 \ No newline at end of file +fe123ab4f17f97ba9d64a7e0589ac47fd9d43877 \ No newline at end of file diff --git a/tool/build-all-msvc.bat b/tool/build-all-msvc.bat index 059f3a1da2..84528e37c2 100755 --- a/tool/build-all-msvc.bat +++ b/tool/build-all-msvc.bat @@ -735,10 +735,10 @@ GOTO no_errors SET VALUE= ENDLOCAL SET %VALUE%= - CALL :fn_ResetErrorLevel ) ELSE ( ENDLOCAL ) + CALL :fn_ResetErrorLevel GOTO :EOF :fn_AppendVariable From 575fad6500070ad7fc7f91a8906b0b285965f99a Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 5 Feb 2016 13:38:36 +0000 Subject: [PATCH 227/570] Add the slightly faster sqlite3DbMallocRawNN(db,n) routine for the majority cases where db is guaranteed to be not NULL. FossilOrigin-Name: 0a802e96ab06e2643834b83671fa8353da1a348d --- manifest | 50 +++++++++++++-------------- manifest.uuid | 2 +- src/analyze.c | 4 +-- src/attach.c | 2 +- src/build.c | 3 +- src/date.c | 2 +- src/delete.c | 2 +- src/expr.c | 27 +++++++++------ src/fkey.c | 2 +- src/insert.c | 4 +-- src/malloc.c | 91 ++++++++++++++++++++++++++++--------------------- src/rowset.c | 2 +- src/select.c | 4 +-- src/sqliteInt.h | 1 + src/update.c | 2 +- src/util.c | 2 +- src/vdbe.c | 8 ++--- src/vdbeaux.c | 2 +- src/vdbemem.c | 5 +-- src/vtab.c | 2 +- src/where.c | 6 ++-- src/whereexpr.c | 4 +-- 22 files changed, 125 insertions(+), 102 deletions(-) diff --git a/manifest b/manifest index be1bead349..9ea4a16054 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C OOM\sfailures\son\ssqlite3_errmsg16()\sin\san\sapp-defined\sfunction\sare\sno\slonger\nbenign. -D 2016-02-05T04:50:27.680 +C Add\sthe\sslightly\sfaster\ssqlite3DbMallocRawNN(db,n)\sroutine\sfor\sthe\smajority\ncases\swhere\sdb\sis\sguaranteed\sto\sbe\snot\sNULL. +D 2016-02-05T13:38:36.171 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -285,8 +285,8 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c e4a5132e6264e002ab87c268108f416df3f1fb10 -F src/analyze.c 5338dbbc9f12087b38d74234de00907bdf023a92 -F src/attach.c b943546856ac657c702e1a92fb7adcf67c1dc397 +F src/analyze.c fbf0e80d83cc893734e872f932f249a056b86e11 +F src/attach.c c16c2648a577fa3def2adfa48c28901376389bc5 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf @@ -294,27 +294,27 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 0b359bcc2316a57acf12f583253974ad22b4654f F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 784c61366e79092b16e116372e66930775d2e6dc +F src/build.c 198eaa849c193f28b802ed135b2483c68ef7a35c F src/callback.c ed6c2a4a712eb7287ff64e20e3c23265dfb8a7ce F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 -F src/date.c 997651e3ee6c2818fbf7fcdb7156cef9eb3ece20 +F src/date.c ca17321bc17cca8f40e0843edea4fafff974998e F src/dbstat.c b2ec6793eef97aebb4d171d490a4ffdfa9f2475c -F src/delete.c 33ed87dc0746b1f8ce186f62b608bf40801af9c0 -F src/expr.c fddb1b19d77730d423ef2c219ae17e10087554ba +F src/delete.c 48802aa3ee6339f576d074336d3ae1b5f40e240f +F src/expr.c fbf0706199aea23c54efe36b6932d8307c4eb872 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c dc893ee37a21868fcf07e3d941c7663957807ad2 +F src/fkey.c 08edad1fce30f761f14b3997e89bad58f9f7f4e0 F src/func.c 86e55fee35b9577e485f47d9dd5c1d34cd513288 F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c e3e2811c69318ff62d8a764b01f5a5677d846b1e +F src/insert.c b84359365bace233919db550a15f131923190efc F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b F src/main.c 62b7fe3ed245757d1ff2e6268a7ec0bc30100308 -F src/malloc.c 92ca6e16c90fb10f97844c08061bd8381423eb89 +F src/malloc.c 55ebb1701ebd39985dbcc497aaecb09192b69682 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 @@ -347,13 +347,13 @@ F src/prepare.c c12b786713df3e8270c0f85f988c5359d8b4d87c F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c -F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c 07178f2ae1239404874492ba7e3b9a46361ebbbc +F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e +F src/select.c 57646a44ba9a0bc4aa926ae9c79b8199c246844b F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h e251b755c71c343434bce1e82c6593603c7af364 +F src/sqliteInt.h 3aeaff9611acd790c8e76719b33db09ab885d537 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -409,28 +409,28 @@ F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 F src/tokenize.c 214b783d6138e9f9fbb6b225ce9a376db3b03d42 F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 -F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 +F src/update.c 310ca7adb86a7d1f2afae46905b21c83580f3e17 F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 -F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 +F src/util.c 49ce0a65306c1c51d61cb5bc214c71cb62452de6 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 2e49c5d1b8f2f24f91ddd6c6b003d8e7fbbc4e56 +F src/vdbe.c c193299e595a13eba247738e22fce25c49346a6c F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 F src/vdbeapi.c 9324f6baee1a1b2284c6543e98f916888a81e459 -F src/vdbeaux.c 777461529f862623e9164eb954fc53e54ddd650a +F src/vdbeaux.c 49b536284c2b8a823dd342d653e18145ca2b393a F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db -F src/vdbemem.c 9a6736339ca581f3b9503d5a1a40b7d718ca4635 +F src/vdbemem.c 68fcfac37dc6601d98c32cc5adee4d39f2c1b7b4 F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 -F src/vtab.c 2cc0b7bb253851c8718b8850dfaed8592b6dc7f8 +F src/vtab.c bef51b4f693d82b4b0184457faa8625654534091 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c d21b99fd1458159d0b1ecdccc8ee6ada4fdc4c54 F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c 8bdb43e09d4e7f20bb371154799da39c25b51dfd +F src/where.c d89fd5cff448ab5c5ca492dd9793b35ffe31ab35 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a F src/wherecode.c 791a784bbf8749d560fdb0b990b607bc4f44a38d -F src/whereexpr.c 85ee2de9ff0fe40a4afaf2a477bd6c9a808548b3 +F src/whereexpr.c de117970b29471177a6901d60ad83a194671dc03 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1426,7 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a8846aeed9992c6c9f1c8bd6e996a4cbe891751e -R d0bf71e8097462f80d2341a6f602c53f +P 9efb223f4ce8ccc00515f8f016f7c494c9ae5096 +R a3e65991654c830e3de734323ec006f3 U drh -Z 1d703e36553aaf91d3187c59187314d2 +Z 1d7c8b6479ccf726221b089b3d2b622f diff --git a/manifest.uuid b/manifest.uuid index 72711c9e2c..9543c6e779 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9efb223f4ce8ccc00515f8f016f7c494c9ae5096 \ No newline at end of file +0a802e96ab06e2643834b83671fa8353da1a348d \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 7a7d68f59a..1e026a7530 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -313,7 +313,7 @@ static void sampleClear(sqlite3 *db, Stat4Sample *p){ static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){ assert( db!=0 ); if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); - p->u.aRowid = sqlite3DbMallocRaw(db, n); + p->u.aRowid = sqlite3DbMallocRawNN(db, n); if( p->u.aRowid ){ p->nRowid = n; memcpy(p->u.aRowid, pData, n); @@ -1115,7 +1115,7 @@ static void analyzeOneTable( if( nColTest>0 ){ int endDistinctTest = sqlite3VdbeMakeLabel(v); int *aGotoChng; /* Array of jump instruction addresses */ - aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*nColTest); + aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest); if( aGotoChng==0 ) continue; /* diff --git a/src/attach.c b/src/attach.c index e167951f68..2288ac9b62 100644 --- a/src/attach.c +++ b/src/attach.c @@ -109,7 +109,7 @@ static void attachFunc( ** hash tables. */ if( db->aDb==db->aDbStatic ){ - aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 ); + aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); if( aNew==0 ) return; memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); }else{ diff --git a/src/build.c b/src/build.c index 4185f48e93..476fc28c41 100644 --- a/src/build.c +++ b/src/build.c @@ -3702,8 +3702,9 @@ SrcList *sqlite3SrcListAppend( ){ struct SrcList_item *pItem; assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */ + assert( db!=0 ); if( pList==0 ){ - pList = sqlite3DbMallocRaw(db, sizeof(SrcList) ); + pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) ); if( pList==0 ) return 0; pList->nAlloc = 1; pList->nSrc = 0; diff --git a/src/date.c b/src/date.c index d78e83cf57..0a1d0e0798 100644 --- a/src/date.c +++ b/src/date.c @@ -967,7 +967,7 @@ static void strftimeFunc( sqlite3_result_error_toobig(context); return; }else{ - z = sqlite3DbMallocRaw(db, (int)n); + z = sqlite3DbMallocRawNN(db, (int)n); if( z==0 ){ sqlite3_result_error_nomem(context); return; diff --git a/src/delete.c b/src/delete.c index 5b5a5e3cb1..0fe064bc45 100644 --- a/src/delete.c +++ b/src/delete.c @@ -439,7 +439,7 @@ void sqlite3DeleteFrom( ** one, so just keep it in its register(s) and fall through to the ** delete code. */ nKey = nPk; /* OP_Found will use an unpacked key */ - aToOpen = sqlite3DbMallocRaw(db, nIdx+2); + aToOpen = sqlite3DbMallocRawNN(db, nIdx+2); if( aToOpen==0 ){ sqlite3WhereEnd(pWInfo); goto delete_from_cleanup; diff --git a/src/expr.c b/src/expr.c index 5b134d6661..8d96ba10cd 100644 --- a/src/expr.c +++ b/src/expr.c @@ -453,6 +453,7 @@ Expr *sqlite3ExprAlloc( int nExtra = 0; int iValue = 0; + assert( db!=0 ); if( pToken ){ if( op!=TK_INTEGER || pToken->z==0 || sqlite3GetInt32(pToken->z, &iValue)==0 ){ @@ -460,7 +461,7 @@ Expr *sqlite3ExprAlloc( assert( iValue>=0 ); } } - pNew = sqlite3DbMallocRaw(db, sizeof(Expr)+nExtra); + pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)+nExtra); if( pNew ){ memset(pNew, 0, sizeof(Expr)); pNew->op = (u8)op; @@ -857,6 +858,7 @@ static int dupedExprSize(Expr *p, int flags){ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ Expr *pNew = 0; /* Value to return */ assert( flags==0 || flags==EXPRDUP_REDUCE ); + assert( db!=0 ); if( p ){ const int isReduced = (flags&EXPRDUP_REDUCE); u8 *zAlloc; @@ -869,7 +871,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ zAlloc = *pzBuffer; staticFlag = EP_Static; }else{ - zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags)); + zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, flags)); } pNew = (Expr *)zAlloc; @@ -992,12 +994,13 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ ExprList *pNew; struct ExprList_item *pItem, *pOldItem; int i; + assert( db!=0 ); if( p==0 ) return 0; - pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); + pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); if( pNew==0 ) return 0; pNew->nExpr = i = p->nExpr; if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; inExpr; i+=i){} - pNew->a = pItem = sqlite3DbMallocRaw(db, i*sizeof(p->a[0]) ); + pNew->a = pItem = sqlite3DbMallocRawNN(db, i*sizeof(p->a[0]) ); if( pItem==0 ){ sqlite3DbFree(db, pNew); return 0; @@ -1028,9 +1031,10 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){ SrcList *pNew; int i; int nByte; + assert( db!=0 ); if( p==0 ) return 0; nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); - pNew = sqlite3DbMallocRaw(db, nByte ); + pNew = sqlite3DbMallocRawNN(db, nByte ); if( pNew==0 ) return 0; pNew->nSrc = pNew->nAlloc = p->nSrc; for(i=0; inSrc; i++){ @@ -1067,11 +1071,12 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){ IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){ IdList *pNew; int i; + assert( db!=0 ); if( p==0 ) return 0; - pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); + pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); if( pNew==0 ) return 0; pNew->nId = p->nId; - pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) ); + pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) ); if( pNew->a==0 ){ sqlite3DbFree(db, pNew); return 0; @@ -1089,8 +1094,9 @@ IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){ } Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ Select *pNew, *pPrior; + assert( db!=0 ); if( p==0 ) return 0; - pNew = sqlite3DbMallocRaw(db, sizeof(*p) ); + pNew = sqlite3DbMallocRawNN(db, sizeof(*p) ); if( pNew==0 ) return 0; pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags); pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags); @@ -1136,13 +1142,14 @@ ExprList *sqlite3ExprListAppend( Expr *pExpr /* Expression to be appended. Might be NULL */ ){ sqlite3 *db = pParse->db; + assert( db!=0 ); if( pList==0 ){ - pList = sqlite3DbMallocRaw(db, sizeof(ExprList) ); + pList = sqlite3DbMallocRawNN(db, sizeof(ExprList) ); if( pList==0 ){ goto no_mem; } pList->nExpr = 0; - pList->a = sqlite3DbMallocRaw(db, sizeof(pList->a[0])); + pList->a = sqlite3DbMallocRawNN(db, sizeof(pList->a[0])); if( pList->a==0 ) goto no_mem; }else if( (pList->nExpr & (pList->nExpr-1))==0 ){ struct ExprList_item *a; diff --git a/src/fkey.c b/src/fkey.c index fae25c4828..38fd4f756b 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -219,7 +219,7 @@ int sqlite3FkLocateIndex( } }else if( paiCol ){ assert( nCol>1 ); - aiCol = (int *)sqlite3DbMallocRaw(pParse->db, nCol*sizeof(int)); + aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int)); if( !aiCol ) return 1; *paiCol = aiCol; } diff --git a/src/insert.c b/src/insert.c index a8cde72954..729e0fedce 100644 --- a/src/insert.c +++ b/src/insert.c @@ -230,7 +230,7 @@ static int autoIncBegin( pInfo = pToplevel->pAinc; while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } if( pInfo==0 ){ - pInfo = sqlite3DbMallocRaw(pParse->db, sizeof(*pInfo)); + pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo)); if( pInfo==0 ) return 0; pInfo->pNext = pToplevel->pAinc; pToplevel->pAinc = pInfo; @@ -787,7 +787,7 @@ void sqlite3Insert( int nIdx; nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0, &iDataCur, &iIdxCur); - aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1)); + aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1)); if( aRegIdx==0 ){ goto insert_cleanup; } diff --git a/src/malloc.c b/src/malloc.c index 441b4cb67d..1ff0a5221d 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -575,10 +575,24 @@ void *sqlite3MallocZero(u64 n){ ** the mallocFailed flag in the connection pointer. */ void *sqlite3DbMallocZero(sqlite3 *db, u64 n){ - void *p = sqlite3DbMallocRaw(db, n); - if( p ){ - memset(p, 0, (size_t)n); - } + void *p; + testcase( db==0 ); + p = sqlite3DbMallocRaw(db, n); + if( p ) memset(p, 0, (size_t)n); + return p; +} + + +/* Finish the work of sqlite3DbMallocRawNN for the unusual and +** slower case when the allocation cannot be fulfilled using lookaside. +*/ +static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){ + void *p; + assert( db!=0 ); + p = sqlite3Malloc(n); + if( !p ) sqlite3OomFault(db); + sqlite3MemdebugSetType(p, + (db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); return p; } @@ -600,50 +614,48 @@ void *sqlite3DbMallocZero(sqlite3 *db, u64 n){ ** ** In other words, if a subsequent malloc (ex: "b") worked, it is assumed ** that all prior mallocs (ex: "a") worked too. +** +** The sqlite3MallocRawNN() variant guarantees that the "db" parameter is +** not a NULL pointer. */ -static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n); void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ - assert( db==0 || sqlite3_mutex_held(db->mutex) ); - assert( db==0 || db->pnBytesFreed==0 ); + void *p; + if( db ) return sqlite3DbMallocRawNN(db, n); + p = sqlite3Malloc(n); + sqlite3MemdebugSetType(p, MEMTYPE_HEAP); + return p; +} +void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){ + assert( db!=0 ); + assert( sqlite3_mutex_held(db->mutex) ); + assert( db->pnBytesFreed==0 ); #ifndef SQLITE_OMIT_LOOKASIDE - if( db ){ - LookasideSlot *pBuf; - if( db->lookaside.bDisable==0 ){ - assert( db->mallocFailed==0 ); - if( n>db->lookaside.sz ){ - db->lookaside.anStat[1]++; - }else if( (pBuf = db->lookaside.pFree)==0 ){ - db->lookaside.anStat[2]++; - }else{ - db->lookaside.pFree = pBuf->pNext; - db->lookaside.nOut++; - db->lookaside.anStat[0]++; - if( db->lookaside.nOut>db->lookaside.mxOut ){ - db->lookaside.mxOut = db->lookaside.nOut; - } - return (void*)pBuf; + LookasideSlot *pBuf; + if( db->lookaside.bDisable==0 ){ + assert( db->mallocFailed==0 ); + if( n>db->lookaside.sz ){ + db->lookaside.anStat[1]++; + }else if( (pBuf = db->lookaside.pFree)==0 ){ + db->lookaside.anStat[2]++; + }else{ + db->lookaside.pFree = pBuf->pNext; + db->lookaside.nOut++; + db->lookaside.anStat[0]++; + if( db->lookaside.nOut>db->lookaside.mxOut ){ + db->lookaside.mxOut = db->lookaside.nOut; } - }else if( db->mallocFailed ){ - return 0; + return (void*)pBuf; } - + }else if( db->mallocFailed ){ + return 0; } #else - if( db && db->mallocFailed ){ + if( db->mallocFailed ){ return 0; } #endif return dbMallocRawFinish(db, n); } -static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){ - void *p = sqlite3Malloc(n); - if( !p && db ){ - sqlite3OomFault(db); - } - sqlite3MemdebugSetType(p, - (db && db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); - return p; -} /* Forward declaration */ static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n); @@ -654,7 +666,7 @@ static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n); */ void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ assert( db!=0 ); - if( p==0 ) return sqlite3DbMallocRaw(db, n); + if( p==0 ) return sqlite3DbMallocRawNN(db, n); assert( sqlite3_mutex_held(db->mutex) ); if( isLookaside(db,p) && n<=db->lookaside.sz ) return p; return dbReallocFinish(db, p, n); @@ -665,7 +677,7 @@ static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){ assert( p!=0 ); if( db->mallocFailed==0 ){ if( isLookaside(db, p) ){ - pNew = sqlite3DbMallocRaw(db, n); + pNew = sqlite3DbMallocRawNN(db, n); if( pNew ){ memcpy(pNew, p, db->lookaside.sz); sqlite3DbFree(db, p); @@ -721,11 +733,12 @@ char *sqlite3DbStrDup(sqlite3 *db, const char *z){ } char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ char *zNew; + assert( db!=0 ); if( z==0 ){ return 0; } assert( (n&0x7fffffff)==n ); - zNew = sqlite3DbMallocRaw(db, n+1); + zNew = sqlite3DbMallocRawNN(db, n+1); if( zNew ){ memcpy(zNew, z, (size_t)n); zNew[n] = 0; diff --git a/src/rowset.c b/src/rowset.c index ff5593892a..c2e73ed72e 100644 --- a/src/rowset.c +++ b/src/rowset.c @@ -181,7 +181,7 @@ static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ assert( p!=0 ); if( p->nFresh==0 ){ struct RowSetChunk *pNew; - pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); + pNew = sqlite3DbMallocRawNN(p->db, sizeof(*pNew)); if( pNew==0 ){ return 0; } diff --git a/src/select.c b/src/select.c index 84d5423de6..ea3e920b9f 100644 --- a/src/select.c +++ b/src/select.c @@ -112,7 +112,7 @@ Select *sqlite3SelectNew( Select *pNew; Select standin; sqlite3 *db = pParse->db; - pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); + pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); if( pNew==0 ){ assert( db->mallocFailed ); pNew = &standin; @@ -2870,7 +2870,7 @@ static int multiSelectOrderBy( ** to the right and the left are evaluated, they use the correct ** collation. */ - aPermute = sqlite3DbMallocRaw(db, sizeof(int)*(nOrderBy + 1)); + aPermute = sqlite3DbMallocRawNN(db, sizeof(int)*(nOrderBy + 1)); if( aPermute ){ struct ExprList_item *pItem; aPermute[0] = nOrderBy; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 70f210c0a2..760c1f4d21 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3227,6 +3227,7 @@ void *sqlite3Malloc(u64); void *sqlite3MallocZero(u64); void *sqlite3DbMallocZero(sqlite3*, u64); void *sqlite3DbMallocRaw(sqlite3*, u64); +void *sqlite3DbMallocRawNN(sqlite3*, u64); char *sqlite3DbStrDup(sqlite3*,const char*); char *sqlite3DbStrNDup(sqlite3*,const char*, u64); void *sqlite3Realloc(void*, u64); diff --git a/src/update.c b/src/update.c index a9735cadca..20951aade9 100644 --- a/src/update.c +++ b/src/update.c @@ -197,7 +197,7 @@ void sqlite3Update( /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. ** Initialize aXRef[] and aToOpen[] to their default values. */ - aXRef = sqlite3DbMallocRaw(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); + aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); if( aXRef==0 ) goto update_cleanup; aRegIdx = aXRef+pTab->nCol; aToOpen = (u8*)(aRegIdx+nIdx); diff --git a/src/util.c b/src/util.c index 96f7c7f3dc..37b585b2ea 100644 --- a/src/util.c +++ b/src/util.c @@ -1150,7 +1150,7 @@ void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){ char *zBlob; int i; - zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1); + zBlob = (char *)sqlite3DbMallocRawNN(db, n/2 + 1); n--; if( zBlob ){ for(i=0; ip3>0 && pOp->p3<=(p->nMem-p->nCursor) ); assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); - pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); + pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); if( pCtx==0 ) goto no_mem; pCtx->pOut = 0; pCtx->pFunc = pOp->p4.pFunc; @@ -2870,7 +2870,7 @@ case OP_Savepoint: { #endif /* Create a new savepoint structure. */ - pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+nName+1); + pNew = sqlite3DbMallocRawNN(db, sizeof(Savepoint)+nName+1); if( pNew ){ pNew->zName = (char *)&pNew[1]; memcpy(pNew->zName, zName, nName+1); @@ -5420,7 +5420,7 @@ case OP_IntegrityCk: { assert( p->bIsReader ); nRoot = pOp->p2; assert( nRoot>0 ); - aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) ); + aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(nRoot+1) ); if( aRoot==0 ) goto no_mem; assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pnErr = &aMem[pOp->p3]; @@ -5917,7 +5917,7 @@ case OP_AggStep0: { assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); - pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); + pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); if( pCtx==0 ) goto no_mem; pCtx->pMem = 0; pCtx->pFunc = pOp->p4.pFunc; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 334f54e414..8eb3141daf 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -289,7 +289,7 @@ int sqlite3VdbeAddOp4Dup8( const u8 *zP4, /* The P4 operand */ int p4type /* P4 operand type */ ){ - char *p4copy = sqlite3DbMallocRaw(sqlite3VdbeDb(p), 8); + char *p4copy = sqlite3DbMallocRawNN(sqlite3VdbeDb(p), 8); if( p4copy ) memcpy(p4copy, zP4, 8); return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type); } diff --git a/src/vdbemem.c b/src/vdbemem.c index 974b990747..6fb7cebbcc 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -116,6 +116,7 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ assert( sqlite3VdbeCheckMemInvariants(pMem) ); assert( (pMem->flags&MEM_RowSet)==0 ); + testcase( pMem->db==0 ); /* If the bPreserve flag is set to true, then the memory cell must already ** contain a valid string or blob value. */ @@ -719,7 +720,7 @@ void sqlite3VdbeMemSetRowSet(Mem *pMem){ assert( db!=0 ); assert( (pMem->flags & MEM_RowSet)==0 ); sqlite3VdbeMemRelease(pMem); - pMem->zMalloc = sqlite3DbMallocRaw(db, 64); + pMem->zMalloc = sqlite3DbMallocRawNN(db, 64); if( db->mallocFailed ){ pMem->flags = MEM_Null; pMem->szMalloc = 0; @@ -1440,7 +1441,7 @@ static void recordFunc( db = sqlite3_context_db_handle(context); nRet = 1 + nSerial + nVal; - aRet = sqlite3DbMallocRaw(db, nRet); + aRet = sqlite3DbMallocRawNN(db, nRet); if( aRet==0 ){ sqlite3_result_error_nomem(context); }else{ diff --git a/src/vtab.c b/src/vtab.c index ca444944f4..e8794e687d 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -49,7 +49,7 @@ static int createModule( rc = SQLITE_MISUSE_BKPT; }else{ Module *pMod; - pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); + pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1); if( pMod ){ Module *pDel; char *zCopy = (char *)(&pMod[1]); diff --git a/src/where.c b/src/where.c index d3a4ab87e4..1bee2ca6fe 100644 --- a/src/where.c +++ b/src/where.c @@ -1735,7 +1735,7 @@ static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){ WhereTerm **paNew; if( p->nLSlot>=n ) return SQLITE_OK; n = (n+7)&~7; - paNew = sqlite3DbMallocRaw(db, sizeof(p->aLTerm[0])*n); + paNew = sqlite3DbMallocRawNN(db, sizeof(p->aLTerm[0])*n); if( paNew==0 ) return SQLITE_NOMEM; memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot); if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm); @@ -2032,7 +2032,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ #endif if( p==0 ){ /* Allocate a new WhereLoop to add to the end of the list */ - *ppPrev = p = sqlite3DbMallocRaw(db, sizeof(WhereLoop)); + *ppPrev = p = sqlite3DbMallocRawNN(db, sizeof(WhereLoop)); if( p==0 ) return SQLITE_NOMEM; whereLoopInit(p); p->pNextLoop = 0; @@ -3529,7 +3529,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ /* Allocate and initialize space for aTo, aFrom and aSortCost[] */ nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; nSpace += sizeof(LogEst) * nOrderBy; - pSpace = sqlite3DbMallocRaw(db, nSpace); + pSpace = sqlite3DbMallocRawNN(db, nSpace); if( pSpace==0 ) return SQLITE_NOMEM; aTo = (WherePath*)pSpace; aFrom = aTo+mxChoice; diff --git a/src/whereexpr.c b/src/whereexpr.c index ec244bcb46..c84d2f230a 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -64,7 +64,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ if( pWC->nTerm>=pWC->nSlot ){ WhereTerm *pOld = pWC->a; sqlite3 *db = pWC->pWInfo->pParse->db; - pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); + pWC->a = sqlite3DbMallocRawNN(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); if( pWC->a==0 ){ if( wtFlags & TERM_DYNAMIC ){ sqlite3ExprDelete(db, p); @@ -549,7 +549,7 @@ static void exprAnalyzeOrTerm( WhereAndInfo *pAndInfo; assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); chngToIN = 0; - pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo)); + pAndInfo = sqlite3DbMallocRawNN(db, sizeof(*pAndInfo)); if( pAndInfo ){ WhereClause *pAndWC; WhereTerm *pAndTerm; From a23bc8a345e9030c56808202d290c8ae0e4cbf6c Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 5 Feb 2016 16:46:09 +0000 Subject: [PATCH 228/570] From test scripts, remove stray "breakpoint" commands and blank lines at the ends of files. FossilOrigin-Name: a6b35273239669189f33402144f58328b133d182 --- manifest | 111 +++++++++++++++++++-------------------- manifest.uuid | 2 +- test/analyze9.test | 3 -- test/analyzeB.test | 1 - test/analyzeD.test | 1 - test/cacheflush.test | 1 - test/cffault.test | 1 - test/corruptH.test | 1 - test/corruptI.test | 1 - test/cost.test | 3 -- test/e_blobbytes.test | 2 - test/e_blobclose.test | 1 - test/e_blobopen.test | 1 - test/e_blobwrite.test | 1 - test/e_walckpt.test | 1 - test/fkey8.test | 1 - test/fordelete.test | 1 - test/fts3conf.test | 1 - test/fts3expr4.test | 1 - test/fts3join.test | 2 - test/fts3matchinfo.test | 2 - test/fts3offsets.test | 1 - test/fts3snippet.test | 1 - test/fts4check.test | 1 - test/fts4content.test | 1 - test/fts4growth.test | 1 - test/fts4growth2.test | 1 - test/fts4noti.test | 3 -- test/fts4onepass.test | 1 - test/fuzz3.test | 1 - test/incrcorrupt.test | 1 - test/mallocK.test | 1 - test/mallocL.test | 1 - test/ovfl.test | 2 - test/pragma2.test | 1 - test/rollback2.test | 1 - test/rollbackfault.test | 2 - test/select7.test | 2 - test/shared3.test | 1 - test/snapshot.test | 1 - test/sort3.test | 1 - test/sort5.test | 1 - test/spellfix.test | 1 - test/sqllog.test | 3 -- test/tkt-9f2eb3abac.test | 1 - test/tkt-ba7cbfaedc.test | 2 - test/triggerE.test | 2 - test/vtab_shared.test | 1 - test/wal6.test | 1 - test/waloverwrite.test | 2 - test/whereI.test | 1 - test/withM.test | 3 -- 52 files changed, 56 insertions(+), 126 deletions(-) diff --git a/manifest b/manifest index 8c2dfea1b7..ca42763a5e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sthe\sway\sout-of-memory\sconditions\sare\shandled,\sresulting\nin\san\salmost\s1%\sperformance\sgain\sin\sthe\scommmon\scase\swhere\sOOM\serrors\sdo\nnot\soccur. -D 2016-02-05T14:11:12.413 +C From\stest\sscripts,\sremove\sstray\s"breakpoint"\scommands\sand\sblank\slines\nat\sthe\sends\sof\sfiles. +D 2016-02-05T16:46:09.824 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -450,11 +450,11 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test c05a461d0a6b05991106467d0c47480f2e709c82 -F test/analyze9.test 3dd9e203fad353ec8027b18a6d9a92af59f4e727 +F test/analyze9.test 88c1f2aa20b614236f03e1cc38c3619e7e8a38b4 F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a -F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d +F test/analyzeB.test a4c1c3048f6d9e090eb76e83eecb18bcf6d31a70 F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93 -F test/analyzeD.test 08f9d0bee4e118a66fff3a32d02dbe0ee0a2b594 +F test/analyzeD.test f3d77cd0fefe2849d784897d52df13beee19271d F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d F test/analyzeF.test 5d1fe1024ba2dfea3c18bede8c1ccef8aba1ab34 F test/analyzer1.test 498e2ff4b62740c2751c3a2f8b744fe26689fae9 @@ -513,7 +513,7 @@ F test/btree02.test fe69453d474d8154d19b904157ff1db4812fed99 F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3 F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0 F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de -F test/cacheflush.test a755c93482ce2e20c04825304bef27e7b7ea0111 +F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61 F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738 F test/capi3.test bf6f0308bbbba1e770dac13aa08e5c2ac61c7324 F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 @@ -521,7 +521,7 @@ F test/capi3c.test 06f6261f9e9b4ef6f76afcd9900f3665408af1c8 F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82 F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3 -F test/cffault.test 1647eef45512817265c360ed4539538eed26ac69 +F test/cffault.test aadc1f61f8811cb600e3e069acbf8796f472a096 F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763 F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815 F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4 @@ -558,10 +558,10 @@ F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040 F test/corruptE.test be8e5088c369fc7979c662cd644efdaafc0f7f6d F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4 F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804 -F test/corruptH.test 5dd4fa98c6c1ed33b178f9e8a48c4fdd3cfc9067 -F test/corruptI.test f2b10e4fec2a4315bca2b936ffa52ccbffac3422 +F test/corruptH.test 99ad81a4bda7cc078c589ef7542ecbc64e453c80 +F test/corruptI.test 347babbf970e7947e3f91dccf7a1bec28a1bab04 F test/corruptJ.test 9e29e7a81ee3b6ac50f77ea7a9e2f3fa03f32d91 -F test/cost.test 19d314526616ce4473eb4e4e450fcb94499ce318 +F test/cost.test 1eedbfd868f806f3fa08ff072b04cf270dcf61c8 F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62 F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f @@ -592,10 +592,10 @@ F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2 F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e F test/distinct.test a1783b960ad8c15a77cd9f207be072898db1026c F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376 -F test/e_blobbytes.test 9bea1d3e2b20f3010b04abba58f6ba172301f49f -F test/e_blobclose.test df756753f571bc30e42e3a6cba2807576e49e716 -F test/e_blobopen.test 234f960d90235a9b51ec3ca1e062e8541dd558d8 -F test/e_blobwrite.test 615b405f29feb2cfb5a1f03dab7933258294fa26 +F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05 +F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d +F test/e_blobopen.test e95e1d40f995056f6f322cd5e1a1b83a27e1a145 +F test/e_blobwrite.test 650ded42ee5e0c2dbf263583ce01adf280129599 F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579 F test/e_createtable.test d4c6059d44dcd4b636de9aae322766062b471844 F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e @@ -615,7 +615,7 @@ F test/e_uri.test eed3eb41b22d051a1164110dacdc778899126e14 F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9 F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625 F test/e_walauto.test 280714ddf14e1a47dcbc59d515cd0b026dfd5567 -F test/e_walckpt.test 65e29b6631e51f210f83e4ff11571e647ba93608 +F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0 F test/e_walhook.test da3ea8b3483d1af72190337bda50155a91a4b664 F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473 @@ -641,9 +641,9 @@ F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d F test/fkey5.test 5a373303f201ac03c22ba1ef17a733d3f56e611a F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48 F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13 -F test/fkey8.test 8f08203458321e6c19a263829de4cfc936274ab0 +F test/fkey8.test 7bd1dd0174a0e29a90c62c517b9e2a410a0b345d F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749 -F test/fordelete.test 57ed9b953eeace09dd2eac3251b40bf9d6990aec +F test/fordelete.test eb93a2f34137bb87bdab88fcab06c0bd92719aff F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7 @@ -704,7 +704,7 @@ F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984 F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958 F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c -F test/fts3conf.test ff90127b2462c788348c0dd7f6f8c573ef9cb5d9 +F test/fts3conf.test 1c8b8adb0ab28a41b68d1514df44380bd7353402 F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7 @@ -717,40 +717,40 @@ F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851 F test/fts3expr.test 3401d47b229c4504424caf362cc4ff704cad4162 F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8 -F test/fts3expr4.test e1be1248566f43c252d4404d52914f1fc4bfa065 +F test/fts3expr4.test c39a15d676b14fc439d9bf845aa7bddcf4a74dc3 F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49 F test/fts3fault.test da49627b280b210ebc6657f76344c7851f10ce66 F test/fts3fault2.test f953bb3cf903988172270a9a0aafd5a890b0f98f F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641 -F test/fts3join.test 53e66a0c21eb568580674a43b21c059acb26f499 +F test/fts3join.test 34750f3ce1e29b2749eaf0f1be2fa6301c5d50da F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6 -F test/fts3matchinfo.test 07009313ad6c082f94d8c9c3228eb8940c93ac71 +F test/fts3matchinfo.test ce864e0bd92429df8008f31cf557269ba172482a F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905 -F test/fts3offsets.test 5b8ec5be27dd2070af3538b23c67f1ca8c822853 +F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2 F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce F test/fts3query.test f33eb71a1fe1084ea585eeb7ee76b390729f5170 F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0 F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e -F test/fts3snippet.test 63dbd687d5bf5191f1b8e6a0977aa9c1e28a7004 +F test/fts3snippet.test 01a4231816e03a0660ae53ba2404fe69012fe0db F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca F test/fts3tok1.test 178c050199af8c05299b1ad572514ce1c54b7827 F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb -F test/fts4check.test 9d9e818fd6cb29c0e007cd6d00447739d4fde430 -F test/fts4content.test 8707425b926663f8ca81de866c007900442b5ec0 +F test/fts4check.test c3056eab9524232e4c9bdcd119912947e07bcc1c +F test/fts4content.test 05716af19a899cd70d5cd916c580043c03f30db4 F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01 -F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53 -F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d +F test/fts4growth.test 60d6bb3f78e25b34f533797dd9f2f9402310a13a +F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269 F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7 F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891 F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7 F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b -F test/fts4noti.test 524807f0c36d49deea7920cdd4cd687408b58849 -F test/fts4onepass.test bfca61f69c6ca74cd71e6dca12a0cdd47192fc24 +F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309 +F test/fts4onepass.test 7319d61a2ed1325fc54afd0c060a0513b462303a F test/fts4unicode.test 27378af76394542cf490cf001d8d1505fe55f6a9 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef @@ -761,7 +761,7 @@ F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4 F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74 F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 -F test/fuzz3.test 53fabcd5f0f430f8b221282f6c12c4d0903c21eb +F test/fuzz3.test b47377143f0c80f91ed29d722861077ff34415d5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26 F test/fuzzcheck.c 3309d793165ca61a9996271cb799694839348f9a @@ -790,7 +790,7 @@ F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4 F test/incrblob4.test f26502a5697893e5acea268c910f16478c2f0fab F test/incrblob_err.test af1f12ba60d220c9752073ff2bda2ad59e88960d F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e -F test/incrcorrupt.test 9786cba68c5832f01887fde1c06b43c3904d86f6 +F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32 F test/incrvacuum2.test 676c41428765d58f1da7dbe659ef27726d3d30ac F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a @@ -876,8 +876,8 @@ F test/mallocG.test 0ff91b65c50bdaba680fb75d87fe4ad35bb7934f F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb F test/mallocI.test a88c2b9627c8506bf4703d8397420043a786cdb6 F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e -F test/mallocK.test da01dcdd316767b8356741f8d33a23a06a23def5 -F test/mallocL.test 252ddc7eb4fbf75364eab17b938816085ff1fc17 +F test/mallocK.test 27cb5566a6e5f2d76f9d4aa2eca45524401fd61e +F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f @@ -930,7 +930,7 @@ F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3 F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f -F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799 +F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71 F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f @@ -946,7 +946,7 @@ F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff F test/permutations.test 382a43c49f49bafe6fddffe904ea33d6bb3ff33e F test/pragma.test 507ac7ef2ea5682241ea0ef041799ca70bb5e0bf -F test/pragma2.test a9400a7289605280576098b97f5cde3f204075c0 +F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054 @@ -967,8 +967,8 @@ F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 F test/releasetest.tcl 975449bf742b8bb9025208292208af816a1fcb58 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea -F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14 -F test/rollbackfault.test 6a004f71087cc399296cffbb5429ea6da655ae65 +F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5 +F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81 F test/rowid.test 5b7509f384f4f6fae1af3c8c104c8ca299fea18d @@ -995,7 +995,7 @@ F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054 F test/select4.test 6d5bc6d178a367e8b48fa1c1d3ea12cae9c2d650 F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535 F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0 -F test/select7.test 71f06cd37cb6f65bb08ba1ccf8e2f5818c09329f +F test/select7.test 95e370c42d47c3c52377d05e9ffc01ccff7c1f61 F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95 F test/selectA.test e452bdb975f488ea46d091382a9185b5853ed2c7 @@ -1008,7 +1008,7 @@ F test/selectG.test e8600e379589e85e9fefd2fe4d44a4cdd63f6982 F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118 F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746 F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879 -F test/shared3.test fcd65cb11d189eff5f5c85cc4fad246fb0933108 +F test/shared3.test ab693f9b6e156b8bfb2a0ad94f29fe69602a5d38 F test/shared4.test c75f476804e76e26bf6fa0e7b421fb0ca7d07558 F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9 F test/shared7.test a81e99f83e6c51b02ac99c96fb3a2a7b5978c956 @@ -1032,15 +1032,15 @@ F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5 F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2 F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b -F test/snapshot.test efc6b4edc5d571161835f9dd8552e181ad1f0ac2 +F test/snapshot.test 5ec4651d16c3d1eb6c010d102febe32b3614bf56 F test/snapshot_fault.test 25973aeb1b86a280800e0bcf1eb5ce70e9ef57ab F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087 F test/sort.test c2adc635c2564241fefec0b3a68391ef6868fd3b F test/sort2.test cc23b7c19d684657559e8a55b02f7fcee03851d0 -F test/sort3.test 1d831e95076b92985754a122e92ebc23bdf6f712 +F test/sort3.test 1480ed7c4c157682542224e05e3b75faf4a149e5 F test/sort4.test 5c34d9623a4ae5921d956dfa2b70e77ed0fc6e5c -F test/sort5.test a448240a42b49239edc00f85d6d7ac7a1b261e1f +F test/sort5.test d3041ce3c475aa04142a959ae56ef6593f98a99f F test/sortfault.test d4ccf606a0c77498e2beb542764fd9394acb4d66 F test/speed1.test f2974a91d79f58507ada01864c0e323093065452 F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb @@ -1051,12 +1051,12 @@ F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b F test/speedtest1.c f8bf04214e7b5f745feea99f7bde68b1c4870666 -F test/spellfix.test 0597065ff57042df1f138e6a2611ae19c2698135 +F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3 F test/spellfix3.test f7bf7b3482971473d32b6b00f6944c5c066cff97 F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5 F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142 -F test/sqllog.test a8faa2df39610a037dd372ed872d124260d32953 +F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a F test/stat.test acc91e80517fff447ae8adcfd953cfdaa5efc0af F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1 F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9 @@ -1125,14 +1125,14 @@ F test/tkt-91e2e8ba6f.test 08c4f94ae07696b05c9b822da0b4e5337a2f54c5 F test/tkt-94c04eaadb.test f738c57c7f68ab8be1c054415af7774617cb6223 F test/tkt-9a8b09f8e6.test b2ef151d0984b2ebf237760dbeaa50724e5a0667 F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67 -F test/tkt-9f2eb3abac.test 85bc63e749f050e6a61c8f9207f1eee65c9d3395 +F test/tkt-9f2eb3abac.test cb6123ac695a08b4454c3792fbe85108f67fabf8 F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4 F test/tkt-a8a0d2996a.test eb597379dbcefa24765763d7f682c00cb5924fa9 F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550 F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0 F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3 F test/tkt-b75a9ca6b0.test 97cc2d5eeaf82799eb42138c0a1ff64370238ce4 -F test/tkt-ba7cbfaedc.test e76d88e572e489ee0d64fe4caf4af18b3d1dc688 +F test/tkt-ba7cbfaedc.test b4c0deccc12aeb55cfdb57935b16b5d67c5a9877 F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898 F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d F test/tkt-c48d99d690.test ba61977d62ab612fc515b3c488a6fbd6464a2447 @@ -1252,7 +1252,7 @@ F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332 F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092 F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650 -F test/triggerE.test 355e9c5cbaed5cd039a60baad1fb2197caeb8e52 +F test/triggerE.test 15fa63f1097db1f83dd62d121616006978063d1f F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1 F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a F test/tt3_lookaside1.c 0377e202c3c2a50d688cb65ba203afeda6fafeb9 @@ -1295,13 +1295,13 @@ F test/vtabH.test 5f5157a1501d9889ec35c1a1832f69612dd31444 F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 -F test/vtab_shared.test ea8778d5b0df200adef2ca7c00c3c37d4375f772 +F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad F test/wal.test 0148c8b3421a25fdb4d9c160e84a681d0646371b F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada F test/wal3.test 5dd734147f1f8f958c5261a1f2775d346d7013ce F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c F test/wal5.test 88b5d9a6a3d1532497ee9f4296f010d66f07e33c -F test/wal6.test 4421cd5a2fa99d29cc91ef12fb23bed171ed3a4c +F test/wal6.test a9d6aa635b9d63607dabdc11406f5f96ca986635 F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8 F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd F test/wal8.test 75c42e1bc4545c277fed212f8fc9b7723cd02216 @@ -1318,7 +1318,7 @@ F test/walfault.test 1f8389f7709877e9b4cc679033d71d6fe529056b F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483 F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496 -F test/waloverwrite.test a0d2ae0783187374c1e6a9571e0916152977cb81 +F test/waloverwrite.test dad2f26567f1b45174e54fbf9a8dc1cb876a7f03 F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6 F test/walprotocol.test 059cb75484a1ecf6357a2c1b3324b8156749221e F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57 @@ -1342,7 +1342,7 @@ F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 F test/whereG.test dde4c52a97385a55be6a7cd46be8373f0cf35501 F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 -F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622 +F test/whereI.test eab5b226bbc344ac70d7dc09b963a064860ae6d7 F test/whereJ.test 55a3221706a7ab706293f17cc8f96da563bf0767 F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864 @@ -1354,7 +1354,7 @@ F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/with1.test cef099a491eac9874f2c28bd2dc86394fb3e47b3 F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87 F test/with3.test 511bacdbe41c49cf34f9fd1bd3245fe1575bca98 -F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991 +F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64 F test/without_rowid1.test 1a7b9bd51b899928d327052df9741d2fe8dbe701 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 F test/without_rowid3.test aad4f9d383e199349b6c7e508a778f7dff5dff79 @@ -1426,8 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P fe123ab4f17f97ba9d64a7e0589ac47fd9d43877 0a802e96ab06e2643834b83671fa8353da1a348d -R 3749c59fe6fdfc59db76e85b115f2d1f -T +closed 0a802e96ab06e2643834b83671fa8353da1a348d +P b082538da774ac77f284fd7e22f9b1b9c2abc343 +R 2d1b67b182c9e99ebe80d7af9546dd2d U drh -Z 89e3d20f1d49685c430d339bf1d58063 +Z 796cfacaa9509982f1af1b696a2e58d2 diff --git a/manifest.uuid b/manifest.uuid index 96f1ef1f1f..e7a723dfc9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b082538da774ac77f284fd7e22f9b1b9c2abc343 \ No newline at end of file +a6b35273239669189f33402144f58328b133d182 \ No newline at end of file diff --git a/test/analyze9.test b/test/analyze9.test index 1ebd69c8d1..e24f3dd49d 100644 --- a/test/analyze9.test +++ b/test/analyze9.test @@ -1244,6 +1244,3 @@ do_eqp_test 26.2.2 { finish_test - - - diff --git a/test/analyzeB.test b/test/analyzeB.test index 2a78c18b3d..e91e7d585e 100644 --- a/test/analyzeB.test +++ b/test/analyzeB.test @@ -680,4 +680,3 @@ for {set i 0} {$i<16} {incr i} { } finish_test - diff --git a/test/analyzeD.test b/test/analyzeD.test index 4d46be6c64..7ef1094f82 100644 --- a/test/analyzeD.test +++ b/test/analyzeD.test @@ -114,4 +114,3 @@ do_eqp_test 1.8 { } finish_test - diff --git a/test/cacheflush.test b/test/cacheflush.test index 007ee8a065..50461893ef 100644 --- a/test/cacheflush.test +++ b/test/cacheflush.test @@ -321,4 +321,3 @@ do_test 4.5 { test_restore_config_pagecache finish_test - diff --git a/test/cffault.test b/test/cffault.test index a89477b617..79cefd24c4 100644 --- a/test/cffault.test +++ b/test/cffault.test @@ -156,4 +156,3 @@ do_faultsim_test 2.4 -prep { } finish_test - diff --git a/test/corruptH.test b/test/corruptH.test index 5c83cb3b90..0e1a1d4429 100644 --- a/test/corruptH.test +++ b/test/corruptH.test @@ -174,4 +174,3 @@ do_test 3.3 { } {1 {database disk image is malformed}} finish_test - diff --git a/test/corruptI.test b/test/corruptI.test index 64323d9608..9f46efb744 100644 --- a/test/corruptI.test +++ b/test/corruptI.test @@ -206,7 +206,6 @@ do_test 6.1 { db close hexio_write test.db 616 8FFFFFFF7F02 sqlite3 db test.db - breakpoint execsql { DELETE FROM t1 WHERE rowid=2 } } {} diff --git a/test/cost.test b/test/cost.test index 92fff9c888..9c10d821d9 100644 --- a/test/cost.test +++ b/test/cost.test @@ -287,6 +287,3 @@ ifcapable stat4 { } finish_test - - - diff --git a/test/e_blobbytes.test b/test/e_blobbytes.test index a6283ab852..d38f56bf34 100644 --- a/test/e_blobbytes.test +++ b/test/e_blobbytes.test @@ -72,5 +72,3 @@ do_test 2.1 { sqlite3_blob_close $B finish_test - - diff --git a/test/e_blobclose.test b/test/e_blobclose.test index a5d432d3b5..2683197854 100644 --- a/test/e_blobclose.test +++ b/test/e_blobclose.test @@ -168,4 +168,3 @@ do_execsql_test 3.5 { do_test 4.0 { sqlite3_blob_close 0 } {} finish_test - diff --git a/test/e_blobopen.test b/test/e_blobopen.test index 01f62cdd78..a6168042e9 100644 --- a/test/e_blobopen.test +++ b/test/e_blobopen.test @@ -546,4 +546,3 @@ do_test 13.5 { finish_test - diff --git a/test/e_blobwrite.test b/test/e_blobwrite.test index a0d33336de..7b2249c243 100644 --- a/test/e_blobwrite.test +++ b/test/e_blobwrite.test @@ -201,4 +201,3 @@ do_execsql_test 3.2.4 { finish_test - diff --git a/test/e_walckpt.test b/test/e_walckpt.test index e022f840cf..3b1f3b015a 100644 --- a/test/e_walckpt.test +++ b/test/e_walckpt.test @@ -751,4 +751,3 @@ do_test 6.5 { finish_test - diff --git a/test/fkey8.test b/test/fkey8.test index 60bb8e4640..b4b6bb75e7 100644 --- a/test/fkey8.test +++ b/test/fkey8.test @@ -103,4 +103,3 @@ foreach {tn use_stmt sql schema} { finish_test - diff --git a/test/fordelete.test b/test/fordelete.test index bc38a4c5e3..9a382d97f5 100644 --- a/test/fordelete.test +++ b/test/fordelete.test @@ -207,4 +207,3 @@ do_execsql_test 5.3 { finish_test - diff --git a/test/fts3conf.test b/test/fts3conf.test index e157c239ef..f9698770cc 100644 --- a/test/fts3conf.test +++ b/test/fts3conf.test @@ -212,4 +212,3 @@ do_execsql_test 4.2.2 { } {} finish_test - diff --git a/test/fts3expr4.test b/test/fts3expr4.test index 4bc62030d5..9fc22c1172 100644 --- a/test/fts3expr4.test +++ b/test/fts3expr4.test @@ -79,4 +79,3 @@ do_icu_expr_test 3.9 { "ab*c" } { PHRASE 3 0 ab+ * c } do_icu_expr_test 3.10 { ab*c } { AND {PHRASE 3 0 ab+} {PHRASE 3 0 c}} finish_test - diff --git a/test/fts3join.test b/test/fts3join.test index 64363639db..0fb8c62022 100644 --- a/test/fts3join.test +++ b/test/fts3join.test @@ -62,5 +62,3 @@ do_catchsql_test 2.5 { } {1 {unable to use function MATCH in the requested context}} finish_test - - diff --git a/test/fts3matchinfo.test b/test/fts3matchinfo.test index b17d7da0a5..8cbcd69041 100644 --- a/test/fts3matchinfo.test +++ b/test/fts3matchinfo.test @@ -524,7 +524,6 @@ foreach {tn expr res} { do_execsql_test 11.1.$tn.2 { SELECT rowid, mit(matchinfo(tt, 'b')) FROM tt WHERE tt MATCH $expr } $r2 - breakpoint do_execsql_test 11.1.$tn.2 { SELECT rowid, mit(matchinfo(tt, 'b')) FROM tt WHERE tt MATCH $expr @@ -552,4 +551,3 @@ do_execsql_test 12.1 { set sqlite_fts3_enable_parentheses 0 finish_test - diff --git a/test/fts3offsets.test b/test/fts3offsets.test index 184321ac01..4a1e63aa4c 100644 --- a/test/fts3offsets.test +++ b/test/fts3offsets.test @@ -121,4 +121,3 @@ do_execsql_test 1.4.1 { set sqlite_fts3_enable_parentheses 0 finish_test - diff --git a/test/fts3snippet.test b/test/fts3snippet.test index 4e1d123b2f..887011cd11 100644 --- a/test/fts3snippet.test +++ b/test/fts3snippet.test @@ -559,4 +559,3 @@ do_test 4.2 { set sqlite_fts3_enable_parentheses 0 finish_test - diff --git a/test/fts4check.test b/test/fts4check.test index 4ded053871..1e2f6b234f 100644 --- a/test/fts4check.test +++ b/test/fts4check.test @@ -210,4 +210,3 @@ do_execsql_test 5.4 { } {} finish_test - diff --git a/test/fts4content.test b/test/fts4content.test index 5a91987867..67642b6b8a 100644 --- a/test/fts4content.test +++ b/test/fts4content.test @@ -636,4 +636,3 @@ do_catchsql_test 11.1 { finish_test - diff --git a/test/fts4growth.test b/test/fts4growth.test index aa5f251f95..e4b5f19ecb 100644 --- a/test/fts4growth.test +++ b/test/fts4growth.test @@ -434,4 +434,3 @@ do_execsql_test 7.7 { finish_test - diff --git a/test/fts4growth2.test b/test/fts4growth2.test index af41d51c18..bcccf89c87 100644 --- a/test/fts4growth2.test +++ b/test/fts4growth2.test @@ -90,4 +90,3 @@ for {set tn 0} {$tn < 40} {incr tn} { finish_test - diff --git a/test/fts4noti.test b/test/fts4noti.test index c90999b4fa..6707203970 100644 --- a/test/fts4noti.test +++ b/test/fts4noti.test @@ -228,6 +228,3 @@ do_execsql_test 6.3.1 { } {0 1 1 0 1 1} finish_test - - - diff --git a/test/fts4onepass.test b/test/fts4onepass.test index d290980dc9..46cb4b794b 100644 --- a/test/fts4onepass.test +++ b/test/fts4onepass.test @@ -144,4 +144,3 @@ foreach {tn tcl1 tcl2} { } finish_test - diff --git a/test/fuzz3.test b/test/fuzz3.test index b432671822..6d2a01c7d3 100644 --- a/test/fuzz3.test +++ b/test/fuzz3.test @@ -173,4 +173,3 @@ for {set ii 0} {$ii < 5000} {incr ii} { test_restore_config_pagecache finish_test - diff --git a/test/incrcorrupt.test b/test/incrcorrupt.test index eda65e4035..2ea68c8c7c 100644 --- a/test/incrcorrupt.test +++ b/test/incrcorrupt.test @@ -124,4 +124,3 @@ do_test 2.16 { sqlite3_errcode db } {SQLITE_CORRUPT} do_test 2.17 { sqlite3_errmsg db } {database disk image is malformed} finish_test - diff --git a/test/mallocK.test b/test/mallocK.test index 65791e79ea..45ee7905c3 100644 --- a/test/mallocK.test +++ b/test/mallocK.test @@ -172,4 +172,3 @@ do_faultsim_test 8 -faults oom* -body { finish_test - diff --git a/test/mallocL.test b/test/mallocL.test index 6532ca5e14..5c2a4ec0b0 100644 --- a/test/mallocL.test +++ b/test/mallocL.test @@ -40,4 +40,3 @@ for {set j 1} {$j < 40} {incr j} { finish_test - diff --git a/test/ovfl.test b/test/ovfl.test index 075b1e43dd..4be7568546 100644 --- a/test/ovfl.test +++ b/test/ovfl.test @@ -45,5 +45,3 @@ do_execsql_test 1.2 { } [expr 2000 * 2000] finish_test - - diff --git a/test/pragma2.test b/test/pragma2.test index a4fb2ce657..5896e52687 100644 --- a/test/pragma2.test +++ b/test/pragma2.test @@ -255,7 +255,6 @@ db close forcedelete test.db sqlite3 db test.db -breakpoint do_execsql_test pragma2-5.1 { PRAGMA page_size=16384; CREATE TABLE t1(x); diff --git a/test/rollback2.test b/test/rollback2.test index 4d42dda5d6..3ba0f3f9fd 100644 --- a/test/rollback2.test +++ b/test/rollback2.test @@ -154,4 +154,3 @@ do_rollback_test 4.4 -setup { } finish_test - diff --git a/test/rollbackfault.test b/test/rollbackfault.test index f248d0758d..4d060b43c8 100644 --- a/test/rollbackfault.test +++ b/test/rollbackfault.test @@ -80,5 +80,3 @@ foreach f {oom ioerr} { finish_test - - diff --git a/test/select7.test b/test/select7.test index 9ed5357748..0df84e13d9 100644 --- a/test/select7.test +++ b/test/select7.test @@ -220,5 +220,3 @@ do_catchsql_test 8.2 { finish_test - - diff --git a/test/shared3.test b/test/shared3.test index acc86d2a07..1d09b69b82 100644 --- a/test/shared3.test +++ b/test/shared3.test @@ -139,4 +139,3 @@ do_test 3.5 { sqlite3_enable_shared_cache $::enable_shared_cache finish_test - diff --git a/test/snapshot.test b/test/snapshot.test index 6e160166c3..63a0e30175 100644 --- a/test/snapshot.test +++ b/test/snapshot.test @@ -55,7 +55,6 @@ do_execsql_test 2.1.0 { SELECT * FROM t1; } {1 2 3 4 5 6 7 8} -breakpoint do_test 2.1.1 { set snapshot [sqlite3_snapshot_get db main] execsql { diff --git a/test/sort3.test b/test/sort3.test index 3aa6512a4b..088ae1642d 100644 --- a/test/sort3.test +++ b/test/sort3.test @@ -111,4 +111,3 @@ do_execsql_test 3 { } finish_test - diff --git a/test/sort5.test b/test/sort5.test index a02b8f920f..5b1292bb48 100644 --- a/test/sort5.test +++ b/test/sort5.test @@ -42,4 +42,3 @@ do_execsql_test 1.2 { db close tvfs delete finish_test - diff --git a/test/spellfix.test b/test/spellfix.test index b47001ebd7..8128bb59d2 100644 --- a/test/spellfix.test +++ b/test/spellfix.test @@ -403,4 +403,3 @@ foreach {tn conflict err bRollback res} { } finish_test - diff --git a/test/sqllog.test b/test/sqllog.test index dca5781dbd..53d8d871d8 100644 --- a/test/sqllog.test +++ b/test/sqllog.test @@ -110,7 +110,4 @@ unset ::env(SQLITE_SQLLOG_DIR) unset ::env(SQLITE_SQLLOG_CONDITIONAL) sqlite3_config_sqllog sqlite3_initialize -breakpoint finish_test - - diff --git a/test/tkt-9f2eb3abac.test b/test/tkt-9f2eb3abac.test index 5b93733afe..8411654cdd 100644 --- a/test/tkt-9f2eb3abac.test +++ b/test/tkt-9f2eb3abac.test @@ -76,4 +76,3 @@ do_faultsim_test 3 -faults oom* -prep { } finish_test - diff --git a/test/tkt-ba7cbfaedc.test b/test/tkt-ba7cbfaedc.test index a558d4cec3..f83f8a3d17 100644 --- a/test/tkt-ba7cbfaedc.test +++ b/test/tkt-ba7cbfaedc.test @@ -61,5 +61,3 @@ do_execsql_test 2.0 { } finish_test - - diff --git a/test/triggerE.test b/test/triggerE.test index e2727bbdcb..a82ac9d2a5 100644 --- a/test/triggerE.test +++ b/test/triggerE.test @@ -108,5 +108,3 @@ do_execsql_test 2.3 { } {1 2 x y z z} finish_test - - diff --git a/test/vtab_shared.test b/test/vtab_shared.test index 3473992900..a9079eac04 100644 --- a/test/vtab_shared.test +++ b/test/vtab_shared.test @@ -276,4 +276,3 @@ ifcapable fts3 { sqlite3_enable_shared_cache 0 finish_test - diff --git a/test/wal6.test b/test/wal6.test index d96166ef59..2574a64a84 100644 --- a/test/wal6.test +++ b/test/wal6.test @@ -236,4 +236,3 @@ do_test 4.4.2 { finish_test - diff --git a/test/waloverwrite.test b/test/waloverwrite.test index aa1154fb97..ff8bc5ab55 100644 --- a/test/waloverwrite.test +++ b/test/waloverwrite.test @@ -131,7 +131,6 @@ foreach {tn xtra} { execsql { UPDATE t1 SET y = randomblob(797) WHERE x=$x } } } - breakpoint execsql {ROLLBACK TO abc} } @@ -161,4 +160,3 @@ foreach {tn xtra} { } finish_test - diff --git a/test/whereI.test b/test/whereI.test index 452e7f8f19..29b08549be 100644 --- a/test/whereI.test +++ b/test/whereI.test @@ -89,4 +89,3 @@ do_execsql_test 3.0 { } finish_test - diff --git a/test/withM.test b/test/withM.test index c1650d9576..78b757f422 100644 --- a/test/withM.test +++ b/test/withM.test @@ -72,6 +72,3 @@ do_faultsim_test withM-1.3 -prep { } finish_test - - - From 1cd0f054921f7fd552bf8711abbf31ba88c6908c Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 5 Feb 2016 17:49:43 +0000 Subject: [PATCH 229/570] Make sure the "bak.db" database file does not actually exist before starting the "quota.test" testing. FossilOrigin-Name: 1cac6c45eeb7dbbcda0c76ba7d3a2ca77bc725cd --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/quota.test | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index ca42763a5e..35ca92466b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C From\stest\sscripts,\sremove\sstray\s"breakpoint"\scommands\sand\sblank\slines\nat\sthe\sends\sof\sfiles. -D 2016-02-05T16:46:09.824 +C Make\ssure\sthe\s"bak.db"\sdatabase\sfile\sdoes\snot\sactually\sexist\sbefore\nstarting\sthe\s"quota.test"\stesting. +D 2016-02-05T17:49:43.402 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -955,7 +955,7 @@ F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26 -F test/quota.test 2379902c25e291eac5c12b4cf96946a3447e3744 +F test/quota.test 36cd78b178c4eb0401d4f25754ef410fbd9df2a7 F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6 F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459 @@ -1426,7 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b082538da774ac77f284fd7e22f9b1b9c2abc343 -R 2d1b67b182c9e99ebe80d7af9546dd2d +P a6b35273239669189f33402144f58328b133d182 +R a53abbe37c3df437dd159edcdce10b4b U drh -Z 796cfacaa9509982f1af1b696a2e58d2 +Z b28b558e8ce57b27d1473527e7eaafc5 diff --git a/manifest.uuid b/manifest.uuid index e7a723dfc9..25bc3f5bbc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a6b35273239669189f33402144f58328b133d182 \ No newline at end of file +1cac6c45eeb7dbbcda0c76ba7d3a2ca77bc725cd \ No newline at end of file diff --git a/test/quota.test b/test/quota.test index f9655fb8c0..7af55a8330 100644 --- a/test/quota.test +++ b/test/quota.test @@ -21,6 +21,7 @@ ifcapable !curdir { source $testdir/malloc_common.tcl +forcedelete bak.db unset -nocomplain defaultVfs set defaultVfs [file_control_vfsname db] db close From b80b8f482c5ef4fe0159db8931995e191f52c95a Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 5 Feb 2016 19:18:02 +0000 Subject: [PATCH 230/570] Further streamlining of fts5 prefix query code. FossilOrigin-Name: ca91bd8ac70a5b3fef127364f73ec675e58bb92c --- ext/fts5/fts5Int.h | 1 + ext/fts5/fts5_buffer.c | 62 ++++++++++++++++++++++------------- ext/fts5/fts5_index.c | 55 ++++++++++++++++++++++--------- ext/fts5/fts5_main.c | 3 +- ext/fts5/test/fts5ad.test | 2 ++ ext/fts5/test/fts5detail.test | 4 +++ manifest | 24 +++++++------- manifest.uuid | 2 +- 8 files changed, 101 insertions(+), 52 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index fc71584909..6318af900f 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -282,6 +282,7 @@ struct Fts5PoslistWriter { i64 iPrev; }; int sqlite3Fts5PoslistWriterAppend(Fts5Buffer*, Fts5PoslistWriter*, i64); +void sqlite3Fts5PoslistSafeAppend(Fts5Buffer*, i64*, i64); int sqlite3Fts5PoslistNext64( const u8 *a, int n, /* Buffer containing poslist */ diff --git a/ext/fts5/fts5_buffer.c b/ext/fts5/fts5_buffer.c index d69adf7d24..878240af4f 100644 --- a/ext/fts5/fts5_buffer.c +++ b/ext/fts5/fts5_buffer.c @@ -16,18 +16,20 @@ #include "fts5Int.h" int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){ - u32 nNew = pBuf->nSpace ? pBuf->nSpace*2 : 64; - u8 *pNew; - while( nNewp, nNew); - if( pNew==0 ){ - *pRc = SQLITE_NOMEM; - return 1; - }else{ - pBuf->nSpace = nNew; - pBuf->p = pNew; + if( pBuf->nSpacenSpace ? pBuf->nSpace : 64; + u8 *pNew; + while( nNewp, nNew); + if( pNew==0 ){ + *pRc = SQLITE_NOMEM; + return 1; + }else{ + pBuf->nSpace = nNew; + pBuf->p = pNew; + } } return 0; } @@ -208,23 +210,37 @@ int sqlite3Fts5PoslistReaderInit( return pIter->bEof; } +/* +** Append position iPos to the position list being accumulated in buffer +** pBuf, which must be already be large enough to hold the new data. +** The previous position written to this list is *piPrev. *piPrev is set +** to iPos before returning. +*/ +void sqlite3Fts5PoslistSafeAppend( + Fts5Buffer *pBuf, + i64 *piPrev, + i64 iPos +){ + static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32; + if( (iPos & colmask) != (*piPrev & colmask) ){ + pBuf->p[pBuf->n++] = 1; + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32)); + *piPrev = (iPos & colmask); + } + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2); + *piPrev = iPos; +} + int sqlite3Fts5PoslistWriterAppend( Fts5Buffer *pBuf, Fts5PoslistWriter *pWriter, i64 iPos ){ static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32; - int rc = SQLITE_OK; - if( 0==fts5BufferGrow(&rc, pBuf, 5+5+5) ){ - if( (iPos & colmask) != (pWriter->iPrev & colmask) ){ - pBuf->p[pBuf->n++] = 1; - pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32)); - pWriter->iPrev = (iPos & colmask); - } - pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-pWriter->iPrev)+2); - pWriter->iPrev = iPos; - } - return rc; + int rc; + if( fts5BufferGrow(&rc, pBuf, 5+5+5) ) return rc; + sqlite3Fts5PoslistSafeAppend(pBuf, &pWriter->iPrev, iPos); + return SQLITE_OK; } void *sqlite3Fts5MallocZero(int *pRc, int nByte){ diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 0461f3a778..3dd9a9c92d 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -4704,6 +4704,7 @@ static void fts5MergePrefixLists( Fts5Buffer *p1, /* First list to merge */ Fts5Buffer *p2 /* Second list to merge */ ){ + if( p2->n ){ if( p1->n==0 ){ fts5BufferSwap(p1, p2); @@ -4719,7 +4720,6 @@ static void fts5MergePrefixLists( fts5DoclistIterInit(p2, &i2); while( 1 ){ - if( i1.iRowidrc, &tmp, i1.nPoslist + i2.nPoslist); + if( p->rc ) break; sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); + assert( iPos1>=0 && iPos2>=0 ); - while( iPos1>=0 || iPos2>=0 ){ - i64 iNew; - if( iPos2<0 || (iPos1>=0 && iPos1=0 && iPos2>=0 ){ + while( 1 ){ + if( iPos1rc = sqlite3Fts5PoslistWriterAppend(&tmp, &writer, iNew); - if( p->rc ) goto error_out; + } + + if( iPos1>=0 ){ + if( iPos1!=iPrev ){ + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); } + fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1); + } + else if( iPos2>=0 ){ + if( iPos2!=iPrev ){ + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); + } + fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2); } /* WRITEPOSLISTSIZE */ @@ -4936,7 +4961,7 @@ int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit){ int sqlite3Fts5IndexRollback(Fts5Index *p){ fts5CloseReader(p); fts5IndexDiscardData(p); - assert( p->rc==SQLITE_OK ); + /* assert( p->rc==SQLITE_OK ); */ return SQLITE_OK; } diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index 9ef8d9a01a..4b798314c0 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -803,7 +803,7 @@ static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){ */ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; - int rc = SQLITE_OK; + int rc; assert( (pCsr->ePlan<3)== (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE) @@ -820,6 +820,7 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ switch( pCsr->ePlan ){ case FTS5_PLAN_SPECIAL: { CsrFlagSet(pCsr, FTS5CSR_EOF); + rc = SQLITE_OK; break; } diff --git a/ext/fts5/test/fts5ad.test b/ext/fts5/test/fts5ad.test index c6b09d8121..974aa781aa 100644 --- a/ext/fts5/test/fts5ad.test +++ b/ext/fts5/test/fts5ad.test @@ -11,6 +11,8 @@ # This file implements regression tests for SQLite library. The # focus of this script is testing the FTS5 module. # +# More specifically, the focus is on testing prefix queries, both with and +# without prefix indexes. # source [file join [file dirname [info script]] fts5_common.tcl] diff --git a/ext/fts5/test/fts5detail.test b/ext/fts5/test/fts5detail.test index 5bdd14424e..58fda3e995 100644 --- a/ext/fts5/test/fts5detail.test +++ b/ext/fts5/test/fts5detail.test @@ -85,6 +85,10 @@ do_execsql_test 2.2 { SELECT fts5_test_poslist(t2) FROM t2('aa'); } {0.0.0} +do_execsql_test 2.3 { + SELECT fts5_test_collist(t2) FROM t2('aa'); +} {0.0} + set ::pc 0 #puts [nearset {{ax bx cx}} -pc ::pc -near 10 -- b*] #exit diff --git a/manifest b/manifest index 35ca92466b..76600b8190 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthe\s"bak.db"\sdatabase\sfile\sdoes\snot\sactually\sexist\sbefore\nstarting\sthe\s"quota.test"\stesting. -D 2016-02-05T17:49:43.402 +C Further\sstreamlining\sof\sfts5\sprefix\squery\scode. +D 2016-02-05T19:18:02.811 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -98,14 +98,14 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 -F ext/fts5/fts5Int.h 2095cc38e776f19cc083ca90e00772ea0b204ab3 +F ext/fts5/fts5Int.h efb02807dbe5a2bfb0ea592a472d1171cb553d53 F ext/fts5/fts5_aux.c b9bcce753ef5b451267b2232f0ca153ddeb3951d -F ext/fts5/fts5_buffer.c f6e0c6018ffc8e39fc0b333b5daa8b8d528ae6e4 +F ext/fts5/fts5_buffer.c ad4bb545c866eea6add1b0f84c2c5029cd689092 F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 F ext/fts5/fts5_expr.c ff5c451a6d025909639ac0f0d0af0cc595b50feb F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c 614c54544f844387ba6728c613a884a1aa151f06 -F ext/fts5/fts5_main.c 7e8a5f27d504bc04e3de7f1cba8867f0332aee9d +F ext/fts5/fts5_index.c 9706959f2188d97d72df750519fee7baccef9964 +F ext/fts5/fts5_main.c 6e23df904049edb498538bd3e22e53ec1ab6f4f7 F ext/fts5/fts5_storage.c 2a1f44deae090cd711f02cec0c2af8e660360d24 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 F ext/fts5/fts5_test_mi.c 1ec66ffdf7632077fbd773b7a6df5153272ec070 @@ -120,7 +120,7 @@ F ext/fts5/test/fts5_common.tcl 61ff0d1a29d98a91c4553b20b3f410d858834ee9 F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b F ext/fts5/test/fts5ac.test 55cad4275a1f5acabfe14d8442a8046b47e49e5f -F ext/fts5/test/fts5ad.test 0ddaa5b692ff220100ee396228838f4331399eaa +F ext/fts5/test/fts5ad.test 36995f0586f30f5602074e012b9224c71ec5171c F ext/fts5/test/fts5ae.test 612dcb51f4069226791ff14c17dbfb3138c56f20 F ext/fts5/test/fts5af.test be858a96b1f5de66ba6d64f0021bd8b2408e126c F ext/fts5/test/fts5ag.test 27180de76c03036be75ee80b93d8c5f540014071 @@ -142,7 +142,7 @@ F ext/fts5/test/fts5content.test 9a952c95518a14182dc3b59e3c8fa71cda82a4e1 F ext/fts5/test/fts5corrupt.test c2ad090192708150d50d961278df10ae7a4b8b62 F ext/fts5/test/fts5corrupt2.test 26c0a39dd9ff73207e6229f83b50b21d37c7658c F ext/fts5/test/fts5corrupt3.test a2b537c120bdd43c79c42fe2438d7b8c81fe5599 -F ext/fts5/test/fts5detail.test 4e971d28e7336c61ab916fc287900355dab7054d +F ext/fts5/test/fts5detail.test ef5c690535a797413acaf5ad9b8ab5d49972df69 F ext/fts5/test/fts5dlidx.test 13871a14641017ae42f6f1055a8067bafd44cb3d F ext/fts5/test/fts5doclist.test 8edb5b57e5f144030ed74ec00ef6fa4294fed79b F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0 @@ -1426,7 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a6b35273239669189f33402144f58328b133d182 -R a53abbe37c3df437dd159edcdce10b4b -U drh -Z b28b558e8ce57b27d1473527e7eaafc5 +P 1cac6c45eeb7dbbcda0c76ba7d3a2ca77bc725cd +R 82ed27d217d52be944f2d4bee3dfe639 +U dan +Z ad1bc1867d7f59ff72d365283a40efbf diff --git a/manifest.uuid b/manifest.uuid index 25bc3f5bbc..8902cb7ad9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1cac6c45eeb7dbbcda0c76ba7d3a2ca77bc725cd \ No newline at end of file +ca91bd8ac70a5b3fef127364f73ec675e58bb92c \ No newline at end of file From a6f28893ed0066a06f03b2ea3f54a31582558ea2 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 5 Feb 2016 19:40:23 +0000 Subject: [PATCH 231/570] More work on Windows 10 SDK integration. FossilOrigin-Name: ebace2c99b6af9230c4bbc31a764c7f397200148 --- Makefile.msc | 24 ++++++++++++++++++++++-- manifest | 17 ++++++++++------- manifest.uuid | 2 +- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 3427b8177a..a507825a20 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -356,6 +356,16 @@ NSDKLIBPATH = $(WINDOWSSDKDIR)\lib NSDKLIBPATH = $(NSDKLIBPATH:\\=\) +# Check for the UCRT library path macro. Othertise, this value will +# default to the version-specific, platform-specific 'lib' directory +# underneath the Windows SDK installation directory. +# +!IFNDEF UCRTLIBPATH +UCRTLIBPATH = $(WINDOWSSDKDIR)\lib\$(WINDOWSSDKLIBVERSION)\ucrt\$(PLATFORM) +!ENDIF + +UCRTLIBPATH = $(UCRTLIBPATH:\\=\) + # C compiler and options for use in building executables that # will run on the platform that is doing the build. # @@ -541,7 +551,7 @@ BCC = $(BCC) /guard:cf -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE # USE_CRT_DLL option is set to force dynamically linking to the # MSVC runtime library. # -!IF $(FOR_WINRT)!=0 || $(FOR_WIN10)!=0 || $(USE_CRT_DLL)!=0 +!IF $(FOR_WINRT)!=0 || $(USE_CRT_DLL)!=0 !IF $(DEBUG)>1 TCC = $(TCC) -MDd BCC = $(BCC) -MDd @@ -888,7 +898,8 @@ LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelH LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib !ENDIF -# When compiling for UAP, some extra linker options are also required. +# When compiling for UAP or the Windows 10 platform, some extra +# linker options are also required. # !IF $(FOR_UAP)!=0 || $(FOR_WIN10)!=0 LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib @@ -898,6 +909,15 @@ LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)" !ENDIF !ENDIF +!IF $(FOR_WIN10)!=0 +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(UCRTLIBPATH)" +!IF $(DEBUG)>1 +LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:libucrtd.lib /DEFAULTLIB:ucrtd.lib +!ELSE +LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:libucrt.lib /DEFAULTLIB:ucrt.lib +!ENDIF +!ENDIF + # If either debugging or symbols are enabled, enable PDBs. # !IF $(DEBUG)>1 || $(SYMBOLS)!=0 diff --git a/manifest b/manifest index 76600b8190..c8a0a95df0 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Further\sstreamlining\sof\sfts5\sprefix\squery\scode. -D 2016-02-05T19:18:02.811 +C More\swork\son\sWindows\s10\sSDK\sintegration. +D 2016-02-05T19:40:23.877 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 +F Makefile.msc 9eadde083c1ef0d0d2a253671c76e0b7e48a3dc6 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -1426,7 +1426,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1cac6c45eeb7dbbcda0c76ba7d3a2ca77bc725cd -R 82ed27d217d52be944f2d4bee3dfe639 -U dan -Z ad1bc1867d7f59ff72d365283a40efbf +P ca91bd8ac70a5b3fef127364f73ec675e58bb92c +R 1ddcbe680d5a6ea9a1dc01ec422c820c +T *branch * win10sdk +T *sym-win10sdk * +T -sym-trunk * +U mistachkin +Z 9a5014635472c911640e985821bf4dea diff --git a/manifest.uuid b/manifest.uuid index 8902cb7ad9..bf7c81653a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ca91bd8ac70a5b3fef127364f73ec675e58bb92c \ No newline at end of file +ebace2c99b6af9230c4bbc31a764c7f397200148 \ No newline at end of file From d120a1e3ab9763ba9c39e08d2b4e6f5f2cfbf346 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 5 Feb 2016 21:09:26 +0000 Subject: [PATCH 232/570] Add tests for and remove unreachable branches from fts5 in order to restore test coverage. FossilOrigin-Name: 22589018ac3321f7bd89ce9fa69e57eae395e324 --- ext/fts5/fts5_buffer.c | 1 - ext/fts5/fts5_index.c | 213 ++++++++++++++++------------------ ext/fts5/fts5_varint.c | 3 + ext/fts5/test/fts5config.test | 4 + manifest | 18 +-- manifest.uuid | 2 +- 6 files changed, 117 insertions(+), 124 deletions(-) diff --git a/ext/fts5/fts5_buffer.c b/ext/fts5/fts5_buffer.c index 878240af4f..c3d4101b8b 100644 --- a/ext/fts5/fts5_buffer.c +++ b/ext/fts5/fts5_buffer.c @@ -236,7 +236,6 @@ int sqlite3Fts5PoslistWriterAppend( Fts5PoslistWriter *pWriter, i64 iPos ){ - static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32; int rc; if( fts5BufferGrow(&rc, pBuf, 5+5+5) ) return rc; sqlite3Fts5PoslistSafeAppend(pBuf, &pWriter->iPrev, iPos); diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 3dd9a9c92d..12e18c6445 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -518,7 +518,6 @@ struct Fts5Iter { int nSeg; /* Size of aSeg[] array */ int bRev; /* True to iterate in reverse order */ u8 bSkipEmpty; /* True to skip deleted entries */ - u8 bFiltered; /* True if column-filter already applied */ i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */ Fts5CResult *aFirst; /* Current merge state (see above) */ @@ -2030,9 +2029,6 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){ iPoslist = 4; } fts5IndexSkipVarint(pLeaf->p, iPoslist); - assert( p->pConfig->eDetail==FTS5_DETAIL_NONE || iPoslist==( - pIter->iLeafOffset - sqlite3Fts5GetVarintLen(pIter->nPos*2+pIter->bDel) - )); pIter->iLeafOffset = iPoslist; /* If this condition is true then the largest rowid for the current @@ -3095,7 +3091,7 @@ static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){ pIter->base.nData = pSeg->nPos; assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE ); - assert( pIter->pColset==0 || pIter->bFiltered ); + assert( pIter->pColset==0 ); if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ /* All data is stored on the current page. Populate the output @@ -3212,7 +3208,7 @@ static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){ pIter->xSetOutputs = fts5IterSetOutputs_None; } - else if( pIter->pColset==0 || pIter->bFiltered ){ + else if( pIter->pColset==0 ){ pIter->xSetOutputs = fts5IterSetOutputs_Nocolset; } @@ -3359,7 +3355,6 @@ static void fts5MultiIterNew2( if( pNew ){ Fts5SegIter *pIter = &pNew->aSeg[1]; - pNew->bFiltered = 1; pIter->flags = FTS5_SEGITER_ONETERM; if( pData->szLeaf>0 ){ pIter->pLeaf = pData; @@ -4704,120 +4699,111 @@ static void fts5MergePrefixLists( Fts5Buffer *p1, /* First list to merge */ Fts5Buffer *p2 /* Second list to merge */ ){ - if( p2->n ){ - if( p1->n==0 ){ - fts5BufferSwap(p1, p2); - }else{ - i64 iLastRowid = 0; - Fts5DoclistIter i1; - Fts5DoclistIter i2; - Fts5Buffer out = {0, 0, 0}; - Fts5Buffer tmp = {0, 0, 0}; + i64 iLastRowid = 0; + Fts5DoclistIter i1; + Fts5DoclistIter i2; + Fts5Buffer out = {0, 0, 0}; + Fts5Buffer tmp = {0, 0, 0}; - if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n) ) return; - fts5DoclistIterInit(p1, &i1); - fts5DoclistIterInit(p2, &i2); + if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n) ) return; + fts5DoclistIterInit(p1, &i1); + fts5DoclistIterInit(p2, &i2); - while( 1 ){ - if( i1.iRowidrc, &tmp, i1.nPoslist + i2.nPoslist); - if( p->rc ) break; - - sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); - sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); - assert( iPos1>=0 && iPos2>=0 ); - - if( iPos1=0 && iPos2>=0 ){ - while( 1 ){ - if( iPos1=0 ){ - if( iPos1!=iPrev ){ - sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); - } - fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1); - } - else if( iPos2>=0 ){ - if( iPos2!=iPrev ){ - sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); - } - fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2); - } - - /* WRITEPOSLISTSIZE */ - fts5BufferSafeAppendVarint(&out, tmp.n * 2); - fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); - fts5DoclistIterNext(&i1); - fts5DoclistIterNext(&i2); - if( i1.aPoslist==0 || i2.aPoslist==0 ) break; - } - } - - if( i1.aPoslist ){ + while( 1 ){ + if( i1.iRowidrc, p1, out.n, out.p); - fts5BufferFree(&tmp); - fts5BufferFree(&out); + i64 iPrev = 0; + Fts5PoslistWriter writer; + memset(&writer, 0, sizeof(writer)); + + fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); + fts5BufferZero(&tmp); + sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist); + if( p->rc ) break; + + sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); + sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); + assert( iPos1>=0 && iPos2>=0 ); + + if( iPos1=0 && iPos2>=0 ){ + while( 1 ){ + if( iPos1=0 ){ + if( iPos1!=iPrev ){ + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); + } + fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1); + }else{ + assert( iPos2>=0 && iPos2!=iPrev ); + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); + fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2); + } + + /* WRITEPOSLISTSIZE */ + fts5BufferSafeAppendVarint(&out, tmp.n * 2); + fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); + fts5DoclistIterNext(&i1); + fts5DoclistIterNext(&i2); + if( i1.aPoslist==0 || i2.aPoslist==0 ) break; + } } + + if( i1.aPoslist ){ + fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid); + fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist); + } + else if( i2.aPoslist ){ + fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); + fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist); + } + + fts5BufferSet(&p->rc, p1, out.n, out.p); + fts5BufferFree(&tmp); + fts5BufferFree(&out); } } @@ -5181,10 +5167,11 @@ int sqlite3Fts5IndexQuery( int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0; buf.p[0] = FTS5_MAIN_PREFIX; fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet); + assert( pRet->pColset==0 ); fts5IterSetOutputCb(&p->rc, pRet); if( p->rc==SQLITE_OK ){ Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst]; - if( p->rc==SQLITE_OK && pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); + if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); } } diff --git a/ext/fts5/fts5_varint.c b/ext/fts5/fts5_varint.c index 21858506ac..bb212ab5a8 100644 --- a/ext/fts5/fts5_varint.c +++ b/ext/fts5/fts5_varint.c @@ -333,7 +333,10 @@ int sqlite3Fts5PutVarint(unsigned char *p, u64 v){ int sqlite3Fts5GetVarintLen(u32 iVal){ +#if 0 if( iVal<(1 << 7 ) ) return 1; +#endif + assert( iVal>=(1 << 7) ); if( iVal<(1 << 14) ) return 2; if( iVal<(1 << 21) ) return 3; if( iVal<(1 << 28) ) return 4; diff --git a/ext/fts5/test/fts5config.test b/ext/fts5/test/fts5config.test index 223e504a65..c30a597242 100644 --- a/ext/fts5/test/fts5config.test +++ b/ext/fts5/test/fts5config.test @@ -243,5 +243,9 @@ foreach {tn opt} { do_catchsql_test 11.$tn "CREATE VIRTUAL TABLE f1 USING fts5(x, $opt)" $res } +do_catchsql_test 12.1 { + INSERT INTO t1(t1, rank) VALUES('rank', NULL);; +} {1 {SQL logic error or missing database}} + finish_test diff --git a/manifest b/manifest index 76600b8190..15c459f19f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\sstreamlining\sof\sfts5\sprefix\squery\scode. -D 2016-02-05T19:18:02.811 +C Add\stests\sfor\sand\sremove\sunreachable\sbranches\sfrom\sfts5\sin\sorder\sto\srestore\stest\scoverage. +D 2016-02-05T21:09:26.310 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -100,11 +100,11 @@ F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 F ext/fts5/fts5Int.h efb02807dbe5a2bfb0ea592a472d1171cb553d53 F ext/fts5/fts5_aux.c b9bcce753ef5b451267b2232f0ca153ddeb3951d -F ext/fts5/fts5_buffer.c ad4bb545c866eea6add1b0f84c2c5029cd689092 +F ext/fts5/fts5_buffer.c 2dac8e23c5b77fccecc234f1a1f37d75113b4e46 F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 F ext/fts5/fts5_expr.c ff5c451a6d025909639ac0f0d0af0cc595b50feb F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c 9706959f2188d97d72df750519fee7baccef9964 +F ext/fts5/fts5_index.c 28f72130400cb54d179a9a120b7232915e3e7a4e F ext/fts5/fts5_main.c 6e23df904049edb498538bd3e22e53ec1ab6f4f7 F ext/fts5/fts5_storage.c 2a1f44deae090cd711f02cec0c2af8e660360d24 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -112,7 +112,7 @@ F ext/fts5/fts5_test_mi.c 1ec66ffdf7632077fbd773b7a6df5153272ec070 F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be F ext/fts5/fts5_tokenize.c 4d5c4f183c7d07d144bc219b92da1ea0e962fae3 F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c -F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1 +F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738 F ext/fts5/fts5_vocab.c 3ef401a8d6932db56368de32f446eb9fe73aa623 F ext/fts5/fts5parse.y 1647eba089b9b3fc058b4dc989d9da87d15b9580 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba @@ -136,7 +136,7 @@ F ext/fts5/test/fts5auxdata.test 141a7cbffcceb1bd2799b4b29c183ff8780d586e F ext/fts5/test/fts5bigpl.test 04ee0d7eebbebf17c31f5a0b5c5f9494eac3a0cb F ext/fts5/test/fts5bigtok.test 981b2790f6fa02773c889bd35d42c6b97f80f0f4 F ext/fts5/test/fts5columnsize.test a8cfef21ffa1c264b9f670a7d94eeaccb5341c07 -F ext/fts5/test/fts5config.test 83941309b94d002ed6f55d9cd814e0353c9ae013 +F ext/fts5/test/fts5config.test 8b2bc6dcc0eb06fa2b7dd65b2ce2db09e829e873 F ext/fts5/test/fts5conflict.test 26f4e46c4d31e16221794832a990dc4e30e18de5 F ext/fts5/test/fts5content.test 9a952c95518a14182dc3b59e3c8fa71cda82a4e1 F ext/fts5/test/fts5corrupt.test c2ad090192708150d50d961278df10ae7a4b8b62 @@ -1426,7 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1cac6c45eeb7dbbcda0c76ba7d3a2ca77bc725cd -R 82ed27d217d52be944f2d4bee3dfe639 +P ca91bd8ac70a5b3fef127364f73ec675e58bb92c +R bc449da6b3e9fd24816f80d5ebb5f8a2 U dan -Z ad1bc1867d7f59ff72d365283a40efbf +Z 6b9788cdb90c1d425a4100a494ea3da5 diff --git a/manifest.uuid b/manifest.uuid index 8902cb7ad9..3643624eee 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ca91bd8ac70a5b3fef127364f73ec675e58bb92c \ No newline at end of file +22589018ac3321f7bd89ce9fa69e57eae395e324 \ No newline at end of file From bb3da060e3d90da84944b1d75df74ce7697d8998 Mon Sep 17 00:00:00 2001 From: pdr Date: Sat, 6 Feb 2016 14:14:43 +0000 Subject: [PATCH 233/570] Fix an assert() to have a test instead of a side effect FossilOrigin-Name: a2952231ac7abe165ed070875728f752ae0be608 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/alter.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 15c459f19f..d6e074a0b5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sfor\sand\sremove\sunreachable\sbranches\sfrom\sfts5\sin\sorder\sto\srestore\stest\scoverage. -D 2016-02-05T21:09:26.310 +C Fix\san\sassert()\sto\shave\sa\stest\sinstead\sof\sa\sside\seffect +D 2016-02-06T14:14:43.463 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -284,7 +284,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c e4a5132e6264e002ab87c268108f416df3f1fb10 +F src/alter.c d50b7dbb49a4affee951301afb76a008463e3625 F src/analyze.c fbf0e80d83cc893734e872f932f249a056b86e11 F src/attach.c c16c2648a577fa3def2adfa48c28901376389bc5 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 @@ -1426,7 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ca91bd8ac70a5b3fef127364f73ec675e58bb92c -R bc449da6b3e9fd24816f80d5ebb5f8a2 -U dan -Z 6b9788cdb90c1d425a4100a494ea3da5 +P 22589018ac3321f7bd89ce9fa69e57eae395e324 +R e3d82b169cbfebcfd4c4fb1447b3dcc4 +U pdr +Z 6e44ca05901e086eb71b8481afaf44d8 diff --git a/manifest.uuid b/manifest.uuid index 3643624eee..4f51f901e5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -22589018ac3321f7bd89ce9fa69e57eae395e324 \ No newline at end of file +a2952231ac7abe165ed070875728f752ae0be608 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 3419059fa2..34ca8abd2c 100644 --- a/src/alter.c +++ b/src/alter.c @@ -695,7 +695,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal); assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); if( rc!=SQLITE_OK ){ - assert( db->mallocFailed = 1 ); + assert( db->mallocFailed == 1 ); return; } if( !pVal ){ From f5818aa560fc463e241bbeeaefba8cfacdd0131f Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 6 Feb 2016 19:48:50 +0000 Subject: [PATCH 234/570] Make sure variable declarations occur at the beginning of blocks, even with SQLITE_DEBUG enabled. FossilOrigin-Name: 2f7778e64d93ef237e23ceac01ea9808df5cf2a1 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/malloc.c | 7 +++++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index d6e074a0b5..098cff6d3a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sassert()\sto\shave\sa\stest\sinstead\sof\sa\sside\seffect -D 2016-02-06T14:14:43.463 +C Make\ssure\svariable\sdeclarations\soccur\sat\sthe\sbeginning\sof\sblocks,\seven\nwith\sSQLITE_DEBUG\senabled. +D 2016-02-06T19:48:50.321 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 @@ -314,7 +314,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b F src/main.c 62b7fe3ed245757d1ff2e6268a7ec0bc30100308 -F src/malloc.c 55ebb1701ebd39985dbcc497aaecb09192b69682 +F src/malloc.c 337e9808b5231855fe28857950f4f60ae42c417f F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 @@ -1426,7 +1426,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 22589018ac3321f7bd89ce9fa69e57eae395e324 -R e3d82b169cbfebcfd4c4fb1447b3dcc4 -U pdr -Z 6e44ca05901e086eb71b8481afaf44d8 +P a2952231ac7abe165ed070875728f752ae0be608 +R da8a8c4dec6af3be8a6f4cff524d4f5f +U drh +Z f3b1e3c58e3e9ab1cb32cfa377da1181 diff --git a/manifest.uuid b/manifest.uuid index 4f51f901e5..c92bb840b3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a2952231ac7abe165ed070875728f752ae0be608 \ No newline at end of file +2f7778e64d93ef237e23ceac01ea9808df5cf2a1 \ No newline at end of file diff --git a/src/malloc.c b/src/malloc.c index 1ff0a5221d..ebe0440350 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -626,11 +626,11 @@ void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ return p; } void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){ +#ifndef SQLITE_OMIT_LOOKASIDE + LookasideSlot *pBuf; assert( db!=0 ); assert( sqlite3_mutex_held(db->mutex) ); assert( db->pnBytesFreed==0 ); -#ifndef SQLITE_OMIT_LOOKASIDE - LookasideSlot *pBuf; if( db->lookaside.bDisable==0 ){ assert( db->mallocFailed==0 ); if( n>db->lookaside.sz ){ @@ -650,6 +650,9 @@ void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){ return 0; } #else + assert( db!=0 ); + assert( sqlite3_mutex_held(db->mutex) ); + assert( db->pnBytesFreed==0 ); if( db->mallocFailed ){ return 0; } From cc5f8a46b975d5afb86bfbe2da2ee7f2d85d7572 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 6 Feb 2016 22:32:06 +0000 Subject: [PATCH 235/570] Add a utility program that looks for assert(), NEVER(), ALWAYS(), and testcase() macros that have side-effects, and reports errors when they are found. Also fix a bug that this utility detected as it was being tested. FossilOrigin-Name: b0b4624fc5d53bb0cc9fae7dad51984837d946ac --- Makefile.in | 8 ++- main.mk | 8 ++- manifest | 19 +++--- manifest.uuid | 2 +- src/btree.c | 15 +++-- src/main.c | 2 +- tool/srcck1.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 192 insertions(+), 19 deletions(-) create mode 100644 tool/srcck1.c diff --git a/Makefile.in b/Makefile.in index a07279c3c9..f0c78a4ee7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -583,6 +583,12 @@ sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) +srcck1$(BEXE): $(TOP)/tool/srcck1.c + $(BCC) -o srcck1$(BEXE) $(TOP)/tool/srcck1.c + +sourcetest: srcck1$(BEXE) sqlite3.c + ./srcck1 sqlite3.c + fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(FUZZERSHELL_OPT) \ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) @@ -1083,7 +1089,7 @@ quicktest: ./testfixture$(TEXE) # This is the common case. Run many tests that do not take too long, # including fuzzcheck, sqlite3_analyzer, and sqldiff tests. # -test: $(TESTPROGS) fastfuzztest +test: $(TESTPROGS) sourcetest fastfuzztest ./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS) # Run a test using valgrind. This can take a really long time diff --git a/main.mk b/main.mk index 1dda2d153f..f4cbbdbb95 100644 --- a/main.mk +++ b/main.mk @@ -480,6 +480,12 @@ sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h $(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB) +srcck1$(EXE): $(TOP)/tool/srcck1.c + $(BCC) -o srcck1$(EXE) $(TOP)/tool/srcck1.c + +sourcetest: srcck1$(EXE) sqlite3.c + ./srcck1 sqlite3.c + fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ $(FUZZERSHELL_OPT) $(TOP)/tool/fuzzershell.c sqlite3.c \ @@ -768,7 +774,7 @@ quicktest: ./testfixture$(EXE) # The default test case. Runs most of the faster standard TCL tests, # and fuzz tests, and sqlite3_analyzer and sqldiff tests. # -test: $(TESTPROGS) fastfuzztest +test: $(TESTPROGS) sourcetest fastfuzztest ./testfixture$(EXE) $(TOP)/test/veryquick.test $(TESTOPTS) # Run a test using valgrind. This can take a really long time diff --git a/manifest b/manifest index 098cff6d3a..9220387b53 100644 --- a/manifest +++ b/manifest @@ -1,6 +1,6 @@ -C Make\ssure\svariable\sdeclarations\soccur\sat\sthe\sbeginning\sof\sblocks,\seven\nwith\sSQLITE_DEBUG\senabled. -D 2016-02-06T19:48:50.321 -F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 +C Add\sa\sutility\sprogram\sthat\slooks\sfor\sassert(),\sNEVER(),\sALWAYS(),\sand\ntestcase()\smacros\sthat\shave\sside-effects,\sand\sreports\serrors\swhen\sthey\sare\nfound.\s\sAlso\sfix\sa\sbug\sthat\sthis\sutility\sdetected\sas\sit\swas\sbeing\stested. +D 2016-02-06T22:32:06.228 +F Makefile.in 0a957a57243a3d55e96b1514e22ffae5db9ea116 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 @@ -272,7 +272,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 960071a0bceb043bc5627573986154f507931f33 +F main.mk f51c0652d2a623160e90a758e01312a6a00f3454 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -291,7 +291,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 0b359bcc2316a57acf12f583253974ad22b4654f +F src/btree.c 4c8caaeed7878aafdb607c3d2bcbc365bb0d19a1 F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 198eaa849c193f28b802ed135b2483c68ef7a35c @@ -313,7 +313,7 @@ F src/insert.c b84359365bace233919db550a15f131923190efc F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b -F src/main.c 62b7fe3ed245757d1ff2e6268a7ec0bc30100308 +F src/main.c b67a45397b93b7ba8fbd6bfcb03423d245baed05 F src/malloc.c 337e9808b5231855fe28857950f4f60ae42c417f F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -1416,6 +1416,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/sqldiff.c 5a26205111e6fa856d9b1535b1637744dcdb930b +F tool/srcck1.c 3119733530abcef14f1b0603c66207a342936263 F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1426,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a2952231ac7abe165ed070875728f752ae0be608 -R da8a8c4dec6af3be8a6f4cff524d4f5f +P 2f7778e64d93ef237e23ceac01ea9808df5cf2a1 +R e75f025e263d6165f7cd0bcd65f5ad12 U drh -Z f3b1e3c58e3e9ab1cb32cfa377da1181 +Z 663376736f9ceb33b8ce1b1cb94df97c diff --git a/manifest.uuid b/manifest.uuid index c92bb840b3..20460304dd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2f7778e64d93ef237e23ceac01ea9808df5cf2a1 \ No newline at end of file +b0b4624fc5d53bb0cc9fae7dad51984837d946ac \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index b99820ddbc..c6f9c34f7b 100644 --- a/src/btree.c +++ b/src/btree.c @@ -6148,7 +6148,7 @@ static int fillInCell( { CellInfo info; pPage->xParseCell(pPage, pCell, &info); - assert( nHeader=(int)(info.pPayload - pCell) ); + assert( nHeader==(int)(info.pPayload - pCell) ); assert( info.nKey==nKey ); assert( *pnSize == info.nSize ); assert( spaceLeft == info.nLocal ); @@ -7807,8 +7807,8 @@ static int balance(BtCursor *pCur){ u8 aBalanceQuickSpace[13]; u8 *pFree = 0; - TESTONLY( int balance_quick_called = 0 ); - TESTONLY( int balance_deeper_called = 0 ); + VVA_ONLY( int balance_quick_called = 0 ); + VVA_ONLY( int balance_deeper_called = 0 ); do { int iPage = pCur->iPage; @@ -7821,7 +7821,8 @@ static int balance(BtCursor *pCur){ ** and copy the current contents of the root-page to it. The ** next iteration of the do-loop will balance the child page. */ - assert( (balance_deeper_called++)==0 ); + assert( balance_deeper_called==0 ); + VVA_ONLY( balance_deeper_called++ ); rc = balance_deeper(pPage, &pCur->apPage[1]); if( rc==SQLITE_OK ){ pCur->iPage = 1; @@ -7860,7 +7861,8 @@ static int balance(BtCursor *pCur){ ** function. If this were not verified, a subtle bug involving reuse ** of the aBalanceQuickSpace[] might sneak in. */ - assert( (balance_quick_called++)==0 ); + assert( balance_quick_called==0 ); + VVA_ONLY( balance_quick_called++ ); rc = balance_quick(pParent, pPage, aBalanceQuickSpace); }else #endif @@ -9327,7 +9329,8 @@ char *sqlite3BtreeIntegrityCheck( sqlite3BtreeEnter(p); assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE ); - assert( (nRef = sqlite3PagerRefcount(pBt->pPager))>=0 ); + VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) ); + assert( nRef>=0 ); sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; sCheck.nPage = btreePagecount(sCheck.pBt); diff --git a/src/main.c b/src/main.c index 588461b48a..922af1315a 100644 --- a/src/main.c +++ b/src/main.c @@ -3566,7 +3566,7 @@ int sqlite3_test_control(int op, ...){ */ case SQLITE_TESTCTRL_ASSERT: { volatile int x = 0; - assert( (x = va_arg(ap,int))!=0 ); + assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 ); rc = x; break; } diff --git a/tool/srcck1.c b/tool/srcck1.c new file mode 100644 index 0000000000..cd4b4990b9 --- /dev/null +++ b/tool/srcck1.c @@ -0,0 +1,157 @@ +/* +** The program does some simple static analysis of the sqlite3.c source +** file looking for mistakes. +** +** Usage: +** +** ./srcck1 sqlite3.c +** +** This program looks for instances of assert(), ALWAYS(), NEVER() or +** testcase() that contain side-effects and reports errors if any such +** instances are found. +** +** The aim of this utility is to prevent recurrences of errors such +** as the one fixed at: +** +** https://www.sqlite.org/src/info/a2952231ac7abe16 +** +** Note that another similar error was found by this utility when it was +** first written. That other error was fixed by the same check-in that +** committed the first version of this utility program. +*/ +#include +#include +#include + +/* Read the complete text of a file into memory. Return a pointer to +** the result. Panic if unable to read the file or allocate memory. +*/ +static char *readFile(const char *zFilename){ + FILE *in; + char *z; + long n; + size_t got; + + in = fopen(zFilename, "rb"); + if( in==0 ){ + fprintf(stderr, "unable to open '%s' for reading\n", zFilename); + exit(1); + } + fseek(in, 0, SEEK_END); + n = ftell(in); + rewind(in); + z = malloc( n+1 ); + if( z==0 ){ + fprintf(stderr, "cannot allocate %d bytes to store '%s'\n", + (int)(n+1), zFilename); + exit(1); + } + got = fread(z, 1, n, in); + fclose(in); + if( got!=(size_t)n ){ + fprintf(stderr, "only read %d of %d bytes from '%s'\n", + (int)got, (int)n, zFilename); + exit(1); + } + z[n] = 0; + return z; +} + +/* Change the C code in the argument to see if it might have +** side effects. The only accurate way to know this is to do a full +** parse of the C code, which this routine does not do. This routine +** uses a simple heuristic of looking for: +** +** * '=' not immediately after '>', '<', '!', or '='. +** * '++' +** * '--' +** +** If the code contains the phrase "side-effects-ok" is inside a +** comment, then always return false. This is used to disable checking +** for assert()s with deliberate side-effects, such as used by +** SQLITE_TESTCTRL_ASSERT - a facility that allows applications to +** determine at runtime whether or not assert()s are enabled. +** Obviously, that determination cannot be made unless the assert() +** has some side-effect. +** +** Return true if a side effect is seen. Return false if not. +*/ +static int hasSideEffect(const char *z, unsigned int n){ + unsigned int i; + for(i=0; i0 && z[i-1]!='=' && z[i-1]!='>' + && z[i-1]!='<' && z[i-1]!='!' && z[i+1]!='=' ) return 1; + if( z[i]=='+' && z[i+1]=='+' ) return 1; + if( z[i]=='-' && z[i+1]=='-' ) return 1; + } + return 0; +} + +/* Return the number of bytes in string z[] prior to the first unmatched ')' +** character. +*/ +static unsigned int findCloseParen(const char *z){ + unsigned int nOpen = 0; + unsigned i; + for(i=0; z[i]; i++){ + if( z[i]=='(' ) nOpen++; + if( z[i]==')' ){ + if( nOpen==0 ) break; + nOpen--; + } + } + return i; +} + +/* Search for instances of assert(...), ALWAYS(...), NEVER(...), and/or +** testcase(...) where the argument contains side effects. +** +** Print error messages whenever a side effect is found. Return the number +** of problems seen. +*/ +static unsigned int findAllSideEffects(const char *z){ + unsigned int lineno = 1; /* Line number */ + unsigned int i; + unsigned int nErr = 0; + char c, prevC = 0; + for(i=0; (c = z[i])!=0; prevC=c, i++){ + if( c=='\n' ){ lineno++; continue; } + if( isalpha(c) && !isalpha(prevC) ){ + if( strncmp(&z[i],"assert(",7)==0 + || strncmp(&z[i],"ALWAYS(",7)==0 + || strncmp(&z[i],"NEVER(",6)==0 + || strncmp(&z[i],"testcase(",9)==0 + ){ + unsigned int j, n; + const char *z2 = &z[i+5]; + while( z2[0]!='(' ){ z2++; } + z2++; + n = findCloseParen(z2); + if( hasSideEffect(z2, n) ){ + nErr++; + fprintf(stderr, "side-effect line %u: %.*s\n", lineno, + (int)(&z2[n+1] - &z[i]), &z[i]); + } + } + } + } + return nErr; +} + +int main(int argc, char **argv){ + char *z; + unsigned int nErr = 0; + if( argc!=2 ){ + fprintf(stderr, "Usage: %s FILENAME\n", argv[0]); + return 1; + } + z = readFile(argv[1]); + nErr = findAllSideEffects(z); + free(z); + if( nErr ){ + fprintf(stderr, "Found %u undesirable side-effects\n", nErr); + return 1; + } + return 0; +} From fd0d93fd71b2c9f1f889bb2e2022a1119a2b52bd Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 7 Feb 2016 00:08:08 +0000 Subject: [PATCH 236/570] Add the sourcetest target to Makefile.msc. FossilOrigin-Name: ab269e720552483c5617906837e294c1be3e0a57 --- Makefile.msc | 10 ++++++++-- manifest | 14 +++++++------- manifest.uuid | 2 +- tool/srcck1.c | 1 + 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 3427b8177a..0ba00d89c7 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1393,6 +1393,12 @@ $(SQLITE3EXE): $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_S sqldiff.exe: $(TOP)\tool\sqldiff.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) +srcck1.exe: $(TOP)\tool\srcck1.c + $(BCC) $(NO_WARN) -Fe$@ $(TOP)\tool\srcck1.c + +sourcetest: srcck1.exe sqlite3.c + srcck1.exe sqlite3.c + fuzzershell.exe: $(TOP)\tool\fuzzershell.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) $(TOP)\tool\fuzzershell.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) @@ -1916,14 +1922,14 @@ fastfuzztest: fuzzcheck.exe # Minimal testing that runs in less than 3 minutes (on a fast machine) # -quicktest: testfixture.exe +quicktest: testfixture.exe sourcetest @set PATH=$(LIBTCLPATH);$(PATH) .\testfixture.exe $(TOP)\test\extraquick.test $(TESTOPTS) # This is the common case. Run many tests that do not take too long, # including fuzzcheck, sqlite3_analyzer, and sqldiff tests. # -test: $(TESTPROGS) fastfuzztest +test: $(TESTPROGS) sourcetest fastfuzztest @set PATH=$(LIBTCLPATH);$(PATH) .\testfixture.exe $(TOP)\test\veryquick.test $(TESTOPTS) diff --git a/manifest b/manifest index 9220387b53..3a81b43628 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Add\sa\sutility\sprogram\sthat\slooks\sfor\sassert(),\sNEVER(),\sALWAYS(),\sand\ntestcase()\smacros\sthat\shave\sside-effects,\sand\sreports\serrors\swhen\sthey\sare\nfound.\s\sAlso\sfix\sa\sbug\sthat\sthis\sutility\sdetected\sas\sit\swas\sbeing\stested. -D 2016-02-06T22:32:06.228 +C Add\sthe\ssourcetest\starget\sto\sMakefile.msc. +D 2016-02-07T00:08:08.480 F Makefile.in 0a957a57243a3d55e96b1514e22ffae5db9ea116 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845 +F Makefile.msc a3f8092763bb5d0057f0f4feb6b7fcc19713e107 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -1416,7 +1416,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/sqldiff.c 5a26205111e6fa856d9b1535b1637744dcdb930b -F tool/srcck1.c 3119733530abcef14f1b0603c66207a342936263 +F tool/srcck1.c 0522865656ed7f89a8acdcfa6ba2d4f898f4e55c F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2f7778e64d93ef237e23ceac01ea9808df5cf2a1 -R e75f025e263d6165f7cd0bcd65f5ad12 +P b0b4624fc5d53bb0cc9fae7dad51984837d946ac +R 08c9d9815def36a9ada11c24d7dc13cb U drh -Z 663376736f9ceb33b8ce1b1cb94df97c +Z 21cfff4994071e02bdb1eef8143a0ef4 diff --git a/manifest.uuid b/manifest.uuid index 20460304dd..16127e2758 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b0b4624fc5d53bb0cc9fae7dad51984837d946ac \ No newline at end of file +ab269e720552483c5617906837e294c1be3e0a57 \ No newline at end of file diff --git a/tool/srcck1.c b/tool/srcck1.c index cd4b4990b9..ae19fbebaa 100644 --- a/tool/srcck1.c +++ b/tool/srcck1.c @@ -22,6 +22,7 @@ #include #include #include +#include /* Read the complete text of a file into memory. Return a pointer to ** the result. Panic if unable to read the file or allocate memory. From 27b6997e9cec6ef3a27e54925db1e377a2903e75 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sun, 7 Feb 2016 20:39:27 +0000 Subject: [PATCH 237/570] Fix harmless compiler warning in 'srcck1' tool and add it to the clean targets. FossilOrigin-Name: 852a529a8b112049f67a3126f677c06ae4a22d73 --- Makefile.in | 1 + Makefile.msc | 2 +- main.mk | 1 + manifest | 20 ++++++++++---------- manifest.uuid | 2 +- tool/srcck1.c | 2 +- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Makefile.in b/Makefile.in index f0c78a4ee7..54f7643327 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1225,6 +1225,7 @@ clean: rm -f sqlite-*-output.vsix rm -f mptester mptester.exe rm -f rbu rbu.exe + rm -f srcck1 srcck1.exe rm -f fuzzershell fuzzershell.exe rm -f fuzzcheck fuzzcheck.exe rm -f sqldiff sqldiff.exe diff --git a/Makefile.msc b/Makefile.msc index 0ba00d89c7..aacacbcec3 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -2016,7 +2016,7 @@ clean: del /Q testfixture.exe test.db 2>NUL del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL - del /Q mptester.exe wordcount.exe rbu.exe 2>NUL + del /Q mptester.exe wordcount.exe rbu.exe srcck1.exe 2>NUL del /Q $(SQLITE3EXE) $(SQLITE3DLL) sqlite3.def 2>NUL del /Q sqlite3.c sqlite3-*.c 2>NUL del /Q sqlite3rc.h 2>NUL diff --git a/main.mk b/main.mk index f4cbbdbb95..149f94e209 100644 --- a/main.mk +++ b/main.mk @@ -899,6 +899,7 @@ clean: rm -f speedtest1 speedtest1.exe rm -f wordcount wordcount.exe rm -f rbu rbu.exe + rm -f srcck1 srcck1.exe rm -f sqlite3.c sqlite3-*.c fts?amal.c tclsqlite3.c rm -f sqlite3rc.h rm -f shell.c sqlite3ext.h diff --git a/manifest b/manifest index 3a81b43628..dbd577f123 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Add\sthe\ssourcetest\starget\sto\sMakefile.msc. -D 2016-02-07T00:08:08.480 -F Makefile.in 0a957a57243a3d55e96b1514e22ffae5db9ea116 +C Fix\sharmless\scompiler\swarning\sin\s'srcck1'\stool\sand\sadd\sit\sto\sthe\sclean\stargets. +D 2016-02-07T20:39:27.144 +F Makefile.in dac2776c84e0d533b158a9af6e57e05c4a6b19f3 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc a3f8092763bb5d0057f0f4feb6b7fcc19713e107 +F Makefile.msc fcf377286d910b47e072da1ac7945976337c0925 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -272,7 +272,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk f51c0652d2a623160e90a758e01312a6a00f3454 +F main.mk 37497b06d3e3acb2c71675d76627a3b2639c6db0 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -1416,7 +1416,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/sqldiff.c 5a26205111e6fa856d9b1535b1637744dcdb930b -F tool/srcck1.c 0522865656ed7f89a8acdcfa6ba2d4f898f4e55c +F tool/srcck1.c 4c39bdfa9a92edd20233ee720df84dbeb2417602 F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b0b4624fc5d53bb0cc9fae7dad51984837d946ac -R 08c9d9815def36a9ada11c24d7dc13cb -U drh -Z 21cfff4994071e02bdb1eef8143a0ef4 +P ab269e720552483c5617906837e294c1be3e0a57 +R b0244c1b9f3d2cf89729e9f132d42a5e +U mistachkin +Z 9a8eb772a0a9cfffcb8487b60e9945a2 diff --git a/manifest.uuid b/manifest.uuid index 16127e2758..3f741fdf8b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ab269e720552483c5617906837e294c1be3e0a57 \ No newline at end of file +852a529a8b112049f67a3126f677c06ae4a22d73 \ No newline at end of file diff --git a/tool/srcck1.c b/tool/srcck1.c index ae19fbebaa..e95765185f 100644 --- a/tool/srcck1.c +++ b/tool/srcck1.c @@ -124,7 +124,7 @@ static unsigned int findAllSideEffects(const char *z){ || strncmp(&z[i],"NEVER(",6)==0 || strncmp(&z[i],"testcase(",9)==0 ){ - unsigned int j, n; + unsigned int n; const char *z2 = &z[i+5]; while( z2[0]!='(' ){ z2++; } z2++; From 8974331fc35a22b48ccf1ca2c709890646f10a3d Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 8 Feb 2016 02:30:50 +0000 Subject: [PATCH 238/570] Demonstrate a much faster sqlite3GetToken() routine by using a lookup table to map initial token characters into a character class. This check-in does not work for EBCDIC. More optimization needed. FossilOrigin-Name: 9115baa1919584dc8ca25bbff54d3b65748a9631 --- manifest | 15 +++--- manifest.uuid | 2 +- src/tokenize.c | 133 ++++++++++++++++++++++++++++++++++--------------- 3 files changed, 102 insertions(+), 48 deletions(-) diff --git a/manifest b/manifest index 3a81b43628..3badb22032 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssourcetest\starget\sto\sMakefile.msc. -D 2016-02-07T00:08:08.480 +C Demonstrate\sa\smuch\sfaster\ssqlite3GetToken()\sroutine\sby\susing\sa\slookup\stable\nto\smap\sinitial\stoken\scharacters\sinto\sa\scharacter\sclass.\s\sThis\scheck-in\sdoes\nnot\swork\sfor\sEBCDIC.\s\sMore\soptimization\sneeded. +D 2016-02-08T02:30:50.194 F Makefile.in 0a957a57243a3d55e96b1514e22ffae5db9ea116 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc a3f8092763bb5d0057f0f4feb6b7fcc19713e107 @@ -406,7 +406,7 @@ F src/test_windirent.c 8f5fada630348558d5745b334702f301da1ffc61 F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 -F src/tokenize.c 214b783d6138e9f9fbb6b225ce9a376db3b03d42 +F src/tokenize.c b3cfc123d65a5bf7ba615f74f28737ae2135620a F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c 310ca7adb86a7d1f2afae46905b21c83580f3e17 @@ -1427,7 +1427,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b0b4624fc5d53bb0cc9fae7dad51984837d946ac -R 08c9d9815def36a9ada11c24d7dc13cb +P ab269e720552483c5617906837e294c1be3e0a57 +R de21eeb460827c84c88aec10967c3b1d +T *branch * tokenizer-char-class +T *sym-tokenizer-char-class * +T -sym-trunk * U drh -Z 21cfff4994071e02bdb1eef8143a0ef4 +Z 8982f608f7ca1f17154501e0dba47865 diff --git a/manifest.uuid b/manifest.uuid index 16127e2758..9b08cb07e9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ab269e720552483c5617906837e294c1be3e0a57 \ No newline at end of file +9115baa1919584dc8ca25bbff54d3b65748a9631 \ No newline at end of file diff --git a/src/tokenize.c b/src/tokenize.c index 5bee3d5a84..c4b36c4758 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -18,6 +18,56 @@ #include "sqliteInt.h" #include +/* Character classes for tokenizing */ +#define CC_X 0 /* The letter 'x' or 'X'. Start of x'01234fed' */ +#define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */ +#define CC_ID 2 /* unicode characters usable in IDs */ +#define CC_DIGIT 3 /* Digits */ +#define CC_DOLLAR 4 /* '$' */ +#define CC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */ +#define CC_VARNUM 6 /* '?'. Numeric SQL variables */ +#define CC_SPACE 7 /* Space characters */ +#define CC_QUOTE 8 /* '"', '\'', or '`'. String literals, quoted ids */ +#define CC_QUOTE2 9 /* '['. [...] style quoted ids */ +#define CC_PIPE 10 /* '|'. Bitwise OR or concatenate */ +#define CC_MINUS 11 /* '-'. Minus or SQL-style comment */ +#define CC_LT 12 /* '<'. Part of < or <= or <> */ +#define CC_GT 13 /* '>'. Part of > or >= */ +#define CC_EQ 14 /* '='. Part of = or == */ +#define CC_BANG 15 /* '!'. Part of != */ +#define CC_SLASH 16 /* '/'. / or c-style comment */ +#define CC_LP 17 /* '(' */ +#define CC_RP 18 /* ')' */ +#define CC_SEMI 19 /* ';' */ +#define CC_PLUS 20 /* '+' */ +#define CC_STAR 21 /* '*' */ +#define CC_PERCENT 22 /* '%' */ +#define CC_COMMA 23 /* ',' */ +#define CC_AND 24 /* '&' */ +#define CC_TILDA 25 /* '~' */ +#define CC_DOT 26 /* '.' */ +#define CC_ILLEGAL 27 /* Illegal character */ + +static const unsigned char aiClass[] = { +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ +/* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27, +/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16, +/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6, +/* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1, +/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27, +/* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* Bx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* Cx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + /* ** The charMap() macro maps alphabetic characters into their ** lower-case ASCII equivalent. On ASCII machines, this is just @@ -115,8 +165,8 @@ int sqlite3IsIdChar(u8 c){ return IdChar(c); } */ int sqlite3GetToken(const unsigned char *z, int *tokenType){ int i, c; - switch( *z ){ - case ' ': case '\t': case '\n': case '\f': case '\r': { + switch( aiClass[*z] ){ + case CC_SPACE: { testcase( z[0]==' ' ); testcase( z[0]=='\t' ); testcase( z[0]=='\n' ); @@ -126,7 +176,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ *tokenType = TK_SPACE; return i; } - case '-': { + case CC_MINUS: { if( z[1]=='-' ){ for(i=2; (c=z[i])!=0 && c!='\n'; i++){} *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ @@ -135,27 +185,27 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ *tokenType = TK_MINUS; return 1; } - case '(': { + case CC_LP: { *tokenType = TK_LP; return 1; } - case ')': { + case CC_RP: { *tokenType = TK_RP; return 1; } - case ';': { + case CC_SEMI: { *tokenType = TK_SEMI; return 1; } - case '+': { + case CC_PLUS: { *tokenType = TK_PLUS; return 1; } - case '*': { + case CC_STAR: { *tokenType = TK_STAR; return 1; } - case '/': { + case CC_SLASH: { if( z[1]!='*' || z[2]==0 ){ *tokenType = TK_SLASH; return 1; @@ -165,15 +215,15 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ return i; } - case '%': { + case CC_PERCENT: { *tokenType = TK_REM; return 1; } - case '=': { + case CC_EQ: { *tokenType = TK_EQ; return 1 + (z[1]=='='); } - case '<': { + case CC_LT: { if( (c=z[1])=='=' ){ *tokenType = TK_LE; return 2; @@ -188,7 +238,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ return 1; } } - case '>': { + case CC_GT: { if( (c=z[1])=='=' ){ *tokenType = TK_GE; return 2; @@ -200,7 +250,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ return 1; } } - case '!': { + case CC_BANG: { if( z[1]!='=' ){ *tokenType = TK_ILLEGAL; return 2; @@ -209,7 +259,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ return 2; } } - case '|': { + case CC_PIPE: { if( z[1]!='|' ){ *tokenType = TK_BITOR; return 1; @@ -218,21 +268,19 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ return 2; } } - case ',': { + case CC_COMMA: { *tokenType = TK_COMMA; return 1; } - case '&': { + case CC_AND: { *tokenType = TK_BITAND; return 1; } - case '~': { + case CC_TILDA: { *tokenType = TK_BITNOT; return 1; } - case '`': - case '\'': - case '"': { + case CC_QUOTE: { int delim = z[0]; testcase( delim=='`' ); testcase( delim=='\'' ); @@ -257,7 +305,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ return i; } } - case '.': { + case CC_DOT: { #ifndef SQLITE_OMIT_FLOATING_POINT if( !sqlite3Isdigit(z[1]) ) #endif @@ -268,8 +316,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ /* If the next character is a digit, this is a floating point ** number that begins with ".". Fall thru into the next case */ } - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { + case CC_DIGIT: { testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); @@ -304,22 +351,18 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ } return i; } - case '[': { + case CC_QUOTE2: { for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} *tokenType = c==']' ? TK_ID : TK_ILLEGAL; return i; } - case '?': { + case CC_VARNUM: { *tokenType = TK_VARIABLE; for(i=1; sqlite3Isdigit(z[i]); i++){} return i; } -#ifndef SQLITE_OMIT_TCL_VARIABLE - case '$': -#endif - case '@': /* For compatibility with MS SQL Server */ - case '#': - case ':': { + case CC_DOLLAR: + case CC_VARALPHA: { int n = 0; testcase( z[0]=='$' ); testcase( z[0]=='@' ); testcase( z[0]==':' ); testcase( z[0]=='#' ); @@ -349,7 +392,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ return i; } #ifndef SQLITE_OMIT_BLOB_LITERAL - case 'x': case 'X': { + case CC_X: { testcase( z[0]=='x' ); testcase( z[0]=='X' ); if( z[1]=='\'' ){ *tokenType = TK_BLOB; @@ -361,20 +404,28 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ if( z[i] ) i++; return i; } - /* Otherwise fall through to the next case */ + i = 1; + break; } #endif - default: { - if( !IdChar(*z) ){ - break; - } - for(i=1; IdChar(z[i]); i++){} + case CC_KYWD: { + for(i=1; aiClass[z[i]]<=CC_KYWD; i++){} + if( aiClass[z[i]]<=CC_DOLLAR ){ i++; break; } *tokenType = TK_ID; return keywordCode((char*)z, i, tokenType); } + case CC_ID: { + i = 1; + break; + } + default: { + *tokenType = TK_ILLEGAL; + return 1; + } } - *tokenType = TK_ILLEGAL; - return 1; + while( aiClass[z[i]]<=CC_DOLLAR ){ i++; } + *tokenType = TK_ID; + return i; } /* From 41aab89b3123f9b7ffcb59d3e57528c88d2f50eb Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 8 Feb 2016 03:23:46 +0000 Subject: [PATCH 239/570] Faster keywordCode() implementation by taking advantage of the fact that the input is always pure ASCII alphabetic and underscore and that the keyword table is always upper-case. FossilOrigin-Name: ff406b9701ebe3a01834837f380641c6f0c495bc --- manifest | 15 ++++++--------- manifest.uuid | 2 +- tool/mkkeywordhash.c | 17 ++++++++++------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index 3badb22032..a3d1184319 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Demonstrate\sa\smuch\sfaster\ssqlite3GetToken()\sroutine\sby\susing\sa\slookup\stable\nto\smap\sinitial\stoken\scharacters\sinto\sa\scharacter\sclass.\s\sThis\scheck-in\sdoes\nnot\swork\sfor\sEBCDIC.\s\sMore\soptimization\sneeded. -D 2016-02-08T02:30:50.194 +C Faster\skeywordCode()\simplementation\sby\staking\sadvantage\sof\sthe\sfact\sthat\nthe\sinput\sis\salways\spure\sASCII\salphabetic\sand\sunderscore\sand\sthat\sthe\skeyword\ntable\sis\salways\supper-case. +D 2016-02-08T03:23:46.173 F Makefile.in 0a957a57243a3d55e96b1514e22ffae5db9ea116 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc a3f8092763bb5d0057f0f4feb6b7fcc19713e107 @@ -1383,7 +1383,7 @@ F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh a29b14d54302b33fd892958f6895582ea90e4a45 -F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8 +F tool/mkkeywordhash.c 4451824f4f68f8e8d89eba080e0c1a9cf83f7b62 F tool/mkmsvcmin.tcl d57e6efc9428605f5418d0b235721ddf7b5d9c0b F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 385c62d78c38b2d92146dcb5abd319dbbc33506d @@ -1427,10 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ab269e720552483c5617906837e294c1be3e0a57 -R de21eeb460827c84c88aec10967c3b1d -T *branch * tokenizer-char-class -T *sym-tokenizer-char-class * -T -sym-trunk * +P 9115baa1919584dc8ca25bbff54d3b65748a9631 +R b013689cd0826a67d194ddf9700064de U drh -Z 8982f608f7ca1f17154501e0dba47865 +Z b5dc027d5e497c867b371327464bbd96 diff --git a/manifest.uuid b/manifest.uuid index 9b08cb07e9..290fa630a8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9115baa1919584dc8ca25bbff54d3b65748a9631 \ No newline at end of file +ff406b9701ebe3a01834837f380641c6f0c495bc \ No newline at end of file diff --git a/tool/mkkeywordhash.c b/tool/mkkeywordhash.c index 003ed7d66e..43455ef97c 100644 --- a/tool/mkkeywordhash.c +++ b/tool/mkkeywordhash.c @@ -565,20 +565,23 @@ int main(int argc, char **argv){ } printf("%s };\n", j==0 ? "" : "\n"); - printf(" int h, i;\n"); + printf(" int h, i, j;\n"); + printf(" const char *zKW;\n"); printf(" if( n>=2 ){\n"); printf(" h = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) %% %d;\n", bestSize); printf(" for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){\n"); - printf(" if( aLen[i]==n &&" - " sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){\n"); + printf(" if( aLen[i]!=n ) continue;\n"); + printf(" j = 0;\n"); + printf(" zKW = &zText[aOffset[i]];\n"); + printf(" while( j Date: Mon, 8 Feb 2016 19:15:48 +0000 Subject: [PATCH 240/570] Add code to get the tokenizer character-class logic working for EBCDIC. FossilOrigin-Name: 04f7da77c13925c1f1e287f4579bb85518297d81 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/tokenize.c | 42 ++++++++++++++++++++++++++++++++++++------ tool/mkkeywordhash.c | 16 ++++++++++++---- 4 files changed, 56 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index a3d1184319..180d6f2232 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Faster\skeywordCode()\simplementation\sby\staking\sadvantage\sof\sthe\sfact\sthat\nthe\sinput\sis\salways\spure\sASCII\salphabetic\sand\sunderscore\sand\sthat\sthe\skeyword\ntable\sis\salways\supper-case. -D 2016-02-08T03:23:46.173 +C Add\scode\sto\sget\sthe\stokenizer\scharacter-class\slogic\sworking\sfor\sEBCDIC. +D 2016-02-08T19:15:48.295 F Makefile.in 0a957a57243a3d55e96b1514e22ffae5db9ea116 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc a3f8092763bb5d0057f0f4feb6b7fcc19713e107 @@ -406,7 +406,7 @@ F src/test_windirent.c 8f5fada630348558d5745b334702f301da1ffc61 F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 -F src/tokenize.c b3cfc123d65a5bf7ba615f74f28737ae2135620a +F src/tokenize.c 5019666f8705e9f7135c6f1c1ffac95a1af76fa6 F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c 310ca7adb86a7d1f2afae46905b21c83580f3e17 @@ -1383,7 +1383,7 @@ F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh a29b14d54302b33fd892958f6895582ea90e4a45 -F tool/mkkeywordhash.c 4451824f4f68f8e8d89eba080e0c1a9cf83f7b62 +F tool/mkkeywordhash.c f7f3b342211ac6a14258b9726d5b97cf4f548f22 F tool/mkmsvcmin.tcl d57e6efc9428605f5418d0b235721ddf7b5d9c0b F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 385c62d78c38b2d92146dcb5abd319dbbc33506d @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9115baa1919584dc8ca25bbff54d3b65748a9631 -R b013689cd0826a67d194ddf9700064de +P ff406b9701ebe3a01834837f380641c6f0c495bc +R f322e625886c02a1fcd0df28b2c76f16 U drh -Z b5dc027d5e497c867b371327464bbd96 +Z 8351e730f91ff26fa5b93d74f8f175a3 diff --git a/manifest.uuid b/manifest.uuid index 290fa630a8..96aac98d14 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ff406b9701ebe3a01834837f380641c6f0c495bc \ No newline at end of file +04f7da77c13925c1f1e287f4579bb85518297d81 \ No newline at end of file diff --git a/src/tokenize.c b/src/tokenize.c index c4b36c4758..68e7b45172 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -18,7 +18,14 @@ #include "sqliteInt.h" #include -/* Character classes for tokenizing */ +/* Character classes for tokenizing +** +** In the sqlite3GetToken() function, a switch() on aiClass[c] is implemented +** using a lookup table, whereas a switch() directly on c uses a binary search. +** The lookup table is much faster. To maximize speed, and to ensure that +** a lookup table is used, all of the classes need to be small integers and +** all of them need to be used within the switch. +*/ #define CC_X 0 /* The letter 'x' or 'X'. Start of x'01234fed' */ #define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */ #define CC_ID 2 /* unicode characters usable in IDs */ @@ -49,6 +56,7 @@ #define CC_ILLEGAL 27 /* Illegal character */ static const unsigned char aiClass[] = { +#ifdef SQLITE_ASCII /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ /* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27, /* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, @@ -66,14 +74,36 @@ static const unsigned char aiClass[] = { /* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +#endif +#ifdef SQLITE_EBCDIC +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ +/* 0x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 7, 7, 27, 27, +/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +/* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +/* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 12, 17, 20, 10, +/* 5x */ 24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15, 4, 21, 18, 19, 27, +/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 7, +/* 7x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 8, 5, 5, 5, 8, 14, 8, +/* 8x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, +/* 9x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, +/* 9x */ 25, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, +/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 27, 27, 27, 27, 27, +/* Cx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, +/* Dx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, +/* Ex */ 27, 27, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, +/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27, 27, +#endif }; /* -** The charMap() macro maps alphabetic characters into their +** The charMap() macro maps alphabetic characters (only) into their ** lower-case ASCII equivalent. On ASCII machines, this is just ** an upper-to-lower case map. On EBCDIC machines we also need -** to adjust the encoding. Only alphabetic characters and underscores -** need to be translated. +** to adjust the encoding. The mapping is only valid for alphabetics +** which are the only characters for which this feature is used. +** +** Used by keywordhash.h */ #ifdef SQLITE_ASCII # define charMap(X) sqlite3UpperToLower[(unsigned char)X] @@ -410,7 +440,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ #endif case CC_KYWD: { for(i=1; aiClass[z[i]]<=CC_KYWD; i++){} - if( aiClass[z[i]]<=CC_DOLLAR ){ i++; break; } + if( IdChar(z[i]) ){ i++; break; } *tokenType = TK_ID; return keywordCode((char*)z, i, tokenType); } @@ -423,7 +453,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ return 1; } } - while( aiClass[z[i]]<=CC_DOLLAR ){ i++; } + while( IdChar(z[i]) ){ i++; } *tokenType = TK_ID; return i; } diff --git a/tool/mkkeywordhash.c b/tool/mkkeywordhash.c index 43455ef97c..7e5287ea54 100644 --- a/tool/mkkeywordhash.c +++ b/tool/mkkeywordhash.c @@ -277,7 +277,10 @@ static Keyword aKeywordTable[] = { /* Number of keywords */ static int nKeyword = (sizeof(aKeywordTable)/sizeof(aKeywordTable[0])); -/* Map all alphabetic characters into the same case */ +/* Map all alphabetic characters into lower-case for hashing. This is +** only valid for alphabetics. In particular it does not work for '_' +** and so the hash cannot be on a keyword position that might be an '_'. +*/ #define charMap(X) (0x20|(X)) /* @@ -565,16 +568,21 @@ int main(int argc, char **argv){ } printf("%s };\n", j==0 ? "" : "\n"); - printf(" int h, i, j;\n"); + printf(" int i, j;\n"); printf(" const char *zKW;\n"); printf(" if( n>=2 ){\n"); - printf(" h = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) %% %d;\n", + printf(" i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) %% %d;\n", bestSize); - printf(" for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){\n"); + printf(" for(i=((int)aHash[i])-1; i>=0; i=((int)aNext[i])-1){\n"); printf(" if( aLen[i]!=n ) continue;\n"); printf(" j = 0;\n"); printf(" zKW = &zText[aOffset[i]];\n"); + printf("#ifdef SQLITE_ASCII\n"); printf(" while( j Date: Mon, 8 Feb 2016 19:40:17 +0000 Subject: [PATCH 241/570] Disable the two-argument form of the fts3_tokenizer() SQL function unless the library is built with -DSQLITE_ENABLE_FTS3_TOKENIZER. FossilOrigin-Name: e0eb217aca7e4aadf9c44ed20822b78139f7c83c --- ext/fts3/fts3_tokenizer.c | 12 ++++- manifest | 21 ++++---- manifest.uuid | 2 +- src/test_config.c | 6 +++ test/fts3atoken.test | 110 ++++++++++++++++++++------------------ test/fts4langid.test | 46 ++++++++-------- 6 files changed, 111 insertions(+), 86 deletions(-) diff --git a/ext/fts3/fts3_tokenizer.c b/ext/fts3/fts3_tokenizer.c index 64cfe07aac..26bac57648 100644 --- a/ext/fts3/fts3_tokenizer.c +++ b/ext/fts3/fts3_tokenizer.c @@ -67,6 +67,7 @@ static void scalarFunc( nName = sqlite3_value_bytes(argv[0])+1; if( argc==2 ){ +#ifdef SQLITE_ENABLE_FTS3_TOKENIZER void *pOld; int n = sqlite3_value_bytes(argv[1]); if( zName==0 || n!=sizeof(pPtr) ){ @@ -79,7 +80,14 @@ static void scalarFunc( sqlite3_result_error(context, "out of memory", -1); return; } - }else{ +#else + sqlite3_result_error(context, "fts3tokenize: " + "disabled - rebuild with -DSQLITE_ENABLE_FTS3_TOKENIZER", -1 + ); + return; +#endif /* SQLITE_ENABLE_FTS3_TOKENIZER */ + }else + { if( zName ){ pPtr = sqlite3Fts3HashFind(pHash, zName, nName); } @@ -420,11 +428,13 @@ static void intTestFunc( assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") ); /* Test the storage function */ +#ifdef SQLITE_ENABLE_FTS3_TOKENIZER rc = registerTokenizer(db, "nosuchtokenizer", p1); assert( rc==SQLITE_OK ); rc = queryTokenizer(db, "nosuchtokenizer", &p2); assert( rc==SQLITE_OK ); assert( p2==p1 ); +#endif sqlite3_result_text(context, "ok", -1, SQLITE_STATIC); } diff --git a/manifest b/manifest index 2902207223..2ad9b86f00 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Changes\sto\shelp\sthe\stokenizer\srun\sabout\s33%\sfaster. -D 2016-02-08T19:36:46.659 +C Disable\sthe\stwo-argument\sform\sof\sthe\sfts3_tokenizer()\sSQL\sfunction\sunless\sthe\slibrary\sis\sbuilt\swith\s-DSQLITE_ENABLE_FTS3_TOKENIZER. +D 2016-02-08T19:40:17.991 F Makefile.in dac2776c84e0d533b158a9af6e57e05c4a6b19f3 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fcf377286d910b47e072da1ac7945976337c0925 @@ -83,7 +83,7 @@ F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7 F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038 F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860 -F ext/fts3/fts3_tokenizer.c 50e7a69a549ac5882cc1971ee43f66aaabc11395 +F ext/fts3/fts3_tokenizer.c 0d3a77bbdc6f394d302f24980fa80667371c6e68 F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145 @@ -372,7 +372,7 @@ F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f -F src/test_config.c 0dee90328e3dedf8ba002ee94b6a7e7ea7726fe4 +F src/test_config.c 7985332c806d1cece793475c75a6abcccde9d331 F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_fs.c a61f54247fdb843761d709879c3bcd1989b2050c @@ -697,7 +697,7 @@ F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8 F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18 F test/fts3ao.test 3e4e3d5e75c076520341d0bdf4eb17c00e8cbde2 -F test/fts3atoken.test e3a126365131a6db52efc20a9a6053cd44e5f289 +F test/fts3atoken.test 76262be798f23a390717d14266f0df551e52a7ee F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9 F test/fts3aux1.test f8f287a4a73f381f8fa15b6a70f36245f903d221 F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba @@ -744,7 +744,7 @@ F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01 F test/fts4growth.test 60d6bb3f78e25b34f533797dd9f2f9402310a13a F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269 F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d -F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7 +F test/fts4langid.test 8bd8759e0d4b04d71771544b861193a6841fee84 F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891 F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7 @@ -1427,8 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 852a529a8b112049f67a3126f677c06ae4a22d73 04f7da77c13925c1f1e287f4579bb85518297d81 -R 64edf86f87d772039cf70265114474cb -T +closed 04f7da77c13925c1f1e287f4579bb85518297d81 -U drh -Z feb6daf33d3b967be60d8c209f5e5987 +P a050e6f096d40aa5b6275797b96e62c228044f5a +R b09b6ba902e95153c88d724675282802 +U dan +Z a5b8919de2cf0c2997cac75a4e3c3a2c diff --git a/manifest.uuid b/manifest.uuid index dc1ddc7e40..fcaa3cc3b9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a050e6f096d40aa5b6275797b96e62c228044f5a \ No newline at end of file +e0eb217aca7e4aadf9c44ed20822b78139f7c83c \ No newline at end of file diff --git a/src/test_config.c b/src/test_config.c index 30b421e00b..5db7117555 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -370,6 +370,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "fts3", "0", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_FTS3_TOKENIZER + Tcl_SetVar2(interp, "sqlite_options", "fts3_tokenizer", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "fts3_tokenizer", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_ENABLE_FTS5 Tcl_SetVar2(interp, "sqlite_options", "fts5", "1", TCL_GLOBAL_ONLY); #else diff --git a/test/fts3atoken.test b/test/fts3atoken.test index 88e3d4f72b..2cdea79a98 100644 --- a/test/fts3atoken.test +++ b/test/fts3atoken.test @@ -24,7 +24,7 @@ ifcapable !fts3 { return } -set ::testprefix fts3token +set ::testprefix fts3atoken proc escape_string {str} { set out "" @@ -40,7 +40,7 @@ proc escape_string {str} { } #-------------------------------------------------------------------------- -# Test cases fts3token-1.* are the warm-body test for the SQL scalar +# Test cases fts3atoken-1.* are the warm-body test for the SQL scalar # function fts3_tokenizer(). The procedure is as follows: # # 1: Verify that there is no such fts3 tokenizer as 'blah'. @@ -56,62 +56,68 @@ proc escape_string {str} { # # 5: Test that the table created to use tokenizer 'blah' is usable. # -do_test fts3token-1.1 { - catchsql { - CREATE VIRTUAL TABLE t1 USING fts3(content, tokenize blah); - } -} {1 {unknown tokenizer: blah}} -do_test fts3token-1.2 { - execsql { +ifcapable fts3_tokenizer { + do_test fts3atoken-1.1 { + catchsql { + CREATE VIRTUAL TABLE t1 USING fts3(content, tokenize blah); + } + } {1 {unknown tokenizer: blah}} + do_test fts3atoken-1.2 { + execsql { + SELECT fts3_tokenizer('blah', fts3_tokenizer('simple')) IS NULL; + } + } {0} + do_test fts3atoken-1.3 { + execsql { + SELECT fts3_tokenizer('blah') == fts3_tokenizer('simple'); + } + } {1} + do_test fts3atoken-1.4 { + catchsql { + CREATE VIRTUAL TABLE t1 USING fts3(content, tokenize blah); + } + } {0 {}} + do_test fts3atoken-1.5 { + execsql { + INSERT INTO t1(content) VALUES('There was movement at the station'); + INSERT INTO t1(content) VALUES('For the word has passed around'); + INSERT INTO t1(content) VALUES('That the colt from ol regret had got'); + SELECT content FROM t1 WHERE content MATCH 'movement' + } + } {{There was movement at the station}} +} else { + do_catchsql_test 1.6 { SELECT fts3_tokenizer('blah', fts3_tokenizer('simple')) IS NULL; - } -} {0} -do_test fts3token-1.3 { - execsql { - SELECT fts3_tokenizer('blah') == fts3_tokenizer('simple'); - } -} {1} -do_test fts3token-1.4 { - catchsql { - CREATE VIRTUAL TABLE t1 USING fts3(content, tokenize blah); - } -} {0 {}} -do_test fts3token-1.5 { - execsql { - INSERT INTO t1(content) VALUES('There was movement at the station'); - INSERT INTO t1(content) VALUES('For the word has passed around'); - INSERT INTO t1(content) VALUES('That the colt from ol regret had got away'); - SELECT content FROM t1 WHERE content MATCH 'movement' - } -} {{There was movement at the station}} + } {1 {fts3tokenize: disabled - rebuild with -DSQLITE_ENABLE_FTS3_TOKENIZER}} +} #-------------------------------------------------------------------------- -# Test cases fts3token-2.* test error cases in the scalar function based +# Test cases fts3atoken-2.* test error cases in the scalar function based # API for getting and setting tokenizers. # -do_test fts3token-2.1 { +do_test fts3atoken-2.1 { catchsql { SELECT fts3_tokenizer('nosuchtokenizer'); } } {1 {unknown tokenizer: nosuchtokenizer}} #-------------------------------------------------------------------------- -# Test cases fts3token-3.* test the three built-in tokenizers with a +# Test cases fts3atoken-3.* test the three built-in tokenizers with a # simple input string via the built-in test function. This is as much # to test the test function as the tokenizer implementations. # -do_test fts3token-3.1 { +do_test fts3atoken-3.1 { execsql { SELECT fts3_tokenizer_test('simple', 'I don''t see how'); } } {{0 i I 1 don don 2 t t 3 see see 4 how how}} -do_test fts3token-3.2 { +do_test fts3atoken-3.2 { execsql { SELECT fts3_tokenizer_test('porter', 'I don''t see how'); } } {{0 i I 1 don don 2 t t 3 see see 4 how how}} ifcapable icu { - do_test fts3token-3.3 { + do_test fts3atoken-3.3 { execsql { SELECT fts3_tokenizer_test('icu', 'I don''t see how'); } @@ -119,7 +125,7 @@ ifcapable icu { } #-------------------------------------------------------------------------- -# Test cases fts3token-4.* test the ICU tokenizer. In practice, this +# Test cases fts3atoken-4.* test the ICU tokenizer. In practice, this # tokenizer only has two modes - "thai" and "everybody else". Some other # Asian languages (Lao, Khmer etc.) require the same special treatment as # Thai, but ICU doesn't support them yet. @@ -133,8 +139,8 @@ ifcapable icu { } $output } - do_icu_test fts3token-4.1 en_US {} {} - do_icu_test fts3token-4.2 en_US {Test cases fts3} [list \ + do_icu_test fts3atoken-4.1 en_US {} {} + do_icu_test fts3atoken-4.2 en_US {Test cases fts3} [list \ 0 test Test 1 cases cases 2 fts3 fts3 ] @@ -147,12 +153,12 @@ ifcapable icu { append output "1 \u0e19\u0e30 \u0e19\u0e30 " append output "2 \u0e04\u0e23\u0e31\u0e1a \u0e04\u0e23\u0e31\u0e1a" - do_icu_test fts3token-4.3 th_TH $input $output - do_icu_test fts3token-4.4 en_US $input $output + do_icu_test fts3atoken-4.3 th_TH $input $output + do_icu_test fts3atoken-4.4 en_US $input $output # ICU handles an unknown locale by falling back to the default. # So this is not an error. - do_icu_test fts3token-4.5 MiddleOfTheOcean $input $output + do_icu_test fts3atoken-4.5 MiddleOfTheOcean $input $output set longtoken "AReallyReallyLongTokenOneThatWillSurelyRequire" append longtoken "AReallocInTheIcuTokenizerCode" @@ -164,9 +170,9 @@ ifcapable icu { append output "2 then then " append output "3 [string tolower $longtoken] $longtoken" - do_icu_test fts3token-4.6 MiddleOfTheOcean $input $output - do_icu_test fts3token-4.7 th_TH $input $output - do_icu_test fts3token-4.8 en_US $input $output + do_icu_test fts3atoken-4.6 MiddleOfTheOcean $input $output + do_icu_test fts3atoken-4.7 th_TH $input $output + do_icu_test fts3atoken-4.8 en_US $input $output do_execsql_test 5.1 { CREATE VIRTUAL TABLE x1 USING fts3(name,TOKENIZE icu en_US); @@ -186,7 +192,7 @@ ifcapable icu { } {} } -do_test fts3token-internal { +do_test fts3atoken-internal { execsql { SELECT fts3_tokenizer_internal_test() } } {ok} @@ -206,12 +212,14 @@ do_catchsql_test 6.1.3 { do_catchsql_test 6.2.1 { SELECT fts3_tokenizer(NULL); } {1 {unknown tokenizer: }} -do_catchsql_test 6.2.2 { - SELECT fts3_tokenizer(NULL, X'1234567812345678'); -} {1 {argument type mismatch}} -do_catchsql_test 6.2.3 { - SELECT fts3_tokenizer(NULL, X'12345678'); -} {1 {argument type mismatch}} +ifcapable fts3_tokenizer { + do_catchsql_test 6.2.2 { + SELECT fts3_tokenizer(NULL, X'1234567812345678'); + } {1 {argument type mismatch}} + do_catchsql_test 6.2.3 { + SELECT fts3_tokenizer(NULL, X'12345678'); + } {1 {argument type mismatch}} +} finish_test diff --git a/test/fts4langid.test b/test/fts4langid.test index 843e11f9ab..a3059931e7 100644 --- a/test/fts4langid.test +++ b/test/fts4langid.test @@ -358,29 +358,31 @@ proc build_multilingual_db_2 {db} { } } -do_test 4.1.0 { - reset_db - set ptr [fts3_test_tokenizer] - execsql { SELECT fts3_tokenizer('testtokenizer', $ptr) } - build_multilingual_db_2 db -} {} -do_execsql_test 4.1.1 { - SELECT docid FROM t4 WHERE t4 MATCH 'quick'; -} {0} -do_execsql_test 4.1.2 { - SELECT docid FROM t4 WHERE t4 MATCH 'quick' AND lid=1; -} {} -do_execsql_test 4.1.3 { - SELECT docid FROM t4 WHERE t4 MATCH 'Quick' AND lid=1; -} {1} -for {set i 0} {$i < 50} {incr i} { - do_execsql_test 4.1.4.$i { - SELECT count(*) FROM t4 WHERE t4 MATCH 'fox' AND lid=$i; - } [expr 0==($i%2)] +ifcapable fts3_tokenizer { + do_test 4.1.0 { + reset_db + set ptr [fts3_test_tokenizer] + execsql { SELECT fts3_tokenizer('testtokenizer', $ptr) } + build_multilingual_db_2 db + } {} + do_execsql_test 4.1.1 { + SELECT docid FROM t4 WHERE t4 MATCH 'quick'; + } {0} + do_execsql_test 4.1.2 { + SELECT docid FROM t4 WHERE t4 MATCH 'quick' AND lid=1; + } {} + do_execsql_test 4.1.3 { + SELECT docid FROM t4 WHERE t4 MATCH 'Quick' AND lid=1; + } {1} + for {set i 0} {$i < 50} {incr i} { + do_execsql_test 4.1.4.$i { + SELECT count(*) FROM t4 WHERE t4 MATCH 'fox' AND lid=$i; + } [expr 0==($i%2)] + } + do_catchsql_test 4.1.5 { + INSERT INTO t4(content, lid) VALUES('hello world', 101) + } {1 {SQL logic error or missing database}} } -do_catchsql_test 4.1.5 { - INSERT INTO t4(content, lid) VALUES('hello world', 101) -} {1 {SQL logic error or missing database}} #------------------------------------------------------------------------- # Test cases 5.* From 83d7920e551c33cf93c8104cf44fc23117b5414b Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 8 Feb 2016 20:06:52 +0000 Subject: [PATCH 242/570] Fix a compiler warning when compiling without SQLITE_ENABLE_FTS3_TOKENIZER. FossilOrigin-Name: 6926f28cd56bf61f7c92877baa54024bee7cbab5 --- ext/fts3/fts3_tokenizer.c | 3 +++ manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ext/fts3/fts3_tokenizer.c b/ext/fts3/fts3_tokenizer.c index 26bac57648..fcabe5cca2 100644 --- a/ext/fts3/fts3_tokenizer.c +++ b/ext/fts3/fts3_tokenizer.c @@ -336,6 +336,7 @@ finish: Tcl_DecrRefCount(pRet); } +#ifdef SQLITE_ENABLE_FTS3_TOKENIZER static int registerTokenizer( sqlite3 *db, @@ -357,6 +358,8 @@ int registerTokenizer( return sqlite3_finalize(pStmt); } +#endif /* SQLITE_ENABLE_FTS3_TOKENIZER */ + static int queryTokenizer( diff --git a/manifest b/manifest index 2ad9b86f00..7b991aaa7c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Disable\sthe\stwo-argument\sform\sof\sthe\sfts3_tokenizer()\sSQL\sfunction\sunless\sthe\slibrary\sis\sbuilt\swith\s-DSQLITE_ENABLE_FTS3_TOKENIZER. -D 2016-02-08T19:40:17.991 +C Fix\sa\scompiler\swarning\swhen\scompiling\swithout\sSQLITE_ENABLE_FTS3_TOKENIZER. +D 2016-02-08T20:06:52.183 F Makefile.in dac2776c84e0d533b158a9af6e57e05c4a6b19f3 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fcf377286d910b47e072da1ac7945976337c0925 @@ -83,7 +83,7 @@ F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7 F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038 F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860 -F ext/fts3/fts3_tokenizer.c 0d3a77bbdc6f394d302f24980fa80667371c6e68 +F ext/fts3/fts3_tokenizer.c 4bd72f767f61c9ce5a7575c844e8d1ed2c3c561a F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a050e6f096d40aa5b6275797b96e62c228044f5a -R b09b6ba902e95153c88d724675282802 -U dan -Z a5b8919de2cf0c2997cac75a4e3c3a2c +P e0eb217aca7e4aadf9c44ed20822b78139f7c83c +R 3ba2bfd061690101a8667e8fadcc2696 +U drh +Z 2da14d7bb409b5abdcdd912d6af6bf8a diff --git a/manifest.uuid b/manifest.uuid index fcaa3cc3b9..116910222d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e0eb217aca7e4aadf9c44ed20822b78139f7c83c \ No newline at end of file +6926f28cd56bf61f7c92877baa54024bee7cbab5 \ No newline at end of file From c2d0b56e6a7fd298113e857df6012e21189dfa13 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 8 Feb 2016 20:14:41 +0000 Subject: [PATCH 243/570] Fix a signed/unsigned comparison warning in fts5. FossilOrigin-Name: 85eb05ddbc3a7cff986af13c3dab6c0063e62171 --- ext/fts5/fts5_buffer.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/fts5/fts5_buffer.c b/ext/fts5/fts5_buffer.c index c3d4101b8b..c552e860eb 100644 --- a/ext/fts5/fts5_buffer.c +++ b/ext/fts5/fts5_buffer.c @@ -16,7 +16,7 @@ #include "fts5Int.h" int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){ - if( pBuf->nSpacenSpacenSpace ? pBuf->nSpace : 64; u8 *pNew; while( nNew Date: Mon, 8 Feb 2016 20:45:37 +0000 Subject: [PATCH 244/570] Fix spelling error in MSVC makefile comments. FossilOrigin-Name: 6eab74c9ae57676044b5bc82fa14e92fd2448008 --- Makefile.msc | 8 ++++---- autoconf/Makefile.msc | 8 ++++---- manifest | 15 +++++++-------- manifest.uuid | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 8d416b77cb..9620ff6237 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -306,7 +306,7 @@ LD = link.exe RC = rc.exe !ENDIF -# Check for the MSVC runtime library path macro. Othertise, this value will +# Check for the MSVC runtime library path macro. Otherwise, this value will # default to the 'lib' directory underneath the MSVC installation directory. # !IFNDEF CRTLIBPATH @@ -343,7 +343,7 @@ NCC = $(NCC:\\=\) NCC = $(CC) !ENDIF -# Check for the MSVC native runtime library path macro. Othertise, +# Check for the MSVC native runtime library path macro. Otherwise, # this value will default to the 'lib' directory underneath the MSVC # installation directory. # @@ -353,7 +353,7 @@ NCRTLIBPATH = $(VCINSTALLDIR)\lib NCRTLIBPATH = $(NCRTLIBPATH:\\=\) -# Check for the Platform SDK library path macro. Othertise, this +# Check for the Platform SDK library path macro. Otherwise, this # value will default to the 'lib' directory underneath the Windows # SDK installation directory (the environment variable used appears # to be available when using Visual C++ 2008 or later via the @@ -365,7 +365,7 @@ NSDKLIBPATH = $(WINDOWSSDKDIR)\lib NSDKLIBPATH = $(NSDKLIBPATH:\\=\) -# Check for the UCRT library path macro. Othertise, this value will +# Check for the UCRT library path macro. Otherwise, this value will # default to the version-specific, platform-specific 'lib' directory # underneath the Windows SDK installation directory. # diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index a4f916f5a7..65f2396180 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -291,7 +291,7 @@ LD = link.exe RC = rc.exe !ENDIF -# Check for the MSVC runtime library path macro. Othertise, this value will +# Check for the MSVC runtime library path macro. Otherwise, this value will # default to the 'lib' directory underneath the MSVC installation directory. # !IFNDEF CRTLIBPATH @@ -328,7 +328,7 @@ NCC = $(NCC:\\=\) NCC = $(CC) !ENDIF -# Check for the MSVC native runtime library path macro. Othertise, +# Check for the MSVC native runtime library path macro. Otherwise, # this value will default to the 'lib' directory underneath the MSVC # installation directory. # @@ -338,7 +338,7 @@ NCRTLIBPATH = $(VCINSTALLDIR)\lib NCRTLIBPATH = $(NCRTLIBPATH:\\=\) -# Check for the Platform SDK library path macro. Othertise, this +# Check for the Platform SDK library path macro. Otherwise, this # value will default to the 'lib' directory underneath the Windows # SDK installation directory (the environment variable used appears # to be available when using Visual C++ 2008 or later via the @@ -350,7 +350,7 @@ NSDKLIBPATH = $(WINDOWSSDKDIR)\lib NSDKLIBPATH = $(NSDKLIBPATH:\\=\) -# Check for the UCRT library path macro. Othertise, this value will +# Check for the UCRT library path macro. Otherwise, this value will # default to the version-specific, platform-specific 'lib' directory # underneath the Windows SDK installation directory. # diff --git a/manifest b/manifest index 24eebb58a9..23d68d6a6c 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C More\swork\son\sWindows\s10\sSDK\sintegration. -D 2016-02-08T20:40:57.726 +C Fix\sspelling\serror\sin\sMSVC\smakefile\scomments. +D 2016-02-08T20:45:37.407 F Makefile.in dac2776c84e0d533b158a9af6e57e05c4a6b19f3 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 8514a6d7c15fa179b45da902a4ddcf0a8e6748b2 +F Makefile.msc b0493f10caddb8adf992a4e6f1943141fc7c6816 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -11,7 +11,7 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 1c1657650775960804945dc392e14d9e43c5ed84 -F autoconf/Makefile.msc de6d40e0c495d761b9813ccb20a649841f6d6b72 +F autoconf/Makefile.msc a35b2aab24d1603f3f0ae65cf01686c2578d319c F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt e9757a381e5ce2553dbaa6247bb8ad00eb8d87aa F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8 @@ -1427,8 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 85eb05ddbc3a7cff986af13c3dab6c0063e62171 ebace2c99b6af9230c4bbc31a764c7f397200148 -R 7f11f3c1dcb5601b2c82dcb73372e020 -T +closed ebace2c99b6af9230c4bbc31a764c7f397200148 +P 1e563c6ebbb02d2e89760c7a7f95aa69964629c6 +R 8450aebd4fe3e5df6689a15f6b4c74a5 U mistachkin -Z ac6553c79aaf86d7e04ebeafa308be17 +Z fa8db5a9236f4356c9f0e0ef9af9fdef diff --git a/manifest.uuid b/manifest.uuid index 583f181cdb..def0c6f083 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1e563c6ebbb02d2e89760c7a7f95aa69964629c6 \ No newline at end of file +6eab74c9ae57676044b5bc82fa14e92fd2448008 \ No newline at end of file From 2fade2f7913f948a6b2ad92e2e0e557de53937fe Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 9 Feb 2016 02:12:20 +0000 Subject: [PATCH 245/570] Make sure every co-routines has its own set of temporary registers and does not share temporaries, since a co-routine might expect the content of a temporary register to be preserved across an OP_Yield. Proposed fix for ticket [d06a25c84454a]. FossilOrigin-Name: ca72be8618e5d466d6f35819ca8bbd2b84269959 --- manifest | 24 ++++++++++++------------ manifest.uuid | 2 +- src/build.c | 2 +- src/insert.c | 2 +- src/select.c | 6 +++--- src/vdbe.h | 1 + src/vdbeaux.c | 15 +++++++++++++++ test/select4.test | 20 ++++++++++++++++++++ 8 files changed, 54 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index 23d68d6a6c..69b6e1ba9f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sspelling\serror\sin\sMSVC\smakefile\scomments. -D 2016-02-08T20:45:37.407 +C Make\ssure\severy\sco-routines\shas\sits\sown\sset\sof\stemporary\sregisters\sand\sdoes\nnot\sshare\stemporaries,\ssince\sa\sco-routine\smight\sexpect\sthe\scontent\sof\sa\ntemporary\sregister\sto\sbe\spreserved\sacross\san\sOP_Yield.\nProposed\sfix\sfor\sticket\s[d06a25c84454a]. +D 2016-02-09T02:12:20.490 F Makefile.in dac2776c84e0d533b158a9af6e57e05c4a6b19f3 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc b0493f10caddb8adf992a4e6f1943141fc7c6816 @@ -294,7 +294,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 4c8caaeed7878aafdb607c3d2bcbc365bb0d19a1 F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 198eaa849c193f28b802ed135b2483c68ef7a35c +F src/build.c 54866fbafa09d494269bdefc79995eb7207003a6 F src/callback.c ed6c2a4a712eb7287ff64e20e3c23265dfb8a7ce F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -309,7 +309,7 @@ F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c b84359365bace233919db550a15f131923190efc +F src/insert.c 046199e085e69e05af7bef197d53c5b4b402b6fa F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b @@ -348,7 +348,7 @@ F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e -F src/select.c 57646a44ba9a0bc4aa926ae9c79b8199c246844b +F src/select.c ff80004a9a6ece891a8d9327a88e7b6e2588ee6d F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -414,10 +414,10 @@ F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 F src/util.c 49ce0a65306c1c51d61cb5bc214c71cb62452de6 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 F src/vdbe.c c193299e595a13eba247738e22fce25c49346a6c -F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 +F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 F src/vdbeapi.c 9324f6baee1a1b2284c6543e98f916888a81e459 -F src/vdbeaux.c 49b536284c2b8a823dd342d653e18145ca2b393a +F src/vdbeaux.c deae5d3bd45da0e57c7d9e1d7436333d142dc3bb F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c 68fcfac37dc6601d98c32cc5adee4d39f2c1b7b4 F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 @@ -992,7 +992,7 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5 F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686 F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56 F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054 -F test/select4.test 6d5bc6d178a367e8b48fa1c1d3ea12cae9c2d650 +F test/select4.test 453631158540e5f685b81cac5b7e8bd8c6b4c5fc F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535 F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0 F test/select7.test 95e370c42d47c3c52377d05e9ffc01ccff7c1f61 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1e563c6ebbb02d2e89760c7a7f95aa69964629c6 -R 8450aebd4fe3e5df6689a15f6b4c74a5 -U mistachkin -Z fa8db5a9236f4356c9f0e0ef9af9fdef +P 6eab74c9ae57676044b5bc82fa14e92fd2448008 +R 28a5285fd29b59b5a769fa2b98c8137d +U drh +Z 50a93197f1857fe46bad3c49957d1f43 diff --git a/manifest.uuid b/manifest.uuid index def0c6f083..9e7ed6ea08 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6eab74c9ae57676044b5bc82fa14e92fd2448008 \ No newline at end of file +ca72be8618e5d466d6f35819ca8bbd2b84269959 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 476fc28c41..250dc20d20 100644 --- a/src/build.c +++ b/src/build.c @@ -1954,7 +1954,7 @@ void sqlite3EndTable( sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); sqlite3Select(pParse, pSelect, &dest); - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); + sqlite3VdbeEndCoroutine(v, regYield); sqlite3VdbeJumpHere(v, addrTop - 1); if( pParse->nErr ) return; pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); diff --git a/src/insert.c b/src/insert.c index 729e0fedce..650f397de0 100644 --- a/src/insert.c +++ b/src/insert.c @@ -685,7 +685,7 @@ void sqlite3Insert( rc = sqlite3Select(pParse, pSelect, &dest); regFromSelect = dest.iSdst; if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup; - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); + sqlite3VdbeEndCoroutine(v, regYield); sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ assert( pSelect->pEList ); nColumn = pSelect->pEList->nExpr; diff --git a/src/select.c b/src/select.c index ea3e920b9f..c3132c2325 100644 --- a/src/select.c +++ b/src/select.c @@ -2952,7 +2952,7 @@ static int multiSelectOrderBy( pPrior->iLimit = regLimitA; explainSetInteger(iSub1, pParse->iNextSelectId); sqlite3Select(pParse, pPrior, &destA); - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrA); + sqlite3VdbeEndCoroutine(v, regAddrA); sqlite3VdbeJumpHere(v, addr1); /* Generate a coroutine to evaluate the SELECT statement on @@ -2969,7 +2969,7 @@ static int multiSelectOrderBy( sqlite3Select(pParse, p, &destB); p->iLimit = savedLimit; p->iOffset = savedOffset; - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrB); + sqlite3VdbeEndCoroutine(v, regAddrB); /* Generate a subroutine that outputs the current row of the A ** select as the next output row of the compound select. @@ -4990,7 +4990,7 @@ int sqlite3Select( pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow); pItem->fg.viaCoroutine = 1; pItem->regResult = dest.iSdst; - sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn); + sqlite3VdbeEndCoroutine(v, pItem->regReturn); sqlite3VdbeJumpHere(v, addrTop-1); sqlite3ClearTempRegCache(pParse); }else{ diff --git a/src/vdbe.h b/src/vdbe.h index f09997bf94..4c02f5844d 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -180,6 +180,7 @@ int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int); int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); +void sqlite3VdbeEndCoroutine(Vdbe*,int); #if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS) void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N); #else diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 8eb3141daf..ce98edd0a5 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -324,6 +324,21 @@ int sqlite3VdbeAddOp4Int( return addr; } +/* Insert the end of a co-routine +*/ +void sqlite3VdbeEndCoroutine(Vdbe *v, int regYield){ + sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); + + /* Clear the temporary register cache, thereby ensuring that each + ** co-routine has its own independent set of registers, because co-routines + ** might expect their registers to be preserved across an OP_Yield, and + ** that could cause problems if two or more co-routines are using the same + ** temporary register. + */ + v->pParse->nTempReg = 0; + v->pParse->nRangeReg = 0; +} + /* ** Create a new symbolic label for an instruction that has yet to be ** coded. The symbolic label is really just a negative number. The diff --git a/test/select4.test b/test/select4.test index a7b1af20a5..be8d0e0ab1 100644 --- a/test/select4.test +++ b/test/select4.test @@ -916,4 +916,24 @@ do_execsql_test select4-14.17 { VALUES(1),(2),(3),(4) UNION ALL SELECT 5 LIMIT 3; } {1 2 3} +# Ticket https://www.sqlite.org/src/info/d06a25c84454a372 +# Incorrect answer due to two co-routines using the same registers and expecting +# those register values to be preserved across a Yield. +# +do_execsql_test select4-15.1 { + DROP TABLE IF EXISTS tx; + CREATE TABLE tx(id INTEGER PRIMARY KEY, a, b); + INSERT INTO tx(a,b) VALUES(33,456); + INSERT INTO tx(a,b) VALUES(33,789); + + SELECT DISTINCT t0.id, t0.a, t0.b + FROM tx AS t0, tx AS t1 + WHERE t0.a=t1.a AND t1.a=33 AND t0.b=456 + UNION + SELECT DISTINCT t0.id, t0.a, t0.b + FROM tx AS t0, tx AS t1 + WHERE t0.a=t1.a AND t1.a=33 AND t0.b=789 + ORDER BY 1; +} {1 33 456 2 33 789} + finish_test From bbde018230ece9d3af08a45594527c10377f2c25 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 9 Feb 2016 16:09:22 +0000 Subject: [PATCH 246/570] Code simplification: ALTER TABLE ADD COLUMN always upgrades the file_format to 4 if is not there already. No need to upgrade to only 2 or 3 since format 4 has now been supported for over 10 years. FossilOrigin-Name: e1d8ec85546caeca3bb7a05ad962a2aed91194ce --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/alter.c | 40 ++++++++++------------------------------ src/sqliteInt.h | 1 - test/alter3.test | 12 ++++++------ 5 files changed, 25 insertions(+), 46 deletions(-) diff --git a/manifest b/manifest index 69b6e1ba9f..ed8c28e037 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\severy\sco-routines\shas\sits\sown\sset\sof\stemporary\sregisters\sand\sdoes\nnot\sshare\stemporaries,\ssince\sa\sco-routine\smight\sexpect\sthe\scontent\sof\sa\ntemporary\sregister\sto\sbe\spreserved\sacross\san\sOP_Yield.\nProposed\sfix\sfor\sticket\s[d06a25c84454a]. -D 2016-02-09T02:12:20.490 +C Code\ssimplification:\s\sALTER\sTABLE\sADD\sCOLUMN\salways\supgrades\sthe\sfile_format\nto\s4\sif\sis\snot\sthere\salready.\s\sNo\sneed\sto\supgrade\sto\sonly\s2\sor\s3\ssince\sformat\n4\shas\snow\sbeen\ssupported\sfor\sover\s10\syears. +D 2016-02-09T16:09:22.275 F Makefile.in dac2776c84e0d533b158a9af6e57e05c4a6b19f3 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc b0493f10caddb8adf992a4e6f1943141fc7c6816 @@ -284,7 +284,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c d50b7dbb49a4affee951301afb76a008463e3625 +F src/alter.c 1fbb01c26c64528088f1df8015992fefda387889 F src/analyze.c fbf0e80d83cc893734e872f932f249a056b86e11 F src/attach.c c16c2648a577fa3def2adfa48c28901376389bc5 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 @@ -353,7 +353,7 @@ F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 3aeaff9611acd790c8e76719b33db09ab885d537 +F src/sqliteInt.h b1850d30a1333de1df076eca979683f696f9d4b4 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -439,7 +439,7 @@ F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783 F test/alter.test 2facdddf08d0d48e75dc6cc312cd2b030f4835dd F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060 -F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d +F test/alter3.test b3568d11c38c4599c92f24242eda34144d78dc10 F test/alter4.test c461150723ac957f3b2214aa0b11552cd72023ec F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 6eab74c9ae57676044b5bc82fa14e92fd2448008 -R 28a5285fd29b59b5a769fa2b98c8137d +P ca72be8618e5d466d6f35819ca8bbd2b84269959 +R f95e307a4f6313b9df891047976f580b U drh -Z 50a93197f1857fe46bad3c49957d1f43 +Z 5769e00c07411a2161fa568f8263dd90 diff --git a/manifest.uuid b/manifest.uuid index 9e7ed6ea08..df0fc10065 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ca72be8618e5d466d6f35819ca8bbd2b84269959 \ No newline at end of file +e1d8ec85546caeca3bb7a05ad962a2aed91194ce \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 34ca8abd2c..34221777a7 100644 --- a/src/alter.c +++ b/src/alter.c @@ -588,33 +588,6 @@ exit_rename_table: db->flags = savedDbFlags; } - -/* -** Generate code to make sure the file format number is at least minFormat. -** The generated code will increase the file format number if necessary. -*/ -void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ - Vdbe *v; - v = sqlite3GetVdbe(pParse); - /* The VDBE should have been allocated before this routine is called. - ** If that allocation failed, we would have quit before reaching this - ** point */ - if( ALWAYS(v) ){ - int r1 = sqlite3GetTempReg(pParse); - int r2 = sqlite3GetTempReg(pParse); - int addr1; - sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); - sqlite3VdbeUsesBtree(v, iDb); - sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); - addr1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); - sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, minFormat); - sqlite3VdbeJumpHere(v, addr1); - sqlite3ReleaseTempReg(pParse, r1); - sqlite3ReleaseTempReg(pParse, r2); - } -} - /* ** This function is called after an "ALTER TABLE ... ADD" statement ** has been parsed. Argument pColDef contains the text of the new @@ -633,9 +606,11 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ Column *pCol; /* The new column */ Expr *pDflt; /* Default value for the new column */ sqlite3 *db; /* The database connection; */ + Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */ db = pParse->db; if( pParse->nErr || db->mallocFailed ) return; + assert( v!=0 ); pNew = pParse->pNewTable; assert( pNew ); @@ -725,11 +700,16 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ db->flags = savedDbFlags; } - /* If the default value of the new column is NULL, then set the file + /* If the default value of the new column is NULL, then the file ** format to 2. If the default value of the new column is not NULL, - ** the file format becomes 3. + ** the file format be 3. Back when this feature was first added + ** in 2006, we went to the trouble to upgrade the file format to the + ** minimum support values. But 10-years on, we can assume that all + ** extent versions of SQLite support file-format 4, so we always and + ** unconditionally upgrade to 4. */ - sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, + SQLITE_MAX_FILE_FORMAT); /* Reload the schema of the modified table. */ reloadTableSchema(pParse, pTab, pTab->zName); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 760c1f4d21..f86e9da653 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3764,7 +3764,6 @@ void sqlite3DeleteIndexSamples(sqlite3*,Index*); void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); -void sqlite3MinimumFileFormat(Parse*, int, int); void sqlite3SchemaClear(void *); Schema *sqlite3SchemaGet(sqlite3 *, Btree *); int sqlite3SchemaToIndex(sqlite3 *db, Schema *); diff --git a/test/alter3.test b/test/alter3.test index 28d293e24b..f8ebe056f2 100644 --- a/test/alter3.test +++ b/test/alter3.test @@ -184,7 +184,7 @@ do_test alter3-3.2 { if {!$has_codec} { do_test alter3-3.3 { get_file_format - } {3} + } {4} } ifcapable schema_version { do_test alter3-3.4 { @@ -220,7 +220,7 @@ do_test alter3-4.2 { if {!$has_codec} { do_test alter3-4.3 { get_file_format - } {3} + } {4} } ifcapable schema_version { do_test alter3-4.4 { @@ -270,7 +270,7 @@ ifcapable attach { if {!$has_codec} { do_test alter3-5.5 { list [get_file_format test2.db] [get_file_format] - } {2 3} + } {4 4} } do_test alter3-5.6 { execsql { @@ -347,19 +347,19 @@ if {!$has_codec} { ALTER TABLE abc ADD d DEFAULT NULL; } get_file_format - } {2} + } {4} do_test alter3-7.3 { execsql { ALTER TABLE abc ADD e DEFAULT 10; } get_file_format - } {3} + } {4} do_test alter3-7.4 { execsql { ALTER TABLE abc ADD f DEFAULT NULL; } get_file_format - } {3} + } {4} do_test alter3-7.5 { execsql { VACUUM; From 74cf74ab7ffd242073ed6f8096c1ab8b99e500ae Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 9 Feb 2016 17:12:22 +0000 Subject: [PATCH 247/570] Fix the top-level makefiles to always include SQLITE_ENABLE_EXPLAIN_COMMENTS when building the shell. Still need to fix main.mk and the amalgamation tarball. FossilOrigin-Name: 992282399cd2d1fc52ff5a1a4bff59f30b62899a --- Makefile.in | 7 ++++--- Makefile.msc | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Makefile.in b/Makefile.in index 54f7643327..e1293d69fa 100644 --- a/Makefile.in +++ b/Makefile.in @@ -549,7 +549,8 @@ TESTOPTS = --verbose=file --output=test-out.txt # Extra compiler options for various shell tools # -SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 +SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 +SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 @@ -575,9 +576,9 @@ libtclsqlite3.la: tclsqlite.lo libsqlite3.la -version-info "8:6:8" \ -avoid-version -sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h +sqlite3$(TEXE): $(TOP)/src/shell.c sqlite3.c $(LTLINK) $(READLINE_FLAGS) $(SHELL_OPT) -o $@ \ - $(TOP)/src/shell.c libsqlite3.la \ + $(TOP)/src/shell.c sqlite3.c \ $(LIBREADLINE) $(TLIBS) -rpath "$(libdir)" sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h diff --git a/Makefile.msc b/Makefile.msc index 9620ff6237..94e78b2169 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1359,7 +1359,7 @@ FUZZDATA = \ # when the shell is not being dynamically linked. # !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 -SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 +SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS !ENDIF # <> diff --git a/manifest b/manifest index ed8c28e037..c320d4221b 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Code\ssimplification:\s\sALTER\sTABLE\sADD\sCOLUMN\salways\supgrades\sthe\sfile_format\nto\s4\sif\sis\snot\sthere\salready.\s\sNo\sneed\sto\supgrade\sto\sonly\s2\sor\s3\ssince\sformat\n4\shas\snow\sbeen\ssupported\sfor\sover\s10\syears. -D 2016-02-09T16:09:22.275 -F Makefile.in dac2776c84e0d533b158a9af6e57e05c4a6b19f3 +C Fix\sthe\stop-level\smakefiles\sto\salways\sinclude\sSQLITE_ENABLE_EXPLAIN_COMMENTS\nwhen\sbuilding\sthe\sshell.\s\sStill\sneed\sto\sfix\smain.mk\sand\sthe\namalgamation\starball. +D 2016-02-09T17:12:22.679 +F Makefile.in 95ea52e9c02962e31f986fe8ea5805104c84f94b F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc b0493f10caddb8adf992a4e6f1943141fc7c6816 +F Makefile.msc d2eef1643b13c02686a5f3f5fa58e6843e910e2a F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ca72be8618e5d466d6f35819ca8bbd2b84269959 -R f95e307a4f6313b9df891047976f580b +P e1d8ec85546caeca3bb7a05ad962a2aed91194ce +R c5ef01ad4ed02f828dd7e74a721278c9 U drh -Z 5769e00c07411a2161fa568f8263dd90 +Z 91487ddf0aeacb78fa9d983e619d08c4 diff --git a/manifest.uuid b/manifest.uuid index df0fc10065..c2594181e4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e1d8ec85546caeca3bb7a05ad962a2aed91194ce \ No newline at end of file +992282399cd2d1fc52ff5a1a4bff59f30b62899a \ No newline at end of file From 406eeff6ff6dcd1eb9271f78ec27398471e39a75 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Tue, 9 Feb 2016 18:28:20 +0000 Subject: [PATCH 248/570] Fix MSVC makefile options that enable control-flow guard. FossilOrigin-Name: 51b6823f4c9376d549f572f5a33cac1e4c9783a2 --- Makefile.msc | 6 +++--- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 94e78b2169..82f405db3b 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -551,8 +551,8 @@ RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP # C compiler options for the Windows 10 platform (needs MSVC 2015). # !IF $(FOR_WIN10)!=0 -TCC = $(TCC) /guard:cf -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE -BCC = $(BCC) /guard:cf -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE +TCC = $(TCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE +BCC = $(BCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE !ENDIF # Also, we need to dynamically link to the correct MSVC runtime @@ -919,7 +919,7 @@ LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)" !ENDIF !IF $(FOR_WIN10)!=0 -LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(UCRTLIBPATH)" +LTLINKOPTS = $(LTLINKOPTS) /guard:cf "/LIBPATH:$(UCRTLIBPATH)" !IF $(DEBUG)>1 LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:libucrtd.lib /DEFAULTLIB:ucrtd.lib !ELSE diff --git a/manifest b/manifest index c320d4221b..972cf74353 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Fix\sthe\stop-level\smakefiles\sto\salways\sinclude\sSQLITE_ENABLE_EXPLAIN_COMMENTS\nwhen\sbuilding\sthe\sshell.\s\sStill\sneed\sto\sfix\smain.mk\sand\sthe\namalgamation\starball. -D 2016-02-09T17:12:22.679 +C Fix\sMSVC\smakefile\soptions\sthat\senable\scontrol-flow\sguard. +D 2016-02-09T18:28:20.640 F Makefile.in 95ea52e9c02962e31f986fe8ea5805104c84f94b F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc d2eef1643b13c02686a5f3f5fa58e6843e910e2a +F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e1d8ec85546caeca3bb7a05ad962a2aed91194ce -R c5ef01ad4ed02f828dd7e74a721278c9 -U drh -Z 91487ddf0aeacb78fa9d983e619d08c4 +P 992282399cd2d1fc52ff5a1a4bff59f30b62899a +R 339c4dc7dafb8a9f839919868c327cb9 +U mistachkin +Z 87542794a9bfaf638d39bc9a323993e0 diff --git a/manifest.uuid b/manifest.uuid index c2594181e4..59daec470f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -992282399cd2d1fc52ff5a1a4bff59f30b62899a \ No newline at end of file +51b6823f4c9376d549f572f5a33cac1e4c9783a2 \ No newline at end of file From 700c252a726ffa142704197ac12ccd34127a6850 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 9 Feb 2016 18:39:25 +0000 Subject: [PATCH 249/570] Add auto-explain mode to the command-line shell. Default on. Auto-explain tries to automatically detect EXPLAIN queries and format them appropriately. FossilOrigin-Name: 1d62aa6b315df47cafb33da7ca79d3386a2fdd48 --- manifest | 17 ++++--- manifest.uuid | 2 +- src/shell.c | 125 ++++++++++++++++++++++++++++---------------------- 3 files changed, 81 insertions(+), 63 deletions(-) diff --git a/manifest b/manifest index 972cf74353..4e297feee8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sMSVC\smakefile\soptions\sthat\senable\scontrol-flow\sguard. -D 2016-02-09T18:28:20.640 +C Add\sauto-explain\smode\sto\sthe\scommand-line\sshell.\s\sDefault\son.\s\sAuto-explain\ntries\sto\sautomatically\sdetect\sEXPLAIN\squeries\sand\sformat\sthem\sappropriately. +D 2016-02-09T18:39:25.001 F Makefile.in 95ea52e9c02962e31f986fe8ea5805104c84f94b F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a @@ -349,7 +349,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c ff80004a9a6ece891a8d9327a88e7b6e2588ee6d -F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 +F src/shell.c eae68d3a7aff0f4195074d5f204dc2c219e748fd F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d @@ -1427,7 +1427,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 992282399cd2d1fc52ff5a1a4bff59f30b62899a -R 339c4dc7dafb8a9f839919868c327cb9 -U mistachkin -Z 87542794a9bfaf638d39bc9a323993e0 +P 51b6823f4c9376d549f572f5a33cac1e4c9783a2 +R 38fbc467636eda7f2b73a6fc60969ca8 +T *branch * auto-explain +T *sym-auto-explain * +T -sym-trunk * +U drh +Z 2feb45f9e3784b1a58bde6f86e718a1d diff --git a/manifest.uuid b/manifest.uuid index 59daec470f..6a13da9877 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -51b6823f4c9376d549f572f5a33cac1e4c9783a2 \ No newline at end of file +1d62aa6b315df47cafb33da7ca79d3386a2fdd48 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 3f8b22f4fa..c45b28b999 100644 --- a/src/shell.c +++ b/src/shell.c @@ -592,6 +592,7 @@ typedef struct ShellState ShellState; struct ShellState { sqlite3 *db; /* The database */ int echoOn; /* True to echo input commands */ + int autoExplain; /* Automatically turn on .explain mode */ int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ int statsOn; /* True to display memory stats before each finalize */ int scanstatsOn; /* True to display scan stats before each finalize */ @@ -603,6 +604,8 @@ struct ShellState { FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ + int cMode; /* temporary output mode for the current query */ + int normalMode; /* Output mode before ".explain on" */ int writableSchema; /* True if PRAGMA writable_schema=ON */ int showHeader; /* True to show column names in List or Column mode */ unsigned shellFlgs; /* Various flags */ @@ -613,7 +616,6 @@ struct ShellState { int actualWidth[100]; /* Actual width of each column */ char nullValue[20]; /* The text to print when a NULL comes back from ** the database */ - SavedModeInfo normalMode;/* Holds the mode just before .explain ON */ char outfile[FILENAME_MAX]; /* Filename for *out */ const char *zDbFilename; /* name of the database file */ char *zFreeOnClose; /* Filename to free when closing */ @@ -882,7 +884,7 @@ static int shell_callback( int i; ShellState *p = (ShellState*)pArg; - switch( p->mode ){ + switch( p->cMode ){ case MODE_Line: { int w = 5; if( azArg==0 ) break; @@ -899,11 +901,24 @@ static int shell_callback( } case MODE_Explain: case MODE_Column: { + static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13}; + const int *colWidth; + int showHdr; + char *rowSep; + if( p->cMode==MODE_Column ){ + colWidth = p->colWidth; + showHdr = p->showHeader; + rowSep = p->rowSeparator; + }else{ + colWidth = aExplainWidths; + showHdr = 1; + rowSep = "\n"; + } if( p->cnt++==0 ){ for(i=0; icolWidth) ){ - w = p->colWidth[i]; + w = colWidth[i]; }else{ w = 0; } @@ -916,17 +931,17 @@ static int shell_callback( if( iactualWidth) ){ p->actualWidth[i] = w; } - if( p->showHeader ){ + if( showHdr ){ if( w<0 ){ utf8_printf(p->out,"%*.*s%s",-w,-w,azCol[i], - i==nArg-1 ? p->rowSeparator : " "); + i==nArg-1 ? rowSep : " "); }else{ utf8_printf(p->out,"%-*.*s%s",w,w,azCol[i], - i==nArg-1 ? p->rowSeparator : " "); + i==nArg-1 ? rowSep : " "); } } } - if( p->showHeader ){ + if( showHdr ){ for(i=0; iactualWidth) ){ @@ -938,7 +953,7 @@ static int shell_callback( utf8_printf(p->out,"%-*.*s%s",w,w, "----------------------------------------------------------" "----------------------------------------------------------", - i==nArg-1 ? p->rowSeparator : " "); + i==nArg-1 ? rowSep : " "); } } } @@ -950,7 +965,7 @@ static int shell_callback( }else{ w = 10; } - if( p->mode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){ + if( p->cMode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){ w = strlen30(azArg[i]); } if( i==1 && p->aiIndent && p->pStmt ){ @@ -962,11 +977,11 @@ static int shell_callback( if( w<0 ){ utf8_printf(p->out,"%*.*s%s",-w,-w, azArg[i] ? azArg[i] : p->nullValue, - i==nArg-1 ? p->rowSeparator : " "); + i==nArg-1 ? rowSep : " "); }else{ utf8_printf(p->out,"%-*.*s%s",w,w, azArg[i] ? azArg[i] : p->nullValue, - i==nArg-1 ? p->rowSeparator : " "); + i==nArg-1 ? rowSep : " "); } } break; @@ -986,7 +1001,7 @@ static int shell_callback( utf8_printf(p->out, "%s", z); if( iout, "%s", p->colSeparator); - }else if( p->mode==MODE_Semi ){ + }else if( p->cMode==MODE_Semi ){ utf8_printf(p->out, ";%s", p->rowSeparator); }else{ utf8_printf(p->out, "%s", p->rowSeparator); @@ -1614,10 +1629,20 @@ static int shell_exec( sqlite3_free(zEQP); } - /* If the shell is currently in ".explain" mode, gather the extra - ** data required to add indents to the output.*/ - if( pArg && pArg->mode==MODE_Explain ){ - explain_data_prepare(pArg, pStmt); + if( pArg ){ + pArg->cMode = pArg->mode; + if( sqlite3_column_count(pStmt)==8 + && sqlite3_strlike("%EXPLAIN%", sqlite3_sql(pStmt),0)==0 + && sqlite3_strlike("%QUERY%", sqlite3_sql(pStmt),0)!=0 + ){ + pArg->cMode = MODE_Explain; + } + + /* If the shell is currently in ".explain" mode, gather the extra + ** data required to add indents to the output.*/ + if( pArg->cMode==MODE_Explain ){ + explain_data_prepare(pArg, pStmt); + } } /* perform the first step. this will tell us if we @@ -1647,7 +1672,7 @@ static int shell_exec( /* extract the data and data types */ for(i=0; imode==MODE_Insert ){ + if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){ azVals[i] = ""; }else{ azVals[i] = (char*)sqlite3_column_text(pStmt, i); @@ -1867,8 +1892,7 @@ static char zHelp[] = ".echo on|off Turn command echo on or off\n" ".eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN\n" ".exit Exit this program\n" - ".explain ?on|off? Turn output mode suitable for EXPLAIN on or off.\n" - " With no args, it turns EXPLAIN on.\n" + ".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n" ".fullschema Show schema and the content of sqlite_stat tables\n" ".headers on|off Turn display of headers on or off\n" ".help Show this message\n" @@ -2855,7 +2879,7 @@ static int do_meta_command(char *zLine, ShellState *p){ open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 1; - data.mode = MODE_Column; + data.cMode = data.mode = MODE_Column; data.colWidth[0] = 3; data.colWidth[1] = 15; data.colWidth[2] = 58; @@ -2950,37 +2974,24 @@ static int do_meta_command(char *zLine, ShellState *p){ }else if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ - int val = nArg>=2 ? booleanValue(azArg[1]) : 1; - if(val == 1) { - if(!p->normalMode.valid) { - p->normalMode.valid = 1; - p->normalMode.mode = p->mode; - p->normalMode.showHeader = p->showHeader; - memcpy(p->normalMode.colWidth,p->colWidth,sizeof(p->colWidth)); + int val = 1; + if( nArg>=2 ){ + if( strcmp(azArg[1],"auto")==0 ){ + val = 99; + }else{ + val = booleanValue(azArg[1]); } - /* We could put this code under the !p->explainValid - ** condition so that it does not execute if we are already in - ** explain mode. However, always executing it allows us an easy - ** was to reset to explain mode in case the user previously - ** did an .explain followed by a .width, .mode or .header - ** command. - */ + } + if( val==1 && p->mode!=MODE_Explain ){ + p->normalMode = p->mode; p->mode = MODE_Explain; - p->showHeader = 1; - memset(p->colWidth,0,sizeof(p->colWidth)); - p->colWidth[0] = 4; /* addr */ - p->colWidth[1] = 13; /* opcode */ - p->colWidth[2] = 4; /* P1 */ - p->colWidth[3] = 4; /* P2 */ - p->colWidth[4] = 4; /* P3 */ - p->colWidth[5] = 13; /* P4 */ - p->colWidth[6] = 2; /* P5 */ - p->colWidth[7] = 13; /* Comment */ - }else if (p->normalMode.valid) { - p->normalMode.valid = 0; - p->mode = p->normalMode.mode; - p->showHeader = p->normalMode.showHeader; - memcpy(p->colWidth,p->normalMode.colWidth,sizeof(p->colWidth)); + p->autoExplain = 0; + }else if( val==0 ){ + if( p->mode==MODE_Explain ) p->mode = p->normalMode; + p->autoExplain = 0; + }else if( val==99 ){ + if( p->mode==MODE_Explain ) p->mode = p->normalMode; + p->autoExplain = 1; } }else @@ -2996,7 +3007,7 @@ static int do_meta_command(char *zLine, ShellState *p){ open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 0; - data.mode = MODE_Semi; + data.cMode = data.mode = MODE_Semi; rc = sqlite3_exec(p->db, "SELECT sql FROM" " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" @@ -3021,7 +3032,7 @@ static int do_meta_command(char *zLine, ShellState *p){ raw_printf(p->out, "ANALYZE sqlite_master;\n"); sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'", callback, &data, &zErrMsg); - data.mode = MODE_Insert; + data.cMode = data.mode = MODE_Insert; data.zDestTable = "sqlite_stat1"; shell_exec(p->db, "SELECT * FROM sqlite_stat1", shell_callback, &data,&zErrMsg); @@ -3253,7 +3264,7 @@ static int do_meta_command(char *zLine, ShellState *p){ open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 0; - data.mode = MODE_List; + data.cMode = data.mode = MODE_List; if( nArg==1 ){ rc = sqlite3_exec(p->db, "SELECT name FROM sqlite_master " @@ -3439,6 +3450,7 @@ static int do_meta_command(char *zLine, ShellState *p){ "ascii column csv html insert line list tabs tcl\n"); rc = 1; } + p->cMode = p->mode; }else if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){ @@ -3628,7 +3640,7 @@ static int do_meta_command(char *zLine, ShellState *p){ open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 0; - data.mode = MODE_Semi; + data.cMode = data.mode = MODE_Semi; if( nArg==2 ){ int i; for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]); @@ -3776,7 +3788,8 @@ static int do_meta_command(char *zLine, ShellState *p){ } utf8_printf(p->out, "%12.12s: %s\n","echo", p->echoOn ? "on" : "off"); utf8_printf(p->out, "%12.12s: %s\n","eqp", p->autoEQP ? "on" : "off"); - utf8_printf(p->out,"%9.9s: %s\n","explain",p->normalMode.valid?"on":"off"); + utf8_printf(p->out, "%12.12s: %s\n","explain", + p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); utf8_printf(p->out,"%12.12s: %s\n","headers", p->showHeader ? "on" : "off"); utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); utf8_printf(p->out, "%12.12s: ", "nullvalue"); @@ -4575,7 +4588,8 @@ static void usage(int showDetail){ */ static void main_init(ShellState *data) { memset(data, 0, sizeof(*data)); - data->mode = MODE_List; + data->normalMode = data->cMode = data->mode = MODE_List; + data->autoExplain = 1; memcpy(data->colSeparator,SEP_Column, 2); memcpy(data->rowSeparator,SEP_Row, 2); data->showHeader = 0; @@ -4908,6 +4922,7 @@ int SQLITE_CDECL main(int argc, char **argv){ raw_printf(stderr,"Use -help for a list of options.\n"); return 1; } + data.cMode = data.mode; } if( !readStdin ){ From 87a24aa1ca36b37e03c102bba8dcde952223803d Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 9 Feb 2016 20:04:07 +0000 Subject: [PATCH 250/570] Improved auto-detection of EXPLAIN output in the shell. FossilOrigin-Name: 6c6d7a6e89e67cdb0813d3eebb869aafb43d43ed --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/shell.c | 27 ++++++++++++++++++++++++--- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 4e297feee8..65f5e85dfc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sauto-explain\smode\sto\sthe\scommand-line\sshell.\s\sDefault\son.\s\sAuto-explain\ntries\sto\sautomatically\sdetect\sEXPLAIN\squeries\sand\sformat\sthem\sappropriately. -D 2016-02-09T18:39:25.001 +C Improved\sauto-detection\sof\sEXPLAIN\soutput\sin\sthe\sshell. +D 2016-02-09T20:04:07.701 F Makefile.in 95ea52e9c02962e31f986fe8ea5805104c84f94b F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a @@ -349,7 +349,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c ff80004a9a6ece891a8d9327a88e7b6e2588ee6d -F src/shell.c eae68d3a7aff0f4195074d5f204dc2c219e748fd +F src/shell.c dad82078194d5dae39d35f131e4b60dd3276ab27 F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d @@ -1427,10 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 51b6823f4c9376d549f572f5a33cac1e4c9783a2 -R 38fbc467636eda7f2b73a6fc60969ca8 -T *branch * auto-explain -T *sym-auto-explain * -T -sym-trunk * +P 1d62aa6b315df47cafb33da7ca79d3386a2fdd48 +R 7efe35d4fa73e934642e7f03926fba5a U drh -Z 2feb45f9e3784b1a58bde6f86e718a1d +Z d64951a4b1ff916463dbab9f9acfa416 diff --git a/manifest.uuid b/manifest.uuid index 6a13da9877..7064810a82 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1d62aa6b315df47cafb33da7ca79d3386a2fdd48 \ No newline at end of file +6c6d7a6e89e67cdb0813d3eebb869aafb43d43ed \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index c45b28b999..b1672f633a 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1506,10 +1506,17 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ /* Try to figure out if this is really an EXPLAIN statement. If this ** cannot be verified, return early. */ + if( sqlite3_column_count(pSql)!=8 ){ + p->cMode = p->mode; + return; + } zSql = sqlite3_sql(pSql); if( zSql==0 ) return; for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++); - if( sqlite3_strnicmp(z, "explain", 7) ) return; + if( sqlite3_strnicmp(z, "explain", 7) ){ + p->cMode = p->mode; + return; + } for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){ int i; @@ -1526,6 +1533,20 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ /* Grow the p->aiIndent array as required */ if( iOp>=nAlloc ){ + if( iOp==0 ){ + /* Do further verfication that this is explain output. Abort if + ** it is not */ + static const char *explainCols[] = { + "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" }; + int jj; + for(jj=0; jjcMode = p->mode; + sqlite3_reset(pSql); + return; + } + } + } nAlloc += 100; p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); @@ -1631,9 +1652,9 @@ static int shell_exec( if( pArg ){ pArg->cMode = pArg->mode; - if( sqlite3_column_count(pStmt)==8 + if( pArg->autoExplain + && sqlite3_column_count(pStmt)==8 && sqlite3_strlike("%EXPLAIN%", sqlite3_sql(pStmt),0)==0 - && sqlite3_strlike("%QUERY%", sqlite3_sql(pStmt),0)!=0 ){ pArg->cMode = MODE_Explain; } From 6d9455591473a284d7b8a3427d7c65080690461a Mon Sep 17 00:00:00 2001 From: mistachkin Date: Tue, 9 Feb 2016 20:31:50 +0000 Subject: [PATCH 251/570] In the shell, use the appropriate string constant instead of a literal new-line. FossilOrigin-Name: 61951b153d47096f30ebc8b84af408d9d709637c --- manifest | 15 +++++++-------- manifest.uuid | 2 +- src/shell.c | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index e16fe81449..8fc5705ca4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\scommand-line\sshell\sto\sbe\sin\sauto-explain\smode\sby\sdefault.\s\sIt\sis\nno\slonger\snecessary\sto\suse\sthe\s".explain"\scommand\sto\sput\sthe\sshell\sinto\sa\smode\nwhere\sthe\sEXPLAIN\soutput\sis\sformatted\snicely.\s\sThat\snow\shappens\sautomatically. -D 2016-02-09T20:11:14.398 +C In\sthe\sshell,\suse\sthe\sappropriate\sstring\sconstant\sinstead\sof\sa\sliteral\snew-line. +D 2016-02-09T20:31:50.440 F Makefile.in 95ea52e9c02962e31f986fe8ea5805104c84f94b F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a @@ -349,7 +349,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c ff80004a9a6ece891a8d9327a88e7b6e2588ee6d -F src/shell.c dad82078194d5dae39d35f131e4b60dd3276ab27 +F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d @@ -1427,8 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 51b6823f4c9376d549f572f5a33cac1e4c9783a2 6c6d7a6e89e67cdb0813d3eebb869aafb43d43ed -R 7efe35d4fa73e934642e7f03926fba5a -T +closed 6c6d7a6e89e67cdb0813d3eebb869aafb43d43ed -U drh -Z 1d6fcdd166387e79c0e00d781ecb3274 +P 751915cb7e4981661a40dc5e4d029ab27434c2d9 +R 6632eb3071442a86edbf0e20c957fb36 +U mistachkin +Z 03c626e8f779d36c2a5f32596caaf00c diff --git a/manifest.uuid b/manifest.uuid index 8d44ae8ba1..e98ff782a3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -751915cb7e4981661a40dc5e4d029ab27434c2d9 \ No newline at end of file +61951b153d47096f30ebc8b84af408d9d709637c \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index b1672f633a..85e36a88df 100644 --- a/src/shell.c +++ b/src/shell.c @@ -912,7 +912,7 @@ static int shell_callback( }else{ colWidth = aExplainWidths; showHdr = 1; - rowSep = "\n"; + rowSep = SEP_Row; } if( p->cnt++==0 ){ for(i=0; i Date: Tue, 9 Feb 2016 20:37:46 +0000 Subject: [PATCH 252/570] Fix the makefiles in the autoconf-tarball so that they build the command-line shell with SQLITE_ENABLE_EXPLAIN_COMMENTS. FossilOrigin-Name: 1135ad014aac8a4ae5169375af1b368feaa8331b --- autoconf/Makefile.am | 7 +++---- autoconf/Makefile.msc | 2 +- manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/autoconf/Makefile.am b/autoconf/Makefile.am index 03424a606b..0e09cfcd95 100644 --- a/autoconf/Makefile.am +++ b/autoconf/Makefile.am @@ -6,11 +6,10 @@ libsqlite3_la_SOURCES = sqlite3.c libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8 bin_PROGRAMS = sqlite3 -sqlite3_SOURCES = shell.c sqlite3.h -EXTRA_sqlite3_SOURCES = sqlite3.c -sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@ +sqlite3_SOURCES = shell.c sqlite3.c sqlite3.h +sqlite3_LDADD = @READLINE_LIBS@ sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@ -sqlite3_CFLAGS = $(AM_CFLAGS) +sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS include_HEADERS = sqlite3.h sqlite3ext.h diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index 65f2396180..ea31a32f77 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -856,7 +856,7 @@ LIBRESOBJS = # when the shell is not being dynamically linked. # !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 -SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 +SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS !ENDIF diff --git a/manifest b/manifest index 8fc5705ca4..9c9255245b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sshell,\suse\sthe\sappropriate\sstring\sconstant\sinstead\sof\sa\sliteral\snew-line. -D 2016-02-09T20:31:50.440 +C Fix\sthe\smakefiles\sin\sthe\sautoconf-tarball\sso\sthat\sthey\sbuild\sthe\scommand-line\nshell\swith\sSQLITE_ENABLE_EXPLAIN_COMMENTS. +D 2016-02-09T20:37:46.079 F Makefile.in 95ea52e9c02962e31f986fe8ea5805104c84f94b F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a @@ -10,8 +10,8 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 -F autoconf/Makefile.am 1c1657650775960804945dc392e14d9e43c5ed84 -F autoconf/Makefile.msc a35b2aab24d1603f3f0ae65cf01686c2578d319c +F autoconf/Makefile.am 29e2a6e8d0c5e32723a48b4faf6b168854dde5f4 +F autoconf/Makefile.msc 28aa3bcecef3edcddf320a7631f92088c47cf00e F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt e9757a381e5ce2553dbaa6247bb8ad00eb8d87aa F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 751915cb7e4981661a40dc5e4d029ab27434c2d9 -R 6632eb3071442a86edbf0e20c957fb36 -U mistachkin -Z 03c626e8f779d36c2a5f32596caaf00c +P 61951b153d47096f30ebc8b84af408d9d709637c +R d75c460e141623bfe7fb7110cba37d7d +U drh +Z 11eb657dc7f95c0de93cd1d08c7016df diff --git a/manifest.uuid b/manifest.uuid index e98ff782a3..cde3d14b19 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -61951b153d47096f30ebc8b84af408d9d709637c \ No newline at end of file +1135ad014aac8a4ae5169375af1b368feaa8331b \ No newline at end of file From c5286de0ee2ffdb300065c07fa15ce5194bc5132 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Tue, 9 Feb 2016 22:00:48 +0000 Subject: [PATCH 253/570] Update the MSVC autoconf makefile with the recent changes from the primary one. FossilOrigin-Name: c7242aa3e9c08e0c019388e89a785a6e59c915d5 --- autoconf/Makefile.msc | 6 +++--- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index ea31a32f77..3dfbb3d20e 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -536,8 +536,8 @@ RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP # C compiler options for the Windows 10 platform (needs MSVC 2015). # !IF $(FOR_WIN10)!=0 -TCC = $(TCC) /guard:cf -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE -BCC = $(BCC) /guard:cf -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE +TCC = $(TCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE +BCC = $(BCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE !ENDIF # Also, we need to dynamically link to the correct MSVC runtime @@ -814,7 +814,7 @@ LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)" !ENDIF !IF $(FOR_WIN10)!=0 -LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(UCRTLIBPATH)" +LTLINKOPTS = $(LTLINKOPTS) /guard:cf "/LIBPATH:$(UCRTLIBPATH)" !IF $(DEBUG)>1 LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:libucrtd.lib /DEFAULTLIB:ucrtd.lib !ELSE diff --git a/manifest b/manifest index 9c9255245b..542977d5e3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\smakefiles\sin\sthe\sautoconf-tarball\sso\sthat\sthey\sbuild\sthe\scommand-line\nshell\swith\sSQLITE_ENABLE_EXPLAIN_COMMENTS. -D 2016-02-09T20:37:46.079 +C Update\sthe\sMSVC\sautoconf\smakefile\swith\sthe\srecent\schanges\sfrom\sthe\sprimary\sone. +D 2016-02-09T22:00:48.288 F Makefile.in 95ea52e9c02962e31f986fe8ea5805104c84f94b F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a @@ -11,7 +11,7 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 29e2a6e8d0c5e32723a48b4faf6b168854dde5f4 -F autoconf/Makefile.msc 28aa3bcecef3edcddf320a7631f92088c47cf00e +F autoconf/Makefile.msc 3ab11cf4b564876efad3f0d59528388e4329b88b F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt e9757a381e5ce2553dbaa6247bb8ad00eb8d87aa F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 61951b153d47096f30ebc8b84af408d9d709637c -R d75c460e141623bfe7fb7110cba37d7d -U drh -Z 11eb657dc7f95c0de93cd1d08c7016df +P 1135ad014aac8a4ae5169375af1b368feaa8331b +R 9aa873b7c8d29e72fd134e7743d1eb40 +U mistachkin +Z b7e0b8af3a354ae18e5de2ce26dd905f diff --git a/manifest.uuid b/manifest.uuid index cde3d14b19..96016126dc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1135ad014aac8a4ae5169375af1b368feaa8331b \ No newline at end of file +c7242aa3e9c08e0c019388e89a785a6e59c915d5 \ No newline at end of file From 07f76568da796cec1c9716e1200413b669603268 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 9 Feb 2016 22:39:39 +0000 Subject: [PATCH 254/570] Add the new "snapshot-tarball" target to the unix makefiles, for building a tarball similar to "amalgamation-tarball" but named by the SHA1 hash of the current check-out rather than by the version number. FossilOrigin-Name: 4f360b2ae78b3d4ccfe6c40ac6b27a00fc70cf23 --- Makefile.in | 9 +++++++-- main.mk | 9 +++++++-- manifest | 18 +++++++++--------- manifest.uuid | 2 +- tool/mkautoconfamal.sh | 30 +++++++++++++++++++++--------- 5 files changed, 45 insertions(+), 23 deletions(-) diff --git a/Makefile.in b/Makefile.in index e1293d69fa..013cf442d1 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1156,10 +1156,15 @@ checksymbols: sqlite3.lo nm -g --defined-only sqlite3.o | grep -v " sqlite3_" ; test $$? -ne 0 echo '0 errors out of 1 tests' -# Build the amalgamation-autoconf package. +# Build the amalgamation-autoconf package. The amalamgation-tarball target builds +# a tarball named for the version number. Ex: sqlite-autoconf-3110000.tar.gz. +# The snapshot-tarball target builds a tarball named by the SHA1 hash # amalgamation-tarball: sqlite3.c - TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh + TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --normal + +snapshot-tarball: sqlite3.c + TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --snapshot # The next two rules are used to support the "threadtest" target. Building # threadtest runs a few thread-safety tests that are implemented in C. This diff --git a/main.mk b/main.mk index 149f94e209..509f4c8273 100644 --- a/main.mk +++ b/main.mk @@ -863,10 +863,15 @@ loadfts: $(TOP)/tool/loadfts.c libsqlite3.a checksymbols: sqlite3.o nm -g --defined-only sqlite3.o | grep -v " sqlite3_" ; test $$? -ne 0 -# Build the amalgamation-autoconf package. +# Build the amalgamation-autoconf package. The amalamgation-tarball target builds +# a tarball named for the version number. Ex: sqlite-autoconf-3110000.tar.gz. +# The snapshot-tarball target builds a tarball named by the SHA1 hash # amalgamation-tarball: sqlite3.c - TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh + TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --normal + +snapshot-tarball: sqlite3.c + TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --snapshot # Standard install and cleanup targets diff --git a/manifest b/manifest index 542977d5e3..5d5b5a73cf 100644 --- a/manifest +++ b/manifest @@ -1,6 +1,6 @@ -C Update\sthe\sMSVC\sautoconf\smakefile\swith\sthe\srecent\schanges\sfrom\sthe\sprimary\sone. -D 2016-02-09T22:00:48.288 -F Makefile.in 95ea52e9c02962e31f986fe8ea5805104c84f94b +C Add\sthe\snew\s"snapshot-tarball"\starget\sto\sthe\sunix\smakefiles,\sfor\sbuilding\na\starball\ssimilar\sto\s"amalgamation-tarball"\sbut\snamed\sby\sthe\sSHA1\shash\sof\nthe\scurrent\scheck-out\srather\sthan\sby\sthe\sversion\snumber. +D 2016-02-09T22:39:39.028 +F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 @@ -272,7 +272,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 37497b06d3e3acb2c71675d76627a3b2639c6db0 +F main.mk aecd0ce0646db48754e2a14523f759593f8ed072 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -1382,7 +1382,7 @@ F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 -F tool/mkautoconfamal.sh a29b14d54302b33fd892958f6895582ea90e4a45 +F tool/mkautoconfamal.sh e4efcad8e94bea57c143175a8ad58e953487f185 F tool/mkkeywordhash.c f7f3b342211ac6a14258b9726d5b97cf4f548f22 F tool/mkmsvcmin.tcl d57e6efc9428605f5418d0b235721ddf7b5d9c0b F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1135ad014aac8a4ae5169375af1b368feaa8331b -R 9aa873b7c8d29e72fd134e7743d1eb40 -U mistachkin -Z b7e0b8af3a354ae18e5de2ce26dd905f +P c7242aa3e9c08e0c019388e89a785a6e59c915d5 +R 1f1da2b535c3a877742d655382e7c04d +U drh +Z 3b1fd5382ba0d09acf8b866801d6e0da diff --git a/manifest.uuid b/manifest.uuid index 96016126dc..b78568f325 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c7242aa3e9c08e0c019388e89a785a6e59c915d5 \ No newline at end of file +4f360b2ae78b3d4ccfe6c40ac6b27a00fc70cf23 \ No newline at end of file diff --git a/tool/mkautoconfamal.sh b/tool/mkautoconfamal.sh index 6081a7b0ec..25a84b4169 100644 --- a/tool/mkautoconfamal.sh +++ b/tool/mkautoconfamal.sh @@ -22,16 +22,26 @@ set -u TMPSPACE=./mkpkg_tmp_dir VERSION=`cat $TOP/VERSION` +HASH=`sed 's/^\(..........\).*/\1/' $TOP/manifest.uuid` -# Set global variable $ARTIFACT to the "3xxyyzz" string incorporated -# into artifact filenames. And $VERSION2 to the "3.x.y[.z]" form. -xx=`echo $VERSION|sed 's/3\.\([0-9]*\)\..*/\1/'` -yy=`echo $VERSION|sed 's/3\.[^.]*\.\([0-9]*\).*/\1/'` -zz=0 -set +e - zz=`echo $VERSION|sed 's/3\.[^.]*\.[^.]*\.\([0-9]*\).*/\1/'|grep -v '\.'` -set -e -ARTIFACT=`printf "3%.2d%.2d%.2d" $xx $yy $zz` +# If this script is given an argument of --snapshot, then generate a +# snapshot tarball named for the current checkout SHA1 hash, rather than +# the version number. +# +if test "$#" -ge 1 -a x$1 != x--snapshot +then + # Set global variable $ARTIFACT to the "3xxyyzz" string incorporated + # into artifact filenames. And $VERSION2 to the "3.x.y[.z]" form. + xx=`echo $VERSION|sed 's/3\.\([0-9]*\)\..*/\1/'` + yy=`echo $VERSION|sed 's/3\.[^.]*\.\([0-9]*\).*/\1/'` + zz=0 + set +e + zz=`echo $VERSION|sed 's/3\.[^.]*\.[^.]*\.\([0-9]*\).*/\1/'|grep -v '\.'` + set -e + ARTIFACT=`printf "3%.2d%.2d%.2d" $xx $yy $zz` +else + ARTIFACT=$HASH +fi rm -rf $TMPSPACE cp -R $TOP/autoconf $TMPSPACE @@ -76,3 +86,5 @@ tar -xzf sqlite-$VERSION.tar.gz mv sqlite-$VERSION sqlite-autoconf-$ARTIFACT tar -czf sqlite-autoconf-$ARTIFACT.tar.gz sqlite-autoconf-$ARTIFACT mv sqlite-autoconf-$ARTIFACT.tar.gz .. +cd .. +ls -l sqlite-autoconf-$ARTIFACT.tar.gz From 8809d821b4a51bf39b4bb555eb5eb883226a2923 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 9 Feb 2016 22:54:39 +0000 Subject: [PATCH 255/570] Update the snapshot tarball name to use the date (ISO8601 format) instead of the SHA1 hash in its name. FossilOrigin-Name: 070ec66f677cdcd30087871feb8afd010a184b75 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/mkautoconfamal.sh | 13 +++++++------ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 5d5b5a73cf..a1e732282a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\snew\s"snapshot-tarball"\starget\sto\sthe\sunix\smakefiles,\sfor\sbuilding\na\starball\ssimilar\sto\s"amalgamation-tarball"\sbut\snamed\sby\sthe\sSHA1\shash\sof\nthe\scurrent\scheck-out\srather\sthan\sby\sthe\sversion\snumber. -D 2016-02-09T22:39:39.028 +C Update\sthe\ssnapshot\starball\sname\sto\suse\sthe\sdate\s(ISO8601\sformat)\sinstead\nof\sthe\sSHA1\shash\sin\sits\sname. +D 2016-02-09T22:54:39.919 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a @@ -1382,7 +1382,7 @@ F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 -F tool/mkautoconfamal.sh e4efcad8e94bea57c143175a8ad58e953487f185 +F tool/mkautoconfamal.sh 11cd32789d8b47bfc09c46487ca7686107b767ef F tool/mkkeywordhash.c f7f3b342211ac6a14258b9726d5b97cf4f548f22 F tool/mkmsvcmin.tcl d57e6efc9428605f5418d0b235721ddf7b5d9c0b F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c7242aa3e9c08e0c019388e89a785a6e59c915d5 -R 1f1da2b535c3a877742d655382e7c04d +P 4f360b2ae78b3d4ccfe6c40ac6b27a00fc70cf23 +R 31af8c3f36c5dfe800721802c10c2a38 U drh -Z 3b1fd5382ba0d09acf8b866801d6e0da +Z be5fe588d1fb7ecaa0371d844a54afd9 diff --git a/manifest.uuid b/manifest.uuid index b78568f325..0366514920 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4f360b2ae78b3d4ccfe6c40ac6b27a00fc70cf23 \ No newline at end of file +070ec66f677cdcd30087871feb8afd010a184b75 \ No newline at end of file diff --git a/tool/mkautoconfamal.sh b/tool/mkautoconfamal.sh index 25a84b4169..11d3f566ff 100644 --- a/tool/mkautoconfamal.sh +++ b/tool/mkautoconfamal.sh @@ -23,6 +23,7 @@ set -u TMPSPACE=./mkpkg_tmp_dir VERSION=`cat $TOP/VERSION` HASH=`sed 's/^\(..........\).*/\1/' $TOP/manifest.uuid` +DATETIME=`grep '^D' $TOP/manifest | sed 's/[^0-9]//g'` # If this script is given an argument of --snapshot, then generate a # snapshot tarball named for the current checkout SHA1 hash, rather than @@ -38,9 +39,9 @@ then set +e zz=`echo $VERSION|sed 's/3\.[^.]*\.[^.]*\.\([0-9]*\).*/\1/'|grep -v '\.'` set -e - ARTIFACT=`printf "3%.2d%.2d%.2d" $xx $yy $zz` + TARBALLNAME=`printf "sqlite-autoconf-3%.2d%.2d%.2d" $xx $yy $zz` else - ARTIFACT=$HASH + TARBALLNAME=sqlite-snapshot-$DATETIME fi rm -rf $TMPSPACE @@ -83,8 +84,8 @@ rm -rf autom4te.cache cd ../ ./configure && make dist tar -xzf sqlite-$VERSION.tar.gz -mv sqlite-$VERSION sqlite-autoconf-$ARTIFACT -tar -czf sqlite-autoconf-$ARTIFACT.tar.gz sqlite-autoconf-$ARTIFACT -mv sqlite-autoconf-$ARTIFACT.tar.gz .. +mv sqlite-$VERSION $TARBALLNAME +tar -czf $TARBALLNAME.tar.gz $TARBALLNAME +mv $TARBALLNAME.tar.gz .. cd .. -ls -l sqlite-autoconf-$ARTIFACT.tar.gz +ls -l $TARBALLNAME.tar.gz From 0d4f9354db3c449ee5237a5a58163047acda54ad Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 10 Feb 2016 13:17:14 +0000 Subject: [PATCH 256/570] Updates to the autoconf tarball README.txt file. FossilOrigin-Name: a3e911e3aa3e35446bed7f300bfe03f66e1494db --- autoconf/README.txt | 14 +++++++------- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/autoconf/README.txt b/autoconf/README.txt index c27c08d0df..fd5605ea9f 100644 --- a/autoconf/README.txt +++ b/autoconf/README.txt @@ -1,13 +1,13 @@ This package contains: - * the SQLite library amalgamation (single file) source code distribution, - * the shell.c file used to build the sqlite3 shell too, and - * the sqlite3.h and sqlite3ext.h header files required to link programs - and sqlite extensions against the installed libary. + * the SQLite library amalgamation source code file: sqlite3.c + * the sqlite3.h and sqlite3ext.h header files that define the C-language + interface to the sqlite3.c library file + * the shell.c file used to build the sqlite3 command-line shell program * autoconf/automake installation infrastucture for building on POSIX - compliant systems. + compliant systems * a Makefile.msc and sqlite3.rc for building with Microsoft Visual C++ on - Windows. + Windows SUMMARY OF HOW TO BUILD ======================= @@ -39,7 +39,7 @@ to produce a smaller installation footprint. Other SQLite compilation parameters can also be set using CFLAGS. For example: - $ CFLAGS="-Os -DSQLITE_OMIT_TRIGGERS" ./configure + $ CFLAGS="-Os -DSQLITE_THREADSAFE=0" ./configure BUILDING WITH MICROSOFT VISUAL C++ diff --git a/manifest b/manifest index a1e732282a..dc9efa1f83 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\ssnapshot\starball\sname\sto\suse\sthe\sdate\s(ISO8601\sformat)\sinstead\nof\sthe\sSHA1\shash\sin\sits\sname. -D 2016-02-09T22:54:39.919 +C Updates\sto\sthe\sautoconf\starball\sREADME.txt\sfile. +D 2016-02-10T13:17:14.170 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a @@ -13,7 +13,7 @@ F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 29e2a6e8d0c5e32723a48b4faf6b168854dde5f4 F autoconf/Makefile.msc 3ab11cf4b564876efad3f0d59528388e4329b88b F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 -F autoconf/README.txt e9757a381e5ce2553dbaa6247bb8ad00eb8d87aa +F autoconf/README.txt 7325022e1cd497e1c3a525c97aa1020665e398cf F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8 F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4f360b2ae78b3d4ccfe6c40ac6b27a00fc70cf23 -R 31af8c3f36c5dfe800721802c10c2a38 +P 070ec66f677cdcd30087871feb8afd010a184b75 +R c35b2492f0a904d8e09d6ee47a7b531b U drh -Z be5fe588d1fb7ecaa0371d844a54afd9 +Z 9b2d2749667b4588e32d718038a8ef78 diff --git a/manifest.uuid b/manifest.uuid index 0366514920..062ac32da4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -070ec66f677cdcd30087871feb8afd010a184b75 \ No newline at end of file +a3e911e3aa3e35446bed7f300bfe03f66e1494db \ No newline at end of file From dd2b59b01dac09d0cf2a9747a50e3b86faee80ca Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 10 Feb 2016 13:36:17 +0000 Subject: [PATCH 257/570] When generating the snapshot-tarball, truncate the date/time in the name to 12 significant digits (YYYYMMDDhhmm) omitting the seconds and fractional seconds. FossilOrigin-Name: 604f77754797a4066f6cf275c7bc8a68d2839c2d --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/mkautoconfamal.sh | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index dc9efa1f83..6b82b46df3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Updates\sto\sthe\sautoconf\starball\sREADME.txt\sfile. -D 2016-02-10T13:17:14.170 +C When\sgenerating\sthe\ssnapshot-tarball,\struncate\sthe\sdate/time\sin\sthe\sname\sto\s\n12\ssignificant\sdigits\s(YYYYMMDDhhmm)\somitting\sthe\sseconds\sand\sfractional\nseconds. +D 2016-02-10T13:36:17.175 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a @@ -1382,7 +1382,7 @@ F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 -F tool/mkautoconfamal.sh 11cd32789d8b47bfc09c46487ca7686107b767ef +F tool/mkautoconfamal.sh c78caa3214f25dc28ea157b5a82abb311f209906 F tool/mkkeywordhash.c f7f3b342211ac6a14258b9726d5b97cf4f548f22 F tool/mkmsvcmin.tcl d57e6efc9428605f5418d0b235721ddf7b5d9c0b F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 070ec66f677cdcd30087871feb8afd010a184b75 -R c35b2492f0a904d8e09d6ee47a7b531b +P a3e911e3aa3e35446bed7f300bfe03f66e1494db +R 30240c9ea7a51d9fb3097cfc2aff9b45 U drh -Z 9b2d2749667b4588e32d718038a8ef78 +Z 38d599a4bb70ac4c3aebf51493f6b3e5 diff --git a/manifest.uuid b/manifest.uuid index 062ac32da4..c9229cedd9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a3e911e3aa3e35446bed7f300bfe03f66e1494db \ No newline at end of file +604f77754797a4066f6cf275c7bc8a68d2839c2d \ No newline at end of file diff --git a/tool/mkautoconfamal.sh b/tool/mkautoconfamal.sh index 11d3f566ff..75a0b09a4c 100644 --- a/tool/mkautoconfamal.sh +++ b/tool/mkautoconfamal.sh @@ -23,7 +23,7 @@ set -u TMPSPACE=./mkpkg_tmp_dir VERSION=`cat $TOP/VERSION` HASH=`sed 's/^\(..........\).*/\1/' $TOP/manifest.uuid` -DATETIME=`grep '^D' $TOP/manifest | sed 's/[^0-9]//g'` +DATETIME=`grep '^D' $TOP/manifest | sed -e 's/[^0-9]//g' -e 's/\(............\).*/\1/'` # If this script is given an argument of --snapshot, then generate a # snapshot tarball named for the current checkout SHA1 hash, rather than From bdb00225abc20bfc9bee34db4bc85daadaa0a003 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 10 Feb 2016 16:03:20 +0000 Subject: [PATCH 258/570] Omit NOT NULL checks on unchanging columns in an UPDATE. FossilOrigin-Name: 6a3aaedfb41735996470abbae6d3cd1be1f508b3 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/insert.c | 11 ++++++++--- src/sqliteInt.h | 2 +- src/update.c | 3 ++- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 6b82b46df3..b8116049d6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\sgenerating\sthe\ssnapshot-tarball,\struncate\sthe\sdate/time\sin\sthe\sname\sto\s\n12\ssignificant\sdigits\s(YYYYMMDDhhmm)\somitting\sthe\sseconds\sand\sfractional\nseconds. -D 2016-02-10T13:36:17.175 +C Omit\sNOT\sNULL\schecks\son\sunchanging\scolumns\sin\san\sUPDATE. +D 2016-02-10T16:03:20.793 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a @@ -309,7 +309,7 @@ F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 046199e085e69e05af7bef197d53c5b4b402b6fa +F src/insert.c f2e7592be43c7101ee8b991ff1cd976f027f7eb9 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b @@ -353,7 +353,7 @@ F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h b1850d30a1333de1df076eca979683f696f9d4b4 +F src/sqliteInt.h 8eff197a6c0934e19f34c1b072bc4abd48bfee6b F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -409,7 +409,7 @@ F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 F src/tokenize.c 813934be70597edfbb685ae08fc4c8b549cf5a1e F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 -F src/update.c 310ca7adb86a7d1f2afae46905b21c83580f3e17 +F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 F src/util.c 49ce0a65306c1c51d61cb5bc214c71cb62452de6 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a3e911e3aa3e35446bed7f300bfe03f66e1494db -R 30240c9ea7a51d9fb3097cfc2aff9b45 +P 604f77754797a4066f6cf275c7bc8a68d2839c2d +R 311aef0cc6bd481061bf1dc7cd93a2e3 U drh -Z 38d599a4bb70ac4c3aebf51493f6b3e5 +Z 273046c163b5169406e9a0408477555f diff --git a/manifest.uuid b/manifest.uuid index c9229cedd9..d0a34f8dfd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -604f77754797a4066f6cf275c7bc8a68d2839c2d \ No newline at end of file +6a3aaedfb41735996470abbae6d3cd1be1f508b3 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 650f397de0..95321cd947 100644 --- a/src/insert.c +++ b/src/insert.c @@ -995,7 +995,7 @@ void sqlite3Insert( { int isReplace; /* Set to true if constraints may cause a replace */ sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, - regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace + regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0 ); sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur, @@ -1171,7 +1171,8 @@ void sqlite3GenerateConstraintChecks( u8 pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */ u8 overrideError, /* Override onError to this if not OE_Default */ int ignoreDest, /* Jump to this label on an OE_Ignore resolution */ - int *pbMayReplace /* OUT: Set to true if constraint may cause a replace */ + int *pbMayReplace, /* OUT: Set to true if constraint may cause a replace */ + int *aiChng /* column i is unchanged if aiChng[i]<0 */ ){ Vdbe *v; /* VDBE under constrution */ Index *pIdx; /* Pointer to one of the indices */ @@ -1217,10 +1218,14 @@ void sqlite3GenerateConstraintChecks( */ for(i=0; iiPKey ){ + continue; /* ROWID is never NULL */ + } + if( aiChng && aiChng[i]<0 ){ + /* Don't bother checking for NOT NULL on columns that do not change */ continue; } onError = pTab->aCol[i].notNull; - if( onError==OE_None ) continue; + if( onError==OE_None ) continue; /* This column is allowed to be NULL */ if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f86e9da653..ef80e8dec9 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3545,7 +3545,7 @@ void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); void sqlite3ResolvePartIdxLabel(Parse*,int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, - u8,u8,int,int*); + u8,u8,int,int*,int*); void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int); int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*); void sqlite3BeginWriteOperation(Parse*, int, int); diff --git a/src/update.c b/src/update.c index 20951aade9..2a436b9701 100644 --- a/src/update.c +++ b/src/update.c @@ -572,7 +572,8 @@ void sqlite3Update( /* Do constraint checks. */ assert( regOldRowid>0 ); sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, - regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace); + regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, + aXRef); /* Do FK constraint checks. */ if( hasFK ){ From 2a0b527b37a16bc8f70287dc93dcac0b66f8d930 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 10 Feb 2016 16:52:24 +0000 Subject: [PATCH 259/570] Omit unnecessary CHECK constraints in UPDATE statements, when none of the columns referenced in the CHECK constraint are modified. FossilOrigin-Name: 02fbdbc782dd98f080bf4482d820f36c0ef3d519 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/insert.c | 36 +++++++++++++++++++++++++++++++++++- src/sqliteInt.h | 1 + 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index b8116049d6..bff561c581 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Omit\sNOT\sNULL\schecks\son\sunchanging\scolumns\sin\san\sUPDATE. -D 2016-02-10T16:03:20.793 +C Omit\sunnecessary\sCHECK\sconstraints\sin\sUPDATE\sstatements,\swhen\snone\sof\sthe\ncolumns\sreferenced\sin\sthe\sCHECK\sconstraint\sare\smodified. +D 2016-02-10T16:52:24.041 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a @@ -309,7 +309,7 @@ F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c f2e7592be43c7101ee8b991ff1cd976f027f7eb9 +F src/insert.c 5b715b726f9705c512d3759c827f2db0f57b6de5 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b @@ -353,7 +353,7 @@ F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 8eff197a6c0934e19f34c1b072bc4abd48bfee6b +F src/sqliteInt.h eb20019610d0bd25c7479ddfdef1fd4c00854dc2 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 604f77754797a4066f6cf275c7bc8a68d2839c2d -R 311aef0cc6bd481061bf1dc7cd93a2e3 +P 6a3aaedfb41735996470abbae6d3cd1be1f508b3 +R 5992825785c26c277f0bebde72670a95 U drh -Z 273046c163b5169406e9a0408477555f +Z 18800c36980a344bd8e3c9fe7e30ed04 diff --git a/manifest.uuid b/manifest.uuid index d0a34f8dfd..ad9bcac94d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6a3aaedfb41735996470abbae6d3cd1be1f508b3 \ No newline at end of file +02fbdbc782dd98f080bf4482d820f36c0ef3d519 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 95321cd947..a77d3e97d5 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1077,6 +1077,38 @@ insert_cleanup: #undef tmask #endif +/* This is the Walker callback from checkConstraintUnchanged(). Set +** pWalker->eCode to 0 if this expression node references any of the +** columns that are being modifed by an UPDATE statement. +*/ +static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ + if( pExpr->op==TK_COLUMN + && pExpr->iColumn>=0 + && pWalker->u.aiCol[pExpr->iColumn]>=0 + ){ + pWalker->eCode = 0; + } + return WRC_Continue; +} + +/* +** pExpr is a CHECK constraint on a row that is being UPDATE-ed. The +** only columns that are modified by the UPDATE are those for which +** aiChng[i]>=0. Return true if CHECK constraint pExpr does not use +** any of the changing columns. In other words, return true if this +** CHECK constraint can be skipped when validating the new row in +** the UPDATE statement. +*/ +static int checkConstraintUnchanged(Expr *pExpr, int *aiChng){ + Walker w; + memset(&w, 0, sizeof(w)); + w.eCode = 1; + w.xExprCallback = checkConstraintExprNode; + w.u.aiCol = aiChng; + sqlite3WalkExpr(&w, pExpr); + return w.eCode; +} + /* ** Generate code to do constraint checks prior to an INSERT or an UPDATE ** on table pTab. @@ -1275,7 +1307,9 @@ void sqlite3GenerateConstraintChecks( onError = overrideError!=OE_Default ? overrideError : OE_Abort; for(i=0; inExpr; i++){ int allOk = sqlite3VdbeMakeLabel(v); - sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL); + Expr *pExpr = pCheck->a[i].pExpr; + if( aiChng && checkConstraintUnchanged(pExpr, aiChng) ) continue; + sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL); if( onError==OE_Ignore ){ sqlite3VdbeGoto(v, ignoreDest); }else{ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ef80e8dec9..001416d56b 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3100,6 +3100,7 @@ struct Walker { SrcList *pSrcList; /* FROM clause */ struct SrcCount *pSrcCount; /* Counting column references */ struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ + int *aiCol; /* array of column indexes */ } u; }; From 98bfa16db247c4887f4c090269413a0c2248b390 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 10 Feb 2016 18:24:05 +0000 Subject: [PATCH 260/570] Fix to previous check-in: Make sure CHECK constraints involving the ROWID are not ignored when the ROWID changes. FossilOrigin-Name: 7782cb1dd5914b867caf5ff2f0f837407abbfd7a --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/insert.c | 40 +++++++++++++++++++++++++++------------- test/check.test | 20 ++++++++++++++++++++ 4 files changed, 55 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index bff561c581..2a9e362c52 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Omit\sunnecessary\sCHECK\sconstraints\sin\sUPDATE\sstatements,\swhen\snone\sof\sthe\ncolumns\sreferenced\sin\sthe\sCHECK\sconstraint\sare\smodified. -D 2016-02-10T16:52:24.041 +C Fix\sto\sprevious\scheck-in:\sMake\ssure\sCHECK\sconstraints\sinvolving\sthe\sROWID\nare\snot\signored\swhen\sthe\sROWID\schanges. +D 2016-02-10T18:24:05.782 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a @@ -309,7 +309,7 @@ F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 5b715b726f9705c512d3759c827f2db0f57b6de5 +F src/insert.c 6699f029049ea119b652b1464c92cae9f3813247 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b @@ -522,7 +522,7 @@ F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82 F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3 F test/cffault.test aadc1f61f8811cb600e3e069acbf8796f472a096 -F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763 +F test/check.test 85a84bfc4be0e83f668747211c7cd45a6721d485 F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815 F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4 F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 6a3aaedfb41735996470abbae6d3cd1be1f508b3 -R 5992825785c26c277f0bebde72670a95 +P 02fbdbc782dd98f080bf4482d820f36c0ef3d519 +R 52598be0e985900f7f9c7a3aa6a38f4a U drh -Z 18800c36980a344bd8e3c9fe7e30ed04 +Z c2e03029353f27985e4cc514e9bd561e diff --git a/manifest.uuid b/manifest.uuid index ad9bcac94d..18e5229953 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -02fbdbc782dd98f080bf4482d820f36c0ef3d519 \ No newline at end of file +7782cb1dd5914b867caf5ff2f0f837407abbfd7a \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index a77d3e97d5..8cb26a54ae 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1077,16 +1077,27 @@ insert_cleanup: #undef tmask #endif +/* +** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged() +*/ +#define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */ +#define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */ + /* This is the Walker callback from checkConstraintUnchanged(). Set +** bit 0x01 of pWalker->eCode if ** pWalker->eCode to 0 if this expression node references any of the ** columns that are being modifed by an UPDATE statement. */ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_COLUMN - && pExpr->iColumn>=0 - && pWalker->u.aiCol[pExpr->iColumn]>=0 - ){ - pWalker->eCode = 0; + if( pExpr->op==TK_COLUMN ){ + assert( pExpr->iColumn>=0 || pExpr->iColumn==-1 ); + if( pExpr->iColumn>=0 ){ + if( pWalker->u.aiCol[pExpr->iColumn]>=0 ){ + pWalker->eCode |= CKCNSTRNT_COLUMN; + } + }else{ + pWalker->eCode |= CKCNSTRNT_ROWID; + } } return WRC_Continue; } @@ -1094,19 +1105,22 @@ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ /* ** pExpr is a CHECK constraint on a row that is being UPDATE-ed. The ** only columns that are modified by the UPDATE are those for which -** aiChng[i]>=0. Return true if CHECK constraint pExpr does not use -** any of the changing columns. In other words, return true if this -** CHECK constraint can be skipped when validating the new row in -** the UPDATE statement. +** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true. +** +** Return true if CHECK constraint pExpr does not use any of the +** changing columns (or the rowid if it is changing). In other words, +** return true if this CHECK constraint can be skipped when validating +** the new row in the UPDATE statement. */ -static int checkConstraintUnchanged(Expr *pExpr, int *aiChng){ +static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){ Walker w; memset(&w, 0, sizeof(w)); - w.eCode = 1; + w.eCode = 0; w.xExprCallback = checkConstraintExprNode; w.u.aiCol = aiChng; sqlite3WalkExpr(&w, pExpr); - return w.eCode; + if( !chngRowid ) w.eCode &= ~CKCNSTRNT_ROWID; + return !w.eCode; } /* @@ -1308,7 +1322,7 @@ void sqlite3GenerateConstraintChecks( for(i=0; inExpr; i++){ int allOk = sqlite3VdbeMakeLabel(v); Expr *pExpr = pCheck->a[i].pExpr; - if( aiChng && checkConstraintUnchanged(pExpr, aiChng) ) continue; + if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue; sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL); if( onError==OE_Ignore ){ sqlite3VdbeGoto(v, ignoreDest); diff --git a/test/check.test b/test/check.test index 02b99f2ac9..43e447f70d 100644 --- a/test/check.test +++ b/test/check.test @@ -459,4 +459,24 @@ do_execsql_test 8.1 { CREATE TABLE t811(b, CHECK( xyzzy.t811.b BETWEEN 5 AND 10 )); } {} +# Make sure check constraints involving the ROWID are not ignored +# +do_execsql_test 9.1 { + CREATE TABLE t1( + a INTEGER PRIMARY KEY, + b INTEGER NOT NULL CONSTRAINT 'b-check' CHECK( b>a ), + c INTEGER NOT NULL CONSTRAINT 'c-check' CHECK( c>rowid*2 ), + d INTEGER NOT NULL CONSTRAINT 'd-check' CHECK( d BETWEEN b AND c ) + ); + INSERT INTO t1(a,b,c,d) VALUES(1,2,4,3),(2,4,6,5),(3,10,30,20); +} {} +do_catchsql_test 9.2 { + UPDATE t1 SET b=0 WHERE a=1; +} {1 {CHECK constraint failed: b-check}} +do_catchsql_test 9.3 { + UPDATE t1 SET c=a*2 WHERE a=1; +} {1 {CHECK constraint failed: c-check}} + + + finish_test From 05723a9e3c44b26d8dae814848fc142af8cb74b1 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 10 Feb 2016 19:10:50 +0000 Subject: [PATCH 261/570] Add testcase() macros to the CHECK constraint avoidance logic. Avoid creating an unused VDBE label during CHECK constraint code generation. FossilOrigin-Name: 970881befd5da6cc837c474d6e917de0bf029350 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/insert.c | 12 ++++++++++-- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 2a9e362c52..3bec510d75 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sto\sprevious\scheck-in:\sMake\ssure\sCHECK\sconstraints\sinvolving\sthe\sROWID\nare\snot\signored\swhen\sthe\sROWID\schanges. -D 2016-02-10T18:24:05.782 +C Add\stestcase()\smacros\sto\sthe\sCHECK\sconstraint\savoidance\slogic.\s\sAvoid\screating\nan\sunused\sVDBE\slabel\sduring\sCHECK\sconstraint\scode\sgeneration. +D 2016-02-10T19:10:50.227 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a @@ -309,7 +309,7 @@ F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 6699f029049ea119b652b1464c92cae9f3813247 +F src/insert.c 9ca97272e9f74ed0efddf3b4350ee12740cebbef F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 02fbdbc782dd98f080bf4482d820f36c0ef3d519 -R 52598be0e985900f7f9c7a3aa6a38f4a +P 7782cb1dd5914b867caf5ff2f0f837407abbfd7a +R f678261a2391a665894eb0de22b6791f U drh -Z c2e03029353f27985e4cc514e9bd561e +Z 3c3c66a5988241bd4f12998cbe4ce5b2 diff --git a/manifest.uuid b/manifest.uuid index 18e5229953..2e6049a80a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7782cb1dd5914b867caf5ff2f0f837407abbfd7a \ No newline at end of file +970881befd5da6cc837c474d6e917de0bf029350 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 8cb26a54ae..7ff884b8c3 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1119,7 +1119,14 @@ static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){ w.xExprCallback = checkConstraintExprNode; w.u.aiCol = aiChng; sqlite3WalkExpr(&w, pExpr); - if( !chngRowid ) w.eCode &= ~CKCNSTRNT_ROWID; + if( !chngRowid ){ + testcase( (w.eCode & CKCNSTRNT_ROWID)!=0 ); + w.eCode &= ~CKCNSTRNT_ROWID; + } + testcase( w.eCode==0 ); + testcase( w.eCode==CKCNSTRNT_COLUMN ); + testcase( w.eCode==CKCNSTRNT_ROWID ); + testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) ); return !w.eCode; } @@ -1320,9 +1327,10 @@ void sqlite3GenerateConstraintChecks( pParse->ckBase = regNewData+1; onError = overrideError!=OE_Default ? overrideError : OE_Abort; for(i=0; inExpr; i++){ - int allOk = sqlite3VdbeMakeLabel(v); + int allOk; Expr *pExpr = pCheck->a[i].pExpr; if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue; + allOk = sqlite3VdbeMakeLabel(v); sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL); if( onError==OE_Ignore ){ sqlite3VdbeGoto(v, ignoreDest); From 8988aeef607f1b39e1176d148d8ac786049a3c92 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 10 Feb 2016 21:45:25 +0000 Subject: [PATCH 262/570] In the MSVC makefile, include the working directory so that it can pickup build generated files (e.g. sqlite3.h, etc). FossilOrigin-Name: e9e6000bd2f7e0ef85178db2b5b8f20e4cf0093c --- Makefile.msc | 4 ++-- autoconf/Makefile.msc | 4 ++-- manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 82f405db3b..07319eac94 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -414,8 +414,8 @@ TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS) TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS) !ENDIF -TCC = $(TCC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src -fp:precise -RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS) +TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise +RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS) # Adjust the names of the primary targets for use with Windows 10. # diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index 3dfbb3d20e..d4035602d0 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -399,8 +399,8 @@ TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS) TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS) !ENDIF -TCC = $(TCC) -DSQLITE_OS_WIN=1 -I$(TOP) -fp:precise -RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) $(RCOPTS) $(RCCOPTS) +TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -fp:precise +RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS) # Adjust the names of the primary targets for use with Windows 10. # diff --git a/manifest b/manifest index 3bec510d75..3c4770b096 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Add\stestcase()\smacros\sto\sthe\sCHECK\sconstraint\savoidance\slogic.\s\sAvoid\screating\nan\sunused\sVDBE\slabel\sduring\sCHECK\sconstraint\scode\sgeneration. -D 2016-02-10T19:10:50.227 +C In\sthe\sMSVC\smakefile,\sinclude\sthe\sworking\sdirectory\sso\sthat\sit\scan\spickup\sbuild\sgenerated\sfiles\s(e.g.\ssqlite3.h,\setc). +D 2016-02-10T21:45:25.033 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a +F Makefile.msc 463edfba5c6fccebc61d8c094ccd463a6a55becb F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -11,7 +11,7 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 29e2a6e8d0c5e32723a48b4faf6b168854dde5f4 -F autoconf/Makefile.msc 3ab11cf4b564876efad3f0d59528388e4329b88b +F autoconf/Makefile.msc 6e27530281128adc3e51ce7f95dffbd1da7e64e1 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 7325022e1cd497e1c3a525c97aa1020665e398cf F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7782cb1dd5914b867caf5ff2f0f837407abbfd7a -R f678261a2391a665894eb0de22b6791f -U drh -Z 3c3c66a5988241bd4f12998cbe4ce5b2 +P 970881befd5da6cc837c474d6e917de0bf029350 +R 5eb3b947cad1b703762744d4a1125c44 +U mistachkin +Z 4770d0013fc64e8d84870f88c904e1b8 diff --git a/manifest.uuid b/manifest.uuid index 2e6049a80a..8eebb78161 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -970881befd5da6cc837c474d6e917de0bf029350 \ No newline at end of file +e9e6000bd2f7e0ef85178db2b5b8f20e4cf0093c \ No newline at end of file From c41c132cf07b8793f2d1b4a4d397083e111977de Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 11 Feb 2016 13:30:36 +0000 Subject: [PATCH 263/570] Minor simplifications deferred to the next release. FossilOrigin-Name: a863729ccb75a56330460d3b7d558e639ad733d1 --- manifest | 17 ++++++++++------- manifest.uuid | 2 +- src/build.c | 8 ++------ 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 3c4770b096..6622249d0b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sMSVC\smakefile,\sinclude\sthe\sworking\sdirectory\sso\sthat\sit\scan\spickup\sbuild\sgenerated\sfiles\s(e.g.\ssqlite3.h,\setc). -D 2016-02-10T21:45:25.033 +C Minor\ssimplifications\sdeferred\sto\sthe\snext\srelease. +D 2016-02-11T13:30:36.283 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 463edfba5c6fccebc61d8c094ccd463a6a55becb @@ -294,7 +294,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 4c8caaeed7878aafdb607c3d2bcbc365bb0d19a1 F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 54866fbafa09d494269bdefc79995eb7207003a6 +F src/build.c 7bc84362e4073841df1a24273e5bf87ddf46199f F src/callback.c ed6c2a4a712eb7287ff64e20e3c23265dfb8a7ce F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -1427,7 +1427,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 970881befd5da6cc837c474d6e917de0bf029350 -R 5eb3b947cad1b703762744d4a1125c44 -U mistachkin -Z 4770d0013fc64e8d84870f88c904e1b8 +P e9e6000bd2f7e0ef85178db2b5b8f20e4cf0093c +R d9f96f88af7f04e58e3b08ec636650be +T *branch * simplify +T *sym-simplify * +T -sym-trunk * +U drh +Z 8d2d1255ad136ffbf4de853d8fcb27f6 diff --git a/manifest.uuid b/manifest.uuid index 8eebb78161..e353a95e47 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e9e6000bd2f7e0ef85178db2b5b8f20e4cf0093c \ No newline at end of file +a863729ccb75a56330460d3b7d558e639ad733d1 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 250dc20d20..ed3b5b0426 100644 --- a/src/build.c +++ b/src/build.c @@ -710,12 +710,8 @@ int sqlite3FindDbName(sqlite3 *db, const char *zName){ int i = -1; /* Database number */ if( zName ){ Db *pDb; - int n = sqlite3Strlen30(zName); for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){ - if( (!OMIT_TEMPDB || i!=1 ) && n==sqlite3Strlen30(pDb->zName) && - 0==sqlite3StrICmp(pDb->zName, zName) ){ - break; - } + if( 0==sqlite3StrICmp(pDb->zName, zName) ) break; } } return i; @@ -3237,7 +3233,7 @@ Index *sqlite3CreateIndex( if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break; z1 = pIdx->azColl[k]; z2 = pIndex->azColl[k]; - if( z1!=z2 && sqlite3StrICmp(z1, z2) ) break; + if( sqlite3StrICmp(z1, z2) ) break; } if( k==pIdx->nKeyCol ){ if( pIdx->onError!=pIndex->onError ){ From df3a907eccf70577725c4dd62120221e9d0ff11c Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 11 Feb 2016 15:37:18 +0000 Subject: [PATCH 264/570] Add JSON1 and FTS5 to the set of extensions subject to close compiler warning analysis. Fix some warnings in each. More (harmless) warnings still exist in FTS5. FossilOrigin-Name: cfe2eb88b504f5e9b1351022036641b1ac4c3e78 --- ext/fts5/fts5Int.h | 17 ++++++----------- ext/fts5/fts5_buffer.c | 5 +---- ext/fts5/fts5_config.c | 3 +-- ext/misc/json1.c | 8 +++++++- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- tool/warnings.sh | 6 ++++-- 7 files changed, 31 insertions(+), 32 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index 6318af900f..f8afd1c122 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -80,6 +80,12 @@ extern int sqlite3_fts5_may_be_corrupt; # define assert_nc(x) assert(x) #endif +/* Mark a function parameter as unused, to suppress nuisance compiler +** warnings. */ +#ifndef UNUSED_PARAM +# define UNUSED_PARAM(X) (void)(X) +#endif + typedef struct Fts5Global Fts5Global; typedef struct Fts5Colset Fts5Colset; @@ -345,16 +351,6 @@ struct Fts5IndexIter { int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**); int sqlite3Fts5IndexClose(Fts5Index *p); -/* -** for( -** sqlite3Fts5IndexQuery(p, "token", 5, 0, 0, &pIter); -** 0==sqlite3Fts5IterEof(pIter); -** sqlite3Fts5IterNext(pIter) -** ){ -** i64 iRowid = sqlite3Fts5IterRowid(pIter); -** } -*/ - /* ** Return a simple checksum value based on the arguments. */ @@ -396,7 +392,6 @@ int sqlite3Fts5IndexQuery( */ int sqlite3Fts5IterNext(Fts5IndexIter*); int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch); -i64 sqlite3Fts5IterRowid(Fts5IndexIter*); /* ** Close an iterator opened by sqlite3Fts5IndexQuery(). diff --git a/ext/fts5/fts5_buffer.c b/ext/fts5/fts5_buffer.c index c552e860eb..0098846be9 100644 --- a/ext/fts5/fts5_buffer.c +++ b/ext/fts5/fts5_buffer.c @@ -236,7 +236,7 @@ int sqlite3Fts5PoslistWriterAppend( Fts5PoslistWriter *pWriter, i64 iPos ){ - int rc; + int rc = 0; /* Initialized only to suppress erroneous warning from Clang */ if( fts5BufferGrow(&rc, pBuf, 5+5+5) ) return rc; sqlite3Fts5PoslistSafeAppend(pBuf, &pWriter->iPrev, iPos); return SQLITE_OK; @@ -390,6 +390,3 @@ void sqlite3Fts5TermsetFree(Fts5Termset *p){ sqlite3_free(p); } } - - - diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c index 70b1229edb..f49cede129 100644 --- a/ext/fts5/fts5_config.c +++ b/ext/fts5/fts5_config.c @@ -206,7 +206,7 @@ static int fts5ConfigSetEnum( const char *zEnum, int *peVal ){ - int nEnum = strlen(zEnum); + int nEnum = (int)strlen(zEnum); int i; int iVal = -1; @@ -943,4 +943,3 @@ int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){ } return rc; } - diff --git a/ext/misc/json1.c b/ext/misc/json1.c index 3c63b6e946..99d299c29c 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -31,7 +31,11 @@ SQLITE_EXTENSION_INIT1 #include #include -#define UNUSED_PARAM(X) (void)(X) +/* Mark a function parameter as unused, to suppress nuisance compiler +** warnings. */ +#ifndef UNUSED_PARAM +# define UNUSED_PARAM(X) (void)(X) +#endif #ifndef LARGEST_INT64 # define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) @@ -1552,6 +1556,7 @@ static void jsonArrayStep( sqlite3_value **argv ){ JsonString *pStr; + UNUSED_PARAM(argc); pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); if( pStr ){ if( pStr->zBuf==0 ){ @@ -1597,6 +1602,7 @@ static void jsonObjectStep( JsonString *pStr; const char *z; u32 n; + UNUSED_PARAM(argc); pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); if( pStr ){ if( pStr->zBuf==0 ){ diff --git a/manifest b/manifest index 3c4770b096..2416a082a8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sMSVC\smakefile,\sinclude\sthe\sworking\sdirectory\sso\sthat\sit\scan\spickup\sbuild\sgenerated\sfiles\s(e.g.\ssqlite3.h,\setc). -D 2016-02-10T21:45:25.033 +C Add\sJSON1\sand\sFTS5\sto\sthe\sset\sof\sextensions\ssubject\sto\sclose\scompiler\swarning\nanalysis.\s\sFix\ssome\swarnings\sin\seach.\s\s\sMore\s(harmless)\swarnings\sstill\sexist\nin\sFTS5. +D 2016-02-11T15:37:18.370 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 463edfba5c6fccebc61d8c094ccd463a6a55becb @@ -98,10 +98,10 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 -F ext/fts5/fts5Int.h efb02807dbe5a2bfb0ea592a472d1171cb553d53 +F ext/fts5/fts5Int.h cb495e7cb2d140ab3fc3547750e14d1feeec1ca8 F ext/fts5/fts5_aux.c b9bcce753ef5b451267b2232f0ca153ddeb3951d -F ext/fts5/fts5_buffer.c 5142f73defd7d2ad7419f3a8e487681b38b72097 -F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 +F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd +F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079 F ext/fts5/fts5_expr.c ff5c451a6d025909639ac0f0d0af0cc595b50feb F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 F ext/fts5/fts5_index.c 28f72130400cb54d179a9a120b7232915e3e7a4e @@ -206,7 +206,7 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2 F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c -F ext/misc/json1.c a27cf1eca6583f9b6e18abab5c2a9a82c4540ca9 +F ext/misc/json1.c b9c88d5c3b6ecd8c731ffdd7f5b3d902857f8c96 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc @@ -1425,9 +1425,9 @@ F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003 F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 -F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b +F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 970881befd5da6cc837c474d6e917de0bf029350 -R 5eb3b947cad1b703762744d4a1125c44 -U mistachkin -Z 4770d0013fc64e8d84870f88c904e1b8 +P e9e6000bd2f7e0ef85178db2b5b8f20e4cf0093c +R 203364b475629e5387d880c7b72b1d29 +U drh +Z 7bc360a50dcd258c28a9003183e0bafc diff --git a/manifest.uuid b/manifest.uuid index 8eebb78161..4cf611f727 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e9e6000bd2f7e0ef85178db2b5b8f20e4cf0093c \ No newline at end of file +cfe2eb88b504f5e9b1351022036641b1ac4c3e78 \ No newline at end of file diff --git a/tool/warnings.sh b/tool/warnings.sh index d69cbaf5db..6c7cb3a8f8 100644 --- a/tool/warnings.sh +++ b/tool/warnings.sh @@ -5,9 +5,10 @@ # rm -f sqlite3.c make sqlite3.c -echo '********** No optimizations. Includes FTS4 and RTREE *********' +echo '********** No optimizations. Includes FTS4/5, RTREE, JSON1 ***' gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \ -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \ + -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \ sqlite3.c echo '********** Android configuration ******************************' gcc -c \ @@ -35,7 +36,8 @@ echo '********** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******' gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \ -ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \ sqlite3.c -echo '********** Optimized -O3. Includes FTS4 and RTREE ************' +echo '********** Optimized -O3. Includes FTS4/5, RTREE, JSON1 ******' gcc -O3 -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \ -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \ + -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \ sqlite3.c From 22e835636825069fe854627c913a00f81c7f51ed Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 11 Feb 2016 17:01:32 +0000 Subject: [PATCH 265/570] Handle parser stack overflow when parsing fts5 query expressions. Fix some compiler warnings in fts5 code. FossilOrigin-Name: bc3f7900d5a06829d123814a5ac7b951bcfc1560 --- ext/fts5/fts5Int.h | 6 +++- ext/fts5/fts5_aux.c | 3 ++ ext/fts5/fts5_expr.c | 24 +++++--------- ext/fts5/fts5_index.c | 62 ++++++++++++++++++----------------- ext/fts5/fts5_main.c | 40 ++++++++++++++-------- ext/fts5/fts5_storage.c | 11 ++++--- ext/fts5/fts5_tokenize.c | 15 ++++++--- ext/fts5/fts5_vocab.c | 10 ++++-- ext/fts5/fts5parse.y | 3 +- ext/fts5/test/fts5simple.test | 10 ++++++ manifest | 32 +++++++++--------- manifest.uuid | 2 +- 12 files changed, 129 insertions(+), 89 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index f8afd1c122..dc1954beba 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -86,6 +86,10 @@ extern int sqlite3_fts5_may_be_corrupt; # define UNUSED_PARAM(X) (void)(X) #endif +#ifndef UNUSED_PARAM2 +# define UNUSED_PARAM2(X, Y) (void)(X), (void)(Y) +#endif + typedef struct Fts5Global Fts5Global; typedef struct Fts5Colset Fts5Colset; @@ -676,7 +680,7 @@ int sqlite3Fts5ExprPopulatePoslists( void sqlite3Fts5ExprCheckPoslists(Fts5Expr*, i64); void sqlite3Fts5ExprClearEof(Fts5Expr*); -int sqlite3Fts5ExprClonePhrase(Fts5Config*, Fts5Expr*, int, Fts5Expr**); +int sqlite3Fts5ExprClonePhrase(Fts5Expr*, int, Fts5Expr**); int sqlite3Fts5ExprPhraseCollist(Fts5Expr *, int, const u8 **, int *); diff --git a/ext/fts5/fts5_aux.c b/ext/fts5/fts5_aux.c index 79bed1c8f7..836de8a0f0 100644 --- a/ext/fts5/fts5_aux.c +++ b/ext/fts5/fts5_aux.c @@ -158,6 +158,8 @@ static int fts5HighlightCb( int rc = SQLITE_OK; int iPos; + UNUSED_PARAM2(pToken, nToken); + if( tflags & FTS5_TOKEN_COLOCATED ) return SQLITE_OK; iPos = p->iPos++; @@ -391,6 +393,7 @@ static int fts5CountCb( void *pUserData /* Pointer to sqlite3_int64 variable */ ){ sqlite3_int64 *pn = (sqlite3_int64*)pUserData; + UNUSED_PARAM2(pApi, pFts); (*pn)++; return SQLITE_OK; } diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index 5006d88d0f..d3f801b022 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -320,8 +320,6 @@ static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){ */ static int fts5ExprSynonymList( Fts5ExprTerm *pTerm, - int bCollist, - Fts5Colset *pColset, i64 iRowid, Fts5Buffer *pBuf, /* Use this buffer for space if required */ u8 **pa, int *pn @@ -405,7 +403,6 @@ static int fts5ExprSynonymList( */ static int fts5ExprPhraseIsMatch( Fts5ExprNode *pNode, /* Node pPhrase belongs to */ - Fts5Colset *pColset, /* Restrict matches to these columns */ Fts5ExprPhrase *pPhrase, /* Phrase object to initialize */ int *pbMatch /* OUT: Set to true if really a match */ ){ @@ -434,9 +431,7 @@ static int fts5ExprPhraseIsMatch( u8 *a = 0; if( pTerm->pSynonym ){ Fts5Buffer buf = {0, 0, 0}; - rc = fts5ExprSynonymList( - pTerm, 0, pColset, pNode->iRowid, &buf, &a, &n - ); + rc = fts5ExprSynonymList(pTerm, pNode->iRowid, &buf, &a, &n); if( rc ){ sqlite3_free(a); goto ismatch_out; @@ -727,7 +722,7 @@ static int fts5ExprNearTest( Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){ int bMatch = 0; - rc = fts5ExprPhraseIsMatch(pNode, pNear->pColset, pPhrase, &bMatch); + rc = fts5ExprPhraseIsMatch(pNode, pPhrase, &bMatch); if( bMatch==0 ) break; }else{ Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; @@ -1476,6 +1471,8 @@ static int fts5ParseTokenize( TokenCtx *pCtx = (TokenCtx*)pContext; Fts5ExprPhrase *pPhrase = pCtx->pPhrase; + UNUSED_PARAM2(iUnused1, iUnused2); + /* If an error has already occurred, this is a no-op */ if( pCtx->rc!=SQLITE_OK ) return pCtx->rc; @@ -1611,7 +1608,6 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm( ** expression passed as the second argument. */ int sqlite3Fts5ExprClonePhrase( - Fts5Config *pConfig, Fts5Expr *pExpr, int iPhrase, Fts5Expr **ppNew @@ -1619,14 +1615,10 @@ int sqlite3Fts5ExprClonePhrase( int rc = SQLITE_OK; /* Return code */ Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */ int i; /* Used to iterate through phrase terms */ - Fts5Expr *pNew = 0; /* Expression to return via *ppNew */ - TokenCtx sCtx = {0,0}; /* Context object for fts5ParseTokenize */ - pOrig = pExpr->apExprPhrase[iPhrase]; - pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr)); if( rc==SQLITE_OK ){ pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc, @@ -2399,13 +2391,15 @@ static int fts5ExprPopulatePoslistsCb( int tflags, /* Mask of FTS5_TOKEN_* flags */ const char *pToken, /* Pointer to buffer containing token */ int nToken, /* Size of token in bytes */ - int iStart, /* Byte offset of token within input text */ - int iEnd /* Byte offset of end of token within input text */ + int iUnused1, /* Byte offset of token within input text */ + int iUnused2 /* Byte offset of end of token within input text */ ){ Fts5ExprCtx *p = (Fts5ExprCtx*)pCtx; Fts5Expr *pExpr = p->pExpr; int i; + UNUSED_PARAM2(iUnused1, iUnused2); + if( (tflags & FTS5_TOKEN_COLOCATED)==0 ) p->iOff++; for(i=0; inPhrase; i++){ Fts5ExprTerm *pTerm; @@ -2550,7 +2544,7 @@ int sqlite3Fts5ExprPhraseCollist( if( pTerm->pSynonym ){ Fts5Buffer *pBuf = (Fts5Buffer*)&pTerm->pSynonym[1]; rc = fts5ExprSynonymList( - pTerm, 1, 0, pNode->iRowid, pBuf, (u8**)ppCollist, pnCollist + pTerm, pNode->iRowid, pBuf, (u8**)ppCollist, pnCollist ); }else{ *ppCollist = pPhrase->aTerm[0].pIter->pData; diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 12e18c6445..7605deb327 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -1770,10 +1770,12 @@ static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5Iter *pIter){ static void fts5SegIterNext_Reverse( Fts5Index *p, /* FTS5 backend object */ Fts5SegIter *pIter, /* Iterator to advance */ - int *pbNewTerm /* OUT: Set for new term */ + int *pbUnused /* Unused */ ){ assert( pIter->flags & FTS5_SEGITER_REVERSE ); assert( pIter->pNextLeaf==0 ); + UNUSED_PARAM(pbUnused); + if( pIter->iRowidOffset>0 ){ u8 *a = pIter->pLeaf->p; int iOff; @@ -2250,7 +2252,6 @@ static void fts5LeafSeek( */ static void fts5SegIterSeekInit( Fts5Index *p, /* FTS5 backend */ - Fts5Buffer *pBuf, /* Buffer to use for loading pages */ const u8 *pTerm, int nTerm, /* Term to seek to */ int flags, /* Mask of FTS5INDEX_XXX flags */ Fts5StructureSegment *pSeg, /* Description of segment */ @@ -2637,7 +2638,7 @@ static void fts5SegIterNextFrom( /* ** Free the iterator object passed as the second argument. */ -static void fts5MultiIterFree(Fts5Index *p, Fts5Iter *pIter){ +static void fts5MultiIterFree(Fts5Iter *pIter){ if( pIter ){ int i; for(i=0; inSeg; i++){ @@ -2678,7 +2679,6 @@ static void fts5MultiIterAdvanced( ** that it deals with more complicated cases as well. */ static int fts5MultiIterAdvanceRowid( - Fts5Index *p, /* FTS5 backend to iterate within */ Fts5Iter *pIter, /* Iterator to update aFirst[] array for */ int iChanged, /* Index of sub-iterator just advanced */ Fts5SegIter **ppFirst @@ -2753,7 +2753,7 @@ static void fts5MultiIterNext( } if( pSeg->pLeaf==0 || bNewTerm - || fts5MultiIterAdvanceRowid(p, pIter, iFirst, &pSeg) + || fts5MultiIterAdvanceRowid(pIter, iFirst, &pSeg) ){ fts5MultiIterAdvanced(p, pIter, iFirst, 1); fts5MultiIterSetEof(pIter); @@ -2786,7 +2786,7 @@ static void fts5MultiIterNext2( assert( p->rc==SQLITE_OK ); pSeg->xNext(p, pSeg, &bNewTerm); if( pSeg->pLeaf==0 || bNewTerm - || fts5MultiIterAdvanceRowid(p, pIter, iFirst, &pSeg) + || fts5MultiIterAdvanceRowid(pIter, iFirst, &pSeg) ){ fts5MultiIterAdvanced(p, pIter, iFirst, 1); fts5MultiIterSetEof(pIter); @@ -2800,7 +2800,8 @@ static void fts5MultiIterNext2( } } -static void fts5IterSetOutputs_Noop(Fts5Iter *pIter, Fts5SegIter *pSeg){ +static void fts5IterSetOutputs_Noop(Fts5Iter *pUnused1, Fts5SegIter *pUnused2){ + UNUSED_PARAM2(pUnused1, pUnused2); } static Fts5Iter *fts5MultiIterAlloc( @@ -2826,10 +2827,11 @@ static Fts5Iter *fts5MultiIterAlloc( } static void fts5PoslistCallback( - Fts5Index *p, + Fts5Index *pUnused, void *pContext, const u8 *pChunk, int nChunk ){ + UNUSED_PARAM(pUnused); assert_nc( nChunk>=0 ); if( nChunk>0 ){ fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk); @@ -2863,11 +2865,12 @@ static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){ } static void fts5PoslistOffsetsCallback( - Fts5Index *p, + Fts5Index *pUnused, void *pContext, const u8 *pChunk, int nChunk ){ PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext; + UNUSED_PARAM(pUnused); assert_nc( nChunk>=0 ); if( nChunk>0 ){ int i = 0; @@ -2885,11 +2888,12 @@ static void fts5PoslistOffsetsCallback( } static void fts5PoslistFilterCallback( - Fts5Index *p, + Fts5Index *pUnused, void *pContext, const u8 *pChunk, int nChunk ){ PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext; + UNUSED_PARAM(pUnused); assert_nc( nChunk>=0 ); if( nChunk>0 ){ /* Search through to find the first varint with value 1. This is the @@ -3253,7 +3257,6 @@ static void fts5MultiIterNew( int nSeg = 0; /* Number of segment-iters in use */ int iIter = 0; /* */ int iSeg; /* Used to iterate through segments */ - Fts5Buffer buf = {0,0,0}; /* Buffer used by fts5SegIterSeekInit() */ Fts5StructureLevel *pLvl; Fts5Iter *pNew; @@ -3296,7 +3299,7 @@ static void fts5MultiIterNew( if( pTerm==0 ){ fts5SegIterInit(p, pSeg, pIter); }else{ - fts5SegIterSeekInit(p, &buf, pTerm, nTerm, flags, pSeg, pIter); + fts5SegIterSeekInit(p, pTerm, nTerm, flags, pSeg, pIter); } } } @@ -3333,11 +3336,9 @@ static void fts5MultiIterNew( } }else{ - fts5MultiIterFree(p, pNew); + fts5MultiIterFree(pNew); *ppOut = 0; } - fts5BufferFree(&buf); - } /* @@ -3475,15 +3476,14 @@ static void fts5IndexDiscardData(Fts5Index *p){ } /* -** Return the size of the prefix, in bytes, that buffer (nNew/pNew) shares -** with buffer (nOld/pOld). +** Return the size of the prefix, in bytes, that buffer +** (pNew/) shares with buffer (pOld/nOld). +** +** Buffer (pNew/) is guaranteed to be greater +** than buffer (pOld/nOld). */ -static int fts5PrefixCompress( - int nOld, const u8 *pOld, - int nNew, const u8 *pNew -){ +static int fts5PrefixCompress(int nOld, const u8 *pOld, const u8 *pNew){ int i; - assert( fts5BlobCompare(pOld, nOld, pNew, nNew)<0 ); for(i=0; iterm.n ){ - n = 1 + fts5PrefixCompress(pPage->term.n, pPage->term.p, nTerm, pTerm); + n = 1 + fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm); } fts5WriteBtreeTerm(p, pWriter, n, pTerm); pPage = &pWriter->writer; } }else{ - nPrefix = fts5PrefixCompress(pPage->term.n, pPage->term.p, nTerm, pTerm); + nPrefix = fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm); fts5BufferAppendVarint(&p->rc, &pPage->buf, nPrefix); } @@ -4165,7 +4165,7 @@ static void fts5IndexMergeLevel( pLvl->nMerge = nInput; } - fts5MultiIterFree(p, pIter); + fts5MultiIterFree(pIter); fts5BufferFree(&term); if( pnRem ) *pnRem -= writer.nLeafWritten; } @@ -4541,9 +4541,10 @@ int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){ static void fts5AppendRowid( Fts5Index *p, i64 iDelta, - Fts5Iter *pMulti, + Fts5Iter *pUnused, Fts5Buffer *pBuf ){ + UNUSED_PARAM(pUnused); fts5BufferAppendVarint(&p->rc, pBuf, iDelta); } @@ -4886,7 +4887,7 @@ static void fts5SetupPrefixIter( } fts5BufferFree(&aBuf[i]); } - fts5MultiIterFree(p, p1); + fts5MultiIterFree(p1); pData = fts5IdxMalloc(p, sizeof(Fts5Data) + doclist.n); if( pData ){ @@ -5167,7 +5168,7 @@ int sqlite3Fts5IndexQuery( int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0; buf.p[0] = FTS5_MAIN_PREFIX; fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet); - assert( pRet->pColset==0 ); + assert( p->rc!=SQLITE_OK || pRet->pColset==0 ); fts5IterSetOutputCb(&p->rc, pRet); if( p->rc==SQLITE_OK ){ Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst]; @@ -5250,7 +5251,7 @@ void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){ if( pIndexIter ){ Fts5Iter *pIter = (Fts5Iter*)pIndexIter; Fts5Index *pIndex = pIter->pIndex; - fts5MultiIterFree(pIter->pIndex, pIter); + fts5MultiIterFree(pIter); fts5CloseReader(pIndex); } } @@ -5809,7 +5810,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){ } fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3); - fts5MultiIterFree(p, pIter); + fts5MultiIterFree(pIter); if( p->rc==SQLITE_OK && cksum!=cksum2 ) p->rc = FTS5_CORRUPT; fts5StructureRelease(pStruct); @@ -6046,6 +6047,7 @@ static void fts5DecodeFunction( int eDetailNone = (sqlite3_user_data(pCtx)!=0); assert( nArg==2 ); + UNUSED_PARAM(nArg); memset(&s, 0, sizeof(Fts5Buffer)); iRowid = sqlite3_value_int64(apVal[0]); diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index 4b798314c0..fe1d72e2b0 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -1096,7 +1096,7 @@ static i64 fts5GetRowidLimit(sqlite3_value *pVal, i64 iDefault){ static int fts5FilterMethod( sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ int idxNum, /* Strategy index */ - const char *idxStr, /* Unused */ + const char *zUnused, /* Unused */ int nVal, /* Number of elements in apVal */ sqlite3_value **apVal /* Arguments for the indexing scheme */ ){ @@ -1114,6 +1114,9 @@ static int fts5FilterMethod( sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */ char **pzErrmsg = pConfig->pzErrmsg; + UNUSED_PARAM(zUnused); + UNUSED_PARAM(nVal); + if( pCsr->ePlan ){ fts5FreeCursorComponents(pCsr); memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr)); @@ -1398,8 +1401,7 @@ static int fts5SpecialInsert( static int fts5SpecialDelete( Fts5Table *pTab, - sqlite3_value **apVal, - sqlite3_int64 *piRowid + sqlite3_value **apVal ){ int rc = SQLITE_OK; int eType1 = sqlite3_value_type(apVal[1]); @@ -1475,7 +1477,7 @@ static int fts5UpdateMethod( if( pConfig->eContent!=FTS5_CONTENT_NORMAL && 0==sqlite3_stricmp("delete", z) ){ - rc = fts5SpecialDelete(pTab, apVal, pRowid); + rc = fts5SpecialDelete(pTab, apVal); }else{ rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]); } @@ -1576,6 +1578,7 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){ ** Implementation of xBegin() method. */ static int fts5BeginMethod(sqlite3_vtab *pVtab){ + UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */ fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0); return SQLITE_OK; } @@ -1586,6 +1589,7 @@ static int fts5BeginMethod(sqlite3_vtab *pVtab){ ** by fts5SyncMethod(). */ static int fts5CommitMethod(sqlite3_vtab *pVtab){ + UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */ fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0); return SQLITE_OK; } @@ -1839,12 +1843,14 @@ static sqlite3_int64 fts5ApiRowid(Fts5Context *pCtx){ static int fts5ColumnSizeCb( void *pContext, /* Pointer to int */ int tflags, - const char *pToken, /* Buffer containing token */ - int nToken, /* Size of token in bytes */ - int iStart, /* Start offset of token */ - int iEnd /* End offset of token */ + const char *pUnused, /* Buffer containing token */ + int nUnused, /* Size of token in bytes */ + int iUnused1, /* Start offset of token */ + int iUnused2 /* End offset of token */ ){ int *pCnt = (int*)pContext; + UNUSED_PARAM2(pUnused, nUnused); + UNUSED_PARAM2(iUnused1, iUnused2); if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){ (*pCnt)++; } @@ -1960,10 +1966,11 @@ static void *fts5ApiGetAuxdata(Fts5Context *pCtx, int bClear){ } static void fts5ApiPhraseNext( - Fts5Context *pCtx, + Fts5Context *pUnused, Fts5PhraseIter *pIter, int *piCol, int *piOff ){ + UNUSED_PARAM(pUnused); if( pIter->a>=pIter->b ){ *piCol = -1; *piOff = -1; @@ -2115,12 +2122,11 @@ static int fts5ApiQueryPhrase( rc = fts5OpenMethod(pCsr->base.pVtab, (sqlite3_vtab_cursor**)&pNew); if( rc==SQLITE_OK ){ - Fts5Config *pConf = pTab->pConfig; pNew->ePlan = FTS5_PLAN_MATCH; pNew->iFirstRowid = SMALLEST_INT64; pNew->iLastRowid = LARGEST_INT64; pNew->base.pVtab = (sqlite3_vtab*)pTab; - rc = sqlite3Fts5ExprClonePhrase(pConf, pCsr->pExpr, iPhrase, &pNew->pExpr); + rc = sqlite3Fts5ExprClonePhrase(pCsr->pExpr, iPhrase, &pNew->pExpr); } if( rc==SQLITE_OK ){ @@ -2333,7 +2339,7 @@ static int fts5ColumnMethod( */ static int fts5FindFunctionMethod( sqlite3_vtab *pVtab, /* Virtual table handle */ - int nArg, /* Number of SQL function arguments */ + int nUnused, /* Number of SQL function arguments */ const char *zName, /* Name of SQL function */ void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */ void **ppArg /* OUT: User data for *pxFunc */ @@ -2341,6 +2347,7 @@ static int fts5FindFunctionMethod( Fts5Table *pTab = (Fts5Table*)pVtab; Fts5Auxiliary *pAux; + UNUSED_PARAM(nUnused); pAux = fts5FindAuxiliary(pTab, zName); if( pAux ){ *pxFunc = fts5ApiCallback; @@ -2370,6 +2377,7 @@ static int fts5RenameMethod( */ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ Fts5Table *pTab = (Fts5Table*)pVtab; + UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint); fts5TripCursors(pTab); return sqlite3Fts5StorageSync(pTab->pStorage, 0); @@ -2382,6 +2390,7 @@ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ */ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ Fts5Table *pTab = (Fts5Table*)pVtab; + UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint); fts5TripCursors(pTab); return sqlite3Fts5StorageSync(pTab->pStorage, 0); @@ -2394,6 +2403,7 @@ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ */ static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ Fts5Table *pTab = (Fts5Table*)pVtab; + UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint); fts5TripCursors(pTab); return sqlite3Fts5StorageRollback(pTab->pStorage); @@ -2573,10 +2583,11 @@ static void fts5ModuleDestroy(void *pCtx){ static void fts5Fts5Func( sqlite3_context *pCtx, /* Function call context */ int nArg, /* Number of args */ - sqlite3_value **apVal /* Function arguments */ + sqlite3_value **apUnused /* Function arguments */ ){ Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx); char buf[8]; + UNUSED_PARAM2(nArg, apUnused); assert( nArg==0 ); assert( sizeof(buf)>=sizeof(pGlobal) ); memcpy(buf, (void*)&pGlobal, sizeof(pGlobal)); @@ -2589,9 +2600,10 @@ static void fts5Fts5Func( static void fts5SourceIdFunc( sqlite3_context *pCtx, /* Function call context */ int nArg, /* Number of args */ - sqlite3_value **apVal /* Function arguments */ + sqlite3_value **apUnused /* Function arguments */ ){ assert( nArg==0 ); + UNUSED_PARAM2(nArg, apUnused); sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT); } diff --git a/ext/fts5/fts5_storage.c b/ext/fts5/fts5_storage.c index da9524dea3..e4f5dd8f51 100644 --- a/ext/fts5/fts5_storage.c +++ b/ext/fts5/fts5_storage.c @@ -362,11 +362,12 @@ static int fts5StorageInsertCallback( int tflags, const char *pToken, /* Buffer containing token */ int nToken, /* Size of token in bytes */ - int iStart, /* Start offset of token */ - int iEnd /* End offset of token */ + int iUnused1, /* Start offset of token */ + int iUnused2 /* End offset of token */ ){ Fts5InsertCtx *pCtx = (Fts5InsertCtx*)pContext; Fts5Index *pIdx = pCtx->pStorage->pIndex; + UNUSED_PARAM2(iUnused1, iUnused2); if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){ pCtx->szCol++; } @@ -797,8 +798,8 @@ static int fts5StorageIntegrityCallback( int tflags, const char *pToken, /* Buffer containing token */ int nToken, /* Size of token in bytes */ - int iStart, /* Start offset of token */ - int iEnd /* End offset of token */ + int iUnused1, /* Start offset of token */ + int iUnused2 /* End offset of token */ ){ Fts5IntegrityCtx *pCtx = (Fts5IntegrityCtx*)pContext; Fts5Termset *pTermset = pCtx->pTermset; @@ -808,6 +809,8 @@ static int fts5StorageIntegrityCallback( int iPos; int iCol; + UNUSED_PARAM2(iUnused1, iUnused2); + if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){ pCtx->szCol++; } diff --git a/ext/fts5/fts5_tokenize.c b/ext/fts5/fts5_tokenize.c index 790adaae47..b72a0c24ab 100644 --- a/ext/fts5/fts5_tokenize.c +++ b/ext/fts5/fts5_tokenize.c @@ -62,12 +62,13 @@ static void fts5AsciiDelete(Fts5Tokenizer *p){ ** Create an "ascii" tokenizer. */ static int fts5AsciiCreate( - void *pCtx, + void *pUnused, const char **azArg, int nArg, Fts5Tokenizer **ppOut ){ int rc = SQLITE_OK; AsciiTokenizer *p = 0; + UNUSED_PARAM(pUnused); if( nArg%2 ){ rc = SQLITE_ERROR; }else{ @@ -116,7 +117,7 @@ static void asciiFold(char *aOut, const char *aIn, int nByte){ static int fts5AsciiTokenize( Fts5Tokenizer *pTokenizer, void *pCtx, - int flags, + int iUnused, const char *pText, int nText, int (*xToken)(void*, int, const char*, int nToken, int iStart, int iEnd) ){ @@ -130,6 +131,8 @@ static int fts5AsciiTokenize( char *pFold = aFold; unsigned char *a = p->aTokenChar; + UNUSED_PARAM(iUnused); + while( isnFold; const char *pEnd = &aFold[nFold-6]; + UNUSED_PARAM(iUnused); + /* Each iteration of this loop gobbles up a contiguous run of separators, ** then the next token. */ while( rc==SQLITE_OK ){ diff --git a/ext/fts5/fts5_vocab.c b/ext/fts5/fts5_vocab.c index b17e8974fb..f3a2381cc1 100644 --- a/ext/fts5/fts5_vocab.c +++ b/ext/fts5/fts5_vocab.c @@ -237,7 +237,7 @@ static int fts5VocabCreateMethod( ** Implementation of the xBestIndex method. */ static int fts5VocabBestIndexMethod( - sqlite3_vtab *pVTab, + sqlite3_vtab *pUnused, sqlite3_index_info *pInfo ){ int i; @@ -247,6 +247,8 @@ static int fts5VocabBestIndexMethod( int idxNum = 0; int nArg = 0; + UNUSED_PARAM(pUnused); + for(i=0; inConstraint; i++){ struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; if( p->usable==0 ) continue; @@ -488,8 +490,8 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ static int fts5VocabFilterMethod( sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ int idxNum, /* Strategy index */ - const char *idxStr, /* Unused */ - int nVal, /* Number of elements in apVal */ + const char *zUnused, /* Unused */ + int nUnused, /* Number of elements in apVal */ sqlite3_value **apVal /* Arguments for the indexing scheme */ ){ Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; @@ -504,6 +506,8 @@ static int fts5VocabFilterMethod( sqlite3_value *pGe = 0; sqlite3_value *pLe = 0; + UNUSED_PARAM2(zUnused, nUnused); + fts5VocabResetCursor(pCsr); if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++]; if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++]; diff --git a/ext/fts5/fts5parse.y b/ext/fts5/fts5parse.y index 0e81771b4f..897fff8a1a 100644 --- a/ext/fts5/fts5parse.y +++ b/ext/fts5/fts5parse.y @@ -33,7 +33,8 @@ ); } %stack_overflow { - assert( 0 ); + UNUSED_PARAM(yypMinor); /* Silence some compiler warnings */ + sqlite3Fts5ParseError(pParse, "fts5: parser stack overflow"); } // The name of the generated procedure that implements the parser diff --git a/ext/fts5/test/fts5simple.test b/ext/fts5/test/fts5simple.test index b6563fd9d0..a095a16230 100644 --- a/ext/fts5/test/fts5simple.test +++ b/ext/fts5/test/fts5simple.test @@ -399,5 +399,15 @@ do_execsql_test 18.1 { SELECT rowid FROM x4('""'); } +#------------------------------------------------------------------------- +reset_db +do_execsql_test 19.1 { + CREATE VIRTUAL TABLE x1 USING fts5(a,b,c); +} + +do_catchsql_test 19.2 { + SELECT * FROM x1 WHERE x1 MATCH 'c0 AND (c1 AND (c2 AND (c3 AND (c4 AND (c5 AND (c6 AND (c7 AND (c8 AND (c9 AND (c10 AND (c11 AND (c12 AND (c13 AND (c14 AND (c15 AND (c16 AND (c17 AND (c18 AND (c19 AND (c20 AND (c21 AND (c22 AND (c23 AND (c24 AND (c25 AND (c26 AND (c27 AND (c28 AND (c29 AND (c30 AND (c31 AND (c32 AND (c33 AND (c34 AND (c35 AND (c36 AND (c37 AND (c38 AND (c39 AND (c40 AND (c41 AND (c42 AND (c43 AND (c44 AND (c45 AND (c46 AND (c47 AND (c48 AND (c49 AND (c50 AND (c51 AND (c52 AND (c53 AND (c54 AND (c55 AND (c56 AND (c57 AND (c58 AND (c59 AND (c60 AND (c61 AND (c62 AND (c63 AND (c64 AND (c65 AND (c66 AND (c67 AND (c68 AND (c69 AND (c70 AND (c71 AND (c72 AND (c73 AND (c74 AND (c75 AND (c76 AND (c77 AND (c78 AND (c79 AND (c80 AND (c81 AND (c82 AND (c83 AND (c84 AND (c85 AND (c86 AND (c87 AND (c88 AND (c89 AND (c90 AND (c91 AND (c92 AND (c93 AND (c94 AND (c95 AND (c96 AND (c97 AND (c98 AND (c99 AND (c100 AND (c101 AND (c102 AND (c103 AND (c104 AND (c105 AND (c106 AND (c107 AND (c108 AND (c109 AND (c110 AND (c111 AND (c112 AND (c113 AND (c114 AND (c115 AND (c116 AND (c117 AND (c118 AND (c119 AND (c120 AND (c121 AND (c122 AND (c123 AND (c124 AND (c125 AND (c126 AND (c127 AND (c128 AND (c129 AND (c130 AND (c131 AND (c132 AND (c133 AND (c134 AND (c135 AND (c136 AND (c137 AND (c138 AND (c139 AND (c140 AND (c141 AND (c142 AND (c143 AND (c144 AND (c145 AND (c146 AND (c147 AND (c148 AND (c149 AND (c150 AND (c151 AND (c152 AND (c153 AND (c154 AND (c155 AND (c156 AND (c157 AND (c158 AND (c159 AND (c160 AND (c161 AND (c162 AND (c163 AND (c164 AND (c165 AND (c166 AND (c167 AND (c168 AND (c169 AND (c170 AND (c171 AND (c172 AND (c173 AND (c174 AND (c175 AND (c176 AND (c177 AND (c178 AND (c179 AND (c180 AND (c181 AND (c182 AND (c183 AND (c184 AND (c185 AND (c186 AND (c187 AND (c188 AND (c189 AND (c190 AND (c191 AND (c192 AND (c193 AND (c194 AND (c195 AND (c196 AND (c197 AND (c198 AND (c199 AND c200)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))'; +} {1 {fts5: parser stack overflow}} + finish_test diff --git a/manifest b/manifest index 2416a082a8..e884d73ffa 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sJSON1\sand\sFTS5\sto\sthe\sset\sof\sextensions\ssubject\sto\sclose\scompiler\swarning\nanalysis.\s\sFix\ssome\swarnings\sin\seach.\s\s\sMore\s(harmless)\swarnings\sstill\sexist\nin\sFTS5. -D 2016-02-11T15:37:18.370 +C Handle\sparser\sstack\soverflow\swhen\sparsing\sfts5\squery\sexpressions.\sFix\ssome\scompiler\swarnings\sin\sfts5\scode. +D 2016-02-11T17:01:32.344 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 463edfba5c6fccebc61d8c094ccd463a6a55becb @@ -98,23 +98,23 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 -F ext/fts5/fts5Int.h cb495e7cb2d140ab3fc3547750e14d1feeec1ca8 -F ext/fts5/fts5_aux.c b9bcce753ef5b451267b2232f0ca153ddeb3951d +F ext/fts5/fts5Int.h f9e7772d3ad2b8aac6ad77a5867a254f4422992e +F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458 F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079 -F ext/fts5/fts5_expr.c ff5c451a6d025909639ac0f0d0af0cc595b50feb +F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c 28f72130400cb54d179a9a120b7232915e3e7a4e -F ext/fts5/fts5_main.c 6e23df904049edb498538bd3e22e53ec1ab6f4f7 -F ext/fts5/fts5_storage.c 2a1f44deae090cd711f02cec0c2af8e660360d24 +F ext/fts5/fts5_index.c 12354c3871dc0e84621449ab52e8dc26ada82294 +F ext/fts5/fts5_main.c 0e01ead4e817483e378e7e38e6d902f50b68d29e +F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 F ext/fts5/fts5_test_mi.c 1ec66ffdf7632077fbd773b7a6df5153272ec070 F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be -F ext/fts5/fts5_tokenize.c 4d5c4f183c7d07d144bc219b92da1ea0e962fae3 +F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8 F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738 -F ext/fts5/fts5_vocab.c 3ef401a8d6932db56368de32f446eb9fe73aa623 -F ext/fts5/fts5parse.y 1647eba089b9b3fc058b4dc989d9da87d15b9580 +F ext/fts5/fts5_vocab.c dba72ca393d71c2588548b51380387f6b44c77a8 +F ext/fts5/fts5parse.y 9f4786e16ff2ce16c27552fb4911dc0a033472ef F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba F ext/fts5/test/fts5_common.tcl 61ff0d1a29d98a91c4553b20b3f410d858834ee9 F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 @@ -176,7 +176,7 @@ F ext/fts5/test/fts5rank.test 7e9e64eac7245637f6f2033aec4b292aaf611aab F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17 F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6 -F ext/fts5/test/fts5simple.test 7fcacfa473a37355af2e60096650c87b5ba8f3ba +F ext/fts5/test/fts5simple.test e6fe2fb10a2b9193648b32bbc2caecabdf8c333d F ext/fts5/test/fts5simple2.test 98377ae1ff7749a42c21fe1a139c1ed312522c46 F ext/fts5/test/fts5simple3.test 8e71733b3d1b0e695011d02c68ebc5ca40b6124e F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e9e6000bd2f7e0ef85178db2b5b8f20e4cf0093c -R 203364b475629e5387d880c7b72b1d29 -U drh -Z 7bc360a50dcd258c28a9003183e0bafc +P cfe2eb88b504f5e9b1351022036641b1ac4c3e78 +R ecfecabfdc2e20b17daae28f5e9c8aee +U dan +Z 2089f51bfc7049c8d149969b8c7916a9 diff --git a/manifest.uuid b/manifest.uuid index 4cf611f727..f37a112d36 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cfe2eb88b504f5e9b1351022036641b1ac4c3e78 \ No newline at end of file +bc3f7900d5a06829d123814a5ac7b951bcfc1560 \ No newline at end of file From 2a44b3d87779fae0e6f40c92ada1e8024a549007 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 11 Feb 2016 18:08:38 +0000 Subject: [PATCH 266/570] Avoid a buffer overread when reading a corrupt fts5 structure record. FossilOrigin-Name: facbc424e555061135aced7b134bf6c19f54e484 --- ext/fts5/fts5_index.c | 31 +++++++++++++++++++-------- ext/fts5/test/fts5corrupt3.test | 38 ++++++++++++++++++++++++++++++--- manifest | 14 ++++++------ manifest.uuid | 2 +- 4 files changed, 65 insertions(+), 20 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 7605deb327..2862f623f3 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -879,25 +879,34 @@ static int fts5StructureDecode( int nTotal; int iSeg; - i += fts5GetVarint32(&pData[i], pLvl->nMerge); - i += fts5GetVarint32(&pData[i], nTotal); - assert( nTotal>=pLvl->nMerge ); - pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc, - nTotal * sizeof(Fts5StructureSegment) - ); + if( i>=nData ){ + rc = FTS5_CORRUPT; + }else{ + i += fts5GetVarint32(&pData[i], pLvl->nMerge); + i += fts5GetVarint32(&pData[i], nTotal); + assert( nTotal>=pLvl->nMerge ); + pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc, + nTotal * sizeof(Fts5StructureSegment) + ); + } if( rc==SQLITE_OK ){ pLvl->nSeg = nTotal; for(iSeg=0; iSeg=nData ){ + rc = FTS5_CORRUPT; + break; + } i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].iSegid); i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoFirst); i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoLast); } - }else{ - fts5StructureRelease(pRet); - pRet = 0; } } + if( rc!=SQLITE_OK ){ + fts5StructureRelease(pRet); + pRet = 0; + } } *ppOut = pRet; @@ -1564,6 +1573,10 @@ static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){ int nNew; /* Bytes of new data */ iOff += fts5GetVarint32(&a[iOff], nNew); + if( iOff+nNew>pIter->pLeaf->nn ){ + p->rc = FTS5_CORRUPT; + return; + } pIter->term.n = nKeep; fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]); iOff += nNew; diff --git a/ext/fts5/test/fts5corrupt3.test b/ext/fts5/test/fts5corrupt3.test index dd70f31a6b..7a8cb5c465 100644 --- a/ext/fts5/test/fts5corrupt3.test +++ b/ext/fts5/test/fts5corrupt3.test @@ -334,12 +334,9 @@ do_catchsql_test 6.3.5 { } {1 {database disk image is malformed}} -} - #------------------------------------------------------------------------ # reset_db -reset_db proc rnddoc {n} { set map [list a b c d] set doc [list] @@ -371,6 +368,41 @@ do_test 7.1 { } } {} +} + +#------------------------------------------------------------------------ +# Corruption within the structure record. +# +reset_db +do_execsql_test 8.1 { + CREATE VIRTUAL TABLE t1 USING fts5(x, y); + INSERT INTO t1 VALUES('one', 'two'); +} + +do_test 9.1.1 { + set blob "12345678" ;# cookie + append blob "0105" ;# 1 level, total of 5 segments + append blob "06" ;# write counter + append blob "0002" ;# first level has 0 segments merging, 2 other. + append blob "450108" ;# first segment + execsql "REPLACE INTO t1_data VALUES(10, X'$blob')" +} {} +do_catchsql_test 9.1.2 { + SELECT * FROM t1('one AND two'); +} {1 {database disk image is malformed}} + +do_test 9.2.1 { + set blob "12345678" ;# cookie + append blob "0205" ;# 2 levels, total of 5 segments + append blob "06" ;# write counter + append blob "0001" ;# first level has 0 segments merging, 1 other. + append blob "450108" ;# first segment + execsql "REPLACE INTO t1_data VALUES(10, X'$blob')" +} {} +do_catchsql_test 9.2.2 { + SELECT * FROM t1('one AND two'); +} {1 {database disk image is malformed}} + sqlite3_fts5_may_be_corrupt 0 finish_test diff --git a/manifest b/manifest index e884d73ffa..9b8bf056df 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Handle\sparser\sstack\soverflow\swhen\sparsing\sfts5\squery\sexpressions.\sFix\ssome\scompiler\swarnings\sin\sfts5\scode. -D 2016-02-11T17:01:32.344 +C Avoid\sa\sbuffer\soverread\swhen\sreading\sa\scorrupt\sfts5\sstructure\srecord. +D 2016-02-11T18:08:38.633 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 463edfba5c6fccebc61d8c094ccd463a6a55becb @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c 12354c3871dc0e84621449ab52e8dc26ada82294 +F ext/fts5/fts5_index.c f8afd5cc076726bd9e5807ab62306c85c58cef22 F ext/fts5/fts5_main.c 0e01ead4e817483e378e7e38e6d902f50b68d29e F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -141,7 +141,7 @@ F ext/fts5/test/fts5conflict.test 26f4e46c4d31e16221794832a990dc4e30e18de5 F ext/fts5/test/fts5content.test 9a952c95518a14182dc3b59e3c8fa71cda82a4e1 F ext/fts5/test/fts5corrupt.test c2ad090192708150d50d961278df10ae7a4b8b62 F ext/fts5/test/fts5corrupt2.test 26c0a39dd9ff73207e6229f83b50b21d37c7658c -F ext/fts5/test/fts5corrupt3.test a2b537c120bdd43c79c42fe2438d7b8c81fe5599 +F ext/fts5/test/fts5corrupt3.test b9558d5b0ca44a8b6247fbb5d4a47592a8976892 F ext/fts5/test/fts5detail.test ef5c690535a797413acaf5ad9b8ab5d49972df69 F ext/fts5/test/fts5dlidx.test 13871a14641017ae42f6f1055a8067bafd44cb3d F ext/fts5/test/fts5doclist.test 8edb5b57e5f144030ed74ec00ef6fa4294fed79b @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P cfe2eb88b504f5e9b1351022036641b1ac4c3e78 -R ecfecabfdc2e20b17daae28f5e9c8aee +P bc3f7900d5a06829d123814a5ac7b951bcfc1560 +R 4e2da5472f7a4a893328894fa9813af5 U dan -Z 2089f51bfc7049c8d149969b8c7916a9 +Z 61d305eb29d472167b30ee2488dbe8c6 diff --git a/manifest.uuid b/manifest.uuid index f37a112d36..80694cdd95 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bc3f7900d5a06829d123814a5ac7b951bcfc1560 \ No newline at end of file +facbc424e555061135aced7b134bf6c19f54e484 \ No newline at end of file From df9c59f74d3214cd9f5684c5c66b11601e4e3227 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 11 Feb 2016 18:18:33 +0000 Subject: [PATCH 267/570] Fix another unused variable warning in fts5 code. FossilOrigin-Name: 61b4c120540afd80a4021b0d3990f13acc38a059 --- ext/fts5/fts5parse.y | 3 ++- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/ext/fts5/fts5parse.y b/ext/fts5/fts5parse.y index 897fff8a1a..43936767b7 100644 --- a/ext/fts5/fts5parse.y +++ b/ext/fts5/fts5parse.y @@ -28,12 +28,13 @@ // This code runs whenever there is a syntax error // %syntax_error { + UNUSED_PARAM(yymajor); /* Silence a compiler warning */ sqlite3Fts5ParseError( pParse, "fts5: syntax error near \"%.*s\"",TOKEN.n,TOKEN.p ); } %stack_overflow { - UNUSED_PARAM(yypMinor); /* Silence some compiler warnings */ + UNUSED_PARAM(yypMinor); /* Silence a compiler warning */ sqlite3Fts5ParseError(pParse, "fts5: parser stack overflow"); } diff --git a/manifest b/manifest index 9b8bf056df..f261f4db04 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\sa\sbuffer\soverread\swhen\sreading\sa\scorrupt\sfts5\sstructure\srecord. -D 2016-02-11T18:08:38.633 +C Fix\sanother\sunused\svariable\swarning\sin\sfts5\scode. +D 2016-02-11T18:18:33.214 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 463edfba5c6fccebc61d8c094ccd463a6a55becb @@ -114,7 +114,7 @@ F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8 F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738 F ext/fts5/fts5_vocab.c dba72ca393d71c2588548b51380387f6b44c77a8 -F ext/fts5/fts5parse.y 9f4786e16ff2ce16c27552fb4911dc0a033472ef +F ext/fts5/fts5parse.y 59432ea369f1aa65511bad465f55d31a22f9f223 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba F ext/fts5/test/fts5_common.tcl 61ff0d1a29d98a91c4553b20b3f410d858834ee9 F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P bc3f7900d5a06829d123814a5ac7b951bcfc1560 -R 4e2da5472f7a4a893328894fa9813af5 +P facbc424e555061135aced7b134bf6c19f54e484 +R 36e010c0ed746dc7878f2a118cec7bdd U dan -Z 61d305eb29d472167b30ee2488dbe8c6 +Z 6610f3f01094a7b96f8ca1dff6e9ec45 diff --git a/manifest.uuid b/manifest.uuid index 80694cdd95..5eb5758b92 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -facbc424e555061135aced7b134bf6c19f54e484 \ No newline at end of file +61b4c120540afd80a4021b0d3990f13acc38a059 \ No newline at end of file From c04c54b8420ac11408ef4565936db6a17dbfc814 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 11 Feb 2016 21:28:16 +0000 Subject: [PATCH 268/570] Enhance the MSVC makefile to enable building 'testfixture' fully from source code. FossilOrigin-Name: 54ff3a26bc45a1c3c0690119e8fd00b02e2a16ba --- Makefile.msc | 191 ++++++++++++++++++++++-------------------------- manifest | 21 +++--- manifest.uuid | 2 +- src/os.c | 54 ++++++++++---- src/os_common.h | 28 +++---- 5 files changed, 154 insertions(+), 142 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 07319eac94..6f9262b689 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1005,9 +1005,9 @@ LIBRESOBJS = !ENDIF # <> -# All of the source code files. +# Core source code files, part 1. # -SRC1 = \ +SRC00 = \ $(TOP)\src\alter.c \ $(TOP)\src\analyze.c \ $(TOP)\src\attach.c \ @@ -1016,8 +1016,6 @@ SRC1 = \ $(TOP)\src\bitvec.c \ $(TOP)\src\btmutex.c \ $(TOP)\src\btree.c \ - $(TOP)\src\btree.h \ - $(TOP)\src\btreeInt.h \ $(TOP)\src\build.c \ $(TOP)\src\callback.c \ $(TOP)\src\complete.c \ @@ -1031,8 +1029,6 @@ SRC1 = \ $(TOP)\src\func.c \ $(TOP)\src\global.c \ $(TOP)\src\hash.c \ - $(TOP)\src\hash.h \ - $(TOP)\src\hwtime.h \ $(TOP)\src\insert.c \ $(TOP)\src\journal.c \ $(TOP)\src\legacy.c \ @@ -1045,29 +1041,22 @@ SRC1 = \ $(TOP)\src\mem3.c \ $(TOP)\src\mem5.c \ $(TOP)\src\memjournal.c \ - $(TOP)\src\msvc.h \ $(TOP)\src\mutex.c \ - $(TOP)\src\mutex.h \ $(TOP)\src\mutex_noop.c \ $(TOP)\src\mutex_unix.c \ $(TOP)\src\mutex_w32.c \ $(TOP)\src\notify.c \ $(TOP)\src\os.c \ - $(TOP)\src\os.h \ - $(TOP)\src\os_common.h \ - $(TOP)\src\os_setup.h \ $(TOP)\src\os_unix.c \ - $(TOP)\src\os_win.c \ - $(TOP)\src\os_win.h -SRC2 = \ + $(TOP)\src\os_win.c + +# Core source code files, part 2. +# +SRC01 = \ $(TOP)\src\pager.c \ - $(TOP)\src\pager.h \ - $(TOP)\src\parse.y \ $(TOP)\src\pcache.c \ - $(TOP)\src\pcache.h \ $(TOP)\src\pcache1.c \ $(TOP)\src\pragma.c \ - $(TOP)\src\pragma.h \ $(TOP)\src\prepare.c \ $(TOP)\src\printf.c \ $(TOP)\src\random.c \ @@ -1075,11 +1064,6 @@ SRC2 = \ $(TOP)\src\rowset.c \ $(TOP)\src\select.c \ $(TOP)\src\status.c \ - $(TOP)\src\shell.c \ - $(TOP)\src\sqlite.h.in \ - $(TOP)\src\sqlite3ext.h \ - $(TOP)\src\sqliteInt.h \ - $(TOP)\src\sqliteLimit.h \ $(TOP)\src\table.c \ $(TOP)\src\threads.c \ $(TOP)\src\tclsqlite.c \ @@ -1091,83 +1075,132 @@ SRC2 = \ $(TOP)\src\util.c \ $(TOP)\src\vacuum.c \ $(TOP)\src\vdbe.c \ - $(TOP)\src\vdbe.h \ $(TOP)\src\vdbeapi.c \ $(TOP)\src\vdbeaux.c \ $(TOP)\src\vdbeblob.c \ $(TOP)\src\vdbemem.c \ $(TOP)\src\vdbesort.c \ $(TOP)\src\vdbetrace.c \ - $(TOP)\src\vdbeInt.h \ $(TOP)\src\vtab.c \ - $(TOP)\src\vxworks.h \ $(TOP)\src\wal.c \ - $(TOP)\src\wal.h \ $(TOP)\src\walker.c \ $(TOP)\src\where.c \ $(TOP)\src\wherecode.c \ - $(TOP)\src\whereexpr.c \ + $(TOP)\src\whereexpr.c + +# Shell source code files. +# +SRC02 = \ + $(TOP)\src\shell.c + +# Core miscellaneous files. +# +SRC03 = \ + $(TOP)\src\parse.y + +# Core header files, part 1. +# +SRC04 = \ + $(TOP)\src\btree.h \ + $(TOP)\src\btreeInt.h \ + $(TOP)\src\hash.h \ + $(TOP)\src\hwtime.h \ + $(TOP)\src\msvc.h \ + $(TOP)\src\mutex.h \ + $(TOP)\src\os.h \ + $(TOP)\src\os_common.h \ + $(TOP)\src\os_setup.h \ + $(TOP)\src\os_win.h + +# Core header files, part 2. +# +SRC05 = \ + $(TOP)\src\pager.h \ + $(TOP)\src\pcache.h \ + $(TOP)\src\pragma.h \ + $(TOP)\src\sqlite.h.in \ + $(TOP)\src\sqlite3ext.h \ + $(TOP)\src\sqliteInt.h \ + $(TOP)\src\sqliteLimit.h \ + $(TOP)\src\vdbe.h \ + $(TOP)\src\vdbeInt.h \ + $(TOP)\src\vxworks.h \ + $(TOP)\src\wal.h \ $(TOP)\src\whereInt.h -# Source code for extensions +# Extension source code files, part 1. # -SRC3 = \ +SRC06 = \ $(TOP)\ext\fts1\fts1.c \ - $(TOP)\ext\fts1\fts1.h \ $(TOP)\ext\fts1\fts1_hash.c \ - $(TOP)\ext\fts1\fts1_hash.h \ $(TOP)\ext\fts1\fts1_porter.c \ - $(TOP)\ext\fts1\fts1_tokenizer.h \ $(TOP)\ext\fts1\fts1_tokenizer1.c \ $(TOP)\ext\fts2\fts2.c \ - $(TOP)\ext\fts2\fts2.h \ $(TOP)\ext\fts2\fts2_hash.c \ - $(TOP)\ext\fts2\fts2_hash.h \ $(TOP)\ext\fts2\fts2_icu.c \ $(TOP)\ext\fts2\fts2_porter.c \ - $(TOP)\ext\fts2\fts2_tokenizer.h \ $(TOP)\ext\fts2\fts2_tokenizer.c \ $(TOP)\ext\fts2\fts2_tokenizer1.c -SRC4 = \ + +# Extension source code files, part 2. +# +SRC07 = \ $(TOP)\ext\fts3\fts3.c \ - $(TOP)\ext\fts3\fts3.h \ - $(TOP)\ext\fts3\fts3Int.h \ $(TOP)\ext\fts3\fts3_aux.c \ $(TOP)\ext\fts3\fts3_expr.c \ $(TOP)\ext\fts3\fts3_hash.c \ - $(TOP)\ext\fts3\fts3_hash.h \ $(TOP)\ext\fts3\fts3_icu.c \ $(TOP)\ext\fts3\fts3_porter.c \ $(TOP)\ext\fts3\fts3_snippet.c \ - $(TOP)\ext\fts3\fts3_tokenizer.h \ $(TOP)\ext\fts3\fts3_tokenizer.c \ $(TOP)\ext\fts3\fts3_tokenizer1.c \ $(TOP)\ext\fts3\fts3_tokenize_vtab.c \ $(TOP)\ext\fts3\fts3_unicode.c \ $(TOP)\ext\fts3\fts3_unicode2.c \ $(TOP)\ext\fts3\fts3_write.c \ - $(TOP)\ext\icu\sqliteicu.h \ $(TOP)\ext\icu\icu.c \ - $(TOP)\ext\rtree\rtree.h \ $(TOP)\ext\rtree\rtree.c \ - $(TOP)\ext\rbu\sqlite3rbu.h \ $(TOP)\ext\rbu\sqlite3rbu.c \ $(TOP)\ext\misc\json1.c +# Extension header files, part 1. +# +SRC08 = \ + $(TOP)\ext\fts1\fts1.h \ + $(TOP)\ext\fts1\fts1_hash.h \ + $(TOP)\ext\fts1\fts1_tokenizer.h \ + $(TOP)\ext\fts2\fts2.h \ + $(TOP)\ext\fts2\fts2_hash.h \ + $(TOP)\ext\fts2\fts2_tokenizer.h + +# Extension header files, part 2. +# +SRC09 = \ + $(TOP)\ext\fts3\fts3.h \ + $(TOP)\ext\fts3\fts3Int.h \ + $(TOP)\ext\fts3\fts3_hash.h \ + $(TOP)\ext\fts3\fts3_tokenizer.h \ + $(TOP)\ext\icu\sqliteicu.h \ + $(TOP)\ext\rtree\rtree.h \ + $(TOP)\ext\rbu\sqlite3rbu.h # Generated source code files # -SRC5 = \ - keywordhash.h \ +SRC10 = \ opcodes.c \ + parse.c + +# Generated header files +# +SRC11 = \ + keywordhash.h \ opcodes.h \ - parse.c \ parse.h \ $(SQLITE3H) # All source code files. # -SRC = $(SRC1) $(SRC2) $(SRC3) $(SRC4) $(SRC5) +SRC = $(SRC00) $(SRC01) $(SRC02) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11) # Source code to the test files. # @@ -1216,7 +1249,7 @@ TESTSRC = \ $(TOP)\ext\fts3\fts3_test.c \ $(TOP)\ext\rbu\test_rbu.c -# Statically linked extensions +# Statically linked extensions. # TESTEXT = \ $(TOP)\ext\misc\amatch.c \ @@ -1236,56 +1269,14 @@ TESTEXT = \ $(TOP)\ext\misc\totype.c \ $(TOP)\ext\misc\wholenumber.c - # Source code to the library files needed by the test fixture # TESTSRC2 = \ - $(TOP)\src\attach.c \ - $(TOP)\src\backup.c \ - $(TOP)\src\bitvec.c \ - $(TOP)\src\btree.c \ - $(TOP)\src\build.c \ - $(TOP)\src\ctime.c \ - $(TOP)\src\date.c \ - $(TOP)\src\dbstat.c \ - $(TOP)\src\expr.c \ - $(TOP)\src\func.c \ - $(TOP)\src\insert.c \ - $(TOP)\src\wal.c \ - $(TOP)\src\main.c \ - $(TOP)\src\mem5.c \ - $(TOP)\src\os.c \ - $(TOP)\src\os_unix.c \ - $(TOP)\src\os_win.c \ - $(TOP)\src\pager.c \ - $(TOP)\src\pragma.c \ - $(TOP)\src\prepare.c \ - $(TOP)\src\printf.c \ - $(TOP)\src\random.c \ - $(TOP)\src\pcache.c \ - $(TOP)\src\pcache1.c \ - $(TOP)\src\select.c \ - $(TOP)\src\tokenize.c \ - $(TOP)\src\utf.c \ - $(TOP)\src\util.c \ - $(TOP)\src\vdbeapi.c \ - $(TOP)\src\vdbeaux.c \ - $(TOP)\src\vdbe.c \ - $(TOP)\src\vdbemem.c \ - $(TOP)\src\vdbesort.c \ - $(TOP)\src\vdbetrace.c \ - $(TOP)\src\where.c \ - $(TOP)\src\wherecode.c \ - $(TOP)\src\whereexpr.c \ - parse.c \ - $(TOP)\ext\fts3\fts3.c \ - $(TOP)\ext\fts3\fts3_aux.c \ - $(TOP)\ext\fts3\fts3_expr.c \ - $(TOP)\ext\fts3\fts3_tokenizer.c \ - $(TOP)\ext\fts3\fts3_tokenize_vtab.c \ - $(TOP)\ext\fts3\fts3_unicode.c \ - $(TOP)\ext\fts3\fts3_unicode2.c \ - $(TOP)\ext\fts3\fts3_write.c \ + $(SRC00) \ + $(SRC01) \ + $(SRC06) \ + $(SRC07) \ + $(SRC10) \ $(TOP)\ext\async\sqlite3async.c # Header files used by all library source files. @@ -1460,11 +1451,7 @@ mptest: mptester.exe .target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c -rmdir /Q/S tsrc 2>NUL -mkdir tsrc - for %i in ($(SRC1)) do copy /Y %i tsrc - for %i in ($(SRC2)) do copy /Y %i tsrc - for %i in ($(SRC3)) do copy /Y %i tsrc - for %i in ($(SRC4)) do copy /Y %i tsrc - for %i in ($(SRC5)) do copy /Y %i tsrc + for %i in ($(SRC)) do copy /Y %i tsrc copy /Y fts5.c tsrc copy /Y fts5.h tsrc del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL @@ -1909,7 +1896,7 @@ TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN) -TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) $(SHELL_CORE_DEP) +TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C) !IF $(USE_AMALGAMATION)==0 TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0) diff --git a/manifest b/manifest index f261f4db04..9da855416e 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Fix\sanother\sunused\svariable\swarning\sin\sfts5\scode. -D 2016-02-11T18:18:33.214 +C Enhance\sthe\sMSVC\smakefile\sto\senable\sbuilding\s'testfixture'\sfully\sfrom\ssource\scode. +D 2016-02-11T21:28:16.615 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 463edfba5c6fccebc61d8c094ccd463a6a55becb +F Makefile.msc 5e216ab1a9d71888cd18f759edc37742b22ab88a F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -328,9 +328,9 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4 F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23 F src/mutex_w32.c 5e6fe1c298fb5a8a15aaed4161d5759311431c17 F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7 -F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 +F src/os.c 205fa2bad945a0dc7cad48f9f95ea3e8dc5408ff F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf -F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e +F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 821ed110197175165cf2f50b0930c7ff9a24504c F src/os_win.c ccf29ddded3e41e506b6bd98c1171aa0963b23f2 @@ -1427,7 +1427,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P facbc424e555061135aced7b134bf6c19f54e484 -R 36e010c0ed746dc7878f2a118cec7bdd -U dan -Z 6610f3f01094a7b96f8ca1dff6e9ec45 +P 61b4c120540afd80a4021b0d3990f13acc38a059 +R b57cf2985771e3ae41eb2414d99c4601 +T *branch * testFixtureSrc +T *sym-testFixtureSrc * +T -sym-trunk * +U mistachkin +Z 5a46bf6df8254b3a0e184f4d03ced4bc diff --git a/manifest.uuid b/manifest.uuid index 5eb5758b92..25c4002fdb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -61b4c120540afd80a4021b0d3990f13acc38a059 \ No newline at end of file +54ff3a26bc45a1c3c0690119e8fd00b02e2a16ba \ No newline at end of file diff --git a/src/os.c b/src/os.c index 2a2cf13c5e..90130d0eb7 100644 --- a/src/os.c +++ b/src/os.c @@ -17,6 +17,28 @@ #include "sqliteInt.h" #undef _SQLITE_OS_C_ +/* +** If we compile with the SQLITE_TEST macro set, then the following block +** of code will give us the ability to simulate a disk I/O error. This +** is used for testing the I/O recovery logic. +*/ +#if defined(SQLITE_TEST) +int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */ +int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */ +int sqlite3_io_error_pending = 0; /* Count down to first I/O error */ +int sqlite3_io_error_persist = 0; /* True if I/O errors persist */ +int sqlite3_io_error_benign = 0; /* True if errors are benign */ +int sqlite3_diskfull_pending = 0; +int sqlite3_diskfull = 0; +#endif /* defined(SQLITE_TEST) */ + +/* +** When testing, also keep a count of the number of open files. +*/ +#if defined(SQLITE_TEST) +int sqlite3_open_file_count = 0; +#endif /* defined(SQLITE_TEST) */ + /* ** The default SQLite sqlite3_vfs implementations do not allocate ** memory (actually, os_unix.c allocates a small amount of memory @@ -24,7 +46,7 @@ ** So we test the effects of a malloc() failing and the sqlite3OsXXX() ** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro. ** -** The following functions are instrumented for malloc() failure +** The following functions are instrumented for malloc() failure ** testing: ** ** sqlite3OsRead() @@ -110,8 +132,8 @@ int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ #ifdef SQLITE_TEST if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){ /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite - ** is using a regular VFS, it is called after the corresponding - ** transaction has been committed. Injecting a fault at this point + ** is using a regular VFS, it is called after the corresponding + ** transaction has been committed. Injecting a fault at this point ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM ** but the transaction is committed anyway. ** @@ -180,10 +202,10 @@ int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){ ** VFS methods. */ int sqlite3OsOpen( - sqlite3_vfs *pVfs, - const char *zPath, - sqlite3_file *pFile, - int flags, + sqlite3_vfs *pVfs, + const char *zPath, + sqlite3_file *pFile, + int flags, int *pFlagsOut ){ int rc; @@ -202,18 +224,18 @@ int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ return pVfs->xDelete(pVfs, zPath, dirSync); } int sqlite3OsAccess( - sqlite3_vfs *pVfs, - const char *zPath, - int flags, + sqlite3_vfs *pVfs, + const char *zPath, + int flags, int *pResOut ){ DO_OS_MALLOC_TEST(0); return pVfs->xAccess(pVfs, zPath, flags, pResOut); } int sqlite3OsFullPathname( - sqlite3_vfs *pVfs, - const char *zPath, - int nPathOut, + sqlite3_vfs *pVfs, + const char *zPath, + int nPathOut, char *zPathOut ){ DO_OS_MALLOC_TEST(0); @@ -259,9 +281,9 @@ int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ } int sqlite3OsOpenMalloc( - sqlite3_vfs *pVfs, - const char *zFile, - sqlite3_file **ppFile, + sqlite3_vfs *pVfs, + const char *zFile, + sqlite3_file **ppFile, int flags, int *pOutFlags ){ diff --git a/src/os_common.h b/src/os_common.h index d18b95a5ff..1ed4d7a8e1 100644 --- a/src/os_common.h +++ b/src/os_common.h @@ -35,8 +35,8 @@ */ #ifdef SQLITE_PERFORMANCE_TRACE -/* -** hwtime.h contains inline assembler code for implementing +/* +** hwtime.h contains inline assembler code for implementing ** high-performance timing routines. */ #include "hwtime.h" @@ -57,14 +57,14 @@ static sqlite_uint64 g_elapsed; ** of code will give us the ability to simulate a disk I/O error. This ** is used for testing the I/O recovery logic. */ -#ifdef SQLITE_TEST -int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */ -int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */ -int sqlite3_io_error_pending = 0; /* Count down to first I/O error */ -int sqlite3_io_error_persist = 0; /* True if I/O errors persist */ -int sqlite3_io_error_benign = 0; /* True if errors are benign */ -int sqlite3_diskfull_pending = 0; -int sqlite3_diskfull = 0; +#if defined(SQLITE_TEST) +extern int sqlite3_io_error_hit; +extern int sqlite3_io_error_hardhit; +extern int sqlite3_io_error_pending; +extern int sqlite3_io_error_persist; +extern int sqlite3_io_error_benign; +extern int sqlite3_diskfull_pending; +extern int sqlite3_diskfull; #define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) #define SimulateIOError(CODE) \ if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ @@ -90,16 +90,16 @@ static void local_ioerr(){ #define SimulateIOErrorBenign(X) #define SimulateIOError(A) #define SimulateDiskfullError(A) -#endif +#endif /* defined(SQLITE_TEST) */ /* ** When testing, keep a count of the number of open files. */ -#ifdef SQLITE_TEST -int sqlite3_open_file_count = 0; +#if defined(SQLITE_TEST) +extern int sqlite3_open_file_count; #define OpenCounter(X) sqlite3_open_file_count+=(X) #else #define OpenCounter(X) -#endif +#endif /* defined(SQLITE_TEST) */ #endif /* !defined(_OS_COMMON_H_) */ From e2eb259fcec2f8b6b86530780891a1697e21a8c3 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 11 Feb 2016 21:38:05 +0000 Subject: [PATCH 269/570] Prevent 'expanded command line X too long' errors during the batch 'for' loops used for copying files. FossilOrigin-Name: 67ee9b5af10a8b57a37f19ac040e49fdfcec4145 --- Makefile.msc | 13 ++++++++++++- manifest | 15 ++++++--------- manifest.uuid | 2 +- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 6f9262b689..be11982e09 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1451,7 +1451,18 @@ mptest: mptester.exe .target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c -rmdir /Q/S tsrc 2>NUL -mkdir tsrc - for %i in ($(SRC)) do copy /Y %i tsrc + for %i in ($(SRC00)) do copy /Y %i tsrc + for %i in ($(SRC01)) do copy /Y %i tsrc + for %i in ($(SRC02)) do copy /Y %i tsrc + for %i in ($(SRC03)) do copy /Y %i tsrc + for %i in ($(SRC04)) do copy /Y %i tsrc + for %i in ($(SRC05)) do copy /Y %i tsrc + for %i in ($(SRC06)) do copy /Y %i tsrc + for %i in ($(SRC07)) do copy /Y %i tsrc + for %i in ($(SRC08)) do copy /Y %i tsrc + for %i in ($(SRC09)) do copy /Y %i tsrc + for %i in ($(SRC10)) do copy /Y %i tsrc + for %i in ($(SRC11)) do copy /Y %i tsrc copy /Y fts5.c tsrc copy /Y fts5.h tsrc del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL diff --git a/manifest b/manifest index 9da855416e..ea98d2649c 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Enhance\sthe\sMSVC\smakefile\sto\senable\sbuilding\s'testfixture'\sfully\sfrom\ssource\scode. -D 2016-02-11T21:28:16.615 +C Prevent\s'expanded\scommand\sline\sX\stoo\slong'\serrors\sduring\sthe\sbatch\s'for'\sloops\sused\sfor\scopying\sfiles. +D 2016-02-11T21:38:05.552 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 5e216ab1a9d71888cd18f759edc37742b22ab88a +F Makefile.msc 9df6e7ea267d09a63ba845df044bf3afe9e4fa48 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -1427,10 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 61b4c120540afd80a4021b0d3990f13acc38a059 -R b57cf2985771e3ae41eb2414d99c4601 -T *branch * testFixtureSrc -T *sym-testFixtureSrc * -T -sym-trunk * +P 54ff3a26bc45a1c3c0690119e8fd00b02e2a16ba +R 42eb6f3594e981fa7242203e9049d719 U mistachkin -Z 5a46bf6df8254b3a0e184f4d03ced4bc +Z 06f173e2669b6a296587f217c0e00623 diff --git a/manifest.uuid b/manifest.uuid index 25c4002fdb..f63ccd12dd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -54ff3a26bc45a1c3c0690119e8fd00b02e2a16ba \ No newline at end of file +67ee9b5af10a8b57a37f19ac040e49fdfcec4145 \ No newline at end of file From 5d2e2f12679f92c93388a470949755d36285c5b0 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 11 Feb 2016 21:53:57 +0000 Subject: [PATCH 270/570] Remove the unused fts5BlobCompare() routine. FossilOrigin-Name: defc762dd11144402abd591278819768a080d5ea --- ext/fts5/fts5_index.c | 11 ----------- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 2862f623f3..c40ffbcbb5 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -607,17 +607,6 @@ static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){ return (res==0 ? (pLeft->n - pRight->n) : res); } -#ifdef SQLITE_DEBUG -static int fts5BlobCompare( - const u8 *pLeft, int nLeft, - const u8 *pRight, int nRight -){ - int nCmp = MIN(nLeft, nRight); - int res = memcmp(pLeft, pRight, nCmp); - return (res==0 ? (nLeft - nRight) : res); -} -#endif - static int fts5LeafFirstTermOff(Fts5Data *pLeaf){ int ret; fts5GetVarint32(&pLeaf->p[pLeaf->szLeaf], ret); diff --git a/manifest b/manifest index f261f4db04..d74e897598 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sanother\sunused\svariable\swarning\sin\sfts5\scode. -D 2016-02-11T18:18:33.214 +C Remove\sthe\sunused\sfts5BlobCompare()\sroutine. +D 2016-02-11T21:53:57.918 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 463edfba5c6fccebc61d8c094ccd463a6a55becb @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 -F ext/fts5/fts5_index.c f8afd5cc076726bd9e5807ab62306c85c58cef22 +F ext/fts5/fts5_index.c c6cd5190c7e5dd94151cb17acd939c82e5c7be2d F ext/fts5/fts5_main.c 0e01ead4e817483e378e7e38e6d902f50b68d29e F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P facbc424e555061135aced7b134bf6c19f54e484 -R 36e010c0ed746dc7878f2a118cec7bdd -U dan -Z 6610f3f01094a7b96f8ca1dff6e9ec45 +P 61b4c120540afd80a4021b0d3990f13acc38a059 +R 529687379591fdd4d2bd925d4a922f7c +U drh +Z 880ed5157f4e91bf42a07f9f7d321ea0 diff --git a/manifest.uuid b/manifest.uuid index 5eb5758b92..0644ca9445 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -61b4c120540afd80a4021b0d3990f13acc38a059 \ No newline at end of file +defc762dd11144402abd591278819768a080d5ea \ No newline at end of file From c50d5908b4c8d246f888409de4f0cf553d36d49d Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 11 Feb 2016 21:55:23 +0000 Subject: [PATCH 271/570] Remove the unexplained extra 3.0 cost factor for the B-tree sorting that is done to implement DISTINCT in the absence of an index to help. FossilOrigin-Name: 52571991fcfa2629e8a8354e0c9a62e749a092bf --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 8 -------- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index d74e897598..cb6259bcc2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\sunused\sfts5BlobCompare()\sroutine. -D 2016-02-11T21:53:57.918 +C Remove\sthe\sunexplained\sextra\s3.0\scost\sfactor\sfor\sthe\sB-tree\ssorting\sthat\sis\ndone\sto\simplement\sDISTINCT\sin\sthe\sabsence\sof\san\sindex\sto\shelp. +D 2016-02-11T21:55:23.162 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 463edfba5c6fccebc61d8c094ccd463a6a55becb @@ -427,7 +427,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c d21b99fd1458159d0b1ecdccc8ee6ada4fdc4c54 F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c d89fd5cff448ab5c5ca492dd9793b35ffe31ab35 +F src/where.c f9683f8b881106e441971bc5eda216722ab16d4c F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a F src/wherecode.c 791a784bbf8749d560fdb0b990b607bc4f44a38d F src/whereexpr.c de117970b29471177a6901d60ad83a194671dc03 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 61b4c120540afd80a4021b0d3990f13acc38a059 -R 529687379591fdd4d2bd925d4a922f7c +P defc762dd11144402abd591278819768a080d5ea +R 38eca6b8eb9deb3a2f0fef0b239b97c5 U drh -Z 880ed5157f4e91bf42a07f9f7d321ea0 +Z 4bfab18ef2ae74dd28795db9a6295a18 diff --git a/manifest.uuid b/manifest.uuid index 0644ca9445..16e0c11371 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -defc762dd11144402abd591278819768a080d5ea \ No newline at end of file +52571991fcfa2629e8a8354e0c9a62e749a092bf \ No newline at end of file diff --git a/src/where.c b/src/where.c index 1bee2ca6fe..73e921f6b3 100644 --- a/src/where.c +++ b/src/where.c @@ -3460,14 +3460,6 @@ static LogEst whereSortingCost( assert( nOrderBy>0 && 66==sqlite3LogEst(100) ); rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66; rSortCost = nRow + estLog(nRow) + rScale + 16; - - /* TUNING: The cost of implementing DISTINCT using a B-TREE is - ** similar but with a larger constant of proportionality. - ** Multiply by an additional factor of 3.0. */ - if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){ - rSortCost += 16; - } - return rSortCost; } From 4553f6ea9129ec695178ce3953f36ed4756f36a9 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 11 Feb 2016 22:41:04 +0000 Subject: [PATCH 272/570] Automatically disable FTS3 and FTS4 when building with SQLITE_OMIT_VIRTUALTABLE. FossilOrigin-Name: 0beb32d20d8dd698138cdb2de6b6056de176754d --- ext/fts3/fts3Int.h | 6 ++++++ manifest | 17 ++++++++--------- manifest.uuid | 2 +- src/sqliteInt.h | 7 +++++++ 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h index 06bcc7202e..0c86c4217e 100644 --- a/ext/fts3/fts3Int.h +++ b/ext/fts3/fts3Int.h @@ -18,6 +18,12 @@ # define NDEBUG 1 #endif +/* FTS3/FTS4 require virtual tables */ +#ifdef SQLITE_OMIT_VIRTUALTABLE +# undef SQLITE_ENABLE_FTS3 +# undef SQLITE_ENABLE_FTS4 +#endif + /* ** FTS4 is really an extension for FTS3. It is enabled using the ** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all diff --git a/manifest b/manifest index 663f1f222b..0f3c507fc9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\sMSVC\smakefile\sto\senable\sbuilding\s'testfixture'\sfully\sfrom\ssource\scode. -D 2016-02-11T21:59:02.687 +C Automatically\sdisable\sFTS3\sand\sFTS4\swhen\sbuilding\swith\sSQLITE_OMIT_VIRTUALTABLE. +D 2016-02-11T22:41:04.941 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 9df6e7ea267d09a63ba845df044bf3afe9e4fa48 @@ -72,7 +72,7 @@ F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d F ext/fts3/fts3.c e028eb13432f108d2e22cded019fc980700e4e00 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe -F ext/fts3/fts3Int.h c84125c666ee54cef6efce6ff64abb0d0e2f4535 +F ext/fts3/fts3Int.h 89d0bd4595a0de384dac78e94b803de12586e8dd F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 F ext/fts3/fts3_expr.c dfd571a24412779ac01f25c01d888c6ef7b2d0ef F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60 @@ -353,7 +353,7 @@ F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h eb20019610d0bd25c7479ddfdef1fd4c00854dc2 +F src/sqliteInt.h 04ca5b3cdb3bcf87ba6300d5d36b51498f65f28c F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -1427,8 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 52571991fcfa2629e8a8354e0c9a62e749a092bf 67ee9b5af10a8b57a37f19ac040e49fdfcec4145 -R 433c8d6ed9428ba17eccff539cc26ec2 -T +closed 67ee9b5af10a8b57a37f19ac040e49fdfcec4145 -U mistachkin -Z 14072e3fe80b7f74a81b8ac3aab7b0a7 +P f183e05990608d1a4002fa8a02c2d2eea6bc94b6 +R dfe12fb76097c62e2abe5dbb44ef76aa +U drh +Z 0896e1216887463484734b70a95ecf26 diff --git a/manifest.uuid b/manifest.uuid index 9b76eadb00..64e2c743fb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f183e05990608d1a4002fa8a02c2d2eea6bc94b6 \ No newline at end of file +0beb32d20d8dd698138cdb2de6b6056de176754d \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 001416d56b..f04aebe79a 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3170,6 +3170,13 @@ int sqlite3CantopenError(int); #define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__) #define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__) +/* +** FTS3 and FTS4 both require virtual table support +*/ +#if defined(SQLITE_OMIT_VIRTUALTABLE) +# undef SQLITE_ENABLE_FTS3 +# undef SQLITE_ENABLE_FTS4 +#endif /* ** FTS4 is really an extension for FTS3. It is enabled using the From f9810937604f756ef65e62a87ad6da3e4be2c4ee Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 12 Feb 2016 00:13:38 +0000 Subject: [PATCH 273/570] Remove an unused parameter from whereSortingCost(). FossilOrigin-Name: b5d771991686bf86a679b7dff9f16301a5029c8b --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 3 +-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 0f3c507fc9..9ff5f47757 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Automatically\sdisable\sFTS3\sand\sFTS4\swhen\sbuilding\swith\sSQLITE_OMIT_VIRTUALTABLE. -D 2016-02-11T22:41:04.941 +C Remove\san\sunused\sparameter\sfrom\swhereSortingCost(). +D 2016-02-12T00:13:38.283 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 9df6e7ea267d09a63ba845df044bf3afe9e4fa48 @@ -427,7 +427,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c d21b99fd1458159d0b1ecdccc8ee6ada4fdc4c54 F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c f9683f8b881106e441971bc5eda216722ab16d4c +F src/where.c 984084584c10c41e46c89ac027a5cca991bc37e6 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a F src/wherecode.c 791a784bbf8749d560fdb0b990b607bc4f44a38d F src/whereexpr.c de117970b29471177a6901d60ad83a194671dc03 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f183e05990608d1a4002fa8a02c2d2eea6bc94b6 -R dfe12fb76097c62e2abe5dbb44ef76aa +P 0beb32d20d8dd698138cdb2de6b6056de176754d +R 0940ecab971a56d675704b07d9c453fc U drh -Z 0896e1216887463484734b70a95ecf26 +Z 74867ce3130a7e0367ef4e3542a53928 diff --git a/manifest.uuid b/manifest.uuid index 64e2c743fb..2ea2fcaa13 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0beb32d20d8dd698138cdb2de6b6056de176754d \ No newline at end of file +b5d771991686bf86a679b7dff9f16301a5029c8b \ No newline at end of file diff --git a/src/where.c b/src/where.c index 73e921f6b3..8ecdd840f3 100644 --- a/src/where.c +++ b/src/where.c @@ -3438,7 +3438,6 @@ static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){ ** order. */ static LogEst whereSortingCost( - WhereInfo *pWInfo, LogEst nRow, int nOrderBy, int nSorted @@ -3593,7 +3592,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ if( isOrdered>=0 && isOrdered Date: Fri, 12 Feb 2016 05:19:29 +0000 Subject: [PATCH 274/570] Naming updates for Universal Windows Platform. FossilOrigin-Name: 717c1fc41a2246e27b324a4071073c286bac4efc --- Makefile.msc | 10 +++++----- autoconf/Makefile.msc | 10 +++++----- autoconf/README.txt | 4 ++-- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- tool/mkvsix.tcl | 10 +++++----- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index be11982e09..843f9a2537 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -126,12 +126,12 @@ USE_RC = 1 FOR_WINRT = 0 !ENDIF -# Set this non-0 to compile binaries suitable for the UAP environment. +# Set this non-0 to compile binaries suitable for the UWP environment. # This setting does not apply to any binaries that require Tcl to operate # properly (i.e. the text fixture, etc). # -!IFNDEF FOR_UAP -FOR_UAP = 0 +!IFNDEF FOR_UWP +FOR_UWP = 0 !ENDIF # Set this non-0 to compile binaries suitable for the Windows 10 platform. @@ -907,10 +907,10 @@ LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelH LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib !ENDIF -# When compiling for UAP or the Windows 10 platform, some extra linker +# When compiling for UWP or the Windows 10 platform, some extra linker # options are also required. # -!IF $(FOR_UAP)!=0 || $(FOR_WIN10)!=0 +!IF $(FOR_UWP)!=0 || $(FOR_WIN10)!=0 LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib LTLINKOPTS = $(LTLINKOPTS) mincore.lib !IFDEF PSDKLIBPATH diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index d4035602d0..0be42b4e5f 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -119,12 +119,12 @@ USE_RC = 1 FOR_WINRT = 0 !ENDIF -# Set this non-0 to compile binaries suitable for the UAP environment. +# Set this non-0 to compile binaries suitable for the UWP environment. # This setting does not apply to any binaries that require Tcl to operate # properly (i.e. the text fixture, etc). # -!IFNDEF FOR_UAP -FOR_UAP = 0 +!IFNDEF FOR_UWP +FOR_UWP = 0 !ENDIF # Set this non-0 to compile binaries suitable for the Windows 10 platform. @@ -802,10 +802,10 @@ LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelH LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib !ENDIF -# When compiling for UAP or the Windows 10 platform, some extra linker +# When compiling for UWP or the Windows 10 platform, some extra linker # options are also required. # -!IF $(FOR_UAP)!=0 || $(FOR_WIN10)!=0 +!IF $(FOR_UWP)!=0 || $(FOR_WIN10)!=0 LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib LTLINKOPTS = $(LTLINKOPTS) mincore.lib !IFDEF PSDKLIBPATH diff --git a/autoconf/README.txt b/autoconf/README.txt index fd5605ea9f..2d6db4f07f 100644 --- a/autoconf/README.txt +++ b/autoconf/README.txt @@ -75,10 +75,10 @@ NMAKE command line as well: "NSDKLIBPATH=%WindowsSdkDir%\..\8.1\lib\winv6.3\um\x86" -Building for UAP 10.0 +Building for UWP 10.0 --------------------- - FOR_WINRT=1 FOR_UAP=1 + FOR_WINRT=1 FOR_UWP=1 Using Microsoft Visual C++ 2015 (or later) is required. When using the above, something like the following macros will need to be added to the diff --git a/manifest b/manifest index 9ff5f47757..70492224b1 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Remove\san\sunused\sparameter\sfrom\swhereSortingCost(). -D 2016-02-12T00:13:38.283 +C Naming\supdates\sfor\sUniversal\sWindows\sPlatform. +D 2016-02-12T05:19:29.324 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 9df6e7ea267d09a63ba845df044bf3afe9e4fa48 +F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -11,9 +11,9 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 29e2a6e8d0c5e32723a48b4faf6b168854dde5f4 -F autoconf/Makefile.msc 6e27530281128adc3e51ce7f95dffbd1da7e64e1 +F autoconf/Makefile.msc b865d2c72cf43cbf39913336415556af8ff2e819 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 -F autoconf/README.txt 7325022e1cd497e1c3a525c97aa1020665e398cf +F autoconf/README.txt 7c31da66232f7590bb987cfcd4e2381744b25d24 F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8 F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 @@ -1394,7 +1394,7 @@ F tool/mksqlite3c-noext.tcl 87240b09c20042999b41d5fabe091b7111287835 F tool/mksqlite3c.tcl b66b4170f693602cd6985aed15d9509fe2f18c84 F tool/mksqlite3h.tcl 1d41ab59bffb025121f75b76e183125ce41b3ec8 F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b -F tool/mkvsix.tcl bbe57cd9ae11c6cc70319241101ef8d2b8c3765b +F tool/mkvsix.tcl fbeb0af7cffdf64e0fba6d65e2e5120dc14595f4 F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091 F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97 F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0beb32d20d8dd698138cdb2de6b6056de176754d -R 0940ecab971a56d675704b07d9c453fc -U drh -Z 74867ce3130a7e0367ef4e3542a53928 +P b5d771991686bf86a679b7dff9f16301a5029c8b +R c5c7b0be1a525c29164d455010760517 +U mistachkin +Z 6d4d0f2a2e82ddbc9f26fd9ded605bf1 diff --git a/manifest.uuid b/manifest.uuid index 2ea2fcaa13..d3f9c73b4b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b5d771991686bf86a679b7dff9f16301a5029c8b \ No newline at end of file +717c1fc41a2246e27b324a4071073c286bac4efc \ No newline at end of file diff --git a/tool/mkvsix.tcl b/tool/mkvsix.tcl index b7c5983dbe..a14fd230d9 100644 --- a/tool/mkvsix.tcl +++ b/tool/mkvsix.tcl @@ -389,7 +389,7 @@ set shortNames(WP80,2013) SQLite.WP80.2013 set shortNames(WP81,2013) SQLite.WP81 set shortNames(Win32,2012) SQLite.Win32 set shortNames(Win32,2013) SQLite.Win32.2013 -set shortNames(UAP,2015) SQLite.UAP.2015 +set shortNames(UWP,2015) SQLite.UWP.2015 set displayNames(WinRT,2012) "SQLite for Windows Runtime" set displayNames(WinRT,2013) "SQLite for Windows Runtime" @@ -399,7 +399,7 @@ set displayNames(WP80,2013) "SQLite for Windows Phone" set displayNames(WP81,2013) "SQLite for Windows Phone 8.1" set displayNames(Win32,2012) "SQLite for Windows" set displayNames(Win32,2013) "SQLite for Windows" -set displayNames(UAP,2015) "SQLite for Universal App Platform" +set displayNames(UWP,2015) "SQLite for Universal Windows Platform" if {[string equal $packageFlavor WinRT]} then { set shortName $shortNames($packageFlavor,$vsVersion) @@ -455,7 +455,7 @@ if {[string equal $packageFlavor WinRT]} then { set extraSdkPath "\\..\\$targetPlatformIdentifier" set extraFileListAttributes \ [getExtraFileListXmlChunk $packageFlavor $vsVersion] -} elseif {[string equal $packageFlavor UAP]} then { +} elseif {[string equal $packageFlavor UWP]} then { if {$vsVersion ne "2015"} then { fail [appendArgs \ "unsupported combination, package flavor " $packageFlavor \ @@ -463,7 +463,7 @@ if {[string equal $packageFlavor WinRT]} then { } set shortName $shortNames($packageFlavor,$vsVersion) set displayName $displayNames($packageFlavor,$vsVersion) - set targetPlatformIdentifier UAP + set targetPlatformIdentifier UWP set targetPlatformVersion v0.8.0.0 set minVsVersion [getMinVsVersionXmlChunk $vsVersion] set maxPlatformVersion \ @@ -485,7 +485,7 @@ if {[string equal $packageFlavor WinRT]} then { } else { fail [appendArgs \ "unsupported package flavor, must be one of: " \ - [list WinRT WinRT81 WP80 WP81 UAP Win32]] + [list WinRT WinRT81 WP80 WP81 UWP Win32]] } ############################################################################### From cd4235252674efa6183a34a409d024f02f247f38 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 12 Feb 2016 17:27:32 +0000 Subject: [PATCH 275/570] Enhance mptester so that it takes great care to delete its test database prior to start-up, including checking the return code from unlink() and retrying after a delay if unlink() fails. Hopefully this will clear intermittant startup problems on Windows. FossilOrigin-Name: 6ea84ec1e02f0a48953bc758027ab7148529c36e --- main.mk | 5 ++--- manifest | 16 ++++++++-------- manifest.uuid | 2 +- mptest/mptest.c | 32 +++++++++++++++++++++++++++++++- 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/main.mk b/main.mk index 509f4c8273..e9920180d9 100644 --- a/main.mk +++ b/main.mk @@ -500,10 +500,9 @@ mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c $(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \ $(TLIBS) $(THREADLIB) -MPTEST1=./mptester$(EXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20 -MPTEST2=./mptester$(EXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20 +MPTEST1=./mptester$(EXE) mptest1.db $(TOP)/mptest/crash01.test --repeat 20 +MPTEST2=./mptester$(EXE) mptest2.db $(TOP)/mptest/multiwrite01.test --repeat 20 mptest: mptester$(EXE) - rm -f mptest.db $(MPTEST1) --journalmode DELETE $(MPTEST2) --journalmode WAL $(MPTEST1) --journalmode WAL diff --git a/manifest b/manifest index 70492224b1..d9310dec28 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Naming\supdates\sfor\sUniversal\sWindows\sPlatform. -D 2016-02-12T05:19:29.324 +C Enhance\smptester\sso\sthat\sit\stakes\sgreat\scare\sto\sdelete\sits\stest\sdatabase\nprior\sto\sstart-up,\sincluding\schecking\sthe\sreturn\scode\sfrom\sunlink()\sand\nretrying\safter\sa\sdelay\sif\sunlink()\sfails.\s\sHopefully\sthis\swill\sclear\s\nintermittant\sstartup\sproblems\son\sWindows. +D 2016-02-12T17:27:32.074 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -272,13 +272,13 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk aecd0ce0646db48754e2a14523f759593f8ed072 +F main.mk 791597b87204f6bd56cdf7b2ab2feeecd608c60d F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421 F mptest/crash02.subtest f4ef05adcd15d60e5d2bd654204f2c008b519df8 -F mptest/mptest.c 0d3f2eb8e373cb692ab362a6dddedd53e0978502 +F mptest/mptest.c aa41ace6dbc5050d76b02548d3521e6bbccae4f0 F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b5d771991686bf86a679b7dff9f16301a5029c8b -R c5c7b0be1a525c29164d455010760517 -U mistachkin -Z 6d4d0f2a2e82ddbc9f26fd9ded605bf1 +P 717c1fc41a2246e27b324a4071073c286bac4efc +R fe68ada3af9b678ecc7b1b483d0cc9f6 +U drh +Z 04c3f99151f7ad228f455f6f996d4b70 diff --git a/manifest.uuid b/manifest.uuid index d3f9c73b4b..9dddc65265 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -717c1fc41a2246e27b324a4071073c286bac4efc \ No newline at end of file +6ea84ec1e02f0a48953bc758027ab7148529c36e \ No newline at end of file diff --git a/mptest/mptest.c b/mptest/mptest.c index b29ebdc9e1..5022b009e6 100644 --- a/mptest/mptest.c +++ b/mptest/mptest.c @@ -41,6 +41,7 @@ #else # include #endif +#include #include #include #include @@ -1244,6 +1245,19 @@ static void usage(const char *argv0){ if( isDirSep(argv0[i]) ) zTail = argv0+i+1; } fprintf(stderr,"Usage: %s DATABASE ?OPTIONS? ?SCRIPT?\n", zTail); + fprintf(stderr, + "Options:\n" + " --errlog FILENAME Write errors to FILENAME\n" + " --journalmode MODE Use MODE as the journal_mode\n" + " --log FILENAME Log messages to FILENAME\n" + " --quiet Suppress unnecessary output\n" + " --vfs NAME Use NAME as the VFS\n" + " --repeat N Repeat the test N times\n" + " --sqltrace Enable SQL tracing\n" + " --sync Enable synchronous disk writes\n" + " --timeout MILLISEC Busy timeout is MILLISEC\n" + " --trace BOOLEAN Enable or disable tracing\n" + ); exit(1); } @@ -1275,6 +1289,8 @@ int SQLITE_CDECL main(int argc, char **argv){ const char *zJMode; const char *zNRep; int nRep = 1, iRep; + int iTmout = 0; /* Default: no timeout */ + const char *zTmout; g.argv0 = argv[0]; g.iTrace = 1; @@ -1301,6 +1317,8 @@ int SQLITE_CDECL main(int argc, char **argv){ zTrace = findOption(argv+2, &n, "trace", 1); if( zTrace ) g.iTrace = atoi(zTrace); if( findOption(argv+2, &n, "quiet", 0)!=0 ) g.iTrace = 0; + zTmout = findOption(argv+2, &n, "timeout", 1); + if( zTmout ) iTmout = atoi(zTmout); g.bSqlTrace = findOption(argv+2, &n, "sqltrace", 0)!=0; g.bSync = findOption(argv+2, &n, "sync", 0)!=0; if( g.zErrLog ){ @@ -1321,6 +1339,7 @@ int SQLITE_CDECL main(int argc, char **argv){ sqlite3_snprintf(sizeof(g.zName), g.zName, "%05d.client%02d", GETPID(), iClient); }else{ + int nTry = 0; if( g.iTrace>0 ){ printf("BEGIN: %s", argv[0]); for(i=1; i5 ? "still " : "", g.zDbFile); + rc = unlink(g.zDbFile); + if( rc && errno==ENOENT ) rc = 0; + }while( rc!=0 && (++nTry)<60 && sqlite3_sleep(1000)>0 ); + if( rc!=0 ){ + fatalError("unable to unlink '%s' after %d attempts\n", + g.zDbFile, nTry); + } openFlags |= SQLITE_OPEN_CREATE; } rc = sqlite3_open_v2(g.zDbFile, &g.db, openFlags, g.zVfs); if( rc ) fatalError("cannot open [%s]", g.zDbFile); + if( iTmout>0 ) sqlite3_busy_timeout(g.db, iTmout); + if( zJMode ){ #if defined(_WIN32) if( sqlite3_stricmp(zJMode,"persist")==0 From aa622c1f4f2e066ff1d1f1b1701a6401bd3447de Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 12 Feb 2016 17:30:39 +0000 Subject: [PATCH 276/570] Fix a documentation typo. No changes to code. FossilOrigin-Name: d9c985878cf7c74a79ccdb9cf94a2d48fdde3e6f --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqlite.h.in | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index d9310dec28..ba9bd0d561 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\smptester\sso\sthat\sit\stakes\sgreat\scare\sto\sdelete\sits\stest\sdatabase\nprior\sto\sstart-up,\sincluding\schecking\sthe\sreturn\scode\sfrom\sunlink()\sand\nretrying\safter\sa\sdelay\sif\sunlink()\sfails.\s\sHopefully\sthis\swill\sclear\s\nintermittant\sstartup\sproblems\son\sWindows. -D 2016-02-12T17:27:32.074 +C Fix\sa\sdocumentation\stypo.\s\sNo\schanges\sto\scode. +D 2016-02-12T17:30:39.594 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -350,7 +350,7 @@ F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c ff80004a9a6ece891a8d9327a88e7b6e2588ee6d F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe -F src/sqlite.h.in cf22ad1d52dca2c9862d63833e581028119aab7e +F src/sqlite.h.in f80c6ebd85588fc514bfedf3ecb00cec269cb410 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d F src/sqliteInt.h 04ca5b3cdb3bcf87ba6300d5d36b51498f65f28c @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 717c1fc41a2246e27b324a4071073c286bac4efc -R fe68ada3af9b678ecc7b1b483d0cc9f6 +P 6ea84ec1e02f0a48953bc758027ab7148529c36e +R 32f39dbecc6e1b0fd64cf3f801eef486 U drh -Z 04c3f99151f7ad228f455f6f996d4b70 +Z 253162cb9c4e3721df2895ed3fc41a73 diff --git a/manifest.uuid b/manifest.uuid index 9dddc65265..ef66c089c1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6ea84ec1e02f0a48953bc758027ab7148529c36e \ No newline at end of file +d9c985878cf7c74a79ccdb9cf94a2d48fdde3e6f \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index fce396c0f6..9e7222bd50 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -347,7 +347,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** from [sqlite3_malloc()] and passed back through the 5th parameter. ** To avoid memory leaks, the application should invoke [sqlite3_free()] ** on error message strings returned through the 5th parameter of -** of sqlite3_exec() after the error message string is no longer needed. +** sqlite3_exec() after the error message string is no longer needed. ** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors ** occur, then sqlite3_exec() sets the pointer in its 5th parameter to ** NULL before returning. From f2d328fa2542b279aa2642b9c7a19e1b39ff53bf Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 12 Feb 2016 17:56:27 +0000 Subject: [PATCH 277/570] Fix a fairly obscure buffer overread in fts5. FossilOrigin-Name: 130580207ab5cee762b2893808acef7c8afad027 --- ext/fts5/fts5Int.h | 1 + ext/fts5/fts5_hash.c | 7 +-- ext/fts5/test/fts5hash.test | 95 ++++++++++++++++++++++--------------- manifest | 18 +++---- manifest.uuid | 2 +- 5 files changed, 72 insertions(+), 51 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index dc1954beba..af40412167 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -26,6 +26,7 @@ SQLITE_EXTENSION_INIT1 typedef unsigned char u8; typedef unsigned int u32; typedef unsigned short u16; +typedef short i16; typedef sqlite3_int64 i64; typedef sqlite3_uint64 u64; diff --git a/ext/fts5/fts5_hash.c b/ext/fts5/fts5_hash.c index 50ca082711..ada8bb16cb 100644 --- a/ext/fts5/fts5_hash.c +++ b/ext/fts5/fts5_hash.c @@ -62,10 +62,10 @@ struct Fts5HashEntry { int nAlloc; /* Total size of allocation */ int iSzPoslist; /* Offset of space for 4-byte poslist size */ int nData; /* Total bytes of data (incl. structure) */ + int nKey; /* Length of zKey[] in bytes */ u8 bDel; /* Set delete-flag @ iSzPoslist */ u8 bContent; /* Set content-flag (detail=none mode) */ - - int iCol; /* Column of last value written */ + i16 iCol; /* Column of last value written */ int iPos; /* Position of last value written */ i64 iRowid; /* Rowid of last value written */ char zKey[8]; /* Nul-terminated entry key */ @@ -245,8 +245,8 @@ int sqlite3Fts5HashWrite( iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken); for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){ if( p->zKey[0]==bByte + && p->nKey==nToken && memcmp(&p->zKey[1], pToken, nToken)==0 - && p->zKey[nToken+1]==0 ){ break; } @@ -273,6 +273,7 @@ int sqlite3Fts5HashWrite( p->zKey[0] = bByte; memcpy(&p->zKey[1], pToken, nToken); assert( iHash==fts5HashKey(pHash->nSlot, (u8*)p->zKey, nToken+1) ); + p->nKey = nToken; p->zKey[nToken+1] = '\0'; p->nData = nToken+1 + 1 + FTS5_HASHENTRYSIZE; p->pHashNext = pHash->aSlot[iHash]; diff --git a/ext/fts5/test/fts5hash.test b/ext/fts5/test/fts5hash.test index ac8486f070..f3952d6157 100644 --- a/ext/fts5/test/fts5hash.test +++ b/ext/fts5/test/fts5hash.test @@ -66,47 +66,66 @@ proc random_doc {vocab nWord} { foreach_detail_mode $testprefix { -set vocab [build_vocab1] -db func r random_doc - -do_execsql_test 1.0 { - CREATE VIRTUAL TABLE eee USING fts5(e, ee, detail=%DETAIL%); - BEGIN; - WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100) - INSERT INTO eee SELECT r($vocab, 5), r($vocab, 7) FROM ii; - INSERT INTO eee(eee) VALUES('integrity-check'); - COMMIT; - INSERT INTO eee(eee) VALUES('integrity-check'); -} - -set hash [sqlite3_fts5_token_hash 1024 xyz] -set vocab [build_vocab1 -prefix xyz -hash $hash] -lappend vocab xyz - -do_execsql_test 1.1 { - CREATE VIRTUAL TABLE vocab USING fts5vocab(eee, 'row'); - BEGIN; -} -do_test 1.2 { - for {set i 1} {$i <= 100} {incr i} { - execsql { INSERT INTO eee VALUES( r($vocab, 5), r($vocab, 7) ) } - } -} {} + set vocab [build_vocab1] + db func r random_doc -do_test 1.3 { - db eval { SELECT term, doc FROM vocab } { - set nRow [db one {SELECT count(*) FROM eee WHERE eee MATCH $term}] - if {$nRow != $doc} { - error "term=$term fts5vocab=$doc cnt=$nRow" - } + do_execsql_test 1.0 { + CREATE VIRTUAL TABLE eee USING fts5(e, ee, detail=%DETAIL%); + BEGIN; + WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100) + INSERT INTO eee SELECT r($vocab, 5), r($vocab, 7) FROM ii; + INSERT INTO eee(eee) VALUES('integrity-check'); + COMMIT; + INSERT INTO eee(eee) VALUES('integrity-check'); + } + + set hash [sqlite3_fts5_token_hash 1024 xyz] + set vocab [build_vocab1 -prefix xyz -hash $hash] + lappend vocab xyz + + do_execsql_test 1.1 { + CREATE VIRTUAL TABLE vocab USING fts5vocab(eee, 'row'); + BEGIN; + } + do_test 1.2 { + for {set i 1} {$i <= 100} {incr i} { + execsql { INSERT INTO eee VALUES( r($vocab, 5), r($vocab, 7) ) } + } + } {} + + do_test 1.3 { + db eval { SELECT term, doc FROM vocab } { + set nRow [db one {SELECT count(*) FROM eee WHERE eee MATCH $term}] + if {$nRow != $doc} { + error "term=$term fts5vocab=$doc cnt=$nRow" + } + } + set {} {} + } {} + + do_execsql_test 1.4 { + COMMIT; + INSERT INTO eee(eee) VALUES('integrity-check'); } - set {} {} -} {} -do_execsql_test 1.4 { - COMMIT; - INSERT INTO eee(eee) VALUES('integrity-check'); -} + #----------------------------------------------------------------------- + # Add a small and very large token with the same hash value to an + # empty table. At one point this would provoke an asan error. + # + do_test 2.0 { + set big [string repeat 12345 40] + set hash [sqlite3_fts5_token_hash 1024 $big] + while {1} { + set small [random_token] + if {[sqlite3_fts5_token_hash 1024 $small]==$hash} break + } + + execsql { CREATE VIRTUAL TABLE t2 USING fts5(x, detail=%DETAIL%) } +breakpoint + execsql { + INSERT INTO t2 VALUES($small || ' ' || $big); + } + } {} } ;# foreach_detail_mode diff --git a/manifest b/manifest index ba9bd0d561..0dad1bc0fe 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sdocumentation\stypo.\s\sNo\schanges\sto\scode. -D 2016-02-12T17:30:39.594 +C Fix\sa\sfairly\sobscure\sbuffer\soverread\sin\sfts5. +D 2016-02-12T17:56:27.467 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -98,12 +98,12 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 -F ext/fts5/fts5Int.h f9e7772d3ad2b8aac6ad77a5867a254f4422992e +F ext/fts5/fts5Int.h fa7c17e5c3ec9c8690387ff962f9dc6aee75e114 F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458 F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 -F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 +F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 F ext/fts5/fts5_index.c c6cd5190c7e5dd94151cb17acd939c82e5c7be2d F ext/fts5/fts5_main.c 0e01ead4e817483e378e7e38e6d902f50b68d29e F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e @@ -158,7 +158,7 @@ F ext/fts5/test/fts5fault8.test 430837fe6dd0511fd3aea52bd602ac02441bcb58 F ext/fts5/test/fts5fault9.test e10e395428a9ea0596ebe752ff7123d16ab78e08 F ext/fts5/test/fts5faultA.test fa5d59c0ff62b7125cd14eee38ded1c46e15a7ea F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741 -F ext/fts5/test/fts5hash.test 00668f6fa9b9bffbd7c1be29f408aa2bdade0451 +F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d F ext/fts5/test/fts5matchinfo.test 86569026d20f1ed748236587ce798de8a96615f1 F ext/fts5/test/fts5merge.test 8f3cdba2ec9c5e7e568246e81b700ad37f764367 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 6ea84ec1e02f0a48953bc758027ab7148529c36e -R 32f39dbecc6e1b0fd64cf3f801eef486 -U drh -Z 253162cb9c4e3721df2895ed3fc41a73 +P d9c985878cf7c74a79ccdb9cf94a2d48fdde3e6f +R 0a862bd7a75e07028d820b1669759dd1 +U dan +Z 281d4ece2b41724c1d776859918d3659 diff --git a/manifest.uuid b/manifest.uuid index ef66c089c1..d57148a112 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d9c985878cf7c74a79ccdb9cf94a2d48fdde3e6f \ No newline at end of file +130580207ab5cee762b2893808acef7c8afad027 \ No newline at end of file From 53ff9c2972aed305e67f3a28375c35977bb17534 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 12 Feb 2016 18:48:09 +0000 Subject: [PATCH 278/570] Fix a potential buffer overread provoked by invalid utf-8 in fts5. FossilOrigin-Name: a049fbbde5da2e43d41aa8c2b41f9eb21507ac76 --- ext/fts3/unicode/mkunicode.tcl | 4 ++-- ext/fts5/fts5_unicode2.c | 4 ++-- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ext/fts3/unicode/mkunicode.tcl b/ext/fts3/unicode/mkunicode.tcl index a2e9b1da29..aafb4e9f9b 100644 --- a/ext/fts3/unicode/mkunicode.tcl +++ b/ext/fts3/unicode/mkunicode.tcl @@ -226,9 +226,9 @@ proc print_isalnum {zFunc lRange} { an_print_range_array $lRange an_print_ascii_bitmap $lRange puts { - if( c<128 ){ + if( (unsigned int)c<128 ){ return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); - }else if( c<(1<<22) ){ + }else if( (unsigned int)c<(1<<22) ){ unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; int iRes = 0; int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; diff --git a/ext/fts5/fts5_unicode2.c b/ext/fts5/fts5_unicode2.c index 8ad709d0fd..1ef56f6156 100644 --- a/ext/fts5/fts5_unicode2.c +++ b/ext/fts5/fts5_unicode2.c @@ -125,9 +125,9 @@ int sqlite3Fts5UnicodeIsalnum(int c){ 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001, }; - if( c<128 ){ + if( (unsigned int)c<128 ){ return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); - }else if( c<(1<<22) ){ + }else if( (unsigned int)c<(1<<22) ){ unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; int iRes = 0; int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; diff --git a/manifest b/manifest index 0dad1bc0fe..edbefc847e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sfairly\sobscure\sbuffer\soverread\sin\sfts5. -D 2016-02-12T17:56:27.467 +C Fix\sa\spotential\sbuffer\soverread\sprovoked\sby\sinvalid\sutf-8\sin\sfts5. +D 2016-02-12T18:48:09.224 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -94,7 +94,7 @@ F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/fts3/tool/fts3view.c 5d78b668f4e9598af9147f8999632599fb0d9dd5 F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7 -F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252 +F ext/fts3/unicode/mkunicode.tcl 2debed3f582d77b3fdd0b8830880250021571fd8 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 @@ -111,7 +111,7 @@ F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 F ext/fts5/fts5_test_mi.c 1ec66ffdf7632077fbd773b7a6df5153272ec070 F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8 -F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c +F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738 F ext/fts5/fts5_vocab.c dba72ca393d71c2588548b51380387f6b44c77a8 F ext/fts5/fts5parse.y 59432ea369f1aa65511bad465f55d31a22f9f223 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P d9c985878cf7c74a79ccdb9cf94a2d48fdde3e6f -R 0a862bd7a75e07028d820b1669759dd1 +P 130580207ab5cee762b2893808acef7c8afad027 +R f6628307ca7dcc5e74da260d3c3d6ac5 U dan -Z 281d4ece2b41724c1d776859918d3659 +Z 7972d84e46f7d6d6e270e54f6c76821e diff --git a/manifest.uuid b/manifest.uuid index d57148a112..10c0eea158 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -130580207ab5cee762b2893808acef7c8afad027 \ No newline at end of file +a049fbbde5da2e43d41aa8c2b41f9eb21507ac76 \ No newline at end of file From 6fee795885e8d4c5032e40d58892caa0861e2f14 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 13 Feb 2016 14:39:46 +0000 Subject: [PATCH 279/570] Fix a problem in sessionfault.test causing it to segfault following a test failure. This commit does not fix the actual test failure - just the subsequent segfault. FossilOrigin-Name: 582b2ae77d65b1e142ceb5774f37b0aaa3851378 --- ext/session/sessionfault.test | 3 ++- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index 39f27bfe6d..dfe15a50c8 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -361,7 +361,7 @@ do_faultsim_test 6 -faults oom-* -body { } faultsim_delete_and_reopen -do_execsql_test 5.prep1 { +do_execsql_test 7.prep1 { CREATE TABLE t1(a, b, PRIMARY KEY(a)); } faultsim_save_and_close @@ -372,6 +372,7 @@ for {set ::i 0} {$::i < 480} {incr ::i 4} { } set res [lsort $res] do_faultsim_test 7 -faults oom-transient -prep { + catch { S delete } faultsim_restore_and_reopen sqlite3session S db main S attach * diff --git a/manifest b/manifest index 3107e34770..4fc05623b8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\schanges\sfor\sthe\s3.11.0\srelease\scandidate\sfrom\strunk. -D 2016-02-13T14:07:56.771 +C Fix\sa\sproblem\sin\ssessionfault.test\scausing\sit\sto\ssegfault\sfollowing\sa\stest\sfailure.\sThis\scommit\sdoes\snot\sfix\sthe\sactual\stest\sfailure\s-\sjust\sthe\ssubsequent\ssegfault. +D 2016-02-13T14:39:46.492 F Makefile.in 5cbf3f753328d1bcd3a6117785b4874d99612f8f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 45e596bd4ccecf2256f68a2e96466aa52cc4bc1f @@ -282,7 +282,7 @@ F ext/session/sessionD.test d4744c78334162851d2a2f285c7e603e31b49aa2 F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26 F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596 -F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc +F ext/session/sessionfault.test 94a4dd100e16cf0b1c44d8487517dbb407eeab1d F ext/session/sqlite3session.c 1ace1d1e4cb32cf60ca6e8ed1ae8d4c9f99ca458 F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce @@ -1448,7 +1448,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f040a5bb62f3473fba6450c97c68f538d1df21ef a049fbbde5da2e43d41aa8c2b41f9eb21507ac76 -R 622532d44eb7d789368cb4bcd5c9c290 -U drh -Z 7f2e42b2e725136d738cebdbb2b0b796 +P 4d7a802e73ef0352f840bc8d74c560afb7666ff7 +R 56ec775a8f26a6fc9784a8bb5f2be4e3 +U dan +Z 3166b3068d23321aad4e67ff074e960a diff --git a/manifest.uuid b/manifest.uuid index 1b543c3534..c918008c70 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4d7a802e73ef0352f840bc8d74c560afb7666ff7 \ No newline at end of file +582b2ae77d65b1e142ceb5774f37b0aaa3851378 \ No newline at end of file From 50d348b1e1dca5f05f79843e8f01dbf7b3572285 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 13 Feb 2016 14:45:56 +0000 Subject: [PATCH 280/570] Harden sqlite3session_delete() against trying to delete a session that is not currently on the session list. FossilOrigin-Name: 6c2d34df76fb7823f307c11a1135ab30674421a9 --- ext/session/sqlite3session.c | 10 +++++++--- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 546a22a072..312e03dcfb 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1615,9 +1615,13 @@ void sqlite3session_delete(sqlite3_session *pSession){ ** database handle. Hold the db mutex while doing so. */ sqlite3_mutex_enter(sqlite3_db_mutex(db)); pHead = (sqlite3_session*)sqlite3_preupdate_hook(db, 0, 0); - for(pp=&pHead; (*pp)!=pSession; pp=&((*pp)->pNext)); - *pp = (*pp)->pNext; - if( pHead ) sqlite3_preupdate_hook(db, xPreUpdate, (void *)pHead); + for(pp=&pHead; ALWAYS((*pp)!=0); pp=&((*pp)->pNext)){ + if( (*pp)==pSession ){ + *pp = (*pp)->pNext; + if( pHead ) sqlite3_preupdate_hook(db, xPreUpdate, (void*)pHead); + break; + } + } sqlite3_mutex_leave(sqlite3_db_mutex(db)); /* Delete all attached table objects. And the contents of their diff --git a/manifest b/manifest index 4fc05623b8..27189df562 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\sin\ssessionfault.test\scausing\sit\sto\ssegfault\sfollowing\sa\stest\sfailure.\sThis\scommit\sdoes\snot\sfix\sthe\sactual\stest\sfailure\s-\sjust\sthe\ssubsequent\ssegfault. -D 2016-02-13T14:39:46.492 +C Harden\ssqlite3session_delete()\sagainst\strying\sto\sdelete\sa\ssession\sthat\nis\snot\scurrently\son\sthe\ssession\slist. +D 2016-02-13T14:45:56.852 F Makefile.in 5cbf3f753328d1bcd3a6117785b4874d99612f8f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 45e596bd4ccecf2256f68a2e96466aa52cc4bc1f @@ -283,7 +283,7 @@ F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26 F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596 F ext/session/sessionfault.test 94a4dd100e16cf0b1c44d8487517dbb407eeab1d -F ext/session/sqlite3session.c 1ace1d1e4cb32cf60ca6e8ed1ae8d4c9f99ca458 +F ext/session/sqlite3session.c b10af3e87ae437bb197b3a23a584d2dc8ad8981a F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1448,7 +1448,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4d7a802e73ef0352f840bc8d74c560afb7666ff7 -R 56ec775a8f26a6fc9784a8bb5f2be4e3 -U dan -Z 3166b3068d23321aad4e67ff074e960a +P 582b2ae77d65b1e142ceb5774f37b0aaa3851378 +R 99d33fcea6ce08ff5ef828796adb3d5d +U drh +Z 9efd5fb5a4c4d606f6b8046dd50f3f7a diff --git a/manifest.uuid b/manifest.uuid index c918008c70..d7c3afaaf6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -582b2ae77d65b1e142ceb5774f37b0aaa3851378 \ No newline at end of file +6c2d34df76fb7823f307c11a1135ab30674421a9 \ No newline at end of file From a66e386225cc63ef5becf5b9299ddeb17299e1c3 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 13 Feb 2016 15:08:25 +0000 Subject: [PATCH 281/570] Fix another test problem in sessionfault.test. FossilOrigin-Name: f6d1cf79437f892220e93635c377513160ee7fd7 --- ext/session/sessionfault.test | 4 ++-- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index dfe15a50c8..6560ea8755 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -389,8 +389,8 @@ do_faultsim_test 7 -faults oom-transient -prep { error "Expected {0 $::res} Got {$cres}" } } else { - S changeset - S delete + catch { S changeset } + catch { S delete } } } diff --git a/manifest b/manifest index 27189df562..cd68f2e235 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Harden\ssqlite3session_delete()\sagainst\strying\sto\sdelete\sa\ssession\sthat\nis\snot\scurrently\son\sthe\ssession\slist. -D 2016-02-13T14:45:56.852 +C Fix\sanother\stest\sproblem\sin\ssessionfault.test. +D 2016-02-13T15:08:25.504 F Makefile.in 5cbf3f753328d1bcd3a6117785b4874d99612f8f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 45e596bd4ccecf2256f68a2e96466aa52cc4bc1f @@ -282,7 +282,7 @@ F ext/session/sessionD.test d4744c78334162851d2a2f285c7e603e31b49aa2 F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26 F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596 -F ext/session/sessionfault.test 94a4dd100e16cf0b1c44d8487517dbb407eeab1d +F ext/session/sessionfault.test d52cbb7bee48cc8ee80335e07eb72fcb6b15eb40 F ext/session/sqlite3session.c b10af3e87ae437bb197b3a23a584d2dc8ad8981a F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce @@ -1448,7 +1448,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 582b2ae77d65b1e142ceb5774f37b0aaa3851378 -R 99d33fcea6ce08ff5ef828796adb3d5d -U drh -Z 9efd5fb5a4c4d606f6b8046dd50f3f7a +P 6c2d34df76fb7823f307c11a1135ab30674421a9 +R aed6007c61153b78ae015657d3f9bbb0 +U dan +Z 2a607f92ff5c33f0d10318ab25e2fc68 diff --git a/manifest.uuid b/manifest.uuid index d7c3afaaf6..8004dd0734 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6c2d34df76fb7823f307c11a1135ab30674421a9 \ No newline at end of file +f6d1cf79437f892220e93635c377513160ee7fd7 \ No newline at end of file From e75a9eb9bbf2e2934e292b475088f447191f9cf4 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 13 Feb 2016 18:54:10 +0000 Subject: [PATCH 282/570] Provide Sqlite3_SafeInit() and Sqlite3_SafeUnload() entry points on the TCL interface, but have the always return TCL_ERROR, because the non-standard TCL builds on Macs require this. FossilOrigin-Name: 37ec3015ec95035d31e3672f520908a0d36c9d67 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/tclsqlite.c | 8 ++++++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index edbefc847e..18d443650d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\spotential\sbuffer\soverread\sprovoked\sby\sinvalid\sutf-8\sin\sfts5. -D 2016-02-12T18:48:09.224 +C Provide\sSqlite3_SafeInit()\sand\sSqlite3_SafeUnload()\sentry\spoints\son\sthe\sTCL\ninterface,\sbut\shave\sthe\salways\sreturn\sTCL_ERROR,\sbecause\sthe\snon-standard\s\nTCL\sbuilds\son\sMacs\srequire\sthis. +D 2016-02-13T18:54:10.051 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -357,7 +357,7 @@ F src/sqliteInt.h 04ca5b3cdb3bcf87ba6300d5d36b51498f65f28c F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e -F src/tclsqlite.c 94ef6e2794220c5b6064d4c78ec7169a8c5cc45d +F src/tclsqlite.c 13debcc6a5ca1217486f8903768c01114fbe8b58 F src/test1.c 4f1b42699068b7806af3111786f5ad760c2c1ff7 F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 130580207ab5cee762b2893808acef7c8afad027 -R f6628307ca7dcc5e74da260d3c3d6ac5 -U dan -Z 7972d84e46f7d6d6e270e54f6c76821e +P a049fbbde5da2e43d41aa8c2b41f9eb21507ac76 +R 0ed7109e4c77d1cb323166614bc90c67 +U drh +Z 0875f4eabfb763252145d2214f48fc91 diff --git a/manifest.uuid b/manifest.uuid index 10c0eea158..5b62ca1a2d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a049fbbde5da2e43d41aa8c2b41f9eb21507ac76 \ No newline at end of file +37ec3015ec95035d31e3672f520908a0d36c9d67 \ No newline at end of file diff --git a/src/tclsqlite.c b/src/tclsqlite.c index aa913ca7c7..77da6eef52 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -3151,9 +3151,13 @@ EXTERN int Sqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } EXTERN int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } /* Because it accesses the file-system and uses persistent state, SQLite -** is not considered appropriate for safe interpreters. Hence, we deliberately -** omit the _SafeInit() interfaces. +** is not considered appropriate for safe interpreters. Hence, we cause +** the _SafeInit() interfaces return TCL_ERROR. */ +EXTERN int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_ERROR; } +EXTERN int Sqlite3_SafeUnload(Tcl_Interp *interp, int flags){return TCL_ERROR;} + + #ifndef SQLITE_3_SUFFIX_ONLY int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } From fad3039c51e1c500d489568b6e726353fa82fb1e Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sat, 13 Feb 2016 23:43:46 +0000 Subject: [PATCH 283/570] Enhance ability to debug out-of-memory errors. FossilOrigin-Name: 6a9c4a3ebfb7cc0738ef6634440ccab44a21ff28 --- manifest | 85 +++++++++++++++++++++++++----------------------- manifest.uuid | 2 +- src/analyze.c | 10 +++--- src/attach.c | 4 +-- src/backup.c | 6 ++-- src/bitvec.c | 4 +-- src/btree.c | 26 +++++++-------- src/build.c | 4 +-- src/complete.c | 2 +- src/dbstat.c | 20 ++++++------ src/journal.c | 2 +- src/legacy.c | 2 +- src/loadext.c | 8 ++--- src/main.c | 37 ++++++++++++++------- src/malloc.c | 2 +- src/memjournal.c | 2 +- src/os.c | 8 +++-- src/os_unix.c | 38 +++++++++++----------- src/os_win.c | 56 +++++++++++++++---------------- src/pager.c | 40 +++++++++++------------ src/pcache.c | 4 +-- src/prepare.c | 8 ++--- src/select.c | 8 ++--- src/sqliteInt.h | 4 +++ src/table.c | 6 ++-- src/threads.c | 14 ++++---- src/tokenize.c | 4 +-- src/utf.c | 4 +-- src/vacuum.c | 4 +-- src/vdbe.c | 8 ++--- src/vdbeapi.c | 8 ++--- src/vdbeaux.c | 14 ++++---- src/vdbemem.c | 22 ++++++------- src/vdbesort.c | 36 ++++++++++---------- src/vtab.c | 8 ++--- src/wal.c | 18 +++++----- src/where.c | 14 ++++---- 37 files changed, 282 insertions(+), 260 deletions(-) diff --git a/manifest b/manifest index 18d443650d..e0d2085551 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Provide\sSqlite3_SafeInit()\sand\sSqlite3_SafeUnload()\sentry\spoints\son\sthe\sTCL\ninterface,\sbut\shave\sthe\salways\sreturn\sTCL_ERROR,\sbecause\sthe\snon-standard\s\nTCL\sbuilds\son\sMacs\srequire\sthis. -D 2016-02-13T18:54:10.051 +C Enhance\sability\sto\sdebug\sout-of-memory\serrors. +D 2016-02-13T23:43:46.135 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -285,21 +285,21 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 1fbb01c26c64528088f1df8015992fefda387889 -F src/analyze.c fbf0e80d83cc893734e872f932f249a056b86e11 -F src/attach.c c16c2648a577fa3def2adfa48c28901376389bc5 +F src/analyze.c 8f89d016dab99d804caff7fec797a5970a16ca5e +F src/attach.c d9526ed44da598d6392f90ca03f1b613cafd582e F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 -F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc -F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf +F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce +F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 4c8caaeed7878aafdb607c3d2bcbc365bb0d19a1 +F src/btree.c 474ad91c1684e9053da64fa88747a1cb0c10d034 F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 54866fbafa09d494269bdefc79995eb7207003a6 +F src/build.c f1c304326b0cd95ac556dd541ad16284face4f99 F src/callback.c ed6c2a4a712eb7287ff64e20e3c23265dfb8a7ce -F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f +F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c ca17321bc17cca8f40e0843edea4fafff974998e -F src/dbstat.c b2ec6793eef97aebb4d171d490a4ffdfa9f2475c +F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b F src/delete.c 48802aa3ee6339f576d074336d3ae1b5f40e240f F src/expr.c fbf0706199aea23c54efe36b6932d8307c4eb872 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb @@ -310,17 +310,17 @@ F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c 9ca97272e9f74ed0efddf3b4350ee12740cebbef -F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d -F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 -F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b -F src/main.c b67a45397b93b7ba8fbd6bfcb03423d245baed05 -F src/malloc.c 337e9808b5231855fe28857950f4f60ae42c417f +F src/journal.c fe3a3e2559ce3ce9d371afd30fbabbc074174575 +F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e +F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f +F src/main.c fa3b9f523bcecf7b35d3f77ad1c091cd6902c74d +F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85 +F src/memjournal.c 349a04fb803db40532cde0993e39758f1acaecce F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 @@ -328,35 +328,35 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4 F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23 F src/mutex_w32.c 5e6fe1c298fb5a8a15aaed4161d5759311431c17 F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7 -F src/os.c 205fa2bad945a0dc7cad48f9f95ea3e8dc5408ff +F src/os.c ca9a104b677328ee037cfdf1a54a16fd1805e8c9 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c 821ed110197175165cf2f50b0930c7ff9a24504c -F src/os_win.c ccf29ddded3e41e506b6bd98c1171aa0963b23f2 +F src/os_unix.c 3a6f20736dfb8a0949cdd66553fdf59f6604be35 +F src/os_win.c 6cce4c3aab5fb5cc6fabf999d785cfccb66ff9d4 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c 67cd2fbab58d0e35fed5f81432856f4f0af9fc6d +F src/pager.c 6812f3803951774b56abded396171e1c12b0b003 F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 F src/parse.y d7bff41d460f2df96fb890f36700e85cb0fc5634 -F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23 +F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 F src/pragma.c 80ee77226d0008d9188356a6cbbe6010866e1bee F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c -F src/prepare.c c12b786713df3e8270c0f85f988c5359d8b4d87c +F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e -F src/select.c ff80004a9a6ece891a8d9327a88e7b6e2588ee6d +F src/select.c 1a7e23a3bb2edb9cdc46ab0cf7c1500109cf2531 F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe F src/sqlite.h.in f80c6ebd85588fc514bfedf3ecb00cec269cb410 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 04ca5b3cdb3bcf87ba6300d5d36b51498f65f28c +F src/sqliteInt.h 11685b0cab74fce0cde801f1525580cd261e3b11 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba -F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e +F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 F src/tclsqlite.c 13debcc6a5ca1217486f8903768c01114fbe8b58 F src/test1.c 4f1b42699068b7806af3111786f5ad760c2c1ff7 F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b @@ -405,29 +405,29 @@ F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_windirent.c 8f5fada630348558d5745b334702f301da1ffc61 F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 -F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 -F src/tokenize.c 813934be70597edfbb685ae08fc4c8b549cf5a1e +F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c +F src/tokenize.c 2a234093ff16791ab3ec5ab60dc7fcf6af575e1c F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca -F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 +F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 49ce0a65306c1c51d61cb5bc214c71cb62452de6 -F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c c193299e595a13eba247738e22fce25c49346a6c +F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 +F src/vdbe.c ad4d5b7ad65793886b09c925fb5d1d74ac78f1a4 F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 -F src/vdbeapi.c 9324f6baee1a1b2284c6543e98f916888a81e459 -F src/vdbeaux.c deae5d3bd45da0e57c7d9e1d7436333d142dc3bb +F src/vdbeapi.c bfc06382d5089944388a90e4f90bb1e975b3613d +F src/vdbeaux.c 3580de0325a05663195d8f8fddf48c6dd9a28522 F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db -F src/vdbemem.c 68fcfac37dc6601d98c32cc5adee4d39f2c1b7b4 -F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 +F src/vdbemem.c 8ffbf660e6481800f1e26323c67e7ae3d5ef073d +F src/vdbesort.c 74c22db608649fd7ed2d19d53eefb6efb14e9ee0 F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 -F src/vtab.c bef51b4f693d82b4b0184457faa8625654534091 +F src/vtab.c c27c0232bbc6bd4b50320ea0ef988334cde7d1ca F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c d21b99fd1458159d0b1ecdccc8ee6ada4fdc4c54 +F src/wal.c 75a8e53f172472d361aa06ef361eeda721a2439d F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c 984084584c10c41e46c89ac027a5cca991bc37e6 +F src/where.c 5b67fb8035ae4697cf721db095f800ef8dff5f56 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a F src/wherecode.c 791a784bbf8749d560fdb0b990b607bc4f44a38d F src/whereexpr.c de117970b29471177a6901d60ad83a194671dc03 @@ -1427,7 +1427,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a049fbbde5da2e43d41aa8c2b41f9eb21507ac76 -R 0ed7109e4c77d1cb323166614bc90c67 -U drh -Z 0875f4eabfb763252145d2214f48fc91 +P 37ec3015ec95035d31e3672f520908a0d36c9d67 +R c35a4cd7d70ca4772cad6122d840cf2a +T *branch * noMemBkpt +T *sym-noMemBkpt * +T -sym-trunk * +U mistachkin +Z 8214b214fa921fedf00745b7f0968f1a diff --git a/manifest.uuid b/manifest.uuid index 5b62ca1a2d..2c1496cdf8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -37ec3015ec95035d31e3672f520908a0d36c9d67 \ No newline at end of file +6a9c4a3ebfb7cc0738ef6634440ccab44a21ff28 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 1e026a7530..1e2ee9ec6e 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1673,7 +1673,7 @@ static int loadStatTbl( assert( db->lookaside.bDisable ); zSql = sqlite3MPrintf(db, zSql1, zDb); if( !zSql ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); sqlite3DbFree(db, zSql); @@ -1713,7 +1713,7 @@ static int loadStatTbl( pIdx->aSample = sqlite3DbMallocZero(db, nByte); if( pIdx->aSample==0 ){ sqlite3_finalize(pStmt); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } pSpace = (tRowcnt*)&pIdx->aSample[nSample]; pIdx->aAvgEq = pSpace; pSpace += nIdxCol; @@ -1729,7 +1729,7 @@ static int loadStatTbl( zSql = sqlite3MPrintf(db, zSql2, zDb); if( !zSql ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); sqlite3DbFree(db, zSql); @@ -1767,7 +1767,7 @@ static int loadStatTbl( pSample->p = sqlite3DbMallocZero(db, pSample->n + 2); if( pSample->p==0 ){ sqlite3_finalize(pStmt); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n); pIdx->nSample++; @@ -1856,7 +1856,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ zSql = sqlite3MPrintf(db, "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase); if( zSql==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else{ rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); sqlite3DbFree(db, zSql); diff --git a/src/attach.c b/src/attach.c index 2288ac9b62..b33ea26bd4 100644 --- a/src/attach.c +++ b/src/attach.c @@ -144,7 +144,7 @@ static void attachFunc( Pager *pPager; aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt); if( !aNew->pSchema ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ zErrDyn = sqlite3MPrintf(db, "attached databases must use the same text encoding as main database"); @@ -164,7 +164,7 @@ static void attachFunc( aNew->safety_level = 3; aNew->zName = sqlite3DbStrDup(db, zName); if( rc==SQLITE_OK && aNew->zName==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; } diff --git a/src/backup.c b/src/backup.c index 1c282242d7..455671a1ad 100644 --- a/src/backup.c +++ b/src/backup.c @@ -88,7 +88,7 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse)); if( pParse==0 ){ sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory"); - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else{ pParse->db = pDb; if( sqlite3OpenTempDatabase(pParse) ){ @@ -182,7 +182,7 @@ sqlite3_backup *sqlite3_backup_init( ** sqlite3_backup_finish(). */ p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup)); if( !p ){ - sqlite3Error(pDestDb, SQLITE_NOMEM); + sqlite3Error(pDestDb, SQLITE_NOMEM_BKPT); } } @@ -581,7 +581,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ } if( rc==SQLITE_IOERR_NOMEM ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; } p->rc = rc; } diff --git a/src/bitvec.c b/src/bitvec.c index f7f544cff7..9d13ba9185 100644 --- a/src/bitvec.c +++ b/src/bitvec.c @@ -177,7 +177,7 @@ int sqlite3BitvecSet(Bitvec *p, u32 i){ i = i%p->iDivisor; if( p->u.apSub[bin]==0 ){ p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor ); - if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM; + if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM_BKPT; } p = p->u.apSub[bin]; } @@ -212,7 +212,7 @@ bitvec_set_rehash: int rc; u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash)); if( aiValues==0 ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; }else{ memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash)); memset(p->u.apSub, 0, sizeof(p->u.apSub)); diff --git a/src/btree.c b/src/btree.c index c6f9c34f7b..cc1eedcb86 100644 --- a/src/btree.c +++ b/src/btree.c @@ -350,7 +350,7 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){ if( !pLock ){ pLock = (BtLock *)sqlite3MallocZero(sizeof(BtLock)); if( !pLock ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } pLock->iTable = iTable; pLock->pBtree = p; @@ -553,7 +553,7 @@ static int btreeSetHasContent(BtShared *pBt, Pgno pgno){ assert( pgno<=pBt->nPage ); pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage); if( !pBt->pHasContent ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; } } if( rc==SQLITE_OK && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){ @@ -632,7 +632,7 @@ static int saveCursorKey(BtCursor *pCur){ sqlite3_free(pKey); } }else{ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; } } assert( !pCur->curIntKey || !pCur->pKey ); @@ -764,7 +764,7 @@ static int btreeMoveto( pIdxKey = sqlite3VdbeAllocUnpackedRecord( pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree ); - if( pIdxKey==0 ) return SQLITE_NOMEM; + if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey); if( pIdxKey->nField==0 ){ sqlite3DbFree(pCur->pKeyInfo->db, pFree); @@ -2176,7 +2176,7 @@ int sqlite3BtreeOpen( } p = sqlite3MallocZero(sizeof(Btree)); if( !p ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } p->inTrans = TRANS_NONE; p->db = db; @@ -2200,7 +2200,7 @@ int sqlite3BtreeOpen( p->sharable = 1; if( !zFullPathname ){ sqlite3_free(p); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } if( isMemdb ){ memcpy(zFullPathname, zFilename, nFilename); @@ -2268,7 +2268,7 @@ int sqlite3BtreeOpen( pBt = sqlite3MallocZero( sizeof(*pBt) ); if( pBt==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto btree_open_out; } rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, @@ -2337,7 +2337,7 @@ int sqlite3BtreeOpen( if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){ pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST); if( pBt->mutex==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto btree_open_out; } } @@ -4114,7 +4114,7 @@ static int btreeCursor( if( wrFlag ){ allocateTempSpace(pBt); - if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM; + if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT; } if( iTable==1 && btreePagecount(pBt)==0 ){ assert( wrFlag==0 ); @@ -4512,7 +4512,7 @@ static int accessPayload( pCur->aOverflow, nOvfl*2*sizeof(Pgno) ); if( aNew==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else{ pCur->nOvflAlloc = nOvfl*2; pCur->aOverflow = aNew; @@ -5217,7 +5217,7 @@ int sqlite3BtreeMovetoUnpacked( } pCellKey = sqlite3Malloc( nCell+18 ); if( pCellKey==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto moveto_finish; } pCur->aiIdx[pCur->iPage] = (u16)idx; @@ -7036,7 +7036,7 @@ static int balance_nonroot( assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx ); if( !aOvflSpace ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } /* Find the sibling pages to balance. Also locate the cells in pParent @@ -7136,7 +7136,7 @@ static int balance_nonroot( assert( szScratch<=6*(int)pBt->pageSize ); b.apCell = sqlite3ScratchMalloc( szScratch ); if( b.apCell==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto balance_cleanup; } b.szCell = (u16*)&b.apCell[nMaxCells]; diff --git a/src/build.c b/src/build.c index 250dc20d20..973be576df 100644 --- a/src/build.c +++ b/src/build.c @@ -927,7 +927,7 @@ void sqlite3StartTable( pTable = sqlite3DbMallocZero(db, sizeof(Table)); if( pTable==0 ){ assert( db->mallocFailed ); - pParse->rc = SQLITE_NOMEM; + pParse->rc = SQLITE_NOMEM_BKPT; pParse->nErr++; goto begin_table_error; } @@ -1608,7 +1608,7 @@ static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){ assert( pIdx->isResized==0 ); nByte = (sizeof(char*) + sizeof(i16) + 1)*N; zExtra = sqlite3DbMallocZero(db, nByte); - if( zExtra==0 ) return SQLITE_NOMEM; + if( zExtra==0 ) return SQLITE_NOMEM_BKPT; memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn); pIdx->azColl = (const char**)zExtra; zExtra += sizeof(char*)*N; diff --git a/src/complete.c b/src/complete.c index b120b7e811..bb2c03098e 100644 --- a/src/complete.c +++ b/src/complete.c @@ -281,7 +281,7 @@ int sqlite3_complete16(const void *zSql){ if( zSql8 ){ rc = sqlite3_complete(zSql8); }else{ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; } sqlite3ValueFree(pVal); return rc & 0xff; diff --git a/src/dbstat.c b/src/dbstat.c index 5e42cdfe38..b8e79b0864 100644 --- a/src/dbstat.c +++ b/src/dbstat.c @@ -162,7 +162,7 @@ static int statConnect( rc = sqlite3_declare_vtab(db, VTAB_SCHEMA); if( rc==SQLITE_OK ){ pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable)); - if( pTab==0 ) rc = SQLITE_NOMEM; + if( pTab==0 ) rc = SQLITE_NOMEM_BKPT; } assert( rc==SQLITE_OK || pTab==0 ); @@ -243,7 +243,7 @@ static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ pCsr = (StatCursor *)sqlite3_malloc64(sizeof(StatCursor)); if( pCsr==0 ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; }else{ memset(pCsr, 0, sizeof(StatCursor)); pCsr->base.pVtab = pVTab; @@ -349,7 +349,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){ nUsable = szPage - sqlite3BtreeGetReserveNoMutex(pBt); sqlite3BtreeLeave(pBt); p->aCell = sqlite3_malloc64((p->nCell+1) * sizeof(StatCell)); - if( p->aCell==0 ) return SQLITE_NOMEM; + if( p->aCell==0 ) return SQLITE_NOMEM_BKPT; memset(p->aCell, 0, (p->nCell+1) * sizeof(StatCell)); for(i=0; inCell; i++){ @@ -382,7 +382,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){ pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4); pCell->nOvfl = nOvfl; pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl); - if( pCell->aOvfl==0 ) return SQLITE_NOMEM; + if( pCell->aOvfl==0 ) return SQLITE_NOMEM_BKPT; pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]); for(j=1; jaPage[0].iCell = 0; pCsr->aPage[0].zPath = z = sqlite3_mprintf("/"); pCsr->iPage = 0; - if( z==0 ) rc = SQLITE_NOMEM; + if( z==0 ) rc = SQLITE_NOMEM_BKPT; }else{ pCsr->isEof = 1; return sqlite3_reset(pCsr->pStmt); @@ -496,7 +496,7 @@ statNextRestart: } pCell->iOvfl++; statSizeAndOffset(pCsr); - return z==0 ? SQLITE_NOMEM : SQLITE_OK; + return z==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK; } if( p->iRightChildPg ) break; p->iCell++; @@ -520,7 +520,7 @@ statNextRestart: p[1].iCell = 0; p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell); p->iCell++; - if( z==0 ) rc = SQLITE_NOMEM; + if( z==0 ) rc = SQLITE_NOMEM_BKPT; } @@ -554,7 +554,7 @@ statNextRestart: pCsr->nUnused = p->nUnused; pCsr->nMxPayload = p->nMxPayload; pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath); - if( z==0 ) rc = SQLITE_NOMEM; + if( z==0 ) rc = SQLITE_NOMEM_BKPT; nPayload = 0; for(i=0; inCell; i++){ nPayload += p->aCell[i].nLocal; @@ -588,7 +588,7 @@ static int statFilter( if( pCsr->iDb<0 ){ sqlite3_free(pCursor->pVtab->zErrMsg); pCursor->pVtab->zErrMsg = sqlite3_mprintf("no such schema: %s", zDbase); - return pCursor->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; + return pCursor->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM_BKPT; } }else{ pCsr->iDb = pTab->iDb; @@ -604,7 +604,7 @@ static int statFilter( " FROM \"%w\".%s WHERE rootpage!=0" " ORDER BY name", pTab->db->aDb[pCsr->iDb].zName, zMaster); if( zSql==0 ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; }else{ rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0); sqlite3_free(zSql); diff --git a/src/journal.c b/src/journal.c index fed27be3e3..a5cf8c8e2f 100644 --- a/src/journal.c +++ b/src/journal.c @@ -212,7 +212,7 @@ int sqlite3JournalOpen( if( nBuf>0 ){ p->zBuf = sqlite3MallocZero(nBuf); if( !p->zBuf ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } }else{ return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); diff --git a/src/legacy.c b/src/legacy.c index 1b5e518d43..bd34512d31 100644 --- a/src/legacy.c +++ b/src/legacy.c @@ -131,7 +131,7 @@ exec_out: if( *pzErrMsg ){ memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg); }else{ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; sqlite3Error(db, SQLITE_NOMEM); } }else if( pzErrMsg ){ diff --git a/src/loadext.c b/src/loadext.c index 94298c4763..3469fbb73d 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -478,7 +478,7 @@ static int sqlite3LoadExtension( #if SQLITE_OS_UNIX || SQLITE_OS_WIN for(ii=0; ii=0 && zFile[iFile]!='/'; iFile--){} @@ -557,7 +557,7 @@ static int sqlite3LoadExtension( /* Append the new shared library handle to the db->aExtension array. */ aHandle = sqlite3DbMallocZero(db, sizeof(handle)*(db->nExtension+1)); if( aHandle==0 ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } if( db->nExtension>0 ){ memcpy(aHandle, db->aExtension, sizeof(handle)*db->nExtension); @@ -679,7 +679,7 @@ int sqlite3_auto_extension(void (*xInit)(void)){ void (**aNew)(void); aNew = sqlite3_realloc64(wsdAutoext.aExt, nByte); if( aNew==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else{ wsdAutoext.aExt = aNew; wsdAutoext.aExt[wsdAutoext.nExt] = xInit; diff --git a/src/main.c b/src/main.c index 922af1315a..a44fec8a5b 100644 --- a/src/main.c +++ b/src/main.c @@ -187,7 +187,7 @@ int sqlite3_initialize(void){ sqlite3GlobalConfig.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); if( sqlite3GlobalConfig.bCoreMutex && !sqlite3GlobalConfig.pInitMutex ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; } } } @@ -1645,7 +1645,7 @@ int sqlite3CreateFunc( p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 1); assert(p || db->mallocFailed); if( !p ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } /* If an older version of the function with a configured destructor is @@ -2149,14 +2149,14 @@ int sqlite3TempInMemory(const sqlite3 *db){ const char *sqlite3_errmsg(sqlite3 *db){ const char *z; if( !db ){ - return sqlite3ErrStr(SQLITE_NOMEM); + return sqlite3ErrStr(SQLITE_NOMEM_BKPT); } if( !sqlite3SafetyCheckSickOrOk(db) ){ return sqlite3ErrStr(SQLITE_MISUSE_BKPT); } sqlite3_mutex_enter(db->mutex); if( db->mallocFailed ){ - z = sqlite3ErrStr(SQLITE_NOMEM); + z = sqlite3ErrStr(SQLITE_NOMEM_BKPT); }else{ testcase( db->pErr==0 ); z = (char*)sqlite3_value_text(db->pErr); @@ -2224,7 +2224,7 @@ int sqlite3_errcode(sqlite3 *db){ return SQLITE_MISUSE_BKPT; } if( !db || db->mallocFailed ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } return db->errCode & db->errMask; } @@ -2233,7 +2233,7 @@ int sqlite3_extended_errcode(sqlite3 *db){ return SQLITE_MISUSE_BKPT; } if( !db || db->mallocFailed ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } return db->errCode; } @@ -2313,7 +2313,7 @@ static int createCollation( } pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 1); - if( pColl==0 ) return SQLITE_NOMEM; + if( pColl==0 ) return SQLITE_NOMEM_BKPT; pColl->xCmp = xCompare; pColl->pUser = pCtx; pColl->xDel = xDel; @@ -2492,7 +2492,7 @@ int sqlite3ParseUri( for(iIn=0; iInpNext = 0; if( pChunk ){ diff --git a/src/os.c b/src/os.c index 90130d0eb7..2fd44abf85 100644 --- a/src/os.c +++ b/src/os.c @@ -68,7 +68,7 @@ int sqlite3_memdebug_vfs_oom_test = 1; #define DO_OS_MALLOC_TEST(x) \ if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3IsMemJournal(x))) { \ void *pTstAlloc = sqlite3Malloc(10); \ - if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ + if (!pTstAlloc) return SQLITE_IOERR_NOMEM_BKPT; \ sqlite3_free(pTstAlloc); \ } #else @@ -287,7 +287,7 @@ int sqlite3OsOpenMalloc( int flags, int *pOutFlags ){ - int rc = SQLITE_NOMEM; + int rc; sqlite3_file *pFile; pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile); if( pFile ){ @@ -297,6 +297,8 @@ int sqlite3OsOpenMalloc( }else{ *ppFile = pFile; } + }else{ + rc = SQLITE_NOMEM_BKPT; } return rc; } @@ -316,7 +318,7 @@ int sqlite3OsCloseFree(sqlite3_file *pFile){ */ int sqlite3OsInit(void){ void *p = sqlite3_malloc(10); - if( p==0 ) return SQLITE_NOMEM; + if( p==0 ) return SQLITE_NOMEM_BKPT; sqlite3_free(p); return sqlite3_os_init(); } diff --git a/src/os_unix.c b/src/os_unix.c index fe1fc6af19..ea07bd99f3 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1302,7 +1302,7 @@ static int findInodeInfo( if( pInode==0 ){ pInode = sqlite3_malloc64( sizeof(*pInode) ); if( pInode==0 ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } memset(pInode, 0, sizeof(*pInode)); memcpy(&pInode->fileId, &fileId, sizeof(fileId)); @@ -4222,7 +4222,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ /* Allocate space for the new unixShm object. */ p = sqlite3_malloc64( sizeof(*p) ); - if( p==0 ) return SQLITE_NOMEM; + if( p==0 ) return SQLITE_NOMEM_BKPT; memset(p, 0, sizeof(*p)); assert( pDbFd->pShm==0 ); @@ -4254,7 +4254,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ #endif pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename ); if( pShmNode==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto shm_open_err; } memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename); @@ -4272,7 +4272,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ pShmNode->pInode = pDbFd->pInode; pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); if( pShmNode->mutex==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto shm_open_err; } @@ -4445,7 +4445,7 @@ static int unixShmMap( pShmNode->apRegion, nReqRegion*sizeof(char *) ); if( !apNew ){ - rc = SQLITE_IOERR_NOMEM; + rc = SQLITE_IOERR_NOMEM_BKPT; goto shmpage_out; } pShmNode->apRegion = apNew; @@ -4465,7 +4465,7 @@ static int unixShmMap( }else{ pMem = sqlite3_malloc64(szRegion); if( pMem==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto shmpage_out; } memset(pMem, 0, szRegion); @@ -5243,7 +5243,7 @@ static int fillInUnixFile( pNew->pId = vxworksFindFileId(zFilename); if( pNew->pId==0 ){ ctrlFlags |= UNIXFILE_NOLOCK; - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; } #endif @@ -5299,7 +5299,7 @@ static int fillInUnixFile( afpLockingContext *pCtx; pNew->lockingContext = pCtx = sqlite3_malloc64( sizeof(*pCtx) ); if( pCtx==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else{ /* NB: zFilename exists and remains valid until the file is closed ** according to requirement F11141. So we do not need to make a @@ -5329,7 +5329,7 @@ static int fillInUnixFile( nFilename = (int)strlen(zFilename) + 6; zLockFile = (char *)sqlite3_malloc64(nFilename); if( zLockFile==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else{ sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename); } @@ -5352,7 +5352,7 @@ static int fillInUnixFile( if( zSemName[n]=='/' ) zSemName[n] = '_'; pNew->pInode->pSem = sem_open(zSemName, O_CREAT, 0666, 1); if( pNew->pInode->pSem == SEM_FAILED ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; pNew->pInode->aSemName[0] = '\0'; } } @@ -5693,7 +5693,7 @@ static int unixOpen( }else{ pUnused = sqlite3_malloc64(sizeof(*pUnused)); if( !pUnused ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } } p->pUnused = pUnused; @@ -5779,7 +5779,7 @@ static int unixOpen( zPath = sqlite3_mprintf("%s", zName); if( zPath==0 ){ robust_close(p, fd, __LINE__); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } #else osUnlink(zName); @@ -6011,7 +6011,7 @@ static int unixFullPathname( if( bLink ){ if( zDel==0 ){ zDel = sqlite3_malloc(nOut); - if( zDel==0 ) rc = SQLITE_NOMEM; + if( zDel==0 ) rc = SQLITE_NOMEM_BKPT; }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ rc = SQLITE_CANTOPEN_BKPT; } @@ -6555,7 +6555,7 @@ static int proxyCreateUnixFile( }else{ pUnused = sqlite3_malloc64(sizeof(*pUnused)); if( !pUnused ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } } if( fd<0 ){ @@ -6588,7 +6588,7 @@ static int proxyCreateUnixFile( pNew = (unixFile *)sqlite3_malloc64(sizeof(*pNew)); if( pNew==NULL ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto end_create_proxy; } memset(pNew, 0, sizeof(unixFile)); @@ -7001,7 +7001,7 @@ static int proxyTakeConch(unixFile *pFile){ if( tempLockPath ){ pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath); if( !pCtx->lockProxyPath ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; } } } @@ -7066,7 +7066,7 @@ static int proxyCreateConchPathname(char *dbPath, char **pConchPath){ ** the name of the original database file. */ *pConchPath = conchPath = (char *)sqlite3_malloc64(len + 8); if( conchPath==0 ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } memcpy(conchPath, dbPath, len+1); @@ -7182,7 +7182,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) { pCtx = sqlite3_malloc64( sizeof(*pCtx) ); if( pCtx==0 ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } memset(pCtx, 0, sizeof(*pCtx)); @@ -7218,7 +7218,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) { if( rc==SQLITE_OK ){ pCtx->dbPath = sqlite3DbStrDup(0, dbPath); if( pCtx->dbPath==NULL ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; } } if( rc==SQLITE_OK ){ diff --git a/src/os_win.c b/src/os_win.c index eda6cf59fb..caa6dea5db 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -1222,7 +1222,7 @@ int sqlite3_win32_compact_heap(LPUINT pnLargest){ if( lastErrno==NO_ERROR ){ sqlite3_log(SQLITE_NOMEM, "failed to HeapCompact (no space), heap=%p", (void*)hHeap); - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else{ sqlite3_log(SQLITE_ERROR, "failed to HeapCompact (%lu), heap=%p", osGetLastError(), (void*)hHeap); @@ -1542,7 +1542,7 @@ static int winMemInit(void *pAppData){ "failed to HeapCreate (%lu), flags=%u, initSize=%lu, maxSize=%lu", osGetLastError(), SQLITE_WIN32_HEAP_FLAGS, dwInitialSize, dwMaximumSize); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } pWinMemData->bOwned = TRUE; assert( pWinMemData->bOwned ); @@ -1552,7 +1552,7 @@ static int winMemInit(void *pAppData){ if( !pWinMemData->hHeap ){ sqlite3_log(SQLITE_NOMEM, "failed to GetProcessHeap (%lu)", osGetLastError()); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } pWinMemData->bOwned = FALSE; assert( !pWinMemData->bOwned ); @@ -1789,7 +1789,7 @@ int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ if( zValue && zValue[0] ){ zValueUtf8 = winUnicodeToUtf8(zValue); if ( zValueUtf8==0 ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } } sqlite3_free(*ppDirectory); @@ -2066,7 +2066,7 @@ static int winceCreateLock(const char *zFilename, winFile *pFile){ zName = winUtf8ToUnicode(zFilename); if( zName==0 ){ /* out of memory */ - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } /* Initialize the local lockdata */ @@ -3615,12 +3615,12 @@ static int winOpenSharedMemory(winFile *pDbFd){ ** allocate space for a new winShmNode and filename. */ p = sqlite3MallocZero( sizeof(*p) ); - if( p==0 ) return SQLITE_IOERR_NOMEM; + if( p==0 ) return SQLITE_IOERR_NOMEM_BKPT; nName = sqlite3Strlen30(pDbFd->zPath); pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 ); if( pNew==0 ){ sqlite3_free(p); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } pNew->zFilename = (char*)&pNew[1]; sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); @@ -3647,7 +3647,7 @@ static int winOpenSharedMemory(winFile *pDbFd){ pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); if( pShmNode->mutex==0 ){ - rc = SQLITE_IOERR_NOMEM; + rc = SQLITE_IOERR_NOMEM_BKPT; goto shm_open_err; } @@ -3952,7 +3952,7 @@ static int winShmMap( pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0]) ); if( !apNew ){ - rc = SQLITE_IOERR_NOMEM; + rc = SQLITE_IOERR_NOMEM_BKPT; goto shmpage_out; } pShmNode->aRegion = apNew; @@ -4382,7 +4382,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ zBuf = sqlite3MallocZero( nBuf ); if( !zBuf ){ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } /* Figure out the effective temporary directory. First, check if one @@ -4440,7 +4440,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ if( !zConverted ){ sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } if( winIsDir(zConverted) ){ sqlite3_snprintf(nMax, zBuf, "%s", zDir); @@ -4453,7 +4453,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ if( !zConverted ){ sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } if( cygwin_conv_path( osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir, @@ -4474,7 +4474,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ sqlite3_free(zConverted); sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } sqlite3_snprintf(nMax, zBuf, "%s", zUtf8); sqlite3_free(zUtf8); @@ -4492,7 +4492,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ if( !zWidePath ){ sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } if( osGetTempPathW(nMax, zWidePath)==0 ){ sqlite3_free(zWidePath); @@ -4510,7 +4510,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ sqlite3_free(zWidePath); sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } } #ifdef SQLITE_WIN32_HAS_ANSI @@ -4520,7 +4520,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ if( !zMbcsPath ){ sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } if( osGetTempPathA(nMax, zMbcsPath)==0 ){ sqlite3_free(zBuf); @@ -4535,7 +4535,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ }else{ sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } } #endif /* SQLITE_WIN32_HAS_ANSI */ @@ -4727,7 +4727,7 @@ static int winOpen( if( zConverted==0 ){ sqlite3_free(zTmpname); OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name)); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } if( winIsDir(zConverted) ){ @@ -4927,7 +4927,7 @@ static int winDelete( zConverted = winConvertFromUtf8Filename(zFilename); if( zConverted==0 ){ OSTRACE(("DELETE name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename)); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } if( osIsNT() ){ do { @@ -5035,7 +5035,7 @@ static int winAccess( zConverted = winConvertFromUtf8Filename(zFilename); if( zConverted==0 ){ OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename)); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } if( osIsNT() ){ int cnt = 0; @@ -5162,7 +5162,7 @@ static int winFullPathname( */ char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 ); if( !zOut ){ - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } if( cygwin_conv_path( (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A) | @@ -5174,7 +5174,7 @@ static int winFullPathname( char *zUtf8 = winConvertToUtf8Filename(zOut); if( !zUtf8 ){ sqlite3_free(zOut); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s", sqlite3_data_directory, winGetDirSep(), zUtf8); @@ -5184,7 +5184,7 @@ static int winFullPathname( }else{ char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 ); if( !zOut ){ - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } if( cygwin_conv_path( (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A), @@ -5196,7 +5196,7 @@ static int winFullPathname( char *zUtf8 = winConvertToUtf8Filename(zOut); if( !zUtf8 ){ sqlite3_free(zOut); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8); sqlite3_free(zUtf8); @@ -5256,7 +5256,7 @@ static int winFullPathname( } zConverted = winConvertFromUtf8Filename(zRelative); if( zConverted==0 ){ - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } if( osIsNT() ){ LPWSTR zTemp; @@ -5270,7 +5270,7 @@ static int winFullPathname( zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); if( zTemp==0 ){ sqlite3_free(zConverted); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0); if( nByte==0 ){ @@ -5296,7 +5296,7 @@ static int winFullPathname( zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); if( zTemp==0 ){ sqlite3_free(zConverted); - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0); if( nByte==0 ){ @@ -5315,7 +5315,7 @@ static int winFullPathname( sqlite3_free(zOut); return SQLITE_OK; }else{ - return SQLITE_IOERR_NOMEM; + return SQLITE_IOERR_NOMEM_BKPT; } #endif } diff --git a/src/pager.c b/src/pager.c index 5c61968e36..67f1ae6b75 100644 --- a/src/pager.c +++ b/src/pager.c @@ -2324,9 +2324,9 @@ static int pager_playback_one_page( pPager->dbFileSize = pgno; } if( pPager->pBackup ){ - CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM); + CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT); sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData); - CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData); + CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData); } }else if( !isMainJrnl && pPg==0 ){ /* If this is a rollback of a savepoint and data was not written to @@ -2398,7 +2398,7 @@ static int pager_playback_one_page( } /* Decode the page just read from disk */ - CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM); + CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT); sqlite3PcacheRelease(pPg); } return rc; @@ -2464,7 +2464,7 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){ pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2); pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile); if( !pMaster ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else{ const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL); rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0); @@ -2481,7 +2481,7 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){ nMasterPtr = pVfs->mxPathname+1; zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 1); if( !zMasterJournal ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto delmaster_out; } zMasterPtr = &zMasterJournal[nMasterJournal+1]; @@ -2951,7 +2951,7 @@ static int readDbPage(PgHdr *pPg, u32 iFrame){ memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers)); } } - CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM); + CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM_BKPT); PAGER_INCR(sqlite3_pager_readdb_count); PAGER_INCR(pPager->nRead); @@ -3311,7 +3311,7 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){ if( pSavepoint ){ pDone = sqlite3BitvecCreate(pSavepoint->nOrig); if( !pDone ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } } @@ -3674,7 +3674,7 @@ int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){ } if( rc==SQLITE_OK ){ pNew = (char *)sqlite3PageMalloc(pageSize); - if( !pNew ) rc = SQLITE_NOMEM; + if( !pNew ) rc = SQLITE_NOMEM_BKPT; } if( rc==SQLITE_OK ){ @@ -3950,7 +3950,7 @@ static int pagerAcquireMapPage( *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra); if( p==0 ){ sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } p->pExtra = (void *)&p[1]; p->flags = PGHDR_MMAP; @@ -4308,7 +4308,7 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){ if( pList->pgno==1 ) pager_write_changecounter(pList); /* Encode the database */ - CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData); + CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM_BKPT, pData); /* Write out the page data. */ rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset); @@ -4395,7 +4395,7 @@ static int subjournalPage(PgHdr *pPg){ i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize); char *pData2; - CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); + CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2); PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno)); rc = write32bits(pPager->sjfd, offset, pPg->pgno); if( rc==SQLITE_OK ){ @@ -4599,7 +4599,7 @@ int sqlite3PagerOpen( memDb = 1; if( zFilename && zFilename[0] ){ zPathname = sqlite3DbStrDup(0, zFilename); - if( zPathname==0 ) return SQLITE_NOMEM; + if( zPathname==0 ) return SQLITE_NOMEM_BKPT; nPathname = sqlite3Strlen30(zPathname); zFilename = 0; } @@ -4615,7 +4615,7 @@ int sqlite3PagerOpen( nPathname = pVfs->mxPathname+1; zPathname = sqlite3DbMallocRaw(0, nPathname*2); if( zPathname==0 ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */ rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname); @@ -4668,7 +4668,7 @@ int sqlite3PagerOpen( assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) ); if( !pPtr ){ sqlite3DbFree(0, zPathname); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } pPager = (Pager*)(pPtr); pPager->pPCache = (PCache*)(pPtr += ROUND8(sizeof(*pPager))); @@ -5388,7 +5388,7 @@ int sqlite3PagerGet( if( rc!=SQLITE_OK ) goto pager_acquire_err; if( pBase==0 ){ pPg = *ppPage = 0; - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto pager_acquire_err; } } @@ -5562,7 +5562,7 @@ static int pager_open_journal(Pager *pPager){ if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize); if( pPager->pInJournal==0 ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } /* Open the journal file if it is not already open. */ @@ -5717,7 +5717,7 @@ static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){ assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); assert( pPager->journalHdr<=pPager->journalOff ); - CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); + CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2); cksum = pager_cksum(pPager, (u8*)pData2); /* Even if an IO or diskfull error occurs while journalling the @@ -6074,7 +6074,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ if( DIRECT_MODE ){ const void *zBuf; assert( pPager->dbFileSize>0 ); - CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf); + CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM_BKPT, zBuf); if( rc==SQLITE_OK ){ rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0); pPager->aStat[PAGER_STAT_WRITE]++; @@ -6573,7 +6573,7 @@ static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){ pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint ); if( !aNew ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint)); pPager->aSavepoint = aNew; @@ -6589,7 +6589,7 @@ static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){ aNew[ii].iSubRec = pPager->nSubRec; aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize); if( !aNew[ii].pInSavepoint ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } if( pagerUseWal(pPager) ){ sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData); diff --git a/src/pcache.c b/src/pcache.c index 5ac9d34a1e..61e7587422 100644 --- a/src/pcache.c +++ b/src/pcache.c @@ -191,7 +191,7 @@ int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)), pCache->bPurgeable ); - if( pNew==0 ) return SQLITE_NOMEM; + if( pNew==0 ) return SQLITE_NOMEM_BKPT; sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache)); if( pCache->pCache ){ sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); @@ -301,7 +301,7 @@ int sqlite3PcacheFetchStress( } } *ppPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2); - return *ppPage==0 ? SQLITE_NOMEM : SQLITE_OK; + return *ppPage==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK; } /* diff --git a/src/prepare.c b/src/prepare.c index f74aa52e0b..6685dfeaf7 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -33,7 +33,7 @@ static void corruptSchema( sqlite3DbFree(db, *pData->pzErrMsg); *pData->pzErrMsg = z; } - pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT_BKPT; + pData->rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_CORRUPT_BKPT; } /* @@ -307,7 +307,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ #endif } if( db->mallocFailed ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; sqlite3ResetAllSchemasOfConnection(db); } if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){ @@ -524,7 +524,7 @@ static int sqlite3Prepare( /* Allocate the parsing context */ pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); if( pParse==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto end_prepare; } pParse->pReprepare = pReprepare; @@ -601,7 +601,7 @@ static int sqlite3Prepare( schemaIsValid(pParse); } if( db->mallocFailed ){ - pParse->rc = SQLITE_NOMEM; + pParse->rc = SQLITE_NOMEM_BKPT; } if( pzTail ){ *pzTail = pParse->zTail; diff --git a/src/select.c b/src/select.c index c3132c2325..ff4d9d85c1 100644 --- a/src/select.c +++ b/src/select.c @@ -1688,7 +1688,7 @@ int sqlite3ColumnsFromExprList( sqlite3DbFree(db, aCol); *paCol = 0; *pnCol = 0; - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } return SQLITE_OK; } @@ -2499,7 +2499,7 @@ static int multiSelect( nCol = p->pEList->nExpr; pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1); if( !pKeyInfo ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto multi_select_end; } for(i=0, apColl=pKeyInfo->aColl; iflags |= EP_IntValue; pNew->u.iValue = i; pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew); @@ -4091,7 +4091,7 @@ static int withExpand( pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); - if( db->mallocFailed ) return SQLITE_NOMEM; + if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; assert( pFrom->pSelect ); /* Check if this is a recursive CTE. */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f04aebe79a..abb827cedb 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3166,9 +3166,13 @@ struct TreeView { int sqlite3CorruptError(int); int sqlite3MisuseError(int); int sqlite3CantopenError(int); +int sqlite3NomemError(int); +int sqlite3IoerrnomemError(int); #define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__) #define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__) #define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__) +#define SQLITE_NOMEM_BKPT sqlite3NomemError(__LINE__) +#define SQLITE_IOERR_NOMEM_BKPT sqlite3IoerrnomemError(__LINE__) /* ** FTS3 and FTS4 both require virtual table support diff --git a/src/table.c b/src/table.c index 153bfb319f..a50d83ce63 100644 --- a/src/table.c +++ b/src/table.c @@ -101,7 +101,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ return 0; malloc_failed: - p->rc = SQLITE_NOMEM; + p->rc = SQLITE_NOMEM_BKPT; return 1; } @@ -142,7 +142,7 @@ int sqlite3_get_table( res.azResult = sqlite3_malloc64(sizeof(char*)*res.nAlloc ); if( res.azResult==0 ){ db->errCode = SQLITE_NOMEM; - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } res.azResult[0] = 0; rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg); @@ -171,7 +171,7 @@ int sqlite3_get_table( if( azNew==0 ){ sqlite3_free_table(&res.azResult[1]); db->errCode = SQLITE_NOMEM; - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } res.azResult = azNew; } diff --git a/src/threads.c b/src/threads.c index 251b9b7631..f128d69fc2 100644 --- a/src/threads.c +++ b/src/threads.c @@ -63,7 +63,7 @@ int sqlite3ThreadCreate( *ppThread = 0; p = sqlite3Malloc(sizeof(*p)); - if( p==0 ) return SQLITE_NOMEM; + if( p==0 ) return SQLITE_NOMEM_BKPT; memset(p, 0, sizeof(*p)); p->xTask = xTask; p->pIn = pIn; @@ -89,7 +89,7 @@ int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ int rc; assert( ppOut!=0 ); - if( NEVER(p==0) ) return SQLITE_NOMEM; + if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT; if( p->done ){ *ppOut = p->pOut; rc = SQLITE_OK; @@ -154,7 +154,7 @@ int sqlite3ThreadCreate( assert( xTask!=0 ); *ppThread = 0; p = sqlite3Malloc(sizeof(*p)); - if( p==0 ) return SQLITE_NOMEM; + if( p==0 ) return SQLITE_NOMEM_BKPT; /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a ** function that returns SQLITE_ERROR when passed the argument 200, that ** forces worker threads to run sequentially and deterministically @@ -186,7 +186,7 @@ int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ BOOL bRc; assert( ppOut!=0 ); - if( NEVER(p==0) ) return SQLITE_NOMEM; + if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT; if( p->xTask==0 ){ /* assert( p->id==GetCurrentThreadId() ); */ rc = WAIT_OBJECT_0; @@ -234,7 +234,7 @@ int sqlite3ThreadCreate( assert( xTask!=0 ); *ppThread = 0; p = sqlite3Malloc(sizeof(*p)); - if( p==0 ) return SQLITE_NOMEM; + if( p==0 ) return SQLITE_NOMEM_BKPT; if( (SQLITE_PTR_TO_INT(p)/17)&1 ){ p->xTask = xTask; p->pIn = pIn; @@ -250,7 +250,7 @@ int sqlite3ThreadCreate( int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ assert( ppOut!=0 ); - if( NEVER(p==0) ) return SQLITE_NOMEM; + if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT; if( p->xTask ){ *ppOut = p->xTask(p->pIn); }else{ @@ -261,7 +261,7 @@ int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ #if defined(SQLITE_TEST) { void *pTstAlloc = sqlite3Malloc(10); - if (!pTstAlloc) return SQLITE_NOMEM; + if (!pTstAlloc) return SQLITE_NOMEM_BKPT; sqlite3_free(pTstAlloc); } #endif diff --git a/src/tokenize.c b/src/tokenize.c index 9b3444ac82..c43a039dde 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -495,7 +495,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ pEngine = sqlite3ParserAlloc(sqlite3Malloc); if( pEngine==0 ){ sqlite3OomFault(db); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } assert( pParse->pNewTable==0 ); assert( pParse->pNewTrigger==0 ); @@ -549,7 +549,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ #endif /* YYDEBUG */ sqlite3ParserFree(pEngine, sqlite3_free); if( db->mallocFailed ){ - pParse->rc = SQLITE_NOMEM; + pParse->rc = SQLITE_NOMEM_BKPT; } if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); diff --git a/src/utf.c b/src/utf.c index e42ab418ad..7801306cb4 100644 --- a/src/utf.c +++ b/src/utf.c @@ -231,7 +231,7 @@ SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ rc = sqlite3VdbeMemMakeWriteable(pMem); if( rc!=SQLITE_OK ){ assert( rc==SQLITE_NOMEM ); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } zIn = (u8*)pMem->z; zTerm = &zIn[pMem->n&~1]; @@ -273,7 +273,7 @@ SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ zTerm = &zIn[pMem->n]; zOut = sqlite3DbMallocRaw(pMem->db, len); if( !zOut ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } z = zOut; diff --git a/src/vacuum.c b/src/vacuum.c index adc802e60b..bc7b5831b6 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -38,7 +38,7 @@ static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ sqlite3_stmt *pStmt; VVA_ONLY( int rc; ) if( !zSql ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){ sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); @@ -219,7 +219,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0)) || NEVER(db->mallocFailed) ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto end_of_vacuum; } diff --git a/src/vdbe.c b/src/vdbe.c index e7c3e48af5..38b101d382 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5315,7 +5315,7 @@ case OP_ParseSchema: { "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", db->aDb[iDb].zName, zMaster, pOp->p4.z); if( zSql==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else{ assert( db->init.busy==0 ); db->init.busy = 1; @@ -6816,7 +6816,7 @@ too_big: no_mem: sqlite3OomFault(db); sqlite3VdbeError(p, "out of memory"); - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto vdbe_error_halt; /* Jump to here for any other kind of fatal error. The "rc" variable @@ -6824,7 +6824,7 @@ no_mem: */ abort_due_to_error: assert( p->zErrMsg==0 ); - if( db->mallocFailed ) rc = SQLITE_NOMEM; + if( db->mallocFailed ) rc = SQLITE_NOMEM_BKPT; if( rc!=SQLITE_IOERR_NOMEM ){ sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); } @@ -6835,7 +6835,7 @@ abort_due_to_error: */ abort_due_to_interrupt: assert( db->u1.isInterrupted ); - rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_INTERRUPT; + rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; p->rc = rc; sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); goto vdbe_error_halt; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index fce43630e7..b25b1ce5f4 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -471,7 +471,7 @@ void sqlite3_result_error_toobig(sqlite3_context *pCtx){ void sqlite3_result_error_nomem(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); - pCtx->isError = SQLITE_NOMEM; + pCtx->isError = SQLITE_NOMEM_BKPT; pCtx->fErrorOrAux = 1; sqlite3OomFault(pCtx->pOut->db); } @@ -547,7 +547,7 @@ static int sqlite3Step(Vdbe *p){ db = p->db; if( db->mallocFailed ){ p->rc = SQLITE_NOMEM; - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } if( p->pc<=0 && p->expired ){ @@ -610,7 +610,7 @@ static int sqlite3Step(Vdbe *p){ db->errCode = rc; if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){ - p->rc = SQLITE_NOMEM; + p->rc = SQLITE_NOMEM_BKPT; } end_of_step: /* At this point local variable rc holds the value that should be @@ -677,7 +677,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){ v->rc = rc2; } else { v->zErrMsg = 0; - v->rc = rc = SQLITE_NOMEM; + v->rc = rc = SQLITE_NOMEM_BKPT; } } rc = sqlite3ApiExit(db, rc); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index ce98edd0a5..b7517edb0a 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -129,7 +129,7 @@ static int growOpArray(Vdbe *v, int nOp){ p->nOpAlloc = p->szOpAlloc/sizeof(Op); v->aOp = pNew; } - return (pNew ? SQLITE_OK : SQLITE_NOMEM); + return (pNew ? SQLITE_OK : SQLITE_NOMEM_BKPT); } #ifdef SQLITE_DEBUG @@ -1530,7 +1530,7 @@ int sqlite3VdbeList( releaseMemArray(pMem, 8); p->pResultSet = 0; - if( p->rc==SQLITE_NOMEM ){ + if( p->rc==SQLITE_NOMEM_BKPT ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ sqlite3OomFault(db); @@ -2119,7 +2119,7 @@ int sqlite3VdbeSetColName( assert( vardb->mallocFailed ){ assert( !zName || xDel!=SQLITE_DYNAMIC ); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } assert( p->aColName!=0 ); pColName = &(p->aColName[idx+var*p->nResColumn]); @@ -2237,7 +2237,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ /* Select a master journal file name */ nMainFile = sqlite3Strlen30(zMainFile); zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz", zMainFile); - if( zMaster==0 ) return SQLITE_NOMEM; + if( zMaster==0 ) return SQLITE_NOMEM_BKPT; do { u32 iRandom; if( retryCount ){ @@ -2527,7 +2527,7 @@ int sqlite3VdbeHalt(Vdbe *p){ */ if( db->mallocFailed ){ - p->rc = SQLITE_NOMEM; + p->rc = SQLITE_NOMEM_BKPT; } if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag); closeAllCursors(p); @@ -2688,7 +2688,7 @@ int sqlite3VdbeHalt(Vdbe *p){ p->magic = VDBE_MAGIC_HALT; checkActiveVdbeCnt(db); if( db->mallocFailed ){ - p->rc = SQLITE_NOMEM; + p->rc = SQLITE_NOMEM_BKPT; } /* If the auto-commit flag is set to true, then any locks that were held @@ -3666,7 +3666,7 @@ static int vdbeCompareMemString( v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); n2 = v2==0 ? 0 : c2.n; rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); - if( (v1==0 || v2==0) && prcErr ) *prcErr = SQLITE_NOMEM; + if( (v1==0 || v2==0) && prcErr ) *prcErr = SQLITE_NOMEM_BKPT; sqlite3VdbeMemRelease(&c1); sqlite3VdbeMemRelease(&c2); return rc; diff --git a/src/vdbemem.c b/src/vdbemem.c index 6fb7cebbcc..d07acefcf6 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -138,7 +138,7 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ sqlite3VdbeMemSetNull(pMem); pMem->z = 0; pMem->szMalloc = 0; - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; }else{ pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); } @@ -196,7 +196,7 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){ f = pMem->flags; if( (f&(MEM_Str|MEM_Blob)) && (pMem->szMalloc==0 || pMem->z!=pMem->zMalloc) ){ if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } pMem->z[pMem->n] = 0; pMem->z[pMem->n+1] = 0; @@ -228,7 +228,7 @@ int sqlite3VdbeMemExpandBlob(Mem *pMem){ nByte = 1; } if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } memset(&pMem->z[pMem->n], 0, pMem->u.nZero); @@ -245,7 +245,7 @@ int sqlite3VdbeMemExpandBlob(Mem *pMem){ */ static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } pMem->z[pMem->n] = 0; pMem->z[pMem->n+1] = 0; @@ -294,7 +294,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8 @@ -905,7 +905,7 @@ int sqlite3VdbeMemSetStr( testcase( nAlloc==31 ); testcase( nAlloc==32 ); if( sqlite3VdbeMemClearAndResize(pMem, MAX(nAlloc,32)) ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } memcpy(pMem->z, z, nAlloc); }else if( xDel==SQLITE_DYNAMIC ){ @@ -925,7 +925,7 @@ int sqlite3VdbeMemSetStr( #ifndef SQLITE_OMIT_UTF16 if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } #endif @@ -1206,7 +1206,7 @@ static int valueFromFunction( if( pList ){ apVal = (sqlite3_value**)sqlite3DbMallocZero(db, sizeof(apVal[0]) * nVal); if( apVal==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto value_from_function_out; } for(i=0; inRec ) return SQLITE_CORRUPT_BKPT; if( pMem==0 ){ pMem = *ppVal = sqlite3ValueNew(db); - if( pMem==0 ) return SQLITE_NOMEM; + if( pMem==0 ) return SQLITE_NOMEM_BKPT; } sqlite3VdbeSerialGet(&a[iField-szField], t, pMem); pMem->enc = ENC(db); diff --git a/src/vdbesort.c b/src/vdbesort.c index 380772ee16..9a5d7b34e3 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -540,7 +540,7 @@ static int vdbePmaReadBlob( int nNew = MAX(128, p->nAlloc*2); while( nByte>nNew ) nNew = nNew*2; aNew = sqlite3Realloc(p->aAlloc, nNew); - if( !aNew ) return SQLITE_NOMEM; + if( !aNew ) return SQLITE_NOMEM_BKPT; p->nAlloc = nNew; p->aAlloc = aNew; } @@ -652,7 +652,7 @@ static int vdbePmaReaderSeek( int iBuf = pReadr->iReadOff % pgsz; if( pReadr->aBuffer==0 ){ pReadr->aBuffer = (u8*)sqlite3Malloc(pgsz); - if( pReadr->aBuffer==0 ) rc = SQLITE_NOMEM; + if( pReadr->aBuffer==0 ) rc = SQLITE_NOMEM_BKPT; pReadr->nBuffer = pgsz; } if( rc==SQLITE_OK && iBuf ){ @@ -968,7 +968,7 @@ int sqlite3VdbeSorterInit( pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo); pCsr->uc.pSorter = pSorter; if( pSorter==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else{ pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz); memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo); @@ -1002,7 +1002,7 @@ int sqlite3VdbeSorterInit( assert( pSorter->iMemory==0 ); pSorter->nMemory = pgsz; pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz); - if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM; + if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM_BKPT; } } @@ -1324,7 +1324,7 @@ static int vdbeSortAllocUnpacked(SortSubtask *pTask){ pTask->pSorter->pKeyInfo, 0, 0, &pFree ); assert( pTask->pUnpacked==(UnpackedRecord*)pFree ); - if( pFree==0 ) return SQLITE_NOMEM; + if( pFree==0 ) return SQLITE_NOMEM_BKPT; pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField; pTask->pUnpacked->errCode = 0; } @@ -1399,7 +1399,7 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){ aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *)); if( !aSlot ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } while( p ){ @@ -1449,7 +1449,7 @@ static void vdbePmaWriterInit( memset(p, 0, sizeof(PmaWriter)); p->aBuffer = (u8*)sqlite3Malloc(nBuf); if( !p->aBuffer ){ - p->eFWErr = SQLITE_NOMEM; + p->eFWErr = SQLITE_NOMEM_BKPT; }else{ p->iBufEnd = p->iBufStart = (iStart % nBuf); p->iWriteOff = iStart - p->iBufStart; @@ -1737,7 +1737,7 @@ static int vdbeSorterFlushPMA(VdbeSorter *pSorter){ pSorter->nMemory = sqlite3MallocSize(aMem); }else if( pSorter->list.aMemory ){ pSorter->list.aMemory = sqlite3Malloc(pSorter->nMemory); - if( !pSorter->list.aMemory ) return SQLITE_NOMEM; + if( !pSorter->list.aMemory ) return SQLITE_NOMEM_BKPT; } rc = vdbeSorterCreateThread(pTask, vdbeSorterFlushThread, pCtx); @@ -1828,7 +1828,7 @@ int sqlite3VdbeSorterWrite( if( nNew < nMin ) nNew = nMin; aNew = sqlite3Realloc(pSorter->list.aMemory, nNew); - if( !aNew ) return SQLITE_NOMEM; + if( !aNew ) return SQLITE_NOMEM_BKPT; pSorter->list.pList = (SorterRecord*)&aNew[iListOff]; pSorter->list.aMemory = aNew; pSorter->nMemory = nNew; @@ -1842,7 +1842,7 @@ int sqlite3VdbeSorterWrite( }else{ pNew = (SorterRecord *)sqlite3Malloc(nReq); if( pNew==0 ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } pNew->u.pNext = pSorter->list.pList; } @@ -1989,7 +1989,7 @@ static int vdbeIncrMergerNew( pTask->file2.iEof += pIncr->mxSz; }else{ vdbeMergeEngineFree(pMerger); - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; } return rc; } @@ -2294,7 +2294,7 @@ static int vdbeMergeEngineLevel0( int rc = SQLITE_OK; *ppOut = pNew = vdbeMergeEngineNew(nPMA); - if( pNew==0 ) rc = SQLITE_NOMEM; + if( pNew==0 ) rc = SQLITE_NOMEM_BKPT; for(i=0; ipIncr==0 ){ MergeEngine *pNew = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT); if( pNew==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else{ rc = vdbeIncrMergerNew(pTask, pNew, &pReadr->pIncr); } @@ -2410,7 +2410,7 @@ static int vdbeSorterMergeTreeBuild( assert( pSorter->bUseThreads || pSorter->nTask==1 ); if( pSorter->nTask>1 ){ pMain = vdbeMergeEngineNew(pSorter->nTask); - if( pMain==0 ) rc = SQLITE_NOMEM; + if( pMain==0 ) rc = SQLITE_NOMEM_BKPT; } #endif @@ -2428,7 +2428,7 @@ static int vdbeSorterMergeTreeBuild( int i; int iSeq = 0; pRoot = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT); - if( pRoot==0 ) rc = SQLITE_NOMEM; + if( pRoot==0 ) rc = SQLITE_NOMEM_BKPT; for(i=0; inPMA && rc==SQLITE_OK; i += SORTER_MAX_MERGE_COUNT){ MergeEngine *pMerger = 0; /* New level-0 PMA merger */ int nReader; /* Number of level-0 PMAs to merge */ @@ -2499,7 +2499,7 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){ if( rc==SQLITE_OK ){ pReadr = (PmaReader*)sqlite3DbMallocZero(db, sizeof(PmaReader)); pSorter->pReader = pReadr; - if( pReadr==0 ) rc = SQLITE_NOMEM; + if( pReadr==0 ) rc = SQLITE_NOMEM_BKPT; } if( rc==SQLITE_OK ){ rc = vdbeIncrMergerNew(pLast, pMain, &pReadr->pIncr); @@ -2676,7 +2676,7 @@ int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){ pSorter = pCsr->uc.pSorter; pKey = vdbeSorterRowkey(pSorter, &nKey); if( sqlite3VdbeMemClearAndResize(pOut, nKey) ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } pOut->n = nKey; MemSetTypeFlag(pOut, MEM_Blob); @@ -2721,7 +2721,7 @@ int sqlite3VdbeSorterCompare( char *p; r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo,0,0,&p); assert( pSorter->pUnpacked==(UnpackedRecord*)p ); - if( r2==0 ) return SQLITE_NOMEM; + if( r2==0 ) return SQLITE_NOMEM_BKPT; r2->nField = nKeyCol; } assert( r2->nField==nKeyCol ); diff --git a/src/vtab.c b/src/vtab.c index e8794e687d..cb443faae9 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -506,13 +506,13 @@ static int vtabCallConstructor( zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); if( !zModuleName ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } pVTable = sqlite3DbMallocZero(db, sizeof(VTable)); if( !pVTable ){ sqlite3DbFree(db, zModuleName); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } pVTable->db = db; pVTable->pMod = pMod; @@ -655,7 +655,7 @@ static int growVTrans(sqlite3 *db){ int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR); aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes); if( !aVTrans ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR); db->aVTrans = aVTrans; @@ -747,7 +747,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); if( pParse==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else{ pParse->declareVtab = 1; pParse->db = db; diff --git a/src/wal.c b/src/wal.c index 7cf2cabffb..11aedfac21 100644 --- a/src/wal.c +++ b/src/wal.c @@ -546,7 +546,7 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte); if( !apNew ){ *ppPage = 0; - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } memset((void*)&apNew[pWal->nWiData], 0, sizeof(u32*)*(iPage+1-pWal->nWiData)); @@ -558,7 +558,7 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ if( pWal->apWiData[iPage]==0 ){ if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ); - if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM; + if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT; }else{ rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, pWal->writeLock, (void volatile **)&pWal->apWiData[iPage] @@ -1173,7 +1173,7 @@ static int walIndexRecover(Wal *pWal){ szFrame = szPage + WAL_FRAME_HDRSIZE; aFrame = (u8 *)sqlite3_malloc64(szFrame); if( !aFrame ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; goto recovery_error; } aData = &aFrame[WAL_FRAME_HDRSIZE]; @@ -1311,7 +1311,7 @@ int sqlite3WalOpen( *ppWal = 0; pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile); if( !pRet ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } pRet->pVfs = pVfs; @@ -1575,7 +1575,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){ + iLast*sizeof(ht_slot); p = (WalIterator *)sqlite3_malloc64(nByte); if( !p ){ - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } memset(p, 0, nByte); p->nSegment = nSegment; @@ -1587,7 +1587,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){ sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) ); if( !aTmp ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; } for(i=0; rc==SQLITE_OK && ipData; #endif @@ -2909,7 +2909,7 @@ static int walRewriteChecksums(Wal *pWal, u32 iLast){ i64 iCksumOff; aBuf = sqlite3_malloc(szPage + WAL_FRAME_HDRSIZE); - if( aBuf==0 ) return SQLITE_NOMEM; + if( aBuf==0 ) return SQLITE_NOMEM_BKPT; /* Find the checksum values to use as input for the recalculating the ** first checksum. If the first frame is frame 1 (implying that the current @@ -3379,7 +3379,7 @@ int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){ pRet = (WalIndexHdr*)sqlite3_malloc(sizeof(WalIndexHdr)); if( pRet==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM_BKPT; }else{ memcpy(pRet, &pWal->hdr, sizeof(WalIndexHdr)); *ppSnapshot = (sqlite3_snapshot*)pRet; diff --git a/src/where.c b/src/where.c index 8ecdd840f3..ca9e4a6f9d 100644 --- a/src/where.c +++ b/src/where.c @@ -1736,7 +1736,7 @@ static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){ if( p->nLSlot>=n ) return SQLITE_OK; n = (n+7)&~7; paNew = sqlite3DbMallocRawNN(db, sizeof(p->aLTerm[0])*n); - if( paNew==0 ) return SQLITE_NOMEM; + if( paNew==0 ) return SQLITE_NOMEM_BKPT; memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot); if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm); p->aLTerm = paNew; @@ -1751,7 +1751,7 @@ static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){ whereLoopClearUnion(db, pTo); if( whereLoopResize(db, pTo, pFrom->nLTerm) ){ memset(&pTo->u, 0, sizeof(pTo->u)); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ); memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0])); @@ -2033,7 +2033,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ if( p==0 ){ /* Allocate a new WhereLoop to add to the end of the list */ *ppPrev = p = sqlite3DbMallocRawNN(db, sizeof(WhereLoop)); - if( p==0 ) return SQLITE_NOMEM; + if( p==0 ) return SQLITE_NOMEM_BKPT; whereLoopInit(p); p->pNextLoop = 0; }else{ @@ -2189,7 +2189,7 @@ static int whereLoopAddBtreeIndex( WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ pNew = pBuilder->pNew; - if( db->mallocFailed ) return SQLITE_NOMEM; + if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); @@ -2806,7 +2806,7 @@ static int whereLoopAddVirtual( pTab = pSrc->pTab; assert( IsVirtual(pTab) ); pIdxInfo = allocateIndexInfo(pParse, pWC, mUnusable, pSrc,pBuilder->pOrderBy); - if( pIdxInfo==0 ) return SQLITE_NOMEM; + if( pIdxInfo==0 ) return SQLITE_NOMEM_BKPT; pNew->prereq = 0; pNew->rSetup = 0; pNew->wsFlags = WHERE_VIRTUALTABLE; @@ -2816,7 +2816,7 @@ static int whereLoopAddVirtual( nConstraint = pIdxInfo->nConstraint; if( whereLoopResize(db, pNew, nConstraint) ){ sqlite3DbFree(db, pIdxInfo); - return SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; } for(iPhase=0; iPhase<=3; iPhase++){ @@ -3521,7 +3521,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; nSpace += sizeof(LogEst) * nOrderBy; pSpace = sqlite3DbMallocRawNN(db, nSpace); - if( pSpace==0 ) return SQLITE_NOMEM; + if( pSpace==0 ) return SQLITE_NOMEM_BKPT; aTo = (WherePath*)pSpace; aFrom = aTo+mxChoice; memset(aFrom, 0, sizeof(aFrom[0])); From 8fd8413aaaa393e3b00c7f7283d805ba0353c1ad Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sun, 14 Feb 2016 00:14:35 +0000 Subject: [PATCH 284/570] Update a comment. FossilOrigin-Name: e9753d9a2c1269050f886e6cb9bc9cba0a8df6ce --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/main.c | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index e0d2085551..50b9a8c744 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sability\sto\sdebug\sout-of-memory\serrors. -D 2016-02-13T23:43:46.135 +C Update\sa\scomment. +D 2016-02-14T00:14:35.173 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -313,7 +313,7 @@ F src/insert.c 9ca97272e9f74ed0efddf3b4350ee12740cebbef F src/journal.c fe3a3e2559ce3ce9d371afd30fbabbc074174575 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f -F src/main.c fa3b9f523bcecf7b35d3f77ad1c091cd6902c74d +F src/main.c 49f6d326bcecdbd2ee137abacd071439273e35ef F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -1427,10 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 37ec3015ec95035d31e3672f520908a0d36c9d67 -R c35a4cd7d70ca4772cad6122d840cf2a -T *branch * noMemBkpt -T *sym-noMemBkpt * -T -sym-trunk * +P 6a9c4a3ebfb7cc0738ef6634440ccab44a21ff28 +R e3819c5f475544c6e34fa514747b2e7e U mistachkin -Z 8214b214fa921fedf00745b7f0968f1a +Z 1f3637cc5e67ca5cc7786677aae5b8ad diff --git a/manifest.uuid b/manifest.uuid index 2c1496cdf8..329a43c604 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6a9c4a3ebfb7cc0738ef6634440ccab44a21ff28 \ No newline at end of file +e9753d9a2c1269050f886e6cb9bc9cba0a8df6ce \ No newline at end of file diff --git a/src/main.c b/src/main.c index a44fec8a5b..326d1ef68a 100644 --- a/src/main.c +++ b/src/main.c @@ -3205,7 +3205,7 @@ int sqlite3_get_autocommit(sqlite3 *db){ /* ** The following routines are substitutes for constants SQLITE_CORRUPT, -** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error +** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_NOMEM and possibly other error ** constants. They serve two purposes: ** ** 1. Serve as a convenient place to set a breakpoint in a debugger From 80738d9c3ed3b1fa4311eee0ed9a2891136718d3 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 15 Feb 2016 00:34:16 +0000 Subject: [PATCH 285/570] Improvements to the application-defined function mechanism so that it is more compact and runs faster, especially when the application defines thousands of new SQL functions. FossilOrigin-Name: 3201fbcc5105d23132e6b8b7ac825e66af4f8a39 --- manifest | 39 +++++++++++----------- manifest.uuid | 2 +- src/alter.c | 10 ++---- src/analyze.c | 9 ++---- src/attach.c | 6 ++-- src/callback.c | 68 +++++++++++++++++++++----------------- src/date.c | 10 ++---- src/expr.c | 8 ++--- src/func.c | 86 +++++++++++++++++++++++++++---------------------- src/global.c | 2 +- src/main.c | 43 ++++++++++++------------- src/resolve.c | 4 +-- src/sqliteInt.h | 56 ++++++++++++++++++-------------- src/util.c | 15 +++++++-- src/vdbemem.c | 13 ++------ 15 files changed, 189 insertions(+), 182 deletions(-) diff --git a/manifest b/manifest index 18d443650d..968113e200 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Provide\sSqlite3_SafeInit()\sand\sSqlite3_SafeUnload()\sentry\spoints\son\sthe\sTCL\ninterface,\sbut\shave\sthe\salways\sreturn\sTCL_ERROR,\sbecause\sthe\snon-standard\s\nTCL\sbuilds\son\sMacs\srequire\sthis. -D 2016-02-13T18:54:10.051 +C Improvements\sto\sthe\sapplication-defined\sfunction\smechanism\sso\sthat\sit\sis\nmore\scompact\sand\sruns\sfaster,\sespecially\swhen\sthe\sapplication\sdefines\nthousands\sof\snew\sSQL\sfunctions. +D 2016-02-15T00:34:16.170 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -284,9 +284,9 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 1fbb01c26c64528088f1df8015992fefda387889 -F src/analyze.c fbf0e80d83cc893734e872f932f249a056b86e11 -F src/attach.c c16c2648a577fa3def2adfa48c28901376389bc5 +F src/alter.c 7603afbd61f55e7c644b8de4a42f33e58c0b7eaa +F src/analyze.c b148441c7d35b5514ec1a66f9df97be8fa4c68a1 +F src/attach.c 07aa6e77c3906d46d4c36d7c81641dedd6adac91 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf @@ -295,17 +295,17 @@ F src/btree.c 4c8caaeed7878aafdb607c3d2bcbc365bb0d19a1 F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 54866fbafa09d494269bdefc79995eb7207003a6 -F src/callback.c ed6c2a4a712eb7287ff64e20e3c23265dfb8a7ce +F src/callback.c 0643b8fb06c95a8977beb201b268210d4b131a22 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 -F src/date.c ca17321bc17cca8f40e0843edea4fafff974998e +F src/date.c 0b73e681c11fca867fec554750c07fe0d4e417c1 F src/dbstat.c b2ec6793eef97aebb4d171d490a4ffdfa9f2475c F src/delete.c 48802aa3ee6339f576d074336d3ae1b5f40e240f -F src/expr.c fbf0706199aea23c54efe36b6932d8307c4eb872 +F src/expr.c 9adb58153f6e943b703d43e9a1f67f77b5a75721 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 08edad1fce30f761f14b3997e89bad58f9f7f4e0 -F src/func.c 86e55fee35b9577e485f47d9dd5c1d34cd513288 -F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 +F src/func.c 552d300265aed09eea21f68ac742a440550c0062 +F src/global.c ded7b97efd16efda5062b65e857198e46c40e652 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 @@ -313,7 +313,7 @@ F src/insert.c 9ca97272e9f74ed0efddf3b4350ee12740cebbef F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b -F src/main.c b67a45397b93b7ba8fbd6bfcb03423d245baed05 +F src/main.c 17cfc8ba39fd86bc8201213140db53a65ff3cf2a F src/malloc.c 337e9808b5231855fe28857950f4f60ae42c417f F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -346,14 +346,14 @@ F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c c12b786713df3e8270c0f85f988c5359d8b4d87c F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 -F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c +F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c ff80004a9a6ece891a8d9327a88e7b6e2588ee6d F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe F src/sqlite.h.in f80c6ebd85588fc514bfedf3ecb00cec269cb410 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 04ca5b3cdb3bcf87ba6300d5d36b51498f65f28c +F src/sqliteInt.h ddd4a48f3ac2a423f003027e73bd8422bfa4d991 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -411,7 +411,7 @@ F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 -F src/util.c 49ce0a65306c1c51d61cb5bc214c71cb62452de6 +F src/util.c 8073bbdab9cc7209f6741bd44264ede606cbadc6 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 F src/vdbe.c c193299e595a13eba247738e22fce25c49346a6c F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 @@ -419,7 +419,7 @@ F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 F src/vdbeapi.c 9324f6baee1a1b2284c6543e98f916888a81e459 F src/vdbeaux.c deae5d3bd45da0e57c7d9e1d7436333d142dc3bb F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db -F src/vdbemem.c 68fcfac37dc6601d98c32cc5adee4d39f2c1b7b4 +F src/vdbemem.c e0dbb7bb9c2ec566c53c6575b4f51b3fcd426811 F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 F src/vtab.c bef51b4f693d82b4b0184457faa8625654534091 @@ -1427,7 +1427,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a049fbbde5da2e43d41aa8c2b41f9eb21507ac76 -R 0ed7109e4c77d1cb323166614bc90c67 +P 37ec3015ec95035d31e3672f520908a0d36c9d67 +R 8daa9c28aeb9b7a90a9f45db47e6f0fa +T *branch * many-app-functions +T *sym-many-app-functions * +T -sym-trunk * U drh -Z 0875f4eabfb763252145d2214f48fc91 +Z 4df4dc22cfe3910711fb118d648968ac diff --git a/manifest.uuid b/manifest.uuid index 5b62ca1a2d..225e4ca215 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -37ec3015ec95035d31e3672f520908a0d36c9d67 \ No newline at end of file +3201fbcc5105d23132e6b8b7ac825e66af4f8a39 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 34221777a7..f10a85022a 100644 --- a/src/alter.c +++ b/src/alter.c @@ -229,7 +229,7 @@ static void renameTriggerFunc( ** Register built-in functions used to help implement ALTER TABLE */ void sqlite3AlterFunctions(void){ - static SQLITE_WSD FuncDef aAlterTableFuncs[] = { + static FuncDef aAlterTableFuncs[] = { FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc), #ifndef SQLITE_OMIT_TRIGGER FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc), @@ -238,13 +238,7 @@ void sqlite3AlterFunctions(void){ FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc), #endif }; - int i; - FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); - FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAlterTableFuncs); - - for(i=0; ia[h]; p; p=p->pHash){ - if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 && p->zName[nFunc]==0 ){ + for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){ + if( sqlite3StrICmp(p->zName, zFunc)==0 ){ return p; } } @@ -301,23 +299,26 @@ static FuncDef *functionSearch( /* ** Insert a new FuncDef into a FuncDefHash hash table. */ -void sqlite3FuncDefInsert( - FuncDefHash *pHash, /* The hash table into which to insert */ - FuncDef *pDef /* The function definition to insert */ +void sqlite3InsertBuiltinFuncs( + FuncDef *aDef, /* List of global functions to be inserted */ + int nDef /* Length of the apDef[] list */ ){ - FuncDef *pOther; - int nName = sqlite3Strlen30(pDef->zName); - u8 c1 = (u8)pDef->zName[0]; - int h = (sqlite3UpperToLower[c1] + nName) % ArraySize(pHash->a); - pOther = functionSearch(pHash, h, pDef->zName, nName); - if( pOther ){ - assert( pOther!=pDef && pOther->pNext!=pDef ); - pDef->pNext = pOther->pNext; - pOther->pNext = pDef; - }else{ - pDef->pNext = 0; - pDef->pHash = pHash->a[h]; - pHash->a[h] = pDef; + int i; + for(i=0; ipNext!=&aDef[i] ); + aDef[i].pNext = pOther->pNext; + pOther->pNext = &aDef[i]; + }else{ + aDef[i].pNext = 0; + aDef[i].u.pHash = sqlite3BuiltinFunctions.a[h]; + sqlite3BuiltinFunctions.a[h] = &aDef[i]; + } } } @@ -344,8 +345,7 @@ void sqlite3FuncDefInsert( */ FuncDef *sqlite3FindFunction( sqlite3 *db, /* An open database */ - const char *zName, /* Name of the function. Not null-terminated */ - int nName, /* Number of characters in the name */ + const char *zName, /* Name of the function. zero-terminated */ int nArg, /* Number of arguments. -1 means any number */ u8 enc, /* Preferred text encoding */ u8 createFlag /* Create new entry if true and does not otherwise exist */ @@ -354,14 +354,15 @@ FuncDef *sqlite3FindFunction( FuncDef *pBest = 0; /* Best match found so far */ int bestScore = 0; /* Score of best match */ int h; /* Hash value */ + int nName; /* Length of the name */ assert( nArg>=(-2) ); assert( nArg>=(-1) || createFlag==0 ); - h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a); + nName = sqlite3Strlen30(zName); /* First search for a match amongst the application-defined functions. */ - p = functionSearch(&db->aFunc, h, zName, nName); + p = (FuncDef*)sqlite3HashFind(&db->aFunc, zName); while( p ){ int score = matchQuality(p, nArg, enc); if( score>bestScore ){ @@ -384,9 +385,9 @@ FuncDef *sqlite3FindFunction( ** So we must not search for built-ins when creating a new function. */ if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){ - FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); bestScore = 0; - p = functionSearch(pHash, h, zName, nName); + h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ; + p = functionSearch(h, zName); while( p ){ int score = matchQuality(p, nArg, enc); if( score>bestScore ){ @@ -403,12 +404,19 @@ FuncDef *sqlite3FindFunction( */ if( createFlag && bestScorezName = (char *)&pBest[1]; pBest->nArg = (u16)nArg; pBest->funcFlags = enc; - memcpy(pBest->zName, zName, nName); - pBest->zName[nName] = 0; - sqlite3FuncDefInsert(&db->aFunc, pBest); + memcpy(pBest->zName, zName, nName+1); + pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest); + if( pOther==pBest ){ + sqlite3DbFree(db, pBest); + sqlite3OomFault(db); + return 0; + }else{ + pBest->pNext = pOther; + } } if( pBest && (pBest->xSFunc || createFlag) ){ diff --git a/src/date.c b/src/date.c index 0a1d0e0798..ef05d44086 100644 --- a/src/date.c +++ b/src/date.c @@ -1136,7 +1136,7 @@ static void currentTimeFunc( ** external linkage. */ void sqlite3RegisterDateTimeFunctions(void){ - static SQLITE_WSD FuncDef aDateTimeFuncs[] = { + static FuncDef aDateTimeFuncs[] = { #ifndef SQLITE_OMIT_DATETIME_FUNCS DFUNCTION(julianday, -1, 0, 0, juliandayFunc ), DFUNCTION(date, -1, 0, 0, dateFunc ), @@ -1152,11 +1152,5 @@ void sqlite3RegisterDateTimeFunctions(void){ STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc), #endif }; - int i; - FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); - FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs); - - for(i=0; inExpr : 0; assert( !ExprHasProperty(pExpr, EP_IntValue) ); zId = pExpr->u.zToken; - nId = sqlite3Strlen30(zId); - pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0); + pDef = sqlite3FindFunction(db, zId, nFarg, enc, 0); if( pDef==0 || pDef->xFinalize!=0 ){ - sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId); + sqlite3ErrorMsg(pParse, "unknown function: %s()", zId); break; } @@ -4132,7 +4130,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ pItem->iMem = ++pParse->nMem; assert( !ExprHasProperty(pExpr, EP_IntValue) ); pItem->pFunc = sqlite3FindFunction(pParse->db, - pExpr->u.zToken, sqlite3Strlen30(pExpr->u.zToken), + pExpr->u.zToken, pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); if( pExpr->flags & EP_Distinct ){ pItem->iDistinct = pParse->nTab++; diff --git a/src/func.c b/src/func.c index d615cf90b1..662a08f504 100644 --- a/src/func.c +++ b/src/func.c @@ -1611,7 +1611,7 @@ static void groupConcatFinalize(sqlite3_context *context){ ** of the built-in functions above are part of the global function set. ** This routine only deals with those that are not global. */ -void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ +void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){ int rc = sqlite3_overload_function(db, "MATCH", 2); assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); if( rc==SQLITE_NOMEM ){ @@ -1624,8 +1624,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ */ static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){ FuncDef *pDef; - pDef = sqlite3FindFunction(db, zName, sqlite3Strlen30(zName), - 2, SQLITE_UTF8, 0); + pDef = sqlite3FindFunction(db, zName, 2, SQLITE_UTF8, 0); if( ALWAYS(pDef) ){ pDef->funcFlags |= flagVal; } @@ -1673,9 +1672,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ return 0; } assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - pDef = sqlite3FindFunction(db, pExpr->u.zToken, - sqlite3Strlen30(pExpr->u.zToken), - 2, SQLITE_UTF8, 0); + pDef = sqlite3FindFunction(db, pExpr->u.zToken, 2, SQLITE_UTF8, 0); if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){ return 0; } @@ -1699,7 +1696,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ ** ** After this routine runs */ -void sqlite3RegisterGlobalFunctions(void){ +void sqlite3RegisterBuiltinFunctions(void){ /* ** The following array holds FuncDef structures for all of the functions ** defined in this file. @@ -1707,8 +1704,27 @@ void sqlite3RegisterGlobalFunctions(void){ ** The array cannot be constant since changes are made to the ** FuncDef.pHash elements at start-time. The elements of this array ** are read-only after initialization is complete. + ** + ** For peak efficiency, put the most frequently used function last. */ - static SQLITE_WSD FuncDef aBuiltinFunc[] = { + static FuncDef aBuiltinFunc[] = { +#ifdef SQLITE_SOUNDEX + FUNCTION(soundex, 1, 0, 0, soundexFunc ), +#endif +#ifndef SQLITE_OMIT_LOAD_EXTENSION + VFUNCTION(load_extension, 1, 0, 0, loadExt ), + VFUNCTION(load_extension, 2, 0, 0, loadExt ), +#endif +#if SQLITE_USER_AUTHENTICATION + FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ), +#endif +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS + DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ), + DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ), +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ + FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), + FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), + FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), FUNCTION(ltrim, 1, 1, 0, trimFunc ), FUNCTION(ltrim, 2, 1, 0, trimFunc ), FUNCTION(rtrim, 1, 2, 0, trimFunc ), @@ -1726,8 +1742,6 @@ void sqlite3RegisterGlobalFunctions(void){ FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(instr, 2, 0, 0, instrFunc ), - FUNCTION(substr, 2, 0, 0, substrFunc ), - FUNCTION(substr, 3, 0, 0, substrFunc ), FUNCTION(printf, -1, 0, 0, printfFunc ), FUNCTION(unicode, 1, 0, 0, unicodeFunc ), FUNCTION(char, -1, 0, 0, charFunc ), @@ -1738,40 +1752,22 @@ void sqlite3RegisterGlobalFunctions(void){ #endif FUNCTION(upper, 1, 0, 0, upperFunc ), FUNCTION(lower, 1, 0, 0, lowerFunc ), - FUNCTION(coalesce, 1, 0, 0, 0 ), - FUNCTION(coalesce, 0, 0, 0, 0 ), - FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), FUNCTION(hex, 1, 0, 0, hexFunc ), FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), - FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), - FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), - FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), VFUNCTION(random, 0, 0, 0, randomFunc ), VFUNCTION(randomblob, 1, 0, 0, randomBlob ), FUNCTION(nullif, 2, 0, 1, nullifFunc ), DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ), DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ), -#if SQLITE_USER_AUTHENTICATION - FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ), -#endif -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS - DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ), - DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ), -#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ FUNCTION(quote, 1, 0, 0, quoteFunc ), VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), VFUNCTION(changes, 0, 0, 0, changes ), VFUNCTION(total_changes, 0, 0, 0, total_changes ), FUNCTION(replace, 3, 0, 0, replaceFunc ), FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ), - #ifdef SQLITE_SOUNDEX - FUNCTION(soundex, 1, 0, 0, soundexFunc ), - #endif - #ifndef SQLITE_OMIT_LOAD_EXTENSION - VFUNCTION(load_extension, 1, 0, 0, loadExt ), - VFUNCTION(load_extension, 2, 0, 0, loadExt ), - #endif + FUNCTION(substr, 2, 0, 0, substrFunc ), + FUNCTION(substr, 3, 0, 0, substrFunc ), AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ), AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ), AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ), @@ -1789,20 +1785,32 @@ void sqlite3RegisterGlobalFunctions(void){ LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE), LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE), #endif + FUNCTION(coalesce, 1, 0, 0, 0 ), + FUNCTION(coalesce, 0, 0, 0, 0 ), + FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), }; - - int i; - FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); - FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc); - - for(i=0; iu.pHash){ + int n = sqlite3Strlen30(p->zName); + int h = p->zName[0] + n; + printf(" %s(%d)", p->zName, h); + } + printf("\n"); + } + } #endif } diff --git a/src/global.c b/src/global.c index 64966b35d7..294d62fea8 100644 --- a/src/global.c +++ b/src/global.c @@ -219,7 +219,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = { ** database connections. After initialization, this table is ** read-only. */ -SQLITE_WSD FuncDefHash sqlite3GlobalFunctions; +FuncDefHash sqlite3BuiltinFunctions; /* ** Constant tokens for values 0 and 1. diff --git a/src/main.c b/src/main.c index 922af1315a..7d36ecf7d0 100644 --- a/src/main.c +++ b/src/main.c @@ -218,7 +218,6 @@ int sqlite3_initialize(void){ */ sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex); if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){ - FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); sqlite3GlobalConfig.inProgress = 1; #ifdef SQLITE_ENABLE_SQLLOG { @@ -226,8 +225,8 @@ int sqlite3_initialize(void){ sqlite3_init_sqllog(); } #endif - memset(pHash, 0, sizeof(sqlite3GlobalFunctions)); - sqlite3RegisterGlobalFunctions(); + memset(&sqlite3BuiltinFunctions, 0, sizeof(sqlite3BuiltinFunctions)); + sqlite3RegisterBuiltinFunctions(); if( sqlite3GlobalConfig.isPCacheInit==0 ){ rc = sqlite3PcacheInitialize(); } @@ -958,7 +957,7 @@ void sqlite3CloseSavepoints(sqlite3 *db){ ** with SQLITE_ANY as the encoding. */ static void functionDestroy(sqlite3 *db, FuncDef *p){ - FuncDestructor *pDestructor = p->pDestructor; + FuncDestructor *pDestructor = p->u.pDestructor; if( pDestructor ){ pDestructor->nRef--; if( pDestructor->nRef==0 ){ @@ -1140,18 +1139,17 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ */ sqlite3ConnectionClosed(db); - for(j=0; jaFunc.a); j++){ - FuncDef *pNext, *pHash, *p; - for(p=db->aFunc.a[j]; p; p=pHash){ - pHash = p->pHash; - while( p ){ - functionDestroy(db, p); - pNext = p->pNext; - sqlite3DbFree(db, p); - p = pNext; - } - } + for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ + FuncDef *pNext, *p; + p = sqliteHashData(i); + do{ + functionDestroy(db, p); + pNext = p->pNext; + sqlite3DbFree(db, p); + p = pNext; + }while( p ); } + sqlite3HashClear(&db->aFunc); for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){ CollSeq *pColl = (CollSeq *)sqliteHashData(i); /* Invoke any destructors registered for collation sequence user data. */ @@ -1630,7 +1628,7 @@ int sqlite3CreateFunc( ** is being overridden/deleted but there are no active VMs, allow the ** operation to continue but invalidate all precompiled statements. */ - p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0); + p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 0); if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){ if( db->nVdbeActive ){ sqlite3ErrorWithMsg(db, SQLITE_BUSY, @@ -1642,7 +1640,7 @@ int sqlite3CreateFunc( } } - p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 1); + p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1); assert(p || db->mallocFailed); if( !p ){ return SQLITE_NOMEM; @@ -1655,7 +1653,7 @@ int sqlite3CreateFunc( if( pDestructor ){ pDestructor->nRef++; } - p->pDestructor = pDestructor; + p->u.pDestructor = pDestructor; p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags; testcase( p->funcFlags & SQLITE_DETERMINISTIC ); p->xSFunc = xSFunc ? xSFunc : xStep; @@ -1770,7 +1768,6 @@ int sqlite3_overload_function( const char *zName, int nArg ){ - int nName = sqlite3Strlen30(zName); int rc = SQLITE_OK; #ifdef SQLITE_ENABLE_API_ARMOR @@ -1779,7 +1776,7 @@ int sqlite3_overload_function( } #endif sqlite3_mutex_enter(db->mutex); - if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){ + if( sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)==0 ){ rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, 0, sqlite3InvalidFunction, 0, 0, 0); } @@ -2361,8 +2358,8 @@ static const int aHardLimit[] = { #if SQLITE_MAX_VDBE_OP<40 # error SQLITE_MAX_VDBE_OP must be at least 40 #endif -#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000 -# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000 +#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>127 +# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 127 #endif #if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125 # error SQLITE_MAX_ATTACHED must be between 0 and 125 @@ -2886,7 +2883,7 @@ static int openDatabase( ** is accessed. */ sqlite3Error(db, SQLITE_OK); - sqlite3RegisterBuiltinFunctions(db); + sqlite3RegisterPerConnectionBuiltinFunctions(db); /* Load automatic extensions - extensions that have been registered ** using the sqlite3_automatic_extension() API. diff --git a/src/resolve.c b/src/resolve.c index 81bb712a2e..8e290af123 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -656,9 +656,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ notValid(pParse, pNC, "functions", NC_PartIdx); zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); - pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); + pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); if( pDef==0 ){ - pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); + pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0); if( pDef==0 ){ no_such_func = 1; }else{ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f04aebe79a..37d9796829 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1109,13 +1109,15 @@ struct LookasideSlot { }; /* -** A hash table for function definitions. +** A hash table for built-in function definitions. (Application-defined +** functions use a regular table table from hash.h.) ** ** Hash each FuncDef structure into one of the FuncDefHash.a[] slots. -** Collisions are on the FuncDef.pHash chain. +** Collisions are on the FuncDef.u.pHash chain. */ +#define SQLITE_FUNC_HASH_SZ 23 struct FuncDefHash { - FuncDef *a[23]; /* Hash table for functions */ + FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */ }; #ifdef SQLITE_USER_AUTHENTICATION @@ -1243,7 +1245,7 @@ struct sqlite3 { VTable **aVTrans; /* Virtual tables with open transactions */ VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */ #endif - FuncDefHash aFunc; /* Hash table of connection functions */ + Hash aFunc; /* Hash table of connection functions */ Hash aCollSeq; /* All collating sequences */ BusyHandler busyHandler; /* Busy callback */ Db aDbStatic[2]; /* Static space for the 2 default backends */ @@ -1370,20 +1372,26 @@ struct sqlite3 { /* ** Each SQL function is defined by an instance of the following -** structure. A pointer to this structure is stored in the sqlite.aFunc -** hash table. When multiple functions have the same name, the hash table -** points to a linked list of these structures. +** structure. For global built-in functions (ex: substr(), max(), count()) +** a pointer to this structure is held in the sqlite3BuiltinFunctions object. +** For per-connection application-defined functions, a pointer to this +** structure is held in the db->aHash hash table. +** +** The u.pHash field is used by the global built-ins. The u.pDestructor +** field is used by per-connection app-def functions. */ struct FuncDef { - i16 nArg; /* Number of arguments. -1 means unlimited */ + i8 nArg; /* Number of arguments. -1 means unlimited */ u16 funcFlags; /* Some combination of SQLITE_FUNC_* */ void *pUserData; /* User data parameter */ FuncDef *pNext; /* Next function with same name */ void (*xSFunc)(sqlite3_context*,int,sqlite3_value**); /* func or agg-step */ void (*xFinalize)(sqlite3_context*); /* Agg finalizer */ char *zName; /* SQL name of the function. */ - FuncDef *pHash; /* Next with a different name but the same hash */ - FuncDestructor *pDestructor; /* Reference counted destructor function */ + union { + FuncDef *pHash; /* Next with a different name but the same hash */ + FuncDestructor *pDestructor; /* Reference counted destructor function */ + } u; }; /* @@ -1463,28 +1471,28 @@ struct FuncDestructor { */ #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ - SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, 0, 0} + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } #define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \ {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ - SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, 0, 0} + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } #define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ - SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, 0, 0} + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\ - SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, 0, 0} + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ - pArg, 0, xFunc, 0, #zName, 0, 0} + pArg, 0, xFunc, 0, #zName, } #define LIKEFUNC(zName, nArg, arg, flags) \ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \ - (void *)arg, 0, likeFunc, 0, #zName, 0, 0} + (void *)arg, 0, likeFunc, 0, #zName, {0} } #define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \ - SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName,0,0} + SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}} #define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ - SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName,0,0} + SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}} /* ** All current savepoints are stored in a linked list starting at @@ -3225,7 +3233,7 @@ int sqlite3IsIdChar(u8); /* ** Internal function prototypes */ -#define sqlite3StrICmp sqlite3_stricmp +int sqlite3StrICmp(const char*,const char*); int sqlite3Strlen30(const char*); #define sqlite3StrNICmp sqlite3_strnicmp @@ -3572,11 +3580,11 @@ void sqlite3SelectSetName(Select*,const char*); #else # define sqlite3SelectSetName(A,B) #endif -void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); -FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8); -void sqlite3RegisterBuiltinFunctions(sqlite3*); +void sqlite3InsertBuiltinFuncs(FuncDef*,int); +FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8); +void sqlite3RegisterBuiltinFunctions(void); void sqlite3RegisterDateTimeFunctions(void); -void sqlite3RegisterGlobalFunctions(void); +void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); int sqlite3SafetyCheckOk(sqlite3*); int sqlite3SafetyCheckSickOrOk(sqlite3*); void sqlite3ChangeCookie(Parse*, int); @@ -3737,7 +3745,7 @@ extern const unsigned char sqlite3UpperToLower[]; extern const unsigned char sqlite3CtypeMap[]; extern const Token sqlite3IntTokens[]; extern SQLITE_WSD struct Sqlite3Config sqlite3Config; -extern SQLITE_WSD FuncDefHash sqlite3GlobalFunctions; +extern FuncDefHash sqlite3BuiltinFunctions; #ifndef SQLITE_OMIT_WSD extern int sqlite3PendingByte; #endif diff --git a/src/util.c b/src/util.c index 37b585b2ea..928d249215 100644 --- a/src/util.c +++ b/src/util.c @@ -256,16 +256,25 @@ void sqlite3TokenInit(Token *p, char *z){ ** independence" that SQLite uses internally when comparing identifiers. */ int sqlite3_stricmp(const char *zLeft, const char *zRight){ - register unsigned char *a, *b; if( zLeft==0 ){ return zRight ? -1 : 0; }else if( zRight==0 ){ return 1; } + return sqlite3StrICmp(zLeft, zRight); +} +int sqlite3StrICmp(const char *zLeft, const char *zRight){ + unsigned char *a, *b; + int c; a = (unsigned char *)zLeft; b = (unsigned char *)zRight; - while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } - return UpperToLower[*a] - UpperToLower[*b]; + for(;;){ + c = (int)UpperToLower[*a] - (int)UpperToLower[*b]; + if( c || *a==0 ) break; + a++; + b++; + } + return c; } int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ register unsigned char *a, *b; diff --git a/src/vdbemem.c b/src/vdbemem.c index 6fb7cebbcc..7ac85c9a76 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -1186,7 +1186,6 @@ static int valueFromFunction( FuncDef *pFunc = 0; /* Function definition */ sqlite3_value *pVal = 0; /* New value */ int rc = SQLITE_OK; /* Return code */ - int nName; /* Size of function name in bytes */ ExprList *pList = 0; /* Function arguments */ int i; /* Iterator variable */ @@ -1194,8 +1193,7 @@ static int valueFromFunction( assert( (p->flags & EP_TokenOnly)==0 ); pList = p->x.pList; if( pList ) nVal = pList->nExpr; - nName = sqlite3Strlen30(p->u.zToken); - pFunc = sqlite3FindFunction(db, p->u.zToken, nName, nVal, enc, 0); + pFunc = sqlite3FindFunction(db, p->u.zToken, nVal, enc, 0); assert( pFunc ); if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) @@ -1457,15 +1455,10 @@ static void recordFunc( ** Register built-in functions used to help read ANALYZE data. */ void sqlite3AnalyzeFunctions(void){ - static SQLITE_WSD FuncDef aAnalyzeTableFuncs[] = { + static FuncDef aAnalyzeTableFuncs[] = { FUNCTION(sqlite_record, 1, 0, 0, recordFunc), }; - int i; - FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); - FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAnalyzeTableFuncs); - for(i=0; i Date: Mon, 15 Feb 2016 15:06:47 +0000 Subject: [PATCH 286/570] Make sure the codec is invoked when overwriting existing frames of the WAL file. Yikes! FossilOrigin-Name: f694e60a79024967a3f4574e3928f0b28589d381 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/wal.c | 8 +++++++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 18d443650d..f13bbfc3ec 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Provide\sSqlite3_SafeInit()\sand\sSqlite3_SafeUnload()\sentry\spoints\son\sthe\sTCL\ninterface,\sbut\shave\sthe\salways\sreturn\sTCL_ERROR,\sbecause\sthe\snon-standard\s\nTCL\sbuilds\son\sMacs\srequire\sthis. -D 2016-02-13T18:54:10.051 +C Make\ssure\sthe\scodec\sis\sinvoked\swhen\soverwriting\sexisting\sframes\sof\sthe\nWAL\sfile.\s\sYikes! +D 2016-02-15T15:06:47.557 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -424,7 +424,7 @@ F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 F src/vtab.c bef51b4f693d82b4b0184457faa8625654534091 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c d21b99fd1458159d0b1ecdccc8ee6ada4fdc4c54 +F src/wal.c 1dd3f1aeed5765be62f27d7d2e44d46a68d891ab F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c 984084584c10c41e46c89ac027a5cca991bc37e6 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a049fbbde5da2e43d41aa8c2b41f9eb21507ac76 -R 0ed7109e4c77d1cb323166614bc90c67 +P 37ec3015ec95035d31e3672f520908a0d36c9d67 +R f2e9debe8cf42a0179962a66a44645cf U drh -Z 0875f4eabfb763252145d2214f48fc91 +Z 12ae21a200342c13300e7567f86ed2d7 diff --git a/manifest.uuid b/manifest.uuid index 5b62ca1a2d..ef76e7a334 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -37ec3015ec95035d31e3672f520908a0d36c9d67 \ No newline at end of file +f694e60a79024967a3f4574e3928f0b28589d381 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 7cf2cabffb..d7a6b701e6 100644 --- a/src/wal.c +++ b/src/wal.c @@ -3062,10 +3062,16 @@ int sqlite3WalFrames( assert( rc==SQLITE_OK || iWrite==0 ); if( iWrite>=iFirst ){ i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE; + void *pData; if( pWal->iReCksum==0 || iWriteiReCksum ){ pWal->iReCksum = iWrite; } - rc = sqlite3OsWrite(pWal->pWalFd, p->pData, szPage, iOff); +#if defined(SQLITE_HAS_CODEC) + if( (pData = sqlite3PagerCodec(p))==0 ) return SQLITE_NOMEM; +#else + pData = p->pData; +#endif + rc = sqlite3OsWrite(pWal->pWalFd, pData, szPage, iOff); if( rc ) return rc; p->flags &= ~PGHDR_WAL_APPEND; continue; From 195c8d5eba26853b65f86ea6c9947f24fea70389 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 15 Feb 2016 17:29:24 +0000 Subject: [PATCH 287/570] Version 3.11.0 FossilOrigin-Name: 3d862f207e3adc00f78066799ac5a8c282430a5f --- manifest | 11 +++++++---- manifest.uuid | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/manifest b/manifest index f13bbfc3ec..a33ec564a2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthe\scodec\sis\sinvoked\swhen\soverwriting\sexisting\sframes\sof\sthe\nWAL\sfile.\s\sYikes! -D 2016-02-15T15:06:47.557 +C Version\s3.11.0 +D 2016-02-15T17:29:24.141 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -1427,7 +1427,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 37ec3015ec95035d31e3672f520908a0d36c9d67 +P f694e60a79024967a3f4574e3928f0b28589d381 R f2e9debe8cf42a0179962a66a44645cf +T +bgcolor * #d0c0ff +T +sym-release * +T +sym-version-3.11.0 * U drh -Z 12ae21a200342c13300e7567f86ed2d7 +Z e719a8e2c047e401006dde85de2084bf diff --git a/manifest.uuid b/manifest.uuid index ef76e7a334..474c1210cb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f694e60a79024967a3f4574e3928f0b28589d381 \ No newline at end of file +3d862f207e3adc00f78066799ac5a8c282430a5f \ No newline at end of file From e683b89880cdbc3db77c3af5220b3bb378aff50b Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 15 Feb 2016 18:47:26 +0000 Subject: [PATCH 288/570] Fix harmless compiler warnings previously seen in 64-bit MSVC builds. FossilOrigin-Name: 7026246300392a83cc23817dbc54c2c66bf1f2b3 --- manifest | 15 +++++++-------- manifest.uuid | 2 +- src/test_fs.c | 4 ++-- test/fuzzcheck.c | 7 ++++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index f81eb39f81..fb28a48001 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_NOMEM_BKPT\smacro\sto\senhance\sthe\sability\sto\sdebug\sOOM\serrors.\nOnly\seffective\swith\scompiling\swith\sSQLITE_DEBUG. -D 2016-02-15T18:15:15.015 +C Fix\sharmless\scompiler\swarnings\spreviously\sseen\sin\s64-bit\sMSVC\sbuilds. +D 2016-02-15T18:47:26.307 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -375,7 +375,7 @@ F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f F src/test_config.c 7985332c806d1cece793475c75a6abcccde9d331 F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc -F src/test_fs.c a61f54247fdb843761d709879c3bcd1989b2050c +F src/test_fs.c f10f840ca4f8c72e4837908bd8347ac4bcab074b F src/test_func.c 37453d346cfcf118774efd5bf6187f7e6a7e3254 F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32 @@ -764,7 +764,7 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test b47377143f0c80f91ed29d722861077ff34415d5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26 -F test/fuzzcheck.c 3309d793165ca61a9996271cb799694839348f9a +F test/fuzzcheck.c 3b1707385ee81ae124a0f35c9df6d6d20550917a F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973 F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba @@ -1427,8 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c3b38efd50c3c07b6dee5dea4c1f95b37d1c0994 e9753d9a2c1269050f886e6cb9bc9cba0a8df6ce -R b0fc853e4a1dd4125cb33093c5176aa5 -T +closed e9753d9a2c1269050f886e6cb9bc9cba0a8df6ce +P 9b3454762d142113f5923d754ca6bd2edefbd362 +R b07e46417f5dffc4daced5861e5000cb U drh -Z 3f49c178a99d041b6eb9f7c9f8c2a0a3 +Z df21a5d736621ec1a72e81dad263dffb diff --git a/manifest.uuid b/manifest.uuid index 60745fe15b..18b1a303eb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9b3454762d142113f5923d754ca6bd2edefbd362 \ No newline at end of file +7026246300392a83cc23817dbc54c2c66bf1f2b3 \ No newline at end of file diff --git a/src/test_fs.c b/src/test_fs.c index 45db0b53b8..32026d0f38 100644 --- a/src/test_fs.c +++ b/src/test_fs.c @@ -496,9 +496,9 @@ static int fstreeFilter( #if SQLITE_OS_WIN zRoot = sqlite3_mprintf("%s%c", getenv("SystemDrive"), '/'); - nRoot = strlen(zRoot); + nRoot = sqlite3Strlen30(zRoot); zPrefix = sqlite3_mprintf("%s", getenv("SystemDrive")); - nPrefix = strlen(zPrefix); + nPrefix = sqlite3Strlen30(zPrefix); #else zRoot = "/"; nRoot = 1; diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c index 03776f1e70..cbe13eafe1 100644 --- a/test/fuzzcheck.c +++ b/test/fuzzcheck.c @@ -255,8 +255,9 @@ static VFile *createVFile(const char *zName, int sz, unsigned char *pData){ if( i>=MX_FILE ) return 0; pNew = &g.aFile[i]; if( zName ){ - pNew->zFilename = safe_realloc(0, strlen(zName)+1); - memcpy(pNew->zFilename, zName, strlen(zName)+1); + int nName = (int)strlen(zName)+1; + pNew->zFilename = safe_realloc(0, nName); + memcpy(pNew->zFilename, zName, nName); }else{ pNew->zFilename = 0; } @@ -1055,7 +1056,7 @@ int main(int argc, char **argv){ /* Print the description, if there is one */ if( !quietFlag ){ zDbName = azSrcDb[iSrcDb]; - i = strlen(zDbName) - 1; + i = (int)strlen(zDbName) - 1; while( i>0 && zDbName[i-1]!='/' && zDbName[i-1]!='\\' ){ i--; } zDbName += i; sqlite3_prepare_v2(db, "SELECT msg FROM readme", -1, &pStmt, 0); From 3719d10d11ccd03be7cba95a0947b2d1fdf4fab6 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 15 Feb 2016 18:58:37 +0000 Subject: [PATCH 289/570] In the tool/warning.sh script, disable Android-specific compiler warning tests when not running on Linux. FossilOrigin-Name: 153f01a821e9844d0a2e418eb83c60f6c7695c8d --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/warnings.sh | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index fb28a48001..aea14572f9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarnings\spreviously\sseen\sin\s64-bit\sMSVC\sbuilds. -D 2016-02-15T18:47:26.307 +C In\sthe\stool/warning.sh\sscript,\sdisable\sAndroid-specific\scompiler\swarning\stests\nwhen\snot\srunning\son\sLinux. +D 2016-02-15T18:58:37.285 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -1425,9 +1425,9 @@ F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003 F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 -F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f +F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9b3454762d142113f5923d754ca6bd2edefbd362 -R b07e46417f5dffc4daced5861e5000cb +P 7026246300392a83cc23817dbc54c2c66bf1f2b3 +R fc9aa743a12cf9b6bf1ff5f64fb6b62a U drh -Z df21a5d736621ec1a72e81dad263dffb +Z e0842079d26b7ffa8e27ebf0376ee458 diff --git a/manifest.uuid b/manifest.uuid index 18b1a303eb..186003bd91 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7026246300392a83cc23817dbc54c2c66bf1f2b3 \ No newline at end of file +153f01a821e9844d0a2e418eb83c60f6c7695c8d \ No newline at end of file diff --git a/tool/warnings.sh b/tool/warnings.sh index 6c7cb3a8f8..cee639dc45 100644 --- a/tool/warnings.sh +++ b/tool/warnings.sh @@ -10,6 +10,7 @@ gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \ -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \ -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \ sqlite3.c +if test x`uname` = 'xLinux'; then echo '********** Android configuration ******************************' gcc -c \ -DHAVE_USLEEP=1 \ @@ -32,6 +33,7 @@ gcc -c \ -DUSE_PREAD64 \ -Wshadow -Wall -Wextra \ -Os sqlite3.c shell.c +fi echo '********** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******' gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \ -ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \ From 4b7b1c9c120257d14a6dde497b87cb6aaaec26c1 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 15 Feb 2016 19:38:17 +0000 Subject: [PATCH 290/570] Add working -q and --help options to testfixture. FossilOrigin-Name: 404494e52b6385671ccde1c83b7b868986645536 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/tester.tcl | 22 ++++++++++++++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index aea14572f9..4dbb251d56 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\stool/warning.sh\sscript,\sdisable\sAndroid-specific\scompiler\swarning\stests\nwhen\snot\srunning\son\sLinux. -D 2016-02-15T18:58:37.285 +C Add\sworking\s-q\sand\s--help\soptions\sto\stestfixture. +D 2016-02-15T19:38:17.026 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -1078,7 +1078,7 @@ F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054 F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl 462376b478c1429030911b4cb7c8c517ef1fbd9b +F test/tester.tcl 750365ff97047ded5f2d6e28df82a998f7c66ae0 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7026246300392a83cc23817dbc54c2c66bf1f2b3 -R fc9aa743a12cf9b6bf1ff5f64fb6b62a +P 153f01a821e9844d0a2e418eb83c60f6c7695c8d +R b996ecd577900723d8e8c822f6ba0fa2 U drh -Z e0842079d26b7ffa8e27ebf0376ee458 +Z 1c21e4bc8961adde657fcb0992c7a61d diff --git a/manifest.uuid b/manifest.uuid index 186003bd91..33f1beae3e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -153f01a821e9844d0a2e418eb83c60f6c7695c8d \ No newline at end of file +404494e52b6385671ccde1c83b7b868986645536 \ No newline at end of file diff --git a/test/tester.tcl b/test/tester.tcl index dc532c97fa..231cef5333 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -374,6 +374,21 @@ proc do_not_use_codec {} { reset_db } +# Print a HELP message and exit +# +proc print_help_and_quit {} { + puts {Options: + --pause Wait for user input before continuing + --soft-heap-limit=N Set the soft-heap-limit to N + --maxerror=N Quit after N errors + --verbose=(0|1) Control the amount of output. Default '1' + --output=FILE set --verbose=2 and output to FILE. Implies -q + -q Shorthand for --verbose=0 + --help This message +} + exit 1 +} + # The following block only runs the first time this file is sourced. It # does not run in slave interpreters (since the ::cmdlinearg array is # populated before the test script is run in slave interpreters). @@ -483,6 +498,13 @@ if {[info exists cmdlinearg]==0} { error "option --verbose= must be set to a boolean or to \"file\"" } } + {.*help.*} { + print_help_and_quit + } + {^-q$} { + set cmdlinearg(output) test-out.txt + set cmdlinearg(verbose) 2 + } default { lappend leftover $a From 8eb3790a8d228d363836c1fcbe790325c747436f Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 15 Feb 2016 20:41:56 +0000 Subject: [PATCH 291/570] Improved entropy gathering for the implementation of winRandomness(). FossilOrigin-Name: fea3705e7750d276a8c8300b7a82dfae2d5979c0 --- manifest | 12 ++++----- manifest.uuid | 2 +- src/os_win.c | 71 +++++++++++++++++++++++++++++++-------------------- 3 files changed, 51 insertions(+), 34 deletions(-) diff --git a/manifest b/manifest index 4dbb251d56..223eb2086c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sworking\s-q\sand\s--help\soptions\sto\stestfixture. -D 2016-02-15T19:38:17.026 +C Improved\sentropy\sgathering\sfor\sthe\simplementation\sof\swinRandomness(). +D 2016-02-15T20:41:56.528 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -333,7 +333,7 @@ F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 3a6f20736dfb8a0949cdd66553fdf59f6604be35 -F src/os_win.c 6cce4c3aab5fb5cc6fabf999d785cfccb66ff9d4 +F src/os_win.c ae1f287a5a47e6cc08c0ac8dd0cfa2c67358f73a F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 6812f3803951774b56abded396171e1c12b0b003 F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 153f01a821e9844d0a2e418eb83c60f6c7695c8d -R b996ecd577900723d8e8c822f6ba0fa2 +P 404494e52b6385671ccde1c83b7b868986645536 +R 65a12199f7ba9145cf2ed73477d5bc07 U drh -Z 1c21e4bc8961adde657fcb0992c7a61d +Z f5568a99b7bf2a6087045b1c5b2d107b diff --git a/manifest.uuid b/manifest.uuid index 33f1beae3e..85665bc05f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -404494e52b6385671ccde1c83b7b868986645536 \ No newline at end of file +fea3705e7750d276a8c8300b7a82dfae2d5979c0 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index caa6dea5db..9824ffb1c7 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -5390,65 +5390,82 @@ static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ #define winDlClose 0 #endif +/* State information for the randomness gatherer. */ +typedef struct EntropyGatherer EntropyGatherer; +struct EntropyGatherer { + unsigned char *a; /* Gather entropy into this buffer */ + int na; /* Size of a[] in bytes */ + int i; /* XOR next input into a[i] */ + int nXor; /* Number of XOR operations done */ +}; + +#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS) +/* Mix sz bytes of entropy into p. */ +static void xorMemory(EntropyGatherer *p, unsigned char *x, int sz){ + int j, k; + for(j=0, k=p->i; ja[k++] ^= x[j]; + if( k>=p->na ) k = 0; + } + p->i = k; + p->nXor += sz; +} +#endif /* ** Write up to nBuf bytes of randomness into zBuf. */ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ - int n = 0; - UNUSED_PARAMETER(pVfs); #if defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) - n = nBuf; + UNUSED_PARAMETER(pVfs); memset(zBuf, 0, nBuf); + return nBuf; #else - if( sizeof(SYSTEMTIME)<=nBuf-n ){ + EntropyGatherer e; + UNUSED_PARAMETER(pVfs); + memset(zBuf, 0, nBuf); + e.a = (unsigned char*)zBuf; + e.na = nBuf; + e.nXor = 0; + e.i = 0; + { SYSTEMTIME x; osGetSystemTime(&x); - memcpy(&zBuf[n], &x, sizeof(x)); - n += sizeof(x); + xorMemory(&e, (unsigned char*)&x, sizeof(x)); } - if( sizeof(DWORD)<=nBuf-n ){ + { DWORD pid = osGetCurrentProcessId(); - memcpy(&zBuf[n], &pid, sizeof(pid)); - n += sizeof(pid); + xorMemory(&e, (unsigned char*)&pid, sizeof(pid)); } #if SQLITE_OS_WINRT - if( sizeof(ULONGLONG)<=nBuf-n ){ + { ULONGLONG cnt = osGetTickCount64(); - memcpy(&zBuf[n], &cnt, sizeof(cnt)); - n += sizeof(cnt); + xorMemory(&e, (unsigned char*)&cnt, sizeof(cnt)); } #else - if( sizeof(DWORD)<=nBuf-n ){ + { DWORD cnt = osGetTickCount(); - memcpy(&zBuf[n], &cnt, sizeof(cnt)); - n += sizeof(cnt); + xorMemory(&e, (unsigned char*)&cnt, sizeof(cnt)); } #endif - if( sizeof(LARGE_INTEGER)<=nBuf-n ){ + { LARGE_INTEGER i; osQueryPerformanceCounter(&i); - memcpy(&zBuf[n], &i, sizeof(i)); - n += sizeof(i); + xorMemory(&e, (unsigned char*)&i, sizeof(i)); } #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID - if( sizeof(UUID)<=nBuf-n ){ + { UUID id; memset(&id, 0, sizeof(UUID)); osUuidCreate(&id); - memcpy(&zBuf[n], &id, sizeof(UUID)); - n += sizeof(UUID); - } - if( sizeof(UUID)<=nBuf-n ){ - UUID id; + xorMemory(&e, (unsigned char*)&id, sizeof(UUID)); memset(&id, 0, sizeof(UUID)); osUuidCreateSequential(&id); - memcpy(&zBuf[n], &id, sizeof(UUID)); - n += sizeof(UUID); + xorMemory(&e, (unsigned char*)&id, sizeof(UUID)); } #endif + return e.nXor>nBuf ? nBuf : e.nXor; #endif /* defined(SQLITE_TEST) || defined(SQLITE_ZERO_PRNG_SEED) */ - return n; } From 51d5ed97f5a09631eb42d1d0be6ba329437e5cb5 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 15 Feb 2016 21:31:51 +0000 Subject: [PATCH 292/570] On windows systems when rand_s() is available, use it to obtain additional seed material in winRandomness(). FossilOrigin-Name: 139081bef9f63c3ebbe9e992408597b1349bdf37 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/msvc.h | 1 + src/os_win.c | 3 +++ 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 223eb2086c..3f4db7acb8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sentropy\sgathering\sfor\sthe\simplementation\sof\swinRandomness(). -D 2016-02-15T20:41:56.528 +C On\swindows\ssystems\swhen\srand_s()\sis\savailable,\suse\sit\sto\sobtain\sadditional\nseed\smaterial\sin\swinRandomness(). +D 2016-02-15T21:31:51.875 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -321,7 +321,7 @@ F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 F src/memjournal.c 349a04fb803db40532cde0993e39758f1acaecce -F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 +F src/msvc.h 32960d4f059c281182accbb3a5e5215d969fc73a F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4 @@ -333,7 +333,7 @@ F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 3a6f20736dfb8a0949cdd66553fdf59f6604be35 -F src/os_win.c ae1f287a5a47e6cc08c0ac8dd0cfa2c67358f73a +F src/os_win.c 382fd1b58ddfe649993110ebdfb7f31d3cdcf7f6 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 6812f3803951774b56abded396171e1c12b0b003 F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 404494e52b6385671ccde1c83b7b868986645536 -R 65a12199f7ba9145cf2ed73477d5bc07 +P fea3705e7750d276a8c8300b7a82dfae2d5979c0 +R 3ea964cea3f85da9036cd633975ae669 U drh -Z f5568a99b7bf2a6087045b1c5b2d107b +Z 9da59384e387e9220326258d227dc94d diff --git a/manifest.uuid b/manifest.uuid index 85665bc05f..cf40acb127 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fea3705e7750d276a8c8300b7a82dfae2d5979c0 \ No newline at end of file +139081bef9f63c3ebbe9e992408597b1349bdf37 \ No newline at end of file diff --git a/src/msvc.h b/src/msvc.h index 01ebf2b46f..e8a1696131 100644 --- a/src/msvc.h +++ b/src/msvc.h @@ -16,6 +16,7 @@ #define _MSVC_H_ #if defined(_MSC_VER) +#define _CRT_RAND_S /* Make rand_s() available on windows systems */ #pragma warning(disable : 4054) #pragma warning(disable : 4055) #pragma warning(disable : 4100) diff --git a/src/os_win.c b/src/os_win.c index 9824ffb1c7..d4b72c9c31 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -5424,6 +5424,9 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ EntropyGatherer e; UNUSED_PARAMETER(pVfs); memset(zBuf, 0, nBuf); +#ifdef _MSC_VER + rand_s((int*)zBuf); /* rand_s() is not available with MinGW */ +#endif e.a = (unsigned char*)zBuf; e.na = nBuf; e.nXor = 0; From bfc9b3f45cd576f765e536d48984e44b2fea8368 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 15 Feb 2016 22:01:24 +0000 Subject: [PATCH 293/570] Revise compiler checks for the rand_s() function. FossilOrigin-Name: 287f508dd6abc1b9ffdbec6a685ebe79eeac992b --- manifest | 18 ++--- manifest.uuid | 2 +- src/msvc.h | 1 - src/os_win.c | 4 +- src/sqliteInt.h | 176 +++++++++++++++++++++++++----------------------- 5 files changed, 104 insertions(+), 97 deletions(-) diff --git a/manifest b/manifest index 3f4db7acb8..805db81009 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C On\swindows\ssystems\swhen\srand_s()\sis\savailable,\suse\sit\sto\sobtain\sadditional\nseed\smaterial\sin\swinRandomness(). -D 2016-02-15T21:31:51.875 +C Revise\scompiler\schecks\sfor\sthe\srand_s()\sfunction. +D 2016-02-15T22:01:24.377 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -321,7 +321,7 @@ F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 F src/memjournal.c 349a04fb803db40532cde0993e39758f1acaecce -F src/msvc.h 32960d4f059c281182accbb3a5e5215d969fc73a +F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4 @@ -333,7 +333,7 @@ F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 3a6f20736dfb8a0949cdd66553fdf59f6604be35 -F src/os_win.c 382fd1b58ddfe649993110ebdfb7f31d3cdcf7f6 +F src/os_win.c d085a0b043abe0c9349c7e8663730cc290041b56 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 6812f3803951774b56abded396171e1c12b0b003 F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 @@ -353,7 +353,7 @@ F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe F src/sqlite.h.in f80c6ebd85588fc514bfedf3ecb00cec269cb410 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h e2ed86c6f5c3e503bbd07328737342afedfe48fc +F src/sqliteInt.h 47f61c35d587d38cbcfc8ba852ff441054d697d3 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P fea3705e7750d276a8c8300b7a82dfae2d5979c0 -R 3ea964cea3f85da9036cd633975ae669 -U drh -Z 9da59384e387e9220326258d227dc94d +P 139081bef9f63c3ebbe9e992408597b1349bdf37 +R 882b4878d4fb3d5db66502eaecb957f2 +U mistachkin +Z 2021541af14002b61ba4d5fc0e59c306 diff --git a/manifest.uuid b/manifest.uuid index cf40acb127..6ac4d5b45c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -139081bef9f63c3ebbe9e992408597b1349bdf37 \ No newline at end of file +287f508dd6abc1b9ffdbec6a685ebe79eeac992b \ No newline at end of file diff --git a/src/msvc.h b/src/msvc.h index e8a1696131..01ebf2b46f 100644 --- a/src/msvc.h +++ b/src/msvc.h @@ -16,7 +16,6 @@ #define _MSVC_H_ #if defined(_MSC_VER) -#define _CRT_RAND_S /* Make rand_s() available on windows systems */ #pragma warning(disable : 4054) #pragma warning(disable : 4055) #pragma warning(disable : 4100) diff --git a/src/os_win.c b/src/os_win.c index d4b72c9c31..237c4fb0b2 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -5424,8 +5424,8 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ EntropyGatherer e; UNUSED_PARAMETER(pVfs); memset(zBuf, 0, nBuf); -#ifdef _MSC_VER - rand_s((int*)zBuf); /* rand_s() is not available with MinGW */ +#if defined(_MSC_VER) && _MSC_VER>=1400 + rand_s((int*)zBuf); /* rand_s() is not available with MinGW */ #endif e.a = (unsigned char*)zBuf; e.na = nBuf; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a45fb02291..85d4158a46 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -15,6 +15,14 @@ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ +/* +** Make sure that rand_s() is available on Windows systems with MSVC 2005 +** or higher. +*/ +#if defined(_MSC_VER) && _MSC_VER>=1400 +# define _CRT_RAND_S +#endif + /* ** Include the header file used to customize the compiler options for MSVC. ** This should be done first so that it can successfully prevent spurious @@ -149,7 +157,7 @@ ** to the next, so we have developed the following set of #if statements ** to generate appropriate macros for a wide range of compilers. ** -** The correct "ANSI" way to do this is to use the intptr_t type. +** The correct "ANSI" way to do this is to use the intptr_t type. ** Unfortunately, that typedef is not available on all compilers, or ** if it is available, it requires an #include of specific headers ** that vary from one machine to the next. @@ -316,7 +324,7 @@ ** is set. Thus NDEBUG becomes an opt-in rather than an opt-out ** feature. */ -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) # define NDEBUG 1 #endif #if defined(NDEBUG) && defined(SQLITE_DEBUG) @@ -331,7 +339,7 @@ #endif /* -** The testcase() macro is used to aid in coverage testing. When +** The testcase() macro is used to aid in coverage testing. When ** doing coverage testing, the condition inside the argument to ** testcase() must be evaluated both true and false in order to ** get full branch coverage. The testcase() macro is inserted @@ -377,7 +385,7 @@ #endif /* -** The ALWAYS and NEVER macros surround boolean expressions which +** The ALWAYS and NEVER macros surround boolean expressions which ** are intended to always be true or false, respectively. Such ** expressions could be omitted from the code completely. But they ** are included in a few cases in order to enhance the resilience @@ -490,7 +498,7 @@ /* ** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0 -** afterward. Having this macro allows us to cause the C compiler +** afterward. Having this macro allows us to cause the C compiler ** to omit code used by TEMP tables without messy #ifndef statements. */ #ifdef SQLITE_OMIT_TEMPDB @@ -529,7 +537,7 @@ /* ** If no value has been provided for SQLITE_MAX_WORKER_THREADS, or if -** SQLITE_TEMP_STORE is set to 3 (never use temporary files), set it +** SQLITE_TEMP_STORE is set to 3 (never use temporary files), set it ** to zero. */ #if SQLITE_TEMP_STORE==3 || SQLITE_THREADSAFE==0 @@ -677,7 +685,7 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */ ** 4 -> 20 1000 -> 99 1048576 -> 200 ** 10 -> 33 1024 -> 100 4294967296 -> 320 ** -** The LogEst can be negative to indicate fractional values. +** The LogEst can be negative to indicate fractional values. ** Examples: ** ** 0.5 -> -10 0.1 -> -33 0.0625 -> -40 @@ -743,7 +751,7 @@ typedef INT16_TYPE LogEst; #define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) #define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) -/* +/* ** Round up a number to the next larger multiple of 8. This is used ** to force 8-byte alignment on 64-bit architectures. */ @@ -837,7 +845,7 @@ typedef INT16_TYPE LogEst; /* ** An instance of the following structure is used to store the busy-handler -** callback for a given sqlite handle. +** callback for a given sqlite handle. ** ** The sqlite.busyHandler member of the sqlite struct contains the busy ** callback for the database handle. Each pager opened via the sqlite @@ -882,9 +890,9 @@ struct BusyHandler { /* ** The following value as a destructor means to use sqlite3DbFree(). -** The sqlite3DbFree() routine requires two parameters instead of the -** one parameter that destructors normally want. So we have to introduce -** this magic value that the code knows to handle differently. Any +** The sqlite3DbFree() routine requires two parameters instead of the +** one parameter that destructors normally want. So we have to introduce +** this magic value that the code knows to handle differently. Any ** pointer will work here as long as it is distinct from SQLITE_STATIC ** and SQLITE_TRANSIENT. */ @@ -911,16 +919,16 @@ struct BusyHandler { int sqlite3_wsd_init(int N, int J); void *sqlite3_wsd_find(void *K, int L); #else - #define SQLITE_WSD + #define SQLITE_WSD #define GLOBAL(t,v) v #define sqlite3GlobalConfig sqlite3Config #endif /* ** The following macros are used to suppress compiler warnings and to -** make it clear to human readers when a function parameter is deliberately +** make it clear to human readers when a function parameter is deliberately ** left unused within the body of a function. This usually happens when -** a function is called via a function pointer. For example the +** a function is called via a function pointer. For example the ** implementation of an SQL aggregate step callback may not use the ** parameter indicating the number of arguments passed to the aggregate, ** if it knows that this is enforced elsewhere. @@ -986,7 +994,7 @@ typedef struct WhereInfo WhereInfo; typedef struct With With; /* -** Defer sourcing vdbe.h and btree.h until after the "u8" and +** Defer sourcing vdbe.h and btree.h until after the "u8" and ** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque ** pointer types (i.e. FuncDef) defined above. */ @@ -1020,7 +1028,7 @@ struct Db { ** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing. ** In shared cache mode, a single Schema object can be shared by multiple ** Btrees that refer to the same underlying BtShared object. -** +** ** Schema objects are automatically deallocated when the last Btree that ** references them is destroyed. The TEMP Schema is manually freed by ** sqlite3_close(). @@ -1045,7 +1053,7 @@ struct Schema { }; /* -** These macros can be used to test, set, or clear bits in the +** These macros can be used to test, set, or clear bits in the ** Db.pSchema->flags field. */ #define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))==(P)) @@ -1210,9 +1218,9 @@ struct sqlite3 { void *pTraceArg; /* Argument to the trace function */ void (*xProfile)(void*,const char*,u64); /* Profiling function */ void *pProfileArg; /* Argument to profile function */ - void *pCommitArg; /* Argument to xCommitCallback() */ + void *pCommitArg; /* Argument to xCommitCallback() */ int (*xCommitCallback)(void*); /* Invoked at every commit. */ - void *pRollbackArg; /* Argument to xRollbackCallback() */ + void *pRollbackArg; /* Argument to xRollbackCallback() */ void (*xRollbackCallback)(void*); /* Invoked at every commit. */ void *pUpdateArg; void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); @@ -1257,8 +1265,8 @@ struct sqlite3 { i64 nDeferredImmCons; /* Net deferred immediate constraints */ int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY - /* The following variables are all protected by the STATIC_MASTER - ** mutex, not by sqlite3.mutex. They are used by code in notify.c. + /* The following variables are all protected by the STATIC_MASTER + ** mutex, not by sqlite3.mutex. They are used by code in notify.c. ** ** When X.pUnlockConnection==Y, that means that X is waiting for Y to ** unlock so that it can proceed. @@ -1398,7 +1406,7 @@ struct FuncDef { ** This structure encapsulates a user-function destructor callback (as ** configured using create_function_v2()) and a reference counter. When ** create_function_v2() is called to create a function with a destructor, -** a single object of this type is allocated. FuncDestructor.nRef is set to +** a single object of this type is allocated. FuncDestructor.nRef is set to ** the number of FuncDef objects created (either 1 or 3, depending on whether ** or not the specified encoding is SQLITE_ANY). The FuncDef.pDestructor ** member of each of the new FuncDef objects is set to point to the allocated @@ -1440,10 +1448,10 @@ struct FuncDestructor { ** used to create the initializers for the FuncDef structures. ** ** FUNCTION(zName, nArg, iArg, bNC, xFunc) -** Used to create a scalar function definition of a function zName +** Used to create a scalar function definition of a function zName ** implemented by C function xFunc that accepts nArg arguments. The ** value passed as iArg is cast to a (void*) and made available -** as the user-data (sqlite3_user_data()) for the function. If +** as the user-data (sqlite3_user_data()) for the function. If ** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set. ** ** VFUNCTION(zName, nArg, iArg, bNC, xFunc) @@ -1462,8 +1470,8 @@ struct FuncDestructor { ** FUNCTION(). ** ** LIKEFUNC(zName, nArg, pArg, flags) -** Used to create a scalar function definition of a function zName -** that accepts nArg arguments and is implemented by a call to C +** Used to create a scalar function definition of a function zName +** that accepts nArg arguments and is implemented by a call to C ** function likeFunc. Argument pArg is cast to a (void *) and made ** available as the function user-data (sqlite3_user_data()). The ** FuncDef.flags variable is set to the value passed as the flags @@ -1579,7 +1587,7 @@ struct CollSeq { ** ** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and ** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve -** the speed a little by numbering the values consecutively. +** the speed a little by numbering the values consecutively. ** ** But rather than start with 0 or 1, we begin with 'A'. That way, ** when multiple affinity types are concatenated into a string and @@ -1598,7 +1606,7 @@ struct CollSeq { /* ** The SQLITE_AFF_MASK values masks off the significant bits of an -** affinity value. +** affinity value. */ #define SQLITE_AFF_MASK 0x47 @@ -1618,20 +1626,20 @@ struct CollSeq { /* ** An object of this type is created for each virtual table present in -** the database schema. +** the database schema. ** ** If the database schema is shared, then there is one instance of this ** structure for each database connection (sqlite3*) that uses the shared ** schema. This is because each database connection requires its own unique -** instance of the sqlite3_vtab* handle used to access the virtual table -** implementation. sqlite3_vtab* handles can not be shared between -** database connections, even when the rest of the in-memory database +** instance of the sqlite3_vtab* handle used to access the virtual table +** implementation. sqlite3_vtab* handles can not be shared between +** database connections, even when the rest of the in-memory database ** schema is shared, as the implementation often stores the database ** connection handle passed to it via the xConnect() or xCreate() method ** during initialization internally. This database connection handle may -** then be used by the virtual table implementation to access real tables -** within the database. So that they appear as part of the callers -** transaction, these accesses need to be made via the same database +** then be used by the virtual table implementation to access real tables +** within the database. So that they appear as part of the callers +** transaction, these accesses need to be made via the same database ** connection as that used to execute SQL operations on the virtual table. ** ** All VTable objects that correspond to a single table in a shared @@ -1643,19 +1651,19 @@ struct CollSeq { ** sqlite3_vtab* handle in the compiled query. ** ** When an in-memory Table object is deleted (for example when the -** schema is being reloaded for some reason), the VTable objects are not -** deleted and the sqlite3_vtab* handles are not xDisconnect()ed +** schema is being reloaded for some reason), the VTable objects are not +** deleted and the sqlite3_vtab* handles are not xDisconnect()ed ** immediately. Instead, they are moved from the Table.pVTable list to ** another linked list headed by the sqlite3.pDisconnect member of the -** corresponding sqlite3 structure. They are then deleted/xDisconnected +** corresponding sqlite3 structure. They are then deleted/xDisconnected ** next time a statement is prepared using said sqlite3*. This is done ** to avoid deadlock issues involving multiple sqlite3.mutex mutexes. ** Refer to comments above function sqlite3VtabUnlockList() for an ** explanation as to why it is safe to add an entry to an sqlite3.pDisconnect ** list without holding the corresponding sqlite3.mutex mutex. ** -** The memory for objects of this type is always allocated by -** sqlite3DbMalloc(), using the connection handle stored in VTable.db as +** The memory for objects of this type is always allocated by +** sqlite3DbMalloc(), using the connection handle stored in VTable.db as ** the first argument. */ struct VTable { @@ -1823,7 +1831,7 @@ struct FKey { ** key is set to NULL. CASCADE means that a DELETE or UPDATE of the ** referenced table row is propagated into the row that holds the ** foreign key. -** +** ** The following symbolic values are used to record which type ** of action to take. */ @@ -1844,7 +1852,7 @@ struct FKey { /* ** An instance of the following structure is passed as the first -** argument to sqlite3VdbeKeyCompare and is used to control the +** argument to sqlite3VdbeKeyCompare and is used to control the ** comparison of the two index keys. ** ** Note that aSortOrder[] and aColl[] have nField+1 slots. There @@ -1885,7 +1893,7 @@ struct KeyInfo { ** The key comparison functions actually return default_rc when they find ** an equals comparison. default_rc can be -1, 0, or +1. If there are ** multiple entries in the b-tree with the same key (when only looking -** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to +** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to ** cause the search to find the last match, or +1 to cause the search to ** find the first match. ** @@ -1922,7 +1930,7 @@ struct UnpackedRecord { ** In the Table structure describing Ex1, nCol==3 because there are ** three columns in the table. In the Index structure describing ** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed. -** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the +** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the ** first column to be indexed (c3) has an index of 2 in Ex1.aCol[]. ** The second column to be indexed (c1) has an index of 0 in ** Ex1.aCol[], hence Ex2.aiColumn[1]==0. @@ -1930,7 +1938,7 @@ struct UnpackedRecord { ** The Index.onError field determines whether or not the indexed columns ** must be unique and what to do if they are not. When Index.onError=OE_None, ** it means this is not a unique index. Otherwise it is a unique index -** and the value of Index.onError indicate the which conflict resolution +** and the value of Index.onError indicate the which conflict resolution ** algorithm to employ whenever an attempt is made to insert a non-unique ** element. ** @@ -1995,7 +2003,7 @@ struct Index { #define XN_EXPR (-2) /* Indexed column is an expression */ /* -** Each sample stored in the sqlite_stat3 table is represented in memory +** Each sample stored in the sqlite_stat3 table is represented in memory ** using a structure of this type. See documentation at the top of the ** analyze.c source file for additional information. */ @@ -2090,9 +2098,9 @@ typedef int ynVar; ** to represent the greater-than-or-equal-to operator in the expression ** tree. ** -** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB, +** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB, ** or TK_STRING), then Expr.token contains the text of the SQL literal. If -** the expression is a variable (TK_VARIABLE), then Expr.token contains the +** the expression is a variable (TK_VARIABLE), then Expr.token contains the ** variable name. Finally, if the expression is an SQL function (TK_FUNCTION), ** then Expr.token contains the name of the function. ** @@ -2103,7 +2111,7 @@ typedef int ynVar; ** a CASE expression or an IN expression of the form " IN (, ...)". ** Expr.x.pSelect is used if the expression is a sub-select or an expression of ** the form " IN (SELECT ...)". If the EP_xIsSelect bit is set in the -** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is +** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is ** valid. ** ** An expression of the form ID or ID.ID refers to a column in a table. @@ -2114,8 +2122,8 @@ typedef int ynVar; ** value is also stored in the Expr.iAgg column in the aggregate so that ** it can be accessed after all aggregates are computed. ** -** If the expression is an unbound variable marker (a question mark -** character '?' in the original SQL) then the Expr.iTable holds the index +** If the expression is an unbound variable marker (a question mark +** character '?' in the original SQL) then the Expr.iTable holds the index ** number for that variable. ** ** If the expression is a subquery then Expr.iColumn holds an integer @@ -2154,7 +2162,7 @@ struct Expr { /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no ** space is allocated for the fields below this point. An attempt to - ** access them will result in a segfault or malfunction. + ** access them will result in a segfault or malfunction. *********************************************************************/ Expr *pLeft; /* Left subnode */ @@ -2220,7 +2228,7 @@ struct Expr { #define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */ /* -** These macros can be used to test, set, or clear bits in the +** These macros can be used to test, set, or clear bits in the ** Expr.flags field. */ #define ExprHasProperty(E,P) (((E)->flags&(P))!=0) @@ -2239,8 +2247,8 @@ struct Expr { #endif /* -** Macros to determine the number of bytes required by a normal Expr -** struct, an Expr struct with the EP_Reduced flag set in Expr.flags +** Macros to determine the number of bytes required by a normal Expr +** struct, an Expr struct with the EP_Reduced flag set in Expr.flags ** and an Expr struct with the EP_TokenOnly flag set. */ #define EXPR_FULLSIZE sizeof(Expr) /* Full size */ @@ -2248,7 +2256,7 @@ struct Expr { #define EXPR_TOKENONLYSIZE offsetof(Expr,pLeft) /* Fewer features */ /* -** Flags passed to the sqlite3ExprDup() function. See the header comment +** Flags passed to the sqlite3ExprDup() function. See the header comment ** above sqlite3ExprDup() for details. */ #define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */ @@ -2447,12 +2455,12 @@ struct SrcList { ** pEList corresponds to the result set of a SELECT and is NULL for ** other statements. ** -** NameContexts can be nested. When resolving names, the inner-most +** NameContexts can be nested. When resolving names, the inner-most ** context is searched first. If no match is found, the next outer ** context is checked. If there is still no match, the next context ** is checked. This process continues until either a match is found ** or all contexts are check. When a match is found, the nRef member of -** the context containing the match is incremented. +** the context containing the match is incremented. ** ** Each subquery gets a new NameContext. The pNext field points to the ** NameContext in the parent query. Thus the process of scanning the @@ -2475,7 +2483,7 @@ struct NameContext { ** ** Note: NC_MinMaxAgg must have the same value as SF_MinMaxAgg and ** SQLITE_FUNC_MINMAX. -** +** */ #define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */ #define NC_HasAgg 0x0002 /* One or more aggregate functions seen */ @@ -2554,7 +2562,7 @@ struct Select { ** by one of the following macros. The "SRT" prefix means "SELECT Result ** Type". ** -** SRT_Union Store results as a key in a temporary index +** SRT_Union Store results as a key in a temporary index ** identified by pDest->iSDParm. ** ** SRT_Except Remove results from the temporary index pDest->iSDParm. @@ -2578,7 +2586,7 @@ struct Select { ** of the query. This destination implies "LIMIT 1". ** ** SRT_Set The result must be a single column. Store each -** row of result as the key in table pDest->iSDParm. +** row of result as the key in table pDest->iSDParm. ** Apply the affinity pDest->affSdst before storing ** results. Used to implement "IN (SELECT ...)". ** @@ -2646,7 +2654,7 @@ struct SelectDest { }; /* -** During code generation of statements that do inserts into AUTOINCREMENT +** During code generation of statements that do inserts into AUTOINCREMENT ** tables, the following information is attached to the Table.u.autoInc.p ** pointer of each autoincrement table to record some side information that ** the code generator needs. We have to keep per-table autoincrement @@ -2669,7 +2677,7 @@ struct AutoincInfo { #endif /* -** At least one instance of the following structure is created for each +** At least one instance of the following structure is created for each ** trigger that may be fired while parsing an INSERT, UPDATE or DELETE ** statement. All such objects are stored in the linked list headed at ** Parse.pTriggerPrg and deleted once statement compilation has been @@ -2682,7 +2690,7 @@ struct AutoincInfo { ** values for both pTrigger and orconf. ** ** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns -** accessed (or set to 0 for triggers fired as a result of INSERT +** accessed (or set to 0 for triggers fired as a result of INSERT ** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to ** a mask of new.* columns used by the program. */ @@ -2723,7 +2731,7 @@ struct TriggerPrg { ** is constant but the second part is reset at the beginning and end of ** each recursion. ** -** The nTableLock and aTableLock variables are only used if the shared-cache +** The nTableLock and aTableLock variables are only used if the shared-cache ** feature is enabled (if sqlite3Tsd()->useSharedData is true). They are ** used to store the set of table-locks required by the statement being ** compiled. Function sqlite3TableLock() is used to add entries to the @@ -2876,10 +2884,10 @@ struct AuthContext { /* * Each trigger present in the database schema is stored as an instance of - * struct Trigger. + * struct Trigger. * * Pointers to instances of struct Trigger are stored in two ways. - * 1. In the "trigHash" hash table (part of the sqlite3* that represents the + * 1. In the "trigHash" hash table (part of the sqlite3* that represents the * database). This allows Trigger structures to be retrieved by name. * 2. All triggers associated with a single table form a linked list, using the * pNext member of struct Trigger. A pointer to the first element of the @@ -2905,7 +2913,7 @@ struct Trigger { /* ** A trigger is either a BEFORE or an AFTER trigger. The following constants -** determine which. +** determine which. ** ** If there are multiple triggers, you might of some BEFORE and some AFTER. ** In that cases, the constants below can be ORed together. @@ -2915,15 +2923,15 @@ struct Trigger { /* * An instance of struct TriggerStep is used to store a single SQL statement - * that is a part of a trigger-program. + * that is a part of a trigger-program. * * Instances of struct TriggerStep are stored in a singly linked list (linked - * using the "pNext" member) referenced by the "step_list" member of the + * using the "pNext" member) referenced by the "step_list" member of the * associated struct Trigger instance. The first element of the linked list is * the first step of the trigger-program. - * + * * The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or - * "SELECT" statement. The meanings of the other members is determined by the + * "SELECT" statement. The meanings of the other members is determined by the * value of "op" as follows: * * (op == TK_INSERT) @@ -2933,7 +2941,7 @@ struct Trigger { * zTarget -> Dequoted name of the table to insert into. * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then * this stores values to be inserted. Otherwise NULL. - * pIdList -> If this is an INSERT INTO ... () VALUES ... + * pIdList -> If this is an INSERT INTO ... () VALUES ... * statement, then this stores the column-names to be * inserted into. * @@ -2941,7 +2949,7 @@ struct Trigger { * zTarget -> Dequoted name of the table to delete from. * pWhere -> The WHERE clause of the DELETE statement if one is specified. * Otherwise NULL. - * + * * (op == TK_UPDATE) * zTarget -> Dequoted name of the table to update. * pWhere -> The WHERE clause of the UPDATE statement if one is specified. @@ -2949,7 +2957,7 @@ struct Trigger { * pExprList -> A list of the columns to update and the expressions to update * them to. See sqlite3Update() documentation of "pChanges" * argument. - * + * */ struct TriggerStep { u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ @@ -2967,7 +2975,7 @@ struct TriggerStep { /* ** The following structure contains information used by the sqliteFix... ** routines as they walk the parse tree to make database references -** explicit. +** explicit. */ typedef struct DbFixer DbFixer; struct DbFixer { @@ -3282,7 +3290,7 @@ int sqlite3HeapNearlyFull(void); #ifdef SQLITE_USE_ALLOCA # define sqlite3StackAllocRaw(D,N) alloca(N) # define sqlite3StackAllocZero(D,N) memset(alloca(N), 0, N) -# define sqlite3StackFree(D,P) +# define sqlite3StackFree(D,P) #else # define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N) # define sqlite3StackAllocZero(D,N) sqlite3DbMallocZero(D,N) @@ -3739,7 +3747,7 @@ u8 sqlite3GetBoolean(const char *z,u8); const void *sqlite3ValueText(sqlite3_value*, u8); int sqlite3ValueBytes(sqlite3_value*, u8); -void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, +void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); void sqlite3ValueSetNull(sqlite3_value*); void sqlite3ValueFree(sqlite3_value*); @@ -3799,7 +3807,7 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*); #ifdef SQLITE_DEBUG int sqlite3KeyInfoIsWriteable(KeyInfo*); #endif -int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, +int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), FuncDestructor *pDestructor @@ -3862,7 +3870,7 @@ void sqlite3AutoLoadExtensions(sqlite3*); # define sqlite3VtabRollback(X) # define sqlite3VtabCommit(X) # define sqlite3VtabInSync(db) 0 -# define sqlite3VtabLock(X) +# define sqlite3VtabLock(X) # define sqlite3VtabUnlock(X) # define sqlite3VtabUnlockList(X) # define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK @@ -3920,7 +3928,7 @@ const char *sqlite3JournalModename(int); ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign ** key functionality is available. If OMIT_TRIGGER is defined but ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In -** this case foreign keys are parsed, but no other functionality is +** this case foreign keys are parsed, but no other functionality is ** provided (enforcement of FK constraints requires the triggers sub-system). */ #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) @@ -4024,7 +4032,7 @@ void sqlite3Put4byte(u8*, u32); /* ** If the SQLITE_ENABLE IOTRACE exists then the global variable ** sqlite3IoTrace is a pointer to a printf-like routine used to -** print I/O tracing messages. +** print I/O tracing messages. */ #ifdef SQLITE_ENABLE_IOTRACE # define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } @@ -4058,7 +4066,7 @@ SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...); ** that allocations that might have been satisfied by lookaside are not ** passed back to non-lookaside free() routines. Asserts such as the ** example above are placed on the non-lookaside free() routines to verify -** this constraint. +** this constraint. ** ** All of this is no-op for a production build. It only comes into ** play when the SQLITE_MEMDEBUG compile-time option is used. From 0ead47d1c70e8edd9d54c94c75545a5e1667b602 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 15 Feb 2016 22:28:50 +0000 Subject: [PATCH 294/570] Fix comment. No changes to code. FossilOrigin-Name: 2e1f2eff27e25280fe626c07b6260b0a7aa903d3 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/os_win.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 805db81009..dc579b914c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Revise\scompiler\schecks\sfor\sthe\srand_s()\sfunction. -D 2016-02-15T22:01:24.377 +C Fix\scomment.\s\sNo\schanges\sto\scode. +D 2016-02-15T22:28:50.979 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -333,7 +333,7 @@ F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 3a6f20736dfb8a0949cdd66553fdf59f6604be35 -F src/os_win.c d085a0b043abe0c9349c7e8663730cc290041b56 +F src/os_win.c 1a781c2362ce07bcb6b3cd4b0c51c833eff70189 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 6812f3803951774b56abded396171e1c12b0b003 F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 139081bef9f63c3ebbe9e992408597b1349bdf37 -R 882b4878d4fb3d5db66502eaecb957f2 +P 287f508dd6abc1b9ffdbec6a685ebe79eeac992b +R 9d5f50ad392123c1263322df3a641869 U mistachkin -Z 2021541af14002b61ba4d5fc0e59c306 +Z 47f9e57e8f4d3a40a70b451a66c69ad4 diff --git a/manifest.uuid b/manifest.uuid index 6ac4d5b45c..a280efdfb0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -287f508dd6abc1b9ffdbec6a685ebe79eeac992b \ No newline at end of file +2e1f2eff27e25280fe626c07b6260b0a7aa903d3 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index 237c4fb0b2..f93fa24589 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -5468,7 +5468,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ } #endif return e.nXor>nBuf ? nBuf : e.nXor; -#endif /* defined(SQLITE_TEST) || defined(SQLITE_ZERO_PRNG_SEED) */ +#endif /* defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) */ } From b71aef34614d108be0ccd041b3d7c7bb2e38713f Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 15 Feb 2016 22:37:18 +0000 Subject: [PATCH 295/570] Readability improvements for winRandomness. FossilOrigin-Name: 1640f814c7a5210f08c81e52e5a3fb89ac26f4d4 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/os_win.c | 18 +++++++++--------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index dc579b914c..429035ea4b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scomment.\s\sNo\schanges\sto\scode. -D 2016-02-15T22:28:50.979 +C Readability\simprovements\sfor\swinRandomness. +D 2016-02-15T22:37:18.018 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -333,7 +333,7 @@ F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 3a6f20736dfb8a0949cdd66553fdf59f6604be35 -F src/os_win.c 1a781c2362ce07bcb6b3cd4b0c51c833eff70189 +F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 6812f3803951774b56abded396171e1c12b0b003 F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 287f508dd6abc1b9ffdbec6a685ebe79eeac992b -R 9d5f50ad392123c1263322df3a641869 +P 2e1f2eff27e25280fe626c07b6260b0a7aa903d3 +R dd8a80ac652728cd502c81c91874767f U mistachkin -Z 47f9e57e8f4d3a40a70b451a66c69ad4 +Z 8e4d3c615023f7e6ecbb584ba3188e53 diff --git a/manifest.uuid b/manifest.uuid index a280efdfb0..492babb232 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2e1f2eff27e25280fe626c07b6260b0a7aa903d3 \ No newline at end of file +1640f814c7a5210f08c81e52e5a3fb89ac26f4d4 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index f93fa24589..af6b1c814c 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -5410,7 +5410,7 @@ static void xorMemory(EntropyGatherer *p, unsigned char *x, int sz){ p->i = k; p->nXor += sz; } -#endif +#endif /* !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS) */ /* ** Write up to nBuf bytes of randomness into zBuf. @@ -5426,7 +5426,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ memset(zBuf, 0, nBuf); #if defined(_MSC_VER) && _MSC_VER>=1400 rand_s((int*)zBuf); /* rand_s() is not available with MinGW */ -#endif +#endif /* defined(_MSC_VER) && _MSC_VER>=1400 */ e.a = (unsigned char*)zBuf; e.na = nBuf; e.nXor = 0; @@ -5434,27 +5434,27 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ { SYSTEMTIME x; osGetSystemTime(&x); - xorMemory(&e, (unsigned char*)&x, sizeof(x)); + xorMemory(&e, (unsigned char*)&x, sizeof(SYSTEMTIME)); } { DWORD pid = osGetCurrentProcessId(); - xorMemory(&e, (unsigned char*)&pid, sizeof(pid)); + xorMemory(&e, (unsigned char*)&pid, sizeof(DWORD)); } #if SQLITE_OS_WINRT { ULONGLONG cnt = osGetTickCount64(); - xorMemory(&e, (unsigned char*)&cnt, sizeof(cnt)); + xorMemory(&e, (unsigned char*)&cnt, sizeof(ULONGLONG)); } #else { DWORD cnt = osGetTickCount(); - xorMemory(&e, (unsigned char*)&cnt, sizeof(cnt)); + xorMemory(&e, (unsigned char*)&cnt, sizeof(DWORD)); } -#endif +#endif /* SQLITE_OS_WINRT */ { LARGE_INTEGER i; osQueryPerformanceCounter(&i); - xorMemory(&e, (unsigned char*)&i, sizeof(i)); + xorMemory(&e, (unsigned char*)&i, sizeof(LARGE_INTEGER)); } #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID { @@ -5466,7 +5466,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ osUuidCreateSequential(&id); xorMemory(&e, (unsigned char*)&id, sizeof(UUID)); } -#endif +#endif /* !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID */ return e.nXor>nBuf ? nBuf : e.nXor; #endif /* defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) */ } From 7ff89807e01fa81cbddac046e2c107a3fbeed455 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 15 Feb 2016 23:46:36 +0000 Subject: [PATCH 296/570] Fix a harmless compiler warning in FTS5. FossilOrigin-Name: e52c90758c53cbb0f74e0d8582e4c3c1bee04150 --- ext/fts5/fts5_index.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index c40ffbcbb5..57d242bc3c 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -865,7 +865,7 @@ static int fts5StructureDecode( for(iLvl=0; rc==SQLITE_OK && iLvlaLevel[iLvl]; - int nTotal; + int nTotal = 0; int iSeg; if( i>=nData ){ diff --git a/manifest b/manifest index 429035ea4b..31d3dac506 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Readability\simprovements\sfor\swinRandomness. -D 2016-02-15T22:37:18.018 +C Fix\sa\sharmless\scompiler\swarning\sin\sFTS5. +D 2016-02-15T23:46:36.756 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c c6cd5190c7e5dd94151cb17acd939c82e5c7be2d +F ext/fts5/fts5_index.c 78069efb54559a17c35906a741362d0b5c899bd0 F ext/fts5/fts5_main.c 0e01ead4e817483e378e7e38e6d902f50b68d29e F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2e1f2eff27e25280fe626c07b6260b0a7aa903d3 -R dd8a80ac652728cd502c81c91874767f -U mistachkin -Z 8e4d3c615023f7e6ecbb584ba3188e53 +P 1640f814c7a5210f08c81e52e5a3fb89ac26f4d4 +R b9aa8d782c6b62a0c225e4bb87cb9bb3 +U drh +Z 2752a99e50374be8d380aa3f6a98228d diff --git a/manifest.uuid b/manifest.uuid index 492babb232..375489a142 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1640f814c7a5210f08c81e52e5a3fb89ac26f4d4 \ No newline at end of file +e52c90758c53cbb0f74e0d8582e4c3c1bee04150 \ No newline at end of file From dab943cf3dc6002b0690ae2db4f7a932a9c919d9 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 16 Feb 2016 01:01:43 +0000 Subject: [PATCH 297/570] Improve the Lemon parser template (lempar.c) so that it avoids unnecessary work when the grammer defines YYNOERRORRECOVERY (as SQLite does). Slightly smaller and faster code results. FossilOrigin-Name: 9235b0cf6a37712ae9e5deeb1e5ee064dd5511fa --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/lempar.c | 6 ++++++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 31d3dac506..4022e2709b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sharmless\scompiler\swarning\sin\sFTS5. -D 2016-02-15T23:46:36.756 +C Improve\sthe\sLemon\sparser\stemplate\s(lempar.c)\sso\sthat\sit\savoids\sunnecessary\nwork\swhen\sthe\sgrammer\sdefines\sYYNOERRORRECOVERY\s(as\sSQLite\sdoes).\s\sSlightly\nsmaller\sand\sfaster\scode\sresults. +D 2016-02-16T01:01:43.571 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -1379,7 +1379,7 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d -F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7 +F tool/lempar.c ff7763747f93c9d7eac6df1e802a200b3f0e2cc0 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh c78caa3214f25dc28ea157b5a82abb311f209906 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1640f814c7a5210f08c81e52e5a3fb89ac26f4d4 -R b9aa8d782c6b62a0c225e4bb87cb9bb3 +P e52c90758c53cbb0f74e0d8582e4c3c1bee04150 +R 14b39a221176c006cbe52f2c99fdaa8f U drh -Z 2752a99e50374be8d380aa3f6a98228d +Z ff87b99d3af559ad671417b818afef7b diff --git a/manifest.uuid b/manifest.uuid index 375489a142..361d87de8f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e52c90758c53cbb0f74e0d8582e4c3c1bee04150 \ No newline at end of file +9235b0cf6a37712ae9e5deeb1e5ee064dd5511fa \ No newline at end of file diff --git a/tool/lempar.c b/tool/lempar.c index 312507e5f1..454702a3a7 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -211,7 +211,9 @@ struct yyParser { #ifdef YYTRACKMAXSTACKDEPTH int yyidxMax; /* Maximum value of yyidx */ #endif +#ifndef YYNOERRORRECOVERY int yyerrcnt; /* Shifts left before out of the error */ +#endif ParseARG_SDECL /* A place to hold %extra_argument */ #if YYSTACKDEPTH<=0 int yystksz; /* Current side of the stack */ @@ -774,7 +776,9 @@ void Parse( } #endif yypParser->yyidx = 0; +#ifndef YYNOERRORRECOVERY yypParser->yyerrcnt = -1; +#endif yypParser->yystack[0].stateno = 0; yypParser->yystack[0].major = 0; #ifndef NDEBUG @@ -801,7 +805,9 @@ void Parse( if( yyact <= YY_MAX_SHIFTREDUCE ){ if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; yy_shift(yypParser,yyact,yymajor,&yyminorunion); +#ifndef YYNOERRORRECOVERY yypParser->yyerrcnt--; +#endif yymajor = YYNOCODE; }else if( yyact <= YY_MAX_REDUCE ){ yy_reduce(yypParser,yyact-YY_MIN_REDUCE); From 30c14728b459a86eef9e141a2a22910a01c1a036 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 16 Feb 2016 13:04:19 +0000 Subject: [PATCH 298/570] Minor simplification to the tokenizer. Slightly smaller and faster. FossilOrigin-Name: 9570b6b43df3bc5ce314cded20bca8be9e968efe --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/tokenize.c | 3 +-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 4022e2709b..86aa0b58ec 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\sthe\sLemon\sparser\stemplate\s(lempar.c)\sso\sthat\sit\savoids\sunnecessary\nwork\swhen\sthe\sgrammer\sdefines\sYYNOERRORRECOVERY\s(as\sSQLite\sdoes).\s\sSlightly\nsmaller\sand\sfaster\scode\sresults. -D 2016-02-16T01:01:43.571 +C Minor\ssimplification\sto\sthe\stokenizer.\s\sSlightly\ssmaller\sand\sfaster. +D 2016-02-16T13:04:19.100 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -406,7 +406,7 @@ F src/test_windirent.c 8f5fada630348558d5745b334702f301da1ffc61 F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c -F src/tokenize.c 2a234093ff16791ab3ec5ab60dc7fcf6af575e1c +F src/tokenize.c 32aeca12f0d57a5c1c9a88d63e46ed2ee795cdb4 F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e52c90758c53cbb0f74e0d8582e4c3c1bee04150 -R 14b39a221176c006cbe52f2c99fdaa8f +P 9235b0cf6a37712ae9e5deeb1e5ee064dd5511fa +R a61b67e5f930748de130d8b41c0bc53a U drh -Z ff87b99d3af559ad671417b818afef7b +Z d1a1b630582c40b1f2edd9cd2e01402a diff --git a/manifest.uuid b/manifest.uuid index 361d87de8f..ee978cebbb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9235b0cf6a37712ae9e5deeb1e5ee064dd5511fa \ No newline at end of file +9570b6b43df3bc5ce314cded20bca8be9e968efe \ No newline at end of file diff --git a/src/tokenize.c b/src/tokenize.c index c43a039dde..4a5fc0a04a 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -523,18 +523,17 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ break; } }else{ - if( tokenType==TK_SEMI ) pParse->zTail = &zSql[i]; sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); lastTokenParsed = tokenType; if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; } } assert( nErr==0 ); + pParse->zTail = &zSql[i]; if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){ assert( zSql[i]==0 ); if( lastTokenParsed!=TK_SEMI ){ sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse); - pParse->zTail = &zSql[i]; } if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){ sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); From 45f31be85dc90a3f76dd930ad4ec2a0174105156 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 16 Feb 2016 21:19:49 +0000 Subject: [PATCH 299/570] Experimental changes to Lemon for improved parser performance. FossilOrigin-Name: a65d583ce97b8c08157268bd054479cda3957a94 --- doc/lemon.html | 12 +++++-- ext/fts5/fts5parse.y | 1 - manifest | 21 ++++++----- manifest.uuid | 2 +- src/parse.y | 1 - tool/lempar.c | 85 +++++++++++++++++++++++++------------------- 6 files changed, 72 insertions(+), 50 deletions(-) diff --git a/doc/lemon.html b/doc/lemon.html index b16e35960e..2b8c613640 100644 --- a/doc/lemon.html +++ b/doc/lemon.html @@ -161,8 +161,9 @@ such as ``identifier'' or ``number'' and the third argument will be the name of the identifier or the value of the number.

    The Parse() function may have either three or four arguments, -depending on the grammar. If the grammar specification file request -it, the Parse() function will have a fourth parameter that can be +depending on the grammar. If the grammar specification file requests +it (via the extra_argument directive), +the Parse() function will have a fourth parameter that can be of any type chosen by the programmer. The parser doesn't do anything with this argument except to pass it through to action routines. This is a convenient mechanism for passing state information down @@ -263,6 +264,12 @@ with prior yacc and bison experience. But after years of experience using Lemon, I firmly believe that the Lemon way of doing things is better.

    +

    Updated as of 2016-02-16: +The text above was written in the 1990s. +We are told that Bison has lately been enhanced to support the +tokenizer-calls-parser paradigm used by Lemon, and to obviate the +need for global variables.

    +

    Input File Syntax

    The main purpose of the grammar specification file for Lemon is @@ -617,6 +624,7 @@ build a parser using Lemon that can be used within a long-running program, such as a GUI, that will not leak memory or other resources. To do the same using yacc or bison is much more difficult.

    +

    The %extra_argument directive

    The %extra_argument directive instructs Lemon to add a 4th parameter diff --git a/ext/fts5/fts5parse.y b/ext/fts5/fts5parse.y index 43936767b7..2bdf4b09b2 100644 --- a/ext/fts5/fts5parse.y +++ b/ext/fts5/fts5parse.y @@ -34,7 +34,6 @@ ); } %stack_overflow { - UNUSED_PARAM(yypMinor); /* Silence a compiler warning */ sqlite3Fts5ParseError(pParse, "fts5: parser stack overflow"); } diff --git a/manifest b/manifest index 86aa0b58ec..309d908101 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\ssimplification\sto\sthe\stokenizer.\s\sSlightly\ssmaller\sand\sfaster. -D 2016-02-16T13:04:19.100 +C Experimental\schanges\sto\sLemon\sfor\simproved\sparser\sperformance. +D 2016-02-16T21:19:49.726 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -33,7 +33,7 @@ F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 F configure 12d96e3798e612e0ffa53a7a8c4d7fb1090df80e x F configure.ac a2224b1162f79848982d3618ac1deffcd94e88ec F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad -F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1 +F doc/lemon.html c30255bea0fd87a81f082d17a72c9dffbc3f6dd9 F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710 F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a F ext/README.txt 913a7bd3f4837ab14d7e063304181787658b14e1 @@ -114,7 +114,7 @@ F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8 F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738 F ext/fts5/fts5_vocab.c dba72ca393d71c2588548b51380387f6b44c77a8 -F ext/fts5/fts5parse.y 59432ea369f1aa65511bad465f55d31a22f9f223 +F ext/fts5/fts5parse.y 86fe6ba094a47e02fe8be2571539e6833d197764 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba F ext/fts5/test/fts5_common.tcl 61ff0d1a29d98a91c4553b20b3f410d858834ee9 F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 @@ -337,7 +337,7 @@ F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 6812f3803951774b56abded396171e1c12b0b003 F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 -F src/parse.y d7bff41d460f2df96fb890f36700e85cb0fc5634 +F src/parse.y 36a367a623589fb1123c10d577737aa3a06177e6 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 @@ -1379,7 +1379,7 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d -F tool/lempar.c ff7763747f93c9d7eac6df1e802a200b3f0e2cc0 +F tool/lempar.c 5478c5298763b47908b6632a7e3f9d656a98748b F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh c78caa3214f25dc28ea157b5a82abb311f209906 @@ -1427,7 +1427,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9235b0cf6a37712ae9e5deeb1e5ee064dd5511fa -R a61b67e5f930748de130d8b41c0bc53a +P 9570b6b43df3bc5ce314cded20bca8be9e968efe +R bd4538940a7fa7274e5766ff6172546b +T *branch * parser-performance +T *sym-parser-performance * +T -sym-trunk * U drh -Z d1a1b630582c40b1f2edd9cd2e01402a +Z c2a93192e4911cf28788507cc4af2d10 diff --git a/manifest.uuid b/manifest.uuid index ee978cebbb..13e75b598d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9570b6b43df3bc5ce314cded20bca8be9e968efe \ No newline at end of file +a65d583ce97b8c08157268bd054479cda3957a94 \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index 0bfe4e473a..b5755820b3 100644 --- a/src/parse.y +++ b/src/parse.y @@ -35,7 +35,6 @@ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); } %stack_overflow { - UNUSED_PARAMETER(yypMinor); /* Silence some compiler warnings */ sqlite3ErrorMsg(pParse, "parser stack overflow"); } diff --git a/tool/lempar.c b/tool/lempar.c index 454702a3a7..c5b65d645d 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -518,7 +518,7 @@ static int yy_find_reduce_action( /* ** The following routine is called if the stack overflows. */ -static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){ +static void yyStackOverflow(yyParser *yypParser){ ParseARG_FETCH; yypParser->yyidx--; #ifndef NDEBUG @@ -562,7 +562,7 @@ static void yy_shift( yyParser *yypParser, /* The parser to be shifted */ int yyNewState, /* The new state to shift in */ int yyMajor, /* The major token to shift in */ - YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */ + ParseTOKENTYPE yyMinor /* The minor token to shift in */ ){ yyStackEntry *yytos; yypParser->yyidx++; @@ -573,14 +573,14 @@ static void yy_shift( #endif #if YYSTACKDEPTH>0 if( yypParser->yyidx>=YYSTACKDEPTH ){ - yyStackOverflow(yypParser, yypMinor); + yyStackOverflow(yypParser); return; } #else if( yypParser->yyidx>=yypParser->yystksz ){ yyGrowStack(yypParser); if( yypParser->yyidx>=yypParser->yystksz ){ - yyStackOverflow(yypParser, yypMinor); + yyStackOverflow(yypParser); return; } } @@ -588,7 +588,7 @@ static void yy_shift( yytos = &yypParser->yystack[yypParser->yyidx]; yytos->stateno = (YYACTIONTYPE)yyNewState; yytos->major = (YYCODETYPE)yyMajor; - yytos->minor = *yypMinor; + yytos->minor.yy0 = yyMinor; yyTraceShift(yypParser, yyNewState); } @@ -627,7 +627,32 @@ static void yy_reduce( yyRuleName[yyruleno], yymsp[-yysize].stateno); } #endif /* NDEBUG */ - yygotominor = yyzerominor; + /* yygotominor = yyzerominor; */ + + /* Check that the stack is large enough to grow by a single entry + ** if the RHS of the rule is empty. This ensures that there is room + ** enough on the stack to push the LHS value */ + if( yyRuleInfo[yyruleno].nrhs==0 ){ +#ifdef YYTRACKMAXSTACKDEPTH + if( yypParser->yyidx>yypParser->yyidxMax ){ + yypParser->yyidxMax = yypParser->yyidx; + } +#endif +#if YYSTACKDEPTH>0 + if( yypParser->yyidx>=YYSTACKDEPTH ){ + yyStackOverflow(yypParser); + return; + } +#else + if( yypParser->yyidx>=yypParser->yystksz ){ + yyGrowStack(yypParser); + if( yypParser->yyidx>=yypParser->yystksz ){ + yyStackOverflow(yypParser); + return; + } + } +#endif + } switch( yyruleno ){ /* Beginning here are the reduction cases. A typical example @@ -645,26 +670,18 @@ static void yy_reduce( assert( yyruleno>=0 && yyrulenoyyidx -= yysize; yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); if( yyact <= YY_MAX_SHIFTREDUCE ){ if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; - /* If the reduce action popped at least - ** one element off the stack, then we can push the new element back - ** onto the stack here, and skip the stack overflow test in yy_shift(). - ** That gives a significant speed improvement. */ - if( yysize ){ - yypParser->yyidx++; - yymsp -= yysize-1; - yymsp->stateno = (YYACTIONTYPE)yyact; - yymsp->major = (YYCODETYPE)yygoto; - yymsp->minor = yygotominor; - yyTraceShift(yypParser, yyact); - }else{ - yy_shift(yypParser,yyact,yygoto,&yygotominor); - } + yypParser->yyidx -= yysize - 1; + yymsp -= yysize-1; + yymsp->stateno = (YYACTIONTYPE)yyact; + yymsp->major = (YYCODETYPE)yygoto; + yymsp->minor = yygotominor; + yyTraceShift(yypParser, yyact); }else{ assert( yyact == YY_ACCEPT_ACTION ); + yypParser->yyidx -= yysize; yy_accept(yypParser); } } @@ -698,10 +715,10 @@ static void yy_parse_failed( static void yy_syntax_error( yyParser *yypParser, /* The parser */ int yymajor, /* The major type of the error token */ - YYMINORTYPE yyminor /* The minor type of the error token */ + ParseTOKENTYPE yyminor /* The minor type of the error token */ ){ ParseARG_FETCH; -#define TOKEN (yyminor.yy0) +#define TOKEN yyminor /************ Begin %syntax_error code ****************************************/ %% /************ End %syntax_error code ******************************************/ @@ -769,9 +786,7 @@ void Parse( if( yypParser->yyidx<0 ){ #if YYSTACKDEPTH<=0 if( yypParser->yystksz <=0 ){ - /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/ - yyminorunion = yyzerominor; - yyStackOverflow(yypParser, &yyminorunion); + yyStackOverflow(yypParser); return; } #endif @@ -788,7 +803,6 @@ void Parse( } #endif } - yyminorunion.yy0 = yyminor; #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) yyendofinput = (yymajor==0); #endif @@ -804,7 +818,7 @@ void Parse( yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); if( yyact <= YY_MAX_SHIFTREDUCE ){ if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; - yy_shift(yypParser,yyact,yymajor,&yyminorunion); + yy_shift(yypParser,yyact,yymajor,yyminor); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt--; #endif @@ -813,6 +827,7 @@ void Parse( yy_reduce(yypParser,yyact-YY_MIN_REDUCE); }else{ assert( yyact == YY_ERROR_ACTION ); + yyminorunion.yy0 = yyminor; #ifdef YYERRORSYMBOL int yymx; #endif @@ -842,7 +857,7 @@ void Parse( ** */ if( yypParser->yyerrcnt<0 ){ - yy_syntax_error(yypParser,yymajor,yyminorunion); + yy_syntax_error(yypParser,yymajor,yyminor); } yymx = yypParser->yystack[yypParser->yyidx].major; if( yymx==YYERRORSYMBOL || yyerrorhit ){ @@ -852,10 +867,10 @@ void Parse( yyTracePrompt,yyTokenName[yymajor]); } #endif - yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion); + yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); yymajor = YYNOCODE; }else{ - while( + while( yypParser->yyidx >= 0 && yymx != YYERRORSYMBOL && (yyact = yy_find_reduce_action( @@ -869,9 +884,7 @@ void Parse( yy_parse_failed(yypParser); yymajor = YYNOCODE; }else if( yymx!=YYERRORSYMBOL ){ - YYMINORTYPE u2; - u2.YYERRSYMDT = 0; - yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2); + yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor); } } yypParser->yyerrcnt = 3; @@ -884,7 +897,7 @@ void Parse( ** Applications can set this macro (for example inside %include) if ** they intend to abandon the parse upon the first syntax error seen. */ - yy_syntax_error(yypParser,yymajor,yyminorunion); + yy_syntax_error(yypParser,yymajor, yyminor); yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); yymajor = YYNOCODE; @@ -899,7 +912,7 @@ void Parse( ** three input tokens have been successfully shifted. */ if( yypParser->yyerrcnt<=0 ){ - yy_syntax_error(yypParser,yymajor,yyminorunion); + yy_syntax_error(yypParser,yymajor, yyminor); } yypParser->yyerrcnt = 3; yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); From 4dd0d3f81909f6a74479c1ac98e1983bb9409897 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 17 Feb 2016 01:18:33 +0000 Subject: [PATCH 300/570] In Lemon, add the ability for the left-most RHS label to be the same as the LHS label, causing the LHS values to be written directly into the stack. FossilOrigin-Name: 4bb94c7c4c3cb3ccad72c2451d88684130dde845 --- manifest | 19 ++-- manifest.uuid | 2 +- src/parse.y | 251 +++++++++++++++++++++++--------------------------- tool/lemon.c | 134 ++++++++++++++++++++++----- tool/lempar.c | 2 - 5 files changed, 239 insertions(+), 169 deletions(-) diff --git a/manifest b/manifest index 309d908101..32bf38b889 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Experimental\schanges\sto\sLemon\sfor\simproved\sparser\sperformance. -D 2016-02-16T21:19:49.726 +C In\sLemon,\sadd\sthe\sability\sfor\sthe\sleft-most\sRHS\slabel\sto\sbe\sthe\ssame\sas\sthe\nLHS\slabel,\scausing\sthe\sLHS\svalues\sto\sbe\swritten\sdirectly\sinto\sthe\sstack. +D 2016-02-17T01:18:33.698 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -337,7 +337,7 @@ F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 6812f3803951774b56abded396171e1c12b0b003 F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 -F src/parse.y 36a367a623589fb1123c10d577737aa3a06177e6 +F src/parse.y eb7d241ca23d6035e5f902de571bb066884fd4ca F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 @@ -1378,8 +1378,8 @@ F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce -F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d -F tool/lempar.c 5478c5298763b47908b6632a7e3f9d656a98748b +F tool/lemon.c 501104fc7fbb01a86078841bed704184ccfd6036 +F tool/lempar.c 08bbb0fbca9c1f61d2a20a7af893110aefd571a0 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh c78caa3214f25dc28ea157b5a82abb311f209906 @@ -1427,10 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9570b6b43df3bc5ce314cded20bca8be9e968efe -R bd4538940a7fa7274e5766ff6172546b -T *branch * parser-performance -T *sym-parser-performance * -T -sym-trunk * +P a65d583ce97b8c08157268bd054479cda3957a94 +R e1ed8179ef03a39381f66ed9ce3ecd2f U drh -Z c2a93192e4911cf28788507cc4af2d10 +Z a9c8340faee95f29d20e3673b4598420 diff --git a/manifest.uuid b/manifest.uuid index 13e75b598d..9f1cd50eb1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a65d583ce97b8c08157268bd054479cda3957a94 \ No newline at end of file +4bb94c7c4c3cb3ccad72c2451d88684130dde845 \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index b5755820b3..b48ed526d4 100644 --- a/src/parse.y +++ b/src/parse.y @@ -200,13 +200,11 @@ columnlist ::= column. // datatype, and other keywords such as PRIMARY KEY, UNIQUE, REFERENCES, // NOT NULL and so forth. // -column(A) ::= columnid(X) type carglist. { - A.z = X.z; - A.n = (int)(pParse->sLastToken.z-X.z) + pParse->sLastToken.n; +column(A) ::= columnid(A) type carglist. { + A.n = (int)(pParse->sLastToken.z-A.z) + pParse->sLastToken.n; } -columnid(A) ::= nm(X). { - sqlite3AddColumn(pParse,&X); - A = X; +columnid(A) ::= nm(A). { + sqlite3AddColumn(pParse,&A); pParse->constraintName.n = 0; } @@ -264,9 +262,9 @@ columnid(A) ::= nm(X). { // The name of a column or table can be any of the following: // %type nm {Token} -nm(A) ::= id(X). {A = X;} -nm(A) ::= STRING(X). {A = X;} -nm(A) ::= JOIN_KW(X). {A = X;} +nm(A) ::= id(A). +nm(A) ::= STRING(A). +nm(A) ::= JOIN_KW(A). // A typetoken is really one or more tokens that form a type name such // as can be found after the column name in a CREATE TABLE statement. @@ -275,18 +273,16 @@ nm(A) ::= JOIN_KW(X). {A = X;} %type typetoken {Token} type ::= . type ::= typetoken(X). {sqlite3AddColumnType(pParse,&X);} -typetoken(A) ::= typename(X). {A = X;} -typetoken(A) ::= typename(X) LP signed RP(Y). { - A.z = X.z; - A.n = (int)(&Y.z[Y.n] - X.z); +typetoken(A) ::= typename(A). +typetoken(A) ::= typename(A) LP signed RP(Y). { + A.n = (int)(&Y.z[Y.n] - A.z); } -typetoken(A) ::= typename(X) LP signed COMMA signed RP(Y). { - A.z = X.z; - A.n = (int)(&Y.z[Y.n] - X.z); +typetoken(A) ::= typename(A) LP signed COMMA signed RP(Y). { + A.n = (int)(&Y.z[Y.n] - A.z); } %type typename {Token} -typename(A) ::= ids(X). {A = X;} -typename(A) ::= typename(X) ids(Y). {A.z=X.z; A.n=Y.n+(int)(Y.z-X.z);} +typename(A) ::= ids(A). +typename(A) ::= typename(A) ids(Y). {A.n=Y.n+(int)(Y.z-A.z);} signed ::= plus_num. signed ::= minus_num. @@ -338,7 +334,7 @@ autoinc(X) ::= AUTOINCR. {X = 1;} // %type refargs {int} refargs(A) ::= . { A = OE_None*0x0101; /* EV: R-19803-45884 */} -refargs(A) ::= refargs(X) refarg(Y). { A = (X & ~Y.mask) | Y.value; } +refargs(A) ::= refargs(A) refarg(Y). { A = (A & ~Y.mask) | Y.value; } %type refarg {struct {int value; int mask;}} refarg(A) ::= MATCH nm. { A.value = 0; A.mask = 0x000000; } refarg(A) ::= ON INSERT refact. { A.value = 0; A.mask = 0x000000; } @@ -359,7 +355,7 @@ init_deferred_pred_opt(A) ::= INITIALLY DEFERRED. {A = 1;} init_deferred_pred_opt(A) ::= INITIALLY IMMEDIATE. {A = 0;} conslist_opt(A) ::= . {A.n = 0; A.z = 0;} -conslist_opt(A) ::= COMMA(X) conslist. {A = X;} +conslist_opt(A) ::= COMMA(A) conslist. conslist ::= conslist tconscomma tcons. conslist ::= tcons. tconscomma ::= COMMA. {pParse->constraintName.n = 0;} @@ -378,7 +374,7 @@ tcons ::= FOREIGN KEY LP eidlist(FA) RP } %type defer_subclause_opt {int} defer_subclause_opt(A) ::= . {A = 0;} -defer_subclause_opt(A) ::= defer_subclause(X). {A = X;} +defer_subclause_opt(A) ::= defer_subclause(A). // The following is a non-standard extension that allows us to declare the // default behavior when there is a constraint conflict. @@ -390,7 +386,7 @@ onconf(A) ::= . {A = OE_Default;} onconf(A) ::= ON CONFLICT resolvetype(X). {A = X;} orconf(A) ::= . {A = OE_Default;} orconf(A) ::= OR resolvetype(X). {A = X;} -resolvetype(A) ::= raisetype(X). {A = X;} +resolvetype(A) ::= raisetype(A). resolvetype(A) ::= IGNORE. {A = OE_Ignore;} resolvetype(A) ::= REPLACE. {A = OE_Replace;} @@ -465,11 +461,11 @@ select(A) ::= with(W) selectnowith(X). { A = p; } -selectnowith(A) ::= oneselect(X). {A = X;} +selectnowith(A) ::= oneselect(A). %ifndef SQLITE_OMIT_COMPOUND_SELECT -selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). { +selectnowith(A) ::= selectnowith(A) multiselect_op(Y) oneselect(Z). { Select *pRhs = Z; - Select *pLhs = X; + Select *pLhs = A; if( pRhs && pRhs->pPrior ){ SrcList *pFrom; Token x; @@ -522,20 +518,19 @@ oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y) } #endif /* SELECTRACE_ENABLED */ } -oneselect(A) ::= values(X). {A = X;} +oneselect(A) ::= values(A). %type values {Select*} %destructor values {sqlite3SelectDelete(pParse->db, $$);} values(A) ::= VALUES LP nexprlist(X) RP. { A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0,0); } -values(A) ::= values(X) COMMA LP exprlist(Y) RP. { - Select *pRight, *pLeft = X; +values(A) ::= values(A) COMMA LP exprlist(Y) RP. { + Select *pRight, *pLeft = A; pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0,0); if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; if( pRight ){ pRight->op = TK_ALL; - pLeft = X; pRight->pPrior = pLeft; A = pRight; }else{ @@ -560,22 +555,22 @@ distinct(A) ::= . {A = 0;} %destructor selcollist {sqlite3ExprListDelete(pParse->db, $$);} %type sclp {ExprList*} %destructor sclp {sqlite3ExprListDelete(pParse->db, $$);} -sclp(A) ::= selcollist(X) COMMA. {A = X;} +sclp(A) ::= selcollist(A) COMMA. sclp(A) ::= . {A = 0;} -selcollist(A) ::= sclp(P) expr(X) as(Y). { - A = sqlite3ExprListAppend(pParse, P, X.pExpr); +selcollist(A) ::= sclp(A) expr(X) as(Y). { + A = sqlite3ExprListAppend(pParse, A, X.pExpr); if( Y.n>0 ) sqlite3ExprListSetName(pParse, A, &Y, 1); sqlite3ExprListSetSpan(pParse,A,&X); } -selcollist(A) ::= sclp(P) STAR. { +selcollist(A) ::= sclp(A) STAR. { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); - A = sqlite3ExprListAppend(pParse, P, p); + A = sqlite3ExprListAppend(pParse, A, p); } -selcollist(A) ::= sclp(P) nm(X) DOT STAR(Y). { +selcollist(A) ::= sclp(A) nm(X) DOT STAR(Y). { Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, &Y); Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); - A = sqlite3ExprListAppend(pParse,P, pDot); + A = sqlite3ExprListAppend(pParse,A, pDot); } // An option "AS " phrase that can follow one of the expressions that @@ -583,7 +578,7 @@ selcollist(A) ::= sclp(P) nm(X) DOT STAR(Y). { // %type as {Token} as(X) ::= AS nm(Y). {X = Y;} -as(X) ::= ids(Y). {X = Y;} +as(X) ::= ids(X). as(X) ::= . {X.n = 0;} @@ -605,32 +600,31 @@ from(A) ::= FROM seltablist(X). { // "seltablist" is a "Select Table List" - the content of the FROM clause // in a SELECT statement. "stl_prefix" is a prefix of this list. // -stl_prefix(A) ::= seltablist(X) joinop(Y). { - A = X; +stl_prefix(A) ::= seltablist(A) joinop(Y). { if( ALWAYS(A && A->nSrc>0) ) A->a[A->nSrc-1].fg.jointype = (u8)Y; } stl_prefix(A) ::= . {A = 0;} -seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) indexed_opt(I) +seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) as(Z) indexed_opt(I) on_opt(N) using_opt(U). { - A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U); + A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,N,U); sqlite3SrcListIndexedBy(pParse, A, &I); } -seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) LP exprlist(E) RP as(Z) +seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z) on_opt(N) using_opt(U). { - A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U); + A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,N,U); sqlite3SrcListFuncArgs(pParse, A, E); } %ifndef SQLITE_OMIT_SUBQUERY - seltablist(A) ::= stl_prefix(X) LP select(S) RP + seltablist(A) ::= stl_prefix(A) LP select(S) RP as(Z) on_opt(N) using_opt(U). { - A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,S,N,U); + A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,S,N,U); } - seltablist(A) ::= stl_prefix(X) LP seltablist(F) RP + seltablist(A) ::= stl_prefix(A) LP seltablist(F) RP as(Z) on_opt(N) using_opt(U). { - if( X==0 && Z.n==0 && N==0 && U==0 ){ + if( A==0 && Z.n==0 && N==0 && U==0 ){ A = F; }else if( F->nSrc==1 ){ - A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,0,N,U); + A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,0,N,U); if( A ){ struct SrcList_item *pNew = &A->a[A->nSrc-1]; struct SrcList_item *pOld = F->a; @@ -645,7 +639,7 @@ seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) LP exprlist(E) RP as(Z) Select *pSubquery; sqlite3SrcListShiftJoinType(F); pSubquery = sqlite3SelectNew(pParse,0,F,0,0,0,0,SF_NestedFrom,0,0); - A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,pSubquery,N,U); + A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,pSubquery,N,U); } } %endif SQLITE_OMIT_SUBQUERY @@ -703,8 +697,8 @@ using_opt(U) ::= . {U = 0;} orderby_opt(A) ::= . {A = 0;} orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;} -sortlist(A) ::= sortlist(X) COMMA expr(Y) sortorder(Z). { - A = sqlite3ExprListAppend(pParse,X,Y.pExpr); +sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z). { + A = sqlite3ExprListAppend(pParse,A,Y.pExpr); sqlite3ExprListSetSortOrder(A,Z); } sortlist(A) ::= expr(Y) sortorder(Z). { @@ -798,8 +792,8 @@ cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) %type setlist {ExprList*} %destructor setlist {sqlite3ExprListDelete(pParse->db, $$);} -setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y). { - A = sqlite3ExprListAppend(pParse, Z, Y.pExpr); +setlist(A) ::= setlist(A) COMMA nm(X) EQ expr(Y). { + A = sqlite3ExprListAppend(pParse, A, Y.pExpr); sqlite3ExprListSetName(pParse, A, &X, 1); } setlist(A) ::= nm(X) EQ expr(Y). { @@ -830,8 +824,8 @@ insert_cmd(A) ::= REPLACE. {A = OE_Replace;} idlist_opt(A) ::= . {A = 0;} idlist_opt(A) ::= LP idlist(X) RP. {A = X;} -idlist(A) ::= idlist(X) COMMA nm(Y). - {A = sqlite3IdListAppend(pParse->db,X,&Y);} +idlist(A) ::= idlist(A) COMMA nm(Y). + {A = sqlite3IdListAppend(pParse->db,A,&Y);} idlist(A) ::= nm(Y). {A = sqlite3IdListAppend(pParse->db,0,&Y);} @@ -864,7 +858,7 @@ idlist(A) ::= nm(Y). } } -expr(A) ::= term(X). {A = X;} +expr(A) ::= term(A). expr(A) ::= LP(B) expr(X) RP(E). {A.pExpr = X.pExpr; spanSet(&A,&B,&E);} term(A) ::= NULL(X). {spanExpr(&A, pParse, @X, &X);} expr(A) ::= id(X). {spanExpr(&A, pParse, TK_ID, &X);} @@ -903,9 +897,8 @@ expr(A) ::= VARIABLE(X). { } spanSet(&A, &X, &X); } -expr(A) ::= expr(E) COLLATE ids(C). { - A.pExpr = sqlite3ExprAddCollateToken(pParse, E.pExpr, &C, 1); - A.zStart = E.zStart; +expr(A) ::= expr(A) COLLATE ids(C). { + A.pExpr = sqlite3ExprAddCollateToken(pParse, A.pExpr, &C, 1); A.zEnd = &C.z[C.n]; } %ifndef SQLITE_OMIT_CAST @@ -938,58 +931,56 @@ term(A) ::= CTIME_KW(OP). { ** objects and uses the result to populate a new ExprSpan object. */ static void spanBinaryExpr( - ExprSpan *pOut, /* Write the result here */ Parse *pParse, /* The parsing context. Errors accumulate here */ int op, /* The binary operation */ - ExprSpan *pLeft, /* The left operand */ + ExprSpan *pLeft, /* The left operand, and output */ ExprSpan *pRight /* The right operand */ ){ - pOut->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0); - pOut->zStart = pLeft->zStart; - pOut->zEnd = pRight->zEnd; + pLeft->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0); + pLeft->zEnd = pRight->zEnd; } /* If doNot is true, then add a TK_NOT Expr-node wrapper around the ** outside of *ppExpr. */ - static void exprNot(Parse *pParse, int doNot, Expr **ppExpr){ - if( doNot ) *ppExpr = sqlite3PExpr(pParse, TK_NOT, *ppExpr, 0, 0); + static void exprNot(Parse *pParse, int doNot, ExprSpan *pSpan){ + if( doNot ){ + pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0, 0); + } } } -expr(A) ::= expr(X) AND(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} -expr(A) ::= expr(X) OR(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} -expr(A) ::= expr(X) LT|GT|GE|LE(OP) expr(Y). - {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} -expr(A) ::= expr(X) EQ|NE(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} -expr(A) ::= expr(X) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y). - {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} -expr(A) ::= expr(X) PLUS|MINUS(OP) expr(Y). - {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} -expr(A) ::= expr(X) STAR|SLASH|REM(OP) expr(Y). - {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} -expr(A) ::= expr(X) CONCAT(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} +expr(A) ::= expr(A) AND(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);} +expr(A) ::= expr(A) OR(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);} +expr(A) ::= expr(A) LT|GT|GE|LE(OP) expr(Y). + {spanBinaryExpr(pParse,@OP,&A,&Y);} +expr(A) ::= expr(A) EQ|NE(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);} +expr(A) ::= expr(A) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y). + {spanBinaryExpr(pParse,@OP,&A,&Y);} +expr(A) ::= expr(A) PLUS|MINUS(OP) expr(Y). + {spanBinaryExpr(pParse,@OP,&A,&Y);} +expr(A) ::= expr(A) STAR|SLASH|REM(OP) expr(Y). + {spanBinaryExpr(pParse,@OP,&A,&Y);} +expr(A) ::= expr(A) CONCAT(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);} %type likeop {struct LikeOp} likeop(A) ::= LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 0;} likeop(A) ::= NOT LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 1;} -expr(A) ::= expr(X) likeop(OP) expr(Y). [LIKE_KW] { +expr(A) ::= expr(A) likeop(OP) expr(Y). [LIKE_KW] { ExprList *pList; pList = sqlite3ExprListAppend(pParse,0, Y.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, X.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, A.pExpr); A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator); - exprNot(pParse, OP.bNot, &A.pExpr); - A.zStart = X.zStart; + exprNot(pParse, OP.bNot, &A); A.zEnd = Y.zEnd; if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc; } -expr(A) ::= expr(X) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] { +expr(A) ::= expr(A) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] { ExprList *pList; pList = sqlite3ExprListAppend(pParse,0, Y.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, X.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, A.pExpr); pList = sqlite3ExprListAppend(pParse,pList, E.pExpr); A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator); - exprNot(pParse, OP.bNot, &A.pExpr); - A.zStart = X.zStart; + exprNot(pParse, OP.bNot, &A); A.zEnd = E.zEnd; if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc; } @@ -998,20 +989,18 @@ expr(A) ::= expr(X) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] { /* Construct an expression node for a unary postfix operator */ static void spanUnaryPostfix( - ExprSpan *pOut, /* Write the new expression node here */ Parse *pParse, /* Parsing context to record errors */ int op, /* The operator */ - ExprSpan *pOperand, /* The operand */ + ExprSpan *pOperand, /* The operand, and output */ Token *pPostOp /* The operand token for setting the span */ ){ - pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); - pOut->zStart = pOperand->zStart; - pOut->zEnd = &pPostOp->z[pPostOp->n]; + pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); + pOperand->zEnd = &pPostOp->z[pPostOp->n]; } } -expr(A) ::= expr(X) ISNULL|NOTNULL(E). {spanUnaryPostfix(&A,pParse,@E,&X,&E);} -expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);} +expr(A) ::= expr(A) ISNULL|NOTNULL(E). {spanUnaryPostfix(pParse,@E,&A,&E);} +expr(A) ::= expr(A) NOT NULL(E). {spanUnaryPostfix(pParse,TK_NOTNULL,&A,&E);} %include { /* A routine to convert a binary TK_IS or TK_ISNOT expression into a @@ -1032,12 +1021,12 @@ expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);} // If expr2 is NULL then code as TK_ISNULL or TK_NOTNULL. If expr2 // is any other expression, code as TK_IS or TK_ISNOT. // -expr(A) ::= expr(X) IS expr(Y). { - spanBinaryExpr(&A,pParse,TK_IS,&X,&Y); +expr(A) ::= expr(A) IS expr(Y). { + spanBinaryExpr(pParse,TK_IS,&A,&Y); binaryToUnaryIfNull(pParse, Y.pExpr, A.pExpr, TK_ISNULL); } -expr(A) ::= expr(X) IS NOT expr(Y). { - spanBinaryExpr(&A,pParse,TK_ISNOT,&X,&Y); +expr(A) ::= expr(A) IS NOT expr(Y). { + spanBinaryExpr(pParse,TK_ISNOT,&A,&Y); binaryToUnaryIfNull(pParse, Y.pExpr, A.pExpr, TK_NOTNULL); } @@ -1069,24 +1058,23 @@ expr(A) ::= PLUS(B) expr(X). [BITNOT] %type between_op {int} between_op(A) ::= BETWEEN. {A = 0;} between_op(A) ::= NOT BETWEEN. {A = 1;} -expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { +expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { ExprList *pList = sqlite3ExprListAppend(pParse,0, X.pExpr); pList = sqlite3ExprListAppend(pParse,pList, Y.pExpr); - A.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, W.pExpr, 0, 0); + A.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, A.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - exprNot(pParse, N, &A.pExpr); - A.zStart = W.zStart; + exprNot(pParse, N, &A); A.zEnd = Y.zEnd; } %ifndef SQLITE_OMIT_SUBQUERY %type in_op {int} in_op(A) ::= IN. {A = 0;} in_op(A) ::= NOT IN. {A = 1;} - expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] { + expr(A) ::= expr(A) in_op(N) LP exprlist(Y) RP(E). [IN] { if( Y==0 ){ /* Expressions of the form ** @@ -1096,8 +1084,8 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ + sqlite3ExprDelete(pParse->db, A.pExpr); A.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[N]); - sqlite3ExprDelete(pParse->db, X.pExpr); }else if( Y->nExpr==1 ){ /* Expressions of the form: ** @@ -1124,18 +1112,17 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { pRHS->flags &= ~EP_Collate; pRHS->flags |= EP_Generic; } - A.pExpr = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, X.pExpr, pRHS, 0); + A.pExpr = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, A.pExpr, pRHS, 0); }else{ - A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); + A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = Y; sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); } - exprNot(pParse, N, &A.pExpr); + exprNot(pParse, N, &A); } - A.zStart = X.zStart; A.zEnd = &E.z[E.n]; } expr(A) ::= LP(B) select(X) RP(E). { @@ -1150,8 +1137,8 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A.zStart = B.z; A.zEnd = &E.z[E.n]; } - expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E). [IN] { - A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); + expr(A) ::= expr(A) in_op(N) LP select(Y) RP(E). [IN] { + A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pSelect = Y; ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); @@ -1159,13 +1146,12 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { }else{ sqlite3SelectDelete(pParse->db, Y); } - exprNot(pParse, N, &A.pExpr); - A.zStart = X.zStart; + exprNot(pParse, N, &A); A.zEnd = &E.z[E.n]; } - expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] { + expr(A) ::= expr(A) in_op(N) nm(Y) dbnm(Z). [IN] { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z); - A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); + A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); @@ -1173,8 +1159,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { }else{ sqlite3SrcListDelete(pParse->db, pSrc); } - exprNot(pParse, N, &A.pExpr); - A.zStart = X.zStart; + exprNot(pParse, N, &A); A.zEnd = Z.z ? &Z.z[Z.n] : &Y.z[Y.n]; } expr(A) ::= EXISTS(B) LP select(Y) RP(E). { @@ -1206,8 +1191,8 @@ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { } %type case_exprlist {ExprList*} %destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);} -case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). { - A = sqlite3ExprListAppend(pParse,X, Y.pExpr); +case_exprlist(A) ::= case_exprlist(A) WHEN expr(Y) THEN expr(Z). { + A = sqlite3ExprListAppend(pParse,A, Y.pExpr); A = sqlite3ExprListAppend(pParse,A, Z.pExpr); } case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). { @@ -1228,10 +1213,10 @@ case_operand(A) ::= . {A = 0;} %type nexprlist {ExprList*} %destructor nexprlist {sqlite3ExprListDelete(pParse->db, $$);} -exprlist(A) ::= nexprlist(X). {A = X;} +exprlist(A) ::= nexprlist(A). exprlist(A) ::= . {A = 0;} -nexprlist(A) ::= nexprlist(X) COMMA expr(Y). - {A = sqlite3ExprListAppend(pParse,X,Y.pExpr);} +nexprlist(A) ::= nexprlist(A) COMMA expr(Y). + {A = sqlite3ExprListAppend(pParse,A,Y.pExpr);} nexprlist(A) ::= expr(Y). {A = sqlite3ExprListAppend(pParse,0,Y.pExpr);} @@ -1297,8 +1282,8 @@ uniqueflag(A) ::= . {A = OE_None;} eidlist_opt(A) ::= . {A = 0;} eidlist_opt(A) ::= LP eidlist(X) RP. {A = X;} -eidlist(A) ::= eidlist(X) COMMA nm(Y) collate(C) sortorder(Z). { - A = parserAddExprIdListTerm(pParse, X, &Y, C, Z); +eidlist(A) ::= eidlist(A) COMMA nm(Y) collate(C) sortorder(Z). { + A = parserAddExprIdListTerm(pParse, A, &Y, C, Z); } eidlist(A) ::= nm(Y) collate(C) sortorder(Z). { A = parserAddExprIdListTerm(pParse, 0, &Y, C, Z); @@ -1383,16 +1368,14 @@ when_clause(A) ::= WHEN expr(X). { A = X.pExpr; } %type trigger_cmd_list {TriggerStep*} %destructor trigger_cmd_list {sqlite3DeleteTriggerStep(pParse->db, $$);} -trigger_cmd_list(A) ::= trigger_cmd_list(Y) trigger_cmd(X) SEMI. { - assert( Y!=0 ); - Y->pLast->pNext = X; - Y->pLast = X; - A = Y; +trigger_cmd_list(A) ::= trigger_cmd_list(A) trigger_cmd(X) SEMI. { + assert( A!=0 ); + A->pLast->pNext = X; + A->pLast = X; } -trigger_cmd_list(A) ::= trigger_cmd(X) SEMI. { - assert( X!=0 ); - X->pLast = X; - A = X; +trigger_cmd_list(A) ::= trigger_cmd(A) SEMI. { + assert( A!=0 ); + A->pLast = A; } // Disallow qualified table names on INSERT, UPDATE, and DELETE statements @@ -1400,7 +1383,7 @@ trigger_cmd_list(A) ::= trigger_cmd(X) SEMI. { // the same database as the table that the trigger fires on. // %type trnm {Token} -trnm(A) ::= nm(X). {A = X;} +trnm(A) ::= nm(A). trnm(A) ::= nm DOT nm(X). { A = X; sqlite3ErrorMsg(pParse, @@ -1557,7 +1540,7 @@ with(A) ::= WITH RECURSIVE wqlist(W). { A = W; } wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. { A = sqlite3WithAdd(pParse, 0, &X, Y, Z); } -wqlist(A) ::= wqlist(W) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. { - A = sqlite3WithAdd(pParse, W, &X, Y, Z); +wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. { + A = sqlite3WithAdd(pParse, A, &X, Y, Z); } %endif SQLITE_OMIT_CTE diff --git a/tool/lemon.c b/tool/lemon.c index d704deb624..c678fa0da6 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -286,6 +286,8 @@ struct rule { const char **rhsalias; /* An alias for each RHS symbol (NULL if none) */ int line; /* Line number at which code begins */ const char *code; /* The code executed when this rule is reduced */ + const char *codePrefix; /* Setup code before code[] above */ + const char *codeSuffix; /* Breakdown code after code[] above */ struct symbol *precsym; /* Precedence symbol for this rule */ int index; /* An index number for this rule */ Boolean canReduce; /* True if this rule is ever reduced */ @@ -3430,6 +3432,7 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){ int c; char zInt[40]; if( zText==0 ){ + if( used==0 && z!=0 ) z[0] = 0; used = 0; return z; } @@ -3471,7 +3474,9 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){ char *cp, *xp; int i; char lhsused = 0; /* True if the LHS element has been used */ + char lhsdirect; /* True if LHS writes directly into stack */ char used[MAXRHS]; /* True for each RHS element which is used */ + char zLhs[50]; /* Convert the LHS symbol into this string */ for(i=0; inrhs; i++) used[i] = 0; lhsused = 0; @@ -3482,6 +3487,48 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){ rp->line = rp->ruleline; } + + if( rp->lhsalias==0 ){ + /* There is no LHS value symbol. */ + lhsdirect = 1; + }else if( rp->nrhs==0 ){ + /* If there are no RHS symbols, then writing directly to the LHS is ok */ + lhsdirect = 1; + }else if( rp->rhsalias[0]==0 ){ + /* The left-most RHS symbol has not value. LHS direct is ok. But + ** we have to call the distructor on the RHS symbol first. */ + lhsdirect = 1; + if( has_destructor(rp->rhs[0],lemp) ){ + append_str(0,0,0,0); + append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0, + rp->rhs[0]->index,1-rp->nrhs); + rp->codePrefix = Strsafe(append_str(0,0,0,0)); + } + }else if( strcmp(rp->lhsalias,rp->rhsalias[0])==0 ){ + /* The LHS symbol and the left-most RHS symbol are the same, so + ** direct writing is allowed */ + lhsdirect = 1; + lhsused = 1; + used[0] = 1; + if( rp->lhs->dtnum!=rp->rhs[0]->dtnum ){ + ErrorMsg(lemp->filename,rp->ruleline, + "%s(%s) and %s(%s) share the same label but have " + "different datatypes.", + rp->lhs->name, rp->lhsalias, rp->rhs[0]->name, rp->rhsalias[0]); + lemp->errorcnt++; + } + }else{ + lhsdirect = 0; + } + if( lhsdirect ){ + sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum); + }else{ + append_str(0,0,0,0); + append_str(" YYMINORTYPE yylhsminor;\n", 0, 0, 0); + rp->codePrefix = Strsafe(append_str(0,0,0,0)); + sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum); + } + append_str(0,0,0,0); /* This const cast is wrong but harmless, if we're careful. */ @@ -3492,7 +3539,7 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){ saved = *xp; *xp = 0; if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ - append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0); + append_str(zLhs,0,0,0); cp = xp; lhsused = 1; }else{ @@ -3523,6 +3570,11 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){ append_str(cp, 1, 0, 0); } /* End loop */ + /* Main code generation completed */ + cp = append_str(0,0,0,0); + if( cp && cp[0] ) rp->code = Strsafe(cp); + append_str(0,0,0,0); + /* Check to make sure the LHS has been used */ if( rp->lhsalias && !lhsused ){ ErrorMsg(lemp->filename,rp->ruleline, @@ -3531,27 +3583,53 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){ lemp->errorcnt++; } - /* Generate destructor code for RHS symbols which are not used in the - ** reduce code */ + /* Generate destructor code for RHS minor values which are not referenced. + ** Generate error messages for unused labels and duplicate labels. + */ for(i=0; inrhs; i++){ - if( rp->rhsalias[i] && !used[i] ){ - ErrorMsg(lemp->filename,rp->ruleline, - "Label %s for \"%s(%s)\" is never used.", - rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]); - lemp->errorcnt++; - }else if( rp->rhsalias[i]==0 ){ - if( has_destructor(rp->rhs[i],lemp) ){ - append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0, - rp->rhs[i]->index,i-rp->nrhs+1); - }else{ - /* No destructor defined for this term */ + if( rp->rhsalias[i] ){ + if( i>0 ){ + int j; + if( rp->lhsalias && strcmp(rp->lhsalias,rp->rhsalias[i])==0 ){ + ErrorMsg(lemp->filename,rp->ruleline, + "%s(%s) has the same label as the LHS but is not the left-most " + "symbol on the RHS.", + rp->rhs[i]->name, rp->rhsalias); + lemp->errorcnt++; + } + for(j=0; jrhsalias[j] && strcmp(rp->rhsalias[j],rp->rhsalias[i])==0 ){ + ErrorMsg(lemp->filename,rp->ruleline, + "Label %s used for multiple symbols on the RHS of a rule.", + rp->rhsalias[i]); + lemp->errorcnt++; + break; + } + } } + if( !used[i] ){ + ErrorMsg(lemp->filename,rp->ruleline, + "Label %s for \"%s(%s)\" is never used.", + rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]); + lemp->errorcnt++; + } + }else if( i>0 && has_destructor(rp->rhs[i],lemp) ){ + append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0, + rp->rhs[i]->index,i-rp->nrhs+1); } } - if( rp->code ){ - cp = append_str(0,0,0,0); - rp->code = Strsafe(cp?cp:""); + + /* If unable to write LHS values directly into the stack, write the + ** saved LHS value now. */ + if( lhsdirect==0 ){ + append_str(" yymsp[%d].minor.yy%d = ", 0, 1-rp->nrhs, rp->lhs->dtnum); + append_str(zLhs, 0, 0, 0); + append_str(";\n", 0, 0, 0); } + + /* Suffix code generation complete */ + cp = append_str(0,0,0,0); + if( cp ) rp->codeSuffix = Strsafe(cp); } /* @@ -3566,6 +3644,12 @@ PRIVATE void emit_code( ){ const char *cp; + /* Setup code prior to the #line directive */ + if( rp->codePrefix && rp->codePrefix[0] ){ + fprintf(out, "{%s", rp->codePrefix); + for(cp=rp->codePrefix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; } + } + /* Generate code to do the reduce action */ if( rp->code ){ if( !lemp->nolinenosflag ){ @@ -3573,15 +3657,23 @@ PRIVATE void emit_code( tplt_linedir(out,rp->line,lemp->filename); } fprintf(out,"{%s",rp->code); - for(cp=rp->code; *cp; cp++){ - if( *cp=='\n' ) (*lineno)++; - } /* End loop */ + for(cp=rp->code; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; } fprintf(out,"}\n"); (*lineno)++; if( !lemp->nolinenosflag ){ (*lineno)++; tplt_linedir(out,*lineno,lemp->outname); } - } /* End if( rp->code ) */ + } + + /* Generate breakdown code that occurs after the #line directive */ + if( rp->codeSuffix && rp->codeSuffix[0] ){ + fprintf(out, "%s", rp->codeSuffix); + for(cp=rp->codeSuffix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; } + } + + if( rp->codePrefix ){ + fprintf(out, "}\n"); (*lineno)++; + } return; } diff --git a/tool/lempar.c b/tool/lempar.c index c5b65d645d..0f25d76037 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -614,7 +614,6 @@ static void yy_reduce( ){ int yygoto; /* The next state */ int yyact; /* The next action */ - YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ ParseARG_FETCH; @@ -677,7 +676,6 @@ static void yy_reduce( yymsp -= yysize-1; yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; - yymsp->minor = yygotominor; yyTraceShift(yypParser, yyact); }else{ assert( yyact == YY_ACCEPT_ACTION ); From dabd04c656f37ef45786c25cb73bf8b517303eda Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 17 Feb 2016 01:46:19 +0000 Subject: [PATCH 301/570] Further improvements to the Lemon-generated code for yy_reduce(). FossilOrigin-Name: ef95a7d6490e33a9af4bc7b4b622de7328742ca7 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/parse.y | 6 ++---- tool/lemon.c | 18 +++++++++++++----- tool/lempar.c | 1 - 5 files changed, 24 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 32bf38b889..afad0890ac 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sLemon,\sadd\sthe\sability\sfor\sthe\sleft-most\sRHS\slabel\sto\sbe\sthe\ssame\sas\sthe\nLHS\slabel,\scausing\sthe\sLHS\svalues\sto\sbe\swritten\sdirectly\sinto\sthe\sstack. -D 2016-02-17T01:18:33.698 +C Further\simprovements\sto\sthe\sLemon-generated\scode\sfor\syy_reduce(). +D 2016-02-17T01:46:19.413 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -337,7 +337,7 @@ F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 6812f3803951774b56abded396171e1c12b0b003 F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 -F src/parse.y eb7d241ca23d6035e5f902de571bb066884fd4ca +F src/parse.y b845cfc4ba7d96b843856007a3c09c5b7ca2878f F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 @@ -1378,8 +1378,8 @@ F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce -F tool/lemon.c 501104fc7fbb01a86078841bed704184ccfd6036 -F tool/lempar.c 08bbb0fbca9c1f61d2a20a7af893110aefd571a0 +F tool/lemon.c 61844c3d01865473bce2dc8134e17346cda07000 +F tool/lempar.c c7dde8fae568759a1a136b1acf35c4084864d035 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh c78caa3214f25dc28ea157b5a82abb311f209906 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a65d583ce97b8c08157268bd054479cda3957a94 -R e1ed8179ef03a39381f66ed9ce3ecd2f +P 4bb94c7c4c3cb3ccad72c2451d88684130dde845 +R 8570435db7ea690b60e76be3d8d02f8b U drh -Z a9c8340faee95f29d20e3673b4598420 +Z bc476c236d739b2c3e79f3d57d12535c diff --git a/manifest.uuid b/manifest.uuid index 9f1cd50eb1..e8f5fde5d6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4bb94c7c4c3cb3ccad72c2451d88684130dde845 \ No newline at end of file +ef95a7d6490e33a9af4bc7b4b622de7328742ca7 \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index b48ed526d4..cf9bc0f2bb 100644 --- a/src/parse.y +++ b/src/parse.y @@ -163,10 +163,8 @@ cmd ::= create_table create_table_args. create_table ::= createkw temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z). { sqlite3StartTable(pParse,&Y,&Z,T,0,0,E); } -createkw(A) ::= CREATE(X). { - disableLookaside(pParse); - A = X; -} +createkw(A) ::= CREATE(A). {disableLookaside(pParse);} + %type ifnotexists {int} ifnotexists(A) ::= . {A = 0;} ifnotexists(A) ::= IF NOT EXISTS. {A = 1;} diff --git a/tool/lemon.c b/tool/lemon.c index c678fa0da6..1f81717c7c 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -3469,10 +3469,14 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){ ** zCode is a string that is the action associated with a rule. Expand ** the symbols in this string so that the refer to elements of the parser ** stack. +** +** Return 1 if the expanded code requires that "yylhsminor" local variable +** to be defined. */ -PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){ +PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ char *cp, *xp; int i; + int rc = 0; /* True if yylhsminor is used */ char lhsused = 0; /* True if the LHS element has been used */ char lhsdirect; /* True if LHS writes directly into stack */ char used[MAXRHS]; /* True for each RHS element which is used */ @@ -3523,9 +3527,7 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){ if( lhsdirect ){ sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum); }else{ - append_str(0,0,0,0); - append_str(" YYMINORTYPE yylhsminor;\n", 0, 0, 0); - rp->codePrefix = Strsafe(append_str(0,0,0,0)); + rc = 1; sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum); } @@ -3630,6 +3632,8 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){ /* Suffix code generation complete */ cp = append_str(0,0,0,0); if( cp ) rp->codeSuffix = Strsafe(cp); + + return rc; } /* @@ -4298,8 +4302,12 @@ void ReportTable( tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which execution during each REDUCE action */ + i = 0; for(rp=lemp->rule; rp; rp=rp->next){ - translate_code(lemp, rp); + i += translate_code(lemp, rp); + } + if( i ){ + fprintf(out," YYMINORTYPE yylhsminor;\n"); lineno++; } /* First output rules other than the default: rule */ for(rp=lemp->rule; rp; rp=rp->next){ diff --git a/tool/lempar.c b/tool/lempar.c index 0f25d76037..1d76779b5e 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -626,7 +626,6 @@ static void yy_reduce( yyRuleName[yyruleno], yymsp[-yysize].stateno); } #endif /* NDEBUG */ - /* yygotominor = yyzerominor; */ /* Check that the stack is large enough to grow by a single entry ** if the RHS of the rule is empty. This ensures that there is room From cf82f0d3d2606af4caff3845240dceb4c7c4d25c Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 17 Feb 2016 04:33:10 +0000 Subject: [PATCH 302/570] Enhance Lemon so that if reduce code contains a comment of the form "/*A-overwrites-X*/" then a LHS label A is allowed to overwrite the RHS label X. FossilOrigin-Name: 5cfe9545d478a2c500083613dd20e14b2ffce645 --- manifest | 14 +++++------ manifest.uuid | 2 +- src/parse.y | 70 ++++++++++++++++++++++++++------------------------- tool/lemon.c | 28 ++++++++++++++++----- 4 files changed, 66 insertions(+), 48 deletions(-) diff --git a/manifest b/manifest index afad0890ac..c34c4dda4b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\simprovements\sto\sthe\sLemon-generated\scode\sfor\syy_reduce(). -D 2016-02-17T01:46:19.413 +C Enhance\sLemon\sso\sthat\sif\sreduce\scode\scontains\sa\scomment\sof\sthe\sform\n"/*A-overwrites-X*/"\sthen\sa\sLHS\slabel\sA\sis\sallowed\sto\soverwrite\sthe\nRHS\slabel\sX. +D 2016-02-17T04:33:10.506 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -337,7 +337,7 @@ F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 6812f3803951774b56abded396171e1c12b0b003 F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 -F src/parse.y b845cfc4ba7d96b843856007a3c09c5b7ca2878f +F src/parse.y 8c2f7e7e12cb03ddeaa204463198978aab2dcde9 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 @@ -1378,7 +1378,7 @@ F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce -F tool/lemon.c 61844c3d01865473bce2dc8134e17346cda07000 +F tool/lemon.c 31a7325a4407fa35af7e5913b67517debae8181b F tool/lempar.c c7dde8fae568759a1a136b1acf35c4084864d035 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4bb94c7c4c3cb3ccad72c2451d88684130dde845 -R 8570435db7ea690b60e76be3d8d02f8b +P ef95a7d6490e33a9af4bc7b4b622de7328742ca7 +R f9d92e1ecf92fd9298e3c4ee80590b18 U drh -Z bc476c236d739b2c3e79f3d57d12535c +Z 42e27a9e216e6c463abe3b883471bdc4 diff --git a/manifest.uuid b/manifest.uuid index e8f5fde5d6..2c12f2f200 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ef95a7d6490e33a9af4bc7b4b622de7328742ca7 \ No newline at end of file +5cfe9545d478a2c500083613dd20e14b2ffce645 \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index cf9bc0f2bb..f1060305ee 100644 --- a/src/parse.y +++ b/src/parse.y @@ -138,9 +138,9 @@ trans_opt ::= TRANSACTION. trans_opt ::= TRANSACTION nm. %type transtype {int} transtype(A) ::= . {A = TK_DEFERRED;} -transtype(A) ::= DEFERRED(X). {A = @X;} -transtype(A) ::= IMMEDIATE(X). {A = @X;} -transtype(A) ::= EXCLUSIVE(X). {A = @X;} +transtype(A) ::= DEFERRED(X). {A = @X; /*A-overwrites-X*/} +transtype(A) ::= IMMEDIATE(X). {A = @X; /*A-overwrites-X*/} +transtype(A) ::= EXCLUSIVE(X). {A = @X; /*A-overwrites-X*/} cmd ::= COMMIT trans_opt. {sqlite3CommitTransaction(pParse);} cmd ::= END trans_opt. {sqlite3CommitTransaction(pParse);} cmd ::= ROLLBACK trans_opt. {sqlite3RollbackTransaction(pParse);} @@ -456,7 +456,7 @@ select(A) ::= with(W) selectnowith(X). { }else{ sqlite3WithDelete(pParse->db, W); } - A = p; + A = p; /*A-overwrites-W*/ } selectnowith(A) ::= oneselect(A). @@ -484,9 +484,9 @@ selectnowith(A) ::= selectnowith(A) multiselect_op(Y) oneselect(Z). { A = pRhs; } %type multiselect_op {int} -multiselect_op(A) ::= UNION(OP). {A = @OP;} +multiselect_op(A) ::= UNION(OP). {A = @OP; /*A-overwrites-OP*/} multiselect_op(A) ::= UNION ALL. {A = TK_ALL;} -multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP;} +multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP; /*A-overwrites-OP*/} %endif SQLITE_OMIT_COMPOUND_SELECT oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y) groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). { @@ -648,14 +648,17 @@ dbnm(A) ::= DOT nm(X). {A = X;} %type fullname {SrcList*} %destructor fullname {sqlite3SrcListDelete(pParse->db, $$);} -fullname(A) ::= nm(X) dbnm(Y). {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y);} +fullname(A) ::= nm(X) dbnm(Y). + {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/} %type joinop {int} joinop(X) ::= COMMA|JOIN. { X = JT_INNER; } -joinop(X) ::= JOIN_KW(A) JOIN. { X = sqlite3JoinType(pParse,&A,0,0); } -joinop(X) ::= JOIN_KW(A) nm(B) JOIN. { X = sqlite3JoinType(pParse,&A,&B,0); } +joinop(X) ::= JOIN_KW(A) JOIN. + {X = sqlite3JoinType(pParse,&A,0,0); /*X-overwrites-A*/} +joinop(X) ::= JOIN_KW(A) nm(B) JOIN. + {X = sqlite3JoinType(pParse,&A,&B,0); /*X-overwrites-A*/} joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN. - { X = sqlite3JoinType(pParse,&A,&B,&C); } + {X = sqlite3JoinType(pParse,&A,&B,&C);/*X-overwrites-A*/} %type on_opt {Expr*} %destructor on_opt {sqlite3ExprDelete(pParse->db, $$);} @@ -700,7 +703,7 @@ sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z). { sqlite3ExprListSetSortOrder(A,Z); } sortlist(A) ::= expr(Y) sortorder(Z). { - A = sqlite3ExprListAppend(pParse,0,Y.pExpr); + A = sqlite3ExprListAppend(pParse,0,Y.pExpr); /*A-overwrites-Y*/ sqlite3ExprListSetSortOrder(A,Z); } @@ -825,7 +828,7 @@ idlist_opt(A) ::= LP idlist(X) RP. {A = X;} idlist(A) ::= idlist(A) COMMA nm(Y). {A = sqlite3IdListAppend(pParse->db,A,&Y);} idlist(A) ::= nm(Y). - {A = sqlite3IdListAppend(pParse->db,0,&Y);} + {A = sqlite3IdListAppend(pParse->db,0,&Y); /*A-overwrites-Y*/} /////////////////////////// Expression Processing ///////////////////////////// // @@ -864,16 +867,16 @@ expr(A) ::= JOIN_KW(X). {spanExpr(&A, pParse, TK_ID, &X);} expr(A) ::= nm(X) DOT nm(Y). { Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y); + spanSet(&A,&X,&Y); /*A-overwrites-X*/ A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); - spanSet(&A,&X,&Y); } expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). { Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y); Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Z); Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); + spanSet(&A,&X,&Z); /*A-overwrites-X*/ A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); - spanSet(&A,&X,&Z); } term(A) ::= INTEGER|FLOAT|BLOB(X). {spanExpr(&A, pParse, @X, &X);} term(A) ::= STRING(X). {spanExpr(&A, pParse, @X, &X);} @@ -961,7 +964,7 @@ expr(A) ::= expr(A) STAR|SLASH|REM(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);} expr(A) ::= expr(A) CONCAT(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);} %type likeop {struct LikeOp} -likeop(A) ::= LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 0;} +likeop(A) ::= LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 0;/*A-overwrites-X*/} likeop(A) ::= NOT LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 1;} expr(A) ::= expr(A) likeop(OP) expr(Y). [LIKE_KW] { ExprList *pList; @@ -1203,7 +1206,7 @@ case_else(A) ::= ELSE expr(X). {A = X.pExpr;} case_else(A) ::= . {A = 0;} %type case_operand {Expr*} %destructor case_operand {sqlite3ExprDelete(pParse->db, $$);} -case_operand(A) ::= expr(X). {A = X.pExpr;} +case_operand(A) ::= expr(X). {A = X.pExpr; /*A-overwrites-X*/} case_operand(A) ::= . {A = 0;} %type exprlist {ExprList*} @@ -1216,7 +1219,7 @@ exprlist(A) ::= . {A = 0;} nexprlist(A) ::= nexprlist(A) COMMA expr(Y). {A = sqlite3ExprListAppend(pParse,A,Y.pExpr);} nexprlist(A) ::= expr(Y). - {A = sqlite3ExprListAppend(pParse,0,Y.pExpr);} + {A = sqlite3ExprListAppend(pParse,0,Y.pExpr); /*A-overwrites-Y*/} ///////////////////////////// The CREATE INDEX command /////////////////////// @@ -1284,7 +1287,7 @@ eidlist(A) ::= eidlist(A) COMMA nm(Y) collate(C) sortorder(Z). { A = parserAddExprIdListTerm(pParse, A, &Y, C, Z); } eidlist(A) ::= nm(Y) collate(C) sortorder(Z). { - A = parserAddExprIdListTerm(pParse, 0, &Y, C, Z); + A = parserAddExprIdListTerm(pParse, 0, &Y, C, Z); /*A-overwrites-Y*/ } %type collate {int} @@ -1316,15 +1319,15 @@ cmd ::= PRAGMA nm(X) dbnm(Z) EQ minus_num(Y). cmd ::= PRAGMA nm(X) dbnm(Z) LP minus_num(Y) RP. {sqlite3Pragma(pParse,&X,&Z,&Y,1);} -nmnum(A) ::= plus_num(X). {A = X;} -nmnum(A) ::= nm(X). {A = X;} -nmnum(A) ::= ON(X). {A = X;} -nmnum(A) ::= DELETE(X). {A = X;} -nmnum(A) ::= DEFAULT(X). {A = X;} +nmnum(A) ::= plus_num(A). +nmnum(A) ::= nm(A). +nmnum(A) ::= ON(A). +nmnum(A) ::= DELETE(A). +nmnum(A) ::= DEFAULT(A). %endif SQLITE_OMIT_PRAGMA %token_class number INTEGER|FLOAT. plus_num(A) ::= PLUS number(X). {A = X;} -plus_num(A) ::= number(X). {A = X;} +plus_num(A) ::= number(A). minus_num(A) ::= MINUS number(X). {A = X;} //////////////////////////// The CREATE TRIGGER command ///////////////////// @@ -1341,7 +1344,7 @@ trigger_decl(A) ::= temp(T) TRIGGER ifnotexists(NOERR) nm(B) dbnm(Z) trigger_time(C) trigger_event(D) ON fullname(E) foreach_clause when_clause(G). { sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, G, T, NOERR); - A = (Z.n==0?B:Z); + A = (Z.n==0?B:Z); /*A-overwrites-T*/ } %type trigger_time {int} @@ -1352,9 +1355,9 @@ trigger_time(A) ::= . { A = TK_BEFORE; } %type trigger_event {struct TrigEvent} %destructor trigger_event {sqlite3IdListDelete(pParse->db, $$.b);} -trigger_event(A) ::= DELETE|INSERT(OP). {A.a = @OP; A.b = 0;} -trigger_event(A) ::= UPDATE(OP). {A.a = @OP; A.b = 0;} -trigger_event(A) ::= UPDATE OF idlist(X). {A.a = TK_UPDATE; A.b = X;} +trigger_event(A) ::= DELETE|INSERT(X). {A.a = @X; /*A-overwrites-X*/ A.b = 0;} +trigger_event(A) ::= UPDATE(X). {A.a = @X; /*A-overwrites-X*/ A.b = 0;} +trigger_event(A) ::= UPDATE OF idlist(X).{A.a = TK_UPDATE; A.b = X;} foreach_clause ::= . foreach_clause ::= FOR EACH ROW. @@ -1423,24 +1426,23 @@ trigger_cmd(A) ::= DELETE FROM trnm(X) tridxby where_opt(Y). {A = sqlite3TriggerDeleteStep(pParse->db, &X, Y);} // SELECT -trigger_cmd(A) ::= select(X). {A = sqlite3TriggerSelectStep(pParse->db, X); } +trigger_cmd(A) ::= select(X). + {A = sqlite3TriggerSelectStep(pParse->db, X); /*A-overwrites-X*/} // The special RAISE expression that may occur in trigger programs expr(A) ::= RAISE(X) LP IGNORE RP(Y). { + spanSet(&A,&X,&Y); /*A-overwrites-X*/ A.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); if( A.pExpr ){ A.pExpr->affinity = OE_Ignore; } - A.zStart = X.z; - A.zEnd = &Y.z[Y.n]; } expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y). { + spanSet(&A,&X,&Y); /*A-overwrites-X*/ A.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &Z); if( A.pExpr ) { A.pExpr->affinity = (char)T; } - A.zStart = X.z; - A.zEnd = &Y.z[Y.n]; } %endif !SQLITE_OMIT_TRIGGER @@ -1536,7 +1538,7 @@ with(A) ::= WITH wqlist(W). { A = W; } with(A) ::= WITH RECURSIVE wqlist(W). { A = W; } wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. { - A = sqlite3WithAdd(pParse, 0, &X, Y, Z); + A = sqlite3WithAdd(pParse, 0, &X, Y, Z); /*A-overwrites-X*/ } wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. { A = sqlite3WithAdd(pParse, A, &X, Y, Z); diff --git a/tool/lemon.c b/tool/lemon.c index 1f81717c7c..1058d14ae6 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -3476,11 +3476,13 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ char *cp, *xp; int i; - int rc = 0; /* True if yylhsminor is used */ - char lhsused = 0; /* True if the LHS element has been used */ - char lhsdirect; /* True if LHS writes directly into stack */ - char used[MAXRHS]; /* True for each RHS element which is used */ - char zLhs[50]; /* Convert the LHS symbol into this string */ + int rc = 0; /* True if yylhsminor is used */ + const char *zSkip = 0; /* The zOvwrt comment within rp->code, or NULL */ + char lhsused = 0; /* True if the LHS element has been used */ + char lhsdirect; /* True if LHS writes directly into stack */ + char used[MAXRHS]; /* True for each RHS element which is used */ + char zLhs[50]; /* Convert the LHS symbol into this string */ + char zOvwrt[900]; /* Comment that to allow LHS to overwrite RHS */ for(i=0; inrhs; i++) used[i] = 0; lhsused = 0; @@ -3522,7 +3524,16 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ lemp->errorcnt++; } }else{ - lhsdirect = 0; + lemon_sprintf(zOvwrt, "/*%s-overwrites-%s*/", + rp->lhsalias, rp->rhsalias[0]); + zSkip = strstr(rp->code, zOvwrt); + if( zSkip!=0 ){ + /* The code contains a special comment that indicates that it is safe + ** for the LHS label to overwrite left-most RHS label. */ + lhsdirect = 1; + }else{ + lhsdirect = 0; + } } if( lhsdirect ){ sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum); @@ -3535,6 +3546,11 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ /* This const cast is wrong but harmless, if we're careful. */ for(cp=(char *)rp->code; *cp; cp++){ + if( cp==zSkip ){ + append_str(zOvwrt,0,0,0); + cp += lemonStrlen(zOvwrt)-1; + continue; + } if( ISALPHA(*cp) && (cp==rp->code || (!ISALNUM(cp[-1]) && cp[-1]!='_')) ){ char saved; for(xp= &cp[1]; ISALNUM(*xp) || *xp=='_'; xp++); From 0ccbc64fd6d3355f0f897de202faab9f1e5a7a9d Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 17 Feb 2016 11:13:20 +0000 Subject: [PATCH 303/570] Documentation typo on sqlite3_wal_hook(). No changes to code. FossilOrigin-Name: fc2043ebaa3f106529500164936bb82f9b921b1c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqlite.h.in | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 86aa0b58ec..12fd666b91 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\ssimplification\sto\sthe\stokenizer.\s\sSlightly\ssmaller\sand\sfaster. -D 2016-02-16T13:04:19.100 +C Documentation\stypo\son\ssqlite3_wal_hook().\s\sNo\schanges\sto\scode. +D 2016-02-17T11:13:20.401 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -350,7 +350,7 @@ F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 1a7e23a3bb2edb9cdc46ab0cf7c1500109cf2531 F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe -F src/sqlite.h.in f80c6ebd85588fc514bfedf3ecb00cec269cb410 +F src/sqlite.h.in a7caa805a345d6a14136c11ccfa6f4c1a6ef6e7b F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d F src/sqliteInt.h 47f61c35d587d38cbcfc8ba852ff441054d697d3 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9235b0cf6a37712ae9e5deeb1e5ee064dd5511fa -R a61b67e5f930748de130d8b41c0bc53a +P 9570b6b43df3bc5ce314cded20bca8be9e968efe +R fa7ad000641c654ec7b23cbb3e1a9847 U drh -Z d1a1b630582c40b1f2edd9cd2e01402a +Z 6e5104d61f82ea485c4100026aadb443 diff --git a/manifest.uuid b/manifest.uuid index ee978cebbb..2b73547074 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9570b6b43df3bc5ce314cded20bca8be9e968efe \ No newline at end of file +fc2043ebaa3f106529500164936bb82f9b921b1c \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 9e7222bd50..dcbda15ce5 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7489,7 +7489,7 @@ void sqlite3_log(int iErrCode, const char *zFormat, ...); ** previously registered write-ahead log callback. ^Note that the ** [sqlite3_wal_autocheckpoint()] interface and the ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will -** those overwrite any prior [sqlite3_wal_hook()] settings. +** overwrite any prior [sqlite3_wal_hook()] settings. */ void *sqlite3_wal_hook( sqlite3*, From 43303de97e768a987db5a389985a97dad553f988 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 17 Feb 2016 12:34:03 +0000 Subject: [PATCH 304/570] More agressive use of /*A-overwrites-X*/ in the parser. Fix an off-by-one error in parser stack overflow detection. FossilOrigin-Name: 417e777701bbf4bd67626d4ca3bc2c5d847f6cd0 --- manifest | 16 +++++------ manifest.uuid | 2 +- src/parse.y | 75 +++++++++++++++++++++++++++------------------------ tool/lemon.c | 9 ++++++- tool/lempar.c | 6 ++--- 5 files changed, 60 insertions(+), 48 deletions(-) diff --git a/manifest b/manifest index c34c4dda4b..1da9e5e200 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sLemon\sso\sthat\sif\sreduce\scode\scontains\sa\scomment\sof\sthe\sform\n"/*A-overwrites-X*/"\sthen\sa\sLHS\slabel\sA\sis\sallowed\sto\soverwrite\sthe\nRHS\slabel\sX. -D 2016-02-17T04:33:10.506 +C More\sagressive\suse\sof\s/*A-overwrites-X*/\sin\sthe\sparser.\s\sFix\san\soff-by-one\nerror\sin\sparser\sstack\soverflow\sdetection. +D 2016-02-17T12:34:03.961 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -337,7 +337,7 @@ F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 6812f3803951774b56abded396171e1c12b0b003 F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 -F src/parse.y 8c2f7e7e12cb03ddeaa204463198978aab2dcde9 +F src/parse.y c3ce2c4a7cbf0b699239be6b2a945c5cb51875e2 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 @@ -1378,8 +1378,8 @@ F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce -F tool/lemon.c 31a7325a4407fa35af7e5913b67517debae8181b -F tool/lempar.c c7dde8fae568759a1a136b1acf35c4084864d035 +F tool/lemon.c 251f5c3f21b553240cbdd42dd187a51bb2372cd3 +F tool/lempar.c 5f626c741e034da827b4224d0c68eaf6d8fcc72c F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh c78caa3214f25dc28ea157b5a82abb311f209906 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ef95a7d6490e33a9af4bc7b4b622de7328742ca7 -R f9d92e1ecf92fd9298e3c4ee80590b18 +P 5cfe9545d478a2c500083613dd20e14b2ffce645 +R d924bff2a49f13e938a4912c2ba811f7 U drh -Z 42e27a9e216e6c463abe3b883471bdc4 +Z be09b78429c9c8eaf29c2a1ea6a1c05b diff --git a/manifest.uuid b/manifest.uuid index 2c12f2f200..329508012e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5cfe9545d478a2c500083613dd20e14b2ffce645 \ No newline at end of file +417e777701bbf4bd67626d4ca3bc2c5d847f6cd0 \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index f1060305ee..e7e0d1d953 100644 --- a/src/parse.y +++ b/src/parse.y @@ -302,7 +302,7 @@ ccons ::= DEFAULT MINUS(A) term(X). { } ccons ::= DEFAULT id(X). { ExprSpan v; - spanExpr(&v, pParse, TK_STRING, &X); + spanExpr(&v, pParse, TK_STRING, X); sqlite3AddDefaultValue(pParse,&v); } @@ -490,6 +490,9 @@ multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP; /*A-overwrites-OP*/} %endif SQLITE_OMIT_COMPOUND_SELECT oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y) groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). { +#if SELECTTRACE_ENABLED + Token s = S; /*A-overwrites-S*/ +#endif A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L.pLimit,L.pOffset); #if SELECTTRACE_ENABLED /* Populate the Select.zSelName[] string that is used to help with @@ -502,7 +505,7 @@ oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y) ** is an integer that is incremented with each SELECT statement seen. */ if( A!=0 ){ - const char *z = S.z+6; + const char *z = s.z+6; int i; sqlite3_snprintf(sizeof(A->zSelName), A->zSelName, "#%d", ++pParse->nSelect); @@ -852,18 +855,19 @@ idlist(A) ::= nm(Y). ** new Expr to populate pOut. Set the span of pOut to be the identifier ** that created the expression. */ - static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token *pValue){ - pOut->pExpr = sqlite3PExpr(pParse, op, 0, 0, pValue); - pOut->zStart = pValue->z; - pOut->zEnd = &pValue->z[pValue->n]; + static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token t){ + pOut->pExpr = sqlite3PExpr(pParse, op, 0, 0, &t); + pOut->zStart = t.z; + pOut->zEnd = &t.z[t.n]; } } expr(A) ::= term(A). -expr(A) ::= LP(B) expr(X) RP(E). {A.pExpr = X.pExpr; spanSet(&A,&B,&E);} -term(A) ::= NULL(X). {spanExpr(&A, pParse, @X, &X);} -expr(A) ::= id(X). {spanExpr(&A, pParse, TK_ID, &X);} -expr(A) ::= JOIN_KW(X). {spanExpr(&A, pParse, TK_ID, &X);} +expr(A) ::= LP(B) expr(X) RP(E). + {spanSet(&A,&B,&E); /*A-overwrites-B*/ A.pExpr = X.pExpr;} +term(A) ::= NULL(X). {spanExpr(&A,pParse,@X,X);/*A-overwrites-X*/} +expr(A) ::= id(X). {spanExpr(&A,pParse,TK_ID,X); /*A-overwrites-X*/} +expr(A) ::= JOIN_KW(X). {spanExpr(&A,pParse,TK_ID,X); /*A-overwrites-X*/} expr(A) ::= nm(X) DOT nm(Y). { Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y); @@ -878,25 +882,26 @@ expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). { spanSet(&A,&X,&Z); /*A-overwrites-X*/ A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); } -term(A) ::= INTEGER|FLOAT|BLOB(X). {spanExpr(&A, pParse, @X, &X);} -term(A) ::= STRING(X). {spanExpr(&A, pParse, @X, &X);} +term(A) ::= INTEGER|FLOAT|BLOB(X). {spanExpr(&A,pParse,@X,X);/*A-overwrites-X*/} +term(A) ::= STRING(X). {spanExpr(&A,pParse,@X,X);/*A-overwrites-X*/} expr(A) ::= VARIABLE(X). { - if( X.n>=2 && X.z[0]=='#' && sqlite3Isdigit(X.z[1]) ){ + Token t = X; /*A-overwrites-X*/ + if( t.n>=2 && t.z[0]=='#' && sqlite3Isdigit(t.z[1]) ){ /* When doing a nested parse, one can include terms in an expression ** that look like this: #1 #2 ... These terms refer to registers ** in the virtual machine. #N is the N-th register. */ + spanSet(&A, &t, &t); if( pParse->nested==0 ){ - sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &X); + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); A.pExpr = 0; }else{ - A.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &X); - if( A.pExpr ) sqlite3GetInt32(&X.z[1], &A.pExpr->iTable); + A.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &t); + if( A.pExpr ) sqlite3GetInt32(&t.z[1], &A.pExpr->iTable); } }else{ - spanExpr(&A, pParse, TK_VARIABLE, &X); + spanExpr(&A, pParse, TK_VARIABLE, t); sqlite3ExprAssignVarNumber(pParse, A.pExpr); } - spanSet(&A, &X, &X); } expr(A) ::= expr(A) COLLATE ids(C). { A.pExpr = sqlite3ExprAddCollateToken(pParse, A.pExpr, &C, 1); @@ -904,8 +909,8 @@ expr(A) ::= expr(A) COLLATE ids(C). { } %ifndef SQLITE_OMIT_CAST expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). { + spanSet(&A,&X,&Y); /*A-overwrites-X*/ A.pExpr = sqlite3PExpr(pParse, TK_CAST, E.pExpr, 0, &T); - spanSet(&A,&X,&Y); } %endif SQLITE_OMIT_CAST expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP(E). { @@ -1041,20 +1046,22 @@ expr(A) ::= expr(A) IS NOT expr(Y). { ExprSpan *pOperand, /* The operand */ Token *pPreOp /* The operand token for setting the span */ ){ - pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); pOut->zStart = pPreOp->z; + pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); pOut->zEnd = pOperand->zEnd; } } -expr(A) ::= NOT(B) expr(X). {spanUnaryPrefix(&A,pParse,@B,&X,&B);} -expr(A) ::= BITNOT(B) expr(X). {spanUnaryPrefix(&A,pParse,@B,&X,&B);} +expr(A) ::= NOT(B) expr(X). + {spanUnaryPrefix(&A,pParse,@B,&X,&B);/*A-overwrites-B*/} +expr(A) ::= BITNOT(B) expr(X). + {spanUnaryPrefix(&A,pParse,@B,&X,&B);/*A-overwrites-B*/} expr(A) ::= MINUS(B) expr(X). [BITNOT] - {spanUnaryPrefix(&A,pParse,TK_UMINUS,&X,&B);} + {spanUnaryPrefix(&A,pParse,TK_UMINUS,&X,&B);/*A-overwrites-B*/} expr(A) ::= PLUS(B) expr(X). [BITNOT] - {spanUnaryPrefix(&A,pParse,TK_UPLUS,&X,&B);} + {spanUnaryPrefix(&A,pParse,TK_UPLUS,&X,&B);/*A-overwrites-B*/} %type between_op {int} between_op(A) ::= BETWEEN. {A = 0;} @@ -1127,6 +1134,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A.zEnd = &E.z[E.n]; } expr(A) ::= LP(B) select(X) RP(E). { + spanSet(&A,&B,&E); /*A-overwrites-B*/ A.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); if( A.pExpr ){ A.pExpr->x.pSelect = X; @@ -1135,8 +1143,6 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { }else{ sqlite3SelectDelete(pParse->db, X); } - A.zStart = B.z; - A.zEnd = &E.z[E.n]; } expr(A) ::= expr(A) in_op(N) LP select(Y) RP(E). [IN] { A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0, 0); @@ -1164,7 +1170,9 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A.zEnd = Z.z ? &Z.z[Z.n] : &Y.z[Y.n]; } expr(A) ::= EXISTS(B) LP select(Y) RP(E). { - Expr *p = A.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); + Expr *p; + spanSet(&A,&B,&E); /*A-overwrites-B*/ + p = A.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); if( p ){ p->x.pSelect = Y; ExprSetProperty(p, EP_xIsSelect|EP_Subquery); @@ -1172,13 +1180,12 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { }else{ sqlite3SelectDelete(pParse->db, Y); } - A.zStart = B.z; - A.zEnd = &E.z[E.n]; } %endif SQLITE_OMIT_SUBQUERY /* CASE expressions */ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { + spanSet(&A,&C,&E); /*A-overwrites-C*/ A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y; @@ -1187,8 +1194,6 @@ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { sqlite3ExprListDelete(pParse->db, Y); sqlite3ExprDelete(pParse->db, Z); } - A.zStart = C.z; - A.zEnd = &E.z[E.n]; } %type case_exprlist {ExprList*} %destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);} @@ -1415,19 +1420,19 @@ tridxby ::= NOT INDEXED. { // UPDATE trigger_cmd(A) ::= UPDATE orconf(R) trnm(X) tridxby SET setlist(Y) where_opt(Z). - { A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R); } + {A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R);} // INSERT trigger_cmd(A) ::= insert_cmd(R) INTO trnm(X) idlist_opt(F) select(S). - {A = sqlite3TriggerInsertStep(pParse->db, &X, F, S, R);} + {A = sqlite3TriggerInsertStep(pParse->db, &X, F, S, R);/*A-overwrites-R*/} // DELETE trigger_cmd(A) ::= DELETE FROM trnm(X) tridxby where_opt(Y). - {A = sqlite3TriggerDeleteStep(pParse->db, &X, Y);} + {A = sqlite3TriggerDeleteStep(pParse->db, &X, Y);} // SELECT trigger_cmd(A) ::= select(X). - {A = sqlite3TriggerSelectStep(pParse->db, X); /*A-overwrites-X*/} + {A = sqlite3TriggerSelectStep(pParse->db, X); /*A-overwrites-X*/} // The special RAISE expression that may occur in trigger programs expr(A) ::= RAISE(X) LP IGNORE RP(Y). { diff --git a/tool/lemon.c b/tool/lemon.c index 1058d14ae6..cefdf80174 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -3477,6 +3477,7 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ char *cp, *xp; int i; int rc = 0; /* True if yylhsminor is used */ + int dontUseRhs0 = 0; /* If true, use of left-most RHS label is illegal */ const char *zSkip = 0; /* The zOvwrt comment within rp->code, or NULL */ char lhsused = 0; /* True if the LHS element has been used */ char lhsdirect; /* True if LHS writes directly into stack */ @@ -3549,6 +3550,7 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ if( cp==zSkip ){ append_str(zOvwrt,0,0,0); cp += lemonStrlen(zOvwrt)-1; + dontUseRhs0 = 1; continue; } if( ISALPHA(*cp) && (cp==rp->code || (!ISALNUM(cp[-1]) && cp[-1]!='_')) ){ @@ -3563,7 +3565,12 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ }else{ for(i=0; inrhs; i++){ if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){ - if( cp!=rp->code && cp[-1]=='@' ){ + if( i==0 && dontUseRhs0 ){ + ErrorMsg(lemp->filename,rp->ruleline, + "Label %s used after '%s'.", + rp->rhsalias[0], zOvwrt); + lemp->errorcnt++; + }else if( cp!=rp->code && cp[-1]=='@' ){ /* If the argument is of the form @X then substituted ** the token number of X, not the value of X */ append_str("yymsp[%d].major",-1,i-rp->nrhs+1,0); diff --git a/tool/lempar.c b/tool/lempar.c index 1d76779b5e..f7cb097c34 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -637,14 +637,14 @@ static void yy_reduce( } #endif #if YYSTACKDEPTH>0 - if( yypParser->yyidx>=YYSTACKDEPTH ){ + if( yypParser->yyidx>=YYSTACKDEPTH-1 ){ yyStackOverflow(yypParser); return; } #else - if( yypParser->yyidx>=yypParser->yystksz ){ + if( yypParser->yyidx>=yypParser->yystksz-1 ){ yyGrowStack(yypParser); - if( yypParser->yyidx>=yypParser->yystksz ){ + if( yypParser->yyidx>=yypParser->yystksz-1 ){ yyStackOverflow(yypParser); return; } From 87d6b35541fa501a46064d4ac7aa8e7ecb96349e Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 17 Feb 2016 14:11:06 +0000 Subject: [PATCH 305/570] Improve test coverage of demo code in fts5_test_mi.c. FossilOrigin-Name: 8a78050dc0e374a0df0f29716df60250e2c4b4f7 --- ext/fts5/fts5_test_mi.c | 8 +-- ext/fts5/test/fts5faultB.test | 83 ++++++++++++++++++++++++++++++++ ext/fts5/test/fts5matchinfo.test | 24 +++++++++ manifest | 18 +++---- manifest.uuid | 2 +- 5 files changed, 119 insertions(+), 16 deletions(-) create mode 100644 ext/fts5/test/fts5faultB.test diff --git a/ext/fts5/fts5_test_mi.c b/ext/fts5/fts5_test_mi.c index 28331773c0..30c0d3f43a 100644 --- a/ext/fts5/fts5_test_mi.c +++ b/ext/fts5/fts5_test_mi.c @@ -244,11 +244,7 @@ static int fts5MatchinfoLocalCb( iOff>=0; pApi->xPhraseNext(pFts, &iter, &iCol, &iOff) ){ - if( f=='b' ){ - aOut[iPhrase * ((p->nCol+31)/32) + iCol/32] |= ((u32)1 << iCol%32); - }else{ - aOut[nMul * (iCol + iPhrase * p->nCol)]++; - } + aOut[nMul * (iCol + iPhrase * p->nCol)]++; } } @@ -409,7 +405,7 @@ int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){ ** ** Also check that the fts5_api object is version 2 or newer. */ - if( pApi==0 || pApi->iVersion<1 ){ + if( pApi==0 || pApi->iVersion<2 ){ return SQLITE_ERROR; } diff --git a/ext/fts5/test/fts5faultB.test b/ext/fts5/test/fts5faultB.test new file mode 100644 index 0000000000..40df8b6043 --- /dev/null +++ b/ext/fts5/test/fts5faultB.test @@ -0,0 +1,83 @@ +# 2016 February 17 +# +# 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 is focused on OOM errors. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +source $testdir/malloc_common.tcl +set testprefix fts5faultB + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +proc mit {blob} { + set scan(littleEndian) i* + set scan(bigEndian) I* + binary scan $blob $scan($::tcl_platform(byteOrder)) r + return $r +} +db func mit mit + + +#------------------------------------------------------------------------- +# Errors while registering the matchinfo() demo function. +# +do_faultsim_test 1 -faults oom* -prep { + sqlite3 db test.db +} -body { + sqlite3_fts5_register_matchinfo db +} -test { + faultsim_test_result {0 {}} {1 SQLITE_ERROR} {1 SQLITE_NOMEM} +} + + +#------------------------------------------------------------------------- +# Errors while executing the matchinfo() demo function. +# +reset_db +sqlite3_fts5_register_matchinfo db +db func mit mit +do_execsql_test 2 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b); + INSERT INTO t1 VALUES('x y z', '1 2 3'); + INSERT INTO t1 VALUES('x', '1 2 3 4 5 6 7'); +} + +do_faultsim_test 2.1 -faults oom* -body { + execsql { SELECT mit(matchinfo(t1, 'a')) FROM t1('x') } +} -test { + faultsim_test_result {0 {{2 5} {2 5}}} +} + +do_faultsim_test 2.2 -faults oom* -body { + execsql { SELECT mit(matchinfo(t1, 'l')) FROM t1('x') } +} -test { + faultsim_test_result {0 {{3 3} {1 7}}} +} + +do_execsql_test 2.3 { + INSERT INTO t1 VALUES('a b c d e f', 'a b d e f c'); + INSERT INTO t1 VALUES('l m b c a', 'n o a b c z'); +} + +do_faultsim_test 2.4 -faults oom* -body { + execsql { SELECT mit(matchinfo(t1, 's')) FROM t1('a b c') } +} -test { + faultsim_test_result {0 {{3 2} {2 3}}} +} + + +finish_test + diff --git a/ext/fts5/test/fts5matchinfo.test b/ext/fts5/test/fts5matchinfo.test index 06f4550b47..99b07677af 100644 --- a/ext/fts5/test/fts5matchinfo.test +++ b/ext/fts5/test/fts5matchinfo.test @@ -467,5 +467,29 @@ do_execsql_test 12.1 { } ;# foreach_detail_mode +#------------------------------------------------------------------------- +# Test that a bad fts5() return is detected +# +reset_db +proc xyz {} {} +db func fts5 -argcount 0 xyz +do_test 13.1 { + list [catch { sqlite3_fts5_register_matchinfo db } msg] $msg +} {1 SQLITE_ERROR} + +#------------------------------------------------------------------------- +# Test that an invalid matchinfo() flag is detected +# +reset_db +sqlite3_fts5_register_matchinfo db +do_execsql_test 14.1 { + CREATE VIRTUAL TABLE x1 USING fts5(z); + INSERT INTO x1 VALUES('a b c a b c a b c'); +} {} + +do_catchsql_test 14.2 { + SELECT matchinfo(x1, 'd') FROM x1('a b c'); +} {1 {unrecognized matchinfo flag: d}} + finish_test diff --git a/manifest b/manifest index c5003ad35d..e4904b1ac7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sLemon\sto\sgenerate\smore\scompact\sand\sefficient\scode\sfor\syy_reduce().\nUpdate\sthe\smain\sSQL\sgrammar\sto\stake\sadvantage\sof\sthe\snew\scapabilities. -D 2016-02-17T13:24:12.055 +C Improve\stest\scoverage\sof\sdemo\scode\sin\sfts5_test_mi.c. +D 2016-02-17T14:11:06.434 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -108,7 +108,7 @@ F ext/fts5/fts5_index.c 78069efb54559a17c35906a741362d0b5c899bd0 F ext/fts5/fts5_main.c 0e01ead4e817483e378e7e38e6d902f50b68d29e F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 -F ext/fts5/fts5_test_mi.c 1ec66ffdf7632077fbd773b7a6df5153272ec070 +F ext/fts5/fts5_test_mi.c d491f9277fcf2b91312a261b9cb4c10da1ff1734 F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8 F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf @@ -157,10 +157,11 @@ F ext/fts5/test/fts5fault7.test cb14ea3c1f42394f06f2284abc58eecee6ff8080 F ext/fts5/test/fts5fault8.test 430837fe6dd0511fd3aea52bd602ac02441bcb58 F ext/fts5/test/fts5fault9.test e10e395428a9ea0596ebe752ff7123d16ab78e08 F ext/fts5/test/fts5faultA.test fa5d59c0ff62b7125cd14eee38ded1c46e15a7ea +F ext/fts5/test/fts5faultB.test 92ae906284062bf081b6c854afa54dcb1aa9ef88 F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741 F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d -F ext/fts5/test/fts5matchinfo.test 86569026d20f1ed748236587ce798de8a96615f1 +F ext/fts5/test/fts5matchinfo.test f7dde99697bcb310ea8faa8eb2714d9f4dfc0e1b F ext/fts5/test/fts5merge.test 8f3cdba2ec9c5e7e568246e81b700ad37f764367 F ext/fts5/test/fts5merge2.test c0cb66eb38a41c26cc5848fb9e50093e0f59ac93 F ext/fts5/test/fts5near.test b214cddb1c1f1bddf45c75af768f20145f7e71cc @@ -1427,8 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P fc2043ebaa3f106529500164936bb82f9b921b1c 417e777701bbf4bd67626d4ca3bc2c5d847f6cd0 -R 2ca4dc2ba891e3629351ceac13b91136 -T +closed 417e777701bbf4bd67626d4ca3bc2c5d847f6cd0 -U drh -Z 146115d4bedb6d62469919152a1417e4 +P 53fd040c98d9647ea135d43c493777bf8da4aebd +R 145e645c5948689d8fe331e9c7c65bd5 +U dan +Z f405d2e5930c75fdd0f048c483569008 diff --git a/manifest.uuid b/manifest.uuid index 4b6e90b619..3ecc2854d7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -53fd040c98d9647ea135d43c493777bf8da4aebd \ No newline at end of file +8a78050dc0e374a0df0f29716df60250e2c4b4f7 \ No newline at end of file From 5e29f38d2c349264b78b53bdf2cb4a4a49333af9 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 17 Feb 2016 14:48:26 +0000 Subject: [PATCH 306/570] Remove the "#ifdef SQLITE_TEST" condition from fts5_test_mi.c. Update fts5_main.c so that if SQLITE_FTS5_TEST_MI is defined when it is built the fts5_test_mi.c entry point is automatically called. This makes it easier to build versions of fts5 that include the matchinfo() demo by default. FossilOrigin-Name: 87e6e225aea3a4d10476d16eab4a6403a4a128c9 --- ext/fts5/fts5_main.c | 11 +++++++++++ ext/fts5/fts5_test_mi.c | 2 -- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index fe1d72e2b0..28f3f3e62c 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -2665,6 +2665,17 @@ static int fts5Init(sqlite3 *db){ ); } } + + /* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file + ** fts5_test_mi.c is compiled and linked into the executable. And call + ** its entry point to enable the matchinfo() demo. */ +#ifdef SQLITE_FTS5_ENABLE_TEST_MI + if( rc==SQLITE_OK ){ + extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*); + rc = sqlite3Fts5TestRegisterMatchinfo(db); + } +#endif + return rc; } diff --git a/ext/fts5/fts5_test_mi.c b/ext/fts5/fts5_test_mi.c index 30c0d3f43a..96fad6d331 100644 --- a/ext/fts5/fts5_test_mi.c +++ b/ext/fts5/fts5_test_mi.c @@ -41,7 +41,6 @@ */ -#ifdef SQLITE_TEST #ifdef SQLITE_ENABLE_FTS5 #include "fts5.h" @@ -416,5 +415,4 @@ int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){ } #endif /* SQLITE_ENABLE_FTS5 */ -#endif /* SQLITE_TEST */ diff --git a/manifest b/manifest index e4904b1ac7..c3c0371b95 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\stest\scoverage\sof\sdemo\scode\sin\sfts5_test_mi.c. -D 2016-02-17T14:11:06.434 +C Remove\sthe\s"#ifdef\sSQLITE_TEST"\scondition\sfrom\sfts5_test_mi.c.\sUpdate\sfts5_main.c\sso\sthat\sif\sSQLITE_FTS5_TEST_MI\sis\sdefined\swhen\sit\sis\sbuilt\sthe\sfts5_test_mi.c\sentry\spoint\sis\sautomatically\scalled.\sThis\smakes\sit\seasier\sto\sbuild\sversions\sof\sfts5\sthat\sinclude\sthe\smatchinfo()\sdemo\sby\sdefault. +D 2016-02-17T14:48:26.564 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -105,10 +105,10 @@ F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 F ext/fts5/fts5_index.c 78069efb54559a17c35906a741362d0b5c899bd0 -F ext/fts5/fts5_main.c 0e01ead4e817483e378e7e38e6d902f50b68d29e +F ext/fts5/fts5_main.c db24ac714c6c4a1b3c24a1f8c25889f2952148c1 F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 -F ext/fts5/fts5_test_mi.c d491f9277fcf2b91312a261b9cb4c10da1ff1734 +F ext/fts5/fts5_test_mi.c c1bb729651d86c7c70bcd1ec3f12fa83f97035cc F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8 F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf @@ -1428,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 53fd040c98d9647ea135d43c493777bf8da4aebd -R 145e645c5948689d8fe331e9c7c65bd5 +P 8a78050dc0e374a0df0f29716df60250e2c4b4f7 +R 3d71cd697bdb97ce7af07964f4cb4585 U dan -Z f405d2e5930c75fdd0f048c483569008 +Z 2fd981c5711b99aa40969af5d950bdc1 diff --git a/manifest.uuid b/manifest.uuid index 3ecc2854d7..c8a854d2f5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8a78050dc0e374a0df0f29716df60250e2c4b4f7 \ No newline at end of file +87e6e225aea3a4d10476d16eab4a6403a4a128c9 \ No newline at end of file From b5a55ce77dd32ca1a5d07365a0c46810c2dfed67 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 17 Feb 2016 15:01:18 +0000 Subject: [PATCH 307/570] Bump the version number to 3.12.0. FossilOrigin-Name: c17d7276b8c114df5fe6e9ea14d59758443c281b --- VERSION | 2 +- configure | 18 +++++++++--------- manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/VERSION b/VERSION index afad818663..92536a9e48 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.11.0 +3.12.0 diff --git a/configure b/configure index b2cb4d1308..09fba81eae 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sqlite 3.11.0. +# Generated by GNU Autoconf 2.69 for sqlite 3.12.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -726,8 +726,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' -PACKAGE_VERSION='3.11.0' -PACKAGE_STRING='sqlite 3.11.0' +PACKAGE_VERSION='3.12.0' +PACKAGE_STRING='sqlite 3.12.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1460,7 +1460,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sqlite 3.11.0 to adapt to many kinds of systems. +\`configure' configures sqlite 3.12.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1525,7 +1525,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.11.0:";; + short | recursive ) echo "Configuration of sqlite 3.12.0:";; esac cat <<\_ACEOF @@ -1646,7 +1646,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.11.0 +sqlite configure 3.12.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2065,7 +2065,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sqlite $as_me 3.11.0, which was +It was created by sqlite $as_me 3.12.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -12079,7 +12079,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sqlite $as_me 3.11.0, which was +This file was extended by sqlite $as_me 3.12.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12145,7 +12145,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sqlite config.status 3.11.0 +sqlite config.status 3.12.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/manifest b/manifest index c3c0371b95..4c47b0808e 100644 --- a/manifest +++ b/manifest @@ -1,10 +1,10 @@ -C Remove\sthe\s"#ifdef\sSQLITE_TEST"\scondition\sfrom\sfts5_test_mi.c.\sUpdate\sfts5_main.c\sso\sthat\sif\sSQLITE_FTS5_TEST_MI\sis\sdefined\swhen\sit\sis\sbuilt\sthe\sfts5_test_mi.c\sentry\spoint\sis\sautomatically\scalled.\sThis\smakes\sit\seasier\sto\sbuild\sversions\sof\sfts5\sthat\sinclude\sthe\smatchinfo()\sdemo\sby\sdefault. -D 2016-02-17T14:48:26.564 +C Bump\sthe\sversion\snumber\sto\s3.12.0. +D 2016-02-17T15:01:18.374 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 -F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 +F VERSION c6b1f51809551d60ad001e6d87cf3ab2c7f54b6f F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 @@ -30,7 +30,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0 F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 -F configure 12d96e3798e612e0ffa53a7a8c4d7fb1090df80e x +F configure 0339a635cd2943a3b56000a10a11b4b2e6ed6d1b x F configure.ac a2224b1162f79848982d3618ac1deffcd94e88ec F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/lemon.html c30255bea0fd87a81f082d17a72c9dffbc3f6dd9 @@ -1428,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 8a78050dc0e374a0df0f29716df60250e2c4b4f7 -R 3d71cd697bdb97ce7af07964f4cb4585 -U dan -Z 2fd981c5711b99aa40969af5d950bdc1 +P 87e6e225aea3a4d10476d16eab4a6403a4a128c9 +R c239316472226b2429c7b466d6a49ed7 +U drh +Z 28d335fbd5135b0e539f7ad24d2e095e diff --git a/manifest.uuid b/manifest.uuid index c8a854d2f5..b7dbf86410 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -87e6e225aea3a4d10476d16eab4a6403a4a128c9 \ No newline at end of file +c17d7276b8c114df5fe6e9ea14d59758443c281b \ No newline at end of file From 9467abf3dd9883c6bb3399bcae8769d25fbe2914 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 17 Feb 2016 18:44:11 +0000 Subject: [PATCH 308/570] Fix up all VDBE opcodes so that they cause an immediate exit on any kind of error, and thereby eliminate the need to test "rc" at the top of the loop. Resulting code is a little smaller and faster. FossilOrigin-Name: a444633a827642bcf4d02a461e7e5f66769d39fd --- manifest | 15 ++-- manifest.uuid | 2 +- src/vdbe.c | 224 +++++++++++++++++++++++++++++--------------------- 3 files changed, 140 insertions(+), 101 deletions(-) diff --git a/manifest b/manifest index 4c47b0808e..1a41847dd1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Bump\sthe\sversion\snumber\sto\s3.12.0. -D 2016-02-17T15:01:18.374 +C Fix\sup\sall\sVDBE\sopcodes\sso\sthat\sthey\scause\san\simmediate\sexit\son\sany\skind\sof\nerror,\sand\sthereby\seliminate\sthe\sneed\sto\stest\s"rc"\sat\sthe\stop\sof\sthe\sloop.\nResulting\scode\sis\sa\slittle\ssmaller\sand\sfaster. +D 2016-02-17T18:44:11.129 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -414,7 +414,7 @@ F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 8073bbdab9cc7209f6741bd44264ede606cbadc6 F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 -F src/vdbe.c ad4d5b7ad65793886b09c925fb5d1d74ac78f1a4 +F src/vdbe.c 4eef77da4b81763a25992cc060506c001ebd4e3d F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 F src/vdbeapi.c bfc06382d5089944388a90e4f90bb1e975b3613d @@ -1428,7 +1428,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 87e6e225aea3a4d10476d16eab4a6403a4a128c9 -R c239316472226b2429c7b466d6a49ed7 +P c17d7276b8c114df5fe6e9ea14d59758443c281b +R 99549bba2f02d5e0c4a44abe6153e853 +T *branch * vdbe-performance +T *sym-vdbe-performance * +T -sym-trunk * U drh -Z 28d335fbd5135b0e539f7ad24d2e095e +Z 63c3fbdaa7e2321f71ac02a9835490a1 diff --git a/manifest.uuid b/manifest.uuid index b7dbf86410..9c9d81be2b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c17d7276b8c114df5fe6e9ea14d59758443c281b \ No newline at end of file +a444633a827642bcf4d02a461e7e5f66769d39fd \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 38b101d382..0f8d75d302 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -627,7 +627,11 @@ int sqlite3VdbeExec( } sqlite3EndBenignMalloc(); #endif - for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){ + for(pOp=&aOp[p->pc]; 1; pOp++){ + /* Errors are detected by individual opcodes, with an immediate + ** jumps to abort_due_to_error. */ + assert( rc==SQLITE_OK ); + assert( pOp>=aOp && pOp<&aOp[p->nOp]); #ifdef VDBE_PROFILE start = sqlite3Hwtime(); @@ -774,7 +778,7 @@ check_for_interrupt: nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps); if( db->xProgress(db->pProgressArg) ){ rc = SQLITE_INTERRUPT; - goto vdbe_error_halt; + goto abort_due_to_error; } } #endif @@ -1053,7 +1057,10 @@ case OP_String8: { /* same as TK_STRING, out2 */ #ifndef SQLITE_OMIT_UTF16 if( encoding!=SQLITE_UTF8 ){ rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC); - if( rc==SQLITE_TOOBIG ) goto too_big; + if( rc ){ + assert( rc==SQLITE_TOOBIG ); /* This is the only possible error here */ + goto too_big; + } if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z ); assert( VdbeMemDynamic(pOut)==0 ); @@ -1319,7 +1326,7 @@ case OP_ResultRow: { && db->xProgress(db->pProgressArg)!=0 ){ rc = SQLITE_INTERRUPT; - goto vdbe_error_halt; + goto abort_due_to_error; } #endif @@ -1329,7 +1336,7 @@ case OP_ResultRow: { if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){ assert( db->flags&SQLITE_CountRows ); assert( p->usesStmtJournal ); - break; + goto abort_due_to_error; } /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then @@ -1349,9 +1356,7 @@ case OP_ResultRow: { */ assert( p->iStatement==0 || db->flags&SQLITE_CountRows ); rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE); - if( NEVER(rc!=SQLITE_OK) ){ - break; - } + assert( rc==SQLITE_OK ); /* Invalidate all ephemeral cursor row caches */ p->cacheCtr = (p->cacheCtr + 2)|1; @@ -1675,6 +1680,7 @@ case OP_Function: { rc = pCtx->isError; } sqlite3VdbeDeleteAuxData(p, pCtx->iOp, pOp->p1); + if( rc ) goto abort_due_to_error; } /* Copy the result of the function into register P3 */ @@ -1858,6 +1864,7 @@ case OP_Cast: { /* in1 */ rc = ExpandBlob(pIn1); sqlite3VdbeMemCast(pIn1, pOp->p2, encoding); UPDATE_MAX_BLOBSIZE(pIn1); + if( rc ) goto abort_due_to_error; break; } #endif /* SQLITE_OMIT_CAST */ @@ -2467,7 +2474,7 @@ case OP_Column: { */ if( offset > 98307 || offset > pC->payloadSize ){ rc = SQLITE_CORRUPT_BKPT; - goto op_column_error; + goto abort_due_to_error; } } @@ -2492,7 +2499,7 @@ case OP_Column: { if( pC->aRow==0 ){ memset(&sMem, 0, sizeof(sMem)); rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], !pC->isTable, &sMem); - if( rc!=SQLITE_OK ) goto op_column_error; + if( rc!=SQLITE_OK ) goto abort_due_to_error; zData = (u8*)sMem.z; }else{ zData = pC->aRow; @@ -2528,7 +2535,7 @@ case OP_Column: { || (offset64 > pC->payloadSize) ){ rc = SQLITE_CORRUPT_BKPT; - goto op_column_error; + goto abort_due_to_error; } }else{ t = 0; @@ -2601,15 +2608,13 @@ case OP_Column: { }else{ rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable, pDest); - if( rc==SQLITE_OK ){ - sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest); - pDest->flags &= ~MEM_Ephem; - } + if( rc!=SQLITE_OK ) goto abort_due_to_error; + sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest); + pDest->flags &= ~MEM_Ephem; } } op_column_out: -op_column_error: UPDATE_MAX_BLOBSIZE(pDest); REGISTER_TRACE(pOp->p3, pDest); break; @@ -2814,6 +2819,7 @@ case OP_Count: { /* out2 */ assert( pCrsr ); nEntry = 0; /* Not needed. Only used to silence a warning. */ rc = sqlite3BtreeCount(pCrsr, &nEntry); + if( rc ) goto abort_due_to_error; pOut = out2Prerelease(p, pOp); pOut->u.i = nEntry; break; @@ -2991,6 +2997,7 @@ case OP_Savepoint: { } } } + if( rc ) goto abort_due_to_error; break; } @@ -3027,7 +3034,7 @@ case OP_AutoCommit: { sqlite3VdbeError(p, "cannot commit transaction - " "SQL statements in progress"); rc = SQLITE_BUSY; - break; + goto abort_due_to_error; }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ goto vdbe_return; }else{ @@ -3054,6 +3061,7 @@ case OP_AutoCommit: { "cannot commit - no transaction is active")); rc = SQLITE_ERROR; + goto abort_due_to_error; } break; } @@ -3176,6 +3184,7 @@ case OP_Transaction: { p->expired = 1; rc = SQLITE_SCHEMA; } + if( rc ) goto abort_due_to_error; break; } @@ -3245,6 +3254,7 @@ case OP_SetCookie: { sqlite3ExpirePreparedStatements(db); p->expired = 0; } + if( rc ) goto abort_due_to_error; break; } @@ -3342,7 +3352,7 @@ case OP_OpenWrite: if( p->expired ){ rc = SQLITE_ABORT_ROLLBACK; - break; + goto abort_due_to_error; } nField = 0; @@ -3376,10 +3386,7 @@ case OP_OpenWrite: ** that opcode will always set the p2 value to 2 or more or else fail. ** If there were a failure, the prepared statement would have halted ** before reaching this instruction. */ - if( NEVER(p2<2) ) { - rc = SQLITE_CORRUPT_BKPT; - goto abort_due_to_error; - } + assert( p2>=2 ); } if( pOp->p4type==P4_KEYINFO ){ pKeyInfo = pOp->p4.pKeyInfo; @@ -3417,6 +3424,7 @@ open_cursor_set_hints: #endif sqlite3BtreeCursorHintFlags(pCur->uc.pCursor, (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ))); + if( rc ) goto abort_due_to_error; break; } @@ -3493,6 +3501,7 @@ case OP_OpenEphemeral: { pCx->isTable = 1; } } + if( rc ) goto abort_due_to_error; pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); break; } @@ -3518,6 +3527,7 @@ case OP_SorterOpen: { assert( pCx->pKeyInfo->db==db ); assert( pCx->pKeyInfo->enc==ENC(db) ); rc = sqlite3VdbeSorterInit(db, pOp->p3, pCx); + if( rc ) goto abort_due_to_error; break; } @@ -3980,7 +3990,7 @@ case OP_Found: { /* jump, in3 */ rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res); sqlite3DbFree(db, pFree); if( rc!=SQLITE_OK ){ - break; + goto abort_due_to_error; } pC->seekResult = res; alreadyExists = (res==0); @@ -4052,6 +4062,7 @@ case OP_NotExists: { /* jump, in3 */ goto jump_to_p2; } } + if( rc ) goto abort_due_to_error; break; } @@ -4194,7 +4205,8 @@ case OP_NewRowid: { /* out2 */ 0, &res))==SQLITE_OK) && (res==0) && (++cnt<100)); - if( rc==SQLITE_OK && res==0 ){ + if( rc ) goto abort_due_to_error; + if( res==0 ){ rc = SQLITE_FULL; /* IMP: R-38219-53002 */ goto abort_due_to_error; } @@ -4308,7 +4320,8 @@ case OP_InsertInt: { pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ - if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ + if( rc ) goto abort_due_to_error; + if( db->xUpdateCallback && pOp->p4.z ){ zDb = db->aDb[pC->iDb].zName; zTbl = pOp->p4.z; op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); @@ -4398,7 +4411,8 @@ case OP_Delete: { pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ - if( rc==SQLITE_OK && hasUpdateCallback ){ + if( rc ) goto abort_due_to_error; + if( hasUpdateCallback ){ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, db->aDb[pC->iDb].zName, pOp->p4.z, pC->movetoTarget); assert( pC->iDb>=0 ); @@ -4447,6 +4461,7 @@ case OP_SorterCompare: { res = 0; rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res); VdbeBranchTaken(res!=0,2); + if( rc ) goto abort_due_to_error; if( res ) goto jump_to_p2; break; }; @@ -4472,6 +4487,7 @@ case OP_SorterData: { rc = sqlite3VdbeSorterRowkey(pC, pOut); assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) ); assert( pOp->p1>=0 && pOp->p1nCursor ); + if( rc ) goto abort_due_to_error; p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE; break; } @@ -4560,6 +4576,7 @@ case OP_RowData: { }else{ rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z); } + if( rc ) goto abort_due_to_error; pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ UPDATE_MAX_BLOBSIZE(pOut); REGISTER_TRACE(pOp->p2, pOut); @@ -4600,6 +4617,7 @@ case OP_Rowid: { /* out2 */ assert( pModule->xRowid ); rc = pModule->xRowid(pC->uc.pVCur, &v); sqlite3VtabImportErrmsg(p, pVtab); + if( rc ) goto abort_due_to_error; #endif /* SQLITE_OMIT_VIRTUALTABLE */ }else{ assert( pC->eCurType==CURTYPE_BTREE ); @@ -4670,6 +4688,7 @@ case OP_Last: { /* jump */ #ifdef SQLITE_DEBUG pC->seekOp = OP_Last; #endif + if( rc ) goto abort_due_to_error; if( pOp->p2>0 ){ VdbeBranchTaken(res!=0,2); if( res ) goto jump_to_p2; @@ -4734,6 +4753,7 @@ case OP_Rewind: { /* jump */ pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; } + if( rc ) goto abort_due_to_error; pC->nullRow = (u8)res; assert( pOp->p2>0 && pOp->p2nOp ); VdbeBranchTaken(res!=0,2); @@ -4846,6 +4866,7 @@ case OP_Next: /* jump */ next_tail: pC->cacheStatus = CACHE_STALE; VdbeBranchTaken(res==0,2); + if( rc ) goto abort_due_to_error; if( res==0 ){ pC->nullRow = 0; p->aCounter[pOp->p5]++; @@ -4896,19 +4917,19 @@ case OP_IdxInsert: { /* in2 */ assert( pC->eCurType==CURTYPE_BTREE || pOp->opcode==OP_SorterInsert ); assert( pC->isTable==0 ); rc = ExpandBlob(pIn2); - if( rc==SQLITE_OK ){ - if( pOp->opcode==OP_SorterInsert ){ - rc = sqlite3VdbeSorterWrite(pC, pIn2); - }else{ - nKey = pIn2->n; - zKey = pIn2->z; - rc = sqlite3BtreeInsert(pC->uc.pCursor, zKey, nKey, "", 0, 0, pOp->p3, - ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) - ); - assert( pC->deferredMoveto==0 ); - pC->cacheStatus = CACHE_STALE; - } + if( rc ) goto abort_due_to_error; + if( pOp->opcode==OP_SorterInsert ){ + rc = sqlite3VdbeSorterWrite(pC, pIn2); + }else{ + nKey = pIn2->n; + zKey = pIn2->z; + rc = sqlite3BtreeInsert(pC->uc.pCursor, zKey, nKey, "", 0, 0, pOp->p3, + ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) + ); + assert( pC->deferredMoveto==0 ); + pC->cacheStatus = CACHE_STALE; } + if( rc) goto abort_due_to_error; break; } @@ -4939,8 +4960,10 @@ case OP_IdxDelete: { r.default_rc = 0; r.aMem = &aMem[pOp->p2]; rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); - if( rc==SQLITE_OK && res==0 ){ + if( rc ) goto abort_due_to_error; + if( res==0 ){ rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); + if( rc ) goto abort_due_to_error; } assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; @@ -5115,6 +5138,7 @@ case OP_IdxGE: { /* jump */ res++; } VdbeBranchTaken(res>0,2); + if( rc ) goto abort_due_to_error; if( res>0 ) goto jump_to_p2; break; } @@ -5150,6 +5174,7 @@ case OP_Destroy: { /* out2 */ if( db->nVdbeRead > db->nVDestroy+1 ){ rc = SQLITE_LOCKED; p->errorAction = OE_Abort; + goto abort_due_to_error; }else{ iDb = pOp->p3; assert( DbMaskTest(p->btreeMask, iDb) ); @@ -5157,8 +5182,9 @@ case OP_Destroy: { /* out2 */ rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved); pOut->flags = MEM_Int; pOut->u.i = iMoved; + if( rc ) goto abort_due_to_error; #ifndef SQLITE_OMIT_AUTOVACUUM - if( rc==SQLITE_OK && iMoved!=0 ){ + if( iMoved!=0 ){ sqlite3RootPageMoved(db, iDb, iMoved, pOp->p1); /* All OP_Destroy operations occur on the same btree */ assert( resetSchemaOnFault==0 || resetSchemaOnFault==iDb+1 ); @@ -5204,6 +5230,7 @@ case OP_Clear: { aMem[pOp->p3].u.i += nChange; } } + if( rc ) goto abort_due_to_error; break; } @@ -5227,6 +5254,7 @@ case OP_ResetSorter: { assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->isEphemeral ); rc = sqlite3BtreeClearTableOfCursor(pC->uc.pCursor); + if( rc ) goto abort_due_to_error; } break; } @@ -5275,6 +5303,7 @@ case OP_CreateTable: { /* out2 */ flags = BTREE_BLOBKEY; } rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); + if( rc ) goto abort_due_to_error; pOut->u.i = pgno; break; } @@ -5327,9 +5356,12 @@ case OP_ParseSchema: { db->init.busy = 0; } } - if( rc ) sqlite3ResetAllSchemasOfConnection(db); - if( rc==SQLITE_NOMEM ){ - goto no_mem; + if( rc ){ + sqlite3ResetAllSchemasOfConnection(db); + if( rc==SQLITE_NOMEM ){ + goto no_mem; + } + goto abort_due_to_error; } break; } @@ -5344,6 +5376,7 @@ case OP_ParseSchema: { case OP_LoadAnalysis: { assert( pOp->p1>=0 && pOp->p1nDb ); rc = sqlite3AnalysisLoad(db, pOp->p1); + if( rc ) goto abort_due_to_error; break; } #endif /* !defined(SQLITE_OMIT_ANALYZE) */ @@ -5603,7 +5636,7 @@ case OP_Program: { /* jump */ if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){ rc = SQLITE_ERROR; sqlite3VdbeError(p, "too many levels of trigger recursion"); - break; + goto abort_due_to_error; } /* Register pRt is used to store the memory required to save the state @@ -5967,6 +6000,7 @@ case OP_AggStep: { rc = pCtx->isError; } sqlite3VdbeMemRelease(&t); + if( rc ) goto abort_due_to_error; }else{ assert( t.flags==MEM_Null ); } @@ -5999,6 +6033,7 @@ case OP_AggFinal: { rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); if( rc ){ sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem)); + goto abort_due_to_error; } sqlite3VdbeChangeEncoding(pMem, encoding); UPDATE_MAX_BLOBSIZE(pMem); @@ -6034,7 +6069,8 @@ case OP_Checkpoint: { || pOp->p2==SQLITE_CHECKPOINT_TRUNCATE ); rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]); - if( rc==SQLITE_BUSY ){ + if( rc ){ + if( rc!=SQLITE_BUSY ) goto abort_due_to_error; rc = SQLITE_OK; aRes[0] = 1; } @@ -6107,7 +6143,7 @@ case OP_JournalMode: { /* out2 */ "cannot change %s wal mode from within a transaction", (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of") ); - break; + goto abort_due_to_error; }else{ if( eOld==PAGER_JOURNALMODE_WAL ){ @@ -6137,9 +6173,7 @@ case OP_JournalMode: { /* out2 */ } #endif /* ifndef SQLITE_OMIT_WAL */ - if( rc ){ - eNew = eOld; - } + if( rc ) eNew = eOld; eNew = sqlite3PagerSetJournalMode(pPager, eNew); pOut->flags = MEM_Str|MEM_Static|MEM_Term; @@ -6147,6 +6181,7 @@ case OP_JournalMode: { /* out2 */ pOut->n = sqlite3Strlen30(pOut->z); pOut->enc = SQLITE_UTF8; sqlite3VdbeChangeEncoding(pOut, encoding); + if( rc ) goto abort_due_to_error; break; }; #endif /* SQLITE_OMIT_PRAGMA */ @@ -6161,6 +6196,7 @@ case OP_JournalMode: { /* out2 */ case OP_Vacuum: { assert( p->readOnly==0 ); rc = sqlite3RunVacuum(&p->zErrMsg, db); + if( rc ) goto abort_due_to_error; break; } #endif @@ -6181,7 +6217,8 @@ case OP_IncrVacuum: { /* jump */ pBt = db->aDb[pOp->p1].pBt; rc = sqlite3BtreeIncrVacuum(pBt); VdbeBranchTaken(rc==SQLITE_DONE,2); - if( rc==SQLITE_DONE ){ + if( rc ){ + if( rc!=SQLITE_DONE ) goto abort_due_to_error; rc = SQLITE_OK; goto jump_to_p2; } @@ -6232,9 +6269,12 @@ case OP_TableLock: { assert( DbMaskTest(p->btreeMask, p1) ); assert( isWriteLock==0 || isWriteLock==1 ); rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock); - if( (rc&0xFF)==SQLITE_LOCKED ){ - const char *z = pOp->p4.z; - sqlite3VdbeError(p, "database table is locked: %s", z); + if( rc ){ + if( (rc&0xFF)==SQLITE_LOCKED ){ + const char *z = pOp->p4.z; + sqlite3VdbeError(p, "database table is locked: %s", z); + } + goto abort_due_to_error; } } break; @@ -6256,6 +6296,7 @@ case OP_VBegin: { pVTab = pOp->p4.pVtab; rc = sqlite3VtabBegin(db, pVTab); if( pVTab ) sqlite3VtabImportErrmsg(p, pVTab->pVtab); + if( rc ) goto abort_due_to_error; break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -6284,6 +6325,7 @@ case OP_VCreate: { rc = sqlite3VtabCallCreate(db, pOp->p1, zTab, &p->zErrMsg); } sqlite3VdbeMemRelease(&sMem); + if( rc ) goto abort_due_to_error; break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -6298,6 +6340,7 @@ case OP_VDestroy: { db->nVDestroy++; rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z); db->nVDestroy--; + if( rc ) goto abort_due_to_error; break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -6321,25 +6364,25 @@ case OP_VOpen: { pVtab = pOp->p4.pVtab->pVtab; if( pVtab==0 || NEVER(pVtab->pModule==0) ){ rc = SQLITE_LOCKED; - break; + goto abort_due_to_error; } pModule = pVtab->pModule; rc = pModule->xOpen(pVtab, &pVCur); sqlite3VtabImportErrmsg(p, pVtab); - if( SQLITE_OK==rc ){ - /* Initialize sqlite3_vtab_cursor base class */ - pVCur->pVtab = pVtab; + if( rc ) goto abort_due_to_error; - /* Initialize vdbe cursor object */ - pCur = allocateCursor(p, pOp->p1, 0, -1, CURTYPE_VTAB); - if( pCur ){ - pCur->uc.pVCur = pVCur; - pVtab->nRef++; - }else{ - assert( db->mallocFailed ); - pModule->xClose(pVCur); - goto no_mem; - } + /* Initialize sqlite3_vtab_cursor base class */ + pVCur->pVtab = pVtab; + + /* Initialize vdbe cursor object */ + pCur = allocateCursor(p, pOp->p1, 0, -1, CURTYPE_VTAB); + if( pCur ){ + pCur->uc.pVCur = pVCur; + pVtab->nRef++; + }else{ + assert( db->mallocFailed ); + pModule->xClose(pVCur); + goto no_mem; } break; } @@ -6401,9 +6444,8 @@ case OP_VFilter: { /* jump */ } rc = pModule->xFilter(pVCur, iQuery, pOp->p4.z, nArg, apArg); sqlite3VtabImportErrmsg(p, pVtab); - if( rc==SQLITE_OK ){ - res = pModule->xEof(pVCur); - } + if( rc ) goto abort_due_to_error; + res = pModule->xEof(pVCur); pCur->nullRow = 0; VdbeBranchTaken(res!=0,2); if( res ) goto jump_to_p2; @@ -6452,6 +6494,7 @@ case OP_VColumn: { if( sqlite3VdbeMemTooBig(pDest) ){ goto too_big; } + if( rc ) goto abort_due_to_error; break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -6487,9 +6530,8 @@ case OP_VNext: { /* jump */ */ rc = pModule->xNext(pCur->uc.pVCur); sqlite3VtabImportErrmsg(p, pVtab); - if( rc==SQLITE_OK ){ - res = pModule->xEof(pCur->uc.pVCur); - } + if( rc ) goto abort_due_to_error; + res = pModule->xEof(pCur->uc.pVCur); VdbeBranchTaken(!res,2); if( !res ){ /* If there is data, jump to P2 */ @@ -6521,11 +6563,11 @@ case OP_VRename: { testcase( pName->enc==SQLITE_UTF16BE ); testcase( pName->enc==SQLITE_UTF16LE ); rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8); - if( rc==SQLITE_OK ){ - rc = pVtab->pModule->xRename(pVtab, pName->z); - sqlite3VtabImportErrmsg(p, pVtab); - p->expired = 0; - } + if( rc ) goto abort_due_to_error; + rc = pVtab->pModule->xRename(pVtab, pName->z); + sqlite3VtabImportErrmsg(p, pVtab); + p->expired = 0; + if( rc ) goto abort_due_to_error; break; } #endif @@ -6574,7 +6616,7 @@ case OP_VUpdate: { pVtab = pOp->p4.pVtab->pVtab; if( pVtab==0 || NEVER(pVtab->pModule==0) ){ rc = SQLITE_LOCKED; - break; + goto abort_due_to_error; } pModule = pVtab->pModule; nArg = pOp->p2; @@ -6606,6 +6648,7 @@ case OP_VUpdate: { }else{ p->nChange++; } + if( rc ) goto abort_due_to_error; } break; } @@ -6777,8 +6820,12 @@ default: { /* This is really OP_Noop and OP_Explain */ /* If we reach this point, it means that execution is finished with ** an error of some kind. */ -vdbe_error_halt: +abort_due_to_error: + if( db->mallocFailed ) rc = SQLITE_NOMEM_BKPT; assert( rc ); + if( p->zErrMsg==0 && rc!=SQLITE_IOERR_NOMEM ){ + sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); + } p->rc = rc; testcase( sqlite3GlobalConfig.xLog!=0 ); sqlite3_log(rc, "statement aborts at %d: [%s] %s", @@ -6809,7 +6856,7 @@ vdbe_return: too_big: sqlite3VdbeError(p, "string or blob too big"); rc = SQLITE_TOOBIG; - goto vdbe_error_halt; + goto abort_due_to_error; /* Jump to here if a malloc() fails. */ @@ -6817,18 +6864,7 @@ no_mem: sqlite3OomFault(db); sqlite3VdbeError(p, "out of memory"); rc = SQLITE_NOMEM_BKPT; - goto vdbe_error_halt; - - /* Jump to here for any other kind of fatal error. The "rc" variable - ** should hold the error number. - */ -abort_due_to_error: - assert( p->zErrMsg==0 ); - if( db->mallocFailed ) rc = SQLITE_NOMEM_BKPT; - if( rc!=SQLITE_IOERR_NOMEM ){ - sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); - } - goto vdbe_error_halt; + goto abort_due_to_error; /* Jump to here if the sqlite3_interrupt() API sets the interrupt ** flag. @@ -6838,5 +6874,5 @@ abort_due_to_interrupt: rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; p->rc = rc; sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); - goto vdbe_error_halt; + goto abort_due_to_error; } From 5b081d8a2839c0d4183f3ceb67bf3b6170e4dd3f Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 18 Feb 2016 01:29:12 +0000 Subject: [PATCH 309/570] Add extra API armor on the sqlite3_bind_blob() interface. FossilOrigin-Name: 80de1ad5eb4c3839756b6467d5b8195b4abfb1f8 --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/vdbeapi.c | 3 +++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index b21fdb1ca1..47cc7ca96b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\sVDBE\sopcodes\sfail,\sthey\scause\san\simmediate\sexit\sfrom\sthe\sloop,\srather\nthan\sdepending\son\sthe\src==SQLITE_OK\stest\sat\sthe\stop\sof\sthe\sloop.\s\sThis\sis\nfaster\sand\ssmaller. -D 2016-02-17T20:47:24.973 +C Add\sextra\sAPI\sarmor\son\sthe\ssqlite3_bind_blob()\sinterface. +D 2016-02-18T01:29:12.161 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -417,7 +417,7 @@ F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c 4eef77da4b81763a25992cc060506c001ebd4e3d F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 -F src/vdbeapi.c bfc06382d5089944388a90e4f90bb1e975b3613d +F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 F src/vdbeaux.c 3580de0325a05663195d8f8fddf48c6dd9a28522 F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c be8381ed6de54eb9cb9dfa802823cdeb5166d855 @@ -1428,8 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c17d7276b8c114df5fe6e9ea14d59758443c281b a444633a827642bcf4d02a461e7e5f66769d39fd -R 99549bba2f02d5e0c4a44abe6153e853 -T +closed a444633a827642bcf4d02a461e7e5f66769d39fd +P 24c7151c1aabeaffcb8bb5836404e70a3ec4681b +R f0b4335702e227844828d1e40e95332a U drh -Z fc76c9d80b0512ba6c14a32a0f780946 +Z ca0837f1f24e7471925104495cb0295d diff --git a/manifest.uuid b/manifest.uuid index adcedef80e..6621d165b5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -24c7151c1aabeaffcb8bb5836404e70a3ec4681b \ No newline at end of file +80de1ad5eb4c3839756b6467d5b8195b4abfb1f8 \ No newline at end of file diff --git a/src/vdbeapi.c b/src/vdbeapi.c index b25b1ce5f4..c2038137d1 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -1301,6 +1301,9 @@ int sqlite3_bind_blob( int nData, void (*xDel)(void*) ){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( nData<0 ) return SQLITE_MISUSE_BKPT; +#endif return bindText(pStmt, i, zData, nData, xDel, 0); } int sqlite3_bind_blob64( From a0c2d3c15502695a82a5fcf7af84e6955321f94a Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 18 Feb 2016 13:32:34 +0000 Subject: [PATCH 310/570] Remove an unnecessary "include " line from fts5_test_mi.c. FossilOrigin-Name: 31d8b69e9e0747e573516570bfe2770384e99134 --- ext/fts5/fts5_test_mi.c | 1 - manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ext/fts5/fts5_test_mi.c b/ext/fts5/fts5_test_mi.c index 96fad6d331..b509240b21 100644 --- a/ext/fts5/fts5_test_mi.c +++ b/ext/fts5/fts5_test_mi.c @@ -44,7 +44,6 @@ #ifdef SQLITE_ENABLE_FTS5 #include "fts5.h" -#include #include #include diff --git a/manifest b/manifest index 47cc7ca96b..b710c6a5c3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sextra\sAPI\sarmor\son\sthe\ssqlite3_bind_blob()\sinterface. -D 2016-02-18T01:29:12.161 +C Remove\san\sunnecessary\s"include\s"\sline\sfrom\sfts5_test_mi.c. +D 2016-02-18T13:32:34.131 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -108,7 +108,7 @@ F ext/fts5/fts5_index.c 78069efb54559a17c35906a741362d0b5c899bd0 F ext/fts5/fts5_main.c db24ac714c6c4a1b3c24a1f8c25889f2952148c1 F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 -F ext/fts5/fts5_test_mi.c c1bb729651d86c7c70bcd1ec3f12fa83f97035cc +F ext/fts5/fts5_test_mi.c 09a332628b65271da5803e72c723a75bfc65695a F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8 F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf @@ -1428,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 24c7151c1aabeaffcb8bb5836404e70a3ec4681b -R f0b4335702e227844828d1e40e95332a -U drh -Z ca0837f1f24e7471925104495cb0295d +P 80de1ad5eb4c3839756b6467d5b8195b4abfb1f8 +R 32cf564ef89201f9d7ee30986c17a6b0 +U dan +Z 78ba4be2d3fd60f090cc3e09bd972230 diff --git a/manifest.uuid b/manifest.uuid index 6621d165b5..ca84a8cd7c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -80de1ad5eb4c3839756b6467d5b8195b4abfb1f8 \ No newline at end of file +31d8b69e9e0747e573516570bfe2770384e99134 \ No newline at end of file From 4c9d22819fd1a287a8bb1ab5ea70deae8c25a7e5 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 18 Feb 2016 14:03:15 +0000 Subject: [PATCH 311/570] Improved handling of the -v option on the fuzzcheck test program. FossilOrigin-Name: c8cd7804dc905b2b20cd7c0192bcfaceaaa7e2a8 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/fuzzcheck.c | 10 ++++------ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index b710c6a5c3..39e9c1af06 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunnecessary\s"include\s"\sline\sfrom\sfts5_test_mi.c. -D 2016-02-18T13:32:34.131 +C Improved\shandling\sof\sthe\s-v\soption\son\sthe\sfuzzcheck\stest\sprogram. +D 2016-02-18T14:03:15.183 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -765,7 +765,7 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test b47377143f0c80f91ed29d722861077ff34415d5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26 -F test/fuzzcheck.c 3b1707385ee81ae124a0f35c9df6d6d20550917a +F test/fuzzcheck.c 19782d888c5542afe16d5c9336192761f38ea70b F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973 F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba @@ -1428,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 80de1ad5eb4c3839756b6467d5b8195b4abfb1f8 -R 32cf564ef89201f9d7ee30986c17a6b0 -U dan -Z 78ba4be2d3fd60f090cc3e09bd972230 +P 31d8b69e9e0747e573516570bfe2770384e99134 +R a027f18f6ed81f6dba546149a0b77304 +U drh +Z 2e72dfb6b81d85b4231b0f2b20f67f3c diff --git a/manifest.uuid b/manifest.uuid index ca84a8cd7c..b4de2ee70b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -31d8b69e9e0747e573516570bfe2770384e99134 \ No newline at end of file +c8cd7804dc905b2b20cd7c0192bcfaceaaa7e2a8 \ No newline at end of file diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c index cbe13eafe1..e3247b773b 100644 --- a/test/fuzzcheck.c +++ b/test/fuzzcheck.c @@ -784,8 +784,7 @@ static void showHelp(void){ " --export-db DIR Write databases to files(s) in DIR. Works with --dbid\n" " --export-sql DIR Write SQL to file(s) in DIR. Also works with --sqlid\n" " --help Show this help text\n" -" -q Reduced output\n" -" --quiet Reduced output\n" +" -q|--quiet Reduced output\n" " --limit-mem N Limit memory used by test SQLite instance to N bytes\n" " --limit-vdbe Panic if an sync SQL runs for more than 100,000 cycles\n" " --load-sql ARGS... Load SQL scripts fro files into SOURCE-DB\n" @@ -796,8 +795,7 @@ static void showHelp(void){ " --result-trace Show the results of each SQL command\n" " --sqlid N Use only SQL where sqlid=N\n" " --timeout N Abort if any single test case needs more than N seconds\n" -" -v Increased output\n" -" --verbose Increased output\n" +" -v|--verbose Increased output. Repeat for more output.\n" ); } @@ -920,8 +918,8 @@ int main(int argc, char **argv){ }else if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){ quietFlag = 0; - verboseFlag = 1; - runFlags |= SQL_TRACE; + verboseFlag++; + if( verboseFlag>1 ) runFlags |= SQL_TRACE; }else { fatalError("unknown option: %s", argv[i]); From b2bddbbc2d00e7a9beec472d0b6ef8a8c3c7b3c0 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 18 Feb 2016 14:49:28 +0000 Subject: [PATCH 312/570] Avoid a potential buffer overrun if an SQL statement being parsed ends with an illegal "!" token. (This problem was detected by fuzzcheck running under valgrind. The problem was introduced by check-in [9570b6b43df3].) FossilOrigin-Name: 2a8d97e7c8976df0312e1294e8c1da8b15686654 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/tokenize.c | 2 +- test/fuzzcheck.c | 3 +++ test/main.test | 2 +- test/misc1.test | 2 +- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 39e9c1af06..6a10514189 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\shandling\sof\sthe\s-v\soption\son\sthe\sfuzzcheck\stest\sprogram. -D 2016-02-18T14:03:15.183 +C Avoid\sa\spotential\sbuffer\soverrun\sif\san\sSQL\sstatement\sbeing\sparsed\sends\nwith\san\sillegal\s"!"\stoken.\s\s(This\sproblem\swas\sdetected\sby\sfuzzcheck\nrunning\sunder\svalgrind.\sThe\sproblem\swas\sintroduced\sby\scheck-in\s[9570b6b43df3].) +D 2016-02-18T14:49:28.741 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -407,7 +407,7 @@ F src/test_windirent.c 8f5fada630348558d5745b334702f301da1ffc61 F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c -F src/tokenize.c 32aeca12f0d57a5c1c9a88d63e46ed2ee795cdb4 +F src/tokenize.c c4c1d360fafa3dc458fcbb535691b134798dbb70 F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca @@ -765,7 +765,7 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test b47377143f0c80f91ed29d722861077ff34415d5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26 -F test/fuzzcheck.c 19782d888c5542afe16d5c9336192761f38ea70b +F test/fuzzcheck.c 93bb9d309888634615e21ef98d1c30d51483e942 F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973 F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba @@ -856,7 +856,7 @@ F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5 F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431 F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035 F test/lookaside.test 90052e87282de256d613fcf8c9cbb845e4001d2f -F test/main.test 16131264ea0c2b93b95201f0c92958e85f2ba11a +F test/main.test bb75e406c9b64931f3dc7e7f04626633365bb22f F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9 F test/malloc.test 21c213365f2cca95ab2d7dc078dc8525f96065f8 F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a @@ -890,7 +890,7 @@ F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354 F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f -F test/misc1.test 48ebfb5b22a6a058f7b7e1df211226dd1d21409c +F test/misc1.test 6430dabfb4b4fa480633590118964201f94d3ccc F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3 @@ -1428,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 31d8b69e9e0747e573516570bfe2770384e99134 -R a027f18f6ed81f6dba546149a0b77304 +P c8cd7804dc905b2b20cd7c0192bcfaceaaa7e2a8 +R ff7407a00ef53a788829701876392bcd U drh -Z 2e72dfb6b81d85b4231b0f2b20f67f3c +Z e801ae846fbe7280611432828d271852 diff --git a/manifest.uuid b/manifest.uuid index b4de2ee70b..a9ce1d047c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c8cd7804dc905b2b20cd7c0192bcfaceaaa7e2a8 \ No newline at end of file +2a8d97e7c8976df0312e1294e8c1da8b15686654 \ No newline at end of file diff --git a/src/tokenize.c b/src/tokenize.c index 4a5fc0a04a..60af259cab 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -285,7 +285,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ case CC_BANG: { if( z[1]!='=' ){ *tokenType = TK_ILLEGAL; - return 2; + return 1; }else{ *tokenType = TK_NE; return 2; diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c index e3247b773b..1e0ce86e66 100644 --- a/test/fuzzcheck.c +++ b/test/fuzzcheck.c @@ -70,6 +70,7 @@ #include #include #include "sqlite3.h" +#include #define ISSPACE(X) isspace((unsigned char)(X)) #define ISDIGIT(X) isdigit((unsigned char)(X)) @@ -621,12 +622,14 @@ static void inmemVfsRegister(void){ */ static void runSql(sqlite3 *db, const char *zSql, unsigned runFlags){ const char *zMore; + const char *zEnd = &zSql[strlen(zSql)]; sqlite3_stmt *pStmt; while( zSql && zSql[0] ){ zMore = 0; pStmt = 0; sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zMore); + assert( zMore<=zEnd ); if( zMore==zSql ) break; if( runFlags & SQL_TRACE ){ const char *z = zSql; diff --git a/test/main.test b/test/main.test index 3f35afe20c..9346cf6ced 100644 --- a/test/main.test +++ b/test/main.test @@ -319,7 +319,7 @@ do_test main-3.1 { sqlite3 db testdb set v [catch {execsql {SELECT * from T1 where x!!5}} msg] lappend v $msg -} {1 {unrecognized token: "!!"}} +} {1 {unrecognized token: "!"}} do_test main-3.2 { catch {db close} foreach f [glob -nocomplain testdb/*] {forcedelete $f} diff --git a/test/misc1.test b/test/misc1.test index 400a4517b4..e646bfd098 100644 --- a/test/misc1.test +++ b/test/misc1.test @@ -699,7 +699,7 @@ do_catchsql_test misc1-23.3 { # do_test misc1-24.0 { list [catch { sqlite3_prepare_v2 db ! -1 dummy } msg] $msg -} {1 {(1) unrecognized token: "!}} +} {1 {(1) unrecognized token: "!"}} # The following query (provided by Kostya Serebryany) used to take 25 # minutes to prepare. This has been speeded up to about 250 milliseconds. From 557d0383ffb2c8aa78d217d4eacda7b7b3568113 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 18 Feb 2016 16:16:43 +0000 Subject: [PATCH 313/570] Remove SQLITE_TEST macros from fts5_test_mi.c. Add the SQLITE_FTS5_ENABLE_TEST_MI compile time symbol - to make it easier to create builds that include the fts5 matchinfo demo by default. FossilOrigin-Name: e2ef6667772eeac6eee3aed5d0609c2a0ef5d8cf --- ext/fts5/fts5_main.c | 11 +++++++++++ ext/fts5/fts5_test_mi.c | 3 --- manifest | 24 +++++++++++++----------- manifest.uuid | 2 +- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index fe1d72e2b0..28f3f3e62c 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -2665,6 +2665,17 @@ static int fts5Init(sqlite3 *db){ ); } } + + /* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file + ** fts5_test_mi.c is compiled and linked into the executable. And call + ** its entry point to enable the matchinfo() demo. */ +#ifdef SQLITE_FTS5_ENABLE_TEST_MI + if( rc==SQLITE_OK ){ + extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*); + rc = sqlite3Fts5TestRegisterMatchinfo(db); + } +#endif + return rc; } diff --git a/ext/fts5/fts5_test_mi.c b/ext/fts5/fts5_test_mi.c index 28331773c0..0987e9e137 100644 --- a/ext/fts5/fts5_test_mi.c +++ b/ext/fts5/fts5_test_mi.c @@ -41,11 +41,9 @@ */ -#ifdef SQLITE_TEST #ifdef SQLITE_ENABLE_FTS5 #include "fts5.h" -#include #include #include @@ -420,5 +418,4 @@ int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){ } #endif /* SQLITE_ENABLE_FTS5 */ -#endif /* SQLITE_TEST */ diff --git a/manifest b/manifest index a33ec564a2..4e7c23afdd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Version\s3.11.0 -D 2016-02-15T17:29:24.141 +C Remove\sSQLITE_TEST\smacros\sfrom\sfts5_test_mi.c.\sAdd\sthe\sSQLITE_FTS5_ENABLE_TEST_MI\scompile\stime\ssymbol\s-\sto\smake\sit\seasier\sto\screate\sbuilds\sthat\sinclude\sthe\sfts5\smatchinfo\sdemo\sby\sdefault. +D 2016-02-18T16:16:43.028 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -105,10 +105,10 @@ F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 F ext/fts5/fts5_index.c c6cd5190c7e5dd94151cb17acd939c82e5c7be2d -F ext/fts5/fts5_main.c 0e01ead4e817483e378e7e38e6d902f50b68d29e +F ext/fts5/fts5_main.c db24ac714c6c4a1b3c24a1f8c25889f2952148c1 F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 -F ext/fts5/fts5_test_mi.c 1ec66ffdf7632077fbd773b7a6df5153272ec070 +F ext/fts5/fts5_test_mi.c 31a42dc3dcf1eb6127a0a1acf42ab4aa1d5e5c81 F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8 F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf @@ -1427,10 +1427,12 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f694e60a79024967a3f4574e3928f0b28589d381 -R f2e9debe8cf42a0179962a66a44645cf -T +bgcolor * #d0c0ff -T +sym-release * -T +sym-version-3.11.0 * -U drh -Z e719a8e2c047e401006dde85de2084bf +P 3d862f207e3adc00f78066799ac5a8c282430a5f +Q +31d8b69e9e0747e573516570bfe2770384e99134 +Q +87e6e225aea3a4d10476d16eab4a6403a4a128c9 +R 484f9306b9fcc0db5560ffd225058ba6 +T *branch * branch-3.11-matchinfo +T *sym-branch-3.11-matchinfo * +T -sym-trunk * +U dan +Z 3fda90a50bad45cca94156f3729f0ff4 diff --git a/manifest.uuid b/manifest.uuid index 474c1210cb..6fc4c0871b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3d862f207e3adc00f78066799ac5a8c282430a5f \ No newline at end of file +e2ef6667772eeac6eee3aed5d0609c2a0ef5d8cf \ No newline at end of file From 45dc877f764068e1f73c835e95adf585659b953c Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 18 Feb 2016 21:00:29 +0000 Subject: [PATCH 314/570] Correct the install location for the UWP VSIX package. FossilOrigin-Name: b47d03027e973e3c8d77246a2d2100881f6a9bd2 --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- tool/mkvsix.tcl | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index a33ec564a2..8223b99bf9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Version\s3.11.0 -D 2016-02-15T17:29:24.141 +C Correct\sthe\sinstall\slocation\sfor\sthe\sUWP\sVSIX\spackage. +D 2016-02-18T21:00:29.393 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -1394,7 +1394,7 @@ F tool/mksqlite3c-noext.tcl 87240b09c20042999b41d5fabe091b7111287835 F tool/mksqlite3c.tcl b66b4170f693602cd6985aed15d9509fe2f18c84 F tool/mksqlite3h.tcl 1d41ab59bffb025121f75b76e183125ce41b3ec8 F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b -F tool/mkvsix.tcl fbeb0af7cffdf64e0fba6d65e2e5120dc14595f4 +F tool/mkvsix.tcl 4abcaf3267171b2faadaf9b82a0dfbaa6e98f8b7 F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091 F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97 F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b @@ -1427,10 +1427,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f694e60a79024967a3f4574e3928f0b28589d381 -R f2e9debe8cf42a0179962a66a44645cf -T +bgcolor * #d0c0ff -T +sym-release * -T +sym-version-3.11.0 * -U drh -Z e719a8e2c047e401006dde85de2084bf +P 3d862f207e3adc00f78066799ac5a8c282430a5f +R def276118187d24a6d1ced842c1b577e +T *branch * branch-3.11 +T *sym-branch-3.11 * +T -sym-trunk * +U mistachkin +Z 6d321d146d87ca8038cd070ce8c81c6a diff --git a/manifest.uuid b/manifest.uuid index 474c1210cb..bd1171e6f5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3d862f207e3adc00f78066799ac5a8c282430a5f \ No newline at end of file +b47d03027e973e3c8d77246a2d2100881f6a9bd2 \ No newline at end of file diff --git a/tool/mkvsix.tcl b/tool/mkvsix.tcl index a14fd230d9..b7350f9c84 100644 --- a/tool/mkvsix.tcl +++ b/tool/mkvsix.tcl @@ -463,7 +463,7 @@ if {[string equal $packageFlavor WinRT]} then { } set shortName $shortNames($packageFlavor,$vsVersion) set displayName $displayNames($packageFlavor,$vsVersion) - set targetPlatformIdentifier UWP + set targetPlatformIdentifier UAP; # NOTE: Not "UWP". set targetPlatformVersion v0.8.0.0 set minVsVersion [getMinVsVersionXmlChunk $vsVersion] set maxPlatformVersion \ From b9076ba4c994a1532f26e74f65c51611d7ef9fbd Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 19 Feb 2016 00:47:18 +0000 Subject: [PATCH 315/570] Further improvements to the MSVC batch build tool. FossilOrigin-Name: 90dd6eb1fec22460473d670519d0e730bb37067d --- manifest | 15 ++++----- manifest.uuid | 2 +- tool/build-all-msvc.bat | 74 +++++++++++++++++++++++++++++++---------- 3 files changed, 64 insertions(+), 27 deletions(-) diff --git a/manifest b/manifest index 8223b99bf9..66116a44c0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Correct\sthe\sinstall\slocation\sfor\sthe\sUWP\sVSIX\spackage. -D 2016-02-18T21:00:29.393 +C Further\simprovements\sto\sthe\sMSVC\sbatch\sbuild\stool. +D 2016-02-19T00:47:18.626 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -1367,7 +1367,7 @@ F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372 F tool/addopcodes.tcl 4ca9c3ef196f08da30add5d07ce0c9458dc8c633 -F tool/build-all-msvc.bat 31866578036cd1d962628059b0760d407c3ce4d8 x +F tool/build-all-msvc.bat ab27285398404cdf99c56430fda7a98f5b1121c2 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 @@ -1427,10 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 3d862f207e3adc00f78066799ac5a8c282430a5f -R def276118187d24a6d1ced842c1b577e -T *branch * branch-3.11 -T *sym-branch-3.11 * -T -sym-trunk * +P b47d03027e973e3c8d77246a2d2100881f6a9bd2 +R 52407255ef725bc9c494bd471eda3f67 U mistachkin -Z 6d321d146d87ca8038cd070ce8c81c6a +Z 739640b3c8a946907b4aabf37d1a947b diff --git a/manifest.uuid b/manifest.uuid index bd1171e6f5..a1149e2673 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b47d03027e973e3c8d77246a2d2100881f6a9bd2 \ No newline at end of file +90dd6eb1fec22460473d670519d0e730bb37067d \ No newline at end of file diff --git a/tool/build-all-msvc.bat b/tool/build-all-msvc.bat index 84528e37c2..c64a4e289c 100755 --- a/tool/build-all-msvc.bat +++ b/tool/build-all-msvc.bat @@ -69,6 +69,11 @@ REM be skipped and they will not appear in the final destination directory. REM Setting this environment variable is never strictly needed and could cause REM issues in some circumstances; therefore, setting it is not recommended. REM +REM NOMEMDEBUG +REM +REM When set, disables use of MEMDEBUG when building binaries for the "Debug" +REM configuration. +REM REM BUILD_ALL_SHELL REM REM When set, the command line shell will be built for each selected platform @@ -99,6 +104,15 @@ REM Using the above command before running this tool will cause the compiled REM binaries to target the WinRT environment, which provides a subset of the REM Win32 API. REM +REM DLL_FILE_NAME +REM DLL_PDB_FILE_NAME +REM LIB_FILE_NAME +REM EXE_FILE_NAME +REM EXE_PDB_FILE_NAME +REM +REM When set, these values will override the associated target file name used +REM for the build. +REM SETLOCAL REM SET __ECHO=ECHO @@ -255,6 +269,30 @@ IF NOT DEFINED %TCLSH_FILE%_PATH ( GOTO errors ) +REM +REM NOTE: Setup the default names for the build targets we are creating. Any +REM ^(or all^) of these may end up being overridden. +REM +IF NOT DEFINED DLL_FILE_NAME ( + SET DLL_FILE_NAME=sqlite3.dll +) + +IF NOT DEFINED DLL_PDB_FILE_NAME ( + SET DLL_PDB_FILE_NAME=sqlite3.pdb +) + +IF NOT DEFINED LIB_FILE_NAME ( + SET LIB_FILE_NAME=sqlite3.lib +) + +IF NOT DEFINED EXE_FILE_NAME ( + SET EXE_FILE_NAME=sqlite3.exe +) + +IF NOT DEFINED EXE_PDB_FILE_NAME ( + SET EXE_PDB_FILE_NAME=sqlite3sh.pdb +) + REM REM NOTE: Set the TOOLPATH variable to contain all the directories where the REM external tools were found in the search above. @@ -434,7 +472,9 @@ FOR %%P IN (%PLATFORMS%) DO ( REM NOTE: Setting this to non-zero should enable the SQLITE_MEMDEBUG REM define. REM - SET MEMDEBUG=1 + IF NOT DEFINED NOMEMDEBUG ( + SET MEMDEBUG=1 + ) ) ELSE ( CALL :fn_UnsetVariable DEBUG CALL :fn_UnsetVariable MEMDEBUG @@ -559,7 +599,7 @@ FOR %%P IN (%PLATFORMS%) DO ( REM specifically wanting to build for each platform. REM %_AECHO% Cleaning final core library output files only... - %__ECHO% DEL /Q *.lo sqlite3.dll sqlite3.lib sqlite3.pdb 2%REDIRECT% NUL + %__ECHO% DEL /Q *.lo "%DLL_FILE_NAME%" "%LIB_FILE_NAME%" "%DLL_PDB_FILE_NAME%" 2%REDIRECT% NUL ) REM @@ -569,10 +609,10 @@ FOR %%P IN (%PLATFORMS%) DO ( REM Also, disable looking for and/or linking to the native Tcl REM runtime library. REM - %__ECHO% %NMAKE_CMD% sqlite3.dll XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% + %__ECHO% %NMAKE_CMD% "%DLL_FILE_NAME%" "PLATFORM=%%D" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% IF ERRORLEVEL 1 ( - ECHO Failed to build %%B "sqlite3.dll" for platform %%P. + ECHO Failed to build %%B "%DLL_FILE_NAME%" for platform %%P. GOTO errors ) @@ -580,10 +620,10 @@ FOR %%P IN (%PLATFORMS%) DO ( REM NOTE: Copy the "sqlite3.dll" file to the appropriate directory for REM the build and platform beneath the binary directory. REM - %__ECHO% XCOPY sqlite3.dll "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% + %__ECHO% XCOPY "%DLL_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% IF ERRORLEVEL 1 ( - ECHO Failed to copy "sqlite3.dll" to "%BINARYDIRECTORY%\%%B\%%D\". + ECHO Failed to copy "%DLL_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\". GOTO errors ) @@ -591,10 +631,10 @@ FOR %%P IN (%PLATFORMS%) DO ( REM NOTE: Copy the "sqlite3.lib" file to the appropriate directory for REM the build and platform beneath the binary directory. REM - %__ECHO% XCOPY sqlite3.lib "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% + %__ECHO% XCOPY "%LIB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% IF ERRORLEVEL 1 ( - ECHO Failed to copy "sqlite3.lib" to "%BINARYDIRECTORY%\%%B\%%D\". + ECHO Failed to copy "%LIB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\". GOTO errors ) @@ -604,10 +644,10 @@ FOR %%P IN (%PLATFORMS%) DO ( REM are prevented from doing so. REM IF NOT DEFINED NOSYMBOLS ( - %__ECHO% XCOPY sqlite3.pdb "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% + %__ECHO% XCOPY "%DLL_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% IF ERRORLEVEL 1 ( - ECHO Failed to copy "sqlite3.pdb" to "%BINARYDIRECTORY%\%%B\%%D\". + ECHO Failed to copy "%DLL_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\". GOTO errors ) ) @@ -627,7 +667,7 @@ FOR %%P IN (%PLATFORMS%) DO ( REM specifically wanting to build for each platform. REM %_AECHO% Cleaning final shell executable output files only... - %__ECHO% DEL /Q sqlite3.exe sqlite3sh.pdb 2%REDIRECT% NUL + %__ECHO% DEL /Q "%EXE_FILE_NAME%" "%EXE_PDB_FILE_NAME%" 2%REDIRECT% NUL ) REM @@ -637,10 +677,10 @@ FOR %%P IN (%PLATFORMS%) DO ( REM Also, disable looking for and/or linking to the native Tcl REM runtime library. REM - %__ECHO% %NMAKE_CMD% sqlite3.exe XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% + %__ECHO% %NMAKE_CMD% "%EXE_FILE_NAME%" "PLATFORM=%%D" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% IF ERRORLEVEL 1 ( - ECHO Failed to build %%B "sqlite3.exe" for platform %%P. + ECHO Failed to build %%B "%EXE_FILE_NAME%" for platform %%P. GOTO errors ) @@ -648,10 +688,10 @@ FOR %%P IN (%PLATFORMS%) DO ( REM NOTE: Copy the "sqlite3.exe" file to the appropriate directory REM for the build and platform beneath the binary directory. REM - %__ECHO% XCOPY sqlite3.exe "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% + %__ECHO% XCOPY "%EXE_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% IF ERRORLEVEL 1 ( - ECHO Failed to copy "sqlite3.exe" to "%BINARYDIRECTORY%\%%B\%%D\". + ECHO Failed to copy "%EXE_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\". GOTO errors ) @@ -661,10 +701,10 @@ FOR %%P IN (%PLATFORMS%) DO ( REM unless we are prevented from doing so. REM IF NOT DEFINED NOSYMBOLS ( - %__ECHO% XCOPY sqlite3sh.pdb "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% + %__ECHO% XCOPY "%EXE_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% IF ERRORLEVEL 1 ( - ECHO Failed to copy "sqlite3sh.pdb" to "%BINARYDIRECTORY%\%%B\%%D\". + ECHO Failed to copy "%EXE_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\". GOTO errors ) ) From b0c99afeda51a77e1b35b428070d3600dbf1cd2e Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 19 Feb 2016 05:07:56 +0000 Subject: [PATCH 316/570] Modify the MSVC batch build tool to support the MSVC autoconf Makefile. FossilOrigin-Name: 72b10e5e7d2db436c7b03cc3735a2e9d0e53ab5d --- Makefile.msc | 27 ++++++++++++++--------- autoconf/Makefile.msc | 30 ++++++++++++++----------- manifest | 18 +++++++-------- manifest.uuid | 2 +- tool/build-all-msvc.bat | 49 ++++++++++++++++++++++++++++++++++------- tool/mkmsvcmin.tcl | 1 + 6 files changed, 86 insertions(+), 41 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 843f9a2537..1782b7551a 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -219,27 +219,43 @@ SQLITE3H = sqlite3.h # This is the name to use for the SQLite dynamic link library (DLL). # !IFNDEF SQLITE3DLL +!IF $(FOR_WIN10)!=0 +SQLITE3DLL = winsqlite3.dll +!ELSE SQLITE3DLL = sqlite3.dll !ENDIF +!ENDIF # This is the name to use for the SQLite import library (LIB). # !IFNDEF SQLITE3LIB +!IF $(FOR_WIN10)!=0 +SQLITE3LIB = winsqlite3.lib +!ELSE SQLITE3LIB = sqlite3.lib !ENDIF +!ENDIF # This is the name to use for the SQLite shell executable (EXE). # !IFNDEF SQLITE3EXE +!IF $(FOR_WIN10)!=0 +SQLITE3EXE = winsqlite3shell.exe +!ELSE SQLITE3EXE = sqlite3.exe !ENDIF +!ENDIF # This is the argument used to set the program database (PDB) file for the # SQLite shell executable (EXE). # !IFNDEF SQLITE3EXEPDB +!IF $(FOR_WIN10)!=0 +SQLITE3EXEPDB = +!ELSE SQLITE3EXEPDB = /pdb:sqlite3sh.pdb !ENDIF +!ENDIF # These are the "standard" SQLite compilation options used when compiling for # the Windows platform. @@ -417,15 +433,6 @@ TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS) TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS) -# Adjust the names of the primary targets for use with Windows 10. -# -!IF $(FOR_WIN10)!=0 -SQLITE3DLL = winsqlite3.dll -SQLITE3LIB = winsqlite3.lib -SQLITE3EXE = winsqlite3shell.exe -SQLITE3EXEPDB = -!ENDIF - # Check if we want to use the "stdcall" calling convention when compiling. # This is not supported by the compilers for non-x86 platforms. It should # also be noted here that building any target with these "stdcall" options @@ -1386,10 +1393,10 @@ dll: $(SQLITE3DLL) # shell: $(SQLITE3EXE) +# <> libsqlite3.lib: $(LIBOBJ) $(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS) -# <> libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib $(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCLSTUB) $(TLIBS) # <> diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index 0be42b4e5f..8bb7ac2973 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -204,27 +204,43 @@ SQLITE3H = sqlite3.h # This is the name to use for the SQLite dynamic link library (DLL). # !IFNDEF SQLITE3DLL +!IF $(FOR_WIN10)!=0 +SQLITE3DLL = winsqlite3.dll +!ELSE SQLITE3DLL = sqlite3.dll !ENDIF +!ENDIF # This is the name to use for the SQLite import library (LIB). # !IFNDEF SQLITE3LIB +!IF $(FOR_WIN10)!=0 +SQLITE3LIB = winsqlite3.lib +!ELSE SQLITE3LIB = sqlite3.lib !ENDIF +!ENDIF # This is the name to use for the SQLite shell executable (EXE). # !IFNDEF SQLITE3EXE +!IF $(FOR_WIN10)!=0 +SQLITE3EXE = winsqlite3shell.exe +!ELSE SQLITE3EXE = sqlite3.exe !ENDIF +!ENDIF # This is the argument used to set the program database (PDB) file for the # SQLite shell executable (EXE). # !IFNDEF SQLITE3EXEPDB +!IF $(FOR_WIN10)!=0 +SQLITE3EXEPDB = +!ELSE SQLITE3EXEPDB = /pdb:sqlite3sh.pdb !ENDIF +!ENDIF # These are the "standard" SQLite compilation options used when compiling for # the Windows platform. @@ -402,15 +418,6 @@ TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS) TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -fp:precise RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS) -# Adjust the names of the primary targets for use with Windows 10. -# -!IF $(FOR_WIN10)!=0 -SQLITE3DLL = winsqlite3.dll -SQLITE3LIB = winsqlite3.lib -SQLITE3EXE = winsqlite3shell.exe -SQLITE3EXEPDB = -!ENDIF - # Check if we want to use the "stdcall" calling convention when compiling. # This is not supported by the compilers for non-x86 platforms. It should # also be noted here that building any target with these "stdcall" options @@ -863,7 +870,7 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_ # This is the default Makefile target. The objects listed here # are what get build when you type just "make" with no arguments. # -all: dll libsqlite3.lib shell +all: dll shell # Dynamic link library section. # @@ -873,9 +880,6 @@ dll: $(SQLITE3DLL) # shell: $(SQLITE3EXE) -libsqlite3.lib: $(LIBOBJ) - $(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS) - $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) diff --git a/manifest b/manifest index 66116a44c0..27f4a99e1c 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Further\simprovements\sto\sthe\sMSVC\sbatch\sbuild\stool. -D 2016-02-19T00:47:18.626 +C Modify\sthe\sMSVC\sbatch\sbuild\stool\sto\ssupport\sthe\sMSVC\sautoconf\sMakefile. +D 2016-02-19T05:07:56.206 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 +F Makefile.msc d3a190d93235a9aa142e4ade7b473435a5d376f9 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -11,7 +11,7 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 29e2a6e8d0c5e32723a48b4faf6b168854dde5f4 -F autoconf/Makefile.msc b865d2c72cf43cbf39913336415556af8ff2e819 +F autoconf/Makefile.msc fe04b5870a3e4b98c73e8a82e04e98f330da7ea7 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 7c31da66232f7590bb987cfcd4e2381744b25d24 F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8 @@ -1367,7 +1367,7 @@ F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372 F tool/addopcodes.tcl 4ca9c3ef196f08da30add5d07ce0c9458dc8c633 -F tool/build-all-msvc.bat ab27285398404cdf99c56430fda7a98f5b1121c2 x +F tool/build-all-msvc.bat fba6e16e6bad4600b6ab278ca90b1fcf74de63de x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 @@ -1384,7 +1384,7 @@ F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh c78caa3214f25dc28ea157b5a82abb311f209906 F tool/mkkeywordhash.c f7f3b342211ac6a14258b9726d5b97cf4f548f22 -F tool/mkmsvcmin.tcl d57e6efc9428605f5418d0b235721ddf7b5d9c0b +F tool/mkmsvcmin.tcl f9fc6f6a373084c0e0feef972485212bd0869c06 F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 385c62d78c38b2d92146dcb5abd319dbbc33506d F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b47d03027e973e3c8d77246a2d2100881f6a9bd2 -R 52407255ef725bc9c494bd471eda3f67 +P 90dd6eb1fec22460473d670519d0e730bb37067d +R c6d10791b59e57f5d1181c2f31399663 U mistachkin -Z 739640b3c8a946907b4aabf37d1a947b +Z 5c3b7d3d4a467152f425917bb5dd9dae diff --git a/manifest.uuid b/manifest.uuid index a1149e2673..92cc237f4b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -90dd6eb1fec22460473d670519d0e730bb37067d \ No newline at end of file +72b10e5e7d2db436c7b03cc3735a2e9d0e53ab5d \ No newline at end of file diff --git a/tool/build-all-msvc.bat b/tool/build-all-msvc.bat index c64a4e289c..c09ab1cd1c 100755 --- a/tool/build-all-msvc.bat +++ b/tool/build-all-msvc.bat @@ -22,7 +22,7 @@ REM REM Example: REM REM CD /D C:\dev\sqlite\core -REM tool\build-all-msvc.bat C:\Temp +REM CALL tool\build-all-msvc.bat C:\Temp REM REM In the example above, "C:\dev\sqlite\core" represents the root of the REM source tree for SQLite and "C:\Temp" represents the final destination @@ -54,6 +54,11 @@ REM REM There are a few other environment variables that impact the build process REM when set ^(to anything^), they are: REM +REM USE_AUTOCONF_MAKEFILE +REM +REM When set, the "autoconf" Makefile for MSVC will be used instead of the main +REM Makefile for MSVC. It must exist at "%ROOT%\autoconf\Makefile.msc". +REM REM NOCLEAN REM REM When set, the "clean" target will not be used during each build iteration. @@ -93,12 +98,16 @@ REM on the WindowsSdkDir environment variable. It causes this batch script to REM assume the Windows 10.0 SDK location should be used. REM REM NMAKE_ARGS +REM NMAKE_ARGS_DEBUG +REM NMAKE_ARGS_RETAIL REM -REM When set, the value is expanded and passed to the NMAKE command line, after -REM its other arguments. This is used to specify additional NMAKE options, for -REM example: +REM When set, these values are expanded and passed to the NMAKE command line, +REM after its other arguments. These may be used to specify additional NMAKE +REM options, for example: REM REM SET NMAKE_ARGS=FOR_WINRT=1 +REM SET NMAKE_ARGS_DEBUG=MEMDEBUG=1 +REM SET NMAKE_ARGS_RETAIL=WIN32HEAP=1 REM REM Using the above command before running this tool will cause the compiled REM binaries to target the WinRT environment, which provides a subset of the @@ -218,11 +227,17 @@ REM NOTE: If the command used to invoke NMAKE is not already set, use the REM default. REM IF NOT DEFINED NMAKE_CMD ( - SET NMAKE_CMD=nmake -B -f Makefile.msc + IF DEFINED USE_AUTOCONF_MAKEFILE ( + SET NMAKE_CMD=nmake -B -f autoconf\Makefile.msc + ) ELSE ( + SET NMAKE_CMD=nmake -B -f Makefile.msc + ) ) %_VECHO% NmakeCmd = '%NMAKE_CMD%' %_VECHO% NmakeArgs = '%NMAKE_ARGS%' +%_VECHO% NmakeArgsDebug = '%NMAKE_ARGS_DEBUG%' +%_VECHO% NmakeArgsRetail = '%NMAKE_ARGS_RETAIL%' REM REM NOTE: Setup environment variables to translate between the MSVC platform @@ -480,6 +495,12 @@ FOR %%P IN (%PLATFORMS%) DO ( CALL :fn_UnsetVariable MEMDEBUG ) + REM + REM NOTE: Copy the extra NMAKE arguments for this configuration into the + REM common variable used by the actual commands. + REM + CALL :fn_CopyVariable NMAKE_ARGS_%%B NMAKE_ARGS_CFG + REM REM NOTE: Launch a nested command shell to perform the following steps: REM @@ -586,7 +607,7 @@ FOR %%P IN (%PLATFORMS%) DO ( REM file, etc. REM IF NOT DEFINED NOCLEAN ( - %__ECHO% %NMAKE_CMD% clean + CALL :fn_MakeClean %%D IF ERRORLEVEL 1 ( ECHO Failed to clean for platform %%P. @@ -609,7 +630,7 @@ FOR %%P IN (%PLATFORMS%) DO ( REM Also, disable looking for and/or linking to the native Tcl REM runtime library. REM - %__ECHO% %NMAKE_CMD% "%DLL_FILE_NAME%" "PLATFORM=%%D" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% + CALL :fn_MakeDll %%D IF ERRORLEVEL 1 ( ECHO Failed to build %%B "%DLL_FILE_NAME%" for platform %%P. @@ -677,7 +698,7 @@ FOR %%P IN (%PLATFORMS%) DO ( REM Also, disable looking for and/or linking to the native Tcl REM runtime library. REM - %__ECHO% %NMAKE_CMD% "%EXE_FILE_NAME%" "PLATFORM=%%D" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% + CALL :fn_MakeExe %%D IF ERRORLEVEL 1 ( ECHO Failed to build %%B "%EXE_FILE_NAME%" for platform %%P. @@ -736,6 +757,18 @@ REM NOTE: If we get to this point, we have succeeded. REM GOTO no_errors +:fn_MakeClean + %__ECHO% %NMAKE_CMD% clean "PLATFORM=%1" %NMAKE_ARGS% %NMAKE_ARGS_CFG% + GOTO :EOF + +:fn_MakeDll + %__ECHO% %NMAKE_CMD% "%DLL_FILE_NAME%" "PLATFORM=%1" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% %NMAKE_ARGS_CFG% + GOTO :EOF + +:fn_MakeExe + %__ECHO% %NMAKE_CMD% "%EXE_FILE_NAME%" "PLATFORM=%1" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% %NMAKE_ARGS_CFG% + GOTO :EOF + :fn_ShowVariable SETLOCAL SET __ECHO_CMD=ECHO %%%2%% diff --git a/tool/mkmsvcmin.tcl b/tool/mkmsvcmin.tcl index da0cd6283c..41754cd576 100644 --- a/tool/mkmsvcmin.tcl +++ b/tool/mkmsvcmin.tcl @@ -92,6 +92,7 @@ foreach i [lsort -integer [array names blocks]] { set data [string map [list " -I\$(TOP)\\src" ""] $data] set data [string map [list " /DEF:sqlite3.def" ""] $data] set data [string map [list " sqlite3.def" ""] $data] +set data [string map [list " libsqlite3.lib" ""] $data] set data [string map [list " \$(ALL_TCL_TARGETS)" ""] $data] set data [string map [list "\$(TOP)\\src\\" "\$(TOP)\\"] $data] From 92b859292d48a24c827d22d8c2fbce5c450991aa Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 19 Feb 2016 10:18:36 +0000 Subject: [PATCH 317/570] Add an "#ifndef SQLITE_AMALGAMATION" guard around a typedef in fts5_test_mi.c to avoid redefining "u32" if it is compiled as part of the amalgamation. FossilOrigin-Name: f9c49ba1edf13cb8c48d73f1b2e3f80c46b3c030 --- ext/fts5/fts5_test_mi.c | 3 +++ manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ext/fts5/fts5_test_mi.c b/ext/fts5/fts5_test_mi.c index b509240b21..bc6d01f126 100644 --- a/ext/fts5/fts5_test_mi.c +++ b/ext/fts5/fts5_test_mi.c @@ -48,7 +48,10 @@ #include typedef struct Fts5MatchinfoCtx Fts5MatchinfoCtx; + +#ifndef SQLITE_AMALGAMATION typedef unsigned int u32; +#endif struct Fts5MatchinfoCtx { int nCol; /* Number of cols in FTS5 table */ diff --git a/manifest b/manifest index 804f19ea26..390f6de035 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\simprovements\sto\sthe\sMSVC\sbatch\sbuild\stool. -D 2016-02-19T00:48:23.870 +C Add\san\s"#ifndef\sSQLITE_AMALGAMATION"\sguard\saround\sa\stypedef\sin\sfts5_test_mi.c\sto\savoid\sredefining\s"u32"\sif\sit\sis\scompiled\sas\spart\sof\sthe\samalgamation. +D 2016-02-19T10:18:36.453 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -108,7 +108,7 @@ F ext/fts5/fts5_index.c 78069efb54559a17c35906a741362d0b5c899bd0 F ext/fts5/fts5_main.c db24ac714c6c4a1b3c24a1f8c25889f2952148c1 F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 -F ext/fts5/fts5_test_mi.c 09a332628b65271da5803e72c723a75bfc65695a +F ext/fts5/fts5_test_mi.c b8d04816428202b2898d4ca38deb1739ac0110ae F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8 F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf @@ -1428,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f74de325ffb01a1ca8ddd4f011188e38296c3402 90dd6eb1fec22460473d670519d0e730bb37067d -R e824ea0707e0554d332b81d14a570ac2 -U mistachkin -Z 514b043e9dc9c196caf2eb7d2fd83711 +P b9626b5954068ae2e7733dd14f906a1f6d7090a5 +R da0a6cae91db1fce2dac362cc1366301 +U dan +Z 070f4a73f6ec42ddf571ffbbc3f021c2 diff --git a/manifest.uuid b/manifest.uuid index 0426425cd8..cb257cad80 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b9626b5954068ae2e7733dd14f906a1f6d7090a5 \ No newline at end of file +f9c49ba1edf13cb8c48d73f1b2e3f80c46b3c030 \ No newline at end of file From 9e2cfad18a5566411b6da5aa200d73b80c3fa6d2 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 19 Feb 2016 10:19:43 +0000 Subject: [PATCH 318/570] Add an "#ifndef SQLITE_AMALGAMATION" guard around a typedef in fts5_test_mi.c to avoid redefining "u32" if it is compiled as part of the amalgamation. Cherrypick of [f9c49ba1]. FossilOrigin-Name: ce0f1ed517e387ca6a687b805088d7c529cd257b --- ext/fts5/fts5_test_mi.c | 3 +++ manifest | 18 +++++++----------- manifest.uuid | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/ext/fts5/fts5_test_mi.c b/ext/fts5/fts5_test_mi.c index 0987e9e137..7bbb4ed600 100644 --- a/ext/fts5/fts5_test_mi.c +++ b/ext/fts5/fts5_test_mi.c @@ -48,7 +48,10 @@ #include typedef struct Fts5MatchinfoCtx Fts5MatchinfoCtx; + +#ifndef SQLITE_AMALGAMATION typedef unsigned int u32; +#endif struct Fts5MatchinfoCtx { int nCol; /* Number of cols in FTS5 table */ diff --git a/manifest b/manifest index 4e7c23afdd..8c52a9794a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sSQLITE_TEST\smacros\sfrom\sfts5_test_mi.c.\sAdd\sthe\sSQLITE_FTS5_ENABLE_TEST_MI\scompile\stime\ssymbol\s-\sto\smake\sit\seasier\sto\screate\sbuilds\sthat\sinclude\sthe\sfts5\smatchinfo\sdemo\sby\sdefault. -D 2016-02-18T16:16:43.028 +C Add\san\s"#ifndef\sSQLITE_AMALGAMATION"\sguard\saround\sa\stypedef\sin\sfts5_test_mi.c\sto\savoid\sredefining\s"u32"\sif\sit\sis\scompiled\sas\spart\sof\sthe\samalgamation.\sCherrypick\sof\s[f9c49ba1]. +D 2016-02-19T10:19:43.655 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -108,7 +108,7 @@ F ext/fts5/fts5_index.c c6cd5190c7e5dd94151cb17acd939c82e5c7be2d F ext/fts5/fts5_main.c db24ac714c6c4a1b3c24a1f8c25889f2952148c1 F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 -F ext/fts5/fts5_test_mi.c 31a42dc3dcf1eb6127a0a1acf42ab4aa1d5e5c81 +F ext/fts5/fts5_test_mi.c 6f76bfc2ec56ce258763c5ace7608636c8745956 F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8 F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf @@ -1427,12 +1427,8 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 3d862f207e3adc00f78066799ac5a8c282430a5f -Q +31d8b69e9e0747e573516570bfe2770384e99134 -Q +87e6e225aea3a4d10476d16eab4a6403a4a128c9 -R 484f9306b9fcc0db5560ffd225058ba6 -T *branch * branch-3.11-matchinfo -T *sym-branch-3.11-matchinfo * -T -sym-trunk * +P e2ef6667772eeac6eee3aed5d0609c2a0ef5d8cf +Q +f9c49ba1edf13cb8c48d73f1b2e3f80c46b3c030 +R 86861d7afb256ba49d3c7d2e1e2e6725 U dan -Z 3fda90a50bad45cca94156f3729f0ff4 +Z 1618528e1896e183cb510df07cb30bf4 diff --git a/manifest.uuid b/manifest.uuid index 6fc4c0871b..6c518eaaf7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e2ef6667772eeac6eee3aed5d0609c2a0ef5d8cf \ No newline at end of file +ce0f1ed517e387ca6a687b805088d7c529cd257b \ No newline at end of file From 51381c208e5a15b140ebda208d30fcd2169227bc Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 19 Feb 2016 13:19:22 +0000 Subject: [PATCH 319/570] Omit the unused yyzerominor constant. FossilOrigin-Name: 60ad68a9f569d2446d76a6453be4fa1c4ed2cd93 --- manifest | 14 +++++++------- manifest.uuid | 2 +- tool/lempar.c | 4 ---- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 390f6de035..e6db1216e9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\san\s"#ifndef\sSQLITE_AMALGAMATION"\sguard\saround\sa\stypedef\sin\sfts5_test_mi.c\sto\savoid\sredefining\s"u32"\sif\sit\sis\scompiled\sas\spart\sof\sthe\samalgamation. -D 2016-02-19T10:18:36.453 +C Omit\sthe\sunused\syyzerominor\sconstant. +D 2016-02-19T13:19:22.204 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -1380,7 +1380,7 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/lemon.c 251f5c3f21b553240cbdd42dd187a51bb2372cd3 -F tool/lempar.c 5f626c741e034da827b4224d0c68eaf6d8fcc72c +F tool/lempar.c d5114c7d13aa3af1e27ff3d02e4dea6eadec7ddf F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh c78caa3214f25dc28ea157b5a82abb311f209906 @@ -1428,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b9626b5954068ae2e7733dd14f906a1f6d7090a5 -R da0a6cae91db1fce2dac362cc1366301 -U dan -Z 070f4a73f6ec42ddf571ffbbc3f021c2 +P f9c49ba1edf13cb8c48d73f1b2e3f80c46b3c030 +R c2e30a818a1524ebcac066213d2c2f9a +U drh +Z d1500e5cad7d5894b150d951c2ce99ae diff --git a/manifest.uuid b/manifest.uuid index cb257cad80..77efe13df0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f9c49ba1edf13cb8c48d73f1b2e3f80c46b3c030 \ No newline at end of file +60ad68a9f569d2446d76a6453be4fa1c4ed2cd93 \ No newline at end of file diff --git a/tool/lempar.c b/tool/lempar.c index f7cb097c34..db7f2dbf1b 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -87,10 +87,6 @@ %% /************* End control #defines *******************************************/ -/* The yyzerominor constant is used to initialize instances of -** YYMINORTYPE objects to zero. */ -static const YYMINORTYPE yyzerominor = { 0 }; - /* Define the yytestcase() macro to be a no-op if is not already defined ** otherwise. ** From 469753d94997464872b5d58f4b727f77b766abf8 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 19 Feb 2016 13:20:02 +0000 Subject: [PATCH 320/570] Add an SQLITE_DISABLE_INTRINSIC #ifdef to the sqlite3Put4Byte() function. FossilOrigin-Name: ba9c6827d0890aaed9168c221fefbdbe89f4f9d3 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/util.c | 6 ++++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index e6db1216e9..6ac0529235 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Omit\sthe\sunused\syyzerominor\sconstant. -D 2016-02-19T13:19:22.204 +C Add\san\sSQLITE_DISABLE_INTRINSIC\s#ifdef\sto\sthe\ssqlite3Put4Byte()\sfunction. +D 2016-02-19T13:20:02.042 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -412,7 +412,7 @@ F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c -F src/util.c 8073bbdab9cc7209f6741bd44264ede606cbadc6 +F src/util.c 38c06684c922694809ccb988a13562c16890a3d5 F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c 4eef77da4b81763a25992cc060506c001ebd4e3d F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 @@ -1428,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f9c49ba1edf13cb8c48d73f1b2e3f80c46b3c030 -R c2e30a818a1524ebcac066213d2c2f9a +P 60ad68a9f569d2446d76a6453be4fa1c4ed2cd93 +R d12bbc92c78d2cfaf446c5b734b63a28 U drh -Z d1500e5cad7d5894b150d951c2ce99ae +Z 22d2505e89be374674fd2948e46d1040 diff --git a/manifest.uuid b/manifest.uuid index 77efe13df0..6d8b3f854a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -60ad68a9f569d2446d76a6453be4fa1c4ed2cd93 \ No newline at end of file +ba9c6827d0890aaed9168c221fefbdbe89f4f9d3 \ No newline at end of file diff --git a/src/util.c b/src/util.c index 928d249215..e325a7311b 100644 --- a/src/util.c +++ b/src/util.c @@ -1116,10 +1116,12 @@ u32 sqlite3Get4byte(const u8 *p){ void sqlite3Put4byte(unsigned char *p, u32 v){ #if SQLITE_BYTEORDER==4321 memcpy(p,&v,4); -#elif SQLITE_BYTEORDER==1234 && defined(__GNUC__) && GCC_VERSION>=4003000 +#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \ + && defined(__GNUC__) && GCC_VERSION>=4003000 u32 x = __builtin_bswap32(v); memcpy(p,&x,4); -#elif SQLITE_BYTEORDER==1234 && defined(_MSC_VER) && _MSC_VER>=1300 +#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \ + && defined(_MSC_VER) && _MSC_VER>=1300 u32 x = _byteswap_ulong(v); memcpy(p,&x,4); #else From 9a1e85ee2e5bc850dfa9c3e1f4135c98c966c37a Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 19 Feb 2016 13:29:52 +0000 Subject: [PATCH 321/570] Fix (harmless) compiler warnings in some of the TCL-based test code. FossilOrigin-Name: 7c26d2b47025edaa289bd4a383b5c1536482ec11 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/test1.c | 2 +- src/test_blob.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 6ac0529235..af30b2d665 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\san\sSQLITE_DISABLE_INTRINSIC\s#ifdef\sto\sthe\ssqlite3Put4Byte()\sfunction. -D 2016-02-19T13:20:02.042 +C Fix\s(harmless)\scompiler\swarnings\sin\ssome\sof\sthe\sTCL-based\stest\scode. +D 2016-02-19T13:29:52.247 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -359,7 +359,7 @@ F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 F src/tclsqlite.c 13debcc6a5ca1217486f8903768c01114fbe8b58 -F src/test1.c 4f1b42699068b7806af3111786f5ad760c2c1ff7 +F src/test1.c 8b17b1ff53aad71e7f9318a2fda247beddeaa601 F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e @@ -371,7 +371,7 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60 F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8 F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 -F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07 +F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f F src/test_config.c 7985332c806d1cece793475c75a6abcccde9d331 F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 @@ -1428,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 60ad68a9f569d2446d76a6453be4fa1c4ed2cd93 -R d12bbc92c78d2cfaf446c5b734b63a28 +P ba9c6827d0890aaed9168c221fefbdbe89f4f9d3 +R b3eefefd48eaf4c05a027f12e3577322 U drh -Z 22d2505e89be374674fd2948e46d1040 +Z ddb549605aed0cf283117ce1e762d390 diff --git a/manifest.uuid b/manifest.uuid index 6d8b3f854a..a7ec0c0aec 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ba9c6827d0890aaed9168c221fefbdbe89f4f9d3 \ No newline at end of file +7c26d2b47025edaa289bd4a383b5c1536482ec11 \ No newline at end of file diff --git a/src/test1.c b/src/test1.c index c5e71582bc..713152b824 100644 --- a/src/test1.c +++ b/src/test1.c @@ -3154,7 +3154,7 @@ static int test_bind_zeroblob64( ){ sqlite3_stmt *pStmt; int idx; - i64 n; + Tcl_WideInt n; int rc; if( objc!=4 ){ diff --git a/src/test_blob.c b/src/test_blob.c index 4a7075a28a..ec2227bb39 100644 --- a/src/test_blob.c +++ b/src/test_blob.c @@ -105,7 +105,7 @@ static int test_blob_open( const char *zDb; const char *zTable; const char *zColumn; - sqlite_int64 iRowid; + Tcl_WideInt iRowid; int flags; const char *zVarname; int nVarname; From 81fd3497f4a9b9842ea7fc4a8a8beda988e8ade9 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 19 Feb 2016 14:10:44 +0000 Subject: [PATCH 322/570] Make sure WhereClause objects are fully initialized before use when planning OR queries. FossilOrigin-Name: 162053021795ff40c447498a76de4d31d58aa808 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/whereexpr.c | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index af30b2d665..74555d9a75 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\s(harmless)\scompiler\swarnings\sin\ssome\sof\sthe\sTCL-based\stest\scode. -D 2016-02-19T13:29:52.247 +C Make\ssure\sWhereClause\sobjects\sare\sfully\sinitialized\sbefore\suse\swhen\nplanning\sOR\squeries. +D 2016-02-19T14:10:44.243 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -431,7 +431,7 @@ F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c 5b67fb8035ae4697cf721db095f800ef8dff5f56 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a F src/wherecode.c 791a784bbf8749d560fdb0b990b607bc4f44a38d -F src/whereexpr.c de117970b29471177a6901d60ad83a194671dc03 +F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1428,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ba9c6827d0890aaed9168c221fefbdbe89f4f9d3 -R b3eefefd48eaf4c05a027f12e3577322 +P 7c26d2b47025edaa289bd4a383b5c1536482ec11 +R 85b43af389af1eb3a02fa6f3878342fe U drh -Z ddb549605aed0cf283117ce1e762d390 +Z 20f7de88f5ee5fb441b8422adb035c25 diff --git a/manifest.uuid b/manifest.uuid index a7ec0c0aec..c4c0293ebc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7c26d2b47025edaa289bd4a383b5c1536482ec11 \ No newline at end of file +162053021795ff40c447498a76de4d31d58aa808 \ No newline at end of file diff --git a/src/whereexpr.c b/src/whereexpr.c index c84d2f230a..0ad1f6a0dc 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -533,6 +533,7 @@ static void exprAnalyzeOrTerm( if( pOrInfo==0 ) return; pTerm->wtFlags |= TERM_ORINFO; pOrWc = &pOrInfo->wc; + memset(pOrWc->aStatic, 0, sizeof(pOrWc->aStatic)); sqlite3WhereClauseInit(pOrWc, pWInfo); sqlite3WhereSplit(pOrWc, pExpr, TK_OR); sqlite3WhereExprAnalyze(pSrc, pOrWc); @@ -559,6 +560,7 @@ static void exprAnalyzeOrTerm( pOrTerm->wtFlags |= TERM_ANDINFO; pOrTerm->eOperator = WO_AND; pAndWC = &pAndInfo->wc; + memset(pAndWC->aStatic, 0, sizeof(pAndWC->aStatic)); sqlite3WhereClauseInit(pAndWC, pWC->pWInfo); sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND); sqlite3WhereExprAnalyze(pSrc, pAndWC); From b1f4efd20b57afbbc163ed8b899ef4e6bec9000a Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 19 Feb 2016 14:20:46 +0000 Subject: [PATCH 323/570] Fix a harmless uninitialized variable access. FossilOrigin-Name: 398522e686b34e7f82a62e62d8b0a0ea924de064 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbesort.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 74555d9a75..2def35da0f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sWhereClause\sobjects\sare\sfully\sinitialized\sbefore\suse\swhen\nplanning\sOR\squeries. -D 2016-02-19T14:10:44.243 +C Fix\sa\sharmless\suninitialized\svariable\saccess. +D 2016-02-19T14:20:46.061 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -421,7 +421,7 @@ F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 F src/vdbeaux.c 3580de0325a05663195d8f8fddf48c6dd9a28522 F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c be8381ed6de54eb9cb9dfa802823cdeb5166d855 -F src/vdbesort.c 74c22db608649fd7ed2d19d53eefb6efb14e9ee0 +F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062 F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 F src/vtab.c c27c0232bbc6bd4b50320ea0ef988334cde7d1ca F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 @@ -1428,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7c26d2b47025edaa289bd4a383b5c1536482ec11 -R 85b43af389af1eb3a02fa6f3878342fe +P 162053021795ff40c447498a76de4d31d58aa808 +R fe0bdee7c9c938489c9da7a703a0aaf9 U drh -Z 20f7de88f5ee5fb441b8422adb035c25 +Z f2650a4b63096d696bdaa068be72bdaf diff --git a/manifest.uuid b/manifest.uuid index c4c0293ebc..289197a1c3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -162053021795ff40c447498a76de4d31d58aa808 \ No newline at end of file +398522e686b34e7f82a62e62d8b0a0ea924de064 \ No newline at end of file diff --git a/src/vdbesort.c b/src/vdbesort.c index 9a5d7b34e3..5913cda6d0 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -2297,7 +2297,7 @@ static int vdbeMergeEngineLevel0( if( pNew==0 ) rc = SQLITE_NOMEM_BKPT; for(i=0; iaReadr[i]; rc = vdbePmaReaderInit(pTask, &pTask->file, iOff, pReadr, &nDummy); iOff = pReadr->iEof; From e1ee002891c4079d5db09d2e3d80e1ed1b151c24 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 19 Feb 2016 15:17:53 +0000 Subject: [PATCH 324/570] Fix a couple of harmless warnings generated by clang. FossilOrigin-Name: a1a3ff1f53145c5a9fbf29398cf4a453729e71f0 --- ext/fts3/fts3_test.c | 3 ++- ext/rbu/sqlite3rbu.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/ext/fts3/fts3_test.c b/ext/fts3/fts3_test.c index 36dcc94e6d..dec977b916 100644 --- a/ext/fts3/fts3_test.c +++ b/ext/fts3/fts3_test.c @@ -526,7 +526,8 @@ static int fts3_test_varint_cmd( #ifdef SQLITE_ENABLE_FTS3 char aBuf[24]; int rc; - Tcl_WideInt w, w2; + Tcl_WideInt w; + sqlite3_int64 w2; int nByte, nByte2; if( objc!=2 ){ diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index 145b446d30..682becbb5c 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -3704,7 +3704,7 @@ static int rbuVfsShmUnmap(sqlite3_file *pFile, int delFlag){ static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){ rbu_file *pDb; sqlite3_mutex_enter(pRbuVfs->mutex); - for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext); + for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){} sqlite3_mutex_leave(pRbuVfs->mutex); return pDb; } diff --git a/manifest b/manifest index 2def35da0f..3ca28caafa 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sharmless\suninitialized\svariable\saccess. -D 2016-02-19T14:20:46.061 +C Fix\sa\scouple\sof\sharmless\swarnings\sgenerated\sby\sclang. +D 2016-02-19T15:17:53.973 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -81,7 +81,7 @@ F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652 F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009 F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7 -F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038 +F ext/fts3/fts3_test.c 11e36437b0f3f2266acea5b4787f615e4337a237 F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860 F ext/fts3/fts3_tokenizer.c 4bd72f767f61c9ce5a7575c844e8d1ed2c3c561a F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 @@ -241,7 +241,7 @@ F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 -F ext/rbu/sqlite3rbu.c bea954197524631f2691ec272e8a42df8cad01cc +F ext/rbu/sqlite3rbu.c 371e8bf06cfb3f691adac47eb15ab1073ed92dcf F ext/rbu/sqlite3rbu.h 0bdeb3be211aaba7d85445fa36f4701a25a3dbde F ext/rbu/test_rbu.c 4a4cdcef4ef9379fc2a21f008805c80b27bcf573 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 @@ -1428,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 162053021795ff40c447498a76de4d31d58aa808 -R fe0bdee7c9c938489c9da7a703a0aaf9 +P 398522e686b34e7f82a62e62d8b0a0ea924de064 +R 8ff116d314d0fbd7bb871b177657846d U drh -Z f2650a4b63096d696bdaa068be72bdaf +Z 530c09cba645391ee26979799d0e5fce diff --git a/manifest.uuid b/manifest.uuid index 289197a1c3..71ee185715 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -398522e686b34e7f82a62e62d8b0a0ea924de064 \ No newline at end of file +a1a3ff1f53145c5a9fbf29398cf4a453729e71f0 \ No newline at end of file From b719e3a747f94b1be16f7daa36d99f8f7ac49a9c Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 19 Feb 2016 16:19:23 +0000 Subject: [PATCH 325/570] Enhance speedtest1 to display the particular version of SQLite under test. FossilOrigin-Name: 0cb728c15c66f1bf09cc1e0731a95ba937c6c71c --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/speedtest1.c | 3 +++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 3ca28caafa..a30569c322 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scouple\sof\sharmless\swarnings\sgenerated\sby\sclang. -D 2016-02-19T15:17:53.973 +C Enhance\sspeedtest1\sto\sdisplay\sthe\sparticular\sversion\sof\sSQLite\sunder\stest. +D 2016-02-19T16:19:23.113 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -1051,7 +1051,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523 F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b -F test/speedtest1.c f8bf04214e7b5f745feea99f7bde68b1c4870666 +F test/speedtest1.c 947421c324f5cd4cb3dcae1ec214e4be763df718 F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3 F test/spellfix3.test f7bf7b3482971473d32b6b00f6944c5c066cff97 @@ -1428,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 398522e686b34e7f82a62e62d8b0a0ea924de064 -R 8ff116d314d0fbd7bb871b177657846d +P a1a3ff1f53145c5a9fbf29398cf4a453729e71f0 +R 40dc747e2685bc8d2296fe54198bd303 U drh -Z 530c09cba645391ee26979799d0e5fce +Z d4723b5bdb5c40e13ea374fd3e41533b diff --git a/manifest.uuid b/manifest.uuid index 71ee185715..ec1fc9cf98 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a1a3ff1f53145c5a9fbf29398cf4a453729e71f0 \ No newline at end of file +0cb728c15c66f1bf09cc1e0731a95ba937c6c71c \ No newline at end of file diff --git a/test/speedtest1.c b/test/speedtest1.c index b41c732053..afb446bbf1 100644 --- a/test/speedtest1.c +++ b/test/speedtest1.c @@ -1196,6 +1196,9 @@ int main(int argc, char **argv){ int i; /* Loop counter */ int rc; /* API return code */ + /* Display the version of SQLite being tested */ + printf("Speedtest1 for SQLite %s %.50s\n", sqlite3_libversion(), sqlite3_sourceid()); + /* Process command-line arguments */ g.zWR = ""; g.zNN = ""; From 3200132add116844c8855bb479c698f7a3a98d34 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 19 Feb 2016 18:54:29 +0000 Subject: [PATCH 326/570] Use a separate list of aux-data structures for each trigger program at the VDBE level. Fix for [dc9b1c91]. FossilOrigin-Name: c4295725015d394f01b8563f47236e0890f1cc0d --- manifest | 19 +++++---- manifest.uuid | 2 +- src/vdbe.c | 3 ++ src/vdbeInt.h | 1 + src/vdbeaux.c | 19 +++++++++ test/regexp2.test | 105 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 139 insertions(+), 10 deletions(-) create mode 100644 test/regexp2.test diff --git a/manifest b/manifest index a30569c322..5a859cea9b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sspeedtest1\sto\sdisplay\sthe\sparticular\sversion\sof\sSQLite\sunder\stest. -D 2016-02-19T16:19:23.113 +C Use\sa\sseparate\slist\sof\saux-data\sstructures\sfor\seach\strigger\sprogram\sat\sthe\sVDBE\slevel.\sFix\sfor\s[dc9b1c91]. +D 2016-02-19T18:54:29.447 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -414,11 +414,11 @@ F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 38c06684c922694809ccb988a13562c16890a3d5 F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 -F src/vdbe.c 4eef77da4b81763a25992cc060506c001ebd4e3d +F src/vdbe.c 822e44c1dd859794f8c414e8bae4d96ac1fa774d F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 -F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79 +F src/vdbeInt.h 581e5bff9a401fabdb917b816503cda7356ec3e1 F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 -F src/vdbeaux.c 3580de0325a05663195d8f8fddf48c6dd9a28522 +F src/vdbeaux.c ec9a4d939a7430b76f53c5ef5cdbca3c8704848a F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c be8381ed6de54eb9cb9dfa802823cdeb5166d855 F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062 @@ -964,6 +964,7 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736 F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 +F test/regexp2.test 09fa89db70f7b1a611b001fd6b6e06b7527ac049 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 F test/releasetest.tcl 975449bf742b8bb9025208292208af816a1fcb58 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb @@ -1428,7 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a1a3ff1f53145c5a9fbf29398cf4a453729e71f0 -R 40dc747e2685bc8d2296fe54198bd303 -U drh -Z d4723b5bdb5c40e13ea374fd3e41533b +P 0cb728c15c66f1bf09cc1e0731a95ba937c6c71c +R 963f22ad65dea502595f87e9f194c57e +U dan +Z c03b3b8a1a2345ca0aa630c7ab428901 diff --git a/manifest.uuid b/manifest.uuid index ec1fc9cf98..ca509f0ca7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0cb728c15c66f1bf09cc1e0731a95ba937c6c71c \ No newline at end of file +c4295725015d394f01b8563f47236e0890f1cc0d \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 0f8d75d302..0cb7f5b24b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5696,6 +5696,9 @@ case OP_Program: { /* jump */ pFrame->lastRowid = lastRowid; pFrame->nChange = p->nChange; pFrame->nDbChange = p->db->nChange; + assert( pFrame->pAuxData==0 ); + pFrame->pAuxData = p->pAuxData; + p->pAuxData = 0; p->nChange = 0; p->pFrame = pFrame; p->aMem = aMem = &VdbeFrameMem(pFrame)[-1]; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 839c2039be..a64f3067dc 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -161,6 +161,7 @@ struct VdbeFrame { VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ void *token; /* Copy of SubProgram.token */ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ + AuxData *pAuxData; /* Linked list of auxdata allocations */ int nCursor; /* Number of entries in apCsr */ int pc; /* Program Counter in parent (calling) frame */ int nOp; /* Size of aOp array */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index b7517edb0a..9aa05fc868 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1476,6 +1476,21 @@ static void releaseMemArray(Mem *p, int N){ } } +/* +** Delete the linked list of AuxData structures attached to frame *p. +*/ +static void deleteAuxdataInFrame(sqlite3 *db, VdbeFrame *p){ + AuxData *pAux = p->pAuxData; + while( pAux ){ + AuxData *pNext = pAux->pNext; + if( pAux->xDelete ){ + pAux->xDelete(pAux->pAux); + } + sqlite3DbFree(db, pAux); + pAux = pNext; + } +} + /* ** Delete a VdbeFrame object and its contents. VdbeFrame objects are ** allocated by the OP_Program opcode in sqlite3VdbeExec(). @@ -1488,6 +1503,7 @@ void sqlite3VdbeFrameDelete(VdbeFrame *p){ sqlite3VdbeFreeCursor(p->v, apCsr[i]); } releaseMemArray(aMem, p->nChildMem); + deleteAuxdataInFrame(p->v->db, p); sqlite3DbFree(p->v->db, p); } @@ -2016,6 +2032,9 @@ int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ v->db->lastRowid = pFrame->lastRowid; v->nChange = pFrame->nChange; v->db->nChange = pFrame->nDbChange; + sqlite3VdbeDeleteAuxData(v, -1, 0); + v->pAuxData = pFrame->pAuxData; + pFrame->pAuxData = 0; return pFrame->pc; } diff --git a/test/regexp2.test b/test/regexp2.test new file mode 100644 index 0000000000..07955e15ee --- /dev/null +++ b/test/regexp2.test @@ -0,0 +1,105 @@ +# 2016 February 19 +# +# 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 tests for the REGEXP operator in ext/misc/regexp.c. +# It focuses on the use of the sqlite3_set_auxdata()/get_auxdata() APIs. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix regexp2 + +load_static_extension db regexp + +#------------------------------------------------------------------------- +# Test that triggers do not become confused and use aux-data created by +# a different trigger for a different REGEXP invocation. +# +do_execsql_test 1.0 { + CREATE TABLE t1(a, b, c); + CREATE TABLE x1(x, y, z); + CREATE TABLE x2(x, y, z); + + CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN + INSERT INTO x1 VALUES( + new.a REGEXP 'abc', + new.b REGEXP 'abc', + new.c REGEXP 'abc' + ); + END; + + CREATE TRIGGER tr2 AFTER INSERT ON t1 BEGIN + INSERT INTO x2 VALUES( + new.a REGEXP 'def', + new.b REGEXP 'def', + new.c REGEXP 'def' + ); + END; + + INSERT INTO t1 VALUES('abc', 'def', 'abc'); + SELECT * FROM t1; +} {abc def abc} + +do_execsql_test 1.1 { SELECT * FROM x1 } {1 0 1} +do_execsql_test 1.2 { SELECT * FROM x2 } {0 1 0} + +#------------------------------------------------------------------------- +# Test that if an exception is thrown several triggers deep, all aux-data +# objects are cleaned up correctly. +# +proc sql_error {} { + error "SQL error!" +} +db func error sql_error +do_execsql_test 2.0 { + CREATE TABLE t2(a, b); + CREATE TABLE t3(c, d); + CREATE TABLE t4(e, f); + + CREATE TRIGGER t2_tr1 AFTER UPDATE ON t2 BEGIN + UPDATE t3 SET d = new.b WHERE c = old.a; + END; + + CREATE TRIGGER t3_tr1 AFTER UPDATE ON t3 BEGIN + UPDATE t4 SET f = new.d WHERE e = old.c AND new.d REGEXP 'a.*'; + END; + + CREATE TRIGGER t4_tr1 AFTER UPDATE ON t4 BEGIN + SELECT CASE WHEN new.f REGEXP '.*y.*' THEN error() ELSE 1 END; + END; + + INSERT INTO t2 VALUES(1, 'a_x_1'); + INSERT INTO t2 VALUES(2, 'a_y_1'); + + INSERT INTO t3 VALUES(1, 'b1'); + INSERT INTO t3 VALUES(2, 'b2'); + + INSERT INTO t4 VALUES(1, 'b1'); + INSERT INTO t4 VALUES(2, 'b2'); +} {} + +do_catchsql_test 2.1 { + UPDATE t2 SET a=a+1 WHERE b REGEXP 'a.*' AND b REGEXP '.*1'; +} {1 {SQL error!}} + +# Test that the triggers used in the test above work as expected. +# +do_execsql_test 2.2 { + UPDATE t2 SET b = 'a_abc_1'; +} {} +do_execsql_test 2.3 { + SELECT * FROM t2; + SELECT * FROM t3; + SELECT * FROM t4; +} {1 a_abc_1 2 a_abc_1 1 a_abc_1 2 a_abc_1 1 a_abc_1 2 a_abc_1} + +finish_test + From 56362a5ab7d1616552d7096876fe6001c1b692ab Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 19 Feb 2016 19:03:04 +0000 Subject: [PATCH 327/570] Enhance clean target in the MSVC makefiles. FossilOrigin-Name: 66a9ad4a6df513f4c35c3d337d4e2e80cd38d586 --- Makefile.msc | 4 ++-- autoconf/Makefile.msc | 3 ++- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 1782b7551a..d84df8345e 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -2032,7 +2032,8 @@ rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H clean: del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL - del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL + del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL + del /Q $(SQLITE3EXE) $(SQLITE3DLL) 2>NUL # <> del /Q $(SQLITE3C) $(SQLITE3H) opcodes.c opcodes.h 2>NUL del /Q lemon.* lempar.c parse.* 2>NUL @@ -2051,7 +2052,6 @@ clean: del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL del /Q mptester.exe wordcount.exe rbu.exe srcck1.exe 2>NUL - del /Q $(SQLITE3EXE) $(SQLITE3DLL) sqlite3.def 2>NUL del /Q sqlite3.c sqlite3-*.c 2>NUL del /Q sqlite3rc.h 2>NUL del /Q shell.c sqlite3ext.h 2>NUL diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index 8bb7ac2973..52f0d91e0c 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -922,4 +922,5 @@ $(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H) clean: del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL - del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL + del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL + del /Q $(SQLITE3EXE) $(SQLITE3DLL) 2>NUL diff --git a/manifest b/manifest index 27f4a99e1c..89b9fc9d7b 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Modify\sthe\sMSVC\sbatch\sbuild\stool\sto\ssupport\sthe\sMSVC\sautoconf\sMakefile. -D 2016-02-19T05:07:56.206 +C Enhance\sclean\starget\sin\sthe\sMSVC\smakefiles. +D 2016-02-19T19:03:04.706 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc d3a190d93235a9aa142e4ade7b473435a5d376f9 +F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -11,7 +11,7 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 29e2a6e8d0c5e32723a48b4faf6b168854dde5f4 -F autoconf/Makefile.msc fe04b5870a3e4b98c73e8a82e04e98f330da7ea7 +F autoconf/Makefile.msc d5ab32cf30d6ba8b5ce20835b4042f6cc2a4cb39 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 7c31da66232f7590bb987cfcd4e2381744b25d24 F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 90dd6eb1fec22460473d670519d0e730bb37067d -R c6d10791b59e57f5d1181c2f31399663 +P 72b10e5e7d2db436c7b03cc3735a2e9d0e53ab5d +R b7460cecc6b485f24aba529c416ef3bb U mistachkin -Z 5c3b7d3d4a467152f425917bb5dd9dae +Z 44264aeb20df837b180d552e8068cd8f diff --git a/manifest.uuid b/manifest.uuid index 92cc237f4b..5eebc0a2af 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -72b10e5e7d2db436c7b03cc3735a2e9d0e53ab5d \ No newline at end of file +66a9ad4a6df513f4c35c3d337d4e2e80cd38d586 \ No newline at end of file From c03c2cf8b3d5ba7df17f7a7d26cf700c8511c89a Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 19 Feb 2016 19:29:44 +0000 Subject: [PATCH 328/570] Use the arguments to NMAKE consistently in the MSVC batch build tool. FossilOrigin-Name: 480e5049486b8b047f533d78b040daa47dd6b946 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/build-all-msvc.bat | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 89b9fc9d7b..e8f5966687 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sclean\starget\sin\sthe\sMSVC\smakefiles. -D 2016-02-19T19:03:04.706 +C Use\sthe\sarguments\sto\sNMAKE\sconsistently\sin\sthe\sMSVC\sbatch\sbuild\stool. +D 2016-02-19T19:29:44.729 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -1367,7 +1367,7 @@ F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372 F tool/addopcodes.tcl 4ca9c3ef196f08da30add5d07ce0c9458dc8c633 -F tool/build-all-msvc.bat fba6e16e6bad4600b6ab278ca90b1fcf74de63de x +F tool/build-all-msvc.bat 55be1cf8545dabd69df2ba6b3de6868da0c26f52 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 72b10e5e7d2db436c7b03cc3735a2e9d0e53ab5d -R b7460cecc6b485f24aba529c416ef3bb +P 66a9ad4a6df513f4c35c3d337d4e2e80cd38d586 +R abade97baee8abed51650334fbde09aa U mistachkin -Z 44264aeb20df837b180d552e8068cd8f +Z 7b92d09a61d34a4957d04f9633ed77f9 diff --git a/manifest.uuid b/manifest.uuid index 5eebc0a2af..613e1048a0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -66a9ad4a6df513f4c35c3d337d4e2e80cd38d586 \ No newline at end of file +480e5049486b8b047f533d78b040daa47dd6b946 \ No newline at end of file diff --git a/tool/build-all-msvc.bat b/tool/build-all-msvc.bat index c09ab1cd1c..c96708cef5 100755 --- a/tool/build-all-msvc.bat +++ b/tool/build-all-msvc.bat @@ -758,7 +758,7 @@ REM GOTO no_errors :fn_MakeClean - %__ECHO% %NMAKE_CMD% clean "PLATFORM=%1" %NMAKE_ARGS% %NMAKE_ARGS_CFG% + %__ECHO% %NMAKE_CMD% clean "PLATFORM=%1" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% %NMAKE_ARGS_CFG% GOTO :EOF :fn_MakeDll From 748e5cd6f97dd720a7429c1c88c840163061b1fb Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 22 Feb 2016 09:45:27 +0000 Subject: [PATCH 329/570] Add an extra test case for the change in commit [c4295725]. FossilOrigin-Name: a48ac4c347813bd2b416b1cb06c3cbf1f4b3781a --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/regexp2.test | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 956c6789b7..2e26cd9363 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\senhancements\sto\sthe\sMSVC\sbatch\sbuild\stool. -D 2016-02-19T19:46:58.037 +C Add\san\sextra\stest\scase\sfor\sthe\schange\sin\scommit\s[c4295725]. +D 2016-02-22T09:45:27.195 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -964,7 +964,7 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736 F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 -F test/regexp2.test 09fa89db70f7b1a611b001fd6b6e06b7527ac049 +F test/regexp2.test aa7ffcc21350007a78361b82bcf3b74d12227144 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 F test/releasetest.tcl 975449bf742b8bb9025208292208af816a1fcb58 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb @@ -1429,7 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c4295725015d394f01b8563f47236e0890f1cc0d 480e5049486b8b047f533d78b040daa47dd6b946 -R 02fc87382f176f4e92d2c83bf9af6520 -U mistachkin -Z f03186686f4366e8689fd530c95e9fd4 +P 06f1495f4b7465e3992f524f56d97847643a9895 +R b86f8e59b295e1048335bf96093b2d01 +U dan +Z f9a2cc9c8dbe56018446b3f984094705 diff --git a/manifest.uuid b/manifest.uuid index dee08de19b..6f698efa34 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -06f1495f4b7465e3992f524f56d97847643a9895 \ No newline at end of file +a48ac4c347813bd2b416b1cb06c3cbf1f4b3781a \ No newline at end of file diff --git a/test/regexp2.test b/test/regexp2.test index 07955e15ee..9928e8ce8e 100644 --- a/test/regexp2.test +++ b/test/regexp2.test @@ -101,5 +101,25 @@ do_execsql_test 2.3 { SELECT * FROM t4; } {1 a_abc_1 2 a_abc_1 1 a_abc_1 2 a_abc_1 1 a_abc_1 2 a_abc_1} +#------------------------------------------------------------------------- +# Test that trigger parameters (i.e. new.* and old.*) refs are not +# considered to be constant across separate invocations of the trigger. +# +do_execsql_test 3.0 { + CREATE TABLE t5(a); + CREATE TABLE t6(x); + + CREATE TRIGGER t5tr AFTER DELETE ON t5 BEGIN + DELETE FROM t6 WHERE t6.x REGEXP old.a; + END; + + INSERT INTO t5 VALUES ('^a.*'), ('^b.*'), ('^c.*'); + INSERT INTO t6 VALUES ('eab'), ('abc'), ('bcd'), ('cde'), ('dea'); + + DELETE FROM t5; + SELECT * FROM t6; +} {eab dea} + + finish_test From e872d5133d8f6c7b4bcebaac697740f3af0080ae Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 22 Feb 2016 13:23:16 +0000 Subject: [PATCH 330/570] Change magic numbers associated with synchronous settings to named constants. FossilOrigin-Name: 9230ba6c01f4a550d92a0cbbf36dbe81af14fbfc --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/main.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 2e26cd9363..737d2b6c22 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\san\sextra\stest\scase\sfor\sthe\schange\sin\scommit\s[c4295725]. -D 2016-02-22T09:45:27.195 +C Change\smagic\snumbers\sassociated\swith\ssynchronous\ssettings\sto\snamed\sconstants. +D 2016-02-22T13:23:16.525 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -314,7 +314,7 @@ F src/insert.c 9ca97272e9f74ed0efddf3b4350ee12740cebbef F src/journal.c fe3a3e2559ce3ce9d371afd30fbabbc074174575 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f -F src/main.c 8d2fd210bfbf2f28becb9452641c5689760a68d4 +F src/main.c d7415cd68121ef24c2e76b9e81ec96ffc90e6517 F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -1429,7 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 06f1495f4b7465e3992f524f56d97847643a9895 -R b86f8e59b295e1048335bf96093b2d01 -U dan -Z f9a2cc9c8dbe56018446b3f984094705 +P a48ac4c347813bd2b416b1cb06c3cbf1f4b3781a +R 5ba950defec5ebb5c806c723cbc4f5b9 +U drh +Z 3422238b7807aea6814e5b393b012e9d diff --git a/manifest.uuid b/manifest.uuid index 6f698efa34..b896d3d101 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a48ac4c347813bd2b416b1cb06c3cbf1f4b3781a \ No newline at end of file +9230ba6c01f4a550d92a0cbbf36dbe81af14fbfc \ No newline at end of file diff --git a/src/main.c b/src/main.c index b8d095b4be..4ffc426b08 100644 --- a/src/main.c +++ b/src/main.c @@ -2865,13 +2865,13 @@ static int openDatabase( sqlite3BtreeLeave(db->aDb[0].pBt); db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); - /* The default safety_level for the main database is 'full'; for the temp - ** database it is 'NONE'. This matches the pager layer defaults. + /* The default safety_level for the main database is FULL; for the temp + ** database it is OFF. This matches the pager layer defaults. */ db->aDb[0].zName = "main"; - db->aDb[0].safety_level = 3; + db->aDb[0].safety_level = PAGER_SYNCHRONOUS_FULL; db->aDb[1].zName = "temp"; - db->aDb[1].safety_level = 1; + db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF; db->magic = SQLITE_MAGIC_OPEN; if( db->mallocFailed ){ From 8e6cf0a7c50ad9e1e8eb09b56d12e22f1a6b380c Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 22 Feb 2016 14:57:38 +0000 Subject: [PATCH 331/570] Avoid creating a master journal unless two or more databases in the transaction can actually benefit from that master journal. FossilOrigin-Name: 3ed1890612bd45bd9c72f670d2cbb0b8fbd35d92 --- manifest | 14 ++++---- manifest.uuid | 2 +- src/vdbeaux.c | 26 ++++++++++++-- test/pager1.test | 92 ++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 105 insertions(+), 29 deletions(-) diff --git a/manifest b/manifest index 737d2b6c22..82a5265498 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\smagic\snumbers\sassociated\swith\ssynchronous\ssettings\sto\snamed\sconstants. -D 2016-02-22T13:23:16.525 +C Avoid\screating\sa\smaster\sjournal\sunless\stwo\sor\smore\sdatabases\sin\sthe\ntransaction\scan\sactually\sbenefit\sfrom\sthat\smaster\sjournal. +D 2016-02-22T14:57:38.065 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -418,7 +418,7 @@ F src/vdbe.c 822e44c1dd859794f8c414e8bae4d96ac1fa774d F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 F src/vdbeInt.h 581e5bff9a401fabdb917b816503cda7356ec3e1 F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 -F src/vdbeaux.c ec9a4d939a7430b76f53c5ef5cdbca3c8704848a +F src/vdbeaux.c 51aaf15e5c29512423429cc0e0477e08f7181514 F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c be8381ed6de54eb9cb9dfa802823cdeb5166d855 F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062 @@ -932,7 +932,7 @@ F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3 F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f -F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa +F test/pager1.test f49df1a8b0e38b9ee3a7dd2ab4d427507b7314ce F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71 F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e @@ -1429,7 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a48ac4c347813bd2b416b1cb06c3cbf1f4b3781a -R 5ba950defec5ebb5c806c723cbc4f5b9 +P 9230ba6c01f4a550d92a0cbbf36dbe81af14fbfc +R 28c7602ad1de5114aacb14204e4f7226 U drh -Z 3422238b7807aea6814e5b393b012e9d +Z aad5fe626dac38bb4fd331764966d6a1 diff --git a/manifest.uuid b/manifest.uuid index b896d3d101..4ab1f4a5a5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9230ba6c01f4a550d92a0cbbf36dbe81af14fbfc \ No newline at end of file +3ed1890612bd45bd9c72f670d2cbb0b8fbd35d92 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 9aa05fc868..4f539f0a29 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2155,7 +2155,9 @@ int sqlite3VdbeSetColName( */ static int vdbeCommit(sqlite3 *db, Vdbe *p){ int i; - int nTrans = 0; /* Number of databases with an active write-transaction */ + int nTrans = 0; /* Number of databases with an active write-transaction + ** that are candidates for a two-phase commit using a + ** master-journal */ int rc = SQLITE_OK; int needXcommit = 0; @@ -2183,10 +2185,28 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ for(i=0; rc==SQLITE_OK && inDb; i++){ Btree *pBt = db->aDb[i].pBt; if( sqlite3BtreeIsInTrans(pBt) ){ + /* Whether or not a database might need a master journal depends upon + ** its journal mode (among other things). This matrix determines which + ** journal modes use a master journal and which do not */ + static const u8 aMJNeeded[] = { + /* DELETE */ 1, + /* PERSIST */ 1, + /* OFF */ 0, + /* TRUNCATE */ 1, + /* MEMORY */ 0, + /* WAL */ 0 + }; + Pager *pPager; /* Pager associated with pBt */ needXcommit = 1; - if( i!=1 ) nTrans++; sqlite3BtreeEnter(pBt); - rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt)); + pPager = sqlite3BtreePager(pBt); + if( db->aDb[i].safety_level!=PAGER_SYNCHRONOUS_OFF + && aMJNeeded[sqlite3PagerGetJournalMode(pPager)] + ){ + assert( i!=1 ); + nTrans++; + } + rc = sqlite3PagerExclusiveLock(pPager); sqlite3BtreeLeave(pBt); } } diff --git a/test/pager1.test b/test/pager1.test index 005b356080..bc9ad83fd4 100644 --- a/test/pager1.test +++ b/test/pager1.test @@ -529,6 +529,7 @@ set pwd [get_pwd] testvfs tv -default 1 tv script copy_on_mj_delete set ::mj_filename_length 0 +set ::mj_delete_cnt 0 proc copy_on_mj_delete {method filename args} { if {[string match *mj* [file tail $filename]]} { # @@ -542,6 +543,7 @@ proc copy_on_mj_delete {method filename args} { set ::mj_filename_length [string length $filename] } faultsim_save + incr ::mj_delete_cnt } return SQLITE_OK } @@ -579,29 +581,68 @@ foreach {tn1 tcl} { } } { eval $tcl - foreach {tn2 sql} { + foreach {tn2 sql usesMJ} { o { PRAGMA main.synchronous=OFF; PRAGMA aux.synchronous=OFF; PRAGMA journal_mode = DELETE; - } + } 0 o512 { PRAGMA main.synchronous=OFF; PRAGMA aux.synchronous=OFF; PRAGMA main.page_size = 512; PRAGMA aux.page_size = 512; PRAGMA journal_mode = DELETE; - } + } 0 n { PRAGMA main.synchronous=NORMAL; PRAGMA aux.synchronous=NORMAL; PRAGMA journal_mode = DELETE; - } + } 1 f { PRAGMA main.synchronous=FULL; PRAGMA aux.synchronous=FULL; PRAGMA journal_mode = DELETE; - } + } 1 + w1 { + PRAGMA main.synchronous=NORMAL; + PRAGMA aux.synchronous=NORMAL; + PRAGMA journal_mode = WAL; + } 0 + w2 { + PRAGMA main.synchronous=NORMAL; + PRAGMA aux.synchronous=NORMAL; + PRAGMA main.journal_mode=DELETE; + PRAGMA aux.journal_mode=WAL; + } 0 + o1a { + PRAGMA main.synchronous=FULL; + PRAGMA aux.synchronous=OFF; + PRAGMA journal_mode=DELETE; + } 0 + o1b { + PRAGMA main.synchronous=OFF; + PRAGMA aux.synchronous=NORMAL; + PRAGMA journal_mode=DELETE; + } 0 + m1 { + PRAGMA main.synchronous=NORMAL; + PRAGMA aux.synchronous=NORMAL; + PRAGMA main.journal_mode=DELETE; + PRAGMA aux.journal_mode = MEMORY; + } 0 + t1 { + PRAGMA main.synchronous=NORMAL; + PRAGMA aux.synchronous=NORMAL; + PRAGMA main.journal_mode=DELETE; + PRAGMA aux.journal_mode = TRUNCATE; + } 1 + p1 { + PRAGMA main.synchronous=NORMAL; + PRAGMA aux.synchronous=NORMAL; + PRAGMA main.journal_mode=DELETE; + PRAGMA aux.journal_mode = PERSIST; + } 1 } { set tn "${tn1}.${tn2}" @@ -613,6 +654,7 @@ foreach {tn1 tcl} { # tv filter xDelete do_test pager1-4.4.$tn.1 { + set ::mj_delete_cnt 0 faultsim_delete_and_reopen $prefix execsql " ATTACH '${prefix}2' AS aux; @@ -634,6 +676,13 @@ foreach {tn1 tcl} { } } {} tv filter {} + + # Verify that a master journal was deleted only for those cases where + # master journals really ought to be used + # + do_test pager1-4.4.$tn.1b { + set ::mj_delete_cnt + } $usesMJ # Check that the transaction was committed successfully. # @@ -644,25 +693,33 @@ foreach {tn1 tcl} { SELECT * FROM b } {won too free double-you why zed} - # Restore the file-system and reopen the databases. Check that it now - # appears that the transaction was not committed (because the file-system - # was restored to the state where it had not been). - # - do_test pager1-4.4.$tn.4 { - faultsim_restore_and_reopen $prefix - execsql "ATTACH '${prefix}2' AS aux" - } {} - do_execsql_test pager1-4.4.$tn.5 {SELECT * FROM a} {double-you why zed} - do_execsql_test pager1-4.4.$tn.6 {SELECT * FROM b} {won too free} + if {$usesMJ} { + # Restore the file-system and reopen the databases. Check that it now + # appears that the transaction was not committed (because the file-system + # was restored to the state where it had not been). + # + do_test pager1-4.4.$tn.4 { + faultsim_restore_and_reopen $prefix + execsql "ATTACH '${prefix}2' AS aux" + } {} + do_execsql_test pager1-4.4.$tn.5 {SELECT * FROM a} {double-you why zed} + do_execsql_test pager1-4.4.$tn.6 {SELECT * FROM b} {won too free} + } # Restore the file-system again. This time, before reopening the databases, # delete the master-journal file from the file-system. It now appears that # the transaction was committed (no master-journal file == no rollback). # do_test pager1-4.4.$tn.7 { - faultsim_restore_and_reopen $prefix - foreach f [glob ${prefix}-mj*] { forcedelete $f } + if {$::mj_delete_cnt>0} { + faultsim_restore_and_reopen $prefix + foreach f [glob ${prefix}-mj*] { forcedelete $f } + } else { + db close + sqlite3 db $prefix + } execsql "ATTACH '${prefix}2' AS aux" + glob -nocomplain ${prefix}-mj* } {} do_execsql_test pager1-4.4.$tn.8 { SELECT * FROM a @@ -678,7 +735,6 @@ db close tv delete forcedelete $dirname - # Set up a VFS to make a copy of the file-system just before deleting a # journal file to commit a transaction. The transaction modifies exactly # two database pages (and page 1 - the change counter). From b9626cfa709ff5f71521035d21efd79b781bb760 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 22 Feb 2016 16:04:31 +0000 Subject: [PATCH 332/570] Always use the sqlite3VdbeDeleteAuxdata() routine for clearing auxdata on function parameter, rather than having a separate deleteAuxdataFromFrame() for doing the job for trigger frames. FossilOrigin-Name: 64386fa339adb91439da979d74062f67a6ec68fd --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/vdbe.c | 2 +- src/vdbeInt.h | 2 +- src/vdbeaux.c | 26 +++++--------------------- 5 files changed, 16 insertions(+), 32 deletions(-) diff --git a/manifest b/manifest index 82a5265498..ee22164613 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\screating\sa\smaster\sjournal\sunless\stwo\sor\smore\sdatabases\sin\sthe\ntransaction\scan\sactually\sbenefit\sfrom\sthat\smaster\sjournal. -D 2016-02-22T14:57:38.065 +C Always\suse\sthe\ssqlite3VdbeDeleteAuxdata()\sroutine\sfor\sclearing\sauxdata\son\nfunction\sparameter,\srather\sthan\shaving\sa\sseparate\sdeleteAuxdataFromFrame()\nfor\sdoing\sthe\sjob\sfor\strigger\sframes. +D 2016-02-22T16:04:31.519 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -414,11 +414,11 @@ F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 38c06684c922694809ccb988a13562c16890a3d5 F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 -F src/vdbe.c 822e44c1dd859794f8c414e8bae4d96ac1fa774d +F src/vdbe.c 87ae3a5657fefed7875f3eb30e7ababd48013d71 F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 -F src/vdbeInt.h 581e5bff9a401fabdb917b816503cda7356ec3e1 +F src/vdbeInt.h 84827a809229917fdd3cc05af719dbb61314a5a3 F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 -F src/vdbeaux.c 51aaf15e5c29512423429cc0e0477e08f7181514 +F src/vdbeaux.c 9583c5c05a75feb699591c9f24e4750def6537fb F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c be8381ed6de54eb9cb9dfa802823cdeb5166d855 F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062 @@ -1429,7 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9230ba6c01f4a550d92a0cbbf36dbe81af14fbfc -R 28c7602ad1de5114aacb14204e4f7226 +P 3ed1890612bd45bd9c72f670d2cbb0b8fbd35d92 +R 087e6cf717ab51d03c5c0e76eb47f593 U drh -Z aad5fe626dac38bb4fd331764966d6a1 +Z ce8b779f1a9ea7c56d4a99bdf5d3c13f diff --git a/manifest.uuid b/manifest.uuid index 4ab1f4a5a5..e6907d43a9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3ed1890612bd45bd9c72f670d2cbb0b8fbd35d92 \ No newline at end of file +64386fa339adb91439da979d74062f67a6ec68fd \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 0cb7f5b24b..3351a44551 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1679,7 +1679,7 @@ case OP_Function: { sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); rc = pCtx->isError; } - sqlite3VdbeDeleteAuxData(p, pCtx->iOp, pOp->p1); + sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1); if( rc ) goto abort_due_to_error; } diff --git a/src/vdbeInt.h b/src/vdbeInt.h index a64f3067dc..710c725e62 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -444,7 +444,7 @@ u8 sqlite3VdbeOneByteSerialTypeLen(u8); u32 sqlite3VdbeSerialType(Mem*, int, u32*); u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32); u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); -void sqlite3VdbeDeleteAuxData(Vdbe*, int, int); +void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 4f539f0a29..8065c290c1 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1476,21 +1476,6 @@ static void releaseMemArray(Mem *p, int N){ } } -/* -** Delete the linked list of AuxData structures attached to frame *p. -*/ -static void deleteAuxdataInFrame(sqlite3 *db, VdbeFrame *p){ - AuxData *pAux = p->pAuxData; - while( pAux ){ - AuxData *pNext = pAux->pNext; - if( pAux->xDelete ){ - pAux->xDelete(pAux->pAux); - } - sqlite3DbFree(db, pAux); - pAux = pNext; - } -} - /* ** Delete a VdbeFrame object and its contents. VdbeFrame objects are ** allocated by the OP_Program opcode in sqlite3VdbeExec(). @@ -1503,7 +1488,7 @@ void sqlite3VdbeFrameDelete(VdbeFrame *p){ sqlite3VdbeFreeCursor(p->v, apCsr[i]); } releaseMemArray(aMem, p->nChildMem); - deleteAuxdataInFrame(p->v->db, p); + sqlite3VdbeDeleteAuxData(p->v->db, &p->pAuxData, -1, 0); sqlite3DbFree(p->v->db, p); } @@ -2032,7 +2017,7 @@ int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ v->db->lastRowid = pFrame->lastRowid; v->nChange = pFrame->nChange; v->db->nChange = pFrame->nDbChange; - sqlite3VdbeDeleteAuxData(v, -1, 0); + sqlite3VdbeDeleteAuxData(v->db, &v->pAuxData, -1, 0); v->pAuxData = pFrame->pAuxData; pFrame->pAuxData = 0; return pFrame->pc; @@ -2066,7 +2051,7 @@ static void closeAllCursors(Vdbe *p){ } /* Delete any auxdata allocations made by the VM */ - if( p->pAuxData ) sqlite3VdbeDeleteAuxData(p, -1, 0); + if( p->pAuxData ) sqlite3VdbeDeleteAuxData(p->db, &p->pAuxData, -1, 0); assert( p->pAuxData==0 ); } @@ -2914,8 +2899,7 @@ int sqlite3VdbeFinalize(Vdbe *p){ ** * the corresponding bit in argument mask is clear (where the first ** function parameter corresponds to bit 0 etc.). */ -void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){ - AuxData **pp = &pVdbe->pAuxData; +void sqlite3VdbeDeleteAuxData(sqlite3 *db, AuxData **pp, int iOp, int mask){ while( *pp ){ AuxData *pAux = *pp; if( (iOp<0) @@ -2926,7 +2910,7 @@ void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){ pAux->xDelete(pAux->pAux); } *pp = pAux->pNext; - sqlite3DbFree(pVdbe->db, pAux); + sqlite3DbFree(db, pAux); }else{ pp= &pAux->pNext; } From a6d2f8eb1e2e1be45ac52106fd31eb8c5c81f7f5 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 22 Feb 2016 20:52:26 +0000 Subject: [PATCH 333/570] Avoid an unnecessary seek operation on some corner-case skip-scans. FossilOrigin-Name: 38e837e605076124b73235e1fd832838d9545cb2 --- manifest | 15 +++++++++------ manifest.uuid | 2 +- src/wherecode.c | 24 +++++++++++++----------- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index ee22164613..14f3934982 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Always\suse\sthe\ssqlite3VdbeDeleteAuxdata()\sroutine\sfor\sclearing\sauxdata\son\nfunction\sparameter,\srather\sthan\shaving\sa\sseparate\sdeleteAuxdataFromFrame()\nfor\sdoing\sthe\sjob\sfor\strigger\sframes. -D 2016-02-22T16:04:31.519 +C Avoid\san\sunnecessary\sseek\soperation\son\ssome\scorner-case\sskip-scans. +D 2016-02-22T20:52:26.579 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -430,7 +430,7 @@ F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c 5b67fb8035ae4697cf721db095f800ef8dff5f56 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a -F src/wherecode.c 791a784bbf8749d560fdb0b990b607bc4f44a38d +F src/wherecode.c 19aa0189a6088f8fde9105839b00be77f85d4469 F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1429,7 +1429,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 3ed1890612bd45bd9c72f670d2cbb0b8fbd35d92 -R 087e6cf717ab51d03c5c0e76eb47f593 +P 64386fa339adb91439da979d74062f67a6ec68fd +R a08f482677879c74e73ef75af70e8b9f +T *branch * skip-scan-improvement +T *sym-skip-scan-improvement * +T -sym-trunk * U drh -Z ce8b779f1a9ea7c56d4a99bdf5d3c13f +Z 08bae61bde61749b6ce2ce908b2beeb6 diff --git a/manifest.uuid b/manifest.uuid index e6907d43a9..e2a870a8f3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -64386fa339adb91439da979d74062f67a6ec68fd \ No newline at end of file +38e837e605076124b73235e1fd832838d9545cb2 \ No newline at end of file diff --git a/src/wherecode.c b/src/wherecode.c index bb48e5dc70..34e166bc48 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1212,17 +1212,19 @@ Bitmask sqlite3WhereCodeOneLoopStart( start_constraints = 1; } codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff); - op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; - assert( op!=0 ); - sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); - VdbeCoverage(v); - VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); - VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); - VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT ); - VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); - VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); - VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT ); - + if( pLoop->nSkip==0 || nConstraint>pLoop->nSkip ){ + op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; + assert( op!=0 ); + sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); + VdbeCoverage(v); + VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); + VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); + VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT ); + VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); + VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); + VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT ); + } + /* Load the value for the inequality constraint at the end of the ** range (if any). */ From 0bf2ad6a18c864efadb0ba79605788d9a29e2cb3 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 22 Feb 2016 21:19:54 +0000 Subject: [PATCH 334/570] Clearer presentation of the logic. No functional changes. FossilOrigin-Name: a3dcf6db76cc09bdfedb1bbeba3b359b77762cbe --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/wherecode.c | 8 ++++++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 14f3934982..5cf124d3e6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\san\sunnecessary\sseek\soperation\son\ssome\scorner-case\sskip-scans. -D 2016-02-22T20:52:26.579 +C Clearer\spresentation\sof\sthe\slogic.\s\sNo\sfunctional\schanges. +D 2016-02-22T21:19:54.531 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -430,7 +430,7 @@ F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c 5b67fb8035ae4697cf721db095f800ef8dff5f56 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a -F src/wherecode.c 19aa0189a6088f8fde9105839b00be77f85d4469 +F src/wherecode.c 39c1ef4598bedf1d66249334c74efd23ddd182ac F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1429,10 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 64386fa339adb91439da979d74062f67a6ec68fd -R a08f482677879c74e73ef75af70e8b9f -T *branch * skip-scan-improvement -T *sym-skip-scan-improvement * -T -sym-trunk * +P 38e837e605076124b73235e1fd832838d9545cb2 +R 56c5c81425d101f0314396c9251634e4 U drh -Z 08bae61bde61749b6ce2ce908b2beeb6 +Z dfca62313f421fb124d083409ac98469 diff --git a/manifest.uuid b/manifest.uuid index e2a870a8f3..e56034d01b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -38e837e605076124b73235e1fd832838d9545cb2 \ No newline at end of file +a3dcf6db76cc09bdfedb1bbeba3b359b77762cbe \ No newline at end of file diff --git a/src/wherecode.c b/src/wherecode.c index 34e166bc48..accc140866 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1212,7 +1212,11 @@ Bitmask sqlite3WhereCodeOneLoopStart( start_constraints = 1; } codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff); - if( pLoop->nSkip==0 || nConstraint>pLoop->nSkip ){ + if( pLoop->nSkip>0 && nConstraint==pLoop->nSkip ){ + /* The skip-scan logic inside the call to codeAllEqualityConstraints() + ** above has already left the cursor sitting on the correct row, + ** so no further seeking is needed */ + }else{ op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; assert( op!=0 ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); @@ -1224,7 +1228,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT ); } - + /* Load the value for the inequality constraint at the end of the ** range (if any). */ From b0529586572f3b3fcfd6bfcab6f177247e1cd9fa Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 22 Feb 2016 23:44:42 +0000 Subject: [PATCH 335/570] Remove code not needed now that synchronous=OFF database files no longer trigger the use of a master journal. FossilOrigin-Name: aa9f4c622af191edbeb6a535942944f8c91f5c37 --- manifest | 21 ++++++++++----------- manifest.uuid | 2 +- src/btree.c | 15 --------------- src/btree.h | 1 - src/pager.c | 8 -------- src/pager.h | 1 - src/vdbeaux.c | 9 ++------- 7 files changed, 13 insertions(+), 44 deletions(-) diff --git a/manifest b/manifest index 3903e0ee29..d23e81374a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\san\sunnecessary\sseek\soperation\ssome\scorner-case\sskip-scan\soperations. -D 2016-02-22T23:14:11.422 +C Remove\scode\snot\sneeded\snow\sthat\ssynchronous=OFF\sdatabase\sfiles\sno\slonger\ntrigger\sthe\suse\sof\sa\smaster\sjournal. +D 2016-02-22T23:44:42.710 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -292,8 +292,8 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 474ad91c1684e9053da64fa88747a1cb0c10d034 -F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e +F src/btree.c 7bb920c473c277380fcb3e8a8ee28ce1a48e0abc +F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 88f185a37d1e087818fd7077d84d65c5babefdb1 F src/callback.c 0643b8fb06c95a8977beb201b268210d4b131a22 @@ -336,8 +336,8 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 3a6f20736dfb8a0949cdd66553fdf59f6604be35 F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c 6812f3803951774b56abded396171e1c12b0b003 -F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865 +F src/pager.c d034c69b958c01289eb8070cbf902e1a68cd7e0b +F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 F src/parse.y c3ce2c4a7cbf0b699239be6b2a945c5cb51875e2 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 @@ -418,7 +418,7 @@ F src/vdbe.c 87ae3a5657fefed7875f3eb30e7ababd48013d71 F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 F src/vdbeInt.h 84827a809229917fdd3cc05af719dbb61314a5a3 F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 -F src/vdbeaux.c 9583c5c05a75feb699591c9f24e4750def6537fb +F src/vdbeaux.c 2c15cf88de4df97428318c8cfac0dea873dae451 F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c be8381ed6de54eb9cb9dfa802823cdeb5166d855 F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062 @@ -1429,8 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 64386fa339adb91439da979d74062f67a6ec68fd a3dcf6db76cc09bdfedb1bbeba3b359b77762cbe -R 56c5c81425d101f0314396c9251634e4 -T +closed a3dcf6db76cc09bdfedb1bbeba3b359b77762cbe +P 2a6003a937a210dfc279e393d3a0b49d1f3ac92e +R 3fce95d53a76531400313bc834bea507 U drh -Z 8dd31c368b55043259ced425c01733ad +Z c128e62f644c513c2811d577cffaf98d diff --git a/manifest.uuid b/manifest.uuid index 9ed2a9c829..0aad55cf0b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2a6003a937a210dfc279e393d3a0b49d1f3ac92e \ No newline at end of file +aa9f4c622af191edbeb6a535942944f8c91f5c37 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index cc1eedcb86..036e63a016 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2619,21 +2619,6 @@ int sqlite3BtreeSetPagerFlags( } #endif -/* -** Return TRUE if the given btree is set to safety level 1. In other -** words, return TRUE if no sync() occurs on the disk files. -*/ -int sqlite3BtreeSyncDisabled(Btree *p){ - BtShared *pBt = p->pBt; - int rc; - assert( sqlite3_mutex_held(p->db->mutex) ); - sqlite3BtreeEnter(p); - assert( pBt && pBt->pPager ); - rc = sqlite3PagerNosync(pBt->pPager); - sqlite3BtreeLeave(p); - return rc; -} - /* ** Change the default pages size and the number of reserved bytes per page. ** Or, if the page size has already been fixed, return SQLITE_READONLY diff --git a/src/btree.h b/src/btree.h index 30522e99e1..9ba233ac33 100644 --- a/src/btree.h +++ b/src/btree.h @@ -68,7 +68,6 @@ int sqlite3BtreeSetSpillSize(Btree*,int); int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64); #endif int sqlite3BtreeSetPagerFlags(Btree*,unsigned); -int sqlite3BtreeSyncDisabled(Btree*); int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); int sqlite3BtreeGetPageSize(Btree*); int sqlite3BtreeMaxPageCount(Btree*,int); diff --git a/src/pager.c b/src/pager.c index 67f1ae6b75..51bd45e486 100644 --- a/src/pager.c +++ b/src/pager.c @@ -6738,14 +6738,6 @@ const char *sqlite3PagerJournalname(Pager *pPager){ return pPager->zJournal; } -/* -** Return true if fsync() calls are disabled for this pager. Return FALSE -** if fsync()s are executed normally. -*/ -int sqlite3PagerNosync(Pager *pPager){ - return pPager->noSync; -} - #ifdef SQLITE_HAS_CODEC /* ** Set or retrieve the codec for this pager diff --git a/src/pager.h b/src/pager.h index 8d9f08108d..38a4982150 100644 --- a/src/pager.h +++ b/src/pager.h @@ -191,7 +191,6 @@ sqlite3_vfs *sqlite3PagerVfs(Pager*); sqlite3_file *sqlite3PagerFile(Pager*); sqlite3_file *sqlite3PagerJrnlFile(Pager*); const char *sqlite3PagerJournalname(Pager*); -int sqlite3PagerNosync(Pager*); void *sqlite3PagerTempSpace(Pager*); int sqlite3PagerIsMemdb(Pager*); void sqlite3PagerCacheStat(Pager *, int, int, int *); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 8065c290c1..9c75d1e078 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2249,7 +2249,6 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ #ifndef SQLITE_OMIT_DISKIO else{ sqlite3_vfs *pVfs = db->pVfs; - int needSync = 0; char *zMaster = 0; /* File-name for the master journal */ char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt); sqlite3_file *pMaster = 0; @@ -2309,9 +2308,6 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ continue; /* Ignore TEMP and :memory: databases */ } assert( zFile[0]!=0 ); - if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){ - needSync = 1; - } rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset); offset += sqlite3Strlen30(zFile)+1; if( rc!=SQLITE_OK ){ @@ -2326,8 +2322,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ /* Sync the master journal file. If the IOCAP_SEQUENTIAL device ** flag is set this is not required. */ - if( needSync - && 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL) + if( 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL) && SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL)) ){ sqlite3OsCloseFree(pMaster); @@ -2363,7 +2358,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ ** doing this the directory is synced again before any individual ** transaction files are deleted. */ - rc = sqlite3OsDelete(pVfs, zMaster, needSync); + rc = sqlite3OsDelete(pVfs, zMaster, 1); sqlite3DbFree(db, zMaster); zMaster = 0; if( rc ){ From 0e0089679fa2a5f191aedde660512d4b5c95d0d1 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 23 Feb 2016 16:28:34 +0000 Subject: [PATCH 336/570] Add the SQLITE_BITMASK_TYPE compile-time option. FossilOrigin-Name: 0064a8c77b2b048c71277d1cfd1ba3975b513b70 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqliteInt.h | 6 +++++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index d23e81374a..15a208ebd8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\scode\snot\sneeded\snow\sthat\ssynchronous=OFF\sdatabase\sfiles\sno\slonger\ntrigger\sthe\suse\sof\sa\smaster\sjournal. -D 2016-02-22T23:44:42.710 +C Add\sthe\sSQLITE_BITMASK_TYPE\scompile-time\soption. +D 2016-02-23T16:28:34.108 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -354,7 +354,7 @@ F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe F src/sqlite.h.in a7caa805a345d6a14136c11ccfa6f4c1a6ef6e7b F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 47f61c35d587d38cbcfc8ba852ff441054d697d3 +F src/sqliteInt.h 1a2f11f92cb3d76c011c04f87de3c0ebcc26230e F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1429,7 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2a6003a937a210dfc279e393d3a0b49d1f3ac92e -R 3fce95d53a76531400313bc834bea507 +P aa9f4c622af191edbeb6a535942944f8c91f5c37 +R 4a575c5637747e2b18640a9618428d3e U drh -Z c128e62f644c513c2811d577cffaf98d +Z c4c6cb390dd2f5f6f2bb80636719a5f7 diff --git a/manifest.uuid b/manifest.uuid index 0aad55cf0b..561abfe587 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -aa9f4c622af191edbeb6a535942944f8c91f5c37 \ No newline at end of file +0064a8c77b2b048c71277d1cfd1ba3975b513b70 \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 85d4158a46..4ebc210ffd 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2338,7 +2338,11 @@ struct IdList { ** tables in a join to 32 instead of 64. But it also reduces the size ** of the library by 738 bytes on ix86. */ -typedef u64 Bitmask; +#ifdef SQLITE_BITMASK_TYPE + typedef SQLITE_BITMASK_TYPE Bitmask; +#else + typedef u64 Bitmask; +#endif /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". From e1dd060898742986b66b9a7646607737abeb9bf3 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 24 Feb 2016 15:43:05 +0000 Subject: [PATCH 337/570] Identify indexes that complete cover their table. FossilOrigin-Name: 71d488b599cbde817de369efac4412569a55b43d --- manifest | 15 +++++++++------ manifest.uuid | 2 +- src/build.c | 11 +++++++++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 15a208ebd8..b5ca9ab6dd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_BITMASK_TYPE\scompile-time\soption. -D 2016-02-23T16:28:34.108 +C Identify\sindexes\sthat\scomplete\scover\stheir\stable. +D 2016-02-24T15:43:05.820 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -295,7 +295,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 7bb920c473c277380fcb3e8a8ee28ce1a48e0abc F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 88f185a37d1e087818fd7077d84d65c5babefdb1 +F src/build.c 2c85d62e502e3f41f37049733c25be77780660e2 F src/callback.c 0643b8fb06c95a8977beb201b268210d4b131a22 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -1429,7 +1429,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P aa9f4c622af191edbeb6a535942944f8c91f5c37 -R 4a575c5637747e2b18640a9618428d3e +P 0064a8c77b2b048c71277d1cfd1ba3975b513b70 +R 5e33894201e325c17491a9fc46b648e7 +T *branch * covering-index +T *sym-covering-index * +T -sym-trunk * U drh -Z c4c6cb390dd2f5f6f2bb80636719a5f7 +Z 47bfdcb1d11cf503d0a7a3e3179c205c diff --git a/manifest.uuid b/manifest.uuid index 561abfe587..4694af3ec7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0064a8c77b2b048c71277d1cfd1ba3975b513b70 \ No newline at end of file +71d488b599cbde817de369efac4412569a55b43d \ No newline at end of file diff --git a/src/build.c b/src/build.c index 13446b790e..18b52bd34b 100644 --- a/src/build.c +++ b/src/build.c @@ -3192,6 +3192,17 @@ Index *sqlite3CreateIndex( }else{ pIndex->aiColumn[i] = XN_ROWID; pIndex->azColl[i] = sqlite3StrBINARY; + /* If this index contains every column of its table, then mark + ** it as a covering index */ + if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){ + pIndex->isCovering = 1; + for(j=0; jnCol; j++){ + if( j==pTab->iPKey ) continue; + if( sqlite3ColumnOfIndex(pIndex,j)>=0 ) continue; + pIndex->isCovering = 0; + break; + } + } } sqlite3DefaultRowEst(pIndex); if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex); From a73086dd9eb4d7a41340920a773e0369ec7db204 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 24 Feb 2016 16:14:07 +0000 Subject: [PATCH 338/570] Fix a problem with handling identifiers that start with "x" if SQLITE_OMIT_BLOB_LITERAL is defined. FossilOrigin-Name: b65217c69c59cbe9cd1494e2eb42ecf22c336399 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/tokenize.c | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 15a208ebd8..15bbc7006f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_BITMASK_TYPE\scompile-time\soption. -D 2016-02-23T16:28:34.108 +C Fix\sa\sproblem\swith\shandling\sidentifiers\sthat\sstart\swith\s"x"\sif\sSQLITE_OMIT_BLOB_LITERAL\sis\sdefined. +D 2016-02-24T16:14:07.366 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -407,7 +407,7 @@ F src/test_windirent.c 8f5fada630348558d5745b334702f301da1ffc61 F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c -F src/tokenize.c c4c1d360fafa3dc458fcbb535691b134798dbb70 +F src/tokenize.c 3d338cdd00d916ce8a05c397001d64ed58e6fe1c F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca @@ -1429,7 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P aa9f4c622af191edbeb6a535942944f8c91f5c37 -R 4a575c5637747e2b18640a9618428d3e -U drh -Z c4c6cb390dd2f5f6f2bb80636719a5f7 +P 0064a8c77b2b048c71277d1cfd1ba3975b513b70 +R 87ae274ca20c267f6abd45bb9b52594d +U dan +Z 138a68927e813b46e7cc6cf9848edebe diff --git a/manifest.uuid b/manifest.uuid index 561abfe587..db93997260 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0064a8c77b2b048c71277d1cfd1ba3975b513b70 \ No newline at end of file +b65217c69c59cbe9cd1494e2eb42ecf22c336399 \ No newline at end of file diff --git a/src/tokenize.c b/src/tokenize.c index 60af259cab..19a5ddf04d 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -435,8 +435,8 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ *tokenType = TK_ID; return keywordCode((char*)z, i, tokenType); } -#ifndef SQLITE_OMIT_BLOB_LITERAL case CC_X: { +#ifndef SQLITE_OMIT_BLOB_LITERAL testcase( z[0]=='x' ); testcase( z[0]=='X' ); if( z[1]=='\'' ){ *tokenType = TK_BLOB; @@ -448,10 +448,10 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ if( z[i] ) i++; return i; } +#endif /* If it is not a BLOB literal, then it must be an ID, since no ** SQL keywords start with the letter 'x'. Fall through */ } -#endif case CC_ID: { i = 1; break; From 6ad224e91e6a27aab9d1d1a2503731911bc144c7 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 24 Feb 2016 19:57:11 +0000 Subject: [PATCH 339/570] Change a char* to const char* in order to suppress some harmless compiler warnings. FossilOrigin-Name: 56f62e34ae9d5c7db07367f0007df258b2e76bd2 --- manifest | 17 ++++++++--------- manifest.uuid | 2 +- src/callback.c | 4 ++-- src/sqliteInt.h | 2 +- src/vtab.c | 4 ++-- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 6c7ff3212d..6ad7ab7026 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\san\sindex\scomplete\scovers\sa\stable,\sit\scan\sbe\sused\sas\sa\scovering\sindex\neven\sif\scolumns\spast\sthe\s63rd\scolumn\sare\sindexed\sand\saccessed. -D 2016-02-24T17:18:51.683 +C Change\sa\schar*\sto\sconst\schar*\sin\sorder\sto\ssuppress\ssome\sharmless\ncompiler\swarnings. +D 2016-02-24T19:57:11.748 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -296,7 +296,7 @@ F src/btree.c 7bb920c473c277380fcb3e8a8ee28ce1a48e0abc F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 2c85d62e502e3f41f37049733c25be77780660e2 -F src/callback.c 0643b8fb06c95a8977beb201b268210d4b131a22 +F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 0b73e681c11fca867fec554750c07fe0d4e417c1 @@ -354,7 +354,7 @@ F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe F src/sqlite.h.in a7caa805a345d6a14136c11ccfa6f4c1a6ef6e7b F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 1a2f11f92cb3d76c011c04f87de3c0ebcc26230e +F src/sqliteInt.h 5200682fc1050f00fba07128c0facc37462c4411 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -423,7 +423,7 @@ F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c be8381ed6de54eb9cb9dfa802823cdeb5166d855 F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062 F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 -F src/vtab.c c27c0232bbc6bd4b50320ea0ef988334cde7d1ca +F src/vtab.c 943c23b355f0a8f859f9583e7315d64bebdb0899 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c @@ -1429,8 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b65217c69c59cbe9cd1494e2eb42ecf22c336399 71d488b599cbde817de369efac4412569a55b43d -R fec3823eb3639f1bd971a3e203837396 -T +closed 71d488b599cbde817de369efac4412569a55b43d +P 3e9ed1aea43e8ce2eb74bb845ea2c05b5882e36e +R a9fa28705051ff7267b4f6fc3a125cf7 U drh -Z 899ea8df55da6e6b0dfa91529a693a53 +Z a55a4b9187efcf601b6a807452ec9fcd diff --git a/manifest.uuid b/manifest.uuid index 61e417a52f..dc11f4b709 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3e9ed1aea43e8ce2eb74bb845ea2c05b5882e36e \ No newline at end of file +56f62e34ae9d5c7db07367f0007df258b2e76bd2 \ No newline at end of file diff --git a/src/callback.c b/src/callback.c index ba846b53f3..2351178867 100644 --- a/src/callback.c +++ b/src/callback.c @@ -405,10 +405,10 @@ FuncDef *sqlite3FindFunction( if( createFlag && bestScorezName = (char *)&pBest[1]; + pBest->zName = (const char*)&pBest[1]; pBest->nArg = (u16)nArg; pBest->funcFlags = enc; - memcpy(pBest->zName, zName, nName+1); + memcpy((char*)&pBest[1], zName, nName+1); pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest); if( pOther==pBest ){ sqlite3DbFree(db, pBest); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 4ebc210ffd..2ea5f57910 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1395,7 +1395,7 @@ struct FuncDef { FuncDef *pNext; /* Next function with same name */ void (*xSFunc)(sqlite3_context*,int,sqlite3_value**); /* func or agg-step */ void (*xFinalize)(sqlite3_context*); /* Agg finalizer */ - char *zName; /* SQL name of the function. */ + const char *zName; /* SQL name of the function. */ union { FuncDef *pHash; /* Next with a different name but the same hash */ FuncDestructor *pDestructor; /* Reference counted destructor function */ diff --git a/src/vtab.c b/src/vtab.c index cb443faae9..fa19548199 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -1059,8 +1059,8 @@ FuncDef *sqlite3VtabOverloadFunction( return pDef; } *pNew = *pDef; - pNew->zName = (char *)&pNew[1]; - memcpy(pNew->zName, pDef->zName, sqlite3Strlen30(pDef->zName)+1); + pNew->zName = (const char*)&pNew[1]; + memcpy((char*)&pNew[1], pDef->zName, sqlite3Strlen30(pDef->zName)+1); pNew->xSFunc = xSFunc; pNew->pUserData = pArg; pNew->funcFlags |= SQLITE_FUNC_EPHEM; From f769cd61b2af2d5bc2168b8f0aeeee3118694d2d Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 24 Feb 2016 20:16:28 +0000 Subject: [PATCH 340/570] Extend [3e9ed1ae] so that covering indexes on WITHOUT ROWID tables are also identified. FossilOrigin-Name: e721975faa0925be4029330550ff2a9666041ff7 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/build.c | 25 ++++++++++++++----------- test/coveridxscan.test | 31 +++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/manifest b/manifest index 6ad7ab7026..a6c34eb4bb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sa\schar*\sto\sconst\schar*\sin\sorder\sto\ssuppress\ssome\sharmless\ncompiler\swarnings. -D 2016-02-24T19:57:11.748 +C Extend\s[3e9ed1ae]\sso\sthat\scovering\sindexes\son\sWITHOUT\sROWID\stables\sare\salso\sidentified. +D 2016-02-24T20:16:28.164 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -295,7 +295,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 7bb920c473c277380fcb3e8a8ee28ce1a48e0abc F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 2c85d62e502e3f41f37049733c25be77780660e2 +F src/build.c 6661513c8f90a23d44ed5e5ada7ea40fac6b6b77 F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -564,7 +564,7 @@ F test/corruptI.test 347babbf970e7947e3f91dccf7a1bec28a1bab04 F test/corruptJ.test 9e29e7a81ee3b6ac50f77ea7a9e2f3fa03f32d91 F test/cost.test 1eedbfd868f806f3fa08ff072b04cf270dcf61c8 F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c -F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62 +F test/coveridxscan.test b629e896b14df2f000a99b8d170d80589c46562c F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651 F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418 @@ -1429,7 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 3e9ed1aea43e8ce2eb74bb845ea2c05b5882e36e -R a9fa28705051ff7267b4f6fc3a125cf7 -U drh -Z a55a4b9187efcf601b6a807452ec9fcd +P 56f62e34ae9d5c7db07367f0007df258b2e76bd2 +R baac3e94ca81a0031c96821cb1862aed +U dan +Z 255768a198e66c588af8c08668af4632 diff --git a/manifest.uuid b/manifest.uuid index dc11f4b709..56555f4bc2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -56f62e34ae9d5c7db07367f0007df258b2e76bd2 \ No newline at end of file +e721975faa0925be4029330550ff2a9666041ff7 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 18b52bd34b..b14d45f6da 100644 --- a/src/build.c +++ b/src/build.c @@ -3192,21 +3192,24 @@ Index *sqlite3CreateIndex( }else{ pIndex->aiColumn[i] = XN_ROWID; pIndex->azColl[i] = sqlite3StrBINARY; - /* If this index contains every column of its table, then mark - ** it as a covering index */ - if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){ - pIndex->isCovering = 1; - for(j=0; jnCol; j++){ - if( j==pTab->iPKey ) continue; - if( sqlite3ColumnOfIndex(pIndex,j)>=0 ) continue; - pIndex->isCovering = 0; - break; - } - } } sqlite3DefaultRowEst(pIndex); if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex); + /* If this index contains every column of its table, then mark + ** it as a covering index */ + assert( HasRowid(pTab) + || pTab->iPKey<0 || sqlite3ColumnOfIndex(pIndex, pTab->iPKey)>=0 ); + if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){ + pIndex->isCovering = 1; + for(j=0; jnCol; j++){ + if( j==pTab->iPKey ) continue; + if( sqlite3ColumnOfIndex(pIndex,j)>=0 ) continue; + pIndex->isCovering = 0; + break; + } + } + if( pTab==pParse->pNewTable ){ /* This routine has been called to create an automatic index as a ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or diff --git a/test/coveridxscan.test b/test/coveridxscan.test index 7b3c0b0be9..a8d1a8ff75 100644 --- a/test/coveridxscan.test +++ b/test/coveridxscan.test @@ -89,5 +89,36 @@ do_test 4.3 { db eval {SELECT b FROM t1} } {2 4 8} +#------------------------------------------------------------------------- +# Test that indexes with large numbers of columns can be correctly +# identified as covering indexes. +reset_db +set L [list] +for {set i 1} {$i<120} {incr i} { + lappend L "c$i" +} +set cols [join $L ,] + +do_execsql_test 5.1.0 " + CREATE TABLE t1(a, b, c, $cols, PRIMARY KEY(a, b, c)) WITHOUT ROWID; + CREATE INDEX i1 ON t1($cols); + + CREATE TABLE t2(i INTEGER PRIMARY KEY, $cols); + CREATE INDEX i2 ON t2($cols); +" + +do_eqp_test 5.1.1 { + SELECT * FROM t1 ORDER BY c1, c2; +} { + 0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1} +} + +do_eqp_test 5.1.2 { + SELECT * FROM t2 ORDER BY c1, c2; +} { + 0 0 0 {SCAN TABLE t2 USING COVERING INDEX i2} +} + + finish_test From 7aa3ebee0fb7df401fa0ecd6a20f3a7f0da50f05 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 24 Feb 2016 21:42:03 +0000 Subject: [PATCH 341/570] Initial work on an automated VSIX testing tool. Not working or tested yet. FossilOrigin-Name: 496e4ac984b2548dd5f2f969cd34656b586cfcfe --- manifest | 36 ++- manifest.uuid | 2 +- vsixtest/App.xaml | 8 + vsixtest/App.xaml.cpp | 120 ++++++++++ vsixtest/App.xaml.h | 27 +++ vsixtest/Assets/LockScreenLogo.scale-200.png | Bin 0 -> 1430 bytes vsixtest/Assets/SplashScreen.scale-200.png | Bin 0 -> 7700 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 0 -> 2937 bytes vsixtest/Assets/Square44x44Logo.scale-200.png | Bin 0 -> 1647 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 1255 bytes vsixtest/Assets/StoreLogo.png | Bin 0 -> 1451 bytes vsixtest/Assets/Wide310x150Logo.scale-200.png | Bin 0 -> 3204 bytes vsixtest/MainPage.xaml | 13 ++ vsixtest/MainPage.xaml.cpp | 27 +++ vsixtest/MainPage.xaml.h | 21 ++ vsixtest/Package.appxmanifest | 49 ++++ vsixtest/pch.cpp | 6 + vsixtest/pch.h | 11 + vsixtest/vsixtest.sln | 40 ++++ vsixtest/vsixtest.tcl | 215 ++++++++++++++++++ vsixtest/vsixtest.vcxproj | 213 +++++++++++++++++ vsixtest/vsixtest.vcxproj.filters | 24 ++ vsixtest/vsixtest_TemporaryKey.pfx | Bin 0 -> 2520 bytes 23 files changed, 805 insertions(+), 7 deletions(-) create mode 100644 vsixtest/App.xaml create mode 100644 vsixtest/App.xaml.cpp create mode 100644 vsixtest/App.xaml.h create mode 100644 vsixtest/Assets/LockScreenLogo.scale-200.png create mode 100644 vsixtest/Assets/SplashScreen.scale-200.png create mode 100644 vsixtest/Assets/Square150x150Logo.scale-200.png create mode 100644 vsixtest/Assets/Square44x44Logo.scale-200.png create mode 100644 vsixtest/Assets/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 vsixtest/Assets/StoreLogo.png create mode 100644 vsixtest/Assets/Wide310x150Logo.scale-200.png create mode 100644 vsixtest/MainPage.xaml create mode 100644 vsixtest/MainPage.xaml.cpp create mode 100644 vsixtest/MainPage.xaml.h create mode 100644 vsixtest/Package.appxmanifest create mode 100644 vsixtest/pch.cpp create mode 100644 vsixtest/pch.h create mode 100644 vsixtest/vsixtest.sln create mode 100644 vsixtest/vsixtest.tcl create mode 100644 vsixtest/vsixtest.vcxproj create mode 100644 vsixtest/vsixtest.vcxproj.filters create mode 100644 vsixtest/vsixtest_TemporaryKey.pfx diff --git a/manifest b/manifest index a6c34eb4bb..e9256df548 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Extend\s[3e9ed1ae]\sso\sthat\scovering\sindexes\son\sWITHOUT\sROWID\stables\sare\salso\sidentified. -D 2016-02-24T20:16:28.164 +C Initial\swork\son\san\sautomated\sVSIX\stesting\stool.\s\sNot\sworking\sor\stested\syet. +D 2016-02-24T21:42:03.852 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -1429,7 +1429,31 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 56f62e34ae9d5c7db07367f0007df258b2e76bd2 -R baac3e94ca81a0031c96821cb1862aed -U dan -Z 255768a198e66c588af8c08668af4632 +F vsixtest/App.xaml 7af5a2a527aa5783e208c436c5227a21b1023cec +F vsixtest/App.xaml.cpp c4aaab1774e771d2b6f662cbd247fd31df087a22 +F vsixtest/App.xaml.h f723ae437a141cd496adfccae517a6011dd95dfb +F vsixtest/Assets/LockScreenLogo.scale-200.png e820c9a3deb909197081b0bf3216c06e13905f0a +F vsixtest/Assets/SplashScreen.scale-200.png cab70988ca71bebec7bfeb3b6dbafe17b9ab0b4a +F vsixtest/Assets/Square150x150Logo.scale-200.png e17b40817db7a239fc239d83efcc951fb824e3ff +F vsixtest/Assets/Square44x44Logo.scale-200.png 2f166237094dea94d952d10b9eeae81806844f1c +F vsixtest/Assets/Square44x44Logo.targetsize-24_altform-unplated.png 5f6a6d391b95a3061ccca6e6fdd6955ede63b4ed +F vsixtest/Assets/StoreLogo.png 0828b7257db74a4ecd5eeb6b7b4971f0fdc4d9d1 +F vsixtest/Assets/Wide310x150Logo.scale-200.png 04ddefe5bc5f43ae12a7433f6f236ddab101ac42 +F vsixtest/MainPage.xaml b17ae614fc9aab5ee0068e16c9a3e3461d13b6d1 +F vsixtest/MainPage.xaml.cpp 66f81d6149d9a09de5c6c7846c6557cdd7a76b15 +F vsixtest/MainPage.xaml.h 5b8d65dc2b9e59e29bc0a6bca81211ff27ac830a +F vsixtest/Package.appxmanifest 0535b2e6708c44ad45ed7fb1dfd4de5de351dd7a +F vsixtest/pch.cpp 681cc12ddc215c95fe300ee8a3dde057fa2ec308 +F vsixtest/pch.h 9d2475a4f6d5c921b86c8f61060b6b04421f1010 +F vsixtest/vsixtest.sln 8950e044dd04a07046990d04bf77e60738e2d136 +F vsixtest/vsixtest.tcl d452077319cd94e626e37a8ea323f4e739dbc5a6 +F vsixtest/vsixtest.vcxproj 15407f0e35e914fecc65ed422ac08b28e52b3e4f +F vsixtest/vsixtest.vcxproj.filters 443739cb985bb81620dc66f375a845b25debe116 +F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 +P e721975faa0925be4029330550ff2a9666041ff7 +R 5235a7354869742aeac200c2498e03f2 +T *branch * vsixTest +T *sym-vsixTest * +T -sym-trunk * +U mistachkin +Z 30aae13ef1f9c0b59510b9ed5eae30fc diff --git a/manifest.uuid b/manifest.uuid index 56555f4bc2..8ebfae5b16 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e721975faa0925be4029330550ff2a9666041ff7 \ No newline at end of file +496e4ac984b2548dd5f2f969cd34656b586cfcfe \ No newline at end of file diff --git a/vsixtest/App.xaml b/vsixtest/App.xaml new file mode 100644 index 0000000000..7f023fe5d7 --- /dev/null +++ b/vsixtest/App.xaml @@ -0,0 +1,8 @@ + + + diff --git a/vsixtest/App.xaml.cpp b/vsixtest/App.xaml.cpp new file mode 100644 index 0000000000..5d60058f6b --- /dev/null +++ b/vsixtest/App.xaml.cpp @@ -0,0 +1,120 @@ +// +// App.xaml.cpp +// Implementation of the App class. +// + +#include "pch.h" +#include "MainPage.xaml.h" + +using namespace vsixtest; + +using namespace Platform; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Windows::UI::Xaml; +using namespace Windows::UI::Xaml::Controls; +using namespace Windows::UI::Xaml::Controls::Primitives; +using namespace Windows::UI::Xaml::Data; +using namespace Windows::UI::Xaml::Input; +using namespace Windows::UI::Xaml::Interop; +using namespace Windows::UI::Xaml::Media; +using namespace Windows::UI::Xaml::Navigation; + +/// +/// Initializes the singleton application object. This is the first line of authored code +/// executed, and as such is the logical equivalent of main() or WinMain(). +/// +App::App() +{ + InitializeComponent(); + Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending); +} + +/// +/// Invoked when the application is launched normally by the end user. Other entry points +/// will be used such as when the application is launched to open a specific file. +/// +/// Details about the launch request and process. +void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) +{ + +#if _DEBUG + // Show graphics profiling information while debugging. + if (IsDebuggerPresent()) + { + // Display the current frame rate counters + DebugSettings->EnableFrameRateCounter = true; + } +#endif + + auto rootFrame = dynamic_cast(Window::Current->Content); + + // Do not repeat app initialization when the Window already has content, + // just ensure that the window is active + if (rootFrame == nullptr) + { + // Create a Frame to act as the navigation context and associate it with + // a SuspensionManager key + rootFrame = ref new Frame(); + + rootFrame->NavigationFailed += ref new Windows::UI::Xaml::Navigation::NavigationFailedEventHandler(this, &App::OnNavigationFailed); + + if (e->PreviousExecutionState == ApplicationExecutionState::Terminated) + { + // TODO: Restore the saved session state only when appropriate, scheduling the + // final launch steps after the restore is complete + + } + + if (rootFrame->Content == nullptr) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments); + } + // Place the frame in the current Window + Window::Current->Content = rootFrame; + // Ensure the current window is active + Window::Current->Activate(); + } + else + { + if (rootFrame->Content == nullptr) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments); + } + // Ensure the current window is active + Window::Current->Activate(); + } +} + +/// +/// Invoked when application execution is being suspended. Application state is saved +/// without knowing whether the application will be terminated or resumed with the contents +/// of memory still intact. +/// +/// The source of the suspend request. +/// Details about the suspend request. +void App::OnSuspending(Object^ sender, SuspendingEventArgs^ e) +{ + (void) sender; // Unused parameter + (void) e; // Unused parameter + + //TODO: Save application state and stop any background activity +} + +/// +/// Invoked when Navigation to a certain page fails +/// +/// The Frame which failed navigation +/// Details about the navigation failure +void App::OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e) +{ + throw ref new FailureException("Failed to load Page " + e->SourcePageType.Name); +} \ No newline at end of file diff --git a/vsixtest/App.xaml.h b/vsixtest/App.xaml.h new file mode 100644 index 0000000000..7322d11b9c --- /dev/null +++ b/vsixtest/App.xaml.h @@ -0,0 +1,27 @@ +// +// App.xaml.h +// Declaration of the App class. +// + +#pragma once + +#include "App.g.h" + +namespace vsixtest +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + ref class App sealed + { + protected: + virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) override; + + internal: + App(); + + private: + void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ e); + void OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e); + }; +} diff --git a/vsixtest/Assets/LockScreenLogo.scale-200.png b/vsixtest/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..735f57adb5dfc01886d137b4e493d7e97cf13af3 GIT binary patch literal 1430 zcmaJ>TTC2P7~aKltDttVHYH6u8Io4i*}3fO&d$gd*bA_<3j~&e7%8(eXJLfhS!M@! zKrliY>>6yT4+Kr95$!DoD(Qn-5TP|{V_KS`k~E6(LGS@#`v$hQo&^^BKsw3HIsZBT z_y6C2n`lK@apunKojRQ^(_P}Mgewt$(^BBKCTZ;*xa?J3wQ7~@S0lUvbcLeq1Bg4o zH-bvQi|wt~L7q$~a-gDFP!{&TQfc3fX*6=uHv* zT&1&U(-)L%Xp^djI2?~eBF2cxC@YOP$+9d?P&h?lPy-9M2UT9fg5jKm1t$m#iWE{M zIf%q9@;fyT?0UP>tcw-bLkz;s2LlKl2qeP0w zECS7Ate+Awk|KQ+DOk;fl}Xsy4o^CY=pwq%QAAKKl628_yNPsK>?A>%D8fQG6IgdJ ztnxttBz#NI_a@fk7SU`WtrpsfZsNs9^0(2a z@C3#YO3>k~w7?2hipBf{#b6`}Xw1hlG$yi?;1dDs7k~xDAw@jiI*+tc;t2Lflg&bM)0!Y;0_@=w%`LW^8DsYpS#-bLOklX9r?Ei}TScw|4DbpW%+7 zFgAI)f51s}{y-eWb|vrU-Ya!GuYKP)J7z#*V_k^Xo>4!1Yqj*m)x&0L^tg3GJbVAJ zJ-Pl$R=NAabouV=^z_t;^K*0AvFs!vYU>_<|I^#c?>>CR<(T?=%{;U=aI*SbZADLH z&(f2wz_Y0??Tf|g;?|1Znw6}6U43Q#qNRwv1vp9uFn1)V#*4p&%$mP9x&15^OaBiDS(XppT|z^>;B{PLVEbS3IFYV yGvCsSX*m literal 0 HcmV?d00001 diff --git a/vsixtest/Assets/SplashScreen.scale-200.png b/vsixtest/Assets/SplashScreen.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..023e7f1feda78d5100569825acedfd213a0d84e9 GIT binary patch literal 7700 zcmeHLYj~4Yw%(;oxoEH#Kxq-eR|+VkP17b#Vk;?4QwkI+A{L04G+#<<(x#Un1#+h5>eArRq zTw$)ZvTWW_Y?bDho0nPVTh08+s`sp!j74rJTTtXIDww0SILedFv?sZ?yb@@}GN;#8 znk_b~Q(A0YR#uV4ef!osoV1M3;vQ8N$O|fStfgf$S5;ddUNv`tWtGjM;koG#N;7M< zP*84lnx(bn_KF&9Z5Ai$)#Cs3a|$OFw>WKCT$of*L7_CqQEinflT|W{JT+aKp-E0v zsxmYg)1(T>DROm+LN1eQw8}KCTp=C!$H7`PU!t9_Hw@TsTI2`udRZv*!a5`#A9hK6Y95L(CDUX&_@QxKV z_feX{UhA#ZWlvgpL$#w^D#lq`_A4AzDqd|Zv6y9PX&DNcN|l}_D^{q@GG&H^Pg583 z8FI6N8^H7b5WjGp;urW)d7F+_lcp%KsLX0viCmE(OHH+=%ZfD_=`voUuoUxFO^L;- z;!;2{g-YiiO6m4bs89OuF9!p{FGtH-f%8<2gY!h9s)4ciN%{Kh1+`}{^}M~+TDH9N z^Z5PlgVXMC&2&k*Hw^Lb9gny#ro$MOIxIt{+r)EA10$VR3 zanN8D{TUkl+v0CQ_>ZoHP<M-x#8@8ZiT#$Kh`(uRaX1g$Bg|qy$<#7 zSSAi{Nb8Y=lvNVeio+UGLCAtoLBfL`iOv`)yoJMDJBN>4IH@(l7YRF;61@>qq1iM9 zr@b#OC~SAxSle?5Pp8Z78{VO0YFr1x7kZU64Z23eLf2T2#6J_t;-E}DkB?NufZ0Ug zi?J&byXeaB-uTNVhuiM!UVQw}bZrJ3GtAETYp->!{q#zfN7D3AS9@Q7*V^85jGx#R z(QxYV(wW#F0XF9^^s>>H8pPlVJ>)3Oz z&_X8Sf@~?cH_O*cgi$U#`v`RRfv#y3m(ZpKk^5uLup+lVs$~}FZU$r_+}#hl%?g5m z-u-}-666ssp-xWQak~>PPy$mRc|~?pVSs1_@mBEXpPVfLF6(Ktf1S* zPPh@QZ=tFMs?LM2(5P3L2;l_6XX6s&cYsP1ip#eg0`ZEP0HGYh{UmS@o`MihLLvkU zgyAG0G`b1|qjxxh1(ODKFE%AP}Dq=3vK$P7TXP4GrM1kQ72!GUVMDl`rDC&2;TA}*nF z8$nQD&6ys_nc1*E7$*1S@R8$ymy(sQV}imGSedB@{!QR5P&N_H=-^o!?LsWs+2|mH z-e=)T^SvI)=_JIm7}j4;@*Z17=(#}m=~YF~z~CLI+vdAGlJDcdF$TM?CVI1%LhUrN zaa6DJ=Yh$)$k&Oz{-~8yw^GM^8prYxSxo zvI4k#ibryMa%%*8oI-5m61Koa_A_xg=(fwp0aBX{;X4Q;NXUhtaoJDo1>TqhWtn=_ zd5~chq#&6~c%8JZK#t_&J(9EVUU&upYeIovLt1>vaHe}UUq>#RGQj!EN#5+0@T`(@ z^g~>*c`VGRiSt;!$_4+0hk^I!@O3``5=sZ8IwlxWW7km1B&_t&E*u0_9UBa#VqwY* zz>nxv?FAsVnRaD(Bui=6i==BFUw0k4n$>`umU`F2l?7CYTD^)c2X+d9X&ddS9|gj? zM?knGkGCX&W8offw8aLC2$D{PjC3nVZwd4k?eZH8*mZ)U@3Qk8RDFOz_#WUA#vnzy zyP>KrCfKwSXea7}jgJjBc}PGY+4#6%lbZyjhy`5sZd_Vy6Wz;ixa?czkN}J9It1K6 zY!eu>|AwF^fwZlLAYyQI*lM@^>O>Iu6Vf6i>Q$?v!SeUS<{>UYMwz$*%Aq?w^`j{h z!$GZbhu=^D{&ET8;))LL%ZBDZkQqRd2;u~!d9bHGmLRhLDctNgYyjsuvoSZ#iVdoB z2!f--UUA#U;<{je#?cYt^{PIyKa%hW>}uepWMyAI{{Zo7?2>?$c9;whJae%oN|I-kpTQSx_C$Z&;f zi2i)qmEn=y4U0uvk)$m;zKfjPK@oc?I`}1Jzl$Q~aoKBd3kt7L#7gyt|A_qgz6ai< z=X%D1i!d2h?rHR^R8SUj&G||dkC?DT>{o#Yau<@uqVT{Xef&XG}5*E4aPk{}~ zplx&XhaV)&1EfI3Em;Bw#O5SV^c;{twb-1Rw)+=0!e_BLbd7tYmXCH0wrlOSS+~`7He8Iqx0{CN+DVit9;*6L~JAN zD&cyT)2?h}xnYmL?^)<7YyzZ3$FHU^Eg;DLqAV{#wv#Wj7S`Jdl1pX&{3(uZ?!uh} zDc$ZTNV*7le_W6}Hju~GMTxZQ1aWCeUc%!jv3MHAzt>Y-nQK%zfT*3ebDQA5b?iGn; zBjv3B+GhLTexd_(CzZDP4|#n5^~scvB6#Pk%Ho!kQ>yYw((Dv{6=$g3jT1!u6gORW zx5#`7Wy-ZHRa~IxGHdrp(bm%lf>2%J660nj$fCqN(epv@y!l9s7@k6EvxS{AMP>WY zX4$@F8^kayphIx-RGO$+LYl9YdoI5d|4#q9##`_F5Xnx`&GPzp2fB{-{P@ATw=X@~ z_|&^UMWAKD;jjBKTK(~o?cUFRK8EX=6>cXpfzg4ZpMB>*w_^8GSiT-Jp|xBOnzM+j z*09-@-~qJ(eqWq5@R4i^u4^{McCP(!3}C|v_WsTR*bIUxN(Nx`u##3B4{sE`Z`v8w zAwIG`?1~PkID~W{uDzmqH98Pew_1(;x2%8r^vY{)_&J2K)cN{W+h5+g)ZcjP&Ci#O zgy|8K@4kyMfwilHd&6TDlhb%++Pk!>9HRld6HT7gwyZGrxS$}CsD6`>6!!2K1@Mjf z(P0WYB7V_OFZyeWrbOFb>O54BNXf~K&?}3=^v;v_wT{DKr?jN^DtN&DXwX%u?s*c6`%8>WFz z7}YW^tp0bp^NriE)AB6M2l<7rn7fzePtR*omOevpfm9n?}2V*+0iW;S)C zhg`NAjL?D=W#k*$aR{>pGf~lD-rVtD;5jW1_*Jn1j1=es@Kcx4ySM_bwcQCT=d+DV z>Sz~L=Hj@(X%31nK$mWI@7d>}ORB`K(p=+`UD)+99YUGQc7y^bHZ1F(8|tL0 zdK*DT0kSXG_{BKTpP2*2PecdKV9;dq$^ZZDP;Nyq1kp-&GI5eAyZsK!e3V zK@rPy*{(`KIfo+lc878mDKk^V#`VT05}64kBtk%DgwLrOvLMj5-;*GNKv6c6pzMuL z6EP%ob|_0IW}lLRXCP2!9wWhEw3LA7iF#1O1mIZ@Z=6&bz41F;@S_GvYAG-#CW3z{ zP3+6vHhvP&A3$##Vo9$dT^#MoGg^|MDm=Bt1d2RRwSZ<;ZHICpLBv5Xs!D?BH^(9_ z7`H=N&^v|Z-%mP}wNzG{aiFCsRgwzwq!N6obW9+7(R; z(SZ=23`|`>qil!LMGG{_Heq!BD>(Y-zV9wD)}hz25JA37YR%39;kI4y9pgtcUass6 zP24}ZY$vvYeI`zy&)A_X#nY3017ap*0&jx|mVwyGhg3;!keU53a}Uhm3BZI$N$6Se zLWlAmy1S0xKJm4G_U@sN_Tm=`$xWJSEwKU98rZ&)1R^*$$1vA3oG#&*%SMxY_~oGP zP&PFJatFLM-Ps%84IV-+Ow)T{C7cqUAvauy4C z(FRz&?6$Rypj{xO!`y=*J5o4@U8Q-(y5(*=YoKeZ+-1YdljXxkA#B)zo=FeQH#?Le zycNUmEEHWO9a=X^pb#&cOq7-`7UA87#|S22)<7RUtZo|(zibX=w;K3qur9vy#`MNV z6UUcf9ZwEnKCCp+OoBnF@OdbvH)ANXO0o~Pi9l8=x3))}L<#vO0-~O4!~--Ket?d} zJaqsj<@CD1%S2cTW%rOP{Vto%0sGW~1RMa_j^)5nil0Yw- z0EE#bP+l4#P^%PQ+N*oxu1Zq05xZ!bXfYTg>9c{(Iw*lnjR^>kz%lAN^zFce7rppy zY8zA~3GD=A6d*hze&l4D_wA~+O!56)BZTe_rEu}Ezi<4!kG|W#amBZ5{&XS2@6R~H z{9o^y*BkH4$~yX9U&@CgbOzX1bn9xqF|zh$Dh0Y5y*E0e90*$!ObrHY3Ok0`2=O~r zCuke6KrP9KOf?V(YDsM<6pX2nVoN%M$LT^q#FmtaF?1^27F*IcNX~XRB(|hCFvdcc zc)$=S-)acdk$g4?_>jRqxpI6M3vHZk?0c^3=byamYDNf;uB{3NlKW5IhnOS3DNkMV z?tK8?kJ}pmvp%&&eTVOVjHP`q34hN1@!aK}H(K!vI`~gf|Gv+FNEQD5Yd<~yX7k_l h&G-K)@HZb3BABY{)U1?^%I#E6`MGoTtustd{~yM6srvu` literal 0 HcmV?d00001 diff --git a/vsixtest/Assets/Square150x150Logo.scale-200.png b/vsixtest/Assets/Square150x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..af49fec1a5484db1d52a7f9b5ec90a27c7030186 GIT binary patch literal 2937 zcma)84OCO-8BSud5)jwMLRVKgX(S?$n?Ld|vrsm<$CF7)&zTbyy1FE5bU`Q17MRv`9ue$;R(@8kR;#vJ*IM0>cJIAOte!d7oRgdH zd%ySjdB6L9=gX^A6)VzH7p2l@v~3zJAMw|DFy#^)F@@F*`mqUn=Il>l)8_+ab;nOW{%+iPx z+s{Eu|&pIs)Z7{La9~?xKfyl z#43?gjEL15d4WbOZo#SiP%>DB^+BcnJ=7dHEe;r#G=tuw|ka z%q@}##Uh7;tc%L_64m(kHtw74ty%BJMb)_1)#S0j`)F8_1jF7vScpsnH=0V19bO8y zR`0SjIdCUo&=>JwMQF8KHA<{ODHTiQh}0^@5QRmCA?gOH6_H3K^-_sNB^RrdNuK-R zOO*vOrKCVvDwgUck`kF(E7j{I#iiN;b*ZdCt4m@HPA`EuEqGGf4%!K<;(=I=&Vyrw z%TwcWtxa}8mCZ%Cyf&ActJ6_$ox5z6-D!0-dvnRx6t7y3d+h6QYpKWO;8OdnvERo7 zuEf>ih5`wqY)~o@OeVt-wM?Q!>QzdGRj!bz6fzYrfw$hZfAKzr2-M+D+R>}~oT574c;_3zquHcElqKIsryILt3g8n3jcMb+j?i?-L3FpZJ z2WRVBRdDPc+G5aaYg#5hpE+6nQ|(VSoxT3|biF;BUq#==-27Xi=gihDPYP$7?=9cP zYKE$jeQ|3~_L0VG-(F~2ZPyD0=k{J4Q~h(t__{-mz_w8{JDY9{`1ouzz!Vr5!ECdE z6U~O1k8c}24V7~zzXWTV-Pe4)y}wQJS&q%H5`Fo_f_JvIU489aCX$;P`u#!I-=^4ijC2{&9!O&h>mi?9oYD=GC#%)6{GzN6nQYw+Fal50!#x^asjBBR50i`+mho*ttoqV)ubM2KD9S~k7+FR4>{29?6 z{!l6kDdyTN0YJ9LgkPWeXm|gyi@zM3?0@{&pXT12w|78&W-q!RRF)&iLCEZVH<|fR zN0fr2^t8H(>L?>K#>^+jWROLral(Qy-xoBq1U7A&DV||wClb)Otd9?(gZ|8znMF}D zf<1haWz^s0qgecz;RFGt0C-B4g`jNGHsFU+;{<%t65v^sjk^h$lmWn#B0#_)9ij&d z-~lc`A)YYExi^7sBuPM^Y|wA2g*5?`K?#7tzELQYNxGo$UB$4J8RJp1k(8Jj+~hMT zlN~>M@KTTh^--8y3PK_NZ@AC!{PT=CziBzGd+wTJ^@icH!Bd}%)g8V)%K?|c&WTUk zy}qv1C%(fjRoZ4ozC3{O%@5?)XzH35zHns$pgU*Q?fj4v?fp1Qbm+j;3l;9jam9Da zXVcKjPlQ73x78QPu|Ffm6x?`~e3oD=gl=4kYK?={kD5j~QCXU)`HSdduNNENzA*2$ zOm3PzF!lN5e*06-f1Uot67wY#{o-S1!KZ7E=!~7ynnk9_iJR#kFoNbAOT#^2Gd17F zMmvU6>lndZQGd|ax9kUoXXO+$N?|j@6qpsF&_j7YXvwo_C{JpmLw5&#e6k>atv%es z5)7r*Wvv_JkUpT}M!_o!nVlEk1Zbl=a*2hQ*<|%*K1Glj^FcF`6kTzGQ3lz~2tCc@ z&x|tj;aH&1&9HwcJBcT`;{?a+pnej;M1HO(6Z{#J!cZA04hnFl;NXA+&`=7bjW_^o zfC40u3LMG?NdPtwGl>Tq6u}*QG)}-y;)lu-_>ee3kibW(69n0$0Zy!}9rQz%*v1iO zT9_H>99yIrSPYVy6^);rR}7Yo=J_T@hi+qhTZXnVWyf;JDYm5#eYLTxr*?kiNn!+Y zQ+LUkBafNJ#rH#C(?d5^;gw9o#%daEI{mA*LHPIHPU`#|H$hD zwm>0&+kahQ)E#%~k>&5@&#Vg82H?s%71=)(soi@174pi9--2{w{1$}Sz4zGn3Du&x bht0Iza^2ykEt4(epJ78uh5nDlX8(TxzDYwP literal 0 HcmV?d00001 diff --git a/vsixtest/Assets/Square44x44Logo.scale-200.png b/vsixtest/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..ce342a2ec8a61291ba76c54604aea7e9d20af11b GIT binary patch literal 1647 zcmaJ?eM}Q)7(e+G1Q(|`V9JhTI2>MkceK4;p;PR&$Pi?ejk3YQ_3o`S&|W_dsOZ8# zWPTt69g`t$ab`0cj-Y0yiBSOqmd)tG7G(}M5aP0_%&9TijB#&)I{zSE^4@#z^FF`l z`8{8`o%wlL(UI|y2!cdsuVamHH~H86F!*-15em4)NqUpCQM5?aoC_eCf@lV4wvF2a zjDQn1JBL69f&@2M3rvzJcfE!eZ8FZUBlFlC5RD)it33{mF9#B82AiyQE%w)`vlwa> zv{<1sm&kSKK$&%2jSFn7$t&P%%6Ue>R=EAnG8N7fqynWG8L3p!4801a;8{+nliO(qd(jNJ_?+9W3#hLIDLoT6~3fx9=`CC-D}-AMrpEO7HK zt3$GicGPc?GmDjy7K2P@La;eu4!$zWCZ`ym{Z$b zu-O6RM&K4JT|BIZB`E-gxqG%FzanI#+2FFmqHqXG7yxWB=w55RGOM)$xMb(>kSNR z2w=1AZi%z=AmG~yea~XaXJR!v7vLn(RUnELfiB1|6D84ICOS}^Zo2AdN}<&*h}G_u z{xZ!(%>tLT3J3<5XhWy-tg+6)0nmUUENLW8TWA{R6bgVd3X;anYFZ^IRis*_P-C-r z;i>%1^eL3UI2-{w8nuFFcs0e~7J{O2k^~Ce%+Ly4U?|=!0LH=t6()xi<^I-rs+9sF z*q{E-CxZbGPeu#a;XJwE;9S1?#R&uns>^0G3p`hEUF*v`M?@h%T%J%RChmD|EVydq zmHWh*_=S%emRC*mhxaVLzT@>Z2SX0u9v*DIJ@WC^kLVdlGV6LpK$KIrlJqc zpJ921)+3JJdTx|<`G&kXpKkjGJv=76R`yYIQ{#c-`%+`#V(7}Q;&@6U8!Td1`d;?N z_9mnI#?AA}4J!r)LN4!E-@H5eXauuB7TOawS>Y|{-P?NNx-lq+z1W-+y(;39P&&LP zL{N80?&=C*qKmdA^moMZRuPcD!B<*mq$ch=0Cnlitw#txRWhb3%TQvPqjkC`F69G4b! ze7z9MZ#+;_#l?H37UqUhDFb^l&s2{oM$3I0o^Q!yx;;V)QmCMo)Tb_ui|mit8MS?U zm##6$sZZ1$@|s%?l@>4Z<*Q}sRBSKMhb4I{e5LdEhsHIHTe8Bod5c>6QtT>$XgUBz z6MK`kO$=jmt@FqggOhJ5j~e@ygRbG;<{Vu)*+nn9aQeo0;$#j;|MS=S$&L?BeV25z xs3B`@=#`5TF{^6(A1rvdY@|-RtQ|iS5{tyX+wH?;n8E)G$kykv-D^wh{{!TZT%7;_ literal 0 HcmV?d00001 diff --git a/vsixtest/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/vsixtest/Assets/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c02ce97e0a802b85f6021e822c89f8bf57d5cd GIT binary patch literal 1255 zcmaJ>TWs4@7*5+{G#S+&C!qC#> zf>5N3P6jO*Cz>ug*(_DmW=)kea&m$gZ^+nyiF`;j%w@}y8)>p*SH}C`m?DXeieF2U zyQHecc_L%Gh!7GMt+hG06y;+|p4>m~}PjA}rKViGiEnn7G0ZO<>G|7q;2?NwGCM3s?eued6%hd$B+ z*kQJ{#~$S=DFE(%=E+UkmlEI*%3llUf~8Ja9YU1Vui0IbGBkW_gHB%Rd&!!ioX zs40O?i9I{};kle7GMvE7(rk`la=gTI)47=>%?q@^iL-nUo3}h4S}N-KHn8t5mVP8w z&bSErwp+37 zNJJ8?a|{r5Q3R0Z5s-LB1WHOwYC@7pCHWND#cL1cZ?{kJ368_*(UDWUDyb<}0y@o# zfMF016iMWPCb6obAxT$JlB6(2DrlXDTB&!0`!m??4F(qWMhjVZo?JXQmz`1*58Z=& zcDmB|S-E@j?BoFGix0flckqdS4jsPNzhfWyWIM98GxcLs89C(~dw%$_t;JjX-SD}E zfiGV;{8Q%8r}w9x>EEigW81>`kvnU@pK)4+xk9@+bNj9L!AAZ@SZ@q|)&BmY3+HZx zul~BeG4|}-;L%cHViQGQX?^zFfO0&#cHwel=d`lH9sJ-@Sl@n*(8J2>%Ac`IxyY?Q z{=GhWvC#gu-~Ia7*n{=+;qM?Ul_wy1+u7ho;=`>EwP^g~R@{unBds`!#@}tluZQpS zm)M~nYEifJWJGx?_6DcTy>#uh%>!H9=hb^(v`=m3F1{L>db=<5_tm+_&knAQ2EU$s Mu9UqpbNZeC0BbUo^Z)<= literal 0 HcmV?d00001 diff --git a/vsixtest/Assets/StoreLogo.png b/vsixtest/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..7385b56c0e4d3c6b0efe3324aa1194157d837826 GIT binary patch literal 1451 zcmaJ>eN5D57_Z|bH;{0+1#mbl)eTU3{h)Wf7EZV?;HD@XL@{B`Ui%(2aMxQ~xdXSv z5nzWi(LW)U2=Vc-cY@s7nPt{i0hc6!7xN4NNHI#EQl>YNBy8l4%x9gr_W-j zEZMQmmTIy(>;lblRfh`dIyTgc9W5d!VP$L4(kKrN1c5G~(O_#xG zAJCNTstD^5SeXFB+&$h=ToJP2H>xr$iqPs-#O*;4(!Fjw25-!gEb*)mU}=)J;Iu>w zxK(5XoD0wrPSKQ~rbL^Cw6O_03*l*}i=ydbu7adJ6y;%@tjFeXIXT+ms30pmbOP%Q zX}S;+LBh8Tea~TSkHzvX6$rYb)+n&{kSbIqh|c7hmlxmwSiq5iVhU#iEQ<>a18|O^Sln-8t&+t`*{qBWo5M?wFM(JuimAOb5!K#D}XbslM@#1ZVz_;!9U zpfEpLAOz=0g@bd6Xj_ILi-x^!M}73h^o@}hM$1jflTs|Yuj9AL@A3<-?MV4!^4q`e z)fO@A;{9K^?W?DbnesnPr6kK>$zaKo&;FhFd(GYFCIU^T+OIMb%Tqo+P%oq(IdX7S zf6+HLO?7o0m+p>~Tp5UrXWh!UH!wZ5kv!E`_w)PTpI(#Iw{AS`gH4^b(bm^ZCq^FZ zY9DD7bH}rq9mg88+KgA$Zp!iWncuU2n1AuIa@=sWvUR-s`Qb{R*kk(SPU^`$6BXz8 zn#7yaFOIK%qGxyi`dYtm#&qqox0$h=pNi#u=M8zUG@bpiZ=3sT=1}Trr}39cC)H|v zbL?W)=&s4zrh)7>L(|cc%$1#!zfL?HjpeP%T+x_a+jZ16b^iKOHxFEX$7d|8${H-* zIrOJ5w&i$>*D>AKaIoYg`;{L@jM((Kt?$N$5OnuPqVvq**Nm}(f0wwOF%iX_Pba;V z;m@wxX&NcV3?<1+u?A{y_DIj7#m3Af1rCE)o`D&Y3}0%7E;iX1yMDiS)sh0wKi!36 zL!Wmq?P^Ku&rK~HJd97KkLTRl>ScGFYZNlYytWnhmuu|)L&ND8_PmkayQb{HOY640 bno1(wj@u8DCVuFR|31B*4ek@pZJqxCDDe1x literal 0 HcmV?d00001 diff --git a/vsixtest/Assets/Wide310x150Logo.scale-200.png b/vsixtest/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..288995b397fdbef1fb7e85afd71445d5de1952c5 GIT binary patch literal 3204 zcmbVPeQXow8NYmBd90>}0NP?GhXW~VaeThm=a0tV#EwJMI!)6M3}|c4_Bl3=Kd>G0 z(GHx1wl<7(tP?FsOQkTilSo*iIvF%uArExJ73~P zSv1xEy!U(Wd4A9D`FQV@W3@F^qJ@PEF$@z`Z!*BbFsS(^?B zyiAzJ+q})bkgiQHWqEb*jJD-coHYr1^iocg)l!Qa{Xqs-l~6J}p-|##ZHYofskQ3$ zI0;xzXyhazBeXhIsg5A=%ufo@f)1yy&ScKS0;HF^!r_2UE^lpZEom(+@duma3awTv zCrCL-%D_SvYWIcdHkmI}#50(fkUi)Qgx!80ju>g1za^}ff>JI8Z@^-iCiaCgg@TgF z+vtE?Q9{VQUX&MW9SYYmGcxA14%N2@7FwBTD4N<(2{nWgV8$e3?-F=L^&FrtWn~(U_Q~~^uYiyeY6-KoTnfh9AWz@ zIKje0)u!_Lw)E}G!#kEfwKVdNt(UAf9*f>tEL_(=xco-T%jTi@7YlC3hs2ik%Le0H ztj}RTeCF(5mwvi3_56>-yB?l;J>-1%!9~=fs|QcNG3J~a@JCu`4SB460s0ZO+##4fFUSGLcj_ja^fL4&BKALfb#$6$O?>P@qx2Agl^x0i&ugt zsy5Pyu=()`7HRMG3IB7F1@`_ z+-!J%#i6e^U$e#+C%Q>_qVRzWRsG^W_n+@OcX@vzI&z;mzHNb!GQ?LWA(wtpqHqTM z1OFw_{Zn?fD)p)`c`kOgv{de=v@suGRqY{N^U7gI1VF3*F=obwaXI6ob5__Yn zVTguS!%(NI09J8x#AO_aW!9W7k*UvB;IWDFC3srwftr{kHj%g)fvnAm;&h_dnl~

    MY- zf+K}sCe8qU6Ujs`3ua{U0Of$R_gVQBuUA za0v=mu#vIOqiiAZOr&h*$WyOw&k-xr$;G4Ixa!#TJNr>95(h>l%)PUy4p+^SgR(uR zta%k*?ny-+nAr8spEk1fo{J4i!b^Fia`N{_F6@zidA2ZTTrjl#^5Z-2KfB@Cu}l9s z(*|Z2jc?p~vn2f)3y9i*7zJV1L{$?|&q)4oaT;uXi6>1GkRXVTOzAz(RHEmr=eFIi z`}<>-Q?K0GN8!IYxeP1XKXO+jsJbp~o^);Bc;%b7Flpe7;1`Ny@3r7ZR;?R)aJt8C ziNlEC<@3f_lIV4TwV}&e;D!Ee5_|e#g0LUh=5vmYWYm7&2h*M>QPKvGh9-)wfMMW3 z8J9b%1k7dzPzO0_NGQy92BZ^FR6R~6;^6?lqO;-QUP4BY%cG%3vEhbm#>4vIhPBh3 z-+pZGjh$x%Hp{?=FHsMp0&wNPlj00us{&`1ZOZTqs8%4X&xH=UDr*xyBW(Zp&Em94 zf)ZSfn#yg0N)>!1kWdkqJ^S*z0FF5|fj&qcE#Na|%OY0$uO>!&hP+1ywfD_WXk@4J(?MBftK7>$Nvqh@tDuarN%PrTLQ2Uzysx>UV=V zk^RrDSvdQ?0;=hY67EgII-f4`t=+i*yS=Y~!XlqIy_4x&%+OdfbKOFPXS2X5%4R{N z$SQMX^AK6(fA + + + + + diff --git a/vsixtest/MainPage.xaml.cpp b/vsixtest/MainPage.xaml.cpp new file mode 100644 index 0000000000..f615f4d89e --- /dev/null +++ b/vsixtest/MainPage.xaml.cpp @@ -0,0 +1,27 @@ +// +// MainPage.xaml.cpp +// Implementation of the MainPage class. +// + +#include "pch.h" +#include "MainPage.xaml.h" + +using namespace vsixtest; + +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Windows::UI::Xaml; +using namespace Windows::UI::Xaml::Controls; +using namespace Windows::UI::Xaml::Controls::Primitives; +using namespace Windows::UI::Xaml::Data; +using namespace Windows::UI::Xaml::Input; +using namespace Windows::UI::Xaml::Media; +using namespace Windows::UI::Xaml::Navigation; + +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 + +MainPage::MainPage() +{ + InitializeComponent(); +} diff --git a/vsixtest/MainPage.xaml.h b/vsixtest/MainPage.xaml.h new file mode 100644 index 0000000000..cf95007d17 --- /dev/null +++ b/vsixtest/MainPage.xaml.h @@ -0,0 +1,21 @@ +// +// MainPage.xaml.h +// Declaration of the MainPage class. +// + +#pragma once + +#include "MainPage.g.h" + +namespace vsixtest +{ + ///

    + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public ref class MainPage sealed + { + public: + MainPage(); + + }; +} diff --git a/vsixtest/Package.appxmanifest b/vsixtest/Package.appxmanifest new file mode 100644 index 0000000000..49e45cbc3e --- /dev/null +++ b/vsixtest/Package.appxmanifest @@ -0,0 +1,49 @@ + + + + + + + + + + vsixtest + mistachkin + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vsixtest/pch.cpp b/vsixtest/pch.cpp new file mode 100644 index 0000000000..ef288d82ad --- /dev/null +++ b/vsixtest/pch.cpp @@ -0,0 +1,6 @@ +// +// pch.cpp +// Include the standard header and generate the precompiled header. +// + +#include "pch.h" diff --git a/vsixtest/pch.h b/vsixtest/pch.h new file mode 100644 index 0000000000..e5006e81d3 --- /dev/null +++ b/vsixtest/pch.h @@ -0,0 +1,11 @@ +// +// pch.h +// Header for standard system include files. +// + +#pragma once + +#include +#include + +#include "App.xaml.h" diff --git a/vsixtest/vsixtest.sln b/vsixtest/vsixtest.sln new file mode 100644 index 0000000000..bebec6355b --- /dev/null +++ b/vsixtest/vsixtest.sln @@ -0,0 +1,40 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vsixtest", "vsixtest.vcxproj", "{60BB14A5-0871-4656-BC38-4F0958230F9A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|ARM.ActiveCfg = Debug|ARM + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|ARM.Build.0 = Debug|ARM + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|ARM.Deploy.0 = Debug|ARM + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x64.ActiveCfg = Debug|x64 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x64.Build.0 = Debug|x64 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x64.Deploy.0 = Debug|x64 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x86.ActiveCfg = Debug|Win32 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x86.Build.0 = Debug|Win32 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x86.Deploy.0 = Debug|Win32 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|ARM.ActiveCfg = Release|ARM + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|ARM.Build.0 = Release|ARM + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|ARM.Deploy.0 = Release|ARM + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x64.ActiveCfg = Release|x64 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x64.Build.0 = Release|x64 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x64.Deploy.0 = Release|x64 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x86.ActiveCfg = Release|Win32 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x86.Build.0 = Release|Win32 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x86.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vsixtest/vsixtest.tcl b/vsixtest/vsixtest.tcl new file mode 100644 index 0000000000..3c0a8dbf56 --- /dev/null +++ b/vsixtest/vsixtest.tcl @@ -0,0 +1,215 @@ +#!/usr/bin/tclsh +# +# This script is used to quickly test a VSIX (Visual Studio Extension) file +# with Visual Studio 2015 on Windows. +# +# PREREQUISITES +# +# 1. Tcl 8.4 and later are supported, earlier versions have not been tested. +# +# 2. The "sqlite-UWP-output.vsix" file is assumed to exist in the parent +# directory of the directory containing this script. The [optional] first +# command line argument to this script may be used to specify an alternate +# file. However, currently, the file must be compatible with both Visual +# Studio 2015 and the Universal Windows Platform. +# +# 3. The temporary directory specified in the TEMP or TMP environment variables +# must refer to an existing directory writable by the current user. +# +# 4. The VS140COMNTOOLS environment variable must refer to the Visual Studio +# 2015 common tools directory. +# +# USAGE +# +# The first argument to this script is optional. If specified, it must be the +# name of the VSIX file to test. +# +package require Tcl 8.4 + +proc fail { {error ""} {usage false} } { + if {[string length $error] > 0} then { + puts stdout $error + if {!$usage} then {exit 1} + } + + puts stdout "usage:\ +[file tail [info nameofexecutable]]\ +[file tail [info script]] \[vsixFile\]" + + exit 1 +} + +proc getEnvironmentVariable { name } { + # + # NOTE: Returns the value of the specified environment variable or an empty + # string for environment variables that do not exist in the current + # process environment. + # + return [expr {[info exists ::env($name)] ? $::env($name) : ""}] +} + +proc getTemporaryPath {} { + # + # NOTE: Returns the normalized path to the first temporary directory found + # in the typical set of environment variables used for that purpose + # or an empty string to signal a failure to locate such a directory. + # + set names [list] + + foreach name [list TEMP TMP] { + lappend names [string toupper $name] [string tolower $name] \ + [string totitle $name] + } + + foreach name $names { + set value [getEnvironmentVariable $name] + + if {[string length $value] > 0} then { + return [file normalize $value] + } + } + + return "" +} + +proc appendArgs { args } { + # + # NOTE: Returns all passed arguments joined together as a single string with + # no intervening spaces between arguments. + # + eval append result $args +} + +# +# NOTE: This is the entry point for this script. +# +set script [file normalize [info script]] + +if {[string length $script] == 0} then { + fail "script file currently being evaluated is unknown" true +} + +set path [file dirname $script] + +############################################################################### + +# +# NOTE: Process and verify all the command line arguments. +# +set argc [llength $argv] +if {$argc > 1} then {fail} + +if {$argc == 1} then { + set fileName [lindex $argv 0] +} else { + set fileName [file join [file dirname $path] sqlite-UWP-output.vsix] +} + +if {[string length $fileName] == 0} then { + fail "invalid VSIX file name" +} + +if {![file exists $fileName] || ![file isfile $fileName]} then { + fail [appendArgs "VSIX file \"" $fileName "\" does not exist"] +} + +set envVarName VS140COMNTOOLS +set vsDirectory [getEnvironmentVariable $envVarName] + +if {[string length $vsDirectory] == 0} then { + fail [appendArgs \ + "Visual Studio 2015 environment variable \"" $envVarName "\" missing"] +} + +if {![file exists $vsDirectory] || ![file isdirectory $vsDirectory]} then { + fail [appendArgs \ + "Visual Studio 2015 directory \"" $vsDirectory \ + "\" does not exist"] +} + +set vsixInstaller [file join [file dirname $vsDirectory] IDE VSIXInstaller.exe] + +if {![file exists $vsixInstaller] || ![file isfile $vsixInstaller]} then { + fail [appendArgs \ + "Visual Studio 2015 VSIX installer \"" $vsixInstaller \ + "\" does not exist"] +} + +set envVarName ProgramFiles +set programFiles [getEnvironmentVariable $envVarName] + +if {[string length $programFiles] == 0} then { + fail [appendArgs \ + "Windows environment variable \"" $envVarName "\" missing"] +} + +if {![file exists $programFiles] || ![file isdirectory $programFiles]} then { + fail [appendArgs \ + "Program Files directory \"" $programFiles "\" does not exist"] +} + +set msBuild [file join $programFiles MSBuild 14.0 Bin MSBuild.exe] + +if {![file exists $msBuild] || ![file isfile $msBuild]} then { + fail [appendArgs \ + "MSBuild 14.0 executable file \"" $msBuild "\" does not exist"] +} + +set temporaryDirectory [getTemporaryPath] + +if {[string length $temporaryDirectory] == 0 || \ + ![file exists $temporaryDirectory] || \ + ![file isdirectory $temporaryDirectory]} then { + fail "cannot locate a usable temporary directory" +} + +set installLogFileName [appendArgs \ + [file rootname [file tail $fileName]] -install- [pid] .log] + +set buildLogFileName [appendArgs \ + [file rootname [file tail $fileName]] -build- [pid] .log] + +set uninstallLogFileName [appendArgs \ + [file rootname [file tail $fileName]] -uninstall- [pid] .log] + +set command(1) [list exec [file nativename $vsixInstaller] /quiet /norepair] +lappend command(1) [appendArgs /logFile: $installLogFileName] +lappend command(1) [file nativename $fileName] + +set command(2) [list exec [file nativename $msBuild]] +lappend command(2) [file nativename [file join $path vsixtest.sln]] +lappend command(2) /target:Rebuild /property:Configuration=Release + +lappend command(2) [appendArgs \ + /logger:FileLogger,Microsoft.Build.Engine\;Logfile= \ + [file nativename [file join $temporaryDirectory $buildLogFileName]] \ + \;Verbosity=diagnostic] + +set command(3) [list exec [file nativename $vsixInstaller] /quiet /norepair] +lappend command(3) [appendArgs /logFile: $uninstallLogFileName] +lappend command(3) [appendArgs /uninstall:SQLite.UWP.2015] + +puts stdout [appendArgs \ + "Install log will be \"" [file nativename [file join \ + $temporaryDirectory $installLogFileName]] "\"."] + +puts stdout [appendArgs \ + "Build log will be \"" [file nativename [file join \ + $temporaryDirectory $buildLogFileName]] "\"."] + +puts stdout [appendArgs \ + "Uninstall log will be \"" [file nativename [file join \ + $temporaryDirectory $uninstallLogFileName]] "\"."] + +puts stdout [appendArgs \ + "First command is \"" $command(1) "\"."] + +puts stdout [appendArgs \ + "Second command is \"" $command(2) "\"."] + +puts stdout [appendArgs \ + "Third command is \"" $command(3) "\"."] + +# eval exec $command(1) +# eval exec $command(2) +# eval exec $command(3) diff --git a/vsixtest/vsixtest.vcxproj b/vsixtest/vsixtest.vcxproj new file mode 100644 index 0000000000..a7b4fd302b --- /dev/null +++ b/vsixtest/vsixtest.vcxproj @@ -0,0 +1,213 @@ + + + + {60bb14a5-0871-4656-bc38-4f0958230f9a} + vsixtest + en-US + 14.0 + true + Windows Store + 10.0.10586.0 + 10.0.10586.0 + 10.0 + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + Application + true + v140 + + + Application + true + v140 + + + Application + true + v140 + + + Application + false + true + v140 + true + + + Application + false + true + v140 + true + + + Application + false + true + v140 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vsixtest_TemporaryKey.pfx + + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + + + + + + + App.xaml + + + MainPage.xaml + + + + + + Designer + + + Designer + + + + + + Designer + + + + + + + + + + + + + + + + + + + App.xaml + + + MainPage.xaml + + + + Create + Create + Create + Create + Create + Create + + + + + + + + + diff --git a/vsixtest/vsixtest.vcxproj.filters b/vsixtest/vsixtest.vcxproj.filters new file mode 100644 index 0000000000..a4a1a305a8 --- /dev/null +++ b/vsixtest/vsixtest.vcxproj.filters @@ -0,0 +1,24 @@ + + + + + 60bb14a5-0871-4656-bc38-4f0958230f9a + + + e6271362-8f96-476d-907f-4da227b02435 + bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + Assets + + + Assets + + + Assets + + + Assets + + + diff --git a/vsixtest/vsixtest_TemporaryKey.pfx b/vsixtest/vsixtest_TemporaryKey.pfx new file mode 100644 index 0000000000000000000000000000000000000000..e6787bcad0527ecc86a43ea007ba8776c4b26215 GIT binary patch literal 2520 zcmY*ac|6o>7ypeJ!=Nx|G_o{dY||aaG7*=uRdx}&bTP8McB-MVjL1zQ`_@>78g~pM zA?Xf@v>;?lA^YyizFzOI`+48{e%{ade4q22?>Xl=&p*%i!BY{vTo5Rpib#PYl;Ta} zw~jz~Aca&!42+7PfHWCT<=*|j6!!v*$~^ zY4Gr)FkYQeF~j*M(BHYZc)DOz*q}&)S9!g{H0k1#-rUN(n(H$|6{LPDexJiZ-kU&FbKR@6F34qKTFux@xniVPiG3Im6+bkmhv?r))l&Dh z+rGAjRwjvXTA0-DCAE3)udY3mp1vfqB3r%W%g$US-xNB~H$WB(SFOM2DM~Wb`WBSD zrsmnx6crY!JKAQdDOCEnQ5#8nJ>48`5K7FJFeu*hS-7x2Y$2yv`B>Nx-3hmP;(RFy z>4r0O+foVl^mk0SOzpMr@0RX8mCUL5tlyl{MKF0b;i|tRD>LlIMi~&oU!IG7AxM`F zd_#_lI(}YT;&5QhZ+qcdpq3+<;;1m9=S>c>udYxaep@Dvv^}7m$fO>mSS38a5RhJ6 zp-1GMa^ics&P9wCvgLhqgvMPaCFq6dHGY*&sET#^P??s~ts;S1JG!ou^>D}dQmSjt1sMDg_CQC%AyT@e zMd7E`TfZE>FFm5?)Q$>8wZZ0VB>N!J@)r83mQBqaF}Y{Uwi%mz)NkpyE3B;@=v5}}d$e3g6>CQ4uG3CVAPb8E{o(WDWx64dZr zp~GyP4l06CQ6(2E;~nvGUC7z+hVM-7p?<&URkIz5MT@xX$>*0mA1g!F3`(i~we1?> zCme&g0u{bUVnnHIuSxUgYmd71`BL_R*$o++|bK}tOlc$|~C=(DW z&rQ$s(beUf`fbWSPAX_@_3*gC*Pkr9Yphb#z6pFcxnVw45Y=$<_o5u#Z_=V`n9!zz zu)AsO#IDlGltwGD^nU@JbmfQa8rJ={g`Km$J)Ta=Pd1Z6YsPH0D+QJE2dCV$Z;mRI zoyfEnsZE4uRpk571wJ}vL|(m}H{2-3%p*&Vn2nbA%Z=y0XEDc((lKYlJv)TC>;1l{ z4O+%tJU7;gv*DgXg{FE!g~fLkvE1lRk_skAi?6>_chzTNljJ+_axug1@=%PeWB%0Y zZx${;(*_#DG_0;p@A?Y9U^3>$)UmrQ#fxUW;;Vns_?~!>9+eAzIa9V4%IASYmApcF z%JBQ$bLiT+QY3$;Vb67wcR@TzA`POm7enC3ZEnyb6f!7AO1VbsZpaJYTo8C3S`57| zib#6NF2;0k*oxm5IQb~biC%Ilb4$wJT?c9XTEws}tY+sLtuz1`yKZw@cF0ubssp1c zsrJo*BF$6j?XPg1Y{hG@mGJXpv)&=crtdfV3DmC&tEcKL<)ULX(L`jYyE!8px{zbP zdcV+{=k8NPMs9i?<7q~8ki-zKG0b$`U)-gMXFKhc0}U67EBYJ~Z%a(oY5lr`<-5oy zH+1oHbv!E+fu0J{^=?;<>A;KpBbNvP0D2z#VV}p$e#h-WBvX zKm#;QaE}AjK_h_~9B>A}10Eo701>PvfpupppN3TP0xDgON^?RXv4sJk^KVx0KFp@SC#Ri>(&9VxcHC3dS?;)F)TWn|xj%(VJ3 z?BI|MHp9_6I#{*17;l37liej`h=-Ca6?L&By%5V;q{3x*D>k(vPJVCyEv&7uJXYo% z`;aL*(Xf#x!O0$>BRgIW^>r~tePV%+pyjw** zk#KpMa)N4+fIjYL{witoF=GL3nQ#>6VURDreL& z;+XWM^-=}m0p0s-z#CP%=~x~n{!7Wma!&{A9~LhUX0X)%-UCX(CLz2T92^D@sI+U@p4S%bFf zuBKCWyS+m`-R;8L+8BouJXjmaBoWznxBFaMql1&t9#(R1%2LWMEzjnN&_X$kt647= z?@6{FoIXEqpW|P0Yan0FI)Mqy{4^nXZ?_B}Y!}4;hL|`Wwnw?p8qjp^wxiS`Z8(W% ze_U458SQ|L%qoqZZ!)U>GH3Z<}rm!iAu)PJfu6%(D`ZS;c)h+(>7zq-s~-0TiS8^=Zq#g60fDwvpi)UWfH^ zk-&0}S@!2@#YsE()`jPgMQ-2rjQtJ5^3%|_Ch^?iMYS>zd>0rju3O#f6!sHHJ!^tBb zDZ7Q;qZ(Sillt1*f-02@<4O^;t9Am&{hY+1%H+{^ubidQN*j-*o#kUV$N5(&)pqV< z>m2PDzKKBfp8fGUMJXRfnKRBDv6{3k@yF}nrSUv)Zsns;E;LLu%ZHQS71R@}Q`~3B lyiSSy3ZJrriAr|rpzb`|H|fj2WbtYE^sH7-kL-^J_itHiY_0$R literal 0 HcmV?d00001 From 78007b2f22f62eaf5ba18e67258557f0a9244e1f Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 24 Feb 2016 23:25:23 +0000 Subject: [PATCH 342/570] Test build all supported configurations and platforms during VSIX testing. FossilOrigin-Name: cce40a0b8ee792482fb7031113eb190ad316d01a --- manifest | 15 ++++++------- manifest.uuid | 2 +- vsixtest/vsixtest.tcl | 50 ++++++++++++++++++++++++++++--------------- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/manifest b/manifest index e9256df548..929cd10cb8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Initial\swork\son\san\sautomated\sVSIX\stesting\stool.\s\sNot\sworking\sor\stested\syet. -D 2016-02-24T21:42:03.852 +C Test\sbuild\sall\ssupported\sconfigurations\sand\splatforms\sduring\sVSIX\stesting. +D 2016-02-24T23:25:23.355 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -1446,14 +1446,11 @@ F vsixtest/Package.appxmanifest 0535b2e6708c44ad45ed7fb1dfd4de5de351dd7a F vsixtest/pch.cpp 681cc12ddc215c95fe300ee8a3dde057fa2ec308 F vsixtest/pch.h 9d2475a4f6d5c921b86c8f61060b6b04421f1010 F vsixtest/vsixtest.sln 8950e044dd04a07046990d04bf77e60738e2d136 -F vsixtest/vsixtest.tcl d452077319cd94e626e37a8ea323f4e739dbc5a6 +F vsixtest/vsixtest.tcl 0f16064663d4e8362381529a4f7f675f242b7b18 F vsixtest/vsixtest.vcxproj 15407f0e35e914fecc65ed422ac08b28e52b3e4f F vsixtest/vsixtest.vcxproj.filters 443739cb985bb81620dc66f375a845b25debe116 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e721975faa0925be4029330550ff2a9666041ff7 -R 5235a7354869742aeac200c2498e03f2 -T *branch * vsixTest -T *sym-vsixTest * -T -sym-trunk * +P 496e4ac984b2548dd5f2f969cd34656b586cfcfe +R 5a3c0879fbd24c05458da7451d8d9c43 U mistachkin -Z 30aae13ef1f9c0b59510b9ed5eae30fc +Z bb333cc3788a57a462cd7d4a3c9c3a93 diff --git a/manifest.uuid b/manifest.uuid index 8ebfae5b16..a73309b7ad 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -496e4ac984b2548dd5f2f969cd34656b586cfcfe \ No newline at end of file +cce40a0b8ee792482fb7031113eb190ad316d01a \ No newline at end of file diff --git a/vsixtest/vsixtest.tcl b/vsixtest/vsixtest.tcl index 3c0a8dbf56..ae7b91bf2c 100644 --- a/vsixtest/vsixtest.tcl +++ b/vsixtest/vsixtest.tcl @@ -167,27 +167,30 @@ set installLogFileName [appendArgs \ [file rootname [file tail $fileName]] -install- [pid] .log] set buildLogFileName [appendArgs \ - [file rootname [file tail $fileName]] -build- [pid] .log] + [file rootname [file tail $fileName]] \ + -build-%configuration%-%platform%- [pid] .log] set uninstallLogFileName [appendArgs \ [file rootname [file tail $fileName]] -uninstall- [pid] .log] -set command(1) [list exec [file nativename $vsixInstaller] /quiet /norepair] -lappend command(1) [appendArgs /logFile: $installLogFileName] -lappend command(1) [file nativename $fileName] +set commands(1) [list exec [file nativename $vsixInstaller] /quiet /norepair] +lappend commands(1) [appendArgs /logFile: $installLogFileName] +lappend commands(1) [file nativename $fileName] -set command(2) [list exec [file nativename $msBuild]] -lappend command(2) [file nativename [file join $path vsixtest.sln]] -lappend command(2) /target:Rebuild /property:Configuration=Release +set commands(2) [list exec [file nativename $msBuild]] +lappend commands(2) [file nativename [file join $path vsixtest.sln]] +lappend commands(2) /target:Rebuild +lappend commands(2) /property:Configuration=%configuration% +lappend commands(2) /property:Platform=%clatform% -lappend command(2) [appendArgs \ +lappend commands(2) [appendArgs \ /logger:FileLogger,Microsoft.Build.Engine\;Logfile= \ [file nativename [file join $temporaryDirectory $buildLogFileName]] \ \;Verbosity=diagnostic] -set command(3) [list exec [file nativename $vsixInstaller] /quiet /norepair] -lappend command(3) [appendArgs /logFile: $uninstallLogFileName] -lappend command(3) [appendArgs /uninstall:SQLite.UWP.2015] +set commands(3) [list exec [file nativename $vsixInstaller] /quiet /norepair] +lappend commands(3) [appendArgs /logFile: $uninstallLogFileName] +lappend commands(3) [appendArgs /uninstall:SQLite.UWP.2015] puts stdout [appendArgs \ "Install log will be \"" [file nativename [file join \ @@ -202,14 +205,27 @@ puts stdout [appendArgs \ $temporaryDirectory $uninstallLogFileName]] "\"."] puts stdout [appendArgs \ - "First command is \"" $command(1) "\"."] + "First command is \"" $commands(1) "\"."] puts stdout [appendArgs \ - "Second command is \"" $command(2) "\"."] + "Second command is \"" $commands(2) "\"."] puts stdout [appendArgs \ - "Third command is \"" $command(3) "\"."] + "Third command is \"" $commands(3) "\"."] -# eval exec $command(1) -# eval exec $command(2) -# eval exec $command(3) +if {0} then { + # eval $commands(1) + + set platforms [list Win32 x64 ARM] + set configurations [list Debug Release] + + foreach platform $platforms { + foreach configuration $configurations { + eval [string map [list \ + %platform% $platform %configuration% \ + $configuration] $commands(2)] + } + } + + # eval $commands(3) +} From 5dad68d3c75014a1a9e9a38c1480f5f96524688e Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 24 Feb 2016 23:31:14 +0000 Subject: [PATCH 343/570] Fix typo. Improve interim debugging. FossilOrigin-Name: e0029bdf20df90abd8b81e5b08133866665b1c87 --- manifest | 12 ++++++------ manifest.uuid | 2 +- vsixtest/vsixtest.tcl | 12 +++++++++--- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 929cd10cb8..14d86ffce0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Test\sbuild\sall\ssupported\sconfigurations\sand\splatforms\sduring\sVSIX\stesting. -D 2016-02-24T23:25:23.355 +C Fix\stypo.\s\sImprove\sinterim\sdebugging. +D 2016-02-24T23:31:14.464 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -1446,11 +1446,11 @@ F vsixtest/Package.appxmanifest 0535b2e6708c44ad45ed7fb1dfd4de5de351dd7a F vsixtest/pch.cpp 681cc12ddc215c95fe300ee8a3dde057fa2ec308 F vsixtest/pch.h 9d2475a4f6d5c921b86c8f61060b6b04421f1010 F vsixtest/vsixtest.sln 8950e044dd04a07046990d04bf77e60738e2d136 -F vsixtest/vsixtest.tcl 0f16064663d4e8362381529a4f7f675f242b7b18 +F vsixtest/vsixtest.tcl e1f20568f5551ae58f395af6440a3f3b65368682 F vsixtest/vsixtest.vcxproj 15407f0e35e914fecc65ed422ac08b28e52b3e4f F vsixtest/vsixtest.vcxproj.filters 443739cb985bb81620dc66f375a845b25debe116 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 496e4ac984b2548dd5f2f969cd34656b586cfcfe -R 5a3c0879fbd24c05458da7451d8d9c43 +P cce40a0b8ee792482fb7031113eb190ad316d01a +R 599ba9dab9a4637ded30c8413d19596a U mistachkin -Z bb333cc3788a57a462cd7d4a3c9c3a93 +Z a097fb629010575b51e2f4b031c45e27 diff --git a/manifest.uuid b/manifest.uuid index a73309b7ad..32d31d334d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cce40a0b8ee792482fb7031113eb190ad316d01a \ No newline at end of file +e0029bdf20df90abd8b81e5b08133866665b1c87 \ No newline at end of file diff --git a/vsixtest/vsixtest.tcl b/vsixtest/vsixtest.tcl index ae7b91bf2c..47357c155b 100644 --- a/vsixtest/vsixtest.tcl +++ b/vsixtest/vsixtest.tcl @@ -181,7 +181,7 @@ set commands(2) [list exec [file nativename $msBuild]] lappend commands(2) [file nativename [file join $path vsixtest.sln]] lappend commands(2) /target:Rebuild lappend commands(2) /property:Configuration=%configuration% -lappend commands(2) /property:Platform=%clatform% +lappend commands(2) /property:Platform=%platform% lappend commands(2) [appendArgs \ /logger:FileLogger,Microsoft.Build.Engine\;Logfile= \ @@ -213,7 +213,7 @@ puts stdout [appendArgs \ puts stdout [appendArgs \ "Third command is \"" $commands(3) "\"."] -if {0} then { +if {1} then { # eval $commands(1) set platforms [list Win32 x64 ARM] @@ -221,9 +221,15 @@ if {0} then { foreach platform $platforms { foreach configuration $configurations { - eval [string map [list \ + puts stdout [string map [list \ %platform% $platform %configuration% \ $configuration] $commands(2)] + + if {0} then { + eval [string map [list \ + %platform% $platform %configuration% \ + $configuration] $commands(2)] + } } } From c32db469f4fc67e2decbc200af3598093093c9ec Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 25 Feb 2016 02:49:58 +0000 Subject: [PATCH 344/570] More work. Install and build steps are now tested. FossilOrigin-Name: 0ab74373bd37d48d6afa7aecb67885afcd3a85b1 --- manifest | 36 +- manifest.uuid | 2 +- vsixtest/App.xaml | 16 +- vsixtest/App.xaml.cpp | 238 +++++----- vsixtest/App.xaml.h | 54 +-- vsixtest/MainPage.xaml | 26 +- vsixtest/MainPage.xaml.cpp | 80 ++-- vsixtest/MainPage.xaml.h | 43 +- vsixtest/Package.appxmanifest | 96 ++-- vsixtest/pch.cpp | 12 +- vsixtest/pch.h | 22 +- vsixtest/vsixtest.sln | 79 ++-- vsixtest/vsixtest.tcl | 126 ++++-- ...vsixtest.vcxproj => vsixtest.vcxproj.data} | 411 +++++++++--------- vsixtest/vsixtest.vcxproj.filters | 81 +++- 15 files changed, 705 insertions(+), 617 deletions(-) rename vsixtest/{vsixtest.vcxproj => vsixtest.vcxproj.data} (67%) diff --git a/manifest b/manifest index 14d86ffce0..0207e92d3e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stypo.\s\sImprove\sinterim\sdebugging. -D 2016-02-24T23:31:14.464 +C More\swork.\s\sInstall\sand\sbuild\ssteps\sare\snow\stested. +D 2016-02-25T02:49:58.520 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -1429,9 +1429,9 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -F vsixtest/App.xaml 7af5a2a527aa5783e208c436c5227a21b1023cec -F vsixtest/App.xaml.cpp c4aaab1774e771d2b6f662cbd247fd31df087a22 -F vsixtest/App.xaml.h f723ae437a141cd496adfccae517a6011dd95dfb +F vsixtest/App.xaml b76d3b48860e7454775c47ea38ffea9c4abe3e85 +F vsixtest/App.xaml.cpp c465147f50871165c60ca16955219f6c5812d6d8 +F vsixtest/App.xaml.h 4a9768e2983d05600ad1e1c2f1b00a132967da9f F vsixtest/Assets/LockScreenLogo.scale-200.png e820c9a3deb909197081b0bf3216c06e13905f0a F vsixtest/Assets/SplashScreen.scale-200.png cab70988ca71bebec7bfeb3b6dbafe17b9ab0b4a F vsixtest/Assets/Square150x150Logo.scale-200.png e17b40817db7a239fc239d83efcc951fb824e3ff @@ -1439,18 +1439,18 @@ F vsixtest/Assets/Square44x44Logo.scale-200.png 2f166237094dea94d952d10b9eeae818 F vsixtest/Assets/Square44x44Logo.targetsize-24_altform-unplated.png 5f6a6d391b95a3061ccca6e6fdd6955ede63b4ed F vsixtest/Assets/StoreLogo.png 0828b7257db74a4ecd5eeb6b7b4971f0fdc4d9d1 F vsixtest/Assets/Wide310x150Logo.scale-200.png 04ddefe5bc5f43ae12a7433f6f236ddab101ac42 -F vsixtest/MainPage.xaml b17ae614fc9aab5ee0068e16c9a3e3461d13b6d1 -F vsixtest/MainPage.xaml.cpp 66f81d6149d9a09de5c6c7846c6557cdd7a76b15 -F vsixtest/MainPage.xaml.h 5b8d65dc2b9e59e29bc0a6bca81211ff27ac830a -F vsixtest/Package.appxmanifest 0535b2e6708c44ad45ed7fb1dfd4de5de351dd7a -F vsixtest/pch.cpp 681cc12ddc215c95fe300ee8a3dde057fa2ec308 -F vsixtest/pch.h 9d2475a4f6d5c921b86c8f61060b6b04421f1010 -F vsixtest/vsixtest.sln 8950e044dd04a07046990d04bf77e60738e2d136 -F vsixtest/vsixtest.tcl e1f20568f5551ae58f395af6440a3f3b65368682 -F vsixtest/vsixtest.vcxproj 15407f0e35e914fecc65ed422ac08b28e52b3e4f -F vsixtest/vsixtest.vcxproj.filters 443739cb985bb81620dc66f375a845b25debe116 +F vsixtest/MainPage.xaml 34f49897e3ca533a7e74506ba0759b66eebce151 +F vsixtest/MainPage.xaml.cpp 7f31fc6de751b64676c0924c97a5485d950a91d7 +F vsixtest/MainPage.xaml.h cc05cca10d50a003f6c6e4448b701cdd07f52f29 +F vsixtest/Package.appxmanifest 6b6db1eb7df3a315c5d681059754d5f0e0c47a93 +F vsixtest/pch.cpp cb823cfac36f1a39a7eb0acbd7e9a0b0de8f23af +F vsixtest/pch.h 9cab7980f2ac4baa40807d8b5e52af32a21cf78c +F vsixtest/vsixtest.sln 77cadbe4e96c1fe1bf51cd77de9e9b0a12ada547 +F vsixtest/vsixtest.tcl 63aff906d5b2635ade235599a45fcc95a7e296bc +F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc w vsixtest/vsixtest.vcxproj +F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P cce40a0b8ee792482fb7031113eb190ad316d01a -R 599ba9dab9a4637ded30c8413d19596a +P e0029bdf20df90abd8b81e5b08133866665b1c87 +R fd73554594351ac51b867a9ca61df57d U mistachkin -Z a097fb629010575b51e2f4b031c45e27 +Z 85ba38141fc589bcd3be4f139cce818c diff --git a/manifest.uuid b/manifest.uuid index 32d31d334d..6408a12e3d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e0029bdf20df90abd8b81e5b08133866665b1c87 \ No newline at end of file +0ab74373bd37d48d6afa7aecb67885afcd3a85b1 \ No newline at end of file diff --git a/vsixtest/App.xaml b/vsixtest/App.xaml index 7f023fe5d7..80889024ca 100644 --- a/vsixtest/App.xaml +++ b/vsixtest/App.xaml @@ -1,8 +1,8 @@ - - - + + + diff --git a/vsixtest/App.xaml.cpp b/vsixtest/App.xaml.cpp index 5d60058f6b..da8f327fa0 100644 --- a/vsixtest/App.xaml.cpp +++ b/vsixtest/App.xaml.cpp @@ -1,120 +1,120 @@ -// -// App.xaml.cpp -// Implementation of the App class. -// - -#include "pch.h" -#include "MainPage.xaml.h" - -using namespace vsixtest; - -using namespace Platform; -using namespace Windows::ApplicationModel; -using namespace Windows::ApplicationModel::Activation; -using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Controls::Primitives; -using namespace Windows::UI::Xaml::Data; -using namespace Windows::UI::Xaml::Input; -using namespace Windows::UI::Xaml::Interop; -using namespace Windows::UI::Xaml::Media; -using namespace Windows::UI::Xaml::Navigation; - -/// -/// Initializes the singleton application object. This is the first line of authored code -/// executed, and as such is the logical equivalent of main() or WinMain(). -/// -App::App() -{ - InitializeComponent(); - Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending); -} - -/// -/// Invoked when the application is launched normally by the end user. Other entry points -/// will be used such as when the application is launched to open a specific file. -/// -/// Details about the launch request and process. -void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) -{ - -#if _DEBUG - // Show graphics profiling information while debugging. - if (IsDebuggerPresent()) - { - // Display the current frame rate counters - DebugSettings->EnableFrameRateCounter = true; - } -#endif - - auto rootFrame = dynamic_cast(Window::Current->Content); - - // Do not repeat app initialization when the Window already has content, - // just ensure that the window is active - if (rootFrame == nullptr) - { - // Create a Frame to act as the navigation context and associate it with - // a SuspensionManager key - rootFrame = ref new Frame(); - - rootFrame->NavigationFailed += ref new Windows::UI::Xaml::Navigation::NavigationFailedEventHandler(this, &App::OnNavigationFailed); - - if (e->PreviousExecutionState == ApplicationExecutionState::Terminated) - { - // TODO: Restore the saved session state only when appropriate, scheduling the - // final launch steps after the restore is complete - - } - - if (rootFrame->Content == nullptr) - { - // When the navigation stack isn't restored navigate to the first page, - // configuring the new page by passing required information as a navigation - // parameter - rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments); - } - // Place the frame in the current Window - Window::Current->Content = rootFrame; - // Ensure the current window is active - Window::Current->Activate(); - } - else - { - if (rootFrame->Content == nullptr) - { - // When the navigation stack isn't restored navigate to the first page, - // configuring the new page by passing required information as a navigation - // parameter - rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments); - } - // Ensure the current window is active - Window::Current->Activate(); - } -} - -/// -/// Invoked when application execution is being suspended. Application state is saved -/// without knowing whether the application will be terminated or resumed with the contents -/// of memory still intact. -/// -/// The source of the suspend request. -/// Details about the suspend request. -void App::OnSuspending(Object^ sender, SuspendingEventArgs^ e) -{ - (void) sender; // Unused parameter - (void) e; // Unused parameter - - //TODO: Save application state and stop any background activity -} - -/// -/// Invoked when Navigation to a certain page fails -/// -/// The Frame which failed navigation -/// Details about the navigation failure -void App::OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e) -{ - throw ref new FailureException("Failed to load Page " + e->SourcePageType.Name); +// +// App.xaml.cpp +// Implementation of the App class. +// + +#include "pch.h" +#include "MainPage.xaml.h" + +using namespace vsixtest; + +using namespace Platform; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Windows::UI::Xaml; +using namespace Windows::UI::Xaml::Controls; +using namespace Windows::UI::Xaml::Controls::Primitives; +using namespace Windows::UI::Xaml::Data; +using namespace Windows::UI::Xaml::Input; +using namespace Windows::UI::Xaml::Interop; +using namespace Windows::UI::Xaml::Media; +using namespace Windows::UI::Xaml::Navigation; + +/// +/// Initializes the singleton application object. This is the first line of authored code +/// executed, and as such is the logical equivalent of main() or WinMain(). +/// +App::App() +{ + InitializeComponent(); + Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending); +} + +/// +/// Invoked when the application is launched normally by the end user. Other entry points +/// will be used such as when the application is launched to open a specific file. +/// +/// Details about the launch request and process. +void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) +{ + +#if _DEBUG + // Show graphics profiling information while debugging. + if (IsDebuggerPresent()) + { + // Display the current frame rate counters + DebugSettings->EnableFrameRateCounter = true; + } +#endif + + auto rootFrame = dynamic_cast(Window::Current->Content); + + // Do not repeat app initialization when the Window already has content, + // just ensure that the window is active + if (rootFrame == nullptr) + { + // Create a Frame to act as the navigation context and associate it with + // a SuspensionManager key + rootFrame = ref new Frame(); + + rootFrame->NavigationFailed += ref new Windows::UI::Xaml::Navigation::NavigationFailedEventHandler(this, &App::OnNavigationFailed); + + if (e->PreviousExecutionState == ApplicationExecutionState::Terminated) + { + // TODO: Restore the saved session state only when appropriate, scheduling the + // final launch steps after the restore is complete + + } + + if (rootFrame->Content == nullptr) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments); + } + // Place the frame in the current Window + Window::Current->Content = rootFrame; + // Ensure the current window is active + Window::Current->Activate(); + } + else + { + if (rootFrame->Content == nullptr) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments); + } + // Ensure the current window is active + Window::Current->Activate(); + } +} + +/// +/// Invoked when application execution is being suspended. Application state is saved +/// without knowing whether the application will be terminated or resumed with the contents +/// of memory still intact. +/// +/// The source of the suspend request. +/// Details about the suspend request. +void App::OnSuspending(Object^ sender, SuspendingEventArgs^ e) +{ + (void) sender; // Unused parameter + (void) e; // Unused parameter + + //TODO: Save application state and stop any background activity +} + +/// +/// Invoked when Navigation to a certain page fails +/// +/// The Frame which failed navigation +/// Details about the navigation failure +void App::OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e) +{ + throw ref new FailureException("Failed to load Page " + e->SourcePageType.Name); } \ No newline at end of file diff --git a/vsixtest/App.xaml.h b/vsixtest/App.xaml.h index 7322d11b9c..5fa8837d38 100644 --- a/vsixtest/App.xaml.h +++ b/vsixtest/App.xaml.h @@ -1,27 +1,27 @@ -// -// App.xaml.h -// Declaration of the App class. -// - -#pragma once - -#include "App.g.h" - -namespace vsixtest -{ - /// - /// Provides application-specific behavior to supplement the default Application class. - /// - ref class App sealed - { - protected: - virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) override; - - internal: - App(); - - private: - void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ e); - void OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e); - }; -} +// +// App.xaml.h +// Declaration of the App class. +// + +#pragma once + +#include "App.g.h" + +namespace vsixtest +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + ref class App sealed + { + protected: + virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) override; + + internal: + App(); + + private: + void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ e); + void OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e); + }; +} diff --git a/vsixtest/MainPage.xaml b/vsixtest/MainPage.xaml index 76724544e1..7472ad8626 100644 --- a/vsixtest/MainPage.xaml +++ b/vsixtest/MainPage.xaml @@ -1,13 +1,13 @@ - - - - - - + + + + + + diff --git a/vsixtest/MainPage.xaml.cpp b/vsixtest/MainPage.xaml.cpp index f615f4d89e..e67dcb83b2 100644 --- a/vsixtest/MainPage.xaml.cpp +++ b/vsixtest/MainPage.xaml.cpp @@ -1,27 +1,53 @@ -// -// MainPage.xaml.cpp -// Implementation of the MainPage class. -// - -#include "pch.h" -#include "MainPage.xaml.h" - -using namespace vsixtest; - -using namespace Platform; -using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Controls::Primitives; -using namespace Windows::UI::Xaml::Data; -using namespace Windows::UI::Xaml::Input; -using namespace Windows::UI::Xaml::Media; -using namespace Windows::UI::Xaml::Navigation; - -// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 - -MainPage::MainPage() -{ - InitializeComponent(); -} +// +// MainPage.xaml.cpp +// Implementation of the MainPage class. +// + +#include "pch.h" +#include "MainPage.xaml.h" +#include "sqlite3.h" + +using namespace vsixtest; + +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Windows::UI::Xaml; +using namespace Windows::UI::Xaml::Controls; +using namespace Windows::UI::Xaml::Controls::Primitives; +using namespace Windows::UI::Xaml::Data; +using namespace Windows::UI::Xaml::Input; +using namespace Windows::UI::Xaml::Media; +using namespace Windows::UI::Xaml::Navigation; + +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 + +MainPage::MainPage() +{ + InitializeComponent(); + UseSQLite(); +} + +void MainPage::UseSQLite(void) +{ + int rc = SQLITE_OK; + sqlite3 *pDb = nullptr; + + rc = sqlite3_open_v2("test.db", &pDb, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + + if (rc != SQLITE_OK) + throw ref new FailureException("Failed to open database."); + + rc = sqlite3_exec(pDb, "VACUUM;", nullptr, nullptr, nullptr); + + if (rc != SQLITE_OK) + throw ref new FailureException("Failed to vacuum database."); + + rc = sqlite3_close(pDb); + + if (rc != SQLITE_OK) + throw ref new FailureException("Failed to close database."); + + pDb = nullptr; +} diff --git a/vsixtest/MainPage.xaml.h b/vsixtest/MainPage.xaml.h index cf95007d17..ea327a3e4c 100644 --- a/vsixtest/MainPage.xaml.h +++ b/vsixtest/MainPage.xaml.h @@ -1,21 +1,22 @@ -// -// MainPage.xaml.h -// Declaration of the MainPage class. -// - -#pragma once - -#include "MainPage.g.h" - -namespace vsixtest -{ - /// - /// An empty page that can be used on its own or navigated to within a Frame. - /// - public ref class MainPage sealed - { - public: - MainPage(); - - }; -} +// +// MainPage.xaml.h +// Declaration of the MainPage class. +// + +#pragma once + +#include "MainPage.g.h" + +namespace vsixtest +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public ref class MainPage sealed + { + public: + MainPage(); + void UseSQLite(void); + + }; +} diff --git a/vsixtest/Package.appxmanifest b/vsixtest/Package.appxmanifest index 49e45cbc3e..106b3f1e41 100644 --- a/vsixtest/Package.appxmanifest +++ b/vsixtest/Package.appxmanifest @@ -1,49 +1,49 @@ - - - - - - - - - - vsixtest - mistachkin - Assets\StoreLogo.png - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + vsixtest + mistachkin + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vsixtest/pch.cpp b/vsixtest/pch.cpp index ef288d82ad..97b544ec11 100644 --- a/vsixtest/pch.cpp +++ b/vsixtest/pch.cpp @@ -1,6 +1,6 @@ -// -// pch.cpp -// Include the standard header and generate the precompiled header. -// - -#include "pch.h" +// +// pch.cpp +// Include the standard header and generate the precompiled header. +// + +#include "pch.h" diff --git a/vsixtest/pch.h b/vsixtest/pch.h index e5006e81d3..b793236d02 100644 --- a/vsixtest/pch.h +++ b/vsixtest/pch.h @@ -1,11 +1,11 @@ -// -// pch.h -// Header for standard system include files. -// - -#pragma once - -#include -#include - -#include "App.xaml.h" +// +// pch.h +// Header for standard system include files. +// + +#pragma once + +#include +#include + +#include "App.xaml.h" diff --git a/vsixtest/vsixtest.sln b/vsixtest/vsixtest.sln index bebec6355b..1ab6e064f9 100644 --- a/vsixtest/vsixtest.sln +++ b/vsixtest/vsixtest.sln @@ -1,40 +1,39 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vsixtest", "vsixtest.vcxproj", "{60BB14A5-0871-4656-BC38-4F0958230F9A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|ARM = Release|ARM - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|ARM.ActiveCfg = Debug|ARM - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|ARM.Build.0 = Debug|ARM - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|ARM.Deploy.0 = Debug|ARM - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x64.ActiveCfg = Debug|x64 - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x64.Build.0 = Debug|x64 - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x64.Deploy.0 = Debug|x64 - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x86.ActiveCfg = Debug|Win32 - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x86.Build.0 = Debug|Win32 - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x86.Deploy.0 = Debug|Win32 - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|ARM.ActiveCfg = Release|ARM - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|ARM.Build.0 = Release|ARM - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|ARM.Deploy.0 = Release|ARM - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x64.ActiveCfg = Release|x64 - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x64.Build.0 = Release|x64 - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x64.Deploy.0 = Release|x64 - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x86.ActiveCfg = Release|Win32 - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x86.Build.0 = Release|Win32 - {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x86.Deploy.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vsixtest", "vsixtest.vcxproj", "{60BB14A5-0871-4656-BC38-4F0958230F9A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|ARM.ActiveCfg = Debug|ARM + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|ARM.Build.0 = Debug|ARM + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|ARM.Deploy.0 = Debug|ARM + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x64.ActiveCfg = Debug|x64 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x64.Build.0 = Debug|x64 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x64.Deploy.0 = Debug|x64 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x86.ActiveCfg = Debug|Win32 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x86.Build.0 = Debug|Win32 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Debug|x86.Deploy.0 = Debug|Win32 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|ARM.ActiveCfg = Release|ARM + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|ARM.Build.0 = Release|ARM + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|ARM.Deploy.0 = Release|ARM + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x64.ActiveCfg = Release|x64 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x64.Build.0 = Release|x64 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x64.Deploy.0 = Release|x64 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x86.ActiveCfg = Release|Win32 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x86.Build.0 = Release|Win32 + {60BB14A5-0871-4656-BC38-4F0958230F9A}.Release|x86.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vsixtest/vsixtest.tcl b/vsixtest/vsixtest.tcl index 47357c155b..d25c51d9b6 100644 --- a/vsixtest/vsixtest.tcl +++ b/vsixtest/vsixtest.tcl @@ -13,10 +13,14 @@ # file. However, currently, the file must be compatible with both Visual # Studio 2015 and the Universal Windows Platform. # -# 3. The temporary directory specified in the TEMP or TMP environment variables +# 3. The "VERSION" file is assumed to exist in the parent directory of the +# directory containing this script. It must contain a version number that +# matches the VSIX file being tested. +# +# 4. The temporary directory specified in the TEMP or TMP environment variables # must refer to an existing directory writable by the current user. # -# 4. The VS140COMNTOOLS environment variable must refer to the Visual Studio +# 5. The VS140COMNTOOLS environment variable must refer to the Visual Studio # 2015 common tools directory. # # USAGE @@ -80,6 +84,35 @@ proc appendArgs { args } { eval append result $args } +proc readFile { fileName } { + # + # NOTE: Reads and returns the entire contents of the specified file, which + # may contain binary data. + # + set file_id [open $fileName RDONLY] + fconfigure $file_id -encoding binary -translation binary + set result [read $file_id] + close $file_id + return $result +} + +proc writeFile { fileName data } { + # + # NOTE: Writes the entire contents of the specified file, which may contain + # binary data. + # + set file_id [open $fileName {WRONLY CREAT TRUNC}] + fconfigure $file_id -encoding binary -translation binary + puts -nonewline $file_id $data + close $file_id + return "" +} + +proc putsAndEval { command } { + catch {puts stdout $command} + return [uplevel 1 $command] +} + # # NOTE: This is the entry point for this script. # @@ -100,17 +133,32 @@ set argc [llength $argv] if {$argc > 1} then {fail} if {$argc == 1} then { - set fileName [lindex $argv 0] + set vsixFileName [lindex $argv 0] } else { - set fileName [file join [file dirname $path] sqlite-UWP-output.vsix] + set vsixFileName [file join [file dirname $path] sqlite-UWP-output.vsix] } -if {[string length $fileName] == 0} then { +if {[string length $vsixFileName] == 0} then { fail "invalid VSIX file name" } -if {![file exists $fileName] || ![file isfile $fileName]} then { - fail [appendArgs "VSIX file \"" $fileName "\" does not exist"] +if {![file exists $vsixFileName] || ![file isfile $vsixFileName]} then { + fail [appendArgs "VSIX file \"" $vsixFileName "\" does not exist"] +} + +set versionFileName [file join [file dirname $path] VERSION] + +if {![file exists $versionFileName] || ![file isfile $versionFileName]} then { + fail [appendArgs "Version file \"" $versionFileName "\" does not exist"] +} + +set projectTemplateFileName [file join $path vsixtest.vcxproj.data] +set projectFileName [file join $path vsixtest.vcxproj] + +if {![file exists $projectTemplateFileName] || \ + ![file isfile $projectTemplateFileName]} then { + fail [appendArgs \ + "Project template file \"" $projectTemplateFileName "\" does not exist"] } set envVarName VS140COMNTOOLS @@ -164,18 +212,18 @@ if {[string length $temporaryDirectory] == 0 || \ } set installLogFileName [appendArgs \ - [file rootname [file tail $fileName]] -install- [pid] .log] + [file rootname [file tail $vsixFileName]] -install- [pid] .log] set buildLogFileName [appendArgs \ - [file rootname [file tail $fileName]] \ + [file rootname [file tail $vsixFileName]] \ -build-%configuration%-%platform%- [pid] .log] set uninstallLogFileName [appendArgs \ - [file rootname [file tail $fileName]] -uninstall- [pid] .log] + [file rootname [file tail $vsixFileName]] -uninstall- [pid] .log] set commands(1) [list exec [file nativename $vsixInstaller] /quiet /norepair] lappend commands(1) [appendArgs /logFile: $installLogFileName] -lappend commands(1) [file nativename $fileName] +lappend commands(1) [file nativename $vsixFileName] set commands(2) [list exec [file nativename $msBuild]] lappend commands(2) [file nativename [file join $path vsixtest.sln]] @@ -192,46 +240,42 @@ set commands(3) [list exec [file nativename $vsixInstaller] /quiet /norepair] lappend commands(3) [appendArgs /logFile: $uninstallLogFileName] lappend commands(3) [appendArgs /uninstall:SQLite.UWP.2015] -puts stdout [appendArgs \ - "Install log will be \"" [file nativename [file join \ - $temporaryDirectory $installLogFileName]] "\"."] - -puts stdout [appendArgs \ - "Build log will be \"" [file nativename [file join \ - $temporaryDirectory $buildLogFileName]] "\"."] - -puts stdout [appendArgs \ - "Uninstall log will be \"" [file nativename [file join \ - $temporaryDirectory $uninstallLogFileName]] "\"."] - -puts stdout [appendArgs \ - "First command is \"" $commands(1) "\"."] - -puts stdout [appendArgs \ - "Second command is \"" $commands(2) "\"."] - -puts stdout [appendArgs \ - "Third command is \"" $commands(3) "\"."] +############################################################################### if {1} then { - # eval $commands(1) + puts stdout [appendArgs \ + "Install log will be \"" [file nativename [file join \ + $temporaryDirectory $installLogFileName]] "\"."] - set platforms [list Win32 x64 ARM] + puts stdout [appendArgs \ + "Build log will be \"" [file nativename [file join \ + $temporaryDirectory $buildLogFileName]] "\"."] + + puts stdout [appendArgs \ + "Uninstall log will be \"" [file nativename [file join \ + $temporaryDirectory $uninstallLogFileName]] "\"."] +} + +############################################################################### + +if {1} then { + # putsAndEval $commands(1) + + set versionNumber [string trim [readFile $versionFileName]] + set data [readFile $projectTemplateFileName] + set data [string map [list %versionNumber% $versionNumber] $data] + writeFile $projectFileName $data + + set platforms [list x86 x64 ARM] set configurations [list Debug Release] foreach platform $platforms { foreach configuration $configurations { - puts stdout [string map [list \ + putsAndEval [string map [list \ %platform% $platform %configuration% \ $configuration] $commands(2)] - - if {0} then { - eval [string map [list \ - %platform% $platform %configuration% \ - $configuration] $commands(2)] - } } } - # eval $commands(3) + # putsAndEval $commands(3) } diff --git a/vsixtest/vsixtest.vcxproj b/vsixtest/vsixtest.vcxproj.data similarity index 67% rename from vsixtest/vsixtest.vcxproj rename to vsixtest/vsixtest.vcxproj.data index a7b4fd302b..a64584c3a2 100644 --- a/vsixtest/vsixtest.vcxproj +++ b/vsixtest/vsixtest.vcxproj.data @@ -1,213 +1,198 @@ - - - - {60bb14a5-0871-4656-bc38-4f0958230f9a} - vsixtest - en-US - 14.0 - true - Windows Store - 10.0.10586.0 - 10.0.10586.0 - 10.0 - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - Application - true - v140 - - - Application - true - v140 - - - Application - true - v140 - - - Application - false - true - v140 - true - - - Application - false - true - v140 - true - - - Application - false - true - v140 - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - vsixtest_TemporaryKey.pfx - - - - - - /bigobj %(AdditionalOptions) - 4453;28204 - - - - - /bigobj %(AdditionalOptions) - 4453;28204 - - - - - /bigobj %(AdditionalOptions) - 4453;28204 - - - - - /bigobj %(AdditionalOptions) - 4453;28204 - - - - - /bigobj %(AdditionalOptions) - 4453;28204 - - - - - /bigobj %(AdditionalOptions) - 4453;28204 - - - - - - - App.xaml - - - MainPage.xaml - - - - - - Designer - - - Designer - - - - - - Designer - - - - - - - - - - - - - - - - - - - App.xaml - - - MainPage.xaml - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - + + + + {60bb14a5-0871-4656-bc38-4f0958230f9a} + vsixtest + en-US + 14.0 + true + Windows Store + 10.0.10586.0 + 10.0.10586.0 + 10.0 + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + Application + true + v140 + + + Application + true + v140 + + + Application + true + v140 + + + Application + false + true + v140 + true + + + Application + false + true + v140 + true + + + Application + false + true + v140 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vsixtest_TemporaryKey.pfx + + + + /bigobj %(AdditionalOptions) + 4453;28204 + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + + + + + + App.xaml + + + MainPage.xaml + + + + + Designer + + + Designer + + + + + Designer + + + + + + + + + + + + + + + App.xaml + + + MainPage.xaml + + + Create + Create + Create + Create + Create + Create + + + + + + + + + \ No newline at end of file diff --git a/vsixtest/vsixtest.vcxproj.filters b/vsixtest/vsixtest.vcxproj.filters index a4a1a305a8..ac1dfca421 100644 --- a/vsixtest/vsixtest.vcxproj.filters +++ b/vsixtest/vsixtest.vcxproj.filters @@ -1,24 +1,57 @@ - - - - - 60bb14a5-0871-4656-bc38-4f0958230f9a - - - e6271362-8f96-476d-907f-4da227b02435 - bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png - - - Assets - - - Assets - - - Assets - - - Assets - - - + + + + + 60bb14a5-0871-4656-bc38-4f0958230f9a + + + e6271362-8f96-476d-907f-4da227b02435 + bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + + + + + + + + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + + + + + + + + \ No newline at end of file From 6ae4d84fdfbe4168ec6e15e4995d78dc31d2f90a Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 25 Feb 2016 02:56:53 +0000 Subject: [PATCH 345/570] Enable all steps and add/update comments. FossilOrigin-Name: 788f99f47f40be42f30d3f324983f39e84d8cfbb --- manifest | 14 +++++++------- manifest.uuid | 2 +- vsixtest/vsixtest.tcl | 16 +++++++++------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 0207e92d3e..dd58c45981 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C More\swork.\s\sInstall\sand\sbuild\ssteps\sare\snow\stested. -D 2016-02-25T02:49:58.520 +C Enable\sall\ssteps\sand\sadd/update\scomments. +D 2016-02-25T02:56:53.408 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -1446,11 +1446,11 @@ F vsixtest/Package.appxmanifest 6b6db1eb7df3a315c5d681059754d5f0e0c47a93 F vsixtest/pch.cpp cb823cfac36f1a39a7eb0acbd7e9a0b0de8f23af F vsixtest/pch.h 9cab7980f2ac4baa40807d8b5e52af32a21cf78c F vsixtest/vsixtest.sln 77cadbe4e96c1fe1bf51cd77de9e9b0a12ada547 -F vsixtest/vsixtest.tcl 63aff906d5b2635ade235599a45fcc95a7e296bc -F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc w vsixtest/vsixtest.vcxproj +F vsixtest/vsixtest.tcl b80b4e1f007448d382e4a0d4f3751dba0fc47ba9 +F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e0029bdf20df90abd8b81e5b08133866665b1c87 -R fd73554594351ac51b867a9ca61df57d +P 0ab74373bd37d48d6afa7aecb67885afcd3a85b1 +R ba41dee91dbb0324b1abb0791f91a36f U mistachkin -Z 85ba38141fc589bcd3be4f139cce818c +Z c3b39230971278db58f1c6301bccf9b2 diff --git a/manifest.uuid b/manifest.uuid index 6408a12e3d..c103aecccb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0ab74373bd37d48d6afa7aecb67885afcd3a85b1 \ No newline at end of file +788f99f47f40be42f30d3f324983f39e84d8cfbb \ No newline at end of file diff --git a/vsixtest/vsixtest.tcl b/vsixtest/vsixtest.tcl index d25c51d9b6..7c30e579cf 100644 --- a/vsixtest/vsixtest.tcl +++ b/vsixtest/vsixtest.tcl @@ -5,22 +5,24 @@ # # PREREQUISITES # -# 1. Tcl 8.4 and later are supported, earlier versions have not been tested. +# 1. This tool must be executed with "elevated administrator" privileges. # -# 2. The "sqlite-UWP-output.vsix" file is assumed to exist in the parent +# 2. Tcl 8.4 and later are supported, earlier versions have not been tested. +# +# 3. The "sqlite-UWP-output.vsix" file is assumed to exist in the parent # directory of the directory containing this script. The [optional] first # command line argument to this script may be used to specify an alternate # file. However, currently, the file must be compatible with both Visual # Studio 2015 and the Universal Windows Platform. # -# 3. The "VERSION" file is assumed to exist in the parent directory of the +# 4. The "VERSION" file is assumed to exist in the parent directory of the # directory containing this script. It must contain a version number that # matches the VSIX file being tested. # -# 4. The temporary directory specified in the TEMP or TMP environment variables +# 5. The temporary directory specified in the TEMP or TMP environment variables # must refer to an existing directory writable by the current user. # -# 5. The VS140COMNTOOLS environment variable must refer to the Visual Studio +# 6. The VS140COMNTOOLS environment variable must refer to the Visual Studio # 2015 common tools directory. # # USAGE @@ -259,7 +261,7 @@ if {1} then { ############################################################################### if {1} then { - # putsAndEval $commands(1) + putsAndEval $commands(1) set versionNumber [string trim [readFile $versionFileName]] set data [readFile $projectTemplateFileName] @@ -277,5 +279,5 @@ if {1} then { } } - # putsAndEval $commands(3) + putsAndEval $commands(3) } From 77b7e2afb1ced6604a561826366908afe695d076 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 25 Feb 2016 08:02:16 +0000 Subject: [PATCH 346/570] Improve readability and logging of the vsixtest script. FossilOrigin-Name: 4fe7c4e90b7adbb1630b4aa15709968a1fcc7d83 --- manifest | 12 +-- manifest.uuid | 2 +- vsixtest/vsixtest.tcl | 176 ++++++++++++++++++++++++++---------------- 3 files changed, 116 insertions(+), 74 deletions(-) diff --git a/manifest b/manifest index dd58c45981..d0f724c2b1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enable\sall\ssteps\sand\sadd/update\scomments. -D 2016-02-25T02:56:53.408 +C Improve\sreadability\sand\slogging\sof\sthe\svsixtest\sscript. +D 2016-02-25T08:02:16.943 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -1446,11 +1446,11 @@ F vsixtest/Package.appxmanifest 6b6db1eb7df3a315c5d681059754d5f0e0c47a93 F vsixtest/pch.cpp cb823cfac36f1a39a7eb0acbd7e9a0b0de8f23af F vsixtest/pch.h 9cab7980f2ac4baa40807d8b5e52af32a21cf78c F vsixtest/vsixtest.sln 77cadbe4e96c1fe1bf51cd77de9e9b0a12ada547 -F vsixtest/vsixtest.tcl b80b4e1f007448d382e4a0d4f3751dba0fc47ba9 +F vsixtest/vsixtest.tcl 41268d1a0937c517f3c2e3f6538c90da70d155f8 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0ab74373bd37d48d6afa7aecb67885afcd3a85b1 -R ba41dee91dbb0324b1abb0791f91a36f +P 788f99f47f40be42f30d3f324983f39e84d8cfbb +R 27bc664c4897fa05fbab9ef38c37f4b7 U mistachkin -Z c3b39230971278db58f1c6301bccf9b2 +Z e145e455c738e58b5464d9cf81ba3318 diff --git a/manifest.uuid b/manifest.uuid index c103aecccb..0838b3b9ba 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -788f99f47f40be42f30d3f324983f39e84d8cfbb \ No newline at end of file +4fe7c4e90b7adbb1630b4aa15709968a1fcc7d83 \ No newline at end of file diff --git a/vsixtest/vsixtest.tcl b/vsixtest/vsixtest.tcl index 7c30e579cf..999c859776 100644 --- a/vsixtest/vsixtest.tcl +++ b/vsixtest/vsixtest.tcl @@ -80,8 +80,8 @@ proc getTemporaryPath {} { proc appendArgs { args } { # - # NOTE: Returns all passed arguments joined together as a single string with - # no intervening spaces between arguments. + # NOTE: Returns all passed arguments joined together as a single string + # with no intervening spaces between arguments. # eval append result $args } @@ -111,10 +111,43 @@ proc writeFile { fileName data } { } proc putsAndEval { command } { - catch {puts stdout $command} + # + # NOTE: Outputs a command to the standard output channel and then evaluates + # it in the callers context. + # + catch { + puts stdout [appendArgs "Running: " [lrange $command 1 end] ...\n] + } + return [uplevel 1 $command] } +proc isBadDirectory { directory } { + # + # NOTE: Returns non-zero if the directory is empty, does not exist, -OR- is + # not a directory. + # + catch { + puts stdout [appendArgs "Checking directory \"" $directory \"...\n] + } + + return [expr {[string length $directory] == 0 || \ + ![file exists $directory] || ![file isdirectory $directory]}] +} + +proc isBadFile { fileName } { + # + # NOTE: Returns non-zero if the file name is empty, does not exist, -OR- is + # not a regular file. + # + catch { + puts stdout [appendArgs "Checking file \"" $fileName \"...\n] + } + + return [expr {[string length $fileName] == 0 || \ + ![file exists $fileName] || ![file isfile $fileName]}] +} + # # NOTE: This is the entry point for this script. # @@ -124,62 +157,52 @@ if {[string length $script] == 0} then { fail "script file currently being evaluated is unknown" true } -set path [file dirname $script] - -############################################################################### - -# -# NOTE: Process and verify all the command line arguments. -# -set argc [llength $argv] -if {$argc > 1} then {fail} +set path [file normalize [file dirname $script]] +set argc [llength $argv]; if {$argc > 1} then {fail "" true} if {$argc == 1} then { set vsixFileName [lindex $argv 0] } else { - set vsixFileName [file join [file dirname $path] sqlite-UWP-output.vsix] + set vsixFileName [file join \ + [file dirname $path] sqlite-UWP-output.vsix] } -if {[string length $vsixFileName] == 0} then { - fail "invalid VSIX file name" -} +############################################################################### -if {![file exists $vsixFileName] || ![file isfile $vsixFileName]} then { - fail [appendArgs "VSIX file \"" $vsixFileName "\" does not exist"] +if {[isBadFile $vsixFileName]} then { + fail [appendArgs \ + "VSIX file \"" $vsixFileName "\" does not exist"] } set versionFileName [file join [file dirname $path] VERSION] -if {![file exists $versionFileName] || ![file isfile $versionFileName]} then { - fail [appendArgs "Version file \"" $versionFileName "\" does not exist"] +if {[isBadFile $versionFileName]} then { + fail [appendArgs \ + "Version file \"" $versionFileName "\" does not exist"] } set projectTemplateFileName [file join $path vsixtest.vcxproj.data] -set projectFileName [file join $path vsixtest.vcxproj] -if {![file exists $projectTemplateFileName] || \ - ![file isfile $projectTemplateFileName]} then { +if {[isBadFile $projectTemplateFileName]} then { fail [appendArgs \ - "Project template file \"" $projectTemplateFileName "\" does not exist"] + "Project template file \"" $projectTemplateFileName \ + "\" does not exist"] } set envVarName VS140COMNTOOLS set vsDirectory [getEnvironmentVariable $envVarName] -if {[string length $vsDirectory] == 0} then { - fail [appendArgs \ - "Visual Studio 2015 environment variable \"" $envVarName "\" missing"] -} - -if {![file exists $vsDirectory] || ![file isdirectory $vsDirectory]} then { +if {[isBadDirectory $vsDirectory]} then { fail [appendArgs \ "Visual Studio 2015 directory \"" $vsDirectory \ + "\" from environment variable \"" $envVarName \ "\" does not exist"] } -set vsixInstaller [file join [file dirname $vsDirectory] IDE VSIXInstaller.exe] +set vsixInstaller [file join \ + [file dirname $vsDirectory] IDE VSIXInstaller.exe] -if {![file exists $vsixInstaller] || ![file isfile $vsixInstaller]} then { +if {[isBadFile $vsixInstaller]} then { fail [appendArgs \ "Visual Studio 2015 VSIX installer \"" $vsixInstaller \ "\" does not exist"] @@ -188,46 +211,49 @@ if {![file exists $vsixInstaller] || ![file isfile $vsixInstaller]} then { set envVarName ProgramFiles set programFiles [getEnvironmentVariable $envVarName] -if {[string length $programFiles] == 0} then { +if {[isBadDirectory $programFiles]} then { fail [appendArgs \ - "Windows environment variable \"" $envVarName "\" missing"] -} - -if {![file exists $programFiles] || ![file isdirectory $programFiles]} then { - fail [appendArgs \ - "Program Files directory \"" $programFiles "\" does not exist"] + "Program Files directory \"" $programFiles \ + "\" from environment variable \"" $envVarName \ + "\" does not exist"] } set msBuild [file join $programFiles MSBuild 14.0 Bin MSBuild.exe] -if {![file exists $msBuild] || ![file isfile $msBuild]} then { +if {[isBadFile $msBuild]} then { fail [appendArgs \ - "MSBuild 14.0 executable file \"" $msBuild "\" does not exist"] + "MSBuild v14.0 executable file \"" $msBuild \ + "\" does not exist"] } set temporaryDirectory [getTemporaryPath] -if {[string length $temporaryDirectory] == 0 || \ - ![file exists $temporaryDirectory] || \ - ![file isdirectory $temporaryDirectory]} then { - fail "cannot locate a usable temporary directory" +if {[isBadDirectory $temporaryDirectory]} then { + fail [appendArgs \ + "Temporary directory \"" $temporaryDirectory \ + "\" does not exist"] } +############################################################################### + set installLogFileName [appendArgs \ - [file rootname [file tail $vsixFileName]] -install- [pid] .log] + [file rootname [file tail $vsixFileName]] \ + -install- [pid] .log] + +set commands(1) [list exec [file nativename $vsixInstaller]] + +lappend commands(1) /quiet /norepair +lappend commands(1) [appendArgs /logFile: $installLogFileName] +lappend commands(1) [file nativename $vsixFileName] + +############################################################################### set buildLogFileName [appendArgs \ [file rootname [file tail $vsixFileName]] \ -build-%configuration%-%platform%- [pid] .log] -set uninstallLogFileName [appendArgs \ - [file rootname [file tail $vsixFileName]] -uninstall- [pid] .log] - -set commands(1) [list exec [file nativename $vsixInstaller] /quiet /norepair] -lappend commands(1) [appendArgs /logFile: $installLogFileName] -lappend commands(1) [file nativename $vsixFileName] - set commands(2) [list exec [file nativename $msBuild]] + lappend commands(2) [file nativename [file join $path vsixtest.sln]] lappend commands(2) /target:Rebuild lappend commands(2) /property:Configuration=%configuration% @@ -235,27 +261,41 @@ lappend commands(2) /property:Platform=%platform% lappend commands(2) [appendArgs \ /logger:FileLogger,Microsoft.Build.Engine\;Logfile= \ - [file nativename [file join $temporaryDirectory $buildLogFileName]] \ - \;Verbosity=diagnostic] + [file nativename [file join $temporaryDirectory \ + $buildLogFileName]] \;Verbosity=diagnostic] -set commands(3) [list exec [file nativename $vsixInstaller] /quiet /norepair] +############################################################################### + +set uninstallLogFileName [appendArgs \ + [file rootname [file tail $vsixFileName]] \ + -uninstall- [pid] .log] + +set commands(3) [list exec [file nativename $vsixInstaller]] + +lappend commands(3) /quiet /norepair lappend commands(3) [appendArgs /logFile: $uninstallLogFileName] lappend commands(3) [appendArgs /uninstall:SQLite.UWP.2015] ############################################################################### if {1} then { - puts stdout [appendArgs \ - "Install log will be \"" [file nativename [file join \ - $temporaryDirectory $installLogFileName]] "\"."] + catch { + puts stdout [appendArgs \ + "Install log: \"" [file nativename [file join \ + $temporaryDirectory $installLogFileName]] \"\n] + } - puts stdout [appendArgs \ - "Build log will be \"" [file nativename [file join \ - $temporaryDirectory $buildLogFileName]] "\"."] + catch { + puts stdout [appendArgs \ + "Build logs: \"" [file nativename [file join \ + $temporaryDirectory $buildLogFileName]] \"\n] + } - puts stdout [appendArgs \ - "Uninstall log will be \"" [file nativename [file join \ - $temporaryDirectory $uninstallLogFileName]] "\"."] + catch { + puts stdout [appendArgs \ + "Uninstall log: \"" [file nativename [file join \ + $temporaryDirectory $uninstallLogFileName]] \"\n] + } } ############################################################################### @@ -266,6 +306,8 @@ if {1} then { set versionNumber [string trim [readFile $versionFileName]] set data [readFile $projectTemplateFileName] set data [string map [list %versionNumber% $versionNumber] $data] + + set projectFileName [file join $path vsixtest.vcxproj] writeFile $projectFileName $data set platforms [list x86 x64 ARM] @@ -274,8 +316,8 @@ if {1} then { foreach platform $platforms { foreach configuration $configurations { putsAndEval [string map [list \ - %platform% $platform %configuration% \ - $configuration] $commands(2)] + %platform% $platform %configuration% $configuration] \ + $commands(2)] } } From d8c22ac655458ce388fe7517e3ff472ce2daf603 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 25 Feb 2016 13:33:02 +0000 Subject: [PATCH 347/570] In the command-line shell: When the ".import" command is creating a new table using column names from the first row of CSV input, make sure double-quotes in the name are properly escaped. FossilOrigin-Name: 2e67a1c823c7003e7d2619c7d8b6db6ce046c527 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index a6c34eb4bb..ed34efd918 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Extend\s[3e9ed1ae]\sso\sthat\scovering\sindexes\son\sWITHOUT\sROWID\stables\sare\salso\sidentified. -D 2016-02-24T20:16:28.164 +C In\sthe\scommand-line\sshell:\s\sWhen\sthe\s".import"\scommand\sis\screating\sa\snew\ntable\susing\scolumn\snames\sfrom\sthe\sfirst\srow\sof\sCSV\sinput,\smake\ssure\s\ndouble-quotes\sin\sthe\sname\sare\sproperly\sescaped. +D 2016-02-25T13:33:02.701 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -350,7 +350,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 1a7e23a3bb2edb9cdc46ab0cf7c1500109cf2531 -F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe +F src/shell.c 89b73e894e737cc2f21e4bce0feb3ea21cc61124 F src/sqlite.h.in a7caa805a345d6a14136c11ccfa6f4c1a6ef6e7b F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d @@ -1429,7 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 56f62e34ae9d5c7db07367f0007df258b2e76bd2 -R baac3e94ca81a0031c96821cb1862aed -U dan -Z 255768a198e66c588af8c08668af4632 +P e721975faa0925be4029330550ff2a9666041ff7 +R c8d6b90bca6c11dea1a586d1afdb957c +U drh +Z 8dad8d5c86c3c0b275d53a26a0713023 diff --git a/manifest.uuid b/manifest.uuid index 56555f4bc2..6f30a6f925 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e721975faa0925be4029330550ff2a9666041ff7 \ No newline at end of file +2e67a1c823c7003e7d2619c7d8b6db6ce046c527 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 85e36a88df..95b75fa877 100644 --- a/src/shell.c +++ b/src/shell.c @@ -3171,7 +3171,7 @@ static int do_meta_command(char *zLine, ShellState *p){ char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable); char cSep = '('; while( xRead(&sCtx) ){ - zCreate = sqlite3_mprintf("%z%c\n \"%s\" TEXT", zCreate, cSep, sCtx.z); + zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z); cSep = ','; if( sCtx.cTerm!=sCtx.cColSep ) break; } From c3489bbf77cf206fdb7d6ffbffe2e3ce6b680c13 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 25 Feb 2016 16:04:59 +0000 Subject: [PATCH 348/570] Take the LIMIT clause into account when estimating the cost of sorting. FossilOrigin-Name: d491745cab951e0de70f1f79b7640ea8aff6e8bb --- manifest | 23 +++++++++++++---------- manifest.uuid | 2 +- src/select.c | 35 +++++++++++++++++++++-------------- src/sqliteInt.h | 42 ++++++++++++++++++++++-------------------- src/treeview.c | 5 +++-- src/where.c | 44 ++++++++++++++++++++++++++++++++------------ src/whereInt.h | 1 + 7 files changed, 93 insertions(+), 59 deletions(-) diff --git a/manifest b/manifest index ed34efd918..d1fca82070 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\scommand-line\sshell:\s\sWhen\sthe\s".import"\scommand\sis\screating\sa\snew\ntable\susing\scolumn\snames\sfrom\sthe\sfirst\srow\sof\sCSV\sinput,\smake\ssure\s\ndouble-quotes\sin\sthe\sname\sare\sproperly\sescaped. -D 2016-02-25T13:33:02.701 +C Take\sthe\sLIMIT\sclause\sinto\saccount\swhen\sestimating\sthe\scost\sof\ssorting. +D 2016-02-25T16:04:59.636 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -349,12 +349,12 @@ F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e -F src/select.c 1a7e23a3bb2edb9cdc46ab0cf7c1500109cf2531 +F src/select.c dbc73a63bee99bf7cfac6052477ffc21e899bb08 F src/shell.c 89b73e894e737cc2f21e4bce0feb3ea21cc61124 F src/sqlite.h.in a7caa805a345d6a14136c11ccfa6f4c1a6ef6e7b F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 5200682fc1050f00fba07128c0facc37462c4411 +F src/sqliteInt.h 5a87bccd05996f4c3facd8f831cf92a05b818b6f F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -408,7 +408,7 @@ F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 3d338cdd00d916ce8a05c397001d64ed58e6fe1c -F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b +F src/treeview.c c525282442111b3f61eb176784567cd6654db5dc F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c @@ -428,8 +428,8 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c 5b67fb8035ae4697cf721db095f800ef8dff5f56 -F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a +F src/where.c ba8f2cd97e5125d2423b3dffad9f77b888b9b1a8 +F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 39c1ef4598bedf1d66249334c74efd23ddd182ac F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1429,7 +1429,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e721975faa0925be4029330550ff2a9666041ff7 -R c8d6b90bca6c11dea1a586d1afdb957c +P 2e67a1c823c7003e7d2619c7d8b6db6ce046c527 +R 537d9f6aec4a86824de8d982730a8e8f +T *branch * planner-improvements +T *sym-planner-improvements * +T -sym-trunk * U drh -Z 8dad8d5c86c3c0b275d53a26a0713023 +Z 54aed3c7f721cc8ad2041b056394372f diff --git a/manifest.uuid b/manifest.uuid index 6f30a6f925..c9fb7a8620 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2e67a1c823c7003e7d2619c7d8b6db6ce046c527 \ No newline at end of file +d491745cab951e0de70f1f79b7640ea8aff6e8bb \ No newline at end of file diff --git a/src/select.c b/src/select.c index ff4d9d85c1..bde278b43c 100644 --- a/src/select.c +++ b/src/select.c @@ -105,7 +105,7 @@ Select *sqlite3SelectNew( ExprList *pGroupBy, /* the GROUP BY clause */ Expr *pHaving, /* the HAVING clause */ ExprList *pOrderBy, /* the ORDER BY clause */ - u16 selFlags, /* Flag parameters, such as SF_Distinct */ + u32 selFlags, /* Flag parameters, such as SF_Distinct */ Expr *pLimit, /* LIMIT value. NULL means not used */ Expr *pOffset /* OFFSET value. NULL means no offset */ ){ @@ -1845,8 +1845,9 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ VdbeComment((v, "LIMIT counter")); if( n==0 ){ sqlite3VdbeGoto(v, iBreak); - }else if( n>=0 && p->nSelectRow>(u64)n ){ - p->nSelectRow = n; + }else if( n>=0 && p->nSelectRow>sqlite3LogEst((u64)n) ){ + p->nSelectRow = sqlite3LogEst((u64)n); + p->selFlags |= SF_FixedLimit; } }else{ sqlite3ExprCode(pParse, p->pLimit, iLimit); @@ -2287,12 +2288,12 @@ static int multiSelect( testcase( rc!=SQLITE_OK ); pDelete = p->pPrior; p->pPrior = pPrior; - p->nSelectRow += pPrior->nSelectRow; + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); if( pPrior->pLimit && sqlite3ExprIsInteger(pPrior->pLimit, &nLimit) - && nLimit>0 && p->nSelectRow > (u64)nLimit + && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) ){ - p->nSelectRow = nLimit; + p->nSelectRow = sqlite3LogEst((u64)nLimit); } if( addr ){ sqlite3VdbeJumpHere(v, addr); @@ -2364,7 +2365,9 @@ static int multiSelect( pDelete = p->pPrior; p->pPrior = pPrior; p->pOrderBy = 0; - if( p->op==TK_UNION ) p->nSelectRow += pPrior->nSelectRow; + if( p->op==TK_UNION ){ + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); + } sqlite3ExprDelete(db, p->pLimit); p->pLimit = pLimit; p->pOffset = pOffset; @@ -3001,7 +3004,7 @@ static int multiSelectOrderBy( addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd); VdbeCoverage(v); sqlite3VdbeGoto(v, addrEofA); - p->nSelectRow += pPrior->nSelectRow; + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); } /* Generate a subroutine to run when the results from select B @@ -4987,7 +4990,7 @@ int sqlite3Select( sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); sqlite3Select(pParse, pSub, &dest); - pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow); + pItem->pTab->nRowLogEst = pSub->nSelectRow; pItem->fg.viaCoroutine = 1; pItem->regResult = dest.iSdst; sqlite3VdbeEndCoroutine(v, pItem->regReturn); @@ -5018,7 +5021,7 @@ int sqlite3Select( sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); sqlite3Select(pParse, pSub, &dest); - pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow); + pItem->pTab->nRowLogEst = pSub->nSelectRow; if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn); VdbeComment((v, "end %s", pItem->pTab->zName)); @@ -5101,7 +5104,7 @@ int sqlite3Select( /* Set the limiter. */ iEnd = sqlite3VdbeMakeLabel(v); - p->nSelectRow = LARGEST_INT64; + p->nSelectRow = 320; /* 4 billion rows */ computeLimitRegisters(pParse, p, iEnd); if( p->iLimit==0 && sSort.addrSortIndex>=0 ){ sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen); @@ -5125,10 +5128,12 @@ int sqlite3Select( if( !isAgg && pGroupBy==0 ){ /* No aggregate functions and no GROUP BY clause */ u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0); + assert( WHERE_USE_LIMIT==SF_FixedLimit ); + wctrlFlags |= p->selFlags & SF_FixedLimit; /* Begin the database scan. */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy, - p->pEList, wctrlFlags, 0); + p->pEList, wctrlFlags, p->nSelectRow); if( pWInfo==0 ) goto select_end; if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){ p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo); @@ -5188,9 +5193,11 @@ int sqlite3Select( for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){ pItem->u.x.iAlias = 0; } - if( p->nSelectRow>100 ) p->nSelectRow = 100; + assert( 66==sqlite3LogEst(100) ); + if( p->nSelectRow>66 ) p->nSelectRow = 66; }else{ - p->nSelectRow = 1; + assert( 0==sqlite3LogEst(1) ); + p->nSelectRow = 0; } /* If there is both a GROUP BY and an ORDER BY clause and they are diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 2ea5f57910..7924ed9dc8 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2442,6 +2442,7 @@ struct SrcList { #define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */ #define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */ #define WHERE_ONEPASS_MULTIROW 0x2000 /* ONEPASS is ok with multiple rows */ +#define WHERE_USE_LIMIT 0x4000 /* There is a constant LIMIT clause */ /* Allowed return values from sqlite3WhereIsDistinct() */ @@ -2520,13 +2521,13 @@ struct NameContext { struct Select { ExprList *pEList; /* The fields of the result */ u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ - u16 selFlags; /* Various SF_* values */ + LogEst nSelectRow; /* Estimated number of result rows */ + u32 selFlags; /* Various SF_* values */ int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ #if SELECTTRACE_ENABLED char zSelName[12]; /* Symbolic name of this SELECT use for debugging */ #endif int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ - u64 nSelectRow; /* Estimated number of result rows */ SrcList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ ExprList *pGroupBy; /* The GROUP BY clause */ @@ -2543,22 +2544,23 @@ struct Select { ** Allowed values for Select.selFlags. The "SF" prefix stands for ** "Select Flag". */ -#define SF_Distinct 0x0001 /* Output should be DISTINCT */ -#define SF_All 0x0002 /* Includes the ALL keyword */ -#define SF_Resolved 0x0004 /* Identifiers have been resolved */ -#define SF_Aggregate 0x0008 /* Contains aggregate functions */ -#define SF_UsesEphemeral 0x0010 /* Uses the OpenEphemeral opcode */ -#define SF_Expanded 0x0020 /* sqlite3SelectExpand() called on this */ -#define SF_HasTypeInfo 0x0040 /* FROM subqueries have Table metadata */ -#define SF_Compound 0x0080 /* Part of a compound query */ -#define SF_Values 0x0100 /* Synthesized from VALUES clause */ -#define SF_MultiValue 0x0200 /* Single VALUES term with multiple rows */ -#define SF_NestedFrom 0x0400 /* Part of a parenthesized FROM clause */ -#define SF_MaybeConvert 0x0800 /* Need convertCompoundSelectToSubquery() */ -#define SF_MinMaxAgg 0x1000 /* Aggregate containing min() or max() */ -#define SF_Recursive 0x2000 /* The recursive part of a recursive CTE */ -#define SF_Converted 0x4000 /* By convertCompoundSelectToSubquery() */ -#define SF_IncludeHidden 0x8000 /* Include hidden columns in output */ +#define SF_Distinct 0x00001 /* Output should be DISTINCT */ +#define SF_All 0x00002 /* Includes the ALL keyword */ +#define SF_Resolved 0x00004 /* Identifiers have been resolved */ +#define SF_Aggregate 0x00008 /* Contains aggregate functions */ +#define SF_UsesEphemeral 0x00010 /* Uses the OpenEphemeral opcode */ +#define SF_Expanded 0x00020 /* sqlite3SelectExpand() called on this */ +#define SF_HasTypeInfo 0x00040 /* FROM subqueries have Table metadata */ +#define SF_Compound 0x00080 /* Part of a compound query */ +#define SF_Values 0x00100 /* Synthesized from VALUES clause */ +#define SF_MultiValue 0x00200 /* Single VALUES term with multiple rows */ +#define SF_NestedFrom 0x00400 /* Part of a parenthesized FROM clause */ +#define SF_MaybeConvert 0x00800 /* Need convertCompoundSelectToSubquery() */ +#define SF_MinMaxAgg 0x01000 /* Aggregate containing min() or max() */ +#define SF_Recursive 0x02000 /* The recursive part of a recursive CTE */ +#define SF_FixedLimit 0x04000 /* nSelectRow set by a constant LIMIT */ +#define SF_Converted 0x08000 /* By convertCompoundSelectToSubquery() */ +#define SF_IncludeHidden 0x10000 /* Include hidden columns in output */ /* @@ -3489,7 +3491,7 @@ Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, void sqlite3DropIndex(Parse*, SrcList*, int); int sqlite3Select(Parse*, Select*, SelectDest*); Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, - Expr*,ExprList*,u16,Expr*,Expr*); + Expr*,ExprList*,u32,Expr*,Expr*); void sqlite3SelectDelete(sqlite3*, Select*); Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); @@ -3501,7 +3503,7 @@ void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); void sqlite3WhereEnd(WhereInfo*); -u64 sqlite3WhereOutputRowCount(WhereInfo*); +LogEst sqlite3WhereOutputRowCount(WhereInfo*); int sqlite3WhereIsDistinct(WhereInfo*); int sqlite3WhereIsOrdered(WhereInfo*); int sqlite3WhereIsSorted(WhereInfo*); diff --git a/src/treeview.c b/src/treeview.c index 2985804314..ff3b4be5aa 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -132,9 +132,10 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ sqlite3TreeViewPush(pView, 1); } do{ - sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x", + sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x nSelectRow=%d", ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), - ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags + ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags, + (int)p->nSelectRow ); if( cnt++ ) sqlite3TreeViewPop(pView); if( p->pPrior ){ diff --git a/src/where.c b/src/where.c index ca9e4a6f9d..addd50674d 100644 --- a/src/where.c +++ b/src/where.c @@ -31,8 +31,8 @@ static int whereLoopResize(sqlite3*, WhereLoop*, int); /* ** Return the estimated number of output rows from a WHERE clause */ -u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){ - return sqlite3LogEstToInt(pWInfo->nRowOut); +LogEst sqlite3WhereOutputRowCount(WhereInfo *pWInfo){ + return pWInfo->nRowOut; } /* @@ -3438,6 +3438,7 @@ static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){ ** order. */ static LogEst whereSortingCost( + WhereInfo *pWInfo, LogEst nRow, int nOrderBy, int nSorted @@ -3458,7 +3459,15 @@ static LogEst whereSortingCost( LogEst rScale, rSortCost; assert( nOrderBy>0 && 66==sqlite3LogEst(100) ); rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66; - rSortCost = nRow + estLog(nRow) + rScale + 16; + rSortCost = nRow + rScale + 16; + + /* Multiple by log(M) where M is the number of output rows. + ** Use the LIMIT for M if it is smaller */ + if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 ){ + LogEst m = sqlite3LogEst(pWInfo->iLimit); + if( m=0 && isOrdereddb; memset(&sWLB, 0, sizeof(sWLB)); @@ -4065,6 +4079,7 @@ WhereInfo *sqlite3WhereBegin( pWInfo->pResultSet = pResultSet; pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v); pWInfo->wctrlFlags = wctrlFlags; + pWInfo->iLimit = iAuxArg; pWInfo->savedNQueryLoop = pParse->nQueryLoop; assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ pMaskSet = &pWInfo->sMaskSet; @@ -4145,9 +4160,14 @@ WhereInfo *sqlite3WhereBegin( } /* Construct the WhereLoop objects */ - WHERETRACE(0xffff,("*** Optimizer Start *** (wctrlFlags: 0x%x)\n", - wctrlFlags)); #if defined(WHERETRACE_ENABLED) + if( sqlite3WhereTrace & 0xffff ){ + sqlite3DebugPrintf("*** Optimizer Start *** (wctrlFlags: 0x%x",wctrlFlags); + if( wctrlFlags & WHERE_USE_LIMIT ){ + sqlite3DebugPrintf(", limit: %d", iAuxArg); + } + sqlite3DebugPrintf(")\n"); + } if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */ int i; for(i=0; inTerm; i++){ @@ -4330,8 +4350,8 @@ WhereInfo *sqlite3WhereBegin( Index *pIx = pLoop->u.btree.pIndex; int iIndexCur; int op = OP_OpenRead; - /* iIdxCur is always set if to a positive value if ONEPASS is possible */ - assert( iIdxCur!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 ); + /* iAuxArg is always set if to a positive value if ONEPASS is possible */ + assert( iAuxArg!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 ); if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx) && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){ @@ -4341,7 +4361,7 @@ WhereInfo *sqlite3WhereBegin( op = 0; }else if( pWInfo->eOnePass!=ONEPASS_OFF ){ Index *pJ = pTabItem->pTab->pIndex; - iIndexCur = iIdxCur; + iIndexCur = iAuxArg; assert( wctrlFlags & WHERE_ONEPASS_DESIRED ); while( ALWAYS(pJ) && pJ!=pIx ){ iIndexCur++; @@ -4349,8 +4369,8 @@ WhereInfo *sqlite3WhereBegin( } op = OP_OpenWrite; pWInfo->aiCurOnePass[1] = iIndexCur; - }else if( iIdxCur && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){ - iIndexCur = iIdxCur; + }else if( iAuxArg && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){ + iIndexCur = iAuxArg; if( wctrlFlags & WHERE_REOPEN_IDX ) op = OP_ReopenIdx; }else{ iIndexCur = pParse->nTab++; diff --git a/src/whereInt.h b/src/whereInt.h index 1a189980ef..eb6ca326f5 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -412,6 +412,7 @@ struct WhereInfo { WhereLoop *pLoops; /* List of all WhereLoop objects */ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ LogEst nRowOut; /* Estimated number of output rows */ + LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */ u8 sorted; /* True if really sorted (not just grouped) */ From 87eb919d05ba5487e3df2db6d0431d7b7b9c28a2 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 25 Feb 2016 18:03:38 +0000 Subject: [PATCH 349/570] Do not use an automatic index on an outer loop that only runs once. FossilOrigin-Name: 5957e793414ff80ed01a7a67e70c3fd096a3f6e0 --- manifest | 17 +++++++---------- manifest.uuid | 2 +- src/where.c | 8 ++++++++ test/autoindex2.test | 7 ++++++- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index d1fca82070..d9b4a87ec1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Take\sthe\sLIMIT\sclause\sinto\saccount\swhen\sestimating\sthe\scost\sof\ssorting. -D 2016-02-25T16:04:59.636 +C Do\snot\suse\san\sautomatic\sindex\son\san\souter\sloop\sthat\sonly\sruns\sonce. +D 2016-02-25T18:03:38.680 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -428,7 +428,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c ba8f2cd97e5125d2423b3dffad9f77b888b9b1a8 +F src/where.c 07bf0330592acd2610d131aabe175cbada3e9710 F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 39c1ef4598bedf1d66249334c74efd23ddd182ac F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a @@ -475,7 +475,7 @@ F test/auth2.test 264c6af53cad9aba5218c68bbe18036e39007bfa F test/auth3.test 5cfa94ed90c6617c42b7ba4b133fd79678b251c7 F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7 F test/autoindex1.test 14b63a9f1e405fe6d5bfc8c8d00249c2ebaf13ea -F test/autoindex2.test af7e595c6864cc6ef5fc38d5db579a3e34940cb8 +F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972 F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf F test/autoindex5.test 96f084a5e6024ea07cace5888df3223f3ea86990 @@ -1429,10 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2e67a1c823c7003e7d2619c7d8b6db6ce046c527 -R 537d9f6aec4a86824de8d982730a8e8f -T *branch * planner-improvements -T *sym-planner-improvements * -T -sym-trunk * +P d491745cab951e0de70f1f79b7640ea8aff6e8bb +R fb78c9128e17cc39ff6d4163eb8b91e3 U drh -Z 54aed3c7f721cc8ad2041b056394372f +Z b2631495aa69546c0305d417243ff503 diff --git a/manifest.uuid b/manifest.uuid index c9fb7a8620..b4a5bbf637 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d491745cab951e0de70f1f79b7640ea8aff6e8bb \ No newline at end of file +5957e793414ff80ed01a7a67e70c3fd096a3f6e0 \ No newline at end of file diff --git a/src/where.c b/src/where.c index addd50674d..3dc3c87a09 100644 --- a/src/where.c +++ b/src/where.c @@ -3585,6 +3585,14 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue; if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue; + if( iLoop==0 + && (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 + && pParse->nQueryLoop==0 + ){ + /* Never put an automatic index in the outer loop if the query + ** is only being run once. */ + continue; + } /* At this point, pWLoop is a candidate to be the next loop. ** Compute its cost */ rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); diff --git a/test/autoindex2.test b/test/autoindex2.test index c8abdf410a..afd4a666b7 100644 --- a/test/autoindex2.test +++ b/test/autoindex2.test @@ -218,10 +218,15 @@ do_execsql_test autoindex2-120 { AND t1.did = t2.did AND t2.uid = t3.uid ORDER BY t1.ptime desc LIMIT 500; -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1x1 (ptime>?)} 0 1 1 {SEARCH TABLE t2 USING INDEX t2x0 (did=?)} 0 2 2 {SEARCH TABLE t3 USING INDEX t3x0 (uid=?)}} +} {~/AUTO/} # # ^^^--- Before being fixed, the above was using an automatic covering # on t3 and reordering the tables so that t3 was in the outer loop and # implementing the ORDER BY clause using a B-Tree. +# +# This test is sanitized data received from a user. The original unsanitized +# data and STAT4 data is found in the th3private test repository. See one of +# the th3private check-ins on 2016-02-25. The test is much more accurate when +# STAT4 data is used. finish_test From 5a6f5ede8175ff253b85925e2728ea76f8c86c9f Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 25 Feb 2016 18:22:09 +0000 Subject: [PATCH 350/570] Improvement on the previous check-in: disallow automatic indexes for any loop that is expected to run less than twice. FossilOrigin-Name: aab53a21894ba51d325fd8f8f4bb4163ece74391 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 10 ++++------ 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index d9b4a87ec1..cb1fddd357 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\suse\san\sautomatic\sindex\son\san\souter\sloop\sthat\sonly\sruns\sonce. -D 2016-02-25T18:03:38.680 +C Improvement\son\sthe\sprevious\scheck-in:\s\sdisallow\sautomatic\sindexes\sfor\sany\nloop\sthat\sis\sexpected\sto\srun\sless\sthan\stwice. +D 2016-02-25T18:22:09.962 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -428,7 +428,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c 07bf0330592acd2610d131aabe175cbada3e9710 +F src/where.c b21a2b3cee42e1db4f14c8fc5124f607e0c668c0 F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 39c1ef4598bedf1d66249334c74efd23ddd182ac F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a @@ -1429,7 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P d491745cab951e0de70f1f79b7640ea8aff6e8bb -R fb78c9128e17cc39ff6d4163eb8b91e3 +P 5957e793414ff80ed01a7a67e70c3fd096a3f6e0 +R 8a8e5a80c02a4dfa694df7d4a40dc042 U drh -Z b2631495aa69546c0305d417243ff503 +Z 5c10952be751c4b6279994eaa94bd734 diff --git a/manifest.uuid b/manifest.uuid index b4a5bbf637..27e8814012 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5957e793414ff80ed01a7a67e70c3fd096a3f6e0 \ No newline at end of file +aab53a21894ba51d325fd8f8f4bb4163ece74391 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 3dc3c87a09..a68dcf5bfc 100644 --- a/src/where.c +++ b/src/where.c @@ -3585,12 +3585,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue; if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue; - if( iLoop==0 - && (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 - && pParse->nQueryLoop==0 - ){ - /* Never put an automatic index in the outer loop if the query - ** is only being run once. */ + if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<10 ){ + /* Do not use an automatic index if the this loop is expected + ** to run less than 2 times. */ + assert( 10==sqlite3LogEst(2) ); continue; } /* At this point, pWLoop is a candidate to be the next loop. From aa9ffaba4af5949feed95660523cae0d5c30c755 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 25 Feb 2016 20:17:55 +0000 Subject: [PATCH 351/570] Disable the RESTRICT foreign key action if "PRAGMA defer_foreign_keys" is set. FossilOrigin-Name: 9ffff484bb4b67c29dda6180d7d766ad13988fe1 --- manifest | 18 ++++++++--------- manifest.uuid | 2 +- src/fkey.c | 3 +++ test/fkey6.test | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index cd7f610e12..c7fe7c9c81 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Query\splanner\simprovements:\s\sTake\sthe\sLIMIT\sinto\saccount\swhen\sestimated\sthe\ncost\sof\san\sORDER\sBY.\s\sAvoid\sautomatic\sindexes\son\squery\sloops\sthat\sare\sexpected\nto\srun\sless\sthan\stwice. -D 2016-02-25T18:40:18.408 +C Disable\sthe\sRESTRICT\sforeign\skey\saction\sif\s"PRAGMA\sdefer_foreign_keys"\sis\sset. +D 2016-02-25T20:17:55.205 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -304,7 +304,7 @@ F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b F src/delete.c 48802aa3ee6339f576d074336d3ae1b5f40e240f F src/expr.c 9adb58153f6e943b703d43e9a1f67f77b5a75721 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c 08edad1fce30f761f14b3997e89bad58f9f7f4e0 +F src/fkey.c a842533c411b9aef63a2814bbdc24f8a21e14cd8 F src/func.c 552d300265aed09eea21f68ac742a440550c0062 F src/global.c ded7b97efd16efda5062b65e857198e46c40e652 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 @@ -640,7 +640,7 @@ F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9 F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d F test/fkey5.test 5a373303f201ac03c22ba1ef17a733d3f56e611a -F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48 +F test/fkey6.test ce3c39cd4f910184f5fd4a48db6783c59956224f F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13 F test/fkey8.test 7bd1dd0174a0e29a90c62c517b9e2a410a0b345d F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749 @@ -1429,8 +1429,8 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2e67a1c823c7003e7d2619c7d8b6db6ce046c527 aab53a21894ba51d325fd8f8f4bb4163ece74391 -R 8a8e5a80c02a4dfa694df7d4a40dc042 -T +closed aab53a21894ba51d325fd8f8f4bb4163ece74391 -U drh -Z a9e5cc9fdd4504d0ecf5a0daa8c57736 +P bf46179d4484376909dce40ffcc06fecb19b3544 +Q +8fea1166016c659ece83e0045bc348f478a9ba6a +R c44565069d5be6a8f7796f6b44b6c97f +U dan +Z 38dd13c1fd26f5b1e4d5f260c4aeb7b1 diff --git a/manifest.uuid b/manifest.uuid index 6a068ab962..5cb14812a5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bf46179d4484376909dce40ffcc06fecb19b3544 \ No newline at end of file +9ffff484bb4b67c29dda6180d7d766ad13988fe1 \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index 38fd4f756b..97eba1ddd7 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -1163,6 +1163,9 @@ static Trigger *fkActionTrigger( action = pFKey->aAction[iAction]; pTrigger = pFKey->apTrigger[iAction]; + if( (db->flags & SQLITE_DeferFKs) && action==OE_Restrict ){ + return 0; + } if( action!=OE_None && !pTrigger ){ char const *zFrom; /* Name of child table */ diff --git a/test/fkey6.test b/test/fkey6.test index 6fc3de211c..45ad1ef2cc 100644 --- a/test/fkey6.test +++ b/test/fkey6.test @@ -23,6 +23,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix fkey6 ifcapable {!foreignkey} { finish_test @@ -171,5 +172,58 @@ do_execsql_test fkey6-2.6 { PRAGMA defer_foreign_keys; } {0} +#-------------------------------------------------------------------------- +# Test that defer_foreign_keys disables RESTRICT. +# +do_execsql_test 3.1 { + CREATE TABLE p2(a PRIMARY KEY, b); + CREATE TABLE c2(x, y REFERENCES p2 ON DELETE RESTRICT ON UPDATE RESTRICT); + INSERT INTO p2 VALUES(1, 'one'); + INSERT INTO p2 VALUES(2, 'two'); + INSERT INTO c2 VALUES('i', 1); +} + +do_catchsql_test 3.2.1 { + BEGIN; + UPDATE p2 SET a=a-1; +} {1 {FOREIGN KEY constraint failed}} +do_execsql_test 3.2.2 { COMMIT } + +do_execsql_test 3.2.3 { + BEGIN; + PRAGMA defer_foreign_keys = 1; + UPDATE p2 SET a=a-1; + COMMIT; +} + +do_execsql_test 3.2.4 { + BEGIN; + PRAGMA defer_foreign_keys = 1; + UPDATE p2 SET a=a-1; +} +do_catchsql_test 3.2.5 { + COMMIT; +} {1 {FOREIGN KEY constraint failed}} +do_execsql_test 3.2.6 { ROLLBACK } + +do_execsql_test 3.3.1 { + CREATE TRIGGER p2t AFTER DELETE ON p2 BEGIN + INSERT INTO p2 VALUES(old.a, 'deleted!'); + END; +} +do_catchsql_test 3.3.2 { + BEGIN; + DELETE FROM p2 WHERE a=1; +} {1 {FOREIGN KEY constraint failed}} +do_execsql_test 3.3.3 { COMMIT } + +do_execsql_test 3.3.4 { + BEGIN; + PRAGMA defer_foreign_keys = 1; + DELETE FROM p2 WHERE a=1; + COMMIT; + SELECT * FROM p2; +} {0 one 1 deleted!} + finish_test From d566c95179c41be3ae89e32636f4de428d3cdeb7 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 25 Feb 2016 21:19:03 +0000 Subject: [PATCH 352/570] Change the "PRAGMA stats" command to report size values in LogEst units. The eliminates the need for sqlite3LogEstToInt() unless non-standard compile-time options are used, so leave it out except in those cases. FossilOrigin-Name: 832c237fcbe83dd4f5a18a06acb0aeb7e2b9e712 --- manifest | 19 +++++++++---------- manifest.uuid | 2 +- src/pragma.c | 8 ++++---- src/sqliteInt.h | 4 ++++ src/util.c | 7 +++++++ 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index c7fe7c9c81..808e1297d9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Disable\sthe\sRESTRICT\sforeign\skey\saction\sif\s"PRAGMA\sdefer_foreign_keys"\sis\sset. -D 2016-02-25T20:17:55.205 +C Change\sthe\s"PRAGMA\sstats"\scommand\sto\sreport\ssize\svalues\sin\sLogEst\sunits.\nThe\seliminates\sthe\sneed\sfor\ssqlite3LogEstToInt()\sunless\snon-standard\ncompile-time\soptions\sare\sused,\sso\sleave\sit\sout\sexcept\sin\sthose\scases. +D 2016-02-25T21:19:03.487 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -342,7 +342,7 @@ F src/parse.y c3ce2c4a7cbf0b699239be6b2a945c5cb51875e2 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 -F src/pragma.c 80ee77226d0008d9188356a6cbbe6010866e1bee +F src/pragma.c d6028d23a9495a8b55f2075e3244ec9a0485e03e F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 @@ -354,7 +354,7 @@ F src/shell.c 89b73e894e737cc2f21e4bce0feb3ea21cc61124 F src/sqlite.h.in a7caa805a345d6a14136c11ccfa6f4c1a6ef6e7b F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 5a87bccd05996f4c3facd8f831cf92a05b818b6f +F src/sqliteInt.h b9ac8b9c9798f57d80a9756f86abf1dbd9424ec9 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -412,7 +412,7 @@ F src/treeview.c c525282442111b3f61eb176784567cd6654db5dc F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c -F src/util.c 38c06684c922694809ccb988a13562c16890a3d5 +F src/util.c 6ed9d7bdd3b0a30742027b6d8e8e1a9e2b14f373 F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c 87ae3a5657fefed7875f3eb30e7ababd48013d71 F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 @@ -1429,8 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P bf46179d4484376909dce40ffcc06fecb19b3544 -Q +8fea1166016c659ece83e0045bc348f478a9ba6a -R c44565069d5be6a8f7796f6b44b6c97f -U dan -Z 38dd13c1fd26f5b1e4d5f260c4aeb7b1 +P 9ffff484bb4b67c29dda6180d7d766ad13988fe1 +R 23bd8dd7478d22b4cba45c8ed3333a25 +U drh +Z bce9cf80c6d6995d2550774b29ef2e7b diff --git a/manifest.uuid b/manifest.uuid index 5cb14812a5..a4a0d9c71b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9ffff484bb4b67c29dda6180d7d766ad13988fe1 \ No newline at end of file +832c237fcbe83dd4f5a18a06acb0aeb7e2b9e712 \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index c34d5421c2..8b8f1f7bfd 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1102,14 +1102,14 @@ void sqlite3Pragma( sqlite3VdbeMultiLoad(v, 1, "ssii", pTab->zName, 0, - (int)sqlite3LogEstToInt(pTab->szTabRow), - (int)sqlite3LogEstToInt(pTab->nRowLogEst)); + pTab->szTabRow, + pTab->nRowLogEst); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ sqlite3VdbeMultiLoad(v, 2, "sii", pIdx->zName, - (int)sqlite3LogEstToInt(pIdx->szIdxRow), - (int)sqlite3LogEstToInt(pIdx->aiRowLogEst[0])); + pIdx->szIdxRow, + pIdx->aiRowLogEst[0]); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); } } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 7924ed9dc8..a62ffb6b69 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3686,7 +3686,11 @@ LogEst sqlite3LogEstAdd(LogEst,LogEst); #ifndef SQLITE_OMIT_VIRTUALTABLE LogEst sqlite3LogEstFromDouble(double); #endif +#if defined(SQLITE_ENABLE_STMT_SCANSTAT) || \ + defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \ + defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) u64 sqlite3LogEstToInt(LogEst); +#endif /* ** Routines to read and write variable-length integers. These used to diff --git a/src/util.c b/src/util.c index e325a7311b..d00a739e53 100644 --- a/src/util.c +++ b/src/util.c @@ -1400,8 +1400,14 @@ LogEst sqlite3LogEstFromDouble(double x){ } #endif /* SQLITE_OMIT_VIRTUALTABLE */ +#if defined(SQLITE_ENABLE_STMT_SCANSTAT) || \ + defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \ + defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) /* ** Convert a LogEst into an integer. +** +** Note that this routine is only used when one or more of various +** non-standard compile-time options is enabled. */ u64 sqlite3LogEstToInt(LogEst x){ u64 n; @@ -1415,3 +1421,4 @@ u64 sqlite3LogEstToInt(LogEst x){ } return (n+8)>>(3-x); } +#endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */ From 27b6649f39183010e4959685e7b5e2a011c3ffc6 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 25 Feb 2016 21:27:03 +0000 Subject: [PATCH 353/570] Change the srcck1.c utility program to use only unsigned characters. FossilOrigin-Name: d64d005eb5df2e3eb1248fc8eff8b1b683e48c74 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/srcck1.c | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 808e1297d9..c83b1eba09 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\s"PRAGMA\sstats"\scommand\sto\sreport\ssize\svalues\sin\sLogEst\sunits.\nThe\seliminates\sthe\sneed\sfor\ssqlite3LogEstToInt()\sunless\snon-standard\ncompile-time\soptions\sare\sused,\sso\sleave\sit\sout\sexcept\sin\sthose\scases. -D 2016-02-25T21:19:03.487 +C Change\sthe\ssrcck1.c\sutility\sprogram\sto\suse\sonly\sunsigned\scharacters. +D 2016-02-25T21:27:03.339 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -1418,7 +1418,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/sqldiff.c 5a26205111e6fa856d9b1535b1637744dcdb930b -F tool/srcck1.c 4c39bdfa9a92edd20233ee720df84dbeb2417602 +F tool/srcck1.c 4f65e1a6748e42f24c0ea629dddc934d821c729a F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1429,7 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9ffff484bb4b67c29dda6180d7d766ad13988fe1 -R 23bd8dd7478d22b4cba45c8ed3333a25 +P 832c237fcbe83dd4f5a18a06acb0aeb7e2b9e712 +R 0714ab3705e4d9ae10258587d2894689 U drh -Z bce9cf80c6d6995d2550774b29ef2e7b +Z 6cd1ed7303c3e6dd998ffd3867295c4f diff --git a/manifest.uuid b/manifest.uuid index a4a0d9c71b..f5d99d5c44 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -832c237fcbe83dd4f5a18a06acb0aeb7e2b9e712 \ No newline at end of file +d64d005eb5df2e3eb1248fc8eff8b1b683e48c74 \ No newline at end of file diff --git a/tool/srcck1.c b/tool/srcck1.c index e95765185f..f92610f544 100644 --- a/tool/srcck1.c +++ b/tool/srcck1.c @@ -111,11 +111,11 @@ static unsigned int findCloseParen(const char *z){ ** Print error messages whenever a side effect is found. Return the number ** of problems seen. */ -static unsigned int findAllSideEffects(const char *z){ +static unsigned int findAllSideEffects(const unsigned char *z){ unsigned int lineno = 1; /* Line number */ unsigned int i; unsigned int nErr = 0; - char c, prevC = 0; + unsigned char c, prevC = 0; for(i=0; (c = z[i])!=0; prevC=c, i++){ if( c=='\n' ){ lineno++; continue; } if( isalpha(c) && !isalpha(prevC) ){ @@ -125,7 +125,7 @@ static unsigned int findAllSideEffects(const char *z){ || strncmp(&z[i],"testcase(",9)==0 ){ unsigned int n; - const char *z2 = &z[i+5]; + unsigned const char *z2 = &z[i+5]; while( z2[0]!='(' ){ z2++; } z2++; n = findCloseParen(z2); @@ -141,7 +141,7 @@ static unsigned int findAllSideEffects(const char *z){ } int main(int argc, char **argv){ - char *z; + unsigned char *z; unsigned int nErr = 0; if( argc!=2 ){ fprintf(stderr, "Usage: %s FILENAME\n", argv[0]); From 9d970c3c9358ee0217eab620bd3a348be954deca Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 25 Feb 2016 21:38:28 +0000 Subject: [PATCH 354/570] Small optimization in FK handling. FossilOrigin-Name: e0d25913b73a813f5987aa70b364b00f19351663 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/fkey.c | 5 +++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index c83b1eba09..1b636cf075 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\ssrcck1.c\sutility\sprogram\sto\suse\sonly\sunsigned\scharacters. -D 2016-02-25T21:27:03.339 +C Small\soptimization\sin\sFK\shandling. +D 2016-02-25T21:38:28.541 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -304,7 +304,7 @@ F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b F src/delete.c 48802aa3ee6339f576d074336d3ae1b5f40e240f F src/expr.c 9adb58153f6e943b703d43e9a1f67f77b5a75721 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c a842533c411b9aef63a2814bbdc24f8a21e14cd8 +F src/fkey.c 5cb42d9a59e2a590776fd3fc8ff6f61d40df3c6e F src/func.c 552d300265aed09eea21f68ac742a440550c0062 F src/global.c ded7b97efd16efda5062b65e857198e46c40e652 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 @@ -1429,7 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 832c237fcbe83dd4f5a18a06acb0aeb7e2b9e712 -R 0714ab3705e4d9ae10258587d2894689 -U drh -Z 6cd1ed7303c3e6dd998ffd3867295c4f +P d64d005eb5df2e3eb1248fc8eff8b1b683e48c74 +R ab8765cbaf5fbfbed19ecf7263e09682 +U mistachkin +Z ff9c90565884f74ae6db48ba3f5b6f95 diff --git a/manifest.uuid b/manifest.uuid index f5d99d5c44..90985bbea9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d64d005eb5df2e3eb1248fc8eff8b1b683e48c74 \ No newline at end of file +e0d25913b73a813f5987aa70b364b00f19351663 \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index 97eba1ddd7..9a1a85fec0 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -1162,11 +1162,12 @@ static Trigger *fkActionTrigger( int iAction = (pChanges!=0); /* 1 for UPDATE, 0 for DELETE */ action = pFKey->aAction[iAction]; - pTrigger = pFKey->apTrigger[iAction]; - if( (db->flags & SQLITE_DeferFKs) && action==OE_Restrict ){ + if( action==OE_Restrict && (db->flags & SQLITE_DeferFKs) ){ return 0; } + pTrigger = pFKey->apTrigger[iAction]; + if( action!=OE_None && !pTrigger ){ char const *zFrom; /* Name of child table */ int nFrom; /* Length in bytes of zFrom */ From 8c098e61b6e9c278df73096198c44cb2d6619745 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 25 Feb 2016 23:21:41 +0000 Subject: [PATCH 355/570] Fix an incorrect cost computation for sorting (introduced just a few check-ins ago). Should be NlogN, not NloglogN. FossilOrigin-Name: 2459d3238853951bc3a507dd975e7ec921cf8446 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/where.c | 5 ++--- test/where.test | 12 +++++++++--- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 1b636cf075..0683bae1ec 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Small\soptimization\sin\sFK\shandling. -D 2016-02-25T21:38:28.541 +C Fix\san\sincorrect\scost\scomputation\sfor\ssorting\s(introduced\sjust\sa\sfew\ncheck-ins\sago).\s\sShould\sbe\sNlogN,\snot\sNloglogN. +D 2016-02-25T23:21:41.832 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -428,7 +428,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c b21a2b3cee42e1db4f14c8fc5124f607e0c668c0 +F src/where.c 32051597188dc632bafb32d50a9c3a04fb97ce39 F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 39c1ef4598bedf1d66249334c74efd23ddd182ac F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a @@ -1327,7 +1327,7 @@ F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e -F test/where.test 9902a3d84e9bc80357a2c54ed0e76c0d6d04a867 +F test/where.test c33bf57e48a34d6cc98018d779a577c2f61ff312 F test/where2.test af78c55589cbc82d793449493adba0dc3d659f23 F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8 @@ -1429,7 +1429,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P d64d005eb5df2e3eb1248fc8eff8b1b683e48c74 -R ab8765cbaf5fbfbed19ecf7263e09682 -U mistachkin -Z ff9c90565884f74ae6db48ba3f5b6f95 +P e0d25913b73a813f5987aa70b364b00f19351663 +R 8ecd868c4f09ad809b17fd8b0dd4a502 +U drh +Z 87b6be9293374710fdcde53ff54603a2 diff --git a/manifest.uuid b/manifest.uuid index 90985bbea9..59f4369738 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e0d25913b73a813f5987aa70b364b00f19351663 \ No newline at end of file +2459d3238853951bc3a507dd975e7ec921cf8446 \ No newline at end of file diff --git a/src/where.c b/src/where.c index a68dcf5bfc..71d3cb01ef 100644 --- a/src/where.c +++ b/src/where.c @@ -3463,9 +3463,8 @@ static LogEst whereSortingCost( /* Multiple by log(M) where M is the number of output rows. ** Use the LIMIT for M if it is smaller */ - if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 ){ - LogEst m = sqlite3LogEst(pWInfo->iLimit); - if( mwctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimitiLimit; } rSortCost += estLog(nRow); return rSortCost; diff --git a/test/where.test b/test/where.test index 0b5bb934d0..2b0b7dcfaf 100644 --- a/test/where.test +++ b/test/where.test @@ -573,11 +573,17 @@ do_test where-6.6 { SELECT * FROM t3 WHERE a>0 ORDER BY a LIMIT 3 } } {1 100 4 2 99 9 3 98 16 nosort} -do_test where-6.7 { +do_test where-6.7.1 { cksort { - SELECT * FROM t3 WHERE b>0 ORDER BY a LIMIT 3 + SELECT * FROM t3 WHERE b>0 ORDER BY a LIMIT 10 } -} {1 100 4 2 99 9 3 98 16 nosort} +} {/1 100 4 2 99 9 3 98 16 .* nosort/} +do_test where-6.7.2 { + cksort { + SELECT * FROM t3 WHERE b>0 ORDER BY a LIMIT 1 + } +} {1 100 4 sort} +exit ifcapable subquery { do_test where-6.8a { cksort { From 7856c1c0eb26da861787d14b7ce1d470944c0310 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 25 Feb 2016 23:22:26 +0000 Subject: [PATCH 356/570] Enhance checking of prerequisites in the vsixtest tool. FossilOrigin-Name: 799d5f09ed058898167e43bd9c8d1bf8c5df23ba --- manifest | 12 +++++------ manifest.uuid | 2 +- vsixtest/vsixtest.tcl | 46 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index d0f724c2b1..ba74fc32b8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\sreadability\sand\slogging\sof\sthe\svsixtest\sscript. -D 2016-02-25T08:02:16.943 +C Enhance\schecking\sof\sprerequisites\sin\sthe\svsixtest\stool. +D 2016-02-25T23:22:26.535 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -1446,11 +1446,11 @@ F vsixtest/Package.appxmanifest 6b6db1eb7df3a315c5d681059754d5f0e0c47a93 F vsixtest/pch.cpp cb823cfac36f1a39a7eb0acbd7e9a0b0de8f23af F vsixtest/pch.h 9cab7980f2ac4baa40807d8b5e52af32a21cf78c F vsixtest/vsixtest.sln 77cadbe4e96c1fe1bf51cd77de9e9b0a12ada547 -F vsixtest/vsixtest.tcl 41268d1a0937c517f3c2e3f6538c90da70d155f8 +F vsixtest/vsixtest.tcl 463b7aa846f8f1bdadf2aadb1ac84c34c247437c F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 788f99f47f40be42f30d3f324983f39e84d8cfbb -R 27bc664c4897fa05fbab9ef38c37f4b7 +P 4fe7c4e90b7adbb1630b4aa15709968a1fcc7d83 +R fa3049ef82e4175b0a6df31159094b76 U mistachkin -Z e145e455c738e58b5464d9cf81ba3318 +Z bc452bd15f3f1d06988b3918e97baf68 diff --git a/manifest.uuid b/manifest.uuid index 0838b3b9ba..27c4b9427d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4fe7c4e90b7adbb1630b4aa15709968a1fcc7d83 \ No newline at end of file +799d5f09ed058898167e43bd9c8d1bf8c5df23ba \ No newline at end of file diff --git a/vsixtest/vsixtest.tcl b/vsixtest/vsixtest.tcl index 999c859776..7baed3af6a 100644 --- a/vsixtest/vsixtest.tcl +++ b/vsixtest/vsixtest.tcl @@ -45,6 +45,44 @@ proc fail { {error ""} {usage false} } { exit 1 } +proc isWindows {} { + # + # NOTE: Returns non-zero only when running on Windows. + # + return [expr {[info exists ::tcl_platform(platform)] && \ + $::tcl_platform(platform) eq "windows"}] +} + +proc isAdministrator {} { + # + # NOTE: Returns non-zero only when running as "elevated administrator". + # + if {[isWindows]} then { + if {[catch {exec -- whoami /groups} groups] == 0} then { + set groups [string map [list \r\n \n] $groups] + + foreach group [split $groups \n] { + # + # NOTE: Match this group line against the "well-known" SID for + # the "Administrators" group on Windows. + # + if {[regexp -- {\sS-1-5-32-544\s} $group]} then { + # + # NOTE: Match this group line against the attributes column + # sub-value that should be present when running with + # elevated administrator credentials. + # + if {[regexp -- {\sEnabled group(?:,|\s)} $group]} then { + return true + } + } + } + } + } + + return false +} + proc getEnvironmentVariable { name } { # # NOTE: Returns the value of the specified environment variable or an empty @@ -157,6 +195,14 @@ if {[string length $script] == 0} then { fail "script file currently being evaluated is unknown" true } +if {![isWindows]} then { + fail "this tool only works properly on Windows" +} + +if {![isAdministrator]} then { + fail "this tool must run with \"elevated administrator\" privileges" +} + set path [file normalize [file dirname $script]] set argc [llength $argv]; if {$argc > 1} then {fail "" true} From 74c2f06668ad09dde5acd12b45e7f4624b21e342 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 25 Feb 2016 23:27:02 +0000 Subject: [PATCH 357/570] Add some comments in the VSIX test tool. FossilOrigin-Name: c871473ffee6dbb0f5b47f1c1329c84b902368ae --- manifest | 13 ++++++------- manifest.uuid | 2 +- vsixtest/vsixtest.tcl | 14 ++++++++------ 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 157cf92745..c46c3db9da 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stool\sfor\ssmoke-testing\sthe\sUWP\sVSIX\spackage. -D 2016-02-25T23:25:00.511 +C Add\ssome\scomments\sin\sthe\sVSIX\stest\stool. +D 2016-02-25T23:27:02.855 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -1446,12 +1446,11 @@ F vsixtest/Package.appxmanifest 6b6db1eb7df3a315c5d681059754d5f0e0c47a93 F vsixtest/pch.cpp cb823cfac36f1a39a7eb0acbd7e9a0b0de8f23af F vsixtest/pch.h 9cab7980f2ac4baa40807d8b5e52af32a21cf78c F vsixtest/vsixtest.sln 77cadbe4e96c1fe1bf51cd77de9e9b0a12ada547 -F vsixtest/vsixtest.tcl 463b7aa846f8f1bdadf2aadb1ac84c34c247437c +F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2459d3238853951bc3a507dd975e7ec921cf8446 799d5f09ed058898167e43bd9c8d1bf8c5df23ba -R a2c41dee5fc3fcec68335e2bea7b9721 -T +closed 799d5f09ed058898167e43bd9c8d1bf8c5df23ba +P d27f32c6d72182198ae6d6cf8e385be76335dc65 +R eaa06d7471a7f3afc4a0fae5257d24c3 U mistachkin -Z 00dca86db1b95b6beaa7d7daeb4c1114 +Z cdb877e6651172a6d5d6ba712087b34e diff --git a/manifest.uuid b/manifest.uuid index a1977c0d14..307808ef47 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d27f32c6d72182198ae6d6cf8e385be76335dc65 \ No newline at end of file +c871473ffee6dbb0f5b47f1c1329c84b902368ae \ No newline at end of file diff --git a/vsixtest/vsixtest.tcl b/vsixtest/vsixtest.tcl index 7baed3af6a..5dce821dc4 100644 --- a/vsixtest/vsixtest.tcl +++ b/vsixtest/vsixtest.tcl @@ -5,24 +5,26 @@ # # PREREQUISITES # -# 1. This tool must be executed with "elevated administrator" privileges. +# 1. This tool is Windows only. # -# 2. Tcl 8.4 and later are supported, earlier versions have not been tested. +# 2. This tool must be executed with "elevated administrator" privileges. # -# 3. The "sqlite-UWP-output.vsix" file is assumed to exist in the parent +# 3. Tcl 8.4 and later are supported, earlier versions have not been tested. +# +# 4. The "sqlite-UWP-output.vsix" file is assumed to exist in the parent # directory of the directory containing this script. The [optional] first # command line argument to this script may be used to specify an alternate # file. However, currently, the file must be compatible with both Visual # Studio 2015 and the Universal Windows Platform. # -# 4. The "VERSION" file is assumed to exist in the parent directory of the +# 5. The "VERSION" file is assumed to exist in the parent directory of the # directory containing this script. It must contain a version number that # matches the VSIX file being tested. # -# 5. The temporary directory specified in the TEMP or TMP environment variables +# 6. The temporary directory specified in the TEMP or TMP environment variables # must refer to an existing directory writable by the current user. # -# 6. The VS140COMNTOOLS environment variable must refer to the Visual Studio +# 7. The VS140COMNTOOLS environment variable must refer to the Visual Studio # 2015 common tools directory. # # USAGE From c9eaeef1fe3bca902c3cb32db978bb2c671e221f Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 26 Feb 2016 04:04:07 +0000 Subject: [PATCH 358/570] Remove a debuggin "exit" command mistakenly left in the "where.test" module. FossilOrigin-Name: beda0b8c76c2c7328a44156257c978cf8f5df59b --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/where.test | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index c46c3db9da..38c37f9331 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\ssome\scomments\sin\sthe\sVSIX\stest\stool. -D 2016-02-25T23:27:02.855 +C Remove\sa\sdebuggin\s"exit"\scommand\smistakenly\sleft\sin\sthe\s"where.test"\smodule. +D 2016-02-26T04:04:07.156 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -1327,7 +1327,7 @@ F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e -F test/where.test c33bf57e48a34d6cc98018d779a577c2f61ff312 +F test/where.test f0c325563acde44f2c4ea6ba348e9e29f7121757 F test/where2.test af78c55589cbc82d793449493adba0dc3d659f23 F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8 @@ -1450,7 +1450,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 d27f32c6d72182198ae6d6cf8e385be76335dc65 -R eaa06d7471a7f3afc4a0fae5257d24c3 -U mistachkin -Z cdb877e6651172a6d5d6ba712087b34e +P c871473ffee6dbb0f5b47f1c1329c84b902368ae +R 6fc01093db6658e430bdeb2c14b7bd88 +U drh +Z 4d54711e77d505069a1e93ab6ffa4de0 diff --git a/manifest.uuid b/manifest.uuid index 307808ef47..368053ee95 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c871473ffee6dbb0f5b47f1c1329c84b902368ae \ No newline at end of file +beda0b8c76c2c7328a44156257c978cf8f5df59b \ No newline at end of file diff --git a/test/where.test b/test/where.test index 2b0b7dcfaf..d4f04e8063 100644 --- a/test/where.test +++ b/test/where.test @@ -583,7 +583,6 @@ do_test where-6.7.2 { SELECT * FROM t3 WHERE b>0 ORDER BY a LIMIT 1 } } {1 100 4 sort} -exit ifcapable subquery { do_test where-6.8a { cksort { From 26bcc7cf4084151d7926f48c8d3802eb6d611f93 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 26 Feb 2016 04:13:39 +0000 Subject: [PATCH 359/570] Ephemeral tables used to hold manifested views may not be unordered since they might be subject to an ordered comparison if they are part of a join. FossilOrigin-Name: 3ef6a3153267d5328202fea24fd29ff4d5409295 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/select.c | 1 - src/vdbeInt.h | 2 +- test/misc8.test | 13 +++++++++++++ 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 38c37f9331..c74fbbede1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sa\sdebuggin\s"exit"\scommand\smistakenly\sleft\sin\sthe\s"where.test"\smodule. -D 2016-02-26T04:04:07.156 +C Ephemeral\stables\sused\sto\shold\smanifested\sviews\smay\snot\sbe\sunordered\ssince\nthey\smight\sbe\ssubject\sto\san\sordered\scomparison\sif\sthey\sare\spart\sof\sa\sjoin. +D 2016-02-26T04:13:39.081 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -349,7 +349,7 @@ F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e -F src/select.c dbc73a63bee99bf7cfac6052477ffc21e899bb08 +F src/select.c 1bacfde7b7cec134d2b354cbcf67bafc67078431 F src/shell.c 89b73e894e737cc2f21e4bce0feb3ea21cc61124 F src/sqlite.h.in a7caa805a345d6a14136c11ccfa6f4c1a6ef6e7b F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -416,7 +416,7 @@ F src/util.c 6ed9d7bdd3b0a30742027b6d8e8e1a9e2b14f373 F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c 87ae3a5657fefed7875f3eb30e7ababd48013d71 F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 -F src/vdbeInt.h 84827a809229917fdd3cc05af719dbb61314a5a3 +F src/vdbeInt.h 49a74fe5ece206d2d8666ba9afaf1abeda5f123b F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 F src/vdbeaux.c 2c15cf88de4df97428318c8cfac0dea873dae451 F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db @@ -897,7 +897,7 @@ F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3 F test/misc5.test f96428ea95b3820aafc6f1c50cf48a09e4597ee1 F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2 -F test/misc8.test fc2754d38892f7dac30c22db3616c2764f117d66 +F test/misc8.test 21ac9d35a5e110279ae9e1588b8914f54de1c60b F test/misuse.test 3c34719944ba045cc6c188a4852ba04680728912 F test/mmap1.test 44a5ff1c1bcc7dcf2de50227d1f997e75a8ef1ae F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022 @@ -1450,7 +1450,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 c871473ffee6dbb0f5b47f1c1329c84b902368ae -R 6fc01093db6658e430bdeb2c14b7bd88 +P beda0b8c76c2c7328a44156257c978cf8f5df59b +R 5d471132c02d748b5b7a9c957a1aab1e U drh -Z 4d54711e77d505069a1e93ab6ffa4de0 +Z 02d11a44d61806b13a4d06a9e5d2f12b diff --git a/manifest.uuid b/manifest.uuid index 368053ee95..18803bd46f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -beda0b8c76c2c7328a44156257c978cf8f5df59b \ No newline at end of file +3ef6a3153267d5328202fea24fd29ff4d5409295 \ No newline at end of file diff --git a/src/select.c b/src/select.c index bde278b43c..aa1f214855 100644 --- a/src/select.c +++ b/src/select.c @@ -2225,7 +2225,6 @@ static int multiSelect( if( dest.eDest==SRT_EphemTab ){ assert( p->pEList ); sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iSDParm, p->pEList->nExpr); - sqlite3VdbeChangeP5(v, BTREE_UNORDERED); dest.eDest = SRT_Table; } diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 710c725e62..b53952fd44 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -87,7 +87,7 @@ struct VdbeCursor { #endif Bool isEphemeral:1; /* True for an ephemeral table */ Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ - Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */ + Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */ Pgno pgnoRoot; /* Root page of the open btree cursor */ i16 nField; /* Number of fields in the header */ u16 nHdrParsed; /* Number of header fields parsed so far */ diff --git a/test/misc8.test b/test/misc8.test index 3ff52e56f1..3817cadf94 100644 --- a/test/misc8.test +++ b/test/misc8.test @@ -94,5 +94,18 @@ do_execsql_test misc8-2.1 { 0 10 {} 10 {} {} } +# 2016-02-26: An assertion fault found by the libFuzzer project +# +do_execsql_test misc8-3.0 { + SELECT * + FROM + ( + (SELECT 0 AS i) AS x1, + (SELECT 1) AS x2 + ) AS x3, + (SELECT 6 AS j UNION ALL SELECT 7) AS x4 + WHERE i Date: Fri, 26 Feb 2016 13:22:21 +0000 Subject: [PATCH 360/570] Fix a typo in a comment (though an important comment in that it is used to generate documentation). FossilOrigin-Name: ff3d7f845e1875d6729f64f5231db1c376892f31 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqlite.h.in | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index c74fbbede1..f3c7712c00 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Ephemeral\stables\sused\sto\shold\smanifested\sviews\smay\snot\sbe\sunordered\ssince\nthey\smight\sbe\ssubject\sto\san\sordered\scomparison\sif\sthey\sare\spart\sof\sa\sjoin. -D 2016-02-26T04:13:39.081 +C Fix\sa\stypo\sin\sa\scomment\s(though\san\simportant\scomment\sin\sthat\sit\sis\sused\s\nto\sgenerate\sdocumentation). +D 2016-02-26T13:22:21.836 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -351,7 +351,7 @@ F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 1bacfde7b7cec134d2b354cbcf67bafc67078431 F src/shell.c 89b73e894e737cc2f21e4bce0feb3ea21cc61124 -F src/sqlite.h.in a7caa805a345d6a14136c11ccfa6f4c1a6ef6e7b +F src/sqlite.h.in 42203c6bf167b8b13c4e6637cbdf8ad2cb2f8685 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d F src/sqliteInt.h b9ac8b9c9798f57d80a9756f86abf1dbd9424ec9 @@ -1450,7 +1450,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 beda0b8c76c2c7328a44156257c978cf8f5df59b -R 5d471132c02d748b5b7a9c957a1aab1e +P 3ef6a3153267d5328202fea24fd29ff4d5409295 +R 77993d5bd700ce83f039b073c94a1fa4 U drh -Z 02d11a44d61806b13a4d06a9e5d2f12b +Z 9609a7717e93d89e1b3f63c437689c08 diff --git a/manifest.uuid b/manifest.uuid index 18803bd46f..af3baca687 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3ef6a3153267d5328202fea24fd29ff4d5409295 \ No newline at end of file +ff3d7f845e1875d6729f64f5231db1c376892f31 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index dcbda15ce5..829eeb86ce 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -1228,7 +1228,7 @@ struct sqlite3_vfs { const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); /* ** The methods above are in versions 1 through 3 of the sqlite_vfs object. - ** New fields may be appended in figure versions. The iVersion + ** New fields may be appended in future versions. The iVersion ** value will increment whenever this happens. */ }; From d42908fb0e09d6ed2df334b4a5f3be6de40292e4 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 26 Feb 2016 15:38:24 +0000 Subject: [PATCH 361/570] Provide the new SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER option to sqlite3_db_config() that can be used to activate the two-argument version of fts3_tokenizer() for a specific database connection at run-time. FossilOrigin-Name: 374b5108087a2eae03676c0f3469b37a272145bf --- ext/fts3/fts3_tokenizer.c | 71 +++++++++++++++++---------------- manifest | 26 ++++++------ manifest.uuid | 2 +- src/main.c | 8 +++- src/sqlite.h.in | 20 ++++++++-- src/sqliteInt.h | 1 + src/test1.c | 48 ++++++++++++++++++++++ src/test_config.c | 6 --- test/fts3atoken.test | 83 ++++++++++++++++++++------------------- test/fts4langid.test | 47 +++++++++++----------- 10 files changed, 189 insertions(+), 123 deletions(-) diff --git a/ext/fts3/fts3_tokenizer.c b/ext/fts3/fts3_tokenizer.c index fcabe5cca2..b7d9d2b3b2 100644 --- a/ext/fts3/fts3_tokenizer.c +++ b/ext/fts3/fts3_tokenizer.c @@ -29,6 +29,18 @@ #include #include +/* +** Return true if the two-argument version of fts3_tokenizer() +** has been activated via a prior call to sqlite3_db_config(db, +** SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, 1, 0); +*/ +static int fts3TokenizerEnabled(sqlite3_context *context){ + sqlite3 *db = sqlite3_context_db_handle(context); + int isEnabled = 0; + sqlite3_db_config(db,SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER,-1,&isEnabled); + return isEnabled; +} + /* ** Implementation of the SQL scalar function for accessing the underlying ** hash table. This function may be called as follows: @@ -49,7 +61,7 @@ ** is a blob containing the pointer stored as the hash data corresponding ** to string (after the hash-table is updated, if applicable). */ -static void scalarFunc( +static void fts3TokenizerFunc( sqlite3_context *context, int argc, sqlite3_value **argv @@ -67,27 +79,23 @@ static void scalarFunc( nName = sqlite3_value_bytes(argv[0])+1; if( argc==2 ){ -#ifdef SQLITE_ENABLE_FTS3_TOKENIZER - void *pOld; - int n = sqlite3_value_bytes(argv[1]); - if( zName==0 || n!=sizeof(pPtr) ){ - sqlite3_result_error(context, "argument type mismatch", -1); + if( fts3TokenizerEnabled(context) ){ + void *pOld; + int n = sqlite3_value_bytes(argv[1]); + if( zName==0 || n!=sizeof(pPtr) ){ + sqlite3_result_error(context, "argument type mismatch", -1); + return; + } + pPtr = *(void **)sqlite3_value_blob(argv[1]); + pOld = sqlite3Fts3HashInsert(pHash, (void *)zName, nName, pPtr); + if( pOld==pPtr ){ + sqlite3_result_error(context, "out of memory", -1); + } + }else{ + sqlite3_result_error(context, "fts3tokenize disabled", -1); return; } - pPtr = *(void **)sqlite3_value_blob(argv[1]); - pOld = sqlite3Fts3HashInsert(pHash, (void *)zName, nName, pPtr); - if( pOld==pPtr ){ - sqlite3_result_error(context, "out of memory", -1); - return; - } -#else - sqlite3_result_error(context, "fts3tokenize: " - "disabled - rebuild with -DSQLITE_ENABLE_FTS3_TOKENIZER", -1 - ); - return; -#endif /* SQLITE_ENABLE_FTS3_TOKENIZER */ - }else - { + }else{ if( zName ){ pPtr = sqlite3Fts3HashFind(pHash, zName, nName); } @@ -98,7 +106,6 @@ static void scalarFunc( return; } } - sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT); } @@ -336,7 +343,6 @@ finish: Tcl_DecrRefCount(pRet); } -#ifdef SQLITE_ENABLE_FTS3_TOKENIZER static int registerTokenizer( sqlite3 *db, @@ -358,7 +364,6 @@ int registerTokenizer( return sqlite3_finalize(pStmt); } -#endif /* SQLITE_ENABLE_FTS3_TOKENIZER */ static @@ -431,13 +436,13 @@ static void intTestFunc( assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") ); /* Test the storage function */ -#ifdef SQLITE_ENABLE_FTS3_TOKENIZER - rc = registerTokenizer(db, "nosuchtokenizer", p1); - assert( rc==SQLITE_OK ); - rc = queryTokenizer(db, "nosuchtokenizer", &p2); - assert( rc==SQLITE_OK ); - assert( p2==p1 ); -#endif + if( fts3TokenizerEnabled(context) ){ + rc = registerTokenizer(db, "nosuchtokenizer", p1); + assert( rc==SQLITE_OK ); + rc = queryTokenizer(db, "nosuchtokenizer", &p2); + assert( rc==SQLITE_OK ); + assert( p2==p1 ); + } sqlite3_result_text(context, "ok", -1, SQLITE_STATIC); } @@ -453,7 +458,7 @@ static void intTestFunc( ** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); ** ** This function adds a scalar function (see header comment above -** scalarFunc() in this file for details) and, if ENABLE_TABLE is +** fts3TokenizerFunc() in this file for details) and, if ENABLE_TABLE is ** defined at compilation time, a temporary virtual table (see header ** comment above struct HashTableVtab) to the database schema. Both ** provide read/write access to the contents of *pHash. @@ -482,10 +487,10 @@ int sqlite3Fts3InitHashTable( #endif if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0); + rc = sqlite3_create_function(db, zName, 1, any, p, fts3TokenizerFunc, 0, 0); } if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0); + rc = sqlite3_create_function(db, zName, 2, any, p, fts3TokenizerFunc, 0, 0); } #ifdef SQLITE_TEST if( SQLITE_OK==rc ){ diff --git a/manifest b/manifest index f3c7712c00..b196f4d2fb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stypo\sin\sa\scomment\s(though\san\simportant\scomment\sin\sthat\sit\sis\sused\s\nto\sgenerate\sdocumentation). -D 2016-02-26T13:22:21.836 +C Provide\sthe\snew\sSQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER\soption\sto\s\nsqlite3_db_config()\sthat\scan\sbe\sused\sto\sactivate\sthe\stwo-argument\sversion\nof\sfts3_tokenizer()\sfor\sa\sspecific\sdatabase\sconnection\sat\srun-time. +D 2016-02-26T15:38:24.549 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -83,7 +83,7 @@ F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7 F ext/fts3/fts3_test.c 11e36437b0f3f2266acea5b4787f615e4337a237 F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860 -F ext/fts3/fts3_tokenizer.c 4bd72f767f61c9ce5a7575c844e8d1ed2c3c561a +F ext/fts3/fts3_tokenizer.c 3cf21cd2212db17a88d4ef7da0fd8a80275979a1 F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145 @@ -314,7 +314,7 @@ F src/insert.c 9ca97272e9f74ed0efddf3b4350ee12740cebbef F src/journal.c fe3a3e2559ce3ce9d371afd30fbabbc074174575 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f -F src/main.c d7415cd68121ef24c2e76b9e81ec96ffc90e6517 +F src/main.c be9309f442ec291177642d2e48e82290e0951f4b F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -351,15 +351,15 @@ F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 1bacfde7b7cec134d2b354cbcf67bafc67078431 F src/shell.c 89b73e894e737cc2f21e4bce0feb3ea21cc61124 -F src/sqlite.h.in 42203c6bf167b8b13c4e6637cbdf8ad2cb2f8685 +F src/sqlite.h.in 6bf029bcb077c6db633a77b7fda5ffd5b7c950b7 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h b9ac8b9c9798f57d80a9756f86abf1dbd9424ec9 +F src/sqliteInt.h 63c0e1b5b5d608a1ba2303fe3a554b859a120406 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 F src/tclsqlite.c 13debcc6a5ca1217486f8903768c01114fbe8b58 -F src/test1.c 8b17b1ff53aad71e7f9318a2fda247beddeaa601 +F src/test1.c f14a6f9e2cff6cba4d83e2b0c52857f61886cead F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e @@ -373,7 +373,7 @@ F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f -F src/test_config.c 7985332c806d1cece793475c75a6abcccde9d331 +F src/test_config.c 0dee90328e3dedf8ba002ee94b6a7e7ea7726fe4 F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_fs.c f10f840ca4f8c72e4837908bd8347ac4bcab074b @@ -698,7 +698,7 @@ F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8 F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18 F test/fts3ao.test 3e4e3d5e75c076520341d0bdf4eb17c00e8cbde2 -F test/fts3atoken.test 76262be798f23a390717d14266f0df551e52a7ee +F test/fts3atoken.test 4b4c16fdcfc972f2cdbba212375a060a86ccf5f1 F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9 F test/fts3aux1.test f8f287a4a73f381f8fa15b6a70f36245f903d221 F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba @@ -745,7 +745,7 @@ F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01 F test/fts4growth.test 60d6bb3f78e25b34f533797dd9f2f9402310a13a F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269 F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d -F test/fts4langid.test 8bd8759e0d4b04d71771544b861193a6841fee84 +F test/fts4langid.test 9794addcc8faaee85ac60eceecdb52feb0c70f68 F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891 F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7 @@ -1450,7 +1450,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 3ef6a3153267d5328202fea24fd29ff4d5409295 -R 77993d5bd700ce83f039b073c94a1fa4 +P ff3d7f845e1875d6729f64f5231db1c376892f31 +R 31d803939428fd2d10225002a384e77a U drh -Z 9609a7717e93d89e1b3f63c437689c08 +Z 2070e36304d2e6c69aaa4c28fc3295af diff --git a/manifest.uuid b/manifest.uuid index af3baca687..dcf6861a1e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ff3d7f845e1875d6729f64f5231db1c376892f31 \ No newline at end of file +374b5108087a2eae03676c0f3469b37a272145bf \ No newline at end of file diff --git a/src/main.c b/src/main.c index 4ffc426b08..2a258da662 100644 --- a/src/main.c +++ b/src/main.c @@ -796,8 +796,9 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){ int op; /* The opcode */ u32 mask; /* Mask of the bit in sqlite3.flags to set/clear */ } aFlagOp[] = { - { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, - { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, + { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, + { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, + { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ @@ -2811,6 +2812,9 @@ static int openDatabase( #endif #if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK) | SQLITE_CellSizeCk +#endif +#if defined(SQLITE_ENABLE_FTS3_TOKENIZER) + | SQLITE_Fts3Tokenizer #endif ; sqlite3HashInit(&db->aCollSeq); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 829eeb86ce..60e2e3b61c 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -1904,11 +1904,25 @@ struct sqlite3_mem_methods { ** following this call. The second parameter may be a NULL pointer, in ** which case the trigger setting is not reported back. ** +**
    SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
    +**
    ^This option is used to enable or disable the two-argument +** version of the [fts3_tokenizer()] function which is part of the +** [FTS3] full-text search engine extension. +** There should be two additional arguments. +** The first argument is an integer which is 0 to disable fts3_tokenizer() or +** positive to enable fts3_tokenizer() or negative to leave the setting +** unchanged. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled +** following this call. The second parameter may be a NULL pointer, in +** which case the new setting is not reported back.
    +** ** */ -#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ -#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ +#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ +#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ /* diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a62ffb6b69..759d7ca5e1 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1327,6 +1327,7 @@ struct sqlite3 { #define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */ #define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */ #define SQLITE_CellSizeCk 0x10000000 /* Check btree cell sizes on load */ +#define SQLITE_Fts3Tokenizer 0x20000000 /* Enable fts3_tokenizer(2) */ /* diff --git a/src/test1.c b/src/test1.c index 713152b824..744b400b2a 100644 --- a/src/test1.c +++ b/src/test1.c @@ -6920,6 +6920,53 @@ static int test_register_dbstat_vtab( #endif /* SQLITE_OMIT_VIRTUALTABLE */ } +/* +** tclcmd: sqlite3_db_config DB SETTING VALUE +** +** Invoke sqlite3_db_config() for one of the setting values. +*/ +static int test_sqlite3_db_config( + void *clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + static const struct { + const char *zName; + int eVal; + } aSetting[] = { + { "FKEY", SQLITE_DBCONFIG_ENABLE_FKEY }, + { "TRIGGER", SQLITE_DBCONFIG_ENABLE_TRIGGER }, + { "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, + }; + int i; + int v; + const char *zSetting; + sqlite3 *db; + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB SETTING VALUE"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zSetting = Tcl_GetString(objv[2]); + if( sqlite3_strglob("SQLITE_*", zSetting)==0 ) zSetting += 7; + if( sqlite3_strglob("DBCONFIG_*", zSetting)==0 ) zSetting += 9; + if( sqlite3_strglob("ENABLE_*", zSetting)==0 ) zSetting += 7; + for(i=0; i=ArraySize(aSetting) ){ + Tcl_SetObjResult(interp, + Tcl_NewStringObj("unknown sqlite3_db_config setting", -1)); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[3], &v) ) return TCL_ERROR; + sqlite3_db_config(db, aSetting[i].eVal, v, &v); + Tcl_SetObjResult(interp, Tcl_NewIntObj(v)); + return TCL_OK; +} + /* ** Register commands with the TCL interpreter. */ @@ -6989,6 +7036,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ Tcl_ObjCmdProc *xProc; void *clientData; } aObjCmd[] = { + { "sqlite3_db_config", test_sqlite3_db_config, 0 }, { "bad_behavior", test_bad_behavior, (void*)&iZero }, { "register_dbstat_vtab", test_register_dbstat_vtab }, { "sqlite3_connection_pointer", get_sqlite_pointer, 0 }, diff --git a/src/test_config.c b/src/test_config.c index 5db7117555..30b421e00b 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -370,12 +370,6 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "fts3", "0", TCL_GLOBAL_ONLY); #endif -#ifdef SQLITE_ENABLE_FTS3_TOKENIZER - Tcl_SetVar2(interp, "sqlite_options", "fts3_tokenizer", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "fts3_tokenizer", "0", TCL_GLOBAL_ONLY); -#endif - #ifdef SQLITE_ENABLE_FTS5 Tcl_SetVar2(interp, "sqlite_options", "fts5", "1", TCL_GLOBAL_ONLY); #else diff --git a/test/fts3atoken.test b/test/fts3atoken.test index 2cdea79a98..4ce38762d6 100644 --- a/test/fts3atoken.test +++ b/test/fts3atoken.test @@ -56,40 +56,41 @@ proc escape_string {str} { # # 5: Test that the table created to use tokenizer 'blah' is usable. # -ifcapable fts3_tokenizer { - do_test fts3atoken-1.1 { - catchsql { - CREATE VIRTUAL TABLE t1 USING fts3(content, tokenize blah); - } - } {1 {unknown tokenizer: blah}} - do_test fts3atoken-1.2 { - execsql { - SELECT fts3_tokenizer('blah', fts3_tokenizer('simple')) IS NULL; - } - } {0} - do_test fts3atoken-1.3 { - execsql { - SELECT fts3_tokenizer('blah') == fts3_tokenizer('simple'); - } - } {1} - do_test fts3atoken-1.4 { - catchsql { - CREATE VIRTUAL TABLE t1 USING fts3(content, tokenize blah); - } - } {0 {}} - do_test fts3atoken-1.5 { - execsql { - INSERT INTO t1(content) VALUES('There was movement at the station'); - INSERT INTO t1(content) VALUES('For the word has passed around'); - INSERT INTO t1(content) VALUES('That the colt from ol regret had got'); - SELECT content FROM t1 WHERE content MATCH 'movement' - } - } {{There was movement at the station}} -} else { - do_catchsql_test 1.6 { +sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1 +do_test fts3atoken-1.1 { + catchsql { + CREATE VIRTUAL TABLE t1 USING fts3(content, tokenize blah); + } +} {1 {unknown tokenizer: blah}} +do_test fts3atoken-1.2 { + execsql { SELECT fts3_tokenizer('blah', fts3_tokenizer('simple')) IS NULL; - } {1 {fts3tokenize: disabled - rebuild with -DSQLITE_ENABLE_FTS3_TOKENIZER}} -} + } +} {0} +do_test fts3atoken-1.3 { + execsql { + SELECT fts3_tokenizer('blah') == fts3_tokenizer('simple'); + } +} {1} +do_test fts3atoken-1.4 { + catchsql { + CREATE VIRTUAL TABLE t1 USING fts3(content, tokenize blah); + } +} {0 {}} +do_test fts3atoken-1.5 { + execsql { + INSERT INTO t1(content) VALUES('There was movement at the station'); + INSERT INTO t1(content) VALUES('For the word has passed around'); + INSERT INTO t1(content) VALUES('That the colt from ol regret had got'); + SELECT content FROM t1 WHERE content MATCH 'movement' + } +} {{There was movement at the station}} + +sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 0 +do_catchsql_test 1.6 { + SELECT fts3_tokenizer('blah', fts3_tokenizer('simple')) IS NULL; +} {1 {fts3tokenize disabled}} + #-------------------------------------------------------------------------- # Test cases fts3atoken-2.* test error cases in the scalar function based @@ -212,14 +213,14 @@ do_catchsql_test 6.1.3 { do_catchsql_test 6.2.1 { SELECT fts3_tokenizer(NULL); } {1 {unknown tokenizer: }} -ifcapable fts3_tokenizer { - do_catchsql_test 6.2.2 { - SELECT fts3_tokenizer(NULL, X'1234567812345678'); - } {1 {argument type mismatch}} - do_catchsql_test 6.2.3 { - SELECT fts3_tokenizer(NULL, X'12345678'); - } {1 {argument type mismatch}} -} + +sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1 +do_catchsql_test 6.2.2 { + SELECT fts3_tokenizer(NULL, X'1234567812345678'); +} {1 {argument type mismatch}} +do_catchsql_test 6.2.3 { + SELECT fts3_tokenizer(NULL, X'12345678'); +} {1 {argument type mismatch}} finish_test diff --git a/test/fts4langid.test b/test/fts4langid.test index a3059931e7..eb3602b4b8 100644 --- a/test/fts4langid.test +++ b/test/fts4langid.test @@ -358,31 +358,30 @@ proc build_multilingual_db_2 {db} { } } -ifcapable fts3_tokenizer { - do_test 4.1.0 { - reset_db - set ptr [fts3_test_tokenizer] - execsql { SELECT fts3_tokenizer('testtokenizer', $ptr) } - build_multilingual_db_2 db - } {} - do_execsql_test 4.1.1 { - SELECT docid FROM t4 WHERE t4 MATCH 'quick'; - } {0} - do_execsql_test 4.1.2 { - SELECT docid FROM t4 WHERE t4 MATCH 'quick' AND lid=1; - } {} - do_execsql_test 4.1.3 { - SELECT docid FROM t4 WHERE t4 MATCH 'Quick' AND lid=1; - } {1} - for {set i 0} {$i < 50} {incr i} { - do_execsql_test 4.1.4.$i { - SELECT count(*) FROM t4 WHERE t4 MATCH 'fox' AND lid=$i; - } [expr 0==($i%2)] - } - do_catchsql_test 4.1.5 { - INSERT INTO t4(content, lid) VALUES('hello world', 101) - } {1 {SQL logic error or missing database}} +do_test 4.1.0 { + reset_db + set ptr [fts3_test_tokenizer] + sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1 + execsql { SELECT fts3_tokenizer('testtokenizer', $ptr) } + build_multilingual_db_2 db +} {} +do_execsql_test 4.1.1 { + SELECT docid FROM t4 WHERE t4 MATCH 'quick'; +} {0} +do_execsql_test 4.1.2 { + SELECT docid FROM t4 WHERE t4 MATCH 'quick' AND lid=1; +} {} +do_execsql_test 4.1.3 { + SELECT docid FROM t4 WHERE t4 MATCH 'Quick' AND lid=1; +} {1} +for {set i 0} {$i < 50} {incr i} { + do_execsql_test 4.1.4.$i { + SELECT count(*) FROM t4 WHERE t4 MATCH 'fox' AND lid=$i; + } [expr 0==($i%2)] } +do_catchsql_test 4.1.5 { + INSERT INTO t4(content, lid) VALUES('hello world', 101) +} {1 {SQL logic error or missing database}} #------------------------------------------------------------------------- # Test cases 5.* From 38c3d3d8a5369a03ed4d796acd7df3d369f2a9b8 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 26 Feb 2016 16:03:29 +0000 Subject: [PATCH 362/570] Fix the ICU extension LIKE function so that it does not read past the end of a buffer if it it passed malformed utf-8. FossilOrigin-Name: 424b7aee3310b9782bd312589dc3d9f287aa04b8 --- ext/icu/icu.c | 64 +++++++++++++++++++++++++++++++++++++-------------- manifest | 14 +++++------ manifest.uuid | 2 +- 3 files changed, 55 insertions(+), 25 deletions(-) diff --git a/ext/icu/icu.c b/ext/icu/icu.c index a2ff49274c..56543667ca 100644 --- a/ext/icu/icu.c +++ b/ext/icu/icu.c @@ -60,6 +60,38 @@ static void xFree(void *p){ sqlite3_free(p); } +/* +** This lookup table is used to help decode the first byte of +** a multi-byte UTF8 character. It is copied here from SQLite source +** code file utf8.c. +*/ +static const unsigned char icuUtf8Trans1[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, +}; + +#define SQLITE_ICU_READ_UTF8(zIn, c) \ + c = *(zIn++); \ + if( c>=0xc0 ){ \ + c = icuUtf8Trans1[c-0xc0]; \ + while( (*zIn & 0xc0)==0x80 ){ \ + c = (c<<6) + (0x3f & *(zIn++)); \ + } \ + } + +#define SQLITE_ICU_SKIP_UTF8(zIn) \ + assert( *zIn ); \ + if( *(zIn++)>=0xc0 ){ \ + while( (*zIn & 0xc0)==0x80 ){zIn++;} \ + } + + /* ** Compare two UTF-8 strings for equality where the first string is ** a "LIKE" expression. Return true (1) if they are the same and @@ -73,16 +105,14 @@ static int icuLikeCompare( static const int MATCH_ONE = (UChar32)'_'; static const int MATCH_ALL = (UChar32)'%'; - int iPattern = 0; /* Current byte index in zPattern */ - int iString = 0; /* Current byte index in zString */ - int prevEscape = 0; /* True if the previous character was uEsc */ - while( zPattern[iPattern]!=0 ){ + while( 1 ){ /* Read (and consume) the next character from the input pattern. */ UChar32 uPattern; - U8_NEXT_UNSAFE(zPattern, iPattern, uPattern); + SQLITE_ICU_READ_UTF8(zPattern, uPattern); + if( uPattern==0 ) break; /* There are now 4 possibilities: ** @@ -99,28 +129,28 @@ static int icuLikeCompare( ** MATCH_ALL. For each MATCH_ONE, skip one character in the ** test string. */ - while( (c=zPattern[iPattern]) == MATCH_ALL || c == MATCH_ONE ){ + while( (c=*zPattern) == MATCH_ALL || c == MATCH_ONE ){ if( c==MATCH_ONE ){ - if( zString[iString]==0 ) return 0; - U8_FWD_1_UNSAFE(zString, iString); + if( *zString==0 ) return 0; + SQLITE_ICU_SKIP_UTF8(zString); } - iPattern++; + zPattern++; } - if( zPattern[iPattern]==0 ) return 1; + if( *zPattern==0 ) return 1; - while( zString[iString] ){ - if( icuLikeCompare(&zPattern[iPattern], &zString[iString], uEsc) ){ + while( *zString ){ + if( icuLikeCompare(zPattern, zString, uEsc) ){ return 1; } - U8_FWD_1_UNSAFE(zString, iString); + SQLITE_ICU_SKIP_UTF8(zString); } return 0; }else if( !prevEscape && uPattern==MATCH_ONE ){ /* Case 2. */ - if( zString[iString]==0 ) return 0; - U8_FWD_1_UNSAFE(zString, iString); + if( *zString==0 ) return 0; + SQLITE_ICU_SKIP_UTF8(zString); }else if( !prevEscape && uPattern==uEsc){ /* Case 3. */ @@ -129,7 +159,7 @@ static int icuLikeCompare( }else{ /* Case 4. */ UChar32 uString; - U8_NEXT_UNSAFE(zString, iString, uString); + SQLITE_ICU_READ_UTF8(zString, uString); uString = u_foldCase(uString, U_FOLD_CASE_DEFAULT); uPattern = u_foldCase(uPattern, U_FOLD_CASE_DEFAULT); if( uString!=uPattern ){ @@ -139,7 +169,7 @@ static int icuLikeCompare( } } - return zString[iString]==0; + return *zString==0; } /* diff --git a/manifest b/manifest index b196f4d2fb..046a24e640 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Provide\sthe\snew\sSQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER\soption\sto\s\nsqlite3_db_config()\sthat\scan\sbe\sused\sto\sactivate\sthe\stwo-argument\sversion\nof\sfts3_tokenizer()\sfor\sa\sspecific\sdatabase\sconnection\sat\srun-time. -D 2016-02-26T15:38:24.549 +C Fix\sthe\sICU\sextension\sLIKE\sfunction\sso\sthat\sit\sdoes\snot\sread\spast\sthe\send\sof\sa\sbuffer\sif\sit\sit\spassed\smalformed\sutf-8. +D 2016-02-26T16:03:29.500 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 @@ -198,7 +198,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093 F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45 F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43 -F ext/icu/icu.c b2732aef0b076e4276d9b39b5a33cec7a05e1413 +F ext/icu/icu.c 194e972ff3545084b56c459131eb80e1485da75e F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37 F ext/misc/amatch.c a1a8f66c29d40bd71b075546ddeddb477b17a2bb F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704 @@ -1450,7 +1450,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 ff3d7f845e1875d6729f64f5231db1c376892f31 -R 31d803939428fd2d10225002a384e77a -U drh -Z 2070e36304d2e6c69aaa4c28fc3295af +P 374b5108087a2eae03676c0f3469b37a272145bf +R 1de55b3a8f2d3749e97e04af07972bbe +U dan +Z 5dfcb2d8f6d42b01529359e44d97d92b diff --git a/manifest.uuid b/manifest.uuid index dcf6861a1e..b891f1a561 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -374b5108087a2eae03676c0f3469b37a272145bf \ No newline at end of file +424b7aee3310b9782bd312589dc3d9f287aa04b8 \ No newline at end of file From 9b88ace82262165380f88befc0aad6beeef33ff0 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 26 Feb 2016 21:01:37 +0000 Subject: [PATCH 363/570] Further refinements to the MSVC batch build process. FossilOrigin-Name: 4e54e9c0fefe417f94a2d95921acf61b1dda5ca4 --- Makefile.msc | 42 +++++++++++++++++++++++++----------------- autoconf/Makefile.msc | 14 +++++++++----- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index d84df8345e..8a6d7fd954 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -472,20 +472,24 @@ CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) # when linking. # !IFNDEF CORE_LINK_DEP -!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +!IF $(DYNAMIC_SHELL)!=0 CORE_LINK_DEP = -!ELSE +!ELSEIF $(FOR_WIN10)==0 || "$(PLATFORM)"=="x86" CORE_LINK_DEP = sqlite3.def +!ELSE +CORE_LINK_DEP = !ENDIF !ENDIF # These are additional linker options used for the core library. # !IFNDEF CORE_LINK_OPTS -!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +!IF $(DYNAMIC_SHELL)!=0 CORE_LINK_OPTS = -!ELSE +!ELSEIF $(FOR_WIN10)==0 || "$(PLATFORM)"=="x86" CORE_LINK_OPTS = /DEF:sqlite3.def +!ELSE +CORE_LINK_OPTS = !ENDIF !ENDIF @@ -1387,11 +1391,11 @@ all: dll libsqlite3.lib shell $(ALL_TCL_TARGETS) # Dynamic link library section. # -dll: $(SQLITE3DLL) +dll: $(SQLITE3DLL) # Shell executable. # -shell: $(SQLITE3EXE) +shell: $(SQLITE3EXE) # <> libsqlite3.lib: $(LIBOBJ) @@ -1401,14 +1405,14 @@ libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib $(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCLSTUB) $(TLIBS) # <> -$(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) +$(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) # <> -sqlite3.def: libsqlite3.lib +sqlite3.def: libsqlite3.lib echo EXPORTS > sqlite3.def dumpbin /all libsqlite3.lib \ - | $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3_.*)$$" \1 \ + | $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3_[^@]*)(?:@\d+)?$$" \1 \ | sort >> sqlite3.def # <> @@ -1784,7 +1788,7 @@ parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\tool\addopcodes.tcl $(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION $(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H) -sqlite3ext.h: .target_source +sqlite3ext.h: .target_source copy tsrc\sqlite3ext.h . mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c @@ -1885,9 +1889,9 @@ fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe del /Q fts5parse.h 2>NUL .\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) fts5parse.y -fts5parse.h: fts5parse.c +fts5parse.h: fts5parse.c -fts5.c: $(FTS5_SRC) +fts5.c: $(FTS5_SRC) $(TCLSH_CMD) $(TOP)\ext\fts5\tool\mkfts5c.tcl copy $(TOP)\ext\fts5\fts5.h . @@ -1928,7 +1932,7 @@ testfixture.exe: $(TESTFIXTURE_SRC) $(SQLITE3H) $(LIBRESOBJS) $(HDR) $(TESTFIXTURE_SRC) \ /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) -extensiontest: testfixture.exe testloadext.dll +extensiontest: testfixture.exe testloadext.dll @set PATH=$(LIBTCLPATH);$(PATH) .\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS) @@ -1971,7 +1975,7 @@ smoketest: $(TESTPROGS) @set PATH=$(LIBTCLPATH);$(PATH) .\testfixture.exe $(TOP)\test\main.test $(TESTOPTS) -sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl +sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl echo #define TCLSH 2 > $@ echo #define SQLITE_ENABLE_DBSTAT_VTAB 1 >> $@ copy $@ + $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@ @@ -1987,7 +1991,7 @@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS) testloadext.lo: $(TOP)\src\test_loadext.c $(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c -testloadext.dll: testloadext.lo +testloadext.dll: testloadext.lo $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(SQLITE3H) @@ -2025,9 +2029,12 @@ speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(TOP)\test\speedtest1.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) -rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H) +rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU -Fe$@ \ $(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) + +moreclean: clean + del /Q $(SQLITE3C) $(SQLITE3H) 2>NUL # <
    > clean: @@ -2035,7 +2042,8 @@ clean: del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL del /Q $(SQLITE3EXE) $(SQLITE3DLL) 2>NUL # <> - del /Q $(SQLITE3C) $(SQLITE3H) opcodes.c opcodes.h 2>NUL + del /Q sqlite3.c sqlite3.h 2>NUL + del /Q opcodes.c opcodes.h 2>NUL del /Q lemon.* lempar.c parse.* 2>NUL del /Q mkkeywordhash.* keywordhash.h 2>NUL del /Q notasharedlib.* 2>NUL diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index 52f0d91e0c..ca7c62e3d4 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -457,7 +457,9 @@ CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) # when linking. # !IFNDEF CORE_LINK_DEP -!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +!IF $(DYNAMIC_SHELL)!=0 +CORE_LINK_DEP = +!ELSEIF $(FOR_WIN10)==0 || "$(PLATFORM)"=="x86" CORE_LINK_DEP = !ELSE CORE_LINK_DEP = @@ -467,7 +469,9 @@ CORE_LINK_DEP = # These are additional linker options used for the core library. # !IFNDEF CORE_LINK_OPTS -!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +!IF $(DYNAMIC_SHELL)!=0 +CORE_LINK_OPTS = +!ELSEIF $(FOR_WIN10)==0 || "$(PLATFORM)"=="x86" CORE_LINK_OPTS = !ELSE CORE_LINK_OPTS = @@ -874,14 +878,14 @@ all: dll shell # Dynamic link library section. # -dll: $(SQLITE3DLL) +dll: $(SQLITE3DLL) # Shell executable. # -shell: $(SQLITE3EXE) +shell: $(SQLITE3EXE) -$(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) +$(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) diff --git a/manifest b/manifest index e8f5966687..5d644993fb 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Use\sthe\sarguments\sto\sNMAKE\sconsistently\sin\sthe\sMSVC\sbatch\sbuild\stool. -D 2016-02-19T19:29:44.729 +C Further\srefinements\sto\sthe\sMSVC\sbatch\sbuild\sprocess. +D 2016-02-26T21:01:37.745 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 28fc4ee02333996d31b3602b39eeb8e609a89ce4 +F Makefile.msc 56ea123a975690bf9ed38b31bb89ff87b02a7c2b F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -11,7 +11,7 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 29e2a6e8d0c5e32723a48b4faf6b168854dde5f4 -F autoconf/Makefile.msc d5ab32cf30d6ba8b5ce20835b4042f6cc2a4cb39 +F autoconf/Makefile.msc 3cbf11c911fafd4d95fbe8aec059b5aa586a0157 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 7c31da66232f7590bb987cfcd4e2381744b25d24 F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 66a9ad4a6df513f4c35c3d337d4e2e80cd38d586 -R abade97baee8abed51650334fbde09aa +P 480e5049486b8b047f533d78b040daa47dd6b946 +R 87ed83a4b8ba227fd93efdc4c65e0468 U mistachkin -Z 7b92d09a61d34a4957d04f9633ed77f9 +Z ceeeca002bf9c099753e1f0c14c10004 diff --git a/manifest.uuid b/manifest.uuid index 613e1048a0..a39c79627c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -480e5049486b8b047f533d78b040daa47dd6b946 \ No newline at end of file +4e54e9c0fefe417f94a2d95921acf61b1dda5ca4 \ No newline at end of file From 88a1650859cd828a80261f4c228247fef5635790 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 26 Feb 2016 21:20:57 +0000 Subject: [PATCH 364/570] Fix a potential buffer overflow in the ICU upper() function. FossilOrigin-Name: b8dc1b9f5d413000387bfe784b69f5d0ee5c0489 --- ext/icu/icu.c | 48 ++++++++++++++++++++++++++++-------------------- manifest | 16 ++++++++-------- manifest.uuid | 2 +- test/icu.test | 9 +++++++++ 4 files changed, 46 insertions(+), 29 deletions(-) diff --git a/ext/icu/icu.c b/ext/icu/icu.c index 56543667ca..263cd98275 100644 --- a/ext/icu/icu.c +++ b/ext/icu/icu.c @@ -355,11 +355,11 @@ static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){ */ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ const UChar *zInput; - UChar *zOutput; + UChar *zOutput = 0; int nInput; - int nOutput; - - UErrorCode status = U_ZERO_ERROR; + int nOut; + int cnt; + UErrorCode status; const char *zLocale = 0; assert(nArg==1 || nArg==2); @@ -371,26 +371,34 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ if( !zInput ){ return; } - nInput = sqlite3_value_bytes16(apArg[0]); - - nOutput = nInput * 2 + 2; - zOutput = sqlite3_malloc(nOutput); - if( !zOutput ){ + nOut = nInput = sqlite3_value_bytes16(apArg[0]); + if( nOut==0 ){ + sqlite3_result_text16(p, "", 0, SQLITE_STATIC); return; } - if( sqlite3_user_data(p) ){ - u_strToUpper(zOutput, nOutput/2, zInput, nInput/2, zLocale, &status); - }else{ - u_strToLower(zOutput, nOutput/2, zInput, nInput/2, zLocale, &status); + for(cnt=0; cnt<2; cnt++){ + UChar *zNew = sqlite3_realloc(zOutput, nOut); + if( zNew==0 ){ + sqlite3_free(zOutput); + sqlite3_result_error_nomem(p); + return; + } + zOutput = zNew; + status = U_ZERO_ERROR; + if( sqlite3_user_data(p) ){ + nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status); + }else{ + nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status); + } + if( !U_SUCCESS(status) ){ + if( status==U_BUFFER_OVERFLOW_ERROR ) continue; + icuFunctionError(p, + sqlite3_user_data(p) ? "u_strToUpper()" : "u_strToLower", status); + return; + } } - - if( !U_SUCCESS(status) ){ - icuFunctionError(p, "u_strToLower()/u_strToUpper", status); - return; - } - - sqlite3_result_text16(p, zOutput, -1, xFree); + sqlite3_result_text16(p, zOutput, nOut, xFree); } /* diff --git a/manifest b/manifest index 3b14fffa3a..6f2f8535ef 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\srefinements\sto\sthe\sMSVC\sbatch\sbuild\sprocess. -D 2016-02-26T21:03:16.418 +C Fix\sa\spotential\sbuffer\soverflow\sin\sthe\sICU\supper()\sfunction. +D 2016-02-26T21:20:57.225 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 56ea123a975690bf9ed38b31bb89ff87b02a7c2b @@ -198,7 +198,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093 F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45 F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43 -F ext/icu/icu.c 194e972ff3545084b56c459131eb80e1485da75e +F ext/icu/icu.c be1f90d8babafe6d1a55a6912161bcac75baee0e F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37 F ext/misc/amatch.c a1a8f66c29d40bd71b075546ddeddb477b17a2bb F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704 @@ -777,7 +777,7 @@ F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98 F test/hexlit.test d7b0a5f41123df1e43985b91b8b2e70f95282d21 F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711 F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f -F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 +F test/icu.test 73956798bace8982909c00476b216714a6d0559a F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607 F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 F test/in.test 61a24ae38d4b64ec69f06ccdf022992f68a98176 @@ -1450,7 +1450,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 424b7aee3310b9782bd312589dc3d9f287aa04b8 4e54e9c0fefe417f94a2d95921acf61b1dda5ca4 -R 7da9769ad29c99be35565d7e5f8b1154 -U mistachkin -Z 7d4c099032b4aee5af44d708663be688 +P cf4e4fbdb6a29b7fbd5150958ab4f8f2a1cd7f21 +R a5aa0b45f5ae16ce5e364c4bc7498593 +U drh +Z d4cfa74b26d8bc26b2ff43ad0d4d53e2 diff --git a/manifest.uuid b/manifest.uuid index 07b70ce13e..38c7afbca2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cf4e4fbdb6a29b7fbd5150958ab4f8f2a1cd7f21 \ No newline at end of file +b8dc1b9f5d413000387bfe784b69f5d0ee5c0489 \ No newline at end of file diff --git a/test/icu.test b/test/icu.test index 73cb9b913e..743bcfaea1 100644 --- a/test/icu.test +++ b/test/icu.test @@ -72,6 +72,10 @@ test_expr icu-2.6 {i1=$::OGRAVE} {upper(i1)} $::OGRAVE test_expr icu-2.7 {i1=$::szlig} {upper(i1)} "SS" test_expr icu-2.8 {i1='SS'} {lower(i1)} "ss" +do_execsql_test icu-2.9 { + SELECT upper(char(0xfb04,0xfb04,0xfb04,0xfb04)); +} {FFLFFLFFLFFL} + # In turkish (locale="tr_TR"), the lower case version of I # is "small dotless i" (code point 0x131 (decimal 305)). # @@ -133,4 +137,9 @@ do_catchsql_test icu-5.4 { do_catchsql_test icu-5.4 { SELECT 'abc' REGEXP } {1 {near " ": syntax error}} do_catchsql_test icu-5.5 { SELECT 'abc' REGEXP, 1 } {1 {near ",": syntax error}} + +do_malloc_test icu-6.10 -sqlbody { + SELECT upper(char(0xfb04,0xdf,0xfb04,0xe8,0xfb04)); +} + finish_test From 9aeb971ceb39390e388d3c6946be9b11f74e9955 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 26 Feb 2016 23:13:16 +0000 Subject: [PATCH 365/570] Support generating the '.def' file using the autoconf Makefile for MSVC. FossilOrigin-Name: 3617564cb630ed418badf43d2c0291c11c166d12 --- Makefile.msc | 12 ++- autoconf/Makefile.msc | 20 +++- autoconf/README.txt | 4 +- manifest | 23 +++-- manifest.uuid | 2 +- tool/Replace.cs | 223 +++++++++++++++++++++++++++++++++++++++++ tool/mkautoconfamal.sh | 1 + tool/mkmsvcmin.tcl | 17 +++- 8 files changed, 282 insertions(+), 20 deletions(-) create mode 100644 tool/Replace.cs diff --git a/Makefile.msc b/Makefile.msc index 8a6d7fd954..db9c83c6c7 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -306,6 +306,14 @@ PROGRAMFILES_X86 = $(PROGRAMFILES_X86:\\=\) CC = cl.exe !ENDIF +# Check for the predefined command macro CSC. This should point to a working +# C Sharp compiler binary. If it is not defined, simply define it to the +# legacy default value 'csc.exe'. +# +!IFNDEF CSC +CSC = csc.exe +!ENDIF + # Check for the command macro LD. This should point to the linker binary for # the target platform. If it is not defined, simply define it to the legacy # default value 'link.exe'. @@ -1408,13 +1416,13 @@ libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) -# <> +# <> sqlite3.def: libsqlite3.lib echo EXPORTS > sqlite3.def dumpbin /all libsqlite3.lib \ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3_[^@]*)(?:@\d+)?$$" \1 \ | sort >> sqlite3.def -# <> +# <> $(SQLITE3EXE): $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H) $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c $(SHELL_CORE_SRC) \ diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index ca7c62e3d4..b453b93c33 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -291,6 +291,14 @@ PROGRAMFILES_X86 = $(PROGRAMFILES_X86:\\=\) CC = cl.exe !ENDIF +# Check for the predefined command macro CSC. This should point to a working +# C Sharp compiler binary. If it is not defined, simply define it to the +# legacy default value 'csc.exe'. +# +!IFNDEF CSC +CSC = csc.exe +!ENDIF + # Check for the command macro LD. This should point to the linker binary for # the target platform. If it is not defined, simply define it to the legacy # default value 'link.exe'. @@ -460,7 +468,7 @@ CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) !IF $(DYNAMIC_SHELL)!=0 CORE_LINK_DEP = !ELSEIF $(FOR_WIN10)==0 || "$(PLATFORM)"=="x86" -CORE_LINK_DEP = +CORE_LINK_DEP = sqlite3.def !ELSE CORE_LINK_DEP = !ENDIF @@ -472,7 +480,7 @@ CORE_LINK_DEP = !IF $(DYNAMIC_SHELL)!=0 CORE_LINK_OPTS = !ELSEIF $(FOR_WIN10)==0 || "$(PLATFORM)"=="x86" -CORE_LINK_OPTS = +CORE_LINK_OPTS = /DEF:sqlite3.def !ELSE CORE_LINK_OPTS = !ENDIF @@ -888,6 +896,14 @@ shell: $(SQLITE3EXE) $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) +Replace.exe: + $(CSC) /target:exe $(TOP)\Replace.cs + +sqlite3.def: Replace.exe $(LIBOBJ) + echo EXPORTS > sqlite3.def + dumpbin /all $(LIBOBJ) \ + | .\Replace.exe "^\s+/EXPORT:_?(sqlite3_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \ + | sort >> sqlite3.def $(SQLITE3EXE): $(TOP)\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H) $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\shell.c $(SHELL_CORE_SRC) \ diff --git a/autoconf/README.txt b/autoconf/README.txt index 2d6db4f07f..6e62a4e138 100644 --- a/autoconf/README.txt +++ b/autoconf/README.txt @@ -6,8 +6,8 @@ This package contains: * the shell.c file used to build the sqlite3 command-line shell program * autoconf/automake installation infrastucture for building on POSIX compliant systems - * a Makefile.msc and sqlite3.rc for building with Microsoft Visual C++ on - Windows + * a Makefile.msc, sqlite3.rc, and Replace.cs for building with Microsoft + Visual C++ on Windows SUMMARY OF HOW TO BUILD ======================= diff --git a/manifest b/manifest index 6f2f8535ef..1c5c27a015 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Fix\sa\spotential\sbuffer\soverflow\sin\sthe\sICU\supper()\sfunction. -D 2016-02-26T21:20:57.225 +C Support\sgenerating\sthe\s'.def'\sfile\susing\sthe\sautoconf\sMakefile\sfor\sMSVC. +D 2016-02-26T23:13:16.711 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 56ea123a975690bf9ed38b31bb89ff87b02a7c2b +F Makefile.msc b6eb7a434c2e160a042036bd5047c3bd89eedacc F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION c6b1f51809551d60ad001e6d87cf3ab2c7f54b6f F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -11,9 +11,9 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 29e2a6e8d0c5e32723a48b4faf6b168854dde5f4 -F autoconf/Makefile.msc 3cbf11c911fafd4d95fbe8aec059b5aa586a0157 +F autoconf/Makefile.msc 91fe02447e4a90b9368b2b1406d51ee5f7e83c6a F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 -F autoconf/README.txt 7c31da66232f7590bb987cfcd4e2381744b25d24 +F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1 F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8 F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 @@ -1368,6 +1368,7 @@ F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372 +F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91 F tool/addopcodes.tcl 4ca9c3ef196f08da30add5d07ce0c9458dc8c633 F tool/build-all-msvc.bat 55be1cf8545dabd69df2ba6b3de6868da0c26f52 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 @@ -1384,9 +1385,9 @@ F tool/lemon.c 251f5c3f21b553240cbdd42dd187a51bb2372cd3 F tool/lempar.c d5114c7d13aa3af1e27ff3d02e4dea6eadec7ddf F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 -F tool/mkautoconfamal.sh c78caa3214f25dc28ea157b5a82abb311f209906 +F tool/mkautoconfamal.sh e855df211ecbcc7131dee817110ff386cfb112f7 F tool/mkkeywordhash.c f7f3b342211ac6a14258b9726d5b97cf4f548f22 -F tool/mkmsvcmin.tcl f9fc6f6a373084c0e0feef972485212bd0869c06 +F tool/mkmsvcmin.tcl 2f12f7fa8858bbe61cf81820a2da96c79ed1ca8d F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 385c62d78c38b2d92146dcb5abd319dbbc33506d F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e @@ -1450,7 +1451,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 cf4e4fbdb6a29b7fbd5150958ab4f8f2a1cd7f21 -R a5aa0b45f5ae16ce5e364c4bc7498593 -U drh -Z d4cfa74b26d8bc26b2ff43ad0d4d53e2 +P b8dc1b9f5d413000387bfe784b69f5d0ee5c0489 +R e824451697993aa684f279d9331c397b +U mistachkin +Z bb33bef608d1de79741a7de07ef806b0 diff --git a/manifest.uuid b/manifest.uuid index 38c7afbca2..3c4acbdac1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b8dc1b9f5d413000387bfe784b69f5d0ee5c0489 \ No newline at end of file +3617564cb630ed418badf43d2c0291c11c166d12 \ No newline at end of file diff --git a/tool/Replace.cs b/tool/Replace.cs new file mode 100644 index 0000000000..3475a47e6e --- /dev/null +++ b/tool/Replace.cs @@ -0,0 +1,223 @@ +/* +** 2016 February 26 +** +** 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 contains C# code to perform regular expression replacements +** using the standard input and output channels. +*/ + +using System; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; + +/////////////////////////////////////////////////////////////////////////////// + +#region Assembly Metadata +[assembly: AssemblyTitle("Replace Tool")] +[assembly: AssemblyDescription("Replace text using standard input/output.")] +[assembly: AssemblyCompany("SQLite Development Team")] +[assembly: AssemblyProduct("SQLite")] +[assembly: AssemblyCopyright("Public Domain")] +[assembly: ComVisible(false)] +[assembly: Guid("95a0513f-8863-48cd-a76f-cb80868cb578")] +[assembly: AssemblyVersion("1.0.*")] + +#if DEBUG +[assembly: AssemblyConfiguration("Debug")] +#else +[assembly: AssemblyConfiguration("Release")] +#endif +#endregion + +/////////////////////////////////////////////////////////////////////////////// + +namespace Replace +{ + /// + /// This enumeration is used to represent all the possible exit codes from + /// this tool. + /// + internal enum ExitCode + { + /// + /// The file download was a success. + /// + Success = 0, + + /// + /// The command line arguments are missing (i.e. null). Generally, + /// this should not happen. + /// + MissingArgs = 1, + + /// + /// The wrong number of command line arguments was supplied. + /// + WrongNumArgs = 2, + + /// + /// The "matchingOnly" flag could not be converted to a value of the + /// type. + /// + BadMatchingOnlyFlag = 3, + + /// + /// An exception was caught in . Generally, this + /// should not happen. + /// + Exception = 4 + } + + /////////////////////////////////////////////////////////////////////////// + + internal static class Replace + { + #region Private Support Methods + /// + /// This method displays an error message to the console and/or + /// displays the command line usage information for this tool. + /// + /// + /// The error message to display, if any. + /// + /// + /// Non-zero to display the command line usage information. + /// + private static void Error( + string message, + bool usage + ) + { + if (message != null) + Console.WriteLine(message); + + string fileName = Path.GetFileName( + Process.GetCurrentProcess().MainModule.FileName); + + Console.WriteLine(String.Format( + "usage: {0} ", + fileName)); + } + #endregion + + /////////////////////////////////////////////////////////////////////// + + #region Program Entry Point + /// + /// This is the entry-point for this tool. It handles processing the + /// command line arguments, reading from the standard input channel, + /// replacing any matching lines of text, and writing to the standard + /// output channel. + /// + /// + /// The command line arguments. + /// + /// + /// Zero upon success; non-zero on failure. This will be one of the + /// values from the enumeration. + /// + private static int Main( + string[] args + ) + { + // + // NOTE: Sanity check the command line arguments. + // + if (args == null) + { + Error(null, true); + return (int)ExitCode.MissingArgs; + } + + if (args.Length != 3) + { + Error(null, true); + return (int)ExitCode.WrongNumArgs; + } + + try + { + // + // NOTE: Create a regular expression from the first command + // line argument. Then, grab the replacement string, + // which is the second argument. + // + Regex regEx = new Regex(args[0]); + string replacement = args[1]; + + // + // NOTE: Attempt to convert the third argument to a boolean. + // + bool matchingOnly; + + if (!bool.TryParse(args[2], out matchingOnly)) + { + Error(null, true); + return (int)ExitCode.BadMatchingOnlyFlag; + } + + // + // NOTE: Grab the standard input and output channels from the + // console. + // + TextReader inputTextReader = Console.In; + TextWriter outputTextWriter = Console.Out; + + // + // NOTE: Loop until end-of-file is hit on the standard input + // stream. + // + while (true) + { + // + // NOTE: Read a line from the standard input channel. If + // null is returned here, there is no more input and + // we are done. + // + string inputLine = inputTextReader.ReadLine(); + + if (inputLine == null) + break; + + // + // NOTE: Perform regular expression replacements on this + // line, if any. Then, write the modified line to + // the standard output channel. + // + string outputLine = regEx.Replace(inputLine, replacement); + + if (!matchingOnly || !String.Equals( + inputLine, outputLine, StringComparison.Ordinal)) + { + outputTextWriter.WriteLine(outputLine); + } + } + + // + // NOTE: At this point, everything has succeeded. + // + return (int)ExitCode.Success; + } + catch (Exception e) + { + // + // NOTE: An exception was caught. Report it via the console + // and return failure. + // + Error(e.ToString(), false); + return (int)ExitCode.Exception; + } + } + #endregion + } +} diff --git a/tool/mkautoconfamal.sh b/tool/mkautoconfamal.sh index 75a0b09a4c..4864ee85c3 100644 --- a/tool/mkautoconfamal.sh +++ b/tool/mkautoconfamal.sh @@ -53,6 +53,7 @@ cp $TOP/sqlite3.1 $TMPSPACE cp $TOP/sqlite3.pc.in $TMPSPACE cp $TOP/src/shell.c $TMPSPACE cp $TOP/src/sqlite3.rc $TMPSPACE +cp $TOP/tool/Replace.cs $TMPSPACE cat $TMPSPACE/configure.ac | sed "s/--SQLITE-VERSION--/$VERSION/" > $TMPSPACE/tmp diff --git a/tool/mkmsvcmin.tcl b/tool/mkmsvcmin.tcl index 41754cd576..88e7f9184e 100644 --- a/tool/mkmsvcmin.tcl +++ b/tool/mkmsvcmin.tcl @@ -72,6 +72,21 @@ $(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H) $(LTRCOMPILE) -fo $(LIBRESOBJS) -DRC_VERONLY $(TOP)\sqlite3.rc }]] +# +# NOTE: This block is used to replace the section marked <> in +# the Makefile, if it exists. +# +set blocks(2) [string trimleft [string map [list \\\\ \\] { +Replace.exe: + $(CSC) /target:exe $(TOP)\Replace.cs + +sqlite3.def: Replace.exe $(LIBOBJ) + echo EXPORTS > sqlite3.def + dumpbin /all $(LIBOBJ) \\ + | .\Replace.exe "^\s+/EXPORT:_?(sqlite3_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \\ + | sort >> sqlite3.def +}]] + set data "#### DO NOT EDIT ####\n" append data "# This makefile is automatically " append data "generated from the [file tail $fromFileName] at\n" @@ -90,8 +105,6 @@ foreach i [lsort -integer [array names blocks]] { } set data [string map [list " -I\$(TOP)\\src" ""] $data] -set data [string map [list " /DEF:sqlite3.def" ""] $data] -set data [string map [list " sqlite3.def" ""] $data] set data [string map [list " libsqlite3.lib" ""] $data] set data [string map [list " \$(ALL_TCL_TARGETS)" ""] $data] set data [string map [list "\$(TOP)\\src\\" "\$(TOP)\\"] $data] From fee1e8d3176ec188fff82b38954da0d8f3cd80f1 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 27 Feb 2016 00:07:18 +0000 Subject: [PATCH 366/570] Make sure the Replace.cs file is included in the autoconf tarball. FossilOrigin-Name: b850df483d4dfc677ec61b119d8c1162b6a823d6 --- autoconf/Makefile.am | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/autoconf/Makefile.am b/autoconf/Makefile.am index 0e09cfcd95..7b6934adde 100644 --- a/autoconf/Makefile.am +++ b/autoconf/Makefile.am @@ -13,7 +13,7 @@ sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS include_HEADERS = sqlite3.h sqlite3ext.h -EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt +EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs pkgconfigdir = ${libdir}/pkgconfig pkgconfig_DATA = sqlite3.pc diff --git a/manifest b/manifest index 1c5c27a015..5cf128e470 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Support\sgenerating\sthe\s'.def'\sfile\susing\sthe\sautoconf\sMakefile\sfor\sMSVC. -D 2016-02-26T23:13:16.711 +C Make\ssure\sthe\sReplace.cs\sfile\sis\sincluded\sin\sthe\sautoconf\starball. +D 2016-02-27T00:07:18.719 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc b6eb7a434c2e160a042036bd5047c3bd89eedacc @@ -10,7 +10,7 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 -F autoconf/Makefile.am 29e2a6e8d0c5e32723a48b4faf6b168854dde5f4 +F autoconf/Makefile.am 4b8bd7896fffb6b22a57747f1f98cba1da9108ae F autoconf/Makefile.msc 91fe02447e4a90b9368b2b1406d51ee5f7e83c6a F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1 @@ -1451,7 +1451,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 b8dc1b9f5d413000387bfe784b69f5d0ee5c0489 -R e824451697993aa684f279d9331c397b -U mistachkin -Z bb33bef608d1de79741a7de07ef806b0 +P 3617564cb630ed418badf43d2c0291c11c166d12 +R 093da9a09b9ba8463976ad6bb6eea8a3 +U drh +Z 9a8d22871125a4adc384815a430d82c9 diff --git a/manifest.uuid b/manifest.uuid index 3c4acbdac1..34a75f85e9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3617564cb630ed418badf43d2c0291c11c166d12 \ No newline at end of file +b850df483d4dfc677ec61b119d8c1162b6a823d6 \ No newline at end of file From 62ab81001491f639eadb77dcf72076f882b4c4db Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sat, 27 Feb 2016 00:21:16 +0000 Subject: [PATCH 367/570] Fix typo in ICU error message. FossilOrigin-Name: 00c8fffd47cec763857389e1e91c026ba3179182 --- ext/icu/icu.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/icu/icu.c b/ext/icu/icu.c index 263cd98275..3f45646194 100644 --- a/ext/icu/icu.c +++ b/ext/icu/icu.c @@ -394,7 +394,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ if( !U_SUCCESS(status) ){ if( status==U_BUFFER_OVERFLOW_ERROR ) continue; icuFunctionError(p, - sqlite3_user_data(p) ? "u_strToUpper()" : "u_strToLower", status); + sqlite3_user_data(p) ? "u_strToUpper" : "u_strToLower", status); return; } } diff --git a/manifest b/manifest index 5cf128e470..8fd100b1fd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthe\sReplace.cs\sfile\sis\sincluded\sin\sthe\sautoconf\starball. -D 2016-02-27T00:07:18.719 +C Fix\stypo\sin\sICU\serror\smessage. +D 2016-02-27T00:21:16.746 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc b6eb7a434c2e160a042036bd5047c3bd89eedacc @@ -198,7 +198,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093 F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45 F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43 -F ext/icu/icu.c be1f90d8babafe6d1a55a6912161bcac75baee0e +F ext/icu/icu.c 4bdf4c5daedabcd8e6eb6e6a377657f7b978f9f7 F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37 F ext/misc/amatch.c a1a8f66c29d40bd71b075546ddeddb477b17a2bb F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704 @@ -1451,7 +1451,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 3617564cb630ed418badf43d2c0291c11c166d12 -R 093da9a09b9ba8463976ad6bb6eea8a3 -U drh -Z 9a8d22871125a4adc384815a430d82c9 +P b850df483d4dfc677ec61b119d8c1162b6a823d6 +R d5cc203073b9c279291539df551306ee +U mistachkin +Z c6ab413d3c48c517b60705cf4b24dfd0 diff --git a/manifest.uuid b/manifest.uuid index 34a75f85e9..6a7495bec3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b850df483d4dfc677ec61b119d8c1162b6a823d6 \ No newline at end of file +00c8fffd47cec763857389e1e91c026ba3179182 \ No newline at end of file From fe41a98fd660727383882c40f199f892f0f1eff9 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sat, 27 Feb 2016 00:21:44 +0000 Subject: [PATCH 368/570] Add 'Replace.exe' to the MSVC clean target. FossilOrigin-Name: c2277fab12d2aecf9e0f69683741a194df17e854 --- Makefile.msc | 2 +- autoconf/Makefile.msc | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index db9c83c6c7..de225305f5 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -2048,7 +2048,7 @@ moreclean: clean clean: del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL - del /Q $(SQLITE3EXE) $(SQLITE3DLL) 2>NUL + del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL # <> del /Q sqlite3.c sqlite3.h 2>NUL del /Q opcodes.c opcodes.h 2>NUL diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index b453b93c33..ad829bffa0 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -943,4 +943,4 @@ $(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H) clean: del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL - del /Q $(SQLITE3EXE) $(SQLITE3DLL) 2>NUL + del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL diff --git a/manifest b/manifest index 8fd100b1fd..761f1250c8 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Fix\stypo\sin\sICU\serror\smessage. -D 2016-02-27T00:21:16.746 +C Add\s'Replace.exe'\sto\sthe\sMSVC\sclean\starget. +D 2016-02-27T00:21:44.269 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc b6eb7a434c2e160a042036bd5047c3bd89eedacc +F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION c6b1f51809551d60ad001e6d87cf3ab2c7f54b6f F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -11,7 +11,7 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 4b8bd7896fffb6b22a57747f1f98cba1da9108ae -F autoconf/Makefile.msc 91fe02447e4a90b9368b2b1406d51ee5f7e83c6a +F autoconf/Makefile.msc b8ada5177e6f39c126a88295af5ad0255e08d280 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1 F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8 @@ -1451,7 +1451,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 b850df483d4dfc677ec61b119d8c1162b6a823d6 -R d5cc203073b9c279291539df551306ee +P 00c8fffd47cec763857389e1e91c026ba3179182 +R 5d5d8a8010dbfa6bc274c104c226fec0 U mistachkin -Z c6ab413d3c48c517b60705cf4b24dfd0 +Z b85e54c141d3cf5bd3e41d9206ec3bb6 diff --git a/manifest.uuid b/manifest.uuid index 6a7495bec3..92117cb7f2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -00c8fffd47cec763857389e1e91c026ba3179182 \ No newline at end of file +c2277fab12d2aecf9e0f69683741a194df17e854 \ No newline at end of file From d892ac97bbf4bc8d32ec7b356f6d61dc6edf1f9b Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 27 Feb 2016 14:00:07 +0000 Subject: [PATCH 369/570] Enhance documentation of sqlite3_snapshot_open() to explain that the database connection must have participated in at least one read operation prior to the beginning of the transaction for which the snapshot is to be opened. Add test cases for this fact. FossilOrigin-Name: 33dd671cb9c17f08dbc61aed91e80eaeb84bfaf5 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/sqlite.h.in | 6 +++++- test/snapshot.test | 20 ++++++++++++++++++++ 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 761f1250c8..c218f74566 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\s'Replace.exe'\sto\sthe\sMSVC\sclean\starget. -D 2016-02-27T00:21:44.269 +C Enhance\sdocumentation\sof\ssqlite3_snapshot_open()\sto\sexplain\sthat\sthe\sdatabase\nconnection\smust\shave\sparticipated\sin\sat\sleast\sone\sread\soperation\sprior\sto\nthe\sbeginning\sof\sthe\stransaction\sfor\swhich\sthe\ssnapshot\sis\sto\sbe\sopened.\nAdd\stest\scases\sfor\sthis\sfact. +D 2016-02-27T14:00:07.182 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -351,7 +351,7 @@ F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 1bacfde7b7cec134d2b354cbcf67bafc67078431 F src/shell.c 89b73e894e737cc2f21e4bce0feb3ea21cc61124 -F src/sqlite.h.in 6bf029bcb077c6db633a77b7fda5ffd5b7c950b7 +F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d F src/sqliteInt.h 63c0e1b5b5d608a1ba2303fe3a554b859a120406 @@ -1034,7 +1034,7 @@ F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5 F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2 F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b -F test/snapshot.test 5ec4651d16c3d1eb6c010d102febe32b3614bf56 +F test/snapshot.test c03eb5ba1602df33c1edc1d12393d6ca7a282a46 F test/snapshot_fault.test 25973aeb1b86a280800e0bcf1eb5ce70e9ef57ab F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087 @@ -1451,7 +1451,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 00c8fffd47cec763857389e1e91c026ba3179182 -R 5d5d8a8010dbfa6bc274c104c226fec0 -U mistachkin -Z b85e54c141d3cf5bd3e41d9206ec3bb6 +P c2277fab12d2aecf9e0f69683741a194df17e854 +R d50b04aa37cc4844a3040bb1385bb8e7 +U drh +Z f370d53fd3d226317497efdfe8ae225f diff --git a/manifest.uuid b/manifest.uuid index 92117cb7f2..4954cc1e24 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c2277fab12d2aecf9e0f69683741a194df17e854 \ No newline at end of file +33dd671cb9c17f08dbc61aed91e80eaeb84bfaf5 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 60e2e3b61c..c81a9d0c43 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7968,7 +7968,11 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( ** the first operation, apart from other sqlite3_snapshot_open() calls, ** following the [BEGIN] that starts a new read transaction. ** ^A [snapshot] will fail to open if it has been overwritten by a -** [checkpoint]. +** [checkpoint]. +** ^A [snapshot] will fail to open if the database connection D has not +** previously completed at least one read operation against the database +** file. (Hint: Run "[PRAGMA application_id]" against a newly opened +** database connection in order to make it ready to use snapshots.) ** ** The [sqlite3_snapshot_open()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. diff --git a/test/snapshot.test b/test/snapshot.test index 63a0e30175..ba3a666796 100644 --- a/test/snapshot.test +++ b/test/snapshot.test @@ -334,6 +334,26 @@ do_test 6.3 { sqlite3_snapshot_open db2 main $::snapshot db2 eval { SELECT * FROM x1 } } {z zz zzz} +do_test 6.4 { + db2 close + sqlite3 db2 test.db + db2 eval "PRAGMA application_id" + db2 eval "BEGIN" + sqlite3_snapshot_open db2 main $::snapshot + db2 eval { SELECT * FROM x1 } +} {z zz zzz} + +# EVIDENCE-OF: R-55491-50411 A snapshot will fail to open if the +# database connection D has not previously completed at least one read +# operation against the database file. +# +do_test 6.5 { + db2 close + sqlite3 db2 test.db + db2 eval "BEGIN" + list [catch {sqlite3_snapshot_open db2 main $::snapshot} msg] $msg +} {1 SQLITE_ERROR} + sqlite3_snapshot_free $snapshot finish_test From 4f8f5e4446f9e49ef25b58d2dbc772f458d50b83 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 27 Feb 2016 14:04:27 +0000 Subject: [PATCH 370/570] Fix a requirement mark to conform to a typo fix in the documentation. FossilOrigin-Name: d1392c627934b89cdb86d82e73d56e8f76952b30 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/e_walhook.test | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index c218f74566..bd340d4ad4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sdocumentation\sof\ssqlite3_snapshot_open()\sto\sexplain\sthat\sthe\sdatabase\nconnection\smust\shave\sparticipated\sin\sat\sleast\sone\sread\soperation\sprior\sto\nthe\sbeginning\sof\sthe\stransaction\sfor\swhich\sthe\ssnapshot\sis\sto\sbe\sopened.\nAdd\stest\scases\sfor\sthis\sfact. -D 2016-02-27T14:00:07.182 +C Fix\sa\srequirement\smark\sto\sconform\sto\sa\stypo\sfix\sin\sthe\sdocumentation. +D 2016-02-27T14:04:27.011 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -617,7 +617,7 @@ F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9 F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625 F test/e_walauto.test 280714ddf14e1a47dcbc59d515cd0b026dfd5567 F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0 -F test/e_walhook.test da3ea8b3483d1af72190337bda50155a91a4b664 +F test/e_walhook.test 4c0613a0c76e7a9d5c4c211e1b4cbcc1143914df F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473 F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6 @@ -1451,7 +1451,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 c2277fab12d2aecf9e0f69683741a194df17e854 -R d50b04aa37cc4844a3040bb1385bb8e7 +P 33dd671cb9c17f08dbc61aed91e80eaeb84bfaf5 +R 262f28bf043321d0cb2a0438d4f47c13 U drh -Z f370d53fd3d226317497efdfe8ae225f +Z 7540cf66865728ef817082a1a3c276f6 diff --git a/manifest.uuid b/manifest.uuid index 4954cc1e24..6fe6cf3e16 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -33dd671cb9c17f08dbc61aed91e80eaeb84bfaf5 \ No newline at end of file +d1392c627934b89cdb86d82e73d56e8f76952b30 \ No newline at end of file diff --git a/test/e_walhook.test b/test/e_walhook.test index c8c8819493..c963524a97 100644 --- a/test/e_walhook.test +++ b/test/e_walhook.test @@ -161,10 +161,10 @@ do_test 5.2 { -# EVIDENCE-OF: R-42842-27162 Note that the sqlite3_wal_autocheckpoint() +# EVIDENCE-OF: R-57445-43425 Note that the sqlite3_wal_autocheckpoint() # interface and the wal_autocheckpoint pragma both invoke -# sqlite3_wal_hook() and will those overwrite any prior -# sqlite3_wal_hook() settings. +# sqlite3_wal_hook() and will overwrite any prior sqlite3_wal_hook() +# settings. # set ::old_wal_hook 0 proc my_old_wal_hook {args} { incr ::old_wal_hook ; return 0 } From 3478490332bab33437a00f3a4d94c0204acf7f8a Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 27 Feb 2016 17:12:36 +0000 Subject: [PATCH 371/570] Enhance the ".stats" command in sqlite3.exe to show one-time stats information if invoked with one argument. Also show /proc/PID/io information if run on Linux. FossilOrigin-Name: 3c36948f16b58fe8042c37d0df634308b4e48217 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/shell.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- test/shell1.test | 8 ++++---- test/shell4.test | 8 ++++---- 5 files changed, 62 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index bd340d4ad4..435c15b0a4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\srequirement\smark\sto\sconform\sto\sa\stypo\sfix\sin\sthe\sdocumentation. -D 2016-02-27T14:04:27.011 +C Enhance\sthe\s".stats"\scommand\sin\ssqlite3.exe\sto\sshow\sone-time\sstats\sinformation\nif\sinvoked\swith\sone\sargument.\s\sAlso\sshow\s/proc/PID/io\sinformation\sif\srun\son\nLinux. +D 2016-02-27T17:12:36.918 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -350,7 +350,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 1bacfde7b7cec134d2b354cbcf67bafc67078431 -F src/shell.c 89b73e894e737cc2f21e4bce0feb3ea21cc61124 +F src/shell.c f30efdd675007ec6006d51193fc47aabda2984a5 F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d @@ -1020,10 +1020,10 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test ce5e744870387164703bf2dee2cc9753e4a71513 +F test/shell1.test a45b424ec23a4b946848ff9e1af5186c677162ab F test/shell2.test 12b8bf901b0e3a8ac58cf5c0c63a0a388d4d1862 F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29 -F test/shell4.test ddf0a99044e2245a87fc17423e3aaa1445b3243b +F test/shell4.test f43e250139dc5dc5f0f2ec1752c50284a1ede102 F test/shell5.test c04e9f9f948305706b88377c464c7f08ce7479f9 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5 @@ -1451,7 +1451,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 33dd671cb9c17f08dbc61aed91e80eaeb84bfaf5 -R 262f28bf043321d0cb2a0438d4f47c13 +P d1392c627934b89cdb86d82e73d56e8f76952b30 +R cc008a8c941c26feeb254cac8325586b U drh -Z 7540cf66865728ef817082a1a3c276f6 +Z 0f34ce71f4553990685c1f98cc5c169c diff --git a/manifest.uuid b/manifest.uuid index 6fe6cf3e16..31a87c6516 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d1392c627934b89cdb86d82e73d56e8f76952b30 \ No newline at end of file +3c36948f16b58fe8042c37d0df634308b4e48217 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 95b75fa877..303fd008ad 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1284,6 +1284,43 @@ static char *save_err_msg( return zErrMsg; } +#ifdef __linux__ +/* +** Attempt to display I/O stats on Linux using /proc/PID/io +*/ +static void displayLinuxIoStats(FILE *out){ + FILE *in; + char z[200]; + sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid()); + in = fopen(z, "rb"); + if( in==0 ) return; + while( fgets(z, sizeof(z), in)!=0 ){ + static const struct { + const char *zPattern; + const char *zDesc; + } aTrans[] = { + { "rchar: ", "Number of bytes received by read():" }, + { "wchar: ", "Number of bytes sent to write():" }, + { "syscr: ", "Number of read() system calls:" }, + { "syscw: ", "Number of write() system calls:" }, + { "read_bytes: ", "Number of bytes from storage:" }, + { "write_bytes: ", "Number of bytes sent to storage:" }, + { "cancelled_write_bytes: ", "Cancelled write bytes:" }, + }; + int i; + for(i=0; iout, "Virtual Machine Steps: %d\n", iCur); } +#ifdef __linux__ + displayLinuxIoStats(pArg->out); +#endif + /* Do not remove this machine readable comment: extra-stats-output-here */ return 0; @@ -1957,7 +1998,7 @@ static char zHelp[] = " separator for both the output mode and .import\n" ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" ".show Show the current values for various settings\n" - ".stats on|off Turn stats on or off\n" + ".stats ?on|off? Show stats or turn stats on or off\n" ".system CMD ARGS... Run CMD ARGS... in a system shell\n" ".tables ?TABLE? List names of tables\n" " If TABLE specified, only list tables matching\n" @@ -3835,8 +3876,10 @@ static int do_meta_command(char *zLine, ShellState *p){ if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){ if( nArg==2 ){ p->statsOn = booleanValue(azArg[1]); + }else if( nArg==1 ){ + display_stats(p->db, p, 0); }else{ - raw_printf(stderr, "Usage: .stats on|off\n"); + raw_printf(stderr, "Usage: .stats ?on|off?\n"); rc = 1; } }else diff --git a/test/shell1.test b/test/shell1.test index 2fda62ee13..1b9ea1d383 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -625,9 +625,9 @@ do_test shell1-3.23.2 { } {1 {Usage: .show}} # .stats ON|OFF Turn stats on or off -do_test shell1-3.23b.1 { - catchcmd "test.db" ".stats" -} {1 {Usage: .stats on|off}} +#do_test shell1-3.23b.1 { +# catchcmd "test.db" ".stats" +#} {1 {Usage: .stats on|off}} do_test shell1-3.23b.2 { catchcmd "test.db" ".stats ON" } {0 {}} @@ -637,7 +637,7 @@ do_test shell1-3.23b.3 { do_test shell1-3.23b.4 { # too many arguments catchcmd "test.db" ".stats OFF BAD" -} {1 {Usage: .stats on|off}} +} {1 {Usage: .stats ?on|off?}} # .tables ?TABLE? List names of tables # If TABLE specified, only list tables matching diff --git a/test/shell4.test b/test/shell4.test index fcb0b2b715..18e7d7fdf6 100644 --- a/test/shell4.test +++ b/test/shell4.test @@ -61,9 +61,9 @@ do_test shell4-1.2.2 { } {0} # .stats ON|OFF Turn stats on or off -do_test shell4-1.3.1 { - catchcmd "test.db" ".stats" -} {1 {Usage: .stats on|off}} +#do_test shell4-1.3.1 { +# catchcmd "test.db" ".stats" +#} {1 {Usage: .stats on|off}} do_test shell4-1.3.2 { catchcmd "test.db" ".stats ON" } {0 {}} @@ -73,7 +73,7 @@ do_test shell4-1.3.3 { do_test shell4-1.3.4 { # too many arguments catchcmd "test.db" ".stats OFF BAD" -} {1 {Usage: .stats on|off}} +} {1 {Usage: .stats ?on|off?}} # NB. whitespace is important do_test shell4-1.4.1 { From fc1a84c57b52c582cb87e00a1366f6a4ee232b02 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 27 Feb 2016 19:19:22 +0000 Subject: [PATCH 372/570] Tighter description of I/O stats in the shell. Show I/O stats on speedtest1.c. FossilOrigin-Name: f681d800340e0e710f73d0f7c09101f899249183 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c | 14 +++++++------- test/speedtest1.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 435c15b0a4..706e06deb0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\s".stats"\scommand\sin\ssqlite3.exe\sto\sshow\sone-time\sstats\sinformation\nif\sinvoked\swith\sone\sargument.\s\sAlso\sshow\s/proc/PID/io\sinformation\sif\srun\son\nLinux. -D 2016-02-27T17:12:36.918 +C Tighter\sdescription\sof\sI/O\sstats\sin\sthe\sshell.\s\sShow\sI/O\sstats\son\sspeedtest1.c. +D 2016-02-27T19:19:22.849 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -350,7 +350,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 1bacfde7b7cec134d2b354cbcf67bafc67078431 -F src/shell.c f30efdd675007ec6006d51193fc47aabda2984a5 +F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d @@ -1052,7 +1052,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523 F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b -F test/speedtest1.c 947421c324f5cd4cb3dcae1ec214e4be763df718 +F test/speedtest1.c 1478cb3fb64ad30f291ddca87ca9dbd72ff552aa F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3 F test/spellfix3.test f7bf7b3482971473d32b6b00f6944c5c066cff97 @@ -1451,7 +1451,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 d1392c627934b89cdb86d82e73d56e8f76952b30 -R cc008a8c941c26feeb254cac8325586b +P 3c36948f16b58fe8042c37d0df634308b4e48217 +R 2b473c8c6b36608ca875feba0d8cbb83 U drh -Z 0f34ce71f4553990685c1f98cc5c169c +Z 565e8454d2408a569a86791d9e6b12a6 diff --git a/manifest.uuid b/manifest.uuid index 31a87c6516..546a6418d6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3c36948f16b58fe8042c37d0df634308b4e48217 \ No newline at end of file +f681d800340e0e710f73d0f7c09101f899249183 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 303fd008ad..789a464d09 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1299,13 +1299,13 @@ static void displayLinuxIoStats(FILE *out){ const char *zPattern; const char *zDesc; } aTrans[] = { - { "rchar: ", "Number of bytes received by read():" }, - { "wchar: ", "Number of bytes sent to write():" }, - { "syscr: ", "Number of read() system calls:" }, - { "syscw: ", "Number of write() system calls:" }, - { "read_bytes: ", "Number of bytes from storage:" }, - { "write_bytes: ", "Number of bytes sent to storage:" }, - { "cancelled_write_bytes: ", "Cancelled write bytes:" }, + { "rchar: ", "Bytes received by read():" }, + { "wchar: ", "Bytes sent to write():" }, + { "syscr: ", "Read() system calls:" }, + { "syscw: ", "Write() system calls:" }, + { "read_bytes: ", "Bytes read from storage:" }, + { "write_bytes: ", "Bytes written to storage:" }, + { "cancelled_write_bytes: ", "Cancelled write bytes:" }, }; int i; for(i=0; i +#include + +/* +** Attempt to display I/O stats on Linux using /proc/PID/io +*/ +static void displayLinuxIoStats(FILE *out){ + FILE *in; + char z[200]; + sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid()); + in = fopen(z, "rb"); + if( in==0 ) return; + while( fgets(z, sizeof(z), in)!=0 ){ + static const struct { + const char *zPattern; + const char *zDesc; + } aTrans[] = { + { "rchar: ", "Bytes received by read():" }, + { "wchar: ", "Bytes sent to write():" }, + { "syscr: ", "Read() system calls:" }, + { "syscw: ", "Write() system calls:" }, + { "read_bytes: ", "Bytes rcvd from storage:" }, + { "write_bytes: ", "Bytes sent to storage:" }, + { "cancelled_write_bytes: ", "Cancelled write bytes:" }, + }; + int i; + for(i=0; i Date: Sat, 27 Feb 2016 20:14:55 +0000 Subject: [PATCH 373/570] Extend the code in memjournal.c so that it subsumes the role of journal.c. And (untested) can flush journal or statement journal files to disk after they grow to a specified size. FossilOrigin-Name: e0b0b4316531fc8afa74b4882d9c74a91030ec69 --- manifest | 25 ++-- manifest.uuid | 2 +- src/journal.c | 2 + src/memjournal.c | 362 ++++++++++++++++++++++++++++++++++------------- src/os.c | 2 +- src/pager.c | 24 +--- src/sqliteInt.h | 5 +- 7 files changed, 288 insertions(+), 134 deletions(-) diff --git a/manifest b/manifest index 706e06deb0..7546ccd6d9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Tighter\sdescription\sof\sI/O\sstats\sin\sthe\sshell.\s\sShow\sI/O\sstats\son\sspeedtest1.c. -D 2016-02-27T19:19:22.849 +C Extend\sthe\scode\sin\smemjournal.c\sso\sthat\sit\ssubsumes\sthe\srole\sof\sjournal.c.\sAnd\s(untested)\scan\sflush\sjournal\sor\sstatement\sjournal\sfiles\sto\sdisk\safter\sthey\sgrow\sto\sa\sspecified\ssize. +D 2016-02-27T20:14:55.339 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -311,7 +311,7 @@ F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c 9ca97272e9f74ed0efddf3b4350ee12740cebbef -F src/journal.c fe3a3e2559ce3ce9d371afd30fbabbc074174575 +F src/journal.c 673cbdde5676eb0c55848f561575d45b609c820d F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f F src/main.c be9309f442ec291177642d2e48e82290e0951f4b @@ -321,7 +321,7 @@ F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memjournal.c 349a04fb803db40532cde0993e39758f1acaecce +F src/memjournal.c 8d045e50120e9988e63bb0af69187e1e5e35122f F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 @@ -329,14 +329,14 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4 F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23 F src/mutex_w32.c 5e6fe1c298fb5a8a15aaed4161d5759311431c17 F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7 -F src/os.c ca9a104b677328ee037cfdf1a54a16fd1805e8c9 +F src/os.c f89e3ca1c2e3d5015b847aec60371c474acbac82 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 3a6f20736dfb8a0949cdd66553fdf59f6604be35 F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c d034c69b958c01289eb8070cbf902e1a68cd7e0b +F src/pager.c e2bf43b506447d649e9d9266e988007ae7248699 F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 F src/parse.y c3ce2c4a7cbf0b699239be6b2a945c5cb51875e2 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df @@ -354,7 +354,7 @@ F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 63c0e1b5b5d608a1ba2303fe3a554b859a120406 +F src/sqliteInt.h 3c4ed7e5dcb8b7d4cd4ab258ee7d0e0d0368f014 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1451,7 +1451,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 3c36948f16b58fe8042c37d0df634308b4e48217 -R 2b473c8c6b36608ca875feba0d8cbb83 -U drh -Z 565e8454d2408a569a86791d9e6b12a6 +P f681d800340e0e710f73d0f7c09101f899249183 +R f456c30e495865d50fc2c9c2ddb305ed +T *branch * memjournal-exp +T *sym-memjournal-exp * +T -sym-trunk * +U dan +Z dad681f00ca4c98b68e43d3727f3c92e diff --git a/manifest.uuid b/manifest.uuid index 546a6418d6..b15150144a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f681d800340e0e710f73d0f7c09101f899249183 \ No newline at end of file +e0b0b4316531fc8afa74b4882d9c74a91030ec69 \ No newline at end of file diff --git a/src/journal.c b/src/journal.c index a5cf8c8e2f..da59db0e50 100644 --- a/src/journal.c +++ b/src/journal.c @@ -24,6 +24,7 @@ ** buffer, or ** 2) The sqlite3JournalCreate() function is called. */ +#if 0 #ifdef SQLITE_ENABLE_ATOMIC_WRITE #include "sqliteInt.h" @@ -254,3 +255,4 @@ int sqlite3JournalSize(sqlite3_vfs *pVfs){ return (pVfs->szOsFile+sizeof(JournalFile)); } #endif +#endif diff --git a/src/memjournal.c b/src/memjournal.c index 62594530e0..6e1bf4edf7 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -21,24 +21,28 @@ typedef struct MemJournal MemJournal; typedef struct FilePoint FilePoint; typedef struct FileChunk FileChunk; -/* Space to hold the rollback journal is allocated in increments of -** this many bytes. -** -** The size chosen is a little less than a power of two. That way, -** the FileChunk object will have a size that almost exactly fills -** a power-of-two allocation. This minimizes wasted space in power-of-two -** memory allocators. -*/ -#define JOURNAL_CHUNKSIZE ((int)(1024-sizeof(FileChunk*))) - /* ** The rollback journal is composed of a linked list of these structures. +** +** The zChunk array is always at least 8 bytes in size - usually much more. +** Its actual size is stored in the MemJournal.nChunkSize variable. */ struct FileChunk { FileChunk *pNext; /* Next chunk in the journal */ - u8 zChunk[JOURNAL_CHUNKSIZE]; /* Content of this chunk */ + u8 zChunk[8]; /* Content of this chunk */ }; +/* +** By default, allocate this many bytes of memory for each FileChunk object. +*/ +#define MEMJOURNAL_DFLT_FILECHUNKSIZE 1024 + +/* +** For chunk size nChunkSize, return the number of bytes that should +** be allocated for each FileChunk structure. +*/ +#define fileChunkSize(nChunkSize) (sizeof(FileChunk) + ((nChunkSize)-8)) + /* ** An instance of this object serves as a cursor into the rollback journal. ** The cursor can be either for reading or writing. @@ -49,14 +53,23 @@ struct FilePoint { }; /* -** This subclass is a subclass of sqlite3_file. Each open memory-journal +** This structure is a subclass of sqlite3_file. Each open memory-journal ** is an instance of this class. */ struct MemJournal { - sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */ + const sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */ + int nChunkSize; /* In-memory chunk-size */ + + int nBuf; /* Bytes of data before flushing */ + int nSize; /* Bytes of data currently in memory */ FileChunk *pFirst; /* Head of in-memory chunk-list */ FilePoint endpoint; /* Pointer to the end of the file */ FilePoint readpoint; /* Pointer to the end of the last xRead() */ + + int flags; /* xOpen flags */ + sqlite3_vfs *pVfs; /* The "real" underlying VFS */ + const char *zJournal; /* Name of the journal file */ + sqlite3_file *pReal; /* The "real" underlying file descriptor */ }; /* @@ -70,41 +83,96 @@ static int memjrnlRead( sqlite_int64 iOfst /* Begin reading at this offset */ ){ MemJournal *p = (MemJournal *)pJfd; - u8 *zOut = zBuf; - int nRead = iAmt; - int iChunkOffset; - FileChunk *pChunk; - - /* SQLite never tries to read past the end of a rollback journal file */ - assert( iOfst+iAmt<=p->endpoint.iOffset ); - - if( p->readpoint.iOffset!=iOfst || iOfst==0 ){ - sqlite3_int64 iOff = 0; - for(pChunk=p->pFirst; - ALWAYS(pChunk) && (iOff+JOURNAL_CHUNKSIZE)<=iOfst; - pChunk=pChunk->pNext - ){ - iOff += JOURNAL_CHUNKSIZE; - } + if( p->pReal ){ + return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); + }else if( (iAmt+iOfst)>p->endpoint.iOffset ){ + return SQLITE_IOERR_SHORT_READ; }else{ - pChunk = p->readpoint.pChunk; - } + u8 *zOut = zBuf; + int nRead = iAmt; + int iChunkOffset; + FileChunk *pChunk; - iChunkOffset = (int)(iOfst%JOURNAL_CHUNKSIZE); - do { - int iSpace = JOURNAL_CHUNKSIZE - iChunkOffset; - int nCopy = MIN(nRead, (JOURNAL_CHUNKSIZE - iChunkOffset)); - memcpy(zOut, &pChunk->zChunk[iChunkOffset], nCopy); - zOut += nCopy; - nRead -= iSpace; - iChunkOffset = 0; - } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 ); - p->readpoint.iOffset = iOfst+iAmt; - p->readpoint.pChunk = pChunk; + if( p->readpoint.iOffset!=iOfst || iOfst==0 ){ + sqlite3_int64 iOff = 0; + for(pChunk=p->pFirst; + ALWAYS(pChunk) && (iOff+p->nChunkSize)<=iOfst; + pChunk=pChunk->pNext + ){ + iOff += p->nChunkSize; + } + }else{ + pChunk = p->readpoint.pChunk; + } + + iChunkOffset = (int)(iOfst%p->nChunkSize); + do { + int iSpace = p->nChunkSize - iChunkOffset; + int nCopy = MIN(nRead, (p->nChunkSize - iChunkOffset)); + memcpy(zOut, &pChunk->zChunk[iChunkOffset], nCopy); + zOut += nCopy; + nRead -= iSpace; + iChunkOffset = 0; + } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 ); + p->readpoint.iOffset = iOfst+iAmt; + p->readpoint.pChunk = pChunk; + } return SQLITE_OK; } +/* +** Free the list of FileChunk structures headed at MemJournal.pFirst. +*/ +static void memjrnlFreeChunks(MemJournal *p){ + FileChunk *pIter; + FileChunk *pNext; + for(pIter=p->pFirst; pIter; pIter=pNext){ + pNext = pIter->pNext; + sqlite3_free(pIter); + } + p->pFirst = 0; +} + +/* +** Flush the contents of memory to a real file on disk. +*/ +static int createFile(MemJournal *p){ + int rc = SQLITE_OK; + if( !p->pReal ){ + sqlite3_file *pReal = (sqlite3_file *)&p[1]; + rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0); + if( rc==SQLITE_OK ){ + int nChunk = p->nChunkSize; + i64 iOff = 0; + FileChunk *pIter; + p->pReal = pReal; + for(pIter=p->pFirst; pIter && rc==SQLITE_OK; pIter=pIter->pNext){ + int nWrite = nChunk; + if( pIter==p->endpoint.pChunk ){ + nWrite = p->endpoint.iOffset % p->nChunkSize; + if( nWrite==0 ) nWrite = p->nChunkSize; + } + rc = sqlite3OsWrite(pReal, pIter->zChunk, nWrite, iOff); + iOff += nWrite; + } + if( rc!=SQLITE_OK ){ + /* If an error occurred while writing to the file, close it before + ** returning. This way, SQLite uses the in-memory journal data to + ** roll back changes made to the internal page-cache before this + ** function was called. */ + sqlite3OsClose(pReal); + p->pReal = 0; + }else{ + /* No error has occurred. Free the in-memory buffers. */ + memjrnlFreeChunks(p); + } + } + } + return rc; +} + + /* ** Write data to the file. */ @@ -118,38 +186,61 @@ static int memjrnlWrite( int nWrite = iAmt; u8 *zWrite = (u8 *)zBuf; - /* An in-memory journal file should only ever be appended to. Random - ** access writes are not required by sqlite. - */ - assert( iOfst==p->endpoint.iOffset ); - UNUSED_PARAMETER(iOfst); + /* If the file has already been created on disk. */ + if( p->pReal ){ + return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); + } - while( nWrite>0 ){ - FileChunk *pChunk = p->endpoint.pChunk; - int iChunkOffset = (int)(p->endpoint.iOffset%JOURNAL_CHUNKSIZE); - int iSpace = MIN(nWrite, JOURNAL_CHUNKSIZE - iChunkOffset); - - if( iChunkOffset==0 ){ - /* New chunk is required to extend the file. */ - FileChunk *pNew = sqlite3_malloc(sizeof(FileChunk)); - if( !pNew ){ - return SQLITE_IOERR_NOMEM_BKPT; - } - pNew->pNext = 0; - if( pChunk ){ - assert( p->pFirst ); - pChunk->pNext = pNew; - }else{ - assert( !p->pFirst ); - p->pFirst = pNew; - } - p->endpoint.pChunk = pNew; + /* If the file should be created now. */ + else if( p->nBuf>0 && (iAmt+iOfst)>p->nBuf ){ + int rc = createFile(p); + if( rc==SQLITE_OK ){ + rc = memjrnlWrite(pJfd, zBuf, iAmt, iOfst); } + return rc; + } - memcpy(&p->endpoint.pChunk->zChunk[iChunkOffset], zWrite, iSpace); - zWrite += iSpace; - nWrite -= iSpace; - p->endpoint.iOffset += iSpace; + /* If the contents of this write should be stored in memory */ + else{ + /* An in-memory journal file should only ever be appended to. Random + ** access writes are not required. The only exception to this is when + ** the in-memory journal is being used by a connection using the + ** atomic-write optimization. In this case the first 28 bytes of the + ** journal file may be written as part of committing the transaction. */ + assert( iOfst==p->endpoint.iOffset || iOfst==0 ); + if( iOfst==0 && p->pFirst ){ + assert( p->nChunkSize>iAmt ); + memcpy(p->pFirst->zChunk, zBuf, iAmt); + }else{ + while( nWrite>0 ){ + FileChunk *pChunk = p->endpoint.pChunk; + int iChunkOffset = (int)(p->endpoint.iOffset%p->nChunkSize); + int iSpace = MIN(nWrite, p->nChunkSize - iChunkOffset); + + if( iChunkOffset==0 ){ + /* New chunk is required to extend the file. */ + FileChunk *pNew = sqlite3_malloc(fileChunkSize(p->nChunkSize)); + if( !pNew ){ + return SQLITE_IOERR_NOMEM_BKPT; + } + pNew->pNext = 0; + if( pChunk ){ + assert( p->pFirst ); + pChunk->pNext = pNew; + }else{ + assert( !p->pFirst ); + p->pFirst = pNew; + } + p->endpoint.pChunk = pNew; + } + + memcpy(&p->endpoint.pChunk->zChunk[iChunkOffset], zWrite, iSpace); + zWrite += iSpace; + nWrite -= iSpace; + p->endpoint.iOffset += iSpace; + } + p->nSize = iAmt + iOfst; + } } return SQLITE_OK; @@ -160,16 +251,16 @@ static int memjrnlWrite( */ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ MemJournal *p = (MemJournal *)pJfd; - FileChunk *pChunk; - assert(size==0); - UNUSED_PARAMETER(size); - pChunk = p->pFirst; - while( pChunk ){ - FileChunk *pTmp = pChunk; - pChunk = pChunk->pNext; - sqlite3_free(pTmp); + if( p->pReal ){ + return sqlite3OsTruncate(p->pReal, size); + }else if( size==0 ){ + memjrnlFreeChunks(p); + p->nSize = 0; + p->endpoint.pChunk = 0; + p->endpoint.iOffset = 0; + p->readpoint.pChunk = 0; + p->readpoint.iOffset = 0; } - sqlite3MemJournalOpen(pJfd); return SQLITE_OK; } @@ -177,21 +268,23 @@ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ ** Close the file. */ static int memjrnlClose(sqlite3_file *pJfd){ - memjrnlTruncate(pJfd, 0); + MemJournal *p = (MemJournal *)pJfd; + memjrnlFreeChunks(p); + if( p->pReal ) sqlite3OsClose(p->pReal); return SQLITE_OK; } - /* ** Sync the file. ** -** Syncing an in-memory journal is a no-op. And, in fact, this routine -** is never called in a working implementation. This implementation -** exists purely as a contingency, in case some malfunction in some other -** part of SQLite causes Sync to be called by mistake. +** If the real file has been created, call its xSync method. Otherwise, +** syncing an in-memory journal is a no-op. */ -static int memjrnlSync(sqlite3_file *NotUsed, int NotUsed2){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); +static int memjrnlSync(sqlite3_file *pJfd, int flags){ + MemJournal *p = (MemJournal *)pJfd; + if( p->pReal ){ + return sqlite3OsSync(p->pReal, flags); + } return SQLITE_OK; } @@ -200,6 +293,9 @@ static int memjrnlSync(sqlite3_file *NotUsed, int NotUsed2){ */ static int memjrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){ MemJournal *p = (MemJournal *)pJfd; + if( p->pReal ){ + return sqlite3OsFileSize(p->pReal, pSize); + } *pSize = (sqlite_int64) p->endpoint.iOffset; return SQLITE_OK; } @@ -230,26 +326,92 @@ static const struct sqlite3_io_methods MemJournalMethods = { }; /* -** Open a journal file. +** Open a journal file. +** +** The behaviour of the journal file depends on the value of parameter +** nBuf. If nBuf is 0, then the journal file is always create and +** accessed using the underlying VFS. If nBuf is less than zero, then +** all content is always stored in main-memory. Finally, if nBuf is a +** positive value, then the journal file is initially created in-memory +** but may be flushed to disk later on. In this case the journal file is +** flushed to disk either when it grows larger than nBuf bytes in size, +** or when sqlite3JournalCreate() is called. */ -void sqlite3MemJournalOpen(sqlite3_file *pJfd){ - MemJournal *p = (MemJournal *)pJfd; - assert( EIGHT_BYTE_ALIGNMENT(p) ); - memset(p, 0, sqlite3MemJournalSize()); - p->pMethod = (sqlite3_io_methods*)&MemJournalMethods; +int sqlite3JournalOpen( + sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */ + const char *zName, /* Name of the journal file */ + sqlite3_file *pJfd, /* Preallocated, blank file handle */ + int flags, /* Opening flags */ + int nBuf /* Bytes buffered before opening the file */ +){ + MemJournal *p = (MemJournal*)pJfd; + + /* Zero the file-handle object. If nBuf was passed zero, initialize + ** it using the sqlite3OsOpen() function of the underlying VFS. In this + ** case none of the code in this module is executed as a result of calls + ** made on the journal file-handle. */ + memset(p, 0, sizeof(MemJournal)); + if( nBuf==0 ){ + return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); + } + + if( nBuf>0 ){ + p->nChunkSize = nBuf; + }else{ + p->nChunkSize = 8 + MEMJOURNAL_DFLT_FILECHUNKSIZE - sizeof(FileChunk); + assert( MEMJOURNAL_DFLT_FILECHUNKSIZE==fileChunkSize(p->nChunkSize) ); + } + + p->pMethod = (const sqlite3_io_methods*)&MemJournalMethods; + p->nBuf = nBuf; + p->flags = flags; + p->zJournal = zName; + p->pVfs = pVfs; + return SQLITE_OK; } /* -** Return true if the file-handle passed as an argument is -** an in-memory journal +** Open an in-memory journal file. +*/ +void sqlite3MemJournalOpen(sqlite3_file *pJfd){ + sqlite3JournalOpen(0, 0, pJfd, 0, -1); +} + +/* +** Return true if the file-handle passed as an argument is an in-memory +** journal. */ int sqlite3IsMemJournal(sqlite3_file *pJfd){ - return pJfd->pMethods==&MemJournalMethods; + return pJfd->pMethods==&MemJournalMethods && ((MemJournal*)pJfd)->pReal==0; +} + +/* +** If the argument p points to a MemJournal structure that is not an +** in-memory-only journal file, and the underlying file has not yet been +** created, create it now. +*/ +int sqlite3JournalCreate(sqlite3_file *p){ + int rc = SQLITE_OK; + if( p->pMethods==&MemJournalMethods && ((MemJournal*)p)->nBuf>=0 ){ + rc = createFile((MemJournal*)p); + } + return rc; +} + +/* +** The file-handle passed as teh only argument is open on a journal file. +** Return true if this "journal file" is actually stored in heap memory, +** or false otherwise. +*/ +int sqlite3JournalIsInMemory(sqlite3_file *p){ + return p->pMethods==&MemJournalMethods && ((MemJournal*)p)->pReal==0; } /* -** Return the number of bytes required to store a MemJournal file descriptor. +** Return the number of bytes required to store a JournalFile that uses vfs +** pVfs to create the underlying on-disk files. */ -int sqlite3MemJournalSize(void){ - return sizeof(MemJournal); +int sqlite3JournalSize(sqlite3_vfs *pVfs){ + return pVfs->szOsFile + sizeof(MemJournal); } + diff --git a/src/os.c b/src/os.c index 2fd44abf85..eed7828538 100644 --- a/src/os.c +++ b/src/os.c @@ -66,7 +66,7 @@ int sqlite3_open_file_count = 0; #if defined(SQLITE_TEST) int sqlite3_memdebug_vfs_oom_test = 1; #define DO_OS_MALLOC_TEST(x) \ - if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3IsMemJournal(x))) { \ + if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3JournalIsInMemory(x))) { \ void *pTstAlloc = sqlite3Malloc(10); \ if (!pTstAlloc) return SQLITE_IOERR_NOMEM_BKPT; \ sqlite3_free(pTstAlloc); \ diff --git a/src/pager.c b/src/pager.c index 51bd45e486..5998a57831 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1724,7 +1724,7 @@ static void releaseAllSavepoints(Pager *pPager){ for(ii=0; iinSavepoint; ii++){ sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); } - if( !pPager->exclusiveMode || sqlite3IsMemJournal(pPager->sjfd) ){ + if( !pPager->exclusiveMode || sqlite3JournalIsInMemory(pPager->sjfd) ){ sqlite3OsClose(pPager->sjfd); } sqlite3_free(pPager->aSavepoint); @@ -1962,8 +1962,8 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ assert( !pagerUseWal(pPager) ); /* Finalize the journal file. */ - if( sqlite3IsMemJournal(pPager->jfd) ){ - assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ); + if( sqlite3JournalIsInMemory(pPager->jfd) ){ + /* assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ); */ sqlite3OsClose(pPager->jfd); }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){ if( pPager->journalOff==0 ){ @@ -1991,7 +1991,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ ** file should be closed and deleted. If this connection writes to ** the database file, it will do so using an in-memory journal. */ - int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd)); + int bDelete = (!pPager->tempFile&&!sqlite3JournalIsInMemory(pPager->jfd)); assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE || pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->journalMode==PAGER_JOURNALMODE_WAL @@ -4578,18 +4578,8 @@ int sqlite3PagerOpen( int nUri = 0; /* Number of bytes of URI args at *zUri */ /* Figure out how much space is required for each journal file-handle - ** (there are two of them, the main journal and the sub-journal). This - ** is the maximum space required for an in-memory journal file handle - ** and a regular journal file-handle. Note that a "regular journal-handle" - ** may be a wrapper capable of caching the first portion of the journal - ** file in memory to implement the atomic-write optimization (see - ** source file journal.c). - */ - if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){ - journalFileSize = ROUND8(sqlite3JournalSize(pVfs)); - }else{ - journalFileSize = ROUND8(sqlite3MemJournalSize()); - } + ** (there are two of them, the main journal and the sub-journal). */ + journalFileSize = ROUND8(sqlite3JournalSize(pVfs)); /* Set the output variable to NULL in case an error occurs. */ *ppPager = 0; @@ -6667,7 +6657,7 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ if( op==SAVEPOINT_RELEASE ){ if( nNew==0 && isOpen(pPager->sjfd) ){ /* Only truncate if it is an in-memory sub-journal. */ - if( sqlite3IsMemJournal(pPager->sjfd) ){ + if( sqlite3JournalIsInMemory(pPager->sjfd) ){ rc = sqlite3OsTruncate(pPager->sjfd, 0); assert( rc==SQLITE_OK ); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 759d7ca5e1..4cbb7f3d06 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4004,15 +4004,12 @@ int sqlite3FindInIndex(Parse *, Expr *, u32, int*); int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); int sqlite3JournalSize(sqlite3_vfs *); int sqlite3JournalCreate(sqlite3_file *); - int sqlite3JournalExists(sqlite3_file *p); #else #define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile) - #define sqlite3JournalExists(p) 1 #endif +int sqlite3JournalIsInMemory(sqlite3_file *p); void sqlite3MemJournalOpen(sqlite3_file *); -int sqlite3MemJournalSize(void); -int sqlite3IsMemJournal(sqlite3_file *); void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p); #if SQLITE_MAX_EXPR_DEPTH>0 From 94fa9c414a4998f60d99d6a65e1d104fe62d2436 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 27 Feb 2016 21:16:04 +0000 Subject: [PATCH 374/570] Eliminate the need for the Column.zDflt (using Column.pDflt instead) to reduce the amount of memory needed to hold the schema. FossilOrigin-Name: d8c94a46dfa94930732c2de2aa79675c5087d36e --- manifest | 28 ++++++++++++++-------------- manifest.uuid | 2 +- src/alter.c | 4 ++-- src/build.c | 14 +++++++++----- src/expr.c | 1 + src/insert.c | 14 +++++++++----- src/pragma.c | 3 ++- src/sqliteInt.h | 1 - src/treeview.c | 6 ++++++ src/vdbemem.c | 2 +- tool/addopcodes.tcl | 1 + 11 files changed, 46 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index 706e06deb0..571cd071e6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Tighter\sdescription\sof\sI/O\sstats\sin\sthe\sshell.\s\sShow\sI/O\sstats\son\sspeedtest1.c. -D 2016-02-27T19:19:22.849 +C Eliminate\sthe\sneed\sfor\sthe\sColumn.zDflt\s(using\sColumn.pDflt\sinstead)\sto\sreduce\nthe\samount\sof\smemory\sneeded\sto\shold\sthe\sschema. +D 2016-02-27T21:16:04.996 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -285,7 +285,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 7603afbd61f55e7c644b8de4a42f33e58c0b7eaa +F src/alter.c 44e18dfd78e8942d65d3cdaec4de972b5cd9f1f2 F src/analyze.c ab57b6763dd4c6170a20673d14882c033affd188 F src/attach.c a3724c64de1099d85e30751213d285752aed9505 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 @@ -295,14 +295,14 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 7bb920c473c277380fcb3e8a8ee28ce1a48e0abc F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 6661513c8f90a23d44ed5e5ada7ea40fac6b6b77 +F src/build.c 6854e717e3257957b1bd87aadd6371d63937a023 F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 0b73e681c11fca867fec554750c07fe0d4e417c1 F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b F src/delete.c 48802aa3ee6339f576d074336d3ae1b5f40e240f -F src/expr.c 9adb58153f6e943b703d43e9a1f67f77b5a75721 +F src/expr.c c4dad2cd6cec00387b75fef4551aff655430dcd2 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 5cb42d9a59e2a590776fd3fc8ff6f61d40df3c6e F src/func.c 552d300265aed09eea21f68ac742a440550c0062 @@ -310,7 +310,7 @@ F src/global.c ded7b97efd16efda5062b65e857198e46c40e652 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 9ca97272e9f74ed0efddf3b4350ee12740cebbef +F src/insert.c 723d5d708cdb61bdd47c00b9f07c75be45aefc09 F src/journal.c fe3a3e2559ce3ce9d371afd30fbabbc074174575 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f @@ -342,7 +342,7 @@ F src/parse.y c3ce2c4a7cbf0b699239be6b2a945c5cb51875e2 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 -F src/pragma.c d6028d23a9495a8b55f2075e3244ec9a0485e03e +F src/pragma.c 35619c4e9f79049cce964ef8ed9710ae3e5b9ca1 F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 @@ -354,7 +354,7 @@ F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 63c0e1b5b5d608a1ba2303fe3a554b859a120406 +F src/sqliteInt.h bcfbf4785436f318459cdbde07a8cce3de7e6f1a F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -408,7 +408,7 @@ F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 3d338cdd00d916ce8a05c397001d64ed58e6fe1c -F src/treeview.c c525282442111b3f61eb176784567cd6654db5dc +F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c @@ -420,7 +420,7 @@ F src/vdbeInt.h 49a74fe5ece206d2d8666ba9afaf1abeda5f123b F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 F src/vdbeaux.c 2c15cf88de4df97428318c8cfac0dea873dae451 F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db -F src/vdbemem.c be8381ed6de54eb9cb9dfa802823cdeb5166d855 +F src/vdbemem.c 9b0cb32cc267ef026515f15a3594d5ff91fe4dfc F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062 F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 F src/vtab.c 943c23b355f0a8f859f9583e7315d64bebdb0899 @@ -1369,7 +1369,7 @@ F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372 F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91 -F tool/addopcodes.tcl 4ca9c3ef196f08da30add5d07ce0c9458dc8c633 +F tool/addopcodes.tcl 2b089684eb8b7d0db64cf9d8e6d2fe1b6d279e8d F tool/build-all-msvc.bat 55be1cf8545dabd69df2ba6b3de6868da0c26f52 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x @@ -1451,7 +1451,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 3c36948f16b58fe8042c37d0df634308b4e48217 -R 2b473c8c6b36608ca875feba0d8cbb83 +P f681d800340e0e710f73d0f7c09101f899249183 +R 68cf98086fc7541dd6cf15ff81e4d2e2 U drh -Z 565e8454d2408a569a86791d9e6b12a6 +Z bde0bd56c07a366738817149aa7f9a7d diff --git a/manifest.uuid b/manifest.uuid index 546a6418d6..629362c836 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f681d800340e0e710f73d0f7c09101f899249183 \ No newline at end of file +d8c94a46dfa94930732c2de2aa79675c5087d36e \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index f10a85022a..9edd7fff3c 100644 --- a/src/alter.c +++ b/src/alter.c @@ -628,7 +628,8 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ ** literal NULL, then set pDflt to 0. This simplifies checking ** for an SQL NULL default below. */ - if( pDflt && pDflt->op==TK_NULL ){ + assert( pDflt==0 || pDflt->op==TK_SPAN ); + if( pDflt && pDflt->pLeft->op==TK_NULL ){ pDflt = 0; } @@ -787,7 +788,6 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ pCol->zColl = 0; pCol->zType = 0; pCol->pDflt = 0; - pCol->zDflt = 0; } pNew->pSchema = db->aDb[iDb].pSchema; pNew->addColOffset = pTab->addColOffset; diff --git a/src/build.c b/src/build.c index b14d45f6da..bcf71442de 100644 --- a/src/build.c +++ b/src/build.c @@ -571,7 +571,6 @@ void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){ for(i=0; inCol; i++, pCol++){ sqlite3DbFree(db, pCol->zName); sqlite3ExprDelete(db, pCol->pDflt); - sqlite3DbFree(db, pCol->zDflt); sqlite3DbFree(db, pCol->zType); sqlite3DbFree(db, pCol->zColl); } @@ -1231,11 +1230,16 @@ void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){ ** tokens that point to volatile memory. The 'span' of the expression ** is required by pragma table_info. */ + Expr x; sqlite3ExprDelete(db, pCol->pDflt); - pCol->pDflt = sqlite3ExprDup(db, pSpan->pExpr, EXPRDUP_REDUCE); - sqlite3DbFree(db, pCol->zDflt); - pCol->zDflt = sqlite3DbStrNDup(db, (char*)pSpan->zStart, - (int)(pSpan->zEnd - pSpan->zStart)); + memset(&x, 0, sizeof(x)); + x.op = TK_SPAN; + x.u.zToken = sqlite3DbStrNDup(db, (char*)pSpan->zStart, + (int)(pSpan->zEnd - pSpan->zStart)); + x.pLeft = pSpan->pExpr; + x.flags = EP_Skip; + pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE); + sqlite3DbFree(db, x.u.zToken); } } sqlite3ExprDelete(db, pSpan->pExpr); diff --git a/src/expr.c b/src/expr.c index 3070de96fa..8a69732195 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3070,6 +3070,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ sqlite3ReleaseTempReg(pParse, r4); break; } + case TK_SPAN: case TK_COLLATE: case TK_UPLUS: { inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); diff --git a/src/insert.c b/src/insert.c index 7ff884b8c3..03fdf09acc 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1999,11 +1999,15 @@ static int xferOptimization( return 0; /* tab2 must be NOT NULL if tab1 is */ } /* Default values for second and subsequent columns need to match. */ - if( i>0 - && ((pDestCol->zDflt==0)!=(pSrcCol->zDflt==0) - || (pDestCol->zDflt && strcmp(pDestCol->zDflt, pSrcCol->zDflt)!=0)) - ){ - return 0; /* Default values must be the same for all columns */ + if( i>0 ){ + assert( pDestCol->pDflt==0 || pDestCol->pDflt->op==TK_SPAN ); + assert( pSrcCol->pDflt==0 || pSrcCol->pDflt->op==TK_SPAN ); + if( (pDestCol->pDflt==0)!=(pSrcCol->pDflt==0) + || (pDestCol->pDflt && strcmp(pDestCol->pDflt->u.zToken, + pSrcCol->pDflt->u.zToken)!=0) + ){ + return 0; /* Default values must be the same for all columns */ + } } } for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ diff --git a/src/pragma.c b/src/pragma.c index 8b8f1f7bfd..0460f663fd 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1076,12 +1076,13 @@ void sqlite3Pragma( }else{ for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} } + assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN ); sqlite3VdbeMultiLoad(v, 1, "issisi", i-nHidden, pCol->zName, pCol->zType ? pCol->zType : "", pCol->notNull ? 1 : 0, - pCol->zDflt, + pCol->pDflt ? pCol->pDflt->u.zToken : 0, k); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 759d7ca5e1..7d1757e4d8 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1545,7 +1545,6 @@ struct Module { struct Column { char *zName; /* Name of this column */ Expr *pDflt; /* Default value of this column */ - char *zDflt; /* Original text of the default value */ char *zType; /* Data type for this column */ char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ diff --git a/src/treeview.c b/src/treeview.c index ff3b4be5aa..907159c06d 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -339,6 +339,12 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ case TK_ISNULL: zUniOp = "ISNULL"; break; case TK_NOTNULL: zUniOp = "NOTNULL"; break; + case TK_SPAN: { + sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken); + sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); + break; + } + case TK_COLLATE: { sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken); sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); diff --git a/src/vdbemem.c b/src/vdbemem.c index 87d233b980..b5139fe32e 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -1285,7 +1285,7 @@ static int valueFromExpr( *ppVal = 0; return SQLITE_OK; } - while( (op = pExpr->op)==TK_UPLUS ) pExpr = pExpr->pLeft; + while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; /* Compressed expressions only appear when parsing the DEFAULT clause diff --git a/tool/addopcodes.tcl b/tool/addopcodes.tcl index 84e3994ce8..9b34cf2e03 100644 --- a/tool/addopcodes.tcl +++ b/tool/addopcodes.tcl @@ -38,6 +38,7 @@ set extras { UPLUS REGISTER ASTERISK + SPAN SPACE ILLEGAL } From 2881ab6298a431d2e37c7040a722b56c17a33ea6 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 27 Feb 2016 23:25:36 +0000 Subject: [PATCH 375/570] Update the parser so that it pulls out the column name and type all in one go, rather than using separate reductions. FossilOrigin-Name: ad3ffe2eec8e8ea2591a78c723d2665735553cb0 --- manifest | 19 +++++++++++-------- manifest.uuid | 2 +- src/build.c | 39 ++++++++++----------------------------- src/parse.y | 10 +++------- src/sqliteInt.h | 3 +-- 5 files changed, 26 insertions(+), 47 deletions(-) diff --git a/manifest b/manifest index 571cd071e6..ca7a05fd5c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Eliminate\sthe\sneed\sfor\sthe\sColumn.zDflt\s(using\sColumn.pDflt\sinstead)\sto\sreduce\nthe\samount\sof\smemory\sneeded\sto\shold\sthe\sschema. -D 2016-02-27T21:16:04.996 +C Update\sthe\sparser\sso\sthat\sit\spulls\sout\sthe\scolumn\sname\sand\stype\sall\sin\sone\ngo,\srather\sthan\susing\sseparate\sreductions. +D 2016-02-27T23:25:36.278 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -295,7 +295,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 7bb920c473c277380fcb3e8a8ee28ce1a48e0abc F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 6854e717e3257957b1bd87aadd6371d63937a023 +F src/build.c 8bde0b1cf0bfd94562398d31592b6b8b2b6ba719 F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -338,7 +338,7 @@ F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c d034c69b958c01289eb8070cbf902e1a68cd7e0b F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 -F src/parse.y c3ce2c4a7cbf0b699239be6b2a945c5cb51875e2 +F src/parse.y 3a29fc291600c48827ea94d5c630972db33e0b81 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 @@ -354,7 +354,7 @@ F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h bcfbf4785436f318459cdbde07a8cce3de7e6f1a +F src/sqliteInt.h 01b43972162c2b5ed864060a23502af3abe0e4f4 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1451,7 +1451,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f681d800340e0e710f73d0f7c09101f899249183 -R 68cf98086fc7541dd6cf15ff81e4d2e2 +P d8c94a46dfa94930732c2de2aa79675c5087d36e +R 08160a7958aa5578e4603f69af85b704 +T *branch * schema-storage +T *sym-schema-storage * +T -sym-trunk * U drh -Z bde0bd56c07a366738817149aa7f9a7d +Z 64cdb714f146eadb7f54fce29197df77 diff --git a/manifest.uuid b/manifest.uuid index 629362c836..fea3e74ff6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d8c94a46dfa94930732c2de2aa79675c5087d36e \ No newline at end of file +ad3ffe2eec8e8ea2591a78c723d2665735553cb0 \ No newline at end of file diff --git a/src/build.c b/src/build.c index bcf71442de..a655c9a301 100644 --- a/src/build.c +++ b/src/build.c @@ -1038,7 +1038,7 @@ void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){ ** first to get things going. Then this routine is called for each ** column. */ -void sqlite3AddColumn(Parse *pParse, Token *pName){ +void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ Table *p; int i; char *z; @@ -1074,12 +1074,15 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){ pCol->zName = z; sqlite3ColumnPropertiesFromName(p, pCol); - /* If there is no type specified, columns have the default affinity - ** 'BLOB'. If there is a type specified, then sqlite3AddColumnType() will - ** be called next to set pCol->affinity correctly. - */ - pCol->affinity = SQLITE_AFF_BLOB; - pCol->szEst = 1; + if( pType==0 ){ + /* If there is no type specified, columns have the default affinity + ** 'BLOB'. */ + pCol->affinity = SQLITE_AFF_BLOB; + pCol->szEst = 1; + }else{ + pCol->zType = sqlite3NameFromToken(pParse->db, pType); + pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst); + } p->nCol++; } @@ -1183,28 +1186,6 @@ char sqlite3AffinityType(const char *zIn, u8 *pszEst){ return aff; } -/* -** This routine is called by the parser while in the middle of -** parsing a CREATE TABLE statement. The pFirst token is the first -** token in the sequence of tokens that describe the type of the -** column currently under construction. pLast is the last token -** in the sequence. Use this information to construct a string -** that contains the typename of the column and store that string -** in zType. -*/ -void sqlite3AddColumnType(Parse *pParse, Token *pType){ - Table *p; - Column *pCol; - - p = pParse->pNewTable; - if( p==0 || NEVER(p->nCol<1) ) return; - pCol = &p->aCol[p->nCol-1]; - assert( pCol->zType==0 || CORRUPT_DB ); - sqlite3DbFree(pParse->db, pCol->zType); - pCol->zType = sqlite3NameFromToken(pParse->db, pType); - pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst); -} - /* ** The expression is the default value for the most recently added column ** of the table currently under construction. diff --git a/src/parse.y b/src/parse.y index e7e0d1d953..b8ae8c8dc1 100644 --- a/src/parse.y +++ b/src/parse.y @@ -198,13 +198,11 @@ columnlist ::= column. // datatype, and other keywords such as PRIMARY KEY, UNIQUE, REFERENCES, // NOT NULL and so forth. // -column(A) ::= columnid(A) type carglist. { +column(A) ::= columnname(A) carglist. { A.n = (int)(pParse->sLastToken.z-A.z) + pParse->sLastToken.n; } -columnid(A) ::= nm(A). { - sqlite3AddColumn(pParse,&A); - pParse->constraintName.n = 0; -} +columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);} +columnname(A) ::= nm(A). {sqlite3AddColumn(pParse,&A,0);} // An IDENTIFIER can be a generic identifier, or one of several @@ -269,8 +267,6 @@ nm(A) ::= JOIN_KW(A). // Multiple tokens are concatenated to form the value of the typetoken. // %type typetoken {Token} -type ::= . -type ::= typetoken(X). {sqlite3AddColumnType(pParse,&X);} typetoken(A) ::= typename(A). typetoken(A) ::= typename(A) LP signed RP(Y). { A.n = (int)(&Y.z[Y.n] - A.z); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 7d1757e4d8..d6acc3227b 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3413,11 +3413,10 @@ void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); #else # define sqlite3ColumnPropertiesFromName(T,C) /* no-op */ #endif -void sqlite3AddColumn(Parse*,Token*); +void sqlite3AddColumn(Parse*,Token*,Token*); void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); void sqlite3AddCheckConstraint(Parse*, Expr*); -void sqlite3AddColumnType(Parse*,Token*); void sqlite3AddDefaultValue(Parse*,ExprSpan*); void sqlite3AddCollateType(Parse*, Token*); void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); From 986dde705234f9a9e9e60f4d75eb60dd0c94ccf3 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 29 Feb 2016 13:37:21 +0000 Subject: [PATCH 376/570] Further simplifications to the grammar. FossilOrigin-Name: 519fd03b845c9b53df9e5397282df2e99f36a672 --- manifest | 17 +++++++---------- manifest.uuid | 2 +- src/build.c | 3 ++- src/parse.y | 24 ++++++++---------------- 4 files changed, 18 insertions(+), 28 deletions(-) diff --git a/manifest b/manifest index ca7a05fd5c..d09c8a0810 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\sparser\sso\sthat\sit\spulls\sout\sthe\scolumn\sname\sand\stype\sall\sin\sone\ngo,\srather\sthan\susing\sseparate\sreductions. -D 2016-02-27T23:25:36.278 +C Further\ssimplifications\sto\sthe\sgrammar. +D 2016-02-29T13:37:21.189 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -295,7 +295,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 7bb920c473c277380fcb3e8a8ee28ce1a48e0abc F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 8bde0b1cf0bfd94562398d31592b6b8b2b6ba719 +F src/build.c 5a3e2c884c7fd30f1cc46424fc1f816cc1218f5d F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -338,7 +338,7 @@ F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c d034c69b958c01289eb8070cbf902e1a68cd7e0b F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 -F src/parse.y 3a29fc291600c48827ea94d5c630972db33e0b81 +F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 @@ -1451,10 +1451,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 d8c94a46dfa94930732c2de2aa79675c5087d36e -R 08160a7958aa5578e4603f69af85b704 -T *branch * schema-storage -T *sym-schema-storage * -T -sym-trunk * +P ad3ffe2eec8e8ea2591a78c723d2665735553cb0 +R 4784b7c67e30974242406c3dce382bf0 U drh -Z 64cdb714f146eadb7f54fce29197df77 +Z 37a93f7c979e487a92cbbe58a4d1f8f4 diff --git a/manifest.uuid b/manifest.uuid index fea3e74ff6..eb7843b3f9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ad3ffe2eec8e8ea2591a78c723d2665735553cb0 \ No newline at end of file +519fd03b845c9b53df9e5397282df2e99f36a672 \ No newline at end of file diff --git a/src/build.c b/src/build.c index a655c9a301..ec8770a454 100644 --- a/src/build.c +++ b/src/build.c @@ -1074,7 +1074,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ pCol->zName = z; sqlite3ColumnPropertiesFromName(p, pCol); - if( pType==0 ){ + if( pType->n==0 ){ /* If there is no type specified, columns have the default affinity ** 'BLOB'. */ pCol->affinity = SQLITE_AFF_BLOB; @@ -1084,6 +1084,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst); } p->nCol++; + pParse->constraintName.n = 0; } /* diff --git a/src/parse.y b/src/parse.y index b8ae8c8dc1..20492edb80 100644 --- a/src/parse.y +++ b/src/parse.y @@ -190,20 +190,9 @@ table_options(A) ::= WITHOUT nm(X). { sqlite3ErrorMsg(pParse, "unknown table option: %.*s", X.n, X.z); } } -columnlist ::= columnlist COMMA column. -columnlist ::= column. - -// A "column" is a complete description of a single column in a -// CREATE TABLE statement. This includes the column name, its -// datatype, and other keywords such as PRIMARY KEY, UNIQUE, REFERENCES, -// NOT NULL and so forth. -// -column(A) ::= columnname(A) carglist. { - A.n = (int)(pParse->sLastToken.z-A.z) + pParse->sLastToken.n; -} +columnlist ::= columnlist COMMA columnname carglist. +columnlist ::= columnname carglist. columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);} -columnname(A) ::= nm(A). {sqlite3AddColumn(pParse,&A,0);} - // An IDENTIFIER can be a generic identifier, or one of several // keywords. Any non-standard keyword can also be an identifier. @@ -262,11 +251,12 @@ nm(A) ::= id(A). nm(A) ::= STRING(A). nm(A) ::= JOIN_KW(A). -// A typetoken is really one or more tokens that form a type name such +// A typetoken is really zero or more tokens that form a type name such // as can be found after the column name in a CREATE TABLE statement. // Multiple tokens are concatenated to form the value of the typetoken. // %type typetoken {Token} +typetoken(A) ::= . {A.n = 0; A.z = 0;} typetoken(A) ::= typename(A). typetoken(A) ::= typename(A) LP signed RP(Y). { A.n = (int)(&Y.z[Y.n] - A.z); @@ -576,7 +566,7 @@ selcollist(A) ::= sclp(A) nm(X) DOT STAR(Y). { %type as {Token} as(X) ::= AS nm(Y). {X = Y;} as(X) ::= ids(X). -as(X) ::= . {X.n = 0;} +as(X) ::= . {X.n = 0; X.z = 0;} %type seltablist {SrcList*} @@ -1495,7 +1485,9 @@ cmd ::= ANALYZE nm(X) dbnm(Y). {sqlite3Analyze(pParse, &X, &Y);} cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). { sqlite3AlterRenameTable(pParse,X,&Z); } -cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column(Y). { +cmd ::= ALTER TABLE add_column_fullname + ADD kwcolumn_opt columnname(Y) carglist. { + Y.n = (int)(pParse->sLastToken.z-Y.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &Y); } add_column_fullname ::= fullname(X). { From 94eaafa9ce6e044b834c56c712d18ba3c1f6d91d Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 29 Feb 2016 15:53:11 +0000 Subject: [PATCH 377/570] Reduce the amount of heap required to store many schemas by storing each column datatype appended to the column name, rather than as a separate allocation. FossilOrigin-Name: 842b21162713bb141b845b01c136457a31af4ab0 --- manifest | 30 ++++++++++++++++-------------- manifest.uuid | 2 +- src/alter.c | 1 - src/build.c | 22 ++++++++++++++-------- src/main.c | 3 ++- src/pragma.c | 6 ++++-- src/select.c | 9 +++------ src/sqliteInt.h | 4 ++-- src/util.c | 8 ++++++++ src/vtab.c | 4 ++-- 10 files changed, 52 insertions(+), 37 deletions(-) diff --git a/manifest b/manifest index cb3d41bb09..a8c210da9f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Very\sminor\simprovement\sto\sthe\sperformance\sand\sreduction\sin\ssize\sto\sthe\nparser\sby\scapturing\sthe\sname\sand\sdatatype\sof\stable\scolumns\sin\sa\ssingle\ngrammar\srule\sreduction. -D 2016-02-29T13:44:38.497 +C Reduce\sthe\samount\sof\sheap\srequired\sto\sstore\smany\sschemas\sby\sstoring\seach\ncolumn\sdatatype\sappended\sto\sthe\scolumn\sname,\srather\sthan\sas\sa\sseparate\nallocation. +D 2016-02-29T15:53:11.458 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -285,7 +285,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 44e18dfd78e8942d65d3cdaec4de972b5cd9f1f2 +F src/alter.c 1bb0709b3048e24217b80ec6bd78a3e99a47c01b F src/analyze.c ab57b6763dd4c6170a20673d14882c033affd188 F src/attach.c a3724c64de1099d85e30751213d285752aed9505 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 @@ -295,7 +295,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 7bb920c473c277380fcb3e8a8ee28ce1a48e0abc F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 5a3e2c884c7fd30f1cc46424fc1f816cc1218f5d +F src/build.c 43b93fe757bfffe00f97462596418b052eefdccd F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -314,7 +314,7 @@ F src/insert.c 723d5d708cdb61bdd47c00b9f07c75be45aefc09 F src/journal.c fe3a3e2559ce3ce9d371afd30fbabbc074174575 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f -F src/main.c be9309f442ec291177642d2e48e82290e0951f4b +F src/main.c 32c45647866429f34d7a13a717172a8e7d0a1056 F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -342,19 +342,19 @@ F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 -F src/pragma.c 35619c4e9f79049cce964ef8ed9710ae3e5b9ca1 +F src/pragma.c 42b3f1475b483710ba1dd1cc1ecc0c0f8db59a2e F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e -F src/select.c 1bacfde7b7cec134d2b354cbcf67bafc67078431 +F src/select.c 137b31daa84d57d67847bf621bb54f3353e2077b F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 01b43972162c2b5ed864060a23502af3abe0e4f4 +F src/sqliteInt.h 8aa9992cb35289ede0946f7ba8e993070e040fc4 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -412,7 +412,7 @@ F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c -F src/util.c 6ed9d7bdd3b0a30742027b6d8e8e1a9e2b14f373 +F src/util.c a64585a74aef6feb16dfe4e090b5de01e26eba3b F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c 87ae3a5657fefed7875f3eb30e7ababd48013d71 F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 @@ -423,7 +423,7 @@ F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c 9b0cb32cc267ef026515f15a3594d5ff91fe4dfc F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062 F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 -F src/vtab.c 943c23b355f0a8f859f9583e7315d64bebdb0899 +F src/vtab.c fd69fd398e23e57ea4ea377d8a44b6998fc569c7 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c @@ -1451,8 +1451,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d8c94a46dfa94930732c2de2aa79675c5087d36e 519fd03b845c9b53df9e5397282df2e99f36a672 -R 4784b7c67e30974242406c3dce382bf0 -T +closed 519fd03b845c9b53df9e5397282df2e99f36a672 +P 4b55c520f554163edc174e5995e66242f169cb04 +R 124650c3359b5cb373643178bc007cde +T *branch * schema-storage +T *sym-schema-storage * +T -sym-trunk * U drh -Z 5a7ee41f15f54141d2ddaa0e30d16756 +Z 9b6160e72c73eb18b594df11fb333e9a diff --git a/manifest.uuid b/manifest.uuid index 6cb702eb1f..472d0208d0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4b55c520f554163edc174e5995e66242f169cb04 \ No newline at end of file +842b21162713bb141b845b01c136457a31af4ab0 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 9edd7fff3c..642c1fb677 100644 --- a/src/alter.c +++ b/src/alter.c @@ -786,7 +786,6 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ Column *pCol = &pNew->aCol[i]; pCol->zName = sqlite3DbStrDup(db, pCol->zName); pCol->zColl = 0; - pCol->zType = 0; pCol->pDflt = 0; } pNew->pSchema = db->aDb[iDb].pSchema; diff --git a/src/build.c b/src/build.c index ec8770a454..a32dfbd029 100644 --- a/src/build.c +++ b/src/build.c @@ -571,7 +571,6 @@ void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){ for(i=0; inCol; i++, pCol++){ sqlite3DbFree(db, pCol->zName); sqlite3ExprDelete(db, pCol->pDflt); - sqlite3DbFree(db, pCol->zType); sqlite3DbFree(db, pCol->zColl); } sqlite3DbFree(db, pTable->aCol); @@ -1042,6 +1041,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ Table *p; int i; char *z; + char *zType; Column *pCol; sqlite3 *db = pParse->db; if( (p = pParse->pNewTable)==0 ) return; @@ -1051,8 +1051,14 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ return; } #endif - z = sqlite3NameFromToken(db, pName); + z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2); if( z==0 ) return; + memcpy(z, pName->z, pName->n); + z[pName->n] = 0; + sqlite3Dequote(z); + zType = z + sqlite3Strlen30(z) + 1; + memcpy(zType, pType->z, pType->n); + zType[pType->n] = 0; for(i=0; inCol; i++){ if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){ sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); @@ -1080,8 +1086,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ pCol->affinity = SQLITE_AFF_BLOB; pCol->szEst = 1; }else{ - pCol->zType = sqlite3NameFromToken(pParse->db, pType); - pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst); + pCol->affinity = sqlite3AffinityType(zType, &pCol->szEst); } p->nCol++; pParse->constraintName.n = 0; @@ -1277,7 +1282,7 @@ void sqlite3AddPrimaryKey( int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */ ){ Table *pTab = pParse->pNewTable; - char *zType = 0; + const char *zName = 0; int iCol = -1, i; int nTerm; if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit; @@ -1290,7 +1295,7 @@ void sqlite3AddPrimaryKey( if( pList==0 ){ iCol = pTab->nCol - 1; pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; - zType = pTab->aCol[iCol].zType; + zName = pTab->aCol[iCol].zName; nTerm = 1; }else{ nTerm = pList->nExpr; @@ -1303,7 +1308,7 @@ void sqlite3AddPrimaryKey( for(iCol=0; iColnCol; iCol++){ if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){ pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; - zType = pTab->aCol[iCol].zType; + zName = pTab->aCol[iCol].zName; break; } } @@ -1311,7 +1316,8 @@ void sqlite3AddPrimaryKey( } } if( nTerm==1 - && zType && sqlite3StrICmp(zType, "INTEGER")==0 + && zName + && sqlite3StrICmp(sqlite3StrNext(zName), "INTEGER")==0 && sortOrder!=SQLITE_SO_DESC ){ pTab->iPKey = iCol; diff --git a/src/main.c b/src/main.c index 2a258da662..3ba5972fa6 100644 --- a/src/main.c +++ b/src/main.c @@ -3335,7 +3335,8 @@ int sqlite3_table_column_metadata( ** explicitly declared column. Copy meta information from *pCol. */ if( pCol ){ - zDataType = pCol->zType; + zDataType = sqlite3StrNext(pCol->zName); + if( zDataType[0]==0 ) zDataType = 0; zCollSeq = pCol->zColl; notnull = pCol->notNull!=0; primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0; diff --git a/src/pragma.c b/src/pragma.c index 0460f663fd..1d62914310 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1065,6 +1065,7 @@ void sqlite3Pragma( setAllColumnNames(v, 6, azCol); assert( 6==ArraySize(azCol) ); sqlite3ViewGetColumnNames(pParse, pTab); for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ + const char *zName; if( IsHiddenColumn(pCol) ){ nHidden++; continue; @@ -1077,10 +1078,11 @@ void sqlite3Pragma( for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} } assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN ); + zName = pCol->zName; sqlite3VdbeMultiLoad(v, 1, "issisi", i-nHidden, - pCol->zName, - pCol->zType ? pCol->zType : "", + zName, + sqlite3StrNext(zName), pCol->notNull ? 1 : 0, pCol->pDflt ? pCol->pDflt->u.zToken : 0, k); diff --git a/src/select.c b/src/select.c index aa1f214855..c9bc389b2f 100644 --- a/src/select.c +++ b/src/select.c @@ -1429,8 +1429,8 @@ static const char *columnTypeImpl( zType = "INTEGER"; zOrigCol = "rowid"; }else{ - zType = pTab->aCol[iCol].zType; zOrigCol = pTab->aCol[iCol].zName; + zType = sqlite3StrNext(zOrigCol); estWidth = pTab->aCol[iCol].szEst; } zOrigTab = pTab->zName; @@ -1442,7 +1442,7 @@ static const char *columnTypeImpl( if( iCol<0 ){ zType = "INTEGER"; }else{ - zType = pTab->aCol[iCol].zType; + zType = sqlite3StrNext(pTab->aCol[iCol].zName); estWidth = pTab->aCol[iCol].szEst; } #endif @@ -1727,10 +1727,7 @@ static void selectAddColumnTypeAndCollation( a = pSelect->pEList->a; for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ p = a[i].pExpr; - if( pCol->zType==0 ){ - pCol->zType = sqlite3DbStrDup(db, - columnType(&sNC, p,0,0,0, &pCol->szEst)); - } + columnType(&sNC, p, 0, 0, 0, &pCol->szEst); szAll += pCol->szEst; pCol->affinity = sqlite3ExprAffinity(p); if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index d6acc3227b..a37da33ed2 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1543,9 +1543,8 @@ struct Module { ** of this structure. */ struct Column { - char *zName; /* Name of this column */ + char *zName; /* Name of this column, \000, then the type */ Expr *pDflt; /* Default value of this column */ - char *zType; /* Data type for this column */ char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ char affinity; /* One of the SQLITE_AFF_... values */ @@ -3258,6 +3257,7 @@ int sqlite3IsIdChar(u8); */ int sqlite3StrICmp(const char*,const char*); int sqlite3Strlen30(const char*); +const char *sqlite3StrNext(const char*); #define sqlite3StrNICmp sqlite3_strnicmp int sqlite3MallocInit(void); diff --git a/src/util.c b/src/util.c index d00a739e53..81274260f4 100644 --- a/src/util.c +++ b/src/util.c @@ -109,6 +109,14 @@ int sqlite3Strlen30(const char *z){ return 0x3fffffff & (int)strlen(z); } +/* +** The string z[] is followed immediately by another string. Return +** a poiner to that other string. +*/ +const char *sqlite3StrNext(const char *z){ + return z + strlen(z) + 1; +} + /* ** Set the current error code to err_code and clear any prior error message. */ diff --git a/src/vtab.c b/src/vtab.c index fa19548199..ad8caef3bc 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -564,10 +564,10 @@ static int vtabCallConstructor( pTab->pVTable = pVTable; for(iCol=0; iColnCol; iCol++){ - char *zType = pTab->aCol[iCol].zType; + char *zType = (char*)sqlite3StrNext(pTab->aCol[iCol].zName); int nType; int i = 0; - if( !zType ){ + if( !zType[0] ){ pTab->tabFlags |= oooHidden; continue; } From 437a54eabaa3b2d92157bcf087c1342642189e34 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 29 Feb 2016 17:16:26 +0000 Subject: [PATCH 378/570] Fix an fts5 problem causing 'optimize' to corrupt the fts index under some circumstances. FossilOrigin-Name: 251d6473f7c9ad95adbdcc49cb8eaf7c0956764b --- ext/fts5/fts5_index.c | 5 ++++- ext/fts5/test/fts5simple.test | 20 ++++++++++++++++++++ manifest | 17 ++++++++--------- manifest.uuid | 2 +- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 57d242bc3c..cb6360ad67 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -4499,7 +4499,10 @@ int sqlite3Fts5IndexOptimize(Fts5Index *p){ if( pLvl->aSeg ){ int iLvl, iSeg; int iSegOut = 0; - for(iLvl=0; iLvlnLevel; iLvl++){ + /* Iterate through all segments, from oldest to newest. Add them to + ** the new Fts5Level object so that pLvl->aSeg[0] is the oldest + ** segment in the data structure. */ + for(iLvl=pStruct->nLevel-1; iLvl>=0; iLvl--){ for(iSeg=0; iSegaLevel[iLvl].nSeg; iSeg++){ pLvl->aSeg[iSegOut] = pStruct->aLevel[iLvl].aSeg[iSeg]; iSegOut++; diff --git a/ext/fts5/test/fts5simple.test b/ext/fts5/test/fts5simple.test index a095a16230..01111d78c8 100644 --- a/ext/fts5/test/fts5simple.test +++ b/ext/fts5/test/fts5simple.test @@ -409,5 +409,25 @@ do_catchsql_test 19.2 { SELECT * FROM x1 WHERE x1 MATCH 'c0 AND (c1 AND (c2 AND (c3 AND (c4 AND (c5 AND (c6 AND (c7 AND (c8 AND (c9 AND (c10 AND (c11 AND (c12 AND (c13 AND (c14 AND (c15 AND (c16 AND (c17 AND (c18 AND (c19 AND (c20 AND (c21 AND (c22 AND (c23 AND (c24 AND (c25 AND (c26 AND (c27 AND (c28 AND (c29 AND (c30 AND (c31 AND (c32 AND (c33 AND (c34 AND (c35 AND (c36 AND (c37 AND (c38 AND (c39 AND (c40 AND (c41 AND (c42 AND (c43 AND (c44 AND (c45 AND (c46 AND (c47 AND (c48 AND (c49 AND (c50 AND (c51 AND (c52 AND (c53 AND (c54 AND (c55 AND (c56 AND (c57 AND (c58 AND (c59 AND (c60 AND (c61 AND (c62 AND (c63 AND (c64 AND (c65 AND (c66 AND (c67 AND (c68 AND (c69 AND (c70 AND (c71 AND (c72 AND (c73 AND (c74 AND (c75 AND (c76 AND (c77 AND (c78 AND (c79 AND (c80 AND (c81 AND (c82 AND (c83 AND (c84 AND (c85 AND (c86 AND (c87 AND (c88 AND (c89 AND (c90 AND (c91 AND (c92 AND (c93 AND (c94 AND (c95 AND (c96 AND (c97 AND (c98 AND (c99 AND (c100 AND (c101 AND (c102 AND (c103 AND (c104 AND (c105 AND (c106 AND (c107 AND (c108 AND (c109 AND (c110 AND (c111 AND (c112 AND (c113 AND (c114 AND (c115 AND (c116 AND (c117 AND (c118 AND (c119 AND (c120 AND (c121 AND (c122 AND (c123 AND (c124 AND (c125 AND (c126 AND (c127 AND (c128 AND (c129 AND (c130 AND (c131 AND (c132 AND (c133 AND (c134 AND (c135 AND (c136 AND (c137 AND (c138 AND (c139 AND (c140 AND (c141 AND (c142 AND (c143 AND (c144 AND (c145 AND (c146 AND (c147 AND (c148 AND (c149 AND (c150 AND (c151 AND (c152 AND (c153 AND (c154 AND (c155 AND (c156 AND (c157 AND (c158 AND (c159 AND (c160 AND (c161 AND (c162 AND (c163 AND (c164 AND (c165 AND (c166 AND (c167 AND (c168 AND (c169 AND (c170 AND (c171 AND (c172 AND (c173 AND (c174 AND (c175 AND (c176 AND (c177 AND (c178 AND (c179 AND (c180 AND (c181 AND (c182 AND (c183 AND (c184 AND (c185 AND (c186 AND (c187 AND (c188 AND (c189 AND (c190 AND (c191 AND (c192 AND (c193 AND (c194 AND (c195 AND (c196 AND (c197 AND (c198 AND (c199 AND c200)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))'; } {1 {fts5: parser stack overflow}} +#------------------------------------------------------------------------- +reset_db +breakpoint +do_execsql_test 20.0 { + CREATE VIRTUAL TABLE x1 USING fts5(x); + INSERT INTO x1(x1, rank) VALUES('pgsz', 32); + INSERT INTO x1(rowid, x) VALUES(11111, 'onetwothree'); +} +do_test 20.1 { + for {set i 1} {$i <= 200} {incr i} { + execsql { INSERT INTO x1(rowid, x) VALUES($i, 'one two three'); } + } + execsql { INSERT INTO x1(x1) VALUES('optimize'); } + execsql { DELETE FROM x1 WHERE rowid = 4; } +} {} +do_execsql_test 20.2 { + INSERT INTO x1(x1) VALUES('optimize'); + INSERT INTO x1(x1) VALUES('integrity-check'); +} {} + finish_test diff --git a/manifest b/manifest index cb3d41bb09..0a0a2a762c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Very\sminor\simprovement\sto\sthe\sperformance\sand\sreduction\sin\ssize\sto\sthe\nparser\sby\scapturing\sthe\sname\sand\sdatatype\sof\stable\scolumns\sin\sa\ssingle\ngrammar\srule\sreduction. -D 2016-02-29T13:44:38.497 +C Fix\san\sfts5\sproblem\scausing\s'optimize'\sto\scorrupt\sthe\sfts\sindex\sunder\ssome\scircumstances. +D 2016-02-29T17:16:26.225 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c 78069efb54559a17c35906a741362d0b5c899bd0 +F ext/fts5/fts5_index.c 745bc6f0e0c13c3b659be0bae72fa6067d1708c9 F ext/fts5/fts5_main.c db24ac714c6c4a1b3c24a1f8c25889f2952148c1 F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -177,7 +177,7 @@ F ext/fts5/test/fts5rank.test 7e9e64eac7245637f6f2033aec4b292aaf611aab F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17 F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6 -F ext/fts5/test/fts5simple.test e6fe2fb10a2b9193648b32bbc2caecabdf8c333d +F ext/fts5/test/fts5simple.test 92e06be1c119f88a73ea11a05599a276ec3ff7fd F ext/fts5/test/fts5simple2.test 98377ae1ff7749a42c21fe1a139c1ed312522c46 F ext/fts5/test/fts5simple3.test 8e71733b3d1b0e695011d02c68ebc5ca40b6124e F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48 @@ -1451,8 +1451,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 d8c94a46dfa94930732c2de2aa79675c5087d36e 519fd03b845c9b53df9e5397282df2e99f36a672 -R 4784b7c67e30974242406c3dce382bf0 -T +closed 519fd03b845c9b53df9e5397282df2e99f36a672 -U drh -Z 5a7ee41f15f54141d2ddaa0e30d16756 +P 4b55c520f554163edc174e5995e66242f169cb04 +R e6d22f9f71f3990f592583cd83eb05c9 +U dan +Z fe2b648248ba7cac53004b260ee02700 diff --git a/manifest.uuid b/manifest.uuid index 6cb702eb1f..6e08bfef94 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4b55c520f554163edc174e5995e66242f169cb04 \ No newline at end of file +251d6473f7c9ad95adbdcc49cb8eaf7c0956764b \ No newline at end of file From 4e9d0d54183e8790a1055a92b34d27580910d18c Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 29 Feb 2016 17:34:16 +0000 Subject: [PATCH 379/570] Fix a problem in fts5 where a corrupt db could lead to a (huge) buffer overread. FossilOrigin-Name: c9a30e117f2c6c9ef0cc0c6ca5227d2961715b8f --- ext/fts5/fts5_index.c | 5 +++++ manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index cb6360ad67..ac97a7d75f 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -698,6 +698,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){ return pRet; } + /* ** Release a reference to data record returned by an earlier call to ** fts5DataRead(). @@ -2154,6 +2155,10 @@ static void fts5LeafSeek( iPgidx = szLeaf; iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff); iOff = iTermOff; + if( iOff>n ){ + p->rc = FTS5_CORRUPT; + return; + } while( 1 ){ diff --git a/manifest b/manifest index 0a0a2a762c..bacddf080c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sfts5\sproblem\scausing\s'optimize'\sto\scorrupt\sthe\sfts\sindex\sunder\ssome\scircumstances. -D 2016-02-29T17:16:26.225 +C Fix\sa\sproblem\sin\sfts5\swhere\sa\scorrupt\sdb\scould\slead\sto\sa\s(huge)\sbuffer\soverread. +D 2016-02-29T17:34:16.069 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c 745bc6f0e0c13c3b659be0bae72fa6067d1708c9 +F ext/fts5/fts5_index.c 26a4a6112864feb599a6f6144d06a78bb179736a F ext/fts5/fts5_main.c db24ac714c6c4a1b3c24a1f8c25889f2952148c1 F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -1451,7 +1451,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 4b55c520f554163edc174e5995e66242f169cb04 -R e6d22f9f71f3990f592583cd83eb05c9 +P 251d6473f7c9ad95adbdcc49cb8eaf7c0956764b +R 1a43d3061a1f154a38fc05ffa17e1f4a U dan -Z fe2b648248ba7cac53004b260ee02700 +Z 0ef60cd2035dd9bea82e9df13f5bcf57 diff --git a/manifest.uuid b/manifest.uuid index 6e08bfef94..2a4a25da5e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -251d6473f7c9ad95adbdcc49cb8eaf7c0956764b \ No newline at end of file +c9a30e117f2c6c9ef0cc0c6ca5227d2961715b8f \ No newline at end of file From 5f37ed5121b705f6e2683b071a4bf34f66005cb9 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 29 Feb 2016 20:00:13 +0000 Subject: [PATCH 380/570] Fix minor problems with new code in memjournal.c. FossilOrigin-Name: 9fd3f7b9c93325a83cdbe7dc9ee312b22a9c2898 --- manifest | 17 +++++++---------- manifest.uuid | 2 +- src/memjournal.c | 25 +++++++++++-------------- src/pager.c | 8 +++++--- 4 files changed, 24 insertions(+), 28 deletions(-) diff --git a/manifest b/manifest index 7546ccd6d9..97a63c3c19 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Extend\sthe\scode\sin\smemjournal.c\sso\sthat\sit\ssubsumes\sthe\srole\sof\sjournal.c.\sAnd\s(untested)\scan\sflush\sjournal\sor\sstatement\sjournal\sfiles\sto\sdisk\safter\sthey\sgrow\sto\sa\sspecified\ssize. -D 2016-02-27T20:14:55.339 +C Fix\sminor\sproblems\swith\snew\scode\sin\smemjournal.c. +D 2016-02-29T20:00:13.233 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -321,7 +321,7 @@ F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memjournal.c 8d045e50120e9988e63bb0af69187e1e5e35122f +F src/memjournal.c 9b71f171dd20827022e9edd874adf8dba2b8d218 F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 @@ -336,7 +336,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 3a6f20736dfb8a0949cdd66553fdf59f6604be35 F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c e2bf43b506447d649e9d9266e988007ae7248699 +F src/pager.c 24dd5e463f527427dd55fccc338c62260ae09b3a F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 F src/parse.y c3ce2c4a7cbf0b699239be6b2a945c5cb51875e2 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df @@ -1451,10 +1451,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 f681d800340e0e710f73d0f7c09101f899249183 -R f456c30e495865d50fc2c9c2ddb305ed -T *branch * memjournal-exp -T *sym-memjournal-exp * -T -sym-trunk * +P e0b0b4316531fc8afa74b4882d9c74a91030ec69 +R 662914373e55c4521cf0e8e3f2bf03da U dan -Z dad681f00ca4c98b68e43d3727f3c92e +Z 9ebd4b81ff0d949546d50775b32308aa diff --git a/manifest.uuid b/manifest.uuid index b15150144a..9b400a9c26 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e0b0b4316531fc8afa74b4882d9c74a91030ec69 \ No newline at end of file +9fd3f7b9c93325a83cdbe7dc9ee312b22a9c2898 \ No newline at end of file diff --git a/src/memjournal.c b/src/memjournal.c index 6e1bf4edf7..632f9dc023 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -248,6 +248,10 @@ static int memjrnlWrite( /* ** Truncate the file. +** +** If the journal file is already on disk, truncate it there. Or, if it +** is still in main memory but is being truncated to zero bytes in size, +** ignore */ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ MemJournal *p = (MemJournal *)pJfd; @@ -350,7 +354,7 @@ int sqlite3JournalOpen( ** it using the sqlite3OsOpen() function of the underlying VFS. In this ** case none of the code in this module is executed as a result of calls ** made on the journal file-handle. */ - memset(p, 0, sizeof(MemJournal)); + memset(p, 0, sizeof(MemJournal) + pVfs ? pVfs->szOsFile : 0); if( nBuf==0 ){ return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); } @@ -377,30 +381,23 @@ void sqlite3MemJournalOpen(sqlite3_file *pJfd){ sqlite3JournalOpen(0, 0, pJfd, 0, -1); } -/* -** Return true if the file-handle passed as an argument is an in-memory -** journal. -*/ -int sqlite3IsMemJournal(sqlite3_file *pJfd){ - return pJfd->pMethods==&MemJournalMethods && ((MemJournal*)pJfd)->pReal==0; -} - /* ** If the argument p points to a MemJournal structure that is not an -** in-memory-only journal file, and the underlying file has not yet been -** created, create it now. +** in-memory-only journal file (i.e. is one that was opened with a +ve +** nBuf parameter), and the underlying file has not yet been created, +** create it now. */ int sqlite3JournalCreate(sqlite3_file *p){ int rc = SQLITE_OK; - if( p->pMethods==&MemJournalMethods && ((MemJournal*)p)->nBuf>=0 ){ + if( p->pMethods==&MemJournalMethods && ((MemJournal*)p)->nBuf>0 ){ rc = createFile((MemJournal*)p); } return rc; } /* -** The file-handle passed as teh only argument is open on a journal file. -** Return true if this "journal file" is actually stored in heap memory, +** The file-handle passed as the only argument is open on a journal file. +** Return true if this "journal file" is currently stored in heap memory, ** or false otherwise. */ int sqlite3JournalIsInMemory(sqlite3_file *p){ diff --git a/src/pager.c b/src/pager.c index 5998a57831..81c6572c9d 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1343,6 +1343,7 @@ static i64 journalHdrOffset(Pager *pPager){ static int zeroJournalHdr(Pager *pPager, int doTruncate){ int rc = SQLITE_OK; /* Return code */ assert( isOpen(pPager->jfd) ); + assert( !sqlite3JournalIsInMemory(pPager->jfd) ); if( pPager->journalOff ){ const i64 iLimit = pPager->journalSizeLimit; /* Local cache of jsl */ @@ -1989,9 +1990,10 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ /* This branch may be executed with Pager.journalMode==MEMORY if ** a hot-journal was just rolled back. In this case the journal ** file should be closed and deleted. If this connection writes to - ** the database file, it will do so using an in-memory journal. + ** the database file, it will do so using an in-memory journal. */ - int bDelete = (!pPager->tempFile&&!sqlite3JournalIsInMemory(pPager->jfd)); + int bDelete = !pPager->tempFile; + assert( sqlite3JournalIsInMemory(pPager->jfd)==0 ); assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE || pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->journalMode==PAGER_JOURNALMODE_WAL @@ -2729,7 +2731,7 @@ static int pager_playback(Pager *pPager, int isHot){ ** TODO: Technically the following is an error because it assumes that ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c, - ** mxPathname is 512, which is the same as the minimum allowable value + ** mxPathname is 512, which is the same as the minimum allowable value ** for pageSize. */ zMaster = pPager->pTmpSpace; From 6e76326d185bc37d386a25181fe275fe3fd7b18e Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 29 Feb 2016 20:18:21 +0000 Subject: [PATCH 381/570] When using a temporary file for a statement journal, store the first 64KiB in memory. If the file grows larger than that, flush it to disk and free the memory. Hardcoding to 64KiB is just an experiment to check that the memjournal.c code works. FossilOrigin-Name: 44b2dc18e200e87cf062cb8f1659727c53fa36e9 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/memjournal.c | 2 +- src/pager.c | 9 ++++++--- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 97a63c3c19..0f2eb5c9d9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sminor\sproblems\swith\snew\scode\sin\smemjournal.c. -D 2016-02-29T20:00:13.233 +C When\susing\sa\stemporary\sfile\sfor\sa\sstatement\sjournal,\sstore\sthe\sfirst\s64KiB\sin\smemory.\sIf\sthe\sfile\sgrows\slarger\sthan\sthat,\sflush\sit\sto\sdisk\sand\sfree\sthe\smemory.\sHardcoding\sto\s64KiB\sis\sjust\san\sexperiment\sto\scheck\sthat\sthe\smemjournal.c\scode\sworks. +D 2016-02-29T20:18:21.986 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -321,7 +321,7 @@ F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memjournal.c 9b71f171dd20827022e9edd874adf8dba2b8d218 +F src/memjournal.c fea987c5809993211da554ba109816fae7e04dae F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 @@ -336,7 +336,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 3a6f20736dfb8a0949cdd66553fdf59f6604be35 F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c 24dd5e463f527427dd55fccc338c62260ae09b3a +F src/pager.c 2bc43817697b5a4e88fd6a2cdb2cb25f2223505c F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 F src/parse.y c3ce2c4a7cbf0b699239be6b2a945c5cb51875e2 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df @@ -1451,7 +1451,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 e0b0b4316531fc8afa74b4882d9c74a91030ec69 -R 662914373e55c4521cf0e8e3f2bf03da +P 9fd3f7b9c93325a83cdbe7dc9ee312b22a9c2898 +R 498bd0458994e1419985675b963a5c33 U dan -Z 9ebd4b81ff0d949546d50775b32308aa +Z de04134d7998c131f105dcb3752be845 diff --git a/manifest.uuid b/manifest.uuid index 9b400a9c26..f58d5d3e8e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9fd3f7b9c93325a83cdbe7dc9ee312b22a9c2898 \ No newline at end of file +44b2dc18e200e87cf062cb8f1659727c53fa36e9 \ No newline at end of file diff --git a/src/memjournal.c b/src/memjournal.c index 632f9dc023..eaa4d4f83a 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -354,7 +354,7 @@ int sqlite3JournalOpen( ** it using the sqlite3OsOpen() function of the underlying VFS. In this ** case none of the code in this module is executed as a result of calls ** made on the journal file-handle. */ - memset(p, 0, sizeof(MemJournal) + pVfs ? pVfs->szOsFile : 0); + memset(p, 0, sizeof(MemJournal) + (pVfs ? pVfs->szOsFile : 0)); if( nBuf==0 ){ return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); } diff --git a/src/pager.c b/src/pager.c index 81c6572c9d..c74748c8e4 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4355,11 +4355,14 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){ static int openSubJournal(Pager *pPager){ int rc = SQLITE_OK; if( !isOpen(pPager->sjfd) ){ + const int flags = SQLITE_OPEN_SUBJOURNAL | SQLITE_OPEN_READWRITE + | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE + | SQLITE_OPEN_DELETEONCLOSE; + int nBuf = 64*1024; if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){ - sqlite3MemJournalOpen(pPager->sjfd); - }else{ - rc = pagerOpentemp(pPager, pPager->sjfd, SQLITE_OPEN_SUBJOURNAL); + nBuf = -1; } + rc = sqlite3JournalOpen(pPager->pVfs, 0, pPager->sjfd, flags, nBuf); } return rc; } From 889cb33b8f1321233d79dead07a8089dcf28ef13 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 1 Mar 2016 02:11:50 +0000 Subject: [PATCH 382/570] Better estimatedCost in the xBestIndex method of the generate_series vtab. FossilOrigin-Name: f2c16094a536e7ef62444d0fe38cbee2a4999426 --- ext/misc/series.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/misc/series.c b/ext/misc/series.c index 2ae312effa..4e6341c33b 100644 --- a/ext/misc/series.c +++ b/ext/misc/series.c @@ -337,7 +337,7 @@ static int seriesBestIndex( if( (idxNum & 3)==3 ){ /* Both start= and stop= boundaries are available. This is the ** the preferred case */ - pIdxInfo->estimatedCost = (double)1; + pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0)); pIdxInfo->estimatedRows = 1000; if( pIdxInfo->nOrderBy==1 ){ if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8; diff --git a/manifest b/manifest index bacddf080c..3cdd9396b7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\sin\sfts5\swhere\sa\scorrupt\sdb\scould\slead\sto\sa\s(huge)\sbuffer\soverread. -D 2016-02-29T17:34:16.069 +C Better\sestimatedCost\sin\sthe\sxBestIndex\smethod\sof\sthe\sgenerate_series\svtab. +D 2016-03-01T02:11:50.810 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -212,7 +212,7 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a -F ext/misc/series.c b8fb7befd85b3a9b4a10e701b30b2b79ca92b6d4 +F ext/misc/series.c 235d6281397003ad5226582de216507642aa0095 F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 F ext/misc/spellfix.c 525190484b7a9dbc6be646c4842274fff4f27d53 F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 @@ -1451,7 +1451,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 251d6473f7c9ad95adbdcc49cb8eaf7c0956764b -R 1a43d3061a1f154a38fc05ffa17e1f4a -U dan -Z 0ef60cd2035dd9bea82e9df13f5bcf57 +P c9a30e117f2c6c9ef0cc0c6ca5227d2961715b8f +R 78072d3e9e5d5130b27dfb7458df9d26 +U drh +Z 00eb8a065721ce5867f81f8e93fd77c0 diff --git a/manifest.uuid b/manifest.uuid index 2a4a25da5e..ead2aaed5e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c9a30e117f2c6c9ef0cc0c6ca5227d2961715b8f \ No newline at end of file +f2c16094a536e7ef62444d0fe38cbee2a4999426 \ No newline at end of file From 45a0e4eb599fcf398abf8741d16150d14b675887 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 1 Mar 2016 14:50:55 +0000 Subject: [PATCH 383/570] Fix an fts5 problem causing 'optimize' to corrupt the fts index under some circumstances. Cherrypick of [251d6473f7]. FossilOrigin-Name: 5b1b7ab5d67f3d691e52ba57dbc14c52d90c6631 --- ext/fts5/fts5_index.c | 5 ++++- ext/fts5/test/fts5simple.test | 20 ++++++++++++++++++++ manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index c40ffbcbb5..8e2fb35f0f 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -4499,7 +4499,10 @@ int sqlite3Fts5IndexOptimize(Fts5Index *p){ if( pLvl->aSeg ){ int iLvl, iSeg; int iSegOut = 0; - for(iLvl=0; iLvlnLevel; iLvl++){ + /* Iterate through all segments, from oldest to newest. Add them to + ** the new Fts5Level object so that pLvl->aSeg[0] is the oldest + ** segment in the data structure. */ + for(iLvl=pStruct->nLevel-1; iLvl>=0; iLvl--){ for(iSeg=0; iSegaLevel[iLvl].nSeg; iSeg++){ pLvl->aSeg[iSegOut] = pStruct->aLevel[iLvl].aSeg[iSeg]; iSegOut++; diff --git a/ext/fts5/test/fts5simple.test b/ext/fts5/test/fts5simple.test index a095a16230..01111d78c8 100644 --- a/ext/fts5/test/fts5simple.test +++ b/ext/fts5/test/fts5simple.test @@ -409,5 +409,25 @@ do_catchsql_test 19.2 { SELECT * FROM x1 WHERE x1 MATCH 'c0 AND (c1 AND (c2 AND (c3 AND (c4 AND (c5 AND (c6 AND (c7 AND (c8 AND (c9 AND (c10 AND (c11 AND (c12 AND (c13 AND (c14 AND (c15 AND (c16 AND (c17 AND (c18 AND (c19 AND (c20 AND (c21 AND (c22 AND (c23 AND (c24 AND (c25 AND (c26 AND (c27 AND (c28 AND (c29 AND (c30 AND (c31 AND (c32 AND (c33 AND (c34 AND (c35 AND (c36 AND (c37 AND (c38 AND (c39 AND (c40 AND (c41 AND (c42 AND (c43 AND (c44 AND (c45 AND (c46 AND (c47 AND (c48 AND (c49 AND (c50 AND (c51 AND (c52 AND (c53 AND (c54 AND (c55 AND (c56 AND (c57 AND (c58 AND (c59 AND (c60 AND (c61 AND (c62 AND (c63 AND (c64 AND (c65 AND (c66 AND (c67 AND (c68 AND (c69 AND (c70 AND (c71 AND (c72 AND (c73 AND (c74 AND (c75 AND (c76 AND (c77 AND (c78 AND (c79 AND (c80 AND (c81 AND (c82 AND (c83 AND (c84 AND (c85 AND (c86 AND (c87 AND (c88 AND (c89 AND (c90 AND (c91 AND (c92 AND (c93 AND (c94 AND (c95 AND (c96 AND (c97 AND (c98 AND (c99 AND (c100 AND (c101 AND (c102 AND (c103 AND (c104 AND (c105 AND (c106 AND (c107 AND (c108 AND (c109 AND (c110 AND (c111 AND (c112 AND (c113 AND (c114 AND (c115 AND (c116 AND (c117 AND (c118 AND (c119 AND (c120 AND (c121 AND (c122 AND (c123 AND (c124 AND (c125 AND (c126 AND (c127 AND (c128 AND (c129 AND (c130 AND (c131 AND (c132 AND (c133 AND (c134 AND (c135 AND (c136 AND (c137 AND (c138 AND (c139 AND (c140 AND (c141 AND (c142 AND (c143 AND (c144 AND (c145 AND (c146 AND (c147 AND (c148 AND (c149 AND (c150 AND (c151 AND (c152 AND (c153 AND (c154 AND (c155 AND (c156 AND (c157 AND (c158 AND (c159 AND (c160 AND (c161 AND (c162 AND (c163 AND (c164 AND (c165 AND (c166 AND (c167 AND (c168 AND (c169 AND (c170 AND (c171 AND (c172 AND (c173 AND (c174 AND (c175 AND (c176 AND (c177 AND (c178 AND (c179 AND (c180 AND (c181 AND (c182 AND (c183 AND (c184 AND (c185 AND (c186 AND (c187 AND (c188 AND (c189 AND (c190 AND (c191 AND (c192 AND (c193 AND (c194 AND (c195 AND (c196 AND (c197 AND (c198 AND (c199 AND c200)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))'; } {1 {fts5: parser stack overflow}} +#------------------------------------------------------------------------- +reset_db +breakpoint +do_execsql_test 20.0 { + CREATE VIRTUAL TABLE x1 USING fts5(x); + INSERT INTO x1(x1, rank) VALUES('pgsz', 32); + INSERT INTO x1(rowid, x) VALUES(11111, 'onetwothree'); +} +do_test 20.1 { + for {set i 1} {$i <= 200} {incr i} { + execsql { INSERT INTO x1(rowid, x) VALUES($i, 'one two three'); } + } + execsql { INSERT INTO x1(x1) VALUES('optimize'); } + execsql { DELETE FROM x1 WHERE rowid = 4; } +} {} +do_execsql_test 20.2 { + INSERT INTO x1(x1) VALUES('optimize'); + INSERT INTO x1(x1) VALUES('integrity-check'); +} {} + finish_test diff --git a/manifest b/manifest index 8c52a9794a..afbce79f63 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\san\s"#ifndef\sSQLITE_AMALGAMATION"\sguard\saround\sa\stypedef\sin\sfts5_test_mi.c\sto\savoid\sredefining\s"u32"\sif\sit\sis\scompiled\sas\spart\sof\sthe\samalgamation.\sCherrypick\sof\s[f9c49ba1]. -D 2016-02-19T10:19:43.655 +C Fix\san\sfts5\sproblem\scausing\s'optimize'\sto\scorrupt\sthe\sfts\sindex\sunder\ssome\scircumstances.\sCherrypick\sof\s[251d6473f7]. +D 2016-03-01T14:50:55.628 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c c6cd5190c7e5dd94151cb17acd939c82e5c7be2d +F ext/fts5/fts5_index.c a32f4059b48ee800a94e8a286bf953d67b75185e F ext/fts5/fts5_main.c db24ac714c6c4a1b3c24a1f8c25889f2952148c1 F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -176,7 +176,7 @@ F ext/fts5/test/fts5rank.test 7e9e64eac7245637f6f2033aec4b292aaf611aab F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17 F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6 -F ext/fts5/test/fts5simple.test e6fe2fb10a2b9193648b32bbc2caecabdf8c333d +F ext/fts5/test/fts5simple.test 92e06be1c119f88a73ea11a05599a276ec3ff7fd F ext/fts5/test/fts5simple2.test 98377ae1ff7749a42c21fe1a139c1ed312522c46 F ext/fts5/test/fts5simple3.test 8e71733b3d1b0e695011d02c68ebc5ca40b6124e F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48 @@ -1427,8 +1427,8 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e2ef6667772eeac6eee3aed5d0609c2a0ef5d8cf -Q +f9c49ba1edf13cb8c48d73f1b2e3f80c46b3c030 -R 86861d7afb256ba49d3c7d2e1e2e6725 +P ce0f1ed517e387ca6a687b805088d7c529cd257b +Q +251d6473f7c9ad95adbdcc49cb8eaf7c0956764b +R 5f7a25988e6c8801d10d40ebf8cc999a U dan -Z 1618528e1896e183cb510df07cb30bf4 +Z 645a7ae1e10094786fc6e926b7bb55a9 diff --git a/manifest.uuid b/manifest.uuid index 6c518eaaf7..ef13a6ec43 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ce0f1ed517e387ca6a687b805088d7c529cd257b \ No newline at end of file +5b1b7ab5d67f3d691e52ba57dbc14c52d90c6631 \ No newline at end of file From b1e8d31edfa3b09210ad21dca1f4939ff934742b Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 1 Mar 2016 14:51:36 +0000 Subject: [PATCH 384/570] Fix a problem in fts5 where a corrupt db could lead to a (huge) buffer overread. Cherrypick of [c9a30e117f]. FossilOrigin-Name: daef5869f4d62ebb24eb03b79fe4be0812fa0496 --- ext/fts5/fts5_index.c | 5 +++++ manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 8e2fb35f0f..7f9a931b02 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -698,6 +698,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){ return pRet; } + /* ** Release a reference to data record returned by an earlier call to ** fts5DataRead(). @@ -2154,6 +2155,10 @@ static void fts5LeafSeek( iPgidx = szLeaf; iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff); iOff = iTermOff; + if( iOff>n ){ + p->rc = FTS5_CORRUPT; + return; + } while( 1 ){ diff --git a/manifest b/manifest index afbce79f63..329486cbd8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sfts5\sproblem\scausing\s'optimize'\sto\scorrupt\sthe\sfts\sindex\sunder\ssome\scircumstances.\sCherrypick\sof\s[251d6473f7]. -D 2016-03-01T14:50:55.628 +C Fix\sa\sproblem\sin\sfts5\swhere\sa\scorrupt\sdb\scould\slead\sto\sa\s(huge)\sbuffer\soverread.\sCherrypick\sof\s[c9a30e117f]. +D 2016-03-01T14:51:36.262 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c a32f4059b48ee800a94e8a286bf953d67b75185e +F ext/fts5/fts5_index.c ecc70368618c6bae4bb59124abc343c02634ad0c F ext/fts5/fts5_main.c db24ac714c6c4a1b3c24a1f8c25889f2952148c1 F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -1427,8 +1427,8 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ce0f1ed517e387ca6a687b805088d7c529cd257b -Q +251d6473f7c9ad95adbdcc49cb8eaf7c0956764b -R 5f7a25988e6c8801d10d40ebf8cc999a +P 5b1b7ab5d67f3d691e52ba57dbc14c52d90c6631 +Q +c9a30e117f2c6c9ef0cc0c6ca5227d2961715b8f +R 9e1a768531e15f702b1609ee77fd97cc U dan -Z 645a7ae1e10094786fc6e926b7bb55a9 +Z 25f98900ae0232bf213e8bdd46c5ac6f diff --git a/manifest.uuid b/manifest.uuid index ef13a6ec43..45cc164a6f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5b1b7ab5d67f3d691e52ba57dbc14c52d90c6631 \ No newline at end of file +daef5869f4d62ebb24eb03b79fe4be0812fa0496 \ No newline at end of file From 5ec04f094313be24e4db725874186a50787534dc Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 1 Mar 2016 15:41:31 +0000 Subject: [PATCH 385/570] Increase the version number to 3.11.1 FossilOrigin-Name: 2dcd2fdafe933b74e2d90923986c5ee5791d8223 --- VERSION | 2 +- configure | 18 +++++++++--------- manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/VERSION b/VERSION index afad818663..371cfe355d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.11.0 +3.11.1 diff --git a/configure b/configure index b2cb4d1308..8fdbb45ec8 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sqlite 3.11.0. +# Generated by GNU Autoconf 2.69 for sqlite 3.11.1. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -726,8 +726,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' -PACKAGE_VERSION='3.11.0' -PACKAGE_STRING='sqlite 3.11.0' +PACKAGE_VERSION='3.11.1' +PACKAGE_STRING='sqlite 3.11.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1460,7 +1460,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sqlite 3.11.0 to adapt to many kinds of systems. +\`configure' configures sqlite 3.11.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1525,7 +1525,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.11.0:";; + short | recursive ) echo "Configuration of sqlite 3.11.1:";; esac cat <<\_ACEOF @@ -1646,7 +1646,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.11.0 +sqlite configure 3.11.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2065,7 +2065,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sqlite $as_me 3.11.0, which was +It was created by sqlite $as_me 3.11.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -12079,7 +12079,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sqlite $as_me 3.11.0, which was +This file was extended by sqlite $as_me 3.11.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12145,7 +12145,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sqlite config.status 3.11.0 +sqlite config.status 3.11.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/manifest b/manifest index 2ef2f4d6b6..6eb0c4b8d7 100644 --- a/manifest +++ b/manifest @@ -1,10 +1,10 @@ -C Merge\sbranch-3.11-matchinfo\sinto\sthis\sbranch. -D 2016-03-01T15:09:15.371 +C Increase\sthe\sversion\snumber\sto\s3.11.1 +D 2016-03-01T15:41:31.146 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 56ea123a975690bf9ed38b31bb89ff87b02a7c2b F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 -F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 +F VERSION 1a9f17ac8a5066544976a390298fe62228c58a9e F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 @@ -30,7 +30,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0 F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 -F configure 12d96e3798e612e0ffa53a7a8c4d7fb1090df80e x +F configure 2ea99f0951819177c002c70727b78e51818624b3 x F configure.ac a2224b1162f79848982d3618ac1deffcd94e88ec F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4e54e9c0fefe417f94a2d95921acf61b1dda5ca4 daef5869f4d62ebb24eb03b79fe4be0812fa0496 -R 941c7c2c1d8ea45171acb610a804d763 -U dan -Z 0133e19e04cb90ccecc941fa59f3b459 +P 42358170b35cc3e25c42f20e56f3f67e809001ba +R 85cb3c3574d71e33da57a24aa6b9d049 +U drh +Z c5c8b142342c3d43dce53788f70a0a50 diff --git a/manifest.uuid b/manifest.uuid index 4e289c8410..fbd4d4c630 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -42358170b35cc3e25c42f20e56f3f67e809001ba \ No newline at end of file +2dcd2fdafe933b74e2d90923986c5ee5791d8223 \ No newline at end of file From fb02bad04f1c432e47fb605203b5fc622267c76a Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 1 Mar 2016 15:52:41 +0000 Subject: [PATCH 386/570] Remove a forgotten "breakpoint" command from an FTS5 test script. FossilOrigin-Name: 61927c8f3156c6e61b768318b3cd3bcc4144e17b --- ext/fts5/test/fts5simple.test | 2 -- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/ext/fts5/test/fts5simple.test b/ext/fts5/test/fts5simple.test index 01111d78c8..d1b5647604 100644 --- a/ext/fts5/test/fts5simple.test +++ b/ext/fts5/test/fts5simple.test @@ -411,7 +411,6 @@ do_catchsql_test 19.2 { #------------------------------------------------------------------------- reset_db -breakpoint do_execsql_test 20.0 { CREATE VIRTUAL TABLE x1 USING fts5(x); INSERT INTO x1(x1, rank) VALUES('pgsz', 32); @@ -430,4 +429,3 @@ do_execsql_test 20.2 { } {} finish_test - diff --git a/manifest b/manifest index 6eb0c4b8d7..35437e3eb6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Increase\sthe\sversion\snumber\sto\s3.11.1 -D 2016-03-01T15:41:31.146 +C Remove\sa\sforgotten\s"breakpoint"\scommand\sfrom\san\sFTS5\stest\sscript. +D 2016-03-01T15:52:41.571 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 56ea123a975690bf9ed38b31bb89ff87b02a7c2b @@ -176,7 +176,7 @@ F ext/fts5/test/fts5rank.test 7e9e64eac7245637f6f2033aec4b292aaf611aab F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17 F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6 -F ext/fts5/test/fts5simple.test 92e06be1c119f88a73ea11a05599a276ec3ff7fd +F ext/fts5/test/fts5simple.test 09420cb1137f3a19d02dacb5b4b6831d2e683773 F ext/fts5/test/fts5simple2.test 98377ae1ff7749a42c21fe1a139c1ed312522c46 F ext/fts5/test/fts5simple3.test 8e71733b3d1b0e695011d02c68ebc5ca40b6124e F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 42358170b35cc3e25c42f20e56f3f67e809001ba -R 85cb3c3574d71e33da57a24aa6b9d049 +P 2dcd2fdafe933b74e2d90923986c5ee5791d8223 +R 58e98448c6fb190107b5ef844b8497ab U drh -Z c5c8b142342c3d43dce53788f70a0a50 +Z d57af09b65899a042bcd085eed028813 diff --git a/manifest.uuid b/manifest.uuid index fbd4d4c630..87652f5d83 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2dcd2fdafe933b74e2d90923986c5ee5791d8223 \ No newline at end of file +61927c8f3156c6e61b768318b3cd3bcc4144e17b \ No newline at end of file From e82126c9d0f784f395923fab3732a80ceadc809b Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 1 Mar 2016 16:02:57 +0000 Subject: [PATCH 387/570] Add -DSQLITE_ENABLE_FTS5 to one of the release-test configurations in releasetest.tcl. Run fts5 tests as part of "make test" if SQLITE_ENABLE_FTS5 is defined. FossilOrigin-Name: 3cee93716f2aece03bf9b835fb7b5294e4ddc176 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- test/permutations.test | 10 +++++++--- test/releasetest.tcl | 1 + 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 35437e3eb6..deaacdfcf2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sa\sforgotten\s"breakpoint"\scommand\sfrom\san\sFTS5\stest\sscript. -D 2016-03-01T15:52:41.571 +C Add\s-DSQLITE_ENABLE_FTS5\sto\sone\sof\sthe\srelease-test\sconfigurations\sin\sreleasetest.tcl.\sRun\sfts5\stests\sas\spart\sof\s"make\stest"\sif\sSQLITE_ENABLE_FTS5\sis\sdefined. +D 2016-03-01T16:02:57.526 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 56ea123a975690bf9ed38b31bb89ff87b02a7c2b @@ -944,7 +944,7 @@ F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test 382a43c49f49bafe6fddffe904ea33d6bb3ff33e +F test/permutations.test ea7d077b4644ba0ed6804666915595e9fc3b1950 F test/pragma.test 507ac7ef2ea5682241ea0ef041799ca70bb5e0bf F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c @@ -964,7 +964,7 @@ F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736 F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 -F test/releasetest.tcl 975449bf742b8bb9025208292208af816a1fcb58 +F test/releasetest.tcl a246ecb14ed594bf44bf77bd21df873971d779bf F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2dcd2fdafe933b74e2d90923986c5ee5791d8223 -R 58e98448c6fb190107b5ef844b8497ab -U drh -Z d57af09b65899a042bcd085eed028813 +P 61927c8f3156c6e61b768318b3cd3bcc4144e17b +R bfee7792832173f4b2f2e0f85f5783ce +U dan +Z d07cc313679c906c74090dbeca08d604 diff --git a/manifest.uuid b/manifest.uuid index 87652f5d83..065199ced8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -61927c8f3156c6e61b768318b3cd3bcc4144e17b \ No newline at end of file +3cee93716f2aece03bf9b835fb7b5294e4ddc176 \ No newline at end of file diff --git a/test/permutations.test b/test/permutations.test index c099889067..5c62218d48 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -85,8 +85,11 @@ proc test_set {args} { # $allquicktests # set alltests [list] -foreach f [glob $testdir/*.test] { lappend alltests [file tail $f] } -foreach f [glob -nocomplain $testdir/../ext/rtree/*.test] { +foreach f [glob -nocomplain \ + $testdir/*.test \ + $testdir/../ext/rtree/*.test \ + $testdir/../ext/fts5/test/*.test \ +] { lappend alltests $f } @@ -157,7 +160,8 @@ test_suite "veryquick" -prefix "" -description { This test suite is the same as the "quick" tests, except that some files that test malloc and IO errors are omitted. } -files [ - test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* *_err* + test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* *_err* \ + *fts5corrupt* *fts5big* *fts5aj* ] test_suite "extraquick" -prefix "" -description { diff --git a/test/releasetest.tcl b/test/releasetest.tcl index bb902eec3e..2bcf1aa511 100644 --- a/test/releasetest.tcl +++ b/test/releasetest.tcl @@ -203,6 +203,7 @@ array set ::Configs [strip_comments { -DSQLITE_MAX_ATTACHED=30 -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_FTS4 + -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_FTS4_PARENTHESIS -DSQLITE_DISABLE_FTS4_DEFERRED -DSQLITE_ENABLE_RTREE From bce50c734b937a9756793c46b4f6db832b381036 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 1 Mar 2016 16:56:26 +0000 Subject: [PATCH 388/570] Do not attempt to run fts5bigtok.test or fts5merge2.test if FTS5 is not compiled in. FossilOrigin-Name: f7ed373953c2dea0919a85dfb461dfef512cd5fc --- ext/fts5/test/fts5_common.tcl | 11 ++++------- ext/fts5/test/fts5bigtok.test | 1 + ext/fts5/test/fts5merge2.test | 3 ++- manifest | 16 ++++++++-------- manifest.uuid | 2 +- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/ext/fts5/test/fts5_common.tcl b/ext/fts5/test/fts5_common.tcl index cf688dcc0d..93a8bab806 100644 --- a/ext/fts5/test/fts5_common.tcl +++ b/ext/fts5/test/fts5_common.tcl @@ -16,7 +16,10 @@ if {![info exists testdir]} { source $testdir/tester.tcl ifcapable !fts5 { - finish_test + proc return_if_no_fts5 {} { + finish_test + return -code return + } return } @@ -25,12 +28,6 @@ catch { reset_db } -# If SQLITE_ENABLE_FTS5 is not defined, skip this test. -ifcapable !fts5 { - finish_test - return -} - proc fts5_test_poslist {cmd} { set res [list] for {set i 0} {$i < [$cmd xInstCount]} {incr i} { diff --git a/ext/fts5/test/fts5bigtok.test b/ext/fts5/test/fts5bigtok.test index 2267be5058..9ccaf6c860 100644 --- a/ext/fts5/test/fts5bigtok.test +++ b/ext/fts5/test/fts5bigtok.test @@ -14,6 +14,7 @@ source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5bigtok +return_if_no_fts5 proc rndterm {} { set L [list 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 z] diff --git a/ext/fts5/test/fts5merge2.test b/ext/fts5/test/fts5merge2.test index 87dbf14332..cd515cc29e 100644 --- a/ext/fts5/test/fts5merge2.test +++ b/ext/fts5/test/fts5merge2.test @@ -13,7 +13,8 @@ # source [file join [file dirname [info script]] fts5_common.tcl] -set testprefix fts5merge +set testprefix fts5merge2 +return_if_no_fts5 proc dump_structure {} { db eval {SELECT fts5_decode(id, block) AS t FROM t1_data WHERE id=10} { diff --git a/manifest b/manifest index deaacdfcf2..9293374902 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\s-DSQLITE_ENABLE_FTS5\sto\sone\sof\sthe\srelease-test\sconfigurations\sin\sreleasetest.tcl.\sRun\sfts5\stests\sas\spart\sof\s"make\stest"\sif\sSQLITE_ENABLE_FTS5\sis\sdefined. -D 2016-03-01T16:02:57.526 +C Do\snot\sattempt\sto\srun\sfts5bigtok.test\sor\sfts5merge2.test\sif\sFTS5\sis\snot\scompiled\sin. +D 2016-03-01T16:56:26.421 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 56ea123a975690bf9ed38b31bb89ff87b02a7c2b @@ -116,7 +116,7 @@ F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738 F ext/fts5/fts5_vocab.c dba72ca393d71c2588548b51380387f6b44c77a8 F ext/fts5/fts5parse.y 59432ea369f1aa65511bad465f55d31a22f9f223 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba -F ext/fts5/test/fts5_common.tcl 61ff0d1a29d98a91c4553b20b3f410d858834ee9 +F ext/fts5/test/fts5_common.tcl fbbf457b1433151789a006f9f94c00780a5e3f78 F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b F ext/fts5/test/fts5ac.test 55cad4275a1f5acabfe14d8442a8046b47e49e5f @@ -134,7 +134,7 @@ F ext/fts5/test/fts5auto.test 401c20e89f1114d733b94809be1e6f893e16c09e F ext/fts5/test/fts5aux.test 8c687c948cc98e9a94be014df7d518acc1b3b74f F ext/fts5/test/fts5auxdata.test 141a7cbffcceb1bd2799b4b29c183ff8780d586e F ext/fts5/test/fts5bigpl.test 04ee0d7eebbebf17c31f5a0b5c5f9494eac3a0cb -F ext/fts5/test/fts5bigtok.test 981b2790f6fa02773c889bd35d42c6b97f80f0f4 +F ext/fts5/test/fts5bigtok.test 017a9397b14e7598883a6328ead4a6539b42d59a F ext/fts5/test/fts5columnsize.test a8cfef21ffa1c264b9f670a7d94eeaccb5341c07 F ext/fts5/test/fts5config.test 8b2bc6dcc0eb06fa2b7dd65b2ce2db09e829e873 F ext/fts5/test/fts5conflict.test 26f4e46c4d31e16221794832a990dc4e30e18de5 @@ -162,7 +162,7 @@ F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d F ext/fts5/test/fts5matchinfo.test 86569026d20f1ed748236587ce798de8a96615f1 F ext/fts5/test/fts5merge.test 8f3cdba2ec9c5e7e568246e81b700ad37f764367 -F ext/fts5/test/fts5merge2.test c0cb66eb38a41c26cc5848fb9e50093e0f59ac93 +F ext/fts5/test/fts5merge2.test 8faa829aa3238a25a200200b54780a9bd5d97c14 F ext/fts5/test/fts5near.test b214cddb1c1f1bddf45c75af768f20145f7e71cc F ext/fts5/test/fts5onepass.test 7ed9608e258132cb8d55e7c479b08676ad68810c F ext/fts5/test/fts5optimize.test 42741e7c085ee0a1276140a752d4407d97c2c9f5 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 61927c8f3156c6e61b768318b3cd3bcc4144e17b -R bfee7792832173f4b2f2e0f85f5783ce +P 3cee93716f2aece03bf9b835fb7b5294e4ddc176 +R ea05f03539d26243966fe5b0665aa396 U dan -Z d07cc313679c906c74090dbeca08d604 +Z 26014b2cea95bca862f77aab9147f990 diff --git a/manifest.uuid b/manifest.uuid index 065199ced8..670de7851f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3cee93716f2aece03bf9b835fb7b5294e4ddc176 \ No newline at end of file +f7ed373953c2dea0919a85dfb461dfef512cd5fc \ No newline at end of file From 8e4251b6336bb16cabf45938bf59e276d1bc4419 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 1 Mar 2016 18:07:43 +0000 Subject: [PATCH 389/570] Add test code useful for testing the planners use of teh virtual table xBestIndex() method. FossilOrigin-Name: de034c0db66298454ae8418949d58eb6e223c0de --- main.mk | 1 + manifest | 21 ++- manifest.uuid | 2 +- src/tclsqlite.c | 2 + src/test_bestindex.c | 436 +++++++++++++++++++++++++++++++++++++++++++ test/bestindex1.test | 61 ++++++ 6 files changed, 514 insertions(+), 9 deletions(-) create mode 100644 src/test_bestindex.c create mode 100644 test/bestindex1.test diff --git a/main.mk b/main.mk index e9920180d9..78cb0ad137 100644 --- a/main.mk +++ b/main.mk @@ -285,6 +285,7 @@ TESTSRC = \ $(TOP)/src/test_autoext.c \ $(TOP)/src/test_async.c \ $(TOP)/src/test_backup.c \ + $(TOP)/src/test_bestindex.c \ $(TOP)/src/test_blob.c \ $(TOP)/src/test_btree.c \ $(TOP)/src/test_config.c \ diff --git a/manifest b/manifest index 3cdd9396b7..ca3e2793bd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Better\sestimatedCost\sin\sthe\sxBestIndex\smethod\sof\sthe\sgenerate_series\svtab. -D 2016-03-01T02:11:50.810 +C Add\stest\scode\suseful\sfor\stesting\sthe\splanners\suse\sof\steh\svirtual\stable\sxBestIndex()\smethod. +D 2016-03-01T18:07:43.649 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -273,7 +273,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 791597b87204f6bd56cdf7b2ab2feeecd608c60d +F main.mk 31027cdd40130bdbb3a0862bb97a8c837c5987d9 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -358,7 +358,7 @@ F src/sqliteInt.h 01b43972162c2b5ed864060a23502af3abe0e4f4 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 -F src/tclsqlite.c 13debcc6a5ca1217486f8903768c01114fbe8b58 +F src/tclsqlite.c 54dca4eaf3a9cb0a4b845ef54ffa99225c30a52e F src/test1.c f14a6f9e2cff6cba4d83e2b0c52857f61886cead F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f @@ -371,6 +371,7 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60 F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8 F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 +F src/test_bestindex.c 2004eeca2d227fe62ed581776dc7fd349d45b8f3 F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f F src/test_config.c 0dee90328e3dedf8ba002ee94b6a7e7ea7726fe4 @@ -492,6 +493,7 @@ F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450 F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f F test/bc_common.tcl 3eda41ef9cda7d5f6c205462c96228b301da4191 +F test/bestindex1.test a7213b26f039edfcdb4c0cc13392b79cd4a23779 F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59 F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc @@ -1451,7 +1453,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c9a30e117f2c6c9ef0cc0c6ca5227d2961715b8f -R 78072d3e9e5d5130b27dfb7458df9d26 -U drh -Z 00eb8a065721ce5867f81f8e93fd77c0 +P f2c16094a536e7ef62444d0fe38cbee2a4999426 +R c8660859b43a9c62a3adc82692a6c451 +T *branch * test-bestindex +T *sym-test-bestindex * +T -sym-trunk * +U dan +Z 7443660e56c432a07b1f019ab23aa0dc diff --git a/manifest.uuid b/manifest.uuid index ead2aaed5e..3fb12f3617 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f2c16094a536e7ef62444d0fe38cbee2a4999426 \ No newline at end of file +de034c0db66298454ae8418949d58eb6e223c0de \ No newline at end of file diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 77da6eef52..4e19f92644 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -3774,6 +3774,7 @@ static void init_all(Tcl_Interp *interp){ extern int SqlitetestSyscall_Init(Tcl_Interp*); extern int Fts5tcl_Init(Tcl_Interp *); extern int SqliteRbu_Init(Tcl_Interp*); + extern int Sqlitetesttcl_Init(Tcl_Interp*); #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) extern int Sqlitetestfts3_Init(Tcl_Interp *interp); #endif @@ -3818,6 +3819,7 @@ static void init_all(Tcl_Interp *interp){ SqlitetestSyscall_Init(interp); Fts5tcl_Init(interp); SqliteRbu_Init(interp); + Sqlitetesttcl_Init(interp); #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) Sqlitetestfts3_Init(interp); diff --git a/src/test_bestindex.c b/src/test_bestindex.c new file mode 100644 index 0000000000..051a784c6d --- /dev/null +++ b/src/test_bestindex.c @@ -0,0 +1,436 @@ +/* +** 2013 Jan 11 +** +** 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. +** +************************************************************************* +** Code for testing the virtual table xBestIndex method and the query +** planner. +*/ + + +/* +** INSTRUCTIONS +** +** This module exports a single tcl command - [register_tcl_module]. When +** invoked, it registers a special virtual table module with a database +** connection. +** +** The virtual table is currently read-only. And always returns zero rows. +** It is created with a single argument - the name of a Tcl command - as +** follows: +** +** CREATE VIRTUAL TABLE x1 USING tcl(tcl_command); +** +** The command [tcl_command] is invoked when the table is first created (or +** connected) and when the xBestIndex() method is invoked. When it is created +** (or connected), it is invoked as follows: +** +** tcl_command xConnect +** +** In this case the return value of the script is passed to the +** sqlite3_declare_vtab() function to create the virtual table schema. +** +** When the xBestIndex() method is called by SQLite, the Tcl command is +** invoked as: +** +** tcl_command xBestIndex CONSTRAINTS ORDERBY MASK +** +** where CONSTRAINTS is a tcl representation of the aConstraints[] array, +** ORDERBY is a representation of the contents of the aOrderBy[] array and +** MASK is a copy of sqlite3_index_info.colUsed. For example if the virtual +** table is declared as: +** +** CREATE TABLE x1(a, b, c) +** +** and the query is: +** +** SELECT * FROM x1 WHERE a=? AND c module name ("fs") +** argv[1] -> database name +** argv[2] -> table name +** argv[...] -> other module argument fields. +*/ +static int tclConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + Tcl_Interp *interp = (Tcl_Interp*)pAux; + tcl_vtab *pTab; + const char *zCmd; + Tcl_Obj *pScript = 0; + int rc; + + if( argc!=4 ){ + *pzErr = sqlite3_mprintf("wrong number of arguments"); + return SQLITE_ERROR; + } + zCmd = argv[3]; + + pTab = (tcl_vtab*)sqlite3_malloc(sizeof(tcl_vtab)); + if( pTab==0 ) return SQLITE_NOMEM; + memset(pTab, 0, sizeof(tcl_vtab)); + + pTab->pCmd = Tcl_NewStringObj(zCmd, -1); + pTab->interp = interp; + Tcl_IncrRefCount(pTab->pCmd); + + pScript = Tcl_DuplicateObj(pTab->pCmd); + Tcl_IncrRefCount(pScript); + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xConnect", -1)); + + rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL); + if( rc!=TCL_OK ){ + *pzErr = sqlite3_mprintf("%s", Tcl_GetStringResult(interp)); + rc = SQLITE_ERROR; + }else{ + rc = sqlite3_declare_vtab(db, Tcl_GetStringResult(interp)); + } + + if( rc!=SQLITE_OK ){ + sqlite3_free(pTab); + pTab = 0; + } + + *ppVtab = &pTab->base; + return rc; +} + +/* The xDisconnect and xDestroy methods are also the same */ +static int tclDisconnect(sqlite3_vtab *pVtab){ + tcl_vtab *pTab = (tcl_vtab*)pVtab; + Tcl_DecrRefCount(pTab->pCmd); + sqlite3_free(pTab); + return SQLITE_OK; +} + +/* +** Open a new tcl cursor. +*/ +static int tclOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + tcl_cursor *pCur; + pCur = sqlite3_malloc(sizeof(tcl_cursor)); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(tcl_cursor)); + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* +** Close a tcl cursor. +*/ +static int tclClose(sqlite3_vtab_cursor *cur){ + tcl_cursor *pCur = (tcl_cursor *)cur; + sqlite3_free(pCur); + return SQLITE_OK; +} + +static int tclNext(sqlite3_vtab_cursor *cur){ + return SQLITE_OK; +} + +static int tclFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + return SQLITE_OK; +} + +static int tclColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ + return SQLITE_OK; +} + +static int tclRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + return SQLITE_OK; +} + +static int tclEof(sqlite3_vtab_cursor *cur){ + return 1; +} + +static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ + tcl_vtab *pTab = (tcl_vtab*)tab; + Tcl_Interp *interp = pTab->interp; + Tcl_Obj *pArg; + Tcl_Obj *pScript; + int ii; + int rc = SQLITE_OK; + + pScript = Tcl_DuplicateObj(pTab->pCmd); + Tcl_IncrRefCount(pScript); + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xBestIndex", -1)); + + pArg = Tcl_NewObj(); + Tcl_IncrRefCount(pArg); + for(ii=0; iinConstraint; ii++){ + struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii]; + Tcl_Obj *pElem = Tcl_NewObj(); + const char *zOp = "?"; + + Tcl_IncrRefCount(pElem); + + switch( pCons->op ){ + case SQLITE_INDEX_CONSTRAINT_EQ: + zOp = "eq"; break; + case SQLITE_INDEX_CONSTRAINT_GT: + zOp = "gt"; break; + case SQLITE_INDEX_CONSTRAINT_LE: + zOp = "le"; break; + case SQLITE_INDEX_CONSTRAINT_LT: + zOp = "lt"; break; + case SQLITE_INDEX_CONSTRAINT_GE: + zOp = "ge"; break; + case SQLITE_INDEX_CONSTRAINT_MATCH: + zOp = "match"; break; + case SQLITE_INDEX_CONSTRAINT_LIKE: + zOp = "like"; break; + case SQLITE_INDEX_CONSTRAINT_GLOB: + zOp = "glob"; break; + case SQLITE_INDEX_CONSTRAINT_REGEXP: + zOp = "regexp"; break; + } + + Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("op", -1)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zOp, -1)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("column", -1)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->iColumn)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("usable", -1)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->usable)); + + Tcl_ListObjAppendElement(0, pArg, pElem); + Tcl_DecrRefCount(pElem); + } + + Tcl_ListObjAppendElement(0, pScript, pArg); + Tcl_DecrRefCount(pArg); + + pArg = Tcl_NewObj(); + Tcl_IncrRefCount(pArg); + for(ii=0; iinOrderBy; ii++){ + struct sqlite3_index_orderby const *pOrder = &pIdxInfo->aOrderBy[ii]; + Tcl_Obj *pElem = Tcl_NewObj(); + Tcl_IncrRefCount(pElem); + + Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("column", -1)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pOrder->iColumn)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("desc", -1)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pOrder->desc)); + + Tcl_ListObjAppendElement(0, pArg, pElem); + Tcl_DecrRefCount(pElem); + } + + Tcl_ListObjAppendElement(0, pScript, pArg); + Tcl_DecrRefCount(pArg); + + Tcl_ListObjAppendElement(0, pScript, Tcl_NewWideIntObj(pIdxInfo->colUsed)); + + rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL); + Tcl_DecrRefCount(pScript); + if( rc!=TCL_OK ){ + const char *zErr = Tcl_GetStringResult(interp); + rc = SQLITE_ERROR; + pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); + }else{ + /* Analyze the scripts return value. The return value should be a tcl + ** list object with an even number of elements. The first element of each + ** pair must be one of: + ** + ** "orderby" (value of orderByConsumed flag) + ** "cost" (value of estimatedCost field) + ** "rows" (value of estimatedRows field) + ** "use" (index of used constraint in aConstraint[]) + ** "idxnum" (value of idxNum field) + ** "idxstr" (value of idxStr field) + */ + Tcl_Obj *pRes = Tcl_GetObjResult(interp); + Tcl_Obj **apElem = 0; + int nElem; + rc = Tcl_ListObjGetElements(interp, pRes, &nElem, &apElem); + if( rc!=TCL_OK ){ + const char *zErr = Tcl_GetStringResult(interp); + rc = SQLITE_ERROR; + pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); + }else{ + int iArgv = 1; + for(ii=0; rc==SQLITE_OK && iiestimatedCost); + }else + if( sqlite3_stricmp("orderby", zCmd)==0 ){ + rc = Tcl_GetIntFromObj(interp, p, &pIdxInfo->orderByConsumed); + }else + if( sqlite3_stricmp("idxnum", zCmd)==0 ){ + rc = Tcl_GetIntFromObj(interp, p, &pIdxInfo->idxNum); + }else + if( sqlite3_stricmp("idxstr", zCmd)==0 ){ + sqlite3_free(pIdxInfo->idxStr); + pIdxInfo->idxStr = sqlite3_mprintf("%s", Tcl_GetString(p)); + }else + if( sqlite3_stricmp("rows", zCmd)==0 ){ + rc = Tcl_GetWideIntFromObj(interp, p, &pIdxInfo->estimatedRows); + }else + if( sqlite3_stricmp("use", zCmd)==0 ){ + int iCons; + rc = Tcl_GetIntFromObj(interp, p, &iCons); + if( rc==SQLITE_OK ){ + if( iCons<0 || iCons>=pIdxInfo->nConstraint ){ + rc = SQLITE_ERROR; + pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %d", iCons); + }else{ + pIdxInfo->aConstraintUsage[iCons].argvIndex = iArgv++; + } + } + }else{ + rc = SQLITE_ERROR; + pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %s", zCmd); + } + if( rc!=SQLITE_OK && pTab->base.zErrMsg==0 ){ + const char *zErr = Tcl_GetStringResult(interp); + pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); + } + } + } + } + + return rc; +} + +/* +** A virtual table module that provides read-only access to a +** Tcl global variable namespace. +*/ +static sqlite3_module tclModule = { + 0, /* iVersion */ + tclConnect, + tclConnect, + tclBestIndex, + tclDisconnect, + tclDisconnect, + tclOpen, /* xOpen - open a cursor */ + tclClose, /* xClose - close a cursor */ + tclFilter, /* xFilter - configure scan constraints */ + tclNext, /* xNext - advance a cursor */ + tclEof, /* xEof - check for end of scan */ + tclColumn, /* xColumn - read data */ + tclRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ +}; + +/* +** Decode a pointer to an sqlite3 object. +*/ +extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); + +/* +** Register the echo virtual table module. +*/ +static int register_tcl_module( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3 *db; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3_create_module(db, "tcl", &tclModule, (void *)interp); +#endif + return TCL_OK; +} + +#endif + + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetesttcl_Init(Tcl_Interp *interp){ +#ifndef SQLITE_OMIT_VIRTUALTABLE + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + void *clientData; + } aObjCmd[] = { + { "register_tcl_module", register_tcl_module, 0 }, + }; + int i; + for(i=0; i Date: Tue, 1 Mar 2016 18:24:36 +0000 Subject: [PATCH 390/570] Allow test_bestindex.c to set the omit flag for a constraint. FossilOrigin-Name: 759b9d5b22aa60cc1d6b606f81eb7366c28cbcbe --- manifest | 17 +++++++---------- manifest.uuid | 2 +- src/test_bestindex.c | 7 ++++++- test/bestindex1.test | 4 ++-- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index ca3e2793bd..6d84721ebf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stest\scode\suseful\sfor\stesting\sthe\splanners\suse\sof\steh\svirtual\stable\sxBestIndex()\smethod. -D 2016-03-01T18:07:43.649 +C Allow\stest_bestindex.c\sto\sset\sthe\somit\sflag\sfor\sa\sconstraint. +D 2016-03-01T18:24:36.515 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -371,7 +371,7 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60 F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8 F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 -F src/test_bestindex.c 2004eeca2d227fe62ed581776dc7fd349d45b8f3 +F src/test_bestindex.c 6448b9b7ef9729f04093462be539255938d256db F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f F src/test_config.c 0dee90328e3dedf8ba002ee94b6a7e7ea7726fe4 @@ -493,7 +493,7 @@ F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450 F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f F test/bc_common.tcl 3eda41ef9cda7d5f6c205462c96228b301da4191 -F test/bestindex1.test a7213b26f039edfcdb4c0cc13392b79cd4a23779 +F test/bestindex1.test 8d8ae7e96a98079f43518cae536535cc52aee49b F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59 F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc @@ -1453,10 +1453,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 f2c16094a536e7ef62444d0fe38cbee2a4999426 -R c8660859b43a9c62a3adc82692a6c451 -T *branch * test-bestindex -T *sym-test-bestindex * -T -sym-trunk * +P de034c0db66298454ae8418949d58eb6e223c0de +R 25f59441195481b2d87b75ea969fe23e U dan -Z 7443660e56c432a07b1f019ab23aa0dc +Z 102ea7e54c5366f48aedd548677f81f2 diff --git a/manifest.uuid b/manifest.uuid index 3fb12f3617..d72f0e3eaf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -de034c0db66298454ae8418949d58eb6e223c0de \ No newline at end of file +759b9d5b22aa60cc1d6b606f81eb7366c28cbcbe \ No newline at end of file diff --git a/src/test_bestindex.c b/src/test_bestindex.c index 051a784c6d..e58c363db5 100644 --- a/src/test_bestindex.c +++ b/src/test_bestindex.c @@ -302,6 +302,7 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ ** "use" (index of used constraint in aConstraint[]) ** "idxnum" (value of idxNum field) ** "idxstr" (value of idxStr field) + ** "omit" (index of omitted constraint in aConstraint[]) */ Tcl_Obj *pRes = Tcl_GetObjResult(interp); Tcl_Obj **apElem = 0; @@ -332,7 +333,9 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ if( sqlite3_stricmp("rows", zCmd)==0 ){ rc = Tcl_GetWideIntFromObj(interp, p, &pIdxInfo->estimatedRows); }else - if( sqlite3_stricmp("use", zCmd)==0 ){ + if( sqlite3_stricmp("use", zCmd)==0 + || sqlite3_stricmp("omit", zCmd)==0 + ){ int iCons; rc = Tcl_GetIntFromObj(interp, p, &iCons); if( rc==SQLITE_OK ){ @@ -340,7 +343,9 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ rc = SQLITE_ERROR; pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %d", iCons); }else{ + int bOmit = (zCmd[0]=='o' || zCmd[0]=='O'); pIdxInfo->aConstraintUsage[iCons].argvIndex = iArgv++; + pIdxInfo->aConstraintUsage[iCons].omit = bOmit; } } }else{ diff --git a/test/bestindex1.test b/test/bestindex1.test index e3443ddc77..7b1fb86228 100644 --- a/test/bestindex1.test +++ b/test/bestindex1.test @@ -29,7 +29,7 @@ proc vtab_command {method args} { catch { array unset C } array set C [lindex $clist 0] if {$C(usable)} { - return "use 0 cost 0 rows 1 idxnum 555 idxstr eq!" + return "omit 0 cost 0 rows 1 idxnum 555 idxstr eq!" } else { return "cost 1000000 rows 0 idxnum 0 idxstr scan..." } @@ -50,11 +50,11 @@ do_eqp_test 1.1 { 0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!} } -#set sqlite_where_trace 0x3ff do_eqp_test 1.2 { SELECT * FROM x1 WHERE a IN ('abc', 'def'); } { 0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!} + 0 0 0 {EXECUTE LIST SUBQUERY 1} } finish_test From 23c3c38dd63e5c8bd8568f18ce6839672d7f2ebe Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 1 Mar 2016 18:35:55 +0000 Subject: [PATCH 391/570] Fix a memory leak in the test code on this branch. FossilOrigin-Name: 7a1add56341f43dc41adc7b370e58860f4dd50a3 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/test_bestindex.c | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 6d84721ebf..775d6d0fdb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Allow\stest_bestindex.c\sto\sset\sthe\somit\sflag\sfor\sa\sconstraint. -D 2016-03-01T18:24:36.515 +C Fix\sa\smemory\sleak\sin\sthe\stest\scode\son\sthis\sbranch. +D 2016-03-01T18:35:55.112 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -371,7 +371,7 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60 F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8 F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 -F src/test_bestindex.c 6448b9b7ef9729f04093462be539255938d256db +F src/test_bestindex.c 31ac82f4b21395572e26c6693bf47fdd032d6e61 F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f F src/test_config.c 0dee90328e3dedf8ba002ee94b6a7e7ea7726fe4 @@ -1453,7 +1453,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 de034c0db66298454ae8418949d58eb6e223c0de -R 25f59441195481b2d87b75ea969fe23e +P 759b9d5b22aa60cc1d6b606f81eb7366c28cbcbe +R e9150850334c910fa82ad79b36b013cf U dan -Z 102ea7e54c5366f48aedd548677f81f2 +Z bc3fb098cb9eaf89cb42b29f1b53a09a diff --git a/manifest.uuid b/manifest.uuid index d72f0e3eaf..0849f0a941 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -759b9d5b22aa60cc1d6b606f81eb7366c28cbcbe \ No newline at end of file +7a1add56341f43dc41adc7b370e58860f4dd50a3 \ No newline at end of file diff --git a/src/test_bestindex.c b/src/test_bestindex.c index e58c363db5..4fbf63bf19 100644 --- a/src/test_bestindex.c +++ b/src/test_bestindex.c @@ -329,6 +329,7 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ if( sqlite3_stricmp("idxstr", zCmd)==0 ){ sqlite3_free(pIdxInfo->idxStr); pIdxInfo->idxStr = sqlite3_mprintf("%s", Tcl_GetString(p)); + pIdxInfo->needToFreeIdxStr = 1; }else if( sqlite3_stricmp("rows", zCmd)==0 ){ rc = Tcl_GetWideIntFromObj(interp, p, &pIdxInfo->estimatedRows); From 4fb48e4eb1ebfec2ea07f0871edef28a188a6c52 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 1 Mar 2016 22:41:27 +0000 Subject: [PATCH 392/570] Improved debugging output with wheretrace. Fix some typos in test script comments. FossilOrigin-Name: 13a37fd487ce7d4f98a12f7a67a9c05dadc66557 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/where.c | 3 ++- test/analyze9.test | 2 +- test/analyzeD.test | 5 ++--- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 3cdd9396b7..e8fac4d6a2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Better\sestimatedCost\sin\sthe\sxBestIndex\smethod\sof\sthe\sgenerate_series\svtab. -D 2016-03-01T02:11:50.810 +C Improved\sdebugging\soutput\swith\swheretrace.\s\sFix\ssome\stypos\sin\stest\sscript\ncomments. +D 2016-03-01T22:41:27.874 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -428,7 +428,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c 32051597188dc632bafb32d50a9c3a04fb97ce39 +F src/where.c 6282e53fcc612a8918262f1432d6fd7fbc24af40 F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 39c1ef4598bedf1d66249334c74efd23ddd182ac F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a @@ -451,11 +451,11 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test c05a461d0a6b05991106467d0c47480f2e709c82 -F test/analyze9.test 88c1f2aa20b614236f03e1cc38c3619e7e8a38b4 +F test/analyze9.test b817b8e798315fc65b820a5463f73ad5f48ed8dd F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a F test/analyzeB.test a4c1c3048f6d9e090eb76e83eecb18bcf6d31a70 F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93 -F test/analyzeD.test f3d77cd0fefe2849d784897d52df13beee19271d +F test/analyzeD.test 42af58de25a6436502e43006e9e59e2d71bcb0cf F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d F test/analyzeF.test 5d1fe1024ba2dfea3c18bede8c1ccef8aba1ab34 F test/analyzer1.test 498e2ff4b62740c2751c3a2f8b744fe26689fae9 @@ -1451,7 +1451,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 c9a30e117f2c6c9ef0cc0c6ca5227d2961715b8f -R 78072d3e9e5d5130b27dfb7458df9d26 +P f2c16094a536e7ef62444d0fe38cbee2a4999426 +R 8bf9dc83caf7a5f48b09e10ce3dd712c U drh -Z 00eb8a065721ce5867f81f8e93fd77c0 +Z cbae5a3ad8eb0cbd1b6534802cfd9e9b diff --git a/manifest.uuid b/manifest.uuid index ead2aaed5e..1fa5c8f4d5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f2c16094a536e7ef62444d0fe38cbee2a4999426 \ No newline at end of file +13a37fd487ce7d4f98a12f7a67a9c05dadc66557 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 71d3cb01ef..e2a482cf90 100644 --- a/src/where.c +++ b/src/where.c @@ -1561,7 +1561,8 @@ static int whereEqualScanEst( pBuilder->nRecValid = nEq; whereKeyStats(pParse, p, pRec, 0, a); - WHERETRACE(0x10,("equality scan regions: %d\n", (int)a[1])); + WHERETRACE(0x10,("equality scan regions %s(%d): %d\n", + p->zName, nEq-1, (int)a[1])); *pnRow = a[1]; return rc; diff --git a/test/analyze9.test b/test/analyze9.test index e24f3dd49d..918577bd19 100644 --- a/test/analyze9.test +++ b/test/analyze9.test @@ -1180,7 +1180,7 @@ do_execsql_test 26.1.3 { # # There should be no other samples that start with (x=10000). So it knows # that (x=10000 AND y<50) must match somewhere between 0 and 99 rows, but -# know more than that. Guessing less than 20 is therefore unreasonable. +# no more than that. Guessing less than 20 is therefore unreasonable. # # At one point though, due to a problem in whereKeyStats(), the planner was # estimating that (x=10000 AND y<50) would match only 2 rows. diff --git a/test/analyzeD.test b/test/analyzeD.test index 7ef1094f82..4588aaeebc 100644 --- a/test/analyzeD.test +++ b/test/analyzeD.test @@ -1,4 +1,4 @@ -# 2005 July 22 +# 2014-10-04 # # 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. # This file implements tests for the ANALYZE command. # -# $Id: analyze.test,v 1.9 2008/08/11 18:44:58 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -75,7 +74,7 @@ do_test 1.3 { } {} # Without stat1, because 3001 is larger than all samples in the stat4 -# table, SQLite things that a=3001 matches just 1 row. So it (incorrectly) +# table, SQLite thinks that a=3001 matches just 1 row. So it (incorrectly) # chooses it over the c=150 index (5 rows). Even with stat1 data, things # worked this way before commit [e6f7f97dbc]. # From 47784529cc3c667c214a6fa5ea37182b26a32a89 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 2 Mar 2016 00:58:49 +0000 Subject: [PATCH 393/570] Add the optional -DSERIES_OMIT_CONSTRAINT_VERIFY=0 option to the series.c extension that implements the generate_series() virtual table. FossilOrigin-Name: 3d9daa929c0abe6dc01e800ef343b0eef2f0c76a --- ext/misc/series.c | 14 +++++++++++--- manifest | 13 ++++++------- manifest.uuid | 2 +- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/ext/misc/series.c b/ext/misc/series.c index 4e6341c33b..f2e0a39658 100644 --- a/ext/misc/series.c +++ b/ext/misc/series.c @@ -217,6 +217,14 @@ static int seriesEof(sqlite3_vtab_cursor *cur){ } } +/* True to omit run-time checking of the start=, stop=, and/or step= +** parameters. The only reason to not omit these is for testing the +** constraint checking logic for virtual tables in the SQLite core. +*/ +#ifndef SERIES_OMIT_CONSTRAINT_VERIFY +# define SERIES_OMIT_CONSTRAINT_VERIFY 1 +#endif + /* ** This method is called to "rewind" the series_cursor object back ** to the first row of output. This method is always called at least @@ -324,15 +332,15 @@ static int seriesBestIndex( } if( startIdx>=0 ){ pIdxInfo->aConstraintUsage[startIdx].argvIndex = ++nArg; - pIdxInfo->aConstraintUsage[startIdx].omit = 1; + pIdxInfo->aConstraintUsage[startIdx].omit = SERIES_OMIT_CONSTRAINT_VERIFY; } if( stopIdx>=0 ){ pIdxInfo->aConstraintUsage[stopIdx].argvIndex = ++nArg; - pIdxInfo->aConstraintUsage[stopIdx].omit = 1; + pIdxInfo->aConstraintUsage[stopIdx].omit = SERIES_OMIT_CONSTRAINT_VERIFY; } if( stepIdx>=0 ){ pIdxInfo->aConstraintUsage[stepIdx].argvIndex = ++nArg; - pIdxInfo->aConstraintUsage[stepIdx].omit = 1; + pIdxInfo->aConstraintUsage[stepIdx].omit = SERIES_OMIT_CONSTRAINT_VERIFY; } if( (idxNum & 3)==3 ){ /* Both start= and stop= boundaries are available. This is the diff --git a/manifest b/manifest index 7784cb3c77..bfe67e6715 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C New\stest\scases\sand\sinfrastructure\sfor\stesting\sthe\sxBestIndex\smethod\sof\s\nvirtual\stables. -D 2016-03-01T22:48:00.766 +C Add\sthe\soptional\s-DSERIES_OMIT_CONSTRAINT_VERIFY=0\soption\sto\sthe\sseries.c\nextension\sthat\simplements\sthe\sgenerate_series()\svirtual\stable. +D 2016-03-02T00:58:49.570 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -212,7 +212,7 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a -F ext/misc/series.c 235d6281397003ad5226582de216507642aa0095 +F ext/misc/series.c e1ef8bc23328d4e2196835737f62b324bdcd1c0d F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 F ext/misc/spellfix.c 525190484b7a9dbc6be646c4842274fff4f27d53 F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 @@ -1453,8 +1453,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 13a37fd487ce7d4f98a12f7a67a9c05dadc66557 7a1add56341f43dc41adc7b370e58860f4dd50a3 -R 0985007e1a98dc617470e125c83c71f2 -T +closed 7a1add56341f43dc41adc7b370e58860f4dd50a3 +P 1d41c161165006d6c2af47e476f05fb13039f8b8 +R 7bc50a1ee335d764bdfff403c9ca0d5d U drh -Z 971ab7ec7b38808209f8a28c1ffc2c5d +Z d249d93e08651d834742ccb923f02a0e diff --git a/manifest.uuid b/manifest.uuid index ab5413d9af..67149f5847 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1d41c161165006d6c2af47e476f05fb13039f8b8 \ No newline at end of file +3d9daa929c0abe6dc01e800ef343b0eef2f0c76a \ No newline at end of file From dbc49161c0bc186351d56743a2ad0e1bac56a3da Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 2 Mar 2016 03:28:07 +0000 Subject: [PATCH 394/570] Allow the left-hand side of IN operators on virtual tables to have the aConstraintUsage[].omit flag clear. FossilOrigin-Name: 1622623cbbfc4325c53d731aba78ca9c382ec612 --- Makefile.in | 1 + Makefile.msc | 1 + ext/misc/series.c | 14 +++++++------- main.mk | 3 ++- manifest | 27 +++++++++++++++------------ manifest.uuid | 2 +- src/where.c | 7 ------- src/wherecode.c | 45 ++++++++++++++++++++++++++++++++++++++++----- test/tabfunc01.test | 15 +++++++++++++++ 9 files changed, 82 insertions(+), 33 deletions(-) diff --git a/Makefile.in b/Makefile.in index 013cf442d1..891329719a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1050,6 +1050,7 @@ sqlite3rbu.lo: $(TOP)/ext/rbu/sqlite3rbu.c $(HDR) $(EXTHDR) TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE TESTFIXTURE_FLAGS += -DBUILD_sqlite +TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la TESTFIXTURE_SRC1 = sqlite3.c diff --git a/Makefile.msc b/Makefile.msc index de225305f5..d9af285c06 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1925,6 +1925,7 @@ sqlite3rbu.lo: $(TOP)\ext\rbu\sqlite3rbu.c $(HDR) $(EXTHDR) TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN) +TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C) diff --git a/ext/misc/series.c b/ext/misc/series.c index f2e0a39658..9f80bb46ca 100644 --- a/ext/misc/series.c +++ b/ext/misc/series.c @@ -217,12 +217,12 @@ static int seriesEof(sqlite3_vtab_cursor *cur){ } } -/* True to omit run-time checking of the start=, stop=, and/or step= -** parameters. The only reason to not omit these is for testing the +/* True to cause run-time checking of the start=, stop=, and/or step= +** parameters. The only reason to do this is for testing the ** constraint checking logic for virtual tables in the SQLite core. */ -#ifndef SERIES_OMIT_CONSTRAINT_VERIFY -# define SERIES_OMIT_CONSTRAINT_VERIFY 1 +#ifndef SQLITE_SERIES_CONSTRAINT_VERIFY +# define SQLITE_SERIES_CONSTRAINT_VERIFY 0 #endif /* @@ -332,15 +332,15 @@ static int seriesBestIndex( } if( startIdx>=0 ){ pIdxInfo->aConstraintUsage[startIdx].argvIndex = ++nArg; - pIdxInfo->aConstraintUsage[startIdx].omit = SERIES_OMIT_CONSTRAINT_VERIFY; + pIdxInfo->aConstraintUsage[startIdx].omit= !SQLITE_SERIES_CONSTRAINT_VERIFY; } if( stopIdx>=0 ){ pIdxInfo->aConstraintUsage[stopIdx].argvIndex = ++nArg; - pIdxInfo->aConstraintUsage[stopIdx].omit = SERIES_OMIT_CONSTRAINT_VERIFY; + pIdxInfo->aConstraintUsage[stopIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY; } if( stepIdx>=0 ){ pIdxInfo->aConstraintUsage[stepIdx].argvIndex = ++nArg; - pIdxInfo->aConstraintUsage[stepIdx].omit = SERIES_OMIT_CONSTRAINT_VERIFY; + pIdxInfo->aConstraintUsage[stepIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY; } if( (idxNum & 3)==3 ){ /* Both start= and stop= boundaries are available. This is the diff --git a/main.mk b/main.mk index 78cb0ad137..97dc254378 100644 --- a/main.mk +++ b/main.mk @@ -726,7 +726,8 @@ sqlite3_analyzer$(EXE): sqlite3_analyzer.c # Rules to build the 'testfixture' application. # TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 -TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE +TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE +TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c $(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \ diff --git a/manifest b/manifest index bfe67e6715..3c5171c6ed 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Add\sthe\soptional\s-DSERIES_OMIT_CONSTRAINT_VERIFY=0\soption\sto\sthe\sseries.c\nextension\sthat\simplements\sthe\sgenerate_series()\svirtual\stable. -D 2016-03-02T00:58:49.570 -F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 +C Allow\sthe\sleft-hand\sside\sof\sIN\soperators\son\svirtual\stables\sto\shave\sthe\naConstraintUsage[].omit\sflag\sclear. +D 2016-03-02T03:28:07.978 +F Makefile.in e335453db0b16da00c884ad51bb56d1c091a74de F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 +F Makefile.msc dbd4621ecc585c2ef0c2aa0874698c54675754f1 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION c6b1f51809551d60ad001e6d87cf3ab2c7f54b6f F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -212,7 +212,7 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a -F ext/misc/series.c e1ef8bc23328d4e2196835737f62b324bdcd1c0d +F ext/misc/series.c e11e534ada797d5b816d7e7a93c022306563ca35 F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 F ext/misc/spellfix.c 525190484b7a9dbc6be646c4842274fff4f27d53 F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 @@ -273,7 +273,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 31027cdd40130bdbb3a0862bb97a8c837c5987d9 +F main.mk 518d93f9f606d515628f99ce03f9e909f4f8a2e3 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -429,9 +429,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c 6282e53fcc612a8918262f1432d6fd7fbc24af40 +F src/where.c 56948ada5aacc3bf2628db3776986e8bf4085383 F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 -F src/wherecode.c 39c1ef4598bedf1d66249334c74efd23ddd182ac +F src/wherecode.c 3ca820435c5b597bb50e63ed11e938786fe5c23e F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1074,7 +1074,7 @@ F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849 F test/sync.test 2f607e1821aa3af3c5c53b58835c05e511c95899 F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 -F test/tabfunc01.test cc33684f9480fcf1fd5ce287ac28d22971cad1cc +F test/tabfunc01.test f977868fa8bb7beb4b2072883190411653473906 F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 @@ -1453,7 +1453,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1d41c161165006d6c2af47e476f05fb13039f8b8 -R 7bc50a1ee335d764bdfff403c9ca0d5d +P 3d9daa929c0abe6dc01e800ef343b0eef2f0c76a +R c059a6ee769a0309e913921e43679d8c +T *branch * vtab-IN-opt +T *sym-vtab-IN-opt * +T -sym-trunk * U drh -Z d249d93e08651d834742ccb923f02a0e +Z f36b44043e8c4337262495e2c87317b9 diff --git a/manifest.uuid b/manifest.uuid index 67149f5847..a061607f33 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3d9daa929c0abe6dc01e800ef343b0eef2f0c76a \ No newline at end of file +1622623cbbfc4325c53d731aba78ca9c382ec612 \ No newline at end of file diff --git a/src/where.c b/src/where.c index e2a482cf90..ed90f61443 100644 --- a/src/where.c +++ b/src/where.c @@ -2898,13 +2898,6 @@ static int whereLoopAddVirtual( testcase( iTerm==16 ); if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<eOperator & WO_IN)!=0 ){ - if( pUsage[i].omit==0 ){ - /* Do not attempt to use an IN constraint if the virtual table - ** says that the equivalent EQ constraint cannot be safely omitted. - ** If we do attempt to use such a constraint, some rows might be - ** repeated in the output. */ - break; - } /* A virtual table that is constrained by an IN clause may not ** consume the ORDER BY clause because (1) the order of IN terms ** is not necessarily related to the order of output terms and diff --git a/src/wherecode.c b/src/wherecode.c index accc140866..bfc52fb470 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -874,6 +874,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( int iReg; /* P3 Value for OP_VFilter */ int addrNotFound; int nConstraint = pLoop->nLTerm; + int iIn; /* Counter for IN constraints */ sqlite3ExprCachePush(pParse); iReg = sqlite3GetTempRange(pParse, nConstraint+2); @@ -896,14 +897,48 @@ Bitmask sqlite3WhereCodeOneLoopStart( pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC); VdbeCoverage(v); pLoop->u.vtab.needFree = 0; - for(j=0; ju.vtab.omitMask>>j)&1 ){ - disableTerm(pLevel, pLoop->aLTerm[j]); - } - } pLevel->p1 = iCur; pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext; pLevel->p2 = sqlite3VdbeCurrentAddr(v); + iIn = pLevel->u.in.nIn; + for(j=nConstraint-1; j>=0; j--){ + pTerm = pLoop->aLTerm[j]; + if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){ + disableTerm(pLevel, pTerm); + }else if( (pTerm->eOperator & WO_IN)!=0 ){ + Expr *pCompare; /* The comparison operator */ + Expr *pRight; /* RHS of the comparison */ + VdbeOp *pOp; /* Opcode to access the value of the IN constraint */ + + /* Reload the constraint value into reg[iReg+j+2]. The same value + ** was loaded into the same register prior to the OP_VFilter, but + ** the xFilter implementation might have changed the datatype or + ** encoding of the value in the register, so it *must* be reloaded. */ + assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed ); + if( pLevel->u.in.aInLoop!=0 ){ + assert( iIn>0 ); + pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[--iIn].addrInTop); + assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid ); + assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 ); + assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 ); + testcase( pOp->opcode==OP_Rowid ); + sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3); + } + + /* Generate code that will continue to the next row if + ** the IN constraint is not satisfied */ + pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0, 0); + assert( pCompare!=0 || db->mallocFailed ); + if( pCompare ){ + pCompare->pLeft = pTerm->pExpr->pLeft; + pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0); + if( pRight ) pRight->iTable = iReg+j+2; + sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0); + pCompare->pLeft = 0; + sqlite3ExprDelete(db, pCompare); + } + } + } sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); sqlite3ExprCachePop(pParse); }else diff --git a/test/tabfunc01.test b/test/tabfunc01.test index d85cb20ff5..879a045b8e 100644 --- a/test/tabfunc01.test +++ b/test/tabfunc01.test @@ -120,4 +120,19 @@ do_catchsql_test tabfunc01-4.3 { SELECT * FROM aux1.generate_series(1,4) } {1 {no such table: aux1.generate_series}} +# The next series of tests is verifying that virtual table are able +# to optimize the IN operator, even on terms that are not marked "omit". +# When the generate_series virtual table is compiled for the testfixture, +# the special -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 option is used, which +# causes the xBestIndex method of generate_series to leave the +# sqlite3_index_constraint_usage.omit flag set to 0, which should cause +# the SQLite core to verify the start=, stop=, and step= constraints on +# each step of output. At one point, the IN operator could not be used +# by virtual tables unless omit was set. +# +do_execsql_test tabfunc01-500 { + SELECT * FROM generate_series WHERE start IN (1,7) AND stop=20 AND step=10 + ORDER BY +1; +} {1 7 11 17} + finish_test From e18ec6acc281d1c213fdfeb0000d7c0a2509b698 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 2 Mar 2016 13:26:19 +0000 Subject: [PATCH 395/570] Fix an error in an fts5 test script. FossilOrigin-Name: b2a03e2d479aec2fc68dfc83a1fa34c740f44e13 --- ext/fts5/test/fts5_common.tcl | 2 ++ ext/fts5/test/fts5merge2.test | 2 -- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/fts5/test/fts5_common.tcl b/ext/fts5/test/fts5_common.tcl index 93a8bab806..32691d1c81 100644 --- a/ext/fts5/test/fts5_common.tcl +++ b/ext/fts5/test/fts5_common.tcl @@ -21,6 +21,8 @@ ifcapable !fts5 { return -code return } return +} else { + proc return_if_no_fts5 {} {} } catch { diff --git a/ext/fts5/test/fts5merge2.test b/ext/fts5/test/fts5merge2.test index cd515cc29e..0d3fad8b08 100644 --- a/ext/fts5/test/fts5merge2.test +++ b/ext/fts5/test/fts5merge2.test @@ -27,8 +27,6 @@ proc dump_structure {} { foreach_detail_mode $testprefix { -if {[detail_is_none]==0} continue - do_execsql_test 1.0 { CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%); INSERT INTO t1(t1, rank) VALUES('pgsz', 32); diff --git a/manifest b/manifest index 9293374902..2738351d63 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sattempt\sto\srun\sfts5bigtok.test\sor\sfts5merge2.test\sif\sFTS5\sis\snot\scompiled\sin. -D 2016-03-01T16:56:26.421 +C Fix\san\serror\sin\san\sfts5\stest\sscript. +D 2016-03-02T13:26:19.396 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 56ea123a975690bf9ed38b31bb89ff87b02a7c2b @@ -116,7 +116,7 @@ F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738 F ext/fts5/fts5_vocab.c dba72ca393d71c2588548b51380387f6b44c77a8 F ext/fts5/fts5parse.y 59432ea369f1aa65511bad465f55d31a22f9f223 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba -F ext/fts5/test/fts5_common.tcl fbbf457b1433151789a006f9f94c00780a5e3f78 +F ext/fts5/test/fts5_common.tcl b9b1fed811c0390511cef8b254826ea15d380f4d F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b F ext/fts5/test/fts5ac.test 55cad4275a1f5acabfe14d8442a8046b47e49e5f @@ -162,7 +162,7 @@ F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d F ext/fts5/test/fts5matchinfo.test 86569026d20f1ed748236587ce798de8a96615f1 F ext/fts5/test/fts5merge.test 8f3cdba2ec9c5e7e568246e81b700ad37f764367 -F ext/fts5/test/fts5merge2.test 8faa829aa3238a25a200200b54780a9bd5d97c14 +F ext/fts5/test/fts5merge2.test a6da3c16d694235938d1939f503cfa53f0943d75 F ext/fts5/test/fts5near.test b214cddb1c1f1bddf45c75af768f20145f7e71cc F ext/fts5/test/fts5onepass.test 7ed9608e258132cb8d55e7c479b08676ad68810c F ext/fts5/test/fts5optimize.test 42741e7c085ee0a1276140a752d4407d97c2c9f5 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 3cee93716f2aece03bf9b835fb7b5294e4ddc176 -R ea05f03539d26243966fe5b0665aa396 +P f7ed373953c2dea0919a85dfb461dfef512cd5fc +R fb67c5bfcdd18aefee22c2054e345c4e U dan -Z 26014b2cea95bca862f77aab9147f990 +Z 0301af39ef437e67ac6a081e34e72ea7 diff --git a/manifest.uuid b/manifest.uuid index 670de7851f..6bb6c19871 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f7ed373953c2dea0919a85dfb461dfef512cd5fc \ No newline at end of file +b2a03e2d479aec2fc68dfc83a1fa34c740f44e13 \ No newline at end of file From 341b20fb125bcc386f8ca4c0035cb8e971021ed0 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 2 Mar 2016 15:37:50 +0000 Subject: [PATCH 396/570] Fix a recently introduced problem in permutations.test causing an error when the QUICKTEST_OMIT environment variable is defined. FossilOrigin-Name: 45bc9557722cc2a1398a53fdb2acd8b6692f3121 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/permutations.test | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 2738351d63..6154587dc0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\serror\sin\san\sfts5\stest\sscript. -D 2016-03-02T13:26:19.396 +C Fix\sa\srecently\sintroduced\sproblem\sin\spermutations.test\scausing\san\serror\swhen\sthe\sQUICKTEST_OMIT\senvironment\svariable\sis\sdefined. +D 2016-03-02T15:37:50.695 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 56ea123a975690bf9ed38b31bb89ff87b02a7c2b @@ -944,7 +944,7 @@ F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test ea7d077b4644ba0ed6804666915595e9fc3b1950 +F test/permutations.test 7c9e145c9b888f719daa28a843db2c25f04f8b1d F test/pragma.test 507ac7ef2ea5682241ea0ef041799ca70bb5e0bf F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f7ed373953c2dea0919a85dfb461dfef512cd5fc -R fb67c5bfcdd18aefee22c2054e345c4e +P b2a03e2d479aec2fc68dfc83a1fa34c740f44e13 +R c3f5f569c1111b59b7a7b8d3cc840098 U dan -Z 0301af39ef437e67ac6a081e34e72ea7 +Z 3f6f2fabdb87bc8705a94a5cd070d288 diff --git a/manifest.uuid b/manifest.uuid index 6bb6c19871..2e84c0697d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b2a03e2d479aec2fc68dfc83a1fa34c740f44e13 \ No newline at end of file +45bc9557722cc2a1398a53fdb2acd8b6692f3121 \ No newline at end of file diff --git a/test/permutations.test b/test/permutations.test index 5c62218d48..6d1b1d7c05 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -85,8 +85,8 @@ proc test_set {args} { # $allquicktests # set alltests [list] +foreach f [glob $testdir/*.test] { lappend alltests [file tail $f] } foreach f [glob -nocomplain \ - $testdir/*.test \ $testdir/../ext/rtree/*.test \ $testdir/../ext/fts5/test/*.test \ ] { From 9cc24c8002c9bbfe0615aee849c8043f7ac702e3 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 2 Mar 2016 16:01:41 +0000 Subject: [PATCH 397/570] Enhance test_bestindex.c so that it can be used to test plans generated by xBestIndex. FossilOrigin-Name: 3c15a9bf45cd7dae2fbd99123b8dd75ce278d6e4 --- manifest | 16 ++--- manifest.uuid | 2 +- src/test_bestindex.c | 146 +++++++++++++++++++++++++++++++++++++++---- test/bestindex1.test | 96 ++++++++++++++++++++++++++++ 4 files changed, 240 insertions(+), 20 deletions(-) diff --git a/manifest b/manifest index bfe67e6715..18c08f648b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\soptional\s-DSERIES_OMIT_CONSTRAINT_VERIFY=0\soption\sto\sthe\sseries.c\nextension\sthat\simplements\sthe\sgenerate_series()\svirtual\stable. -D 2016-03-02T00:58:49.570 +C Enhance\stest_bestindex.c\sso\sthat\sit\scan\sbe\sused\sto\stest\splans\sgenerated\sby\sxBestIndex. +D 2016-03-02T16:01:41.146 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -371,7 +371,7 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60 F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8 F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 -F src/test_bestindex.c cd2eb53d7abf082665bca161e6762c4ba395f17a +F src/test_bestindex.c a711473c79e812e4082fbf045ed6c18c99c16058 F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f F src/test_config.c 0dee90328e3dedf8ba002ee94b6a7e7ea7726fe4 @@ -493,7 +493,7 @@ F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450 F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f F test/bc_common.tcl 3eda41ef9cda7d5f6c205462c96228b301da4191 -F test/bestindex1.test 41c763428e403663b3e15b2acba7f07b40b22592 +F test/bestindex1.test ca4a6457c276f564d9db91e22980a9fa08e66e6b F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59 F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc @@ -1453,7 +1453,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 1d41c161165006d6c2af47e476f05fb13039f8b8 -R 7bc50a1ee335d764bdfff403c9ca0d5d -U drh -Z d249d93e08651d834742ccb923f02a0e +P 3d9daa929c0abe6dc01e800ef343b0eef2f0c76a +R 10e42f20a022f81e947260641e83d066 +U dan +Z 32cbbe1a7e810bc34e8a7796bb6fedf4 diff --git a/manifest.uuid b/manifest.uuid index 67149f5847..a4b1d5378e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3d9daa929c0abe6dc01e800ef343b0eef2f0c76a \ No newline at end of file +3c15a9bf45cd7dae2fbd99123b8dd75ce278d6e4 \ No newline at end of file diff --git a/src/test_bestindex.c b/src/test_bestindex.c index c0e67299f4..6982ce3ca9 100644 --- a/src/test_bestindex.c +++ b/src/test_bestindex.c @@ -28,8 +28,9 @@ ** CREATE VIRTUAL TABLE x1 USING tcl(tcl_command); ** ** The command [tcl_command] is invoked when the table is first created (or -** connected) and when the xBestIndex() method is invoked. When it is created -** (or connected), it is invoked as follows: +** connected), when the xBestIndex() method is invoked and when the xFilter() +** method is called. When it is created (or connected), it is invoked as +** follows: ** ** tcl_command xConnect ** @@ -67,10 +68,27 @@ ** "cost" (value of estimatedCost field) ** "rows" (value of estimatedRows field) ** "use" (index of used constraint in aConstraint[]) +** "omit" (like "use", but also sets omit flag) ** "idxnum" (value of idxNum field) ** "idxstr" (value of idxStr field) ** ** Refer to code below for further details. +** +** When SQLite calls the xFilter() method, this module invokes the following +** Tcl script: +** +** tcl_command xFilter IDXNUM IDXSTR ARGLIST +** +** IDXNUM and IDXSTR are the values of the idxNum and idxStr parameters +** passed to xFilter. ARGLIST is a Tcl list containing each of the arguments +** passed to xFilter in text form. +** +** As with xBestIndex(), the return value of the script is interpreted as a +** list of key-value pairs. There is currently only one key defined - "sql". +** The value must be the full text of an SQL statement that returns the data +** for the current scan. The leftmost column returned by the SELECT is assumed +** to contain the rowid. Other columns must follow, in order from left to +** right. */ @@ -89,11 +107,13 @@ struct tcl_vtab { sqlite3_vtab base; Tcl_Interp *interp; Tcl_Obj *pCmd; + sqlite3 *db; }; /* A tcl cursor object */ struct tcl_cursor { sqlite3_vtab_cursor base; + sqlite3_stmt *pStmt; /* Read data from here */ }; /* @@ -132,6 +152,7 @@ static int tclConnect( pTab->pCmd = Tcl_NewStringObj(zCmd, -1); pTab->interp = interp; + pTab->db = db; Tcl_IncrRefCount(pTab->pCmd); pScript = Tcl_DuplicateObj(pTab->pCmd); @@ -180,11 +201,29 @@ static int tclOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ */ static int tclClose(sqlite3_vtab_cursor *cur){ tcl_cursor *pCur = (tcl_cursor *)cur; - sqlite3_free(pCur); + if( pCur ){ + sqlite3_finalize(pCur->pStmt); + sqlite3_free(pCur); + } return SQLITE_OK; } -static int tclNext(sqlite3_vtab_cursor *cur){ +static int tclNext(sqlite3_vtab_cursor *pVtabCursor){ + tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; + tcl_vtab *pTab = (tcl_vtab*)(pVtabCursor->pVtab); + if( pCsr->pStmt ){ + tcl_vtab *pTab = (tcl_vtab*)(pVtabCursor->pVtab); + int rc = sqlite3_step(pCsr->pStmt); + if( rc!=SQLITE_ROW ){ + const char *zErr; + rc = sqlite3_finalize(pCsr->pStmt); + pCsr->pStmt = 0; + if( rc!=SQLITE_OK ){ + zErr = sqlite3_errmsg(pTab->db); + pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); + } + } + } return SQLITE_OK; } @@ -193,19 +232,104 @@ static int tclFilter( int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ + tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; + tcl_vtab *pTab = (tcl_vtab*)(pVtabCursor->pVtab); + Tcl_Interp *interp = pTab->interp; + Tcl_Obj *pScript; + Tcl_Obj *pArg; + int ii; + int rc; + + pScript = Tcl_DuplicateObj(pTab->pCmd); + Tcl_IncrRefCount(pScript); + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xFilter", -1)); + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewIntObj(idxNum)); + if( idxStr ){ + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(idxStr, -1)); + }else{ + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("", -1)); + } + + pArg = Tcl_NewObj(); + Tcl_IncrRefCount(pArg); + for(ii=0; iibase.zErrMsg = sqlite3_mprintf("%s", zErr); + }else{ + /* Analyze the scripts return value. The return value should be a tcl + ** list object with an even number of elements. The first element of each + ** pair must be one of: + ** + ** "sql" (SQL statement to return data) + */ + Tcl_Obj *pRes = Tcl_GetObjResult(interp); + Tcl_Obj **apElem = 0; + int nElem; + rc = Tcl_ListObjGetElements(interp, pRes, &nElem, &apElem); + if( rc!=TCL_OK ){ + const char *zErr = Tcl_GetStringResult(interp); + rc = SQLITE_ERROR; + pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); + }else{ + int iArgv = 1; + for(ii=0; rc==SQLITE_OK && iidb, zSql, -1, &pCsr->pStmt, 0); + if( rc!=SQLITE_OK ){ + const char *zErr = sqlite3_errmsg(pTab->db); + pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %s", zErr); + } + }else{ + rc = SQLITE_ERROR; + pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %s", zCmd); + } + } + } + } + + if( rc==SQLITE_OK ){ + rc = tclNext(pVtabCursor); + } + return rc; +} + +static int tclColumn( + sqlite3_vtab_cursor *pVtabCursor, + sqlite3_context *ctx, + int i +){ + tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; + sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, i+1)); return SQLITE_OK; } -static int tclColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ +static int tclRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){ + tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; + *pRowid = sqlite3_column_int64(pCsr->pStmt, 0); return SQLITE_OK; } -static int tclRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - return SQLITE_OK; -} - -static int tclEof(sqlite3_vtab_cursor *cur){ - return 1; +static int tclEof(sqlite3_vtab_cursor *pVtabCursor){ + tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; + return (pCsr->pStmt==0); } static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ diff --git a/test/bestindex1.test b/test/bestindex1.test index 840219b620..87ec9cc56a 100644 --- a/test/bestindex1.test +++ b/test/bestindex1.test @@ -57,4 +57,100 @@ do_eqp_test 1.2 { 0 0 0 {EXECUTE LIST SUBQUERY 1} } +#------------------------------------------------------------------------- +# +reset_db +register_tcl_module db + +# Parameter $mode may be one of: +# +# "omit" - Implement filtering. Set the omit flag. +# "use" - Implement filtering. Use the constraint, but do not set omit. +# "use2" - Do not implement filtering. Use the constraint anyway. +# +# +proc t1_vtab {mode method args} { + switch -- $method { + xConnect { + return "CREATE TABLE t1(a, b)" + } + + xBestIndex { + set SQL_FILTER {SELECT * FROM t1x WHERE a='%1%'} + set SQL_SCAN {SELECT * FROM t1x} + + set clist [lindex $args 0] + set idx 0 + for {set idx 0} {$idx < [llength $clist]} {incr idx} { + array unset C + array set C [lindex $clist $idx] + if {$C(column)==0 && $C(op)=="eq" && $C(usable)} { + switch -- $mode { + "omit" { + return [list omit $idx rows 10 cost 10 idxstr $SQL_FILTER] + } + "use" { + return [list use $idx rows 10 cost 10 idxstr $SQL_FILTER] + } + "use2" { + return [list use $idx rows 10 cost 10 idxstr $SQL_SCAN] + } + default { + error "Bad mode - $mode" + } + } + } + } + + return [list idxstr {SELECT * FROM t1x}] + } + + xFilter { + set map [list %1% [lindex $args 2 0]] + set sql [string map $map [lindex $args 1]] + return [list sql $sql] + } + } + + return {} +} + +do_execsql_test 2.1 { + CREATE TABLE t1x(i INTEGER PRIMARY KEY, a, b); + INSERT INTO t1x VALUES(1, 'one', 1); + INSERT INTO t1x VALUES(2, 'two', 2); + INSERT INTO t1x VALUES(3, 'three', 3); + INSERT INTO t1x VALUES(4, 'four', 4); +} + +foreach {tn mode} { + 1 use 2 omit 3 use2 +} { + do_execsql_test 2.2.$mode.1 " + DROP TABLE IF EXISTS t1; + CREATE VIRTUAL TABLE t1 USING tcl(t1_vtab $mode); + " + + do_execsql_test 2.2.$mode.2 {SELECT * FROM t1} {one 1 two 2 three 3 four 4} + do_execsql_test 2.2.$mode.3 {SELECT rowid FROM t1} {1 2 3 4} + do_execsql_test 2.2.$mode.4 {SELECT rowid FROM t1 WHERE a='two'} {2} + + do_execsql_test 2.2.$mode.5 { + SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid + } {1 4} + + set plan(use) {0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x}} + set plan(use2) {0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x}} + set plan(omit) { + 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'} + 0 0 0 {EXECUTE LIST SUBQUERY 1} + } + + do_eqp_test 2.2.$mode.6 { + SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid + } [concat $plan($mode) {0 0 0 {USE TEMP B-TREE FOR ORDER BY}}] +} + finish_test + + From b78b83a2f68cea70e50b07978d16bee912e46465 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 2 Mar 2016 17:57:53 +0000 Subject: [PATCH 398/570] Add new test script bestindex1.test to the utf16 permutation. FossilOrigin-Name: 5893e97244126c80762e55249461f21a4e81bb70 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/permutations.test | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 7914b48dc3..80c0005276 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\san\sextra\stest\sfor\sthe\schange\son\sthis\sbranch. -D 2016-03-02T16:13:53.809 +C Add\snew\stest\sscript\sbestindex1.test\sto\sthe\sutf16\spermutation. +D 2016-03-02T17:57:53.035 F Makefile.in e335453db0b16da00c884ad51bb56d1c091a74de F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc dbd4621ecc585c2ef0c2aa0874698c54675754f1 @@ -947,7 +947,7 @@ F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test 382a43c49f49bafe6fddffe904ea33d6bb3ff33e +F test/permutations.test 7872debaba9e4513dfc7bb52ff32f5a1429985e4 F test/pragma.test 507ac7ef2ea5682241ea0ef041799ca70bb5e0bf F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c @@ -1453,7 +1453,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 1622623cbbfc4325c53d731aba78ca9c382ec612 3c15a9bf45cd7dae2fbd99123b8dd75ce278d6e4 -R bdc2b3d0e5cbd463ccc4765d0aeeef84 +P d2d28251566d2a0ec1a07fe5b8ed047136840bfd +R f53f8a06609558c5e139632a3abf7f8d U dan -Z d9e37a89daaed1ba1547f52769e0ebb4 +Z 9060a915fc132a5c0981e5ef43325748 diff --git a/manifest.uuid b/manifest.uuid index 562b522fef..2e05ec2241 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d2d28251566d2a0ec1a07fe5b8ed047136840bfd \ No newline at end of file +5893e97244126c80762e55249461f21a4e81bb70 \ No newline at end of file diff --git a/test/permutations.test b/test/permutations.test index c099889067..975021a611 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -612,6 +612,7 @@ test_suite "utf16" -description { trace.test trigger1.test trigger2.test trigger3.test trigger4.test types2.test types.test unique.test update.test vacuum.test view.test where.test + bestindex1.test } # Run some tests in exclusive locking mode. From 2396fce54ec748917837ab0b41a6d8e05079bd92 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 3 Mar 2016 15:16:15 +0000 Subject: [PATCH 399/570] Increase the default upper bound on scope to 30. FossilOrigin-Name: b1258814f6100f594210775e9e3007b5b0c65025 --- ext/misc/spellfix.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/misc/spellfix.c b/ext/misc/spellfix.c index cac1edcff8..5734d04f41 100644 --- a/ext/misc/spellfix.c +++ b/ext/misc/spellfix.c @@ -1775,7 +1775,7 @@ static void scriptCodeSqlFunc( */ /* Maximum length of a phonehash used for querying the shadow table */ -#define SPELLFIX_MX_HASH 8 +#define SPELLFIX_MX_HASH 32 /* Maximum number of hash strings to examine per query */ #define SPELLFIX_MX_RUN 1 diff --git a/manifest b/manifest index 6154587dc0..437867ecc2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\srecently\sintroduced\sproblem\sin\spermutations.test\scausing\san\serror\swhen\sthe\sQUICKTEST_OMIT\senvironment\svariable\sis\sdefined. -D 2016-03-02T15:37:50.695 +C Increase\sthe\sdefault\supper\sbound\son\sscope\sto\s30. +D 2016-03-03T15:16:15.336 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 56ea123a975690bf9ed38b31bb89ff87b02a7c2b @@ -213,7 +213,7 @@ F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a F ext/misc/series.c b8fb7befd85b3a9b4a10e701b30b2b79ca92b6d4 F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 -F ext/misc/spellfix.c 525190484b7a9dbc6be646c4842274fff4f27d53 +F ext/misc/spellfix.c 194b5fc3a9a63cb6c5680d8f713800012bddca7c F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b2a03e2d479aec2fc68dfc83a1fa34c740f44e13 -R c3f5f569c1111b59b7a7b8d3cc840098 -U dan -Z 3f6f2fabdb87bc8705a94a5cd070d288 +P 45bc9557722cc2a1398a53fdb2acd8b6692f3121 +R da5680e10572eb2ee67e7f4f853b931e +U drh +Z 04cb77a072223fec31cd6c5dab87e3c4 diff --git a/manifest.uuid b/manifest.uuid index 2e84c0697d..28ed117fc7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -45bc9557722cc2a1398a53fdb2acd8b6692f3121 \ No newline at end of file +b1258814f6100f594210775e9e3007b5b0c65025 \ No newline at end of file From c5c1507612e0e5d45b8683ba406e12fe6ac9c94a Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 3 Mar 2016 16:17:53 +0000 Subject: [PATCH 400/570] Version 3.11.1 FossilOrigin-Name: f047920ce16971e573bc6ec9a48b118c9de2b3a7 --- manifest | 11 +++++++---- manifest.uuid | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/manifest b/manifest index 437867ecc2..907e6740e1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Increase\sthe\sdefault\supper\sbound\son\sscope\sto\s30. -D 2016-03-03T15:16:15.336 +C Version\s3.11.1 +D 2016-03-03T16:17:53.102 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 56ea123a975690bf9ed38b31bb89ff87b02a7c2b @@ -1427,7 +1427,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 45bc9557722cc2a1398a53fdb2acd8b6692f3121 +P b1258814f6100f594210775e9e3007b5b0c65025 R da5680e10572eb2ee67e7f4f853b931e +T +bgcolor * #d0c0ff +T +sym-release * +T +sym-version-3.11.1 * U drh -Z 04cb77a072223fec31cd6c5dab87e3c4 +Z ad71638129773a9e26cf148e72895b35 diff --git a/manifest.uuid b/manifest.uuid index 28ed117fc7..6b480a26b8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b1258814f6100f594210775e9e3007b5b0c65025 \ No newline at end of file +f047920ce16971e573bc6ec9a48b118c9de2b3a7 \ No newline at end of file From ff6b82663181c0ebdd4b57a0e858466c3658c78d Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 4 Mar 2016 00:13:29 +0000 Subject: [PATCH 401/570] Get in-memory subjournals working for builds without SQLITE_ENABLE_ATOMIC_WRITE. FossilOrigin-Name: b5378dcea53d4cd1744d13ddee5e50869607b771 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/memjournal.c | 3 ++- src/sqliteInt.h | 6 ++---- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index c50e674c64..9f2d2fdb74 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\slatest\supdates\sfrom\strunk. -D 2016-03-03T21:29:10.682 +C Get\sin-memory\ssubjournals\sworking\sfor\sbuilds\swithout\sSQLITE_ENABLE_ATOMIC_WRITE. +D 2016-03-04T00:13:29.040 F Makefile.in e335453db0b16da00c884ad51bb56d1c091a74de F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc dbd4621ecc585c2ef0c2aa0874698c54675754f1 @@ -321,7 +321,7 @@ F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memjournal.c fea987c5809993211da554ba109816fae7e04dae +F src/memjournal.c 56c7688565cf407c5f22f03e3be478d3a92bdc81 F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 @@ -354,7 +354,7 @@ F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 57da6fd6aa35dff72eb946064ff4999eab6bc616 +F src/sqliteInt.h 8a4810fa90b17eb08acab43649b877e894ea1e98 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1453,7 +1453,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 44b2dc18e200e87cf062cb8f1659727c53fa36e9 16fbf2e19c22df9441aef5c8b7f5670adc38a6b6 -R bdaefcabe5bf87c04d8b11c17326d65d +P 55c00f716dc98b188c91f3a5a010242c9497785f +R 9e3fbc3007cf6215e63dd7896623508e U drh -Z 002d922341500f2c0dc185f71a114083 +Z 727109808ff36a69d33c43dee6d82c50 diff --git a/manifest.uuid b/manifest.uuid index 5a1d0fe44a..7f1e0b5ee4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -55c00f716dc98b188c91f3a5a010242c9497785f \ No newline at end of file +b5378dcea53d4cd1744d13ddee5e50869607b771 \ No newline at end of file diff --git a/src/memjournal.c b/src/memjournal.c index eaa4d4f83a..9ecd2a9ba3 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -381,6 +381,7 @@ void sqlite3MemJournalOpen(sqlite3_file *pJfd){ sqlite3JournalOpen(0, 0, pJfd, 0, -1); } +#ifdef SQLITE_ENABLE_ATOMIC_WRITE /* ** If the argument p points to a MemJournal structure that is not an ** in-memory-only journal file (i.e. is one that was opened with a +ve @@ -394,6 +395,7 @@ int sqlite3JournalCreate(sqlite3_file *p){ } return rc; } +#endif /* ** The file-handle passed as the only argument is open on a journal file. @@ -411,4 +413,3 @@ int sqlite3JournalIsInMemory(sqlite3_file *p){ int sqlite3JournalSize(sqlite3_vfs *pVfs){ return pVfs->szOsFile + sizeof(MemJournal); } - diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 69cbb6c604..387bb7436b 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3998,12 +3998,10 @@ const char *sqlite3JournalModename(int); #define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */ int sqlite3FindInIndex(Parse *, Expr *, u32, int*); +int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); +int sqlite3JournalSize(sqlite3_vfs *); #ifdef SQLITE_ENABLE_ATOMIC_WRITE - int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); - int sqlite3JournalSize(sqlite3_vfs *); int sqlite3JournalCreate(sqlite3_file *); -#else - #define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile) #endif int sqlite3JournalIsInMemory(sqlite3_file *p); From e32a256acd23dcde4671a662426afa8a6d3a354b Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 4 Mar 2016 02:38:00 +0000 Subject: [PATCH 402/570] Update the configure script to detect pread/pwrite and update os_unix.c to use those routines if they are available. FossilOrigin-Name: 2cffb9e50bed77d1079603f5b4a71b7559de7294 --- config.h.in | 12 ++++++++++++ configure | 2 +- configure.ac | 2 +- manifest | 19 +++++++++---------- manifest.uuid | 2 +- src/os_unix.c | 37 +++++++++++++++++++++++++++---------- 6 files changed, 51 insertions(+), 23 deletions(-) diff --git a/config.h.in b/config.h.in index 36fd60781c..f2ba7d4fc4 100644 --- a/config.h.in +++ b/config.h.in @@ -45,6 +45,18 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have the pread() function. */ +#undef HAVE_PREAD + +/* Define to 1 if you have the pread64() function. */ +#undef HAVE_PREAD64 + +/* Define to 1 if you have the pwrite() function. */ +#undef HAVE_PWRITE + +/* Define to 1 if you have the pwrite64() function. */ +#undef HAVE_PWRITE64 + /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H diff --git a/configure b/configure index 09fba81eae..8363818c6f 100755 --- a/configure +++ b/configure @@ -10273,7 +10273,7 @@ done ######### # Figure out whether or not we have these functions # -for ac_func in fdatasync gmtime_r isnan localtime_r localtime_s malloc_usable_size strchrnul usleep utime +for ac_func in fdatasync gmtime_r isnan localtime_r localtime_s malloc_usable_size strchrnul usleep utime pread pread64 pwrite pwrite64 do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/configure.ac b/configure.ac index 19f85dc875..08c8867f06 100644 --- a/configure.ac +++ b/configure.ac @@ -108,7 +108,7 @@ AC_CHECK_HEADERS([sys/types.h stdlib.h stdint.h inttypes.h malloc.h]) ######### # Figure out whether or not we have these functions # -AC_CHECK_FUNCS([fdatasync gmtime_r isnan localtime_r localtime_s malloc_usable_size strchrnul usleep utime]) +AC_CHECK_FUNCS([fdatasync gmtime_r isnan localtime_r localtime_s malloc_usable_size strchrnul usleep utime pread pread64 pwrite pwrite64]) ######### # By default, we use the amalgamation (this may be changed below...) diff --git a/manifest b/manifest index 7f70989146..06e5c8c969 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Reduce\sthe\samount\sof\sheap\smemory\srequired\sto\sstore\smany\sschemas\sby\sstoring\s\nthe\scolumn\sdatatype\sappended\sto\sthe\scolumn\sname\s(with\sa\s\\000\sseparator),\s\nrather\sthan\sin\sseparate\smemory\sallocation. -D 2016-03-03T21:22:53.735 +C Update\sthe\sconfigure\sscript\sto\sdetect\spread/pwrite\sand\supdate\sos_unix.c\sto\nuse\sthose\sroutines\sif\sthey\sare\savailable. +D 2016-03-04T02:38:00.565 F Makefile.in e335453db0b16da00c884ad51bb56d1c091a74de F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc dbd4621ecc585c2ef0c2aa0874698c54675754f1 @@ -28,10 +28,10 @@ F autoconf/tea/win/makefile.vc f89d0184d0eee5f7e356ea407964dcd139939928 F autoconf/tea/win/nmakehlp.c 247538ad8e8c508f33c03ec1fbd67d3a07ef6291 F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 -F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0 +F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 -F configure 0339a635cd2943a3b56000a10a11b4b2e6ed6d1b x -F configure.ac a2224b1162f79848982d3618ac1deffcd94e88ec +F configure c01a159fdf7ea0171ad01ce2937283f2c7972bde x +F configure.ac 89e4e02a83d8a1528011f8395621b8c3186b4089 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/lemon.html c30255bea0fd87a81f082d17a72c9dffbc3f6dd9 F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710 @@ -333,7 +333,7 @@ F src/os.c ca9a104b677328ee037cfdf1a54a16fd1805e8c9 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c 3a6f20736dfb8a0949cdd66553fdf59f6604be35 +F src/os_unix.c a1aaf2d8d253138e63d2a8a972693f9f624f885d F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c d034c69b958c01289eb8070cbf902e1a68cd7e0b @@ -1453,8 +1453,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 3eb74342740cd393e03aa38cd01690ccab173b76 842b21162713bb141b845b01c136457a31af4ab0 -R 8594cd13d54710bae620a17d4ba5114b -T +closed 842b21162713bb141b845b01c136457a31af4ab0 +P 16fbf2e19c22df9441aef5c8b7f5670adc38a6b6 +R 8390ec5e0d9e5eb3999e5eee0cb5ce81 U drh -Z 4f9819dace7a151b6043885dfe386959 +Z b764ac5f33b779f6bf5d09a763220c12 diff --git a/manifest.uuid b/manifest.uuid index 82610772e0..ec9225526f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -16fbf2e19c22df9441aef5c8b7f5670adc38a6b6 \ No newline at end of file +2cffb9e50bed77d1079603f5b4a71b7559de7294 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index ea07bd99f3..9bcefb1195 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -71,6 +71,20 @@ # endif #endif +/* Use pread() and pwrite() if they are available */ +#if defined(HAVE_PREAD64) && defined(HAVE_PWRITE64) +# undef USE_PREAD +# undef USE_PWRITE +# define USE_PREAD64 1 +# define USE_PWRITE64 1 +#elif defined(HAVE_PREAD) && defined(HAVE_PWRITE) +# undef USE_PREAD +# undef USE_PWRITE +# define USE_PREAD64 1 +# define USE_PWRITE64 1 +#endif + + /* ** standard include files. */ @@ -200,6 +214,9 @@ struct unixFile { const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ +#if !defined(USE_PREAD) && !defined(USE_PREAD64) + off64_t iOfst; /* Current offset */ +#endif #if SQLITE_MAX_MMAP_SIZE>0 int nFetchOut; /* Number of outstanding xFetch refs */ sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */ @@ -3097,9 +3114,6 @@ static int nfsUnlock(sqlite3_file *id, int eFileLock){ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ int got; int prior = 0; -#if (!defined(USE_PREAD) && !defined(USE_PREAD64)) - i64 newOffset; -#endif TIMER_START; assert( cnt==(cnt&0x1ffff) ); assert( id->h>2 ); @@ -3111,13 +3125,15 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ got = osPread64(id->h, pBuf, cnt, offset); SimulateIOError( got = -1 ); #else - newOffset = lseek(id->h, offset, SEEK_SET); - SimulateIOError( newOffset = -1 ); - if( newOffset<0 ){ - storeLastErrno((unixFile*)id, errno); - return -1; - } - got = osRead(id->h, pBuf, cnt); + if( offset!=id->iOfst ){ + id->iOfst = lseek(id->h, offset, SEEK_SET); + SimulateIOError( id->iOfst = -1 ); + if( id->iOfst<0 ){ + storeLastErrno((unixFile*)id, errno); + return -1; + } + got = osRead(id->h, pBuf, cnt); + if( got>=0 ) id->iOfst += got; #endif if( got==cnt ) break; if( got<0 ){ @@ -3223,6 +3239,7 @@ static int seekAndWriteFd( do{ rc = (int)osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR); #else do{ + if( iOff!=fd i64 iSeek = lseek(fd, iOff, SEEK_SET); SimulateIOError( iSeek = -1 ); if( iSeek<0 ){ From ddebf16f1f209dca695f813c6f87e4ad72c639ec Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 4 Mar 2016 02:59:35 +0000 Subject: [PATCH 403/570] Add the test_bestindex.c file to Makefile.in and Makefile.msc so that "make test" will work again. FossilOrigin-Name: 6ec6b6a97e62be1abe1e349b5bc04c6f5ae88968 --- Makefile.in | 1 + Makefile.msc | 1 + manifest | 15 +++++++-------- manifest.uuid | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Makefile.in b/Makefile.in index 891329719a..93d4181e8d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -376,6 +376,7 @@ TESTSRC = \ $(TOP)/src/test_autoext.c \ $(TOP)/src/test_async.c \ $(TOP)/src/test_backup.c \ + $(TOP)/src/test_bestindex.c \ $(TOP)/src/test_blob.c \ $(TOP)/src/test_btree.c \ $(TOP)/src/test_config.c \ diff --git a/Makefile.msc b/Makefile.msc index d9af285c06..c5130beb1e 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1236,6 +1236,7 @@ TESTSRC = \ $(TOP)\src\test_autoext.c \ $(TOP)\src\test_async.c \ $(TOP)\src\test_backup.c \ + $(TOP)\src\test_bestindex.c \ $(TOP)\src\test_blob.c \ $(TOP)\src\test_btree.c \ $(TOP)\src\test_config.c \ diff --git a/manifest b/manifest index 7f70989146..d5a273c8df 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Reduce\sthe\samount\sof\sheap\smemory\srequired\sto\sstore\smany\sschemas\sby\sstoring\s\nthe\scolumn\sdatatype\sappended\sto\sthe\scolumn\sname\s(with\sa\s\\000\sseparator),\s\nrather\sthan\sin\sseparate\smemory\sallocation. -D 2016-03-03T21:22:53.735 -F Makefile.in e335453db0b16da00c884ad51bb56d1c091a74de +C Add\sthe\stest_bestindex.c\sfile\sto\sMakefile.in\sand\sMakefile.msc\sso\sthat\n"make\stest"\swill\swork\sagain. +D 2016-03-04T02:59:35.823 +F Makefile.in 4c3d3d1b98454bf60e8977223b26ef30777a2bf2 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc dbd4621ecc585c2ef0c2aa0874698c54675754f1 +F Makefile.msc 0dc13352b84b257d81736076d8101a584940c409 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION c6b1f51809551d60ad001e6d87cf3ab2c7f54b6f F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -1453,8 +1453,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 3eb74342740cd393e03aa38cd01690ccab173b76 842b21162713bb141b845b01c136457a31af4ab0 -R 8594cd13d54710bae620a17d4ba5114b -T +closed 842b21162713bb141b845b01c136457a31af4ab0 +P 16fbf2e19c22df9441aef5c8b7f5670adc38a6b6 +R 7c159ecc947e100f72a0b55ddd229f42 U drh -Z 4f9819dace7a151b6043885dfe386959 +Z bb6e56d7a0bd406da0bf812970d93fdb diff --git a/manifest.uuid b/manifest.uuid index 82610772e0..d8612046f6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -16fbf2e19c22df9441aef5c8b7f5670adc38a6b6 \ No newline at end of file +6ec6b6a97e62be1abe1e349b5bc04c6f5ae88968 \ No newline at end of file From a46cadc42e5cc1da7ea8a739b50a7b4c9a7d9e84 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 4 Mar 2016 03:02:06 +0000 Subject: [PATCH 404/570] Fix the build for cases when pread()/pwrite() are not available. FossilOrigin-Name: 7d67d876b70c7a4199697c5b112d809c600e140e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/os_unix.c | 24 ++++++++++-------------- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index 06e5c8c969..1d5201bf29 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\sconfigure\sscript\sto\sdetect\spread/pwrite\sand\supdate\sos_unix.c\sto\nuse\sthose\sroutines\sif\sthey\sare\savailable. -D 2016-03-04T02:38:00.565 +C Fix\sthe\sbuild\sfor\scases\swhen\spread()/pwrite()\sare\snot\savailable. +D 2016-03-04T03:02:06.930 F Makefile.in e335453db0b16da00c884ad51bb56d1c091a74de F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc dbd4621ecc585c2ef0c2aa0874698c54675754f1 @@ -333,7 +333,7 @@ F src/os.c ca9a104b677328ee037cfdf1a54a16fd1805e8c9 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c a1aaf2d8d253138e63d2a8a972693f9f624f885d +F src/os_unix.c 14a28aeb3b77102a90ed645534a8d319b8ac6082 F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c d034c69b958c01289eb8070cbf902e1a68cd7e0b @@ -1453,7 +1453,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 16fbf2e19c22df9441aef5c8b7f5670adc38a6b6 -R 8390ec5e0d9e5eb3999e5eee0cb5ce81 +P 2cffb9e50bed77d1079603f5b4a71b7559de7294 +R 340d2ced6d6364f0299bbd36b34b2f41 U drh -Z b764ac5f33b779f6bf5d09a763220c12 +Z a704f390d3e95dbf657db754d417ef5a diff --git a/manifest.uuid b/manifest.uuid index ec9225526f..6b0c506b3d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2cffb9e50bed77d1079603f5b4a71b7559de7294 \ No newline at end of file +7d67d876b70c7a4199697c5b112d809c600e140e \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 9bcefb1195..844a1c46e1 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -84,7 +84,6 @@ # define USE_PWRITE64 1 #endif - /* ** standard include files. */ @@ -214,9 +213,6 @@ struct unixFile { const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ -#if !defined(USE_PREAD) && !defined(USE_PREAD64) - off64_t iOfst; /* Current offset */ -#endif #if SQLITE_MAX_MMAP_SIZE>0 int nFetchOut; /* Number of outstanding xFetch refs */ sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */ @@ -3114,6 +3110,9 @@ static int nfsUnlock(sqlite3_file *id, int eFileLock){ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ int got; int prior = 0; +#if (!defined(USE_PREAD) && !defined(USE_PREAD64)) + i64 newOffset; +#endif TIMER_START; assert( cnt==(cnt&0x1ffff) ); assert( id->h>2 ); @@ -3125,15 +3124,13 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ got = osPread64(id->h, pBuf, cnt, offset); SimulateIOError( got = -1 ); #else - if( offset!=id->iOfst ){ - id->iOfst = lseek(id->h, offset, SEEK_SET); - SimulateIOError( id->iOfst = -1 ); - if( id->iOfst<0 ){ - storeLastErrno((unixFile*)id, errno); - return -1; - } - got = osRead(id->h, pBuf, cnt); - if( got>=0 ) id->iOfst += got; + newOffset = lseek(id->h, offset, SEEK_SET); + SimulateIOError( newOffset = -1 ); + if( newOffset<0 ){ + storeLastErrno((unixFile*)id, errno); + return -1; + } + got = osRead(id->h, pBuf, cnt); #endif if( got==cnt ) break; if( got<0 ){ @@ -3239,7 +3236,6 @@ static int seekAndWriteFd( do{ rc = (int)osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR); #else do{ - if( iOff!=fd i64 iSeek = lseek(fd, iOff, SEEK_SET); SimulateIOError( iSeek = -1 ); if( iSeek<0 ){ From 79a2ca394467bdddb4ac5f607b1d0c54d176bc42 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 4 Mar 2016 03:14:39 +0000 Subject: [PATCH 405/570] Further fixes to the pread()/pwrite() enabling logic. FossilOrigin-Name: 38fb54e7854ac0500a88585ff9dd7487b4b2e586 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/os_unix.c | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 1d5201bf29..be929a8bc7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\sbuild\sfor\scases\swhen\spread()/pwrite()\sare\snot\savailable. -D 2016-03-04T03:02:06.930 +C Further\sfixes\sto\sthe\spread()/pwrite()\senabling\slogic. +D 2016-03-04T03:14:39.390 F Makefile.in e335453db0b16da00c884ad51bb56d1c091a74de F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc dbd4621ecc585c2ef0c2aa0874698c54675754f1 @@ -333,7 +333,7 @@ F src/os.c ca9a104b677328ee037cfdf1a54a16fd1805e8c9 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c 14a28aeb3b77102a90ed645534a8d319b8ac6082 +F src/os_unix.c f5bac8e74aaefc4ea520e43b4540793c3b8a9e8f F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c d034c69b958c01289eb8070cbf902e1a68cd7e0b @@ -1453,7 +1453,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 2cffb9e50bed77d1079603f5b4a71b7559de7294 -R 340d2ced6d6364f0299bbd36b34b2f41 +P 7d67d876b70c7a4199697c5b112d809c600e140e +R ce4934ea34542df91b05d44a6acdf078 U drh -Z a704f390d3e95dbf657db754d417ef5a +Z 4e6c0c7126b5fe5706a071d24d8aba5f diff --git a/manifest.uuid b/manifest.uuid index 6b0c506b3d..0966145f3c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7d67d876b70c7a4199697c5b112d809c600e140e \ No newline at end of file +38fb54e7854ac0500a88585ff9dd7487b4b2e586 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 844a1c46e1..d6fbd80588 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -72,16 +72,16 @@ #endif /* Use pread() and pwrite() if they are available */ +#if defined(__APPLE__) +# define HAVE_PREAD 1 +# define HAVE_PWRITE 1 +#endif #if defined(HAVE_PREAD64) && defined(HAVE_PWRITE64) # undef USE_PREAD -# undef USE_PWRITE # define USE_PREAD64 1 -# define USE_PWRITE64 1 #elif defined(HAVE_PREAD) && defined(HAVE_PWRITE) -# undef USE_PREAD -# undef USE_PWRITE -# define USE_PREAD64 1 -# define USE_PWRITE64 1 +# undef USE_PREAD64 +# define USE_PREAD 1 #endif /* From 9878fefd6fcc28dbe4a40a2dfa8659c1dcce14bc Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 4 Mar 2016 03:43:10 +0000 Subject: [PATCH 406/570] Change the default page size for new database files to 4096 (from 1024). Except, when building the testfixture, preserve the legacy page size. Also fix a comment on SQLITE_MAX_ATTACHED. FossilOrigin-Name: 2e8a9ca9d3d6efddc31f01074d14acae56568c37 --- Makefile.in | 1 + Makefile.msc | 1 + main.mk | 1 + manifest | 19 +++++++++---------- manifest.uuid | 2 +- src/sqliteLimit.h | 7 ++++--- 6 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Makefile.in b/Makefile.in index 93d4181e8d..61d4d671ce 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1052,6 +1052,7 @@ TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE TESTFIXTURE_FLAGS += -DBUILD_sqlite TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 +TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024 TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la TESTFIXTURE_SRC1 = sqlite3.c diff --git a/Makefile.msc b/Makefile.msc index c5130beb1e..59ce3c2ec2 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1927,6 +1927,7 @@ TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN) TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 +TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024 TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C) diff --git a/main.mk b/main.mk index 97dc254378..2ea493d111 100644 --- a/main.mk +++ b/main.mk @@ -728,6 +728,7 @@ sqlite3_analyzer$(EXE): sqlite3_analyzer.c TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 +TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024 testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c $(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \ diff --git a/manifest b/manifest index 5f2a222724..6ef4154770 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Detect\sthe\spresence\sof\spread()/pwrite()\ssystem\scalls\son\sunix\ssystems\sand\nuse\sthem\sif\savailable. -D 2016-03-04T03:20:05.475 -F Makefile.in 4c3d3d1b98454bf60e8977223b26ef30777a2bf2 +C Change\sthe\sdefault\spage\ssize\sfor\snew\sdatabase\sfiles\sto\s4096\s(from\s1024).\nExcept,\swhen\sbuilding\sthe\stestfixture,\spreserve\sthe\slegacy\spage\ssize.\nAlso\sfix\sa\scomment\son\sSQLITE_MAX_ATTACHED. +D 2016-03-04T03:43:10.844 +F Makefile.in ead489fe5d3313b8a2a8d5f3710173a4b50dd2e0 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 0dc13352b84b257d81736076d8101a584940c409 +F Makefile.msc d68db8ddac21ea2576ea5b446f12cf9ebe897a03 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION c6b1f51809551d60ad001e6d87cf3ab2c7f54b6f F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -273,7 +273,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 518d93f9f606d515628f99ce03f9e909f4f8a2e3 +F main.mk d9982cb6a42b1c9da7d61cebae973cd6b034de61 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -355,7 +355,7 @@ F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d F src/sqliteInt.h 8aa9992cb35289ede0946f7ba8e993070e040fc4 -F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 +F src/sqliteLimit.h 7c17293db62f238ccdec1498dd855fc126fa07a9 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 F src/tclsqlite.c 54dca4eaf3a9cb0a4b845ef54ffa99225c30a52e @@ -1453,8 +1453,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 6ec6b6a97e62be1abe1e349b5bc04c6f5ae88968 38fb54e7854ac0500a88585ff9dd7487b4b2e586 -R 2f3feca250b12264f442f8836aa34529 -T +closed 38fb54e7854ac0500a88585ff9dd7487b4b2e586 +P 82cbf5ad2ed988a006106e188e98096a52e6779d +R 0406775a6be9491c81a210a63da6c171 U drh -Z 6deed976f37e6ab4c44908da24567cb0 +Z 4f7c554d47a12cc14f56cbfb2a874afa diff --git a/manifest.uuid b/manifest.uuid index a3b88f39bd..5cef88240a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -82cbf5ad2ed988a006106e188e98096a52e6779d \ No newline at end of file +2e8a9ca9d3d6efddc31f01074d14acae56568c37 \ No newline at end of file diff --git a/src/sqliteLimit.h b/src/sqliteLimit.h index 75cad1274b..ac06881953 100644 --- a/src/sqliteLimit.h +++ b/src/sqliteLimit.h @@ -120,8 +120,9 @@ /* ** The maximum number of attached databases. This must be between 0 -** and 62. The upper bound on 62 is because a 64-bit integer bitmap -** is used internally to track attached databases. +** and 125. The upper bound of 125 is because the attached databases are +** counted using a signed 8-bit integer which has a maximum value of 127 +** and we have to allow 2 extra counts for the "main" and "temp" databases. */ #ifndef SQLITE_MAX_ATTACHED # define SQLITE_MAX_ATTACHED 10 @@ -156,7 +157,7 @@ ** The default size of a database page. */ #ifndef SQLITE_DEFAULT_PAGE_SIZE -# define SQLITE_DEFAULT_PAGE_SIZE 1024 +# define SQLITE_DEFAULT_PAGE_SIZE 4096 #endif #if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE # undef SQLITE_DEFAULT_PAGE_SIZE From 94580868f5b9eea4b52710b7304a423006a44f98 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 4 Mar 2016 04:01:43 +0000 Subject: [PATCH 407/570] Change the default cache_size to -2000 (which means 2000*1024 bytes independent of page_size). FossilOrigin-Name: 2682e8e413fadbca0673f242769af17bfd291559 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqliteLimit.h | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 6ef4154770..d39a07ce5c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sdefault\spage\ssize\sfor\snew\sdatabase\sfiles\sto\s4096\s(from\s1024).\nExcept,\swhen\sbuilding\sthe\stestfixture,\spreserve\sthe\slegacy\spage\ssize.\nAlso\sfix\sa\scomment\son\sSQLITE_MAX_ATTACHED. -D 2016-03-04T03:43:10.844 +C Change\sthe\sdefault\scache_size\sto\s-2000\s(which\smeans\s2000*1024\sbytes\nindependent\sof\spage_size). +D 2016-03-04T04:01:43.190 F Makefile.in ead489fe5d3313b8a2a8d5f3710173a4b50dd2e0 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc d68db8ddac21ea2576ea5b446f12cf9ebe897a03 @@ -355,7 +355,7 @@ F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d F src/sqliteInt.h 8aa9992cb35289ede0946f7ba8e993070e040fc4 -F src/sqliteLimit.h 7c17293db62f238ccdec1498dd855fc126fa07a9 +F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 F src/tclsqlite.c 54dca4eaf3a9cb0a4b845ef54ffa99225c30a52e @@ -1453,7 +1453,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 82cbf5ad2ed988a006106e188e98096a52e6779d -R 0406775a6be9491c81a210a63da6c171 +P 2e8a9ca9d3d6efddc31f01074d14acae56568c37 +R bce4d7ea1e35eefbc9f3bc83f2294e5c U drh -Z 4f7c554d47a12cc14f56cbfb2a874afa +Z 8be75f8161fe6fe960ec420b19540c0b diff --git a/manifest.uuid b/manifest.uuid index 5cef88240a..0d4fa9e4a9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2e8a9ca9d3d6efddc31f01074d14acae56568c37 \ No newline at end of file +2682e8e413fadbca0673f242769af17bfd291559 \ No newline at end of file diff --git a/src/sqliteLimit.h b/src/sqliteLimit.h index ac06881953..4b5ddaadec 100644 --- a/src/sqliteLimit.h +++ b/src/sqliteLimit.h @@ -102,12 +102,12 @@ ** the main database table and for temporary tables. ** ** IMPLEMENTATION-OF: R-31093-59126 The default suggested cache size -** is 2000 pages. +** is 2000*1024 bytes. ** IMPLEMENTATION-OF: R-48205-43578 The default suggested cache size can be ** altered using the SQLITE_DEFAULT_CACHE_SIZE compile-time options. */ #ifndef SQLITE_DEFAULT_CACHE_SIZE -# define SQLITE_DEFAULT_CACHE_SIZE 2000 +# define SQLITE_DEFAULT_CACHE_SIZE -2000 #endif /* From 3ac9a86415ad92af53f10964b6b522ef96c03afb Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 4 Mar 2016 14:23:10 +0000 Subject: [PATCH 408/570] Update test cases to taken deferred statement-journal opening into account. FossilOrigin-Name: 5b2fe5219ab9ad15969e3374894a75979b65cb3c --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- test/conflict.test | 12 +++++++----- test/conflict2.test | 23 +++++++++++++---------- test/exclusive.test | 9 ++++++--- test/stmt.test | 10 ++++++---- test/tempdb.test | 2 +- 7 files changed, 44 insertions(+), 34 deletions(-) diff --git a/manifest b/manifest index 58b8efaa39..b827dc21f1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\schanges\sfrom\strunk. -D 2016-03-04T13:08:35.636 +C Update\stest\scases\sto\staken\sdeferred\sstatement-journal\sopening\sinto\saccount. +D 2016-03-04T14:23:10.937 F Makefile.in ead489fe5d3313b8a2a8d5f3710173a4b50dd2e0 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc d68db8ddac21ea2576ea5b446f12cf9ebe897a03 @@ -541,8 +541,8 @@ F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6 F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1 F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b -F test/conflict.test 841bcf7cabbfca39c577eb8411ea8601843b46a8 -F test/conflict2.test a82dd3b9b41fceb5dd6ff0707c5c7ffba208d538 +F test/conflict.test 029faa2d81a0d1cafb5f88614beb663d972c01db +F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c F test/conflict3.test dec0634c0f31dec9a4b01c63063e939f0cd21b6b F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4 F test/corrupt.test 141c39ea650c1365e85a49e402fa05cb9617fb97 @@ -627,7 +627,7 @@ F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020 F test/eqp.test 85873fa5816c48915c82c4e74cb5c35a5b48160f F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401 F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c -F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75 +F test/exclusive.test f48243eaf40e0957215501a12f510a8644d13a02 F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308 F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7 F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30 @@ -1063,7 +1063,7 @@ F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142 F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a F test/stat.test acc91e80517fff447ae8adcfd953cfdaa5efc0af F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1 -F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9 +F test/stmt.test 64844332db69cf1a735fcb3e11548557fc95392f F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f F test/subquery2.test 438f8a7da1457277b22e4176510f7659b286995f F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 @@ -1079,7 +1079,7 @@ F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054 -F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c +F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 F test/tester.tcl 750365ff97047ded5f2d6e28df82a998f7c66ae0 @@ -1453,7 +1453,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 b5378dcea53d4cd1744d13ddee5e50869607b771 2682e8e413fadbca0673f242769af17bfd291559 -R 1d5f238c78a751f41b8ce4e327b6fc98 +P a87305dfd49ee17632d0bce66ce7c2e9407b7b3e +R bcfeac6deb0b24b3190e8b427e406c58 U drh -Z 35e5851abb6d53f81aa001148a407eb0 +Z 82bd4288d2e4175a3c31e21a46f9d82d diff --git a/manifest.uuid b/manifest.uuid index 7ae252503c..5596275a80 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a87305dfd49ee17632d0bce66ce7c2e9407b7b3e \ No newline at end of file +5b2fe5219ab9ad15969e3374894a75979b65cb3c \ No newline at end of file diff --git a/test/conflict.test b/test/conflict.test index af5668ed72..a39988adb0 100644 --- a/test/conflict.test +++ b/test/conflict.test @@ -285,15 +285,17 @@ do_test conflict-6.0 { # t3 Number of temporary files for tables # t4 Number of temporary files for statement journals # -# Update: Since temporary table files are now opened lazily, and none -# of the following tests use large quantities of data, t3 is always 0. +# Update (2007-08-21): Since temporary table files are now opened lazily, +# and none of the following tests use large quantities of data, t3 is always 0. +# +# Update (2016-03-04): Subjournals now also open lazily, so t4 is also always 0. # foreach {i conf1 cmd t0 t1 t2 t3 t4} { - 1 {} UPDATE 1 {6 7 8 9} 1 0 1 + 1 {} UPDATE 1 {6 7 8 9} 1 0 0 2 REPLACE UPDATE 0 {7 6 9} 1 0 0 3 IGNORE UPDATE 0 {6 7 3 9} 1 0 0 4 FAIL UPDATE 1 {6 7 3 4} 1 0 0 - 5 ABORT UPDATE 1 {1 2 3 4} 1 0 1 + 5 ABORT UPDATE 1 {1 2 3 4} 1 0 0 6 ROLLBACK UPDATE 1 {1 2 3 4} 0 0 0 7 REPLACE {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 8 IGNORE {UPDATE OR REPLACE} 0 {7 6 9} 1 0 0 @@ -303,7 +305,7 @@ foreach {i conf1 cmd t0 t1 t2 t3 t4} { 12 {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 13 {} {UPDATE OR REPLACE} 0 {7 6 9} 1 0 0 14 {} {UPDATE OR FAIL} 1 {6 7 3 4} 1 0 0 - 15 {} {UPDATE OR ABORT} 1 {1 2 3 4} 1 0 1 + 15 {} {UPDATE OR ABORT} 1 {1 2 3 4} 1 0 0 16 {} {UPDATE OR ROLLBACK} 1 {1 2 3 4} 0 0 0 } { if {$t0} {set t1 {UNIQUE constraint failed: t1.a}} diff --git a/test/conflict2.test b/test/conflict2.test index 6496913849..f33e01d582 100644 --- a/test/conflict2.test +++ b/test/conflict2.test @@ -287,22 +287,25 @@ do_test conflict2-6.0 { # Update: Since temporary table files are now opened lazily, and none # of the following tests use large quantities of data, t3 is always 0. # +# Update (2016-03-04): Subjournals now only open when their size +# exceeds 64KB. +# foreach {i conf1 cmd t0 t1 t2 t3 t4} { - 1 {} UPDATE 1 {6 7 8 9} 1 0 1 - 2 REPLACE UPDATE 0 {7 6 9} 1 0 1 - 3 IGNORE UPDATE 0 {6 7 3 9} 1 0 1 - 4 FAIL UPDATE 1 {6 7 3 4} 1 0 1 - 5 ABORT UPDATE 1 {1 2 3 4} 1 0 1 - 6 ROLLBACK UPDATE 1 {1 2 3 4} 0 0 1 + 1 {} UPDATE 1 {6 7 8 9} 1 0 0 + 2 REPLACE UPDATE 0 {7 6 9} 1 0 0 + 3 IGNORE UPDATE 0 {6 7 3 9} 1 0 0 + 4 FAIL UPDATE 1 {6 7 3 4} 1 0 0 + 5 ABORT UPDATE 1 {1 2 3 4} 1 0 0 + 6 ROLLBACK UPDATE 1 {1 2 3 4} 0 0 0 7 REPLACE {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 - 8 IGNORE {UPDATE OR REPLACE} 0 {7 6 9} 1 0 1 + 8 IGNORE {UPDATE OR REPLACE} 0 {7 6 9} 1 0 0 9 FAIL {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 - 10 ABORT {UPDATE OR REPLACE} 0 {7 6 9} 1 0 1 + 10 ABORT {UPDATE OR REPLACE} 0 {7 6 9} 1 0 0 11 ROLLBACK {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 12 {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 - 13 {} {UPDATE OR REPLACE} 0 {7 6 9} 1 0 1 + 13 {} {UPDATE OR REPLACE} 0 {7 6 9} 1 0 0 14 {} {UPDATE OR FAIL} 1 {6 7 3 4} 1 0 0 - 15 {} {UPDATE OR ABORT} 1 {1 2 3 4} 1 0 1 + 15 {} {UPDATE OR ABORT} 1 {1 2 3 4} 1 0 0 16 {} {UPDATE OR ROLLBACK} 1 {1 2 3 4} 0 0 0 } { diff --git a/test/exclusive.test b/test/exclusive.test index c000dfefa4..c7b88cfbca 100644 --- a/test/exclusive.test +++ b/test/exclusive.test @@ -420,9 +420,10 @@ do_test exclusive-5.0 { } {} do_test exclusive-5.1 { # Three files are open: The db, journal and statement-journal. + # (2016-03-04) The statement-journal is now opened lazily set sqlite_open_file_count expr $sqlite_open_file_count-$extrafds -} [expr 3 - ($TEMP_STORE>=2)] +} [expr 2 - ($TEMP_STORE>=2)] do_test exclusive-5.2 { execsql { COMMIT; @@ -446,17 +447,19 @@ do_test exclusive-5.4 { INSERT INTO abc SELECT a+10, b+10, c+10 FROM abc; } # Three files are open: The db, journal and statement-journal. + # 2016-03-04: The statement-journal open is deferred set sqlite_open_file_count expr $sqlite_open_file_count-$extrafds -} [expr 3 - ($TEMP_STORE>=2)] +} [expr 2 - ($TEMP_STORE>=2)] do_test exclusive-5.5 { execsql { COMMIT; } # Three files are still open: The db, journal and statement-journal. + # 2016-03-04: The statement-journal open is deferred set sqlite_open_file_count expr $sqlite_open_file_count-$extrafds -} [expr 3 - ($TEMP_STORE>=2)] +} [expr 2 - ($TEMP_STORE>=2)] do_test exclusive-5.6 { execsql { PRAGMA locking_mode = normal; diff --git a/test/stmt.test b/test/stmt.test index 49a41414b7..df501f7654 100644 --- a/test/stmt.test +++ b/test/stmt.test @@ -46,7 +46,8 @@ do_test stmt-1.4 { INSERT INTO t1 SELECT a+1, b+1 FROM t1; } set sqlite_open_file_count -} {3} + # 2016-03-04: statement-journal open deferred +} {2} do_test stmt-1.5 { execsql COMMIT set sqlite_open_file_count @@ -61,7 +62,8 @@ do_test stmt-1.6.1 { do_test stmt-1.6.2 { execsql { INSERT INTO t1 SELECT a+4, b+4 FROM t1 } set sqlite_open_file_count -} {3} + # 2016-03-04: statement-journal open deferred +} {2} do_test stmt-1.7 { execsql COMMIT set sqlite_open_file_count @@ -84,7 +86,7 @@ filecount stmt-2.3 { INSERT INTO t1 SELECT 9, 9 } 2 filecount stmt-2.4 { INSERT INTO t1 SELECT 9, 9; INSERT INTO t1 SELECT 10, 10; -} 3 +} 2 do_test stmt-2.5 { execsql { CREATE INDEX i1 ON t1(b) } @@ -92,6 +94,6 @@ do_test stmt-2.5 { filecount stmt-2.6 { REPLACE INTO t1 VALUES(5, 5); REPLACE INTO t1 VALUES(5, 5); -} 3 +} 2 finish_test diff --git a/test/tempdb.test b/test/tempdb.test index ecd23d4e32..61416ec81c 100644 --- a/test/tempdb.test +++ b/test/tempdb.test @@ -76,7 +76,7 @@ do_test tempdb-2.2 { } catchsql { INSERT INTO t1 SELECT * FROM t2 } set sqlite_open_file_count -} [expr 1 + (0==$jrnl_in_memory) + (0==$subj_in_memory)] +} [expr 1 + (0==$jrnl_in_memory)] do_test tempdb-2.3 { execsql { PRAGMA temp_store = 'memory'; From 6f17c09fcfa7c36c4e462243bedabce7ad255170 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 4 Mar 2016 21:18:09 +0000 Subject: [PATCH 409/570] Fix an assert() in sqlite3VarintLen(), even though it is impossible to hit in SQLite due to the way sqlite3VarintLen() is used. FossilOrigin-Name: 251424c5869f43012fc1e1a545de362036b883db --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/util.c | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 5e68a8f7a2..ddb0f32ead 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Defer\sopening\sand\swriting\sstatement\sjournals\suntil\sthe\ssize\sreaches\sa\nthreshold\s(currently\s64KiB). -D 2016-03-04T14:43:44.681 +C Fix\san\sassert()\sin\ssqlite3VarintLen(),\seven\sthough\sit\sis\simpossible\sto\shit\nin\sSQLite\sdue\sto\sthe\sway\ssqlite3VarintLen()\sis\sused. +D 2016-03-04T21:18:09.041 F Makefile.in ead489fe5d3313b8a2a8d5f3710173a4b50dd2e0 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc d68db8ddac21ea2576ea5b446f12cf9ebe897a03 @@ -413,7 +413,7 @@ F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c -F src/util.c a64585a74aef6feb16dfe4e090b5de01e26eba3b +F src/util.c 9da96848829029db21490ccf5de0a83b9826301d F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c 87ae3a5657fefed7875f3eb30e7ababd48013d71 F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 @@ -1453,8 +1453,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 2682e8e413fadbca0673f242769af17bfd291559 5b2fe5219ab9ad15969e3374894a75979b65cb3c -R bcfeac6deb0b24b3190e8b427e406c58 -T +closed 5b2fe5219ab9ad15969e3374894a75979b65cb3c +P cb9302cca423de41305719a49208daa392ec09da +R 3f65b65b7495c9f571c8ba6ae5d73738 U drh -Z 04f483c25715ded0ed1694d083bfc434 +Z b8ec485efc1d4705a2d34eb295972964 diff --git a/manifest.uuid b/manifest.uuid index 68d02d516a..8ca70165cd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cb9302cca423de41305719a49208daa392ec09da \ No newline at end of file +251424c5869f43012fc1e1a545de362036b883db \ No newline at end of file diff --git a/src/util.c b/src/util.c index 81274260f4..cf9aa3aa3b 100644 --- a/src/util.c +++ b/src/util.c @@ -1093,7 +1093,7 @@ u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){ */ int sqlite3VarintLen(u64 v){ int i; - for(i=1; (v >>= 7)!=0; i++){ assert( i<9 ); } + for(i=1; (v >>= 7)!=0; i++){ assert( i<10 ); } return i; } From 14bfd99143099ea60f3f0b956a7e3515d83715a7 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 5 Mar 2016 14:00:09 +0000 Subject: [PATCH 410/570] Fix an incorrect #ifdef on sqlite3LogEstToInt(). FossilOrigin-Name: dca7b23354a6b08c926b6ed3f7345d942a409862 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/sqliteInt.h | 2 +- src/util.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index ddb0f32ead..844e594cf9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sassert()\sin\ssqlite3VarintLen(),\seven\sthough\sit\sis\simpossible\sto\shit\nin\sSQLite\sdue\sto\sthe\sway\ssqlite3VarintLen()\sis\sused. -D 2016-03-04T21:18:09.041 +C Fix\san\sincorrect\s#ifdef\son\ssqlite3LogEstToInt(). +D 2016-03-05T14:00:09.835 F Makefile.in ead489fe5d3313b8a2a8d5f3710173a4b50dd2e0 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc d68db8ddac21ea2576ea5b446f12cf9ebe897a03 @@ -354,7 +354,7 @@ F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 8a4810fa90b17eb08acab43649b877e894ea1e98 +F src/sqliteInt.h 2ce28b3c1228de3b6d392d6bd69b47f3aa2f2931 F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -413,7 +413,7 @@ F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c -F src/util.c 9da96848829029db21490ccf5de0a83b9826301d +F src/util.c 12800a93f0664f41575f96799eb881a786d565e6 F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c 87ae3a5657fefed7875f3eb30e7ababd48013d71 F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 @@ -1453,7 +1453,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 cb9302cca423de41305719a49208daa392ec09da -R 3f65b65b7495c9f571c8ba6ae5d73738 +P 251424c5869f43012fc1e1a545de362036b883db +R 90305ca4dfd4aba0131d1df776abe7c9 U drh -Z b8ec485efc1d4705a2d34eb295972964 +Z 712c8c7e19abd0b144a0db443a2a27a2 diff --git a/manifest.uuid b/manifest.uuid index 8ca70165cd..becac63118 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -251424c5869f43012fc1e1a545de362036b883db \ No newline at end of file +dca7b23354a6b08c926b6ed3f7345d942a409862 \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 387bb7436b..c7514d4c96 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3685,7 +3685,7 @@ LogEst sqlite3LogEstAdd(LogEst,LogEst); #ifndef SQLITE_OMIT_VIRTUALTABLE LogEst sqlite3LogEstFromDouble(double); #endif -#if defined(SQLITE_ENABLE_STMT_SCANSTAT) || \ +#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \ defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) u64 sqlite3LogEstToInt(LogEst); diff --git a/src/util.c b/src/util.c index cf9aa3aa3b..6aead47faa 100644 --- a/src/util.c +++ b/src/util.c @@ -1408,7 +1408,7 @@ LogEst sqlite3LogEstFromDouble(double x){ } #endif /* SQLITE_OMIT_VIRTUALTABLE */ -#if defined(SQLITE_ENABLE_STMT_SCANSTAT) || \ +#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \ defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) /* From 07eab3b87f36670f0b3f6fcfbe60279ec9dbbd44 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 5 Mar 2016 14:19:32 +0000 Subject: [PATCH 411/570] Fix an integer size mismatch problem in test_bestindex.c FossilOrigin-Name: 2e35eb6b7464455467c868adfbcaad4da16d3207 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/test_bestindex.c | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 844e594cf9..d2dded5209 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sincorrect\s#ifdef\son\ssqlite3LogEstToInt(). -D 2016-03-05T14:00:09.835 +C Fix\san\sinteger\ssize\smismatch\sproblem\sin\stest_bestindex.c +D 2016-03-05T14:19:32.489 F Makefile.in ead489fe5d3313b8a2a8d5f3710173a4b50dd2e0 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc d68db8ddac21ea2576ea5b446f12cf9ebe897a03 @@ -371,7 +371,7 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60 F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8 F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 -F src/test_bestindex.c cd36324f05404df5f1a82608a321b91932a549ea +F src/test_bestindex.c 1da6fa21ac9413e8985a698b962541e615a9f311 F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f F src/test_config.c 0dee90328e3dedf8ba002ee94b6a7e7ea7726fe4 @@ -1453,7 +1453,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 251424c5869f43012fc1e1a545de362036b883db -R 90305ca4dfd4aba0131d1df776abe7c9 +P dca7b23354a6b08c926b6ed3f7345d942a409862 +R 419fa6ee740f29be7406090838523282 U drh -Z 712c8c7e19abd0b144a0db443a2a27a2 +Z dc391039bf997df63fda556410810121 diff --git a/manifest.uuid b/manifest.uuid index becac63118..43346ec462 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dca7b23354a6b08c926b6ed3f7345d942a409862 \ No newline at end of file +2e35eb6b7464455467c868adfbcaad4da16d3207 \ No newline at end of file diff --git a/src/test_bestindex.c b/src/test_bestindex.c index ab10463fd9..abbdf1a02b 100644 --- a/src/test_bestindex.c +++ b/src/test_bestindex.c @@ -454,7 +454,9 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ pIdxInfo->needToFreeIdxStr = 1; }else if( sqlite3_stricmp("rows", zCmd)==0 ){ - rc = Tcl_GetWideIntFromObj(interp, p, &pIdxInfo->estimatedRows); + Tcl_WideInt x = 0; + rc = Tcl_GetWideIntFromObj(interp, p, &x); + pIdxInfo->estimatedRows = (tRowcnt)x; }else if( sqlite3_stricmp("use", zCmd)==0 || sqlite3_stricmp("omit", zCmd)==0 From 65a7e769e7ac91e27e27623ba3f8d6021f78df41 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 5 Mar 2016 15:03:31 +0000 Subject: [PATCH 412/570] Work around (incorrect) ASAN warnings in memjournal.c. FossilOrigin-Name: 4de09777dad6188b7e897473700af3c9655e8547 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/memjournal.c | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index d2dded5209..e1c699e0d2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sinteger\ssize\smismatch\sproblem\sin\stest_bestindex.c -D 2016-03-05T14:19:32.489 +C Work\saround\s(incorrect)\sASAN\swarnings\sin\smemjournal.c. +D 2016-03-05T15:03:31.910 F Makefile.in ead489fe5d3313b8a2a8d5f3710173a4b50dd2e0 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc d68db8ddac21ea2576ea5b446f12cf9ebe897a03 @@ -321,7 +321,7 @@ F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memjournal.c 56c7688565cf407c5f22f03e3be478d3a92bdc81 +F src/memjournal.c 7bdc7bced5884ab3a38a4ccf10487b9e01d9ebb5 F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 @@ -1453,7 +1453,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 dca7b23354a6b08c926b6ed3f7345d942a409862 -R 419fa6ee740f29be7406090838523282 +P 2e35eb6b7464455467c868adfbcaad4da16d3207 +R ec05aaf410156a1b332fc5b2fb0ea4f0 U drh -Z dc391039bf997df63fda556410810121 +Z da5e511cdc73c2d6d55df28700c71c4a diff --git a/manifest.uuid b/manifest.uuid index 43346ec462..cf351af72e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2e35eb6b7464455467c868adfbcaad4da16d3207 \ No newline at end of file +4de09777dad6188b7e897473700af3c9655e8547 \ No newline at end of file diff --git a/src/memjournal.c b/src/memjournal.c index 9ecd2a9ba3..12b77fc340 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -109,7 +109,7 @@ static int memjrnlRead( do { int iSpace = p->nChunkSize - iChunkOffset; int nCopy = MIN(nRead, (p->nChunkSize - iChunkOffset)); - memcpy(zOut, &pChunk->zChunk[iChunkOffset], nCopy); + memcpy(zOut, (u8*)pChunk->zChunk + iChunkOffset, nCopy); zOut += nCopy; nRead -= iSpace; iChunkOffset = 0; @@ -153,7 +153,7 @@ static int createFile(MemJournal *p){ nWrite = p->endpoint.iOffset % p->nChunkSize; if( nWrite==0 ) nWrite = p->nChunkSize; } - rc = sqlite3OsWrite(pReal, pIter->zChunk, nWrite, iOff); + rc = sqlite3OsWrite(pReal, (u8*)pIter->zChunk, nWrite, iOff); iOff += nWrite; } if( rc!=SQLITE_OK ){ @@ -210,7 +210,7 @@ static int memjrnlWrite( assert( iOfst==p->endpoint.iOffset || iOfst==0 ); if( iOfst==0 && p->pFirst ){ assert( p->nChunkSize>iAmt ); - memcpy(p->pFirst->zChunk, zBuf, iAmt); + memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt); }else{ while( nWrite>0 ){ FileChunk *pChunk = p->endpoint.pChunk; @@ -234,7 +234,7 @@ static int memjrnlWrite( p->endpoint.pChunk = pNew; } - memcpy(&p->endpoint.pChunk->zChunk[iChunkOffset], zWrite, iSpace); + memcpy((u8*)p->endpoint.pChunk->zChunk + iChunkOffset, zWrite, iSpace); zWrite += iSpace; nWrite -= iSpace; p->endpoint.iOffset += iSpace; From c2f18adde59927255447e2c854e867c3602f1370 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 5 Mar 2016 15:35:09 +0000 Subject: [PATCH 413/570] Remove the unused journal.c source file (its function have been subsumed into memjournal.c). Refactor some of the names in memjournal.c. No functional changes. FossilOrigin-Name: 5f2a262d3f6b1531001326faf1d3b3d92c20a30a --- Makefile.in | 6 +- Makefile.msc | 6 +- main.mk | 3 +- manifest | 21 ++-- manifest.uuid | 2 +- src/journal.c | 258 -------------------------------------------- src/memjournal.c | 34 +++--- tool/mksqlite3c.tcl | 1 - 8 files changed, 31 insertions(+), 300 deletions(-) delete mode 100644 src/journal.c diff --git a/Makefile.in b/Makefile.in index 61d4d671ce..d8f5695e5d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -173,7 +173,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \ fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \ fts5.lo \ func.lo global.lo hash.lo \ - icu.lo insert.lo journal.lo json1.lo legacy.lo loadext.lo \ + icu.lo insert.lo json1.lo legacy.lo loadext.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ @@ -224,7 +224,6 @@ SRC = \ $(TOP)/src/hash.h \ $(TOP)/src/hwtime.h \ $(TOP)/src/insert.c \ - $(TOP)/src/journal.c \ $(TOP)/src/legacy.c \ $(TOP)/src/loadext.c \ $(TOP)/src/main.c \ @@ -739,9 +738,6 @@ hash.lo: $(TOP)/src/hash.c $(HDR) insert.lo: $(TOP)/src/insert.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/insert.c -journal.lo: $(TOP)/src/journal.c $(HDR) - $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/journal.c - legacy.lo: $(TOP)/src/legacy.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/legacy.c diff --git a/Makefile.msc b/Makefile.msc index 59ce3c2ec2..15fbf6c65d 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -985,7 +985,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \ fts3_tokenize_vtab.lo fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \ fts5.lo \ func.lo global.lo hash.lo \ - icu.lo insert.lo journal.lo legacy.lo loadext.lo \ + icu.lo insert.lo legacy.lo loadext.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ @@ -1049,7 +1049,6 @@ SRC00 = \ $(TOP)\src\global.c \ $(TOP)\src\hash.c \ $(TOP)\src\insert.c \ - $(TOP)\src\journal.c \ $(TOP)\src\legacy.c \ $(TOP)\src\loadext.c \ $(TOP)\src\main.c \ @@ -1610,9 +1609,6 @@ hash.lo: $(TOP)\src\hash.c $(HDR) insert.lo: $(TOP)\src\insert.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\insert.c -journal.lo: $(TOP)\src\journal.c $(HDR) - $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\journal.c - legacy.lo: $(TOP)\src\legacy.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\legacy.c diff --git a/main.mk b/main.mk index 2ea493d111..12b92260f1 100644 --- a/main.mk +++ b/main.mk @@ -61,7 +61,7 @@ LIBOBJ+= vdbe.o parse.o \ fts3_tokenize_vtab.o \ fts3_unicode.o fts3_unicode2.o \ fts3_write.o fts5.o func.o global.o hash.o \ - icu.o insert.o journal.o json1.o legacy.o loadext.o \ + icu.o insert.o json1.o legacy.o loadext.o \ main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \ memjournal.o \ mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ @@ -104,7 +104,6 @@ SRC = \ $(TOP)/src/hash.h \ $(TOP)/src/hwtime.h \ $(TOP)/src/insert.c \ - $(TOP)/src/journal.c \ $(TOP)/src/legacy.c \ $(TOP)/src/loadext.c \ $(TOP)/src/main.c \ diff --git a/manifest b/manifest index e1c699e0d2..10ffbe9dbe 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Work\saround\s(incorrect)\sASAN\swarnings\sin\smemjournal.c. -D 2016-03-05T15:03:31.910 -F Makefile.in ead489fe5d3313b8a2a8d5f3710173a4b50dd2e0 +C Remove\sthe\sunused\sjournal.c\ssource\sfile\s(its\sfunction\shave\sbeen\ssubsumed\sinto\nmemjournal.c).\s\sRefactor\ssome\sof\sthe\snames\sin\smemjournal.c.\s\sNo\sfunctional\nchanges. +D 2016-03-05T15:35:09.793 +F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc d68db8ddac21ea2576ea5b446f12cf9ebe897a03 +F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION c6b1f51809551d60ad001e6d87cf3ab2c7f54b6f F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -273,7 +273,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk d9982cb6a42b1c9da7d61cebae973cd6b034de61 +F main.mk 91cfc30d0fa295be28a86657ad3b1053f0428c9e F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -311,7 +311,6 @@ F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c 723d5d708cdb61bdd47c00b9f07c75be45aefc09 -F src/journal.c 673cbdde5676eb0c55848f561575d45b609c820d F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f F src/main.c 32c45647866429f34d7a13a717172a8e7d0a1056 @@ -321,7 +320,7 @@ F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memjournal.c 7bdc7bced5884ab3a38a4ccf10487b9e01d9ebb5 +F src/memjournal.c 011da5236a7250385cc74c253f14bbee04c0d61e F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 @@ -1396,7 +1395,7 @@ F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkpragmatab.tcl f0d5bb266d1d388cf86fce5ba01a891e95d72d41 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl 87240b09c20042999b41d5fabe091b7111287835 -F tool/mksqlite3c.tcl b66b4170f693602cd6985aed15d9509fe2f18c84 +F tool/mksqlite3c.tcl 9382100c82a0a08e63265780536a6c8efead4b65 F tool/mksqlite3h.tcl 1d41ab59bffb025121f75b76e183125ce41b3ec8 F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b F tool/mkvsix.tcl 4abcaf3267171b2faadaf9b82a0dfbaa6e98f8b7 @@ -1453,7 +1452,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 2e35eb6b7464455467c868adfbcaad4da16d3207 -R ec05aaf410156a1b332fc5b2fb0ea4f0 +P 4de09777dad6188b7e897473700af3c9655e8547 +R 323dedc301dba3a5e5eae684c7c211b0 U drh -Z da5e511cdc73c2d6d55df28700c71c4a +Z 93b1612ed0c564573b8e6748ccaa7792 diff --git a/manifest.uuid b/manifest.uuid index cf351af72e..2cc497c082 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4de09777dad6188b7e897473700af3c9655e8547 \ No newline at end of file +5f2a262d3f6b1531001326faf1d3b3d92c20a30a \ No newline at end of file diff --git a/src/journal.c b/src/journal.c deleted file mode 100644 index da59db0e50..0000000000 --- a/src/journal.c +++ /dev/null @@ -1,258 +0,0 @@ -/* -** 2007 August 22 -** -** 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 a special kind of sqlite3_file object used -** by SQLite to create journal files if the atomic-write optimization -** is enabled. -** -** The distinctive characteristic of this sqlite3_file is that the -** actual on disk file is created lazily. When the file is created, -** the caller specifies a buffer size for an in-memory buffer to -** be used to service read() and write() requests. The actual file -** on disk is not created or populated until either: -** -** 1) The in-memory representation grows too large for the allocated -** buffer, or -** 2) The sqlite3JournalCreate() function is called. -*/ -#if 0 -#ifdef SQLITE_ENABLE_ATOMIC_WRITE -#include "sqliteInt.h" - - -/* -** A JournalFile object is a subclass of sqlite3_file used by -** as an open file handle for journal files. -*/ -struct JournalFile { - sqlite3_io_methods *pMethod; /* I/O methods on journal files */ - int nBuf; /* Size of zBuf[] in bytes */ - char *zBuf; /* Space to buffer journal writes */ - int iSize; /* Amount of zBuf[] currently used */ - int flags; /* xOpen flags */ - sqlite3_vfs *pVfs; /* The "real" underlying VFS */ - sqlite3_file *pReal; /* The "real" underlying file descriptor */ - const char *zJournal; /* Name of the journal file */ -}; -typedef struct JournalFile JournalFile; - -/* -** If it does not already exists, create and populate the on-disk file -** for JournalFile p. -*/ -static int createFile(JournalFile *p){ - int rc = SQLITE_OK; - if( !p->pReal ){ - sqlite3_file *pReal = (sqlite3_file *)&p[1]; - rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0); - if( rc==SQLITE_OK ){ - p->pReal = pReal; - if( p->iSize>0 ){ - assert(p->iSize<=p->nBuf); - rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); - } - if( rc!=SQLITE_OK ){ - /* If an error occurred while writing to the file, close it before - ** returning. This way, SQLite uses the in-memory journal data to - ** roll back changes made to the internal page-cache before this - ** function was called. */ - sqlite3OsClose(pReal); - p->pReal = 0; - } - } - } - return rc; -} - -/* -** Close the file. -*/ -static int jrnlClose(sqlite3_file *pJfd){ - JournalFile *p = (JournalFile *)pJfd; - if( p->pReal ){ - sqlite3OsClose(p->pReal); - } - sqlite3_free(p->zBuf); - return SQLITE_OK; -} - -/* -** Read data from the file. -*/ -static int jrnlRead( - sqlite3_file *pJfd, /* The journal file from which to read */ - void *zBuf, /* Put the results here */ - int iAmt, /* Number of bytes to read */ - sqlite_int64 iOfst /* Begin reading at this offset */ -){ - int rc = SQLITE_OK; - JournalFile *p = (JournalFile *)pJfd; - if( p->pReal ){ - rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); - }else if( (iAmt+iOfst)>p->iSize ){ - rc = SQLITE_IOERR_SHORT_READ; - }else{ - memcpy(zBuf, &p->zBuf[iOfst], iAmt); - } - return rc; -} - -/* -** Write data to the file. -*/ -static int jrnlWrite( - sqlite3_file *pJfd, /* The journal file into which to write */ - const void *zBuf, /* Take data to be written from here */ - int iAmt, /* Number of bytes to write */ - sqlite_int64 iOfst /* Begin writing at this offset into the file */ -){ - int rc = SQLITE_OK; - JournalFile *p = (JournalFile *)pJfd; - if( !p->pReal && (iOfst+iAmt)>p->nBuf ){ - rc = createFile(p); - } - if( rc==SQLITE_OK ){ - if( p->pReal ){ - rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); - }else{ - memcpy(&p->zBuf[iOfst], zBuf, iAmt); - if( p->iSize<(iOfst+iAmt) ){ - p->iSize = (iOfst+iAmt); - } - } - } - return rc; -} - -/* -** Truncate the file. -*/ -static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ - int rc = SQLITE_OK; - JournalFile *p = (JournalFile *)pJfd; - if( p->pReal ){ - rc = sqlite3OsTruncate(p->pReal, size); - }else if( sizeiSize ){ - p->iSize = size; - } - return rc; -} - -/* -** Sync the file. -*/ -static int jrnlSync(sqlite3_file *pJfd, int flags){ - int rc; - JournalFile *p = (JournalFile *)pJfd; - if( p->pReal ){ - rc = sqlite3OsSync(p->pReal, flags); - }else{ - rc = SQLITE_OK; - } - return rc; -} - -/* -** Query the size of the file in bytes. -*/ -static int jrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){ - int rc = SQLITE_OK; - JournalFile *p = (JournalFile *)pJfd; - if( p->pReal ){ - rc = sqlite3OsFileSize(p->pReal, pSize); - }else{ - *pSize = (sqlite_int64) p->iSize; - } - return rc; -} - -/* -** Table of methods for JournalFile sqlite3_file object. -*/ -static struct sqlite3_io_methods JournalFileMethods = { - 1, /* iVersion */ - jrnlClose, /* xClose */ - jrnlRead, /* xRead */ - jrnlWrite, /* xWrite */ - jrnlTruncate, /* xTruncate */ - jrnlSync, /* xSync */ - jrnlFileSize, /* xFileSize */ - 0, /* xLock */ - 0, /* xUnlock */ - 0, /* xCheckReservedLock */ - 0, /* xFileControl */ - 0, /* xSectorSize */ - 0, /* xDeviceCharacteristics */ - 0, /* xShmMap */ - 0, /* xShmLock */ - 0, /* xShmBarrier */ - 0 /* xShmUnmap */ -}; - -/* -** Open a journal file. -*/ -int sqlite3JournalOpen( - sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */ - const char *zName, /* Name of the journal file */ - sqlite3_file *pJfd, /* Preallocated, blank file handle */ - int flags, /* Opening flags */ - int nBuf /* Bytes buffered before opening the file */ -){ - JournalFile *p = (JournalFile *)pJfd; - memset(p, 0, sqlite3JournalSize(pVfs)); - if( nBuf>0 ){ - p->zBuf = sqlite3MallocZero(nBuf); - if( !p->zBuf ){ - return SQLITE_NOMEM_BKPT; - } - }else{ - return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); - } - p->pMethod = &JournalFileMethods; - p->nBuf = nBuf; - p->flags = flags; - p->zJournal = zName; - p->pVfs = pVfs; - return SQLITE_OK; -} - -/* -** If the argument p points to a JournalFile structure, and the underlying -** file has not yet been created, create it now. -*/ -int sqlite3JournalCreate(sqlite3_file *p){ - if( p->pMethods!=&JournalFileMethods ){ - return SQLITE_OK; - } - return createFile((JournalFile *)p); -} - -/* -** The file-handle passed as the only argument is guaranteed to be an open -** file. It may or may not be of class JournalFile. If the file is a -** JournalFile, and the underlying file on disk has not yet been opened, -** return 0. Otherwise, return 1. -*/ -int sqlite3JournalExists(sqlite3_file *p){ - return (p->pMethods!=&JournalFileMethods || ((JournalFile *)p)->pReal!=0); -} - -/* -** Return the number of bytes required to store a JournalFile that uses vfs -** pVfs to create the underlying on-disk files. -*/ -int sqlite3JournalSize(sqlite3_vfs *pVfs){ - return (pVfs->szOsFile+sizeof(JournalFile)); -} -#endif -#endif diff --git a/src/memjournal.c b/src/memjournal.c index 12b77fc340..04780df99c 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -60,7 +60,7 @@ struct MemJournal { const sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */ int nChunkSize; /* In-memory chunk-size */ - int nBuf; /* Bytes of data before flushing */ + int nSpill; /* Bytes of data before flushing */ int nSize; /* Bytes of data currently in memory */ FileChunk *pFirst; /* Head of in-memory chunk-list */ FilePoint endpoint; /* Pointer to the end of the file */ @@ -137,7 +137,7 @@ static void memjrnlFreeChunks(MemJournal *p){ /* ** Flush the contents of memory to a real file on disk. */ -static int createFile(MemJournal *p){ +static int memjrnlCreateFile(MemJournal *p){ int rc = SQLITE_OK; if( !p->pReal ){ sqlite3_file *pReal = (sqlite3_file *)&p[1]; @@ -192,8 +192,8 @@ static int memjrnlWrite( } /* If the file should be created now. */ - else if( p->nBuf>0 && (iAmt+iOfst)>p->nBuf ){ - int rc = createFile(p); + else if( p->nSpill>0 && (iAmt+iOfst)>p->nSpill ){ + int rc = memjrnlCreateFile(p); if( rc==SQLITE_OK ){ rc = memjrnlWrite(pJfd, zBuf, iAmt, iOfst); } @@ -333,12 +333,12 @@ static const struct sqlite3_io_methods MemJournalMethods = { ** Open a journal file. ** ** The behaviour of the journal file depends on the value of parameter -** nBuf. If nBuf is 0, then the journal file is always create and -** accessed using the underlying VFS. If nBuf is less than zero, then -** all content is always stored in main-memory. Finally, if nBuf is a +** nSpill. If nSpill is 0, then the journal file is always create and +** accessed using the underlying VFS. If nSpill is less than zero, then +** all content is always stored in main-memory. Finally, if nSpill is a ** positive value, then the journal file is initially created in-memory ** but may be flushed to disk later on. In this case the journal file is -** flushed to disk either when it grows larger than nBuf bytes in size, +** flushed to disk either when it grows larger than nSpill bytes in size, ** or when sqlite3JournalCreate() is called. */ int sqlite3JournalOpen( @@ -346,28 +346,28 @@ int sqlite3JournalOpen( const char *zName, /* Name of the journal file */ sqlite3_file *pJfd, /* Preallocated, blank file handle */ int flags, /* Opening flags */ - int nBuf /* Bytes buffered before opening the file */ + int nSpill /* Bytes buffered before opening the file */ ){ MemJournal *p = (MemJournal*)pJfd; - /* Zero the file-handle object. If nBuf was passed zero, initialize + /* Zero the file-handle object. If nSpill was passed zero, initialize ** it using the sqlite3OsOpen() function of the underlying VFS. In this ** case none of the code in this module is executed as a result of calls ** made on the journal file-handle. */ memset(p, 0, sizeof(MemJournal) + (pVfs ? pVfs->szOsFile : 0)); - if( nBuf==0 ){ + if( nSpill==0 ){ return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); } - if( nBuf>0 ){ - p->nChunkSize = nBuf; + if( nSpill>0 ){ + p->nChunkSize = nSpill; }else{ p->nChunkSize = 8 + MEMJOURNAL_DFLT_FILECHUNKSIZE - sizeof(FileChunk); assert( MEMJOURNAL_DFLT_FILECHUNKSIZE==fileChunkSize(p->nChunkSize) ); } p->pMethod = (const sqlite3_io_methods*)&MemJournalMethods; - p->nBuf = nBuf; + p->nSpill = nSpill; p->flags = flags; p->zJournal = zName; p->pVfs = pVfs; @@ -385,13 +385,13 @@ void sqlite3MemJournalOpen(sqlite3_file *pJfd){ /* ** If the argument p points to a MemJournal structure that is not an ** in-memory-only journal file (i.e. is one that was opened with a +ve -** nBuf parameter), and the underlying file has not yet been created, +** nSpill parameter), and the underlying file has not yet been created, ** create it now. */ int sqlite3JournalCreate(sqlite3_file *p){ int rc = SQLITE_OK; - if( p->pMethods==&MemJournalMethods && ((MemJournal*)p)->nBuf>0 ){ - rc = createFile((MemJournal*)p); + if( p->pMethods==&MemJournalMethods && ((MemJournal*)p)->nSpill>0 ){ + rc = memjrnlCreateFile((MemJournal*)p); } return rc; } diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl index 23241e27a6..7bc05d2f75 100644 --- a/tool/mksqlite3c.tcl +++ b/tool/mksqlite3c.tcl @@ -323,7 +323,6 @@ foreach file { vdbe.c vdbeblob.c vdbesort.c - journal.c memjournal.c walker.c From 115305ff000b635c9ecb2978fdcbecb2151fc20f Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 5 Mar 2016 17:29:08 +0000 Subject: [PATCH 414/570] Change the way SQLite invokes the xBestIndex method of virtual tables so that N-way joins involving virtual tables work as expected. FossilOrigin-Name: ffc65968ede2c402e616147e6e3d737e6f9de21d --- manifest | 20 ++- manifest.uuid | 2 +- src/test_bestindex.c | 86 ++++++++--- src/where.c | 356 ++++++++++++++++++++++++++----------------- test/bestindex2.test | 127 +++++++++++++++ 5 files changed, 421 insertions(+), 170 deletions(-) create mode 100644 test/bestindex2.test diff --git a/manifest b/manifest index 10ffbe9dbe..f9803d8323 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\sunused\sjournal.c\ssource\sfile\s(its\sfunction\shave\sbeen\ssubsumed\sinto\nmemjournal.c).\s\sRefactor\ssome\sof\sthe\snames\sin\smemjournal.c.\s\sNo\sfunctional\nchanges. -D 2016-03-05T15:35:09.793 +C Change\sthe\sway\sSQLite\sinvokes\sthe\sxBestIndex\smethod\sof\svirtual\stables\sso\sthat\sN-way\sjoins\sinvolving\svirtual\stables\swork\sas\sexpected. +D 2016-03-05T17:29:08.396 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -370,7 +370,7 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60 F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8 F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 -F src/test_bestindex.c 1da6fa21ac9413e8985a698b962541e615a9f311 +F src/test_bestindex.c 29af3cc3b963ffe5760c85d142b9b3e5302c1e3d F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f F src/test_config.c 0dee90328e3dedf8ba002ee94b6a7e7ea7726fe4 @@ -428,7 +428,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c 56948ada5aacc3bf2628db3776986e8bf4085383 +F src/where.c bada38bf45ea4437318164f915243b3f0822ceda F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 3ca820435c5b597bb50e63ed11e938786fe5c23e F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a @@ -493,6 +493,7 @@ F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f F test/bc_common.tcl 3eda41ef9cda7d5f6c205462c96228b301da4191 F test/bestindex1.test e228fe1e3794dbe20271481164e000d695abcd24 +F test/bestindex2.test b5c1fbcf7a6e73b22763445262399c9fc50276bc F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59 F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc @@ -1452,7 +1453,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4de09777dad6188b7e897473700af3c9655e8547 -R 323dedc301dba3a5e5eae684c7c211b0 -U drh -Z 93b1612ed0c564573b8e6748ccaa7792 +P 5f2a262d3f6b1531001326faf1d3b3d92c20a30a +R 5392a3186cae79bf12c69e9ed8cd8a4b +T *branch * xbestindex-fix +T *sym-xbestindex-fix * +T -sym-trunk * +U dan +Z 7116cca1dca1d43002adf5a35b7161d9 diff --git a/manifest.uuid b/manifest.uuid index 2cc497c082..28b8b67ddf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5f2a262d3f6b1531001326faf1d3b3d92c20a30a \ No newline at end of file +ffc65968ede2c402e616147e6e3d737e6f9de21d \ No newline at end of file diff --git a/src/test_bestindex.c b/src/test_bestindex.c index abbdf1a02b..a955c2782c 100644 --- a/src/test_bestindex.c +++ b/src/test_bestindex.c @@ -116,6 +116,40 @@ struct tcl_cursor { sqlite3_stmt *pStmt; /* Read data from here */ }; +/* +** Dequote string z in place. +*/ +static void tclDequote(char *z){ + char q = z[0]; + + /* Set stack variable q to the close-quote character */ + if( q=='[' || q=='\'' || q=='"' || q=='`' ){ + int iIn = 1; + int iOut = 0; + if( q=='[' ) q = ']'; + + while( ALWAYS(z[iIn]) ){ + if( z[iIn]==q ){ + if( z[iIn+1]!=q ){ + /* Character iIn was the close quote. */ + iIn++; + break; + }else{ + /* Character iIn and iIn+1 form an escaped quote character. Skip + ** the input cursor past both and copy a single quote character + ** to the output buffer. */ + iIn += 2; + z[iOut++] = q; + } + }else{ + z[iOut++] = z[iIn++]; + } + } + + z[iOut] = '\0'; + } +} + /* ** This function is the implementation of both the xConnect and xCreate ** methods of the fs virtual table. @@ -135,43 +169,49 @@ static int tclConnect( char **pzErr ){ Tcl_Interp *interp = (Tcl_Interp*)pAux; - tcl_vtab *pTab; - const char *zCmd; + tcl_vtab *pTab = 0; + char *zCmd = 0; Tcl_Obj *pScript = 0; - int rc; + int rc = SQLITE_OK; if( argc!=4 ){ *pzErr = sqlite3_mprintf("wrong number of arguments"); return SQLITE_ERROR; } - zCmd = argv[3]; + zCmd = sqlite3_malloc(strlen(argv[3])+1); pTab = (tcl_vtab*)sqlite3_malloc(sizeof(tcl_vtab)); - if( pTab==0 ) return SQLITE_NOMEM; - memset(pTab, 0, sizeof(tcl_vtab)); + if( zCmd && pTab ){ + memcpy(zCmd, argv[3], strlen(argv[3])+1); + tclDequote(zCmd); + memset(pTab, 0, sizeof(tcl_vtab)); - pTab->pCmd = Tcl_NewStringObj(zCmd, -1); - pTab->interp = interp; - pTab->db = db; - Tcl_IncrRefCount(pTab->pCmd); + pTab->pCmd = Tcl_NewStringObj(zCmd, -1); + pTab->interp = interp; + pTab->db = db; + Tcl_IncrRefCount(pTab->pCmd); - pScript = Tcl_DuplicateObj(pTab->pCmd); - Tcl_IncrRefCount(pScript); - Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xConnect", -1)); + pScript = Tcl_DuplicateObj(pTab->pCmd); + Tcl_IncrRefCount(pScript); + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xConnect", -1)); - rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL); - if( rc!=TCL_OK ){ - *pzErr = sqlite3_mprintf("%s", Tcl_GetStringResult(interp)); - rc = SQLITE_ERROR; + rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL); + if( rc!=TCL_OK ){ + *pzErr = sqlite3_mprintf("%s", Tcl_GetStringResult(interp)); + rc = SQLITE_ERROR; + }else{ + rc = sqlite3_declare_vtab(db, Tcl_GetStringResult(interp)); + } + + if( rc!=SQLITE_OK ){ + sqlite3_free(pTab); + pTab = 0; + } }else{ - rc = sqlite3_declare_vtab(db, Tcl_GetStringResult(interp)); - } - - if( rc!=SQLITE_OK ){ - sqlite3_free(pTab); - pTab = 0; + rc = SQLITE_NOMEM; } + sqlite3_free(zCmd); *ppVtab = &pTab->base; return rc; } diff --git a/src/where.c b/src/where.c index ed90f61443..07936c5914 100644 --- a/src/where.c +++ b/src/where.c @@ -2748,6 +2748,151 @@ static int whereLoopAddBtree( } #ifndef SQLITE_OMIT_VIRTUALTABLE + +/* +** Argument pIdxInfo is already populated with all constraints that may +** be used by the virtual table identified by pBuilder->pNew->iTab. This +** function marks a subset of those constraints usable, invokes the +** xBestIndex method and adds the returned plan to pBuilder. +** +** A constraint is marked usable if: +** +** * Argument mUsable indicates that its prerequisites are available, and +** +** * It is not one of the operators specified in the mExclude mask passed +** as the fourth argument (which in practice is either WO_IN or 0). +** +** Argument mExtra is a mask of tables that must be scanned before the +** virtual table in question. These are added to the plans prerequisites +** before it is added to pBuilder. +** +** Output parameter *pbIn is set to true if the plan added to pBuilder +** uses one or more WO_IN terms, or false otherwise. +*/ +static int whereLoopAddVirtualOne( + WhereLoopBuilder *pBuilder, + Bitmask mExtra, /* Mask of tables that must be used. */ + Bitmask mUsable, /* Mask of usable prereqs */ + u16 mExclude, /* Exclude terms for this operator */ + sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */ + int *pbIn /* OUT: True if plan uses an IN(...) op */ +){ + WhereClause *pWC = pBuilder->pWC; + struct sqlite3_index_constraint *pIdxCons; + struct sqlite3_index_constraint_usage *pUsage = pIdxInfo->aConstraintUsage; + int i; + int mxTerm; + int rc = SQLITE_OK; + WhereLoop *pNew = pBuilder->pNew; + Parse *pParse = pBuilder->pWInfo->pParse; + struct SrcList_item *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab]; + int nConstraint = pIdxInfo->nConstraint; + + assert( (mUsable & mExtra)==mExtra ); + *pbIn = 0; + pNew->prereq = mExtra; + + /* Set the usable flag on the subset of constraints identified by + ** arguments mUsable and mExclude. */ + pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; + for(i=0; ia[pIdxCons->iTermOffset]; + pIdxCons->usable = 0; + if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight + && (pTerm->eOperator & mExclude)==0 + ){ + pIdxCons->usable = 1; + } + } + + /* Initialize the output fields of the sqlite3_index_info structure */ + memset(pUsage, 0, sizeof(pUsage[0])*nConstraint); + if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr); + pIdxInfo->idxStr = 0; + pIdxInfo->idxNum = 0; + pIdxInfo->needToFreeIdxStr = 0; + pIdxInfo->orderByConsumed = 0; + pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; + pIdxInfo->estimatedRows = 25; + pIdxInfo->idxFlags = 0; + pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed; + + /* Invoke the virtual table xBestIndex() method */ + rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo); + if( rc ) return rc; + + mxTerm = -1; + assert( pNew->nLSlot>=nConstraint ); + for(i=0; iaLTerm[i] = 0; + pNew->u.vtab.omitMask = 0; + pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; + for(i=0; i=0 ){ + WhereTerm *pTerm; + int j = pIdxCons->iTermOffset; + if( iTerm>=nConstraint + || j<0 + || j>=pWC->nTerm + || pNew->aLTerm[iTerm]!=0 + ){ + rc = SQLITE_ERROR; + sqlite3ErrorMsg(pParse,"%s.xBestIndex() malfunction",pSrc->pTab->zName); + return rc; + } + testcase( iTerm==nConstraint-1 ); + testcase( j==0 ); + testcase( j==pWC->nTerm-1 ); + pTerm = &pWC->a[j]; + pNew->prereq |= pTerm->prereqRight; + assert( iTermnLSlot ); + pNew->aLTerm[iTerm] = pTerm; + if( iTerm>mxTerm ) mxTerm = iTerm; + testcase( iTerm==15 ); + testcase( iTerm==16 ); + if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<eOperator & WO_IN)!=0 ){ + /* A virtual table that is constrained by an IN clause may not + ** consume the ORDER BY clause because (1) the order of IN terms + ** is not necessarily related to the order of output terms and + ** (2) Multiple outputs from a single IN value will not merge + ** together. */ + pIdxInfo->orderByConsumed = 0; + pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; + *pbIn = 1; + } + } + } + + pNew->nLTerm = mxTerm+1; + assert( pNew->nLTerm<=pNew->nLSlot ); + pNew->u.vtab.idxNum = pIdxInfo->idxNum; + pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; + pIdxInfo->needToFreeIdxStr = 0; + pNew->u.vtab.idxStr = pIdxInfo->idxStr; + pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ? + pIdxInfo->nOrderBy : 0); + pNew->rSetup = 0; + pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost); + pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows); + + /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated + ** that the scan will visit at most one row. Clear it otherwise. */ + if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){ + pNew->wsFlags |= WHERE_ONEROW; + }else{ + pNew->wsFlags &= ~WHERE_ONEROW; + } + whereLoopInsert(pBuilder, pNew); + if( pNew->u.vtab.needFree ){ + sqlite3_free(pNew->u.vtab.idxStr); + pNew->u.vtab.needFree = 0; + } + + return SQLITE_OK; +} + + /* ** Add all WhereLoop objects for a table of the join identified by ** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table. @@ -2778,167 +2923,102 @@ static int whereLoopAddVirtual( Bitmask mExtra, /* Tables that must be scanned before this one */ Bitmask mUnusable /* Tables that must be scanned after this one */ ){ + int rc = SQLITE_OK; /* Return code */ WhereInfo *pWInfo; /* WHERE analysis context */ Parse *pParse; /* The parsing context */ WhereClause *pWC; /* The WHERE clause */ struct SrcList_item *pSrc; /* The FROM clause term to search */ - Table *pTab; - sqlite3 *db; - sqlite3_index_info *pIdxInfo; - struct sqlite3_index_constraint *pIdxCons; - struct sqlite3_index_constraint_usage *pUsage; - WhereTerm *pTerm; - int i, j; - int iTerm, mxTerm; - int nConstraint; - int seenIn = 0; /* True if an IN operator is seen */ - int seenVar = 0; /* True if a non-constant constraint is seen */ - int iPhase; /* 0: const w/o IN, 1: const, 2: no IN, 2: IN */ + sqlite3_index_info *p; /* Object to pass to xBestIndex() */ + int nConstraint; /* Number of constraints in p */ + int bIn; /* True if plan uses IN(...) operator */ WhereLoop *pNew; - int rc = SQLITE_OK; + Bitmask mBest; /* Tables used by best possible plan */ assert( (mExtra & mUnusable)==0 ); pWInfo = pBuilder->pWInfo; pParse = pWInfo->pParse; - db = pParse->db; pWC = pBuilder->pWC; pNew = pBuilder->pNew; pSrc = &pWInfo->pTabList->a[pNew->iTab]; - pTab = pSrc->pTab; - assert( IsVirtual(pTab) ); - pIdxInfo = allocateIndexInfo(pParse, pWC, mUnusable, pSrc,pBuilder->pOrderBy); - if( pIdxInfo==0 ) return SQLITE_NOMEM_BKPT; - pNew->prereq = 0; + assert( IsVirtual(pSrc->pTab) ); + p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc,pBuilder->pOrderBy); + if( p==0 ) return SQLITE_NOMEM_BKPT; pNew->rSetup = 0; pNew->wsFlags = WHERE_VIRTUALTABLE; pNew->nLTerm = 0; pNew->u.vtab.needFree = 0; - pUsage = pIdxInfo->aConstraintUsage; - nConstraint = pIdxInfo->nConstraint; - if( whereLoopResize(db, pNew, nConstraint) ){ - sqlite3DbFree(db, pIdxInfo); + nConstraint = p->nConstraint; + if( whereLoopResize(pParse->db, pNew, nConstraint) ){ + sqlite3DbFree(pParse->db, p); return SQLITE_NOMEM_BKPT; } - for(iPhase=0; iPhase<=3; iPhase++){ - if( !seenIn && (iPhase&1)!=0 ){ - iPhase++; - if( iPhase>3 ) break; - } - if( !seenVar && iPhase>1 ) break; - pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; - for(i=0; inConstraint; i++, pIdxCons++){ - j = pIdxCons->iTermOffset; - pTerm = &pWC->a[j]; - switch( iPhase ){ - case 0: /* Constants without IN operator */ - pIdxCons->usable = 0; - if( (pTerm->eOperator & WO_IN)!=0 ){ - seenIn = 1; - } - if( (pTerm->prereqRight & ~mExtra)!=0 ){ - seenVar = 1; - }else if( (pTerm->eOperator & WO_IN)==0 ){ - pIdxCons->usable = 1; - } - break; - case 1: /* Constants with IN operators */ - assert( seenIn ); - pIdxCons->usable = (pTerm->prereqRight & ~mExtra)==0; - break; - case 2: /* Variables without IN */ - assert( seenVar ); - pIdxCons->usable = (pTerm->eOperator & WO_IN)==0; - break; - default: /* Variables with IN */ - assert( seenVar && seenIn ); - pIdxCons->usable = 1; - break; - } - } - memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); - if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr); - pIdxInfo->idxStr = 0; - pIdxInfo->idxNum = 0; - pIdxInfo->needToFreeIdxStr = 0; - pIdxInfo->orderByConsumed = 0; - pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; - pIdxInfo->estimatedRows = 25; - pIdxInfo->idxFlags = 0; - pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed; - rc = vtabBestIndex(pParse, pTab, pIdxInfo); - if( rc ) goto whereLoopAddVtab_exit; - pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; - pNew->prereq = mExtra; - mxTerm = -1; - assert( pNew->nLSlot>=nConstraint ); - for(i=0; iaLTerm[i] = 0; - pNew->u.vtab.omitMask = 0; - for(i=0; i=0 ){ - j = pIdxCons->iTermOffset; - if( iTerm>=nConstraint - || j<0 - || j>=pWC->nTerm - || pNew->aLTerm[iTerm]!=0 - ){ - rc = SQLITE_ERROR; - sqlite3ErrorMsg(pParse, "%s.xBestIndex() malfunction", pTab->zName); - goto whereLoopAddVtab_exit; - } - testcase( iTerm==nConstraint-1 ); - testcase( j==0 ); - testcase( j==pWC->nTerm-1 ); - pTerm = &pWC->a[j]; - pNew->prereq |= pTerm->prereqRight; - assert( iTermnLSlot ); - pNew->aLTerm[iTerm] = pTerm; - if( iTerm>mxTerm ) mxTerm = iTerm; - testcase( iTerm==15 ); - testcase( iTerm==16 ); - if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<eOperator & WO_IN)!=0 ){ - /* A virtual table that is constrained by an IN clause may not - ** consume the ORDER BY clause because (1) the order of IN terms - ** is not necessarily related to the order of output terms and - ** (2) Multiple outputs from a single IN value will not merge - ** together. */ - pIdxInfo->orderByConsumed = 0; - pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; - } - } - } - if( i>=nConstraint ){ - pNew->nLTerm = mxTerm+1; - assert( pNew->nLTerm<=pNew->nLSlot ); - pNew->u.vtab.idxNum = pIdxInfo->idxNum; - pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; - pIdxInfo->needToFreeIdxStr = 0; - pNew->u.vtab.idxStr = pIdxInfo->idxStr; - pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ? - pIdxInfo->nOrderBy : 0); - pNew->rSetup = 0; - pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost); - pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows); + /* First call xBestIndex() with all constraints usable. */ + rc = whereLoopAddVirtualOne(pBuilder, mExtra, (Bitmask)(-1), 0, p, &bIn); + mBest = pNew->prereq & ~mExtra; - /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated - ** that the scan will visit at most one row. Clear it otherwise. */ - if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){ - pNew->wsFlags |= WHERE_ONEROW; - }else{ - pNew->wsFlags &= ~WHERE_ONEROW; - } - whereLoopInsert(pBuilder, pNew); - if( pNew->u.vtab.needFree ){ - sqlite3_free(pNew->u.vtab.idxStr); - pNew->u.vtab.needFree = 0; + /* If the call to xBestIndex() with all terms enabled produced a plan + ** that does not require any source tables, there is no point in making + ** any further calls - if the xBestIndex() method is sane they will all + ** return the same plan anyway. + */ + if( mBest ){ + int seenZero = 0; /* True if a plan with no prereqs seen */ + int seenZeroNoIN = 0; /* Plan with no prereqs and no IN(...) seen */ + Bitmask mPrev = 0; + Bitmask mBestNoIn = 0; + + /* If the plan produced by the earlier call uses an IN(...) term, call + ** xBestIndex again, this time with IN(...) terms disabled. */ + if( rc==SQLITE_OK && bIn ){ + rc = whereLoopAddVirtualOne(pBuilder, mExtra, (Bitmask)-1, WO_IN, p,&bIn); + mBestNoIn = pNew->prereq & ~mExtra; + if( mBestNoIn==0 ){ + seenZero = 1; + if( bIn==0 ) seenZeroNoIN = 1; } } - } -whereLoopAddVtab_exit: - if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr); - sqlite3DbFree(db, pIdxInfo); + /* Call xBestIndex once for each distinct value of (prereqRight & ~mExtra) + ** in the set of terms that apply to the current virtual table. */ + while( rc==SQLITE_OK ){ + int i; + Bitmask mNext = (Bitmask)(-1); + assert( mNext>0 ); + for(i=0; ia[p->aConstraint[i].iTermOffset].prereqRight & ~mExtra + ); + if( mThis>mPrev && mThisprereq==mExtra ){ + seenZero = 1; + if( bIn==0 ) seenZeroNoIN = 1; + } + } + + /* If the calls to xBestIndex() in the above loop did not find a plan + ** that requires no source tables at all (i.e. one guaranteed to be + ** usable), make a call here with all source tables disabled */ + if( rc==SQLITE_OK && seenZero==0 ){ + rc = whereLoopAddVirtualOne(pBuilder, mExtra, mExtra, 0, p, &bIn); + if( bIn==0 ) seenZeroNoIN = 1; + } + + /* If the calls to xBestIndex() have so far failed to find a plan + ** that requires no source tables at all and does not use an IN(...) + ** operator, make a final call to obtain one here. */ + if( rc==SQLITE_OK && seenZeroNoIN==0 ){ + rc = whereLoopAddVirtualOne(pBuilder, mExtra, mExtra, WO_IN, p, &bIn); + } + } + + if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr); + sqlite3DbFree(pParse->db, p); return rc; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ diff --git a/test/bestindex2.test b/test/bestindex2.test new file mode 100644 index 0000000000..3c50d54865 --- /dev/null +++ b/test/bestindex2.test @@ -0,0 +1,127 @@ +# 2016 March 3 +# +# 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. +# +#*********************************************************************** + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix bestindex2 + + +#------------------------------------------------------------------------- +# Virtual table callback for table named $tbl, with the columns specified +# by list argument $cols. e.g. if the function is invoked as: +# +# vtab_cmd t1 {a b c} ... +# +# The table created is: +# +# "CREATE TABLE t1 (a, b, c)" +# +# The tables xBestIndex method behaves as if all possible combinations of +# "=" constraints (but no others) may be optimized. The cost of a full table +# scan is: +# +# "WHERE 1" "cost 1000000 rows 1000000" +# +# If one or more "=" constraints are in use, the cost and estimated number +# of rows returned are both is (11 - nCons)*1000, where nCons is the number +# of constraints used. e.g. +# +# "WHERE a=? AND b=?" -> "cost 900 rows 900" +# "WHERE c=? AND b "cost 1000 rows 1000" +# +proc vtab_cmd {tbl cols method args} { + switch -- $method { + xConnect { + return "CREATE TABLE $tbl ([join $cols ,])" + } + xBestIndex { + foreach {clist orderby mask} $args {} + + set cons [list] + set used [list] + + for {set i 0} {$i < [llength $clist]} {incr i} { + array unset C + array set C [lindex $clist $i] + if {$C(op)=="eq" && $C(usable) && [lsearch $cons $C(column)]<0} { + lappend used use $i + lappend cons $C(column) + } + } + + set nCons [llength $cons] + if {$nCons==0} { + return "cost 1000000 rows 1000000" + } else { + set cost [expr (11-$nCons) * 1000] + set ret [concat $used "cost $cost rows $cost"] + + set txt [list] + foreach c $cons { lappend txt "[lindex $cols $c]=?" } + lappend ret idxstr "indexed([join $txt { AND }])" + + return $ret + } + } + } + return "" +} + +register_tcl_module db + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING tcl("vtab_cmd t1 {a b}"); + CREATE VIRTUAL TABLE t2 USING tcl("vtab_cmd t2 {c d}"); + CREATE VIRTUAL TABLE t3 USING tcl("vtab_cmd t3 {e f}"); +} + +do_eqp_test 1.1 { + SELECT * FROM t1 WHERE a='abc' +} { + 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)} +} +do_eqp_test 1.2 { + SELECT * FROM t1 WHERE a='abc' AND b='def' +} { + 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)} +} +do_eqp_test 1.3 { + SELECT * FROM t1 WHERE a='abc' AND a='def' +} { + 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)} +} +do_eqp_test 1.4 { + SELECT * FROM t1,t2 WHERE c=a +} { + 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:} + 0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)} +} + +do_eqp_test 1.5 { + SELECT * FROM t1, t2 CROSS JOIN t3 WHERE t2.c = +t1.b AND t3.e=t2.d +} { + 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:} + 0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)} + 0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)} +} + +# This is the one that fails (as of 2016/3/3). +# +do_eqp_test 1.6 { + SELECT * FROM t1, t2, t3 WHERE t2.c = +t1.b AND t3.e = t2.d +} { + 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:} + 0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)} + 0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)} +} + +finish_test + From 2ea74dc805e3f565ad1f11feda59befd5fafeb2b Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 5 Mar 2016 20:28:24 +0000 Subject: [PATCH 415/570] Adjust the cost estimates for RTREE such that the expected number of rows and expected cost is halved for each additional constraint. FossilOrigin-Name: fd7cd0609381a85673d1f737ebeb19dde3de180f --- ext/rtree/rtree.c | 2 +- manifest | 17 +++++++---------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 4e473a22c2..012c48d6d1 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -1741,7 +1741,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ return SQLITE_NOMEM; } - nRow = pRtree->nRowEst / (iIdx + 1); + nRow = pRtree->nRowEst >> (iIdx/2); pIdxInfo->estimatedCost = (double)6.0 * (double)nRow; setEstimatedRows(pIdxInfo, nRow); diff --git a/manifest b/manifest index f9803d8323..81e614ac63 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sway\sSQLite\sinvokes\sthe\sxBestIndex\smethod\sof\svirtual\stables\sso\sthat\sN-way\sjoins\sinvolving\svirtual\stables\swork\sas\sexpected. -D 2016-03-05T17:29:08.396 +C Adjust\sthe\scost\sestimates\sfor\sRTREE\ssuch\sthat\sthe\sexpected\snumber\sof\srows\sand\nexpected\scost\sis\shalved\sfor\seach\sadditional\sconstraint. +D 2016-03-05T20:28:24.332 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -245,7 +245,7 @@ F ext/rbu/sqlite3rbu.c 371e8bf06cfb3f691adac47eb15ab1073ed92dcf F ext/rbu/sqlite3rbu.h 0bdeb3be211aaba7d85445fa36f4701a25a3dbde F ext/rbu/test_rbu.c 4a4cdcef4ef9379fc2a21f008805c80b27bcf573 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 0f9b595bd0debcbedf1d7a63d0e0678d619e6c9c +F ext/rtree/rtree.c 0b870ccb7b58b734a2a8e1e2755a7c0ded070920 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test 96a80c08440c932cd72aac50660e7af2612d2cda F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -1453,10 +1453,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 5f2a262d3f6b1531001326faf1d3b3d92c20a30a -R 5392a3186cae79bf12c69e9ed8cd8a4b -T *branch * xbestindex-fix -T *sym-xbestindex-fix * -T -sym-trunk * -U dan -Z 7116cca1dca1d43002adf5a35b7161d9 +P ffc65968ede2c402e616147e6e3d737e6f9de21d +R 8203917822af6549d587abdbaf41bca8 +U drh +Z 50bb6547d93efe3f9c2eda315226d306 diff --git a/manifest.uuid b/manifest.uuid index 28b8b67ddf..294a618c78 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ffc65968ede2c402e616147e6e3d737e6f9de21d \ No newline at end of file +fd7cd0609381a85673d1f737ebeb19dde3de180f \ No newline at end of file From 104ead923e40fd2844631ef9c4962b9abb5d7b08 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 5 Mar 2016 21:32:14 +0000 Subject: [PATCH 416/570] Fix a problem in the previous commit affecting queries with three or more tables joined together to the right of a LEFT or CROSS JOIN operator. FossilOrigin-Name: d8d89d69a490a708b83147945f74134ae0e4b387 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 2 +- test/bestindex2.test | 15 +++++++++++++-- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 47385eaf16..966cd7c3e6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sway\sSQLite\sinvokes\sthe\sxBestIndex\smethod\sof\svirtual\stables\sso\sthat\sN-way\sjoins\sinvolving\svirtual\stables\swork\sas\sexpected. -D 2016-03-05T21:07:49.054 +C Fix\sa\sproblem\sin\sthe\sprevious\scommit\saffecting\squeries\swith\sthree\sor\smore\stables\sjoined\stogether\sto\sthe\sright\sof\sa\sLEFT\sor\sCROSS\sJOIN\soperator. +D 2016-03-05T21:32:14.419 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -428,7 +428,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c bada38bf45ea4437318164f915243b3f0822ceda +F src/where.c ccc62c39af1e6340f6af36fcf68efb96482d4c3a F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 3ca820435c5b597bb50e63ed11e938786fe5c23e F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a @@ -493,7 +493,7 @@ F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f F test/bc_common.tcl 3eda41ef9cda7d5f6c205462c96228b301da4191 F test/bestindex1.test e228fe1e3794dbe20271481164e000d695abcd24 -F test/bestindex2.test b5c1fbcf7a6e73b22763445262399c9fc50276bc +F test/bestindex2.test 10f2c6791f1cd0de414012528cd10a114648fd8f F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59 F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc @@ -1453,7 +1453,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 5f2a262d3f6b1531001326faf1d3b3d92c20a30a fd7cd0609381a85673d1f737ebeb19dde3de180f -R 8203917822af6549d587abdbaf41bca8 +P 195444380bafd3d95d37ad83047c75ca20978de4 +R e0527fe33379f8b0f9960c0e82e97b5e U dan -Z 91287ee7a6808d5de733f697deaa38da +Z e8beaa0235978227df4d188254085ea8 diff --git a/manifest.uuid b/manifest.uuid index 4337cd8755..b5e68e1cb8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -195444380bafd3d95d37ad83047c75ca20978de4 \ No newline at end of file +d8d89d69a490a708b83147945f74134ae0e4b387 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 07936c5914..ea62617c53 100644 --- a/src/where.c +++ b/src/where.c @@ -2994,7 +2994,7 @@ static int whereLoopAddVirtual( mPrev = mNext; if( mNext==(Bitmask)(-1) ) break; if( mNext==mBest || mNext==mBestNoIn ) continue; - rc = whereLoopAddVirtualOne(pBuilder, mExtra, mNext, 0, p, &bIn); + rc = whereLoopAddVirtualOne(pBuilder, mExtra, mNext|mExtra, 0, p, &bIn); if( pNew->prereq==mExtra ){ seenZero = 1; if( bIn==0 ) seenZeroNoIN = 1; diff --git a/test/bestindex2.test b/test/bestindex2.test index 3c50d54865..7ccd61640d 100644 --- a/test/bestindex2.test +++ b/test/bestindex2.test @@ -113,8 +113,6 @@ do_eqp_test 1.5 { 0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)} } -# This is the one that fails (as of 2016/3/3). -# do_eqp_test 1.6 { SELECT * FROM t1, t2, t3 WHERE t2.c = +t1.b AND t3.e = t2.d } { @@ -123,5 +121,18 @@ do_eqp_test 1.6 { 0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)} } +do_execsql_test 1.7.1 { + CREATE TABLE x1(a, b); +} +do_eqp_test 1.7.2 { + SELECT * FROM x1 CROSS JOIN t1, t2, t3 + WHERE t1.a = t2.c AND t1.b = t3.e +} { + 0 0 0 {SCAN TABLE x1} + 0 1 1 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:} + 0 2 2 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)} + 0 3 3 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)} +} + finish_test From 8c71a98ce13ce3169e6533dd05fce3c2cac2926a Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 7 Mar 2016 17:37:37 +0000 Subject: [PATCH 417/570] Add the SQLITE_CONFIG_STMTJRNL_SPILL option for sqlite3_config(). FossilOrigin-Name: b6c4202432dc96f8f1740f52d0bf872116357fcc --- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- src/global.c | 13 +++++++++++++ src/main.c | 5 +++++ src/pager.c | 6 +++--- src/sqlite.h.in | 15 +++++++++++++++ src/sqliteInt.h | 1 + 7 files changed, 49 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 966cd7c3e6..6cf99353de 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\sin\sthe\sprevious\scommit\saffecting\squeries\swith\sthree\sor\smore\stables\sjoined\stogether\sto\sthe\sright\sof\sa\sLEFT\sor\sCROSS\sJOIN\soperator. -D 2016-03-05T21:32:14.419 +C Add\sthe\sSQLITE_CONFIG_STMTJRNL_SPILL\soption\sfor\ssqlite3_config(). +D 2016-03-07T17:37:37.281 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -306,14 +306,14 @@ F src/expr.c c4dad2cd6cec00387b75fef4551aff655430dcd2 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 5cb42d9a59e2a590776fd3fc8ff6f61d40df3c6e F src/func.c 552d300265aed09eea21f68ac742a440550c0062 -F src/global.c ded7b97efd16efda5062b65e857198e46c40e652 +F src/global.c 884d4c7eba9f5fc25c96a23b21520da19b7713e2 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c 723d5d708cdb61bdd47c00b9f07c75be45aefc09 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f -F src/main.c 32c45647866429f34d7a13a717172a8e7d0a1056 +F src/main.c 93c571d78bc41b257f36912e678db4817d3c540e F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -335,7 +335,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c f5bac8e74aaefc4ea520e43b4540793c3b8a9e8f F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c 2bc43817697b5a4e88fd6a2cdb2cb25f2223505c +F src/pager.c d40cf1e890a0582b6ac7cb208c24619d72d2c900 F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df @@ -350,10 +350,10 @@ F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 137b31daa84d57d67847bf621bb54f3353e2077b F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e -F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68 +F src/sqlite.h.in 0235586b3fb639e85998d495c90f007657fd82af F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 2ce28b3c1228de3b6d392d6bd69b47f3aa2f2931 +F src/sqliteInt.h 8c32c1f4566c577cfb8e1c96e56f61e8b3e780d7 F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1453,7 +1453,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 195444380bafd3d95d37ad83047c75ca20978de4 -R e0527fe33379f8b0f9960c0e82e97b5e -U dan -Z e8beaa0235978227df4d188254085ea8 +P d8d89d69a490a708b83147945f74134ae0e4b387 +R bbf6d9fea009c5097a1f1af27ba30392 +U drh +Z 638bda7b36ac0921edfae65baff4e139 diff --git a/manifest.uuid b/manifest.uuid index b5e68e1cb8..9a5e54bf85 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d8d89d69a490a708b83147945f74134ae0e4b387 \ No newline at end of file +b6c4202432dc96f8f1740f52d0bf872116357fcc \ No newline at end of file diff --git a/src/global.c b/src/global.c index 294d62fea8..bd70b38273 100644 --- a/src/global.c +++ b/src/global.c @@ -159,6 +159,18 @@ const unsigned char sqlite3CtypeMap[256] = { # define SQLITE_SORTER_PMASZ 250 #endif +/* Statement journals spill to disk when their size exceeds the following +** threashold (in bytes). 0 means that statement journals are created and +** written to disk immediately (the default behavior for SQLite versions +** before 3.12.0). -1 means always keep the entire statement journal in +** memory. (The statement journal is also always held entirely in memory +** if journal_mode=MEMORY or if temp_store=MEMORY, regardless of this +** setting.) +*/ +#ifndef SQLITE_STMTJRNL_SPILL +# define SQLITE_STMTJRNL_SPILL (64*1024) +#endif + /* ** The following singleton contains the global configuration for ** the SQLite library. @@ -173,6 +185,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = { 0, /* neverCorrupt */ 128, /* szLookaside */ 500, /* nLookaside */ + SQLITE_STMTJRNL_SPILL, /* nStmtSpill */ {0,0,0,0,0,0,0,0}, /* m */ {0,0,0,0,0,0,0,0,0}, /* mutex */ {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */ diff --git a/src/main.c b/src/main.c index 3ba5972fa6..e4252e7aa9 100644 --- a/src/main.c +++ b/src/main.c @@ -633,6 +633,11 @@ int sqlite3_config(int op, ...){ break; } + case SQLITE_CONFIG_STMTJRNL_SPILL: { + sqlite3GlobalConfig.nStmtSpill = va_arg(ap, int); + break; + } + default: { rc = SQLITE_ERROR; break; diff --git a/src/pager.c b/src/pager.c index c74748c8e4..f045ce0eff 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4358,11 +4358,11 @@ static int openSubJournal(Pager *pPager){ const int flags = SQLITE_OPEN_SUBJOURNAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE; - int nBuf = 64*1024; + int nStmtSpill = sqlite3Config.nStmtSpill; if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){ - nBuf = -1; + nStmtSpill = -1; } - rc = sqlite3JournalOpen(pPager->pVfs, 0, pPager->sjfd, flags, nBuf); + rc = sqlite3JournalOpen(pPager->pVfs, 0, pPager->sjfd, flags, nStmtSpill); } return rc; } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index c81a9d0c43..3b267974b5 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -1820,6 +1820,20 @@ struct sqlite3_mem_methods { ** is enabled (using the [PRAGMA threads] command) and the amount of content ** to be sorted exceeds the page size times the minimum of the ** [PRAGMA cache_size] setting and this value. +** +** [[SQLITE_CONFIG_STMTJRNL_SPILL]] +**
    SQLITE_CONFIG_STMTJRNL_SPILL +**
    ^The SQLITE_CONFIG_STMTJRNL_SPILL option takes a single parameter which +** becomes the [statement journal] spill-to-disk threshold. +** [Statement journals] are held in memory until their size (in bytes) +** exceeds this threshold, at which point they are written to disk. +** Or if the threshold is -1, statement journals are always held +** exclusively in memory. +** Since many statement journals never become large, setting the spill +** threshold to a value such as 64KiB can greatly reduce the amount of +** I/O required to support statement rollback. +** The default value for this setting is controlled by the +** [SQLITE_STMTJRNL_SPILL] compile-time option. ** */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ @@ -1847,6 +1861,7 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ +#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */ /* ** CAPI3REF: Database Connection Configuration Options diff --git a/src/sqliteInt.h b/src/sqliteInt.h index c7514d4c96..e9aab2e1bd 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3041,6 +3041,7 @@ struct Sqlite3Config { int neverCorrupt; /* Database is always well-formed */ int szLookaside; /* Default lookaside buffer size */ int nLookaside; /* Default lookaside buffer count */ + int nStmtSpill; /* Stmt-journal spill-to-disk threshold */ sqlite3_mem_methods m; /* Low-level memory allocation interface */ sqlite3_mutex_methods mutex; /* Low-level mutex interface */ sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */ From e45216fd9d90e193302c2bf990fc13481458f1d6 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 7 Mar 2016 17:39:30 +0000 Subject: [PATCH 418/570] Add a new row type to RBU (a peer of insert, update and delete) - "delete then insert". FossilOrigin-Name: 169311c85b30f625bdb6986c9cd11db70942d73b --- ext/rbu/rbuC.test | 142 ++++++++++++++++++++++++++++++++++++ ext/rbu/sqlite3rbu.c | 166 +++++++++++++++++++++++-------------------- manifest | 18 +++-- manifest.uuid | 2 +- 4 files changed, 244 insertions(+), 84 deletions(-) create mode 100644 ext/rbu/rbuC.test diff --git a/ext/rbu/rbuC.test b/ext/rbu/rbuC.test new file mode 100644 index 0000000000..89fd01518f --- /dev/null +++ b/ext/rbu/rbuC.test @@ -0,0 +1,142 @@ +# 2016 March 7 +# +# 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. +# +#*********************************************************************** +# Tests for RBU focused on the REPLACE operation (rbu_control column +# contains integer value 2). +# + +source [file join [file dirname [info script]] rbu_common.tcl] +set ::testprefix rbuC + +#------------------------------------------------------------------------- +# This test is actually of an UPDATE directive. Just to establish that +# these work with UNIQUE indexes before preceding to REPLACE. +# +do_execsql_test 1.0 { + CREATE TABLE t1(i INTEGER PRIMARY KEY, a, b, c UNIQUE); + INSERT INTO t1 VALUES(1, 'a', 'b', 'c'); +} + +forcedelete rbu.db +do_execsql_test 1.1 { + ATTACH 'rbu.db' AS rbu; + CREATE TABLE rbu.data_t1(i, a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(1, 'a', 'b', 'c', '.xxx'); +} + +do_test 1.2 { + step_rbu test.db rbu.db +} {SQLITE_DONE} + +do_execsql_test 1.3 { + SELECT * FROM t1 +} { + 1 a b c +} + +#------------------------------------------------------------------------- +# +foreach {tn schema} { + 1 { + CREATE TABLE t1(i INTEGER PRIMARY KEY, a, b, c UNIQUE); + CREATE INDEX t1a ON t1(a); + } + 2 { + CREATE TABLE t1(i PRIMARY KEY, a, b, c UNIQUE); + CREATE INDEX t1a ON t1(a); + } + 3 { + CREATE TABLE t1(i PRIMARY KEY, a, b, c UNIQUE) WITHOUT ROWID; + CREATE INDEX t1a ON t1(a); + } +} { + reset_db + forcedelete rbu.db + execsql $schema + + do_execsql_test 2.$tn.0 { + INSERT INTO t1 VALUES(1, 'a', 'b', 'c'); + INSERT INTO t1 VALUES(2, 'b', 'c', 'd'); + INSERT INTO t1 VALUES(3, 'c', 'd', 'e'); + } + + do_execsql_test 2.$tn.1 { + ATTACH 'rbu.db' AS rbu; + CREATE TABLE rbu.data_t1(i, a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(1, 1, 2, 3, 2); + INSERT INTO data_t1 VALUES(3, 'c', 'd', 'e', 2); + INSERT INTO data_t1 VALUES(4, 'd', 'e', 'f', 2); + } + + do_test 2.$tn.2 { + step_rbu test.db rbu.db + } {SQLITE_DONE} + + do_execsql_test 2.$tn.3 { + SELECT * FROM t1 ORDER BY i + } { + 1 1 2 3 + 2 b c d + 3 c d e + 4 d e f + } + + integrity_check 2.$tn.4 +} + +foreach {tn schema} { + 1 { + CREATE TABLE t1(a, b, c UNIQUE); + CREATE INDEX t1a ON t1(a); + } + + 2 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, c); + } +} { + if {$tn==2} { ifcapable !fts5 break } + reset_db + forcedelete rbu.db + execsql $schema + + do_execsql_test 3.$tn.0 { + INSERT INTO t1 VALUES('a', 'b', 'c'); + INSERT INTO t1 VALUES('b', 'c', 'd'); + INSERT INTO t1 VALUES('c', 'd', 'e'); + } + + do_execsql_test 3.$tn.1 { + ATTACH 'rbu.db' AS rbu; + CREATE TABLE rbu.data_t1(rbu_rowid, a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(1, 1, 2, 3, 2); + INSERT INTO data_t1 VALUES(3, 'c', 'd', 'e', 2); + INSERT INTO data_t1 VALUES(4, 'd', 'e', 'f', 2); + } + + do_test 3.$tn.2 { + step_rbu test.db rbu.db + } {SQLITE_DONE} + + do_execsql_test 3.$tn.3 { + SELECT rowid, * FROM t1 ORDER BY 1 + } { + 1 1 2 3 + 2 b c d + 3 c d e + 4 d e f + } + + integrity_check 3.$tn.4 +} + + + +finish_test + diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index 682becbb5c..7f27399988 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -280,10 +280,11 @@ struct RbuObjIter { */ #define RBU_INSERT 1 /* Insert on a main table b-tree */ #define RBU_DELETE 2 /* Delete a row from a main table b-tree */ -#define RBU_IDX_DELETE 3 /* Delete a row from an aux. index b-tree */ -#define RBU_IDX_INSERT 4 /* Insert on an aux. index b-tree */ -#define RBU_UPDATE 5 /* Update a row in a main table b-tree */ +#define RBU_REPLACE 3 /* Delete and then insert a row */ +#define RBU_IDX_DELETE 4 /* Delete a row from an aux. index b-tree */ +#define RBU_IDX_INSERT 5 /* Insert on an aux. index b-tree */ +#define RBU_UPDATE 6 /* Update a row in a main table b-tree */ /* ** A single step of an incremental checkpoint - frame iWalFrame of the wal @@ -1909,13 +1910,13 @@ static int rbuObjIterPrepareAll( ); }else{ zSql = sqlite3_mprintf( + "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' " + "UNION ALL " "SELECT %s, rbu_control FROM '%q' " "WHERE typeof(rbu_control)='integer' AND rbu_control!=1 " - "UNION ALL " - "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' " "ORDER BY %s%s", - zCollist, pIter->zDataTbl, zCollist, p->zStateDb, pIter->zDataTbl, + zCollist, pIter->zDataTbl, zCollist, zLimit ); } @@ -1981,17 +1982,17 @@ static int rbuObjIterPrepareAll( rbuMPrintfExec(p, p->dbMain, "CREATE TEMP TRIGGER rbu_delete_tr BEFORE DELETE ON \"%s%w\" " "BEGIN " - " SELECT rbu_tmp_insert(2, %s);" + " SELECT rbu_tmp_insert(3, %s);" "END;" "CREATE TEMP TRIGGER rbu_update1_tr BEFORE UPDATE ON \"%s%w\" " "BEGIN " - " SELECT rbu_tmp_insert(2, %s);" + " SELECT rbu_tmp_insert(3, %s);" "END;" "CREATE TEMP TRIGGER rbu_update2_tr AFTER UPDATE ON \"%s%w\" " "BEGIN " - " SELECT rbu_tmp_insert(3, %s);" + " SELECT rbu_tmp_insert(4, %s);" "END;", zWrite, zTbl, zOldlist, zWrite, zTbl, zOldlist, @@ -2509,14 +2510,12 @@ static int rbuStepType(sqlite3rbu *p, const char **pzMask){ switch( sqlite3_column_type(p->objiter.pSelect, iCol) ){ case SQLITE_INTEGER: { int iVal = sqlite3_column_int(p->objiter.pSelect, iCol); - if( iVal==0 ){ - res = RBU_INSERT; - }else if( iVal==1 ){ - res = RBU_DELETE; - }else if( iVal==2 ){ - res = RBU_IDX_DELETE; - }else if( iVal==3 ){ - res = RBU_IDX_INSERT; + switch( iVal ){ + case 0: res = RBU_INSERT; break; + case 1: res = RBU_DELETE; break; + case 2: res = RBU_REPLACE; break; + case 3: res = RBU_IDX_DELETE; break; + case 4: res = RBU_IDX_INSERT; break; } break; } @@ -2555,6 +2554,67 @@ static void assertColumnName(sqlite3_stmt *pStmt, int iCol, const char *zName){ # define assertColumnName(x,y,z) #endif +/* +** Argument eType must be one of RBU_INSERT, RBU_DELETE, RBU_IDX_INSERT or +** RBU_IDX_DELETE. This function performs the work of a single +** sqlite3rbu_step() call for the type of operation specified by eType. +*/ +static void rbuStepOneOp(sqlite3rbu *p, int eType){ + RbuObjIter *pIter = &p->objiter; + sqlite3_value *pVal; + sqlite3_stmt *pWriter; + int i; + + assert( p->rc==SQLITE_OK ); + assert( eType!=RBU_DELETE || pIter->zIdx==0 ); + + if( eType==RBU_IDX_DELETE || eType==RBU_DELETE ){ + pWriter = pIter->pDelete; + }else{ + pWriter = pIter->pInsert; + } + + for(i=0; inCol; i++){ + /* If this is an INSERT into a table b-tree and the table has an + ** explicit INTEGER PRIMARY KEY, check that this is not an attempt + ** to write a NULL into the IPK column. That is not permitted. */ + if( eType==RBU_INSERT + && pIter->zIdx==0 && pIter->eType==RBU_PK_IPK && pIter->abTblPk[i] + && sqlite3_column_type(pIter->pSelect, i)==SQLITE_NULL + ){ + p->rc = SQLITE_MISMATCH; + p->zErrmsg = sqlite3_mprintf("datatype mismatch"); + return; + } + + if( eType==RBU_DELETE && pIter->abTblPk[i]==0 ){ + continue; + } + + pVal = sqlite3_column_value(pIter->pSelect, i); + p->rc = sqlite3_bind_value(pWriter, i+1, pVal); + if( p->rc ) return; + } + if( pIter->zIdx==0 + && (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) + ){ + /* For a virtual table, or a table with no primary key, the + ** SELECT statement is: + ** + ** SELECT , rbu_control, rbu_rowid FROM .... + ** + ** Hence column_value(pIter->nCol+1). + */ + assertColumnName(pIter->pSelect, pIter->nCol+1, "rbu_rowid"); + pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); + p->rc = sqlite3_bind_value(pWriter, pIter->nCol+1, pVal); + } + if( p->rc==SQLITE_OK ){ + sqlite3_step(pWriter); + p->rc = resetAndCollectError(pWriter, &p->zErrmsg); + } +} + /* ** This function does the work for an sqlite3rbu_step() call. ** @@ -2569,78 +2629,32 @@ static void assertColumnName(sqlite3_stmt *pStmt, int iCol, const char *zName){ static int rbuStep(sqlite3rbu *p){ RbuObjIter *pIter = &p->objiter; const char *zMask = 0; - int i; int eType = rbuStepType(p, &zMask); if( eType ){ + assert( eType==RBU_INSERT || eType==RBU_DELETE + || eType==RBU_REPLACE || eType==RBU_IDX_DELETE + || eType==RBU_IDX_INSERT || eType==RBU_UPDATE + ); assert( eType!=RBU_UPDATE || pIter->zIdx==0 ); if( pIter->zIdx==0 && eType==RBU_IDX_DELETE ){ rbuBadControlError(p); } - else if( - eType==RBU_INSERT - || eType==RBU_DELETE - || eType==RBU_IDX_DELETE - || eType==RBU_IDX_INSERT - ){ - sqlite3_value *pVal; - sqlite3_stmt *pWriter; - - assert( eType!=RBU_UPDATE ); - assert( eType!=RBU_DELETE || pIter->zIdx==0 ); - - if( eType==RBU_IDX_DELETE || eType==RBU_DELETE ){ - pWriter = pIter->pDelete; - }else{ - pWriter = pIter->pInsert; - } - - for(i=0; inCol; i++){ - /* If this is an INSERT into a table b-tree and the table has an - ** explicit INTEGER PRIMARY KEY, check that this is not an attempt - ** to write a NULL into the IPK column. That is not permitted. */ - if( eType==RBU_INSERT - && pIter->zIdx==0 && pIter->eType==RBU_PK_IPK && pIter->abTblPk[i] - && sqlite3_column_type(pIter->pSelect, i)==SQLITE_NULL - ){ - p->rc = SQLITE_MISMATCH; - p->zErrmsg = sqlite3_mprintf("datatype mismatch"); - goto step_out; - } - - if( eType==RBU_DELETE && pIter->abTblPk[i]==0 ){ - continue; - } - - pVal = sqlite3_column_value(pIter->pSelect, i); - p->rc = sqlite3_bind_value(pWriter, i+1, pVal); - if( p->rc ) goto step_out; - } - if( pIter->zIdx==0 - && (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) - ){ - /* For a virtual table, or a table with no primary key, the - ** SELECT statement is: - ** - ** SELECT , rbu_control, rbu_rowid FROM .... - ** - ** Hence column_value(pIter->nCol+1). - */ - assertColumnName(pIter->pSelect, pIter->nCol+1, "rbu_rowid"); - pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); - p->rc = sqlite3_bind_value(pWriter, pIter->nCol+1, pVal); - } - if( p->rc==SQLITE_OK ){ - sqlite3_step(pWriter); - p->rc = resetAndCollectError(pWriter, &p->zErrmsg); - } - }else{ + else if( eType==RBU_REPLACE ){ + if( pIter->zIdx==0 ) rbuStepOneOp(p, RBU_DELETE); + if( p->rc==SQLITE_OK ) rbuStepOneOp(p, RBU_INSERT); + } + else if( eType!=RBU_UPDATE ){ + rbuStepOneOp(p, eType); + } + else{ sqlite3_value *pVal; sqlite3_stmt *pUpdate = 0; assert( eType==RBU_UPDATE ); rbuGetUpdateStmt(p, pIter, zMask, &pUpdate); if( pUpdate ){ + int i; for(i=0; p->rc==SQLITE_OK && inCol; i++){ char c = zMask[pIter->aiSrcOrder[i]]; pVal = sqlite3_column_value(pIter->pSelect, i); diff --git a/manifest b/manifest index 6cf99353de..9153631b3a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_CONFIG_STMTJRNL_SPILL\soption\sfor\ssqlite3_config(). -D 2016-03-07T17:37:37.281 +C Add\sa\snew\srow\stype\sto\sRBU\s(a\speer\sof\sinsert,\supdate\sand\sdelete)\s-\s"delete\sthen\sinsert". +D 2016-03-07T17:39:30.317 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -234,6 +234,7 @@ F ext/rbu/rbu8.test 3bbf2c35d71a843c463efe93946f14ad10c3ede0 F ext/rbu/rbu9.test 0806d1772c9f4981774ff028de6656e4183082af F ext/rbu/rbuA.test c1a7b3e2d926b8f8448bb3b4ae787e314ee4b2b3 F ext/rbu/rbuB.test c25bc325b8072a766e56bb76c001866b405925c2 +F ext/rbu/rbuC.test efe47db508a0269b683cb2a1913a425ffd39a831 F ext/rbu/rbu_common.tcl 0398545fed614f807d5f0ba55a85a51f08ba8f1a F ext/rbu/rbucrash.test 8d2ed5d4b05fef6c00c2a6b5f7ead71fa172a695 F ext/rbu/rbudiff.test 6cc806dc36389292f2a8f5842d0103721df4a07d @@ -241,7 +242,7 @@ F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 -F ext/rbu/sqlite3rbu.c 371e8bf06cfb3f691adac47eb15ab1073ed92dcf +F ext/rbu/sqlite3rbu.c 0d901d773bf4c9e7d101daaf545263044e7e6615 F ext/rbu/sqlite3rbu.h 0bdeb3be211aaba7d85445fa36f4701a25a3dbde F ext/rbu/test_rbu.c 4a4cdcef4ef9379fc2a21f008805c80b27bcf573 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 @@ -1453,7 +1454,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d8d89d69a490a708b83147945f74134ae0e4b387 -R bbf6d9fea009c5097a1f1af27ba30392 -U drh -Z 638bda7b36ac0921edfae65baff4e139 +P b6c4202432dc96f8f1740f52d0bf872116357fcc +R 56e1f15e83703ebf857ebd55a98bbcfe +T *branch * rbu-delete-then-insert +T *sym-rbu-delete-then-insert * +T -sym-trunk * +U dan +Z 681ea677d41a7fd6408ffd5219102c46 diff --git a/manifest.uuid b/manifest.uuid index 9a5e54bf85..683dc4199a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b6c4202432dc96f8f1740f52d0bf872116357fcc \ No newline at end of file +169311c85b30f625bdb6986c9cd11db70942d73b \ No newline at end of file From 237b2b7111b4d8df3417b6a4aa77546609ada1db Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 7 Mar 2016 19:08:27 +0000 Subject: [PATCH 419/570] Avoid a NULL pointer dereference following an OOM while generating code for IN operators on virtual tables. FossilOrigin-Name: c924008692e35f1f5144830af08d6de051dd21dd --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/wherecode.c | 6 ++++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 6cf99353de..381efdf956 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_CONFIG_STMTJRNL_SPILL\soption\sfor\ssqlite3_config(). -D 2016-03-07T17:37:37.281 +C Avoid\sa\sNULL\spointer\sdereference\sfollowing\san\sOOM\swhile\sgenerating\scode\nfor\sIN\soperators\son\svirtual\stables. +D 2016-03-07T19:08:27.802 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -430,7 +430,7 @@ F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c ccc62c39af1e6340f6af36fcf68efb96482d4c3a F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 -F src/wherecode.c 3ca820435c5b597bb50e63ed11e938786fe5c23e +F src/wherecode.c 870f3e92602f216701a14d3f26805caffbfb5c34 F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1453,7 +1453,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 d8d89d69a490a708b83147945f74134ae0e4b387 -R bbf6d9fea009c5097a1f1af27ba30392 +P b6c4202432dc96f8f1740f52d0bf872116357fcc +R e48be4f1fe6a73cf9fce9701a7a4b585 U drh -Z 638bda7b36ac0921edfae65baff4e139 +Z 61bc8adb3df986a31e200efbd3ce6ae3 diff --git a/manifest.uuid b/manifest.uuid index 9a5e54bf85..c96048b4e5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b6c4202432dc96f8f1740f52d0bf872116357fcc \ No newline at end of file +c924008692e35f1f5144830af08d6de051dd21dd \ No newline at end of file diff --git a/src/wherecode.c b/src/wherecode.c index bfc52fb470..1f5a324ec0 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -932,8 +932,10 @@ Bitmask sqlite3WhereCodeOneLoopStart( if( pCompare ){ pCompare->pLeft = pTerm->pExpr->pLeft; pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0); - if( pRight ) pRight->iTable = iReg+j+2; - sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0); + if( pRight ){ + pRight->iTable = iReg+j+2; + sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0); + } pCompare->pLeft = 0; sqlite3ExprDelete(db, pCompare); } From 108b7953ed1ec8b434edcd3764bed457fedab4bd Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 7 Mar 2016 20:14:27 +0000 Subject: [PATCH 420/570] Update fts3/4 so that the 'merge=X,0' command merges X pages from all segments of the first level in the fts index that contains 2 or more segments. FossilOrigin-Name: cddf69dbc46f10ee7e87538dd850e086386b544c --- ext/fts3/fts3_write.c | 13 +++- manifest | 17 +++-- manifest.uuid | 2 +- test/fts4merge.test | 1 - test/fts4opt.test | 169 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 188 insertions(+), 14 deletions(-) create mode 100644 test/fts4opt.test diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index d5a408222e..6a2299fccf 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -333,7 +333,8 @@ static int fts3SqlStmt( ** of the oldest level in the db that contains at least ? segments. Or, ** if no level in the FTS index contains more than ? segments, the statement ** returns zero rows. */ -/* 28 */ "SELECT level FROM %Q.'%q_segdir' GROUP BY level HAVING count(*)>=?" +/* 28 */ "SELECT level, count(*) AS cnt FROM %Q.'%q_segdir' " + " GROUP BY level HAVING cnt>=?" " ORDER BY (level %% 1024) ASC LIMIT 1", /* Estimate the upper limit on the number of leaf nodes in a new segment @@ -4836,10 +4837,14 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ ** set nSeg to -1. */ rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0); - sqlite3_bind_int(pFindLevel, 1, nMin); + sqlite3_bind_int(pFindLevel, 1, MAX(2, nMin)); if( sqlite3_step(pFindLevel)==SQLITE_ROW ){ iAbsLevel = sqlite3_column_int64(pFindLevel, 0); - nSeg = nMin; + if( nMin<2 ){ + nSeg = sqlite3_column_int(pFindLevel, 1); + }else{ + nSeg = nMin; + } }else{ nSeg = -1; } @@ -4991,7 +4996,7 @@ static int fts3DoIncrmerge( nMin = fts3Getint(&z); } - if( z[0]!='\0' || nMin<2 ){ + if( z[0]!='\0' || nMin<0 || nMin==1 ){ rc = SQLITE_ERROR; }else{ rc = SQLITE_OK; diff --git a/manifest b/manifest index 381efdf956..c6b7f7d8a4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\sa\sNULL\spointer\sdereference\sfollowing\san\sOOM\swhile\sgenerating\scode\nfor\sIN\soperators\son\svirtual\stables. -D 2016-03-07T19:08:27.802 +C Update\sfts3/4\sso\sthat\sthe\s'merge=X,0'\scommand\smerges\sX\spages\sfrom\sall\ssegments\sof\sthe\sfirst\slevel\sin\sthe\sfts\sindex\sthat\scontains\s2\sor\smore\ssegments. +D 2016-03-07T20:14:27.338 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -88,7 +88,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145 F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057 -F ext/fts3/fts3_write.c f442223e4a1914dc1fc12b65af7e4f2c255fa47c +F ext/fts3/fts3_write.c f56345c64387ca30bf91b91511082fa83d9b5178 F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/fts3/tool/fts3view.c 5d78b668f4e9598af9147f8999632599fb0d9dd5 @@ -748,12 +748,13 @@ F test/fts4growth.test 60d6bb3f78e25b34f533797dd9f2f9402310a13a F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269 F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d F test/fts4langid.test 9794addcc8faaee85ac60eceecdb52feb0c70f68 -F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee +F test/fts4merge.test 146563df4a90ccb7f111a6e11ab29bbfe9e6ce2c F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891 F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7 F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309 F test/fts4onepass.test 7319d61a2ed1325fc54afd0c060a0513b462303a +F test/fts4opt.test f15c84305c4b78c665fc476d8569e27ab9a0d418 F test/fts4unicode.test 27378af76394542cf490cf001d8d1505fe55f6a9 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef @@ -1453,7 +1454,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 b6c4202432dc96f8f1740f52d0bf872116357fcc -R e48be4f1fe6a73cf9fce9701a7a4b585 -U drh -Z 61bc8adb3df986a31e200efbd3ce6ae3 +P c924008692e35f1f5144830af08d6de051dd21dd +R f3add94e73abe6caae33e7ec37099121 +U dan +Z db7aad48334dff0e6979b8c94cd633a5 diff --git a/manifest.uuid b/manifest.uuid index c96048b4e5..9c4f38bdba 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c924008692e35f1f5144830af08d6de051dd21dd \ No newline at end of file +cddf69dbc46f10ee7e87538dd850e086386b544c \ No newline at end of file diff --git a/test/fts4merge.test b/test/fts4merge.test index fabb651e64..41f91fdc8f 100644 --- a/test/fts4merge.test +++ b/test/fts4merge.test @@ -89,7 +89,6 @@ foreach mod {fts3 fts4} { 5 {merge=6,%} 6 {merge=6,six} 7 {merge=6,1} - 8 {merge=6,0} } { do_catchsql_test 2.$tn { INSERT INTO t2(t2) VALUES($arg); diff --git a/test/fts4opt.test b/test/fts4opt.test new file mode 100644 index 0000000000..5638aff1b1 --- /dev/null +++ b/test/fts4opt.test @@ -0,0 +1,169 @@ +# 2016 March 8 +# +# 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. +# +#************************************************************************* +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/fts3_common.tcl +set ::testprefix fts4opt + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts3 { + finish_test + return +} + +# Create the fts_kjv_genesis procedure which fills and FTS3/4 table +# with the complete text of the Book of Genesis. +# +source $testdir/genesis.tcl + +do_execsql_test 1.0 { CREATE TABLE t1(docid, words) } +fts_kjv_genesis + +#------------------------------------------------------------------------- +# Argument $db is an open database handle. $tbl is the name of an FTS3/4 +# table with the database. This command rearranges the contents of the +# %_segdir table so that all segments within each index are on the same +# level. This means that the 'merge' command can then be used for an +# incremental optimize routine. +# +proc prepare_for_optimize {db tbl} { + $db eval [string map [list % $tbl] { + BEGIN; + CREATE TEMP TABLE tmp_segdir( + level, idx, start_block, leaves_end_block, end_block, root + ); + + INSERT INTO temp.tmp_segdir + SELECT + 1024*(o.level / 1024) + 32, -- level + sum(o.leveli.idx)), -- idx + o.start_block, o.leaves_end_block, o.end_block, o.root -- other + FROM %_segdir o, %_segdir i + WHERE (o.level / 1024) = (i.level / 1024) + GROUP BY o.level, o.idx; + + DELETE FROM %_segdir; + INSERT INTO %_segdir SELECT * FROM temp.tmp_segdir; + DROP TABLE temp.tmp_segdir; + + COMMIT; + }] +} + +do_test 1.1 { + execsql { CREATE VIRTUAL TABLE t2 USING fts4(words, prefix="1,2,3") } + foreach {docid words} [db eval { SELECT * FROM t1 }] { + execsql { INSERT INTO t2(docid, words) VALUES($docid, $words) } + } +} {} + +do_execsql_test 1.2 { + SELECT level, count(*) FROM t2_segdir GROUP BY level +} { + 0 13 1 15 2 5 + 1024 13 1025 15 1026 5 + 2048 13 2049 15 2050 5 + 3072 13 3073 15 3074 5 +} + +do_execsql_test 1.3 { INSERT INTO t2(t2) VALUES('integrity-check') } +prepare_for_optimize db t2 +do_execsql_test 1.4 { INSERT INTO t2(t2) VALUES('integrity-check') } + +do_execsql_test 1.5 { + SELECT level, count(*) FROM t2_segdir GROUP BY level +} { + 32 33 + 1056 33 + 2080 33 + 3104 33 +} + +do_test 1.6 { + while 1 { + set tc1 [db total_changes] + execsql { INSERT INTO t2(t2) VALUES('merge=5,0') } + set tc2 [db total_changes] + if {($tc2 - $tc1) < 2} break + } + execsql { SELECT level, count(*) FROM t2_segdir GROUP BY level } +} {33 1 1057 1 2081 1 3105 1} +do_execsql_test 1.7 { INSERT INTO t2(t2) VALUES('integrity-check') } + +do_execsql_test 1.8 { + INSERT INTO t2(words) SELECT words FROM t1; + SELECT level, count(*) FROM t2_segdir GROUP BY level; +} {0 2 1024 2 2048 2 3072 2} + +#------------------------------------------------------------------------- + +do_execsql_test 2.0 { + DELETE FROM t2; +} +do_test 2.1 { + foreach {docid words} [db eval { SELECT * FROM t1 }] { + execsql { INSERT INTO t2(docid, words) VALUES($docid, $words) } + } + + set i 0 + foreach {docid words} [db eval { SELECT * FROM t1 }] { + if {[incr i] % 2} { execsql { DELETE FROM t2 WHERE docid = $docid } } + } + + set i 0 + foreach {docid words} [db eval { SELECT * FROM t1 }] { + if {[incr i] % 3} { + execsql { INSERT OR REPLACE INTO t2(docid, words) VALUES($docid, $words) } + } + } +} {} + +do_execsql_test 2.2 { + SELECT level, count(*) FROM t2_segdir GROUP BY level +} { + 0 10 1 15 2 12 + 1024 10 1025 15 1026 12 + 2048 10 2049 15 2050 12 + 3072 10 3073 15 3074 12 +} + +do_execsql_test 2.3 { INSERT INTO t2(t2) VALUES('integrity-check') } +prepare_for_optimize db t2 +do_execsql_test 2.4 { INSERT INTO t2(t2) VALUES('integrity-check') } + +do_execsql_test 2.5 { + SELECT level, count(*) FROM t2_segdir GROUP BY level +} { + 32 37 + 1056 37 + 2080 37 + 3104 37 +} + +do_test 2.6 { + while 1 { + set tc1 [db total_changes] + execsql { INSERT INTO t2(t2) VALUES('merge=5,0') } + set tc2 [db total_changes] + if {($tc2 - $tc1) < 2} break + } + execsql { SELECT level, count(*) FROM t2_segdir GROUP BY level } +} {33 1 1057 1 2081 1 3105 1} +do_execsql_test 2.7 { INSERT INTO t2(t2) VALUES('integrity-check') } + +do_execsql_test 2.8 { + INSERT INTO t2(words) SELECT words FROM t1; + SELECT level, count(*) FROM t2_segdir GROUP BY level; +} {0 2 1024 2 2048 2 3072 2} + +finish_test From fb826b8c13d10fbabfd83301979c9779bc8fe8b3 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Mar 2016 00:39:58 +0000 Subject: [PATCH 421/570] Changes so that some assert()s in the virtual table query planner are correct even following an OOM error. FossilOrigin-Name: 9805f6f85211dcb5a0ab3ceca204e6f2e48530ea --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/wherecode.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index c6b7f7d8a4..1361fa2b6d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sfts3/4\sso\sthat\sthe\s'merge=X,0'\scommand\smerges\sX\spages\sfrom\sall\ssegments\sof\sthe\sfirst\slevel\sin\sthe\sfts\sindex\sthat\scontains\s2\sor\smore\ssegments. -D 2016-03-07T20:14:27.338 +C Changes\sso\sthat\ssome\sassert()s\sin\sthe\svirtual\stable\squery\splanner\sare\ncorrect\seven\sfollowing\san\sOOM\serror. +D 2016-03-08T00:39:58.482 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -430,7 +430,7 @@ F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c ccc62c39af1e6340f6af36fcf68efb96482d4c3a F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 -F src/wherecode.c 870f3e92602f216701a14d3f26805caffbfb5c34 +F src/wherecode.c 36ea3526e4d297b8438453689176c6543fe67b3a F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1454,7 +1454,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 c924008692e35f1f5144830af08d6de051dd21dd -R f3add94e73abe6caae33e7ec37099121 -U dan -Z db7aad48334dff0e6979b8c94cd633a5 +P cddf69dbc46f10ee7e87538dd850e086386b544c +R eadc238ea6455af5bdaa5c7ea27cb6ae +U drh +Z 93924e30a271561dfe424f31cad070b7 diff --git a/manifest.uuid b/manifest.uuid index 9c4f38bdba..2b6f7883de 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cddf69dbc46f10ee7e87538dd850e086386b544c \ No newline at end of file +9805f6f85211dcb5a0ab3ceca204e6f2e48530ea \ No newline at end of file diff --git a/src/wherecode.c b/src/wherecode.c index 1f5a324ec0..4c0878a5af 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -915,7 +915,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( ** the xFilter implementation might have changed the datatype or ** encoding of the value in the register, so it *must* be reloaded. */ assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed ); - if( pLevel->u.in.aInLoop!=0 ){ + if( !db->mallocFailed ){ assert( iIn>0 ); pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[--iIn].addrInTop); assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid ); From 599d57645625e39738952326d4618f7e86d104c3 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Mar 2016 01:11:51 +0000 Subject: [PATCH 422/570] Add a NEVER() to the code generator. Change the parameter name "mExtra" to "mPrereq" in the query planner, to more closely reflect its meaning. FossilOrigin-Name: 721ae51e443647291f3a8f7f2128aa410fee2682 --- manifest | 14 +++++------ manifest.uuid | 2 +- src/where.c | 66 ++++++++++++++++++++++++------------------------- src/wherecode.c | 2 +- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/manifest b/manifest index 1361fa2b6d..773add8218 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Changes\sso\sthat\ssome\sassert()s\sin\sthe\svirtual\stable\squery\splanner\sare\ncorrect\seven\sfollowing\san\sOOM\serror. -D 2016-03-08T00:39:58.482 +C Add\sa\sNEVER()\sto\sthe\scode\sgenerator.\s\sChange\sthe\sparameter\sname\s"mExtra"\nto\s"mPrereq"\sin\sthe\squery\splanner,\sto\smore\sclosely\sreflect\sits\smeaning. +D 2016-03-08T01:11:51.292 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -428,9 +428,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c ccc62c39af1e6340f6af36fcf68efb96482d4c3a +F src/where.c 3787158e3b365eec7553d6f1d6596b7fa64ea6de F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 -F src/wherecode.c 36ea3526e4d297b8438453689176c6543fe67b3a +F src/wherecode.c 863aedf086131743763c1960637fde904eadc442 F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1454,7 +1454,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 cddf69dbc46f10ee7e87538dd850e086386b544c -R eadc238ea6455af5bdaa5c7ea27cb6ae +P 9805f6f85211dcb5a0ab3ceca204e6f2e48530ea +R ee7409507ed80149a169811d9e037a32 U drh -Z 93924e30a271561dfe424f31cad070b7 +Z 2ec5edc1158dca51232e491f1a3a4594 diff --git a/manifest.uuid b/manifest.uuid index 2b6f7883de..4c968a7a8f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9805f6f85211dcb5a0ab3ceca204e6f2e48530ea \ No newline at end of file +721ae51e443647291f3a8f7f2128aa410fee2682 \ No newline at end of file diff --git a/src/where.c b/src/where.c index ea62617c53..9ed2d561cb 100644 --- a/src/where.c +++ b/src/where.c @@ -2554,7 +2554,7 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ */ static int whereLoopAddBtree( WhereLoopBuilder *pBuilder, /* WHERE clause information */ - Bitmask mExtra /* Extra prerequesites for using this table */ + Bitmask mPrereq /* Extra prerequesites for using this table */ ){ WhereInfo *pWInfo; /* WHERE analysis context */ Index *pProbe; /* An index we are evaluating */ @@ -2654,7 +2654,7 @@ static int whereLoopAddBtree( pNew->nOut = 43; assert( 43==sqlite3LogEst(20) ); pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut); pNew->wsFlags = WHERE_AUTO_INDEX; - pNew->prereq = mExtra | pTerm->prereqRight; + pNew->prereq = mPrereq | pTerm->prereqRight; rc = whereLoopInsert(pBuilder, pNew); } } @@ -2675,7 +2675,7 @@ static int whereLoopAddBtree( pNew->nLTerm = 0; pNew->iSortIdx = 0; pNew->rSetup = 0; - pNew->prereq = mExtra; + pNew->prereq = mPrereq; pNew->nOut = rSize; pNew->u.btree.pIndex = pProbe; b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor); @@ -2762,7 +2762,7 @@ static int whereLoopAddBtree( ** * It is not one of the operators specified in the mExclude mask passed ** as the fourth argument (which in practice is either WO_IN or 0). ** -** Argument mExtra is a mask of tables that must be scanned before the +** Argument mPrereq is a mask of tables that must be scanned before the ** virtual table in question. These are added to the plans prerequisites ** before it is added to pBuilder. ** @@ -2771,7 +2771,7 @@ static int whereLoopAddBtree( */ static int whereLoopAddVirtualOne( WhereLoopBuilder *pBuilder, - Bitmask mExtra, /* Mask of tables that must be used. */ + Bitmask mPrereq, /* Mask of tables that must be used. */ Bitmask mUsable, /* Mask of usable prereqs */ u16 mExclude, /* Exclude terms for this operator */ sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */ @@ -2788,9 +2788,9 @@ static int whereLoopAddVirtualOne( struct SrcList_item *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab]; int nConstraint = pIdxInfo->nConstraint; - assert( (mUsable & mExtra)==mExtra ); + assert( (mUsable & mPrereq)==mPrereq ); *pbIn = 0; - pNew->prereq = mExtra; + pNew->prereq = mPrereq; /* Set the usable flag on the subset of constraints identified by ** arguments mUsable and mExclude. */ @@ -2897,8 +2897,8 @@ static int whereLoopAddVirtualOne( ** Add all WhereLoop objects for a table of the join identified by ** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table. ** -** If there are no LEFT or CROSS JOIN joins in the query, both mExtra and -** mUnusable are set to 0. Otherwise, mExtra is a mask of all FROM clause +** If there are no LEFT or CROSS JOIN joins in the query, both mPrereq and +** mUnusable are set to 0. Otherwise, mPrereq is a mask of all FROM clause ** entries that occur before the virtual table in the FROM clause and are ** separated from it by at least one LEFT or CROSS JOIN. Similarly, the ** mUnusable mask contains all FROM clause entries that occur after the @@ -2909,18 +2909,18 @@ static int whereLoopAddVirtualOne( ** ** ... FROM t1, t2 LEFT JOIN t3, t4, vt CROSS JOIN t5, t6; ** -** then mExtra corresponds to (t1, t2) and mUnusable to (t5, t6). +** then mPrereq corresponds to (t1, t2) and mUnusable to (t5, t6). ** -** All the tables in mExtra must be scanned before the current virtual +** All the tables in mPrereq must be scanned before the current virtual ** table. So any terms for which all prerequisites are satisfied by -** mExtra may be specified as "usable" in all calls to xBestIndex. +** mPrereq may be specified as "usable" in all calls to xBestIndex. ** Conversely, all tables in mUnusable must be scanned after the current ** virtual table, so any terms for which the prerequisites overlap with ** mUnusable should always be configured as "not-usable" for xBestIndex. */ static int whereLoopAddVirtual( WhereLoopBuilder *pBuilder, /* WHERE clause information */ - Bitmask mExtra, /* Tables that must be scanned before this one */ + Bitmask mPrereq, /* Tables that must be scanned before this one */ Bitmask mUnusable /* Tables that must be scanned after this one */ ){ int rc = SQLITE_OK; /* Return code */ @@ -2934,7 +2934,7 @@ static int whereLoopAddVirtual( WhereLoop *pNew; Bitmask mBest; /* Tables used by best possible plan */ - assert( (mExtra & mUnusable)==0 ); + assert( (mPrereq & mUnusable)==0 ); pWInfo = pBuilder->pWInfo; pParse = pWInfo->pParse; pWC = pBuilder->pWC; @@ -2954,8 +2954,8 @@ static int whereLoopAddVirtual( } /* First call xBestIndex() with all constraints usable. */ - rc = whereLoopAddVirtualOne(pBuilder, mExtra, (Bitmask)(-1), 0, p, &bIn); - mBest = pNew->prereq & ~mExtra; + rc = whereLoopAddVirtualOne(pBuilder, mPrereq, (Bitmask)(-1), 0, p, &bIn); + mBest = pNew->prereq & ~mPrereq; /* If the call to xBestIndex() with all terms enabled produced a plan ** that does not require any source tables, there is no point in making @@ -2971,15 +2971,15 @@ static int whereLoopAddVirtual( /* If the plan produced by the earlier call uses an IN(...) term, call ** xBestIndex again, this time with IN(...) terms disabled. */ if( rc==SQLITE_OK && bIn ){ - rc = whereLoopAddVirtualOne(pBuilder, mExtra, (Bitmask)-1, WO_IN, p,&bIn); - mBestNoIn = pNew->prereq & ~mExtra; + rc = whereLoopAddVirtualOne(pBuilder,mPrereq,(Bitmask)-1,WO_IN,p,&bIn); + mBestNoIn = pNew->prereq & ~mPrereq; if( mBestNoIn==0 ){ seenZero = 1; if( bIn==0 ) seenZeroNoIN = 1; } } - /* Call xBestIndex once for each distinct value of (prereqRight & ~mExtra) + /* Call xBestIndex once for each distinct value of (prereqRight & ~mPrereq) ** in the set of terms that apply to the current virtual table. */ while( rc==SQLITE_OK ){ int i; @@ -2987,15 +2987,15 @@ static int whereLoopAddVirtual( assert( mNext>0 ); for(i=0; ia[p->aConstraint[i].iTermOffset].prereqRight & ~mExtra + pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq ); if( mThis>mPrev && mThisprereq==mExtra ){ + rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mNext|mPrereq, 0, p, &bIn); + if( pNew->prereq==mPrereq ){ seenZero = 1; if( bIn==0 ) seenZeroNoIN = 1; } @@ -3005,7 +3005,7 @@ static int whereLoopAddVirtual( ** that requires no source tables at all (i.e. one guaranteed to be ** usable), make a call here with all source tables disabled */ if( rc==SQLITE_OK && seenZero==0 ){ - rc = whereLoopAddVirtualOne(pBuilder, mExtra, mExtra, 0, p, &bIn); + rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mPrereq, 0, p, &bIn); if( bIn==0 ) seenZeroNoIN = 1; } @@ -3013,7 +3013,7 @@ static int whereLoopAddVirtual( ** that requires no source tables at all and does not use an IN(...) ** operator, make a final call to obtain one here. */ if( rc==SQLITE_OK && seenZeroNoIN==0 ){ - rc = whereLoopAddVirtualOne(pBuilder, mExtra, mExtra, WO_IN, p, &bIn); + rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mPrereq, WO_IN, p, &bIn); } } @@ -3029,7 +3029,7 @@ static int whereLoopAddVirtual( */ static int whereLoopAddOr( WhereLoopBuilder *pBuilder, - Bitmask mExtra, + Bitmask mPrereq, Bitmask mUnusable ){ WhereInfo *pWInfo = pBuilder->pWInfo; @@ -3090,14 +3090,14 @@ static int whereLoopAddOr( #endif #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pItem->pTab) ){ - rc = whereLoopAddVirtual(&sSubBuild, mExtra, mUnusable); + rc = whereLoopAddVirtual(&sSubBuild, mPrereq, mUnusable); }else #endif { - rc = whereLoopAddBtree(&sSubBuild, mExtra); + rc = whereLoopAddBtree(&sSubBuild, mPrereq); } if( rc==SQLITE_OK ){ - rc = whereLoopAddOr(&sSubBuild, mExtra, mUnusable); + rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable); } assert( rc==SQLITE_OK || sCur.n==0 ); if( sCur.n==0 ){ @@ -3154,7 +3154,7 @@ static int whereLoopAddOr( */ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ WhereInfo *pWInfo = pBuilder->pWInfo; - Bitmask mExtra = 0; + Bitmask mPrereq = 0; Bitmask mPrior = 0; int iTab; SrcList *pTabList = pWInfo->pTabList; @@ -3175,7 +3175,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){ /* This condition is true when pItem is the FROM clause term on the ** right-hand-side of a LEFT or CROSS JOIN. */ - mExtra = mPrior; + mPrereq = mPrior; } priorJointype = pItem->fg.jointype; if( IsVirtual(pItem->pTab) ){ @@ -3185,12 +3185,12 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor); } } - rc = whereLoopAddVirtual(pBuilder, mExtra, mUnusable); + rc = whereLoopAddVirtual(pBuilder, mPrereq, mUnusable); }else{ - rc = whereLoopAddBtree(pBuilder, mExtra); + rc = whereLoopAddBtree(pBuilder, mPrereq); } if( rc==SQLITE_OK ){ - rc = whereLoopAddOr(pBuilder, mExtra, mUnusable); + rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable); } mPrior |= pNew->maskSelf; if( rc || db->mallocFailed ) break; diff --git a/src/wherecode.c b/src/wherecode.c index 4c0878a5af..3705aab51d 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -882,7 +882,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( for(j=0; jaLTerm[j]; - if( pTerm==0 ) continue; + if( NEVER(pTerm==0) ) continue; if( pTerm->eOperator & WO_IN ){ codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); addrNotFound = pLevel->addrNxt; From 8426e36c8f55d4b73892afd4c81aa67d2735ced3 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Mar 2016 01:32:30 +0000 Subject: [PATCH 423/570] Add the ALLBITS macro as a shorthand for "(Bitmask)(-1)". FossilOrigin-Name: 91bd619d27e4d91510a187bbb88de961a31c8a2e --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/sqliteInt.h | 1 + src/update.c | 2 +- src/where.c | 18 +++++++++--------- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 773add8218..4cdc82a8c0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\sNEVER()\sto\sthe\scode\sgenerator.\s\sChange\sthe\sparameter\sname\s"mExtra"\nto\s"mPrereq"\sin\sthe\squery\splanner,\sto\smore\sclosely\sreflect\sits\smeaning. -D 2016-03-08T01:11:51.292 +C Add\sthe\sALLBITS\smacro\sas\sa\sshorthand\sfor\s"(Bitmask)(-1)". +D 2016-03-08T01:32:30.559 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -353,7 +353,7 @@ F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 0235586b3fb639e85998d495c90f007657fd82af F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 8c32c1f4566c577cfb8e1c96e56f61e8b3e780d7 +F src/sqliteInt.h 4c7b8501b37eb768a5457b01cb9a9a5505f3fd85 F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -410,7 +410,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 3d338cdd00d916ce8a05c397001d64ed58e6fe1c F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 -F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca +F src/update.c 56b3db7edff0110360a12b76af97c39ebe3ea8b8 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 12800a93f0664f41575f96799eb881a786d565e6 F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 @@ -428,7 +428,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c 3787158e3b365eec7553d6f1d6596b7fa64ea6de +F src/where.c e4d2d0ea8403339db188e75b75ca44fff225abba F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 863aedf086131743763c1960637fde904eadc442 F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a @@ -1454,7 +1454,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 9805f6f85211dcb5a0ab3ceca204e6f2e48530ea -R ee7409507ed80149a169811d9e037a32 +P 721ae51e443647291f3a8f7f2128aa410fee2682 +R 06f3b1fde5a5e4d09bcfebd9ae1525b6 U drh -Z 2ec5edc1158dca51232e491f1a3a4594 +Z acf689ff3c45ad889c44d18cadd3bf9c diff --git a/manifest.uuid b/manifest.uuid index 4c968a7a8f..78794d5451 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -721ae51e443647291f3a8f7f2128aa410fee2682 \ No newline at end of file +91bd619d27e4d91510a187bbb88de961a31c8a2e \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index e9aab2e1bd..ff4dbd4864 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2353,6 +2353,7 @@ struct IdList { */ #define MASKBIT(n) (((Bitmask)1)<<(n)) #define MASKBIT32(n) (((unsigned int)1)<<(n)) +#define ALLBITS ((Bitmask)-1) /* ** The following structure describes the FROM clause of a SELECT statement. diff --git a/src/update.c b/src/update.c index 2a436b9701..9b351662e2 100644 --- a/src/update.c +++ b/src/update.c @@ -268,7 +268,7 @@ void sqlite3Update( ** case, set all bits of the colUsed mask (to ensure that the virtual ** table implementation makes all columns available). */ - pTabList->a[0].colUsed = IsVirtual(pTab) ? (Bitmask)-1 : 0; + pTabList->a[0].colUsed = IsVirtual(pTab) ? ALLBITS : 0; hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey); diff --git a/src/where.c b/src/where.c index 9ed2d561cb..7510839791 100644 --- a/src/where.c +++ b/src/where.c @@ -2771,9 +2771,9 @@ static int whereLoopAddBtree( */ static int whereLoopAddVirtualOne( WhereLoopBuilder *pBuilder, - Bitmask mPrereq, /* Mask of tables that must be used. */ - Bitmask mUsable, /* Mask of usable prereqs */ - u16 mExclude, /* Exclude terms for this operator */ + Bitmask mPrereq, /* Mask of tables that must be used. */ + Bitmask mUsable, /* Mask of usable tables */ + u16 mExclude, /* Exclude terms using these operators */ sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */ int *pbIn /* OUT: True if plan uses an IN(...) op */ ){ @@ -2941,7 +2941,7 @@ static int whereLoopAddVirtual( pNew = pBuilder->pNew; pSrc = &pWInfo->pTabList->a[pNew->iTab]; assert( IsVirtual(pSrc->pTab) ); - p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc,pBuilder->pOrderBy); + p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy); if( p==0 ) return SQLITE_NOMEM_BKPT; pNew->rSetup = 0; pNew->wsFlags = WHERE_VIRTUALTABLE; @@ -2954,7 +2954,7 @@ static int whereLoopAddVirtual( } /* First call xBestIndex() with all constraints usable. */ - rc = whereLoopAddVirtualOne(pBuilder, mPrereq, (Bitmask)(-1), 0, p, &bIn); + rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, &bIn); mBest = pNew->prereq & ~mPrereq; /* If the call to xBestIndex() with all terms enabled produced a plan @@ -2971,7 +2971,7 @@ static int whereLoopAddVirtual( /* If the plan produced by the earlier call uses an IN(...) term, call ** xBestIndex again, this time with IN(...) terms disabled. */ if( rc==SQLITE_OK && bIn ){ - rc = whereLoopAddVirtualOne(pBuilder,mPrereq,(Bitmask)-1,WO_IN,p,&bIn); + rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, WO_IN, p, &bIn); mBestNoIn = pNew->prereq & ~mPrereq; if( mBestNoIn==0 ){ seenZero = 1; @@ -2983,7 +2983,7 @@ static int whereLoopAddVirtual( ** in the set of terms that apply to the current virtual table. */ while( rc==SQLITE_OK ){ int i; - Bitmask mNext = (Bitmask)(-1); + Bitmask mNext = ALLBITS; assert( mNext>0 ); for(i=0; imPrev && mThisprereq==mPrereq ){ @@ -4280,7 +4280,7 @@ WhereInfo *sqlite3WhereBegin( } } if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){ - pWInfo->revMask = (Bitmask)(-1); + pWInfo->revMask = ALLBITS; } if( pParse->nErr || NEVER(db->mallocFailed) ){ goto whereBeginError; From 6de32e7cdb9fe691ff3b046d69ebfe458887c3d5 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Mar 2016 02:59:33 +0000 Subject: [PATCH 424/570] Simplified error detection in the xBestIndex processing. FossilOrigin-Name: 82ca2131b670505578628687746135ac413d156b --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 13 +++++++++---- test/vtab6.test | 4 ++-- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 4cdc82a8c0..02f759a644 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sALLBITS\smacro\sas\sa\sshorthand\sfor\s"(Bitmask)(-1)". -D 2016-03-08T01:32:30.559 +C Simplified\serror\sdetection\sin\sthe\sxBestIndex\sprocessing. +D 2016-03-08T02:59:33.371 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -428,7 +428,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c e4d2d0ea8403339db188e75b75ca44fff225abba +F src/where.c dff52f7f0842430f80a7017c7859124685b08453 F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 863aedf086131743763c1960637fde904eadc442 F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a @@ -1286,7 +1286,7 @@ F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3 F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391 -F test/vtab6.test d2986cf418dc51e7fb81d12366bea2caa8b812df +F test/vtab6.test 8e789f526e6594cf7ae933d1adee0caa87dc9f78 F test/vtab7.test ae560ebea870ed04e9aa4177cc302f910faaabb5 F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583 F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b @@ -1454,7 +1454,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 721ae51e443647291f3a8f7f2128aa410fee2682 -R 06f3b1fde5a5e4d09bcfebd9ae1525b6 +P 91bd619d27e4d91510a187bbb88de961a31c8a2e +R 925559caeda122c2e0a2ca4fc28cc0ee U drh -Z acf689ff3c45ad889c44d18cadd3bf9c +Z b4b54118bbf4d13b5c60372c03985e73 diff --git a/manifest.uuid b/manifest.uuid index 78794d5451..21eda15faa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -91bd619d27e4d91510a187bbb88de961a31c8a2e \ No newline at end of file +82ca2131b670505578628687746135ac413d156b \ No newline at end of file diff --git a/src/where.c b/src/where.c index 7510839791..2d7272a742 100644 --- a/src/where.c +++ b/src/where.c @@ -934,7 +934,6 @@ static sqlite3_index_info *allocateIndexInfo( */ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; - int i; int rc; TRACE_IDX_INPUTS(p); @@ -953,12 +952,16 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ sqlite3_free(pVtab->zErrMsg); pVtab->zErrMsg = 0; +#if 0 + /* This error is now caught by the caller. + ** Search for "xBestIndex malfunction" below */ for(i=0; inConstraint; i++){ if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){ sqlite3ErrorMsg(pParse, "table %s: xBestIndex returned an invalid plan", pTab->zName); } } +#endif return pParse->nErr; } @@ -2835,9 +2838,10 @@ static int whereLoopAddVirtualOne( || j<0 || j>=pWC->nTerm || pNew->aLTerm[iTerm]!=0 + || pIdxCons->usable==0 ){ rc = SQLITE_ERROR; - sqlite3ErrorMsg(pParse,"%s.xBestIndex() malfunction",pSrc->pTab->zName); + sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName); return rc; } testcase( iTerm==nConstraint-1 ); @@ -2859,7 +2863,7 @@ static int whereLoopAddVirtualOne( ** together. */ pIdxInfo->orderByConsumed = 0; pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; - *pbIn = 1; + *pbIn = 1; assert( (mExclude & WO_IN)==0 ); } } } @@ -2972,10 +2976,11 @@ static int whereLoopAddVirtual( ** xBestIndex again, this time with IN(...) terms disabled. */ if( rc==SQLITE_OK && bIn ){ rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, WO_IN, p, &bIn); + assert( bIn==0 ); mBestNoIn = pNew->prereq & ~mPrereq; if( mBestNoIn==0 ){ seenZero = 1; - if( bIn==0 ) seenZeroNoIN = 1; + seenZeroNoIN = 1; } } diff --git a/test/vtab6.test b/test/vtab6.test index f8e0935a28..f4504b017d 100644 --- a/test/vtab6.test +++ b/test/vtab6.test @@ -566,12 +566,12 @@ do_test vtab6-11.4.1 { catchsql { SELECT a, b, c FROM ab NATURAL JOIN bc; } -} {1 {table ab: xBestIndex returned an invalid plan}} +} {1 {ab.xBestIndex malfunction}} do_test vtab6-11.4.2 { catchsql { SELECT a, b, c FROM bc NATURAL JOIN ab; } -} {1 {table bc: xBestIndex returned an invalid plan}} +} {1 {bc.xBestIndex malfunction}} unset ::echo_module_ignore_usable From 0dba3304f61cc07aac8e64421eec824db7792584 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Mar 2016 13:56:02 +0000 Subject: [PATCH 425/570] Fix comments on pager flag settings to include synchronous=EXTRA. FossilOrigin-Name: 3a65a1fc0fd2408c6984153801ec5dcd5211c897 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/pager.c | 9 +++++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 02f759a644..2807800e01 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplified\serror\sdetection\sin\sthe\sxBestIndex\sprocessing. -D 2016-03-08T02:59:33.371 +C Fix\scomments\son\spager\sflag\ssettings\sto\sinclude\ssynchronous=EXTRA. +D 2016-03-08T13:56:02.581 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -335,7 +335,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c f5bac8e74aaefc4ea520e43b4540793c3b8a9e8f F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c d40cf1e890a0582b6ac7cb208c24619d72d2c900 +F src/pager.c 17aa37b3b53a62a1bd98fe6f3c758bb41429ef08 F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df @@ -1454,7 +1454,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 91bd619d27e4d91510a187bbb88de961a31c8a2e -R 925559caeda122c2e0a2ca4fc28cc0ee +P 82ca2131b670505578628687746135ac413d156b +R 4e1de8a7b93ab084a5d8af152570ff89 U drh -Z b4b54118bbf4d13b5c60372c03985e73 +Z 8d271451485b418fda3cdda213f61b81 diff --git a/manifest.uuid b/manifest.uuid index 21eda15faa..9831ba312c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -82ca2131b670505578628687746135ac413d156b \ No newline at end of file +3a65a1fc0fd2408c6984153801ec5dcd5211c897 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index f045ce0eff..6cc6ebff42 100644 --- a/src/pager.c +++ b/src/pager.c @@ -3460,7 +3460,7 @@ void sqlite3PagerShrink(Pager *pPager){ ** The "level" in pgFlags & PAGER_SYNCHRONOUS_MASK sets the robustness ** of the database to damage due to OS crashes or power failures by ** changing the number of syncs()s when writing the journals. -** There are three levels: +** There are four levels: ** ** OFF sqlite3OsSync() is never called. This is the default ** for temporary and transient files. @@ -3480,6 +3480,10 @@ void sqlite3PagerShrink(Pager *pPager){ ** assurance that the journal will not be corrupted to the ** point of causing damage to the database during rollback. ** +** EXTRA This is like FULL except that is also syncs the directory +** that contains the rollback journal after the rollback +** journal is unlinked. +** ** The above is for a rollback-journal mode. For WAL mode, OFF continues ** to mean that no syncs ever occur. NORMAL means that the WAL is synced ** prior to the start of checkpoint and that the database file is synced @@ -3487,7 +3491,8 @@ void sqlite3PagerShrink(Pager *pPager){ ** was written back into the database. But no sync operations occur for ** an ordinary commit in NORMAL mode with WAL. FULL means that the WAL ** file is synced following each commit operation, in addition to the -** syncs associated with NORMAL. +** syncs associated with NORMAL. There is no difference between FULL +** and EXTRA for WAL mode. ** ** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL. The ** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync From 6702f761ea6e942b042952376e086c64b69d193a Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Mar 2016 14:16:23 +0000 Subject: [PATCH 426/570] Fix ATTACH to use the symbolic name PAGER_SYNCHRONOUS_FULL rather than an integer literal. FossilOrigin-Name: c4e192a0e5a408e198dbacb2752859a00d2b572f --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/attach.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 2807800e01..cff32735ef 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scomments\son\spager\sflag\ssettings\sto\sinclude\ssynchronous=EXTRA. -D 2016-03-08T13:56:02.581 +C Fix\sATTACH\sto\suse\sthe\ssymbolic\sname\sPAGER_SYNCHRONOUS_FULL\srather\sthan\nan\sinteger\sliteral. +D 2016-03-08T14:16:23.535 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -287,7 +287,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 1bb0709b3048e24217b80ec6bd78a3e99a47c01b F src/analyze.c ab57b6763dd4c6170a20673d14882c033affd188 -F src/attach.c a3724c64de1099d85e30751213d285752aed9505 +F src/attach.c 34b254f398339c5283f91684bff6d9b19a899255 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 @@ -1454,7 +1454,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 82ca2131b670505578628687746135ac413d156b -R 4e1de8a7b93ab084a5d8af152570ff89 +P 3a65a1fc0fd2408c6984153801ec5dcd5211c897 +R 713ccf93fbf940d5f93658dc674d69a8 U drh -Z 8d271451485b418fda3cdda213f61b81 +Z 60af40306ae0297078d0f487c0fa1cd6 diff --git a/manifest.uuid b/manifest.uuid index 9831ba312c..60ec4c1d29 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3a65a1fc0fd2408c6984153801ec5dcd5211c897 \ No newline at end of file +c4e192a0e5a408e198dbacb2752859a00d2b572f \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 484a5a110c..3101357113 100644 --- a/src/attach.c +++ b/src/attach.c @@ -161,7 +161,7 @@ static void attachFunc( #endif sqlite3BtreeLeave(aNew->pBt); } - aNew->safety_level = 3; + aNew->safety_level = PAGER_SYNCHRONOUS_FULL; aNew->zName = sqlite3DbStrDup(db, zName); if( rc==SQLITE_OK && aNew->zName==0 ){ rc = SQLITE_NOMEM_BKPT; From 50a1a5aaca05efe5682668e009146023b05688c9 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Mar 2016 14:40:11 +0000 Subject: [PATCH 427/570] Add compile-time options SQLITE_DEFAULT_SYNCHRONOUS and SQLITE_DEFAULT_WAL_SYNCHRONOUS used to specify the default synchronous settings for all database connections. FossilOrigin-Name: 1fefa967aa93372d232b96b1e0232b7b855d6d00 --- manifest | 21 ++++++++++++--------- manifest.uuid | 2 +- src/attach.c | 2 +- src/main.c | 2 +- src/pragma.c | 1 + src/sqliteInt.h | 11 ++++++++++- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index cff32735ef..63f123d486 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sATTACH\sto\suse\sthe\ssymbolic\sname\sPAGER_SYNCHRONOUS_FULL\srather\sthan\nan\sinteger\sliteral. -D 2016-03-08T14:16:23.535 +C Add\scompile-time\soptions\sSQLITE_DEFAULT_SYNCHRONOUS\sand\nSQLITE_DEFAULT_WAL_SYNCHRONOUS\sused\sto\sspecify\sthe\sdefault\ssynchronous\nsettings\sfor\sall\sdatabase\sconnections. +D 2016-03-08T14:40:11.978 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -287,7 +287,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 1bb0709b3048e24217b80ec6bd78a3e99a47c01b F src/analyze.c ab57b6763dd4c6170a20673d14882c033affd188 -F src/attach.c 34b254f398339c5283f91684bff6d9b19a899255 +F src/attach.c 3d23c66919305799201749c75cae4774a520d773 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 @@ -313,7 +313,7 @@ F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c 723d5d708cdb61bdd47c00b9f07c75be45aefc09 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f -F src/main.c 93c571d78bc41b257f36912e678db4817d3c540e +F src/main.c ae066482662f47b596ff5441c3efc8f6536761b8 F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -341,7 +341,7 @@ F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 -F src/pragma.c 42b3f1475b483710ba1dd1cc1ecc0c0f8db59a2e +F src/pragma.c c7061870c235702a513ce4152fe978faf3f282eb F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 @@ -353,7 +353,7 @@ F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 0235586b3fb639e85998d495c90f007657fd82af F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 4c7b8501b37eb768a5457b01cb9a9a5505f3fd85 +F src/sqliteInt.h fa49759aff49ab56eed9c0b4670895924b66aedb F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1454,7 +1454,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 3a65a1fc0fd2408c6984153801ec5dcd5211c897 -R 713ccf93fbf940d5f93658dc674d69a8 +P c4e192a0e5a408e198dbacb2752859a00d2b572f +R ed8cb54862c87c7000f2b5316b253427 +T *branch * default-synchronous +T *sym-default-synchronous * +T -sym-trunk * U drh -Z 60af40306ae0297078d0f487c0fa1cd6 +Z e2df223f431828867c29b052b714b5b9 diff --git a/manifest.uuid b/manifest.uuid index 60ec4c1d29..789760b567 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c4e192a0e5a408e198dbacb2752859a00d2b572f \ No newline at end of file +1fefa967aa93372d232b96b1e0232b7b855d6d00 \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 3101357113..30f6739bba 100644 --- a/src/attach.c +++ b/src/attach.c @@ -161,7 +161,7 @@ static void attachFunc( #endif sqlite3BtreeLeave(aNew->pBt); } - aNew->safety_level = PAGER_SYNCHRONOUS_FULL; + aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS; aNew->zName = sqlite3DbStrDup(db, zName); if( rc==SQLITE_OK && aNew->zName==0 ){ rc = SQLITE_NOMEM_BKPT; diff --git a/src/main.c b/src/main.c index e4252e7aa9..fd74c97e29 100644 --- a/src/main.c +++ b/src/main.c @@ -2878,7 +2878,7 @@ static int openDatabase( ** database it is OFF. This matches the pager layer defaults. */ db->aDb[0].zName = "main"; - db->aDb[0].safety_level = PAGER_SYNCHRONOUS_FULL; + db->aDb[0].safety_level = SQLITE_DEFAULT_SYNCHRONOUS; db->aDb[1].zName = "temp"; db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF; diff --git a/src/pragma.c b/src/pragma.c index 1d62914310..883ab60c67 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -993,6 +993,7 @@ void sqlite3Pragma( int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK; if( iLevel==0 ) iLevel = 1; pDb->safety_level = iLevel; + pDb->bSyncSet = 1; setAllPagerFlags(db); } } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ff4dbd4864..a49601e748 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1002,10 +1002,18 @@ typedef struct With With; #include "vdbe.h" #include "pager.h" #include "pcache.h" - #include "os.h" #include "mutex.h" +/* +** Default synchronous levels +*/ +#ifndef SQLITE_DEFAULT_SYNCHRONOUS +# define SQLITE_DEFAULT_SYNCHRONOUS PAGER_SYNCHRONOUS_FULL +#endif +#ifndef SQLITE_DEFAULT_WAL_SYNCHRONOUS +# define SQLITE_DEFAULT_WAL_SYNCHRONOUS SQLITE_DEFAULT_SYNCHRONOUS +#endif /* ** Each database file to be accessed by the system is an instance @@ -1018,6 +1026,7 @@ struct Db { char *zName; /* Name of this database */ Btree *pBt; /* The B*Tree structure for this database file */ u8 safety_level; /* How aggressive at syncing data to disk */ + u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */ Schema *pSchema; /* Pointer to database schema (possibly shared) */ }; From e243de5cf51f5799d91b4b9fc7c22800dcfe3a78 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Mar 2016 15:14:26 +0000 Subject: [PATCH 428/570] If SQLITE_DEFAULT_WAL_SYNCHRONOUS is not the same value as SQLITE_DEFAULT_SYNCHRONOUS and the application has not run "PRAGMA synchronous", then set synchronous to the SQLITE_DEFAULT_WAL_SYNCHRONOUS setting when entering WAL mode for the first time. FossilOrigin-Name: 5791407b523abd24e832fc2361b3e9f01ee2f36a --- manifest | 21 +++++++++------------ manifest.uuid | 2 +- src/btree.c | 22 +++++++++++++++++++--- test/unixexcl.test | 1 + test/wal2.test | 2 +- test/zerodamage.test | 1 + 6 files changed, 32 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index 63f123d486..64534b8ae9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\scompile-time\soptions\sSQLITE_DEFAULT_SYNCHRONOUS\sand\nSQLITE_DEFAULT_WAL_SYNCHRONOUS\sused\sto\sspecify\sthe\sdefault\ssynchronous\nsettings\sfor\sall\sdatabase\sconnections. -D 2016-03-08T14:40:11.978 +C If\sSQLITE_DEFAULT_WAL_SYNCHRONOUS\sis\snot\sthe\ssame\svalue\sas\nSQLITE_DEFAULT_SYNCHRONOUS\sand\sthe\sapplication\shas\snot\srun\n"PRAGMA\ssynchronous",\sthen\sset\ssynchronous\sto\sthe\s\nSQLITE_DEFAULT_WAL_SYNCHRONOUS\ssetting\swhen\sentering\sWAL\smode\sfor\nthe\sfirst\stime. +D 2016-03-08T15:14:26.164 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -292,7 +292,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 7bb920c473c277380fcb3e8a8ee28ce1a48e0abc +F src/btree.c be3ac34a9d669fed0e0b315e4b62fb198b3534a1 F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 43b93fe757bfffe00f97462596418b052eefdccd @@ -1268,7 +1268,7 @@ F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84 F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264 F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2 -F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825 +F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97 F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8 F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32 F test/uri.test 6630ecbdea2aac10df3c89dbae2243f4c2c353e4 @@ -1302,7 +1302,7 @@ F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad F test/wal.test 0148c8b3421a25fdb4d9c160e84a681d0646371b -F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada +F test/wal2.test 25ae059e900dbb584e0775627e45415ba5940df1 F test/wal3.test 5dd734147f1f8f958c5261a1f2775d346d7013ce F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c F test/wal5.test 88b5d9a6a3d1532497ee9f4296f010d66f07e33c @@ -1368,7 +1368,7 @@ F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e F test/wordcount.c 2a0a6c0d0e8e8bbbac1f06d72a6791828c37c0cf F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa -F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac +F test/zerodamage.test 2d725c214b883e25ae6bb85ef228ecdfa03c6a7b F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372 F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91 @@ -1454,10 +1454,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 c4e192a0e5a408e198dbacb2752859a00d2b572f -R ed8cb54862c87c7000f2b5316b253427 -T *branch * default-synchronous -T *sym-default-synchronous * -T -sym-trunk * +P 1fefa967aa93372d232b96b1e0232b7b855d6d00 +R 96b74d7d7452050d9fb3b3bb7ed48b9b U drh -Z e2df223f431828867c29b052b714b5b9 +Z fb25535cfc55b70029b29a9169aa4b7e diff --git a/manifest.uuid b/manifest.uuid index 789760b567..1546aa7117 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1fefa967aa93372d232b96b1e0232b7b855d6d00 \ No newline at end of file +5791407b523abd24e832fc2361b3e9f01ee2f36a \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 036e63a016..bc16cbedd4 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2864,9 +2864,25 @@ static int lockBtree(BtShared *pBt){ rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen); if( rc!=SQLITE_OK ){ goto page1_init_failed; - }else if( isOpen==0 ){ - releasePage(pPage1); - return SQLITE_OK; + }else{ +#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS + sqlite3 *db; + Db *pDb; + if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){ + while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; } + if( pDb->bSyncSet==0 + && pDb->safety_level==SQLITE_DEFAULT_SYNCHRONOUS + ){ + pDb->safety_level = SQLITE_DEFAULT_WAL_SYNCHRONOUS; + sqlite3PagerSetFlags(pBt->pPager, + pDb->safety_level | (db->flags & PAGER_FLAGS_MASK)); + } + } +#endif + if( isOpen==0 ){ + releasePage(pPage1); + return SQLITE_OK; + } } rc = SQLITE_NOTADB; } diff --git a/test/unixexcl.test b/test/unixexcl.test index d6762178dd..8e9c4644d1 100644 --- a/test/unixexcl.test +++ b/test/unixexcl.test @@ -87,6 +87,7 @@ do_multiclient_test tn { sql1 { PRAGMA auto_vacuum = 0; PRAGMA journal_mode = WAL; + PRAGMA synchronous = FULL; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); } diff --git a/test/wal2.test b/test/wal2.test index 9d45444d6a..4b9bbf315f 100644 --- a/test/wal2.test +++ b/test/wal2.test @@ -1196,7 +1196,7 @@ foreach {tn sql reslist} { } { faultsim_delete_and_reopen - execsql {PRAGMA auto_vacuum = 0} + execsql {PRAGMA auto_vacuum = 0; PRAGMA synchronous = FULL;} execsql $sql do_execsql_test wal2-14.$tn.0 { PRAGMA page_size = 4096 } {} do_execsql_test wal2-14.$tn.1 { PRAGMA journal_mode = WAL } {wal} diff --git a/test/zerodamage.test b/test/zerodamage.test index dccaba816e..d781ab89a3 100644 --- a/test/zerodamage.test +++ b/test/zerodamage.test @@ -112,6 +112,7 @@ ifcapable wal { db close sqlite3 db file:test.db?psow=FALSE -uri 1 db eval { + PRAGMA synchronous=FULL; UPDATE t1 SET y=randomblob(50) WHERE x=124; } file size test.db-wal From c2ae2073d93f0cd0c85cd7adddbaacd5b622cac1 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Mar 2016 15:30:01 +0000 Subject: [PATCH 429/570] Make the SQLITE_DEFAULT_SYNCHRONOUS and SQLITE_DEFAULT_WAL_SYNCHRONOUS values zero-based to agree with PRAGMA synchronous. FossilOrigin-Name: 592d2104361500e5002783ba329a2609389c57b9 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/attach.c | 2 +- src/btree.c | 4 ++-- src/main.c | 2 +- src/sqliteInt.h | 17 +++++++++++++++-- 6 files changed, 29 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 64534b8ae9..f00f793ab6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\sSQLITE_DEFAULT_WAL_SYNCHRONOUS\sis\snot\sthe\ssame\svalue\sas\nSQLITE_DEFAULT_SYNCHRONOUS\sand\sthe\sapplication\shas\snot\srun\n"PRAGMA\ssynchronous",\sthen\sset\ssynchronous\sto\sthe\s\nSQLITE_DEFAULT_WAL_SYNCHRONOUS\ssetting\swhen\sentering\sWAL\smode\sfor\nthe\sfirst\stime. -D 2016-03-08T15:14:26.164 +C Make\sthe\sSQLITE_DEFAULT_SYNCHRONOUS\sand\sSQLITE_DEFAULT_WAL_SYNCHRONOUS\nvalues\szero-based\sto\sagree\swith\sPRAGMA\ssynchronous. +D 2016-03-08T15:30:01.003 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -287,12 +287,12 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 1bb0709b3048e24217b80ec6bd78a3e99a47c01b F src/analyze.c ab57b6763dd4c6170a20673d14882c033affd188 -F src/attach.c 3d23c66919305799201749c75cae4774a520d773 +F src/attach.c 771153bd1f4ab0b97a44a13dde2c7e5e1efeba22 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c be3ac34a9d669fed0e0b315e4b62fb198b3534a1 +F src/btree.c 2712f087351f5c4ff0e71631b1e67b461611b99d F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 43b93fe757bfffe00f97462596418b052eefdccd @@ -313,7 +313,7 @@ F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c 723d5d708cdb61bdd47c00b9f07c75be45aefc09 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f -F src/main.c ae066482662f47b596ff5441c3efc8f6536761b8 +F src/main.c 29ea8ebb23ceb5159da167e18d5c807fbb1545c4 F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -353,7 +353,7 @@ F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 0235586b3fb639e85998d495c90f007657fd82af F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h fa49759aff49ab56eed9c0b4670895924b66aedb +F src/sqliteInt.h b017fbf491606a0fd1a5d43af40dbe965a928ead F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1454,7 +1454,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 1fefa967aa93372d232b96b1e0232b7b855d6d00 -R 96b74d7d7452050d9fb3b3bb7ed48b9b +P 5791407b523abd24e832fc2361b3e9f01ee2f36a +R bba2e4d185d472ce58e719fcfcf03f67 U drh -Z fb25535cfc55b70029b29a9169aa4b7e +Z 6f7df0629a8472a1465e8e2960a9953c diff --git a/manifest.uuid b/manifest.uuid index 1546aa7117..ba3ff1f350 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5791407b523abd24e832fc2361b3e9f01ee2f36a \ No newline at end of file +592d2104361500e5002783ba329a2609389c57b9 \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 30f6739bba..ea378a40a2 100644 --- a/src/attach.c +++ b/src/attach.c @@ -161,7 +161,7 @@ static void attachFunc( #endif sqlite3BtreeLeave(aNew->pBt); } - aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS; + aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; aNew->zName = sqlite3DbStrDup(db, zName); if( rc==SQLITE_OK && aNew->zName==0 ){ rc = SQLITE_NOMEM_BKPT; diff --git a/src/btree.c b/src/btree.c index bc16cbedd4..4b9bba55ac 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2871,9 +2871,9 @@ static int lockBtree(BtShared *pBt){ if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){ while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; } if( pDb->bSyncSet==0 - && pDb->safety_level==SQLITE_DEFAULT_SYNCHRONOUS + && pDb->safety_level==SQLITE_DEFAULT_SYNCHRONOUS+1 ){ - pDb->safety_level = SQLITE_DEFAULT_WAL_SYNCHRONOUS; + pDb->safety_level = SQLITE_DEFAULT_WAL_SYNCHRONOUS+1; sqlite3PagerSetFlags(pBt->pPager, pDb->safety_level | (db->flags & PAGER_FLAGS_MASK)); } diff --git a/src/main.c b/src/main.c index fd74c97e29..70e46a4ee1 100644 --- a/src/main.c +++ b/src/main.c @@ -2878,7 +2878,7 @@ static int openDatabase( ** database it is OFF. This matches the pager layer defaults. */ db->aDb[0].zName = "main"; - db->aDb[0].safety_level = SQLITE_DEFAULT_SYNCHRONOUS; + db->aDb[0].safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; db->aDb[1].zName = "temp"; db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a49601e748..741caec3e3 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1006,10 +1006,23 @@ typedef struct With With; #include "mutex.h" /* -** Default synchronous levels +** Default synchronous levels. +** +** Note that (for historcal reasons) the PAGER_SYNCHRONOUS_* macros differ +** from the SQLITE_DEFAULT_SYNCHRONOUS value by 1. +** +** PAGER_SYNCHRONOUS DEFAULT_SYNCHRONOUS +** OFF 1 0 +** NORMAL 2 1 +** FULL 3 2 +** EXTRA 4 3 +** +** The "PRAGMA synchronous" statement also uses the zero-based numbers. +** In other words, the zero-based numbers are used for all external interfaces +** and the one-based values are used internally. */ #ifndef SQLITE_DEFAULT_SYNCHRONOUS -# define SQLITE_DEFAULT_SYNCHRONOUS PAGER_SYNCHRONOUS_FULL +# define SQLITE_DEFAULT_SYNCHRONOUS (PAGER_SYNCHRONOUS_FULL-1) #endif #ifndef SQLITE_DEFAULT_WAL_SYNCHRONOUS # define SQLITE_DEFAULT_WAL_SYNCHRONOUS SQLITE_DEFAULT_SYNCHRONOUS From c7dbce0f2a533a146ea556523e433e6f042c5334 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 8 Mar 2016 15:37:48 +0000 Subject: [PATCH 430/570] Update fts3/4 so that the 'merge=X,Y' command merges at least, instead of exactly, Y segments from a single level. This matches the documentation. 'merge=X,0' is, as it was in 3.11, an error. FossilOrigin-Name: 64b3cb29159491cbfab7e01844b54408541ece5e --- ext/fts3/fts3_write.c | 9 +++------ manifest | 26 +++++++++++++------------- manifest.uuid | 2 +- test/backcompat.test | 10 ++++++++-- test/fts4growth.test | 40 ++++++++++++++++++++++------------------ test/fts4langid.test | 2 +- test/fts4merge.test | 25 ++++++++----------------- test/fts4merge3.test | 6 +++--- test/fts4opt.test | 4 ++-- 9 files changed, 61 insertions(+), 63 deletions(-) diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index 6a2299fccf..24039aef30 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -4840,11 +4840,8 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ sqlite3_bind_int(pFindLevel, 1, MAX(2, nMin)); if( sqlite3_step(pFindLevel)==SQLITE_ROW ){ iAbsLevel = sqlite3_column_int64(pFindLevel, 0); - if( nMin<2 ){ - nSeg = sqlite3_column_int(pFindLevel, 1); - }else{ - nSeg = nMin; - } + nSeg = sqlite3_column_int(pFindLevel, 1); + assert( nSeg>=2 ); }else{ nSeg = -1; } @@ -4996,7 +4993,7 @@ static int fts3DoIncrmerge( nMin = fts3Getint(&z); } - if( z[0]!='\0' || nMin<0 || nMin==1 ){ + if( z[0]!='\0' || nMin<2 ){ rc = SQLITE_ERROR; }else{ rc = SQLITE_OK; diff --git a/manifest b/manifest index cff32735ef..27e5d3a87d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sATTACH\sto\suse\sthe\ssymbolic\sname\sPAGER_SYNCHRONOUS_FULL\srather\sthan\nan\sinteger\sliteral. -D 2016-03-08T14:16:23.535 +C Update\sfts3/4\sso\sthat\sthe\s'merge=X,Y'\scommand\smerges\sat\sleast,\sinstead\sof\sexactly,\sY\ssegments\sfrom\sa\ssingle\slevel.\sThis\smatches\sthe\sdocumentation.\s'merge=X,0'\sis,\sas\sit\swas\sin\s3.11,\san\serror. +D 2016-03-08T15:37:48.202 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -88,7 +88,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145 F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057 -F ext/fts3/fts3_write.c f56345c64387ca30bf91b91511082fa83d9b5178 +F ext/fts3/fts3_write.c fb0456fa1407758f82458417c76fe4b06c86be98 F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/fts3/tool/fts3view.c 5d78b668f4e9598af9147f8999632599fb0d9dd5 @@ -482,7 +482,7 @@ F test/autoindex5.test 96f084a5e6024ea07cace5888df3223f3ea86990 F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74 F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4 F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85 -F test/backcompat.test 19a1f337c68419b020a7481dd272a472c4ad8ef4 +F test/backcompat.test 28403f43d11624e696c5ef134c7c7d81015cd19e F test/backup.test b79299a536a4c6d919094786595b95be56d02014 F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf F test/backup4.test 2a2e4a64388090b152de753fd9e123f28f6a3bd4 @@ -744,17 +744,17 @@ F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb F test/fts4check.test c3056eab9524232e4c9bdcd119912947e07bcc1c F test/fts4content.test 05716af19a899cd70d5cd916c580043c03f30db4 F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01 -F test/fts4growth.test 60d6bb3f78e25b34f533797dd9f2f9402310a13a +F test/fts4growth.test e5390da74619cacc389711bac9349640b32c4f9a F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269 F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d -F test/fts4langid.test 9794addcc8faaee85ac60eceecdb52feb0c70f68 -F test/fts4merge.test 146563df4a90ccb7f111a6e11ab29bbfe9e6ce2c +F test/fts4langid.test 65a7332c9bc257919e259a304aa8a38c41655b9d +F test/fts4merge.test d2b39f6b1bd4a9738a13540e2d044cba11c43d47 F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891 -F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7 +F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0 F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309 F test/fts4onepass.test 7319d61a2ed1325fc54afd0c060a0513b462303a -F test/fts4opt.test f15c84305c4b78c665fc476d8569e27ab9a0d418 +F test/fts4opt.test 1901f696214c4e16a995dd7fdd70576fc5c41dbe F test/fts4unicode.test 27378af76394542cf490cf001d8d1505fe55f6a9 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef @@ -1454,7 +1454,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 3a65a1fc0fd2408c6984153801ec5dcd5211c897 -R 713ccf93fbf940d5f93658dc674d69a8 -U drh -Z 60af40306ae0297078d0f487c0fa1cd6 +P c4e192a0e5a408e198dbacb2752859a00d2b572f +R 3e8d6ecab7b420c32f9b7a175d510e4d +U dan +Z 45820e8758a67cfc47c6d8f8a214769a diff --git a/manifest.uuid b/manifest.uuid index 60ec4c1d29..5eb2c62ef9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c4e192a0e5a408e198dbacb2752859a00d2b572f \ No newline at end of file +64b3cb29159491cbfab7e01844b54408541ece5e \ No newline at end of file diff --git a/test/backcompat.test b/test/backcompat.test index ea7e6a9eed..fe8a83f0a6 100644 --- a/test/backcompat.test +++ b/test/backcompat.test @@ -63,7 +63,7 @@ proc do_backcompat_test {rv bin1 bin2 script} { set v [split [db version] .] if {[llength $v]==3} {lappend v 0} set ::sqlite_libversion [format \ - "%d%.2d%.2d%2d" [lindex $v 0] [lindex $v 1] [lindex $v 2] [lindex $v 3] + "%d%.2d%.2d%.2d" [lindex $v 0] [lindex $v 1] [lindex $v 2] [lindex $v 3] ] } } @@ -420,6 +420,12 @@ ifcapable fts3 { if {[code1 { set ::sqlite_libversion }] >=3071200 && [code2 { set ::sqlite_libversion }] >=3071200 } { + if {[code1 { set ::sqlite_libversion }]<3120000} { + set res {0 {0 1} 1 0} + } else { + set res {1 0} + } + do_test backcompat-3.9 { sql1 { INSERT INTO t2(t2) VALUES('merge=100,4'); } sql2 { INSERT INTO t2(t2) VALUES('merge=100,4'); } @@ -428,7 +434,7 @@ ifcapable fts3 { sql2 { SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level; } - } {0 {0 1} 1 0} + } $res do_test backcompat-3.10 { sql1 { INSERT INTO t2(t2) VALUES('integrity-check') } diff --git a/test/fts4growth.test b/test/fts4growth.test index e4b5f19ecb..4dc2212464 100644 --- a/test/fts4growth.test +++ b/test/fts4growth.test @@ -59,11 +59,11 @@ do_test 1.4 { INSERT INTO x1(x1) VALUES('merge=4,4'); SELECT level, end_block, length(root) FROM x1_segdir; } -} {0 {0 110} 110 0 {0 132} 132 0 {0 129} 129 1 {128 658} 2} +} {1 {224 921} 2} do_execsql_test 1.5 { SELECT length(block) FROM x1_segments; -} {658 {}} +} {921 {}} do_test 1.6 { foreach L { @@ -71,27 +71,33 @@ do_test 1.6 { {That perched above Dead Man's Creek, beside the mountain road.} {He turned the cycle down the hill and mounted for the fray,} {But 'ere he'd gone a dozen yards it bolted clean away.} + {It left the track, and through the trees, just like a silver steak,} {It whistled down the awful slope towards the Dead Man's Creek.} {It shaved a stump by half an inch, it dodged a big white-box:} {The very wallaroos in fright went scrambling up the rocks,} + {The wombats hiding in their caves dug deeper underground,} {As Mulga Bill, as white as chalk, sat tight to every bound.} {It struck a stone and gave a spring that cleared a fallen tree,} {It raced beside a precipice as close as close could be;} + {And then as Mulga Bill let out one last despairing shriek} {It made a leap of twenty feet into the Dead Man's Creek.} + {It shaved a stump by half an inch, it dodged a big white-box:} + {The very wallaroos in fright went scrambling up the rocks,} + {The wombats hiding in their caves dug deeper underground,} } { execsql { INSERT INTO x1 VALUES($L) } } execsql { SELECT level, end_block, length(root) FROM x1_segdir; } -} {1 {128 658} 2 1 {130 1377} 6 0 {0 117} 117} +} {1 {224 921} 2 1 {226 1230} 7 0 {0 98} 98} do_execsql_test 1.7 { - SELECT sum(length(block)) FROM x1_segments WHERE blockid IN (129, 130); -} {1377} + SELECT sum(length(block)) FROM x1_segments WHERE blockid IN (224,225,226) +} {1230} #------------------------------------------------------------------------- # @@ -131,24 +137,24 @@ do_execsql_test 2.5 { SELECT end_block FROM x2_segdir WHERE level=3; INSERT INTO x2(x2) VALUES('merge=4,4'); SELECT end_block FROM x2_segdir WHERE level=3; -} {{3828 -3430} {3828 -10191} {3828 -14109}} +} {{5588 -3950} {5588 -11766} {5588 -15541}} do_execsql_test 2.6 { SELECT sum(length(block)) FROM x2_segdir, x2_segments WHERE blockid BETWEEN start_block AND leaves_end_block AND level=3 -} {14109} +} {15541} do_execsql_test 2.7 { INSERT INTO x2(x2) VALUES('merge=1000,4'); SELECT end_block FROM x2_segdir WHERE level=3; -} {{3828 86120}} +} {{5588 127563}} do_execsql_test 2.8 { SELECT sum(length(block)) FROM x2_segdir, x2_segments WHERE blockid BETWEEN start_block AND leaves_end_block AND level=3 -} {86120} +} {127563} #-------------------------------------------------------------------------- # Test that delete markers are removed from FTS segments when possible. @@ -391,7 +397,7 @@ do_execsql_test 7.2 { } { 0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006} 0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006} - 1 0 {16014 -51226} + 1 0 {23694 -69477} } do_execsql_test 7.3 { @@ -400,7 +406,7 @@ do_execsql_test 7.3 { } { 0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006} 0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006} - 1 0 16014 + 1 0 23694 } do_execsql_test 7.4 { @@ -409,28 +415,26 @@ do_execsql_test 7.4 { } { 0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006} 0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006} - 1 0 16014 + 1 0 23694 } do_execsql_test 7.5 { INSERT INTO x6(x6) VALUES('merge=2500,4'); - SELECT level, idx, end_block FROM x6_segdir; + SELECT level, idx, start_block, leaves_end_block, end_block FROM x6_segdir; } { - 0 0 {598 118006} 0 1 {718 118006} 1 0 16014 + 1 0 719 1171 23694 } do_execsql_test 7.6 { INSERT INTO x6(x6) VALUES('merge=2500,2'); SELECT level, idx, start_block, leaves_end_block, end_block FROM x6_segdir; } { - 2 0 23695 24147 {41262 633507} + 1 0 719 1171 23694 } do_execsql_test 7.7 { SELECT sum(length(block)) FROM x6_segments - WHERE blockid BETWEEN 23695 AND 24147 -} {633507} - +} {635247} finish_test diff --git a/test/fts4langid.test b/test/fts4langid.test index eb3602b4b8..fdb1876be8 100644 --- a/test/fts4langid.test +++ b/test/fts4langid.test @@ -481,6 +481,6 @@ foreach lid [list 4 [expr 1<<30]] { do_execsql_test 5.4.$lid.5 { SELECT count(*) FROM t6_segdir; SELECT count(*) FROM t6_segments; - } {4 4} + } {1 2} } finish_test diff --git a/test/fts4merge.test b/test/fts4merge.test index 41f91fdc8f..eac18311d3 100644 --- a/test/fts4merge.test +++ b/test/fts4merge.test @@ -55,8 +55,6 @@ foreach mod {fts3 fts4} { do_execsql_test 1.3 { SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level } { - 0 {0 1 2 3} - 1 {0 1 2 3 4 5 6} 2 {0 1 2 3} } @@ -71,7 +69,6 @@ foreach mod {fts3 fts4} { do_execsql_test 1.5 { SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level } { - 2 {0 1} 3 0 } @@ -118,11 +115,7 @@ foreach mod {fts3 fts4} { INSERT INTO t2(t2) VALUES('merge=1000000,2'); SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level } { - 0 0 - 2 0 - 3 0 4 0 - 6 0 } #------------------------------------------------------------------------- @@ -202,28 +195,27 @@ foreach mod {fts3 fts4} { INSERT INTO t1(t1) VALUES('merge=1,5'); SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level; } { - 0 {0 1 2} 1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14} 2 {0 1 2 3} } - do_execsql_test 5.4 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'0105'} + do_execsql_test 5.4 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'010F'} do_test 5.5 { foreach docid [execsql {SELECT docid FROM t1}] { execsql {INSERT INTO t1 SELECT * FROM t1 WHERE docid=$docid} } } {} - do_execsql_test 5.6 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'0105'} + do_execsql_test 5.6 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'010F'} do_execsql_test 5.7 { SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level; SELECT quote(value) from t1_stat WHERE rowid=1; } { - 0 {0 1 2 3 4 5 6 7 8 9 10} + 0 {0 1 2 3 4 5 6 7} 1 {0 1 2 3 4 5 6 7 8 9 10 11 12} - 2 {0 1 2 3 4 5 6 7} - X'0105' + 2 {0 1 2 3 4 5 6 7} + X'010F' } do_execsql_test 5.8 { @@ -232,9 +224,8 @@ foreach mod {fts3 fts4} { SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level; SELECT quote(value) from t1_stat WHERE rowid=1; } { - 0 {0 1 2 3 4} 1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13} - 2 {0 1 2 3 4 5 6 7 8} X'0106' + 2 {0 1 2 3 4 5 6 7 8} X'010E' } do_test 5.8.1 { fts3_integrity_check t1 } ok @@ -252,7 +243,7 @@ foreach mod {fts3 fts4} { SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level; SELECT quote(value) from t1_stat WHERE rowid=1; } { - 0 0 1 {0 1} 2 0 3 0 X'0106' + 0 {0 1 2 3 4 5 6 7 8 9 10 11} 1 0 2 0 3 0 X'010E' } do_execsql_test 5.11 { @@ -260,7 +251,7 @@ foreach mod {fts3 fts4} { SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level; SELECT quote(value) from t1_stat WHERE rowid=1; } { - 0 0 1 {0 1} 2 0 3 0 X'' + 1 {0 1} 2 0 3 0 X'010E' } #------------------------------------------------------------------------- diff --git a/test/fts4merge3.test b/test/fts4merge3.test index 329b4d2cc4..08b68b97d9 100644 --- a/test/fts4merge3.test +++ b/test/fts4merge3.test @@ -62,7 +62,7 @@ do_all_bc_test { do_test 1.7 { sql2 { SELECT level, count(*) FROM t2_segdir GROUP BY level ORDER BY 1 - } } [list 0 1 2 18 3 5] + } } {2 15 3 5} # Using the old connection, insert many rows. do_test 1.8 { @@ -73,7 +73,7 @@ do_all_bc_test { do_test 1.9 { sql2 { SELECT level, count(*) FROM t2_segdir GROUP BY level ORDER BY 1 - } } [list 0 13 1 13 2 5 3 6] + } } [list 0 12 1 13 2 4 3 6] # Run a big incr-merge operation on the db. do_test 1.10 { sql1 { INSERT INTO t2(t2) VALUES('merge=2000,2') } } {} @@ -97,7 +97,7 @@ do_all_bc_test { do_test 1.15 { sql2 { SELECT level, count(*) FROM t2_segdir GROUP BY level ORDER BY 1 - } } {6 1} + } } {4 1} } } diff --git a/test/fts4opt.test b/test/fts4opt.test index 5638aff1b1..1933c57b1b 100644 --- a/test/fts4opt.test +++ b/test/fts4opt.test @@ -92,7 +92,7 @@ do_execsql_test 1.5 { do_test 1.6 { while 1 { set tc1 [db total_changes] - execsql { INSERT INTO t2(t2) VALUES('merge=5,0') } + execsql { INSERT INTO t2(t2) VALUES('merge=5,2') } set tc2 [db total_changes] if {($tc2 - $tc1) < 2} break } @@ -153,7 +153,7 @@ do_execsql_test 2.5 { do_test 2.6 { while 1 { set tc1 [db total_changes] - execsql { INSERT INTO t2(t2) VALUES('merge=5,0') } + execsql { INSERT INTO t2(t2) VALUES('merge=5,2') } set tc2 [db total_changes] if {($tc2 - $tc1) < 2} break } From 15d36c603d51a64aa161458a25183363fe0b1c72 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Mar 2016 16:02:37 +0000 Subject: [PATCH 431/570] Remove an unused goto label in the RBU extension. FossilOrigin-Name: 2179a106e8dd7943d4f37093e65ce7826720904e --- ext/rbu/sqlite3rbu.c | 2 -- manifest | 15 +++++++-------- manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index 7f27399988..474e39fe8d 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -2677,8 +2677,6 @@ static int rbuStep(sqlite3rbu *p){ } } } - - step_out: return p->rc; } diff --git a/manifest b/manifest index 95a229990c..f93e9c0c2c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\snew\srow\stype\sto\sRBU\s(a\speer\sof\sinsert,\supdate\sand\sdelete)\s-\s"delete\sthen\sinsert". -D 2016-03-08T15:52:43.903 +C Remove\san\sunused\sgoto\slabel\sin\sthe\sRBU\sextension. +D 2016-03-08T16:02:37.304 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -242,7 +242,7 @@ F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 -F ext/rbu/sqlite3rbu.c 0d901d773bf4c9e7d101daaf545263044e7e6615 +F ext/rbu/sqlite3rbu.c 5956f8bee63b5ab2b04e65c1801ea0f5920dac92 F ext/rbu/sqlite3rbu.h 0bdeb3be211aaba7d85445fa36f4701a25a3dbde F ext/rbu/test_rbu.c 4a4cdcef4ef9379fc2a21f008805c80b27bcf573 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 @@ -1455,8 +1455,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 5a847a676e756bbe33436596d4279f339bfb247c 169311c85b30f625bdb6986c9cd11db70942d73b -R 43c0b748ba126143d737a43b13d0c445 -T +closed 169311c85b30f625bdb6986c9cd11db70942d73b -U dan -Z 99ed19537580c1e7328c1d8043178b0a +P 1d9468d2427d2c9b7240b364554ac85a0b62fa44 +R 45c0cb408cd3189b0d141b544c4ab247 +U drh +Z 224db619cbf5201e3fc07a0cf6e997b5 diff --git a/manifest.uuid b/manifest.uuid index e6281cbd82..ad37f3bd4b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1d9468d2427d2c9b7240b364554ac85a0b62fa44 \ No newline at end of file +2179a106e8dd7943d4f37093e65ce7826720904e \ No newline at end of file From 33b104af0849a0d820b041c6200e1d93b37ae7ab Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Mar 2016 16:07:59 +0000 Subject: [PATCH 432/570] Drop support for SQLITE_EXTRA_DURABLE. The new SQLITE_DEFAULT_SYNCHRONOUS compile-time option is a more general replacement. FossilOrigin-Name: f6d3156ba9af1da517dd77c1df03fa7869888463 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/pager.c | 17 ----------------- src/sqliteInt.h | 8 ++++++++ 4 files changed, 16 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index f93e9c0c2c..40a77bc19a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunused\sgoto\slabel\sin\sthe\sRBU\sextension. -D 2016-03-08T16:02:37.304 +C Drop\ssupport\sfor\sSQLITE_EXTRA_DURABLE.\s\sThe\snew\sSQLITE_DEFAULT_SYNCHRONOUS\ncompile-time\soption\sis\sa\smore\sgeneral\sreplacement. +D 2016-03-08T16:07:59.373 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -336,7 +336,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c f5bac8e74aaefc4ea520e43b4540793c3b8a9e8f F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c 17aa37b3b53a62a1bd98fe6f3c758bb41429ef08 +F src/pager.c 2d950142528e5d9b291a1160443d7ade0d90700d F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df @@ -354,7 +354,7 @@ F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 0235586b3fb639e85998d495c90f007657fd82af F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h b017fbf491606a0fd1a5d43af40dbe965a928ead +F src/sqliteInt.h 24e2eed36a68d48bd43d866adb528001b0795275 F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1455,7 +1455,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 1d9468d2427d2c9b7240b364554ac85a0b62fa44 -R 45c0cb408cd3189b0d141b544c4ab247 +P 2179a106e8dd7943d4f37093e65ce7826720904e +R 82b2467863d1f8153e3f75a5d4f56472 U drh -Z 224db619cbf5201e3fc07a0cf6e997b5 +Z ded4eae64cbc81643a193c9cf7561702 diff --git a/manifest.uuid b/manifest.uuid index ad37f3bd4b..d7438755d1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2179a106e8dd7943d4f37093e65ce7826720904e \ No newline at end of file +f6d3156ba9af1da517dd77c1df03fa7869888463 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 6cc6ebff42..316a5e8ec0 100644 --- a/src/pager.c +++ b/src/pager.c @@ -428,19 +428,6 @@ int sqlite3PagerTrace=1; /* True to enable tracing */ */ #define MAX_SECTOR_SIZE 0x10000 -/* -** If the option SQLITE_EXTRA_DURABLE option is set at compile-time, then -** SQLite will do extra fsync() operations when synchronous==FULL to help -** ensure that transactions are durable across a power failure. Most -** applications are happy as long as transactions are consistent across -** a power failure, and are perfectly willing to lose the last transaction -** in exchange for the extra performance of avoiding directory syncs. -** And so the default SQLITE_EXTRA_DURABLE setting is off. -*/ -#ifndef SQLITE_EXTRA_DURABLE -# define SQLITE_EXTRA_DURABLE 0 -#endif - /* ** An instance of the following structure is allocated for each active @@ -4823,11 +4810,7 @@ act_like_temp_file: assert( pPager->ckptSyncFlags==0 ); }else{ pPager->fullSync = 1; -#if SQLITE_EXTRA_DURABLE - pPager->extraSync = 1; -#else pPager->extraSync = 0; -#endif pPager->syncFlags = SQLITE_SYNC_NORMAL; pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS; pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 741caec3e3..350832a2e7 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1005,6 +1005,14 @@ typedef struct With With; #include "os.h" #include "mutex.h" +/* The SQLITE_EXTRA_DURABLE compile-time option used to set the default +** synchronous setting to EXTRA. It is no longer supported. +*/ +#ifdef SQLITE_EXTRA_DURABLE +# warning Use SQLITE_DEFAULT_SYNCHRONOUS=3 instead of SQLITE_EXTRA_DURABLE +# define SQLITE_DEFAULT_SYNCHRONOUS 3 +#endif + /* ** Default synchronous levels. ** From 7ed4020890fbcc93dbf09a7ee75ab600355a9097 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 8 Mar 2016 17:44:08 +0000 Subject: [PATCH 433/570] Modify the memjournal.c code to make it a bit smaller. FossilOrigin-Name: d99ac4154812065eef26c298de52954d7ee0bd75 --- manifest | 16 +++++---- manifest.uuid | 2 +- src/memjournal.c | 93 ++++++++++++++++++++---------------------------- 3 files changed, 49 insertions(+), 62 deletions(-) diff --git a/manifest b/manifest index 95a229990c..40bd34b006 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\snew\srow\stype\sto\sRBU\s(a\speer\sof\sinsert,\supdate\sand\sdelete)\s-\s"delete\sthen\sinsert". -D 2016-03-08T15:52:43.903 +C Modify\sthe\smemjournal.c\scode\sto\smake\sit\sa\sbit\ssmaller. +D 2016-03-08T17:44:08.043 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -321,7 +321,7 @@ F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memjournal.c 011da5236a7250385cc74c253f14bbee04c0d61e +F src/memjournal.c 02deb8930ae8103fbe5640433a9d55c5dd2c13f1 F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 @@ -1455,8 +1455,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5a847a676e756bbe33436596d4279f339bfb247c 169311c85b30f625bdb6986c9cd11db70942d73b -R 43c0b748ba126143d737a43b13d0c445 -T +closed 169311c85b30f625bdb6986c9cd11db70942d73b +P 1d9468d2427d2c9b7240b364554ac85a0b62fa44 +R f53a6f3e4bc637f282a01c3504067543 +T *branch * memjournal-exp +T *sym-memjournal-exp * +T -sym-trunk * U dan -Z 99ed19537580c1e7328c1d8043178b0a +Z e2ab5ced3facb0c6a3be08b7e7370857 diff --git a/manifest.uuid b/manifest.uuid index e6281cbd82..c324dea819 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1d9468d2427d2c9b7240b364554ac85a0b62fa44 \ No newline at end of file +d99ac4154812065eef26c298de52954d7ee0bd75 \ No newline at end of file diff --git a/src/memjournal.c b/src/memjournal.c index 04780df99c..2d6922ddeb 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -69,7 +69,6 @@ struct MemJournal { int flags; /* xOpen flags */ sqlite3_vfs *pVfs; /* The "real" underlying VFS */ const char *zJournal; /* Name of the journal file */ - sqlite3_file *pReal; /* The "real" underlying file descriptor */ }; /* @@ -83,9 +82,7 @@ static int memjrnlRead( sqlite_int64 iOfst /* Begin reading at this offset */ ){ MemJournal *p = (MemJournal *)pJfd; - if( p->pReal ){ - return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); - }else if( (iAmt+iOfst)>p->endpoint.iOffset ){ + if( (iAmt+iOfst)>p->endpoint.iOffset ){ return SQLITE_IOERR_SHORT_READ; }else{ u8 *zOut = zBuf; @@ -138,36 +135,37 @@ static void memjrnlFreeChunks(MemJournal *p){ ** Flush the contents of memory to a real file on disk. */ static int memjrnlCreateFile(MemJournal *p){ - int rc = SQLITE_OK; - if( !p->pReal ){ - sqlite3_file *pReal = (sqlite3_file *)&p[1]; - rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0); - if( rc==SQLITE_OK ){ - int nChunk = p->nChunkSize; - i64 iOff = 0; - FileChunk *pIter; - p->pReal = pReal; - for(pIter=p->pFirst; pIter && rc==SQLITE_OK; pIter=pIter->pNext){ - int nWrite = nChunk; - if( pIter==p->endpoint.pChunk ){ - nWrite = p->endpoint.iOffset % p->nChunkSize; - if( nWrite==0 ) nWrite = p->nChunkSize; - } - rc = sqlite3OsWrite(pReal, (u8*)pIter->zChunk, nWrite, iOff); - iOff += nWrite; - } - if( rc!=SQLITE_OK ){ - /* If an error occurred while writing to the file, close it before - ** returning. This way, SQLite uses the in-memory journal data to - ** roll back changes made to the internal page-cache before this - ** function was called. */ - sqlite3OsClose(pReal); - p->pReal = 0; - }else{ - /* No error has occurred. Free the in-memory buffers. */ - memjrnlFreeChunks(p); + int rc; + sqlite3_file *pReal = (sqlite3_file*)p; + MemJournal copy = *p; + + memset(p, 0, sizeof(MemJournal)); + rc = sqlite3OsOpen(copy.pVfs, copy.zJournal, pReal, copy.flags, 0); + if( rc==SQLITE_OK ){ + int nChunk = copy.nChunkSize; + i64 iOff = 0; + FileChunk *pIter; + for(pIter=copy.pFirst; pIter && rc==SQLITE_OK; pIter=pIter->pNext){ + int nWrite = nChunk; + if( pIter==copy.endpoint.pChunk ){ + nWrite = copy.endpoint.iOffset % copy.nChunkSize; + if( nWrite==0 ) nWrite = copy.nChunkSize; } + rc = sqlite3OsWrite(pReal, (u8*)pIter->zChunk, nWrite, iOff); + iOff += nWrite; } + if( rc==SQLITE_OK ){ + /* No error has occurred. Free the in-memory buffers. */ + memjrnlFreeChunks(©); + } + } + if( rc!=SQLITE_OK ){ + /* If an error occurred while creating or writing to the file, restore + ** the original before returning. This way, SQLite uses the in-memory + ** journal data to roll back changes made to the internal page-cache + ** before this function was called. */ + sqlite3OsClose(pReal); + *p = copy; } return rc; } @@ -186,16 +184,12 @@ static int memjrnlWrite( int nWrite = iAmt; u8 *zWrite = (u8 *)zBuf; - /* If the file has already been created on disk. */ - if( p->pReal ){ - return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); - } - - /* If the file should be created now. */ - else if( p->nSpill>0 && (iAmt+iOfst)>p->nSpill ){ + /* If the file should be created now, create it and write the new data + ** into the file on disk. */ + if( p->nSpill>0 && (iAmt+iOfst)>p->nSpill ){ int rc = memjrnlCreateFile(p); if( rc==SQLITE_OK ){ - rc = memjrnlWrite(pJfd, zBuf, iAmt, iOfst); + rc = sqlite3OsWrite(pJfd, zBuf, iAmt, iOfst); } return rc; } @@ -255,9 +249,7 @@ static int memjrnlWrite( */ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ MemJournal *p = (MemJournal *)pJfd; - if( p->pReal ){ - return sqlite3OsTruncate(p->pReal, size); - }else if( size==0 ){ + if( size==0 ){ memjrnlFreeChunks(p); p->nSize = 0; p->endpoint.pChunk = 0; @@ -274,7 +266,6 @@ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ static int memjrnlClose(sqlite3_file *pJfd){ MemJournal *p = (MemJournal *)pJfd; memjrnlFreeChunks(p); - if( p->pReal ) sqlite3OsClose(p->pReal); return SQLITE_OK; } @@ -285,10 +276,7 @@ static int memjrnlClose(sqlite3_file *pJfd){ ** syncing an in-memory journal is a no-op. */ static int memjrnlSync(sqlite3_file *pJfd, int flags){ - MemJournal *p = (MemJournal *)pJfd; - if( p->pReal ){ - return sqlite3OsSync(p->pReal, flags); - } + UNUSED_PARAMETER2(pJfd, flags); return SQLITE_OK; } @@ -297,9 +285,6 @@ static int memjrnlSync(sqlite3_file *pJfd, int flags){ */ static int memjrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){ MemJournal *p = (MemJournal *)pJfd; - if( p->pReal ){ - return sqlite3OsFileSize(p->pReal, pSize); - } *pSize = (sqlite_int64) p->endpoint.iOffset; return SQLITE_OK; } @@ -354,7 +339,7 @@ int sqlite3JournalOpen( ** it using the sqlite3OsOpen() function of the underlying VFS. In this ** case none of the code in this module is executed as a result of calls ** made on the journal file-handle. */ - memset(p, 0, sizeof(MemJournal) + (pVfs ? pVfs->szOsFile : 0)); + memset(p, 0, sizeof(MemJournal)); if( nSpill==0 ){ return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); } @@ -403,7 +388,7 @@ int sqlite3JournalCreate(sqlite3_file *p){ ** or false otherwise. */ int sqlite3JournalIsInMemory(sqlite3_file *p){ - return p->pMethods==&MemJournalMethods && ((MemJournal*)p)->pReal==0; + return p->pMethods==&MemJournalMethods; } /* @@ -411,5 +396,5 @@ int sqlite3JournalIsInMemory(sqlite3_file *p){ ** pVfs to create the underlying on-disk files. */ int sqlite3JournalSize(sqlite3_vfs *pVfs){ - return pVfs->szOsFile + sizeof(MemJournal); + return MAX(pVfs->szOsFile, sizeof(MemJournal)); } From 3349d9bea956eaf1a2d9554ce3e4c9e1d5b34075 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Mar 2016 23:18:51 +0000 Subject: [PATCH 434/570] Improved comments on virtual table query planning. Added many new WHERETRACE() macros. FossilOrigin-Name: 4c89c2534abcf67bc486d5a900a84a6c4f59537e --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/where.c | 22 +++++++++++++++------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index bb6f77ee42..25c4175d4a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\smemjournal.c,\sreuse\sthe\ssame\ssqlite3_file\sobject\sfor\sboth\sthe\sin-memory\nphase\sand\sthe\son-disk\sphase. -D 2016-03-08T17:59:19.784 +C Improved\scomments\son\svirtual\stable\squery\splanning.\s\sAdded\smany\snew\nWHERETRACE()\smacros. +D 2016-03-08T23:18:51.182 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -429,7 +429,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c dff52f7f0842430f80a7017c7859124685b08453 +F src/where.c a3f6db088f335a9217fe53d976f9441610061a2f F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 863aedf086131743763c1960637fde904eadc442 F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a @@ -1455,8 +1455,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 f6d3156ba9af1da517dd77c1df03fa7869888463 d99ac4154812065eef26c298de52954d7ee0bd75 -R bec56382cb26d93b90f8b590f852c457 -T +closed d99ac4154812065eef26c298de52954d7ee0bd75 +P e7fbbdc25c0991d4e58d78a5fcb7386e1aa7f3af +R 624279792742522c1a4793f09c7ca2f6 U drh -Z 55dc3dcac976fd228dc3d62385f9ab1a +Z ab3adc4bc8a1b11824c36206a5455ed4 diff --git a/manifest.uuid b/manifest.uuid index 45d67c3642..572a4db2fb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e7fbbdc25c0991d4e58d78a5fcb7386e1aa7f3af \ No newline at end of file +4c89c2534abcf67bc486d5a900a84a6c4f59537e \ No newline at end of file diff --git a/src/where.c b/src/where.c index 2d7272a742..364bfca3c5 100644 --- a/src/where.c +++ b/src/where.c @@ -2892,6 +2892,9 @@ static int whereLoopAddVirtualOne( sqlite3_free(pNew->u.vtab.idxStr); pNew->u.vtab.needFree = 0; } + WHERETRACE(0xffff, (" bIn=%d prereqIn=%04llx prereqOut=%04llx\n", + *pbIn, (sqlite3_uint64)mPrereq, + (sqlite3_uint64)(pNew->prereq & ~mPrereq))); return SQLITE_OK; } @@ -2958,15 +2961,15 @@ static int whereLoopAddVirtual( } /* First call xBestIndex() with all constraints usable. */ + WHERETRACE(0x40, (" VirtualOne: all usable\n")); rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, &bIn); - mBest = pNew->prereq & ~mPrereq; /* If the call to xBestIndex() with all terms enabled produced a plan - ** that does not require any source tables, there is no point in making - ** any further calls - if the xBestIndex() method is sane they will all - ** return the same plan anyway. - */ - if( mBest ){ + ** that does not require any source tables (IOW: a plan with mBest==0), + ** then there is no point in making any further calls to xBestIndex() + ** since they will all return the same result (if the xBestIndex() + ** implementation is sane). */ + if( rc==SQLITE_OK && (mBest = (pNew->prereq & ~mPrereq))!=0 ){ int seenZero = 0; /* True if a plan with no prereqs seen */ int seenZeroNoIN = 0; /* Plan with no prereqs and no IN(...) seen */ Bitmask mPrev = 0; @@ -2974,7 +2977,8 @@ static int whereLoopAddVirtual( /* If the plan produced by the earlier call uses an IN(...) term, call ** xBestIndex again, this time with IN(...) terms disabled. */ - if( rc==SQLITE_OK && bIn ){ + if( bIn ){ + WHERETRACE(0x40, (" VirtualOne: all usable w/o IN\n")); rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, WO_IN, p, &bIn); assert( bIn==0 ); mBestNoIn = pNew->prereq & ~mPrereq; @@ -2999,6 +3003,8 @@ static int whereLoopAddVirtual( mPrev = mNext; if( mNext==ALLBITS ) break; if( mNext==mBest || mNext==mBestNoIn ) continue; + WHERETRACE(0x40, (" VirtualOne: mPrev=%04llx mNext=%04llx\n", + (sqlite3_uint64)mPrev, (sqlite3_uint64)mNext)); rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mNext|mPrereq, 0, p, &bIn); if( pNew->prereq==mPrereq ){ seenZero = 1; @@ -3010,6 +3016,7 @@ static int whereLoopAddVirtual( ** that requires no source tables at all (i.e. one guaranteed to be ** usable), make a call here with all source tables disabled */ if( rc==SQLITE_OK && seenZero==0 ){ + WHERETRACE(0x40, (" VirtualOne: all disabled\n")); rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mPrereq, 0, p, &bIn); if( bIn==0 ) seenZeroNoIN = 1; } @@ -3018,6 +3025,7 @@ static int whereLoopAddVirtual( ** that requires no source tables at all and does not use an IN(...) ** operator, make a final call to obtain one here. */ if( rc==SQLITE_OK && seenZeroNoIN==0 ){ + WHERETRACE(0x40, (" VirtualOne: all disabled and w/o IN\n")); rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mPrereq, WO_IN, p, &bIn); } } From d1cca3b721485738e96e3cc34bc8fef862016101 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Mar 2016 23:44:48 +0000 Subject: [PATCH 435/570] Change an unreachable branch in the virtual table query planner into an assert(). FossilOrigin-Name: 73b97b9ec3c39ab2828ae6353b5d7e04a27996c9 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 3 +-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 25c4175d4a..7dcb18c721 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\scomments\son\svirtual\stable\squery\splanning.\s\sAdded\smany\snew\nWHERETRACE()\smacros. -D 2016-03-08T23:18:51.182 +C Change\san\sunreachable\sbranch\sin\sthe\svirtual\stable\squery\splanner\sinto\nan\sassert(). +D 2016-03-08T23:44:48.075 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -429,7 +429,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c a3f6db088f335a9217fe53d976f9441610061a2f +F src/where.c f2859a4f9e3ce0585fd75648fb5cae9f985c458d F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 863aedf086131743763c1960637fde904eadc442 F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a @@ -1455,7 +1455,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 e7fbbdc25c0991d4e58d78a5fcb7386e1aa7f3af -R 624279792742522c1a4793f09c7ca2f6 +P 4c89c2534abcf67bc486d5a900a84a6c4f59537e +R ba189513b00cd0d7f1cb51ba2837236b U drh -Z ab3adc4bc8a1b11824c36206a5455ed4 +Z b92bcbc09edaf6b80c374c7506559755 diff --git a/manifest.uuid b/manifest.uuid index 572a4db2fb..b773d03caf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4c89c2534abcf67bc486d5a900a84a6c4f59537e \ No newline at end of file +73b97b9ec3c39ab2828ae6353b5d7e04a27996c9 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 364bfca3c5..927469f0d5 100644 --- a/src/where.c +++ b/src/where.c @@ -2810,10 +2810,9 @@ static int whereLoopAddVirtualOne( /* Initialize the output fields of the sqlite3_index_info structure */ memset(pUsage, 0, sizeof(pUsage[0])*nConstraint); - if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr); + assert( pIdxInfo->needToFreeIdxStr==0 ); pIdxInfo->idxStr = 0; pIdxInfo->idxNum = 0; - pIdxInfo->needToFreeIdxStr = 0; pIdxInfo->orderByConsumed = 0; pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; pIdxInfo->estimatedRows = 25; From 273021d71a892d8155ad17354e52ce3b743b8c3a Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 9 Mar 2016 02:03:03 +0000 Subject: [PATCH 436/570] Add an #ifdef and an ALWAYS() for coverage. FossilOrigin-Name: 069337a922867ad0d023f5bf36e13ea46e047000 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/memjournal.c | 9 +++++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 7dcb18c721..7b1d29dc01 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\san\sunreachable\sbranch\sin\sthe\svirtual\stable\squery\splanner\sinto\nan\sassert(). -D 2016-03-08T23:44:48.075 +C Add\san\s#ifdef\sand\san\sALWAYS()\sfor\scoverage. +D 2016-03-09T02:03:03.758 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -321,7 +321,7 @@ F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memjournal.c 02deb8930ae8103fbe5640433a9d55c5dd2c13f1 +F src/memjournal.c 9704b40cd63d53f584ac06c0cd1b52d399bb63ec F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 @@ -1455,7 +1455,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 4c89c2534abcf67bc486d5a900a84a6c4f59537e -R ba189513b00cd0d7f1cb51ba2837236b +P 73b97b9ec3c39ab2828ae6353b5d7e04a27996c9 +R ff350e249f52320a06e1a0030d694c10 U drh -Z b92bcbc09edaf6b80c374c7506559755 +Z 4b008537bb55e8cdb449348ac3153700 diff --git a/manifest.uuid b/manifest.uuid index b773d03caf..1716d33ca2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -73b97b9ec3c39ab2828ae6353b5d7e04a27996c9 \ No newline at end of file +069337a922867ad0d023f5bf36e13ea46e047000 \ No newline at end of file diff --git a/src/memjournal.c b/src/memjournal.c index 2d6922ddeb..706703ed80 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -202,10 +202,15 @@ static int memjrnlWrite( ** atomic-write optimization. In this case the first 28 bytes of the ** journal file may be written as part of committing the transaction. */ assert( iOfst==p->endpoint.iOffset || iOfst==0 ); +#ifdef SQLITE_ENABLE_ATOMIC_WRITE if( iOfst==0 && p->pFirst ){ assert( p->nChunkSize>iAmt ); memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt); - }else{ + }else +#else + assert( iOfst>0 || p->pFirst==0 ); +#endif + { while( nWrite>0 ){ FileChunk *pChunk = p->endpoint.pChunk; int iChunkOffset = (int)(p->endpoint.iOffset%p->nChunkSize); @@ -249,7 +254,7 @@ static int memjrnlWrite( */ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ MemJournal *p = (MemJournal *)pJfd; - if( size==0 ){ + if( ALWAYS(size==0) ){ memjrnlFreeChunks(p); p->nSize = 0; p->endpoint.pChunk = 0; From 2f1e02e8a7f263b4af5322cab874a4bc68c54080 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 9 Mar 2016 02:12:44 +0000 Subject: [PATCH 437/570] Change a branch made obsolete by recent parser enhancements into an assert(). FossilOrigin-Name: ee486ef742557244f532e8d3b3604ff04e024b8a --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/build.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 7b1d29dc01..e6d9d8a391 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\san\s#ifdef\sand\san\sALWAYS()\sfor\scoverage. -D 2016-03-09T02:03:03.758 +C Change\sa\sbranch\smade\sobsolete\sby\srecent\sparser\senhancements\sinto\san\sassert(). +D 2016-03-09T02:12:44.430 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -296,7 +296,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 2712f087351f5c4ff0e71631b1e67b461611b99d F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 43b93fe757bfffe00f97462596418b052eefdccd +F src/build.c 213cbf84e99dd834e6ea46615633656d7ef79321 F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -1455,7 +1455,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 73b97b9ec3c39ab2828ae6353b5d7e04a27996c9 -R ff350e249f52320a06e1a0030d694c10 +P 069337a922867ad0d023f5bf36e13ea46e047000 +R 3e57a4be2efca34c86d71580042aa5c5 U drh -Z 4b008537bb55e8cdb449348ac3153700 +Z 969405448d01de3e3b82aafcc7d6fe5a diff --git a/manifest.uuid b/manifest.uuid index 1716d33ca2..fb4b683b73 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -069337a922867ad0d023f5bf36e13ea46e047000 \ No newline at end of file +ee486ef742557244f532e8d3b3604ff04e024b8a \ No newline at end of file diff --git a/src/build.c b/src/build.c index a32dfbd029..e89c744461 100644 --- a/src/build.c +++ b/src/build.c @@ -1135,7 +1135,7 @@ char sqlite3AffinityType(const char *zIn, u8 *pszEst){ char aff = SQLITE_AFF_NUMERIC; const char *zChar = 0; - if( zIn==0 ) return aff; + assert( zIn!=0 ); while( zIn[0] ){ h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff]; zIn++; From c1fb2b87bd2bf58959dec99cc34441437cf2a799 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 9 Mar 2016 03:29:27 +0000 Subject: [PATCH 438/570] Update a comment in btree.c to account for WITHOUT ROWID tables. No code changes. FossilOrigin-Name: fa20dcb03b92be3bb32f8e3d6f88681ace3f6c84 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index e6d9d8a391..0c5b9408ab 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sa\sbranch\smade\sobsolete\sby\srecent\sparser\senhancements\sinto\san\sassert(). -D 2016-03-09T02:12:44.430 +C Update\sa\scomment\sin\sbtree.c\sto\saccount\sfor\sWITHOUT\sROWID\stables.\s\sNo\scode\nchanges. +D 2016-03-09T03:29:27.407 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -293,7 +293,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 2712f087351f5c4ff0e71631b1e67b461611b99d +F src/btree.c 6eee126fe9d1f57118de9be2be840a4c6e691828 F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 213cbf84e99dd834e6ea46615633656d7ef79321 @@ -1455,7 +1455,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 069337a922867ad0d023f5bf36e13ea46e047000 -R 3e57a4be2efca34c86d71580042aa5c5 +P ee486ef742557244f532e8d3b3604ff04e024b8a +R 58c822ca96b5496f25a8c479ed6f41b8 U drh -Z 969405448d01de3e3b82aafcc7d6fe5a +Z 14a12081690d2b5a8e4723ef05aa614c diff --git a/manifest.uuid b/manifest.uuid index fb4b683b73..758bea7f1a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ee486ef742557244f532e8d3b3604ff04e024b8a \ No newline at end of file +fa20dcb03b92be3bb32f8e3d6f88681ace3f6c84 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 4b9bba55ac..18e6be9f38 100644 --- a/src/btree.c +++ b/src/btree.c @@ -7572,9 +7572,9 @@ static int balance_nonroot( ** any cell). But it is important to pass the correct size to ** insertCell(), so reparse the cell now. ** - ** Note that this can never happen in an SQLite data file, as all - ** cells are at least 4 bytes. It only happens in b-trees used - ** to evaluate "IN (SELECT ...)" and similar clauses. + ** This can only happen for b-trees used to evaluate "IN (SELECT ...)" + ** and WITHOUT ROWID tables with exactly one column which is the + ** primary key. */ if( b.szCell[j]==4 ){ assert(leafCorrection==4); From 769b4c95ca98318bf5ff2152f09148a9694e9ed7 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 9 Mar 2016 03:44:32 +0000 Subject: [PATCH 439/570] Move the write failure test in memjrnlCreateFile() to just after the actual write, thus reducing the number of instances of the test by one. FossilOrigin-Name: 7f00d80c63b15376391f661d872f2b29a970702d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/memjournal.c | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 0c5b9408ab..cc0b431865 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sa\scomment\sin\sbtree.c\sto\saccount\sfor\sWITHOUT\sROWID\stables.\s\sNo\scode\nchanges. -D 2016-03-09T03:29:27.407 +C Move\sthe\swrite\sfailure\stest\sin\smemjrnlCreateFile()\sto\sjust\safter\sthe\nactual\swrite,\sthus\sreducing\sthe\snumber\sof\sinstances\sof\sthe\stest\sby\sone. +D 2016-03-09T03:44:32.424 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -321,7 +321,7 @@ F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memjournal.c 9704b40cd63d53f584ac06c0cd1b52d399bb63ec +F src/memjournal.c 13ae08696117438e7fa2518af71e52ee00c02395 F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 @@ -1455,7 +1455,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 ee486ef742557244f532e8d3b3604ff04e024b8a -R 58c822ca96b5496f25a8c479ed6f41b8 +P fa20dcb03b92be3bb32f8e3d6f88681ace3f6c84 +R ddfc9f5547c4cd989efbf516628daef2 U drh -Z 14a12081690d2b5a8e4723ef05aa614c +Z f80415911853dbc4f72e4c714eb20705 diff --git a/manifest.uuid b/manifest.uuid index 758bea7f1a..ad041f10c3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fa20dcb03b92be3bb32f8e3d6f88681ace3f6c84 \ No newline at end of file +7f00d80c63b15376391f661d872f2b29a970702d \ No newline at end of file diff --git a/src/memjournal.c b/src/memjournal.c index 706703ed80..ed1d6bba8c 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -145,13 +145,14 @@ static int memjrnlCreateFile(MemJournal *p){ int nChunk = copy.nChunkSize; i64 iOff = 0; FileChunk *pIter; - for(pIter=copy.pFirst; pIter && rc==SQLITE_OK; pIter=pIter->pNext){ + for(pIter=copy.pFirst; pIter; pIter=pIter->pNext){ int nWrite = nChunk; if( pIter==copy.endpoint.pChunk ){ nWrite = copy.endpoint.iOffset % copy.nChunkSize; if( nWrite==0 ) nWrite = copy.nChunkSize; } rc = sqlite3OsWrite(pReal, (u8*)pIter->zChunk, nWrite, iOff); + if( rc ) break; iOff += nWrite; } if( rc==SQLITE_OK ){ From d93b2b840d916442bd0b3655788a4571e7adba5f Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 9 Mar 2016 04:17:17 +0000 Subject: [PATCH 440/570] Simplifications to the memjournal.c logic to facilitate testing. FossilOrigin-Name: 8baa2c2c7698e03418531482a8314a5d7ae2c7d3 --- manifest | 12 ++++---- manifest.uuid | 2 +- src/memjournal.c | 71 ++++++++++++++++++++++++------------------------ 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/manifest b/manifest index cc0b431865..463e7f81dd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Move\sthe\swrite\sfailure\stest\sin\smemjrnlCreateFile()\sto\sjust\safter\sthe\nactual\swrite,\sthus\sreducing\sthe\snumber\sof\sinstances\sof\sthe\stest\sby\sone. -D 2016-03-09T03:44:32.424 +C Simplifications\sto\sthe\smemjournal.c\slogic\sto\sfacilitate\stesting. +D 2016-03-09T04:17:17.100 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -321,7 +321,7 @@ F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memjournal.c 13ae08696117438e7fa2518af71e52ee00c02395 +F src/memjournal.c 6423a0817ffd8c7a04ef9e5fb974b6b9dd71f8b6 F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 @@ -1455,7 +1455,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 fa20dcb03b92be3bb32f8e3d6f88681ace3f6c84 -R ddfc9f5547c4cd989efbf516628daef2 +P 7f00d80c63b15376391f661d872f2b29a970702d +R 3dfe324883f59e455687da1f2d0dc6fa U drh -Z f80415911853dbc4f72e4c714eb20705 +Z 09a89868e4ca6983fd083bec8c9845f2 diff --git a/manifest.uuid b/manifest.uuid index ad041f10c3..2a3c3e97a0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7f00d80c63b15376391f661d872f2b29a970702d \ No newline at end of file +8baa2c2c7698e03418531482a8314a5d7ae2c7d3 \ No newline at end of file diff --git a/src/memjournal.c b/src/memjournal.c index ed1d6bba8c..b81682de85 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -82,38 +82,41 @@ static int memjrnlRead( sqlite_int64 iOfst /* Begin reading at this offset */ ){ MemJournal *p = (MemJournal *)pJfd; + u8 *zOut = zBuf; + int nRead = iAmt; + int iChunkOffset; + FileChunk *pChunk; + +#ifdef SQLITE_ENABLE_ATOMIC_WRITE if( (iAmt+iOfst)>p->endpoint.iOffset ){ return SQLITE_IOERR_SHORT_READ; - }else{ - u8 *zOut = zBuf; - int nRead = iAmt; - int iChunkOffset; - FileChunk *pChunk; - - if( p->readpoint.iOffset!=iOfst || iOfst==0 ){ - sqlite3_int64 iOff = 0; - for(pChunk=p->pFirst; - ALWAYS(pChunk) && (iOff+p->nChunkSize)<=iOfst; - pChunk=pChunk->pNext - ){ - iOff += p->nChunkSize; - } - }else{ - pChunk = p->readpoint.pChunk; - } - - iChunkOffset = (int)(iOfst%p->nChunkSize); - do { - int iSpace = p->nChunkSize - iChunkOffset; - int nCopy = MIN(nRead, (p->nChunkSize - iChunkOffset)); - memcpy(zOut, (u8*)pChunk->zChunk + iChunkOffset, nCopy); - zOut += nCopy; - nRead -= iSpace; - iChunkOffset = 0; - } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 ); - p->readpoint.iOffset = iOfst+iAmt; - p->readpoint.pChunk = pChunk; } +#endif + + assert( (iAmt+iOfst)<=p->endpoint.iOffset ); + if( p->readpoint.iOffset!=iOfst || iOfst==0 ){ + sqlite3_int64 iOff = 0; + for(pChunk=p->pFirst; + ALWAYS(pChunk) && (iOff+p->nChunkSize)<=iOfst; + pChunk=pChunk->pNext + ){ + iOff += p->nChunkSize; + } + }else{ + pChunk = p->readpoint.pChunk; + } + + iChunkOffset = (int)(iOfst%p->nChunkSize); + do { + int iSpace = p->nChunkSize - iChunkOffset; + int nCopy = MIN(nRead, (p->nChunkSize - iChunkOffset)); + memcpy(zOut, (u8*)pChunk->zChunk + iChunkOffset, nCopy); + zOut += nCopy; + nRead -= iSpace; + iChunkOffset = 0; + } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 ); + p->readpoint.iOffset = iOfst+iAmt; + p->readpoint.pChunk = pChunk; return SQLITE_OK; } @@ -146,14 +149,12 @@ static int memjrnlCreateFile(MemJournal *p){ i64 iOff = 0; FileChunk *pIter; for(pIter=copy.pFirst; pIter; pIter=pIter->pNext){ - int nWrite = nChunk; - if( pIter==copy.endpoint.pChunk ){ - nWrite = copy.endpoint.iOffset % copy.nChunkSize; - if( nWrite==0 ) nWrite = copy.nChunkSize; + if( iOff + nChunk > copy.endpoint.iOffset ){ + nChunk = copy.endpoint.iOffset - iOff; } - rc = sqlite3OsWrite(pReal, (u8*)pIter->zChunk, nWrite, iOff); + rc = sqlite3OsWrite(pReal, (u8*)pIter->zChunk, nChunk, iOff); if( rc ) break; - iOff += nWrite; + iOff += nChunk; } if( rc==SQLITE_OK ){ /* No error has occurred. Free the in-memory buffers. */ From c5644346b698a37763942e55fb41d310d0d45461 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 9 Mar 2016 11:59:16 +0000 Subject: [PATCH 441/570] Disable the bestindex*.test modules when building without virtual table support. FossilOrigin-Name: e0bac2f3eed900d3a26de339fb7d5963f9b47724 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/bestindex1.test | 7 +++++-- test/bestindex2.test | 5 ++++- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 463e7f81dd..1db0431740 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplifications\sto\sthe\smemjournal.c\slogic\sto\sfacilitate\stesting. -D 2016-03-09T04:17:17.100 +C Disable\sthe\sbestindex*.test\smodules\swhen\sbuilding\swithout\svirtual\stable\ssupport. +D 2016-03-09T11:59:16.171 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -493,8 +493,8 @@ F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450 F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f F test/bc_common.tcl 3eda41ef9cda7d5f6c205462c96228b301da4191 -F test/bestindex1.test e228fe1e3794dbe20271481164e000d695abcd24 -F test/bestindex2.test 10f2c6791f1cd0de414012528cd10a114648fd8f +F test/bestindex1.test d5ba89a7941a941476d8d69be39b146aaed3614c +F test/bestindex2.test 4a06b8922ab2fd09434870da8d1cdf525aaf7060 F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59 F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc @@ -1455,7 +1455,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 7f00d80c63b15376391f661d872f2b29a970702d -R 3dfe324883f59e455687da1f2d0dc6fa +P 8baa2c2c7698e03418531482a8314a5d7ae2c7d3 +R edb83c934a274796cafb7c4f60da05c5 U drh -Z 09a89868e4ca6983fd083bec8c9845f2 +Z 1fd2317c8384669beba01778fd436686 diff --git a/manifest.uuid b/manifest.uuid index 2a3c3e97a0..aeb04d38bc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8baa2c2c7698e03418531482a8314a5d7ae2c7d3 \ No newline at end of file +e0bac2f3eed900d3a26de339fb7d5963f9b47724 \ No newline at end of file diff --git a/test/bestindex1.test b/test/bestindex1.test index fffb7aebea..97ae4b0f81 100644 --- a/test/bestindex1.test +++ b/test/bestindex1.test @@ -15,6 +15,11 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix bestindex1 +ifcapable !vtab { + finish_test + return +} + register_tcl_module db proc vtab_command {method args} { @@ -161,5 +166,3 @@ foreach {tn mode} { } finish_test - - diff --git a/test/bestindex2.test b/test/bestindex2.test index 7ccd61640d..8bc3fbc323 100644 --- a/test/bestindex2.test +++ b/test/bestindex2.test @@ -13,6 +13,10 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix bestindex2 +ifcapable !vtab { + finish_test + return +} #------------------------------------------------------------------------- # Virtual table callback for table named $tbl, with the columns specified @@ -135,4 +139,3 @@ do_eqp_test 1.7.2 { } finish_test - From bacbbccd16aefaeb51c30f6a3b8d0c8ba20b07b1 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 9 Mar 2016 12:35:18 +0000 Subject: [PATCH 442/570] In the query planner, make sure OOM errors are reported up into whereLoopAddVirtual() so that it shuts down appropriately. FossilOrigin-Name: a13c59d08bcbc6f26ce6ac761a892eff8f035201 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 9 +++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 1db0431740..729dbda1a4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Disable\sthe\sbestindex*.test\smodules\swhen\sbuilding\swithout\svirtual\stable\ssupport. -D 2016-03-09T11:59:16.171 +C In\sthe\squery\splanner,\smake\ssure\sOOM\serrors\sare\sreported\sup\sinto\nwhereLoopAddVirtual()\sso\sthat\sit\sshuts\sdown\sappropriately. +D 2016-03-09T12:35:18.466 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -429,7 +429,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c f2859a4f9e3ce0585fd75648fb5cae9f985c458d +F src/where.c 5533002ddf4fbc256f450cb629668a200b06a3ce F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 863aedf086131743763c1960637fde904eadc442 F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a @@ -1455,7 +1455,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 8baa2c2c7698e03418531482a8314a5d7ae2c7d3 -R edb83c934a274796cafb7c4f60da05c5 +P e0bac2f3eed900d3a26de339fb7d5963f9b47724 +R ef93df8fd296bfa582e1a9a9087c3fc6 U drh -Z 1fd2317c8384669beba01778fd436686 +Z 498b8899efc263dd56cd46e3ec14e230 diff --git a/manifest.uuid b/manifest.uuid index aeb04d38bc..809eeb8fca 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e0bac2f3eed900d3a26de339fb7d5963f9b47724 \ No newline at end of file +a13c59d08bcbc6f26ce6ac761a892eff8f035201 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 927469f0d5..83d72ee397 100644 --- a/src/where.c +++ b/src/where.c @@ -1979,6 +1979,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ WhereLoop **ppPrev, *p; WhereInfo *pWInfo = pBuilder->pWInfo; sqlite3 *db = pWInfo->pParse->db; + int rc; /* If pBuilder->pOrSet is defined, then only keep track of the costs ** and prereqs. @@ -2061,14 +2062,14 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ whereLoopDelete(db, pToDel); } } - whereLoopXfer(db, p, pTemplate); + rc = whereLoopXfer(db, p, pTemplate); if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ Index *pIndex = p->u.btree.pIndex; if( pIndex && pIndex->tnum==0 ){ p->u.btree.pIndex = 0; } } - return SQLITE_OK; + return rc; } /* @@ -2886,7 +2887,7 @@ static int whereLoopAddVirtualOne( }else{ pNew->wsFlags &= ~WHERE_ONEROW; } - whereLoopInsert(pBuilder, pNew); + rc = whereLoopInsert(pBuilder, pNew); if( pNew->u.vtab.needFree ){ sqlite3_free(pNew->u.vtab.idxStr); pNew->u.vtab.needFree = 0; @@ -2895,7 +2896,7 @@ static int whereLoopAddVirtualOne( *pbIn, (sqlite3_uint64)mPrereq, (sqlite3_uint64)(pNew->prereq & ~mPrereq))); - return SQLITE_OK; + return rc; } From 7c621fb967b21c1f780a43b5e20118c9d0122b17 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 9 Mar 2016 13:39:43 +0000 Subject: [PATCH 443/570] Automatically disable SQLITE_ENABLE_EXPLAIN_COMMENTS if SQLITE_OMIT_EXPLAIN is defined. FossilOrigin-Name: 8d4b6b2b519a80f831d64345ac26db825b0e2ebe --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqliteInt.h | 7 +++++++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 729dbda1a4..32aef606c9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\squery\splanner,\smake\ssure\sOOM\serrors\sare\sreported\sup\sinto\nwhereLoopAddVirtual()\sso\sthat\sit\sshuts\sdown\sappropriately. -D 2016-03-09T12:35:18.466 +C Automatically\sdisable\sSQLITE_ENABLE_EXPLAIN_COMMENTS\sif\sSQLITE_OMIT_EXPLAIN\nis\sdefined. +D 2016-03-09T13:39:43.412 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -354,7 +354,7 @@ F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 0235586b3fb639e85998d495c90f007657fd82af F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 24e2eed36a68d48bd43d866adb528001b0795275 +F src/sqliteInt.h 84c673f27b77dfbd367cb3ed1de8b6f3b73102dc F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1455,7 +1455,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 e0bac2f3eed900d3a26de339fb7d5963f9b47724 -R ef93df8fd296bfa582e1a9a9087c3fc6 +P a13c59d08bcbc6f26ce6ac761a892eff8f035201 +R dc65bf9f81f047db6984b996890cdadd U drh -Z 498b8899efc263dd56cd46e3ec14e230 +Z 0ec66dff68629b4a77d366f261f0f00c diff --git a/manifest.uuid b/manifest.uuid index 809eeb8fca..5d4e109453 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a13c59d08bcbc6f26ce6ac761a892eff8f035201 \ No newline at end of file +8d4b6b2b519a80f831d64345ac26db825b0e2ebe \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 350832a2e7..f2f485778a 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -451,6 +451,13 @@ # undef SQLITE_NEED_ERR_NAME #endif +/* +** SQLITE_ENABLE_EXPLAIN_COMMENTS is incompatible with SQLITE_OMIT_EXPLAIN +*/ +#ifdef SQLITE_OMIT_EXPLAIN +# undef SQLITE_ENABLE_EXPLAIN_COMMENTS +#endif + /* ** Return true (non-zero) if the input is an integer that is too large ** to fit in 32-bits. This macro is used inside of various testcase() From 90730c9e689cc79921b8e1ce7252b40ea1f232cc Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 9 Mar 2016 15:09:22 +0000 Subject: [PATCH 444/570] When optimizing expressions of the form "x IN (SELECT ...)" make sure that the subquery is not correlated. Fix for ticket [5e3c886796e5512]. FossilOrigin-Name: 1ed6b06ea3c432f920fb2b66b6042be906c5d21c --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/expr.c | 5 ++++- test/where2.test | 11 +++++++++++ 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 32aef606c9..6ca9667196 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Automatically\sdisable\sSQLITE_ENABLE_EXPLAIN_COMMENTS\sif\sSQLITE_OMIT_EXPLAIN\nis\sdefined. -D 2016-03-09T13:39:43.412 +C When\soptimizing\sexpressions\sof\sthe\sform\s"x\sIN\s(SELECT\s...)"\smake\ssure\sthat\nthe\ssubquery\sis\snot\scorrelated.\s\sFix\sfor\sticket\s[5e3c886796e5512]. +D 2016-03-09T15:09:22.795 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -303,7 +303,7 @@ F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 0b73e681c11fca867fec554750c07fe0d4e417c1 F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b F src/delete.c 48802aa3ee6339f576d074336d3ae1b5f40e240f -F src/expr.c c4dad2cd6cec00387b75fef4551aff655430dcd2 +F src/expr.c 4ce9e66a297ec08d234817c3d9f7fa8c3bf4d851 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 5cb42d9a59e2a590776fd3fc8ff6f61d40df3c6e F src/func.c 552d300265aed09eea21f68ac742a440550c0062 @@ -1332,7 +1332,7 @@ F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e F test/where.test f0c325563acde44f2c4ea6ba348e9e29f7121757 -F test/where2.test af78c55589cbc82d793449493adba0dc3d659f23 +F test/where2.test 478d2170637b9211f593120648858593bf2445a1 F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8 F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 @@ -1455,7 +1455,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 a13c59d08bcbc6f26ce6ac761a892eff8f035201 -R dc65bf9f81f047db6984b996890cdadd +P 8d4b6b2b519a80f831d64345ac26db825b0e2ebe +R 903e4bb527a74ada303408f9543fd4d8 U drh -Z 0ec66dff68629b4a77d366f261f0f00c +Z 88acb6b3e9ba3ec690e7fd39f78d002e diff --git a/manifest.uuid b/manifest.uuid index 5d4e109453..95f57d41b6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8d4b6b2b519a80f831d64345ac26db825b0e2ebe \ No newline at end of file +1ed6b06ea3c432f920fb2b66b6042be906c5d21c \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 8a69732195..22ca21de01 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1584,6 +1584,7 @@ static int isCandidateForInOpt(Select *p){ SrcList *pSrc; ExprList *pEList; Table *pTab; + Expr *pRes; /* Result expression */ if( p==0 ) return 0; /* right-hand side of IN is SELECT */ if( p->pPrior ) return 0; /* Not a compound SELECT */ if( p->selFlags & (SF_Distinct|SF_Aggregate) ){ @@ -1605,7 +1606,9 @@ static int isCandidateForInOpt(Select *p){ if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */ pEList = p->pEList; if( pEList->nExpr!=1 ) return 0; /* One column in the result set */ - if( pEList->a[0].pExpr->op!=TK_COLUMN ) return 0; /* Result is a column */ + pRes = pEList->a[0].pExpr; + if( pRes->op!=TK_COLUMN ) return 0; /* Result is a column */ + if( pRes->iTable!=pSrc->a[0].iCursor ) return 0; /* Not a correlated subq */ return 1; } #endif /* SQLITE_OMIT_SUBQUERY */ diff --git a/test/where2.test b/test/where2.test index 434a7bcd9a..0a0533506a 100644 --- a/test/where2.test +++ b/test/where2.test @@ -765,4 +765,15 @@ do_execsql_test where2-13.1 { SELECT * FROM t13 WHERE (1=2 AND a=3) OR a=4; } {4 5} +# https://www.sqlite.org/src/info/5e3c886796e5512e (2016-03-09) +# Correlated subquery on the RHS of an IN operator +# +do_execsql_test where2-14.1 { + CREATE TABLE t14a(x INTEGER PRIMARY KEY); + INSERT INTO t14a(x) VALUES(1),(2),(3),(4); + CREATE TABLE t14b(y INTEGER PRIMARY KEY); + INSERT INTO t14b(y) VALUES(1); + SELECT x FROM t14a WHERE x NOT IN (SELECT x FROM t14b); +} {} + finish_test From ab8aa11b960a916fa25330837334ff06918fda7e Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 9 Mar 2016 15:14:54 +0000 Subject: [PATCH 445/570] Add another test case for bug [5e3c8867]. FossilOrigin-Name: d91e57e49f23414ec9211b775eb11cd6230a4f96 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/in5.test | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 6ca9667196..75c68eb813 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\soptimizing\sexpressions\sof\sthe\sform\s"x\sIN\s(SELECT\s...)"\smake\ssure\sthat\nthe\ssubquery\sis\snot\scorrelated.\s\sFix\sfor\sticket\s[5e3c886796e5512]. -D 2016-03-09T15:09:22.795 +C Add\sanother\stest\scase\sfor\sbug\s[5e3c8867]. +D 2016-03-09T15:14:54.990 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -788,7 +788,7 @@ F test/in.test 61a24ae38d4b64ec69f06ccdf022992f68a98176 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068 -F test/in5.test 1de657472fa9ac2924be25c2c959ac5ca1aae554 +F test/in5.test acc710c12af118df5f8645eaba9479f5619eed81 F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328 F test/incrblob2.test a5ce5ed1d0b01e2ed347245a21170372528af0a5 F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4 @@ -1455,7 +1455,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 8d4b6b2b519a80f831d64345ac26db825b0e2ebe -R 903e4bb527a74ada303408f9543fd4d8 -U drh -Z 88acb6b3e9ba3ec690e7fd39f78d002e +P 1ed6b06ea3c432f920fb2b66b6042be906c5d21c +R 95d0f94d6b7106c7ee892a8bac9f59f5 +U dan +Z b79fcffb60dd8a57430224ebf643a8ab diff --git a/manifest.uuid b/manifest.uuid index 95f57d41b6..519f37196f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1ed6b06ea3c432f920fb2b66b6042be906c5d21c \ No newline at end of file +d91e57e49f23414ec9211b775eb11cd6230a4f96 \ No newline at end of file diff --git a/test/in5.test b/test/in5.test index 67d212589d..b49c93e15b 100644 --- a/test/in5.test +++ b/test/in5.test @@ -183,4 +183,39 @@ do_execsql_test 6.3.1 { SELECT count(*) FROM x2 WHERE b IN (SELECT DISTINCT a FROM x1 LIMIT 2); } {2} +#------------------------------------------------------------------------- +# Test to confirm that bug [5e3c886796e5] is fixed. +# +do_execsql_test 7.1 { + CREATE TABLE y1(a, b); + CREATE TABLE y2(c); + + INSERT INTO y1 VALUES(1, 'one'); + INSERT INTO y1 VALUES('two', 'two'); + INSERT INTO y1 VALUES(3, 'three'); + + INSERT INTO y2 VALUES('one'); + INSERT INTO y2 VALUES('two'); + INSERT INTO y2 VALUES('three'); +} {} + +do_execsql_test 7.2.1 { + SELECT a FROM y1 WHERE b NOT IN (SELECT a FROM y2); +} {1 3} +do_execsql_test 7.2.2 { + SELECT a FROM y1 WHERE b IN (SELECT a FROM y2); +} {two} + +do_execsql_test 7.3.1 { + CREATE INDEX y2c ON y2(c); + SELECT a FROM y1 WHERE b NOT IN (SELECT a FROM y2); +} {1 3} +do_execsql_test 7.3.2 { + SELECT a FROM y1 WHERE b IN (SELECT a FROM y2); +} {two} + +finish_test + + + finish_test From 69c355bd9a749eb6349f2a67aeefbc937ca458bb Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 9 Mar 2016 15:34:51 +0000 Subject: [PATCH 446/570] Slight simplification to the query optimizer logic associated with IN (SELECT). FossilOrigin-Name: 2c55c3c2950cafdc256ab540f60dc4609b9c354b --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/expr.c | 34 +++++++++++++++------------------- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/manifest b/manifest index 75c68eb813..5189ebea8e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sanother\stest\scase\sfor\sbug\s[5e3c8867]. -D 2016-03-09T15:14:54.990 +C Slight\ssimplification\sto\sthe\squery\soptimizer\slogic\sassociated\swith\sIN\s(SELECT). +D 2016-03-09T15:34:51.959 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -303,7 +303,7 @@ F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 0b73e681c11fca867fec554750c07fe0d4e417c1 F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b F src/delete.c 48802aa3ee6339f576d074336d3ae1b5f40e240f -F src/expr.c 4ce9e66a297ec08d234817c3d9f7fa8c3bf4d851 +F src/expr.c c329d581e5d631153456369684d7d4bcd94c907d F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 5cb42d9a59e2a590776fd3fc8ff6f61d40df3c6e F src/func.c 552d300265aed09eea21f68ac742a440550c0062 @@ -1455,7 +1455,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 1ed6b06ea3c432f920fb2b66b6042be906c5d21c -R 95d0f94d6b7106c7ee892a8bac9f59f5 -U dan -Z b79fcffb60dd8a57430224ebf643a8ab +P d91e57e49f23414ec9211b775eb11cd6230a4f96 +R c1ca42221fb7dbc6b010dbeefd096918 +U drh +Z 8017c7a46c10555b3cc0af7ce0a6b14d diff --git a/manifest.uuid b/manifest.uuid index 519f37196f..41eb62d748 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d91e57e49f23414ec9211b775eb11cd6230a4f96 \ No newline at end of file +2c55c3c2950cafdc256ab540f60dc4609b9c354b \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 22ca21de01..3672d02df1 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1568,24 +1568,22 @@ int sqlite3IsRowid(const char *z){ } /* -** Return true if we are able to the IN operator optimization on a -** query of the form -** -** x IN (SELECT ...) -** -** Where the SELECT... clause is as specified by the parameter to this -** routine. -** -** The Select object passed in has already been preprocessed and no -** errors have been found. +** pX is the RHS of an IN operator. If pX is a SELECT statement +** that can be simplified to a direct table access, then return +** a pointer to the SELECT statement. If pX is not a SELECT statement, +** or if the SELECT statement needs to be manifested into a transient +** table, then return NULL. */ #ifndef SQLITE_OMIT_SUBQUERY -static int isCandidateForInOpt(Select *p){ +static Select *isCandidateForInOpt(Expr *pX){ + Select *p; SrcList *pSrc; ExprList *pEList; + Expr *pRes; Table *pTab; - Expr *pRes; /* Result expression */ - if( p==0 ) return 0; /* right-hand side of IN is SELECT */ + if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0; /* Not a subquery */ + if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */ + p = pX->x.pSelect; if( p->pPrior ) return 0; /* Not a compound SELECT */ if( p->selFlags & (SF_Distinct|SF_Aggregate) ){ testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); @@ -1601,15 +1599,15 @@ static int isCandidateForInOpt(Select *p){ if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */ if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */ pTab = pSrc->a[0].pTab; - if( NEVER(pTab==0) ) return 0; + assert( pTab!=0 ); assert( pTab->pSelect==0 ); /* FROM clause is not a view */ if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */ pEList = p->pEList; if( pEList->nExpr!=1 ) return 0; /* One column in the result set */ pRes = pEList->a[0].pExpr; if( pRes->op!=TK_COLUMN ) return 0; /* Result is a column */ - if( pRes->iTable!=pSrc->a[0].iCursor ) return 0; /* Not a correlated subq */ - return 1; + assert( pRes->iTable==pSrc->a[0].iCursor ); /* Not a correlated subquery */ + return p; } #endif /* SQLITE_OMIT_SUBQUERY */ @@ -1741,15 +1739,13 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){ ** satisfy the query. This is preferable to generating a new ** ephemeral table. */ - p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0); - if( pParse->nErr==0 && isCandidateForInOpt(p) ){ + if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){ sqlite3 *db = pParse->db; /* Database connection */ Table *pTab; /* Table . */ Expr *pExpr; /* Expression */ i16 iCol; /* Index of column */ i16 iDb; /* Database idx for pTab */ - assert( p ); /* Because of isCandidateForInOpt(p) */ assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ From 57ebc84a6e2baf82d0f11fab0f94006d15abcb28 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 9 Mar 2016 18:17:42 +0000 Subject: [PATCH 447/570] Fix a problem in fts3/4 that was causing it to discard data cached in-memory if an 'optimize' command is run when there is no data on disk. The usual way this would happen is if the very first transaction that writes to the fts3/4 table also includes an 'optimize' command. FossilOrigin-Name: 79338b991bf01e81d336790ca87a0fa747da4ff3 --- ext/fts3/fts3_write.c | 2 +- manifest | 16 ++++++++-------- manifest.uuid | 2 +- test/fts4opt.test | 44 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 10 deletions(-) diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index 24039aef30..3ff481b0b0 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -3195,7 +3195,7 @@ static int fts3SegmentMerge( ** segment. The level of the new segment is equal to the numerically ** greatest segment level currently present in the database for this ** index. The idx of the new segment is always 0. */ - if( csr.nSegment==1 ){ + if( csr.nSegment==1 && 0==fts3SegReaderIsPending(csr.apSegment[0]) ){ rc = SQLITE_DONE; goto finished; } diff --git a/manifest b/manifest index 5189ebea8e..6d3b9274dd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Slight\ssimplification\sto\sthe\squery\soptimizer\slogic\sassociated\swith\sIN\s(SELECT). -D 2016-03-09T15:34:51.959 +C Fix\sa\sproblem\sin\sfts3/4\sthat\swas\scausing\sit\sto\sdiscard\sdata\scached\sin-memory\sif\san\s'optimize'\scommand\sis\srun\swhen\sthere\sis\sno\sdata\son\sdisk.\sThe\susual\sway\sthis\swould\shappen\sis\sif\sthe\svery\sfirst\stransaction\sthat\swrites\sto\sthe\sfts3/4\stable\salso\sincludes\san\s'optimize'\scommand. +D 2016-03-09T18:17:42.821 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -88,7 +88,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145 F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057 -F ext/fts3/fts3_write.c fb0456fa1407758f82458417c76fe4b06c86be98 +F ext/fts3/fts3_write.c c3863f23b6b4623c8b9d5cf31c12ce4469f78ca9 F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/fts3/tool/fts3view.c 5d78b668f4e9598af9147f8999632599fb0d9dd5 @@ -755,7 +755,7 @@ F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0 F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309 F test/fts4onepass.test 7319d61a2ed1325fc54afd0c060a0513b462303a -F test/fts4opt.test 1901f696214c4e16a995dd7fdd70576fc5c41dbe +F test/fts4opt.test fd6a11684b965e1999564ae763797b7fb9e34c96 F test/fts4unicode.test 27378af76394542cf490cf001d8d1505fe55f6a9 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef @@ -1455,7 +1455,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 d91e57e49f23414ec9211b775eb11cd6230a4f96 -R c1ca42221fb7dbc6b010dbeefd096918 -U drh -Z 8017c7a46c10555b3cc0af7ce0a6b14d +P 2c55c3c2950cafdc256ab540f60dc4609b9c354b +R b4dbf73ab3865664cce5c88a4214186d +U dan +Z a31e8746a8bf8afd08aed0fea525a7d3 diff --git a/manifest.uuid b/manifest.uuid index 41eb62d748..190da3e5ed 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2c55c3c2950cafdc256ab540f60dc4609b9c354b \ No newline at end of file +79338b991bf01e81d336790ca87a0fa747da4ff3 \ No newline at end of file diff --git a/test/fts4opt.test b/test/fts4opt.test index 1933c57b1b..0d0ed9f4f0 100644 --- a/test/fts4opt.test +++ b/test/fts4opt.test @@ -166,4 +166,48 @@ do_execsql_test 2.8 { SELECT level, count(*) FROM t2_segdir GROUP BY level; } {0 2 1024 2 2048 2 3072 2} +#------------------------------------------------------------------------- +# Check that 'optimize' works when there is data in the in-memory hash +# table, but no segments at all on disk. +# +do_execsql_test 3.1 { + CREATE VIRTUAL TABLE fts USING fts4 (t); + INSERT INTO fts (fts) VALUES ('optimize'); +} +do_execsql_test 3.2 { + INSERT INTO fts(fts) VALUES('integrity-check'); + SELECT count(*) FROM fts_segdir; +} {0} +do_execsql_test 3.3 { + BEGIN; + INSERT INTO fts (rowid, t) VALUES (2, 'test'); + INSERT INTO fts (fts) VALUES ('optimize'); + COMMIT; + SELECT level, idx FROM fts_segdir; +} {0 0} +do_execsql_test 3.4 { + INSERT INTO fts(fts) VALUES('integrity-check'); + SELECT rowid FROM fts WHERE fts MATCH 'test'; +} {2} +do_execsql_test 3.5 { + INSERT INTO fts (fts) VALUES ('optimize'); + INSERT INTO fts(fts) VALUES('integrity-check'); +} +do_test 3.6 { + set c1 [db total_changes] + execsql { INSERT INTO fts (fts) VALUES ('optimize') } + expr {[db total_changes] - $c1} +} {1} +do_test 3.7 { + execsql { INSERT INTO fts (rowid, t) VALUES (3, 'xyz') } + set c1 [db total_changes] + execsql { INSERT INTO fts (fts) VALUES ('optimize') } + expr {([db total_changes] - $c1) > 1} +} {1} +do_test 3.8 { + set c1 [db total_changes] + execsql { INSERT INTO fts (fts) VALUES ('optimize') } + expr {[db total_changes] - $c1} +} {1} + finish_test From 4dbc65b29a61ceab44fd5d0726a5d491f676ebb6 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 9 Mar 2016 20:54:14 +0000 Subject: [PATCH 448/570] Add an incremental optimize capability to fts5. Make the 'merge' command independent of the 'automerge' settings. FossilOrigin-Name: 556671444c03e3afca072d0f5e9bea2657de6fd3 --- ext/fts5/fts5Int.h | 1 + ext/fts5/fts5_config.c | 14 ++++ ext/fts5/fts5_index.c | 112 +++++++++++++++++++++++--------- ext/fts5/fts5_main.c | 6 +- ext/fts5/fts5_test_mi.c | 25 ++++--- ext/fts5/test/fts5_common.tcl | 6 ++ ext/fts5/test/fts5merge.test | 49 +++++++++++--- ext/fts5/test/fts5optimize.test | 41 +++++++++++- manifest | 26 ++++---- manifest.uuid | 2 +- 10 files changed, 213 insertions(+), 69 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index af40412167..f9e1567fb6 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -172,6 +172,7 @@ struct Fts5Config { int pgsz; /* Approximate page size used in %_data */ int nAutomerge; /* 'automerge' setting */ int nCrisisMerge; /* Maximum allowed segments per level */ + int nUsermerge; /* 'usermerge' setting */ int nHashSize; /* Bytes of memory for in-memory hash */ char *zRank; /* Name of rank function */ char *zRankArgs; /* Arguments to rank function */ diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c index f49cede129..ccc154c3b4 100644 --- a/ext/fts5/fts5_config.c +++ b/ext/fts5/fts5_config.c @@ -18,6 +18,7 @@ #define FTS5_DEFAULT_PAGE_SIZE 4050 #define FTS5_DEFAULT_AUTOMERGE 4 +#define FTS5_DEFAULT_USERMERGE 4 #define FTS5_DEFAULT_CRISISMERGE 16 #define FTS5_DEFAULT_HASHSIZE (1024*1024) @@ -857,6 +858,18 @@ int sqlite3Fts5ConfigSetValue( } } + else if( 0==sqlite3_stricmp(zKey, "usermerge") ){ + int nUsermerge = -1; + if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){ + nUsermerge = sqlite3_value_int(pVal); + } + if( nUsermerge<2 || nUsermerge>16 ){ + *pbBadkey = 1; + }else{ + pConfig->nUsermerge = nUsermerge; + } + } + else if( 0==sqlite3_stricmp(zKey, "crisismerge") ){ int nCrisisMerge = -1; if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){ @@ -903,6 +916,7 @@ int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){ /* Set default values */ pConfig->pgsz = FTS5_DEFAULT_PAGE_SIZE; pConfig->nAutomerge = FTS5_DEFAULT_AUTOMERGE; + pConfig->nUsermerge = FTS5_DEFAULT_USERMERGE; pConfig->nCrisisMerge = FTS5_DEFAULT_CRISISMERGE; pConfig->nHashSize = FTS5_DEFAULT_HASHSIZE; diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index ac97a7d75f..6f0b2d93cf 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -4179,13 +4179,17 @@ static void fts5IndexMergeLevel( /* ** Do up to nPg pages of automerge work on the index. +** +** Return true if any changes were actually made, or false otherwise. */ -static void fts5IndexMerge( +static int fts5IndexMerge( Fts5Index *p, /* FTS5 backend object */ Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */ - int nPg /* Pages of work to do */ + int nPg, /* Pages of work to do */ + int nMin /* Minimum number of segments to merge */ ){ int nRem = nPg; + int bRet = 0; Fts5Structure *pStruct = *ppStruct; while( nRem>0 && p->rc==SQLITE_OK ){ int iLvl; /* To iterate through levels */ @@ -4216,17 +4220,17 @@ static void fts5IndexMerge( } #endif - if( nBestpConfig->nAutomerge - && pStruct->aLevel[iBestLvl].nMerge==0 - ){ + if( nBestaLevel[iBestLvl].nMerge==0 ){ break; } + bRet = 1; fts5IndexMergeLevel(p, &pStruct, iBestLvl, &nRem); if( p->rc==SQLITE_OK && pStruct->aLevel[iBestLvl].nMerge==0 ){ fts5StructurePromote(p, iBestLvl+1, pStruct); } } *ppStruct = pStruct; + return bRet; } /* @@ -4254,7 +4258,7 @@ static void fts5IndexAutomerge( pStruct->nWriteCounter += nLeaf; nRem = (int)(p->nWorkUnit * nWork * pStruct->nLevel); - fts5IndexMerge(p, ppStruct, nRem); + fts5IndexMerge(p, ppStruct, nRem, p->pConfig->nAutomerge); } } @@ -4474,25 +4478,38 @@ static void fts5IndexFlush(Fts5Index *p){ } } - -int sqlite3Fts5IndexOptimize(Fts5Index *p){ - Fts5Structure *pStruct; +static Fts5Structure *fts5IndexOptimizeStruct( + Fts5Index *p, + Fts5Structure *pStruct +){ Fts5Structure *pNew = 0; - int nSeg = 0; + int nByte = sizeof(Fts5Structure); + int nSeg = pStruct->nSegment; + int i; - assert( p->rc==SQLITE_OK ); - fts5IndexFlush(p); - pStruct = fts5StructureRead(p); - - if( pStruct ){ - assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); - nSeg = pStruct->nSegment; - if( nSeg>1 ){ - int nByte = sizeof(Fts5Structure); - nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel); - pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte); + /* Figure out if this structure requires optimization. A structure does + ** not require optimization if either: + ** + ** + it consists of fewer than two segments, or + ** + all segments are on the same level, or + ** + all segments except one are currently inputs to a merge operation. + ** + ** In the first case, return NULL. In the second, increment the ref-count + ** on *pStruct and return a copy of the pointer to it. + */ + if( nSeg<2 ) return 0; + for(i=0; inLevel; i++){ + int nThis = pStruct->aLevel[i].nSeg; + if( nThis==nSeg || (nThis==nSeg-1 && pStruct->aLevel[i].nMerge==nThis) ){ + fts5StructureRef(pStruct); + return pStruct; } + assert( pStruct->aLevel[i].nMerge<=nThis ); } + + nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel); + pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte); + if( pNew ){ Fts5StructureLevel *pLvl; int nByte = nSeg * sizeof(Fts5StructureSegment); @@ -4520,8 +4537,28 @@ int sqlite3Fts5IndexOptimize(Fts5Index *p){ } } - if( pNew ){ - int iLvl = pNew->nLevel-1; + return pNew; +} + +int sqlite3Fts5IndexOptimize(Fts5Index *p){ + Fts5Structure *pStruct; + Fts5Structure *pNew = 0; + int nSeg = 0; + + assert( p->rc==SQLITE_OK ); + fts5IndexFlush(p); + pStruct = fts5StructureRead(p); + + if( pStruct ){ + pNew = fts5IndexOptimizeStruct(p, pStruct); + } + fts5StructureRelease(pStruct); + + if( pNew && pNew->nSegment>0 ){ + int iLvl; + for(iLvl=0; iLvlnLevel; iLvl++){ + if( pNew->aLevel[iLvl].nSeg ) break; + } while( p->rc==SQLITE_OK && pNew->aLevel[iLvl].nSeg>0 ){ int nRem = FTS5_OPT_WORK_UNIT; fts5IndexMergeLevel(p, &pNew, iLvl, &nRem); @@ -4531,20 +4568,31 @@ int sqlite3Fts5IndexOptimize(Fts5Index *p){ fts5StructureRelease(pNew); } - fts5StructureRelease(pStruct); return fts5IndexReturn(p); } +/* +** This is called to implement the special "VALUES('merge', $nMerge)" +** INSERT command. +*/ int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){ - Fts5Structure *pStruct; - - pStruct = fts5StructureRead(p); - if( pStruct && pStruct->nLevel ){ - fts5IndexMerge(p, &pStruct, nMerge); - fts5StructureWrite(p, pStruct); + Fts5Structure *pStruct = fts5StructureRead(p); + if( pStruct ){ + int nMin = p->pConfig->nUsermerge; + if( nMerge<0 ){ + Fts5Structure *pNew = fts5IndexOptimizeStruct(p, pStruct); + fts5StructureRelease(pStruct); + pStruct = pNew; + nMin = 2; + nMerge = nMerge*-1; + } + if( pStruct && pStruct->nLevel ){ + if( fts5IndexMerge(p, &pStruct, nMerge, nMin) ){ + fts5StructureWrite(p, pStruct); + } + } + fts5StructureRelease(pStruct); } - fts5StructureRelease(pStruct); - return fts5IndexReturn(p); } diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index 28f3f3e62c..dcd131c74a 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -1511,13 +1511,13 @@ static int fts5UpdateMethod( rc = SQLITE_ERROR; } - /* Case 1: DELETE */ + /* DELETE */ else if( nArg==1 ){ i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0); } - /* Case 2: INSERT */ + /* INSERT */ else if( eType0!=SQLITE_INTEGER ){ /* If this is a REPLACE, first remove the current entry (if any) */ if( eConflict==SQLITE_REPLACE @@ -1529,7 +1529,7 @@ static int fts5UpdateMethod( fts5StorageInsert(&rc, pTab, apVal, pRowid); } - /* Case 2: UPDATE */ + /* UPDATE */ else{ i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */ i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */ diff --git a/ext/fts5/fts5_test_mi.c b/ext/fts5/fts5_test_mi.c index bc6d01f126..a905b85bb9 100644 --- a/ext/fts5/fts5_test_mi.c +++ b/ext/fts5/fts5_test_mi.c @@ -68,18 +68,22 @@ struct Fts5MatchinfoCtx { ** If an error occurs, return NULL and leave an error in the database ** handle (accessible using sqlite3_errcode()/errmsg()). */ -static fts5_api *fts5_api_from_db(sqlite3 *db){ - fts5_api *pRet = 0; +static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi){ sqlite3_stmt *pStmt = 0; + int rc; - if( SQLITE_OK==sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0) - && SQLITE_ROW==sqlite3_step(pStmt) - && sizeof(pRet)==sqlite3_column_bytes(pStmt, 0) - ){ - memcpy(&pRet, sqlite3_column_blob(pStmt, 0), sizeof(pRet)); + *ppApi = 0; + rc = sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0); + if( rc==SQLITE_OK ){ + if( SQLITE_ROW==sqlite3_step(pStmt) + && sizeof(fts5_api*)==sqlite3_column_bytes(pStmt, 0) + ){ + memcpy(ppApi, sqlite3_column_blob(pStmt, 0), sizeof(fts5_api*)); + } + rc = sqlite3_finalize(pStmt); } - sqlite3_finalize(pStmt); - return pRet; + + return rc; } @@ -399,7 +403,8 @@ int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){ /* Extract the FTS5 API pointer from the database handle. The ** fts5_api_from_db() function above is copied verbatim from the ** FTS5 documentation. Refer there for details. */ - pApi = fts5_api_from_db(db); + rc = fts5_api_from_db(db, &pApi); + if( rc!=SQLITE_OK ) return rc; /* If fts5_api_from_db() returns NULL, then either FTS5 is not registered ** with this database handle, or an error (OOM perhaps?) has occurred. diff --git a/ext/fts5/test/fts5_common.tcl b/ext/fts5/test/fts5_common.tcl index 32691d1c81..0f371dcfd9 100644 --- a/ext/fts5/test/fts5_common.tcl +++ b/ext/fts5/test/fts5_common.tcl @@ -159,6 +159,12 @@ proc fts5_aux_test_functions {db} { } } +proc fts5_segcount {tbl} { + set N 0 + foreach n [fts5_level_segs $tbl] { incr N $n } + set N +} + proc fts5_level_segs {tbl} { set sql "SELECT fts5_decode(rowid,block) aS r FROM ${tbl}_data WHERE rowid=10" set ret [list] diff --git a/ext/fts5/test/fts5merge.test b/ext/fts5/test/fts5merge.test index 9dd1ecd026..48e3dce933 100644 --- a/ext/fts5/test/fts5merge.test +++ b/ext/fts5/test/fts5merge.test @@ -45,7 +45,7 @@ proc do_merge1_test {testname nRowPerSeg} { WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<$::nRowPerSeg) INSERT INTO x8 SELECT repeat('x y ', i % 16) FROM ii; - INSERT INTO x8(x8, rank) VALUES('automerge', 2); + INSERT INTO x8(x8, rank) VALUES('usermerge', 2); } for {set tn 1} {[lindex [fts5_level_segs x8] 0]>0} {incr tn} { @@ -84,9 +84,9 @@ proc do_merge2_test {testname nRow} { execsql { INSERT INTO x8 VALUES( rnddoc(($i%16) + 5) ) } while {[not_merged x8]} { execsql { - INSERT INTO x8(x8, rank) VALUES('automerge', 2); + INSERT INTO x8(x8, rank) VALUES('usermerge', 2); INSERT INTO x8(x8, rank) VALUES('merge', 1); - INSERT INTO x8(x8, rank) VALUES('automerge', 16); + INSERT INTO x8(x8, rank) VALUES('usermerge', 16); INSERT INTO x8(x8) VALUES('integrity-check'); } } @@ -104,9 +104,9 @@ do_merge2_test 2.2 10 do_merge2_test 2.3 20 #------------------------------------------------------------------------- -# Test that an auto-merge will complete any merge that has already been +# Test that a merge will complete any merge that has already been # started, even if the number of input segments is less than the current -# value of the 'automerge' configuration parameter. +# value of the 'usermerge' configuration parameter. # db func rnddoc fts5_rnddoc @@ -119,7 +119,7 @@ do_execsql_test 3.1 { } do_test 3.2 { execsql { - INSERT INTO x8(x8, rank) VALUES('automerge', 4); + INSERT INTO x8(x8, rank) VALUES('usermerge', 4); INSERT INTO x8(x8, rank) VALUES('merge', 1); } fts5_level_segs x8 @@ -127,14 +127,14 @@ do_test 3.2 { do_test 3.3 { execsql { - INSERT INTO x8(x8, rank) VALUES('automerge', 2); + INSERT INTO x8(x8, rank) VALUES('usermerge', 2); INSERT INTO x8(x8, rank) VALUES('merge', 1); } fts5_level_segs x8 } {2 1} do_test 3.4 { - execsql { INSERT INTO x8(x8, rank) VALUES('automerge', 4) } + execsql { INSERT INTO x8(x8, rank) VALUES('usermerge', 4) } while {[not_merged x8]} { execsql { INSERT INTO x8(x8, rank) VALUES('merge', 1) } } @@ -176,7 +176,7 @@ foreach {tn pgsz} { INSERT INTO x8 SELECT mydoc() FROM ii; WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100) INSERT INTO x8 SELECT mydoc() FROM ii; - INSERT INTO x8(x8, rank) VALUES('automerge', 2); + INSERT INTO x8(x8, rank) VALUES('usermerge', 2); } set expect [mycount] @@ -190,5 +190,36 @@ foreach {tn pgsz} { # db eval {SELECT fts5_decode(rowid, block) AS r FROM x8_data} { puts $r } } +#------------------------------------------------------------------------- +# Test that the 'merge' command does not modify the database if there is +# no work to do. + +do_execsql_test 5.1 { + CREATE VIRTUAL TABLE x9 USING fts5(one, two); + INSERT INTO x9(x9, rank) VALUES('pgsz', 32); + INSERT INTO x9(x9, rank) VALUES('automerge', 2); + INSERT INTO x9(x9, rank) VALUES('usermerge', 2); + INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); + INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); + INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); + INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); + INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); + INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); + INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); + INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); +} + +do_test 5.2 { + while 1 { + set nChange [db total_changes] + execsql { INSERT INTO x9(x9, rank) VALUES('merge', 1); } + set nChange [expr [db total_changes] - $nChange] + #puts $nChange + if {$nChange<2} break + } +} {} + + + finish_test diff --git a/ext/fts5/test/fts5optimize.test b/ext/fts5/test/fts5optimize.test index 984af8c532..48d4e1dd36 100644 --- a/ext/fts5/test/fts5optimize.test +++ b/ext/fts5/test/fts5optimize.test @@ -37,7 +37,6 @@ foreach {tn nStep} { 3 50 4 500 } { -if {$tn!=4} continue reset_db db func rnddoc rnddoc do_execsql_test 1.$tn.1 { @@ -60,6 +59,46 @@ if {$tn!=4} continue do_execsql_test 1.$tn.5 { INSERT INTO t1(t1) VALUES('integrity-check'); } + + do_test 1.$tn.6 { fts5_segcount t1 } 1 +} + +foreach {tn nStep} { + 1 2 + 2 10 + 3 50 + 4 500 +} { + reset_db + db func rnddoc rnddoc + do_execsql_test 1.$tn.1 { + CREATE VIRTUAL TABLE t1 USING fts5(x, y); + } + do_test 2.$tn.2 { + for {set i 0} {$i < $nStep} {incr i} { + execsql { INSERT INTO t1 VALUES( rnddoc(5), rnddoc(5) ) } + } + } {} + + do_execsql_test 2.$tn.3 { + INSERT INTO t1(t1) VALUES('integrity-check'); + } + + do_test 2.$tn.4 { + execsql { INSERT INTO t1(t1, rank) VALUES('merge', -1) } + while 1 { + set c [db total_changes] + execsql { INSERT INTO t1(t1, rank) VALUES('merge', 1) } + set c [expr [db total_changes]-$c] + if {$c<2} break + } + } {} + + do_execsql_test 2.$tn.5 { + INSERT INTO t1(t1) VALUES('integrity-check'); + } + + do_test 2.$tn.6 { fts5_segcount t1 } 1 } finish_test diff --git a/manifest b/manifest index 6d3b9274dd..590403a1e0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\sin\sfts3/4\sthat\swas\scausing\sit\sto\sdiscard\sdata\scached\sin-memory\sif\san\s'optimize'\scommand\sis\srun\swhen\sthere\sis\sno\sdata\son\sdisk.\sThe\susual\sway\sthis\swould\shappen\sis\sif\sthe\svery\sfirst\stransaction\sthat\swrites\sto\sthe\sfts3/4\stable\salso\sincludes\san\s'optimize'\scommand. -D 2016-03-09T18:17:42.821 +C Add\san\sincremental\soptimize\scapability\sto\sfts5.\sMake\sthe\s'merge'\scommand\sindependent\sof\sthe\s'automerge'\ssettings. +D 2016-03-09T20:54:14.606 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -98,17 +98,17 @@ F ext/fts3/unicode/mkunicode.tcl 2debed3f582d77b3fdd0b8830880250021571fd8 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 -F ext/fts5/fts5Int.h fa7c17e5c3ec9c8690387ff962f9dc6aee75e114 +F ext/fts5/fts5Int.h 59e13423371512df1992532a08fe80518244f96b F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458 F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd -F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079 +F ext/fts5/fts5_config.c abd3ae1107ca8b8def7445a0a3b70c2e46d05986 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c 26a4a6112864feb599a6f6144d06a78bb179736a -F ext/fts5/fts5_main.c db24ac714c6c4a1b3c24a1f8c25889f2952148c1 +F ext/fts5/fts5_index.c f7f3c042edf3e6a8984efa95ce1d5305d73bb535 +F ext/fts5/fts5_main.c b8501e1a6a11591c53b18ce7aea7e5386cfb0421 F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 -F ext/fts5/fts5_test_mi.c b8d04816428202b2898d4ca38deb1739ac0110ae +F ext/fts5/fts5_test_mi.c 783b86697ebf773c18fc109992426c0173a055bc F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8 F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf @@ -116,7 +116,7 @@ F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738 F ext/fts5/fts5_vocab.c dba72ca393d71c2588548b51380387f6b44c77a8 F ext/fts5/fts5parse.y 86fe6ba094a47e02fe8be2571539e6833d197764 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba -F ext/fts5/test/fts5_common.tcl b9b1fed811c0390511cef8b254826ea15d380f4d +F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841 F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b F ext/fts5/test/fts5ac.test 55cad4275a1f5acabfe14d8442a8046b47e49e5f @@ -162,11 +162,11 @@ F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741 F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d F ext/fts5/test/fts5matchinfo.test f7dde99697bcb310ea8faa8eb2714d9f4dfc0e1b -F ext/fts5/test/fts5merge.test 8f3cdba2ec9c5e7e568246e81b700ad37f764367 +F ext/fts5/test/fts5merge.test 9e04a16963e32bf7c51835ce23e58325bbdfb35f F ext/fts5/test/fts5merge2.test a6da3c16d694235938d1939f503cfa53f0943d75 F ext/fts5/test/fts5near.test b214cddb1c1f1bddf45c75af768f20145f7e71cc F ext/fts5/test/fts5onepass.test 7ed9608e258132cb8d55e7c479b08676ad68810c -F ext/fts5/test/fts5optimize.test 42741e7c085ee0a1276140a752d4407d97c2c9f5 +F ext/fts5/test/fts5optimize.test 0f25ce4cc1f78a4cf5dd1247d30135b3f7180a19 F ext/fts5/test/fts5phrase.test f6d1d464da5beb25dc56277aa4f1d6102f0d9a2f F ext/fts5/test/fts5plan.test 6a55ecbac9890765b0e16f8c421c7e0888cfe436 F ext/fts5/test/fts5porter.test 7cdc07bef301d70eebbfa75dcaf45c3680e1d0e1 @@ -1455,7 +1455,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 2c55c3c2950cafdc256ab540f60dc4609b9c354b -R b4dbf73ab3865664cce5c88a4214186d +P 79338b991bf01e81d336790ca87a0fa747da4ff3 +R a3916c8b307d01845fad235da028d539 U dan -Z a31e8746a8bf8afd08aed0fea525a7d3 +Z 1a31d386083951a3ddfabf8f6c0df92f diff --git a/manifest.uuid b/manifest.uuid index 190da3e5ed..39d9cd0036 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -79338b991bf01e81d336790ca87a0fa747da4ff3 \ No newline at end of file +556671444c03e3afca072d0f5e9bea2657de6fd3 \ No newline at end of file From 6459ca0b8ceb8a8ac6008c810667d7060836b939 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 10 Mar 2016 14:22:42 +0000 Subject: [PATCH 449/570] Remove an unused local variable. FossilOrigin-Name: 3c343c3d012367942037e64a9855b825cb459844 --- ext/fts5/fts5_index.c | 1 - manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 6f0b2d93cf..fc6c8e0f9b 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -4543,7 +4543,6 @@ static Fts5Structure *fts5IndexOptimizeStruct( int sqlite3Fts5IndexOptimize(Fts5Index *p){ Fts5Structure *pStruct; Fts5Structure *pNew = 0; - int nSeg = 0; assert( p->rc==SQLITE_OK ); fts5IndexFlush(p); diff --git a/manifest b/manifest index 590403a1e0..c0ca7ed9bb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\san\sincremental\soptimize\scapability\sto\sfts5.\sMake\sthe\s'merge'\scommand\sindependent\sof\sthe\s'automerge'\ssettings. -D 2016-03-09T20:54:14.606 +C Remove\san\sunused\slocal\svariable. +D 2016-03-10T14:22:42.064 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c abd3ae1107ca8b8def7445a0a3b70c2e46d05986 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c f7f3c042edf3e6a8984efa95ce1d5305d73bb535 +F ext/fts5/fts5_index.c 8def6f0ac63b960634674d9dc844244f39b4f25d F ext/fts5/fts5_main.c b8501e1a6a11591c53b18ce7aea7e5386cfb0421 F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -1455,7 +1455,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 79338b991bf01e81d336790ca87a0fa747da4ff3 -R a3916c8b307d01845fad235da028d539 -U dan -Z 1a31d386083951a3ddfabf8f6c0df92f +P 556671444c03e3afca072d0f5e9bea2657de6fd3 +R a2320da0e2fa85ffcb15f59a61bf4023 +U drh +Z c878404512f3f3f9c49842f23ff627b0 diff --git a/manifest.uuid b/manifest.uuid index 39d9cd0036..fba18405da 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -556671444c03e3afca072d0f5e9bea2657de6fd3 \ No newline at end of file +3c343c3d012367942037e64a9855b825cb459844 \ No newline at end of file From ecdf20d3a420d3c5d31238cae6422751f8be824c Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 10 Mar 2016 14:28:24 +0000 Subject: [PATCH 450/570] Use #ifdefs to remove code that is unreachable in some configurations, replacing it with an assert(). FossilOrigin-Name: f96ec84d605fd73c323344a753acf35b76307af9 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/util.c | 13 +++++++++---- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index c0ca7ed9bb..18172bf6eb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunused\slocal\svariable. -D 2016-03-10T14:22:42.064 +C Use\s#ifdefs\sto\sremove\scode\sthat\sis\sunreachable\sin\ssome\sconfigurations,\sreplacing\nit\swith\san\sassert(). +D 2016-03-10T14:28:24.490 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -413,7 +413,7 @@ F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c 56b3db7edff0110360a12b76af97c39ebe3ea8b8 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c -F src/util.c 12800a93f0664f41575f96799eb881a786d565e6 +F src/util.c 34ef7be420f82415ec48131404995ddb6ee7502f F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c 87ae3a5657fefed7875f3eb30e7ababd48013d71 F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 @@ -1455,7 +1455,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 556671444c03e3afca072d0f5e9bea2657de6fd3 -R a2320da0e2fa85ffcb15f59a61bf4023 +P 3c343c3d012367942037e64a9855b825cb459844 +R cc439e49a58b31085f4379adad06b3a4 U drh -Z c878404512f3f3f9c49842f23ff627b0 +Z ed62054916964b4fe2af635a90038c7e diff --git a/manifest.uuid b/manifest.uuid index fba18405da..765f18c2cc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3c343c3d012367942037e64a9855b825cb459844 \ No newline at end of file +f96ec84d605fd73c323344a753acf35b76307af9 \ No newline at end of file diff --git a/src/util.c b/src/util.c index 6aead47faa..d6a6f6b954 100644 --- a/src/util.c +++ b/src/util.c @@ -1424,9 +1424,14 @@ u64 sqlite3LogEstToInt(LogEst x){ x /= 10; if( n>=5 ) n -= 2; else if( n>=1 ) n -= 1; - if( x>=3 ){ - return x>60 ? (u64)LARGEST_INT64 : (n+8)<<(x-3); - } - return (n+8)>>(3-x); +#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ + defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) + if( x>60 ) return (u64)LARGEST_INT64; +#else + /* If only SQLITE_ENABLE_STAT3_OR_STAT4 is on, then the largest input + ** possible to this routine is 310, resulting in a maximum x of 31 */ + assert( x<=60 ); +#endif + return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x); } #endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */ From 1bb85f3ed342deb13bbe47c24dbd75f47a1e2e15 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 10 Mar 2016 15:12:47 +0000 Subject: [PATCH 451/570] Add tests to cover untested branches in recent fts5 changes. FossilOrigin-Name: fa0033edf6ddf3c6631fa95b343225dbc8ac9429 --- ext/fts5/fts5_index.c | 7 +++---- ext/fts5/test/fts5config.test | 16 ++++++++++++++++ ext/fts5/test/fts5fault8.test | 25 +++++++++++++++++++++++++ ext/fts5/test/fts5merge.test | 19 +++++++++++++++++++ ext/fts5/test/fts5optimize.test | 8 ++++++-- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- 7 files changed, 81 insertions(+), 18 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index fc6c8e0f9b..323e6cefdc 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -4553,11 +4553,10 @@ int sqlite3Fts5IndexOptimize(Fts5Index *p){ } fts5StructureRelease(pStruct); - if( pNew && pNew->nSegment>0 ){ + assert( pNew==0 || pNew->nSegment>0 ); + if( pNew ){ int iLvl; - for(iLvl=0; iLvlnLevel; iLvl++){ - if( pNew->aLevel[iLvl].nSeg ) break; - } + for(iLvl=0; pNew->aLevel[iLvl].nSeg==0; iLvl++){} while( p->rc==SQLITE_OK && pNew->aLevel[iLvl].nSeg>0 ){ int nRem = FTS5_OPT_WORK_UNIT; fts5IndexMergeLevel(p, &pNew, iLvl, &nRem); diff --git a/ext/fts5/test/fts5config.test b/ext/fts5/test/fts5config.test index c30a597242..386d112e7d 100644 --- a/ext/fts5/test/fts5config.test +++ b/ext/fts5/test/fts5config.test @@ -247,5 +247,21 @@ do_catchsql_test 12.1 { INSERT INTO t1(t1, rank) VALUES('rank', NULL);; } {1 {SQL logic error or missing database}} +#------------------------------------------------------------------------- +# errors in the 'usermerge' option +# +do_execsql_test 13.0 { + CREATE VIRTUAL TABLE tt USING fts5(ttt); +} +foreach {tn val} { + 1 -1 + 2 4.2 + 3 17 + 4 1 +} { + set sql "INSERT INTO tt(tt, rank) VALUES('usermerge', $val)" + do_catchsql_test 13.$tn $sql {1 {SQL logic error or missing database}} +} + finish_test diff --git a/ext/fts5/test/fts5fault8.test b/ext/fts5/test/fts5fault8.test index ae5849495b..c613490e54 100644 --- a/ext/fts5/test/fts5fault8.test +++ b/ext/fts5/test/fts5fault8.test @@ -54,7 +54,32 @@ foreach_detail_mode $testprefix { faultsim_test_result {0 {1 3}} {1 SQLITE_NOMEM} } } + } ;# foreach_detail_mode... + +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE x2 USING fts5(a); + INSERT INTO x2(x2, rank) VALUES('crisismerge', 2); + INSERT INTO x2(x2, rank) VALUES('pgsz', 32); + INSERT INTO x2 VALUES('a b c d'); + INSERT INTO x2 VALUES('e f g h'); + INSERT INTO x2 VALUES('i j k l'); + INSERT INTO x2 VALUES('m n o p'); + INSERT INTO x2 VALUES('q r s t'); + INSERT INTO x2 VALUES('u v w x'); + INSERT INTO x2 VALUES('y z a b'); +} +faultsim_save_and_close + +do_faultsim_test 4 -faults oom-* -prep { + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO x2(x2) VALUES('optimize') } +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} +} + + finish_test diff --git a/ext/fts5/test/fts5merge.test b/ext/fts5/test/fts5merge.test index 48e3dce933..73e006a7d2 100644 --- a/ext/fts5/test/fts5merge.test +++ b/ext/fts5/test/fts5merge.test @@ -220,6 +220,25 @@ do_test 5.2 { } {} +#-------------------------------------------------------------------------- +# Test that running 'merge' on an empty database does not cause a +# problem. +# +reset_db +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE g1 USING fts5(a, b); +} +do_execsql_test 6.1 { + INSERT INTO g1(g1, rank) VALUES('merge', 10); +} +do_execsql_test 6.2 { + INSERT INTO g1(g1, rank) VALUES('merge', -10); +} +do_execsql_test 6.3 { + INSERT INTO g1(g1) VALUES('integrity-check'); +} + + finish_test diff --git a/ext/fts5/test/fts5optimize.test b/ext/fts5/test/fts5optimize.test index 48d4e1dd36..3ef6d8a165 100644 --- a/ext/fts5/test/fts5optimize.test +++ b/ext/fts5/test/fts5optimize.test @@ -20,6 +20,12 @@ ifcapable !fts5 { return } +# +# 1.* - Warm body tests for index optimization using ('optimize') +# +# 2.* - Warm body tests for index optimization using ('merge', -1) +# + proc rnddoc {nWord} { set vocab {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 z} set nVocab [llength $vocab] @@ -30,7 +36,6 @@ proc rnddoc {nWord} { return $ret } - foreach {tn nStep} { 1 2 2 10 @@ -100,6 +105,5 @@ foreach {tn nStep} { do_test 2.$tn.6 { fts5_segcount t1 } 1 } - finish_test diff --git a/manifest b/manifest index 18172bf6eb..238a295d30 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\s#ifdefs\sto\sremove\scode\sthat\sis\sunreachable\sin\ssome\sconfigurations,\sreplacing\nit\swith\san\sassert(). -D 2016-03-10T14:28:24.490 +C Add\stests\sto\scover\suntested\sbranches\sin\srecent\sfts5\schanges. +D 2016-03-10T15:12:47.687 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c abd3ae1107ca8b8def7445a0a3b70c2e46d05986 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c 8def6f0ac63b960634674d9dc844244f39b4f25d +F ext/fts5/fts5_index.c d4f0c12e4f04bbc3a06b6da052039f2ce3e45438 F ext/fts5/fts5_main.c b8501e1a6a11591c53b18ce7aea7e5386cfb0421 F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -136,7 +136,7 @@ F ext/fts5/test/fts5auxdata.test 141a7cbffcceb1bd2799b4b29c183ff8780d586e F ext/fts5/test/fts5bigpl.test 04ee0d7eebbebf17c31f5a0b5c5f9494eac3a0cb F ext/fts5/test/fts5bigtok.test 017a9397b14e7598883a6328ead4a6539b42d59a F ext/fts5/test/fts5columnsize.test a8cfef21ffa1c264b9f670a7d94eeaccb5341c07 -F ext/fts5/test/fts5config.test 8b2bc6dcc0eb06fa2b7dd65b2ce2db09e829e873 +F ext/fts5/test/fts5config.test 7788b9c058074d640dfcdd81d97b6a9480000368 F ext/fts5/test/fts5conflict.test 26f4e46c4d31e16221794832a990dc4e30e18de5 F ext/fts5/test/fts5content.test 9a952c95518a14182dc3b59e3c8fa71cda82a4e1 F ext/fts5/test/fts5corrupt.test c2ad090192708150d50d961278df10ae7a4b8b62 @@ -154,7 +154,7 @@ F ext/fts5/test/fts5fault4.test 532b6dacb963016cbf7003196bd87fb366540277 F ext/fts5/test/fts5fault5.test 10c13a783de3f42a21e3e53e123b62ed0c3a1618 F ext/fts5/test/fts5fault6.test 9682664d679643ac6736e90c225526cc84073cda F ext/fts5/test/fts5fault7.test cb14ea3c1f42394f06f2284abc58eecee6ff8080 -F ext/fts5/test/fts5fault8.test 430837fe6dd0511fd3aea52bd602ac02441bcb58 +F ext/fts5/test/fts5fault8.test 6785af34bd1760de74e2824ea9c161965af78f85 F ext/fts5/test/fts5fault9.test e10e395428a9ea0596ebe752ff7123d16ab78e08 F ext/fts5/test/fts5faultA.test fa5d59c0ff62b7125cd14eee38ded1c46e15a7ea F ext/fts5/test/fts5faultB.test 92ae906284062bf081b6c854afa54dcb1aa9ef88 @@ -162,11 +162,11 @@ F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741 F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d F ext/fts5/test/fts5matchinfo.test f7dde99697bcb310ea8faa8eb2714d9f4dfc0e1b -F ext/fts5/test/fts5merge.test 9e04a16963e32bf7c51835ce23e58325bbdfb35f +F ext/fts5/test/fts5merge.test 9f65f090d214ff865c56bef4f864aaa1182af6e3 F ext/fts5/test/fts5merge2.test a6da3c16d694235938d1939f503cfa53f0943d75 F ext/fts5/test/fts5near.test b214cddb1c1f1bddf45c75af768f20145f7e71cc F ext/fts5/test/fts5onepass.test 7ed9608e258132cb8d55e7c479b08676ad68810c -F ext/fts5/test/fts5optimize.test 0f25ce4cc1f78a4cf5dd1247d30135b3f7180a19 +F ext/fts5/test/fts5optimize.test 9d3ac53bb9cae58cb070d795db86bcb2f9fec105 F ext/fts5/test/fts5phrase.test f6d1d464da5beb25dc56277aa4f1d6102f0d9a2f F ext/fts5/test/fts5plan.test 6a55ecbac9890765b0e16f8c421c7e0888cfe436 F ext/fts5/test/fts5porter.test 7cdc07bef301d70eebbfa75dcaf45c3680e1d0e1 @@ -1455,7 +1455,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 3c343c3d012367942037e64a9855b825cb459844 -R cc439e49a58b31085f4379adad06b3a4 -U drh -Z ed62054916964b4fe2af635a90038c7e +P f96ec84d605fd73c323344a753acf35b76307af9 +R 051c67540d0eafc760e9e2909fb96246 +U dan +Z d3ddde89c58a1d5ab316ef215efd6168 diff --git a/manifest.uuid b/manifest.uuid index 765f18c2cc..74d9440081 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f96ec84d605fd73c323344a753acf35b76307af9 \ No newline at end of file +fa0033edf6ddf3c6631fa95b343225dbc8ac9429 \ No newline at end of file From a0ca3bc854908494190f5a2d727e5269dbe48d3e Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 10 Mar 2016 19:08:44 +0000 Subject: [PATCH 452/570] Check for PDB files prior to attempting to copy them in the MSVC batch build tool. FossilOrigin-Name: d7c20f04e69fb1848b2e2f3b04fbd56e06c7c854 --- manifest | 14 +++++++------- manifest.uuid | 2 +- tool/build-all-msvc.bat | 20 ++++++++++++-------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 238a295d30..5ec513ed1c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sto\scover\suntested\sbranches\sin\srecent\sfts5\schanges. -D 2016-03-10T15:12:47.687 +C Check\sfor\sPDB\sfiles\sprior\sto\sattempting\sto\scopy\sthem\sin\sthe\sMSVC\sbatch\sbuild\stool. +D 2016-03-10T19:08:44.973 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1374,7 +1374,7 @@ F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372 F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91 F tool/addopcodes.tcl 2b089684eb8b7d0db64cf9d8e6d2fe1b6d279e8d -F tool/build-all-msvc.bat 55be1cf8545dabd69df2ba6b3de6868da0c26f52 x +F tool/build-all-msvc.bat 3e4e4043b53f1aede4308e0d2567bbd773614630 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 @@ -1455,7 +1455,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 f96ec84d605fd73c323344a753acf35b76307af9 -R 051c67540d0eafc760e9e2909fb96246 -U dan -Z d3ddde89c58a1d5ab316ef215efd6168 +P fa0033edf6ddf3c6631fa95b343225dbc8ac9429 +R 306b8c821d3092af90856b15d0070f67 +U mistachkin +Z c66ddc08ff47a327984a1b8fcbda8cec diff --git a/manifest.uuid b/manifest.uuid index 74d9440081..b9cc10f12d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fa0033edf6ddf3c6631fa95b343225dbc8ac9429 \ No newline at end of file +d7c20f04e69fb1848b2e2f3b04fbd56e06c7c854 \ No newline at end of file diff --git a/tool/build-all-msvc.bat b/tool/build-all-msvc.bat index c96708cef5..ae8b76af5a 100755 --- a/tool/build-all-msvc.bat +++ b/tool/build-all-msvc.bat @@ -665,11 +665,13 @@ FOR %%P IN (%PLATFORMS%) DO ( REM are prevented from doing so. REM IF NOT DEFINED NOSYMBOLS ( - %__ECHO% XCOPY "%DLL_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% + IF EXIST "%DLL_PDB_FILE_NAME%" ( + %__ECHO% XCOPY "%DLL_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% - IF ERRORLEVEL 1 ( - ECHO Failed to copy "%DLL_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\". - GOTO errors + IF ERRORLEVEL 1 ( + ECHO Failed to copy "%DLL_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\". + GOTO errors + ) ) ) @@ -722,11 +724,13 @@ FOR %%P IN (%PLATFORMS%) DO ( REM unless we are prevented from doing so. REM IF NOT DEFINED NOSYMBOLS ( - %__ECHO% XCOPY "%EXE_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% + IF EXIST "%EXE_PDB_FILE_NAME%" ( + %__ECHO% XCOPY "%EXE_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% - IF ERRORLEVEL 1 ( - ECHO Failed to copy "%EXE_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\". - GOTO errors + IF ERRORLEVEL 1 ( + ECHO Failed to copy "%EXE_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\". + GOTO errors + ) ) ) ) From 811f17bac031aec31626304edb95313ba3a0217b Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 11 Mar 2016 14:30:18 +0000 Subject: [PATCH 453/570] Update spellfix1_scriptcode() to output 215 (latin) for pure numeric text. FossilOrigin-Name: df44308b862e932ff0ad25b6328d13be22047b96 --- ext/misc/spellfix.c | 10 ++++++++-- manifest | 16 ++++++++-------- manifest.uuid | 2 +- test/spellfix3.test | 11 ++++++++++- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/ext/misc/spellfix.c b/ext/misc/spellfix.c index 5734d04f41..b5859ea2c8 100644 --- a/ext/misc/spellfix.c +++ b/ext/misc/spellfix.c @@ -1734,6 +1734,7 @@ static void scriptCodeSqlFunc( int c, sz; int scriptMask = 0; int res; + int seenDigit = 0; # define SCRIPT_LATIN 0x0001 # define SCRIPT_CYRILLIC 0x0002 # define SCRIPT_GREEK 0x0004 @@ -1744,8 +1745,12 @@ static void scriptCodeSqlFunc( c = utf8Read(zIn, nIn, &sz); zIn += sz; nIn -= sz; - if( c<0x02af && (c>=0x80 || midClass[c&0x7f]=0x80 || midClass[c&0x7f]='0' && c<='9' ){ + seenDigit = 1; + } }else if( c>=0x0400 && c<=0x04ff ){ scriptMask |= SCRIPT_CYRILLIC; }else if( c>=0x0386 && c<=0x03ce ){ @@ -1756,6 +1761,7 @@ static void scriptCodeSqlFunc( scriptMask |= SCRIPT_ARABIC; } } + if( scriptMask==0 && seenDigit ) scriptMask = SCRIPT_LATIN; switch( scriptMask ){ case 0: res = 999; break; case SCRIPT_LATIN: res = 215; break; diff --git a/manifest b/manifest index 5ec513ed1c..b0746bb445 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Check\sfor\sPDB\sfiles\sprior\sto\sattempting\sto\scopy\sthem\sin\sthe\sMSVC\sbatch\sbuild\stool. -D 2016-03-10T19:08:44.973 +C Update\sspellfix1_scriptcode()\sto\soutput\s215\s(latin)\sfor\spure\snumeric\stext. +D 2016-03-11T14:30:18.667 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -214,7 +214,7 @@ F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a F ext/misc/series.c e11e534ada797d5b816d7e7a93c022306563ca35 F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 -F ext/misc/spellfix.c 194b5fc3a9a63cb6c5680d8f713800012bddca7c +F ext/misc/spellfix.c 598bbc45516227701558becdd38f4e6fe8e97cc2 F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e @@ -1059,7 +1059,7 @@ F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b F test/speedtest1.c 1478cb3fb64ad30f291ddca87ca9dbd72ff552aa F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3 -F test/spellfix3.test f7bf7b3482971473d32b6b00f6944c5c066cff97 +F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33 F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5 F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142 F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a @@ -1455,7 +1455,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 fa0033edf6ddf3c6631fa95b343225dbc8ac9429 -R 306b8c821d3092af90856b15d0070f67 -U mistachkin -Z c66ddc08ff47a327984a1b8fcbda8cec +P d7c20f04e69fb1848b2e2f3b04fbd56e06c7c854 +R 6aa12144d3c644bf9edbd83316218d69 +U drh +Z c13ed9f7b14004f5942c430b85f3af01 diff --git a/manifest.uuid b/manifest.uuid index b9cc10f12d..12423c25d8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d7c20f04e69fb1848b2e2f3b04fbd56e06c7c854 \ No newline at end of file +df44308b862e932ff0ad25b6328d13be22047b96 \ No newline at end of file diff --git a/test/spellfix3.test b/test/spellfix3.test index ce002edd4f..e24ea31ee7 100644 --- a/test/spellfix3.test +++ b/test/spellfix3.test @@ -35,9 +35,18 @@ do_execsql_test 140 { } {160} do_execsql_test 200 { SELECT spellfix1_scriptcode('+3.14159'); -} {999} +} {215} do_execsql_test 210 { SELECT spellfix1_scriptcode('And God said: "Да будет свет"'); } {998} +do_execsql_test 220 { + SELECT spellfix1_scriptcode('+3.14159 light'); +} {215} +do_execsql_test 230 { + SELECT spellfix1_scriptcode('+3.14159 свет'); +} {220} +do_execsql_test 240 { + SELECT spellfix1_scriptcode('וַיֹּ֥אמֶר +3.14159'); +} {125} finish_test From e1f1ffa55acfad0770ee0a4828515decb658610b Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 11 Mar 2016 15:25:13 +0000 Subject: [PATCH 454/570] Tweak the amalgamation autoconf files so that the --disable-static-shell option works again. FossilOrigin-Name: 83efcdebfa255cd0663ecc6b74eb99183e2f3a10 --- autoconf/Makefile.am | 5 +++-- autoconf/configure.ac | 2 +- manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/autoconf/Makefile.am b/autoconf/Makefile.am index 7b6934adde..cca23ba67d 100644 --- a/autoconf/Makefile.am +++ b/autoconf/Makefile.am @@ -6,8 +6,9 @@ libsqlite3_la_SOURCES = sqlite3.c libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8 bin_PROGRAMS = sqlite3 -sqlite3_SOURCES = shell.c sqlite3.c sqlite3.h -sqlite3_LDADD = @READLINE_LIBS@ +sqlite3_SOURCES = shell.c sqlite3.h +EXTRA_sqlite3_SOURCES = sqlite3.c +sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@ sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@ sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS diff --git a/autoconf/configure.ac b/autoconf/configure.ac index 9492530680..f86a39c37b 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -130,7 +130,7 @@ AC_ARG_ENABLE(static-shell, [AS_HELP_STRING( [statically link libsqlite3 into shell tool [default=yes]])], [], [enable_static_shell=yes]) if test x"$enable_static_shell" == "xyes"; then - EXTRA_SHELL_OBJ=sqlite3.$OBJEXT + EXTRA_SHELL_OBJ=sqlite3-sqlite3.$OBJEXT else EXTRA_SHELL_OBJ=libsqlite3.la fi diff --git a/manifest b/manifest index b0746bb445..5e5214e2d2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sspellfix1_scriptcode()\sto\soutput\s215\s(latin)\sfor\spure\snumeric\stext. -D 2016-03-11T14:30:18.667 +C Tweak\sthe\samalgamation\sautoconf\sfiles\sso\sthat\sthe\s--disable-static-shell\soption\sworks\sagain. +D 2016-03-11T15:25:13.462 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -10,11 +10,11 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 -F autoconf/Makefile.am 4b8bd7896fffb6b22a57747f1f98cba1da9108ae +F autoconf/Makefile.am 42f7eb1fb2b06ddd6c6adab3e4388cc0a237ba40 F autoconf/Makefile.msc b8ada5177e6f39c126a88295af5ad0255e08d280 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1 -F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8 +F autoconf/configure.ac d807b567f73a2b0986ccdd206b782cecb4d08fff F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43 @@ -1455,7 +1455,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 d7c20f04e69fb1848b2e2f3b04fbd56e06c7c854 -R 6aa12144d3c644bf9edbd83316218d69 -U drh -Z c13ed9f7b14004f5942c430b85f3af01 +P df44308b862e932ff0ad25b6328d13be22047b96 +R 19b1fa38a58d00a667be85fd411c2202 +U dan +Z bd858a2f3f6240bb0acfbf97ee308bf8 diff --git a/manifest.uuid b/manifest.uuid index 12423c25d8..d06900f0e6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -df44308b862e932ff0ad25b6328d13be22047b96 \ No newline at end of file +83efcdebfa255cd0663ecc6b74eb99183e2f3a10 \ No newline at end of file From ffbb02a36169fddc4eec4dc156b1b23bb1c2744b Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 11 Mar 2016 23:07:30 +0000 Subject: [PATCH 455/570] Do not allow the use of WAL mode with nolock=1 because it does not work. FossilOrigin-Name: 74f5d3b07f6e5e977858c73957c6f9337ae3ca3e --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/pager.c | 1 + test/nolock.test | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 5e5214e2d2..eb0ce7dd6e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Tweak\sthe\samalgamation\sautoconf\sfiles\sso\sthat\sthe\s--disable-static-shell\soption\sworks\sagain. -D 2016-03-11T15:25:13.462 +C Do\snot\sallow\sthe\suse\sof\sWAL\smode\swith\snolock=1\sbecause\sit\sdoes\snot\swork. +D 2016-03-11T23:07:30.911 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -336,7 +336,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c f5bac8e74aaefc4ea520e43b4540793c3b8a9e8f F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c 2d950142528e5d9b291a1160443d7ade0d90700d +F src/pager.c 38718a019ca762ba4f6795425d5a54db70d1790d F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df @@ -915,7 +915,7 @@ F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4 F test/mutex1.test e0a44072d98189003deae4b091106f085d94bea8 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a -F test/nolock.test 0540dd96f39b8876e3ffdd8814fad0ea425efeee +F test/nolock.test 96e922d2d3db71c2dd6557c98e8027a28277b415 F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161 F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934 @@ -1455,7 +1455,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 df44308b862e932ff0ad25b6328d13be22047b96 -R 19b1fa38a58d00a667be85fd411c2202 -U dan -Z bd858a2f3f6240bb0acfbf97ee308bf8 +P 83efcdebfa255cd0663ecc6b74eb99183e2f3a10 +R 95ba30529f9bfc1f4da2d6ab93334cdc +U drh +Z 5b477c118f77a96b5b851b408af856c1 diff --git a/manifest.uuid b/manifest.uuid index d06900f0e6..3b0b773e3e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -83efcdebfa255cd0663ecc6b74eb99183e2f3a10 \ No newline at end of file +74f5d3b07f6e5e977858c73957c6f9337ae3ca3e \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 316a5e8ec0..c18b3a32f7 100644 --- a/src/pager.c +++ b/src/pager.c @@ -7167,6 +7167,7 @@ int sqlite3PagerWalCallback(Pager *pPager){ */ int sqlite3PagerWalSupported(Pager *pPager){ const sqlite3_io_methods *pMethods = pPager->fd->pMethods; + if( pPager->noLock ) return 0; return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap); } diff --git a/test/nolock.test b/test/nolock.test index 331af08ad7..fdaef6ef07 100644 --- a/test/nolock.test +++ b/test/nolock.test @@ -182,4 +182,36 @@ do_test nolock-3.12 { db2 close db close tvfs delete + +# 2016-03-11: Make sure all works when transitioning to WAL mode under nolock. +# +do_test nolock-4.1 { + forcedelete test.db + sqlite3 db file:test.db?nolock=1 -uri 1 + db eval { + PRAGMA journal_mode=WAL; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES('youngling'); + SELECT * FROM t1; + } +} {delete youngling} +db close + +do_test nolock-4.2 { + forcedelete test.db + sqlite3 db test.db + db eval { + PRAGMA journal_mode=WAL; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES('catbird'); + SELECT * FROM t1; + } +} {wal catbird} +do_test nolock-4.3 { + db close + sqlite3 db file:test.db?nolock=1 -uri 1 + set rc [catch {db eval {SELECT * FROM t1}} msg] + lappend rc $msg +} {1 {unable to open database file}} + finish_test From e8c20120ce388253bcf5671b2aaf77348305272d Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 12 Mar 2016 16:32:16 +0000 Subject: [PATCH 456/570] Fix handling of strings that contain zero tokens in fts5. And other problems found by fuzzing. FossilOrigin-Name: 72b3ff0f0df83e62adda6584b4281cf086d45e45 --- ext/fts5/fts5Int.h | 6 ++ ext/fts5/fts5_config.c | 4 +- ext/fts5/fts5_expr.c | 150 ++++++++++++++++++++++++++--------- ext/fts5/fts5parse.y | 2 +- ext/fts5/test/fts5eb.test | 12 +-- ext/fts5/test/fts5fuzz1.test | 89 +++++++++++++++++++++ manifest | 23 +++--- manifest.uuid | 2 +- 8 files changed, 232 insertions(+), 56 deletions(-) create mode 100644 ext/fts5/test/fts5fuzz1.test diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index f9e1567fb6..35f15abbaf 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -701,6 +701,12 @@ Fts5ExprNode *sqlite3Fts5ParseNode( Fts5ExprNearset *pNear ); +Fts5ExprNode *sqlite3Fts5ParseImplicitAnd( + Fts5Parse *pParse, + Fts5ExprNode *pLeft, + Fts5ExprNode *pRight +); + Fts5ExprPhrase *sqlite3Fts5ParseTerm( Fts5Parse *pParse, Fts5ExprPhrase *pPhrase, diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c index ccc154c3b4..17fc43e011 100644 --- a/ext/fts5/fts5_config.c +++ b/ext/fts5/fts5_config.c @@ -442,7 +442,9 @@ static const char *fts5ConfigGobbleWord( *pbQuoted = 1; }else{ zRet = fts5ConfigSkipBareword(zIn); - zOut[zRet-zIn] = '\0'; + if( zRet ){ + zOut[zRet-zIn] = '\0'; + } } } diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index d3f801b022..153d1c6472 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -1268,6 +1268,8 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ if( Fts5NodeIsString(pNode) ){ /* Initialize all term iterators in the NEAR object. */ rc = fts5ExprNearInitAll(pExpr, pNode); + }else if( pNode->xNext==0 ){ + pNode->bEof = 1; }else{ int i; int nEof = 0; @@ -1319,23 +1321,22 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ */ int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){ Fts5ExprNode *pRoot = p->pRoot; - int rc = SQLITE_OK; - if( pRoot->xNext ){ - p->pIndex = pIdx; - p->bDesc = bDesc; - rc = fts5ExprNodeFirst(p, pRoot); + int rc; /* Return code */ - /* If not at EOF but the current rowid occurs earlier than iFirst in - ** the iteration order, move to document iFirst or later. */ - if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){ - rc = fts5ExprNodeNext(p, pRoot, 1, iFirst); - } + p->pIndex = pIdx; + p->bDesc = bDesc; + rc = fts5ExprNodeFirst(p, pRoot); - /* If the iterator is not at a real match, skip forward until it is. */ - while( pRoot->bNomatch ){ - assert( pRoot->bEof==0 && rc==SQLITE_OK ); - rc = fts5ExprNodeNext(p, pRoot, 0, 0); - } + /* If not at EOF but the current rowid occurs earlier than iFirst in + ** the iteration order, move to document iFirst or later. */ + if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){ + rc = fts5ExprNodeNext(p, pRoot, 1, iFirst); + } + + /* If the iterator is not at a real match, skip forward until it is. */ + while( pRoot->bNomatch ){ + assert( pRoot->bEof==0 && rc==SQLITE_OK ); + rc = fts5ExprNodeNext(p, pRoot, 0, 0); } return rc; } @@ -1476,8 +1477,7 @@ static int fts5ParseTokenize( /* If an error has already occurred, this is a no-op */ if( pCtx->rc!=SQLITE_OK ) return pCtx->rc; - assert( pPhrase==0 || pPhrase->nTerm>0 ); - if( pPhrase && (tflags & FTS5_TOKEN_COLOCATED) ){ + if( pPhrase && pPhrase->nTerm>0 && (tflags & FTS5_TOKEN_COLOCATED) ){ Fts5ExprTerm *pSyn; int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1; pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte); @@ -1578,7 +1578,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm( pParse->rc = rc; fts5ExprPhraseFree(sCtx.pPhrase); sCtx.pPhrase = 0; - }else if( sCtx.pPhrase ){ + }else{ if( pAppend==0 ){ if( (pParse->nPhrase % 8)==0 ){ @@ -1595,9 +1595,14 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm( pParse->nPhrase++; } + if( sCtx.pPhrase==0 ){ + /* This happens when parsing a token or quoted phrase that contains + ** no token characters at all. (e.g ... MATCH '""'). */ + sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase)); + }else if( sCtx.pPhrase->nTerm ){ + sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix; + } pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase; - assert( sCtx.pPhrase->nTerm>0 ); - sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix; } return sCtx.pPhrase; @@ -1693,23 +1698,25 @@ void sqlite3Fts5ParseSetDistance( Fts5ExprNearset *pNear, Fts5Token *p ){ - int nNear = 0; - int i; - if( p->n ){ - for(i=0; in; i++){ - char c = (char)p->p[i]; - if( c<'0' || c>'9' ){ - sqlite3Fts5ParseError( - pParse, "expected integer, got \"%.*s\"", p->n, p->p - ); - return; + if( pNear ){ + int nNear = 0; + int i; + if( p->n ){ + for(i=0; in; i++){ + char c = (char)p->p[i]; + if( c<'0' || c>'9' ){ + sqlite3Fts5ParseError( + pParse, "expected integer, got \"%.*s\"", p->n, p->p + ); + return; + } + nNear = nNear * 10 + (p->p[i] - '0'); } - nNear = nNear * 10 + (p->p[i] - '0'); + }else{ + nNear = FTS5_DEFAULT_NEARDIST; } - }else{ - nNear = FTS5_DEFAULT_NEARDIST; + pNear->nNear = nNear; } - pNear->nNear = nNear; } /* @@ -1896,10 +1903,14 @@ Fts5ExprNode *sqlite3Fts5ParseNode( int iPhrase; for(iPhrase=0; iPhrasenPhrase; iPhrase++){ pNear->apPhrase[iPhrase]->pNode = pRet; + if( pNear->apPhrase[iPhrase]->nTerm==0 ){ + pRet->xNext = 0; + pRet->eType = FTS5_EOF; + } } if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL - && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm!=1) + && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm>1) ){ assert( pParse->rc==SQLITE_OK ); pParse->rc = SQLITE_ERROR; @@ -1928,6 +1939,70 @@ Fts5ExprNode *sqlite3Fts5ParseNode( return pRet; } +Fts5ExprNode *sqlite3Fts5ParseImplicitAnd( + Fts5Parse *pParse, /* Parse context */ + Fts5ExprNode *pLeft, /* Left hand child expression */ + Fts5ExprNode *pRight /* Right hand child expression */ +){ + Fts5ExprNode *pRet = 0; + Fts5ExprNode *pPrev; + + if( pParse->rc ){ + sqlite3Fts5ParseNodeFree(pLeft); + sqlite3Fts5ParseNodeFree(pRight); + }else{ + + assert( pLeft->eType==FTS5_STRING + || pLeft->eType==FTS5_TERM + || pLeft->eType==FTS5_EOF + || pLeft->eType==FTS5_AND + ); + assert( pRight->eType==FTS5_STRING + || pRight->eType==FTS5_TERM + || pRight->eType==FTS5_EOF + ); + + if( pLeft->eType==FTS5_AND ){ + pPrev = pLeft->apChild[pLeft->nChild-1]; + }else{ + pPrev = pLeft; + } + assert( pPrev->eType==FTS5_STRING + || pPrev->eType==FTS5_TERM + || pPrev->eType==FTS5_EOF + ); + + if( pRight->eType==FTS5_EOF ){ + assert( pParse->apPhrase[pParse->nPhrase-1]==pRight->pNear->apPhrase[0] ); + sqlite3Fts5ParseNodeFree(pRight); + pRet = pLeft; + pParse->nPhrase--; + } + else if( pPrev->eType==FTS5_EOF ){ + Fts5ExprPhrase **ap; + + if( pPrev==pLeft ){ + pRet = pRight; + }else{ + pLeft->apChild[pLeft->nChild-1] = pRight; + pRet = pLeft; + } + + ap = &pParse->apPhrase[pParse->nPhrase-1-pRight->pNear->nPhrase]; + assert( ap[0]==pPrev->pNear->apPhrase[0] ); + memmove(ap, &ap[1], sizeof(Fts5ExprPhrase*)*pRight->pNear->nPhrase); + pParse->nPhrase--; + + sqlite3Fts5ParseNodeFree(pPrev); + } + else{ + pRet = sqlite3Fts5ParseNode(pParse, FTS5_AND, pLeft, pRight, 0); + } + } + + return pRet; +} + static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){ int nByte = 0; Fts5ExprTerm *p; @@ -2062,6 +2137,9 @@ static char *fts5ExprPrintTcl( static char *fts5ExprPrint(Fts5Config *pConfig, Fts5ExprNode *pExpr){ char *zRet = 0; + if( pExpr->eType==0 ){ + return sqlite3_mprintf("\"\""); + }else if( pExpr->eType==FTS5_STRING || pExpr->eType==FTS5_TERM ){ Fts5ExprNearset *pNear = pExpr->pNear; int i; @@ -2122,7 +2200,7 @@ static char *fts5ExprPrint(Fts5Config *pConfig, Fts5ExprNode *pExpr){ zRet = 0; }else{ int e = pExpr->apChild[i]->eType; - int b = (e!=FTS5_STRING && e!=FTS5_TERM); + int b = (e!=FTS5_STRING && e!=FTS5_TERM && e!=FTS5_EOF); zRet = fts5PrintfAppend(zRet, "%s%s%z%s", (i==0 ? "" : zOp), (b?"(":""), z, (b?")":"") diff --git a/ext/fts5/fts5parse.y b/ext/fts5/fts5parse.y index 2bdf4b09b2..1607d3846a 100644 --- a/ext/fts5/fts5parse.y +++ b/ext/fts5/fts5parse.y @@ -104,7 +104,7 @@ expr(A) ::= exprlist(X). {A = X;} exprlist(A) ::= cnearset(X). {A = X;} exprlist(A) ::= exprlist(X) cnearset(Y). { - A = sqlite3Fts5ParseNode(pParse, FTS5_AND, X, Y, 0); + A = sqlite3Fts5ParseImplicitAnd(pParse, X, Y); } cnearset(A) ::= nearset(X). { diff --git a/ext/fts5/test/fts5eb.test b/ext/fts5/test/fts5eb.test index 8205396047..69418aae63 100644 --- a/ext/fts5/test/fts5eb.test +++ b/ext/fts5/test/fts5eb.test @@ -33,12 +33,12 @@ foreach {tn expr res} { 1 {abc} {"abc"} 2 {abc ""} {"abc"} 3 {""} {} - 4 {abc OR ""} {"abc"} - 5 {abc NOT ""} {"abc"} - 6 {abc AND ""} {"abc"} - 7 {"" OR abc} {"abc"} - 8 {"" NOT abc} {"abc"} - 9 {"" AND abc} {"abc"} + 4 {abc OR ""} {"abc" OR ""} + 5 {abc NOT ""} {"abc" NOT ""} + 6 {abc AND ""} {"abc" AND ""} + 7 {"" OR abc} {"" OR "abc"} + 8 {"" NOT abc} {"" NOT "abc"} + 9 {"" AND abc} {"" AND "abc"} 10 {abc + "" + def} {"abc" + "def"} 11 {abc "" def} {"abc" AND "def"} 12 {r+e OR w} {"r" + "e" OR "w"} diff --git a/ext/fts5/test/fts5fuzz1.test b/ext/fts5/test/fts5fuzz1.test new file mode 100644 index 0000000000..638620d025 --- /dev/null +++ b/ext/fts5/test/fts5fuzz1.test @@ -0,0 +1,89 @@ +# 2014 June 17 +# +# 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. The +# focus of this script is testing the FTS5 module. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +return_if_no_fts5 +set testprefix fts5fuzz1 + + +#------------------------------------------------------------------------- +reset_db +do_catchsql_test 1.1 { + CREATE VIRTUAL TABLE f1 USING fts5(a b); +} {/1 {parse error in.*}/} + + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 2.1 { + CREATE VIRTUAL TABLE f1 USING fts5(a, b); + INSERT INTO f1 VALUES('a b', 'c d'); + INSERT INTO f1 VALUES('e f', 'a b'); +} + +do_execsql_test 2.2.1 { + SELECT rowid FROM f1('""'); +} {} + +do_execsql_test 2.2.2 { + SELECT rowid FROM f1('"" AND a'); +} {} + + +do_execsql_test 2.2.3 { + SELECT rowid FROM f1('"" a'); +} {1 2} + +do_execsql_test 2.2.4 { + SELECT rowid FROM f1('"" OR a'); +} {1 2} + +do_execsql_test 2.3 { + SELECT a, b FROM f1('NEAR("")'); +} {} + +do_execsql_test 2.4 { + SELECT a, b FROM f1('NEAR("", 5)'); +} {} + +do_execsql_test 2.5 { + SELECT a, b FROM f1('NEAR("" c, 5)'); +} {} + +do_execsql_test 2.6 { + SELECT a, b FROM f1('NEAR("" c d, 5)'); +} {} + +do_execsql_test 2.7 { + SELECT a, b FROM f1('NEAR(c d, 5)'); +} {{a b} {c d}} + +do_execsql_test 2.8 { + SELECT rowid FROM f1('NEAR("a" "b", 5)'); +} {1 2} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 3.2 { + CREATE VIRTUAL TABLE f2 USING fts5(o, t, tokenize="ascii separators abc"); + SELECT * FROM f2('a+4'); +} {} + + + + + +finish_test + + diff --git a/manifest b/manifest index eb0ce7dd6e..b9bfda53ca 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sallow\sthe\suse\sof\sWAL\smode\swith\snolock=1\sbecause\sit\sdoes\snot\swork. -D 2016-03-11T23:07:30.911 +C Fix\shandling\sof\sstrings\sthat\scontain\szero\stokens\sin\sfts5.\sAnd\sother\sproblems\sfound\sby\sfuzzing. +D 2016-03-12T16:32:16.002 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -98,11 +98,11 @@ F ext/fts3/unicode/mkunicode.tcl 2debed3f582d77b3fdd0b8830880250021571fd8 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 -F ext/fts5/fts5Int.h 59e13423371512df1992532a08fe80518244f96b +F ext/fts5/fts5Int.h 4060504b7979601d99e1385c2b5713036854979a F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458 F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd -F ext/fts5/fts5_config.c abd3ae1107ca8b8def7445a0a3b70c2e46d05986 -F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337 +F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 +F ext/fts5/fts5_expr.c c4166ba0de2e87c444a7eedc8623e32653138ca0 F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 F ext/fts5/fts5_index.c d4f0c12e4f04bbc3a06b6da052039f2ce3e45438 F ext/fts5/fts5_main.c b8501e1a6a11591c53b18ce7aea7e5386cfb0421 @@ -114,7 +114,7 @@ F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8 F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738 F ext/fts5/fts5_vocab.c dba72ca393d71c2588548b51380387f6b44c77a8 -F ext/fts5/fts5parse.y 86fe6ba094a47e02fe8be2571539e6833d197764 +F ext/fts5/fts5parse.y fcc5e92e570d38cab38488b2109cbf67468923b2 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841 F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 @@ -146,7 +146,7 @@ F ext/fts5/test/fts5detail.test ef5c690535a797413acaf5ad9b8ab5d49972df69 F ext/fts5/test/fts5dlidx.test 13871a14641017ae42f6f1055a8067bafd44cb3d F ext/fts5/test/fts5doclist.test 8edb5b57e5f144030ed74ec00ef6fa4294fed79b F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0 -F ext/fts5/test/fts5eb.test 021aa80b7ac09b964249aa32ced9ee908703e4aa +F ext/fts5/test/fts5eb.test c516ae0c934be6fd29ec95ea8b5f11f461311535 F ext/fts5/test/fts5fault1.test e09040d3e17b8c0837101e8c79c8a874c4376fb7 F ext/fts5/test/fts5fault2.test d8c6c7f916ccbdfc10b2c69530e9dd3bc8313232 F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3 @@ -159,6 +159,7 @@ F ext/fts5/test/fts5fault9.test e10e395428a9ea0596ebe752ff7123d16ab78e08 F ext/fts5/test/fts5faultA.test fa5d59c0ff62b7125cd14eee38ded1c46e15a7ea F ext/fts5/test/fts5faultB.test 92ae906284062bf081b6c854afa54dcb1aa9ef88 F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741 +F ext/fts5/test/fts5fuzz1.test 7a6411c39959d8f4cb8f11e840a787e74a3bfbef F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d F ext/fts5/test/fts5matchinfo.test f7dde99697bcb310ea8faa8eb2714d9f4dfc0e1b @@ -1455,7 +1456,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 83efcdebfa255cd0663ecc6b74eb99183e2f3a10 -R 95ba30529f9bfc1f4da2d6ab93334cdc -U drh -Z 5b477c118f77a96b5b851b408af856c1 +P 74f5d3b07f6e5e977858c73957c6f9337ae3ca3e +R 561f4a7c15c16c270cfb03e11b79c482 +U dan +Z 78cc445fb6679cc3e05486871c5dafe8 diff --git a/manifest.uuid b/manifest.uuid index 3b0b773e3e..00db2d08b1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -74f5d3b07f6e5e977858c73957c6f9337ae3ca3e \ No newline at end of file +72b3ff0f0df83e62adda6584b4281cf086d45e45 \ No newline at end of file From 5cf98f101e1a475ed4572d405edf56c5244162d4 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 12 Mar 2016 19:33:47 +0000 Subject: [PATCH 457/570] Fix a problem handling 'NEAR("" token)' in fts5 found by fuzzing. FossilOrigin-Name: 10a827ae5f3f322af836c15e581fdc958a433a5a --- ext/fts5/fts5_expr.c | 15 +++++++++++++++ ext/fts5/test/fts5fuzz1.test | 4 ++-- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index 153d1c6472..26ee3f9472 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -1445,6 +1445,21 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset( sqlite3Fts5ParseNearsetFree(pNear); sqlite3Fts5ParsePhraseFree(pPhrase); }else{ + if( pRet->nPhrase>0 ){ + Fts5ExprPhrase *pLast = pRet->apPhrase[pRet->nPhrase-1]; + assert( pLast==pParse->apPhrase[pParse->nPhrase-2] ); + if( pPhrase->nTerm==0 ){ + fts5ExprPhraseFree(pPhrase); + pRet->nPhrase--; + pParse->nPhrase--; + pPhrase = pLast; + }else if( pLast->nTerm==0 ){ + fts5ExprPhraseFree(pLast); + pParse->apPhrase[pParse->nPhrase-2] = pPhrase; + pParse->nPhrase--; + pRet->nPhrase--; + } + } pRet->apPhrase[pRet->nPhrase++] = pPhrase; } return pRet; diff --git a/ext/fts5/test/fts5fuzz1.test b/ext/fts5/test/fts5fuzz1.test index 638620d025..326229181d 100644 --- a/ext/fts5/test/fts5fuzz1.test +++ b/ext/fts5/test/fts5fuzz1.test @@ -59,11 +59,11 @@ do_execsql_test 2.4 { do_execsql_test 2.5 { SELECT a, b FROM f1('NEAR("" c, 5)'); -} {} +} {{a b} {c d}} do_execsql_test 2.6 { SELECT a, b FROM f1('NEAR("" c d, 5)'); -} {} +} {{a b} {c d}} do_execsql_test 2.7 { SELECT a, b FROM f1('NEAR(c d, 5)'); diff --git a/manifest b/manifest index b9bfda53ca..4616625054 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\shandling\sof\sstrings\sthat\scontain\szero\stokens\sin\sfts5.\sAnd\sother\sproblems\sfound\sby\sfuzzing. -D 2016-03-12T16:32:16.002 +C Fix\sa\sproblem\shandling\s'NEAR(""\stoken)'\sin\sfts5\sfound\sby\sfuzzing. +D 2016-03-12T19:33:47.637 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -102,7 +102,7 @@ F ext/fts5/fts5Int.h 4060504b7979601d99e1385c2b5713036854979a F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458 F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 -F ext/fts5/fts5_expr.c c4166ba0de2e87c444a7eedc8623e32653138ca0 +F ext/fts5/fts5_expr.c f11757a251346df38c04fd67d0703fbb0c084ef7 F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 F ext/fts5/fts5_index.c d4f0c12e4f04bbc3a06b6da052039f2ce3e45438 F ext/fts5/fts5_main.c b8501e1a6a11591c53b18ce7aea7e5386cfb0421 @@ -159,7 +159,7 @@ F ext/fts5/test/fts5fault9.test e10e395428a9ea0596ebe752ff7123d16ab78e08 F ext/fts5/test/fts5faultA.test fa5d59c0ff62b7125cd14eee38ded1c46e15a7ea F ext/fts5/test/fts5faultB.test 92ae906284062bf081b6c854afa54dcb1aa9ef88 F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741 -F ext/fts5/test/fts5fuzz1.test 7a6411c39959d8f4cb8f11e840a787e74a3bfbef +F ext/fts5/test/fts5fuzz1.test 74b638ca214b91614cadb2de14e6269385819e99 F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d F ext/fts5/test/fts5matchinfo.test f7dde99697bcb310ea8faa8eb2714d9f4dfc0e1b @@ -1456,7 +1456,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 74f5d3b07f6e5e977858c73957c6f9337ae3ca3e -R 561f4a7c15c16c270cfb03e11b79c482 +P 72b3ff0f0df83e62adda6584b4281cf086d45e45 +R f6701c1b7c325b06b9e793bf0b9b6f39 U dan -Z 78cc445fb6679cc3e05486871c5dafe8 +Z ac91e536ca766cb3c7d727597fcc6975 diff --git a/manifest.uuid b/manifest.uuid index 00db2d08b1..c16d8c43cd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -72b3ff0f0df83e62adda6584b4281cf086d45e45 \ No newline at end of file +10a827ae5f3f322af836c15e581fdc958a433a5a \ No newline at end of file From 7d85774da81c3352df1a53ff3634e96b0403a6af Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 14 Mar 2016 12:16:23 +0000 Subject: [PATCH 458/570] Fix a memory leak in fts5 that could occur following a syntax error in a query expression. FossilOrigin-Name: 54b8968e335760105206b894672213c1d56771a4 --- ext/fts5/fts5_expr.c | 2 ++ ext/fts5/test/fts5fuzz1.test | 8 ++++++-- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index 26ee3f9472..1e9be8117d 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -258,6 +258,8 @@ int sqlite3Fts5ExprNew( pNew->nPhrase = sParse.nPhrase; sParse.apPhrase = 0; } + }else{ + sqlite3Fts5ParseNodeFree(sParse.pExpr); } sqlite3_free(sParse.apPhrase); diff --git a/ext/fts5/test/fts5fuzz1.test b/ext/fts5/test/fts5fuzz1.test index 326229181d..599d7bcc89 100644 --- a/ext/fts5/test/fts5fuzz1.test +++ b/ext/fts5/test/fts5fuzz1.test @@ -82,8 +82,12 @@ do_execsql_test 3.2 { - +#------------------------------------------------------------------------- +reset_db +do_catchsql_test 4.1 { + CREATE VIRTUAL TABLE f2 USING fts5(o, t); + SELECT * FROM f2('(8 AND 9)`AND 10'); +} {1 {fts5: syntax error near "`"}} finish_test - diff --git a/manifest b/manifest index 4616625054..437c838595 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\shandling\s'NEAR(""\stoken)'\sin\sfts5\sfound\sby\sfuzzing. -D 2016-03-12T19:33:47.637 +C Fix\sa\smemory\sleak\sin\sfts5\sthat\scould\soccur\sfollowing\sa\ssyntax\serror\sin\sa\squery\sexpression. +D 2016-03-14T12:16:23.063 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -102,7 +102,7 @@ F ext/fts5/fts5Int.h 4060504b7979601d99e1385c2b5713036854979a F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458 F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 -F ext/fts5/fts5_expr.c f11757a251346df38c04fd67d0703fbb0c084ef7 +F ext/fts5/fts5_expr.c be309fb227003c931107bfcc12d5be4f2fd2bb8c F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 F ext/fts5/fts5_index.c d4f0c12e4f04bbc3a06b6da052039f2ce3e45438 F ext/fts5/fts5_main.c b8501e1a6a11591c53b18ce7aea7e5386cfb0421 @@ -159,7 +159,7 @@ F ext/fts5/test/fts5fault9.test e10e395428a9ea0596ebe752ff7123d16ab78e08 F ext/fts5/test/fts5faultA.test fa5d59c0ff62b7125cd14eee38ded1c46e15a7ea F ext/fts5/test/fts5faultB.test 92ae906284062bf081b6c854afa54dcb1aa9ef88 F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741 -F ext/fts5/test/fts5fuzz1.test 74b638ca214b91614cadb2de14e6269385819e99 +F ext/fts5/test/fts5fuzz1.test bece4695fc169b61ab236ada7931c6e4942cbef9 F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d F ext/fts5/test/fts5matchinfo.test f7dde99697bcb310ea8faa8eb2714d9f4dfc0e1b @@ -1456,7 +1456,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 72b3ff0f0df83e62adda6584b4281cf086d45e45 -R f6701c1b7c325b06b9e793bf0b9b6f39 +P 10a827ae5f3f322af836c15e581fdc958a433a5a +R 044bc4807e350ab5b23a4e059317d425 U dan -Z ac91e536ca766cb3c7d727597fcc6975 +Z 7cd8dbc9719c56da8d0f172ae33ba6b2 diff --git a/manifest.uuid b/manifest.uuid index c16d8c43cd..d8fc8d0201 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -10a827ae5f3f322af836c15e581fdc958a433a5a \ No newline at end of file +54b8968e335760105206b894672213c1d56771a4 \ No newline at end of file From d5704a8961a237d07ad8c58ec550e439bf7e9ca9 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 14 Mar 2016 13:42:29 +0000 Subject: [PATCH 459/570] Run TCL tests in a subdirectory "testdir". FossilOrigin-Name: f632bba0d6ad3edc60f4127380ce8320378dac42 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- test/analyzer1.test | 9 ++++++--- test/tester.tcl | 13 ++++++++++++- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 437c838595..be4618cf04 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\smemory\sleak\sin\sfts5\sthat\scould\soccur\sfollowing\sa\ssyntax\serror\sin\sa\squery\sexpression. -D 2016-03-14T12:16:23.063 +C Run\sTCL\stests\sin\sa\ssubdirectory\s"testdir". +D 2016-03-14T13:42:29.333 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -460,7 +460,7 @@ F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93 F test/analyzeD.test 42af58de25a6436502e43006e9e59e2d71bcb0cf F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d F test/analyzeF.test 5d1fe1024ba2dfea3c18bede8c1ccef8aba1ab34 -F test/analyzer1.test 498e2ff4b62740c2751c3a2f8b744fe26689fae9 +F test/analyzer1.test 459fa02c445ddbf0101a3bad47b34290a35f2e49 F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7 @@ -1085,7 +1085,7 @@ F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl 750365ff97047ded5f2d6e28df82a998f7c66ae0 +F test/tester.tcl 5e4888b6bfa9862716531c085a7d450d80427884 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1456,7 +1456,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 10a827ae5f3f322af836c15e581fdc958a433a5a -R 044bc4807e350ab5b23a4e059317d425 -U dan -Z 7cd8dbc9719c56da8d0f172ae33ba6b2 +P 54b8968e335760105206b894672213c1d56771a4 +R 51c96c83fefb55fe62e20e36b1c079f2 +U drh +Z ad4f0a6837143665327a52812ce6dad2 diff --git a/manifest.uuid b/manifest.uuid index d8fc8d0201..837a8076f0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -54b8968e335760105206b894672213c1d56771a4 \ No newline at end of file +f632bba0d6ad3edc60f4127380ce8320378dac42 \ No newline at end of file diff --git a/test/analyzer1.test b/test/analyzer1.test index ac46704fba..51b5f8b6af 100644 --- a/test/analyzer1.test +++ b/test/analyzer1.test @@ -25,9 +25,12 @@ if {$tcl_platform(platform)=="windows"} { set PROG "./sqlite3_analyzer" } if {![file exe $PROG]} { - puts "analyzer1 cannot run because $PROG is not available" - finish_test - return + set PROG [file normalize [file join $::cmdlinearg(TESTFIXTURE_HOME) $PROG]] + if {![file exe $PROG]} { + puts "analyzer1 cannot run because $PROG is not available" + finish_test + return + } } db close forcedelete test.db test.db-journal test.db-wal diff --git a/test/tester.tcl b/test/tester.tcl index 231cef5333..e8d41fd4a2 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -411,6 +411,8 @@ if {[info exists cmdlinearg]==0} { # --match=$pattern # --verbose=$val # --output=$filename + # -q Reduce output + # --testdir=$dir Run tests in subdirectory $dir # --help # set cmdlinearg(soft-heap-limit) 0 @@ -425,6 +427,7 @@ if {[info exists cmdlinearg]==0} { set cmdlinearg(match) "" set cmdlinearg(verbose) "" set cmdlinearg(output) "" + set cmdlinearg(testdir) "testdir" set leftover [list] foreach a $argv { @@ -498,6 +501,9 @@ if {[info exists cmdlinearg]==0} { error "option --verbose= must be set to a boolean or to \"file\"" } } + {^-+testdir=.*$} { + foreach {dummy cmdlinearg(testdir)} [split $a =] break + } {.*help.*} { print_help_and_quit } @@ -507,10 +513,15 @@ if {[info exists cmdlinearg]==0} { } default { - lappend leftover $a + lappend leftover [file normalize $a] } } } + set cmdlinearg(TESTFIXTURE_HOME) [pwd] + if {$cmdlinearg(testdir)!=""} { + file mkdir $cmdlinearg(testdir) + cd $cmdlinearg(testdir) + } set argv $leftover # Install the malloc layer used to inject OOM errors. And the 'automatic' From bea14132cf8f814e52de30676f098c94a50c49b9 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 14 Mar 2016 14:28:43 +0000 Subject: [PATCH 460/570] Normalize the $testdir and $argv0 paths so that they continue to work in the testing subdirectory. FossilOrigin-Name: 19225b8130f1640772fc54250583b571a89063b6 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/tester.tcl | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index be4618cf04..8f5aa6a6b2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Run\sTCL\stests\sin\sa\ssubdirectory\s"testdir". -D 2016-03-14T13:42:29.333 +C Normalize\sthe\s$testdir\sand\s$argv0\spaths\sso\sthat\sthey\scontinue\sto\swork\nin\sthe\stesting\ssubdirectory. +D 2016-03-14T14:28:43.708 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1085,7 +1085,7 @@ F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl 5e4888b6bfa9862716531c085a7d450d80427884 +F test/tester.tcl 91d34b1d829a25b63ad79160fafce8d626f433ef F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1456,7 +1456,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 54b8968e335760105206b894672213c1d56771a4 -R 51c96c83fefb55fe62e20e36b1c079f2 +P f632bba0d6ad3edc60f4127380ce8320378dac42 +R 22b406abedcbf80fe60cfc67f5d3bedf U drh -Z ad4f0a6837143665327a52812ce6dad2 +Z 43e678777243a6003b283ca0fdf3c95b diff --git a/manifest.uuid b/manifest.uuid index 837a8076f0..63fbc091c0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f632bba0d6ad3edc60f4127380ce8320378dac42 \ No newline at end of file +19225b8130f1640772fc54250583b571a89063b6 \ No newline at end of file diff --git a/test/tester.tcl b/test/tester.tcl index e8d41fd4a2..d8b37579a6 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -517,7 +517,9 @@ if {[info exists cmdlinearg]==0} { } } } + set testdir [file normalize $testdir] set cmdlinearg(TESTFIXTURE_HOME) [pwd] + set argv0 [file normalize $argv0] if {$cmdlinearg(testdir)!=""} { file mkdir $cmdlinearg(testdir) cd $cmdlinearg(testdir) From e500f65a2c4b1d5df8053c33bc697721cf7733f3 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 14 Mar 2016 14:59:35 +0000 Subject: [PATCH 461/570] More file pathname normalization. FossilOrigin-Name: fa8c12921f8361f1889724bb7c5f7eca9c48b075 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/tester.tcl | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 8f5aa6a6b2..5c365e1771 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Normalize\sthe\s$testdir\sand\s$argv0\spaths\sso\sthat\sthey\scontinue\sto\swork\nin\sthe\stesting\ssubdirectory. -D 2016-03-14T14:28:43.708 +C More\sfile\spathname\snormalization. +D 2016-03-14T14:59:35.248 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1085,7 +1085,7 @@ F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl 91d34b1d829a25b63ad79160fafce8d626f433ef +F test/tester.tcl 8fbf071b23ec66ce9bb8607fc92fdc4326393697 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1456,7 +1456,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 f632bba0d6ad3edc60f4127380ce8320378dac42 -R 22b406abedcbf80fe60cfc67f5d3bedf +P 19225b8130f1640772fc54250583b571a89063b6 +R e6d4ff0cfaea5c603741eca2f2c0aea1 U drh -Z 43e678777243a6003b283ca0fdf3c95b +Z f2a7315c22032835cedc7ee778272809 diff --git a/manifest.uuid b/manifest.uuid index 63fbc091c0..4c4029ef69 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -19225b8130f1640772fc54250583b571a89063b6 \ No newline at end of file +fa8c12921f8361f1889724bb7c5f7eca9c48b075 \ No newline at end of file diff --git a/test/tester.tcl b/test/tester.tcl index d8b37579a6..6dc507f70e 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -457,6 +457,7 @@ if {[info exists cmdlinearg]==0} { } {^-+binarylog=.+$} { foreach {dummy cmdlinearg(binarylog)} [split $a =] break + set cmdlinearg(binarylog) [file normalize $cmdlinearg(binarylog)] } {^-+soak=.+$} { foreach {dummy cmdlinearg(soak)} [split $a =] break @@ -489,6 +490,7 @@ if {[info exists cmdlinearg]==0} { {^-+output=.+$} { foreach {dummy cmdlinearg(output)} [split $a =] break + set cmdlinearg(output) [file normalize $cmdlinearg(output)] if {$cmdlinearg(verbose)==""} { set cmdlinearg(verbose) 2 } From de503eb166ce4c0f4a392ce2084e1de2741f6d61 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 14 Mar 2016 15:43:03 +0000 Subject: [PATCH 462/570] Fix the backcompat.test script so that it works with the --testdir test option. FossilOrigin-Name: f7480e33eb82f2eae219d17ce46cd2d4edac07d2 --- manifest | 17 ++++++++--------- manifest.uuid | 2 +- test/backcompat.test | 3 ++- test/bc_common.tcl | 5 +++-- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 8cf8ea024d..73224a31d8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Run\sTCL\stests\sin\sthe\s"testdir"\ssubdirectory. -D 2016-03-14T15:03:54.569 +C Fix\sthe\sbackcompat.test\sscript\sso\sthat\sit\sworks\swith\sthe\s--testdir\stest\soption. +D 2016-03-14T15:43:03.210 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -484,7 +484,7 @@ F test/autoindex5.test 96f084a5e6024ea07cace5888df3223f3ea86990 F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74 F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4 F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85 -F test/backcompat.test 28403f43d11624e696c5ef134c7c7d81015cd19e +F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d F test/backup.test b79299a536a4c6d919094786595b95be56d02014 F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf F test/backup4.test 2a2e4a64388090b152de753fd9e123f28f6a3bd4 @@ -493,7 +493,7 @@ F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135 F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450 F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f -F test/bc_common.tcl 3eda41ef9cda7d5f6c205462c96228b301da4191 +F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c F test/bestindex1.test d5ba89a7941a941476d8d69be39b146aaed3614c F test/bestindex2.test 4a06b8922ab2fd09434870da8d1cdf525aaf7060 F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c @@ -1456,8 +1456,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 54b8968e335760105206b894672213c1d56771a4 fa8c12921f8361f1889724bb7c5f7eca9c48b075 -R e6d4ff0cfaea5c603741eca2f2c0aea1 -T +closed fa8c12921f8361f1889724bb7c5f7eca9c48b075 -U drh -Z 3e9e43a77139e0aba2725db0c4d642ac +P 90e0cc7b0be31ee2f155c2c053b0cbac584f6154 +R 02e42b4c9a3b088e9b811e95ac0b8895 +U dan +Z adf33e3278f777c691b4da9ad8602fb1 diff --git a/manifest.uuid b/manifest.uuid index 365f26434f..352d970249 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -90e0cc7b0be31ee2f155c2c053b0cbac584f6154 \ No newline at end of file +f7480e33eb82f2eae219d17ce46cd2d4edac07d2 \ No newline at end of file diff --git a/test/backcompat.test b/test/backcompat.test index fe8a83f0a6..87ffc4b3ea 100644 --- a/test/backcompat.test +++ b/test/backcompat.test @@ -85,7 +85,8 @@ proc do_allbackcompat_test {script} { set nErr [set_test_counter errors] foreach dir {0 1} { - set bintag [string map {testfixture {}} $bin] + set bintag $bin + regsub {.*testfixture\.} $bintag {} bintag set bintag [string map {\.exe {}} $bintag] if {$bintag == ""} {set bintag self} set ::bcname ".$bintag.$dir." diff --git a/test/bc_common.tcl b/test/bc_common.tcl index 78010dfa46..c47f99681f 100644 --- a/test/bc_common.tcl +++ b/test/bc_common.tcl @@ -7,7 +7,7 @@ proc bc_find_binaries {zCaption} { # against. # set binaries [list] - set self [file tail [info nameofexec]] + set self [info nameofexec] set pattern "$self?*" if {$::tcl_platform(platform)=="windows"} { set pattern [string map {\.exe {}} $pattern] @@ -52,7 +52,8 @@ proc do_bc_test {bin script} { code1 { sqlite3 db test.db } code2 { sqlite3 db test.db } - set bintag [string map {testfixture {}} $bin] + set bintag $bin + regsub {.*testfixture\.} $bintag {} bintag set bintag [string map {\.exe {}} $bintag] if {$bintag == ""} {set bintag self} set saved_prefix $::testprefix From 7bd6b49a3e03818b60e58b5aa0eeacd29a0b643a Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 14 Mar 2016 16:16:43 +0000 Subject: [PATCH 463/570] Test script changes to support testing the SQLite Encryption Extension. FossilOrigin-Name: 1c70aa5c014fc48ab06215992a61c6f92490abe4 --- manifest | 22 ++++++++++++---------- manifest.uuid | 2 +- test/autovacuum.test | 17 ++++++++++++++--- test/e_uri.test | 2 +- test/superlock.test | 1 + test/walbak.test | 1 + 6 files changed, 30 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 8cf8ea024d..320c150381 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Run\sTCL\stests\sin\sthe\s"testdir"\ssubdirectory. -D 2016-03-14T15:03:54.569 +C Test\sscript\schanges\sto\ssupport\stesting\sthe\sSQLite\sEncryption\sExtension. +D 2016-03-14T16:16:43.649 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -481,7 +481,7 @@ F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972 F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf F test/autoindex5.test 96f084a5e6024ea07cace5888df3223f3ea86990 -F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74 +F test/autovacuum.test 92c24eedbdb68e49f3fb71f26f9ce6d8988cac15 F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4 F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85 F test/backcompat.test 28403f43d11624e696c5ef134c7c7d81015cd19e @@ -616,7 +616,7 @@ F test/e_select.test 52692ff3849541e828ad4661fe3773a9b8711763 F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10 F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528 -F test/e_uri.test eed3eb41b22d051a1164110dacdc778899126e14 +F test/e_uri.test 25385396082b67fd02ae0038b95a3b3575fe0519 F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9 F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625 F test/e_walauto.test 280714ddf14e1a47dcbc59d515cd0b026dfd5567 @@ -1072,7 +1072,7 @@ F test/subquery2.test 438f8a7da1457277b22e4176510f7659b286995f F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 -F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2 +F test/superlock.test 168011a6730aee70c28ea8d5e1c0592de4026f79 F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849 F test/sync.test 2f607e1821aa3af3c5c53b58835c05e511c95899 F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c @@ -1314,7 +1314,7 @@ F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd F test/wal8.test 75c42e1bc4545c277fed212f8fc9b7723cd02216 F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750 F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe -F test/walbak.test b9f68e39646375c2b877be906babcc15d38b4877 +F test/walbak.test 8f4466e574dcd3a41cad3f25c45dc15aa74959d8 F test/walbig.test f437473a16cfb314867c6b5d1dbcd519e73e3434 F test/walblock.test be48f3a75eff0b4456209f26b3ce186c2015497d F test/walcksum.test bb234a1bb42248b3515d992b719708015c384278 @@ -1456,8 +1456,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 54b8968e335760105206b894672213c1d56771a4 fa8c12921f8361f1889724bb7c5f7eca9c48b075 -R e6d4ff0cfaea5c603741eca2f2c0aea1 -T +closed fa8c12921f8361f1889724bb7c5f7eca9c48b075 +P 90e0cc7b0be31ee2f155c2c053b0cbac584f6154 +R 923bd9deb3676f2e6a04ffc9c99e77ab +T *branch * see-testing +T *sym-see-testing * +T -sym-trunk * U drh -Z 3e9e43a77139e0aba2725db0c4d642ac +Z 56d0f9475e233b620a1fb1bf6022de74 diff --git a/manifest.uuid b/manifest.uuid index 365f26434f..7f70b633fd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -90e0cc7b0be31ee2f155c2c053b0cbac584f6154 \ No newline at end of file +1c70aa5c014fc48ab06215992a61c6f92490abe4 \ No newline at end of file diff --git a/test/autovacuum.test b/test/autovacuum.test index 9ee2cd0fa8..5c14ed85d3 100644 --- a/test/autovacuum.test +++ b/test/autovacuum.test @@ -269,7 +269,7 @@ do_test autovacuum-2.4.3 { } {3 4 5 6 7 8 9 10} # Right now there are 5 free pages in the database. Consume and then free -# a 520 pages. Then create 520 tables. This ensures that at least some of the +# all 520 pages. Then create 520 tables. This ensures that at least some of the # desired root-pages reside on the second free-list trunk page, and that the # trunk itself is required at some point. do_test autovacuum-2.4.4 { @@ -280,9 +280,20 @@ do_test autovacuum-2.4.4 { } {} set root_page_list [list] set pending_byte_page [expr ($::sqlite_pending_byte / 1024) + 1] + +# unusable_pages +# These are either the pending_byte page or the pointer map pages +# +unset -nocomplain unusable_page +if {[sqlite3 -has-codec]} { + array set unusable_page {205 1 408 1} +} else { + array set unusable_page {207 1 412 1} +} +set unusable_page($pending_byte_page) 1 + for {set i 3} {$i<=532} {incr i} { - # 207 and 412 are pointer-map pages. - if { $i!=207 && $i!=412 && $i != $pending_byte_page} { + if {![info exists unusable_page($i)]} { lappend root_page_list $i } } diff --git a/test/e_uri.test b/test/e_uri.test index 7a7f2559ec..95b53f1d6b 100644 --- a/test/e_uri.test +++ b/test/e_uri.test @@ -13,7 +13,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix e_uri - +do_not_use_codec db close proc parse_uri {uri} { diff --git a/test/superlock.test b/test/superlock.test index 8199d5218d..1e4a4a78d9 100644 --- a/test/superlock.test +++ b/test/superlock.test @@ -15,6 +15,7 @@ source $testdir/tester.tcl source $testdir/lock_common.tcl set testprefix superlock +do_not_use_codec # Test organization: # diff --git a/test/walbak.test b/test/walbak.test index 303a628a84..8d4ee01175 100644 --- a/test/walbak.test +++ b/test/walbak.test @@ -127,6 +127,7 @@ do_test walbak-2.1 { } } {} do_test walbak-2.2 { + forcedelete abc.db db backup abc.db sqlite3 db2 abc.db string compare [sig db] [sig db2] From af3906a7980c6aff862d3af7e4d329a2789fca9c Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 14 Mar 2016 17:05:04 +0000 Subject: [PATCH 464/570] Many test cases fixed to work with encryption. FossilOrigin-Name: d866fffb8b1af5003a8730ce7029d1edddb24d46 --- manifest | 47 ++++++++++++++---------------- manifest.uuid | 2 +- test/backup4.test | 5 ++++ test/close.test | 4 +++ test/corrupt3.test | 7 ++--- test/corrupt4.test | 7 ++--- test/corrupt6.test | 7 ++--- test/corrupt7.test | 7 ++--- test/corruptE.test | 7 ++--- test/corruptG.test | 7 ++--- test/corruptH.test | 8 ++--- test/corruptI.test | 8 ++--- test/corruptJ.test | 8 ++--- test/crash8.test | 1 + test/e_vacuum.test | 58 +++++++++++++++++++------------------ test/eqp.test | 66 ++++++++++++++++++++++-------------------- test/incrblob.test | 10 +++---- test/incrblob_err.test | 4 +-- test/tester.tcl | 7 +++++ 19 files changed, 141 insertions(+), 129 deletions(-) diff --git a/manifest b/manifest index 320c150381..4ca965b914 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Test\sscript\schanges\sto\ssupport\stesting\sthe\sSQLite\sEncryption\sExtension. -D 2016-03-14T16:16:43.649 +C Many\stest\scases\sfixed\sto\swork\swith\sencryption. +D 2016-03-14T17:05:04.050 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -487,7 +487,7 @@ F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85 F test/backcompat.test 28403f43d11624e696c5ef134c7c7d81015cd19e F test/backup.test b79299a536a4c6d919094786595b95be56d02014 F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf -F test/backup4.test 2a2e4a64388090b152de753fd9e123f28f6a3bd4 +F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32 F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4 F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135 F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450 @@ -528,7 +528,7 @@ F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3 F test/cffault.test aadc1f61f8811cb600e3e069acbf8796f472a096 F test/check.test 85a84bfc4be0e83f668747211c7cd45a6721d485 -F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815 +F test/close.test 83947daf3b700631f90f4850ddaab455be4af73d F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4 F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91 F test/collate1.test 08c18e7512a5a32c97938854263fa15362eeb846 @@ -549,23 +549,23 @@ F test/conflict3.test dec0634c0f31dec9a4b01c63063e939f0cd21b6b F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4 F test/corrupt.test 141c39ea650c1365e85a49e402fa05cb9617fb97 F test/corrupt2.test cb787825d761b0f869764d6990531382840de872 -F test/corrupt3.test 4b548d0bbe2933bc81d3f54099a05fc4d28aff18 -F test/corrupt4.test b99652079d542b21f4965f6248703b983e40fe80 +F test/corrupt3.test e676f478fe602915d721472811f6f410b75ddc7e +F test/corrupt4.test 8d1d86b850fcc43e417450454f2044e52d55778a F test/corrupt5.test 8ead52af76006f3286e9396cb41898018ccea107 -F test/corrupt6.test 269548d19427ac554c830763b1c5ea54a0252f80 -F test/corrupt7.test e4fa6d6584276679cc1d20c4e58beb9559a4eb85 +F test/corrupt6.test fc6a891716139665dae0073b6945e3670bf92568 +F test/corrupt7.test b036f94bda4b0b23a2919bf717046ce9ecca4543 F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516 F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85 F test/corruptA.test 53e56dafd180addcdadb402244b8cb9771d2ba26 F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec F test/corruptC.test 0c46574f8d4f27ecc799b1b5c4cbf9b1817bce9a F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040 -F test/corruptE.test be8e5088c369fc7979c662cd644efdaafc0f7f6d +F test/corruptE.test 82ccf4f8f543fdbedd4aa42c709cb077f7374c62 F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4 -F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804 -F test/corruptH.test 99ad81a4bda7cc078c589ef7542ecbc64e453c80 -F test/corruptI.test 347babbf970e7947e3f91dccf7a1bec28a1bab04 -F test/corruptJ.test 9e29e7a81ee3b6ac50f77ea7a9e2f3fa03f32d91 +F test/corruptG.test adf79b669cbfd19e28c8191a610d083ae53a6d51 +F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454 +F test/corruptI.test 075fe1d75aa1d84e2949be56b6264376c41502e4 +F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4 F test/cost.test 1eedbfd868f806f3fa08ff072b04cf270dcf61c8 F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c F test/coveridxscan.test b629e896b14df2f000a99b8d170d80589c46562c @@ -576,7 +576,7 @@ F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc F test/crash5.test 05dd3aa9dbb751a22d5cdaf22a9c49b6667aa219 F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df -F test/crash8.test 61442a9964ab6b124fc5254e4258b45747842e6f +F test/crash8.test a63907617d8e74fb54b4bff23eca8a4435625245 F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2 F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8 @@ -617,7 +617,7 @@ F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10 F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528 F test/e_uri.test 25385396082b67fd02ae0038b95a3b3575fe0519 -F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9 +F test/e_vacuum.test 4d5b391384bb7d56bb9337d956f08035332421fc F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625 F test/e_walauto.test 280714ddf14e1a47dcbc59d515cd0b026dfd5567 F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0 @@ -626,7 +626,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473 F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6 F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020 -F test/eqp.test 85873fa5816c48915c82c4e74cb5c35a5b48160f +F test/eqp.test 3fe051af50921284189d1970eb653f9fcf5117d2 F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401 F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c F test/exclusive.test f48243eaf40e0957215501a12f510a8644d13a02 @@ -790,11 +790,11 @@ F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068 F test/in5.test acc710c12af118df5f8645eaba9479f5619eed81 -F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328 +F test/incrblob.test 8a6d31ba3243d7c00cebf0b0d9ff533410e8b412 F test/incrblob2.test a5ce5ed1d0b01e2ed347245a21170372528af0a5 F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4 F test/incrblob4.test f26502a5697893e5acea268c910f16478c2f0fab -F test/incrblob_err.test af1f12ba60d220c9752073ff2bda2ad59e88960d +F test/incrblob_err.test 69f9247fed50278d48ea710d1a8f9cdb09e4c0b8 F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32 @@ -1085,7 +1085,7 @@ F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl 8fbf071b23ec66ce9bb8607fc92fdc4326393697 +F test/tester.tcl d6dee24773e20320ab64d39bb5ce6e1a91b6029e F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1456,10 +1456,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 90e0cc7b0be31ee2f155c2c053b0cbac584f6154 -R 923bd9deb3676f2e6a04ffc9c99e77ab -T *branch * see-testing -T *sym-see-testing * -T -sym-trunk * +P 1c70aa5c014fc48ab06215992a61c6f92490abe4 +R ac90bb020079fb64a047783b4d5bc228 U drh -Z 56d0f9475e233b620a1fb1bf6022de74 +Z 40fa5f4f9bc49db4a476fd7c95e3e453 diff --git a/manifest.uuid b/manifest.uuid index 7f70b633fd..de29d5f426 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1c70aa5c014fc48ab06215992a61c6f92490abe4 \ No newline at end of file +d866fffb8b1af5003a8730ce7029d1edddb24d46 \ No newline at end of file diff --git a/test/backup4.test b/test/backup4.test index 417df80e55..2756995c3a 100644 --- a/test/backup4.test +++ b/test/backup4.test @@ -23,6 +23,11 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix backup4 +# The codec logic does not work for zero-length database files. A database +# file must contain at least one page in order to be recognized as an +# encrypted database. +do_not_use_codec + #------------------------------------------------------------------------- # At one point this test was failing because [db] was using an out of # date schema in test case 1.2. diff --git a/test/close.test b/test/close.test index d5d6391ae5..1b789bc776 100644 --- a/test/close.test +++ b/test/close.test @@ -17,6 +17,10 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix close +# This module bypasses the "-key" logic in tester.tcl, so it cannot run +# with the codec enabled. +do_not_use_codec + do_execsql_test 1.0 { CREATE TABLE t1(x); INSERT INTO t1 VALUES('one'); diff --git a/test/corrupt3.test b/test/corrupt3.test index 436a466189..85139420b8 100644 --- a/test/corrupt3.test +++ b/test/corrupt3.test @@ -18,10 +18,9 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -# Do not use a codec for tests in this file, as the database file is -# manipulated directly using tcl scripts (using the [hexio_write] command). -# -do_not_use_codec +# This module uses hard-coded offsets which do not work if the reserved_bytes +# value is nonzero. +if {[nonzero_reserved_bytes]} {finish_test; return;} # These tests deal with corrupt database files # diff --git a/test/corrupt4.test b/test/corrupt4.test index 24db60fd52..55969c6a8c 100644 --- a/test/corrupt4.test +++ b/test/corrupt4.test @@ -18,10 +18,9 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -# Do not use a codec for tests in this file, as the database file is -# manipulated directly using tcl scripts (using the [hexio_write] command). -# -do_not_use_codec +# This module uses hard-coded offsets which do not work if the reserved_bytes +# value is nonzero. +if {[nonzero_reserved_bytes]} {finish_test; return;} # These tests deal with corrupt database files # diff --git a/test/corrupt6.test b/test/corrupt6.test index 7d90c4a3ba..dd773c9265 100644 --- a/test/corrupt6.test +++ b/test/corrupt6.test @@ -19,10 +19,9 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -# Do not use a codec for tests in this file, as the database file is -# manipulated directly using tcl scripts (using the [hexio_write] command). -# -do_not_use_codec +# This module uses hard-coded offsets which do not work if the reserved_bytes +# value is nonzero. +if {[nonzero_reserved_bytes]} {finish_test; return;} # These tests deal with corrupt database files # diff --git a/test/corrupt7.test b/test/corrupt7.test index 7ebebd94e7..aa66cc7ece 100644 --- a/test/corrupt7.test +++ b/test/corrupt7.test @@ -19,10 +19,9 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -# Do not use a codec for tests in this file, as the database file is -# manipulated directly using tcl scripts (using the [hexio_write] command). -# -do_not_use_codec +# This module uses hard-coded offsets which do not work if the reserved_bytes +# value is nonzero. +if {[nonzero_reserved_bytes]} {finish_test; return;} # These tests deal with corrupt database files # diff --git a/test/corruptE.test b/test/corruptE.test index 78cabbec8e..54aa420f43 100644 --- a/test/corruptE.test +++ b/test/corruptE.test @@ -18,10 +18,9 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -# Do not use a codec for tests in this file, as the database file is -# manipulated directly using tcl scripts (using the [hexio_write] command). -# -do_not_use_codec +# This module uses hard-coded offsets which do not work if the reserved_bytes +# value is nonzero. +if {[nonzero_reserved_bytes]} {finish_test; return;} # These tests deal with corrupt database files # diff --git a/test/corruptG.test b/test/corruptG.test index af920edf41..94480340a7 100644 --- a/test/corruptG.test +++ b/test/corruptG.test @@ -14,10 +14,9 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix corruptG -# Do not use a codec for tests in this file, as the database file is -# manipulated directly using tcl scripts (using the [hexio_write] command). -# -do_not_use_codec +# This module uses hard-coded offsets which do not work if the reserved_bytes +# value is nonzero. +if {[nonzero_reserved_bytes]} {finish_test; return;} # These tests deal with corrupt database files # diff --git a/test/corruptH.test b/test/corruptH.test index 0e1a1d4429..9ba7522422 100644 --- a/test/corruptH.test +++ b/test/corruptH.test @@ -14,10 +14,10 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix corruptH -# Do not use a codec for tests in this file, as the database file is -# manipulated directly using tcl scripts (using the [hexio_write] command). -# -do_not_use_codec +# This module uses hard-coded offsets which do not work if the reserved_bytes +# value is nonzero. +if {[nonzero_reserved_bytes]} {finish_test; return;} + database_may_be_corrupt # The corruption migrations tested by the code in this file are not detected diff --git a/test/corruptI.test b/test/corruptI.test index 9f46efb744..cdcb94201e 100644 --- a/test/corruptI.test +++ b/test/corruptI.test @@ -19,10 +19,10 @@ if {[permutation]=="mmap"} { return } -# Do not use a codec for tests in this file, as the database file is -# manipulated directly using tcl scripts (using the [hexio_write] command). -# -do_not_use_codec +# This module uses hard-coded offsets which do not work if the reserved_bytes +# value is nonzero. +if {[nonzero_reserved_bytes]} {finish_test; return;} + database_may_be_corrupt # Initialize the database. diff --git a/test/corruptJ.test b/test/corruptJ.test index c08e628e2d..732adb085c 100644 --- a/test/corruptJ.test +++ b/test/corruptJ.test @@ -22,10 +22,10 @@ if {[permutation]=="mmap"} { return } -# Do not use a codec for tests in this file, as the database file is -# manipulated directly using tcl scripts (using the [hexio_write] command). -# -do_not_use_codec +# This module uses hard-coded offsets which do not work if the reserved_bytes +# value is nonzero. +if {[nonzero_reserved_bytes]} {finish_test; return;} + database_may_be_corrupt # Initialize the database. diff --git a/test/crash8.test b/test/crash8.test index 930834a962..f3b6f6e244 100644 --- a/test/crash8.test +++ b/test/crash8.test @@ -25,6 +25,7 @@ ifcapable !crashtest { finish_test return } +do_not_use_codec do_test crash8-1.1 { execsql { diff --git a/test/e_vacuum.test b/test/e_vacuum.test index 99b31aaca4..1113a1fb6e 100644 --- a/test/e_vacuum.test +++ b/test/e_vacuum.test @@ -159,35 +159,37 @@ do_test e_vacuum-1.3.1.2 { execsql { PRAGMA page_size ; PRAGMA auto_vacuum } } {1024 1} -# EVIDENCE-OF: R-08570-19916 However, when not in write-ahead log mode, -# the page_size and/or auto_vacuum properties of an existing database -# may be changed by using the page_size and/or pragma auto_vacuum -# pragmas and then immediately VACUUMing the database. -# -do_test e_vacuum-1.3.2.1 { - execsql { PRAGMA journal_mode = delete } - execsql { PRAGMA page_size = 2048 } - execsql { PRAGMA auto_vacuum = NONE } - execsql VACUUM - execsql { PRAGMA page_size ; PRAGMA auto_vacuum } -} {2048 0} - -# EVIDENCE-OF: R-48521-51450 When in write-ahead log mode, only the -# auto_vacuum support property can be changed using VACUUM. -# -ifcapable wal { -do_test e_vacuum-1.3.3.1 { - execsql { PRAGMA journal_mode = wal } - execsql { PRAGMA page_size ; PRAGMA auto_vacuum } -} {2048 0} -do_test e_vacuum-1.3.3.2 { - execsql { PRAGMA page_size = 1024 } - execsql { PRAGMA auto_vacuum = FULL } - execsql VACUUM - execsql { PRAGMA page_size ; PRAGMA auto_vacuum } -} {2048 1} +if {![nonzero_reserved_bytes]} { + # EVIDENCE-OF: R-08570-19916 However, when not in write-ahead log mode, + # the page_size and/or auto_vacuum properties of an existing database + # may be changed by using the page_size and/or pragma auto_vacuum + # pragmas and then immediately VACUUMing the database. + # + do_test e_vacuum-1.3.2.1 { + execsql { PRAGMA journal_mode = delete } + execsql { PRAGMA page_size = 2048 } + execsql { PRAGMA auto_vacuum = NONE } + execsql VACUUM + execsql { PRAGMA page_size ; PRAGMA auto_vacuum } + } {2048 0} + + # EVIDENCE-OF: R-48521-51450 When in write-ahead log mode, only the + # auto_vacuum support property can be changed using VACUUM. + # + ifcapable wal { + do_test e_vacuum-1.3.3.1 { + execsql { PRAGMA journal_mode = wal } + execsql { PRAGMA page_size ; PRAGMA auto_vacuum } + } {2048 0} + do_test e_vacuum-1.3.3.2 { + execsql { PRAGMA page_size = 1024 } + execsql { PRAGMA auto_vacuum = FULL } + execsql VACUUM + execsql { PRAGMA page_size ; PRAGMA auto_vacuum } + } {2048 1} + } } - + # EVIDENCE-OF: R-38001-03952 VACUUM only works on the main database. It # is not possible to VACUUM an attached database file. forcedelete test.db2 diff --git a/test/eqp.test b/test/eqp.test index 046088c9c5..c955a80c21 100644 --- a/test/eqp.test +++ b/test/eqp.test @@ -516,45 +516,47 @@ det 5.13 "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1" { } -#------------------------------------------------------------------------- -# The following tests - eqp-6.* - test that the example C code on -# documentation page eqp.html works. The C code is duplicated in test1.c -# and wrapped in Tcl command [print_explain_query_plan] -# -set boilerplate { - proc explain_query_plan {db sql} { - set stmt [sqlite3_prepare_v2 db $sql -1 DUMMY] - print_explain_query_plan $stmt - sqlite3_finalize $stmt +if {![nonzero_reserved_bytes]} { + #------------------------------------------------------------------------- + # The following tests - eqp-6.* - test that the example C code on + # documentation page eqp.html works. The C code is duplicated in test1.c + # and wrapped in Tcl command [print_explain_query_plan] + # + set boilerplate { + proc explain_query_plan {db sql} { + set stmt [sqlite3_prepare_v2 db $sql -1 DUMMY] + print_explain_query_plan $stmt + sqlite3_finalize $stmt + } + sqlite3 db test.db + explain_query_plan db {%SQL%} + db close + exit } - sqlite3 db test.db - explain_query_plan db {%SQL%} - db close - exit -} - -# Do a "Print Explain Query Plan" test. -proc do_peqp_test {tn sql res} { - set fd [open script.tcl w] - puts $fd [string map [list %SQL% $sql] $::boilerplate] - close $fd - - uplevel do_test $tn [list { - set fd [open "|[info nameofexec] script.tcl"] - set data [read $fd] + + # Do a "Print Explain Query Plan" test. + proc do_peqp_test {tn sql res} { + set fd [open script.tcl w] + puts $fd [string map [list %SQL% $sql] $::boilerplate] close $fd - set data - }] [list $res] -} - -do_peqp_test 6.1 { - SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1 -} [string trimleft { + + uplevel do_test $tn [list { + set fd [open "|[info nameofexec] script.tcl"] + set data [read $fd] + close $fd + set data + }] [list $res] + } + + do_peqp_test 6.1 { + SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1 + } [string trimleft { 1 0 0 SCAN TABLE t1 USING COVERING INDEX i2 2 0 0 SCAN TABLE t2 2 0 0 USE TEMP B-TREE FOR ORDER BY 0 0 0 COMPOUND SUBQUERIES 1 AND 2 (EXCEPT) }] +} #------------------------------------------------------------------------- # The following tests - eqp-7.* - test that queries that use the OP_Count diff --git a/test/incrblob.test b/test/incrblob.test index 4277e5c4c1..44182287ec 100644 --- a/test/incrblob.test +++ b/test/incrblob.test @@ -384,7 +384,7 @@ ifcapable vtab { ifcapable attach { do_test incrblob-5.1 { forcedelete test2.db test2.db-journal - set ::size [expr [file size [info script]]] + set ::size [expr [file size $::cmdlinearg(INFO_SCRIPT)]] execsql { ATTACH 'test2.db' AS aux; CREATE TABLE aux.files(name, text); @@ -392,16 +392,16 @@ ifcapable attach { } set fd [db incrblob aux files text 1] fconfigure $fd -translation binary - set fd2 [open [info script]] + set fd2 [open $::cmdlinearg(INFO_SCRIPT)] fconfigure $fd2 -translation binary puts -nonewline $fd [read $fd2] close $fd close $fd2 set ::text [db one {select text from aux.files}] string length $::text - } [file size [info script]] + } [file size $::cmdlinearg(INFO_SCRIPT)] do_test incrblob-5.2 { - set fd2 [open [info script]] + set fd2 [open $::cmdlinearg(INFO_SCRIPT)] fconfigure $fd2 -translation binary set ::data [read $fd2] close $fd2 @@ -576,7 +576,7 @@ foreach {tn arg} {1 "" 2 -readonly} { } -set fd [open [info script]] +set fd [open $::cmdlinearg(INFO_SCRIPT)] fconfigure $fd -translation binary set ::data [read $fd 14000] close $fd diff --git a/test/incrblob_err.test b/test/incrblob_err.test index a08bea3e4e..0db8b0dcba 100644 --- a/test/incrblob_err.test +++ b/test/incrblob_err.test @@ -24,12 +24,12 @@ ifcapable {!incrblob || !memdebug || !tclvar} { source $testdir/malloc_common.tcl unset -nocomplain ::fd ::data -set ::fd [open [info script]] +set ::fd [open $::cmdlinearg(INFO_SCRIPT)] set ::data [read $::fd] close $::fd do_malloc_test 1 -tclprep { - set bytes [file size [info script]] + set bytes [file size $::cmdlinearg(INFO_SCRIPT)] execsql { CREATE TABLE blobs(k, v BLOB); INSERT INTO blobs VALUES(1, zeroblob($::bytes)); diff --git a/test/tester.tcl b/test/tester.tcl index 6dc507f70e..3a881138e2 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -374,6 +374,12 @@ proc do_not_use_codec {} { reset_db } +# Return true if the "reserved_bytes" integer on database files is non-zero. +# +proc nonzero_reserved_bytes {} { + return [sqlite3 -has-codec] +} + # Print a HELP message and exit # proc print_help_and_quit {} { @@ -521,6 +527,7 @@ if {[info exists cmdlinearg]==0} { } set testdir [file normalize $testdir] set cmdlinearg(TESTFIXTURE_HOME) [pwd] + set cmdlinearg(INFO_SCRIPT) [file normalize [info script]] set argv0 [file normalize $argv0] if {$cmdlinearg(testdir)!=""} { file mkdir $cmdlinearg(testdir) From 7da56b4f65ceb4cecb5bd5f1a167e00b393d9889 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 14 Mar 2016 18:34:42 +0000 Subject: [PATCH 465/570] Many more test cases fixed. Only a few remain. FossilOrigin-Name: 99b9d7eef68fd6d5c9eecb5fbe3dfe002c1ca4a8 --- manifest | 46 ++++++++-------- manifest.uuid | 2 +- test/e_walauto.test | 5 ++ test/incrblob.test | 13 +++-- test/io.test | 2 +- test/memsubsys1.test | 2 +- test/mmap1.test | 6 ++- test/mmap3.test | 3 ++ test/nan.test | 80 +++++++++++++-------------- test/pageropt.test | 1 + test/pragma.test | 126 ++++++++++++++++++++++--------------------- test/pragma3.test | 1 + test/stat.test | 4 ++ test/tclsqlite.test | 5 +- test/tkt4018.test | 1 + test/wal.test | 2 + test/wal5.test | 1 + test/wal8.test | 1 + test/walbak.test | 1 + test/walro.test | 2 +- 20 files changed, 167 insertions(+), 137 deletions(-) diff --git a/manifest b/manifest index 4ca965b914..ae6b61c7de 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Many\stest\scases\sfixed\sto\swork\swith\sencryption. -D 2016-03-14T17:05:04.050 +C Many\smore\stest\scases\sfixed.\s\sOnly\sa\sfew\sremain. +D 2016-03-14T18:34:42.199 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -619,7 +619,7 @@ F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528 F test/e_uri.test 25385396082b67fd02ae0038b95a3b3575fe0519 F test/e_vacuum.test 4d5b391384bb7d56bb9337d956f08035332421fc F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625 -F test/e_walauto.test 280714ddf14e1a47dcbc59d515cd0b026dfd5567 +F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8 F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0 F test/e_walhook.test 4c0613a0c76e7a9d5c4c211e1b4cbcc1143914df F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea @@ -790,7 +790,7 @@ F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068 F test/in5.test acc710c12af118df5f8645eaba9479f5619eed81 -F test/incrblob.test 8a6d31ba3243d7c00cebf0b0d9ff533410e8b412 +F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822 F test/incrblob2.test a5ce5ed1d0b01e2ed347245a21170372528af0a5 F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4 F test/incrblob4.test f26502a5697893e5acea268c910f16478c2f0fab @@ -821,7 +821,7 @@ F test/instr.test 737bbf80685232033f3abedc6ae92f75860b5dd2 F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4 F test/interrupt.test dfe9a67a94b0b2d8f70545ba1a6cca10780d71cc F test/intpkey.test 7506090fc08e028712a8bf47e5f54111947e3844 -F test/io.test 3a7abcef18727cc0f2399e04b0e8903eccae50f8 +F test/io.test f95bca1783b01ea7761671560d023360d2dfa4cc F test/ioerr.test 2a24bd6ed5a8b062e64bfe1f6cf94fb25e92210d F test/ioerr2.test 2593563599e2cc6b6b4fcf5878b177bdd5d8df26 F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd @@ -889,7 +889,7 @@ F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 -F test/memsubsys1.test d2b2d6ca37890b26703a2258df8fd66f9869da02 +F test/memsubsys1.test 0311bfb4edd2615e3aa56c7a9cf44574e4229077 F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc @@ -904,9 +904,9 @@ F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2 F test/misc8.test 21ac9d35a5e110279ae9e1588b8914f54de1c60b F test/misuse.test 3c34719944ba045cc6c188a4852ba04680728912 -F test/mmap1.test 44a5ff1c1bcc7dcf2de50227d1f997e75a8ef1ae +F test/mmap1.test d2cfc1635171c434dcff0ece2f1c8e0a658807ce F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022 -F test/mmap3.test c92273e16eb8d23c1d55c9815b446bb72ef0512e +F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93 F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3 F test/multiplex.test efd015ca0b5b4a57dc9535b8feb1273eebeadb60 @@ -915,7 +915,7 @@ F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101 F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4 F test/mutex1.test e0a44072d98189003deae4b091106f085d94bea8 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 -F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a +F test/nan.test dacc57f80859c06a433d30839336fe227d2038b3 F test/nolock.test 96e922d2d3db71c2dd6557c98e8027a28277b415 F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161 @@ -944,16 +944,16 @@ F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e F test/pagerfault.test ae9ee0db5a30aecda9db8290ce3dd12e5f7bbaa1 F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8 -F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6 +F test/pageropt.test f8d840f0fed84854dbd12b4c17fb3506eeb8224c F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305 F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff F test/permutations.test 64abe58d53cde4adcfb881e37aa5ea1b2a980e58 -F test/pragma.test 507ac7ef2ea5682241ea0ef041799ca70bb5e0bf +F test/pragma.test afbf028be1c35b68f57db8eb015c4a3c59d8f28e F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f -F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c +F test/pragma3.test 3f1984a04657331f838df5c519b443c2088df922 F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054 F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb @@ -1064,7 +1064,7 @@ F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33 F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5 F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142 F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a -F test/stat.test acc91e80517fff447ae8adcfd953cfdaa5efc0af +F test/stat.test b65bad7120c52583b8f0054d99eff80718119a77 F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1 F test/stmt.test 64844332db69cf1a735fcb3e11548557fc95392f F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f @@ -1081,7 +1081,7 @@ F test/tabfunc01.test f977868fa8bb7beb4b2072883190411653473906 F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 -F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054 +F test/tclsqlite.test c6d9f546f79d15d0134c1e06583fb3ee0c3afad3 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 @@ -1237,7 +1237,7 @@ F test/tkt3929.test cdf67acf5aa936ec4ffead81db87f8a71fe40e59 F test/tkt3935.test e15261fedb9e30a4305a311da614a5d8e693c767 F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd -F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1 +F test/tkt4018.test 18dbc6617f7a4b90e938d1bd6d26ad18daafaf08 F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7 F test/tpch01.test 04adbf8d8300fa60a222f28d901abd76e7be6dd4 F test/trace.test 6f676313e3ebd2a50585036d2f212a3319dd5836 @@ -1303,18 +1303,18 @@ F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad -F test/wal.test 0148c8b3421a25fdb4d9c160e84a681d0646371b +F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477 F test/wal2.test 25ae059e900dbb584e0775627e45415ba5940df1 F test/wal3.test 5dd734147f1f8f958c5261a1f2775d346d7013ce F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c -F test/wal5.test 88b5d9a6a3d1532497ee9f4296f010d66f07e33c +F test/wal5.test 22cb252502c5ff851925add2ca8a7e2af012e1d6 F test/wal6.test a9d6aa635b9d63607dabdc11406f5f96ca986635 F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8 F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd -F test/wal8.test 75c42e1bc4545c277fed212f8fc9b7723cd02216 +F test/wal8.test d9df3fba4caad5854ed69ed673c68482514203c8 F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750 F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe -F test/walbak.test 8f4466e574dcd3a41cad3f25c45dc15aa74959d8 +F test/walbak.test 018d4e5a3d45c6298d11b99f09a8ef6876527946 F test/walbig.test f437473a16cfb314867c6b5d1dbcd519e73e3434 F test/walblock.test be48f3a75eff0b4456209f26b3ce186c2015497d F test/walcksum.test bb234a1bb42248b3515d992b719708015c384278 @@ -1328,7 +1328,7 @@ F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496 F test/waloverwrite.test dad2f26567f1b45174e54fbf9a8dc1cb876a7f03 F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6 F test/walprotocol.test 059cb75484a1ecf6357a2c1b3324b8156749221e -F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57 +F test/walro.test 4ab7ac01b77c2f894235c699d59e3e3c7f15a160 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e @@ -1456,7 +1456,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 1c70aa5c014fc48ab06215992a61c6f92490abe4 -R ac90bb020079fb64a047783b4d5bc228 +P d866fffb8b1af5003a8730ce7029d1edddb24d46 +R 3cbc3d8762ef570c005be926f5a219e3 U drh -Z 40fa5f4f9bc49db4a476fd7c95e3e453 +Z 5481496fbfdbf0fce1abf7df1c171e0c diff --git a/manifest.uuid b/manifest.uuid index de29d5f426..fd9549389f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d866fffb8b1af5003a8730ce7029d1edddb24d46 \ No newline at end of file +99b9d7eef68fd6d5c9eecb5fbe3dfe002c1ca4a8 \ No newline at end of file diff --git a/test/e_walauto.test b/test/e_walauto.test index 093b13f940..7665b1bf73 100644 --- a/test/e_walauto.test +++ b/test/e_walauto.test @@ -24,6 +24,11 @@ if {$tcl_platform(os) == "OpenBSD"} { return } +# This module uses hard-coded offsets which do not work if the reserved_bytes +# value is nonzero. +if {[nonzero_reserved_bytes]} {finish_test; return;} + + proc read_nbackfill {} { seek $::shmfd 96 binary scan [read $::shmfd 4] n nBackfill diff --git a/test/incrblob.test b/test/incrblob.test index 44182287ec..c56689ee1b 100644 --- a/test/incrblob.test +++ b/test/incrblob.test @@ -126,6 +126,11 @@ foreach AutoVacuumMode [list 0 1] { execsql "PRAGMA mmap_size = 0" execsql "PRAGMA auto_vacuum = $AutoVacuumMode" + # Extra value added to size answers + set ib2_extra 0 + if {$AutoVacuumMode} {incr ib2_extra} + if {[nonzero_reserved_bytes]} {incr ib2_extra} + do_test incrblob-2.$AutoVacuumMode.1 { set ::str [string repeat abcdefghij 2900] execsql { @@ -136,7 +141,7 @@ foreach AutoVacuumMode [list 0 1] { COMMIT; } expr [file size test.db]/1024 - } [expr 31 + $AutoVacuumMode] + } [expr 31 + $ib2_extra] ifcapable autovacuum { do_test incrblob-2.$AutoVacuumMode.2 { @@ -163,7 +168,7 @@ foreach AutoVacuumMode [list 0 1] { # sqlite uses the ptrmap pages to avoid reading the other pages. # nRead db - } [expr $AutoVacuumMode ? 4 : 30] + } [expr $AutoVacuumMode ? 4 : 30+$ib2_extra] do_test incrblob-2.$AutoVacuumMode.4 { string range [db one {SELECT v FROM blobs}] end-19 end @@ -187,7 +192,7 @@ foreach AutoVacuumMode [list 0 1] { # sqlite uses the ptrmap pages to avoid reading the other pages. # nRead db - } [expr $AutoVacuumMode ? 4 : 30] + } [expr $AutoVacuumMode ? 4 : 30 + $ib2_extra] # Pages 1 (the write-counter) and 32 (the blob data) were written. do_test incrblob-2.$AutoVacuumMode.6 { @@ -210,7 +215,7 @@ foreach AutoVacuumMode [list 0 1] { do_test incrblob-2.$AutoVacuumMode.9 { nRead db - } [expr $AutoVacuumMode ? 4 : 30] + } [expr $AutoVacuumMode ? 4 : 30 + $ib2_extra] } sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit) diff --git a/test/io.test b/test/io.test index c5086c10ec..e1af808a3f 100644 --- a/test/io.test +++ b/test/io.test @@ -424,7 +424,7 @@ ifcapable pager_pragmas { # The COMMIT requires a single fsync() - to the database file. execsql { COMMIT } list [file size test.db] [nSync] - } {39936 1} + } "[expr {[nonzero_reserved_bytes]?40960:39936}] 1" } #---------------------------------------------------------------------- diff --git a/test/memsubsys1.test b/test/memsubsys1.test index 8265ce6317..e9a4cf08a8 100644 --- a/test/memsubsys1.test +++ b/test/memsubsys1.test @@ -255,7 +255,7 @@ do_test memsubsys1-7.4 { } 0 do_test memsubsys1-7.5 { set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2] - expr {$maxreq<4100} + expr {$maxreq<4100 + 4200*[nonzero_reserved_bytes]} } 1 do_test memsubsys1-7.6 { set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2] diff --git a/test/mmap1.test b/test/mmap1.test index 199a058754..c7c72c0ab2 100644 --- a/test/mmap1.test +++ b/test/mmap1.test @@ -88,7 +88,7 @@ foreach {t mmap_size nRead c2init} { sql2 { DELETE FROM t1 WHERE rowid%2; } do_test $t.$tn.2 { sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count" - } {16 ok 42} + } "16 ok [expr {42+[nonzero_reserved_bytes]}]" # Have connection 2 grow the file. Check connection 1 can still read it. sql2 { INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1 } @@ -104,7 +104,9 @@ foreach {t mmap_size nRead c2init} { # Check that the number of pages read by connection 1 indicates that the # "PRAGMA mmap_size" command worked. - do_test $t.$tn.5 { nRead db } $nRead + if {[nonzero_reserved_bytes]==0} { + do_test $t.$tn.5 { nRead db } $nRead + } } } diff --git a/test/mmap3.test b/test/mmap3.test index 07b5152968..184dda5f86 100644 --- a/test/mmap3.test +++ b/test/mmap3.test @@ -19,6 +19,9 @@ ifcapable !mmap||!vtab { source $testdir/lock_common.tcl set testprefix mmap3 +# A codec shuts down memory-mapped I/O +if {[nonzero_reserved_bytes]} {finish_test; return;} + do_test mmap3-1.0 { load_static_extension db wholenumber db eval { diff --git a/test/nan.test b/test/nan.test index df3f65b8e6..27fa04a351 100644 --- a/test/nan.test +++ b/test/nan.test @@ -151,45 +151,47 @@ sqlite3_finalize $::STMT # Then it reads the value of the database to verify it is converted into # NULL. # -do_test nan-3.1 { - db eval { - DELETE FROM t1; - INSERT INTO t1 VALUES(0.5); - PRAGMA auto_vacuum=OFF; - PRAGMA page_size=1024; - VACUUM; - } - hexio_read test.db 2040 8 -} {3FE0000000000000} -do_test nan-3.2 { - db eval { - SELECT x, typeof(x) FROM t1 - } -} {0.5 real} -do_test nan-3.3 { - db close - hexio_write test.db 2040 FFF8000000000000 - sqlite3 db test.db - db eval {SELECT x, typeof(x) FROM t1} -} {{} null} -do_test nan-3.4 { - db close - hexio_write test.db 2040 7FF8000000000000 - sqlite3 db test.db - db eval {SELECT x, typeof(x) FROM t1} -} {{} null} -do_test nan-3.5 { - db close - hexio_write test.db 2040 FFFFFFFFFFFFFFFF - sqlite3 db test.db - db eval {SELECT x, typeof(x) FROM t1} -} {{} null} -do_test nan-3.6 { - db close - hexio_write test.db 2040 7FFFFFFFFFFFFFFF - sqlite3 db test.db - db eval {SELECT x, typeof(x) FROM t1} -} {{} null} +if {![nonzero_reserved_bytes]} { + do_test nan-3.1 { + db eval { + DELETE FROM t1; + INSERT INTO t1 VALUES(0.5); + PRAGMA auto_vacuum=OFF; + PRAGMA page_size=1024; + VACUUM; + } + hexio_read test.db 2040 8 + } {3FE0000000000000} + do_test nan-3.2 { + db eval { + SELECT x, typeof(x) FROM t1 + } + } {0.5 real} + do_test nan-3.3 { + db close + hexio_write test.db 2040 FFF8000000000000 + sqlite3 db test.db + db eval {SELECT x, typeof(x) FROM t1} + } {{} null} + do_test nan-3.4 { + db close + hexio_write test.db 2040 7FF8000000000000 + sqlite3 db test.db + db eval {SELECT x, typeof(x) FROM t1} + } {{} null} + do_test nan-3.5 { + db close + hexio_write test.db 2040 FFFFFFFFFFFFFFFF + sqlite3 db test.db + db eval {SELECT x, typeof(x) FROM t1} + } {{} null} + do_test nan-3.6 { + db close + hexio_write test.db 2040 7FFFFFFFFFFFFFFF + sqlite3 db test.db + db eval {SELECT x, typeof(x) FROM t1} + } {{} null} +} # Verify that the sqlite3AtoF routine is able to handle extreme # numbers. diff --git a/test/pageropt.test b/test/pageropt.test index 7191661ba5..f8f5c71892 100644 --- a/test/pageropt.test +++ b/test/pageropt.test @@ -16,6 +16,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +do_not_use_codec ifcapable {!pager_pragmas||secure_delete||direct_read} { finish_test diff --git a/test/pragma.test b/test/pragma.test index befa5cf548..acbe74599e 100644 --- a/test/pragma.test +++ b/test/pragma.test @@ -1741,73 +1741,75 @@ forcedelete data_dir } ;# endif windows database_may_be_corrupt +if {![nonzero_reserved_bytes]} { -do_test 21.1 { - # Create a corrupt database in testerr.db. And a non-corrupt at test.db. - # - db close - forcedelete test.db - sqlite3 db test.db - execsql { - PRAGMA page_size = 1024; - PRAGMA auto_vacuum = 0; - CREATE TABLE t1(a PRIMARY KEY, b); - INSERT INTO t1 VALUES(1, 1); - } - for {set i 0} {$i < 10} {incr i} { - execsql { INSERT INTO t1 SELECT a + (1 << $i), b + (1 << $i) FROM t1 } - } - db close - forcecopy test.db testerr.db - hexio_write testerr.db 15000 [string repeat 55 100] -} {100} - -set mainerr {*** in database main *** + do_test 21.1 { + # Create a corrupt database in testerr.db. And a non-corrupt at test.db. + # + db close + forcedelete test.db + sqlite3 db test.db + execsql { + PRAGMA page_size = 1024; + PRAGMA auto_vacuum = 0; + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES(1, 1); + } + for {set i 0} {$i < 10} {incr i} { + execsql { INSERT INTO t1 SELECT a + (1 << $i), b + (1 << $i) FROM t1 } + } + db close + forcecopy test.db testerr.db + hexio_write testerr.db 15000 [string repeat 55 100] + } {100} + + set mainerr {*** in database main *** Multiple uses for byte 672 of page 15} -set auxerr {*** in database aux *** + set auxerr {*** in database aux *** Multiple uses for byte 672 of page 15} - -set mainerr {/{\*\*\* in database main \*\*\* + + set mainerr {/{\*\*\* in database main \*\*\* Multiple uses for byte 672 of page 15}.*/} -set auxerr {/{\*\*\* in database aux \*\*\* + set auxerr {/{\*\*\* in database aux \*\*\* Multiple uses for byte 672 of page 15}.*/} - -do_test 22.2 { - catch { db close } - sqlite3 db testerr.db - execsql { PRAGMA integrity_check } -} $mainerr - -do_test 22.3.1 { - catch { db close } - sqlite3 db test.db - execsql { - ATTACH 'testerr.db' AS 'aux'; - PRAGMA integrity_check; - } -} $auxerr -do_test 22.3.2 { - execsql { PRAGMA main.integrity_check; } -} {ok} -do_test 22.3.3 { - execsql { PRAGMA aux.integrity_check; } -} $auxerr - -do_test 22.4.1 { - catch { db close } - sqlite3 db testerr.db - execsql { - ATTACH 'test.db' AS 'aux'; - PRAGMA integrity_check; - } -} $mainerr -do_test 22.4.2 { - execsql { PRAGMA main.integrity_check; } -} $mainerr -do_test 22.4.3 { - execsql { PRAGMA aux.integrity_check; } -} {ok} - + + do_test 22.2 { + catch { db close } + sqlite3 db testerr.db + execsql { PRAGMA integrity_check } + } $mainerr + + do_test 22.3.1 { + catch { db close } + sqlite3 db test.db + execsql { + ATTACH 'testerr.db' AS 'aux'; + PRAGMA integrity_check; + } + } $auxerr + do_test 22.3.2 { + execsql { PRAGMA main.integrity_check; } + } {ok} + do_test 22.3.3 { + execsql { PRAGMA aux.integrity_check; } + } $auxerr + + do_test 22.4.1 { + catch { db close } + sqlite3 db testerr.db + execsql { + ATTACH 'test.db' AS 'aux'; + PRAGMA integrity_check; + } + } $mainerr + do_test 22.4.2 { + execsql { PRAGMA main.integrity_check; } + } $mainerr + do_test 22.4.3 { + execsql { PRAGMA aux.integrity_check; } + } {ok} +} + db close forcedelete test.db test.db-wal test.db-journal sqlite3 db test.db diff --git a/test/pragma3.test b/test/pragma3.test index b7ea4d3fc6..1a67d72350 100644 --- a/test/pragma3.test +++ b/test/pragma3.test @@ -15,6 +15,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +do_not_use_codec do_execsql_test pragma3-100 { PRAGMA data_version; diff --git a/test/stat.test b/test/stat.test index 288153dbb3..95586e94bc 100644 --- a/test/stat.test +++ b/test/stat.test @@ -21,6 +21,10 @@ ifcapable !vtab||!compound { return } +# This module uses hard-coded results that depend on exact measurements of +# pages sizes at the byte level, and hence will not work if the reserved_bytes +# value is nonzero. +if {[nonzero_reserved_bytes]} {finish_test; return;} set ::asc 1 proc a_string {n} { string range [string repeat [incr ::asc]. $n] 1 $n } diff --git a/test/tclsqlite.test b/test/tclsqlite.test index 8d7fea0d2a..d5c078de15 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -22,10 +22,9 @@ source $testdir/tester.tcl # Check the error messages generated by tclsqlite # +set r "sqlite_orig HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?" if {[sqlite3 -has-codec]} { - set r "sqlite_orig HANDLE FILENAME ?-key CODEC-KEY?" -} else { - set r "sqlite_orig HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?" + append r " ?-key CODECKEY?" } do_test tcl-1.1 { set v [catch {sqlite3 bogus} msg] diff --git a/test/tkt4018.test b/test/tkt4018.test index 2bc41d47aa..77582a5c41 100644 --- a/test/tkt4018.test +++ b/test/tkt4018.test @@ -16,6 +16,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +do_not_use_codec proc testsql {sql} { set fd [open tf_main.tcl w] diff --git a/test/wal.test b/test/wal.test index 92b65e66ba..bb164bb76a 100644 --- a/test/wal.test +++ b/test/wal.test @@ -1378,6 +1378,7 @@ do_test wal-21.3 { #------------------------------------------------------------------------- # Test reading and writing of databases with different page-sizes. # +incr ::do_not_use_codec foreach pgsz {512 1024 2048 4096 8192 16384 32768 65536} { do_multiclient_test tn [string map [list %PGSZ% $pgsz] { do_test wal-22.%PGSZ%.$tn.1 { @@ -1398,6 +1399,7 @@ foreach pgsz {512 1024 2048 4096 8192 16384 32768 65536} { } {0} }] } +incr ::do_not_use_codec -1 #------------------------------------------------------------------------- # Test that when 1 or more pages are recovered from a WAL file, diff --git a/test/wal5.test b/test/wal5.test index 360d9c911e..0f6dcfa6a7 100644 --- a/test/wal5.test +++ b/test/wal5.test @@ -18,6 +18,7 @@ source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } +do_not_use_codec set testprefix wal5 diff --git a/test/wal8.test b/test/wal8.test index 0682fce35b..3e5a0c2617 100644 --- a/test/wal8.test +++ b/test/wal8.test @@ -27,6 +27,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix wal8 ifcapable !wal {finish_test ; return } +do_not_use_codec db close forcedelete test.db test.db-wal diff --git a/test/walbak.test b/test/walbak.test index 8d4ee01175..0e0f999534 100644 --- a/test/walbak.test +++ b/test/walbak.test @@ -240,6 +240,7 @@ foreach {tn setup} { } } { + if {$tn==4 && [sqlite3 -has-codec]} continue foreach f [glob -nocomplain test.db*] { forcedelete $f } eval $setup diff --git a/test/walro.test b/test/walro.test index 6d920b1e24..f46e44d4cb 100644 --- a/test/walro.test +++ b/test/walro.test @@ -212,7 +212,7 @@ do_multiclient_test tn { INSERT INTO t2 SELECT x||y, y||x FROM t2; } file size test.db-wal - } {147800} + } [expr {[nonzero_reserved_bytes]?148848:147800}] do_test 1.4.4.2 { csql1 { SELECT * FROM t1 } } {0 {a b c d e f g h i j k l 1 2 3 4 5 6}} From 4a8a64672348245df8244997144d2db3f362d852 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 14 Mar 2016 20:49:24 +0000 Subject: [PATCH 466/570] Changing page size using VACUUM or backup is not allowed with a codec attached. FossilOrigin-Name: 92be06c1a828d56652fa5269a3029f8cb029b2cd --- manifest | 14 ++++---- manifest.uuid | 2 +- test/pager1.test | 85 +++++++++++++++++++++++++++++++-------------- test/superlock.test | 24 +++++++++---- 4 files changed, 83 insertions(+), 42 deletions(-) diff --git a/manifest b/manifest index 0391aaeca7..3b3c5f3c3b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\stest\sscript\sfixes\sfrom\strunk. -D 2016-03-14T18:42:04.674 +C Changing\spage\ssize\susing\sVACUUM\sor\sbackup\sis\snot\sallowed\swith\sa\scodec\sattached. +D 2016-03-14T20:49:24.177 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -937,7 +937,7 @@ F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3 F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f -F test/pager1.test f49df1a8b0e38b9ee3a7dd2ab4d427507b7314ce +F test/pager1.test 841868017e9dd3cb459b8d78862091a7d9cff21d F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71 F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e @@ -1072,7 +1072,7 @@ F test/subquery2.test 438f8a7da1457277b22e4176510f7659b286995f F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 -F test/superlock.test 168011a6730aee70c28ea8d5e1c0592de4026f79 +F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12 F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849 F test/sync.test 2f607e1821aa3af3c5c53b58835c05e511c95899 F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c @@ -1456,7 +1456,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 99b9d7eef68fd6d5c9eecb5fbe3dfe002c1ca4a8 f7480e33eb82f2eae219d17ce46cd2d4edac07d2 -R a4b3be370b53beddc257d6f309680c72 +P ea1d2cddd59192251ee5fd912b190cded4959879 +R 24275616ba2669073b7ddeb77ba67682 U drh -Z 068814209d932469f07bb4748200130f +Z 86d93a0053c6301f416af4041023113a diff --git a/manifest.uuid b/manifest.uuid index 873981d4c5..ca6831f8bf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ea1d2cddd59192251ee5fd912b190cded4959879 \ No newline at end of file +92be06c1a828d56652fa5269a3029f8cb029b2cd \ No newline at end of file diff --git a/test/pager1.test b/test/pager1.test index bc9ad83fd4..c25c837b67 100644 --- a/test/pager1.test +++ b/test/pager1.test @@ -1396,26 +1396,47 @@ do_test pager1-9.3.1 { execsql { PRAGMA page_size = 1024 } for {set ii 0} {$ii < 4} {incr ii} { execsql "CREATE TABLE t${ii}(a, b)" } } {} -do_test pager1-9.3.2 { - sqlite3 db2 test.db2 - - execsql { - PRAGMA page_size = 4096; - PRAGMA synchronous = OFF; - CREATE TABLE t1(a, b); - CREATE TABLE t2(a, b); - } db2 - - sqlite3_backup B db2 main db main - B step 30 - list [B step 10000] [B finish] -} {SQLITE_DONE SQLITE_OK} -do_test pager1-9.3.3 { - db2 close - db close - tv delete - file size test.db2 -} [file size test.db] +if {[nonzero_reserved_bytes]} { + # backup with a page size changes is not possible with the codec + # + do_test pager1-9.3.2codec { + sqlite3 db2 test.db2 + execsql { + PRAGMA page_size = 4096; + PRAGMA synchronous = OFF; + CREATE TABLE t1(a, b); + CREATE TABLE t2(a, b); + } db2 + sqlite3_backup B db2 main db main + B step 30 + list [B step 10000] [B finish] + } {SQLITE_READONLY SQLITE_READONLY} + do_test pager1-9.3.3codec { + db2 close + db close + tv delete + file size test.db2 + } [file size test.db2] +} else { + do_test pager1-9.3.2 { + sqlite3 db2 test.db2 + execsql { + PRAGMA page_size = 4096; + PRAGMA synchronous = OFF; + CREATE TABLE t1(a, b); + CREATE TABLE t2(a, b); + } db2 + sqlite3_backup B db2 main db main + B step 30 + list [B step 10000] [B finish] + } {SQLITE_DONE SQLITE_OK} + do_test pager1-9.3.3 { + db2 close + db close + tv delete + file size test.db2 + } [file size test.db] +} do_test pager1-9.4.1 { faultsim_delete_and_reopen @@ -2447,13 +2468,23 @@ do_test pager1-29.1 { } file size test.db } [expr 1024*3] -do_test pager1-29.2 { - execsql { - PRAGMA page_size = 4096; - VACUUM; - } - file size test.db -} [expr 4096*3] +if {[nonzero_reserved_bytes]} { + # VACUUM with size changes is not possible with the codec. + do_test pager1-29.2 { + catchsql { + PRAGMA page_size = 4096; + VACUUM; + } + } {1 {attempt to write a readonly database}} +} else { + do_test pager1-29.2 { + execsql { + PRAGMA page_size = 4096; + VACUUM; + } + file size test.db + } [expr 4096*3] +} #------------------------------------------------------------------------- # Test that if an empty database file (size 0 bytes) is opened in diff --git a/test/superlock.test b/test/superlock.test index 1e4a4a78d9..704b0677a1 100644 --- a/test/superlock.test +++ b/test/superlock.test @@ -239,13 +239,23 @@ db_swap test.db2 test.db do_catchsql_test 6.9 { SELECT * FROM t1 } {0 {1 2 3 4}} do_catchsql_test 6.10 { SELECT * FROM t2 } {1 {no such table: t2}} -do_execsql_test 6.11 { - PRAGMA journal_mode = delete; - PRAGMA page_size = 512; - VACUUM; - PRAGMA journal_mode = wal; - INSERT INTO t1 VALUES(5, 6); -} {delete wal} +if {[nonzero_reserved_bytes]} { + # Vacuum with a size change is not allowed with the codec + do_execsql_test 6.11codec { + PRAGMA journal_mode = delete; + VACUUM; + PRAGMA journal_mode = wal; + INSERT INTO t1 VALUES(5, 6); + } {delete wal} +} else { + do_execsql_test 6.11 { + PRAGMA journal_mode = delete; + PRAGMA page_size = 512; + VACUUM; + PRAGMA journal_mode = wal; + INSERT INTO t1 VALUES(5, 6); + } {delete wal} +} db_swap test.db2 test.db do_catchsql_test 6.12 { SELECT * FROM t1 } {1 {no such table: t1}} From a580936383cd6fd971b9895bca635b1aa6d72ac3 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 14 Mar 2016 21:26:25 +0000 Subject: [PATCH 467/570] Fix the permutations.test script so that it works again. FossilOrigin-Name: 9f194f90c07d5415b1d6bb10ec049f74999d6885 --- manifest | 13 ++++++------- manifest.uuid | 2 +- test/permutations.test | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 7a5dde7ec7..056a1fb6f3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\stest\sscripts\sso\sthat\sthey\swork\swith\sSEE. -D 2016-03-14T21:12:26.457 +C Fix\sthe\spermutations.test\sscript\sso\sthat\sit\sworks\sagain. +D 2016-03-14T21:26:25.596 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -950,7 +950,7 @@ F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test 64abe58d53cde4adcfb881e37aa5ea1b2a980e58 +F test/permutations.test af8067e4b6d684518956f8e2a744f42bde99014d F test/pragma.test afbf028be1c35b68f57db8eb015c4a3c59d8f28e F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f F test/pragma3.test 3f1984a04657331f838df5c519b443c2088df922 @@ -1456,8 +1456,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 f7480e33eb82f2eae219d17ce46cd2d4edac07d2 92be06c1a828d56652fa5269a3029f8cb029b2cd -R 24275616ba2669073b7ddeb77ba67682 -T +closed 92be06c1a828d56652fa5269a3029f8cb029b2cd +P f4693ba4bbd9738b45012cf507fc0d7b6d04b7ee +R b91725f8858bc448d609dcaeb28fa81e U drh -Z d1492fd2b8bf4cccc192885ce03fdf82 +Z 51ddcfc985bc0e936856bdb8a64dca36 diff --git a/manifest.uuid b/manifest.uuid index 39aab6c8e0..bac1f45a16 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f4693ba4bbd9738b45012cf507fc0d7b6d04b7ee \ No newline at end of file +9f194f90c07d5415b1d6bb10ec049f74999d6885 \ No newline at end of file diff --git a/test/permutations.test b/test/permutations.test index 6c02af8fbe..37736feb81 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -1068,12 +1068,12 @@ proc help {} { exit -1 } -if {[info script] == $argv0} { +if {[file tail $argv0] == "permutations.test"} { proc main {argv} { if {[llength $argv]==0} { help } else { - set suite [lindex $argv 0] + set suite [file tail [lindex $argv 0]] if {[info exists ::testspec($suite)]==0} help set extra "" if {[llength $argv]>1} { set extra [list -files [lrange $argv 1 end]] } From 089555c8e9fabb1b19db0ad03b5b31936af7a98f Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 15 Mar 2016 09:55:44 +0000 Subject: [PATCH 468/570] Fix the shellN.test test scripts so that they work with the --testdir option. FossilOrigin-Name: 051c61ebae921b70f843c55aacf046a9922cc187 --- manifest | 24 ++++++++++++------------ manifest.uuid | 2 +- test/shell1.test | 10 +--------- test/shell2.test | 10 +--------- test/shell3.test | 10 +--------- test/shell4.test | 10 +--------- test/shell5.test | 10 +--------- test/tester.tcl | 18 ++++++++++++++++++ 8 files changed, 36 insertions(+), 58 deletions(-) diff --git a/manifest b/manifest index 056a1fb6f3..c36b917a58 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\spermutations.test\sscript\sso\sthat\sit\sworks\sagain. -D 2016-03-14T21:26:25.596 +C Fix\sthe\sshellN.test\stest\sscripts\sso\sthat\sthey\swork\swith\sthe\s--testdir\soption. +D 2016-03-15T09:55:44.853 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1025,11 +1025,11 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test a45b424ec23a4b946848ff9e1af5186c677162ab -F test/shell2.test 12b8bf901b0e3a8ac58cf5c0c63a0a388d4d1862 -F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29 -F test/shell4.test f43e250139dc5dc5f0f2ec1752c50284a1ede102 -F test/shell5.test c04e9f9f948305706b88377c464c7f08ce7479f9 +F test/shell1.test e7dac9830b7d80432be9cebfae06eff9c18675f5 +F test/shell2.test 2e7a32c9ee03c6398478637d72416d5b9ebd9777 +F test/shell3.test c39453d3012a39ffec944566eca8a6bda10a2284 +F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9 +F test/shell5.test 50a732c1c2158b1cd62cf53975ce1ea7ce6b9dc9 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5 F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce @@ -1085,7 +1085,7 @@ F test/tclsqlite.test c6d9f546f79d15d0134c1e06583fb3ee0c3afad3 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl d6dee24773e20320ab64d39bb5ce6e1a91b6029e +F test/tester.tcl 859a7ccbe5bd65f0f8b524cd51c318d3edcd3008 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1456,7 +1456,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 f4693ba4bbd9738b45012cf507fc0d7b6d04b7ee -R b91725f8858bc448d609dcaeb28fa81e -U drh -Z 51ddcfc985bc0e936856bdb8a64dca36 +P 9f194f90c07d5415b1d6bb10ec049f74999d6885 +R 50980fd60bfbb727ae154c36fe3906ce +U dan +Z f0681fd41f2ae1a8be1bbfb650e8fc11 diff --git a/manifest.uuid b/manifest.uuid index bac1f45a16..77d14b9109 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9f194f90c07d5415b1d6bb10ec049f74999d6885 \ No newline at end of file +051c61ebae921b70f843c55aacf046a9922cc187 \ No newline at end of file diff --git a/test/shell1.test b/test/shell1.test index 1b9ea1d383..1f1f3de320 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -21,15 +21,7 @@ # set testdir [file dirname $argv0] source $testdir/tester.tcl -if {$tcl_platform(platform)=="windows"} { - set CLI "sqlite3.exe" -} else { - set CLI "./sqlite3" -} -if {![file executable $CLI]} { - finish_test - return -} +set CLI [test_find_cli] db close forcedelete test.db test.db-journal test.db-wal sqlite3 db test.db diff --git a/test/shell2.test b/test/shell2.test index 616610bd4b..9388b719b3 100644 --- a/test/shell2.test +++ b/test/shell2.test @@ -20,15 +20,7 @@ # set testdir [file dirname $argv0] source $testdir/tester.tcl -if {$tcl_platform(platform)=="windows"} { - set CLI "sqlite3.exe" -} else { - set CLI "./sqlite3" -} -if {![file executable $CLI]} { - finish_test - return -} +set CLI [test_find_cli] db close forcedelete test.db test.db-journal test.db-wal sqlite3 db test.db diff --git a/test/shell3.test b/test/shell3.test index ce1fd4ecb5..3ded8f5ccd 100644 --- a/test/shell3.test +++ b/test/shell3.test @@ -21,15 +21,7 @@ # set testdir [file dirname $argv0] source $testdir/tester.tcl -if {$tcl_platform(platform)=="windows"} { - set CLI "sqlite3.exe" -} else { - set CLI "./sqlite3" -} -if {![file executable $CLI]} { - finish_test - return -} +set CLI [test_find_cli] db close forcedelete test.db test.db-journal test.db-wal sqlite3 db test.db diff --git a/test/shell4.test b/test/shell4.test index 18e7d7fdf6..3e4ae55816 100644 --- a/test/shell4.test +++ b/test/shell4.test @@ -21,15 +21,7 @@ # set testdir [file dirname $argv0] source $testdir/tester.tcl -if {$tcl_platform(platform)=="windows"} { - set CLI "sqlite3.exe" -} else { - set CLI "./sqlite3" -} -if {![file executable $CLI]} { - finish_test - return -} +set CLI [test_find_cli] db close forcedelete test.db test.db-journal test.db-wal sqlite3 db test.db diff --git a/test/shell5.test b/test/shell5.test index b921accca5..bb2511a525 100644 --- a/test/shell5.test +++ b/test/shell5.test @@ -21,15 +21,7 @@ # set testdir [file dirname $argv0] source $testdir/tester.tcl -if {$tcl_platform(platform)=="windows"} { - set CLI "sqlite3.exe" -} else { - set CLI "./sqlite3" -} -if {![file executable $CLI]} { - finish_test - return -} +set CLI [test_find_cli] db close forcedelete test.db test.db-journal test.db-wal diff --git a/test/tester.tcl b/test/tester.tcl index 3a881138e2..1c83e34c0d 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -2136,6 +2136,24 @@ proc test_restore_config_pagecache {} { sqlite3 db test.db } +# Find the name of the 'shell' executable (e.g. "sqlite3.exe") to use for +# the tests in shell[1-5].test. If no such executable can be found, invoke +# [finish_test ; return] in the callers context. +# +proc test_find_cli {} { + if {$::tcl_platform(platform)=="windows"} { + set ret "sqlite3.exe" + } else { + set ret "sqlite3" + } + set ret [file normalize [file join $::cmdlinearg(TESTFIXTURE_HOME) $ret]] + if {![file executable $ret]} { + finish_test + return -code return + } + return $ret +} + # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set # to non-zero, then set the global variable $AUTOVACUUM to 1. set AUTOVACUUM $sqlite_options(default_autovacuum) From 82f525406af6e0ca6887a82c8bb561fac610fa59 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 15 Mar 2016 12:37:08 +0000 Subject: [PATCH 469/570] More test-case changes so that everything works when the reserved_bytes value in the header is non-zero. FossilOrigin-Name: 2fd095b14b03a508169bba710d2e8e2addf4b8f5 --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- test/corrupt2.test | 44 +++++++++++++++++++++++--------------------- test/filefmt.test | 16 ++++++++++------ test/pageropt.test | 4 ++++ test/wal5.test | 6 +++--- 6 files changed, 51 insertions(+), 41 deletions(-) diff --git a/manifest b/manifest index c36b917a58..5b830ffdfa 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\sshellN.test\stest\sscripts\sso\sthat\sthey\swork\swith\sthe\s--testdir\soption. -D 2016-03-15T09:55:44.853 +C More\stest-case\schanges\sso\sthat\severything\sworks\swhen\sthe\sreserved_bytes\nvalue\sin\sthe\sheader\sis\snon-zero. +D 2016-03-15T12:37:08.820 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -548,7 +548,7 @@ F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c F test/conflict3.test dec0634c0f31dec9a4b01c63063e939f0cd21b6b F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4 F test/corrupt.test 141c39ea650c1365e85a49e402fa05cb9617fb97 -F test/corrupt2.test cb787825d761b0f869764d6990531382840de872 +F test/corrupt2.test e4964cee73dda57a90958e0087a6b388b1d9cb58 F test/corrupt3.test e676f478fe602915d721472811f6f410b75ddc7e F test/corrupt4.test 8d1d86b850fcc43e417450454f2044e52d55778a F test/corrupt5.test 8ead52af76006f3286e9396cb41898018ccea107 @@ -638,7 +638,7 @@ F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9 F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79 F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7 F test/filectrl.test 7c13f96457435238da99aff7343ad6a3a4885787 -F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146 +F test/filefmt.test e4edbdc637ca9576ccf4337a3cce627d9df7a56c F test/fkey1.test 13e3d48236a2b9f5c5ebd232eef9b3ab682a8a2c F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9 F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 @@ -944,7 +944,7 @@ F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e F test/pagerfault.test ae9ee0db5a30aecda9db8290ce3dd12e5f7bbaa1 F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8 -F test/pageropt.test f8d840f0fed84854dbd12b4c17fb3506eeb8224c +F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0 F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305 F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b @@ -1307,7 +1307,7 @@ F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477 F test/wal2.test 25ae059e900dbb584e0775627e45415ba5940df1 F test/wal3.test 5dd734147f1f8f958c5261a1f2775d346d7013ce F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c -F test/wal5.test 22cb252502c5ff851925add2ca8a7e2af012e1d6 +F test/wal5.test 9c11da7aeccd83a46d79a556ad11a18d3cb15aa9 F test/wal6.test a9d6aa635b9d63607dabdc11406f5f96ca986635 F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8 F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd @@ -1456,7 +1456,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 9f194f90c07d5415b1d6bb10ec049f74999d6885 -R 50980fd60bfbb727ae154c36fe3906ce -U dan -Z f0681fd41f2ae1a8be1bbfb650e8fc11 +P 051c61ebae921b70f843c55aacf046a9922cc187 +R 1b522ee9926e242e3422d1eddaaf0fbf +U drh +Z 3fc58440746cd83f06c07d7c16cdd74a diff --git a/manifest.uuid b/manifest.uuid index 77d14b9109..e76d63af73 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -051c61ebae921b70f843c55aacf046a9922cc187 \ No newline at end of file +2fd095b14b03a508169bba710d2e8e2addf4b8f5 \ No newline at end of file diff --git a/test/corrupt2.test b/test/corrupt2.test index 9bd29cf90f..efeb26bc8a 100644 --- a/test/corrupt2.test +++ b/test/corrupt2.test @@ -346,27 +346,29 @@ ifcapable autovacuum { } {1 {database disk image is malformed}} } - corruption_test -sqlprep { - PRAGMA auto_vacuum = 1; - PRAGMA page_size = 1024; - CREATE TABLE t1(a INTEGER PRIMARY KEY, b); - INSERT INTO t1 VALUES(1, randomblob(2500)); - DELETE FROM t1 WHERE a = 1; - } -corrupt { - set nAppend [expr 1024*207 - [file size corrupt.db]] - set fd [open corrupt.db r+] - seek $fd 0 end - puts -nonewline $fd [string repeat x $nAppend] - close $fd - hexio_write corrupt.db 28 00000000 - } -test { - do_test corrupt2-6.4 { - catchsql " - $::presql - BEGIN EXCLUSIVE; - COMMIT; - " - } {1 {database disk image is malformed}} + if {![nonzero_reserved_bytes]} { + corruption_test -sqlprep { + PRAGMA auto_vacuum = 1; + PRAGMA page_size = 1024; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + INSERT INTO t1 VALUES(1, randomblob(2500)); + DELETE FROM t1 WHERE a = 1; + } -corrupt { + set nAppend [expr 1024*207 - [file size corrupt.db]] + set fd [open corrupt.db r+] + seek $fd 0 end + puts -nonewline $fd [string repeat x $nAppend] + close $fd + hexio_write corrupt.db 28 00000000 + } -test { + do_test corrupt2-6.4 { + catchsql " + $::presql + BEGIN EXCLUSIVE; + COMMIT; + " + } {1 {database disk image is malformed}} + } } } diff --git a/test/filefmt.test b/test/filefmt.test index 2df1424436..087a955c39 100644 --- a/test/filefmt.test +++ b/test/filefmt.test @@ -144,9 +144,11 @@ do_execsql_test filefmt-2.1.1 { CREATE TABLE t2(a); INSERT INTO t2 VALUES(1); } {} -do_test filefmt-2.1.2 { - hexio_read test.db 28 4 -} {00000009} +if {![nonzero_reserved_bytes]} { + do_test filefmt-2.1.2 { + hexio_read test.db 28 4 + } {00000009} +} do_test filefmt-2.1.3 { sql36231 { INSERT INTO t1 VALUES(a_string(3000)) } @@ -170,9 +172,11 @@ do_execsql_test filefmt-2.2.1 { CREATE TABLE t2(a); INSERT INTO t2 VALUES(1); } {} -do_test filefmt-2.2.2 { - hexio_read test.db 28 4 -} {00000009} +if {![nonzero_reserved_bytes]} { + do_test filefmt-2.2.2 { + hexio_read test.db 28 4 + } {00000009} +} do_test filefmt-2.2.3 { sql36231 { INSERT INTO t1 VALUES(a_string(3000)) } diff --git a/test/pageropt.test b/test/pageropt.test index f8f5c71892..f58b8ee781 100644 --- a/test/pageropt.test +++ b/test/pageropt.test @@ -23,6 +23,10 @@ ifcapable {!pager_pragmas||secure_delete||direct_read} { return } +# A non-zero reserved_bytes value changes the number of pages in the +# database file, which messes up the results in this test. +if {[nonzero_reserved_bytes]} {finish_test; return;} + # Run the SQL statement supplied by the argument and return # the results. Prepend four integers to the beginning of the # result which are diff --git a/test/wal5.test b/test/wal5.test index 0f6dcfa6a7..50c517286a 100644 --- a/test/wal5.test +++ b/test/wal5.test @@ -141,13 +141,13 @@ foreach {testprefix do_wal_checkpoint} { do_test 1.$tn.7 { reopen_all list [db_page_count] [wal_page_count] $::nBusyHandler - } {7 0 0} + } [expr {[nonzero_reserved_bytes]?"/# # 0/":"7 0 0"}] do_test 1.$tn.8 { sql2 { BEGIN ; SELECT x FROM t1 } } {1 2 3 4 5} do_test 1.$tn.9 { sql1 { INSERT INTO t1 VALUES(6, zeroblob(1200)) } list [db_page_count] [wal_page_count] $::nBusyHandler - } {7 5 0} + } [expr {[nonzero_reserved_bytes]?"/# # #/":"7 5 0"}] do_test 1.$tn.10 { sql3 { BEGIN ; SELECT x FROM t1 } } {1 2 3 4 5 6} set ::busy_handler_script { @@ -158,7 +158,7 @@ foreach {testprefix do_wal_checkpoint} { do_test 1.$tn.11 { code1 { do_wal_checkpoint db -mode restart } list [db_page_count] [wal_page_count] $::nBusyHandler - } {10 5 8} + } [expr {[nonzero_reserved_bytes]?"/# # #/":"10 5 8"}] do_test 1.$tn.12 { set ::db_file_size } 10 } From 0ff47e9e1b74e270648cac1ea72f9bcf4e35031d Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 15 Mar 2016 17:52:12 +0000 Subject: [PATCH 470/570] Implement FROM-clause subqueries as co-routines whenever they are guaranteed to be the outer-most loop of the join. FossilOrigin-Name: c7bae50bdccb5bcf3bc22e8ac5bb6725ef13db39 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/select.c | 20 +++++++++++++++++--- test/select4.test | 37 ++++++++++++++++++++++++++++++++++++- 4 files changed, 61 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 5b830ffdfa..61ece923e2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C More\stest-case\schanges\sso\sthat\severything\sworks\swhen\sthe\sreserved_bytes\nvalue\sin\sthe\sheader\sis\snon-zero. -D 2016-03-15T12:37:08.820 +C Implement\sFROM-clause\ssubqueries\sas\sco-routines\swhenever\sthey\sare\sguaranteed\nto\sbe\sthe\souter-most\sloop\sof\sthe\sjoin. +D 2016-03-15T17:52:12.224 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -350,7 +350,7 @@ F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e -F src/select.c 137b31daa84d57d67847bf621bb54f3353e2077b +F src/select.c 6dd2097bb158efe3b8d68683dcc3b4a49e907a34 F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 0235586b3fb639e85998d495c90f007657fd82af F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -999,7 +999,7 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5 F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686 F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56 F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054 -F test/select4.test 453631158540e5f685b81cac5b7e8bd8c6b4c5fc +F test/select4.test d926792a5e4d88fef0ddcddeb45d27ce75f7296c F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535 F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0 F test/select7.test 95e370c42d47c3c52377d05e9ffc01ccff7c1f61 @@ -1456,7 +1456,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 051c61ebae921b70f843c55aacf046a9922cc187 -R 1b522ee9926e242e3422d1eddaaf0fbf +P 2fd095b14b03a508169bba710d2e8e2addf4b8f5 +R dae03fc18d1aaaa839efcf6d42490a7e U drh -Z 3fc58440746cd83f06c07d7c16cdd74a +Z 042547ad8e59422492ad781582901ed5 diff --git a/manifest.uuid b/manifest.uuid index e76d63af73..b2a61f89c1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2fd095b14b03a508169bba710d2e8e2addf4b8f5 \ No newline at end of file +c7bae50bdccb5bcf3bc22e8ac5bb6725ef13db39 \ No newline at end of file diff --git a/src/select.c b/src/select.c index c9bc389b2f..a62581efc1 100644 --- a/src/select.c +++ b/src/select.c @@ -4970,10 +4970,24 @@ int sqlite3Select( } /* Generate code to implement the subquery + ** + ** The subquery is implemented as a co-routine if all of these are true: + ** (1) The subquery is guaranteed to be the outer loop (so that it + ** does not need to be computed more than once) + ** (2) The ALL keyword after SELECT is omitted. (Applications are + ** allowed to say "SELECT ALL" instead of just "SELECT" to disable + ** the use of co-routines.) + ** (3) Co-routines are not disabled using sqlite3_test_control() + ** with SQLITE_TESTCTRL_OPTIMIZATIONS. + ** + ** TODO: Are there other reasons beside (1) to use a co-routine + ** implementation? */ - if( pTabList->nSrc==1 - && (p->selFlags & SF_All)==0 - && OptimizationEnabled(db, SQLITE_SubqCoroutine) + if( i==0 + && (pTabList->nSrc==1 + || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */ + && (p->selFlags & SF_All)==0 /* (2) */ + && OptimizationEnabled(db, SQLITE_SubqCoroutine) /* (3) */ ){ /* Implement a co-routine that will return a single row of the result ** set on each invocation. diff --git a/test/select4.test b/test/select4.test index be8d0e0ab1..1f29f29073 100644 --- a/test/select4.test +++ b/test/select4.test @@ -12,7 +12,6 @@ # focus of this file is testing UNION, INTERSECT and EXCEPT operators # in SELECT statements. # -# $Id: select4.test,v 1.30 2009/04/16 00:24:24 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -936,4 +935,40 @@ do_execsql_test select4-15.1 { ORDER BY 1; } {1 33 456 2 33 789} +# Enhancement (2016-03-15): Use a co-routine for subqueries if the +# subquery is guaranteed to be the outer-most query +# +do_execsql_test select4-16.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(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,z, + PRIMARY KEY(a,b DESC)) WITHOUT ROWID; + + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) + INSERT INTO t1(a,b,c,d) + SELECT x%10, x/10, x, printf('xyz%dabc',x) FROM c; + + SELECT t3.c FROM + (SELECT a,max(b) AS m FROM t1 WHERE a>=5 GROUP BY a) AS t2 + JOIN t1 AS t3 + WHERE t2.a=t3.a AND t2.m=t3.b + ORDER BY t3.a; +} {95 96 97 98 99} +do_execsql_test select4-16.2 { + SELECT t3.c FROM + (SELECT a,max(b) AS m FROM t1 WHERE a>=5 GROUP BY a) AS t2 + CROSS JOIN t1 AS t3 + WHERE t2.a=t3.a AND t2.m=t3.b + ORDER BY t3.a; +} {95 96 97 98 99} +do_execsql_test select4-16.3 { + SELECT t3.c FROM + (SELECT a,max(b) AS m FROM t1 WHERE a>=5 GROUP BY a) AS t2 + LEFT JOIN t1 AS t3 + WHERE t2.a=t3.a AND t2.m=t3.b + ORDER BY t3.a; +} {95 96 97 98 99} + + + + finish_test From b7b91068ee0e5bc18d8f490056dd20f79a2f4d27 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Tue, 15 Mar 2016 19:10:39 +0000 Subject: [PATCH 471/570] In the Win32 VFS, use SQLITE_FCNTL_LAST_ERRNO instead of (the older) SQLITE_LAST_ERRNO. FossilOrigin-Name: 9463762c437488970a87093ef13131c39b2adadc --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/os_win.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 61ece923e2..e0adb2742c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Implement\sFROM-clause\ssubqueries\sas\sco-routines\swhenever\sthey\sare\sguaranteed\nto\sbe\sthe\souter-most\sloop\sof\sthe\sjoin. -D 2016-03-15T17:52:12.224 +C In\sthe\sWin32\sVFS,\suse\sSQLITE_FCNTL_LAST_ERRNO\sinstead\sof\s(the\solder)\sSQLITE_LAST_ERRNO. +D 2016-03-15T19:10:39.513 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -335,7 +335,7 @@ F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c f5bac8e74aaefc4ea520e43b4540793c3b8a9e8f -F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d +F src/os_win.c cbf8c442a0d818d05bcf40b093cb3ebad435b9be F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 38718a019ca762ba4f6795425d5a54db70d1790d F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 @@ -1456,7 +1456,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 2fd095b14b03a508169bba710d2e8e2addf4b8f5 -R dae03fc18d1aaaa839efcf6d42490a7e -U drh -Z 042547ad8e59422492ad781582901ed5 +P c7bae50bdccb5bcf3bc22e8ac5bb6725ef13db39 +R 46123ac548d09b6e0ffa37ea5d80c14d +U mistachkin +Z d90a9a53fb7ea7a50e56b06b4f7c6bc4 diff --git a/manifest.uuid b/manifest.uuid index b2a61f89c1..14d2985670 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c7bae50bdccb5bcf3bc22e8ac5bb6725ef13db39 \ No newline at end of file +9463762c437488970a87093ef13131c39b2adadc \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index af6b1c814c..6ff50c554b 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -3257,7 +3257,7 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } - case SQLITE_LAST_ERRNO: { + case SQLITE_FCNTL_LAST_ERRNO: { *(int*)pArg = (int)pFile->lastErrno; OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; From 98968b22c5c6b2b4c9fb89b8d7d0199a650044a0 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 15 Mar 2016 22:00:39 +0000 Subject: [PATCH 472/570] Change the OP_IntegrityCk opcode to accept the list of root pages as an intarray argument in P4. Slightly smaller and faster. FossilOrigin-Name: 15e4a272df46cbad8e71b21551dc06a126d64d46 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/pragma.c | 28 ++++++++++++++++------------ src/vdbe.c | 17 +++++------------ 4 files changed, 30 insertions(+), 33 deletions(-) diff --git a/manifest b/manifest index e0adb2742c..95e98afa0f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sWin32\sVFS,\suse\sSQLITE_FCNTL_LAST_ERRNO\sinstead\sof\s(the\solder)\sSQLITE_LAST_ERRNO. -D 2016-03-15T19:10:39.513 +C Change\sthe\sOP_IntegrityCk\sopcode\sto\saccept\sthe\slist\sof\sroot\spages\sas\san\nintarray\sargument\sin\sP4.\s\sSlightly\ssmaller\sand\sfaster. +D 2016-03-15T22:00:39.610 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -343,7 +343,7 @@ F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 -F src/pragma.c c7061870c235702a513ce4152fe978faf3f282eb +F src/pragma.c 04baa9343771f913f1c86b2720f768be8a3ad52a F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 @@ -416,7 +416,7 @@ F src/update.c 56b3db7edff0110360a12b76af97c39ebe3ea8b8 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 34ef7be420f82415ec48131404995ddb6ee7502f F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 -F src/vdbe.c 87ae3a5657fefed7875f3eb30e7ababd48013d71 +F src/vdbe.c 8cf45bb8da77d39f55d108e759d15a57acd0255c F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 F src/vdbeInt.h 49a74fe5ece206d2d8666ba9afaf1abeda5f123b F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 @@ -1456,7 +1456,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 c7bae50bdccb5bcf3bc22e8ac5bb6725ef13db39 -R 46123ac548d09b6e0ffa37ea5d80c14d -U mistachkin -Z d90a9a53fb7ea7a50e56b06b4f7c6bc4 +P 9463762c437488970a87093ef13131c39b2adadc +R 6817ca21db6938155940db404d48bb61 +U drh +Z e5f48f52274ef8efc53f2f946a6d2fff diff --git a/manifest.uuid b/manifest.uuid index 14d2985670..a7f49d3bce 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9463762c437488970a87093ef13131c39b2adadc \ No newline at end of file +15e4a272df46cbad8e71b21551dc06a126d64d46 \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index 883ab60c67..70c2950c8e 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1439,6 +1439,7 @@ void sqlite3Pragma( for(i=0; inDb; i++){ HashElem *x; Hash *pTbls; + int *aRoot; int cnt = 0; if( OMIT_TEMPDB && i==1 ) continue; @@ -1452,31 +1453,34 @@ void sqlite3Pragma( /* Do an integrity check of the B-Tree ** - ** Begin by filling registers 2, 3, ... with the root pages numbers + ** Begin by finding the root pages numbers ** for all tables and indices in the database. */ assert( sqlite3SchemaMutexHeld(db, i, 0) ); pTbls = &db->aDb[i].pSchema->tblHash; - for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; - if( HasRowid(pTab) ){ - sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt); - VdbeComment((v, "%s", pTab->zName)); - cnt++; - } + if( HasRowid(pTab) ) cnt++; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ cnt++; } + } + aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(cnt+1)); + if( aRoot==0 ) break; + for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + Table *pTab = sqliteHashData(x); + Index *pIdx; + if( HasRowid(pTab) ) aRoot[cnt++] = pTab->tnum; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 2+cnt); - VdbeComment((v, "%s", pIdx->zName)); - cnt++; + aRoot[cnt++] = pIdx->tnum; } } + aRoot[cnt] = 0; /* Make sure sufficient number of registers have been allocated */ - pParse->nMem = MAX( pParse->nMem, cnt+8 ); + pParse->nMem = MAX( pParse->nMem, 14 ); /* Do the b-tree integrity checks */ - sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1); + sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY); sqlite3VdbeChangeP5(v, (u8)i); addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, diff --git a/src/vdbe.c b/src/vdbe.c index 3351a44551..6f4ac5713d 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5422,7 +5422,7 @@ case OP_DropTrigger: { #ifndef SQLITE_OMIT_INTEGRITY_CHECK -/* Opcode: IntegrityCk P1 P2 P3 * P5 +/* Opcode: IntegrityCk P1 P2 P3 P4 P5 ** ** Do an analysis of the currently open database. Store in ** register P1 the text of an error message describing any problems. @@ -5433,9 +5433,8 @@ case OP_DropTrigger: { ** In other words, the analysis stops as soon as reg(P1) errors are ** seen. Reg(P1) is updated with the number of errors remaining. ** -** The root page numbers of all tables in the database are integer -** stored in reg(P1), reg(P1+1), reg(P1+2), .... There are P2 tables -** total. +** The root page numbers of all tables in the database are integers +** stored in P4_INTARRAY argument. ** ** If P5 is not zero, the check is done on the auxiliary database ** file, not the main database file. @@ -5445,30 +5444,24 @@ case OP_DropTrigger: { case OP_IntegrityCk: { int nRoot; /* Number of tables to check. (Number of root pages.) */ int *aRoot; /* Array of rootpage numbers for tables to be checked */ - int j; /* Loop counter */ int nErr; /* Number of errors reported */ char *z; /* Text of the error report */ Mem *pnErr; /* Register keeping track of errors remaining */ assert( p->bIsReader ); nRoot = pOp->p2; + aRoot = pOp->p4.ai; assert( nRoot>0 ); - aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(nRoot+1) ); - if( aRoot==0 ) goto no_mem; + assert( aRoot[nRoot]==0 ); assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pnErr = &aMem[pOp->p3]; assert( (pnErr->flags & MEM_Int)!=0 ); assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); pIn1 = &aMem[pOp->p1]; - for(j=0; jp5nDb ); assert( DbMaskTest(p->btreeMask, pOp->p5) ); z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, (int)pnErr->u.i, &nErr); - sqlite3DbFree(db, aRoot); pnErr->u.i -= nErr; sqlite3VdbeMemSetNull(pIn1); if( nErr==0 ){ From c5db1d4b4c8978825ee79d660e6d7cf25fdd103d Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 16 Mar 2016 00:36:19 +0000 Subject: [PATCH 473/570] Rearrange some internal fields in the sqlite3_stmt object to avoid a harmless TSAN warning. FossilOrigin-Name: e0b116edd64a55c971c368685aa343cb6beed0f1 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbeInt.h | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 95e98afa0f..8154a2631d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sOP_IntegrityCk\sopcode\sto\saccept\sthe\slist\sof\sroot\spages\sas\san\nintarray\sargument\sin\sP4.\s\sSlightly\ssmaller\sand\sfaster. -D 2016-03-15T22:00:39.610 +C Rearrange\ssome\sinternal\sfields\sin\sthe\ssqlite3_stmt\sobject\sto\savoid\sa\sharmless\nTSAN\swarning. +D 2016-03-16T00:36:19.731 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -418,7 +418,7 @@ F src/util.c 34ef7be420f82415ec48131404995ddb6ee7502f F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c 8cf45bb8da77d39f55d108e759d15a57acd0255c F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 -F src/vdbeInt.h 49a74fe5ece206d2d8666ba9afaf1abeda5f123b +F src/vdbeInt.h f88d3115e9bde33b01d81f0dd26d8dd51f995991 F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 F src/vdbeaux.c 2c15cf88de4df97428318c8cfac0dea873dae451 F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db @@ -1456,7 +1456,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 9463762c437488970a87093ef13131c39b2adadc -R 6817ca21db6938155940db404d48bb61 +P 15e4a272df46cbad8e71b21551dc06a126d64d46 +R 82478b12d64974258326bdaae56626ca U drh -Z e5f48f52274ef8efc53f2f946a6d2fff +Z e403476d229295941bbcf1df1a4408f9 diff --git a/manifest.uuid b/manifest.uuid index a7f49d3bce..f76cceaf73 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -15e4a272df46cbad8e71b21551dc06a126d64d46 \ No newline at end of file +e0b116edd64a55c971c368685aa343cb6beed0f1 \ No newline at end of file diff --git a/src/vdbeInt.h b/src/vdbeInt.h index b53952fd44..a78795f61c 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -381,16 +381,16 @@ struct Vdbe { #endif u16 nResColumn; /* Number of columns in one row of the result set */ u8 errorAction; /* Recovery action to do in case of an error */ + bft expired:1; /* True if the VM needs to be recompiled */ + bft doingRerun:1; /* True if rerunning after an auto-reprepare */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ bft explain:2; /* True if EXPLAIN present on SQL command */ bft changeCntOn:1; /* True to update the change-counter */ - bft expired:1; /* True if the VM needs to be recompiled */ bft runOnlyOnce:1; /* Automatically expire on reset */ bft usesStmtJournal:1; /* True if uses a statement journal */ bft readOnly:1; /* True for statements that do not write */ bft bIsReader:1; /* True for statements that read */ bft isPrepareV2:1; /* True if prepared with prepare_v2() */ - bft doingRerun:1; /* True if rerunning after an auto-reprepare */ int nChange; /* Number of db changes made since last reset */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ From 32f57d4c373c8f49b59f4a40149c136ef8a5632b Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 16 Mar 2016 01:03:10 +0000 Subject: [PATCH 474/570] Add the SQLITE_OMIT_CODEC_FROM_TCL compile-time option. FossilOrigin-Name: 45f7f0c80bd91a0c7ff859c27fd9e82e551bd83e --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/tclsqlite.c | 14 +++++++------- src/test1.c | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 8154a2631d..bf413d574c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Rearrange\ssome\sinternal\sfields\sin\sthe\ssqlite3_stmt\sobject\sto\savoid\sa\sharmless\nTSAN\swarning. -D 2016-03-16T00:36:19.731 +C Add\sthe\sSQLITE_OMIT_CODEC_FROM_TCL\scompile-time\soption. +D 2016-03-16T01:03:10.251 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -359,8 +359,8 @@ F src/sqliteInt.h 84c673f27b77dfbd367cb3ed1de8b6f3b73102dc F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 -F src/tclsqlite.c 54dca4eaf3a9cb0a4b845ef54ffa99225c30a52e -F src/test1.c f14a6f9e2cff6cba4d83e2b0c52857f61886cead +F src/tclsqlite.c 4bf3bea9b03aeac176ac114700f35f76a1de4c8a +F src/test1.c 52965bd684ddcd7f22328ebd7d50fd0b6e51f0d4 F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e @@ -1456,7 +1456,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 15e4a272df46cbad8e71b21551dc06a126d64d46 -R 82478b12d64974258326bdaae56626ca +P e0b116edd64a55c971c368685aa343cb6beed0f1 +R 1b0c52bbc749be5b9a732d29d3d099e5 U drh -Z e403476d229295941bbcf1df1a4408f9 +Z 5dddb7cbfc6ef15baab9797e73067d60 diff --git a/manifest.uuid b/manifest.uuid index f76cceaf73..3aa4fcd861 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e0b116edd64a55c971c368685aa343cb6beed0f1 \ No newline at end of file +45f7f0c80bd91a0c7ff859c27fd9e82e551bd83e \ No newline at end of file diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 4e19f92644..42dd6b0f49 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -2574,7 +2574,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ ** Change the encryption key on the currently open database. */ case DB_REKEY: { -#ifdef SQLITE_HAS_CODEC +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) int nKey; void *pKey; #endif @@ -2582,7 +2582,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ Tcl_WrongNumArgs(interp, 2, objv, "KEY"); return TCL_ERROR; } -#ifdef SQLITE_HAS_CODEC +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey); rc = sqlite3_rekey(pDb->db, pKey, nKey); if( rc ){ @@ -2955,7 +2955,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ const char *zVfs = 0; int flags; Tcl_DString translatedFilename; -#ifdef SQLITE_HAS_CODEC +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) void *pKey = 0; int nKey = 0; #endif @@ -2984,7 +2984,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ return TCL_OK; } if( strcmp(zArg,"-has-codec")==0 ){ -#ifdef SQLITE_HAS_CODEC +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) Tcl_AppendResult(interp,"1",(char*)0); #else Tcl_AppendResult(interp,"0",(char*)0); @@ -2995,7 +2995,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ for(i=3; i+1db ){ sqlite3_key(p->db, pKey, nKey); } diff --git a/src/test1.c b/src/test1.c index 744b400b2a..8ad653ca6c 100644 --- a/src/test1.c +++ b/src/test1.c @@ -651,7 +651,7 @@ static int test_key( int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ -#ifdef SQLITE_HAS_CODEC +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) sqlite3 *db; const char *zKey; int nKey; From 892ffcc7fc5b0a6d20c20c64b56096ee8ecbd207 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 16 Mar 2016 18:26:54 +0000 Subject: [PATCH 475/570] Fix the query planner so that it is able to use the integer primary key from an index as part of a multi-column constraint. FossilOrigin-Name: 96ea9909429f0b3b4a67002e8340ae3f7dc0b73f --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 3 ++- test/intpkey.test | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index bf413d574c..9530ffa5fc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_OMIT_CODEC_FROM_TCL\scompile-time\soption. -D 2016-03-16T01:03:10.251 +C Fix\sthe\squery\splanner\sso\sthat\sit\sis\sable\sto\suse\sthe\sinteger\sprimary\skey\nfrom\san\sindex\sas\spart\sof\sa\smulti-column\sconstraint. +D 2016-03-16T18:26:54.117 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -430,7 +430,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c 5533002ddf4fbc256f450cb629668a200b06a3ce +F src/where.c fe7925faafbe9a458972035c0bb4753d672f04ed F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 863aedf086131743763c1960637fde904eadc442 F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a @@ -820,7 +820,7 @@ F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6 F test/instr.test 737bbf80685232033f3abedc6ae92f75860b5dd2 F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4 F test/interrupt.test dfe9a67a94b0b2d8f70545ba1a6cca10780d71cc -F test/intpkey.test 7506090fc08e028712a8bf47e5f54111947e3844 +F test/intpkey.test 70aab09756b9bd3bcb6b0358f971d7bbace46522 F test/io.test f95bca1783b01ea7761671560d023360d2dfa4cc F test/ioerr.test 2a24bd6ed5a8b062e64bfe1f6cf94fb25e92210d F test/ioerr2.test 2593563599e2cc6b6b4fcf5878b177bdd5d8df26 @@ -1456,7 +1456,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 e0b116edd64a55c971c368685aa343cb6beed0f1 -R 1b0c52bbc749be5b9a732d29d3d099e5 +P 45f7f0c80bd91a0c7ff859c27fd9e82e551bd83e +R 48d902683e4b6144f631d91ce9dec30e U drh -Z 5dddb7cbfc6ef15baab9797e73067d60 +Z 4770e56ece3387d541183edf6806d70a diff --git a/manifest.uuid b/manifest.uuid index 3aa4fcd861..11ed7df765 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -45f7f0c80bd91a0c7ff859c27fd9e82e551bd83e \ No newline at end of file +96ea9909429f0b3b4a67002e8340ae3f7dc0b73f \ No newline at end of file diff --git a/src/where.c b/src/where.c index 83d72ee397..cf23aa62a4 100644 --- a/src/where.c +++ b/src/where.c @@ -289,6 +289,7 @@ static WhereTerm *whereScanInit( j = iColumn; iColumn = pIdx->aiColumn[j]; if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; + if( iColumn==pIdx->pTable->iPKey ) iColumn = XN_ROWID; } if( pIdx && iColumn>=0 ){ pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; @@ -3929,7 +3930,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){ int j; Table *pTab; Index *pIdx; - + pWInfo = pBuilder->pWInfo; if( pWInfo->wctrlFlags & WHERE_FORCE_TABLE ) return 0; assert( pWInfo->pTabList->nSrc>=1 ); diff --git a/test/intpkey.test b/test/intpkey.test index 41858e5d46..a149f43fb2 100644 --- a/test/intpkey.test +++ b/test/intpkey.test @@ -296,7 +296,7 @@ do_test intpkey-3.8 { count { SELECT * FROM t1 WHERE c=='world' AND a>7; } -} {11 hello world 4} +} {11 hello world 3} do_test intpkey-3.9 { count { SELECT * FROM t1 WHERE 7 Date: Wed, 16 Mar 2016 19:45:54 +0000 Subject: [PATCH 476/570] Enhance Lemon so that it reorders the reduce rules such that rules without actions occur at the end and so that the first rule is number 0. This reduces the size of the jump table on the reduce switch, and helps the parser to run faster. FossilOrigin-Name: d5712f21ec758ff096a7b1bb8ed4fc5ec400ca5d --- manifest | 15 ++++---- manifest.uuid | 2 +- tool/lemon.c | 97 +++++++++++++++++++++++++++++++++++++++++---------- tool/lempar.c | 11 +++--- 4 files changed, 92 insertions(+), 33 deletions(-) diff --git a/manifest b/manifest index 000b9dec54..c10487dd6a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\sa\sfew\sunnecessary\sfstat()s\son\sjournal\sfiles. -D 2016-03-16T19:10:46.537 +C Enhance\sLemon\sso\sthat\sit\sreorders\sthe\sreduce\srules\ssuch\sthat\srules\swithout\nactions\soccur\sat\sthe\send\sand\sso\sthat\sthe\sfirst\srule\sis\snumber\s0.\s\sThis\nreduces\sthe\ssize\sof\sthe\sjump\stable\son\sthe\sreduce\sswitch,\sand\shelps\sthe\sparser\nto\srun\sfaster. +D 2016-03-16T19:45:54.638 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1386,8 +1386,8 @@ F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce -F tool/lemon.c 251f5c3f21b553240cbdd42dd187a51bb2372cd3 -F tool/lempar.c d5114c7d13aa3af1e27ff3d02e4dea6eadec7ddf +F tool/lemon.c cfbfe061a4b2766512f6b484882eee2c86a14506 +F tool/lempar.c 404ea3dc27dbeed343f0e61b1d36e97b9f5f0fb6 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh e855df211ecbcc7131dee817110ff386cfb112f7 @@ -1456,8 +1456,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 96ea9909429f0b3b4a67002e8340ae3f7dc0b73f f3c0579e931799088e9a83757e25bae229120697 -R 2179dd350d027a0023ff0b4d274ede19 -T +closed f3c0579e931799088e9a83757e25bae229120697 +P dbf84705913c0845ca4e75eb30c91536c754efeb +R 864f536bc3cc564acb40b05c95555e64 U drh -Z 6f4affaf464559d5d4fad621b1dda7eb +Z 3c44460af79cebe8997bb55087f66950 diff --git a/manifest.uuid b/manifest.uuid index 9fc448cbd8..33a88b381b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dbf84705913c0845ca4e75eb30c91536c754efeb \ No newline at end of file +d5712f21ec758ff096a7b1bb8ed4fc5ec400ca5d \ No newline at end of file diff --git a/tool/lemon.c b/tool/lemon.c index cefdf80174..903fe97cfb 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -290,6 +290,7 @@ struct rule { const char *codeSuffix; /* Breakdown code after code[] above */ struct symbol *precsym; /* Precedence symbol for this rule */ int index; /* An index number for this rule */ + int iRule; /* Rule number as used in the generated tables */ Boolean canReduce; /* True if this rule is ever reduced */ struct rule *nextlhs; /* Next rule with the same LHS */ struct rule *next; /* Next rule in the global list */ @@ -372,6 +373,7 @@ struct plink { struct lemon { struct state **sorted; /* Table of states sorted by state number */ struct rule *rule; /* List of all rules */ + struct rule *startRule; /* First rule */ int nstate; /* Number of states */ int nxstate; /* nstate with tail degenerate states removed */ int nrule; /* Number of rules */ @@ -858,12 +860,12 @@ void FindStates(struct lemon *lemp) ErrorMsg(lemp->filename,0, "The specified start symbol \"%s\" is not \ in a nonterminal of the grammar. \"%s\" will be used as the start \ -symbol instead.",lemp->start,lemp->rule->lhs->name); +symbol instead.",lemp->start,lemp->startRule->lhs->name); lemp->errorcnt++; - sp = lemp->rule->lhs; + sp = lemp->startRule->lhs; } }else{ - sp = lemp->rule->lhs; + sp = lemp->startRule->lhs; } /* Make sure the start symbol doesn't occur on the right-hand side of @@ -1117,9 +1119,9 @@ void FindActions(struct lemon *lemp) /* Add the accepting token */ if( lemp->start ){ sp = Symbol_find(lemp->start); - if( sp==0 ) sp = lemp->rule->lhs; + if( sp==0 ) sp = lemp->startRule->lhs; }else{ - sp = lemp->rule->lhs; + sp = lemp->startRule->lhs; } /* Add to the first state (which is always the starting state of the ** finite state machine) an action to ACCEPT if the lookahead is the @@ -1497,6 +1499,54 @@ static void handle_T_option(char *z){ lemon_strcpy(user_templatename, z); } +/* Merge together to lists of rules order by rule.iRule */ +static struct rule *Rule_merge(struct rule *pA, struct rule *pB){ + struct rule *pFirst = 0; + struct rule **ppPrev = &pFirst; + while( pA && pB ){ + if( pA->iRuleiRule ){ + *ppPrev = pA; + ppPrev = &pA->next; + pA = pA->next; + }else{ + *ppPrev = pB; + ppPrev = &pB->next; + pB = pB->next; + } + } + if( pA ){ + *ppPrev = pA; + }else{ + *ppPrev = pB; + } + return pFirst; +} + +/* +** Sort a list of rules in order of increasing iRule value +*/ +static struct rule *Rule_sort(struct rule *rp){ + int i; + struct rule *pNext; + struct rule *x[32]; + memset(x, 0, sizeof(x)); + while( rp ){ + pNext = rp->next; + rp->next = 0; + for(i=0; iname[0]); i++); lem.nterminal = i; + /* Assign sequential rule numbers */ + for(i=0, rp=lem.rule; rp; rp=rp->next){ + rp->iRule = rp->code ? i++ : -1; + } + for(rp=lem.rule; rp; rp=rp->next){ + if( rp->iRule<0 ) rp->iRule = i++; + } + lem.startRule = lem.rule; + lem.rule = Rule_sort(lem.rule); + /* Generate a reprint of the grammar, if requested on the command line */ if( rpflag ){ Reprint(&lem); @@ -3054,13 +3115,13 @@ int PrintAction( } case REDUCE: { struct rule *rp = ap->x.rp; - fprintf(fp,"%*s reduce %-7d",indent,ap->sp->name,rp->index); + fprintf(fp,"%*s reduce %-7d",indent,ap->sp->name,rp->iRule); RulePrint(fp, rp, -1); break; } case SHIFTREDUCE: { struct rule *rp = ap->x.rp; - fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->index); + fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->iRule); RulePrint(fp, rp, -1); break; } @@ -3073,7 +3134,7 @@ int PrintAction( case SRCONFLICT: case RRCONFLICT: fprintf(fp,"%*s reduce %-7d ** Parsing conflict **", - indent,ap->sp->name,ap->x.rp->index); + indent,ap->sp->name,ap->x.rp->iRule); break; case SSCONFLICT: fprintf(fp,"%*s shift %-7d ** Parsing conflict **", @@ -3090,7 +3151,7 @@ int PrintAction( case RD_RESOLVED: if( showPrecedenceConflict ){ fprintf(fp,"%*s reduce %-7d -- dropped by precedence", - indent,ap->sp->name,ap->x.rp->index); + indent,ap->sp->name,ap->x.rp->iRule); }else{ result = 0; } @@ -3121,7 +3182,7 @@ void ReportOutput(struct lemon *lemp) while( cfp ){ char buf[20]; if( cfp->dot==cfp->rp->nrhs ){ - lemon_sprintf(buf,"(%d)",cfp->rp->index); + lemon_sprintf(buf,"(%d)",cfp->rp->iRule); fprintf(fp," %5s ",buf); }else{ fprintf(fp," "); @@ -3222,8 +3283,8 @@ PRIVATE int compute_action(struct lemon *lemp, struct action *ap) int act; switch( ap->type ){ case SHIFT: act = ap->x.stp->statenum; break; - case SHIFTREDUCE: act = ap->x.rp->index + lemp->nstate; break; - case REDUCE: act = ap->x.rp->index + lemp->nstate+lemp->nrule; break; + case SHIFTREDUCE: act = ap->x.rp->iRule + lemp->nstate; break; + case REDUCE: act = ap->x.rp->iRule + lemp->nstate+lemp->nrule; break; case ERROR: act = lemp->nstate + lemp->nrule*2; break; case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1; break; default: act = -1; break; @@ -4241,7 +4302,7 @@ void ReportTable( ** when tracing REDUCE actions. */ for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){ - assert( rp->index==i ); + assert( rp->iRule==i ); fprintf(out," /* %3d */ \"", i); writeRuleText(out, rp); fprintf(out,"\",\n"); lineno++; @@ -4337,14 +4398,14 @@ void ReportTable( struct rule *rp2; /* Other rules with the same action */ if( rp->code==0 ) continue; if( rp->code[0]=='\n' && rp->code[1]==0 ) continue; /* Will be default: */ - fprintf(out," case %d: /* ", rp->index); + fprintf(out," case %d: /* ", rp->iRule); writeRuleText(out, rp); fprintf(out, " */\n"); lineno++; for(rp2=rp->next; rp2; rp2=rp2->next){ if( rp2->code==rp->code ){ - fprintf(out," case %d: /* ", rp2->index); + fprintf(out," case %d: /* ", rp2->iRule); writeRuleText(out, rp2); - fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->index); lineno++; + fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++; rp2->code = 0; } } @@ -4358,9 +4419,9 @@ void ReportTable( for(rp=lemp->rule; rp; rp=rp->next){ if( rp->code==0 ) continue; assert( rp->code[0]=='\n' && rp->code[1]==0 ); - fprintf(out," /* (%d) ", rp->index); + fprintf(out," /* (%d) ", rp->iRule); writeRuleText(out, rp); - fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->index); lineno++; + fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++; } fprintf(out," break;\n"); lineno++; tplt_xfer(lemp->name,in,out,&lineno); diff --git a/tool/lempar.c b/tool/lempar.c index db7f2dbf1b..e313904082 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -418,7 +418,7 @@ int ParseStackPeak(void *p){ ** Find the appropriate action for a parser given the terminal ** look-ahead token iLookAhead. */ -static int yy_find_shift_action( +static unsigned int yy_find_shift_action( yyParser *pParser, /* The parser */ YYCODETYPE iLookAhead /* The look-ahead token */ ){ @@ -606,7 +606,7 @@ static void yy_accept(yyParser*); /* Forward Declaration */ */ static void yy_reduce( yyParser *yypParser, /* The parser */ - int yyruleno /* Number of the rule by which to reduce */ + unsigned int yyruleno /* Number of the rule by which to reduce */ ){ int yygoto; /* The next state */ int yyact; /* The next action */ @@ -615,8 +615,7 @@ static void yy_reduce( ParseARG_FETCH; yymsp = &yypParser->yystack[yypParser->yyidx]; #ifndef NDEBUG - if( yyTraceFILE && yyruleno>=0 - && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ + if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ yysize = yyRuleInfo[yyruleno].nrhs; fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, yyRuleName[yyruleno], yymsp[-yysize].stateno); @@ -661,7 +660,7 @@ static void yy_reduce( %% /********** End reduce actions ************************************************/ }; - assert( yyruleno>=0 && yyruleno Date: Wed, 16 Mar 2016 19:48:10 +0000 Subject: [PATCH 477/570] Have fts5 cache the decoded structure of fts5 indexes in memory. Use "PRAGMA data_version" to detect stale caches. FossilOrigin-Name: 33ef2210ef19e55c8d460bfe9d3dc146034c8acc --- ext/fts5/fts5Int.h | 2 + ext/fts5/fts5_index.c | 115 +++++++++++++++++++++++++++----- ext/fts5/fts5_main.c | 39 +++++++---- ext/fts5/fts5_storage.c | 4 ++ ext/fts5/test/fts5corrupt3.test | 4 ++ ext/fts5/test/fts5dlidx.test | 4 +- manifest | 27 ++++---- manifest.uuid | 2 +- 8 files changed, 153 insertions(+), 44 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index 35f15abbaf..961206f2b3 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -480,6 +480,7 @@ int sqlite3Fts5IndexReads(Fts5Index *p); int sqlite3Fts5IndexReinit(Fts5Index *p); int sqlite3Fts5IndexOptimize(Fts5Index *p); int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge); +int sqlite3Fts5IndexReset(Fts5Index *p); int sqlite3Fts5IndexLoadConfig(Fts5Index *p); @@ -622,6 +623,7 @@ int sqlite3Fts5StorageDeleteAll(Fts5Storage *p); int sqlite3Fts5StorageRebuild(Fts5Storage *p); int sqlite3Fts5StorageOptimize(Fts5Storage *p); int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge); +int sqlite3Fts5StorageReset(Fts5Storage *p); /* ** End of interface to code in fts5_storage.c. diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 323e6cefdc..78003396d6 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -304,6 +304,10 @@ struct Fts5Index { sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=? */ sqlite3_stmt *pIdxSelect; int nRead; /* Total number of blocks read */ + + sqlite3_stmt *pDataVersion; + i64 iStructVersion; /* data_version when pStruct read */ + Fts5Structure *pStruct; /* Current db structure (or NULL) */ }; struct Fts5DoclistIter { @@ -959,6 +963,48 @@ static void fts5StructureExtendLevel( } } +static Fts5Structure *fts5StructureReadUncached(Fts5Index *p){ + Fts5Structure *pRet = 0; + Fts5Config *pConfig = p->pConfig; + int iCookie; /* Configuration cookie */ + Fts5Data *pData; + + pData = fts5DataRead(p, FTS5_STRUCTURE_ROWID); + if( p->rc==SQLITE_OK ){ + /* TODO: Do we need this if the leaf-index is appended? Probably... */ + memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING); + p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet); + if( p->rc==SQLITE_OK && pConfig->iCookie!=iCookie ){ + p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie); + } + fts5DataRelease(pData); + if( p->rc!=SQLITE_OK ){ + fts5StructureRelease(pRet); + pRet = 0; + } + } + + return pRet; +} + +static i64 fts5IndexDataVersion(Fts5Index *p){ + i64 iVersion = 0; + + if( p->pDataVersion==0 ){ + p->rc = fts5IndexPrepareStmt(p, &p->pDataVersion, + sqlite3_mprintf("PRAGMA %Q.data_version", p->pConfig->zDb) + ); + if( p->rc ) return 0; + } + + if( SQLITE_ROW==sqlite3_step(p->pDataVersion) ){ + iVersion = sqlite3_column_int64(p->pDataVersion, 0); + } + p->rc = sqlite3_reset(p->pDataVersion); + + return iVersion; +} + /* ** Read, deserialize and return the structure record. ** @@ -971,28 +1017,51 @@ static void fts5StructureExtendLevel( ** is called, it is a no-op. */ static Fts5Structure *fts5StructureRead(Fts5Index *p){ - Fts5Config *pConfig = p->pConfig; - Fts5Structure *pRet = 0; /* Object to return */ - int iCookie; /* Configuration cookie */ - Fts5Data *pData; + Fts5Structure *pRet; /* Object to return */ - pData = fts5DataRead(p, FTS5_STRUCTURE_ROWID); - if( p->rc ) return 0; - /* TODO: Do we need this if the leaf-index is appended? Probably... */ - memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING); - p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet); - if( p->rc==SQLITE_OK && pConfig->iCookie!=iCookie ){ - p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie); + if( p->pStruct ){ + pRet = p->pStruct; +#ifdef SQLITE_DEBUG + { + Fts5Structure *pTest = fts5StructureReadUncached(p); + if( pTest ){ + int i, j; + assert_nc( pRet->nSegment==pTest->nSegment ); + assert_nc( pRet->nLevel==pTest->nLevel ); + for(i=0; inLevel; i++){ + assert_nc( pRet->aLevel[i].nMerge==pTest->aLevel[i].nMerge ); + assert_nc( pRet->aLevel[i].nSeg==pTest->aLevel[i].nSeg ); + for(j=0; jaLevel[i].nSeg; j++){ + Fts5StructureSegment *p1 = &pTest->aLevel[i].aSeg[j]; + Fts5StructureSegment *p2 = &pRet->aLevel[i].aSeg[j]; + assert_nc( p1->iSegid==p2->iSegid ); + assert_nc( p1->pgnoFirst==p2->pgnoFirst ); + assert_nc( p1->pgnoLast==p2->pgnoLast ); + } + } + fts5StructureRelease(pTest); + } + } +#endif + }else{ + pRet = fts5StructureReadUncached(p); } - fts5DataRelease(pData); - if( p->rc!=SQLITE_OK ){ - fts5StructureRelease(pRet); - pRet = 0; + if( pRet ){ + fts5StructureRef(pRet); + p->pStruct = pRet; + p->iStructVersion = fts5IndexDataVersion(p); } return pRet; } +static void fts5StructureInvalidate(Fts5Index *p){ + if( p->pStruct ){ + fts5StructureRelease(p->pStruct); + p->pStruct = 0; + } +} + /* ** Return the total number of segments in index structure pStruct. This ** function is only ever used as part of assert() conditions. @@ -4328,6 +4397,7 @@ static void fts5FlushOneHash(Fts5Index *p){ ** for the new level-0 segment. */ pStruct = fts5StructureRead(p); iSegid = fts5AllocateSegid(p, pStruct); + fts5StructureInvalidate(p); if( iSegid ){ const int pgsz = p->pConfig->pgsz; @@ -4547,6 +4617,7 @@ int sqlite3Fts5IndexOptimize(Fts5Index *p){ assert( p->rc==SQLITE_OK ); fts5IndexFlush(p); pStruct = fts5StructureRead(p); + fts5StructureInvalidate(p); if( pStruct ){ pNew = fts5IndexOptimizeStruct(p, pStruct); @@ -4577,6 +4648,7 @@ int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){ Fts5Structure *pStruct = fts5StructureRead(p); if( pStruct ){ int nMin = p->pConfig->nUsermerge; + fts5StructureInvalidate(p); if( nMerge<0 ){ Fts5Structure *pNew = fts5IndexOptimizeStruct(p, pStruct); fts5StructureRelease(pStruct); @@ -5004,6 +5076,7 @@ int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit){ int sqlite3Fts5IndexRollback(Fts5Index *p){ fts5CloseReader(p); fts5IndexDiscardData(p); + fts5StructureInvalidate(p); /* assert( p->rc==SQLITE_OK ); */ return SQLITE_OK; } @@ -5015,6 +5088,7 @@ int sqlite3Fts5IndexRollback(Fts5Index *p){ */ int sqlite3Fts5IndexReinit(Fts5Index *p){ Fts5Structure s; + fts5StructureInvalidate(p); memset(&s, 0, sizeof(Fts5Structure)); fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0); fts5StructureWrite(p, &s); @@ -5073,11 +5147,13 @@ int sqlite3Fts5IndexClose(Fts5Index *p){ int rc = SQLITE_OK; if( p ){ assert( p->pReader==0 ); + fts5StructureInvalidate(p); sqlite3_finalize(p->pWriter); sqlite3_finalize(p->pDeleter); sqlite3_finalize(p->pIdxWriter); sqlite3_finalize(p->pIdxDeleter); sqlite3_finalize(p->pIdxSelect); + sqlite3_finalize(p->pDataVersion); sqlite3Fts5HashFree(p->pHash); sqlite3_free(p->zDataTbl); sqlite3_free(p); @@ -6333,3 +6409,12 @@ int sqlite3Fts5IndexInit(sqlite3 *db){ } return rc; } + + +int sqlite3Fts5IndexReset(Fts5Index *p){ + assert( p->pStruct==0 || p->iStructVersion!=0 ); + if( fts5IndexDataVersion(p)!=p->iStructVersion ){ + fts5StructureInvalidate(p); + } + return fts5IndexReturn(p); +} diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index dcd131c74a..4feb3e1a2f 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -597,27 +597,38 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ return SQLITE_OK; } +static int fts5NewTransaction(Fts5Table *pTab){ + Fts5Cursor *pCsr; + for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){ + if( pCsr->base.pVtab==(sqlite3_vtab*)pTab ) return SQLITE_OK; + } + return sqlite3Fts5StorageReset(pTab->pStorage); +} + /* ** Implementation of xOpen method. */ static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ Fts5Table *pTab = (Fts5Table*)pVTab; Fts5Config *pConfig = pTab->pConfig; - Fts5Cursor *pCsr; /* New cursor object */ + Fts5Cursor *pCsr = 0; /* New cursor object */ int nByte; /* Bytes of space to allocate */ - int rc = SQLITE_OK; /* Return code */ + int rc; /* Return code */ - nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int); - pCsr = (Fts5Cursor*)sqlite3_malloc(nByte); - if( pCsr ){ - Fts5Global *pGlobal = pTab->pGlobal; - memset(pCsr, 0, nByte); - pCsr->aColumnSize = (int*)&pCsr[1]; - pCsr->pNext = pGlobal->pCsr; - pGlobal->pCsr = pCsr; - pCsr->iCsrId = ++pGlobal->iNextId; - }else{ - rc = SQLITE_NOMEM; + rc = fts5NewTransaction(pTab); + if( rc==SQLITE_OK ){ + nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int); + pCsr = (Fts5Cursor*)sqlite3_malloc(nByte); + if( pCsr ){ + Fts5Global *pGlobal = pTab->pGlobal; + memset(pCsr, 0, nByte); + pCsr->aColumnSize = (int*)&pCsr[1]; + pCsr->pNext = pGlobal->pCsr; + pGlobal->pCsr = pCsr; + pCsr->iCsrId = ++pGlobal->iNextId; + }else{ + rc = SQLITE_NOMEM; + } } *ppCsr = (sqlite3_vtab_cursor*)pCsr; return rc; @@ -1578,8 +1589,8 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){ ** Implementation of xBegin() method. */ static int fts5BeginMethod(sqlite3_vtab *pVtab){ - UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */ fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0); + fts5NewTransaction((Fts5Table*)pVtab); return SQLITE_OK; } diff --git a/ext/fts5/fts5_storage.c b/ext/fts5/fts5_storage.c index e4f5dd8f51..bd1c1f88e9 100644 --- a/ext/fts5/fts5_storage.c +++ b/ext/fts5/fts5_storage.c @@ -639,6 +639,10 @@ int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge){ return sqlite3Fts5IndexMerge(p->pIndex, nMerge); } +int sqlite3Fts5StorageReset(Fts5Storage *p){ + return sqlite3Fts5IndexReset(p->pIndex); +} + /* ** Allocate a new rowid. This is used for "external content" tables when ** a NULL value is inserted into the rowid column. The new rowid is allocated diff --git a/ext/fts5/test/fts5corrupt3.test b/ext/fts5/test/fts5corrupt3.test index 7a8cb5c465..9653bcaac2 100644 --- a/ext/fts5/test/fts5corrupt3.test +++ b/ext/fts5/test/fts5corrupt3.test @@ -179,6 +179,10 @@ for {set i 1} {1} {incr i} { if {$end<=$i} break lset var end [expr $end - $i] set struct [binary format c* $var] + + db close + sqlite3 db test.db + db eval { BEGIN; UPDATE t1_data SET block = $struct WHERE id=10; diff --git a/ext/fts5/test/fts5dlidx.test b/ext/fts5/test/fts5dlidx.test index 232b5021f1..655beb984b 100644 --- a/ext/fts5/test/fts5dlidx.test +++ b/ext/fts5/test/fts5dlidx.test @@ -178,7 +178,7 @@ do_execsql_test 3.2 { ORDER BY rowid DESC; } {16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1} -do_execsql_test 3.2 { +do_execsql_test 3.3 { INSERT INTO abc(abc) VALUES('integrity-check'); INSERT INTO abc(abc) VALUES('optimize'); INSERT INTO abc(abc) VALUES('integrity-check'); @@ -187,7 +187,7 @@ do_execsql_test 3.2 { set v [lindex $vocab 0] set i 0 foreach v $vocab { - do_execsql_test 3.3.[incr i] { + do_execsql_test 3.4.[incr i] { SELECT rowid FROM abc WHERE abc MATCH $v } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16} } diff --git a/manifest b/manifest index bf413d574c..7c682009be 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_OMIT_CODEC_FROM_TCL\scompile-time\soption. -D 2016-03-16T01:03:10.251 +C Have\sfts5\scache\sthe\sdecoded\sstructure\sof\sfts5\sindexes\sin\smemory.\sUse\s"PRAGMA\sdata_version"\sto\sdetect\sstale\scaches. +D 2016-03-16T19:48:10.873 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -98,15 +98,15 @@ F ext/fts3/unicode/mkunicode.tcl 2debed3f582d77b3fdd0b8830880250021571fd8 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 -F ext/fts5/fts5Int.h 4060504b7979601d99e1385c2b5713036854979a +F ext/fts5/fts5Int.h 4e507abebae0d7d3ac9b8daebf049d5153d00961 F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458 F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 F ext/fts5/fts5_expr.c be309fb227003c931107bfcc12d5be4f2fd2bb8c F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c d4f0c12e4f04bbc3a06b6da052039f2ce3e45438 -F ext/fts5/fts5_main.c b8501e1a6a11591c53b18ce7aea7e5386cfb0421 -F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e +F ext/fts5/fts5_index.c 317040cb17cdad05e973376b39239b29c75f90b5 +F ext/fts5/fts5_main.c b4a0fc5bf17f2f1f056ee76cdd7d2af08b360f55 +F ext/fts5/fts5_storage.c a3361410422e69639ca2bcd5a56a0933dadf84d2 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 F ext/fts5/fts5_test_mi.c 783b86697ebf773c18fc109992426c0173a055bc F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be @@ -141,9 +141,9 @@ F ext/fts5/test/fts5conflict.test 26f4e46c4d31e16221794832a990dc4e30e18de5 F ext/fts5/test/fts5content.test 9a952c95518a14182dc3b59e3c8fa71cda82a4e1 F ext/fts5/test/fts5corrupt.test c2ad090192708150d50d961278df10ae7a4b8b62 F ext/fts5/test/fts5corrupt2.test 26c0a39dd9ff73207e6229f83b50b21d37c7658c -F ext/fts5/test/fts5corrupt3.test b9558d5b0ca44a8b6247fbb5d4a47592a8976892 +F ext/fts5/test/fts5corrupt3.test f77f65e386231daf62902466b40ff998b2c8ce4f F ext/fts5/test/fts5detail.test ef5c690535a797413acaf5ad9b8ab5d49972df69 -F ext/fts5/test/fts5dlidx.test 13871a14641017ae42f6f1055a8067bafd44cb3d +F ext/fts5/test/fts5dlidx.test 007e9390c94638760797dbec2990c97c3fa08dfe F ext/fts5/test/fts5doclist.test 8edb5b57e5f144030ed74ec00ef6fa4294fed79b F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0 F ext/fts5/test/fts5eb.test c516ae0c934be6fd29ec95ea8b5f11f461311535 @@ -1456,7 +1456,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e0b116edd64a55c971c368685aa343cb6beed0f1 -R 1b0c52bbc749be5b9a732d29d3d099e5 -U drh -Z 5dddb7cbfc6ef15baab9797e73067d60 +P 45f7f0c80bd91a0c7ff859c27fd9e82e551bd83e +R 7875ababc9def91b1b2c4626dd7ef0ad +T *branch * fts5-data-version +T *sym-fts5-data-version * +T -sym-trunk * +U dan +Z 015dc4987d82758ea8c0d324359dc366 diff --git a/manifest.uuid b/manifest.uuid index 3aa4fcd861..3d6ceeb2ed 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -45f7f0c80bd91a0c7ff859c27fd9e82e551bd83e \ No newline at end of file +33ef2210ef19e55c8d460bfe9d3dc146034c8acc \ No newline at end of file From 377ba3842935e1629ea7cc5379716e084a25e54f Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 16 Mar 2016 19:53:58 +0000 Subject: [PATCH 478/570] Add a cast to an implict (size_t -> int) conversion in fts5_expr.c. FossilOrigin-Name: d9b5ff7aba3a8f6ca4505eac308fa9d510254c3e --- ext/fts5/fts5_expr.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index 1e9be8117d..0bc61414b0 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -2500,7 +2500,7 @@ static int fts5ExprPopulatePoslistsCb( Fts5ExprTerm *pTerm; if( p->aPopulator[i].bOk==0 ) continue; for(pTerm=&pExpr->apExprPhrase[i]->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){ - int nTerm = strlen(pTerm->zTerm); + int nTerm = (int)strlen(pTerm->zTerm); if( (nTerm==nToken || (nTermbPrefix)) && memcmp(pTerm->zTerm, pToken, nTerm)==0 ){ diff --git a/manifest b/manifest index c10487dd6a..7a984cba21 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sLemon\sso\sthat\sit\sreorders\sthe\sreduce\srules\ssuch\sthat\srules\swithout\nactions\soccur\sat\sthe\send\sand\sso\sthat\sthe\sfirst\srule\sis\snumber\s0.\s\sThis\nreduces\sthe\ssize\sof\sthe\sjump\stable\son\sthe\sreduce\sswitch,\sand\shelps\sthe\sparser\nto\srun\sfaster. -D 2016-03-16T19:45:54.638 +C Add\sa\scast\sto\san\simplict\s(size_t\s->\sint)\sconversion\sin\sfts5_expr.c. +D 2016-03-16T19:53:58.157 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -102,7 +102,7 @@ F ext/fts5/fts5Int.h 4060504b7979601d99e1385c2b5713036854979a F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458 F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 -F ext/fts5/fts5_expr.c be309fb227003c931107bfcc12d5be4f2fd2bb8c +F ext/fts5/fts5_expr.c 35e9d92c89e7c7ea0759b73d24da1ecb7630a24b F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 F ext/fts5/fts5_index.c d4f0c12e4f04bbc3a06b6da052039f2ce3e45438 F ext/fts5/fts5_main.c b8501e1a6a11591c53b18ce7aea7e5386cfb0421 @@ -1456,7 +1456,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 dbf84705913c0845ca4e75eb30c91536c754efeb -R 864f536bc3cc564acb40b05c95555e64 -U drh -Z 3c44460af79cebe8997bb55087f66950 +P d5712f21ec758ff096a7b1bb8ed4fc5ec400ca5d +R 9f805acde28759cca26c223b9435e99d +U dan +Z 15773d15bd52be46557d40c4ca5e6748 diff --git a/manifest.uuid b/manifest.uuid index 33a88b381b..4f9852189d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d5712f21ec758ff096a7b1bb8ed4fc5ec400ca5d \ No newline at end of file +d9b5ff7aba3a8f6ca4505eac308fa9d510254c3e \ No newline at end of file From e459bd4986e8221464357233d0419b60c6e5daae Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 16 Mar 2016 20:05:57 +0000 Subject: [PATCH 479/570] Fix a comment on the freelist_count and data_version pragmas. FossilOrigin-Name: 10a3e2a01db9f80452a2a3369fd25b6fd9798274 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/pragma.c | 4 +++- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 7a984cba21..71037fc133 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\scast\sto\san\simplict\s(size_t\s->\sint)\sconversion\sin\sfts5_expr.c. -D 2016-03-16T19:53:58.157 +C Fix\sa\scomment\son\sthe\sfreelist_count\sand\sdata_version\spragmas. +D 2016-03-16T20:05:57.514 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -343,7 +343,7 @@ F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 -F src/pragma.c 04baa9343771f913f1c86b2720f768be8a3ad52a +F src/pragma.c fb8e3e73431a39dc47727ef74aad94a86cfb1d36 F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 @@ -1456,7 +1456,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 d5712f21ec758ff096a7b1bb8ed4fc5ec400ca5d -R 9f805acde28759cca26c223b9435e99d -U dan -Z 15773d15bd52be46557d40c4ca5e6748 +P d9b5ff7aba3a8f6ca4505eac308fa9d510254c3e +R fafe07c0411ab81f336ee3834565f5dd +U drh +Z 9641eb94b1becd7c7420d553fe575786 diff --git a/manifest.uuid b/manifest.uuid index 4f9852189d..a6b92c6b67 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d9b5ff7aba3a8f6ca4505eac308fa9d510254c3e \ No newline at end of file +10a3e2a01db9f80452a2a3369fd25b6fd9798274 \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index 70c2950c8e..4c4bc71ad1 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1706,7 +1706,9 @@ void sqlite3Pragma( ** PRAGMA [schema.]user_version ** PRAGMA [schema.]user_version = ** - ** PRAGMA [schema.]freelist_count = + ** PRAGMA [schema.]freelist_count + ** + ** PRAGMA [schema.]data_version ** ** PRAGMA [schema.]application_id ** PRAGMA [schema.]application_id = From f71a366407a52fc479582de4194ec0da3081bb23 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 16 Mar 2016 20:44:45 +0000 Subject: [PATCH 480/570] Some pragmas can be reused without an automatic reprepare. FossilOrigin-Name: db1ce7e13e656fcd2766f1b1f225cbfefe8f73ad --- manifest | 19 +++++++++++-------- manifest.uuid | 2 +- src/pragma.c | 2 ++ src/vdbe.h | 1 + src/vdbeaux.c | 7 +++++++ 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 71037fc133..2fb10eeede 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scomment\son\sthe\sfreelist_count\sand\sdata_version\spragmas. -D 2016-03-16T20:05:57.514 +C Some\spragmas\scan\sbe\sreused\swithout\san\sautomatic\sreprepare. +D 2016-03-16T20:44:45.683 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -343,7 +343,7 @@ F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 -F src/pragma.c fb8e3e73431a39dc47727ef74aad94a86cfb1d36 +F src/pragma.c f0670909e915179fec47e17f72f14660995b8022 F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 @@ -417,10 +417,10 @@ F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 34ef7be420f82415ec48131404995ddb6ee7502f F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c 8cf45bb8da77d39f55d108e759d15a57acd0255c -F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 +F src/vdbe.h 6f44193e7be52fd5f7c308175a936555b1e6b101 F src/vdbeInt.h f88d3115e9bde33b01d81f0dd26d8dd51f995991 F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 -F src/vdbeaux.c 2c15cf88de4df97428318c8cfac0dea873dae451 +F src/vdbeaux.c a930f913d40e4ca6f6caaef6a7b5906a369fa2b1 F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c 9b0cb32cc267ef026515f15a3594d5ff91fe4dfc F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062 @@ -1456,7 +1456,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d9b5ff7aba3a8f6ca4505eac308fa9d510254c3e -R fafe07c0411ab81f336ee3834565f5dd +P 10a3e2a01db9f80452a2a3369fd25b6fd9798274 +R 2716c51dfa2bfe8ed5e18127e51ae3c8 +T *branch * reusable-pragma +T *sym-reusable-pragma * +T -sym-trunk * U drh -Z 9641eb94b1becd7c7420d553fe575786 +Z 7789d1f13489cbc314e26c9b80a11a2d diff --git a/manifest.uuid b/manifest.uuid index a6b92c6b67..7ffbbd6257 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -10a3e2a01db9f80452a2a3369fd25b6fd9798274 \ No newline at end of file +db1ce7e13e656fcd2766f1b1f225cbfefe8f73ad \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index 4c4bc71ad1..54858afbf1 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1764,6 +1764,7 @@ void sqlite3Pragma( aOp[1].p3 = iCookie; sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); + sqlite3VdbeReusable(v); } } break; @@ -1785,6 +1786,7 @@ void sqlite3Pragma( sqlite3VdbeLoadString(v, 1, zOpt); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); } + sqlite3VdbeReusable(v); } break; #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ diff --git a/src/vdbe.h b/src/vdbe.h index 4c02f5844d..ace28ffdb3 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -202,6 +202,7 @@ void sqlite3VdbeUsesBtree(Vdbe*, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeRunOnlyOnce(Vdbe*); +void sqlite3VdbeReusable(Vdbe*); void sqlite3VdbeDelete(Vdbe*); void sqlite3VdbeClearObject(sqlite3*,Vdbe*); void sqlite3VdbeMakeReady(Vdbe*,Parse*); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 9c75d1e078..c71605cdd2 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -391,6 +391,13 @@ void sqlite3VdbeRunOnlyOnce(Vdbe *p){ p->runOnlyOnce = 1; } +/* +** Mark the VDBE as one that can only be run multiple times. +*/ +void sqlite3VdbeReusable(Vdbe *p){ + p->runOnlyOnce = 0; +} + #ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */ /* From c9460ab989d1a01aac7535811df01094ce0c8e9b Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 17 Mar 2016 12:39:56 +0000 Subject: [PATCH 481/570] Fix some OOM-handling issues in the fts5 changes on this branch. FossilOrigin-Name: 020a0bda59fe93b9361ceeed0d5a8ba4177380c8 --- ext/fts5/fts5_index.c | 83 ++++++++++++++++++++++--------------------- manifest | 12 +++---- manifest.uuid | 2 +- 3 files changed, 50 insertions(+), 47 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 78003396d6..3fb1458526 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -990,17 +990,19 @@ static Fts5Structure *fts5StructureReadUncached(Fts5Index *p){ static i64 fts5IndexDataVersion(Fts5Index *p){ i64 iVersion = 0; - if( p->pDataVersion==0 ){ - p->rc = fts5IndexPrepareStmt(p, &p->pDataVersion, - sqlite3_mprintf("PRAGMA %Q.data_version", p->pConfig->zDb) - ); - if( p->rc ) return 0; - } + if( p->rc==SQLITE_OK ){ + if( p->pDataVersion==0 ){ + p->rc = fts5IndexPrepareStmt(p, &p->pDataVersion, + sqlite3_mprintf("PRAGMA %Q.data_version", p->pConfig->zDb) + ); + if( p->rc ) return 0; + } - if( SQLITE_ROW==sqlite3_step(p->pDataVersion) ){ - iVersion = sqlite3_column_int64(p->pDataVersion, 0); + if( SQLITE_ROW==sqlite3_step(p->pDataVersion) ){ + iVersion = sqlite3_column_int64(p->pDataVersion, 0); + } + p->rc = sqlite3_reset(p->pDataVersion); } - p->rc = sqlite3_reset(p->pDataVersion); return iVersion; } @@ -1019,39 +1021,40 @@ static i64 fts5IndexDataVersion(Fts5Index *p){ static Fts5Structure *fts5StructureRead(Fts5Index *p){ Fts5Structure *pRet; /* Object to return */ - if( p->pStruct ){ - pRet = p->pStruct; -#ifdef SQLITE_DEBUG - { - Fts5Structure *pTest = fts5StructureReadUncached(p); - if( pTest ){ - int i, j; - assert_nc( pRet->nSegment==pTest->nSegment ); - assert_nc( pRet->nLevel==pTest->nLevel ); - for(i=0; inLevel; i++){ - assert_nc( pRet->aLevel[i].nMerge==pTest->aLevel[i].nMerge ); - assert_nc( pRet->aLevel[i].nSeg==pTest->aLevel[i].nSeg ); - for(j=0; jaLevel[i].nSeg; j++){ - Fts5StructureSegment *p1 = &pTest->aLevel[i].aSeg[j]; - Fts5StructureSegment *p2 = &pRet->aLevel[i].aSeg[j]; - assert_nc( p1->iSegid==p2->iSegid ); - assert_nc( p1->pgnoFirst==p2->pgnoFirst ); - assert_nc( p1->pgnoLast==p2->pgnoLast ); - } - } - fts5StructureRelease(pTest); - } - } -#endif - }else{ - pRet = fts5StructureReadUncached(p); - } - - if( pRet ){ - fts5StructureRef(pRet); - p->pStruct = pRet; + if( p->pStruct==0 ){ p->iStructVersion = fts5IndexDataVersion(p); + if( p->rc==SQLITE_OK ){ + p->pStruct = pRet = fts5StructureReadUncached(p); + } + if( p->rc!=SQLITE_OK ) return 0; + assert( p->iStructVersion!=0 ); + assert( p->pStruct!=0 ); } +#ifdef SQLITE_DEBUG + else{ + Fts5Structure *pTest = fts5StructureReadUncached(p); + if( pTest ){ + int i, j; + assert_nc( p->pStruct->nSegment==pTest->nSegment ); + assert_nc( p->pStruct->nLevel==pTest->nLevel ); + for(i=0; inLevel; i++){ + assert_nc( p->pStruct->aLevel[i].nMerge==pTest->aLevel[i].nMerge ); + assert_nc( p->pStruct->aLevel[i].nSeg==pTest->aLevel[i].nSeg ); + for(j=0; jaLevel[i].nSeg; j++){ + Fts5StructureSegment *p1 = &pTest->aLevel[i].aSeg[j]; + Fts5StructureSegment *p2 = &p->pStruct->aLevel[i].aSeg[j]; + assert_nc( p1->iSegid==p2->iSegid ); + assert_nc( p1->pgnoFirst==p2->pgnoFirst ); + assert_nc( p1->pgnoLast==p2->pgnoLast ); + } + } + fts5StructureRelease(pTest); + } + } +#endif + + pRet = p->pStruct; + fts5StructureRef(pRet); return pRet; } diff --git a/manifest b/manifest index 4ea9b53d9e..8f5bdc1491 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\schanges\son\sthe\sreusable-pragma\sbranch\sinto\sthis\sone. -D 2016-03-16T20:53:33.830 +C Fix\ssome\sOOM-handling\sissues\sin\sthe\sfts5\schanges\son\sthis\sbranch. +D 2016-03-17T12:39:56.371 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 F ext/fts5/fts5_expr.c 35e9d92c89e7c7ea0759b73d24da1ecb7630a24b F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c 317040cb17cdad05e973376b39239b29c75f90b5 +F ext/fts5/fts5_index.c afac2ffe3198776626b99366e18af1f32ea9eb85 F ext/fts5/fts5_main.c b4a0fc5bf17f2f1f056ee76cdd7d2af08b360f55 F ext/fts5/fts5_storage.c a3361410422e69639ca2bcd5a56a0933dadf84d2 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -1456,7 +1456,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 33ef2210ef19e55c8d460bfe9d3dc146034c8acc db1ce7e13e656fcd2766f1b1f225cbfefe8f73ad -R 9bcd2375f3bee3eec21a0e0d6e512aed +P 6c4a17b963916d19c9433d7a251338042f32e9fa +R bc1955b591517ca84e5bb3a7a87f0726 U dan -Z 9f0b8bb8494a2ee2e21e8a8509116058 +Z 380059b0b3811052efb55863df364c4f diff --git a/manifest.uuid b/manifest.uuid index 71f9d7efce..d6022948ee 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6c4a17b963916d19c9433d7a251338042f32e9fa \ No newline at end of file +020a0bda59fe93b9361ceeed0d5a8ba4177380c8 \ No newline at end of file From 1b9f2141a7c9e048eb5408a84559151ba8aabd3a Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 17 Mar 2016 16:01:23 +0000 Subject: [PATCH 482/570] Experimental implementation of the sqlite3_system_errno() interface. FossilOrigin-Name: 6782c87b3722fbd09684a5b1e5df05247956f1c6 --- manifest | 32 +++++++++++++++++--------------- manifest.uuid | 2 +- src/loadext.c | 4 +++- src/main.c | 4 ++++ src/os.c | 3 +++ src/os.h | 1 + src/os_unix.c | 15 +++++---------- src/sqlite.h.in | 12 ++++++++++++ src/sqlite3ext.h | 4 ++++ src/sqliteInt.h | 2 ++ src/util.c | 12 ++++++++++++ 11 files changed, 64 insertions(+), 27 deletions(-) diff --git a/manifest b/manifest index 3d02d28e9b..ebc861b735 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sprepared\sstatements\sfor\ssome\spragmas\scan\snow\sbe\sreused\swithout\sinvoking\nan\sautomatic\sreprepare. -D 2016-03-16T21:29:54.761 +C Experimental\simplementation\sof\sthe\ssqlite3_system_errno()\sinterface. +D 2016-03-17T16:01:23.259 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -314,8 +314,8 @@ F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c 723d5d708cdb61bdd47c00b9f07c75be45aefc09 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e -F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f -F src/main.c 29ea8ebb23ceb5159da167e18d5c807fbb1545c4 +F src/loadext.c e70f8f9e97624a232870ea5486e682c813ac3002 +F src/main.c 74591e0405e5e71b276105ac5f8d419dd54e6495 F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -330,11 +330,11 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4 F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23 F src/mutex_w32.c 5e6fe1c298fb5a8a15aaed4161d5759311431c17 F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7 -F src/os.c f89e3ca1c2e3d5015b847aec60371c474acbac82 -F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf +F src/os.c ca10edb445ad2c5fdc7285b49d72bcdf261fa23e +F src/os.h 91ff889115ecd01f436d3611f7f5ea4dc12d92f1 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c 4bde11921a2bebcf2167efc8540ddabc814189dc +F src/os_unix.c 50103f69121bca969761b821e2b0e393b55fe869 F src/os_win.c cbf8c442a0d818d05bcf40b093cb3ebad435b9be F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 38718a019ca762ba4f6795425d5a54db70d1790d @@ -352,10 +352,10 @@ F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 6dd2097bb158efe3b8d68683dcc3b4a49e907a34 F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e -F src/sqlite.h.in 0235586b3fb639e85998d495c90f007657fd82af +F src/sqlite.h.in e877f141b15ef68ef28f84714e69d7234f9a071e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 -F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 84c673f27b77dfbd367cb3ed1de8b6f3b73102dc +F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 +F src/sqliteInt.h 5256653cc049ad48e03189abe106cb45f5eaf2c8 F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -414,7 +414,7 @@ F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c 56b3db7edff0110360a12b76af97c39ebe3ea8b8 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c -F src/util.c 34ef7be420f82415ec48131404995ddb6ee7502f +F src/util.c c3fc5193e6f039fa61afbcc0db87d5a5d563a18a F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c 8cf45bb8da77d39f55d108e759d15a57acd0255c F src/vdbe.h 6f44193e7be52fd5f7c308175a936555b1e6b101 @@ -1456,8 +1456,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 10a3e2a01db9f80452a2a3369fd25b6fd9798274 db1ce7e13e656fcd2766f1b1f225cbfefe8f73ad -R 2716c51dfa2bfe8ed5e18127e51ae3c8 -T +closed db1ce7e13e656fcd2766f1b1f225cbfefe8f73ad +P 97b0e88cc7c3d677217d0bfab4cb4a34a4abb238 +R 2fd7ee41c15d4ef6398866450bc883db +T *branch * sqlite_system_errno +T *sym-sqlite_system_errno * +T -sym-trunk * U drh -Z e3b23194e47816995dbce6c752704ef0 +Z 77c764a9e283f7fe52499f77098482f4 diff --git a/manifest.uuid b/manifest.uuid index 06db10b8a2..f695385706 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -97b0e88cc7c3d677217d0bfab4cb4a34a4abb238 \ No newline at end of file +6782c87b3722fbd09684a5b1e5df05247956f1c6 \ No newline at end of file diff --git a/src/loadext.c b/src/loadext.c index 3469fbb73d..495001e55a 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -414,7 +414,9 @@ static const sqlite3_api_routines sqlite3Apis = { /* Version 3.10.0 and later */ sqlite3_status64, sqlite3_strlike, - sqlite3_db_cacheflush + sqlite3_db_cacheflush, + /* Version 3.12.0 and later */ + sqlite3_system_errno }; /* diff --git a/src/main.c b/src/main.c index 70e46a4ee1..e4d5cb494c 100644 --- a/src/main.c +++ b/src/main.c @@ -2240,6 +2240,9 @@ int sqlite3_extended_errcode(sqlite3 *db){ } return db->errCode; } +int sqlite3_system_errno(sqlite3 *db){ + return db ? db->iSysErrno : 0; +} /* ** Return a string that describes the kind of error specified in the @@ -2865,6 +2868,7 @@ static int openDatabase( if( rc==SQLITE_IOERR_NOMEM ){ rc = SQLITE_NOMEM_BKPT; } + sqlite3SystemError(db, rc); sqlite3Error(db, rc); goto opendb_out; } diff --git a/src/os.c b/src/os.c index eed7828538..bfcc9cdd05 100644 --- a/src/os.c +++ b/src/os.c @@ -262,6 +262,9 @@ int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ return pVfs->xSleep(pVfs, nMicro); } +int sqlite3OsGetLastError(sqlite3_vfs *pVfs){ + return pVfs->xGetLastError ? pVfs->xGetLastError(pVfs, 0, 0) : 0; +} int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ int rc; /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64() diff --git a/src/os.h b/src/os.h index 2c1b86f913..f813541561 100644 --- a/src/os.h +++ b/src/os.h @@ -197,6 +197,7 @@ void sqlite3OsDlClose(sqlite3_vfs *, void *); #endif /* SQLITE_OMIT_LOAD_EXTENSION */ int sqlite3OsRandomness(sqlite3_vfs *, int, char *); int sqlite3OsSleep(sqlite3_vfs *, int); +int sqlite3OsGetLastError(sqlite3_vfs*); int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*); /* diff --git a/src/os_unix.c b/src/os_unix.c index eb1a63c687..d593b952f5 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -6264,23 +6264,18 @@ static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){ # define unixCurrentTime 0 #endif -#ifndef SQLITE_OMIT_DEPRECATED /* -** We added the xGetLastError() method with the intention of providing -** better low-level error messages when operating-system problems come up -** during SQLite operation. But so far, none of that has been implemented -** in the core. So this routine is never called. For now, it is merely -** a place-holder. +** The xGetLastError() method is designed to return a better +** low-level error message when operating-system problems come up +** during SQLite operation. Only the integer return code is currently +** used. */ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ UNUSED_PARAMETER(NotUsed); UNUSED_PARAMETER(NotUsed2); UNUSED_PARAMETER(NotUsed3); - return 0; + return errno; } -#else -# define unixGetLastError 0 -#endif /* diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 3b267974b5..04f4359ecf 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7915,6 +7915,18 @@ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); */ int sqlite3_db_cacheflush(sqlite3*); +/* +** CAPI3REF: Low-level system error code +** +** ^Attempt to return the underlying operating system error code or error +** number that caused the most reason I/O error or failure to open a file. +** The return value is OS-dependent. For example, on unix systems, after +** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be +** called to get back the underlying "errno" that caused the problem, such +** as ENOSPC, EAUTH, EISDIR, and so forth. +*/ +int sqlite3_system_errno(sqlite3*); + /* ** CAPI3REF: Database Snapshot ** KEYWORDS: {snapshot} diff --git a/src/sqlite3ext.h b/src/sqlite3ext.h index 2e1c764a52..20a2fcdf02 100644 --- a/src/sqlite3ext.h +++ b/src/sqlite3ext.h @@ -279,6 +279,8 @@ struct sqlite3_api_routines { int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int); int (*strlike)(const char*,const char*,unsigned int); int (*db_cacheflush)(sqlite3*); + /* Version 3.12.0 and later */ + int (*system_errno)(sqlite3*); }; /* @@ -522,6 +524,8 @@ struct sqlite3_api_routines { #define sqlite3_status64 sqlite3_api->status64 #define sqlite3_strlike sqlite3_api->strlike #define sqlite3_db_cacheflush sqlite3_api->db_cacheflush +/* Version 3.12.0 and later */ +#define sqlite3_system_errno sqlite3_api->system_errno #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f2f485778a..99917b1666 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1220,6 +1220,7 @@ struct sqlite3 { unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ int errCode; /* Most recent error code (SQLITE_*) */ int errMask; /* & result codes with this before returning */ + int iSysErrno; /* Errno value from last system error */ u16 dbOptFlags; /* Flags to enable/disable optimizations */ u8 enc; /* Text encoding */ u8 autoCommit; /* The auto-commit flag. */ @@ -3763,6 +3764,7 @@ int sqlite3Atoi64(const char*, i64*, int, u8); int sqlite3DecOrHexToI64(const char*, i64*); void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...); void sqlite3Error(sqlite3*,int); +void sqlite3SystemError(sqlite3*,int); void *sqlite3HexToBlob(sqlite3*, const char *z, int n); u8 sqlite3HexToInt(int h); int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); diff --git a/src/util.c b/src/util.c index d6a6f6b954..0a705a6a6e 100644 --- a/src/util.c +++ b/src/util.c @@ -126,6 +126,18 @@ void sqlite3Error(sqlite3 *db, int err_code){ if( db->pErr ) sqlite3ValueSetNull(db->pErr); } +/* +** Load the sqlite3.iSysErrno field if that is an appropriate thing +** to do based on the SQLite error code in rc. +*/ +void sqlite3SystemError(sqlite3 *db, int rc){ + if( rc==SQLITE_IOERR_NOMEM ) return; + rc &= 0xff; + if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){ + db->iSysErrno = sqlite3OsGetLastError(db->pVfs); + } +} + /* ** Set the most recent error code and error string for the sqlite ** handle "db". The error code is set to "err_code". From 0e80e50984e2a6128efb64c4998380d5f0595700 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 17 Mar 2016 17:23:11 +0000 Subject: [PATCH 483/570] Simple test cases for sqlite3_system_errno() FossilOrigin-Name: 185bc8644c806597194dc532a4d547a03a2dedaa --- manifest | 17 +++++++---------- manifest.uuid | 2 +- src/test1.c | 24 ++++++++++++++++++++++++ test/capi3.test | 9 +++++---- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index ebc861b735..6cc0c36998 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Experimental\simplementation\sof\sthe\ssqlite3_system_errno()\sinterface. -D 2016-03-17T16:01:23.259 +C Simple\stest\scases\sfor\ssqlite3_system_errno() +D 2016-03-17T17:23:11.511 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -360,7 +360,7 @@ F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 F src/tclsqlite.c 4bf3bea9b03aeac176ac114700f35f76a1de4c8a -F src/test1.c 52965bd684ddcd7f22328ebd7d50fd0b6e51f0d4 +F src/test1.c 289e7dab5b1aec4f4d44f2cc84972c97458d739f F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e @@ -520,7 +520,7 @@ F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0 F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61 F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738 -F test/capi3.test bf6f0308bbbba1e770dac13aa08e5c2ac61c7324 +F test/capi3.test 84ab8993016cd7edfe91af58a04def17075ec9b9 F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 F test/capi3c.test 06f6261f9e9b4ef6f76afcd9900f3665408af1c8 F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82 @@ -1456,10 +1456,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 97b0e88cc7c3d677217d0bfab4cb4a34a4abb238 -R 2fd7ee41c15d4ef6398866450bc883db -T *branch * sqlite_system_errno -T *sym-sqlite_system_errno * -T -sym-trunk * +P 6782c87b3722fbd09684a5b1e5df05247956f1c6 +R b7a0980686d8da4da394952a90c389a3 U drh -Z 77c764a9e283f7fe52499f77098482f4 +Z 861529470b9b3fd5330fda28dd73536f diff --git a/manifest.uuid b/manifest.uuid index f695385706..5df27f10bb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6782c87b3722fbd09684a5b1e5df05247956f1c6 \ No newline at end of file +185bc8644c806597194dc532a4d547a03a2dedaa \ No newline at end of file diff --git a/src/test1.c b/src/test1.c index 8ad653ca6c..cb41a70c2d 100644 --- a/src/test1.c +++ b/src/test1.c @@ -4847,6 +4847,29 @@ static int test_db_cacheflush( return TCL_OK; } +/* +** Usage: sqlite3_system_errno DB +** +** Return the low-level system errno value. +*/ +static int test_system_errno( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + int iErrno; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + iErrno = sqlite3_system_errno(db); + Tcl_SetObjResult(interp, Tcl_NewIntObj(iErrno)); + return TCL_OK; +} + /* ** Usage: sqlite3_db_filename DB DBNAME ** @@ -7084,6 +7107,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_release_memory", test_release_memory, 0}, { "sqlite3_db_release_memory", test_db_release_memory, 0}, { "sqlite3_db_cacheflush", test_db_cacheflush, 0}, + { "sqlite3_system_errno", test_system_errno, 0}, { "sqlite3_db_filename", test_db_filename, 0}, { "sqlite3_db_readonly", test_db_readonly, 0}, { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0}, diff --git a/test/capi3.test b/test/capi3.test index 163bb19ada..e91c044632 100644 --- a/test/capi3.test +++ b/test/capi3.test @@ -172,14 +172,15 @@ do_test capi3-3.3 { catch { set db2 [sqlite3_open /bogus/path/test.db {}] } - sqlite3_extended_errcode $db2 -} {SQLITE_CANTOPEN} + set ::capi3_errno [sqlite3_system_errno $db2] + list [sqlite3_extended_errcode $db2] [expr {$::capi3_errno!=0}] +} {SQLITE_CANTOPEN 1} do_test capi3-3.4 { sqlite3_errmsg $db2 } {unable to open database file} do_test capi3-3.5 { - sqlite3_close $db2 -} {SQLITE_OK} + list [sqlite3_system_errno $db2] [sqlite3_close $db2] +} [list $::capi3_errno SQLITE_OK] if {[clang_sanitize_address]==0} { do_test capi3-3.6.1-misuse { sqlite3_close $db2 From de845c2f5aab918ad86d7b0313ddc3e0085129fb Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 17 Mar 2016 19:07:52 +0000 Subject: [PATCH 484/570] A more compact implementation of the code generator for the IS and IS NOT operators. FossilOrigin-Name: 8607e3ac7a9d44372a4a66da21bbb3d28ae2528a --- manifest | 13 +++++------ manifest.uuid | 2 +- src/expr.c | 63 +++++++++++++++++++++++---------------------------- 3 files changed, 35 insertions(+), 43 deletions(-) diff --git a/manifest b/manifest index 3d02d28e9b..68ccf6c76c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sprepared\sstatements\sfor\ssome\spragmas\scan\snow\sbe\sreused\swithout\sinvoking\nan\sautomatic\sreprepare. -D 2016-03-16T21:29:54.761 +C A\smore\scompact\simplementation\sof\sthe\scode\sgenerator\sfor\sthe\nIS\sand\sIS\sNOT\soperators. +D 2016-03-17T19:07:52.217 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -304,7 +304,7 @@ F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 0b73e681c11fca867fec554750c07fe0d4e417c1 F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b F src/delete.c 48802aa3ee6339f576d074336d3ae1b5f40e240f -F src/expr.c c329d581e5d631153456369684d7d4bcd94c907d +F src/expr.c f8137b7d3d3f2a991f9622e41d170e0adf0abc71 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 5cb42d9a59e2a590776fd3fc8ff6f61d40df3c6e F src/func.c 552d300265aed09eea21f68ac742a440550c0062 @@ -1456,8 +1456,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 10a3e2a01db9f80452a2a3369fd25b6fd9798274 db1ce7e13e656fcd2766f1b1f225cbfefe8f73ad -R 2716c51dfa2bfe8ed5e18127e51ae3c8 -T +closed db1ce7e13e656fcd2766f1b1f225cbfefe8f73ad +P 97b0e88cc7c3d677217d0bfab4cb4a34a4abb238 +R 7d24921d4d6b93efccc35ce02f43234b U drh -Z e3b23194e47816995dbce6c752704ef0 +Z d01f371f2a1444a2eb95b11e7cec5f5e diff --git a/manifest.uuid b/manifest.uuid index 06db10b8a2..ad8858c776 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -97b0e88cc7c3d677217d0bfab4cb4a34a4abb238 \ No newline at end of file +8607e3ac7a9d44372a4a66da21bbb3d28ae2528a \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 3672d02df1..352edc5424 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1283,7 +1283,8 @@ u32 sqlite3ExprListFlags(const ExprList *pList){ if( pList ){ for(i=0; inExpr; i++){ Expr *pExpr = pList->a[i].pExpr; - if( ALWAYS(pExpr) ) m |= pExpr->flags; + assert( pExpr!=0 ); + m |= pExpr->flags; } } return m; @@ -3548,6 +3549,13 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); break; } + case TK_IS: + case TK_ISNOT: + testcase( op==TK_IS ); + testcase( op==TK_ISNOT ); + op = (op==TK_IS) ? TK_EQ : TK_NE; + jumpIfNull = SQLITE_NULLEQ; + /* Fall thru */ case TK_LT: case TK_LE: case TK_GT: @@ -3563,23 +3571,12 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); - assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); - assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_IS: - case TK_ISNOT: { - testcase( op==TK_IS ); - testcase( op==TK_ISNOT ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - op = (op==TK_IS) ? TK_EQ : TK_NE; - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, SQLITE_NULLEQ); - VdbeCoverageIf(v, op==TK_EQ); - VdbeCoverageIf(v, op==TK_NE); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); + VdbeCoverageIf(v, op==OP_Eq && jumpIfNull==SQLITE_NULLEQ); + VdbeCoverageIf(v, op==OP_Eq && jumpIfNull!=SQLITE_NULLEQ); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); + VdbeCoverageIf(v, op==OP_Ne && jumpIfNull==SQLITE_NULLEQ); + VdbeCoverageIf(v, op==OP_Ne && jumpIfNull!=SQLITE_NULLEQ); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -3704,6 +3701,13 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); break; } + case TK_IS: + case TK_ISNOT: + testcase( pExpr->op==TK_IS ); + testcase( pExpr->op==TK_ISNOT ); + op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; + jumpIfNull = SQLITE_NULLEQ; + /* Fall thru */ case TK_LT: case TK_LE: case TK_GT: @@ -3719,23 +3723,12 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); - assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); - assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_IS: - case TK_ISNOT: { - testcase( pExpr->op==TK_IS ); - testcase( pExpr->op==TK_ISNOT ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, SQLITE_NULLEQ); - VdbeCoverageIf(v, op==TK_EQ); - VdbeCoverageIf(v, op==TK_NE); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); + VdbeCoverageIf(v, op==OP_Eq && jumpIfNull!=SQLITE_NULLEQ); + VdbeCoverageIf(v, op==OP_Eq && jumpIfNull==SQLITE_NULLEQ); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); + VdbeCoverageIf(v, op==OP_Ne && jumpIfNull!=SQLITE_NULLEQ); + VdbeCoverageIf(v, op==OP_Ne && jumpIfNull==SQLITE_NULLEQ); testcase( regFree1==0 ); testcase( regFree2==0 ); break; From 762e32bcfae029d0f40bf888338415d559148211 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 17 Mar 2016 19:28:19 +0000 Subject: [PATCH 485/570] Change the xGetLastError() method on the windows VFS so that it continues to format an error message (if requested) but returns the system error code, rather than an SQLite status code. FossilOrigin-Name: 1602f6b53698bd3a1a4be218c2e3145dd895f1f1 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/os_win.c | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 6cc0c36998..c0896b3d7e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simple\stest\scases\sfor\ssqlite3_system_errno() -D 2016-03-17T17:23:11.511 +C Change\sthe\sxGetLastError()\smethod\son\sthe\swindows\sVFS\sso\sthat\sit\scontinues\sto\nformat\san\serror\smessage\s(if\srequested)\sbut\sreturns\sthe\ssystem\serror\scode,\nrather\sthan\san\sSQLite\sstatus\scode. +D 2016-03-17T19:28:19.609 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -335,7 +335,7 @@ F src/os.h 91ff889115ecd01f436d3611f7f5ea4dc12d92f1 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 50103f69121bca969761b821e2b0e393b55fe869 -F src/os_win.c cbf8c442a0d818d05bcf40b093cb3ebad435b9be +F src/os_win.c 551d973ada67127430e41d9e514e53f6beb6c5a7 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 38718a019ca762ba4f6795425d5a54db70d1790d F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 @@ -1456,7 +1456,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 6782c87b3722fbd09684a5b1e5df05247956f1c6 -R b7a0980686d8da4da394952a90c389a3 +P 185bc8644c806597194dc532a4d547a03a2dedaa +R d7bafa1f512c1236fc42737f63cfb05e U drh -Z 861529470b9b3fd5330fda28dd73536f +Z df3bbf22437c6fe25ac3bbf281848b7c diff --git a/manifest.uuid b/manifest.uuid index 5df27f10bb..688543bf04 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -185bc8644c806597194dc532a4d547a03a2dedaa \ No newline at end of file +1602f6b53698bd3a1a4be218c2e3145dd895f1f1 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index 6ff50c554b..fd95c00e3a 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -5584,8 +5584,10 @@ static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){ ** sqlite3_errmsg(), possibly making IO errors easier to debug. */ static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ + DWORD e = osGetLastError(); UNUSED_PARAMETER(pVfs); - return winGetLastErrorMsg(osGetLastError(), nBuf, zBuf); + if( nBuf>0 ) winGetLastErrorMsg(e, nBuf, zBuf); + return e; } /* From e42195b0440c03403d6f928c9cf7865a49c9a4b4 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 17 Mar 2016 21:06:42 +0000 Subject: [PATCH 486/570] Add an API to indicate the percentage progress of an rbu update. FossilOrigin-Name: ffc58d2c2576a5b6e1c2c7112612c5760e711afd --- ext/rbu/rbuprogress.test | 179 +++++++++++++++++++++++++++++++++++++++ ext/rbu/sqlite3rbu.c | 179 ++++++++++++++++++++++++++++++++++++--- ext/rbu/sqlite3rbu.h | 2 + ext/rbu/test_rbu.c | 13 +++ manifest | 23 ++--- manifest.uuid | 2 +- 6 files changed, 377 insertions(+), 21 deletions(-) create mode 100644 ext/rbu/rbuprogress.test diff --git a/ext/rbu/rbuprogress.test b/ext/rbu/rbuprogress.test new file mode 100644 index 0000000000..9fcd014065 --- /dev/null +++ b/ext/rbu/rbuprogress.test @@ -0,0 +1,179 @@ +# 2016 March 18 +# +# 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. +# +#*********************************************************************** +# + +source [file join [file dirname [info script]] rbu_common.tcl] +set ::testprefix rbuprogress + + +# Create a simple RBU database. That expects to write to a table: +# +# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); +# +proc create_rbu1 {filename} { + forcedelete $filename + sqlite3 rbu1 $filename + rbu1 eval { + CREATE TABLE data_t1(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(1, 2, 3, 0); + INSERT INTO data_t1 VALUES(2, 'two', 'three', 0); + INSERT INTO data_t1 VALUES(3, NULL, 8.2, 0); + + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data_t1', 3); + } + rbu1 close + return $filename +} + + +do_execsql_test 1.0 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); +} + +do_test 1.1 { + create_rbu1 rbu.db + sqlite3rbu rbu test.db rbu.db + rbu stage_progress +} {0 0} +do_test 1.2 { rbu step ; rbu stage_progress } {3333 0} +do_test 1.3 { rbu step ; rbu stage_progress } {6666 0} +do_test 1.4 { rbu step ; rbu stage_progress } {10000 0} +do_test 1.5 { rbu step ; rbu stage_progress } {10000 0} +do_test 1.6 { rbu step ; rbu stage_progress } {10000 0} +do_test 1.7 { rbu step ; rbu stage_progress } {10000 5000} +do_test 1.8 { rbu step ; rbu stage_progress } {10000 10000} +do_test 1.9 { rbu step ; rbu stage_progress } {10000 10000} + +do_test 1.10 { + rbu close +} {SQLITE_DONE} + +#------------------------------------------------------------------------- + +proc do_sp_test {tn target rbu reslist} { + uplevel [list do_test $tn [subst -nocommands { + sqlite3rbu rbu $target $rbu + set res [list] + while 1 { + set rc [rbu step] + if {[set rc] != "SQLITE_OK"} { error "error 1" } + lappend res [lindex [rbu stage_progress] 0] + if {[lindex [set res] end]==10000} break + } + if {[set res] != [list $reslist]} { + error "reslist is incorrect (expect=$reslist got=[set res])" + } + + # One step to clean up the temporary tables used to update the only + # target table in the rbu database. And one more to move the *-oal + # file to *-wal. + rbu step + rbu step + + # Do the checkpoint. + while {[rbu step]=="SQLITE_OK"} { } + + rbu close + }] {SQLITE_DONE}] +} + +proc create_db_file {filename sql} { + forcedelete $filename + sqlite3 tmpdb $filename + tmpdb eval $sql + tmpdb close +} + +reset_db +do_test 2.1.0 { + execsql { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + } + create_db_file rbu.db { + CREATE TABLE data_t1(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(4, 4, 4, 0); + INSERT INTO data_t1 VALUES(5, 5, 5, 0); + + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data_t1', 2); + } +} {} +do_sp_test 2.1.1 test.db rbu.db {5000 10000} + +reset_db +do_test 2.2.0 { + execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) } + create_rbu1 rbu.db +} {rbu.db} +do_sp_test 2.2.1 test.db rbu.db {3333 6666 10000} + +reset_db +do_test 2.3.0 { + execsql { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX i1 ON t1(b); + INSERT INTO t1 VALUES(1, 1, 1); + INSERT INTO t1 VALUES(2, 2, 2); + INSERT INTO t1 VALUES(3, 3, 3); + } + create_db_file rbu.db { + CREATE TABLE data_t1(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(4, 4, 4, 0); + INSERT INTO data_t1 VALUES(2, NULL, NULL, 1); + INSERT INTO data_t1 VALUES(5, NULL, NULL, 1); + + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data_t1', 3); + } +} {} +do_sp_test 2.3.1 test.db rbu.db {1666 3333 6000 8000 10000} + +reset_db +do_test 2.4.0 { + execsql { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX i1 ON t1(b); + INSERT INTO t1 VALUES(1, 1, 1); + INSERT INTO t1 VALUES(2, 2, 2); + INSERT INTO t1 VALUES(3, 3, 3); + } + create_db_file rbu.db { + CREATE TABLE data_t1(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(2, 4, 4, '.xx'); + + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data_t1', 1); + } +} {} +do_sp_test 2.4.1 test.db rbu.db {3333 6666 10000} + +reset_db +do_test 2.5.0 { + execsql { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX i1 ON t1(b); + INSERT INTO t1 VALUES(1, 1, 1); + INSERT INTO t1 VALUES(2, 2, 2); + INSERT INTO t1 VALUES(3, 3, 3); + } + create_db_file rbu.db { + CREATE TABLE data_t1(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(4, NULL, 4, '.xx'); + + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data_t1', 1); + } +} {} +do_sp_test 2.5.1 test.db rbu.db {10000} + +finish_test + diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index 474e39fe8d..31d462b2b7 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -147,14 +147,15 @@ ** RBU_STATE_OALSZ: ** Valid if STAGE==1. The size in bytes of the *-oal file. */ -#define RBU_STATE_STAGE 1 -#define RBU_STATE_TBL 2 -#define RBU_STATE_IDX 3 -#define RBU_STATE_ROW 4 -#define RBU_STATE_PROGRESS 5 -#define RBU_STATE_CKPT 6 -#define RBU_STATE_COOKIE 7 -#define RBU_STATE_OALSZ 8 +#define RBU_STATE_STAGE 1 +#define RBU_STATE_TBL 2 +#define RBU_STATE_IDX 3 +#define RBU_STATE_ROW 4 +#define RBU_STATE_PROGRESS 5 +#define RBU_STATE_CKPT 6 +#define RBU_STATE_COOKIE 7 +#define RBU_STATE_OALSZ 8 +#define RBU_STATE_PHASEONESTEP 9 #define RBU_STAGE_OAL 1 #define RBU_STAGE_MOVE 2 @@ -200,6 +201,7 @@ struct RbuState { i64 nProgress; u32 iCookie; i64 iOalSz; + i64 nPhaseOneStep; }; struct RbuUpdateStmt { @@ -244,6 +246,7 @@ struct RbuObjIter { int iTnum; /* Root page of current object */ int iPkTnum; /* If eType==EXTERNAL, root of PK index */ int bUnique; /* Current index is unique */ + int nIndex; /* Number of aux. indexes on table zTbl */ /* Statements created by rbuObjIterPrepareAll() */ int nCol; /* Number of columns in current object */ @@ -314,6 +317,7 @@ struct sqlite3rbu { const char *zVfsName; /* Name of automatically created rbu vfs */ rbu_file *pTargetFd; /* File handle open on target db */ i64 iOalSz; + i64 nPhaseOneStep; /* The following state variables are used as part of the incremental ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding @@ -1144,6 +1148,7 @@ static void rbuObjIterCacheIndexedCols(sqlite3rbu *p, RbuObjIter *pIter){ ); } + pIter->nIndex = 0; while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pList) ){ const char *zIdx = (const char*)sqlite3_column_text(pList, 1); sqlite3_stmt *pXInfo = 0; @@ -1157,6 +1162,7 @@ static void rbuObjIterCacheIndexedCols(sqlite3rbu *p, RbuObjIter *pIter){ } rbuFinalize(p, pXInfo); bIndex = 1; + pIter->nIndex++; } rbuFinalize(p, pList); @@ -1823,6 +1829,14 @@ static void rbuTmpInsertFunc( int rc = SQLITE_OK; int i; + assert( sqlite3_value_int(apVal[0])!=0 + || p->objiter.eType==RBU_PK_EXTERNAL + || p->objiter.eType==RBU_PK_NONE + ); + if( sqlite3_value_int(apVal[0])!=0 ){ + p->nPhaseOneStep += p->objiter.nIndex; + } + for(i=0; rc==SQLITE_OK && iobjiter.pTmpInsert, i+1, apVal[i]); } @@ -2567,6 +2581,17 @@ static void rbuStepOneOp(sqlite3rbu *p, int eType){ assert( p->rc==SQLITE_OK ); assert( eType!=RBU_DELETE || pIter->zIdx==0 ); + assert( eType==RBU_DELETE || eType==RBU_IDX_DELETE + || eType==RBU_INSERT || eType==RBU_IDX_INSERT + ); + + /* If this is a delete, decrement nPhaseOneStep by nIndex. If the DELETE + ** statement below does actually delete a row, nPhaseOneStep will be + ** incremented by the same amount when SQL function rbu_tmp_insert() + ** is invoked by the trigger. */ + if( eType==RBU_DELETE ){ + p->nPhaseOneStep -= p->objiter.nIndex; + } if( eType==RBU_IDX_DELETE || eType==RBU_DELETE ){ pWriter = pIter->pDelete; @@ -2642,7 +2667,10 @@ static int rbuStep(sqlite3rbu *p){ rbuBadControlError(p); } else if( eType==RBU_REPLACE ){ - if( pIter->zIdx==0 ) rbuStepOneOp(p, RBU_DELETE); + if( pIter->zIdx==0 ){ + p->nPhaseOneStep += p->objiter.nIndex; + rbuStepOneOp(p, RBU_DELETE); + } if( p->rc==SQLITE_OK ) rbuStepOneOp(p, RBU_INSERT); } else if( eType!=RBU_UPDATE ){ @@ -2652,6 +2680,7 @@ static int rbuStep(sqlite3rbu *p){ sqlite3_value *pVal; sqlite3_stmt *pUpdate = 0; assert( eType==RBU_UPDATE ); + p->nPhaseOneStep -= p->objiter.nIndex; rbuGetUpdateStmt(p, pIter, zMask, &pUpdate); if( pUpdate ){ int i; @@ -2729,6 +2758,7 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){ "(%d, %d), " "(%d, %lld), " "(%d, %lld), " + "(%d, %lld), " "(%d, %lld) ", p->zStateDb, RBU_STATE_STAGE, eStage, @@ -2738,7 +2768,8 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){ RBU_STATE_PROGRESS, p->nProgress, RBU_STATE_CKPT, p->iWalCksum, RBU_STATE_COOKIE, (i64)p->pTargetFd->iCookie, - RBU_STATE_OALSZ, p->iOalSz + RBU_STATE_OALSZ, p->iOalSz, + RBU_STATE_PHASEONESTEP, p->nPhaseOneStep ) ); assert( pInsert==0 || rc==SQLITE_OK ); @@ -2925,6 +2956,10 @@ static RbuState *rbuLoadState(sqlite3rbu *p){ pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1); break; + case RBU_STATE_PHASEONESTEP: + pRet->nPhaseOneStep = (u32)sqlite3_column_int64(pStmt, 1); + break; + default: rc = SQLITE_CORRUPT; break; @@ -3032,6 +3067,97 @@ static void rbuDeleteVfs(sqlite3rbu *p){ } } +/* +** +*/ +static void rbuIndexCntFunc( + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal +){ + sqlite3rbu *p = (sqlite3rbu*)sqlite3_user_data(pCtx); + sqlite3_stmt *pStmt = 0; + char *zErrmsg = 0; + int rc; + + assert( nVal==1 ); + + rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &zErrmsg, + sqlite3_mprintf("PRAGMA index_list = %Q", sqlite3_value_text(apVal[0])) + ); + if( rc!=SQLITE_OK ){ + sqlite3_result_error(pCtx, zErrmsg, -1); + }else{ + int nIndex = 0; + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + nIndex++; + } + rc = sqlite3_finalize(pStmt); + if( rc==SQLITE_OK ){ + sqlite3_result_int(pCtx, nIndex); + }else{ + sqlite3_result_error(pCtx, sqlite3_errmsg(p->dbMain), -1); + } + } + + sqlite3_free(zErrmsg); +} + +/* +** If the RBU database contains the rbu_count table, use it to initialize +** the sqlite3rbu.nPhaseOneStep variable. The schema of the rbu_count table +** is assumed to contain the same columns as: +** +** CREATE TABLE rbu_count(tbl TEXT PRIMARY KEY, cnt INTEGER) WITHOUT ROWID; +** +** There should be one row in the table for each data_xxx table in the +** database. The 'tbl' column should contain the name of a data_xxx table, +** and the cnt column the number of rows it contains. +** +** sqlite3rbu.nPhaseOneStep is initialized to the sum of (1 + nIndex) * cnt +** for all rows in the rbu_count table, where nIndex is the number of +** indexes on the corresponding target database table. +*/ +static void rbuInitPhaseOneSteps(sqlite3rbu *p){ + if( p->rc==SQLITE_OK ){ + sqlite3_stmt *pStmt = 0; + int bExists = 0; /* True if rbu_count exists */ + + p->nPhaseOneStep = -1; + + p->rc = sqlite3_create_function(p->dbRbu, + "rbu_index_cnt", 1, SQLITE_UTF8, (void*)p, rbuIndexCntFunc, 0, 0 + ); + + /* Check for the rbu_count table. If it does not exist, or if an error + ** occurs, nPhaseOneStep will be left set to -1. */ + if( p->rc==SQLITE_OK ){ + p->rc = prepareAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, + "SELECT 1 FROM sqlite_master WHERE tbl_name = 'rbu_count'" + ); + } + if( p->rc==SQLITE_OK ){ + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + bExists = 1; + } + p->rc = sqlite3_finalize(pStmt); + } + + if( p->rc==SQLITE_OK && bExists ){ + p->rc = prepareAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, + "SELECT sum(cnt * (1 + rbu_index_cnt(rbu_target_name(tbl))))" + "FROM rbu_count" + ); + if( p->rc==SQLITE_OK ){ + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + p->nPhaseOneStep = sqlite3_column_int64(pStmt, 0); + } + p->rc = sqlite3_finalize(pStmt); + } + } + } +} + /* ** Open and return a new RBU handle. */ @@ -3077,6 +3203,7 @@ sqlite3rbu *sqlite3rbu_open( if( pState->eStage==0 ){ rbuDeleteOalFile(p); + rbuInitPhaseOneSteps(p); p->eStage = RBU_STAGE_OAL; }else{ p->eStage = pState->eStage; @@ -3243,6 +3370,38 @@ sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu){ return pRbu->nProgress; } +void sqlite3rbu_stage_progress(sqlite3rbu *p, int *pnOne, int *pnTwo){ + const int MAX_PROGRESS = 10000; + switch( p->eStage ){ + case RBU_STAGE_OAL: + if( p->nPhaseOneStep>0 ){ + *pnOne = (int)(MAX_PROGRESS * (i64)p->nProgress/(i64)p->nPhaseOneStep); + }else{ + *pnOne = -1; + } + *pnTwo = 0; + break; + + case RBU_STAGE_MOVE: + *pnOne = MAX_PROGRESS; + *pnTwo = 0; + break; + + case RBU_STAGE_CKPT: + *pnOne = MAX_PROGRESS; + *pnTwo = (int)(MAX_PROGRESS * (i64)p->nStep / (i64)p->nFrame); + break; + + case RBU_STAGE_DONE: + *pnOne = MAX_PROGRESS; + *pnTwo = MAX_PROGRESS; + break; + + default: + assert( 0 ); + } +} + int sqlite3rbu_savestate(sqlite3rbu *p){ int rc = p->rc; diff --git a/ext/rbu/sqlite3rbu.h b/ext/rbu/sqlite3rbu.h index f1a0f3cd84..fb81c85a0a 100644 --- a/ext/rbu/sqlite3rbu.h +++ b/ext/rbu/sqlite3rbu.h @@ -400,6 +400,8 @@ int sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg); */ sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu); +void sqlite3rbu_stage_progress(sqlite3rbu *pRbu, int *pnOne, int *pnTwo); + /* ** Create an RBU VFS named zName that accesses the underlying file-system ** via existing VFS zParent. Or, if the zParent parameter is passed NULL, diff --git a/ext/rbu/test_rbu.c b/ext/rbu/test_rbu.c index 3fa85b7569..e35d76e745 100644 --- a/ext/rbu/test_rbu.c +++ b/ext/rbu/test_rbu.c @@ -66,6 +66,7 @@ static int test_sqlite3rbu_cmd( {"create_rbu_delta", 2, ""}, /* 2 */ {"savestate", 2, ""}, /* 3 */ {"dbMain_eval", 3, "SQL"}, /* 4 */ + {"stage_progress", 2, ""}, /* 5 */ {0,0,0} }; int iCmd; @@ -136,6 +137,18 @@ static int test_sqlite3rbu_cmd( break; } + case 5: /* stage_progress */ { + int one, two; + Tcl_Obj *pObj; + sqlite3rbu_stage_progress(pRbu, &one, &two); + + pObj = Tcl_NewObj(); + Tcl_ListObjAppendElement(interp, pObj, Tcl_NewIntObj(one)); + Tcl_ListObjAppendElement(interp, pObj, Tcl_NewIntObj(two)); + Tcl_SetObjResult(interp, pObj); + break; + } + default: /* seems unlikely */ assert( !"cannot happen" ); break; diff --git a/manifest b/manifest index 3d02d28e9b..e0a85e57cc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sprepared\sstatements\sfor\ssome\spragmas\scan\snow\sbe\sreused\swithout\sinvoking\nan\sautomatic\sreprepare. -D 2016-03-16T21:29:54.761 +C Add\san\sAPI\sto\sindicate\sthe\spercentage\sprogress\sof\san\srbu\supdate. +D 2016-03-17T21:06:42.412 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -242,10 +242,11 @@ F ext/rbu/rbudiff.test 6cc806dc36389292f2a8f5842d0103721df4a07d F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda +F ext/rbu/rbuprogress.test d63b70f838a20422dce6445bcaed10890e506d02 F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 -F ext/rbu/sqlite3rbu.c 5956f8bee63b5ab2b04e65c1801ea0f5920dac92 -F ext/rbu/sqlite3rbu.h 0bdeb3be211aaba7d85445fa36f4701a25a3dbde -F ext/rbu/test_rbu.c 4a4cdcef4ef9379fc2a21f008805c80b27bcf573 +F ext/rbu/sqlite3rbu.c 9bcf35b2f1d8eaf1c82b47bead114b2289ea06c6 +F ext/rbu/sqlite3rbu.h f8ee94f95fc80a35b7cb7ef3f2f5ea740b662477 +F ext/rbu/test_rbu.c 5b6d31af188193d929234d1cd08ee967df092f66 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 F ext/rtree/rtree.c 0b870ccb7b58b734a2a8e1e2755a7c0ded070920 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e @@ -1456,8 +1457,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 10a3e2a01db9f80452a2a3369fd25b6fd9798274 db1ce7e13e656fcd2766f1b1f225cbfefe8f73ad -R 2716c51dfa2bfe8ed5e18127e51ae3c8 -T +closed db1ce7e13e656fcd2766f1b1f225cbfefe8f73ad -U drh -Z e3b23194e47816995dbce6c752704ef0 +P 97b0e88cc7c3d677217d0bfab4cb4a34a4abb238 +R 9de86de419de6ede9128347e06885dfc +T *branch * rbu-percent-progress +T *sym-rbu-percent-progress * +T -sym-trunk * +U dan +Z f4146c58d33c341586c7f6e824f90dbe diff --git a/manifest.uuid b/manifest.uuid index 06db10b8a2..ca52cccd3f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -97b0e88cc7c3d677217d0bfab4cb4a34a4abb238 \ No newline at end of file +ffc58d2c2576a5b6e1c2c7112612c5760e711afd \ No newline at end of file From 790b151e19cb274f11baad738d6058b6f79dcd1e Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 17 Mar 2016 23:00:42 +0000 Subject: [PATCH 487/570] Changes to releasetest.tcl: Rename the "OS-X" configuration to "Apple". Bring the "Apple" configuration up to date. Allow the use of "if:os=..." arguments in a configuration. Run the Apple configuration on Linux in addition to on Macs, but without -DSQLITE_ENABLE_LOCKING_STYLE. FossilOrigin-Name: beb2a80b430e0ad561a58d8f00b80cbdc74b5e03 --- manifest | 12 ++++----- manifest.uuid | 2 +- test/releasetest.tcl | 62 ++++++++++++++++++++++++++++++++++---------- 3 files changed, 55 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index 68ccf6c76c..c420888c92 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C A\smore\scompact\simplementation\sof\sthe\scode\sgenerator\sfor\sthe\nIS\sand\sIS\sNOT\soperators. -D 2016-03-17T19:07:52.217 +C Changes\sto\sreleasetest.tcl:\s\sRename\sthe\s"OS-X"\sconfiguration\sto\s"Apple".\nBring\sthe\s"Apple"\sconfiguration\sup\sto\sdate.\s\sAllow\sthe\suse\sof\s"if:os=..."\narguments\sin\sa\sconfiguration.\s\sRun\sthe\sApple\sconfiguration\son\sLinux\sin\saddition\nto\son\sMacs,\sbut\swithout\s-DSQLITE_ENABLE_LOCKING_STYLE. +D 2016-03-17T23:00:42.207 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -971,7 +971,7 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/regexp2.test aa7ffcc21350007a78361b82bcf3b74d12227144 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 -F test/releasetest.tcl a246ecb14ed594bf44bf77bd21df873971d779bf +F test/releasetest.tcl a07c3a11fb1bd00a77673bd6f72bd0cd59c8d6af F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5 @@ -1456,7 +1456,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 97b0e88cc7c3d677217d0bfab4cb4a34a4abb238 -R 7d24921d4d6b93efccc35ce02f43234b +P 8607e3ac7a9d44372a4a66da21bbb3d28ae2528a +R b7facb3a60b8b0eb25dafd6297755878 U drh -Z d01f371f2a1444a2eb95b11e7cec5f5e +Z da6ac72adf144eb20e25874187166c45 diff --git a/manifest.uuid b/manifest.uuid index ad8858c776..f226e93a8e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8607e3ac7a9d44372a4a66da21bbb3d28ae2528a \ No newline at end of file +beb2a80b430e0ad561a58d8f00b80cbdc74b5e03 \ No newline at end of file diff --git a/test/releasetest.tcl b/test/releasetest.tcl index 2bcf1aa511..db36690ebc 100644 --- a/test/releasetest.tcl +++ b/test/releasetest.tcl @@ -174,24 +174,47 @@ array set ::Configs [strip_comments { -O2 -DSQLITE_ENABLE_LOCKING_STYLE=1 } - "OS-X" { + "Apple" { -O1 # Avoid a compiler bug in gcc 4.2.1 build 5658 - -DSQLITE_OMIT_LOAD_EXTENSION=1 - -DSQLITE_DEFAULT_MEMSTATUS=0 - -DSQLITE_THREADSAFE=2 - -DSQLITE_OS_UNIX=1 - -DSQLITE_ENABLE_JSON1=1 - -DSQLITE_ENABLE_LOCKING_STYLE=1 - -DUSE_PREAD=1 - -DSQLITE_ENABLE_RTREE=1 + -DHAVE_GMTIME_R=1 + -DHAVE_ISNAN=1 + -DHAVE_LOCALTIME_R=1 + -DHAVE_PREAD=1 + -DHAVE_PWRITE=1 + -DHAVE_USLEEP=1 + -DHAVE_USLEEP=1 + -DHAVE_UTIME=1 + -DSQLITE_DEFAULT_CACHE_SIZE=1000 + -DSQLITE_DEFAULT_CKPTFULLFSYNC=1 + -DSQLITE_DEFAULT_MEMSTATUS=1 + -DSQLITE_DEFAULT_PAGE_SIZE=1024 + -DSQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS=1 + -DSQLITE_ENABLE_API_ARMOR=1 + -DSQLITE_ENABLE_AUTO_PROFILE=1 + -DSQLITE_ENABLE_FLOCKTIMEOUT=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 - -DSQLITE_DEFAULT_CACHE_SIZE=1000 + -DSQLITE_ENABLE_FTS3_TOKENIZER=1 + if:os=="Darwin" -DSQLITE_ENABLE_LOCKING_STYLE=1 + -DSQLITE_ENABLE_PERSIST_WAL=1 + -DSQLITE_ENABLE_PURGEABLE_PCACHE=1 + -DSQLITE_ENABLE_RTREE=1 + -DSQLITE_ENABLE_SNAPSHOT=1 + # -DSQLITE_ENABLE_SQLLOG=1 + -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1 -DSQLITE_MAX_LENGTH=2147483645 -DSQLITE_MAX_VARIABLE_NUMBER=500000 - -DSQLITE_DEBUG=1 + -DSQLITE_MEMDEBUG=1 + -DSQLITE_NO_SYNC=1 + -DSQLITE_OMIT_AUTORESET=1 + -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_PREFER_PROXY_LOCKING=1 - -DSQLITE_ENABLE_API_ARMOR=1 + -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 + -DSQLITE_THREADSAFE=2 + -DSQLITE_USE_URI=1 + -DSQLITE_WRITE_WALFRAME_PREBUFFERED=1 + -DUSE_GUARDED_FD=1 + -DUSE_PREAD=1 --enable-json1 --enable-fts5 } "Extra-Robustness" { @@ -248,6 +271,7 @@ array set ::Platforms [strip_comments { "Device-Two" test "No-lookaside" test "Devkit" test + "Apple" test "Sanitize" {QUICKTEST_OMIT=func4.test,nan.test test} "Device-One" fulltest "Default" "threadtest fulltest" @@ -264,12 +288,12 @@ array set ::Platforms [strip_comments { Darwin-i386 { "Locking-Style" "mptest test" "Have-Not" test - "OS-X" "threadtest fulltest" + "Apple" "threadtest fulltest" } Darwin-x86_64 { "Locking-Style" "mptest test" "Have-Not" test - "OS-X" "threadtest fulltest" + "Apple" "threadtest fulltest" } "Windows NT-intel" { "Have-Not" test @@ -588,13 +612,23 @@ proc add_test_suite {listvar name testtarget config} { set opts "" set title ${name}($testtarget) set configOpts $::WITHTCL + set skip 0 regsub -all {#[^\n]*\n} $config \n config foreach arg $config { + if {$skip} { + set skip 0 + continue + } if {[regexp {^-[UD]} $arg]} { lappend opts $arg } elseif {[regexp {^[A-Z]+=} $arg]} { lappend testtarget $arg + } elseif {[regexp {^if:([a-z]+)(.*)} $arg all key tail]} { + # Arguments of the form 'if:os=="Linux"' will cause the subsequent + # argument to be skipped if the $tcl_platform(os) is not "Linux", for + # example... + set skip [expr !(\$::tcl_platform($key)$tail)] } elseif {[regexp {^--(enable|disable)-} $arg]} { if {$::MSVC} { if {$arg eq "--disable-amalgamation"} { From 9493cafe6f54f0bcff3c21014ea3b8d2c971e03d Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 17 Mar 2016 23:16:37 +0000 Subject: [PATCH 488/570] Fix harmless compiler warnings that arise with -DSQLITE_OMIT_LOAD_EXTENSION FossilOrigin-Name: 65ba2f0b465a1493de6e467f55e0300ac3fb08e1 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/pcache1.c | 12 +++++++----- src/test1.c | 2 ++ test/releasetest.tcl | 2 +- tool/sqldiff.c | 4 +++- 6 files changed, 23 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index c420888c92..9d6db86ef2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Changes\sto\sreleasetest.tcl:\s\sRename\sthe\s"OS-X"\sconfiguration\sto\s"Apple".\nBring\sthe\s"Apple"\sconfiguration\sup\sto\sdate.\s\sAllow\sthe\suse\sof\s"if:os=..."\narguments\sin\sa\sconfiguration.\s\sRun\sthe\sApple\sconfiguration\son\sLinux\sin\saddition\nto\son\sMacs,\sbut\swithout\s-DSQLITE_ENABLE_LOCKING_STYLE. -D 2016-03-17T23:00:42.207 +C Fix\sharmless\scompiler\swarnings\sthat\sarise\swith\s-DSQLITE_OMIT_LOAD_EXTENSION +D 2016-03-17T23:16:37.996 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -342,7 +342,7 @@ F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 -F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 +F src/pcache1.c c40cdb93586e21b5dd826b5e671240bd91c26b05 F src/pragma.c f0670909e915179fec47e17f72f14660995b8022 F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e @@ -360,7 +360,7 @@ F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 F src/tclsqlite.c 4bf3bea9b03aeac176ac114700f35f76a1de4c8a -F src/test1.c 52965bd684ddcd7f22328ebd7d50fd0b6e51f0d4 +F src/test1.c 941f1cb50a601c30fd426a381e783b863c9d7d13 F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e @@ -971,7 +971,7 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/regexp2.test aa7ffcc21350007a78361b82bcf3b74d12227144 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 -F test/releasetest.tcl a07c3a11fb1bd00a77673bd6f72bd0cd59c8d6af +F test/releasetest.tcl f2519836bebefcc7db36b4946e8028d4885baa59 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5 @@ -1423,7 +1423,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c -F tool/sqldiff.c 5a26205111e6fa856d9b1535b1637744dcdb930b +F tool/sqldiff.c 0e9b76f9f4a72856d0384f5e0a038bbeb78dd222 F tool/srcck1.c 4f65e1a6748e42f24c0ea629dddc934d821c729a F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d @@ -1456,7 +1456,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 8607e3ac7a9d44372a4a66da21bbb3d28ae2528a -R b7facb3a60b8b0eb25dafd6297755878 +P beb2a80b430e0ad561a58d8f00b80cbdc74b5e03 +R 37561b4e78990edaf3c970fae7bb038b U drh -Z da6ac72adf144eb20e25874187166c45 +Z cf3b29714b0e10f6a050d8250c16f911 diff --git a/manifest.uuid b/manifest.uuid index f226e93a8e..5f8e183ba7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -beb2a80b430e0ad561a58d8f00b80cbdc74b5e03 \ No newline at end of file +65ba2f0b465a1493de6e467f55e0300ac3fb08e1 \ No newline at end of file diff --git a/src/pcache1.c b/src/pcache1.c index 7147f6a7a8..d168e7fbcb 100644 --- a/src/pcache1.c +++ b/src/pcache1.c @@ -348,7 +348,6 @@ static void *pcache1Alloc(int nByte){ ** Free an allocated buffer obtained from pcache1Alloc(). */ static void pcache1Free(void *p){ - int nFreed = 0; if( p==0 ) return; if( SQLITE_WITHIN(p, pcache1.pStart, pcache1.pEnd) ){ PgFreeslot *pSlot; @@ -365,10 +364,13 @@ static void pcache1Free(void *p){ assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS - nFreed = sqlite3MallocSize(p); - sqlite3_mutex_enter(pcache1.mutex); - sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed); - sqlite3_mutex_leave(pcache1.mutex); + { + int nFreed = 0; + nFreed = sqlite3MallocSize(p); + sqlite3_mutex_enter(pcache1.mutex); + sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed); + sqlite3_mutex_leave(pcache1.mutex); + } #endif sqlite3_free(p); } diff --git a/src/test1.c b/src/test1.c index 8ad653ca6c..0de5faf82d 100644 --- a/src/test1.c +++ b/src/test1.c @@ -1931,6 +1931,8 @@ static int test_load_extension( #ifdef SQLITE_OMIT_LOAD_EXTENSION rc = SQLITE_ERROR; zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()"); + (void)zProc; + (void)zFile; #else rc = sqlite3_load_extension(db, zFile, zProc, &zErr); #endif diff --git a/test/releasetest.tcl b/test/releasetest.tcl index db36690ebc..15f64e3218 100644 --- a/test/releasetest.tcl +++ b/test/releasetest.tcl @@ -204,7 +204,7 @@ array set ::Configs [strip_comments { -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1 -DSQLITE_MAX_LENGTH=2147483645 -DSQLITE_MAX_VARIABLE_NUMBER=500000 - -DSQLITE_MEMDEBUG=1 + # -DSQLITE_MEMDEBUG=1 -DSQLITE_NO_SYNC=1 -DSQLITE_OMIT_AUTORESET=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 diff --git a/tool/sqldiff.c b/tool/sqldiff.c index ae01cd3c4d..d2423a73ba 100644 --- a/tool/sqldiff.c +++ b/tool/sqldiff.c @@ -1757,8 +1757,10 @@ int main(int argc, char **argv){ char *zTab = 0; FILE *out = stdout; void (*xDiff)(const char*,FILE*) = diff_one_table; +#ifndef SQLITE_OMIT_LOAD_EXTENSION int nExt = 0; char **azExt = 0; +#endif int useTransaction = 0; int neverUseTransaction = 0; @@ -1841,8 +1843,8 @@ int main(int argc, char **argv){ cmdlineError("error loading %s: %s", azExt[i], zErrMsg); } } -#endif free(azExt); +#endif zSql = sqlite3_mprintf("ATTACH %Q as aux;", zDb2); rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); if( rc || zErrMsg ){ From 108e5a9a6cafbdeab09bc24fd17d7050a0273b9b Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 17 Mar 2016 23:56:23 +0000 Subject: [PATCH 489/570] Fix some test cases so that they work under the Apple configuration. FossilOrigin-Name: 399c60764d3fdec49dab1745c30930ca1dbafe70 --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/test_config.c | 7 +++++++ test/capi3.test | 21 +++++++++++---------- test/capi3c.test | 21 +++++++++++---------- test/wal2.test | 3 +++ test/wal3.test | 1 + 7 files changed, 44 insertions(+), 31 deletions(-) diff --git a/manifest b/manifest index 9d6db86ef2..6b11a73093 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarnings\sthat\sarise\swith\s-DSQLITE_OMIT_LOAD_EXTENSION -D 2016-03-17T23:16:37.996 +C Fix\ssome\stest\scases\sso\sthat\sthey\swork\sunder\sthe\sApple\sconfiguration. +D 2016-03-17T23:56:23.638 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -375,7 +375,7 @@ F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 F src/test_bestindex.c 29af3cc3b963ffe5760c85d142b9b3e5302c1e3d F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f -F src/test_config.c 0dee90328e3dedf8ba002ee94b6a7e7ea7726fe4 +F src/test_config.c 57e52a768ea0dd3499164e307559d5eb96df7ee3 F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_fs.c f10f840ca4f8c72e4837908bd8347ac4bcab074b @@ -520,9 +520,9 @@ F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0 F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61 F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738 -F test/capi3.test bf6f0308bbbba1e770dac13aa08e5c2ac61c7324 +F test/capi3.test db0731f6e2a94f96c6d4c478fedef4e0c077026c F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 -F test/capi3c.test 06f6261f9e9b4ef6f76afcd9900f3665408af1c8 +F test/capi3c.test b28ec47692f0fc50eb61b2d464d8d52e816b3732 F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82 F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3 @@ -1304,8 +1304,8 @@ F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477 -F test/wal2.test 25ae059e900dbb584e0775627e45415ba5940df1 -F test/wal3.test 5dd734147f1f8f958c5261a1f2775d346d7013ce +F test/wal2.test 56b0bc95b8693a0be294f8d210c49025dd094bd7 +F test/wal3.test 2a93004bc0fb2b5c29888964024695bade278ab2 F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c F test/wal5.test 9c11da7aeccd83a46d79a556ad11a18d3cb15aa9 F test/wal6.test a9d6aa635b9d63607dabdc11406f5f96ca986635 @@ -1456,7 +1456,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 beb2a80b430e0ad561a58d8f00b80cbdc74b5e03 -R 37561b4e78990edaf3c970fae7bb038b +P 65ba2f0b465a1493de6e467f55e0300ac3fb08e1 +R 7cf410a0d799b5e757a3a8b96ff17372 U drh -Z cf3b29714b0e10f6a050d8250c16f911 +Z 802d45975b74ad53aebc4d60c61be48a diff --git a/manifest.uuid b/manifest.uuid index 5f8e183ba7..b971b998c3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -65ba2f0b465a1493de6e467f55e0300ac3fb08e1 \ No newline at end of file +399c60764d3fdec49dab1745c30930ca1dbafe70 \ No newline at end of file diff --git a/src/test_config.c b/src/test_config.c index 30b421e00b..cc6243e44f 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -79,6 +79,13 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "debug", "0", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_DEFAULT_CKPTFULLFSYNC + Tcl_SetVar2(interp, "sqlite_options", "default_ckptfullfsync", + SQLITE_DEFAULT_CKPTFULLFSYNC ? "1" : "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "default_ckptfullfsync", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_DIRECT_OVERFLOW_READ Tcl_SetVar2(interp, "sqlite_options", "direct_read", "1", TCL_GLOBAL_ONLY); #else diff --git a/test/capi3.test b/test/capi3.test index 163bb19ada..684872bc6b 100644 --- a/test/capi3.test +++ b/test/capi3.test @@ -925,19 +925,20 @@ do_test capi3-11.9.3 { do_test capi3-11.10 { sqlite3_step $STMT } {SQLITE_ROW} -ifcapable !autoreset { - # If SQLITE_OMIT_AUTORESET is defined, then the statement must be - # reset() before it can be passed to step() again. - do_test capi3-11.11a { sqlite3_step $STMT } {SQLITE_MISUSE} - do_test capi3-11.11b { sqlite3_reset $STMT } {SQLITE_ABORT} -} do_test capi3-11.11 { sqlite3_step $STMT } {SQLITE_DONE} -do_test capi3-11.12 { - sqlite3_step $STMT - sqlite3_step $STMT -} {SQLITE_ROW} +ifcapable api_armor { + do_test capi3-11.12armor { + sqlite3_step $STMT + sqlite3_step $STMT + } {SQLITE_MISUSE} +} else { + do_test capi3-11.12 { + sqlite3_step $STMT + sqlite3_step $STMT + } {SQLITE_ROW} +} do_test capi3-11.13 { sqlite3_finalize $STMT } {SQLITE_OK} diff --git a/test/capi3c.test b/test/capi3c.test index 15307a7f7a..91c02561b1 100644 --- a/test/capi3c.test +++ b/test/capi3c.test @@ -865,19 +865,20 @@ do_test capi3c-11.9.3 { do_test capi3c-11.10 { sqlite3_step $STMT } {SQLITE_ROW} -ifcapable !autoreset { - # If SQLITE_OMIT_AUTORESET is defined, then the statement must be - # reset() before it can be passed to step() again. - do_test capi3-11.11a { sqlite3_step $STMT } {SQLITE_MISUSE} - do_test capi3-11.11b { sqlite3_reset $STMT } {SQLITE_ABORT} -} do_test capi3c-11.11 { sqlite3_step $STMT } {SQLITE_DONE} -do_test capi3c-11.12 { - sqlite3_step $STMT - sqlite3_step $STMT -} {SQLITE_ROW} +ifcapable api_armor { + do_test capi3c-11.12armor { + sqlite3_step $STMT + sqlite3_step $STMT + } {SQLITE_MISUSE} +} else { + do_test capi3c-11.12 { + sqlite3_step $STMT + sqlite3_step $STMT + } {SQLITE_ROW} +} do_test capi3c-11.13 { sqlite3_finalize $STMT } {SQLITE_OK} diff --git a/test/wal2.test b/test/wal2.test index 4b9bbf315f..0b15b15461 100644 --- a/test/wal2.test +++ b/test/wal2.test @@ -1194,6 +1194,9 @@ foreach {tn sql reslist} { 2 { PRAGMA checkpoint_fullfsync = 1 } {10 4 4 2 6 2} 3 { PRAGMA checkpoint_fullfsync = 0 } {10 0 4 0 6 0} } { + ifcapable default_ckptfullfsync { + if {[string trim $sql]==""} continue + } faultsim_delete_and_reopen execsql {PRAGMA auto_vacuum = 0; PRAGMA synchronous = FULL;} diff --git a/test/wal3.test b/test/wal3.test index da3d318773..56f40ab539 100644 --- a/test/wal3.test +++ b/test/wal3.test @@ -220,6 +220,7 @@ foreach {tn syncmode synccount} { sqlite3 db test.db -vfs T execsql "PRAGMA synchronous = $syncmode" + execsql "PRAGMA checkpoint_fullfsync = 0" execsql { PRAGMA journal_mode = WAL } execsql { CREATE TABLE filler(a,b,c); } From b99185f278ccca4eef38637ac3d19b5ceb3db411 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 Mar 2016 00:19:48 +0000 Subject: [PATCH 490/570] Fix more test-case errors in the Apple configuration. FossilOrigin-Name: 6631e1e655604a7d1fb45b4d151938d4a13b47f3 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/test_config.c | 12 +++++++++++- test/memsubsys1.test | 10 ++++++---- test/mutex1.test | 2 +- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 6b11a73093..4447b95603 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\stest\scases\sso\sthat\sthey\swork\sunder\sthe\sApple\sconfiguration. -D 2016-03-17T23:56:23.638 +C Fix\smore\stest-case\serrors\sin\sthe\sApple\sconfiguration. +D 2016-03-18T00:19:48.288 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -375,7 +375,7 @@ F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 F src/test_bestindex.c 29af3cc3b963ffe5760c85d142b9b3e5302c1e3d F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f -F src/test_config.c 57e52a768ea0dd3499164e307559d5eb96df7ee3 +F src/test_config.c 0fb2571777ef43a8442be4f9c62a25f530872328 F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_fs.c f10f840ca4f8c72e4837908bd8347ac4bcab074b @@ -889,7 +889,7 @@ F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 -F test/memsubsys1.test 0311bfb4edd2615e3aa56c7a9cf44574e4229077 +F test/memsubsys1.test 69924593856040e266fdd9aa1ecb4d5a0888eb12 F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc @@ -913,7 +913,7 @@ F test/multiplex.test efd015ca0b5b4a57dc9535b8feb1273eebeadb60 F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101 F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4 -F test/mutex1.test e0a44072d98189003deae4b091106f085d94bea8 +F test/mutex1.test ea2cc74d97f077b9e74c84cbd024f14d79a8126f F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 F test/nan.test dacc57f80859c06a433d30839336fe227d2038b3 F test/nolock.test 96e922d2d3db71c2dd6557c98e8027a28277b415 @@ -1456,7 +1456,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 65ba2f0b465a1493de6e467f55e0300ac3fb08e1 -R 7cf410a0d799b5e757a3a8b96ff17372 +P 399c60764d3fdec49dab1745c30930ca1dbafe70 +R 6d659b59f432dac31e8bf0c8b3f7d1b0 U drh -Z 802d45975b74ad53aebc4d60c61be48a +Z 34dc8dd8397892469013fc1a83c5fbd6 diff --git a/manifest.uuid b/manifest.uuid index b971b998c3..03b3a4a5c6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -399c60764d3fdec49dab1745c30930ca1dbafe70 \ No newline at end of file +6631e1e655604a7d1fb45b4d151938d4a13b47f3 \ No newline at end of file diff --git a/src/test_config.c b/src/test_config.c index cc6243e44f..7a51accc6f 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -104,6 +104,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "lfs", "1", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS + Tcl_SetVar2(interp, "sqlite_options", "pagecache_overflow_stats","0",TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "pagecache_overflow_stats","1",TCL_GLOBAL_ONLY); +#endif + #if SQLITE_MAX_MMAP_SIZE>0 Tcl_SetVar2(interp, "sqlite_options", "mmap", "1", TCL_GLOBAL_ONLY); #else @@ -583,7 +589,11 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY); #endif Tcl_SetVar2(interp, "sqlite_options", "threadsafe", - STRINGVALUE(SQLITE_THREADSAFE), TCL_GLOBAL_ONLY); + SQLITE_THREADSAFE ? "1" : "0", TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, "sqlite_options", "threadsafe1", + SQLITE_THREADSAFE==1 ? "1" : "0", TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, "sqlite_options", "threadsafe2", + SQLITE_THREADSAFE==2 ? "1" : "0", TCL_GLOBAL_ONLY); assert( sqlite3_threadsafe()==SQLITE_THREADSAFE ); #ifdef SQLITE_OMIT_TEMPDB diff --git a/test/memsubsys1.test b/test/memsubsys1.test index e9a4cf08a8..f0b060fc9f 100644 --- a/test/memsubsys1.test +++ b/test/memsubsys1.test @@ -100,10 +100,12 @@ reset_highwater_marks build_test_db memsubsys1-2 {PRAGMA page_size=1024; PRAGMA mmap_size=0} #show_memstats set MEMORY_MANAGEMENT $sqlite_options(memorymanage) -ifcapable !malloc_usable_size { - do_test memsubsys1-2.3 { - set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2] - } [expr ($TEMP_STORE>1 || $MEMORY_MANAGEMENT==0)*1024] +ifcapable pagecache_overflow_stats { + ifcapable !malloc_usable_size { + do_test memsubsys1-2.3 { + set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2] + } [expr ($TEMP_STORE>1 || $MEMORY_MANAGEMENT==0)*1024] + } } do_test memsubsys1-2.4 { set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2] diff --git a/test/mutex1.test b/test/mutex1.test index 340e271175..f567a0d930 100644 --- a/test/mutex1.test +++ b/test/mutex1.test @@ -97,7 +97,7 @@ do_test mutex1-1.9 { # * Multi-threaded mode, # * Single-threaded mode. # -ifcapable threadsafe&&shared_cache { +ifcapable threadsafe1&&shared_cache { set enable_shared_cache [sqlite3_enable_shared_cache 1] foreach {mode mutexes} { singlethread {} From 860443da10c8665304f30ed1c4a3b6718ca8855d Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 Mar 2016 00:39:40 +0000 Subject: [PATCH 491/570] Fix FTS5 so that it works with SQLITE_OMIT_AUTORESET. FossilOrigin-Name: b199637d81d7e2a767131ac03c7679b101fd459c --- ext/fts5/fts5_storage.c | 3 +-- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ext/fts5/fts5_storage.c b/ext/fts5/fts5_storage.c index e4f5dd8f51..e052d03cd2 100644 --- a/ext/fts5/fts5_storage.c +++ b/ext/fts5/fts5_storage.c @@ -145,6 +145,7 @@ static int fts5StorageGetStmt( } *ppStmt = p->aStmt[eStmt]; + sqlite3_reset(*ppStmt); return rc; } @@ -1121,5 +1122,3 @@ int sqlite3Fts5StorageConfigValue( } return rc; } - - diff --git a/manifest b/manifest index 4447b95603..729634b431 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\smore\stest-case\serrors\sin\sthe\sApple\sconfiguration. -D 2016-03-18T00:19:48.288 +C Fix\sFTS5\sso\sthat\sit\sworks\swith\sSQLITE_OMIT_AUTORESET. +D 2016-03-18T00:39:40.456 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -106,7 +106,7 @@ F ext/fts5/fts5_expr.c 35e9d92c89e7c7ea0759b73d24da1ecb7630a24b F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 F ext/fts5/fts5_index.c d4f0c12e4f04bbc3a06b6da052039f2ce3e45438 F ext/fts5/fts5_main.c b8501e1a6a11591c53b18ce7aea7e5386cfb0421 -F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e +F ext/fts5/fts5_storage.c 2a38c6fa5db193a6a00588865134450ef5812daa F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 F ext/fts5/fts5_test_mi.c 783b86697ebf773c18fc109992426c0173a055bc F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be @@ -1456,7 +1456,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 399c60764d3fdec49dab1745c30930ca1dbafe70 -R 6d659b59f432dac31e8bf0c8b3f7d1b0 +P 6631e1e655604a7d1fb45b4d151938d4a13b47f3 +R 472ca36ca6048890d22e3e80bb68c577 U drh -Z 34dc8dd8397892469013fc1a83c5fbd6 +Z 94c5a688910df424330581238168e35b diff --git a/manifest.uuid b/manifest.uuid index 03b3a4a5c6..d2044dd6ea 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6631e1e655604a7d1fb45b4d151938d4a13b47f3 \ No newline at end of file +b199637d81d7e2a767131ac03c7679b101fd459c \ No newline at end of file From fe485c0e56050c1963bc7b5a3599628a3fe45212 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 18 Mar 2016 10:29:47 +0000 Subject: [PATCH 492/570] Add tests for the changes on this branch. Fix a problem with calls to the new progress indicator API made after an rbu update has been resumed. FossilOrigin-Name: bf82321724d3b0feb51e26d9b76090e03cc3964a --- ext/rbu/rbuprogress.test | 198 ++++++++++++++++++++++----------------- ext/rbu/sqlite3rbu.c | 1 + manifest | 17 ++-- manifest.uuid | 2 +- 4 files changed, 120 insertions(+), 98 deletions(-) diff --git a/ext/rbu/rbuprogress.test b/ext/rbu/rbuprogress.test index 9fcd014065..005aec5b24 100644 --- a/ext/rbu/rbuprogress.test +++ b/ext/rbu/rbuprogress.test @@ -13,7 +13,6 @@ source [file join [file dirname [info script]] rbu_common.tcl] set ::testprefix rbuprogress - # Create a simple RBU database. That expects to write to a table: # # CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); @@ -58,29 +57,51 @@ do_test 1.10 { } {SQLITE_DONE} #------------------------------------------------------------------------- - -proc do_sp_test {tn target rbu reslist} { +# +proc do_sp_test {tn bReopen target rbu reslist} { uplevel [list do_test $tn [subst -nocommands { - sqlite3rbu rbu $target $rbu + if {$bReopen==0} { sqlite3rbu rbu $target $rbu } set res [list] while 1 { + if {$bReopen} { sqlite3rbu rbu $target $rbu } set rc [rbu step] if {[set rc] != "SQLITE_OK"} { error "error 1" } lappend res [lindex [rbu stage_progress] 0] if {[lindex [set res] end]==10000} break + if {$bReopen} { rbu close } } if {[set res] != [list $reslist]} { - error "reslist is incorrect (expect=$reslist got=[set res])" + error "1. reslist incorrect (expect=$reslist got=[set res])" } # One step to clean up the temporary tables used to update the only # target table in the rbu database. And one more to move the *-oal - # file to *-wal. + # file to *-wal. After each of these steps, the progress remains + # at "10000 0". + # rbu step + set res [rbu stage_progress] + if {[set res] != [list 10000 0]} { + error "2. reslist incorrect (expect=10000 0 got=[set res])" + } rbu step + set res [rbu stage_progress] + if {[set res] != [list 10000 0]} { + error "3. reslist incorrect (expect=10000 0 got=[set res])" + } # Do the checkpoint. - while {[rbu step]=="SQLITE_OK"} { } + while {[rbu step]=="SQLITE_OK"} { + foreach {a b} [rbu stage_progress] {} + if {[set a]!=10000 || [set b]<=0 || [set b]>10000} { + error "4. reslist incorrect (expect=10000 1..10000 got=[set a] [set b])" + } + } + + set res [rbu stage_progress] + if {[set res] != [list 10000 10000]} { + error "5. reslist is incorrect (expect=10000 10000 got=[set res])" + } rbu close }] {SQLITE_DONE}] @@ -93,87 +114,90 @@ proc create_db_file {filename sql} { tmpdb close } -reset_db -do_test 2.1.0 { - execsql { - CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); - } - create_db_file rbu.db { - CREATE TABLE data_t1(a, b, c, rbu_control); - INSERT INTO data_t1 VALUES(4, 4, 4, 0); - INSERT INTO data_t1 VALUES(5, 5, 5, 0); +foreach {bReopen} { 0 1 } { - CREATE TABLE rbu_count(tbl, cnt); - INSERT INTO rbu_count VALUES('data_t1', 2); - } -} {} -do_sp_test 2.1.1 test.db rbu.db {5000 10000} - -reset_db -do_test 2.2.0 { - execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) } - create_rbu1 rbu.db -} {rbu.db} -do_sp_test 2.2.1 test.db rbu.db {3333 6666 10000} - -reset_db -do_test 2.3.0 { - execsql { - CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); - CREATE INDEX i1 ON t1(b); - INSERT INTO t1 VALUES(1, 1, 1); - INSERT INTO t1 VALUES(2, 2, 2); - INSERT INTO t1 VALUES(3, 3, 3); - } - create_db_file rbu.db { - CREATE TABLE data_t1(a, b, c, rbu_control); - INSERT INTO data_t1 VALUES(4, 4, 4, 0); - INSERT INTO data_t1 VALUES(2, NULL, NULL, 1); - INSERT INTO data_t1 VALUES(5, NULL, NULL, 1); - - CREATE TABLE rbu_count(tbl, cnt); - INSERT INTO rbu_count VALUES('data_t1', 3); - } -} {} -do_sp_test 2.3.1 test.db rbu.db {1666 3333 6000 8000 10000} - -reset_db -do_test 2.4.0 { - execsql { - CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); - CREATE INDEX i1 ON t1(b); - INSERT INTO t1 VALUES(1, 1, 1); - INSERT INTO t1 VALUES(2, 2, 2); - INSERT INTO t1 VALUES(3, 3, 3); - } - create_db_file rbu.db { - CREATE TABLE data_t1(a, b, c, rbu_control); - INSERT INTO data_t1 VALUES(2, 4, 4, '.xx'); - - CREATE TABLE rbu_count(tbl, cnt); - INSERT INTO rbu_count VALUES('data_t1', 1); - } -} {} -do_sp_test 2.4.1 test.db rbu.db {3333 6666 10000} - -reset_db -do_test 2.5.0 { - execsql { - CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); - CREATE INDEX i1 ON t1(b); - INSERT INTO t1 VALUES(1, 1, 1); - INSERT INTO t1 VALUES(2, 2, 2); - INSERT INTO t1 VALUES(3, 3, 3); - } - create_db_file rbu.db { - CREATE TABLE data_t1(a, b, c, rbu_control); - INSERT INTO data_t1 VALUES(4, NULL, 4, '.xx'); - - CREATE TABLE rbu_count(tbl, cnt); - INSERT INTO rbu_count VALUES('data_t1', 1); - } -} {} -do_sp_test 2.5.1 test.db rbu.db {10000} + reset_db + do_test 2.$bReopen.1.0 { + execsql { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + } + create_db_file rbu.db { + CREATE TABLE data_t1(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(4, 4, 4, 0); + INSERT INTO data_t1 VALUES(5, 5, 5, 0); + + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data_t1', 2); + } + } {} + do_sp_test 2.$bReopen.1.1 $bReopen test.db rbu.db {5000 10000} + + reset_db + do_test 2.$bReopen.2.0 { + execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) } + create_rbu1 rbu.db + } {rbu.db} + do_sp_test 2.$bReopen.2.1 $bReopen test.db rbu.db {3333 6666 10000} + + reset_db + do_test 2.$bReopen.3.0 { + execsql { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX i1 ON t1(b); + INSERT INTO t1 VALUES(1, 1, 1); + INSERT INTO t1 VALUES(2, 2, 2); + INSERT INTO t1 VALUES(3, 3, 3); + } + create_db_file rbu.db { + CREATE TABLE data_t1(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(4, 4, 4, 0); + INSERT INTO data_t1 VALUES(2, NULL, NULL, 1); + INSERT INTO data_t1 VALUES(5, NULL, NULL, 1); + + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data_t1', 3); + } + } {} + do_sp_test 2.$bReopen.3.1 $bReopen test.db rbu.db {1666 3333 6000 8000 10000} + + reset_db + do_test 2.$bReopen.4.0 { + execsql { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX i1 ON t1(b); + INSERT INTO t1 VALUES(1, 1, 1); + INSERT INTO t1 VALUES(2, 2, 2); + INSERT INTO t1 VALUES(3, 3, 3); + } + create_db_file rbu.db { + CREATE TABLE data_t1(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(2, 4, 4, '.xx'); + + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data_t1', 1); + } + } {} + do_sp_test 2.$bReopen.4.1 $bReopen test.db rbu.db {3333 6666 10000} + + reset_db + do_test 2.$bReopen.5.0 { + execsql { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX i1 ON t1(b); + INSERT INTO t1 VALUES(1, 1, 1); + INSERT INTO t1 VALUES(2, 2, 2); + INSERT INTO t1 VALUES(3, 3, 3); + } + create_db_file rbu.db { + CREATE TABLE data_t1(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(4, NULL, 4, '.xx'); + + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data_t1', 1); + } + } {} + do_sp_test 2.$bReopen.5.1 $bReopen test.db rbu.db {10000} +} finish_test diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index 31d462b2b7..4b2529bf34 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -3207,6 +3207,7 @@ sqlite3rbu *sqlite3rbu_open( p->eStage = RBU_STAGE_OAL; }else{ p->eStage = pState->eStage; + p->nPhaseOneStep = pState->nPhaseOneStep; } p->nProgress = pState->nProgress; p->iOalSz = pState->iOalSz; diff --git a/manifest b/manifest index e0a85e57cc..7cbf1886a9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\san\sAPI\sto\sindicate\sthe\spercentage\sprogress\sof\san\srbu\supdate. -D 2016-03-17T21:06:42.412 +C Add\stests\sfor\sthe\schanges\son\sthis\sbranch.\sFix\sa\sproblem\swith\scalls\sto\sthe\snew\sprogress\sindicator\sAPI\smade\safter\san\srbu\supdate\shas\sbeen\sresumed. +D 2016-03-18T10:29:47.529 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -242,9 +242,9 @@ F ext/rbu/rbudiff.test 6cc806dc36389292f2a8f5842d0103721df4a07d F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda -F ext/rbu/rbuprogress.test d63b70f838a20422dce6445bcaed10890e506d02 +F ext/rbu/rbuprogress.test c4a9b3262bc0cafbf19709b56fbda0c3a9e69ac2 F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 -F ext/rbu/sqlite3rbu.c 9bcf35b2f1d8eaf1c82b47bead114b2289ea06c6 +F ext/rbu/sqlite3rbu.c c89f1e59eb09257e126d2cdcb3c5588e16a44fee F ext/rbu/sqlite3rbu.h f8ee94f95fc80a35b7cb7ef3f2f5ea740b662477 F ext/rbu/test_rbu.c 5b6d31af188193d929234d1cd08ee967df092f66 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 @@ -1457,10 +1457,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 97b0e88cc7c3d677217d0bfab4cb4a34a4abb238 -R 9de86de419de6ede9128347e06885dfc -T *branch * rbu-percent-progress -T *sym-rbu-percent-progress * -T -sym-trunk * +P ffc58d2c2576a5b6e1c2c7112612c5760e711afd +R b5c08658920cbd4a66ad9300ad32e622 U dan -Z f4146c58d33c341586c7f6e824f90dbe +Z 25ebcfe6c5065c93d73006dcdc7ea2c0 diff --git a/manifest.uuid b/manifest.uuid index ca52cccd3f..a1b8da46e4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ffc58d2c2576a5b6e1c2c7112612c5760e711afd \ No newline at end of file +bf82321724d3b0feb51e26d9b76090e03cc3964a \ No newline at end of file From 789780d8f6cd1c770ef8f39aed0ccd2a2f37d14b Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 18 Mar 2016 18:56:45 +0000 Subject: [PATCH 493/570] Change the name of the new API on this branch to "sqlite3_bp_progress". Add tests and documentation for the same. FossilOrigin-Name: 1a1b69e87eb7d18f76f5b733e44da75136a686b6 --- ext/rbu/rbuprogress.test | 145 +++++++++++++++++++++++++++++++-------- ext/rbu/sqlite3rbu.c | 49 ++++++++++++- ext/rbu/sqlite3rbu.h | 42 +++++++++++- ext/rbu/test_rbu.c | 6 +- manifest | 18 ++--- manifest.uuid | 2 +- 6 files changed, 217 insertions(+), 45 deletions(-) diff --git a/ext/rbu/rbuprogress.test b/ext/rbu/rbuprogress.test index 005aec5b24..8459bc09e0 100644 --- a/ext/rbu/rbuprogress.test +++ b/ext/rbu/rbuprogress.test @@ -13,14 +13,20 @@ source [file join [file dirname [info script]] rbu_common.tcl] set ::testprefix rbuprogress + +proc create_db_file {filename sql} { + forcedelete $filename + sqlite3 tmpdb $filename + tmpdb eval $sql + tmpdb close +} + # Create a simple RBU database. That expects to write to a table: # # CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); # proc create_rbu1 {filename} { - forcedelete $filename - sqlite3 rbu1 $filename - rbu1 eval { + create_db_file $filename { CREATE TABLE data_t1(a, b, c, rbu_control); INSERT INTO data_t1 VALUES(1, 2, 3, 0); INSERT INTO data_t1 VALUES(2, 'two', 'three', 0); @@ -29,7 +35,6 @@ proc create_rbu1 {filename} { CREATE TABLE rbu_count(tbl, cnt); INSERT INTO rbu_count VALUES('data_t1', 3); } - rbu1 close return $filename } @@ -41,16 +46,16 @@ do_execsql_test 1.0 { do_test 1.1 { create_rbu1 rbu.db sqlite3rbu rbu test.db rbu.db - rbu stage_progress + rbu bp_progress } {0 0} -do_test 1.2 { rbu step ; rbu stage_progress } {3333 0} -do_test 1.3 { rbu step ; rbu stage_progress } {6666 0} -do_test 1.4 { rbu step ; rbu stage_progress } {10000 0} -do_test 1.5 { rbu step ; rbu stage_progress } {10000 0} -do_test 1.6 { rbu step ; rbu stage_progress } {10000 0} -do_test 1.7 { rbu step ; rbu stage_progress } {10000 5000} -do_test 1.8 { rbu step ; rbu stage_progress } {10000 10000} -do_test 1.9 { rbu step ; rbu stage_progress } {10000 10000} +do_test 1.2 { rbu step ; rbu bp_progress } {3333 0} +do_test 1.3 { rbu step ; rbu bp_progress } {6666 0} +do_test 1.4 { rbu step ; rbu bp_progress } {10000 0} +do_test 1.5 { rbu step ; rbu bp_progress } {10000 0} +do_test 1.6 { rbu step ; rbu bp_progress } {10000 0} +do_test 1.7 { rbu step ; rbu bp_progress } {10000 5000} +do_test 1.8 { rbu step ; rbu bp_progress } {10000 10000} +do_test 1.9 { rbu step ; rbu bp_progress } {10000 10000} do_test 1.10 { rbu close @@ -66,7 +71,7 @@ proc do_sp_test {tn bReopen target rbu reslist} { if {$bReopen} { sqlite3rbu rbu $target $rbu } set rc [rbu step] if {[set rc] != "SQLITE_OK"} { error "error 1" } - lappend res [lindex [rbu stage_progress] 0] + lappend res [lindex [rbu bp_progress] 0] if {[lindex [set res] end]==10000} break if {$bReopen} { rbu close } } @@ -79,26 +84,29 @@ proc do_sp_test {tn bReopen target rbu reslist} { # file to *-wal. After each of these steps, the progress remains # at "10000 0". # - rbu step - set res [rbu stage_progress] - if {[set res] != [list 10000 0]} { - error "2. reslist incorrect (expect=10000 0 got=[set res])" + if {[lindex [list $reslist] 0]!=-1} { + rbu step + set res [rbu bp_progress] + if {[set res] != [list 10000 0]} { + error "2. reslist incorrect (expect=10000 0 got=[set res])" + } } + rbu step - set res [rbu stage_progress] + set res [rbu bp_progress] if {[set res] != [list 10000 0]} { error "3. reslist incorrect (expect=10000 0 got=[set res])" } # Do the checkpoint. while {[rbu step]=="SQLITE_OK"} { - foreach {a b} [rbu stage_progress] {} + foreach {a b} [rbu bp_progress] {} if {[set a]!=10000 || [set b]<=0 || [set b]>10000} { error "4. reslist incorrect (expect=10000 1..10000 got=[set a] [set b])" } } - set res [rbu stage_progress] + set res [rbu bp_progress] if {[set res] != [list 10000 10000]} { error "5. reslist is incorrect (expect=10000 10000 got=[set res])" } @@ -107,13 +115,6 @@ proc do_sp_test {tn bReopen target rbu reslist} { }] {SQLITE_DONE}] } -proc create_db_file {filename sql} { - forcedelete $filename - sqlite3 tmpdb $filename - tmpdb eval $sql - tmpdb close -} - foreach {bReopen} { 0 1 } { reset_db @@ -197,7 +198,95 @@ foreach {bReopen} { 0 1 } { } } {} do_sp_test 2.$bReopen.5.1 $bReopen test.db rbu.db {10000} + + reset_db + do_test 2.$bReopen.6.0 { + execsql { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX i1 ON t1(b); + INSERT INTO t1 VALUES(1, 1, 1); + INSERT INTO t1 VALUES(2, 2, 2); + INSERT INTO t1 VALUES(3, 3, 3); + } + create_db_file rbu.db { + CREATE TABLE data_t1(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(4, 4, 4, 0); + INSERT INTO data_t1 VALUES(2, NULL, NULL, 1); + INSERT INTO data_t1 VALUES(5, NULL, NULL, 1); + } + } {} + do_sp_test 2.$bReopen.6.1 $bReopen test.db rbu.db {-1 -1 -1 -1 -1 10000} } +#------------------------------------------------------------------------- +# The following tests verify that the API works when resuming an update +# during the incremental checkpoint stage. +# +proc do_phase2_test {tn bReopen target rbu nStep} { + uplevel [list do_test $tn [subst -nocommands { + + # Build the OAL/WAL file: + sqlite3rbu rbu $target $rbu + while {[lindex [rbu bp_progress] 0]<10000} { + set rc [rbu step] + if {"SQLITE_OK" != [set rc]} { rbu close } + } + + # Clean up the temp tables and move the *-oal file to *-wal. + rbu step + rbu step + + for {set i 0} {[set i] < $nStep} {incr i} { + if {$bReopen} { + rbu close + sqlite3rbu rbu $target $rbu + } + rbu step + set res [rbu bp_progress] + set expect [expr (1 + [set i]) * 10000 / $nStep] + if {[lindex [set res] 1] != [set expect]} { + error "Have [set res], expected 10000 [set expect]" + } + } + + set rc [rbu step] + if {[set rc] != "SQLITE_DONE"} { + error "Have [set rc], expected SQLITE_DONE" + } + + rbu close + }] {SQLITE_DONE}] +} + +foreach bReopen {0 1} { + do_test 3.$bReopen.1.0 { + reset_db + execsql { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + CREATE TABLE t2(a INTEGER PRIMARY KEY, b); + CREATE TABLE t3(a INTEGER PRIMARY KEY, b); + CREATE TABLE t4(a INTEGER PRIMARY KEY, b); + } + create_db_file rbu.db { + CREATE TABLE data_t1(a, b, rbu_control); + CREATE TABLE data_t2(a, b, rbu_control); + CREATE TABLE data_t3(a, b, rbu_control); + CREATE TABLE data_t4(a, b, rbu_control); + INSERT INTO data_t1 VALUES(1, 2, 0); + INSERT INTO data_t2 VALUES(1, 2, 0); + INSERT INTO data_t3 VALUES(1, 2, 0); + INSERT INTO data_t4 VALUES(1, 2, 0); + + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data_t1', 1); + INSERT INTO rbu_count VALUES('data_t2', 1); + INSERT INTO rbu_count VALUES('data_t3', 1); + INSERT INTO rbu_count VALUES('data_t4', 1); + } + } {} + do_phase2_test 3.$bReopen.1.1 $bReopen test.db rbu.db 5 +} + + finish_test diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index 4b2529bf34..ab7b983ead 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -300,6 +300,43 @@ struct RbuFrame { /* ** RBU handle. +** +** nPhaseOneStep: +** If the RBU database contains an rbu_count table, this value is set to +** a running estimate of the number of b-tree operations required to +** finish populating the *-oal file. This allows the sqlite3_bp_progress() +** API to calculate the permyriadage progress of populating the *-oal file +** using the formula: +** +** permyriadage = (10000 * nProgress) / nPhaseOneStep +** +** nPhaseOneStep is initialized to the sum of: +** +** nRow * (nIndex + 1) +** +** for all source tables in the RBU database, where nRow is the number +** of rows in the source table and nIndex the number of indexes on the +** corresponding target database table. +** +** This estimate is accurate if the RBU update consists entirely of +** INSERT operations. However, it is inaccurate if: +** +** * the RBU update contains any UPDATE operations. If the PK specified +** for an UPDATE operation does not exist in the target table, then +** no b-tree operations are required on index b-trees. Or if the +** specified PK does exist, then (nIndex*2) such operations are +** required (one delete and one insert on each index b-tree). +** +** * the RBU update contains any DELETE operations for which the specified +** PK does not exist. In this case no operations are required on index +** b-trees. +** +** * the RBU update contains REPLACE operations. These are similar to +** UPDATE operations. +** +** nPhaseOneStep is updated to account for the conditions above during the +** first pass of each source table. The updated nPhaseOneStep value is +** stored in the rbu_state table if the RBU update is suspended. */ struct sqlite3rbu { int eStage; /* Value of RBU_STATE_STAGE field */ @@ -2957,7 +2994,7 @@ static RbuState *rbuLoadState(sqlite3rbu *p){ break; case RBU_STATE_PHASEONESTEP: - pRet->nPhaseOneStep = (u32)sqlite3_column_int64(pStmt, 1); + pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1); break; default: @@ -3068,7 +3105,9 @@ static void rbuDeleteVfs(sqlite3rbu *p){ } /* -** +** This user-defined SQL function is invoked with a single argument - the +** name of a table expected to appear in the target database. It returns +** the number of auxilliary indexes on the table. */ static void rbuIndexCntFunc( sqlite3_context *pCtx, @@ -3371,7 +3410,11 @@ sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu){ return pRbu->nProgress; } -void sqlite3rbu_stage_progress(sqlite3rbu *p, int *pnOne, int *pnTwo){ +/* +** Return permyriadage progress indications for the two main stages of +** an RBU update. +*/ +void sqlite3rbu_bp_progress(sqlite3rbu *p, int *pnOne, int *pnTwo){ const int MAX_PROGRESS = 10000; switch( p->eStage ){ case RBU_STAGE_OAL: diff --git a/ext/rbu/sqlite3rbu.h b/ext/rbu/sqlite3rbu.h index fb81c85a0a..f379bb5b41 100644 --- a/ext/rbu/sqlite3rbu.h +++ b/ext/rbu/sqlite3rbu.h @@ -400,7 +400,47 @@ int sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg); */ sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu); -void sqlite3rbu_stage_progress(sqlite3rbu *pRbu, int *pnOne, int *pnTwo); +/* +** Obtain permyriadage (permyriadage is to 10000 as percentage is to 100) +** progress indications for the two stages of an RBU update. This API may +** be useful for driving GUI progress indicators and similar. +** +** An RBU update is divided into two stages: +** +** * Stage 1, in which changes are accumulated in an oal/wal file, and +** * Stage 2, in which the contents of the wal file are copied into the +** main database. +** +** The update is visible to non-RBU clients during stage 2. During stage 1 +** non-RBU reader clients may see the original database. +** +** If this API is called during stage 2 of the update, output variable +** (*pnOne) is set to 10000 to indicate that stage 1 has finished and (*pnTwo) +** to a value between 0 and 10000 to indicate the permyriadage progress of +** stage 2. A value of 5000 indicates that stage 2 is half finished, +** 9000 indicates that it is 90% finished, and so on. +** +** If this API is called during stage 1 of the update, output variable +** (*pnTwo) is set to 0 to indicate that stage 2 has not yet started. The +** value to which (*pnOne) is set depends on whether or not the RBU +** database contains an "rbu_count" table. The rbu_count table, if it +** exists, must contain the same columns as the following: +** +** CREATE TABLE rbu_count(tbl TEXT PRIMARY KEY, cnt INTEGER) WITHOUT ROWID; +** +** There must be one row in the table for each source (data_xxx) table within +** the RBU database. The 'tbl' column should contain the name of the source +** table. The 'cnt' column should contain the number of rows within the +** source table. +** +** If the rbu_count table is present and populated correctly and this +** API is called during stage 1, the *pnOne output variable is set to the +** permyriadage progress of the same stage. If the rbu_count table does +** not exist, then (*pnOne) is set to -1 during stage 1. If the rbu_count +** table exists but is not correctly populated, the value of the *pnOne +** output variable during stage 1 is undefined. +*/ +void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int *pnTwo); /* ** Create an RBU VFS named zName that accesses the underlying file-system diff --git a/ext/rbu/test_rbu.c b/ext/rbu/test_rbu.c index e35d76e745..5e8640a9f8 100644 --- a/ext/rbu/test_rbu.c +++ b/ext/rbu/test_rbu.c @@ -66,7 +66,7 @@ static int test_sqlite3rbu_cmd( {"create_rbu_delta", 2, ""}, /* 2 */ {"savestate", 2, ""}, /* 3 */ {"dbMain_eval", 3, "SQL"}, /* 4 */ - {"stage_progress", 2, ""}, /* 5 */ + {"bp_progress", 2, ""}, /* 5 */ {0,0,0} }; int iCmd; @@ -137,10 +137,10 @@ static int test_sqlite3rbu_cmd( break; } - case 5: /* stage_progress */ { + case 5: /* bp_progress */ { int one, two; Tcl_Obj *pObj; - sqlite3rbu_stage_progress(pRbu, &one, &two); + sqlite3rbu_bp_progress(pRbu, &one, &two); pObj = Tcl_NewObj(); Tcl_ListObjAppendElement(interp, pObj, Tcl_NewIntObj(one)); diff --git a/manifest b/manifest index 7cbf1886a9..106d447afa 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sfor\sthe\schanges\son\sthis\sbranch.\sFix\sa\sproblem\swith\scalls\sto\sthe\snew\sprogress\sindicator\sAPI\smade\safter\san\srbu\supdate\shas\sbeen\sresumed. -D 2016-03-18T10:29:47.529 +C Change\sthe\sname\sof\sthe\snew\sAPI\son\sthis\sbranch\sto\s"sqlite3_bp_progress".\sAdd\stests\sand\sdocumentation\sfor\sthe\ssame. +D 2016-03-18T18:56:45.343 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -242,11 +242,11 @@ F ext/rbu/rbudiff.test 6cc806dc36389292f2a8f5842d0103721df4a07d F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda -F ext/rbu/rbuprogress.test c4a9b3262bc0cafbf19709b56fbda0c3a9e69ac2 +F ext/rbu/rbuprogress.test 77fe3cd10d3c408bef364bc2e529310495ddd07e F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 -F ext/rbu/sqlite3rbu.c c89f1e59eb09257e126d2cdcb3c5588e16a44fee -F ext/rbu/sqlite3rbu.h f8ee94f95fc80a35b7cb7ef3f2f5ea740b662477 -F ext/rbu/test_rbu.c 5b6d31af188193d929234d1cd08ee967df092f66 +F ext/rbu/sqlite3rbu.c 6b7dc899b3980d4236bffa5048218f8dba85ac0a +F ext/rbu/sqlite3rbu.h d7cc99350c10134f358fe1a8997d9225b3f712b2 +F ext/rbu/test_rbu.c 3505641a78b723589b8780d5f9b2faeeb73e037d F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 F ext/rtree/rtree.c 0b870ccb7b58b734a2a8e1e2755a7c0ded070920 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e @@ -1457,7 +1457,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 ffc58d2c2576a5b6e1c2c7112612c5760e711afd -R b5c08658920cbd4a66ad9300ad32e622 +P bf82321724d3b0feb51e26d9b76090e03cc3964a +R 14faa32cca0db38c921d7bc3da7dea4c U dan -Z 25ebcfe6c5065c93d73006dcdc7ea2c0 +Z 40a2b2dbafc34d98f3493240ec44ac36 diff --git a/manifest.uuid b/manifest.uuid index a1b8da46e4..d6c18684be 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bf82321724d3b0feb51e26d9b76090e03cc3964a \ No newline at end of file +1a1b69e87eb7d18f76f5b733e44da75136a686b6 \ No newline at end of file From eea627da9e35aec681f8f7c54e933668a5f238bc Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 18 Mar 2016 20:12:28 +0000 Subject: [PATCH 494/570] Add further tests for sqlite3rbu_bp_progress(). Fix a problem in handling WITHOUT ROWID tables in the same. FossilOrigin-Name: 65e02368e2b6cec349ea71af5a456d6783b0d15e --- ext/rbu/rbuprogress.test | 117 ++++++++++++++++++++++++++++++++++++++- ext/rbu/sqlite3rbu.c | 13 ++++- manifest | 14 ++--- manifest.uuid | 2 +- 4 files changed, 133 insertions(+), 13 deletions(-) diff --git a/ext/rbu/rbuprogress.test b/ext/rbu/rbuprogress.test index 8459bc09e0..6e6c7faf61 100644 --- a/ext/rbu/rbuprogress.test +++ b/ext/rbu/rbuprogress.test @@ -70,12 +70,13 @@ proc do_sp_test {tn bReopen target rbu reslist} { while 1 { if {$bReopen} { sqlite3rbu rbu $target $rbu } set rc [rbu step] - if {[set rc] != "SQLITE_OK"} { error "error 1" } + if {[set rc] != "SQLITE_OK"} { rbu close ; error "error 1" } lappend res [lindex [rbu bp_progress] 0] if {[lindex [set res] end]==10000} break if {$bReopen} { rbu close } } if {[set res] != [list $reslist]} { + rbu close error "1. reslist incorrect (expect=$reslist got=[set res])" } @@ -88,6 +89,7 @@ proc do_sp_test {tn bReopen target rbu reslist} { rbu step set res [rbu bp_progress] if {[set res] != [list 10000 0]} { + rbu close error "2. reslist incorrect (expect=10000 0 got=[set res])" } } @@ -95,6 +97,7 @@ proc do_sp_test {tn bReopen target rbu reslist} { rbu step set res [rbu bp_progress] if {[set res] != [list 10000 0]} { + rbu close error "3. reslist incorrect (expect=10000 0 got=[set res])" } @@ -102,12 +105,14 @@ proc do_sp_test {tn bReopen target rbu reslist} { while {[rbu step]=="SQLITE_OK"} { foreach {a b} [rbu bp_progress] {} if {[set a]!=10000 || [set b]<=0 || [set b]>10000} { + rbu close error "4. reslist incorrect (expect=10000 1..10000 got=[set a] [set b])" } } set res [rbu bp_progress] if {[set res] != [list 10000 10000]} { + rbu close error "5. reslist is incorrect (expect=10000 10000 got=[set res])" } @@ -116,7 +121,6 @@ proc do_sp_test {tn bReopen target rbu reslist} { } foreach {bReopen} { 0 1 } { - reset_db do_test 2.$bReopen.1.0 { execsql { @@ -288,5 +292,114 @@ foreach bReopen {0 1} { } +foreach {bReopen} { 0 1 } { + foreach {tn tbl} { + ipk { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) } + wr { CREATE TABLE t1(a INT PRIMARY KEY, b, c) WITHOUT ROWID } + pk { CREATE TABLE t1(a INT PRIMARY KEY, b, c) } + } { + + foreach {tn2 rbusql r1 r3} { + 1 { + CREATE TABLE data0_t1(a, b, c, rbu_control); + INSERT INTO data0_t1 VALUES(15, 15, 15, 0); + INSERT INTO data0_t1 VALUES(20, 20, 20, 0); + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data0_t1', 2); + } + {2500 5000 7500 10000} + {1666 3333 5000 6666 8333 10000} + + 2 { + CREATE TABLE data0_t1(a, b, c, rbu_control); + INSERT INTO data0_t1 VALUES(10, 10, 10, 2); + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data0_t1', 1); + } + {3333 6666 10000} + {2000 4000 6000 8000 10000} + + 3 { + CREATE TABLE data0_t1(a, b, c, rbu_control); + INSERT INTO data0_t1 VALUES(7, 7, 7, 2); + INSERT INTO data0_t1 VALUES(10, 10, 10, 2); + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data0_t1', 2); + } + {2500 4000 6000 8000 10000} + {1666 2500 3750 5000 6250 7500 8750 10000} + + } { + + reset_db ; execsql $tbl + do_test 4.$tn.$bReopen.$tn2.0 { + execsql { + CREATE INDEX t1c ON t1(c); + INSERT INTO t1 VALUES(1, 1, 1); + INSERT INTO t1 VALUES(5, 5, 5); + INSERT INTO t1 VALUES(10, 10, 10); + } + create_db_file rbu.db $rbusql + } {} + + set R(ipk) $r1 + set R(wr) $r1 + set R(pk) $r3 + do_sp_test 4.$tn.$bReopen.$tn2.1 $bReopen test.db rbu.db $R($tn) + } + } +} + +foreach {bReopen} { 0 1 } { + foreach {tn tbl} { + nopk { + CREATE TABLE t1(a, b, c); + CREATE INDEX t1c ON t1(c); + } + vtab { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, c); + } + } { + + foreach {tn2 rbusql r1 r2} { + 1 { + CREATE TABLE data0_t1(a, b, c, rbu_rowid, rbu_control); + INSERT INTO data0_t1 VALUES(15, 15, 15, 4, 0); + INSERT INTO data0_t1 VALUES(20, 20, 20, 5, 0); + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data0_t1', 2); + } + {2500 5000 7500 10000} + {5000 10000} + + 2 { + CREATE TABLE data0_t1(rbu_rowid, a, b, c, rbu_control); + INSERT INTO data0_t1 VALUES(0, 7, 7, 7, 2); + INSERT INTO data0_t1 VALUES(2, 10, 10, 10, 2); + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data0_t1', 2); + } + {2500 4000 6000 8000 10000} + {5000 10000} + } { + + reset_db ; execsql $tbl + do_test 5.$tn.$bReopen.$tn2.0 { + execsql { + INSERT INTO t1 VALUES(1, 1, 1); + INSERT INTO t1 VALUES(5, 5, 5); + INSERT INTO t1 VALUES(10, 10, 10); + } + create_db_file rbu.db $rbusql + } {} + + set R(nopk) $r1 + set R(vtab) $r2 + do_sp_test 5.$tn.$bReopen.$tn2.1 $bReopen test.db rbu.db $R($tn) + } + } +} + + finish_test diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index ab7b983ead..b587d2bb20 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -1202,6 +1202,11 @@ static void rbuObjIterCacheIndexedCols(sqlite3rbu *p, RbuObjIter *pIter){ pIter->nIndex++; } + if( pIter->eType==RBU_PK_WITHOUT_ROWID ){ + /* "PRAGMA index_list" includes the main PK b-tree */ + pIter->nIndex--; + } + rbuFinalize(p, pList); if( bIndex==0 ) pIter->abIndexed = 0; } @@ -1313,6 +1318,7 @@ static int rbuObjIterCacheTableInfo(sqlite3rbu *p, RbuObjIter *pIter){ rbuFinalize(p, pStmt); rbuObjIterCacheIndexedCols(p, pIter); assert( pIter->eType!=RBU_PK_VTAB || pIter->abIndexed==0 ); + assert( pIter->eType!=RBU_PK_VTAB || pIter->nIndex==0 ); } return p->rc; @@ -3122,14 +3128,15 @@ static void rbuIndexCntFunc( assert( nVal==1 ); rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &zErrmsg, - sqlite3_mprintf("PRAGMA index_list = %Q", sqlite3_value_text(apVal[0])) + sqlite3_mprintf("SELECT count(*) FROM sqlite_master " + "WHERE type='index' AND tbl_name = %Q", sqlite3_value_text(apVal[0])) ); if( rc!=SQLITE_OK ){ sqlite3_result_error(pCtx, zErrmsg, -1); }else{ int nIndex = 0; - while( SQLITE_ROW==sqlite3_step(pStmt) ){ - nIndex++; + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + nIndex = sqlite3_column_int(pStmt, 0); } rc = sqlite3_finalize(pStmt); if( rc==SQLITE_OK ){ diff --git a/manifest b/manifest index 106d447afa..ec9f64957f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sname\sof\sthe\snew\sAPI\son\sthis\sbranch\sto\s"sqlite3_bp_progress".\sAdd\stests\sand\sdocumentation\sfor\sthe\ssame. -D 2016-03-18T18:56:45.343 +C Add\sfurther\stests\sfor\ssqlite3rbu_bp_progress().\sFix\sa\sproblem\sin\shandling\sWITHOUT\sROWID\stables\sin\sthe\ssame. +D 2016-03-18T20:12:28.661 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -242,9 +242,9 @@ F ext/rbu/rbudiff.test 6cc806dc36389292f2a8f5842d0103721df4a07d F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda -F ext/rbu/rbuprogress.test 77fe3cd10d3c408bef364bc2e529310495ddd07e +F ext/rbu/rbuprogress.test 9d2dfd82fc001f26997e36db256df31f2e19e133 F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 -F ext/rbu/sqlite3rbu.c 6b7dc899b3980d4236bffa5048218f8dba85ac0a +F ext/rbu/sqlite3rbu.c edeb8f90a1bccc567438036e083123cec1403091 F ext/rbu/sqlite3rbu.h d7cc99350c10134f358fe1a8997d9225b3f712b2 F ext/rbu/test_rbu.c 3505641a78b723589b8780d5f9b2faeeb73e037d F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 @@ -1457,7 +1457,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 bf82321724d3b0feb51e26d9b76090e03cc3964a -R 14faa32cca0db38c921d7bc3da7dea4c +P 1a1b69e87eb7d18f76f5b733e44da75136a686b6 +R 4f2c92bc8e3f772f06e8b5d5663259fa U dan -Z 40a2b2dbafc34d98f3493240ec44ac36 +Z bf41c4bf32ca5beb18733d3a05925431 diff --git a/manifest.uuid b/manifest.uuid index d6c18684be..5b3c08d363 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1a1b69e87eb7d18f76f5b733e44da75136a686b6 \ No newline at end of file +65e02368e2b6cec349ea71af5a456d6783b0d15e \ No newline at end of file From bb9b5f26085b12a0800dcce9fd2d5e31e6ac72ba Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 19 Mar 2016 00:35:02 +0000 Subject: [PATCH 495/570] Fix a register allocation bug in the VDBE code generator for PRAGMA integrity_check; FossilOrigin-Name: 88439a866b3b16ad7c308ebe59198662a05e7eeb --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/expr.c | 23 +++++++++++++++++++++++ src/pragma.c | 10 +++++++--- src/sqliteInt.h | 3 +++ 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 729634b431..828c368a4f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sFTS5\sso\sthat\sit\sworks\swith\sSQLITE_OMIT_AUTORESET. -D 2016-03-18T00:39:40.456 +C Fix\sa\sregister\sallocation\sbug\sin\sthe\sVDBE\scode\sgenerator\sfor\nPRAGMA\sintegrity_check; +D 2016-03-19T00:35:02.035 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -304,7 +304,7 @@ F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 0b73e681c11fca867fec554750c07fe0d4e417c1 F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b F src/delete.c 48802aa3ee6339f576d074336d3ae1b5f40e240f -F src/expr.c f8137b7d3d3f2a991f9622e41d170e0adf0abc71 +F src/expr.c 289ffac5240b60fee0a824d3d5ab2d7bd2630c94 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 5cb42d9a59e2a590776fd3fc8ff6f61d40df3c6e F src/func.c 552d300265aed09eea21f68ac742a440550c0062 @@ -343,7 +343,7 @@ F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c c40cdb93586e21b5dd826b5e671240bd91c26b05 -F src/pragma.c f0670909e915179fec47e17f72f14660995b8022 +F src/pragma.c e7e8f380efec6075a722822306435afc1eeca88a F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 @@ -355,7 +355,7 @@ F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in 0235586b3fb639e85998d495c90f007657fd82af F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 84c673f27b77dfbd367cb3ed1de8b6f3b73102dc +F src/sqliteInt.h 751ced73be8c449a75e075e0545cdd832ed3591e F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1456,7 +1456,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 6631e1e655604a7d1fb45b4d151938d4a13b47f3 -R 472ca36ca6048890d22e3e80bb68c577 +P b199637d81d7e2a767131ac03c7679b101fd459c +R aa6d8166f4985600b2fe26e199ff3347 U drh -Z 94c5a688910df424330581238168e35b +Z 34d82988bd3c2eee6ead07b5f4503f1c diff --git a/manifest.uuid b/manifest.uuid index d2044dd6ea..8f7a7e9b8d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b199637d81d7e2a767131ac03c7679b101fd459c \ No newline at end of file +88439a866b3b16ad7c308ebe59198662a05e7eeb \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 352edc5424..998c94f231 100644 --- a/src/expr.c +++ b/src/expr.c @@ -4251,3 +4251,26 @@ void sqlite3ClearTempRegCache(Parse *pParse){ pParse->nTempReg = 0; pParse->nRangeReg = 0; } + +/* +** Validate that no temporary register falls within the range of +** iFirst..iLast, inclusive. This routine is only call from within assert() +** statements. +*/ +#ifdef SQLITE_DEBUG +int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int iLast){ + int i; + if( pParse->nRangeReg>0 + && pParse->iRangeReg+pParse->nRangeRegiRangeReg>=iFirst + ){ + return 0; + } + for(i=0; inTempReg; i++){ + if( pParse->aTempReg[i]>=iFirst && pParse->aTempReg[i]<=iLast ){ + return 0; + } + } + return 1; +} +#endif /* SQLITE_DEBUG */ diff --git a/src/pragma.c b/src/pragma.c index 54858afbf1..65c43ad1e5 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1441,6 +1441,8 @@ void sqlite3Pragma( Hash *pTbls; int *aRoot; int cnt = 0; + int mxIdx = 0; + int nIdx; if( OMIT_TEMPDB && i==1 ) continue; if( iDb>=0 && i!=iDb ) continue; @@ -1462,7 +1464,8 @@ void sqlite3Pragma( Table *pTab = sqliteHashData(x); Index *pIdx; if( HasRowid(pTab) ) cnt++; - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ cnt++; } + for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; } + if( nIdx>mxIdx ) mxIdx = nIdx; } aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(cnt+1)); if( aRoot==0 ) break; @@ -1477,7 +1480,7 @@ void sqlite3Pragma( aRoot[cnt] = 0; /* Make sure sufficient number of registers have been allocated */ - pParse->nMem = MAX( pParse->nMem, 14 ); + pParse->nMem = MAX( pParse->nMem, 8+mxIdx ); /* Do the b-tree integrity checks */ sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY); @@ -1514,7 +1517,8 @@ void sqlite3Pragma( for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */ } - pParse->nMem = MAX(pParse->nMem, 8+j); + assert( pParse->nMem>=8+j ); + assert( sqlite3NoTempsInRange(pParse,1,7+j) ); sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); /* Verify that all NOT NULL columns really are NOT NULL */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f2f485778a..3b97533090 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3419,6 +3419,9 @@ void sqlite3ReleaseTempReg(Parse*,int); int sqlite3GetTempRange(Parse*,int); void sqlite3ReleaseTempRange(Parse*,int,int); void sqlite3ClearTempRegCache(Parse*); +#ifdef SQLITE_DEBUG +int sqlite3NoTempsInRange(Parse*,int,int); +#endif Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int); Expr *sqlite3Expr(sqlite3*,int,const char*); void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); From cf9bce34ab757b637ebe36f04a7997dc5a1fc379 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Mar 2016 14:47:28 +0000 Subject: [PATCH 496/570] Add test file fts5multiclient.test. FossilOrigin-Name: 7832466f9177cca59455ba272802145297fcd53d --- ext/fts5/test/fts5multiclient.test | 48 ++++++++++++++++++++++++++++++ manifest | 11 +++---- manifest.uuid | 2 +- 3 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 ext/fts5/test/fts5multiclient.test diff --git a/ext/fts5/test/fts5multiclient.test b/ext/fts5/test/fts5multiclient.test new file mode 100644 index 0000000000..a1e9aa0d30 --- /dev/null +++ b/ext/fts5/test/fts5multiclient.test @@ -0,0 +1,48 @@ +# 2016 March 17 +# +# 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. +# +#************************************************************************* +# + +source [file join [file dirname [info script]] fts5_common.tcl] +source $testdir/lock_common.tcl + +set testprefix fts5multiclient +return_if_no_fts5 + +foreach_detail_mode $testprefix { + +do_multiclient_test tn { + + do_test 1.$tn.1 { + sql1 { CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%) } + sql1 { INSERT INTO t1 VALUES('a b c') } + sql2 { SELECT rowid FROM t1('b') } + } {1} + + do_test 1.$tn.2 { + sql2 { INSERT INTO t1 VALUES('a b c') } + sql1 { SELECT rowid FROM t1('b') } + } {1 2} + + do_test 1.$tn.3 { + sql2 { INSERT INTO t1 VALUES('a b c') } + sql1 { SELECT rowid FROM t1('b') } + } {1 2 3} + + do_test 1.$tn.4 { + sql2 { INSERT INTO t1 VALUES('a b c') } + sql1 { INSERT INTO t1 VALUES('a b c') } + sql3 { INSERT INTO t1(t1) VALUES('integrity-check') } + } {} + +};# do_multiclient_test +};# foreach_detail_mode +finish_test + diff --git a/manifest b/manifest index 8f5bdc1491..346832e33f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\sOOM-handling\sissues\sin\sthe\sfts5\schanges\son\sthis\sbranch. -D 2016-03-17T12:39:56.371 +C Add\stest\sfile\sfts5multiclient.test. +D 2016-03-19T14:47:28.441 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -165,6 +165,7 @@ F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d F ext/fts5/test/fts5matchinfo.test f7dde99697bcb310ea8faa8eb2714d9f4dfc0e1b F ext/fts5/test/fts5merge.test 9f65f090d214ff865c56bef4f864aaa1182af6e3 F ext/fts5/test/fts5merge2.test a6da3c16d694235938d1939f503cfa53f0943d75 +F ext/fts5/test/fts5multiclient.test 5bd54a6bc8ff818be233a50a8dec93da99098f2a F ext/fts5/test/fts5near.test b214cddb1c1f1bddf45c75af768f20145f7e71cc F ext/fts5/test/fts5onepass.test 7ed9608e258132cb8d55e7c479b08676ad68810c F ext/fts5/test/fts5optimize.test 9d3ac53bb9cae58cb070d795db86bcb2f9fec105 @@ -1456,7 +1457,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 6c4a17b963916d19c9433d7a251338042f32e9fa -R bc1955b591517ca84e5bb3a7a87f0726 +P 020a0bda59fe93b9361ceeed0d5a8ba4177380c8 +R f14c9b8edfca8f7bf113e7bd0b21996b U dan -Z 380059b0b3811052efb55863df364c4f +Z d493def8e880a32e2aca451bc5e776cf diff --git a/manifest.uuid b/manifest.uuid index d6022948ee..91ed807a0b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -020a0bda59fe93b9361ceeed0d5a8ba4177380c8 \ No newline at end of file +7832466f9177cca59455ba272802145297fcd53d \ No newline at end of file From 1e8dae0e438a20211f619def9c5ce908a1787252 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Mar 2016 14:53:36 +0000 Subject: [PATCH 497/570] Fix test scripts sqldiff.test and rbudiff.test so that they work with the --testdir option. FossilOrigin-Name: 1ffe3cde03f924bb8405a8729c8e1bc01f5b6d3b --- ext/rbu/rbudiff.test | 11 +---------- manifest | 18 +++++++++--------- manifest.uuid | 2 +- test/sqldiff1.test | 12 ++---------- test/tester.tcl | 27 ++++++++++++++++++++------- 5 files changed, 33 insertions(+), 37 deletions(-) diff --git a/ext/rbu/rbudiff.test b/ext/rbu/rbudiff.test index 10be9e0d53..0ebc0dad0f 100644 --- a/ext/rbu/rbudiff.test +++ b/ext/rbu/rbudiff.test @@ -18,16 +18,7 @@ if {![info exists testdir]} { source $testdir/tester.tcl set testprefix rbudiff -if {$tcl_platform(platform)=="windows"} { - set PROG "sqldiff.exe" -} else { - set PROG "./sqldiff" -} -if {![file exe $PROG]} { - puts "rbudiff.test cannot run because $PROG is not available" - finish_test - return -} +set PROG [test_find_sqldiff] db close proc get_rbudiff_sql {db1 db2} { diff --git a/manifest b/manifest index 828c368a4f..a56e5123a4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sregister\sallocation\sbug\sin\sthe\sVDBE\scode\sgenerator\sfor\nPRAGMA\sintegrity_check; -D 2016-03-19T00:35:02.035 +C Fix\stest\sscripts\ssqldiff.test\sand\srbudiff.test\sso\sthat\sthey\swork\swith\sthe\s--testdir\soption. +D 2016-03-19T14:53:36.705 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -238,7 +238,7 @@ F ext/rbu/rbuB.test c25bc325b8072a766e56bb76c001866b405925c2 F ext/rbu/rbuC.test efe47db508a0269b683cb2a1913a425ffd39a831 F ext/rbu/rbu_common.tcl 0398545fed614f807d5f0ba55a85a51f08ba8f1a F ext/rbu/rbucrash.test 8d2ed5d4b05fef6c00c2a6b5f7ead71fa172a695 -F ext/rbu/rbudiff.test 6cc806dc36389292f2a8f5842d0103721df4a07d +F ext/rbu/rbudiff.test 7f0fbf54912b9f8898819504c8465df12c970a00 F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda @@ -1061,7 +1061,7 @@ F test/speedtest1.c 1478cb3fb64ad30f291ddca87ca9dbd72ff552aa F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3 F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33 -F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5 +F test/sqldiff1.test 28cd737cf1b0078b1ec1bbf425e674c47785835e F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142 F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a F test/stat.test b65bad7120c52583b8f0054d99eff80718119a77 @@ -1085,7 +1085,7 @@ F test/tclsqlite.test c6d9f546f79d15d0134c1e06583fb3ee0c3afad3 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl 859a7ccbe5bd65f0f8b524cd51c318d3edcd3008 +F test/tester.tcl d9831491ddc902ef62ef11438eca83ac0d4cf969 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1456,7 +1456,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 b199637d81d7e2a767131ac03c7679b101fd459c -R aa6d8166f4985600b2fe26e199ff3347 -U drh -Z 34d82988bd3c2eee6ead07b5f4503f1c +P 88439a866b3b16ad7c308ebe59198662a05e7eeb +R 3b6913cf00d6ce7b8c04137012202e6b +U dan +Z d63e42a30b9cbf754c53eb2c6783a9e9 diff --git a/manifest.uuid b/manifest.uuid index 8f7a7e9b8d..0bf3c490c2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -88439a866b3b16ad7c308ebe59198662a05e7eeb \ No newline at end of file +1ffe3cde03f924bb8405a8729c8e1bc01f5b6d3b \ No newline at end of file diff --git a/test/sqldiff1.test b/test/sqldiff1.test index 3201fb3654..ea4e1f9993 100644 --- a/test/sqldiff1.test +++ b/test/sqldiff1.test @@ -14,16 +14,8 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -if {$tcl_platform(platform)=="windows"} { - set PROG "sqldiff.exe" -} else { - set PROG "./sqldiff" -} -if {![file exe $PROG]} { - puts "sqldiff cannot run because $PROG is not available" - finish_test - return -} +set PROG [test_find_sqldiff] + db close forcedelete test.db test2.db sqlite3 db test.db diff --git a/test/tester.tcl b/test/tester.tcl index 1c83e34c0d..065acc37be 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -2136,15 +2136,11 @@ proc test_restore_config_pagecache {} { sqlite3 db test.db } -# Find the name of the 'shell' executable (e.g. "sqlite3.exe") to use for -# the tests in shell[1-5].test. If no such executable can be found, invoke -# [finish_test ; return] in the callers context. -# -proc test_find_cli {} { +proc test_find_binary {nm} { if {$::tcl_platform(platform)=="windows"} { - set ret "sqlite3.exe" + set ret "$nm.exe" } else { - set ret "sqlite3" + set ret $nm } set ret [file normalize [file join $::cmdlinearg(TESTFIXTURE_HOME) $ret]] if {![file executable $ret]} { @@ -2154,6 +2150,23 @@ proc test_find_cli {} { return $ret } +# Find the name of the 'shell' executable (e.g. "sqlite3.exe") to use for +# the tests in shell[1-5].test. If no such executable can be found, invoke +# [finish_test ; return] in the callers context. +# +proc test_find_cli {} { + uplevel test_find_binary sqlite3 +} + +# Find the name of the 'sqldiff' executable (e.g. "sqlite3.exe") to use for +# the tests in sqldiff tests. If no such executable can be found, invoke +# [finish_test ; return] in the callers context. +# +proc test_find_sqldiff {} { + uplevel test_find_binary sqldiff +} + + # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set # to non-zero, then set the global variable $AUTOVACUUM to 1. set AUTOVACUUM $sqlite_options(default_autovacuum) From 49aed58b7ff2a60f5bba3b2dab5deff1350a708e Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Mar 2016 15:13:59 +0000 Subject: [PATCH 498/570] Fix another problem in test script rbudiff.test. FossilOrigin-Name: 41c29c123ff347db720ed1a541c0b2ffc04670aa --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/tester.tcl | 10 +++++++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index a56e5123a4..9053c93d5a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stest\sscripts\ssqldiff.test\sand\srbudiff.test\sso\sthat\sthey\swork\swith\sthe\s--testdir\soption. -D 2016-03-19T14:53:36.705 +C Fix\sanother\sproblem\sin\stest\sscript\srbudiff.test. +D 2016-03-19T15:13:59.043 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1085,7 +1085,7 @@ F test/tclsqlite.test c6d9f546f79d15d0134c1e06583fb3ee0c3afad3 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl d9831491ddc902ef62ef11438eca83ac0d4cf969 +F test/tester.tcl 2a82a76c1704a1d5f6c71bcebcffc3041e4d9856 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1456,7 +1456,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 88439a866b3b16ad7c308ebe59198662a05e7eeb -R 3b6913cf00d6ce7b8c04137012202e6b +P 1ffe3cde03f924bb8405a8729c8e1bc01f5b6d3b +R b5342d0d86cc431c9e51a0ed18eda8f1 U dan -Z d63e42a30b9cbf754c53eb2c6783a9e9 +Z 45d735e7ccd57967a5a5daaae9ccf4a0 diff --git a/manifest.uuid b/manifest.uuid index 0bf3c490c2..5de6868b9a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1ffe3cde03f924bb8405a8729c8e1bc01f5b6d3b \ No newline at end of file +41c29c123ff347db720ed1a541c0b2ffc04670aa \ No newline at end of file diff --git a/test/tester.tcl b/test/tester.tcl index 065acc37be..a452883cc4 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -2145,7 +2145,7 @@ proc test_find_binary {nm} { set ret [file normalize [file join $::cmdlinearg(TESTFIXTURE_HOME) $ret]] if {![file executable $ret]} { finish_test - return -code return + return "" } return $ret } @@ -2155,7 +2155,9 @@ proc test_find_binary {nm} { # [finish_test ; return] in the callers context. # proc test_find_cli {} { - uplevel test_find_binary sqlite3 + set cli [test_find_binary sqlite3] + if {$prog==""} { return -code return } + return $prog } # Find the name of the 'sqldiff' executable (e.g. "sqlite3.exe") to use for @@ -2163,7 +2165,9 @@ proc test_find_cli {} { # [finish_test ; return] in the callers context. # proc test_find_sqldiff {} { - uplevel test_find_binary sqldiff + set prog [test_find_binary sqldiff] + if {$prog==""} { return -code return } + return $prog } From febfe0230097f4bc0f57edf1d626331b2cbc1bae Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Mar 2016 16:21:26 +0000 Subject: [PATCH 499/570] Update the sqldiff tool so that it generates an rbu_count table. FossilOrigin-Name: 1f7afb6e9be9f549a91bf2ab492df15698df89fd --- ext/rbu/rbudiff.test | 22 ++++++++++++++++++++++ ext/rbu/rbuprogress.test | 10 ++++++++++ manifest | 16 ++++++++-------- manifest.uuid | 2 +- tool/sqldiff.c | 16 +++++++++++++++- 5 files changed, 56 insertions(+), 10 deletions(-) diff --git a/ext/rbu/rbudiff.test b/ext/rbu/rbudiff.test index 0ebc0dad0f..0863f6e807 100644 --- a/ext/rbu/rbudiff.test +++ b/ext/rbu/rbudiff.test @@ -36,6 +36,7 @@ proc step_rbu {target rbu} { } proc apply_rbudiff {sql target} { + test_rbucount $sql forcedelete rbu.db sqlite3 rbudb rbu.db rbudb eval $sql @@ -43,6 +44,27 @@ proc apply_rbudiff {sql target} { step_rbu $target rbu.db } +# The only argument is the output of an [sqldiff -rbu] run. This command +# tests that the contents of the rbu_count table is correct. An exception +# is thrown if it is not. +# +proc test_rbucount {sql} { + sqlite3 tmpdb "" + tmpdb eval $sql + tmpdb eval { + SELECT name FROM sqlite_master WHERE name LIKE 'data%' AND type='table' + } { + set a [tmpdb eval "SELECT count(*) FROM $name"] + set b [tmpdb eval {SELECT cnt FROM rbu_count WHERE tbl = $name}] + if {$a != $b} { + tmpdb close + error "rbu_count error - tbl = $name" + } + } + tmpdb close + return "" +} + proc rbudiff_cksum {db1} { set txt "" diff --git a/ext/rbu/rbuprogress.test b/ext/rbu/rbuprogress.test index 6e6c7faf61..6afbffe8ed 100644 --- a/ext/rbu/rbuprogress.test +++ b/ext/rbu/rbuprogress.test @@ -381,6 +381,16 @@ foreach {bReopen} { 0 1 } { } {2500 4000 6000 8000 10000} {5000 10000} + + 3 { + CREATE TABLE data0_t1(rbu_rowid, a, b, c, rbu_control); + INSERT INTO data0_t1 VALUES(1, NULL, NULL, NULL, 1); + INSERT INTO data0_t1 VALUES(2, NULL, NULL, 7, '..x'); + CREATE TABLE rbu_count(tbl, cnt); + INSERT INTO rbu_count VALUES('data0_t1', 2); + } + {2500 4000 6000 8000 10000} + {5000 10000} } { reset_db ; execsql $tbl diff --git a/manifest b/manifest index c781c627e1..0d19f8488d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\slatest\strunk\schanges,\sincluding\sfixes\sto\stest\sscript\srbudiff.test,\sinto\sthis\sbranch. -D 2016-03-19T15:34:42.291 +C Update\sthe\ssqldiff\stool\sso\sthat\sit\sgenerates\san\srbu_count\stable. +D 2016-03-19T16:21:26.457 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -238,11 +238,11 @@ F ext/rbu/rbuB.test c25bc325b8072a766e56bb76c001866b405925c2 F ext/rbu/rbuC.test efe47db508a0269b683cb2a1913a425ffd39a831 F ext/rbu/rbu_common.tcl 0398545fed614f807d5f0ba55a85a51f08ba8f1a F ext/rbu/rbucrash.test 8d2ed5d4b05fef6c00c2a6b5f7ead71fa172a695 -F ext/rbu/rbudiff.test 7f0fbf54912b9f8898819504c8465df12c970a00 +F ext/rbu/rbudiff.test 2df0a8a7d998ecf81764c21eeda3cde5611c5091 F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda -F ext/rbu/rbuprogress.test 9d2dfd82fc001f26997e36db256df31f2e19e133 +F ext/rbu/rbuprogress.test 2023a7df2c523e3df1cb532eff811cda385a789a F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 F ext/rbu/sqlite3rbu.c edeb8f90a1bccc567438036e083123cec1403091 F ext/rbu/sqlite3rbu.h d7cc99350c10134f358fe1a8997d9225b3f712b2 @@ -1424,7 +1424,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c -F tool/sqldiff.c 0e9b76f9f4a72856d0384f5e0a038bbeb78dd222 +F tool/sqldiff.c ca315aca4e2d24233e8f2000edea5880c53d1875 F tool/srcck1.c 4f65e1a6748e42f24c0ea629dddc934d821c729a F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d @@ -1457,7 +1457,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 65e02368e2b6cec349ea71af5a456d6783b0d15e 41c29c123ff347db720ed1a541c0b2ffc04670aa -R 4672da949ef7e2ff98784ed13b0995da +P 734fc68fb12f06e97026d4637138b82b37809f5b +R 10d61b7fcae01138c8363988e8c8eb47 U dan -Z 877e0d37b31de9a8b8cab0dfbc82a372 +Z 3bf67face0611b0cfd47029621ad6bf5 diff --git a/manifest.uuid b/manifest.uuid index 5a343a598e..60d114711c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -734fc68fb12f06e97026d4637138b82b37809f5b \ No newline at end of file +1f7afb6e9be9f549a91bf2ab492df15698df89fd \ No newline at end of file diff --git a/tool/sqldiff.c b/tool/sqldiff.c index d2423a73ba..319acafdbd 100644 --- a/tool/sqldiff.c +++ b/tool/sqldiff.c @@ -1244,6 +1244,7 @@ static void rbudiff_one_table(const char *zTab, FILE *out){ Str sql = {0, 0, 0}; /* Query to find differences */ Str insert = {0, 0, 0}; /* First part of output INSERT statement */ sqlite3_stmt *pStmt = 0; + int nRow = 0; /* Total rows in data_xxx table */ /* --rbu mode must use real primary keys. */ g.bSchemaPK = 1; @@ -1289,6 +1290,7 @@ static void rbudiff_one_table(const char *zTab, FILE *out){ /* Output the first part of the INSERT statement */ fprintf(out, "%s", insert.z); + nRow++; if( sqlite3_column_type(pStmt, nCol)==SQLITE_INTEGER ){ for(i=0; i<=nCol; i++){ @@ -1342,6 +1344,12 @@ static void rbudiff_one_table(const char *zTab, FILE *out){ } sqlite3_finalize(pStmt); + if( nRow>0 ){ + Str cnt = {0, 0, 0}; + strPrintf(&cnt, "INSERT INTO rbu_count VALUES('data_%q', %d);", zTab, nRow); + fprintf(out, "%s\n", cnt.z); + strFree(&cnt); + } strFree(&ct); strFree(&sql); @@ -1856,7 +1864,13 @@ int main(int argc, char **argv){ } if( neverUseTransaction ) useTransaction = 0; - if( useTransaction ) printf("BEGIN TRANSACTION;\n"); + if( useTransaction ) fprintf(out, "BEGIN TRANSACTION;\n"); + if( xDiff==rbudiff_one_table ){ + fprintf(out, "CREATE TABLE IF NOT EXISTS rbu_count" + "(tbl TEXT PRIMARY KEY COLLATE NOCASE, cnt INTEGER) " + "WITHOUT ROWID;\n" + ); + } if( zTab ){ xDiff(zTab, out); }else{ From fce07fb9449f0f9880a2944525eb0a3452c768c8 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Mar 2016 17:09:30 +0000 Subject: [PATCH 500/570] Fix a problem detecting invalid values in the rbu_control column of an rbu database table. FossilOrigin-Name: a1132dd9027d1c6dd845be307eeb38e535393f2c --- ext/rbu/rbu1.test | 2 +- ext/rbu/sqlite3rbu.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/rbu/rbu1.test b/ext/rbu/rbu1.test index 19b3d27a9f..51d2ce8171 100644 --- a/ext/rbu/rbu1.test +++ b/ext/rbu/rbu1.test @@ -611,7 +611,7 @@ foreach {tn3 create_vfs destroy_vfs} { 9 { CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; CREATE TABLE rbu.data_t1(a, b, rbu_control); - INSERT INTO rbu.data_t1 VALUES(1, 2, 2); + INSERT INTO rbu.data_t1 VALUES(1, 2, 3); } {SQLITE_ERROR - invalid rbu_control value} 10 { diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index b587d2bb20..93b756aa6a 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -2706,7 +2706,7 @@ static int rbuStep(sqlite3rbu *p){ ); assert( eType!=RBU_UPDATE || pIter->zIdx==0 ); - if( pIter->zIdx==0 && eType==RBU_IDX_DELETE ){ + if( pIter->zIdx==0 && (eType==RBU_IDX_DELETE || eType==RBU_IDX_INSERT) ){ rbuBadControlError(p); } else if( eType==RBU_REPLACE ){ diff --git a/manifest b/manifest index 0d19f8488d..4f60482def 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\ssqldiff\stool\sso\sthat\sit\sgenerates\san\srbu_count\stable. -D 2016-03-19T16:21:26.457 +C Fix\sa\sproblem\sdetecting\sinvalid\svalues\sin\sthe\srbu_control\scolumn\sof\san\srbu\sdatabase\stable. +D 2016-03-19T17:09:30.416 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -221,7 +221,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rbu/rbu.c ba3983dceffa0938532e79142f391737513de023 -F ext/rbu/rbu1.test 57601977588603e82700a43c279bd55282ffa482 +F ext/rbu/rbu1.test 42bd835e019eff789ec241017965277baeb658b1 F ext/rbu/rbu10.test 046b0980041d30700464a800bbf6733ed2df515d F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702 F ext/rbu/rbu12.test bde22ed0004dd5d1888c72a84ae407e574aeae16 @@ -244,7 +244,7 @@ F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda F ext/rbu/rbuprogress.test 2023a7df2c523e3df1cb532eff811cda385a789a F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 -F ext/rbu/sqlite3rbu.c edeb8f90a1bccc567438036e083123cec1403091 +F ext/rbu/sqlite3rbu.c 007fc4db8c0b95c7ef10162b5864921ef5cc8106 F ext/rbu/sqlite3rbu.h d7cc99350c10134f358fe1a8997d9225b3f712b2 F ext/rbu/test_rbu.c 3505641a78b723589b8780d5f9b2faeeb73e037d F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 @@ -1457,7 +1457,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 734fc68fb12f06e97026d4637138b82b37809f5b -R 10d61b7fcae01138c8363988e8c8eb47 +P 1f7afb6e9be9f549a91bf2ab492df15698df89fd +R 514d2969d6e0309f243db8f417770908 U dan -Z 3bf67face0611b0cfd47029621ad6bf5 +Z 5251b6a3ad2fccca44307445ac5141c6 diff --git a/manifest.uuid b/manifest.uuid index 60d114711c..1c195bb6c5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1f7afb6e9be9f549a91bf2ab492df15698df89fd \ No newline at end of file +a1132dd9027d1c6dd845be307eeb38e535393f2c \ No newline at end of file From 9bccde3d03a75ca4730b7c4dfc83c69a4b86b0fb Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 19 Mar 2016 18:00:44 +0000 Subject: [PATCH 501/570] Updates to the Lemon documentation. FossilOrigin-Name: f095341471aa822e6d556cb65512ec081c3918da --- doc/lemon.html | 279 ++++++++++++++++++++++++++++++++----------------- manifest | 14 +-- manifest.uuid | 2 +- 3 files changed, 191 insertions(+), 104 deletions(-) diff --git a/doc/lemon.html b/doc/lemon.html index 2b8c613640..773c68e6ad 100644 --- a/doc/lemon.html +++ b/doc/lemon.html @@ -5,14 +5,17 @@

    The Lemon Parser Generator

    -

    Lemon is an LALR(1) parser generator for C or C++. -It does the same job as ``bison'' and ``yacc''. -But lemon is not another bison or yacc clone. It +

    Lemon is an LALR(1) parser generator for C. +It does the same job as "bison" and "yacc". +But lemon is not a bison or yacc clone. Lemon uses a different grammar syntax which is designed to -reduce the number of coding errors. Lemon also uses a more -sophisticated parsing engine that is faster than yacc and -bison and which is both reentrant and thread-safe. -Furthermore, Lemon implements features that can be used +reduce the number of coding errors. Lemon also uses a +parsing engine that is faster than yacc and +bison and which is both reentrant and threadsafe. +(Update: Since the previous sentence was written, bison +has also been updated so that it too can generate a +reentrant and threadsafe parser.) +Lemon also implements features that can be used to eliminate resource leaks, making is suitable for use in long-running programs such as graphical user interfaces or embedded controllers.

    @@ -44,18 +47,18 @@ one and three files of outputs. automaton. By default, all three of these output files are generated. -The header file is suppressed if the ``-m'' command-line option is -used and the report file is omitted when ``-q'' is selected.

    +The header file is suppressed if the "-m" command-line option is +used and the report file is omitted when "-q" is selected.

    -

    The grammar specification file uses a ``.y'' suffix, by convention. +

    The grammar specification file uses a ".y" suffix, by convention. In the examples used in this document, we'll assume the name of the -grammar file is ``gram.y''. A typical use of Lemon would be the +grammar file is "gram.y". A typical use of Lemon would be the following command:

        lemon gram.y
     
    -This command will generate three output files named ``gram.c'', -``gram.h'' and ``gram.out''. +This command will generate three output files named "gram.c", +"gram.h" and "gram.out". The first is C code to implement the parser. The second is the header file that defines numerical values for all terminal symbols, and the last is the report that explains @@ -71,39 +74,35 @@ with a brief explanation of what each does by typing As of this writing, the following command-line options are supported:
      -
    • -b -
    • -c -
    • -g -
    • -m -
    • -q -
    • -s -
    • -x +
    • -b +Show only the basis for each parser state in the report file. +
    • -c +Do not compress the generated action tables. +
    • -Dname +Define C preprocessor macro name. This macro is useable by +"%ifdef" lines in the grammar file. +
    • -g +Do not generate a parser. Instead write the input grammar to standard +output with all comments, actions, and other extraneous text removed. +
    • -l +Omit "#line" directives int the generated parser C code. +
    • -m +Cause the output C source code to be compatible with the "makeheaders" +program. +
    • -p +Display all conflicts that are resolved by +precedence rules. +
    • -q +Suppress generation of the report file. +
    • -r +Do not sort or renumber the parser states as part of optimization. +
    • -s +Show parser statistics before existing. +
    • -Tfile +Use file as the template for the generated C-code parser implementation. +
    • -x +Print the Lemon version number.
    -The ``-b'' option reduces the amount of text in the report file by -printing only the basis of each parser state, rather than the full -configuration. -The ``-c'' option suppresses action table compression. Using -c -will make the parser a little larger and slower but it will detect -syntax errors sooner. -The ``-g'' option causes no output files to be generated at all. -Instead, the input grammar file is printed on standard output but -with all comments, actions and other extraneous text deleted. This -is a useful way to get a quick summary of a grammar. -The ``-m'' option causes the output C source file to be compatible -with the ``makeheaders'' program. -Makeheaders is a program that automatically generates header files -from C source code. When the ``-m'' option is used, the header -file is not output since the makeheaders program will take care -of generated all header files automatically. -The ``-q'' option suppresses the report file. -Using ``-s'' causes a brief summary of parser statistics to be -printed. Like this: -
    -   Parser statistics: 74 terminals, 70 nonterminals, 179 rules
    -                      340 states, 2026 parser table entries, 0 conflicts
    -
    -Finally, the ``-x'' option causes Lemon to print its version number -and then stops without attempting to read the grammar or generate a parser.

    The Parser Interface

    @@ -121,12 +120,12 @@ A new parser is created as follows: The ParseAlloc() routine allocates and initializes a new parser and returns a pointer to it. -The actual data structure used to represent a parser is opaque -- +The actual data structure used to represent a parser is opaque — its internal structure is not visible or usable by the calling routine. For this reason, the ParseAlloc() routine returns a pointer to void rather than a pointer to some particular structure. The sole argument to the ParseAlloc() routine is a pointer to the -subroutine used to allocate memory. Typically this means ``malloc()''.

    +subroutine used to allocate memory. Typically this means malloc().

    After a program is finished using a parser, it can reclaim all memory allocated by that parser by calling @@ -151,13 +150,13 @@ type of the next token in the data stream. There is one token type for each terminal symbol in the grammar. The gram.h file generated by Lemon contains #define statements that map symbolic terminal symbol names into appropriate integer values. -(A value of 0 for the second argument is a special flag to the -parser to indicate that the end of input has been reached.) +A value of 0 for the second argument is a special flag to the +parser to indicate that the end of input has been reached. The third argument is the value of the given token. By default, the type of the third argument is integer, but the grammar will usually redefine this type to be some kind of structure. Typically the second argument will be a broad category of tokens -such as ``identifier'' or ``number'' and the third argument will +such as "identifier" or "number" and the third argument will be the name of the identifier or the value of the number.

    The Parse() function may have either three or four arguments, @@ -193,7 +192,7 @@ following: This example shows a user-written routine that parses a file of text and returns a pointer to the parse tree. -(We've omitted all error-handling from this example to keep it +(All error-handling code is omitted from this example to keep it simple.) We assume the existence of some kind of tokenizer which is created using TokenizerCreate() on line 8 and deleted by TokenizerFree() @@ -287,7 +286,7 @@ tokens) and it honors the same commenting conventions as C and C++.

    Terminals and Nonterminals

    A terminal symbol (token) is any string of alphanumeric -and underscore characters +and/or underscore characters that begins with an upper case letter. A terminal can contain lowercase letters after the first character, but the usual convention is to make terminals all upper case. @@ -314,7 +313,7 @@ must have alphanumeric names.

    The main component of a Lemon grammar file is a sequence of grammar rules. Each grammar rule consists of a nonterminal symbol followed by -the special symbol ``::='' and then a list of terminals and/or nonterminals. +the special symbol "::=" and then a list of terminals and/or nonterminals. The rule is terminated by a period. The list of terminals and nonterminals on the right-hand side of the rule can be empty. @@ -330,9 +329,9 @@ A typical sequence of grammar rules might look something like this:

    -

    There is one non-terminal in this example, ``expr'', and five -terminal symbols or tokens: ``PLUS'', ``TIMES'', ``LPAREN'', -``RPAREN'' and ``VALUE''.

    +

    There is one non-terminal in this example, "expr", and five +terminal symbols or tokens: "PLUS", "TIMES", "LPAREN", +"RPAREN" and "VALUE".

    Like yacc and bison, Lemon allows the grammar to specify a block of C code that will be executed whenever a grammar rule is reduced @@ -348,15 +347,15 @@ For example:

    In order to be useful, grammar actions must normally be linked to their associated grammar rules. -In yacc and bison, this is accomplished by embedding a ``$$'' in the +In yacc and bison, this is accomplished by embedding a "$$" in the action to stand for the value of the left-hand side of the rule and -symbols ``$1'', ``$2'', and so forth to stand for the value of +symbols "$1", "$2", and so forth to stand for the value of the terminal or nonterminal at position 1, 2 and so forth on the right-hand side of the rule. This idea is very powerful, but it is also very error-prone. The single most common source of errors in a yacc or bison grammar is to miscount the number of symbols on the right-hand side of a grammar -rule and say ``$7'' when you really mean ``$8''.

    +rule and say "$7" when you really mean "$8".

    Lemon avoids the need to count grammar symbols by assigning symbolic names to each symbol in a grammar rule and then using those symbolic @@ -386,7 +385,7 @@ For example, the rule

       expr(A) ::= expr(B) PLUS expr(C).  { A = B; }
     
    -will generate an error because the linking symbol ``C'' is used +will generate an error because the linking symbol "C" is used in the grammar rule but not in the reduce action.

    The Lemon notation for linking grammar rules to reduce actions @@ -394,6 +393,7 @@ also facilitates the use of destructors for reclaiming memory allocated by the values of terminals and nonterminals on the right-hand side of a rule.

    +

    Precedence Rules

    Lemon resolves parsing ambiguities in exactly the same way as @@ -405,7 +405,10 @@ whichever rule comes first in the grammar file.

    yacc and bison, Lemon allows a measure of control over the resolution of paring conflicts using precedence rules. A precedence value can be assigned to any terminal symbol -using the %left, %right or %nonassoc directives. Terminal symbols +using the +%left, +%right or +%nonassoc directives. Terminal symbols mentioned in earlier directives have a lower precedence that terminal symbols mentioned in later directives. For example:

    @@ -525,7 +528,11 @@ other than that, the order of directives in Lemon is arbitrary.

  • %default_destructor
  • %default_type
  • %destructor +
  • %endif
  • %extra_argument +
  • %fallback +
  • %ifdef +
  • %ifndef
  • %include
  • %left
  • %name @@ -537,49 +544,57 @@ other than that, the order of directives in Lemon is arbitrary.

  • %stack_size
  • %start_symbol
  • %syntax_error +
  • %token_class
  • %token_destructor
  • %token_prefix
  • %token_type
  • %type +
  • %wildcard Each of these directives will be described separately in the following sections:

    +

    The %code directive

    -

    The %code directive is used to specify addition C/C++ code that +

    The %code directive is used to specify addition C code that is added to the end of the main output file. This is similar to -the %include directive except that %include is inserted at the -beginning of the main output file.

    +the %include directive except that %include +is inserted at the beginning of the main output file.

    %code is typically used to include some action routines or perhaps -a tokenizer as part of the output file.

    +a tokenizer or even the "main()" function +as part of the output file.

    +

    The %default_destructor directive

    The %default_destructor directive specifies a destructor to use for non-terminals that do not have their own destructor specified by a separate %destructor directive. See the documentation -on the %destructor directive below for additional information.

    +on the %destructor directive below for +additional information.

    In some grammers, many different non-terminal symbols have the same datatype and hence the same destructor. This directive is a convenience way to specify the same destructor for all those non-terminals using a single statement.

    +

    The %default_type directive

    The %default_type directive specifies the datatype of non-terminal symbols that do no have their own datatype defined using a separate -%type directive. See the documentation on %type below for addition -information.

    +%type directive. +

    +

    The %destructor directive

    The %destructor directive is used to specify a destructor for a non-terminal symbol. -(See also the %token_destructor directive which is used to -specify a destructor for terminal symbols.)

    +(See also the %token_destructor +directive which is used to specify a destructor for terminal symbols.)

    A non-terminal's destructor is called to dispose of the non-terminal's value whenever the non-terminal is popped from @@ -602,26 +617,25 @@ or other resources held by that non-terminal.

    This example is a bit contrived but it serves to illustrate how destructors work. The example shows a non-terminal named -``nt'' that holds values of type ``void*''. When the rule for -an ``nt'' reduces, it sets the value of the non-terminal to +"nt" that holds values of type "void*". When the rule for +an "nt" reduces, it sets the value of the non-terminal to space obtained from malloc(). Later, when the nt non-terminal is popped from the stack, the destructor will fire and call free() on this malloced space, thus avoiding a memory leak. -(Note that the symbol ``$$'' in the destructor code is replaced +(Note that the symbol "$$" in the destructor code is replaced by the value of the non-terminal.)

    It is important to note that the value of a non-terminal is passed to the destructor whenever the non-terminal is removed from the stack, unless the non-terminal is used in a C-code action. If the non-terminal is used by C-code, then it is assumed that the -C-code will take care of destroying it if it should really -be destroyed. More commonly, the value is used to build some +C-code will take care of destroying it. +More commonly, the value is used to build some larger structure and we don't want to destroy it, which is why the destructor is not called in this circumstance.

    -

    By appropriate use of destructors, it is possible to -build a parser using Lemon that can be used within a long-running -program, such as a GUI, that will not leak memory or other resources. +

    Destructors help avoid memory leaks by automatically freeing +allocated objects when they go out of scope. To do the same using yacc or bison is much more difficult.

    @@ -638,17 +652,66 @@ and so forth. For example, if the grammar file contains:

    Then the Parse() function generated will have an 4th parameter -of type ``MyStruct*'' and all action routines will have access to -a variable named ``pAbc'' that is the value of the 4th parameter +of type "MyStruct*" and all action routines will have access to +a variable named "pAbc" that is the value of the 4th parameter in the most recent call to Parse().

    + +

    The %fallback directive

    + +

    The %fallback directive specifies an alternative meaning for one +or more tokens. The alternative meaning is tried if the original token +would have generated a syntax error. + +

    The %fallback directive was added to support robust parsing of SQL +syntax in SQLite. +The SQL language contains a large assortment of keywords, each of which +appears as a different token to the language parser. SQL contains so +many keywords, that it can be difficult for programmers to keep up with +them all. Programmers will, therefore, sometimes mistakenly use an +obscure language keyword for an identifier. The %fallback directive +provides a mechanism to tell the parser: "If you are unable to parse +this keyword, try treating it as an identifier instead." + +

    The syntax of %fallback is as follows: + +

    +%fallback ID TOKEN... . +
    + +

    In words, the %fallback directive is followed by a list of token names +terminated by a period. The first token name is the fallback token - the +token to which all the other tokens fall back to. The second and subsequent +arguments are tokens which fall back to the token identified by the first +argument. + + +

    The %ifdef, %ifndef, and %endif directives.

    + +

    The %ifdef, %ifndef, and %endif directives are similar to +#ifdef, #ifndef, and #endif in the C-preprocessor, just not as general. +Each of these directives must begin at the left margin. No whitespace +is allowed between the "%" and the directive name. + +

    Grammar text in between "%ifdef MACRO" and the next nested "%endif" is +ignored unless the "-DMACRO" command-line option is used. Grammar text +betwen "%ifndef MACRO" and the next nested "%endif" is included except when +the "-DMACRO" command-line option is used. + +

    Note that the argument to %ifdef and %ifndef must be a single +preprocessor symbol name, not a general expression. There is no "%else" +directive. + + +

    The %include directive

    The %include directive specifies C code that is included at the top of the generated parser. You can include any text you want -- the Lemon parser generator copies it blindly. If you have multiple -%include directives in your grammar file the value of the last -%include directive overwrites all the others.

    The %include directive is very handy for getting some extra #include preprocessor statements at the beginning of the generated parser. @@ -661,12 +724,13 @@ For example:

    This might be needed, for example, if some of the C actions in the grammar call functions that are prototyed in unistd.h.

    +

    The %left directive

    -The %left directive is used (along with the %right and -%nonassoc directives) to declare precedences of terminal -symbols. Every terminal symbol whose name appears after -a %left directive but before the next period (``.'') is +The %left directive is used (along with the %right and +%nonassoc directives) to declare precedences of +terminal symbols. Every terminal symbol whose name appears after +a %left directive but before the next period (".") is given the same left-associative precedence value. Subsequent %left directives have higher precedence. For example:

    @@ -687,10 +751,11 @@ a large amount of stack space if you make heavy use or right-associative operators. For this reason, it is recommended that you use %left rather than %right whenever possible.

    +

    The %name directive

    By default, the functions generated by Lemon all begin with the -five-character string ``Parse''. You can change this string to something +five-character string "Parse". You can change this string to something different using the %name directive. For instance:

    @@ -709,16 +774,19 @@ The %name directive allows you to generator two or more different
     parsers and link them all into the same executable.
     

    +

    The %nonassoc directive

    This directive is used to assign non-associative precedence to -one or more terminal symbols. See the section on precedence rules -or on the %left directive for additional information.

    +one or more terminal symbols. See the section on +precedence rules +or on the %left directive for additional information.

    +

    The %parse_accept directive

    The %parse_accept directive specifies a block of C code that is -executed whenever the parser accepts its input string. To ``accept'' +executed whenever the parser accepts its input string. To "accept" an input string means that the parser was able to process all tokens without error.

    @@ -730,7 +798,7 @@ without error.

    }

    - +

    The %parse_failure directive

    The %parse_failure directive specifies a block of C code that @@ -745,12 +813,15 @@ only invoked when parsing is unable to continue.

    }

    +

    The %right directive

    This directive is used to assign right-associative precedence to -one or more terminal symbols. See the section on precedence rules -or on the %left directive for additional information.

    +one or more terminal symbols. See the section on +precedence rules +or on the %left directive for additional information.

    +

    The %stack_overflow directive

    The %stack_overflow directive specifies a block of C code that @@ -779,6 +850,7 @@ Not like this: list ::= . +

    The %stack_size directive

    If stack overflow is a problem and you can't resolve the trouble @@ -791,6 +863,7 @@ with a stack of the requested size. The default value is 100.

    %stack_size 2000

    +

    The %start_symbol directive

    By default, the start-symbol for the grammar that Lemon generates @@ -801,6 +874,7 @@ can choose a different start-symbol using the %start_symbol directive.

    %start_symbol prog

    +

    The %token_destructor directive

    The %destructor directive assigns a destructor to a non-terminal @@ -813,6 +887,7 @@ the %token_type directive) and so they use a common destructor. Other than that, the token destructor works just like the non-terminal destructors.

    +

    The %token_prefix directive

    Lemon generates #defines that assign small integer constants @@ -838,6 +913,7 @@ to cause Lemon to produce these symbols instead: #define TOKEN_PLUS 4 +

    The %token_type and %type directives

    These directives are used to specify the data types for values @@ -853,7 +929,7 @@ token structure. Like this:

    If the data type of terminals is not specified, the default value -is ``int''.

    +is "int".

    Non-terminal symbols can each have their own data types. Typically the data type of a non-terminal is a pointer to the root of a parse-tree @@ -874,6 +950,17 @@ non-terminal whose data type requires 1K of storage, then your 100 entry parser stack will require 100K of heap space. If you are willing and able to pay that price, fine. You just need to know.

    + +

    The %wildcard directive

    + +

    The %wildcard directive is followed by a single token name and a +period. This directive specifies that the identified token should +match any input token. + +

    When the generated parser has the choice of matching an input against +the wildcard token and some other token, the other token is always used. +The wildcard token is only matched if there are no other alternatives. +

    Error Processing

    After extensive experimentation over several years, it has been @@ -885,7 +972,7 @@ first invokes the code specified by the %syntax_error directive, if any. It then enters its error recovery strategy. The error recovery strategy is to begin popping the parsers stack until it enters a state where it is permitted to shift a special non-terminal symbol -named ``error''. It then shifts this non-terminal and continues +named "error". It then shifts this non-terminal and continues parsing. But the %syntax_error routine will not be called again until at least three new tokens have been successfully shifted.

    @@ -894,7 +981,7 @@ is unable to shift the error symbol, then the %parse_failed routine is invoked and the parser resets itself to its start state, ready to begin parsing a new file. This is what will happen at the very first syntax error, of course, if there are no instances of the -``error'' non-terminal in your grammar.

    +"error" non-terminal in your grammar.

    diff --git a/manifest b/manifest index 16d972c4c4..0f76cddd77 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssqlite3rbu_bp_progress()\sAPI\sto\sthe\sRBU\sextension.\sUsed\sto\sobtain\sthe\spercentage\sprogress\sof\san\sRBU\supdate. -D 2016-03-19T17:48:12.474 +C Updates\sto\sthe\sLemon\sdocumentation. +D 2016-03-19T18:00:44.390 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -33,7 +33,7 @@ F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 F configure c01a159fdf7ea0171ad01ce2937283f2c7972bde x F configure.ac 89e4e02a83d8a1528011f8395621b8c3186b4089 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad -F doc/lemon.html c30255bea0fd87a81f082d17a72c9dffbc3f6dd9 +F doc/lemon.html e2118945e5f07ed146b45c9cd2b2dd6eabb8ebf2 F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710 F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a F ext/README.txt 913a7bd3f4837ab14d7e063304181787658b14e1 @@ -1457,7 +1457,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 41c29c123ff347db720ed1a541c0b2ffc04670aa a1132dd9027d1c6dd845be307eeb38e535393f2c -R cb043230718add9f6d5b3a52d3cc19f9 -U dan -Z 67d28afde6e42b0d24beaa12aaf943b4 +P 209e31c729b9c8a09a80e43e3e4a2f3cd9384b3a +R fc92092a5d7485b32fa03b1aa106ab60 +U drh +Z 281323da864a48bf6b3196a4def3800c diff --git a/manifest.uuid b/manifest.uuid index 8119ca882f..e217909057 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -209e31c729b9c8a09a80e43e3e4a2f3cd9384b3a \ No newline at end of file +f095341471aa822e6d556cb65512ec081c3918da \ No newline at end of file From b6eb666264d2885e78288abc7a21798cd7092f7d Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Mar 2016 18:11:59 +0000 Subject: [PATCH 502/570] Fix exclusive.test so that it works with -DSQLITE_TEMP_STORE=3. FossilOrigin-Name: d7852c639683a1d305a1e731df3cccafa64b594b --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/exclusive.test | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 0f76cddd77..847bc79890 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Updates\sto\sthe\sLemon\sdocumentation. -D 2016-03-19T18:00:44.390 +C Fix\sexclusive.test\sso\sthat\sit\sworks\swith\s-DSQLITE_TEMP_STORE=3. +D 2016-03-19T18:11:59.750 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -630,7 +630,7 @@ F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020 F test/eqp.test 3fe051af50921284189d1970eb653f9fcf5117d2 F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401 F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c -F test/exclusive.test f48243eaf40e0957215501a12f510a8644d13a02 +F test/exclusive.test 9a57bd66e39144b888ca75c309914fcdefb4e3f9 F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308 F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7 F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30 @@ -1457,7 +1457,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 209e31c729b9c8a09a80e43e3e4a2f3cd9384b3a -R fc92092a5d7485b32fa03b1aa106ab60 -U drh -Z 281323da864a48bf6b3196a4def3800c +P f095341471aa822e6d556cb65512ec081c3918da +R eda7e2fd58d6241fa97b2fe69addd6c1 +U dan +Z fdac7ca02eef2361aeb61c0eeeaed018 diff --git a/manifest.uuid b/manifest.uuid index e217909057..378b71e1fc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f095341471aa822e6d556cb65512ec081c3918da \ No newline at end of file +d7852c639683a1d305a1e731df3cccafa64b594b \ No newline at end of file diff --git a/test/exclusive.test b/test/exclusive.test index c7b88cfbca..45f9318205 100644 --- a/test/exclusive.test +++ b/test/exclusive.test @@ -423,7 +423,7 @@ do_test exclusive-5.1 { # (2016-03-04) The statement-journal is now opened lazily set sqlite_open_file_count expr $sqlite_open_file_count-$extrafds -} [expr 2 - ($TEMP_STORE>=2)] +} {2} do_test exclusive-5.2 { execsql { COMMIT; @@ -450,7 +450,7 @@ do_test exclusive-5.4 { # 2016-03-04: The statement-journal open is deferred set sqlite_open_file_count expr $sqlite_open_file_count-$extrafds -} [expr 2 - ($TEMP_STORE>=2)] +} {2} do_test exclusive-5.5 { execsql { COMMIT; @@ -459,7 +459,7 @@ do_test exclusive-5.5 { # 2016-03-04: The statement-journal open is deferred set sqlite_open_file_count expr $sqlite_open_file_count-$extrafds -} [expr 2 - ($TEMP_STORE>=2)] +} {2} do_test exclusive-5.6 { execsql { PRAGMA locking_mode = normal; From 9f6168b6a3bbd7656fd2428049144e403e9cb037 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 19 Mar 2016 23:32:58 +0000 Subject: [PATCH 503/570] Change the Vdbe.aMem array so that it is zero-based instead of one-based. FossilOrigin-Name: e07b0c47eb5a39623f5fe0e66b939bba0906691c --- manifest | 21 +++++++------ manifest.uuid | 2 +- src/vdbe.c | 82 ++++++++++++++++++++++++++------------------------- src/vdbeaux.c | 21 ++++++------- src/vdbemem.c | 2 +- 5 files changed, 67 insertions(+), 61 deletions(-) diff --git a/manifest b/manifest index 847bc79890..dc84917b98 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sexclusive.test\sso\sthat\sit\sworks\swith\s-DSQLITE_TEMP_STORE=3. -D 2016-03-19T18:11:59.750 +C Change\sthe\sVdbe.aMem\sarray\sso\sthat\sit\sis\szero-based\sinstead\sof\sone-based. +D 2016-03-19T23:32:59.000 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -417,13 +417,13 @@ F src/update.c 56b3db7edff0110360a12b76af97c39ebe3ea8b8 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 34ef7be420f82415ec48131404995ddb6ee7502f F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 -F src/vdbe.c 8cf45bb8da77d39f55d108e759d15a57acd0255c +F src/vdbe.c 90d18d0a91284092a099e9a048982df38920190c F src/vdbe.h 6f44193e7be52fd5f7c308175a936555b1e6b101 F src/vdbeInt.h f88d3115e9bde33b01d81f0dd26d8dd51f995991 F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 -F src/vdbeaux.c a930f913d40e4ca6f6caaef6a7b5906a369fa2b1 +F src/vdbeaux.c 4a38b9f9dab7350f670b9efff25f605933f81963 F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db -F src/vdbemem.c 9b0cb32cc267ef026515f15a3594d5ff91fe4dfc +F src/vdbemem.c fe76c1f866de362d9b8332e59d74aa44f6560d69 F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062 F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 F src/vtab.c fd69fd398e23e57ea4ea377d8a44b6998fc569c7 @@ -1457,7 +1457,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f095341471aa822e6d556cb65512ec081c3918da -R eda7e2fd58d6241fa97b2fe69addd6c1 -U dan -Z fdac7ca02eef2361aeb61c0eeeaed018 +P d7852c639683a1d305a1e731df3cccafa64b594b +R 4a4c5282463bb7b6f1f36414c3f19a6f +T *branch * zero-base-aMem +T *sym-zero-base-aMem * +T -sym-trunk * +U drh +Z 5ba539d03a989ddc8c4359f1a3ede74d diff --git a/manifest.uuid b/manifest.uuid index 378b71e1fc..24fae6a151 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d7852c639683a1d305a1e731df3cccafa64b594b \ No newline at end of file +e07b0c47eb5a39623f5fe0e66b939bba0906691c \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 6f4ac5713d..bdab41b6b6 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -192,11 +192,11 @@ static VdbeCursor *allocateCursor( ** be freed lazily via the sqlite3_release_memory() API. This ** minimizes the number of malloc calls made by the system. ** - ** Memory cells for cursors are allocated at the top of the address - ** space. Memory cell (p->nMem) corresponds to cursor 0. Space for - ** cursor 1 is managed by memory cell (p->nMem-1), etc. + ** Memory cell for cursor 0 is Mem[0]. The rest are allocated from + ** the top of the register space. Cursor 1 is at Mem[p->nMem-1]. + ** Cursor 2 is at Mem[p->nMem-2]. And so forth. */ - Mem *pMem = &p->aMem[p->nMem-iCur]; + Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem; int nByte; VdbeCursor *pCx = 0; @@ -204,7 +204,7 @@ static VdbeCursor *allocateCursor( ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField + (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0); - assert( iCurnCursor ); + assert( iCur>=0 && iCurnCursor ); if( p->apCsr[iCur] ){ sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); p->apCsr[iCur] = 0; @@ -529,7 +529,7 @@ static SQLITE_NOINLINE Mem *out2PrereleaseWithClear(Mem *pOut){ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){ Mem *pOut; assert( pOp->p2>0 ); - assert( pOp->p2<=(p->nMem-p->nCursor) ); + assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); pOut = &p->aMem[pOp->p2]; memAboutToChange(p, pOut); if( VdbeMemDynamic(pOut) ){ @@ -667,33 +667,33 @@ int sqlite3VdbeExec( assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] ); if( (pOp->opflags & OPFLG_IN1)!=0 ){ assert( pOp->p1>0 ); - assert( pOp->p1<=(p->nMem-p->nCursor) ); + assert( pOp->p1<=(p->nMem+1 - p->nCursor) ); assert( memIsValid(&aMem[pOp->p1]) ); assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) ); REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]); } if( (pOp->opflags & OPFLG_IN2)!=0 ){ assert( pOp->p2>0 ); - assert( pOp->p2<=(p->nMem-p->nCursor) ); + assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); assert( memIsValid(&aMem[pOp->p2]) ); assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) ); REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]); } if( (pOp->opflags & OPFLG_IN3)!=0 ){ assert( pOp->p3>0 ); - assert( pOp->p3<=(p->nMem-p->nCursor) ); + assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); assert( memIsValid(&aMem[pOp->p3]) ); assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) ); REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]); } if( (pOp->opflags & OPFLG_OUT2)!=0 ){ assert( pOp->p2>0 ); - assert( pOp->p2<=(p->nMem-p->nCursor) ); + assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); memAboutToChange(p, &aMem[pOp->p2]); } if( (pOp->opflags & OPFLG_OUT3)!=0 ){ assert( pOp->p3>0 ); - assert( pOp->p3<=(p->nMem-p->nCursor) ); + assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); memAboutToChange(p, &aMem[pOp->p3]); } #endif @@ -792,7 +792,7 @@ check_for_interrupt: ** and then jump to address P2. */ case OP_Gosub: { /* jump */ - assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); + assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); pIn1 = &aMem[pOp->p1]; assert( VdbeMemDynamic(pIn1)==0 ); memAboutToChange(p, pIn1); @@ -832,7 +832,7 @@ case OP_Return: { /* in1 */ ** See also: EndCoroutine */ case OP_InitCoroutine: { /* jump */ - assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); + assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); assert( pOp->p2>=0 && pOp->p2nOp ); assert( pOp->p3>=0 && pOp->p3nOp ); pOut = &aMem[pOp->p1]; @@ -1101,7 +1101,7 @@ case OP_String: { /* out2 */ #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS if( pOp->p5 ){ assert( pOp->p3>0 ); - assert( pOp->p3<=(p->nMem-p->nCursor) ); + assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); pIn3 = &aMem[pOp->p3]; assert( pIn3->flags & MEM_Int ); if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term; @@ -1127,7 +1127,7 @@ case OP_Null: { /* out2 */ u16 nullFlag; pOut = out2Prerelease(p, pOp); cnt = pOp->p3-pOp->p2; - assert( pOp->p3<=(p->nMem-p->nCursor) ); + assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; while( cnt>0 ){ pOut++; @@ -1148,7 +1148,7 @@ case OP_Null: { /* out2 */ ** previously copied using OP_SCopy, the copies will continue to be valid. */ case OP_SoftNull: { - assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); + assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); pOut = &aMem[pOp->p1]; pOut->flags = (pOut->flags|MEM_Null)&~MEM_Undefined; break; @@ -1215,8 +1215,8 @@ case OP_Move: { pIn1 = &aMem[p1]; pOut = &aMem[p2]; do{ - assert( pOut<=&aMem[(p->nMem-p->nCursor)] ); - assert( pIn1<=&aMem[(p->nMem-p->nCursor)] ); + assert( pOut<=&aMem[(p->nMem+1 - p->nCursor)] ); + assert( pIn1<=&aMem[(p->nMem+1 - p->nCursor)] ); assert( memIsValid(pIn1) ); memAboutToChange(p, pOut); sqlite3VdbeMemMove(pOut, pIn1); @@ -1316,7 +1316,7 @@ case OP_ResultRow: { int i; assert( p->nResColumn==pOp->p2 ); assert( pOp->p1>0 ); - assert( pOp->p1+pOp->p2<=(p->nMem-p->nCursor)+1 ); + assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 ); #ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* Run the progress counter just before returning. @@ -1628,8 +1628,8 @@ case OP_Function0: { assert( pOp->p4type==P4_FUNCDEF ); n = pOp->p5; - assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); - assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); + assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) ); assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); if( pCtx==0 ) goto no_mem; @@ -2129,11 +2129,11 @@ case OP_Compare: { if( aPermute ){ int k, mx = 0; for(k=0; kmx ) mx = aPermute[k]; - assert( p1>0 && p1+mx<=(p->nMem-p->nCursor)+1 ); - assert( p2>0 && p2+mx<=(p->nMem-p->nCursor)+1 ); + assert( p1>0 && p1+mx<=(p->nMem+1 - p->nCursor)+1 ); + assert( p2>0 && p2+mx<=(p->nMem+1 - p->nCursor)+1 ); }else{ - assert( p1>0 && p1+n<=(p->nMem-p->nCursor)+1 ); - assert( p2>0 && p2+n<=(p->nMem-p->nCursor)+1 ); + assert( p1>0 && p1+n<=(p->nMem+1 - p->nCursor)+1 ); + assert( p2>0 && p2+n<=(p->nMem+1 - p->nCursor)+1 ); } #endif /* SQLITE_DEBUG */ for(i=0; ip3>0 && pOp->p3<=(p->nMem-p->nCursor) ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); pDest = &aMem[pOp->p3]; memAboutToChange(p, pDest); assert( pOp->p1>=0 && pOp->p1nCursor ); @@ -2638,7 +2638,7 @@ case OP_Affinity: { assert( zAffinity[pOp->p2]==0 ); pIn1 = &aMem[pOp->p1]; while( (cAff = *(zAffinity++))!=0 ){ - assert( pIn1 <= &p->aMem[(p->nMem-p->nCursor)] ); + assert( pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)] ); assert( memIsValid(pIn1) ); applyAffinity(pIn1, cAff, encoding); pIn1++; @@ -2700,7 +2700,7 @@ case OP_MakeRecord: { nZero = 0; /* Number of zero bytes at the end of the record */ nField = pOp->p1; zAffinity = pOp->p4.z; - assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem-p->nCursor)+1 ); + assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem+1 - p->nCursor)+1 ); pData0 = &aMem[nField]; nField = pOp->p2; pLast = &pData0[nField-1]; @@ -2790,7 +2790,7 @@ case OP_MakeRecord: { assert( i==nHdr ); assert( j==nByte ); - assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); pOut->n = (int)nByte; pOut->flags = MEM_Blob; if( nZero ){ @@ -3376,7 +3376,7 @@ case OP_OpenWrite: } if( pOp->p5 & OPFLAG_P2ISREG ){ assert( p2>0 ); - assert( p2<=(p->nMem-p->nCursor) ); + assert( p2<=(p->nMem+1 - p->nCursor) ); pIn2 = &aMem[p2]; assert( memIsValid(pIn2) ); assert( (pIn2->flags & MEM_Int)!=0 ); @@ -4171,7 +4171,7 @@ case OP_NewRowid: { /* out2 */ pMem = &pFrame->aMem[pOp->p3]; }else{ /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3<=(p->nMem-p->nCursor) ); + assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); pMem = &aMem[pOp->p3]; memAboutToChange(p, pMem); } @@ -4947,7 +4947,7 @@ case OP_IdxDelete: { UnpackedRecord r; assert( pOp->p3>0 ); - assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem-p->nCursor)+1 ); + assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem+1 - p->nCursor)+1 ); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); @@ -5453,7 +5453,7 @@ case OP_IntegrityCk: { aRoot = pOp->p4.ai; assert( nRoot>0 ); assert( aRoot[nRoot]==0 ); - assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); pnErr = &aMem[pOp->p3]; assert( (pnErr->flags & MEM_Int)!=0 ); assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); @@ -5643,6 +5643,7 @@ case OP_Program: { /* jump */ ** variable nMem (and later, VdbeFrame.nChildMem) to this value. */ nMem = pProgram->nMem + pProgram->nCsr; + if( pProgram->nCsr==0 && nMem>0 ) nMem++; nByte = ROUND8(sizeof(VdbeFrame)) + nMem * sizeof(Mem) + pProgram->nCsr * sizeof(VdbeCursor *) @@ -5679,7 +5680,8 @@ case OP_Program: { /* jump */ } }else{ pFrame = pRt->u.pFrame; - assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem ); + assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem + || (pProgram->nCsr==0 && pProgram->nMem+1==pFrame->nChildMem) ); assert( pProgram->nCsr==pFrame->nChildCsr ); assert( (int)(pOp - aOp)==pFrame->pc ); } @@ -5694,10 +5696,10 @@ case OP_Program: { /* jump */ p->pAuxData = 0; p->nChange = 0; p->pFrame = pFrame; - p->aMem = aMem = &VdbeFrameMem(pFrame)[-1]; + p->aMem = aMem = VdbeFrameMem(pFrame); p->nMem = pFrame->nChildMem; p->nCursor = (u16)pFrame->nChildCsr; - p->apCsr = (VdbeCursor **)&aMem[p->nMem+1]; + p->apCsr = (VdbeCursor **)&aMem[p->nMem]; p->aOp = aOp = pProgram->aOp; p->nOp = pProgram->nOp; p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor]; @@ -5943,8 +5945,8 @@ case OP_AggStep0: { assert( pOp->p4type==P4_FUNCDEF ); n = pOp->p5; - assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); - assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); + assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) ); assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); if( pCtx==0 ) goto no_mem; @@ -6023,7 +6025,7 @@ case OP_AggStep: { */ case OP_AggFinal: { Mem *pMem; - assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); + assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); pMem = &aMem[pOp->p1]; assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); @@ -6465,7 +6467,7 @@ case OP_VColumn: { VdbeCursor *pCur = p->apCsr[pOp->p1]; assert( pCur->eCurType==CURTYPE_VTAB ); - assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); pDest = &aMem[pOp->p3]; memAboutToChange(p, pDest); if( pCur->nullRow ){ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index c71605cdd2..75307c258e 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1801,7 +1801,7 @@ void sqlite3VdbeRewind(Vdbe *p){ p->magic = VDBE_MAGIC_RUN; #ifdef SQLITE_DEBUG - for(i=1; inMem; i++){ + for(i=0; inMem; i++){ assert( p->aMem[i].db==p->db ); } #endif @@ -1866,16 +1866,18 @@ void sqlite3VdbeMakeReady( nOnce = pParse->nOnce; if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */ - /* For each cursor required, also allocate a memory cell. Memory - ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by + /* For each cursor required, also allocate a memory cell. Memory + ** cells 0 and (nMem-nCursor)..nMem-1 inclusive will never be used by ** the vdbe program. Instead they are used to allocate memory for ** VdbeCursor/BtCursor structures. The blob of memory associated with - ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1) - ** stores the blob of memory associated with cursor 1, etc. + ** cursor 0 is stored in memory cell 0. Memory cell (nMem-1) + ** stores the blob of memory associated with cursor 1. Memory cell + ** (nMem-iCur) is used for cursor iCur. ** ** See also: allocateCursor(). */ nMem += nCursor; + if( nCursor==0 && nMem>0 ) nMem++; /* Space for aMem[0] even if not used */ /* Figure out how much reusable memory is available at the end of the ** opcode array. This extra memory will be reallocated for other elements @@ -1937,9 +1939,8 @@ void sqlite3VdbeMakeReady( pParse->nzVar = 0; pParse->azVar = 0; if( p->aMem ){ - p->aMem--; /* aMem[] goes from 1..nMem */ - p->nMem = nMem; /* not from 0..nMem-1 */ - for(n=1; n<=nMem; n++){ + p->nMem = nMem; + for(n=0; naMem[n].flags = MEM_Undefined; p->aMem[n].db = db; } @@ -2049,7 +2050,7 @@ static void closeAllCursors(Vdbe *p){ assert( p->nFrame==0 ); closeCursorsInFrame(p); if( p->aMem ){ - releaseMemArray(&p->aMem[1], p->nMem); + releaseMemArray(p->aMem, p->nMem); } while( p->pDelFrame ){ VdbeFrame *pDel = p->pDelFrame; @@ -2074,7 +2075,7 @@ static void Cleanup(Vdbe *p){ int i; if( p->apCsr ) for(i=0; inCursor; i++) assert( p->apCsr[i]==0 ); if( p->aMem ){ - for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined ); + for(i=0; inMem; i++) assert( p->aMem[i].flags==MEM_Undefined ); } #endif diff --git a/src/vdbemem.c b/src/vdbemem.c index b5139fe32e..2c03baf562 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -761,7 +761,7 @@ int sqlite3VdbeMemTooBig(Mem *p){ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ int i; Mem *pX; - for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){ + for(i=0, pX=pVdbe->aMem; inMem; i++, pX++){ if( pX->pScopyFrom==pMem ){ pX->flags |= MEM_Undefined; pX->pScopyFrom = 0; From 3cdce92c3863567d49f149f6b736c4987acf5fec Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 21 Mar 2016 00:30:40 +0000 Subject: [PATCH 504/570] Remove an unreachable branch. Improvements to comments. FossilOrigin-Name: c5677ecd5cd2637d92a831ec6bd5b002f8d75626 --- manifest | 17 +++++++---------- manifest.uuid | 2 +- src/vdbe.c | 5 +++-- src/vdbeaux.c | 11 +++-------- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index dc84917b98..24f48cdd5b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sVdbe.aMem\sarray\sso\sthat\sit\sis\szero-based\sinstead\sof\sone-based. -D 2016-03-19T23:32:59.000 +C Remove\san\sunreachable\sbranch.\s\sImprovements\sto\scomments. +D 2016-03-21T00:30:40.611 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -417,11 +417,11 @@ F src/update.c 56b3db7edff0110360a12b76af97c39ebe3ea8b8 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 34ef7be420f82415ec48131404995ddb6ee7502f F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 -F src/vdbe.c 90d18d0a91284092a099e9a048982df38920190c +F src/vdbe.c 3b542ffd5b6aaab55255ec3801fc86dcbfaea543 F src/vdbe.h 6f44193e7be52fd5f7c308175a936555b1e6b101 F src/vdbeInt.h f88d3115e9bde33b01d81f0dd26d8dd51f995991 F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 -F src/vdbeaux.c 4a38b9f9dab7350f670b9efff25f605933f81963 +F src/vdbeaux.c c8dd3e4e932bede6363b380519d05c0557ad27ce F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c fe76c1f866de362d9b8332e59d74aa44f6560d69 F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062 @@ -1457,10 +1457,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 d7852c639683a1d305a1e731df3cccafa64b594b -R 4a4c5282463bb7b6f1f36414c3f19a6f -T *branch * zero-base-aMem -T *sym-zero-base-aMem * -T -sym-trunk * +P e07b0c47eb5a39623f5fe0e66b939bba0906691c +R 3918e948fd7d72bc109c3b7a0fa018f3 U drh -Z 5ba539d03a989ddc8c4359f1a3ede74d +Z ae546b517b9c79f405f4513ed17a526d diff --git a/manifest.uuid b/manifest.uuid index 24fae6a151..7cf8597f25 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e07b0c47eb5a39623f5fe0e66b939bba0906691c \ No newline at end of file +c5677ecd5cd2637d92a831ec6bd5b002f8d75626 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index bdab41b6b6..52747ce8ba 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -192,7 +192,7 @@ static VdbeCursor *allocateCursor( ** be freed lazily via the sqlite3_release_memory() API. This ** minimizes the number of malloc calls made by the system. ** - ** Memory cell for cursor 0 is Mem[0]. The rest are allocated from + ** The memory cell for cursor 0 is aMem[0]. The rest are allocated from ** the top of the register space. Cursor 1 is at Mem[p->nMem-1]. ** Cursor 2 is at Mem[p->nMem-2]. And so forth. */ @@ -5643,7 +5643,8 @@ case OP_Program: { /* jump */ ** variable nMem (and later, VdbeFrame.nChildMem) to this value. */ nMem = pProgram->nMem + pProgram->nCsr; - if( pProgram->nCsr==0 && nMem>0 ) nMem++; + assert( nMem>0 ); + if( pProgram->nCsr==0 ) nMem++; nByte = ROUND8(sizeof(VdbeFrame)) + nMem * sizeof(Mem) + pProgram->nCsr * sizeof(VdbeCursor *) diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 75307c258e..e651589ace 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1866,14 +1866,9 @@ void sqlite3VdbeMakeReady( nOnce = pParse->nOnce; if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */ - /* For each cursor required, also allocate a memory cell. Memory - ** cells 0 and (nMem-nCursor)..nMem-1 inclusive will never be used by - ** the vdbe program. Instead they are used to allocate memory for - ** VdbeCursor/BtCursor structures. The blob of memory associated with - ** cursor 0 is stored in memory cell 0. Memory cell (nMem-1) - ** stores the blob of memory associated with cursor 1. Memory cell - ** (nMem-iCur) is used for cursor iCur. - ** + /* Each cursor uses a memory cell. The first cursor (cursor 0) can + ** use aMem[0] which is not otherwise used by the VDBE program. Allocate + ** space at the end of aMem[] for cursors 1 and greater. ** See also: allocateCursor(). */ nMem += nCursor; From ef480d37dcc22f4da07d797341c96462f61f9e91 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 21 Mar 2016 09:56:19 +0000 Subject: [PATCH 505/570] Change the way fts5 internally allocates segment ids in order to eliminated non-determinism from the module. FossilOrigin-Name: d6e2637df16764aa9723a30ea2eb8a631d28cb2b --- ext/fts5/fts5_index.c | 39 +++++++++++++++++++++++++++--------- ext/fts5/tool/fts5txt2db.tcl | 5 +++-- manifest | 17 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 323e6cefdc..44fba94c84 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -3453,18 +3453,35 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){ if( pStruct->nSegment>=FTS5_MAX_SEGMENT ){ p->rc = SQLITE_FULL; }else{ - while( iSegid==0 ){ - int iLvl, iSeg; - sqlite3_randomness(sizeof(u32), (void*)&iSegid); - iSegid = iSegid & ((1 << FTS5_DATA_ID_B)-1); - for(iLvl=0; iLvlnLevel; iLvl++){ - for(iSeg=0; iSegaLevel[iLvl].nSeg; iSeg++){ - if( iSegid==pStruct->aLevel[iLvl].aSeg[iSeg].iSegid ){ - iSegid = 0; - } + /* FTS5_MAX_SEGMENT is currently defined as 2000. So the following + ** array is 63 elements, or 252 bytes, in size. */ + u32 aUsed[(FTS5_MAX_SEGMENT+31) / 32]; + int iLvl, iSeg; + int i; + u32 mask; + memset(aUsed, 0, sizeof(aUsed)); + for(iLvl=0; iLvlnLevel; iLvl++){ + for(iSeg=0; iSegaLevel[iLvl].nSeg; iSeg++){ + int iId = pStruct->aLevel[iLvl].aSeg[iSeg].iSegid; + if( iId<=FTS5_MAX_SEGMENT ){ + aUsed[(iId-1) / 32] |= 1 << ((iId-1) % 32); } } } + + for(i=0; aUsed[i]==0xFFFFFFFF; i++); + mask = aUsed[i]; + for(iSegid=0; mask & (1 << iSegid); iSegid++); + iSegid += 1 + i*32; + +#ifdef SQLITE_DEBUG + for(iLvl=0; iLvlnLevel; iLvl++){ + for(iSeg=0; iSegaLevel[iLvl].nSeg; iSeg++){ + assert( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid ); + } + } + assert( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT ); +#endif } } @@ -3909,7 +3926,9 @@ static void fts5WriteFinish( fts5WriteFlushLeaf(p, pWriter); } *pnLeaf = pLeaf->pgno-1; - fts5WriteFlushBtree(p, pWriter); + if( pLeaf->pgno>1 ){ + fts5WriteFlushBtree(p, pWriter); + } } fts5BufferFree(&pLeaf->term); fts5BufferFree(&pLeaf->buf); diff --git a/ext/fts5/tool/fts5txt2db.tcl b/ext/fts5/tool/fts5txt2db.tcl index d5df971d4d..4766b00b06 100644 --- a/ext/fts5/tool/fts5txt2db.tcl +++ b/ext/fts5/tool/fts5txt2db.tcl @@ -17,6 +17,7 @@ proc process_cmdline {} { {detail "full" "Fts5 detail mode to use"} {repeat 1 "Load each file this many times"} {prefix "" "Fts prefix= option"} + {trans 1 "True to use a transaction"} database file... } { @@ -214,7 +215,7 @@ foreach c [lrange $cols 1 end] { } append sql ")" -db eval BEGIN +if {$A(trans)} { db eval BEGIN } while {$i < $N} { foreach c $cols s $A(colsize) { set R($c) [lrange $tokens $i [expr $i+$s-1]] @@ -222,7 +223,7 @@ db eval BEGIN } db eval $sql } -db eval COMMIT +if {$A(trans)} { db eval COMMIT } diff --git a/manifest b/manifest index 0773bab205..b4be055c28 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sVdbe.aMem\sarray\sso\sthat\sit\sis\szero-based\sinstead\sof\sone-based. -D 2016-03-21T00:38:59.802 +C Change\sthe\sway\sfts5\sinternally\sallocates\ssegment\sids\sin\sorder\sto\seliminated\snon-determinism\sfrom\sthe\smodule. +D 2016-03-21T09:56:19.361 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 F ext/fts5/fts5_expr.c 35e9d92c89e7c7ea0759b73d24da1ecb7630a24b F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c d4f0c12e4f04bbc3a06b6da052039f2ce3e45438 +F ext/fts5/fts5_index.c d3759c2f7d878e9e0a392b027a1c6e05c356007d F ext/fts5/fts5_main.c b8501e1a6a11591c53b18ce7aea7e5386cfb0421 F ext/fts5/fts5_storage.c 2a38c6fa5db193a6a00588865134450ef5812daa F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -194,7 +194,7 @@ F ext/fts5/test/fts5update.test 57c7012a7919889048947addae10e0613df45529 F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e F ext/fts5/test/fts5vocab.test 480d780aa6b699816c5066225fbd86f3a0239477 F ext/fts5/tool/fts5speed.tcl b0056f91a55b2d1a3684ec05729de92b042e2f85 -F ext/fts5/tool/fts5txt2db.tcl 1343745b89ca2a1e975c23f836d0cee410052975 +F ext/fts5/tool/fts5txt2db.tcl 526a9979c963f1c54fd50976a05a502e533a4c59 F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093 F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45 F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c @@ -1457,8 +1457,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 d7852c639683a1d305a1e731df3cccafa64b594b c5677ecd5cd2637d92a831ec6bd5b002f8d75626 -R 3918e948fd7d72bc109c3b7a0fa018f3 -T +closed c5677ecd5cd2637d92a831ec6bd5b002f8d75626 -U drh -Z 542f0ebd1ebe0cc42b5001043dab2846 +P c39081e878faccc8552141afa5732a2bf2f77570 +R b7f851b6f7c0c6dc2d06642c2058dff4 +U dan +Z 052aba56922a1e224a7195cfbf595d27 diff --git a/manifest.uuid b/manifest.uuid index d4e8a322fa..775d397701 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c39081e878faccc8552141afa5732a2bf2f77570 \ No newline at end of file +d6e2637df16764aa9723a30ea2eb8a631d28cb2b \ No newline at end of file From 8d2f41ccd2945061d4e1d0e4bf82ef8937637c82 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 21 Mar 2016 11:38:01 +0000 Subject: [PATCH 506/570] Do a better job of capturing all system errno values regardless of when they occur. FossilOrigin-Name: 7d49998d571d841a6d1b55f5f9889e613daaab2a --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/main.c | 1 - src/util.c | 7 ++++++- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 23d5324bc8..535a69183e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\supdates\sfrom\strunk. -D 2016-03-21T10:49:49.647 +C Do\sa\sbetter\sjob\sof\scapturing\sall\ssystem\serrno\svalues\sregardless\sof\swhen\nthey\soccur. +D 2016-03-21T11:38:01.899 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -316,7 +316,7 @@ F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c 723d5d708cdb61bdd47c00b9f07c75be45aefc09 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c e70f8f9e97624a232870ea5486e682c813ac3002 -F src/main.c 74591e0405e5e71b276105ac5f8d419dd54e6495 +F src/main.c f6c6e61bfd4cc9306a737d0c5c3f1e0eaf6086e0 F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -415,7 +415,7 @@ F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c 56b3db7edff0110360a12b76af97c39ebe3ea8b8 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c -F src/util.c c3fc5193e6f039fa61afbcc0db87d5a5d563a18a +F src/util.c 161266913716ec2b35cf477239d3bdf1e2038305 F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c 3b542ffd5b6aaab55255ec3801fc86dcbfaea543 F src/vdbe.h 6f44193e7be52fd5f7c308175a936555b1e6b101 @@ -1457,7 +1457,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 1602f6b53698bd3a1a4be218c2e3145dd895f1f1 d6e2637df16764aa9723a30ea2eb8a631d28cb2b -R 612a3877b08babb8ce38fd27cb203dde +P 86ab8643969bd2e51a257d80da9316c668437f7b +R 79a2efa83ad9e99707ee54a3ce3858c7 U drh -Z a4bea0f6db7341ce1f534f224a30953a +Z deb9ef153d45658bc99716f0bcf98cb3 diff --git a/manifest.uuid b/manifest.uuid index a54112ab69..9ddd083acd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -86ab8643969bd2e51a257d80da9316c668437f7b \ No newline at end of file +7d49998d571d841a6d1b55f5f9889e613daaab2a \ No newline at end of file diff --git a/src/main.c b/src/main.c index e4d5cb494c..2e5ba08393 100644 --- a/src/main.c +++ b/src/main.c @@ -2868,7 +2868,6 @@ static int openDatabase( if( rc==SQLITE_IOERR_NOMEM ){ rc = SQLITE_NOMEM_BKPT; } - sqlite3SystemError(db, rc); sqlite3Error(db, rc); goto opendb_out; } diff --git a/src/util.c b/src/util.c index 0a705a6a6e..b231342916 100644 --- a/src/util.c +++ b/src/util.c @@ -120,10 +120,14 @@ const char *sqlite3StrNext(const char *z){ /* ** Set the current error code to err_code and clear any prior error message. */ +static SQLITE_NOINLINE void sqlite3ErrorFinish(sqlite3 *db, int err_code){ + if( db->pErr ) sqlite3ValueSetNull(db->pErr); + sqlite3SystemError(db, err_code); +} void sqlite3Error(sqlite3 *db, int err_code){ assert( db!=0 ); db->errCode = err_code; - if( db->pErr ) sqlite3ValueSetNull(db->pErr); + if( err_code || db->pErr ) sqlite3ErrorFinish(db, err_code); } /* @@ -162,6 +166,7 @@ void sqlite3SystemError(sqlite3 *db, int rc){ void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *zFormat, ...){ assert( db!=0 ); db->errCode = err_code; + sqlite3SystemError(db, err_code); if( zFormat==0 ){ sqlite3Error(db, err_code); }else if( db->pErr || (db->pErr = sqlite3ValueNew(db))!=0 ){ From 80fbee092ed6f2316fde79caeda7ef5684c9f020 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 21 Mar 2016 11:57:13 +0000 Subject: [PATCH 507/570] Improved comments. No logical changes to code. FossilOrigin-Name: a6b6c6c466f3feb257b4fc08ef6b9a27a68ca073 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/util.c | 10 +++++++++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 535a69183e..9f56848d53 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\sa\sbetter\sjob\sof\scapturing\sall\ssystem\serrno\svalues\sregardless\sof\swhen\nthey\soccur. -D 2016-03-21T11:38:01.899 +C Improved\scomments.\s\sNo\slogical\schanges\sto\scode. +D 2016-03-21T11:57:13.971 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -415,7 +415,7 @@ F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c 56b3db7edff0110360a12b76af97c39ebe3ea8b8 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c -F src/util.c 161266913716ec2b35cf477239d3bdf1e2038305 +F src/util.c cf7dce85ab9af5280b8a45985df2591efbfefe56 F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c 3b542ffd5b6aaab55255ec3801fc86dcbfaea543 F src/vdbe.h 6f44193e7be52fd5f7c308175a936555b1e6b101 @@ -1457,7 +1457,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 86ab8643969bd2e51a257d80da9316c668437f7b -R 79a2efa83ad9e99707ee54a3ce3858c7 +P 7d49998d571d841a6d1b55f5f9889e613daaab2a +R 2f9bb272499f0485ddab735cd0415aba U drh -Z deb9ef153d45658bc99716f0bcf98cb3 +Z ece300b1b257b87eefa9cd94f35c2874 diff --git a/manifest.uuid b/manifest.uuid index 9ddd083acd..3f5f26ea7b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7d49998d571d841a6d1b55f5f9889e613daaab2a \ No newline at end of file +a6b6c6c466f3feb257b4fc08ef6b9a27a68ca073 \ No newline at end of file diff --git a/src/util.c b/src/util.c index b231342916..428dfd046c 100644 --- a/src/util.c +++ b/src/util.c @@ -118,12 +118,20 @@ const char *sqlite3StrNext(const char *z){ } /* -** Set the current error code to err_code and clear any prior error message. +** Helper function for sqlite3Error() - called rarely. Broken out into +** a separate routine to avoid unnecessary register saves on entry to +** sqlite3Error(). */ static SQLITE_NOINLINE void sqlite3ErrorFinish(sqlite3 *db, int err_code){ if( db->pErr ) sqlite3ValueSetNull(db->pErr); sqlite3SystemError(db, err_code); } + +/* +** Set the current error code to err_code and clear any prior error message. +** Also set iSysErrno (by calling sqlite3System) if the err_code indicates +** that would be appropriate. +*/ void sqlite3Error(sqlite3 *db, int err_code){ assert( db!=0 ); db->errCode = err_code; From f68521c4e69c64633b60d59477ab83b2872db034 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 21 Mar 2016 12:28:02 +0000 Subject: [PATCH 508/570] Make sure system errors that occur durign sqlite3_step() are captured for use by sqlite3_system_errno(). FossilOrigin-Name: b4a1114f730c62e93623f889bc0e4fd8d0b31efa --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 9f56848d53..97d82ae77a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\scomments.\s\sNo\slogical\schanges\sto\scode. -D 2016-03-21T11:57:13.971 +C Make\ssure\ssystem\serrors\sthat\soccur\sdurign\ssqlite3_step()\sare\scaptured\sfor\nuse\sby\ssqlite3_system_errno(). +D 2016-03-21T12:28:02.060 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -417,7 +417,7 @@ F src/update.c 56b3db7edff0110360a12b76af97c39ebe3ea8b8 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c cf7dce85ab9af5280b8a45985df2591efbfefe56 F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 -F src/vdbe.c 3b542ffd5b6aaab55255ec3801fc86dcbfaea543 +F src/vdbe.c f19741f2d8b33e8f09cd2219570b6c9ed924c3f1 F src/vdbe.h 6f44193e7be52fd5f7c308175a936555b1e6b101 F src/vdbeInt.h f88d3115e9bde33b01d81f0dd26d8dd51f995991 F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 @@ -1457,7 +1457,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 7d49998d571d841a6d1b55f5f9889e613daaab2a -R 2f9bb272499f0485ddab735cd0415aba +P a6b6c6c466f3feb257b4fc08ef6b9a27a68ca073 +R 6870e1f7d1e452978a882de2dd2b0506 U drh -Z ece300b1b257b87eefa9cd94f35c2874 +Z 3347e0ff1ad1a288a0d7114b0f195e81 diff --git a/manifest.uuid b/manifest.uuid index 3f5f26ea7b..c8872252d5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a6b6c6c466f3feb257b4fc08ef6b9a27a68ca073 \ No newline at end of file +b4a1114f730c62e93623f889bc0e4fd8d0b31efa \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 52747ce8ba..90269cbe30 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -6826,6 +6826,7 @@ abort_due_to_error: sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); } p->rc = rc; + sqlite3SystemError(db, rc); testcase( sqlite3GlobalConfig.xLog!=0 ); sqlite3_log(rc, "statement aborts at %d: [%s] %s", (int)(pOp - aOp), p->zSql, p->zErrMsg); From 3c6707f72b6efeaa7b3933fae427010a444914cb Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 21 Mar 2016 15:18:13 +0000 Subject: [PATCH 509/570] Rearrange code so that tests pass whether SQLITE_DEBUG is defined or not. FossilOrigin-Name: 89296a46c3b891ee0b637ff6f89d828d6e46e7b5 --- ext/fts5/fts5_index.c | 15 +++++++-------- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 3fb1458526..eb1d3c4b61 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -1019,17 +1019,14 @@ static i64 fts5IndexDataVersion(Fts5Index *p){ ** is called, it is a no-op. */ static Fts5Structure *fts5StructureRead(Fts5Index *p){ - Fts5Structure *pRet; /* Object to return */ if( p->pStruct==0 ){ p->iStructVersion = fts5IndexDataVersion(p); if( p->rc==SQLITE_OK ){ - p->pStruct = pRet = fts5StructureReadUncached(p); + p->pStruct = fts5StructureReadUncached(p); } - if( p->rc!=SQLITE_OK ) return 0; - assert( p->iStructVersion!=0 ); - assert( p->pStruct!=0 ); } + #ifdef SQLITE_DEBUG else{ Fts5Structure *pTest = fts5StructureReadUncached(p); @@ -1053,9 +1050,11 @@ static Fts5Structure *fts5StructureRead(Fts5Index *p){ } #endif - pRet = p->pStruct; - fts5StructureRef(pRet); - return pRet; + if( p->rc!=SQLITE_OK ) return 0; + assert( p->iStructVersion!=0 ); + assert( p->pStruct!=0 ); + fts5StructureRef(p->pStruct); + return p->pStruct; } static void fts5StructureInvalidate(Fts5Index *p){ diff --git a/manifest b/manifest index 346832e33f..65691a0210 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stest\sfile\sfts5multiclient.test. -D 2016-03-19T14:47:28.441 +C Rearrange\scode\sso\sthat\stests\spass\swhether\sSQLITE_DEBUG\sis\sdefined\sor\snot. +D 2016-03-21T15:18:13.028 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 F ext/fts5/fts5_expr.c 35e9d92c89e7c7ea0759b73d24da1ecb7630a24b F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c afac2ffe3198776626b99366e18af1f32ea9eb85 +F ext/fts5/fts5_index.c 39939320ee5185cbfd0a8c8c7e1c878ebde7c43d F ext/fts5/fts5_main.c b4a0fc5bf17f2f1f056ee76cdd7d2af08b360f55 F ext/fts5/fts5_storage.c a3361410422e69639ca2bcd5a56a0933dadf84d2 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -1457,7 +1457,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 020a0bda59fe93b9361ceeed0d5a8ba4177380c8 -R f14c9b8edfca8f7bf113e7bd0b21996b +P 7832466f9177cca59455ba272802145297fcd53d +R e2f3ffc019af1c2320d4d618c0233909 U dan -Z d493def8e880a32e2aca451bc5e776cf +Z 04b6e502bb8ccbe0b89bf7d08daf8ee8 diff --git a/manifest.uuid b/manifest.uuid index 91ed807a0b..62bde4070e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7832466f9177cca59455ba272802145297fcd53d \ No newline at end of file +89296a46c3b891ee0b637ff6f89d828d6e46e7b5 \ No newline at end of file From 6369bc3fbb0e561b0df0f10f9c9601218388074a Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 21 Mar 2016 16:06:42 +0000 Subject: [PATCH 510/570] Remove an unreachable branch from the unlink verification logic in the UNIX VFS. FossilOrigin-Name: 4dc30cce7fdb7dba9a9aad96bb8b499b965610b2 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/os_unix.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 5d26916c17..2357dbffd8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Have\sfts5\scache\sthe\sstructure\sof\sits\sindex\sin\smain\smemory.\sUse\s"PRAGMA\sdata_version"\sto\sfigure\sout\swhen\sthis\scache\sshould\sbe\sinvalidated. -D 2016-03-21T15:30:50.247 +C Remove\san\sunreachable\sbranch\sfrom\sthe\sunlink\sverification\slogic\sin\sthe\sUNIX\nVFS. +D 2016-03-21T16:06:42.310 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -336,7 +336,7 @@ F src/os.c ca10edb445ad2c5fdc7285b49d72bcdf261fa23e F src/os.h 91ff889115ecd01f436d3611f7f5ea4dc12d92f1 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c 50103f69121bca969761b821e2b0e393b55fe869 +F src/os_unix.c b1ccb273771f41dbdbe0ba7c1ad63c38ad5972ec F src/os_win.c 551d973ada67127430e41d9e514e53f6beb6c5a7 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 38718a019ca762ba4f6795425d5a54db70d1790d @@ -1458,7 +1458,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 4bd12b57ea177cfb1f44d54bfa7aedfb8a8c0c64 89296a46c3b891ee0b637ff6f89d828d6e46e7b5 -R 81b99f33bb0a77bc5e744352db10978f -U dan -Z db5fc495668353fb57116ffc2b5d2027 +P 902f221754f3cc6fb4ae049c135f85efce604ed3 +R 36c20d433515aed31fbc005a13e11c2d +U drh +Z 514dfe801f60757ebd0519594eb7ecde diff --git a/manifest.uuid b/manifest.uuid index fb9fd2a351..4d4fd3e0b6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -902f221754f3cc6fb4ae049c135f85efce604ed3 \ No newline at end of file +4dc30cce7fdb7dba9a9aad96bb8b499b965610b2 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index d593b952f5..6d1bb0b46d 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1366,7 +1366,7 @@ static void verifyDbFile(unixFile *pFile){ sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath); return; } - if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){ + if( buf.st_nlink==0 ){ sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath); return; } From 4567beefac9c044f9cb80f1c5c3ce1d565bb3c3f Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 21 Mar 2016 16:19:29 +0000 Subject: [PATCH 511/570] Skip recently added test cases in nolock.test when running in the inmemory_journal permutation. FossilOrigin-Name: a1dcf7af42bb7394d46138318f9367fe9e8be560 --- manifest | 12 +++++----- manifest.uuid | 2 +- test/nolock.test | 61 +++++++++++++++++++++++++----------------------- 3 files changed, 39 insertions(+), 36 deletions(-) diff --git a/manifest b/manifest index 2357dbffd8..78be64c56a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunreachable\sbranch\sfrom\sthe\sunlink\sverification\slogic\sin\sthe\sUNIX\nVFS. -D 2016-03-21T16:06:42.310 +C Skip\srecently\sadded\stest\scases\sin\snolock.test\swhen\srunning\sin\nthe\sinmemory_journal\spermutation. +D 2016-03-21T16:19:29.587 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -918,7 +918,7 @@ F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4 F test/mutex1.test ea2cc74d97f077b9e74c84cbd024f14d79a8126f F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 F test/nan.test dacc57f80859c06a433d30839336fe227d2038b3 -F test/nolock.test 96e922d2d3db71c2dd6557c98e8027a28277b415 +F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161 F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934 @@ -1458,7 +1458,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 902f221754f3cc6fb4ae049c135f85efce604ed3 -R 36c20d433515aed31fbc005a13e11c2d +P 4dc30cce7fdb7dba9a9aad96bb8b499b965610b2 +R 1f352d94053f76691b11c27a8d4a5d8f U drh -Z 514dfe801f60757ebd0519594eb7ecde +Z d3631fb4e80d910681e8351d2aa12531 diff --git a/manifest.uuid b/manifest.uuid index 4d4fd3e0b6..2c79e1a3ec 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4dc30cce7fdb7dba9a9aad96bb8b499b965610b2 \ No newline at end of file +a1dcf7af42bb7394d46138318f9367fe9e8be560 \ No newline at end of file diff --git a/test/nolock.test b/test/nolock.test index fdaef6ef07..e732dcf13b 100644 --- a/test/nolock.test +++ b/test/nolock.test @@ -183,35 +183,38 @@ db2 close db close tvfs delete -# 2016-03-11: Make sure all works when transitioning to WAL mode under nolock. -# -do_test nolock-4.1 { - forcedelete test.db - sqlite3 db file:test.db?nolock=1 -uri 1 - db eval { - PRAGMA journal_mode=WAL; - CREATE TABLE t1(x); - INSERT INTO t1 VALUES('youngling'); - SELECT * FROM t1; - } -} {delete youngling} -db close - -do_test nolock-4.2 { - forcedelete test.db - sqlite3 db test.db - db eval { - PRAGMA journal_mode=WAL; - CREATE TABLE t1(x); - INSERT INTO t1 VALUES('catbird'); - SELECT * FROM t1; - } -} {wal catbird} -do_test nolock-4.3 { +if {[permutation]!="inmemory_journal"} { + # 2016-03-11: Make sure all works when transitioning to WAL mode + # under nolock. + # + do_test nolock-4.1 { + forcedelete test.db + sqlite3 db file:test.db?nolock=1 -uri 1 + db eval { + PRAGMA journal_mode=WAL; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES('youngling'); + SELECT * FROM t1; + } + } {delete youngling} db close - sqlite3 db file:test.db?nolock=1 -uri 1 - set rc [catch {db eval {SELECT * FROM t1}} msg] - lappend rc $msg -} {1 {unable to open database file}} + + do_test nolock-4.2 { + forcedelete test.db + sqlite3 db test.db + db eval { + PRAGMA journal_mode=WAL; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES('catbird'); + SELECT * FROM t1; + } + } {wal catbird} + do_test nolock-4.3 { + db close + sqlite3 db file:test.db?nolock=1 -uri 1 + set rc [catch {db eval {SELECT * FROM t1}} msg] + lappend rc $msg + } {1 {unable to open database file}} +} finish_test From 6737aab5cfd17cfc7819e8fdd00463bbbff34aad Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 21 Mar 2016 16:25:34 +0000 Subject: [PATCH 512/570] Add tests to ensure that fts5 is now deterministic. FossilOrigin-Name: 3d076094ce411bffcfeb76c0284d15d0f83bd459 --- ext/fts5/test/fts5determin.test | 67 +++++++++++++++++++++++++++++++++ manifest | 13 ++++--- manifest.uuid | 2 +- 3 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 ext/fts5/test/fts5determin.test diff --git a/ext/fts5/test/fts5determin.test b/ext/fts5/test/fts5determin.test new file mode 100644 index 0000000000..e368c4704e --- /dev/null +++ b/ext/fts5/test/fts5determin.test @@ -0,0 +1,67 @@ +# 2016 March 21 +# +# 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. The +# focus of this script is testing the FTS5 module. +# +# Specifically, that the fts5 module is deterministic. At one point, when +# segment ids were allocated using sqlite3_randomness(), this was not the +# case. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5aa +return_if_no_fts5 + +proc do_determin_test {tn} { + uplevel [list + do_execsql_test $tn { + SELECT (SELECT md5sum(id, block) FROM t1_data)== + (SELECT md5sum(id, block) FROM t2_data), + (SELECT md5sum(id, block) FROM t1_data)== + (SELECT md5sum(id, block) FROM t3_data) + } {1 1} + ] +} + +foreach_detail_mode $::testprefix { + do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix="1 2", detail=%DETAIL%); + CREATE VIRTUAL TABLE t2 USING fts5(a, b, prefix="1 2", detail=%DETAIL%); + CREATE VIRTUAL TABLE t3 USING fts5(a, b, prefix="1 2", detail=%DETAIL%); + } + + do_test 1.1 { + foreach t {t1 t2 t3} { + execsql [string map [list TBL $t] { + INSERT INTO TBL VALUES('a b c', 'd e f'); + INSERT INTO TBL VALUES('c1 c2 c3', 'c1 c2 c3'); + INSERT INTO TBL VALUES('xyzxyzxyz', 'xyzxyzxyz'); + }] + } + } {} + + do_determin_test 1.2 + + do_test 1.3 { + foreach t {t1 t2 t3} { + execsql [string map [list TBL $t] { + INSERT INTO TBL(TBL) VALUES('optimize'); + }] + } + } {} + + do_determin_test 1.4 +} + + +finish_test + + diff --git a/manifest b/manifest index 78be64c56a..7fca6a827a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Skip\srecently\sadded\stest\scases\sin\snolock.test\swhen\srunning\sin\nthe\sinmemory_journal\spermutation. -D 2016-03-21T16:19:29.587 +C Add\stests\sto\sensure\sthat\sfts5\sis\snow\sdeterministic. +D 2016-03-21T16:25:34.085 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -143,6 +143,7 @@ F ext/fts5/test/fts5corrupt.test c2ad090192708150d50d961278df10ae7a4b8b62 F ext/fts5/test/fts5corrupt2.test 26c0a39dd9ff73207e6229f83b50b21d37c7658c F ext/fts5/test/fts5corrupt3.test f77f65e386231daf62902466b40ff998b2c8ce4f F ext/fts5/test/fts5detail.test ef5c690535a797413acaf5ad9b8ab5d49972df69 +F ext/fts5/test/fts5determin.test 10648edb75ef1e196b10978fd21a9be0c31e09c3 F ext/fts5/test/fts5dlidx.test 007e9390c94638760797dbec2990c97c3fa08dfe F ext/fts5/test/fts5doclist.test 8edb5b57e5f144030ed74ec00ef6fa4294fed79b F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0 @@ -1458,7 +1459,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 4dc30cce7fdb7dba9a9aad96bb8b499b965610b2 -R 1f352d94053f76691b11c27a8d4a5d8f -U drh -Z d3631fb4e80d910681e8351d2aa12531 +P a1dcf7af42bb7394d46138318f9367fe9e8be560 +R d12464ec7adc7a5a41759a981f3bde86 +U dan +Z 8af492a5f67a993085e11843c854eec0 diff --git a/manifest.uuid b/manifest.uuid index 2c79e1a3ec..eacdf09ef0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a1dcf7af42bb7394d46138318f9367fe9e8be560 \ No newline at end of file +3d076094ce411bffcfeb76c0284d15d0f83bd459 \ No newline at end of file From 13969f5af0583fc3d661297d2d90ae4a0ef11103 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 21 Mar 2016 22:28:51 +0000 Subject: [PATCH 513/570] Fix harmless compiler warnings. FossilOrigin-Name: 25d776e4523aefeec007943fe29aa17c23ccb301 --- ext/fts5/fts5_index.c | 2 +- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/memjournal.c | 2 +- src/sqliteInt.h | 8 ++++++-- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 2e8349d51c..f0751bd655 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -4603,7 +4603,7 @@ static Fts5Structure *fts5IndexOptimizeStruct( if( pNew ){ Fts5StructureLevel *pLvl; - int nByte = nSeg * sizeof(Fts5StructureSegment); + nByte = nSeg * sizeof(Fts5StructureSegment); pNew->nLevel = pStruct->nLevel+1; pNew->nRef = 1; pNew->nWriteCounter = pStruct->nWriteCounter; diff --git a/manifest b/manifest index 7fca6a827a..8624bb132c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sto\sensure\sthat\sfts5\sis\snow\sdeterministic. -D 2016-03-21T16:25:34.085 +C Fix\sharmless\scompiler\swarnings. +D 2016-03-21T22:28:51.426 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 F ext/fts5/fts5_expr.c 35e9d92c89e7c7ea0759b73d24da1ecb7630a24b F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c 40fde2538deeb7f018435c1d1bacf057f89c3c42 +F ext/fts5/fts5_index.c 0fe734b1e2574fdbcfad4d71f861b8598dd7f91b F ext/fts5/fts5_main.c b4a0fc5bf17f2f1f056ee76cdd7d2af08b360f55 F ext/fts5/fts5_storage.c 98e3129047d250fc5acc4a4ba7ba4fde9b0ae030 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -325,7 +325,7 @@ F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memjournal.c 6423a0817ffd8c7a04ef9e5fb974b6b9dd71f8b6 +F src/memjournal.c 5253fd4335a8d9c64e5df25cb9da6329af5242c7 F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 @@ -358,7 +358,7 @@ F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in e877f141b15ef68ef28f84714e69d7234f9a071e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 -F src/sqliteInt.h 4eb80a9b9a512180a9739f99d754915e03d8091a +F src/sqliteInt.h 47847a919790e2a30bb1dfb89ba0dc59fc6ed0be F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1459,7 +1459,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 a1dcf7af42bb7394d46138318f9367fe9e8be560 -R d12464ec7adc7a5a41759a981f3bde86 -U dan -Z 8af492a5f67a993085e11843c854eec0 +P 3d076094ce411bffcfeb76c0284d15d0f83bd459 +R 8b7871914efe43742b6c5e5d156225cc +U drh +Z 74feddb89c21c363d080129c819f5a2b diff --git a/manifest.uuid b/manifest.uuid index eacdf09ef0..adb1b4e66e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3d076094ce411bffcfeb76c0284d15d0f83bd459 \ No newline at end of file +25d776e4523aefeec007943fe29aa17c23ccb301 \ No newline at end of file diff --git a/src/memjournal.c b/src/memjournal.c index b81682de85..4f0efc174e 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -403,5 +403,5 @@ int sqlite3JournalIsInMemory(sqlite3_file *p){ ** pVfs to create the underlying on-disk files. */ int sqlite3JournalSize(sqlite3_vfs *pVfs){ - return MAX(pVfs->szOsFile, sizeof(MemJournal)); + return MAX(pVfs->szOsFile, (int)sizeof(MemJournal)); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index fc36d8d091..858f737356 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -583,8 +583,12 @@ /* ** Macros to compute minimum and maximum of two numbers. */ -#define MIN(A,B) ((A)<(B)?(A):(B)) -#define MAX(A,B) ((A)>(B)?(A):(B)) +#ifndef MIN +# define MIN(A,B) ((A)<(B)?(A):(B)) +#endif +#ifndef MAX +# define MAX(A,B) ((A)>(B)?(A):(B)) +#endif /* ** Swap two objects of type TYPE. From 0b98207c5b7ef2ac85cc06e4971a5393c4cffd57 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 22 Mar 2016 14:10:45 +0000 Subject: [PATCH 514/570] Avoid the possibility of integer overflow on a pointer comparison test for corruption in the database file. FossilOrigin-Name: ff1b1ac3313ba9d70414e928ef3dd82913298a1a --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 9 +++++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 8624bb132c..d6d21ac7ef 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarnings. -D 2016-03-21T22:28:51.426 +C Avoid\sthe\spossibility\sof\sinteger\soverflow\son\sa\spointer\scomparison\stest\sfor\ncorruption\sin\sthe\sdatabase\sfile. +D 2016-03-22T14:10:45.052 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -297,7 +297,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 6eee126fe9d1f57118de9be2be840a4c6e691828 +F src/btree.c 5753da53071b5d5a8ace8fd9ea7a54cefeb8187b F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 213cbf84e99dd834e6ea46615633656d7ef79321 @@ -1459,7 +1459,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 3d076094ce411bffcfeb76c0284d15d0f83bd459 -R 8b7871914efe43742b6c5e5d156225cc +P 25d776e4523aefeec007943fe29aa17c23ccb301 +R 7b06b50bff5ae9500629c34b0d5509bb U drh -Z 74feddb89c21c363d080129c819f5a2b +Z 3c0767287744fc9671f0ea1849fc5941 diff --git a/manifest.uuid b/manifest.uuid index adb1b4e66e..bf5169d0f4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -25d776e4523aefeec007943fe29aa17c23ccb301 \ No newline at end of file +ff1b1ac3313ba9d70414e928ef3dd82913298a1a \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 18e6be9f38..3e29f8469d 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4472,8 +4472,13 @@ static int accessPayload( #endif assert( offset+amt <= pCur->info.nPayload ); - if( &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] ){ - /* Trying to read or write past the end of the data is an error */ + assert( aPayload > pPage->aData ); + if( (aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){ + /* Trying to read or write past the end of the data is an error. The + ** conditional above is really: + ** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] + ** but is recast into its current form to avoid integer overflow problems + */ return SQLITE_CORRUPT_BKPT; } From 3bfa7e82b618fea9904cb5c36bff3b9bf311bab9 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 22 Mar 2016 14:37:59 +0000 Subject: [PATCH 515/570] Create the "uptr" typedef (the same as uintptr_t when available) and use it to cast pointers before comparison. FossilOrigin-Name: 2484cc0c3ffc8834a155f89af1581bd07d453a90 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/btree.c | 4 ++-- src/sqliteInt.h | 36 +++++++++++++++++++++--------------- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index d6d21ac7ef..6c9eb30c1e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\sthe\spossibility\sof\sinteger\soverflow\son\sa\spointer\scomparison\stest\sfor\ncorruption\sin\sthe\sdatabase\sfile. -D 2016-03-22T14:10:45.052 +C Create\sthe\s"uptr"\stypedef\s(the\ssame\sas\suintptr_t\swhen\savailable)\sand\suse\sit\nto\scast\spointers\sbefore\scomparison. +D 2016-03-22T14:37:59.457 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -297,7 +297,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 5753da53071b5d5a8ace8fd9ea7a54cefeb8187b +F src/btree.c 8a02b1fb98eb11b9ce50cb3ab6a031f852b69303 F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 213cbf84e99dd834e6ea46615633656d7ef79321 @@ -358,7 +358,7 @@ F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in e877f141b15ef68ef28f84714e69d7234f9a071e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 -F src/sqliteInt.h 47847a919790e2a30bb1dfb89ba0dc59fc6ed0be +F src/sqliteInt.h cb02015eac6d642bd23d8cbd76cc116635c17540 F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1459,7 +1459,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 25d776e4523aefeec007943fe29aa17c23ccb301 -R 7b06b50bff5ae9500629c34b0d5509bb +P ff1b1ac3313ba9d70414e928ef3dd82913298a1a +R db2868426a9aae9f4cc9b8c065b04b6c U drh -Z 3c0767287744fc9671f0ea1849fc5941 +Z 0cd59c36c28d6740a5e8b1f16f08075a diff --git a/manifest.uuid b/manifest.uuid index bf5169d0f4..b4fc72f392 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ff1b1ac3313ba9d70414e928ef3dd82913298a1a \ No newline at end of file +2484cc0c3ffc8834a155f89af1581bd07d453a90 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 3e29f8469d..1a82176f18 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2360,12 +2360,12 @@ int sqlite3BtreeOpen( for(i=0; inDb; i++){ if( (pSib = db->aDb[i].pBt)!=0 && pSib->sharable ){ while( pSib->pPrev ){ pSib = pSib->pPrev; } - if( p->pBtpBt ){ + if( (uptr)p->pBt<(uptr)pSib->pBt ){ p->pNext = pSib; p->pPrev = 0; pSib->pPrev = p; }else{ - while( pSib->pNext && pSib->pNext->pBtpBt ){ + while( pSib->pNext && (uptr)pSib->pNext->pBt<(uptr)p->pBt ){ pSib = pSib->pNext; } p->pNext = pSib->pNext; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 858f737356..d256262b05 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -181,21 +181,6 @@ # define SQLITE_PTR_TO_INT(X) ((int)(X)) #endif -/* -** The SQLITE_WITHIN(P,S,E) macro checks to see if pointer P points to -** something between S (inclusive) and E (exclusive). -** -** In other words, S is a buffer and E is a pointer to the first byte after -** the end of buffer S. This macro returns true if P points to something -** contained within the buffer S. -*/ -#if defined(HAVE_STDINT_H) -# define SQLITE_WITHIN(P,S,E) \ - ((uintptr_t)(P)>=(uintptr_t)(S) && (uintptr_t)(P)<(uintptr_t)(E)) -#else -# define SQLITE_WITHIN(P,S,E) ((P)>=(S) && (P)<(E)) -#endif - /* ** A macro to hint to the compiler that a function should not be ** inlined. @@ -717,6 +702,27 @@ typedef INT16_TYPE LogEst; # endif #endif +/* The uptr type is an unsigned integer large enough to hold a pointer +*/ +#if defined(HAVE_STDINT_H) + typedef uintptr_t uptr; +#elif SQLITE_PTRSIZE==4 + typedef u32 uptr; +#else + typedef u64 uptr; +#endif + +/* +** The SQLITE_WITHIN(P,S,E) macro checks to see if pointer P points to +** something between S (inclusive) and E (exclusive). +** +** In other words, S is a buffer and E is a pointer to the first byte after +** the end of buffer S. This macro returns true if P points to something +** contained within the buffer S. +*/ +#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E))) + + /* ** Macros to determine whether the machine is big or little endian, ** and whether or not that determination is run-time or compile-time. From 0a2f2b546a1615c257351a872cda726f5d56a075 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 22 Mar 2016 15:01:54 +0000 Subject: [PATCH 516/570] Fix some errors in fts5 test scripts. FossilOrigin-Name: e1ab2d376a72786098125a41c1ea8140fcbd15c6 --- ext/fts5/fts5_index.c | 2 +- ext/fts5/test/fts5aa.test | 9 ++++++++- ext/fts5/test/fts5fault4.test | 2 +- ext/fts5/test/fts5simple.test | 6 +++--- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- 6 files changed, 24 insertions(+), 17 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index f0751bd655..d08e65bfe6 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -1027,7 +1027,7 @@ static Fts5Structure *fts5StructureRead(Fts5Index *p){ } } -#ifdef SQLITE_DEBUG +#if 0 else{ Fts5Structure *pTest = fts5StructureReadUncached(p); if( pTest ){ diff --git a/ext/fts5/test/fts5aa.test b/ext/fts5/test/fts5aa.test index fdcf08398d..428ca6c1ea 100644 --- a/ext/fts5/test/fts5aa.test +++ b/ext/fts5/test/fts5aa.test @@ -432,9 +432,16 @@ proc funk {} { } db func funk funk +# This test case corrupts the structure record within the first invocation +# of function funk(). Which used to cause the bm25() function to throw an +# exception. But since bm25() can now used the cached structure record, +# it never sees the corruption introduced by funk() and so the following +# statement no longer fails. +# do_catchsql_test 16.2 { SELECT funk(), bm25(n1), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d' -} {1 {SQL logic error or missing database}} +} {0 {{} -1e-06 {}}} +# {1 {SQL logic error or missing database}} #------------------------------------------------------------------------- # diff --git a/ext/fts5/test/fts5fault4.test b/ext/fts5/test/fts5fault4.test index acc43ebfc6..bfa54a5b04 100644 --- a/ext/fts5/test/fts5fault4.test +++ b/ext/fts5/test/fts5fault4.test @@ -86,7 +86,7 @@ set ::res [db eval {SELECT rowid, x1 FROM x1 WHERE x1 MATCH '*reads'}] do_faultsim_test 4 -faults oom-* -body { db eval {SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'} } -test { - faultsim_test_result {0 {0 {} 4}} + faultsim_test_result {0 {0 {} 3}} } #------------------------------------------------------------------------- diff --git a/ext/fts5/test/fts5simple.test b/ext/fts5/test/fts5simple.test index 464b601548..3483e40ba5 100644 --- a/ext/fts5/test/fts5simple.test +++ b/ext/fts5/test/fts5simple.test @@ -340,7 +340,7 @@ do_test 14.2 { #------------------------------------------------------------------------- db func rnddoc fts5_rnddoc -do_execsql_test 4.0 { +do_execsql_test 14.3 { CREATE VIRTUAL TABLE x1 USING fts5(x); INSERT INTO x1(x1, rank) VALUES('pgsz', 32); @@ -348,9 +348,9 @@ do_execsql_test 4.0 { INSERT INTO x1 SELECT rnddoc(5) FROM ii; } -do_execsql_test 4.1 { +do_execsql_test 14.4 { SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads' -} {0 {} 4} +} {0 {} 3} #------------------------------------------------------------------------- reset_db diff --git a/manifest b/manifest index 6c9eb30c1e..358587aaa3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Create\sthe\s"uptr"\stypedef\s(the\ssame\sas\suintptr_t\swhen\savailable)\sand\suse\sit\nto\scast\spointers\sbefore\scomparison. -D 2016-03-22T14:37:59.457 +C Fix\ssome\serrors\sin\sfts5\stest\sscripts. +D 2016-03-22T15:01:54.312 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 F ext/fts5/fts5_expr.c 35e9d92c89e7c7ea0759b73d24da1ecb7630a24b F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c 0fe734b1e2574fdbcfad4d71f861b8598dd7f91b +F ext/fts5/fts5_index.c 19df86d29d24cc56bfb01a6a07dcaac227d2fcdf F ext/fts5/fts5_main.c b4a0fc5bf17f2f1f056ee76cdd7d2af08b360f55 F ext/fts5/fts5_storage.c 98e3129047d250fc5acc4a4ba7ba4fde9b0ae030 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -117,7 +117,7 @@ F ext/fts5/fts5_vocab.c dba72ca393d71c2588548b51380387f6b44c77a8 F ext/fts5/fts5parse.y fcc5e92e570d38cab38488b2109cbf67468923b2 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841 -F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 +F ext/fts5/test/fts5aa.test bd2d88182b9f7f30d300044048ad14683306b745 F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b F ext/fts5/test/fts5ac.test 55cad4275a1f5acabfe14d8442a8046b47e49e5f F ext/fts5/test/fts5ad.test 36995f0586f30f5602074e012b9224c71ec5171c @@ -151,7 +151,7 @@ F ext/fts5/test/fts5eb.test c516ae0c934be6fd29ec95ea8b5f11f461311535 F ext/fts5/test/fts5fault1.test e09040d3e17b8c0837101e8c79c8a874c4376fb7 F ext/fts5/test/fts5fault2.test d8c6c7f916ccbdfc10b2c69530e9dd3bc8313232 F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3 -F ext/fts5/test/fts5fault4.test 532b6dacb963016cbf7003196bd87fb366540277 +F ext/fts5/test/fts5fault4.test dcbe3043c5611edd350191ea03a8daa190f0de5a F ext/fts5/test/fts5fault5.test 10c13a783de3f42a21e3e53e123b62ed0c3a1618 F ext/fts5/test/fts5fault6.test 9682664d679643ac6736e90c225526cc84073cda F ext/fts5/test/fts5fault7.test cb14ea3c1f42394f06f2284abc58eecee6ff8080 @@ -180,7 +180,7 @@ F ext/fts5/test/fts5rank.test 7e9e64eac7245637f6f2033aec4b292aaf611aab F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17 F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6 -F ext/fts5/test/fts5simple.test ac5006cc3d0d08b3538e1e76c7300de9f24fbed1 +F ext/fts5/test/fts5simple.test 5b7b05bcc89bcb718a0fc7f473092d3513cc8e19 F ext/fts5/test/fts5simple2.test 98377ae1ff7749a42c21fe1a139c1ed312522c46 F ext/fts5/test/fts5simple3.test 8e71733b3d1b0e695011d02c68ebc5ca40b6124e F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48 @@ -1459,7 +1459,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 ff1b1ac3313ba9d70414e928ef3dd82913298a1a -R db2868426a9aae9f4cc9b8c065b04b6c -U drh -Z 0cd59c36c28d6740a5e8b1f16f08075a +P 2484cc0c3ffc8834a155f89af1581bd07d453a90 +R ab98ce57ff7e19fbcedd913d7355f5be +U dan +Z e1d6ab80a5a2193f9db22bd77af06553 diff --git a/manifest.uuid b/manifest.uuid index b4fc72f392..43213d63e1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2484cc0c3ffc8834a155f89af1581bd07d453a90 \ No newline at end of file +e1ab2d376a72786098125a41c1ea8140fcbd15c6 \ No newline at end of file From c5e7f94494a27bc13b5f62584101166e91ebdcf4 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 22 Mar 2016 15:25:16 +0000 Subject: [PATCH 517/570] Fix a harmless compiler warning. FossilOrigin-Name: 5ace870d3ac3e9eb29cb4602c9036873adbcb99d --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/btree.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 358587aaa3..1fb0bc726f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\serrors\sin\sfts5\stest\sscripts. -D 2016-03-22T15:01:54.312 +C Fix\sa\sharmless\scompiler\swarning. +D 2016-03-22T15:25:16.949 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -297,7 +297,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 8a02b1fb98eb11b9ce50cb3ab6a031f852b69303 +F src/btree.c 577fb5674e2f0aa0a38246afc19e1885a0b8c9b0 F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 213cbf84e99dd834e6ea46615633656d7ef79321 @@ -1459,7 +1459,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 2484cc0c3ffc8834a155f89af1581bd07d453a90 -R ab98ce57ff7e19fbcedd913d7355f5be -U dan -Z e1d6ab80a5a2193f9db22bd77af06553 +P e1ab2d376a72786098125a41c1ea8140fcbd15c6 +R bdaff546f18a9832fa859fa7ed0eb2c5 +U drh +Z e5f40ebb5a86d8be765f1d7f6d3191da diff --git a/manifest.uuid b/manifest.uuid index 43213d63e1..a62797cd9e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e1ab2d376a72786098125a41c1ea8140fcbd15c6 \ No newline at end of file +5ace870d3ac3e9eb29cb4602c9036873adbcb99d \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 1a82176f18..bf99597095 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4473,7 +4473,7 @@ static int accessPayload( assert( offset+amt <= pCur->info.nPayload ); assert( aPayload > pPage->aData ); - if( (aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){ + if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){ /* Trying to read or write past the end of the data is an error. The ** conditional above is really: ** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] From 527b0435fabe2795865d52e4db827173a1cb2d65 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Tue, 22 Mar 2016 15:26:03 +0000 Subject: [PATCH 518/570] Fix harmless compiler warning for MSVC. FossilOrigin-Name: 142cd359d37f1d8d53de32e329523d9a93c7d6e5 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/os_win.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 1fb0bc726f..8de110620f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sharmless\scompiler\swarning. -D 2016-03-22T15:25:16.949 +C Fix\sharmless\scompiler\swarning\sfor\sMSVC. +D 2016-03-22T15:26:03.280 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -338,7 +338,7 @@ F src/os.h 91ff889115ecd01f436d3611f7f5ea4dc12d92f1 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c b1ccb273771f41dbdbe0ba7c1ad63c38ad5972ec -F src/os_win.c 551d973ada67127430e41d9e514e53f6beb6c5a7 +F src/os_win.c 17493f12b0b023c2d5a349b6860009f0d45e08d6 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 38718a019ca762ba4f6795425d5a54db70d1790d F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 @@ -1459,7 +1459,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 e1ab2d376a72786098125a41c1ea8140fcbd15c6 -R bdaff546f18a9832fa859fa7ed0eb2c5 -U drh -Z e5f40ebb5a86d8be765f1d7f6d3191da +P 5ace870d3ac3e9eb29cb4602c9036873adbcb99d +R 005c1e5cbc7587970df3ccd3cc730064 +U mistachkin +Z 4de36823f78a549c0eee8008ed054760 diff --git a/manifest.uuid b/manifest.uuid index a62797cd9e..7b06c9c521 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5ace870d3ac3e9eb29cb4602c9036873adbcb99d \ No newline at end of file +142cd359d37f1d8d53de32e329523d9a93c7d6e5 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index fd95c00e3a..3f9fefcac4 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -5425,7 +5425,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ UNUSED_PARAMETER(pVfs); memset(zBuf, 0, nBuf); #if defined(_MSC_VER) && _MSC_VER>=1400 - rand_s((int*)zBuf); /* rand_s() is not available with MinGW */ + rand_s((unsigned int*)zBuf); /* rand_s() is not available with MinGW */ #endif /* defined(_MSC_VER) && _MSC_VER>=1400 */ e.a = (unsigned char*)zBuf; e.na = nBuf; From d7564865adc966c21fcdc10ea5ee5bb5910c46da Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 22 Mar 2016 20:05:09 +0000 Subject: [PATCH 519/570] The sqlite3_column_decltype() routine should return NULL, not an empty string, if the column has no declared type. FossilOrigin-Name: 605eba4a756e7185119088e2242f82691d078b01 --- manifest | 26 +++++++++++++------------- manifest.uuid | 2 +- src/build.c | 15 ++++++++------- src/main.c | 3 +-- src/pragma.c | 6 ++---- src/select.c | 4 ++-- src/sqliteInt.h | 3 ++- src/util.c | 12 ++++++++---- src/vtab.c | 20 +++++++------------- 9 files changed, 44 insertions(+), 47 deletions(-) diff --git a/manifest b/manifest index 8de110620f..19c00ee626 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarning\sfor\sMSVC. -D 2016-03-22T15:26:03.280 +C The\ssqlite3_column_decltype()\sroutine\sshould\sreturn\sNULL,\snot\san\sempty\sstring,\nif\sthe\scolumn\shas\sno\sdeclared\stype. +D 2016-03-22T20:05:09.546 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -300,7 +300,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 577fb5674e2f0aa0a38246afc19e1885a0b8c9b0 F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 213cbf84e99dd834e6ea46615633656d7ef79321 +F src/build.c 7d1a5e64fcd10110edc8ce9ffb710d06af0a59f5 F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -318,7 +318,7 @@ F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c 723d5d708cdb61bdd47c00b9f07c75be45aefc09 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c e70f8f9e97624a232870ea5486e682c813ac3002 -F src/main.c f6c6e61bfd4cc9306a737d0c5c3f1e0eaf6086e0 +F src/main.c 63791c66321f07b5828bb9161b477d5e0b511d7e F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -346,19 +346,19 @@ F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c c40cdb93586e21b5dd826b5e671240bd91c26b05 -F src/pragma.c e7e8f380efec6075a722822306435afc1eeca88a +F src/pragma.c faf42922bb7ab2f6672cb550356c1967abae3c84 F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e -F src/select.c 6dd2097bb158efe3b8d68683dcc3b4a49e907a34 +F src/select.c 7849cee0a01952a9c93cd28989daedfa57731143 F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in e877f141b15ef68ef28f84714e69d7234f9a071e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 -F src/sqliteInt.h cb02015eac6d642bd23d8cbd76cc116635c17540 +F src/sqliteInt.h 3a68b48967a7d62fcb38572d27fd21ab4e4bcca3 F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -417,7 +417,7 @@ F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/update.c 56b3db7edff0110360a12b76af97c39ebe3ea8b8 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c -F src/util.c cf7dce85ab9af5280b8a45985df2591efbfefe56 +F src/util.c 8873d696c9ccc4206058c402e09e101f1b81561a F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 F src/vdbe.c f19741f2d8b33e8f09cd2219570b6c9ed924c3f1 F src/vdbe.h 6f44193e7be52fd5f7c308175a936555b1e6b101 @@ -428,7 +428,7 @@ F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbemem.c fe76c1f866de362d9b8332e59d74aa44f6560d69 F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062 F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 -F src/vtab.c fd69fd398e23e57ea4ea377d8a44b6998fc569c7 +F src/vtab.c 23b6cdfa996152d43b390504ed4a942c8caf3a00 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c @@ -1459,7 +1459,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 5ace870d3ac3e9eb29cb4602c9036873adbcb99d -R 005c1e5cbc7587970df3ccd3cc730064 -U mistachkin -Z 4de36823f78a549c0eee8008ed054760 +P 142cd359d37f1d8d53de32e329523d9a93c7d6e5 +R 54bb94e9ede3ebe9fafd5624cdd5946f +U drh +Z 8ae8a72878a637ee00e9de9bf1db9104 diff --git a/manifest.uuid b/manifest.uuid index 7b06c9c521..43fdf15940 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -142cd359d37f1d8d53de32e329523d9a93c7d6e5 \ No newline at end of file +605eba4a756e7185119088e2242f82691d078b01 \ No newline at end of file diff --git a/src/build.c b/src/build.c index e89c744461..28eb55ab6c 100644 --- a/src/build.c +++ b/src/build.c @@ -1087,6 +1087,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ pCol->szEst = 1; }else{ pCol->affinity = sqlite3AffinityType(zType, &pCol->szEst); + pCol->colFlags |= COLFLAG_HASTYPE; } p->nCol++; pParse->constraintName.n = 0; @@ -1282,7 +1283,7 @@ void sqlite3AddPrimaryKey( int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */ ){ Table *pTab = pParse->pNewTable; - const char *zName = 0; + Column *pCol = 0; int iCol = -1, i; int nTerm; if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit; @@ -1294,8 +1295,8 @@ void sqlite3AddPrimaryKey( pTab->tabFlags |= TF_HasPrimaryKey; if( pList==0 ){ iCol = pTab->nCol - 1; - pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; - zName = pTab->aCol[iCol].zName; + pCol = &pTab->aCol[iCol]; + pCol->colFlags |= COLFLAG_PRIMKEY; nTerm = 1; }else{ nTerm = pList->nExpr; @@ -1307,8 +1308,8 @@ void sqlite3AddPrimaryKey( const char *zCName = pCExpr->u.zToken; for(iCol=0; iColnCol; iCol++){ if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){ - pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; - zName = pTab->aCol[iCol].zName; + pCol = &pTab->aCol[iCol]; + pCol->colFlags |= COLFLAG_PRIMKEY; break; } } @@ -1316,8 +1317,8 @@ void sqlite3AddPrimaryKey( } } if( nTerm==1 - && zName - && sqlite3StrICmp(sqlite3StrNext(zName), "INTEGER")==0 + && pCol + && sqlite3StrICmp(sqlite3ColumnType(pCol,""), "INTEGER")==0 && sortOrder!=SQLITE_SO_DESC ){ pTab->iPKey = iCol; diff --git a/src/main.c b/src/main.c index 2e5ba08393..0c4cfbbea0 100644 --- a/src/main.c +++ b/src/main.c @@ -3343,8 +3343,7 @@ int sqlite3_table_column_metadata( ** explicitly declared column. Copy meta information from *pCol. */ if( pCol ){ - zDataType = sqlite3StrNext(pCol->zName); - if( zDataType[0]==0 ) zDataType = 0; + zDataType = sqlite3ColumnType(pCol,0); zCollSeq = pCol->zColl; notnull = pCol->notNull!=0; primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0; diff --git a/src/pragma.c b/src/pragma.c index 65c43ad1e5..e0a0255ec0 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1066,7 +1066,6 @@ void sqlite3Pragma( setAllColumnNames(v, 6, azCol); assert( 6==ArraySize(azCol) ); sqlite3ViewGetColumnNames(pParse, pTab); for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ - const char *zName; if( IsHiddenColumn(pCol) ){ nHidden++; continue; @@ -1079,11 +1078,10 @@ void sqlite3Pragma( for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} } assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN ); - zName = pCol->zName; sqlite3VdbeMultiLoad(v, 1, "issisi", i-nHidden, - zName, - sqlite3StrNext(zName), + pCol->zName, + sqlite3ColumnType(pCol,""), pCol->notNull ? 1 : 0, pCol->pDflt ? pCol->pDflt->u.zToken : 0, k); diff --git a/src/select.c b/src/select.c index a62581efc1..ed76f621f9 100644 --- a/src/select.c +++ b/src/select.c @@ -1430,7 +1430,7 @@ static const char *columnTypeImpl( zOrigCol = "rowid"; }else{ zOrigCol = pTab->aCol[iCol].zName; - zType = sqlite3StrNext(zOrigCol); + zType = sqlite3ColumnType(&pTab->aCol[iCol],0); estWidth = pTab->aCol[iCol].szEst; } zOrigTab = pTab->zName; @@ -1442,7 +1442,7 @@ static const char *columnTypeImpl( if( iCol<0 ){ zType = "INTEGER"; }else{ - zType = sqlite3StrNext(pTab->aCol[iCol].zName); + zType = sqlite3ColumnType(&pTab->aCol[iCol],0); estWidth = pTab->aCol[iCol].szEst; } #endif diff --git a/src/sqliteInt.h b/src/sqliteInt.h index d256262b05..242ae8e2cf 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1604,6 +1604,7 @@ struct Column { */ #define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */ #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ +#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */ /* ** A "Collating Sequence" is defined by an instance of the following @@ -3307,7 +3308,7 @@ int sqlite3IsIdChar(u8); */ int sqlite3StrICmp(const char*,const char*); int sqlite3Strlen30(const char*); -const char *sqlite3StrNext(const char*); +char *sqlite3ColumnType(Column*,char*); #define sqlite3StrNICmp sqlite3_strnicmp int sqlite3MallocInit(void); diff --git a/src/util.c b/src/util.c index 428dfd046c..08b0c46a5c 100644 --- a/src/util.c +++ b/src/util.c @@ -110,11 +110,15 @@ int sqlite3Strlen30(const char *z){ } /* -** The string z[] is followed immediately by another string. Return -** a poiner to that other string. +** Return the declared type of a column. Or return zDflt if the column +** has no declared type. +** +** The column type is an extra string stored after the zero-terminator on +** the column name if and only if the COLFLAG_HASTYPE flag is set. */ -const char *sqlite3StrNext(const char *z){ - return z + strlen(z) + 1; +char *sqlite3ColumnType(Column *pCol, char *zDflt){ + if( (pCol->colFlags & COLFLAG_HASTYPE)==0 ) return zDflt; + return pCol->zName + strlen(pCol->zName) + 1; } /* diff --git a/src/vtab.c b/src/vtab.c index ad8caef3bc..802a8cac3a 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -564,22 +564,16 @@ static int vtabCallConstructor( pTab->pVTable = pVTable; for(iCol=0; iColnCol; iCol++){ - char *zType = (char*)sqlite3StrNext(pTab->aCol[iCol].zName); + char *zType = sqlite3ColumnType(&pTab->aCol[iCol], ""); int nType; int i = 0; - if( !zType[0] ){ - pTab->tabFlags |= oooHidden; - continue; - } nType = sqlite3Strlen30(zType); - if( sqlite3StrNICmp("hidden", zType, 6)||(zType[6] && zType[6]!=' ') ){ - for(i=0; i Date: Wed, 23 Mar 2016 13:46:05 +0000 Subject: [PATCH 520/570] Update a requirement mark. No changes to code. FossilOrigin-Name: 412984642af40578ec611d8c0b7c0508cb5cf9c9 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqliteLimit.h | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 19c00ee626..187f8d0c9b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\ssqlite3_column_decltype()\sroutine\sshould\sreturn\sNULL,\snot\san\sempty\sstring,\nif\sthe\scolumn\shas\sno\sdeclared\stype. -D 2016-03-22T20:05:09.546 +C Update\sa\srequirement\smark.\s\sNo\schanges\sto\scode. +D 2016-03-23T13:46:05.453 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -359,7 +359,7 @@ F src/sqlite.h.in e877f141b15ef68ef28f84714e69d7234f9a071e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 F src/sqliteInt.h 3a68b48967a7d62fcb38572d27fd21ab4e4bcca3 -F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24 +F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 F src/tclsqlite.c 4bf3bea9b03aeac176ac114700f35f76a1de4c8a @@ -1459,7 +1459,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 142cd359d37f1d8d53de32e329523d9a93c7d6e5 -R 54bb94e9ede3ebe9fafd5624cdd5946f +P 605eba4a756e7185119088e2242f82691d078b01 +R 0cef5aac6dc3fd4662874a0245bd6fe2 U drh -Z 8ae8a72878a637ee00e9de9bf1db9104 +Z 79401c6ddf17e634854d1f69b3d42451 diff --git a/manifest.uuid b/manifest.uuid index 43fdf15940..48f9df63e0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -605eba4a756e7185119088e2242f82691d078b01 \ No newline at end of file +412984642af40578ec611d8c0b7c0508cb5cf9c9 \ No newline at end of file diff --git a/src/sqliteLimit.h b/src/sqliteLimit.h index 4b5ddaadec..0554e61581 100644 --- a/src/sqliteLimit.h +++ b/src/sqliteLimit.h @@ -101,8 +101,8 @@ ** The suggested maximum number of in-memory pages to use for ** the main database table and for temporary tables. ** -** IMPLEMENTATION-OF: R-31093-59126 The default suggested cache size -** is 2000*1024 bytes. +** IMPLEMENTATION-OF: R-30185-15359 The default suggested cache size is -2000, +** which means the cache size is limited to 2048000 bytes of memory. ** IMPLEMENTATION-OF: R-48205-43578 The default suggested cache size can be ** altered using the SQLITE_DEFAULT_CACHE_SIZE compile-time options. */ From 848b190e4079cc60f3cbbc63e3ae6638cfe06d92 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 23 Mar 2016 15:04:00 +0000 Subject: [PATCH 521/570] Explicitly limit the size of fts5 tokens to 32768 bytes. FossilOrigin-Name: 70fc69eed9b09159899d7cbd1416a59d04210a63 --- ext/fts5/fts5Int.h | 4 +++ ext/fts5/fts5_expr.c | 2 ++ ext/fts5/fts5_index.c | 47 +++++++++++++++++++++++++---------- ext/fts5/fts5_storage.c | 2 ++ ext/fts5/test/fts5simple.test | 20 +++++++++++++++ manifest | 22 ++++++++-------- manifest.uuid | 2 +- 7 files changed, 74 insertions(+), 25 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index 961206f2b3..c4e7506fb1 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -47,6 +47,10 @@ typedef sqlite3_uint64 u64; #endif +/* Truncate very long tokens to this many bytes. Hard limit is +** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset +** field that occurs at the start of each leaf page (see fts5_index.c). */ +#define FTS5_MAX_TOKEN_SIZE 32768 /* ** Maximum number of prefix indexes on single FTS5 table. This must be diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index 0bc61414b0..eada84f70e 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -1493,6 +1493,7 @@ static int fts5ParseTokenize( /* If an error has already occurred, this is a no-op */ if( pCtx->rc!=SQLITE_OK ) return pCtx->rc; + if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE; if( pPhrase && pPhrase->nTerm>0 && (tflags & FTS5_TOKEN_COLOCATED) ){ Fts5ExprTerm *pSyn; @@ -2495,6 +2496,7 @@ static int fts5ExprPopulatePoslistsCb( UNUSED_PARAM2(iUnused1, iUnused2); + if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE; if( (tflags & FTS5_TOKEN_COLOCATED)==0 ) p->iOff++; for(i=0; inPhrase; i++){ Fts5ExprTerm *pTerm; diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index d08e65bfe6..c477ea6ca6 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -2321,6 +2321,18 @@ static void fts5LeafSeek( fts5SegIterLoadNPos(p, pIter); } +static sqlite3_stmt *fts5IdxSelectStmt(Fts5Index *p){ + if( p->pIdxSelect==0 ){ + Fts5Config *pConfig = p->pConfig; + fts5IndexPrepareStmt(p, &p->pIdxSelect, sqlite3_mprintf( + "SELECT pgno FROM '%q'.'%q_idx' WHERE " + "segid=? AND term<=? ORDER BY term DESC LIMIT 1", + pConfig->zDb, pConfig->zName + )); + } + return p->pIdxSelect; +} + /* ** Initialize the object pIter to point to term pTerm/nTerm within segment ** pSeg. If there is no such term in the index, the iterator is set to EOF. @@ -2338,6 +2350,7 @@ static void fts5SegIterSeekInit( int iPg = 1; int bGe = (flags & FTS5INDEX_QUERY_SCAN); int bDlidx = 0; /* True if there is a doclist-index */ + sqlite3_stmt *pIdxSelect = 0; assert( bGe==0 || (flags & FTS5INDEX_QUERY_DESC)==0 ); assert( pTerm && nTerm ); @@ -2346,23 +2359,16 @@ static void fts5SegIterSeekInit( /* This block sets stack variable iPg to the leaf page number that may ** contain term (pTerm/nTerm), if it is present in the segment. */ - if( p->pIdxSelect==0 ){ - Fts5Config *pConfig = p->pConfig; - fts5IndexPrepareStmt(p, &p->pIdxSelect, sqlite3_mprintf( - "SELECT pgno FROM '%q'.'%q_idx' WHERE " - "segid=? AND term<=? ORDER BY term DESC LIMIT 1", - pConfig->zDb, pConfig->zName - )); - } + pIdxSelect = fts5IdxSelectStmt(p); if( p->rc ) return; - sqlite3_bind_int(p->pIdxSelect, 1, pSeg->iSegid); - sqlite3_bind_blob(p->pIdxSelect, 2, pTerm, nTerm, SQLITE_STATIC); - if( SQLITE_ROW==sqlite3_step(p->pIdxSelect) ){ - i64 val = sqlite3_column_int(p->pIdxSelect, 0); + sqlite3_bind_int(pIdxSelect, 1, pSeg->iSegid); + sqlite3_bind_blob(pIdxSelect, 2, pTerm, nTerm, SQLITE_STATIC); + if( SQLITE_ROW==sqlite3_step(pIdxSelect) ){ + i64 val = sqlite3_column_int(pIdxSelect, 0); iPg = (int)(val>>1); bDlidx = (val & 0x0001); } - p->rc = sqlite3_reset(p->pIdxSelect); + p->rc = sqlite3_reset(pIdxSelect); if( iPgpgnoFirst ){ iPg = pSeg->pgnoFirst; @@ -3552,6 +3558,18 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){ } } assert( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT ); + + { + sqlite3_stmt *pIdxSelect = fts5IdxSelectStmt(p); + if( p->rc==SQLITE_OK ){ + int rc; + u8 aBlob[2] = {0xff, 0xff}; + sqlite3_bind_int(pIdxSelect, 1, iSegid); + sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC); + assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW ); + p->rc = sqlite3_reset(pIdxSelect); + } + } #endif } } @@ -3798,6 +3816,9 @@ static void fts5WriteFlushLeaf(Fts5Index *p, Fts5SegWriter *pWriter){ Fts5PageWriter *pPage = &pWriter->writer; i64 iRowid; +static int nCall = 0; +nCall++; + assert( (pPage->pgidx.n==0)==(pWriter->bFirstTermInPage) ); /* Set the szLeaf header field. */ diff --git a/ext/fts5/fts5_storage.c b/ext/fts5/fts5_storage.c index 3cca990ed5..90df3396c3 100644 --- a/ext/fts5/fts5_storage.c +++ b/ext/fts5/fts5_storage.c @@ -369,6 +369,7 @@ static int fts5StorageInsertCallback( Fts5InsertCtx *pCtx = (Fts5InsertCtx*)pContext; Fts5Index *pIdx = pCtx->pStorage->pIndex; UNUSED_PARAM2(iUnused1, iUnused2); + if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE; if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){ pCtx->szCol++; } @@ -815,6 +816,7 @@ static int fts5StorageIntegrityCallback( int iCol; UNUSED_PARAM2(iUnused1, iUnused2); + if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE; if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){ pCtx->szCol++; diff --git a/ext/fts5/test/fts5simple.test b/ext/fts5/test/fts5simple.test index 3483e40ba5..2bc02cf49a 100644 --- a/ext/fts5/test/fts5simple.test +++ b/ext/fts5/test/fts5simple.test @@ -448,4 +448,24 @@ do_execsql_test 20.2 { INSERT INTO x1(x1) VALUES('integrity-check'); } {} +#------------------------------------------------------------------------- +reset_db +set doc "a b [string repeat x 100000]" +do_execsql_test 21.0 { + CREATE VIRTUAL TABLE x1 USING fts5(x); + INSERT INTO x1(rowid, x) VALUES(11111, $doc); + INSERT INTO x1(rowid, x) VALUES(11112, $doc); +} +do_execsql_test 21.1 { + INSERT INTO x1(x1) VALUES('integrity-check'); +} +do_execsql_test 21.2 { + SELECT rowid FROM x1($doc); +} {11111 11112} +do_execsql_test 21.3 { + DELETE FROM x1 WHERE rowid=11111; + INSERT INTO x1(x1) VALUES('integrity-check'); + SELECT rowid FROM x1($doc); +} {11112} + finish_test diff --git a/manifest b/manifest index 187f8d0c9b..79eb4b3013 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sa\srequirement\smark.\s\sNo\schanges\sto\scode. -D 2016-03-23T13:46:05.453 +C Explicitly\slimit\sthe\ssize\sof\sfts5\stokens\sto\s32768\sbytes. +D 2016-03-23T15:04:00.239 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -98,15 +98,15 @@ F ext/fts3/unicode/mkunicode.tcl 2debed3f582d77b3fdd0b8830880250021571fd8 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 -F ext/fts5/fts5Int.h 4e507abebae0d7d3ac9b8daebf049d5153d00961 +F ext/fts5/fts5Int.h 3677076aecbf645a7f2a019115c6a4ec3272dd78 F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458 F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 -F ext/fts5/fts5_expr.c 35e9d92c89e7c7ea0759b73d24da1ecb7630a24b +F ext/fts5/fts5_expr.c 5ca4bafe29aa3d27683c90e836192e4aefd20a3f F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c 19df86d29d24cc56bfb01a6a07dcaac227d2fcdf +F ext/fts5/fts5_index.c b271b19dd28d3501772c3a9317272add4751af95 F ext/fts5/fts5_main.c b4a0fc5bf17f2f1f056ee76cdd7d2af08b360f55 -F ext/fts5/fts5_storage.c 98e3129047d250fc5acc4a4ba7ba4fde9b0ae030 +F ext/fts5/fts5_storage.c 3309c6a8e34b974513016fd1ef47c83f5898f94c F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 F ext/fts5/fts5_test_mi.c 783b86697ebf773c18fc109992426c0173a055bc F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be @@ -180,7 +180,7 @@ F ext/fts5/test/fts5rank.test 7e9e64eac7245637f6f2033aec4b292aaf611aab F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17 F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6 -F ext/fts5/test/fts5simple.test 5b7b05bcc89bcb718a0fc7f473092d3513cc8e19 +F ext/fts5/test/fts5simple.test cd23d4072ea095d652c9b6db12284cc642e49c98 F ext/fts5/test/fts5simple2.test 98377ae1ff7749a42c21fe1a139c1ed312522c46 F ext/fts5/test/fts5simple3.test 8e71733b3d1b0e695011d02c68ebc5ca40b6124e F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48 @@ -1459,7 +1459,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 605eba4a756e7185119088e2242f82691d078b01 -R 0cef5aac6dc3fd4662874a0245bd6fe2 -U drh -Z 79401c6ddf17e634854d1f69b3d42451 +P 412984642af40578ec611d8c0b7c0508cb5cf9c9 +R 7ff8c5a33cf0f5a9bc31dcb4123a3529 +U dan +Z a8f8abdf00b8979540d6caa40226ffc8 diff --git a/manifest.uuid b/manifest.uuid index 48f9df63e0..efdf00d8e6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -412984642af40578ec611d8c0b7c0508cb5cf9c9 \ No newline at end of file +70fc69eed9b09159899d7cbd1416a59d04210a63 \ No newline at end of file From 997de998a8f4c84e9fdcc91cb308d06864dff90b Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 23 Mar 2016 15:53:45 +0000 Subject: [PATCH 522/570] Remove an unused local variable from FTS5. FossilOrigin-Name: 0ed693c29f184223cde3b3d51f0e06273e586803 --- ext/fts5/fts5_index.c | 1 - manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index c477ea6ca6..1200f5707b 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -3562,7 +3562,6 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){ { sqlite3_stmt *pIdxSelect = fts5IdxSelectStmt(p); if( p->rc==SQLITE_OK ){ - int rc; u8 aBlob[2] = {0xff, 0xff}; sqlite3_bind_int(pIdxSelect, 1, iSegid); sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC); diff --git a/manifest b/manifest index 79eb4b3013..c04dd5f417 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Explicitly\slimit\sthe\ssize\sof\sfts5\stokens\sto\s32768\sbytes. -D 2016-03-23T15:04:00.239 +C Remove\san\sunused\slocal\svariable\sfrom\sFTS5. +D 2016-03-23T15:53:45.875 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -104,7 +104,7 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 F ext/fts5/fts5_expr.c 5ca4bafe29aa3d27683c90e836192e4aefd20a3f F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337 -F ext/fts5/fts5_index.c b271b19dd28d3501772c3a9317272add4751af95 +F ext/fts5/fts5_index.c fdd82bb421a5d1e64d004acb43f4dd9970c8d2b3 F ext/fts5/fts5_main.c b4a0fc5bf17f2f1f056ee76cdd7d2af08b360f55 F ext/fts5/fts5_storage.c 3309c6a8e34b974513016fd1ef47c83f5898f94c F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 @@ -1459,7 +1459,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 412984642af40578ec611d8c0b7c0508cb5cf9c9 -R 7ff8c5a33cf0f5a9bc31dcb4123a3529 -U dan -Z a8f8abdf00b8979540d6caa40226ffc8 +P 70fc69eed9b09159899d7cbd1416a59d04210a63 +R 873e340080925d4861d8b0305a1e9665 +U drh +Z 80f86ca0927f258d1530b1b8654e3fe4 diff --git a/manifest.uuid b/manifest.uuid index efdf00d8e6..e4a6517082 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -70fc69eed9b09159899d7cbd1416a59d04210a63 \ No newline at end of file +0ed693c29f184223cde3b3d51f0e06273e586803 \ No newline at end of file From 231ee688083efe09940c2b6c60c4527d35c2d809 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 23 Mar 2016 16:32:29 +0000 Subject: [PATCH 523/570] Fix "ifcapable" tests in capi3.test and capi3c.test so that the tests work with more build configurations. FossilOrigin-Name: 3fa88f68c3e1bbb3421cb0d2b82b9bb3fe7b9b14 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- test/capi3.test | 2 +- test/capi3c.test | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index c04dd5f417..339c6e1490 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunused\slocal\svariable\sfrom\sFTS5. -D 2016-03-23T15:53:45.875 +C Fix\s"ifcapable"\stests\sin\scapi3.test\sand\scapi3c.test\sso\sthat\sthe\stests\swork\swith\smore\sbuild\sconfigurations. +D 2016-03-23T16:32:29.404 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -523,9 +523,9 @@ F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0 F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61 F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738 -F test/capi3.test 860dafdc04f651a67781018cb1a0b179d22d7d15 +F test/capi3.test f0c66919e43d42e1572a69be039e4527a931b00f F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 -F test/capi3c.test b28ec47692f0fc50eb61b2d464d8d52e816b3732 +F test/capi3c.test 0b9edb0c2156a964b9271cd5ea7ae56736cc2fcb F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82 F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3 @@ -1459,7 +1459,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 70fc69eed9b09159899d7cbd1416a59d04210a63 -R 873e340080925d4861d8b0305a1e9665 -U drh -Z 80f86ca0927f258d1530b1b8654e3fe4 +P 0ed693c29f184223cde3b3d51f0e06273e586803 +R 405228ca43a6aac7fb0de536de78cc72 +U dan +Z fb0a5f0fe48a39fd4b3b3bb440d1982d diff --git a/manifest.uuid b/manifest.uuid index e4a6517082..0d41a4b253 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0ed693c29f184223cde3b3d51f0e06273e586803 \ No newline at end of file +3fa88f68c3e1bbb3421cb0d2b82b9bb3fe7b9b14 \ No newline at end of file diff --git a/test/capi3.test b/test/capi3.test index 8096d29bec..84889f5faf 100644 --- a/test/capi3.test +++ b/test/capi3.test @@ -929,7 +929,7 @@ do_test capi3-11.10 { do_test capi3-11.11 { sqlite3_step $STMT } {SQLITE_DONE} -ifcapable api_armor { +ifcapable !autoreset { do_test capi3-11.12armor { sqlite3_step $STMT sqlite3_step $STMT diff --git a/test/capi3c.test b/test/capi3c.test index 91c02561b1..57cf146c73 100644 --- a/test/capi3c.test +++ b/test/capi3c.test @@ -868,7 +868,7 @@ do_test capi3c-11.10 { do_test capi3c-11.11 { sqlite3_step $STMT } {SQLITE_DONE} -ifcapable api_armor { +ifcapable !autoreset { do_test capi3c-11.12armor { sqlite3_step $STMT sqlite3_step $STMT From c5412d533c73b8e247cd7850817ddf07dcb8068f Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 23 Mar 2016 17:54:19 +0000 Subject: [PATCH 524/570] Avoid calling realloc() with a zero size in fuzzcheck.c. FossilOrigin-Name: a1fd14694c1adc54e5c443ebfdef38e38637f5c5 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/fuzzcheck.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 339c6e1490..f86978ab06 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\s"ifcapable"\stests\sin\scapi3.test\sand\scapi3c.test\sso\sthat\sthe\stests\swork\swith\smore\sbuild\sconfigurations. -D 2016-03-23T16:32:29.404 +C Avoid\scalling\srealloc()\swith\sa\szero\ssize\sin\sfuzzcheck.c. +D 2016-03-23T17:54:19.633 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -773,7 +773,7 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test b47377143f0c80f91ed29d722861077ff34415d5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26 -F test/fuzzcheck.c 93bb9d309888634615e21ef98d1c30d51483e942 +F test/fuzzcheck.c f01d432d001ba29e7916df8411be7d4e7cddc574 F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973 F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba @@ -1459,7 +1459,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 0ed693c29f184223cde3b3d51f0e06273e586803 -R 405228ca43a6aac7fb0de536de78cc72 -U dan -Z fb0a5f0fe48a39fd4b3b3bb440d1982d +P 3fa88f68c3e1bbb3421cb0d2b82b9bb3fe7b9b14 +R 6050811335a4694faefeb0d2dc871228 +U drh +Z bf4eed3170d70e06db77678976293947 diff --git a/manifest.uuid b/manifest.uuid index 0d41a4b253..fc3163dd80 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3fa88f68c3e1bbb3421cb0d2b82b9bb3fe7b9b14 \ No newline at end of file +a1fd14694c1adc54e5c443ebfdef38e38637f5c5 \ No newline at end of file diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c index 1e0ce86e66..1d11b2986f 100644 --- a/test/fuzzcheck.c +++ b/test/fuzzcheck.c @@ -189,7 +189,7 @@ static int progressHandler(void *pVdbeLimitFlag){ ** Reallocate memory. Show and error and quit if unable. */ static void *safe_realloc(void *pOld, int szNew){ - void *pNew = realloc(pOld, szNew); + void *pNew = realloc(pOld, szNew<=0 ? 1 : szNew); if( pNew==0 ) fatalError("unable to realloc for %d bytes", szNew); return pNew; } From cc47eac00555ac1af94fde3ab9f8c7d2b6bf8766 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 24 Mar 2016 15:09:14 +0000 Subject: [PATCH 525/570] Fix some test scripts so that they work with various permutations. FossilOrigin-Name: f4d234b5013bf93b6eac7f8be6d4c074cf9f5293 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- test/snapshot.test | 9 +++++++++ test/snapshot_fault.test | 2 +- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index f86978ab06..19ae78878e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\scalling\srealloc()\swith\sa\szero\ssize\sin\sfuzzcheck.c. -D 2016-03-23T17:54:19.633 +C Fix\ssome\stest\sscripts\sso\sthat\sthey\swork\swith\svarious\spermutations. +D 2016-03-24T15:09:14.368 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1042,8 +1042,8 @@ F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5 F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2 F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b -F test/snapshot.test c03eb5ba1602df33c1edc1d12393d6ca7a282a46 -F test/snapshot_fault.test 25973aeb1b86a280800e0bcf1eb5ce70e9ef57ab +F test/snapshot.test 9ed24c792fb05382814258daf68b2256f23de57f +F test/snapshot_fault.test 062ff0438a074978d45e9f9a92e7ad459b74ee73 F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087 F test/sort.test c2adc635c2564241fefec0b3a68391ef6868fd3b @@ -1459,7 +1459,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 3fa88f68c3e1bbb3421cb0d2b82b9bb3fe7b9b14 -R 6050811335a4694faefeb0d2dc871228 -U drh -Z bf4eed3170d70e06db77678976293947 +P a1fd14694c1adc54e5c443ebfdef38e38637f5c5 +R 36309b59b7cae947470048aeed54391f +U dan +Z b85dfb4995f4f514e1ad3337ff91de1c diff --git a/manifest.uuid b/manifest.uuid index fc3163dd80..7a09317688 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a1fd14694c1adc54e5c443ebfdef38e38637f5c5 \ No newline at end of file +f4d234b5013bf93b6eac7f8be6d4c074cf9f5293 \ No newline at end of file diff --git a/test/snapshot.test b/test/snapshot.test index ba3a666796..c6710e3691 100644 --- a/test/snapshot.test +++ b/test/snapshot.test @@ -17,6 +17,15 @@ source $testdir/tester.tcl ifcapable !snapshot {finish_test; return} set testprefix snapshot +# This test does not work with the inmemory_journal permutation. The reason +# is that each connection opened as part of this permutation executes +# "PRAGMA journal_mode=memory", which fails if the database is in wal mode +# and there are one or more existing connections. +if {[permutation]=="inmemory_journal"} { + finish_test + return +} + #------------------------------------------------------------------------- # Check some error conditions in snapshot_get(). It is an error if: # diff --git a/test/snapshot_fault.test b/test/snapshot_fault.test index 3ac13daefd..f90690e3f6 100644 --- a/test/snapshot_fault.test +++ b/test/snapshot_fault.test @@ -146,7 +146,7 @@ do_faultsim_test 3.0 -prep { error $msg } } -test { - faultsim_test_result {0 {}} {1 SQLITE_IOERR} \ + faultsim_test_result {0 {}} {1 SQLITE_IOERR} {1 SQLITE_NOMEM} \ {1 SQLITE_IOERR_NOMEM} {1 SQLITE_IOERR_READ} if {$testrc==0} { set res [db eval { From d38a2e2511daf120d37c58c95e333e29bdb7f3a4 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 24 Mar 2016 15:32:19 +0000 Subject: [PATCH 526/570] Larger margins for one memsubsys1 range check when running with a non-zero reserved-bytes value. FossilOrigin-Name: 6db1d1fbc6c1acc896fa635dfdc5564800502c40 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/memsubsys1.test | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 19ae78878e..63d4b9b8b2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\stest\sscripts\sso\sthat\sthey\swork\swith\svarious\spermutations. -D 2016-03-24T15:09:14.368 +C Larger\smargins\sfor\sone\smemsubsys1\srange\scheck\swhen\srunning\swith\sa\nnon-zero\sreserved-bytes\svalue. +D 2016-03-24T15:32:19.097 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -892,7 +892,7 @@ F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 -F test/memsubsys1.test 69924593856040e266fdd9aa1ecb4d5a0888eb12 +F test/memsubsys1.test 6d268d0ae90f8d61a2356a1838665654d83de518 F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc @@ -1459,7 +1459,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 a1fd14694c1adc54e5c443ebfdef38e38637f5c5 -R 36309b59b7cae947470048aeed54391f -U dan -Z b85dfb4995f4f514e1ad3337ff91de1c +P f4d234b5013bf93b6eac7f8be6d4c074cf9f5293 +R 918e030f39e9a5a455482186d2119a1e +U drh +Z 4c4813ba0d5bb38b250579ca5f32f159 diff --git a/manifest.uuid b/manifest.uuid index 7a09317688..75cadabba3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f4d234b5013bf93b6eac7f8be6d4c074cf9f5293 \ No newline at end of file +6db1d1fbc6c1acc896fa635dfdc5564800502c40 \ No newline at end of file diff --git a/test/memsubsys1.test b/test/memsubsys1.test index f0b060fc9f..36427f9bae 100644 --- a/test/memsubsys1.test +++ b/test/memsubsys1.test @@ -257,7 +257,7 @@ do_test memsubsys1-7.4 { } 0 do_test memsubsys1-7.5 { set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2] - expr {$maxreq<4100 + 4200*[nonzero_reserved_bytes]} + expr {$maxreq<(4100 + 8200*[nonzero_reserved_bytes])} } 1 do_test memsubsys1-7.6 { set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2] From eb2329bed34ec38248e7d78ed34fc79eb9976cc2 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 24 Mar 2016 20:36:47 +0000 Subject: [PATCH 527/570] Prevent negative values of SQLITE_DEFAULT_CACHE_SIZE from making SQLITE_WIN32_HEAP_INIT_SIZE negative. FossilOrigin-Name: e0737f5236ed3e85bd03203c880ee41b34619137 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/os_win.c | 14 +++++++++++++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 63d4b9b8b2..3716cd5a4b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Larger\smargins\sfor\sone\smemsubsys1\srange\scheck\swhen\srunning\swith\sa\nnon-zero\sreserved-bytes\svalue. -D 2016-03-24T15:32:19.097 +C Prevent\snegative\svalues\sof\sSQLITE_DEFAULT_CACHE_SIZE\sfrom\smaking\sSQLITE_WIN32_HEAP_INIT_SIZE\snegative. +D 2016-03-24T20:36:47.715 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -338,7 +338,7 @@ F src/os.h 91ff889115ecd01f436d3611f7f5ea4dc12d92f1 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c b1ccb273771f41dbdbe0ba7c1ad63c38ad5972ec -F src/os_win.c 17493f12b0b023c2d5a349b6860009f0d45e08d6 +F src/os_win.c 7c071f7f8f04827ab25a8f441080832be58688e9 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 38718a019ca762ba4f6795425d5a54db70d1790d F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 @@ -1459,7 +1459,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 f4d234b5013bf93b6eac7f8be6d4c074cf9f5293 -R 918e030f39e9a5a455482186d2119a1e -U drh -Z 4c4813ba0d5bb38b250579ca5f32f159 +P 6db1d1fbc6c1acc896fa635dfdc5564800502c40 +R 5e26e94cafc58d6fd55eccc4e6c637ee +U mistachkin +Z 1088b9c27d83d36a2ae2a2fd6824e14f diff --git a/manifest.uuid b/manifest.uuid index 75cadabba3..1b00761a79 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6db1d1fbc6c1acc896fa635dfdc5564800502c40 \ No newline at end of file +e0737f5236ed3e85bd03203c880ee41b34619137 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index 3f9fefcac4..7ae833d3f5 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -344,11 +344,23 @@ struct winFile { # define SQLITE_WIN32_HEAP_CREATE (TRUE) #endif +/* + * This is cache size used in the calculation of the initial size of the + * Win32-specific heap. It cannot be negative. + */ +#ifndef SQLITE_WIN32_CACHE_SIZE +# if SQLITE_DEFAULT_CACHE_SIZE>=0 +# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE) +# else +# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE)) +# endif +#endif + /* * The initial size of the Win32-specific heap. This value may be zero. */ #ifndef SQLITE_WIN32_HEAP_INIT_SIZE -# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \ +# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \ (SQLITE_DEFAULT_PAGE_SIZE) + 4194304) #endif From cb620b479783d42e637b7b54631879daa89f30f7 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 24 Mar 2016 20:55:03 +0000 Subject: [PATCH 528/570] Make test cases in shell1.test robust against TCL deciding to quote strings using lots of backslashes. FossilOrigin-Name: 817e93f42c09eb876421e27eb8eceb7b077cb45d --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/shell1.test | 10 ++++++---- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 3716cd5a4b..7c64a1af14 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Prevent\snegative\svalues\sof\sSQLITE_DEFAULT_CACHE_SIZE\sfrom\smaking\sSQLITE_WIN32_HEAP_INIT_SIZE\snegative. -D 2016-03-24T20:36:47.715 +C Make\stest\scases\sin\sshell1.test\srobust\sagainst\sTCL\sdeciding\sto\squote\sstrings\nusing\slots\sof\sbackslashes. +D 2016-03-24T20:55:03.263 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1028,7 +1028,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test e7dac9830b7d80432be9cebfae06eff9c18675f5 +F test/shell1.test 94538224ee7b7a52952dea67d2633b358abde271 F test/shell2.test 2e7a32c9ee03c6398478637d72416d5b9ebd9777 F test/shell3.test c39453d3012a39ffec944566eca8a6bda10a2284 F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9 @@ -1459,7 +1459,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 6db1d1fbc6c1acc896fa635dfdc5564800502c40 -R 5e26e94cafc58d6fd55eccc4e6c637ee -U mistachkin -Z 1088b9c27d83d36a2ae2a2fd6824e14f +P e0737f5236ed3e85bd03203c880ee41b34619137 +R 203f39504a0cd47826f57431bf7289e6 +U drh +Z ba68271edf3c6755b87aa606194c0bcd diff --git a/manifest.uuid b/manifest.uuid index 1b00761a79..d8ea0b1033 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e0737f5236ed3e85bd03203c880ee41b34619137 \ No newline at end of file +817e93f42c09eb876421e27eb8eceb7b077cb45d \ No newline at end of file diff --git a/test/shell1.test b/test/shell1.test index 1f1f3de320..b08c08ffc0 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -275,12 +275,14 @@ do_test shell1-3.2.4 { # .databases List names and files of attached databases do_test shell1-3.3.1 { - catchcmd "-csv test.db" ".databases" -} "/0 +.*main +[string map {/ .} [string range [get_pwd] 0 10]].*/" + set x [catchcmd "-csv test.db" ".databases"] + set x [subst -nocommands -novariables $x] +} "/0.+main.+[string map {/ .} [string range [get_pwd] 0 10]].*/" do_test shell1-3.3.2 { # extra arguments ignored - catchcmd "test.db" ".databases BAD" -} "/0 +.*main +[string map {/ .} [string range [get_pwd] 0 10]].*/" + set x [catchcmd "test.db" ".databases BAD"] + set x [subst -nocommands -novariables $x] +} "/0.+main.+[string map {/ .} [string range [get_pwd] 0 10]].*/" # .dump ?TABLE? ... Dump the database in an SQL text format # If TABLE specified, only dump tables matching From ddb2b4a31015c8ad93f52f8c07ae8e592e6d02c6 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 25 Mar 2016 12:10:32 +0000 Subject: [PATCH 529/570] Fix two instances of undefined behavior in the C code - both harmless for all current compilers. FossilOrigin-Name: 99fd194c83dbcfcdcc582983b86678b85b1b9570 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/build.c | 6 +++--- src/vdbe.c | 4 +++- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 7c64a1af14..9995948b77 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\stest\scases\sin\sshell1.test\srobust\sagainst\sTCL\sdeciding\sto\squote\sstrings\nusing\slots\sof\sbackslashes. -D 2016-03-24T20:55:03.263 +C Fix\stwo\sinstances\sof\sundefined\sbehavior\sin\sthe\sC\scode\s-\sboth\sharmless\sfor\nall\scurrent\scompilers. +D 2016-03-25T12:10:32.929 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -300,7 +300,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 577fb5674e2f0aa0a38246afc19e1885a0b8c9b0 F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 7d1a5e64fcd10110edc8ce9ffb710d06af0a59f5 +F src/build.c 39faaaeecb77eb3936d4bd5024e865e3836ca323 F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -419,7 +419,7 @@ F src/update.c 56b3db7edff0110360a12b76af97c39ebe3ea8b8 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 8873d696c9ccc4206058c402e09e101f1b81561a F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 -F src/vdbe.c f19741f2d8b33e8f09cd2219570b6c9ed924c3f1 +F src/vdbe.c cd990451b504507b455cc649d46dad51f2835a67 F src/vdbe.h 6f44193e7be52fd5f7c308175a936555b1e6b101 F src/vdbeInt.h f88d3115e9bde33b01d81f0dd26d8dd51f995991 F src/vdbeapi.c 95b1f8e527240a18a9aea41a655b013bf07a7009 @@ -1459,7 +1459,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 e0737f5236ed3e85bd03203c880ee41b34619137 -R 203f39504a0cd47826f57431bf7289e6 +P 817e93f42c09eb876421e27eb8eceb7b077cb45d +R aca0111531dd13b444e2634c40aa3c16 U drh -Z ba68271edf3c6755b87aa606194c0bcd +Z a7abe0dd0ebfdb648c54f66b764dd2a5 diff --git a/manifest.uuid b/manifest.uuid index d8ea0b1033..eec1194704 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -817e93f42c09eb876421e27eb8eceb7b077cb45d \ No newline at end of file +99fd194c83dbcfcdcc582983b86678b85b1b9570 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 28eb55ab6c..d4d0c173cc 100644 --- a/src/build.c +++ b/src/build.c @@ -1056,9 +1056,6 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ memcpy(z, pName->z, pName->n); z[pName->n] = 0; sqlite3Dequote(z); - zType = z + sqlite3Strlen30(z) + 1; - memcpy(zType, pType->z, pType->n); - zType[pType->n] = 0; for(i=0; inCol; i++){ if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){ sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); @@ -1086,6 +1083,9 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ pCol->affinity = SQLITE_AFF_BLOB; pCol->szEst = 1; }else{ + zType = z + sqlite3Strlen30(z) + 1; + memcpy(zType, pType->z, pType->n); + zType[pType->n] = 0; pCol->affinity = sqlite3AffinityType(zType, &pCol->szEst); pCol->colFlags |= COLFLAG_HASTYPE; } diff --git a/src/vdbe.c b/src/vdbe.c index 90269cbe30..e6d17ad26e 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2524,7 +2524,6 @@ case OP_Column: { }while( i<=p2 && zHdrnHdrParsed = i; pC->iHdrOffset = (u32)(zHdr - zData); - if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); /* The record is corrupt if any of the following are true: ** (1) the bytes of the header extend past the declared header size @@ -2534,9 +2533,12 @@ case OP_Column: { if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset64!=pC->payloadSize)) || (offset64 > pC->payloadSize) ){ + if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); rc = SQLITE_CORRUPT_BKPT; goto abort_due_to_error; } + if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); + }else{ t = 0; } From 5729c31dafbf5bb7796f62cb30e3b6c7ae32d4d4 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 25 Mar 2016 17:09:16 +0000 Subject: [PATCH 530/570] Add the catchcmd_collapse_space command and use it to help make shell testing more robust against TCL space escapes. FossilOrigin-Name: 93caabb66082f76ef161a51ac822b919517a7171 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/shell1.test | 6 ++---- test/tester.tcl | 11 +++++++++++ 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 9995948b77..b34eb55e70 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stwo\sinstances\sof\sundefined\sbehavior\sin\sthe\sC\scode\s-\sboth\sharmless\sfor\nall\scurrent\scompilers. -D 2016-03-25T12:10:32.929 +C Add\sthe\scatchcmd_collapse_space\scommand\sand\suse\sit\sto\shelp\smake\sshell\stesting\nmore\srobust\sagainst\sTCL\sspace\sescapes. +D 2016-03-25T17:09:16.750 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1028,7 +1028,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test 94538224ee7b7a52952dea67d2633b358abde271 +F test/shell1.test 12d1774936facc17a889e0c31877670ef5526f8c F test/shell2.test 2e7a32c9ee03c6398478637d72416d5b9ebd9777 F test/shell3.test c39453d3012a39ffec944566eca8a6bda10a2284 F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9 @@ -1088,7 +1088,7 @@ F test/tclsqlite.test c6d9f546f79d15d0134c1e06583fb3ee0c3afad3 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl f2b99e912d4da1e5755969b8614febd883885c8b +F test/tester.tcl 5604f2697e8fa9b12b6180122d84e1a9093ca8a3 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1459,7 +1459,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 817e93f42c09eb876421e27eb8eceb7b077cb45d -R aca0111531dd13b444e2634c40aa3c16 +P 99fd194c83dbcfcdcc582983b86678b85b1b9570 +R cfe872b896f4c791395847cc13daead3 U drh -Z a7abe0dd0ebfdb648c54f66b764dd2a5 +Z 0d389fd777e66fc5d8e3b6840aab7902 diff --git a/manifest.uuid b/manifest.uuid index eec1194704..aa0e2349f2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -99fd194c83dbcfcdcc582983b86678b85b1b9570 \ No newline at end of file +93caabb66082f76ef161a51ac822b919517a7171 \ No newline at end of file diff --git a/test/shell1.test b/test/shell1.test index b08c08ffc0..87edc3c816 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -275,13 +275,11 @@ do_test shell1-3.2.4 { # .databases List names and files of attached databases do_test shell1-3.3.1 { - set x [catchcmd "-csv test.db" ".databases"] - set x [subst -nocommands -novariables $x] + catchcmd_collapse_space "-csv test.db" ".databases" } "/0.+main.+[string map {/ .} [string range [get_pwd] 0 10]].*/" do_test shell1-3.3.2 { # extra arguments ignored - set x [catchcmd "test.db" ".databases BAD"] - set x [subst -nocommands -novariables $x] + catchcmd_collapse_space "test.db" ".databases BAD" } "/0.+main.+[string map {/ .} [string range [get_pwd] 0 10]].*/" # .dump ?TABLE? ... Dump the database in an SQL text format diff --git a/test/tester.tcl b/test/tester.tcl index eadaf2eb31..75963e108d 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -823,6 +823,17 @@ proc catchcmd {db {cmd ""}} { list $rc $msg } +proc catchcmd_collapse_space {db {cmd ""}} { + global CLI + set out [open cmds.txt w] + puts $out $cmd + close $out + set line "exec $CLI $db < cmds.txt" + set rc [catch { eval $line } msg] + regsub -all {\s+} $msg { } msg + list $rc $msg +} + proc catchcmdex {db {cmd ""}} { global CLI set out [open cmds.txt w] From 82452480ea1d3e7bad96914a82377bda1ae10ed1 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 25 Mar 2016 17:19:57 +0000 Subject: [PATCH 531/570] In the Win32 VFS, avoid trying to use rand_s() on Windows CE. FossilOrigin-Name: 183350fa7cc6a5ab8bd0a86cab231a6e4c915890 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/os_win.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index b34eb55e70..8558fe1c18 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\scatchcmd_collapse_space\scommand\sand\suse\sit\sto\shelp\smake\sshell\stesting\nmore\srobust\sagainst\sTCL\sspace\sescapes. -D 2016-03-25T17:09:16.750 +C In\sthe\sWin32\sVFS,\savoid\strying\sto\suse\srand_s()\son\sWindows\sCE. +D 2016-03-25T17:19:57.501 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -338,7 +338,7 @@ F src/os.h 91ff889115ecd01f436d3611f7f5ea4dc12d92f1 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c b1ccb273771f41dbdbe0ba7c1ad63c38ad5972ec -F src/os_win.c 7c071f7f8f04827ab25a8f441080832be58688e9 +F src/os_win.c ff870d89f4cb088a04cbf5ea0cbd9ff1b089ff4a F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 38718a019ca762ba4f6795425d5a54db70d1790d F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 @@ -1459,7 +1459,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 99fd194c83dbcfcdcc582983b86678b85b1b9570 -R cfe872b896f4c791395847cc13daead3 -U drh -Z 0d389fd777e66fc5d8e3b6840aab7902 +P 93caabb66082f76ef161a51ac822b919517a7171 +R 5aa2c9bfd4173374520b94533760d2da +U mistachkin +Z 700a9aa1ab3cd081c3674af5a63a2d5f diff --git a/manifest.uuid b/manifest.uuid index aa0e2349f2..f363c251a7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -93caabb66082f76ef161a51ac822b919517a7171 \ No newline at end of file +183350fa7cc6a5ab8bd0a86cab231a6e4c915890 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index 7ae833d3f5..f64a7d43a7 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -5436,7 +5436,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ EntropyGatherer e; UNUSED_PARAMETER(pVfs); memset(zBuf, 0, nBuf); -#if defined(_MSC_VER) && _MSC_VER>=1400 +#if defined(_MSC_VER) && _MSC_VER>=1400 && !SQLITE_OS_WINCE rand_s((unsigned int*)zBuf); /* rand_s() is not available with MinGW */ #endif /* defined(_MSC_VER) && _MSC_VER>=1400 */ e.a = (unsigned char*)zBuf; From 4f69540b7168fc0d83e6191ae8e6c42d3c3d1946 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 25 Mar 2016 20:10:20 +0000 Subject: [PATCH 532/570] Do not run the shell3.test module under mingw because of mingw's dodgy command-line parsing. FossilOrigin-Name: a7c080a90a236fbc18b9a42b78dbed4dd8a25160 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/shell3.test | 7 +++++++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 8558fe1c18..b02404a99f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sWin32\sVFS,\savoid\strying\sto\suse\srand_s()\son\sWindows\sCE. -D 2016-03-25T17:19:57.501 +C Do\snot\srun\sthe\sshell3.test\smodule\sunder\smingw\sbecause\sof\smingw's\sdodgy\ncommand-line\sparsing. +D 2016-03-25T20:10:20.882 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1030,7 +1030,7 @@ F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 F test/shell1.test 12d1774936facc17a889e0c31877670ef5526f8c F test/shell2.test 2e7a32c9ee03c6398478637d72416d5b9ebd9777 -F test/shell3.test c39453d3012a39ffec944566eca8a6bda10a2284 +F test/shell3.test 1448cb715b8b5f139d96e0e4d3e94ae31fd0a713 F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9 F test/shell5.test 50a732c1c2158b1cd62cf53975ce1ea7ce6b9dc9 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 @@ -1459,7 +1459,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 93caabb66082f76ef161a51ac822b919517a7171 -R 5aa2c9bfd4173374520b94533760d2da -U mistachkin -Z 700a9aa1ab3cd081c3674af5a63a2d5f +P 183350fa7cc6a5ab8bd0a86cab231a6e4c915890 +R 9c42844e710d61bbe7fe13708d65edbf +U drh +Z ea11cf0717b5526a95e62f1683bac7ce diff --git a/manifest.uuid b/manifest.uuid index f363c251a7..7dafaa5910 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -183350fa7cc6a5ab8bd0a86cab231a6e4c915890 \ No newline at end of file +a7c080a90a236fbc18b9a42b78dbed4dd8a25160 \ No newline at end of file diff --git a/test/shell3.test b/test/shell3.test index 3ded8f5ccd..08d31f24eb 100644 --- a/test/shell3.test +++ b/test/shell3.test @@ -26,6 +26,13 @@ db close forcedelete test.db test.db-journal test.db-wal sqlite3 db test.db +if {[info exists env(MSYSCON)] && $env(MSYSCON)=="sh.exe"} { + puts "shell3 tests do not work with the mingw shell due to dodgy\ + command-line parsing" + finish_test + return +} + #---------------------------------------------------------------------------- # shell3-1.*: Basic tests for running SQL statments from command line. # From 15707ac992d801d2d637a0b59c21a9b7c6413cf5 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 26 Mar 2016 13:26:35 +0000 Subject: [PATCH 533/570] Update shell1.test tests to deal with backslash escaping in TCL on Windows-style pathnames. FossilOrigin-Name: 219a251e182bf43376fbc8ae1ce6f77f18a1b092 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/shell1.test | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index b02404a99f..71c59993da 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\srun\sthe\sshell3.test\smodule\sunder\smingw\sbecause\sof\smingw's\sdodgy\ncommand-line\sparsing. -D 2016-03-25T20:10:20.882 +C Update\sshell1.test\stests\sto\sdeal\swith\sbackslash\sescaping\sin\sTCL\son\sWindows-style\npathnames. +D 2016-03-26T13:26:35.335 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1028,7 +1028,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test 12d1774936facc17a889e0c31877670ef5526f8c +F test/shell1.test 25de3bf73c2a24fd3f0240396a3719d8679fd156 F test/shell2.test 2e7a32c9ee03c6398478637d72416d5b9ebd9777 F test/shell3.test 1448cb715b8b5f139d96e0e4d3e94ae31fd0a713 F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9 @@ -1459,7 +1459,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 183350fa7cc6a5ab8bd0a86cab231a6e4c915890 -R 9c42844e710d61bbe7fe13708d65edbf +P a7c080a90a236fbc18b9a42b78dbed4dd8a25160 +R 4fb0bc40e02c2e4ca004a6ff507130b3 U drh -Z ea11cf0717b5526a95e62f1683bac7ce +Z 2e9acf052ed53f3a7f143522bd4e6960 diff --git a/manifest.uuid b/manifest.uuid index 7dafaa5910..37f54adfef 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a7c080a90a236fbc18b9a42b78dbed4dd8a25160 \ No newline at end of file +219a251e182bf43376fbc8ae1ce6f77f18a1b092 \ No newline at end of file diff --git a/test/shell1.test b/test/shell1.test index 87edc3c816..44886b9f38 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -276,11 +276,11 @@ do_test shell1-3.2.4 { # .databases List names and files of attached databases do_test shell1-3.3.1 { catchcmd_collapse_space "-csv test.db" ".databases" -} "/0.+main.+[string map {/ .} [string range [get_pwd] 0 10]].*/" +} "/0.+main.+[string map {/ ".{1,2}"} [string range [get_pwd] 0 10]].*/" do_test shell1-3.3.2 { # extra arguments ignored catchcmd_collapse_space "test.db" ".databases BAD" -} "/0.+main.+[string map {/ .} [string range [get_pwd] 0 10]].*/" +} "/0.+main.+[string map {/ ".{1,2}"} [string range [get_pwd] 0 10]].*/" # .dump ?TABLE? ... Dump the database in an SQL text format # If TABLE specified, only dump tables matching From eaa544d44d7c06dc858a8acbd5b10852f2032dad Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 26 Mar 2016 14:41:13 +0000 Subject: [PATCH 534/570] Remove the catchcmd_collapse_space procedure in tester.tcl - no longer needed. FossilOrigin-Name: 3bd499d3bdf4e80f83513966c2ee9dd11e67cbd1 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/shell1.test | 4 ++-- test/tester.tcl | 11 ----------- 4 files changed, 10 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index 71c59993da..a1183f5492 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sshell1.test\stests\sto\sdeal\swith\sbackslash\sescaping\sin\sTCL\son\sWindows-style\npathnames. -D 2016-03-26T13:26:35.335 +C Remove\sthe\scatchcmd_collapse_space\sprocedure\sin\stester.tcl\s-\sno\slonger\sneeded. +D 2016-03-26T14:41:13.450 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1028,7 +1028,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test 25de3bf73c2a24fd3f0240396a3719d8679fd156 +F test/shell1.test d36a68f0d560b7f50177845e409910ed855b1a27 F test/shell2.test 2e7a32c9ee03c6398478637d72416d5b9ebd9777 F test/shell3.test 1448cb715b8b5f139d96e0e4d3e94ae31fd0a713 F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9 @@ -1088,7 +1088,7 @@ F test/tclsqlite.test c6d9f546f79d15d0134c1e06583fb3ee0c3afad3 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl 5604f2697e8fa9b12b6180122d84e1a9093ca8a3 +F test/tester.tcl f2b99e912d4da1e5755969b8614febd883885c8b F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1459,7 +1459,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 a7c080a90a236fbc18b9a42b78dbed4dd8a25160 -R 4fb0bc40e02c2e4ca004a6ff507130b3 +P 219a251e182bf43376fbc8ae1ce6f77f18a1b092 +R c56b0aa6959f9b74a14b039c91d81909 U drh -Z 2e9acf052ed53f3a7f143522bd4e6960 +Z 93b7eb233dfe81212bc718ee014c61a9 diff --git a/manifest.uuid b/manifest.uuid index 37f54adfef..bd4275f994 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -219a251e182bf43376fbc8ae1ce6f77f18a1b092 \ No newline at end of file +3bd499d3bdf4e80f83513966c2ee9dd11e67cbd1 \ No newline at end of file diff --git a/test/shell1.test b/test/shell1.test index 44886b9f38..8669559e44 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -275,11 +275,11 @@ do_test shell1-3.2.4 { # .databases List names and files of attached databases do_test shell1-3.3.1 { - catchcmd_collapse_space "-csv test.db" ".databases" + catchcmd "-csv test.db" ".databases" } "/0.+main.+[string map {/ ".{1,2}"} [string range [get_pwd] 0 10]].*/" do_test shell1-3.3.2 { # extra arguments ignored - catchcmd_collapse_space "test.db" ".databases BAD" + catchcmd "test.db" ".databases BAD" } "/0.+main.+[string map {/ ".{1,2}"} [string range [get_pwd] 0 10]].*/" # .dump ?TABLE? ... Dump the database in an SQL text format diff --git a/test/tester.tcl b/test/tester.tcl index 75963e108d..eadaf2eb31 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -823,17 +823,6 @@ proc catchcmd {db {cmd ""}} { list $rc $msg } -proc catchcmd_collapse_space {db {cmd ""}} { - global CLI - set out [open cmds.txt w] - puts $out $cmd - close $out - set line "exec $CLI $db < cmds.txt" - set rc [catch { eval $line } msg] - regsub -all {\s+} $msg { } msg - list $rc $msg -} - proc catchcmdex {db {cmd ""}} { global CLI set out [open cmds.txt w] From 60c4249fcc5bb322e3f380ad3181dbb381a7f404 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 26 Mar 2016 15:36:36 +0000 Subject: [PATCH 535/570] More changes to the shellN.test scripts to get them working on all variations of Windows. FossilOrigin-Name: 8213c2f58167243411d29cc58e303b4be656f756 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- test/shell1.test | 2 +- test/shell2.test | 2 +- test/shell3.test | 11 ++++++++--- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index a1183f5492..8d623daff5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\scatchcmd_collapse_space\sprocedure\sin\stester.tcl\s-\sno\slonger\sneeded. -D 2016-03-26T14:41:13.450 +C More\schanges\sto\sthe\sshellN.test\sscripts\sto\sget\sthem\sworking\son\sall\svariations\nof\sWindows. +D 2016-03-26T15:36:36.768 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1028,9 +1028,9 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test d36a68f0d560b7f50177845e409910ed855b1a27 -F test/shell2.test 2e7a32c9ee03c6398478637d72416d5b9ebd9777 -F test/shell3.test 1448cb715b8b5f139d96e0e4d3e94ae31fd0a713 +F test/shell1.test dff5b20ad989770aface6d714491121172dfe8b0 +F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b +F test/shell3.test da513d522ef6f01cee8475dcf8332bff8982b3dd F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9 F test/shell5.test 50a732c1c2158b1cd62cf53975ce1ea7ce6b9dc9 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 @@ -1459,7 +1459,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 219a251e182bf43376fbc8ae1ce6f77f18a1b092 -R c56b0aa6959f9b74a14b039c91d81909 +P 3bd499d3bdf4e80f83513966c2ee9dd11e67cbd1 +R 0f980ceb534899c3d74e7aadbdc990e8 U drh -Z 93b7eb233dfe81212bc718ee014c61a9 +Z 6df6f858842cee4837ac5cccff369bba diff --git a/manifest.uuid b/manifest.uuid index bd4275f994..23fb133ea2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3bd499d3bdf4e80f83513966c2ee9dd11e67cbd1 \ No newline at end of file +8213c2f58167243411d29cc58e303b4be656f756 \ No newline at end of file diff --git a/test/shell1.test b/test/shell1.test index 8669559e44..49b6a7923d 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -45,7 +45,7 @@ do_test shell1-1.1.1b { } {1 1} # error on extra options do_test shell1-1.1.2 { - catchcmd "test.db \"select 3\" \"select 4\"" "" + catchcmd "test.db \"select+3\" \"select+4\"" "" } {0 {3 4}} # error on extra options diff --git a/test/shell2.test b/test/shell2.test index 9388b719b3..2de6bf7514 100644 --- a/test/shell2.test +++ b/test/shell2.test @@ -43,7 +43,7 @@ do_test shell2-1.1.1 { # Shell silently ignores extra parameters. # Ticket [f5cb008a65]. do_test shell2-1.2.1 { - set rc [catch { eval exec $CLI \":memory:\" \"select 3\" \"select 4\" } msg] + set rc [catch { eval exec $CLI \":memory:\" \"select+3\" \"select+4\" } msg] list $rc $msg } {0 {3 4}} diff --git a/test/shell3.test b/test/shell3.test index 08d31f24eb..6e38021d0c 100644 --- a/test/shell3.test +++ b/test/shell3.test @@ -26,9 +26,14 @@ db close forcedelete test.db test.db-journal test.db-wal sqlite3 db test.db -if {[info exists env(MSYSCON)] && $env(MSYSCON)=="sh.exe"} { - puts "shell3 tests do not work with the mingw shell due to dodgy\ - command-line parsing" +# There are inconsistencies in command-line argument quoting on Windows. +# In particular, individual applications are responsible for command-line +# parsing in Windows, not the shell. Depending on whether the sqlite3.exe +# program is compiled with MinGW or MSVC, the command-line parsing is +# different. This causes problems for the tests below. To avoid +# issues, these tests are disabled for windows. +# +if {$::tcl_platform(platform)=="windows"} { finish_test return } From 72cd360caffca027211972e1189e26c8ad121995 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 28 Mar 2016 11:01:54 +0000 Subject: [PATCH 536/570] Fix the multiplexor so that it does not assume that the xGetLastError method is non-NULL in the child VFS. FossilOrigin-Name: f6a88cccbc0c62a0b453f4711298c9d5e1882b18 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/test_multiplex.c | 6 +++++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 8d623daff5..943c941a23 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C More\schanges\sto\sthe\sshellN.test\sscripts\sto\sget\sthem\sworking\son\sall\svariations\nof\sWindows. -D 2016-03-26T15:36:36.768 +C Fix\sthe\smultiplexor\sso\sthat\sit\sdoes\snot\sassume\sthat\sthe\sxGetLastError\smethod\nis\snon-NULL\sin\sthe\schild\sVFS. +D 2016-03-28T11:01:54.323 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -390,7 +390,7 @@ F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202 F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd F src/test_malloc.c 96df9381a1ff1f6d3805ff7231b9baf1386aaabf -F src/test_multiplex.c 6a088d8d9d4aad4bec45dd8878af11b15900702d +F src/test_multiplex.c 6a9de820fcaaf506c59aa14bc8693822333cea48 F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3 F src/test_mutex.c dbdfaff8580071f2212a0deae3325a93a737819c F src/test_onefile.c 38f7cbe79d5bafe95bde683cc3a53b8ca16daf10 @@ -1459,7 +1459,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 3bd499d3bdf4e80f83513966c2ee9dd11e67cbd1 -R 0f980ceb534899c3d74e7aadbdc990e8 +P 8213c2f58167243411d29cc58e303b4be656f756 +R 345c74a0cb9568a53ff6b8825c4a812b U drh -Z 6df6f858842cee4837ac5cccff369bba +Z 80e7037d98d6e1826970b484373d3274 diff --git a/manifest.uuid b/manifest.uuid index 23fb133ea2..7c1af05774 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8213c2f58167243411d29cc58e303b4be656f756 \ No newline at end of file +f6a88cccbc0c62a0b453f4711298c9d5e1882b18 \ No newline at end of file diff --git a/src/test_multiplex.c b/src/test_multiplex.c index 82845ea7e1..07dcbbc1aa 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -717,7 +717,11 @@ static int multiplexCurrentTime(sqlite3_vfs *a, double *b){ return gMultiplex.pOrigVfs->xCurrentTime(gMultiplex.pOrigVfs, b); } static int multiplexGetLastError(sqlite3_vfs *a, int b, char *c){ - return gMultiplex.pOrigVfs->xGetLastError(gMultiplex.pOrigVfs, b, c); + if( gMultiplex.pOrigVfs->xGetLastError ){ + return gMultiplex.pOrigVfs->xGetLastError(gMultiplex.pOrigVfs, b, c); + }else{ + return 0; + } } static int multiplexCurrentTimeInt64(sqlite3_vfs *a, sqlite3_int64 *b){ return gMultiplex.pOrigVfs->xCurrentTimeInt64(gMultiplex.pOrigVfs, b); From 10df23fe4f73a8eb1bd820f22b6e65e3bcbfd09d Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 29 Mar 2016 10:14:15 +0000 Subject: [PATCH 537/570] Version 3.12.0 FossilOrigin-Name: e9bb4cf40f4971974a74468ef922bdee481c988b --- manifest | 11 +++++++---- manifest.uuid | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/manifest b/manifest index 943c941a23..769e820b33 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\smultiplexor\sso\sthat\sit\sdoes\snot\sassume\sthat\sthe\sxGetLastError\smethod\nis\snon-NULL\sin\sthe\schild\sVFS. -D 2016-03-28T11:01:54.323 +C Version\s3.12.0 +D 2016-03-29T10:14:15.762 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1459,7 +1459,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8213c2f58167243411d29cc58e303b4be656f756 +P f6a88cccbc0c62a0b453f4711298c9d5e1882b18 R 345c74a0cb9568a53ff6b8825c4a812b +T +bgcolor * #d0c0ff +T +sym-relaese * +T +sym-version-3.12.0 * U drh -Z 80e7037d98d6e1826970b484373d3274 +Z 9c957a50c25c5de44ce9010b47906f30 diff --git a/manifest.uuid b/manifest.uuid index 7c1af05774..21845f2bab 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f6a88cccbc0c62a0b453f4711298c9d5e1882b18 \ No newline at end of file +e9bb4cf40f4971974a74468ef922bdee481c988b \ No newline at end of file From fbcd3130f6b11d4037917284a9ccf6b839dd5ee4 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 30 Mar 2016 12:20:24 +0000 Subject: [PATCH 538/570] Improvements to the performance testing program "speedtest1.c" and the shell script that invokes it. FossilOrigin-Name: e4bee561fdead5d35c24da3fe8a11bf6548550c6 --- manifest | 17 +++++++---------- manifest.uuid | 2 +- test/speedtest1.c | 3 ++- tool/run-speed-test.sh | 36 +++++++++++++++++++++++++++++------- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 769e820b33..0b01f20998 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Version\s3.12.0 -D 2016-03-29T10:14:15.762 +C Improvements\sto\sthe\sperformance\stesting\sprogram\s"speedtest1.c"\sand\sthe\nshell\sscript\sthat\sinvokes\sit. +D 2016-03-30T12:20:24.594 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -1060,7 +1060,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523 F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b -F test/speedtest1.c 1478cb3fb64ad30f291ddca87ca9dbd72ff552aa +F test/speedtest1.c 21af8db2492a903835b654517ac8d90aed0af91f F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3 F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33 @@ -1412,7 +1412,7 @@ F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b F tool/replace.tcl 7727c60a04299b65a92f5e1590896fea0f25b9e0 F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5 -F tool/run-speed-test.sh 0ae485af4fe9f826e2b494be8c81f8ca9e222a4a +F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076 F tool/showdb.c 82dca79a999b2701c62417636345e9974151fdad F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818 F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68 @@ -1459,10 +1459,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 f6a88cccbc0c62a0b453f4711298c9d5e1882b18 -R 345c74a0cb9568a53ff6b8825c4a812b -T +bgcolor * #d0c0ff -T +sym-relaese * -T +sym-version-3.12.0 * +P e9bb4cf40f4971974a74468ef922bdee481c988b +R 4acc2ba84abf0860d40142ef07554f22 U drh -Z 9c957a50c25c5de44ce9010b47906f30 +Z 4975a52cd95acaed6ad2d9bf0b3f9807 diff --git a/manifest.uuid b/manifest.uuid index 21845f2bab..3d3b955b01 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e9bb4cf40f4971974a74468ef922bdee481c988b \ No newline at end of file +e4bee561fdead5d35c24da3fe8a11bf6548550c6 \ No newline at end of file diff --git a/test/speedtest1.c b/test/speedtest1.c index d7f2af47b8..8ed0424f88 100644 --- a/test/speedtest1.c +++ b/test/speedtest1.c @@ -1236,7 +1236,8 @@ int main(int argc, char **argv){ int rc; /* API return code */ /* Display the version of SQLite being tested */ - printf("Speedtest1 for SQLite %s %.50s\n", sqlite3_libversion(), sqlite3_sourceid()); + printf("-- Speedtest1 for SQLite %s %.50s\n", + sqlite3_libversion(), sqlite3_sourceid()); /* Process command-line arguments */ g.zWR = ""; diff --git a/tool/run-speed-test.sh b/tool/run-speed-test.sh index ee2ceac660..0e970ea0f6 100644 --- a/tool/run-speed-test.sh +++ b/tool/run-speed-test.sh @@ -12,7 +12,7 @@ # # summary-$BASE.txt # Copy of standard output # cout-$BASE.txt # cachegrind output -# explain-$BASE.txt # EXPLAIN listings +# explain-$BASE.txt # EXPLAIN listings (only with --explain) # if test "$1" = "" then @@ -21,9 +21,10 @@ then fi NAME=$1 shift -CC_OPTS="-DSQLITE_ENABLE_RTREE" -SPEEDTEST_OPTS="--shrink-memory --reprepare" +CC_OPTS="-DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_MEMSYS5" +SPEEDTEST_OPTS="--shrink-memory --reprepare --heap 10000000 64" SIZE=5 +doExplain=0 while test "$1" != ""; do case $1 in --reprepare) @@ -35,12 +36,29 @@ while test "$1" != ""; do --utf16be) SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1" ;; + --stats) + SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1" + ;; --without-rowid) SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1" ;; + --nomemstat) + SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1" + ;; + --wal) + SPEEDTEST_OPTS="$SPEEDTEST_OPTS --journal wal" + ;; --size) shift; SIZE=$1 ;; + --explain) + doExplain=1 + ;; + --heap) + CC_OPTS="$CC_OPTS -DSQLITE_ENABLE_MEMSYS5" + shift; + SPEEDTEST_OPTS="$SPEEDTEST_OPTS --heap $1 64" + ;; *) CC_OPTS="$CC_OPTS $1" ;; @@ -54,9 +72,11 @@ echo "CC_OPTS = $CC_OPTS" | tee -a summary-$NAME.txt rm -f cachegrind.out.* speedtest1 speedtest1.db sqlite3.o gcc -g -Os -Wall -I. $CC_OPTS -c sqlite3.c size sqlite3.o | tee -a summary-$NAME.txt -gcc -g -Os -Wall -I. $CC_OPTS \ - -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ - ./shell.c ./sqlite3.c -o sqlite3 -ldl -lpthread +if test $doExplain -eq 1; then + gcc -g -Os -Wall -I. $CC_OPTS \ + -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ + ./shell.c ./sqlite3.c -o sqlite3 -ldl -lpthread +fi SRC=./speedtest1.c gcc -g -Os -Wall -I. $CC_OPTS $SRC ./sqlite3.o -o speedtest1 -ldl -lpthread ls -l speedtest1 | tee -a summary-$NAME.txt @@ -65,4 +85,6 @@ valgrind --tool=cachegrind ./speedtest1 speedtest1.db \ size sqlite3.o | tee -a summary-$NAME.txt wc sqlite3.c cg_anno.tcl cachegrind.out.* >cout-$NAME.txt -./speedtest1 --explain $SPEEDTEST_OPTS | ./sqlite3 >explain-$NAME.txt +if test $doExplain -eq 1; then + ./speedtest1 --explain $SPEEDTEST_OPTS | ./sqlite3 >explain-$NAME.txt +fi From 74c3302fd1931b0f4a10c9c660dbf368502efbbb Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 30 Mar 2016 12:56:55 +0000 Subject: [PATCH 539/570] Avoid compiler warnings and excess opcodes when SQLITE_ENABLE_PREUPDATE_HOOK is not used. Fix the EXPLAIN output for P4_TABLE opcodes. FossilOrigin-Name: 5ab46d760dff327491703478d6d7c7c44a0147ca --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/update.c | 6 ++++++ src/vdbe.c | 13 ++++++++++--- src/vdbeInt.h | 5 +++-- src/vdbeaux.c | 6 ++++++ 6 files changed, 35 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index a2911f768d..bb8ac6846d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\schanges\sfor\s3.12.0. -D 2016-03-29T10:19:29.541 +C Avoid\scompiler\swarnings\sand\sexcess\sopcodes\swhen\sSQLITE_ENABLE_PREUPDATE_HOOK\nis\snot\sused.\s\sFix\sthe\sEXPLAIN\soutput\sfor\sP4_TABLE\sopcodes. +D 2016-03-30T12:56:55.161 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e6ee58b849c116d5554024f524cbf61f064f6f01 @@ -435,15 +435,15 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 3d338cdd00d916ce8a05c397001d64ed58e6fe1c F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 -F src/update.c 14c6916d0194a7f25ad429292f4831b8c31e93d9 +F src/update.c 3e67ab3c0814635f355fb1f8ab010a2b9e016e7d F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 8873d696c9ccc4206058c402e09e101f1b81561a F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 -F src/vdbe.c da8f4d04fb134d7e64fd34d519b0eba4883ed779 +F src/vdbe.c 04e0606bc0505924036a974759703af6a3664904 F src/vdbe.h c16ba943d407baa1c7085eefea73a063fc631863 -F src/vdbeInt.h 9b704336a69f62ba189eafb06a46171e3463d27b +F src/vdbeInt.h ddb157974436d87652de7dc641f7191496d9a8cd F src/vdbeapi.c ba85b78fe08dc4a9ce747e62c89a2b4a4547e74c -F src/vdbeaux.c 03b2a622bf7714153bf06f9a6789e94aad9a5f89 +F src/vdbeaux.c fa06ba5441714160ab5f64422660ee286968672f F src/vdbeblob.c c9f2f494b911c6fa34efd9803f0a10807da80f77 F src/vdbemem.c 5cfef60e60e19cab6275d1b975bf4c791d575beb F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062 @@ -1480,7 +1480,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 beb5ea1439995fb8ab112451a8ffcc08fe42d0c4 e9bb4cf40f4971974a74468ef922bdee481c988b -R 491d941731d06e3edceeb8f36a9265ac +P ed22eb653f2809446ace6a27e7ea3926ac6db30c +R 5630f9e5708bbc437f2437f3c1df072c U drh -Z 3f9fc483108428866f896f452f439d76 +Z eacbad43019a9bff0f7b72fbe90e323f diff --git a/manifest.uuid b/manifest.uuid index b49c17cf93..a44439793a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ed22eb653f2809446ace6a27e7ea3926ac6db30c \ No newline at end of file +5ab46d760dff327491703478d6d7c7c44a0147ca \ No newline at end of file diff --git a/src/update.c b/src/update.c index c147eaaad9..7b38c5bcc5 100644 --- a/src/update.c +++ b/src/update.c @@ -601,6 +601,7 @@ void sqlite3Update( ** is the column index supplied by the user. */ assert( regNew==regNewRowid+1 ); +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK sqlite3VdbeAddOp3(v, OP_Delete, iDataCur, OPFLAG_ISUPDATE | ((hasFK || chngKey || pPk!=0) ? 0 : OPFLAG_ISNOOP), regNewRowid @@ -608,6 +609,11 @@ void sqlite3Update( if( !pParse->nested ){ sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE); } +#else + if( hasFK || chngKey || pPk!=0 ){ + sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); + } +#endif if( bReplace || chngKey ){ sqlite3VdbeJumpHere(v, addr1); } diff --git a/src/vdbe.c b/src/vdbe.c index 18e955c0ff..787d2b7b48 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -91,9 +91,9 @@ static void updateMaxBlobsize(Mem *p){ ** hook are enabled for database connect DB. */ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK -# define HAS_UPDATE_HOOK(DB) ((DB)->xPreUpdateCallback||(DB)->xUpdateCallback) +# define HAS_UPDATE_HOOK(DB) ((DB)->xPreUpdateCallback||(DB)->xUpdateCallback) #else -# define HAS_UPDATE_HOOK(DB) ((DB)->xUpdateCallback) +# define HAS_UPDATE_HOOK(DB) ((DB)->xUpdateCallback) #endif /* @@ -4287,8 +4287,9 @@ case OP_InsertInt: { int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */ const char *zDb; /* database name - used by the update hook */ Table *pTab; /* Table structure - used by update and pre-update hooks */ - int op = 0; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ + int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ + op = 0; pData = &aMem[pOp->p2]; assert( pOp->p1>=0 && pOp->p1nCursor ); assert( memIsValid(pData) ); @@ -4317,6 +4318,9 @@ case OP_InsertInt: { zDb = db->aDb[pC->iDb].zName; pTab = pOp->p4.pTab; op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); + }else{ + pTab = 0; /* Not needed. Silence a comiler warning. */ + zDb = 0; /* Not needed. Silence a compiler warning. */ } #ifdef SQLITE_ENABLE_PREUPDATE_HOOK @@ -4431,6 +4435,9 @@ case OP_Delete: { if( pOp->p5 && pC->isTable ){ sqlite3BtreeKeySize(pC->uc.pCursor, &pC->movetoTarget); } + }else{ + zDb = 0; /* Not needed. Silence a compiler warning. */ + pTab = 0; /* Not needed. Silence a compiler warning. */ } #ifdef SQLITE_ENABLE_PREUPDATE_HOOK diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 1218009d0a..61561e9dce 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -506,8 +506,9 @@ int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); int sqlite3VdbeCloseStatement(Vdbe *, int); void sqlite3VdbeFrameDelete(VdbeFrame*); int sqlite3VdbeFrameRestore(VdbeFrame *); -void sqlite3VdbePreUpdateHook( - Vdbe *, VdbeCursor *, int, const char*, Table *, i64, int); +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK +void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int); +#endif int sqlite3VdbeTransferError(Vdbe *p); int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 932821f383..48d1b5ae15 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1318,6 +1318,10 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ zTemp[0] = 0; break; } + case P4_TABLE: { + sqlite3XPrintf(&x, "%s", pOp->p4.pTab->zName); + break; + } default: { zP4 = pOp->p4.z; if( zP4==0 ){ @@ -4509,7 +4513,9 @@ static void vdbeFreeUnpacked(sqlite3 *db, UnpackedRecord *p){ sqlite3DbFree(db, p); } } +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** Invoke the pre-update hook. If this is an UPDATE or DELETE pre-update call, ** then cursor passed as the second argument should point to the row about From 3875a96ad9d33650ac37996df92c43f564663054 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 30 Mar 2016 14:17:36 +0000 Subject: [PATCH 540/570] Remove a redundant test for disabling RESTRICT with defer_foreign_keys=ON. FossilOrigin-Name: 9cdf813c6aaaddc01d2d4e04636c83fcda04d971 --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/fkey.c | 4 ---- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index f94cbc8139..bdf6e1ef9f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Incorporate\sthe\ssessions\sextension\sand\sthe\nSQLITE_ENABLE_PREUPDATE_HOOK\scompile-time\soption. -D 2016-03-30T13:43:09.573 +C Remove\sa\sredundant\stest\sfor\sdisabling\sRESTRICT\swith\sdefer_foreign_keys=ON. +D 2016-03-30T14:17:36.686 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e6ee58b849c116d5554024f524cbf61f064f6f01 @@ -329,7 +329,7 @@ F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b F src/delete.c eeac28b3d3d88e3541bdf93e91ea7492a7b67842 F src/expr.c 289ffac5240b60fee0a824d3d5ab2d7bd2630c94 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c 5da47ff524e2f687997a74737ce598f043e1342a +F src/fkey.c 4c0bd09e602b8ae8d36d81e31e4872d0b53c87bb F src/func.c 552d300265aed09eea21f68ac742a440550c0062 F src/global.c 884d4c7eba9f5fc25c96a23b21520da19b7713e2 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 @@ -1480,8 +1480,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 e4bee561fdead5d35c24da3fe8a11bf6548550c6 5ab46d760dff327491703478d6d7c7c44a0147ca -R 9dafbaa8421126ca3296fa72ec1f46aa -T +closed 5ab46d760dff327491703478d6d7c7c44a0147ca +P 4af7a90f980ade3566fc5da2f0db2669ac7d8256 +R 8a337360e7d496c90cf72795a6dab55f U drh -Z ca91103b707261c36c558c8ac5546192 +Z d1fd34700ce8bf6be699758638dac3cb diff --git a/manifest.uuid b/manifest.uuid index 9549a9a3b1..c0d0673209 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4af7a90f980ade3566fc5da2f0db2669ac7d8256 \ No newline at end of file +9cdf813c6aaaddc01d2d4e04636c83fcda04d971 \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index 4f2740ec30..fa19fbc1ce 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -1165,11 +1165,7 @@ static Trigger *fkActionTrigger( if( action==OE_Restrict && (db->flags & SQLITE_DeferFKs) ){ return 0; } - pTrigger = pFKey->apTrigger[iAction]; - if( (db->flags & SQLITE_DeferFKs) && action==OE_Restrict ){ - return 0; - } if( action!=OE_None && !pTrigger ){ char const *zFrom; /* Name of child table */ From 9fc4caf64c67cfcc91339924cde9cc37e1eaa78a Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 30 Mar 2016 14:26:36 +0000 Subject: [PATCH 541/570] Increase the version number to 3.13.0 on account of the new session extension. FossilOrigin-Name: e9bcd5acb9ab7b3d55c96519ca10f51f35e24cd9 --- VERSION | 2 +- configure | 18 +++++++++--------- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/VERSION b/VERSION index 92536a9e48..4eba2a62eb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.12.0 +3.13.0 diff --git a/configure b/configure index 8363818c6f..27cb1ea0b9 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sqlite 3.12.0. +# Generated by GNU Autoconf 2.69 for sqlite 3.13.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -726,8 +726,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' -PACKAGE_VERSION='3.12.0' -PACKAGE_STRING='sqlite 3.12.0' +PACKAGE_VERSION='3.13.0' +PACKAGE_STRING='sqlite 3.13.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1460,7 +1460,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sqlite 3.12.0 to adapt to many kinds of systems. +\`configure' configures sqlite 3.13.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1525,7 +1525,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.12.0:";; + short | recursive ) echo "Configuration of sqlite 3.13.0:";; esac cat <<\_ACEOF @@ -1646,7 +1646,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.12.0 +sqlite configure 3.13.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2065,7 +2065,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sqlite $as_me 3.12.0, which was +It was created by sqlite $as_me 3.13.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -12079,7 +12079,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sqlite $as_me 3.12.0, which was +This file was extended by sqlite $as_me 3.13.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12145,7 +12145,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sqlite config.status 3.12.0 +sqlite config.status 3.13.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/manifest b/manifest index bdf6e1ef9f..c6e2c51338 100644 --- a/manifest +++ b/manifest @@ -1,10 +1,10 @@ -C Remove\sa\sredundant\stest\sfor\sdisabling\sRESTRICT\swith\sdefer_foreign_keys=ON. -D 2016-03-30T14:17:36.686 +C Increase\sthe\sversion\snumber\sto\s3.13.0\son\saccount\sof\sthe\snew\ssession\sextension. +D 2016-03-30T14:26:36.915 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e6ee58b849c116d5554024f524cbf61f064f6f01 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 -F VERSION c6b1f51809551d60ad001e6d87cf3ab2c7f54b6f +F VERSION 5d234da9b5dae329fab75ff75884cfe0a9cb3fda F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 @@ -30,7 +30,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 -F configure c01a159fdf7ea0171ad01ce2937283f2c7972bde x +F configure dbd42c55ca6b65e0fb37ef54121755f26a890edf x F configure.ac 89e4e02a83d8a1528011f8395621b8c3186b4089 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/lemon.html e2118945e5f07ed146b45c9cd2b2dd6eabb8ebf2 @@ -1480,7 +1480,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 4af7a90f980ade3566fc5da2f0db2669ac7d8256 -R 8a337360e7d496c90cf72795a6dab55f +P 9cdf813c6aaaddc01d2d4e04636c83fcda04d971 +R 7a69958e274665351e7e782b27ccbb0b U drh -Z d1fd34700ce8bf6be699758638dac3cb +Z fc241d926edbc77d507e66ad4423e83d diff --git a/manifest.uuid b/manifest.uuid index c0d0673209..5ef2f2b86c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9cdf813c6aaaddc01d2d4e04636c83fcda04d971 \ No newline at end of file +e9bcd5acb9ab7b3d55c96519ca10f51f35e24cd9 \ No newline at end of file From c556f3c33f54e6e1de9163c6710bc4fe7498278c Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 30 Mar 2016 15:30:07 +0000 Subject: [PATCH 542/570] Simplifications and clarification to update callback handling in the OP_Delete and OP_Insert opcodes. FossilOrigin-Name: 47887ef89ed60ddb869d65e0957c1c4b2115f169 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/sqliteInt.h | 5 ++--- src/vdbe.c | 14 +++++++------- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index c6e2c51338..b61de4df04 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Increase\sthe\sversion\snumber\sto\s3.13.0\son\saccount\sof\sthe\snew\ssession\sextension. -D 2016-03-30T14:26:36.915 +C Simplifications\sand\sclarification\sto\supdate\scallback\shandling\sin\sthe\nOP_Delete\sand\sOP_Insert\sopcodes. +D 2016-03-30T15:30:07.231 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e6ee58b849c116d5554024f524cbf61f064f6f01 @@ -378,7 +378,7 @@ F src/shell.c cd3f82fdc5c895b817a375b7ab8319cb41f447ce F src/sqlite.h.in a1d7a367997f80c7075303aaf73e5fc46261c11c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 -F src/sqliteInt.h 410bd07098423b887874d9d2ff9ed6f8e3284839 +F src/sqliteInt.h 594bf31a7a0cc788688ca947e562576e23bd7904 F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -439,7 +439,7 @@ F src/update.c 3e67ab3c0814635f355fb1f8ab010a2b9e016e7d F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 8873d696c9ccc4206058c402e09e101f1b81561a F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 -F src/vdbe.c 04e0606bc0505924036a974759703af6a3664904 +F src/vdbe.c 0f0e4a6255f9a5272857a818314d081db26bcd90 F src/vdbe.h c16ba943d407baa1c7085eefea73a063fc631863 F src/vdbeInt.h ddb157974436d87652de7dc641f7191496d9a8cd F src/vdbeapi.c ba85b78fe08dc4a9ce747e62c89a2b4a4547e74c @@ -1480,7 +1480,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 9cdf813c6aaaddc01d2d4e04636c83fcda04d971 -R 7a69958e274665351e7e782b27ccbb0b +P e9bcd5acb9ab7b3d55c96519ca10f51f35e24cd9 +R 7d699e46158684aaeb0674ba8ed1262b U drh -Z fc241d926edbc77d507e66ad4423e83d +Z 8edbe6879cd34861bc153d7b5712adb5 diff --git a/manifest.uuid b/manifest.uuid index 5ef2f2b86c..7ffd9886fc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e9bcd5acb9ab7b3d55c96519ca10f51f35e24cd9 \ No newline at end of file +47887ef89ed60ddb869d65e0957c1c4b2115f169 \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 85004035ba..d789cc00e4 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2927,9 +2927,6 @@ struct AuthContext { /* ** Bitfield flags for P5 value in various opcodes. -** -** Note that the values for ISNOOP and LENGTHARG are the same. But as -** those bits are never used on the same opcode, the overlap is harmless. */ #define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */ /* Also used in P2 (not P5) of OP_Delete */ @@ -2938,7 +2935,9 @@ struct AuthContext { #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK #define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */ +#endif #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ diff --git a/src/vdbe.c b/src/vdbe.c index 787d2b7b48..84a5087e01 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4317,6 +4317,7 @@ case OP_InsertInt: { assert( pC->iDb>=0 ); zDb = db->aDb[pC->iDb].zName; pTab = pOp->p4.pTab; + assert( HasRowid(pTab) ); op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); }else{ pTab = 0; /* Not needed. Silence a comiler warning. */ @@ -4328,7 +4329,6 @@ case OP_InsertInt: { if( db->xPreUpdateCallback && pOp->p4type==P4_TABLE && !(pOp->p5 & OPFLAG_ISUPDATE) - && HasRowid(pTab) ){ sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, iKey, pOp->p2); } @@ -4357,7 +4357,7 @@ case OP_InsertInt: { /* Invoke the update-hook if required. */ if( rc ) goto abort_due_to_error; - if( db->xUpdateCallback && op && HasRowid(pTab) ){ + if( db->xUpdateCallback && op ){ db->xUpdateCallback(db->pUpdateArg, op, zDb, pTab->zName, iKey); } break; @@ -4428,11 +4428,12 @@ case OP_Delete: { ** of p4.pTab. Finally, if p5 is true, indicating that this cursor was ** last moved with OP_Next or OP_Prev, not Seek or NotFound, set ** VdbeCursor.movetoTarget to the current rowid. */ - if( pOp->p4.pTab && HAS_UPDATE_HOOK(db) ){ + if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ assert( pC->iDb>=0 ); + assert( pOp->p4.pTab!=0 ); zDb = db->aDb[pC->iDb].zName; pTab = pOp->p4.pTab; - if( pOp->p5 && pC->isTable ){ + if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){ sqlite3BtreeKeySize(pC->uc.pCursor, &pC->movetoTarget); } }else{ @@ -4450,9 +4451,8 @@ case OP_Delete: { pOp->p3 ); } -#endif - if( opflags & OPFLAG_ISNOOP ) break; +#endif /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 ); @@ -4480,7 +4480,7 @@ case OP_Delete: { /* Invoke the update-hook if required. */ if( opflags & OPFLAG_NCHANGE ){ p->nChange++; - if( rc==SQLITE_OK && db->xUpdateCallback && HasRowid(pTab) ){ + if( db->xUpdateCallback && HasRowid(pTab) ){ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName, pC->movetoTarget); assert( pC->iDb>=0 ); From b932bf63e6806e31c8cfea56ed21dfcfc2717fc9 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 30 Mar 2016 16:22:18 +0000 Subject: [PATCH 543/570] Fix typo in comment. No changes to code. FossilOrigin-Name: 64d75cbe2c45af67124fa7ce5688d91cc6ddb755 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/sqlite.h.in | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index b61de4df04..572118f49d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplifications\sand\sclarification\sto\supdate\scallback\shandling\sin\sthe\nOP_Delete\sand\sOP_Insert\sopcodes. -D 2016-03-30T15:30:07.231 +C Fix\stypo\sin\scomment.\s\sNo\schanges\sto\scode. +D 2016-03-30T16:22:18.401 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e6ee58b849c116d5554024f524cbf61f064f6f01 @@ -375,7 +375,7 @@ F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 7849cee0a01952a9c93cd28989daedfa57731143 F src/shell.c cd3f82fdc5c895b817a375b7ab8319cb41f447ce -F src/sqlite.h.in a1d7a367997f80c7075303aaf73e5fc46261c11c +F src/sqlite.h.in 843a0dfcf8c5e961cfafa62009fed0867b88241e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 F src/sqliteInt.h 594bf31a7a0cc788688ca947e562576e23bd7904 @@ -1480,7 +1480,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 e9bcd5acb9ab7b3d55c96519ca10f51f35e24cd9 -R 7d699e46158684aaeb0674ba8ed1262b -U drh -Z 8edbe6879cd34861bc153d7b5712adb5 +P 47887ef89ed60ddb869d65e0957c1c4b2115f169 +R b936f16f86444f27d224909ef15c00ab +U mistachkin +Z ee43622ecca2631579c58c415c88d4a1 diff --git a/manifest.uuid b/manifest.uuid index 7ffd9886fc..ac46899c6a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -47887ef89ed60ddb869d65e0957c1c4b2115f169 \ No newline at end of file +64d75cbe2c45af67124fa7ce5688d91cc6ddb755 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index c9b80d6567..35de70ff7f 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8014,7 +8014,7 @@ SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); ** CAPI3REF: Low-level system error code ** ** ^Attempt to return the underlying operating system error code or error -** number that caused the most reason I/O error or failure to open a file. +** number that caused the most recent I/O error or failure to open a file. ** The return value is OS-dependent. For example, on unix systems, after ** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be ** called to get back the underlying "errno" that caused the problem, such From 05004784a50504c6e34f512a103b7c0dc7e9fa35 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 30 Mar 2016 16:23:06 +0000 Subject: [PATCH 544/570] Updates for the MSVC makefiles. FossilOrigin-Name: 7cf0cab730e2d570c82dd789279ad6501ac598c8 --- Makefile.msc | 36 +++++++++++------------------------- autoconf/Makefile.msc | 2 ++ manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 21 insertions(+), 33 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index a6a2394a6a..84c2eac2f4 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -264,6 +264,8 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1 !ENDIF # These are the "extended" SQLite compilation options used when compiling for @@ -784,14 +786,6 @@ RCC = $(RCC) -DSQLITE_TEMP_STORE=1 # The same set of OMIT and ENABLE flags should be passed to the # LEMON parser generator and the mkkeywordhash tool as well. -# BEGIN standard options -OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 -OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 -OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 -OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1 -OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1 -# END standard options - # These are the required SQLite compilation options used when compiling for # the Windows platform. # @@ -1189,9 +1183,7 @@ SRC07 = \ $(TOP)\ext\fts3\fts3_write.c \ $(TOP)\ext\icu\icu.c \ $(TOP)\ext\rtree\rtree.c \ - $(TOP)\ext\session\sqlite3session.h \ $(TOP)\ext\session\sqlite3session.c \ - $(TOP)\ext\rbu\sqlite3rbu.h \ $(TOP)\ext\rbu\sqlite3rbu.c \ $(TOP)\ext\misc\json1.c @@ -1214,7 +1206,8 @@ SRC09 = \ $(TOP)\ext\fts3\fts3_tokenizer.h \ $(TOP)\ext\icu\sqliteicu.h \ $(TOP)\ext\rtree\rtree.h \ - $(TOP)\ext\rbu\sqlite3rbu.h + $(TOP)\ext\rbu\sqlite3rbu.h \ + $(TOP)\ext\session\sqlite3session.h # Generated source code files # @@ -1280,8 +1273,8 @@ TESTSRC = \ $(TOP)\src\test_wsd.c \ $(TOP)\ext\fts3\fts3_term.c \ $(TOP)\ext\fts3\fts3_test.c \ - $(TOP)\ext\session\test_session.c \ - $(TOP)\ext\rbu\test_rbu.c + $(TOP)\ext\rbu\test_rbu.c \ + $(TOP)\ext\session\test_session.c # Statically linked extensions. # @@ -1312,14 +1305,7 @@ TESTSRC2 = \ $(SRC06) \ $(SRC07) \ $(SRC10) \ - $(TOP)\ext\async\sqlite3async.c \ - $(TOP)\ext\session\sqlite3session.c - -# Source code to the library files needed by the test fixture -# (amalgamation) -# -TESTSRC3 = - + $(TOP)\ext\async\sqlite3async.c # Header files used by all library source files. # @@ -1897,7 +1883,7 @@ rtree.lo: $(TOP)\ext\rtree\rtree.c $(HDR) $(EXTHDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\rtree\rtree.c sqlite3session.lo: $(TOP)\ext\session\sqlite3sesion.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\session\sqlite3session.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\session\sqlite3session.c # FTS5 things # @@ -1955,7 +1941,7 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024 TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) -TESTFIXTURE_SRC1 = $(TESTEXT) $(TESTSRC3) $(SQLITE3C) +TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C) !IF $(USE_AMALGAMATION)==0 TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0) !ELSE @@ -2047,8 +2033,8 @@ showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H) $(TOP)\tool\showwal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) - $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ - $(TOP)\ext\session\changeset.c $(SQLITE3C) + $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ + $(TOP)\ext\session\changeset.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index ad829bffa0..ed99ce9587 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -249,6 +249,8 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1 !ENDIF # These are the "extended" SQLite compilation options used when compiling for diff --git a/manifest b/manifest index 572118f49d..c602040523 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Fix\stypo\sin\scomment.\s\sNo\schanges\sto\scode. -D 2016-03-30T16:22:18.401 +C Updates\sfor\sthe\sMSVC\smakefiles. +D 2016-03-30T16:23:06.801 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc e6ee58b849c116d5554024f524cbf61f064f6f01 +F Makefile.msc cde766eb7c27a7ca42000e66c5f0c37a17a05998 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 5d234da9b5dae329fab75ff75884cfe0a9cb3fda F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -11,7 +11,7 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 42f7eb1fb2b06ddd6c6adab3e4388cc0a237ba40 -F autoconf/Makefile.msc b8ada5177e6f39c126a88295af5ad0255e08d280 +F autoconf/Makefile.msc dc0d0500e4a827cb3891d08d846dd6dd40241b51 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1 F autoconf/configure.ac d807b567f73a2b0986ccdd206b782cecb4d08fff @@ -1480,7 +1480,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 47887ef89ed60ddb869d65e0957c1c4b2115f169 -R b936f16f86444f27d224909ef15c00ab +P 64d75cbe2c45af67124fa7ce5688d91cc6ddb755 +R 77269b95e931ac6cca96bcd2fa718a38 U mistachkin -Z ee43622ecca2631579c58c415c88d4a1 +Z 37f983898af724eda9f571ecd8a4d862 diff --git a/manifest.uuid b/manifest.uuid index ac46899c6a..2aa68317b9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -64d75cbe2c45af67124fa7ce5688d91cc6ddb755 \ No newline at end of file +7cf0cab730e2d570c82dd789279ad6501ac598c8 \ No newline at end of file From d91515267744eeb5be69ed2b97d93ea958cd8746 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 30 Mar 2016 21:19:00 +0000 Subject: [PATCH 545/570] Have the sqlite3session_apply() function and its streaming equivalent retry any operations that failed with SQLITE_CONSTRAINT after all other operations on the same table have been attempted. New code is largely untested. FossilOrigin-Name: 1085911afb51744f32fe9db183b50e8e88bdd73e --- ext/session/session1.test | 4 +- ext/session/sessionG.test | 66 +++++++++++++ ext/session/sqlite3session.c | 182 +++++++++++++++++++++++++++-------- manifest | 20 ++-- manifest.uuid | 2 +- 5 files changed, 225 insertions(+), 49 deletions(-) create mode 100644 ext/session/sessionG.test diff --git a/ext/session/session1.test b/ext/session/session1.test index 7aebe8c000..e97aa3c20d 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -206,8 +206,8 @@ do_conflict_test 3.1.2 -tables t1 -sql { INSERT INTO t1 VALUES(7, 'seven'); INSERT INTO t1 VALUES(8, NULL); } -conflicts { - {INSERT t1 CONSTRAINT {i 8 n {}}} {INSERT t1 CONFLICT {i 6 t six} {i 6 t VI}} + {INSERT t1 CONSTRAINT {i 8 n {}}} } do_db2_test 3.1.3 "SELECT * FROM t1" { @@ -272,9 +272,9 @@ do_conflict_test 3.3.3 -tables t4 -sql { UPDATE t4 SET a = NULL WHERE c = 9; UPDATE t4 SET a = 'x' WHERE b = 11; } -conflicts { - {UPDATE t4 CONSTRAINT {i 7 i 8 i 9} {n {} {} {} {} {}}} {UPDATE t4 DATA {i 1 i 2 i 3} {i -1 {} {} {} {}} {i 0 i 2 i 3}} {UPDATE t4 NOTFOUND {i 4 i 5 i 6} {i -1 {} {} {} {}}} + {UPDATE t4 CONSTRAINT {i 7 i 8 i 9} {n {} {} {} {} {}}} } do_db2_test 3.3.4 { SELECT * FROM t4 } {0 2 3 4 5 7 7 8 9 x 11 12} do_execsql_test 3.3.5 { SELECT * FROM t4 } {-1 2 3 -1 5 6 {} 8 9 x 11 12} diff --git a/ext/session/sessionG.test b/ext/session/sessionG.test new file mode 100644 index 0000000000..5ebdbbed6b --- /dev/null +++ b/ext/session/sessionG.test @@ -0,0 +1,66 @@ +# 2016 March 30 +# +# 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 the sessions module. +# Specifically, it tests that UNIQUE constraints are dealt with correctly. +# + + + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} +set testprefix sessionG + + +forcedelete test.db2 +sqlite3 db2 test.db2 + +do_test 1.0 { + do_common_sql { + CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); + INSERT INTO t1 VALUES(1, 'one'); + INSERT INTO t1 VALUES(2, 'two'); + INSERT INTO t1 VALUES(3, 'three'); + } + do_then_apply_sql { + DELETE FROM t1 WHERE a=1; + INSERT INTO t1 VALUES(4, 'one'); + } + compare_db db db2 +} {} + +do_test 1.1 { + do_then_apply_sql { + DELETE FROM t1 WHERE a=4; + INSERT INTO t1 VALUES(1, 'one'); + } + compare_db db db2 +} {} + +do_test 1.2 { + execsql { INSERT INTO t1 VALUES(5, 'five') } db2 + do_then_apply_sql { + INSERT INTO t1 VALUES(11, 'eleven'); + INSERT INTO t1 VALUES(12, 'five'); + } + execsql { SELECT * FROM t1 } db2 +} {2 two 3 three 1 one 5 five 11 eleven} + +do_test 1.3 { + execsql { SELECT * FROM t1 } +} {2 two 3 three 1 one 11 eleven 12 five} + +finish_test + diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 312e03dcfb..826911f299 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -67,6 +67,8 @@ struct SessionBuffer { ** sqlite3changeset_start_strm()). */ struct SessionInput { + int bNoDiscard; /* If true, discard no data */ + int iCurrent; /* Offset in aData[] of current change */ int iNext; /* Offset in aData[] of next change */ u8 *aData; /* Pointer to buffer containing changeset */ int nData; /* Number of bytes in aData */ @@ -2460,7 +2462,6 @@ static int sessionChangesetStart( pRet->in.nData = nChangeset; pRet->in.xInput = xInput; pRet->in.pIn = pIn; - pRet->in.iNext = 0; pRet->in.bEof = (xInput ? 0 : 1); /* Populate the output variable and return success. */ @@ -2490,6 +2491,23 @@ int sqlite3changeset_start_strm( return sessionChangesetStart(pp, xInput, pIn, 0, 0); } +/* +** If the SessionInput object passed as the only argument is a streaming +** object and the buffer is full, discard some data to free up space. +*/ +static void sessionDiscardData(SessionInput *pIn){ + if( pIn->bEof && pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ + int nMove = pIn->buf.nBuf - pIn->iNext; + assert( nMove>=0 ); + if( nMove>0 ){ + memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove); + } + pIn->buf.nBuf -= pIn->iNext; + pIn->iNext = 0; + pIn->nData = pIn->buf.nBuf; + } +} + /* ** Ensure that there are at least nByte bytes available in the buffer. Or, ** if there are not nByte bytes remaining in the input, that all available @@ -2503,13 +2521,7 @@ static int sessionInputBuffer(SessionInput *pIn, int nByte){ while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){ int nNew = SESSIONS_STRM_CHUNK_SIZE; - if( pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ - int nMove = pIn->buf.nBuf - pIn->iNext; - memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove); - pIn->buf.nBuf -= pIn->iNext; - pIn->iNext = 0; - } - + if( pIn->bNoDiscard==0 ) sessionDiscardData(pIn); if( SQLITE_OK==sessionBufferGrow(&pIn->buf, nNew, &rc) ){ rc = pIn->xInput(pIn->pIn, &pIn->buf.aBuf[pIn->buf.nBuf], &nNew); if( nNew==0 ){ @@ -2818,11 +2830,15 @@ static int sessionChangesetNext( return SQLITE_DONE; } + sessionDiscardData(&p->in); + p->in.iCurrent = p->in.iNext; + op = p->in.aData[p->in.iNext++]; if( op=='T' || op=='P' ){ p->bPatchset = (op=='P'); if( sessionChangesetReadTblhdr(p) ) return p->rc; if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc; + p->in.iCurrent = p->in.iNext; op = p->in.aData[p->in.iNext++]; } @@ -3266,6 +3282,9 @@ struct SessionApplyCtx { int nCol; /* Size of azCol[] and abPK[] arrays */ const char **azCol; /* Array of column names */ u8 *abPK; /* Boolean array - true if column is in PK */ + + int bDeferConstraints; /* True to defer constraints */ + SessionBuffer constraints; /* Deferred constraints are stored here */ }; /* @@ -3516,7 +3535,7 @@ static int sessionBindValue( ** transfers new.* values from the current iterator entry to statement ** pStmt. The table being inserted into has nCol columns. ** -** New.* value $i 0 from the iterator is bound to variable ($i+1) of +** New.* value $i from the iterator is bound to variable ($i+1) of ** statement pStmt. If parameter abPK is NULL, all values from 0 to (nCol-1) ** are transfered to the statement. Otherwise, if abPK is not NULL, it points ** to an array nCol elements in size. In this case only those values for @@ -3662,9 +3681,18 @@ static int sessionConflictHandler( pIter->pConflict = 0; rc = sqlite3_reset(p->pSelect); }else if( rc==SQLITE_OK ){ - /* No other row with the new.* primary key. */ - res = xConflict(pCtx, eType+1, pIter); - if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE; + if( p->bDeferConstraints && eType==SQLITE_CHANGESET_CONFLICT ){ + /* Instead of invoking the conflict handler, append the change blob + ** to the SessionApplyCtx.constraints buffer. */ + u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent]; + int nBlob = pIter->in.iNext - pIter->in.iCurrent; + sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc); + res = SQLITE_CHANGESET_OMIT; + }else{ + /* No other row with the new.* primary key. */ + res = xConflict(pCtx, eType+1, pIter); + if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE; + } } if( rc==SQLITE_OK ){ @@ -3824,6 +3852,96 @@ static int sessionApplyOneOp( return rc; } +static int sessionApplyOneWithRetry( + sqlite3 *db, /* Apply change to "main" db of this handle */ + sqlite3_changeset_iter *pIter, /* Changeset iterator to read change from */ + SessionApplyCtx *pApply, /* Apply context */ + int(*xConflict)(void*, int, sqlite3_changeset_iter*), + void *pCtx /* First argument passed to xConflict */ +){ + int bReplace = 0; + int bRetry = 0; + int rc; + + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry); + + if( rc==SQLITE_OK && bRetry ){ + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, 0); + } + + if( bReplace ){ + assert( pIter->op==SQLITE_INSERT ); + rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); + if( rc==SQLITE_OK ){ + rc = sessionBindRow(pIter, + sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete); + sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1); + } + if( rc==SQLITE_OK ){ + sqlite3_step(pApply->pDelete); + rc = sqlite3_reset(pApply->pDelete); + } + if( rc==SQLITE_OK ){ + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); + } + } + + return rc; +} + +/* +** Retry the changes accumulated in the pApply->constraints buffer. +*/ +static int sessionRetryConstraints( + sqlite3 *db, + int bPatchset, + const char *zTab, + SessionApplyCtx *pApply, + int(*xConflict)(void*, int, sqlite3_changeset_iter*), + void *pCtx /* First argument passed to xConflict */ +){ + int rc = SQLITE_OK; + + while( pApply->constraints.nBuf ){ + sqlite3_changeset_iter *pIter2 = 0; + SessionBuffer cons = pApply->constraints; + memset(&pApply->constraints, 0, sizeof(SessionBuffer)); + + rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf); + if( rc==SQLITE_OK ){ + int nByte = 2*pApply->nCol*sizeof(sqlite3_value*); + int rc2; + pIter2->bPatchset = bPatchset; + pIter2->zTab = (char*)zTab; + pIter2->nCol = pApply->nCol; + pIter2->abPK = pApply->abPK; + sessionBufferGrow(&pIter2->tblhdr, nByte, &rc); + pIter2->apValue = (sqlite3_value**)pIter2->tblhdr.aBuf; + if( rc==SQLITE_OK ) memset(pIter2->apValue, 0, nByte); + + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter2) ){ + rc = sessionApplyOneWithRetry(db, pIter2, pApply, xConflict, pCtx); + } + + rc2 = sqlite3changeset_finalize(pIter2); + if( rc==SQLITE_OK ) rc==rc2; + } + assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 ); + + sqlite3_free(cons.aBuf); + if( rc!=SQLITE_OK ) break; + if( pApply->constraints.nBuf>=cons.nBuf ){ + /* No progress was made on the last round. */ + pApply->bDeferConstraints = 0; + } + } + + return rc; +} + /* ** Argument pIter is a changeset iterator that has been initialized, but ** not yet passed to sqlite3changeset_next(). This function applies the @@ -3853,6 +3971,7 @@ static int sessionChangesetApply( assert( xConflict!=0 ); + pIter->in.bNoDiscard = 1; memset(&sApply, 0, sizeof(sApply)); sqlite3_mutex_enter(sqlite3_db_mutex(db)); rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); @@ -3862,8 +3981,6 @@ static int sessionChangesetApply( while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){ int nCol; int op; - int bReplace = 0; - int bRetry = 0; const char *zNew; sqlite3changeset_op(pIter, &zNew, &nCol, &op, 0); @@ -3871,6 +3988,11 @@ static int sessionChangesetApply( if( zTab==0 || sqlite3_strnicmp(zNew, zTab, nTab+1) ){ u8 *abPK; + rc = sessionRetryConstraints( + db, pIter->bPatchset, zTab, &sApply, xConflict, pCtx + ); + if( rc!=SQLITE_OK ) break; + sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ sqlite3_finalize(sApply.pDelete); sqlite3_finalize(sApply.pUpdate); @@ -3878,6 +4000,7 @@ static int sessionChangesetApply( sqlite3_finalize(sApply.pSelect); memset(&sApply, 0, sizeof(sApply)); sApply.db = db; + sApply.bDeferConstraints = 1; /* If an xFilter() callback was specified, invoke it now. If the ** xFilter callback returns zero, skip this table. If it returns @@ -3933,31 +4056,13 @@ static int sessionChangesetApply( ** next change. A log message has already been issued. */ if( schemaMismatch ) continue; - rc = sessionApplyOneOp(pIter, &sApply, xConflict, pCtx, &bReplace, &bRetry); + rc = sessionApplyOneWithRetry(db, pIter, &sApply, xConflict, pCtx); + } - if( rc==SQLITE_OK && bRetry ){ - rc = sessionApplyOneOp(pIter, &sApply, xConflict, pCtx, &bReplace, 0); - } - - if( bReplace ){ - assert( pIter->op==SQLITE_INSERT ); - rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); - if( rc==SQLITE_OK ){ - rc = sessionBindRow(pIter, - sqlite3changeset_new, sApply.nCol, sApply.abPK, sApply.pDelete); - sqlite3_bind_int(sApply.pDelete, sApply.nCol+1, 1); - } - if( rc==SQLITE_OK ){ - sqlite3_step(sApply.pDelete); - rc = sqlite3_reset(sApply.pDelete); - } - if( rc==SQLITE_OK ){ - rc = sessionApplyOneOp(pIter, &sApply, xConflict, pCtx, 0, 0); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); - } - } + if( rc==SQLITE_OK ){ + rc = sessionRetryConstraints( + db, pIter->bPatchset, zTab, &sApply, xConflict, pCtx + ); } if( rc==SQLITE_OK ){ @@ -3994,6 +4099,7 @@ static int sessionChangesetApply( sqlite3_finalize(sApply.pUpdate); sqlite3_finalize(sApply.pSelect); sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ + sqlite3_free((char*)sApply.constraints.aBuf); sqlite3_mutex_leave(sqlite3_db_mutex(db)); return rc; } diff --git a/manifest b/manifest index c602040523..27e749b9fb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Updates\sfor\sthe\sMSVC\smakefiles. -D 2016-03-30T16:23:06.801 +C Have\sthe\ssqlite3session_apply()\sfunction\sand\sits\sstreaming\sequivalent\sretry\sany\soperations\sthat\sfailed\swith\sSQLITE_CONSTRAINT\safter\sall\sother\soperations\son\sthe\ssame\stable\shave\sbeen\sattempted.\sNew\scode\sis\slargely\suntested. +D 2016-03-30T21:19:00.012 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc cde766eb7c27a7ca42000e66c5f0c37a17a05998 @@ -273,7 +273,7 @@ F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a -F ext/session/session1.test 5dab50ce55c859e829bae24f0787013f51775fc5 +F ext/session/session1.test 98f384736e2bc21ccf5ed81bdadcff4ad863393b F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0 F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 @@ -287,9 +287,10 @@ F ext/session/sessionC.test 97556f5164ac29f2344b24bd7de6a3a35a95c390 F ext/session/sessionD.test d4744c78334162851d2a2f285c7e603e31b49aa2 F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26 F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce +F ext/session/sessionG.test 388b4f311176411301c35f90f0bf2cb7c6c3dec9 F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596 F ext/session/sessionfault.test d52cbb7bee48cc8ee80335e07eb72fcb6b15eb40 -F ext/session/sqlite3session.c b10af3e87ae437bb197b3a23a584d2dc8ad8981a +F ext/session/sqlite3session.c e682828d3ca542617b54808e6d551559e802a605 F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1480,7 +1481,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 64d75cbe2c45af67124fa7ce5688d91cc6ddb755 -R 77269b95e931ac6cca96bcd2fa718a38 -U mistachkin -Z 37f983898af724eda9f571ecd8a4d862 +P 7cf0cab730e2d570c82dd789279ad6501ac598c8 +R ee6c26b884210802b6544dcc00c10c18 +T *branch * session-retry +T *sym-session-retry * +T -sym-trunk * +U dan +Z 9b2c9e9e66a7c0858e38132bf4058066 diff --git a/manifest.uuid b/manifest.uuid index 2aa68317b9..b9607529d1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7cf0cab730e2d570c82dd789279ad6501ac598c8 \ No newline at end of file +1085911afb51744f32fe9db183b50e8e88bdd73e \ No newline at end of file From 7e0765a9ec01abc1b4acc9cc0423fa79d61bb80e Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 31 Mar 2016 00:45:58 +0000 Subject: [PATCH 546/570] Fix the return code in sessionRetryConstraints(). FossilOrigin-Name: ea917c14b940f95b20b91dae77567dc25a651ef6 --- ext/session/sqlite3session.c | 2 +- manifest | 17 +++++++---------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 826911f299..2fb1b7c81c 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -3927,7 +3927,7 @@ static int sessionRetryConstraints( } rc2 = sqlite3changeset_finalize(pIter2); - if( rc==SQLITE_OK ) rc==rc2; + if( rc==SQLITE_OK ) rc = rc2; } assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 ); diff --git a/manifest b/manifest index 27e749b9fb..b111bf531f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Have\sthe\ssqlite3session_apply()\sfunction\sand\sits\sstreaming\sequivalent\sretry\sany\soperations\sthat\sfailed\swith\sSQLITE_CONSTRAINT\safter\sall\sother\soperations\son\sthe\ssame\stable\shave\sbeen\sattempted.\sNew\scode\sis\slargely\suntested. -D 2016-03-30T21:19:00.012 +C Fix\sthe\sreturn\scode\sin\ssessionRetryConstraints(). +D 2016-03-31T00:45:58.444 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc cde766eb7c27a7ca42000e66c5f0c37a17a05998 @@ -290,7 +290,7 @@ F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce F ext/session/sessionG.test 388b4f311176411301c35f90f0bf2cb7c6c3dec9 F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596 F ext/session/sessionfault.test d52cbb7bee48cc8ee80335e07eb72fcb6b15eb40 -F ext/session/sqlite3session.c e682828d3ca542617b54808e6d551559e802a605 +F ext/session/sqlite3session.c 401776afb4886a25182051ae5d68b9b07f70a99c F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1481,10 +1481,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 7cf0cab730e2d570c82dd789279ad6501ac598c8 -R ee6c26b884210802b6544dcc00c10c18 -T *branch * session-retry -T *sym-session-retry * -T -sym-trunk * -U dan -Z 9b2c9e9e66a7c0858e38132bf4058066 +P 1085911afb51744f32fe9db183b50e8e88bdd73e +R d0981524bf93277ec5c96a0100bce6e7 +U drh +Z 5d6f324097a8e5b94e7625885f845746 diff --git a/manifest.uuid b/manifest.uuid index b9607529d1..991df518ed 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1085911afb51744f32fe9db183b50e8e88bdd73e \ No newline at end of file +ea917c14b940f95b20b91dae77567dc25a651ef6 \ No newline at end of file From c8be64373314839a5166281c825b50b994a0d4a8 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 31 Mar 2016 02:44:56 +0000 Subject: [PATCH 547/570] Enhanced comments describing the sessions file format. No changes to code. FossilOrigin-Name: 84dc41e2df1092e9724a535b670343181a9cd0dd --- ext/session/sqlite3session.c | 4 ++-- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 2fb1b7c81c..0f5c558463 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -177,7 +177,7 @@ struct SessionTable { ** ** Followed by one or more changes to the table. ** -** 1 byte: Either SQLITE_INSERT, UPDATE or DELETE. +** 1 byte: Either SQLITE_INSERT (0x12), UPDATE (0x17) or DELETE (0x09). ** 1 byte: The "indirect-change" flag. ** old.* record: (delete and update only) ** new.* record: (insert and update only) @@ -219,7 +219,7 @@ struct SessionTable { ** ** Followed by one or more changes to the table. ** -** 1 byte: Either SQLITE_INSERT, UPDATE or DELETE. +** 1 byte: Either SQLITE_INSERT (0x12), UPDATE (0x17) or DELETE (0x09). ** 1 byte: The "indirect-change" flag. ** single record: (PK fields for DELETE, PK and modified fields for UPDATE, ** full record for INSERT). diff --git a/manifest b/manifest index b111bf531f..96777daf79 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\sreturn\scode\sin\ssessionRetryConstraints(). -D 2016-03-31T00:45:58.444 +C Enhanced\scomments\sdescribing\sthe\ssessions\sfile\sformat.\s\sNo\schanges\sto\scode. +D 2016-03-31T02:44:56.615 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc cde766eb7c27a7ca42000e66c5f0c37a17a05998 @@ -290,7 +290,7 @@ F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce F ext/session/sessionG.test 388b4f311176411301c35f90f0bf2cb7c6c3dec9 F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596 F ext/session/sessionfault.test d52cbb7bee48cc8ee80335e07eb72fcb6b15eb40 -F ext/session/sqlite3session.c 401776afb4886a25182051ae5d68b9b07f70a99c +F ext/session/sqlite3session.c 8ed9c3acf81b12d9d6fcb61b198d851c06046555 F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1481,7 +1481,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 1085911afb51744f32fe9db183b50e8e88bdd73e -R d0981524bf93277ec5c96a0100bce6e7 +P ea917c14b940f95b20b91dae77567dc25a651ef6 +R 703150f896b886ff9303fa6318e268aa U drh -Z 5d6f324097a8e5b94e7625885f845746 +Z 55b5826bc78e3fc677b5c1348287f2c3 diff --git a/manifest.uuid b/manifest.uuid index 991df518ed..fe7a39a337 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ea917c14b940f95b20b91dae77567dc25a651ef6 \ No newline at end of file +84dc41e2df1092e9724a535b670343181a9cd0dd \ No newline at end of file From 5f5663dc237c56595624615f014cd5dc4ca67328 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 31 Mar 2016 10:50:26 +0000 Subject: [PATCH 548/570] Add further tests for the code on this branch. Fix a problem in OOM handling. FossilOrigin-Name: 195f3340ee4d870420e4f58d44300bab5436b920 --- ext/session/sessionG.test | 111 +++++++++++++++++++++++++++++++++ ext/session/sessionfault2.test | 75 ++++++++++++++++++++++ ext/session/sqlite3session.c | 42 ++++++++++--- manifest | 17 ++--- manifest.uuid | 2 +- 5 files changed, 229 insertions(+), 18 deletions(-) create mode 100644 ext/session/sessionfault2.test diff --git a/ext/session/sessionG.test b/ext/session/sessionG.test index 5ebdbbed6b..5c057350e4 100644 --- a/ext/session/sessionG.test +++ b/ext/session/sessionG.test @@ -62,5 +62,116 @@ do_test 1.3 { execsql { SELECT * FROM t1 } } {2 two 3 three 1 one 11 eleven 12 five} +#------------------------------------------------------------------------- +# +reset_db +db2 close +forcedelete test.db2 +sqlite3 db2 test.db2 + +do_test 2.1 { + do_common_sql { + CREATE TABLE t1(a PRIMARY KEY, b UNIQUE, c UNIQUE); + INSERT INTO t1 VALUES(1, 1, 1); + INSERT INTO t1 VALUES(2, 2, 2); + INSERT INTO t1 VALUES(3, 3, 3); + } +} {} + +do_test 2.2.1 { + # It is not possible to apply the changeset generated by the following + # SQL, as none of the three updated rows may be updated as part of the + # first pass. + do_then_apply_sql { + UPDATE t1 SET b=0 WHERE a=1; + UPDATE t1 SET b=1 WHERE a=2; + UPDATE t1 SET b=2 WHERE a=3; + UPDATE t1 SET b=3 WHERE a=1; + } + db2 eval { SELECT a, b FROM t1 } +} {1 1 2 2 3 3} +do_test 2.2.2 { db eval { SELECT a, b FROM t1 } } {1 3 2 1 3 2} + +#------------------------------------------------------------------------- +# +reset_db +db2 close +forcedelete test.db2 +sqlite3 db2 test.db2 + +do_test 3.1 { + do_common_sql { + CREATE TABLE t1(a PRIMARY KEY, b UNIQUE, c UNIQUE); + INSERT INTO t1 VALUES(1, 1, 1); + INSERT INTO t1 VALUES(2, 2, 2); + INSERT INTO t1 VALUES(3, 3, 3); + } +} {} + +do_test 3.3 { + do_then_apply_sql { + UPDATE t1 SET b=4 WHERE a=3; + UPDATE t1 SET b=3 WHERE a=2; + UPDATE t1 SET b=2 WHERE a=1; + } + compare_db db db2 +} {} + +do_test 3.4 { + do_then_apply_sql { + UPDATE t1 SET b=1 WHERE a=1; + UPDATE t1 SET b=2 WHERE a=2; + UPDATE t1 SET b=3 WHERE a=3; + } + compare_db db db2 +} {} + +#------------------------------------------------------------------------- +# +reset_db +db2 close +forcedelete test.db2 +sqlite3 db2 test.db2 + +do_test 4.1 { + do_common_sql { + CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t1 VALUES(2, 2); + INSERT INTO t1 VALUES(3, 3); + + CREATE TABLE t2(a PRIMARY KEY, b UNIQUE); + INSERT INTO t2 VALUES(1, 1); + INSERT INTO t2 VALUES(2, 2); + INSERT INTO t2 VALUES(3, 3); + } +} {} + +do_test 4.2 { + do_then_apply_sql { + UPDATE t1 SET b=4 WHERE a=3; + UPDATE t1 SET b=3 WHERE a=2; + UPDATE t1 SET b=2 WHERE a=1; + + UPDATE t2 SET b=0 WHERE a=1; + UPDATE t2 SET b=1 WHERE a=2; + UPDATE t2 SET b=2 WHERE a=3; + } + compare_db db db2 +} {} + +do_test 4.3 { + do_then_apply_sql { + UPDATE t1 SET b=1 WHERE a=1; + UPDATE t1 SET b=2 WHERE a=2; + UPDATE t1 SET b=3 WHERE a=3; + + UPDATE t2 SET b=3 WHERE a=3; + UPDATE t2 SET b=2 WHERE a=2; + UPDATE t2 SET b=1 WHERE a=1; + } + compare_db db db2 +} {} + finish_test diff --git a/ext/session/sessionfault2.test b/ext/session/sessionfault2.test new file mode 100644 index 0000000000..2fc0780227 --- /dev/null +++ b/ext/session/sessionfault2.test @@ -0,0 +1,75 @@ +# 2016 March 31 +# +# 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. +# +#*********************************************************************** +# +# The focus of this file is testing the session module. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +set testprefix sessionfault2 + +do_execsql_test 1.0.0 { + CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t1 VALUES(2, 2); + INSERT INTO t1 VALUES(3, 3); + + CREATE TABLE t2(a PRIMARY KEY, b UNIQUE); + INSERT INTO t2 VALUES(1, 1); + INSERT INTO t2 VALUES(2, 2); + INSERT INTO t2 VALUES(3, 3); +} +faultsim_save_and_close + +faultsim_restore_and_reopen +do_test 1.0.1 { + set ::C [changeset_from_sql { + UPDATE t1 SET b=4 WHERE a=3; + UPDATE t1 SET b=3 WHERE a=2; + UPDATE t1 SET b=2 WHERE a=1; + UPDATE t2 SET b=0 WHERE a=1; + UPDATE t2 SET b=1 WHERE a=2; + UPDATE t2 SET b=2 WHERE a=3; + }] + set {} {} +} {} + +proc xConflict args { return "OMIT" } + +do_faultsim_test 1 -faults oom-p* -prep { + faultsim_restore_and_reopen +} -body { + sqlite3changeset_apply db $::C xConflict +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + faultsim_integrity_check + + catch { db eval ROLLBACK } + set res [db eval { + SELECT * FROM t1; + SELECT * FROM t2; + }] + + if {$testrc==0} { + if {$res != "1 2 2 3 3 4 1 0 2 1 3 2"} { error "data error" } + } else { + if { + $res != "1 2 2 3 3 4 1 0 2 1 3 2" + && $res != "1 1 2 2 3 3 1 1 2 2 3 3" + } { error "data error!! $res" } + } +} + +finish_test + diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 0f5c558463..437549dd70 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -3852,6 +3852,16 @@ static int sessionApplyOneOp( return rc; } +/* +** Attempt to apply the change that the iterator passed as the first argument +** currently points to to the database. If a conflict is encountered, invoke +** the conflict handler callback. +** +** The difference between this function and sessionApplyOne() is that this +** function handles the case where the conflict-handler is invoked and +** returns SQLITE_CHANGESET_REPLACE - indicating that the change should be +** retried in some manner. +*/ static int sessionApplyOneWithRetry( sqlite3 *db, /* Apply change to "main" db of this handle */ sqlite3_changeset_iter *pIter, /* Changeset iterator to read change from */ @@ -3864,12 +3874,26 @@ static int sessionApplyOneWithRetry( int rc; rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry); + assert( rc==SQLITE_OK || (bRetry==0 && bReplace==0) ); - if( rc==SQLITE_OK && bRetry ){ - rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, 0); + /* If the bRetry flag is set, the change has not been applied due to an + ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and + ** a row with the correct PK is present in the db, but one or more other + ** fields do not contain the expected values) and the conflict handler + ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation, + ** but pass NULL as the final argument so that sessionApplyOneOp() ignores + ** the SQLITE_CHANGESET_DATA problem. */ + if( bRetry ){ + assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE ); + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); } - if( bReplace ){ + /* If the bReplace flag is set, the change is an INSERT that has not + ** been performed because the database already contains a row with the + ** specified primary key and the conflict handler returned + ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row + ** before reattempting the INSERT. */ + else if( bReplace ){ assert( pIter->op==SQLITE_INSERT ); rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); if( rc==SQLITE_OK ){ @@ -3968,6 +3992,7 @@ static int sessionChangesetApply( const char *zTab = 0; /* Name of current table */ int nTab = 0; /* Result of sqlite3Strlen30(zTab) */ SessionApplyCtx sApply; /* changeset_apply() context object */ + int bPatchset; assert( xConflict!=0 ); @@ -4059,18 +4084,17 @@ static int sessionChangesetApply( rc = sessionApplyOneWithRetry(db, pIter, &sApply, xConflict, pCtx); } - if( rc==SQLITE_OK ){ - rc = sessionRetryConstraints( - db, pIter->bPatchset, zTab, &sApply, xConflict, pCtx - ); - } - + bPatchset = pIter->bPatchset; if( rc==SQLITE_OK ){ rc = sqlite3changeset_finalize(pIter); }else{ sqlite3changeset_finalize(pIter); } + if( rc==SQLITE_OK ){ + rc = sessionRetryConstraints(db, bPatchset, zTab, &sApply, xConflict, pCtx); + } + if( rc==SQLITE_OK ){ int nFk, notUsed; sqlite3_db_status(db, SQLITE_DBSTATUS_DEFERRED_FKS, &nFk, ¬Used, 0); diff --git a/manifest b/manifest index 96777daf79..cdbeeaf1de 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhanced\scomments\sdescribing\sthe\ssessions\sfile\sformat.\s\sNo\schanges\sto\scode. -D 2016-03-31T02:44:56.615 +C Add\sfurther\stests\sfor\sthe\scode\son\sthis\sbranch.\sFix\sa\sproblem\sin\sOOM\shandling. +D 2016-03-31T10:50:26.149 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc cde766eb7c27a7ca42000e66c5f0c37a17a05998 @@ -287,10 +287,11 @@ F ext/session/sessionC.test 97556f5164ac29f2344b24bd7de6a3a35a95c390 F ext/session/sessionD.test d4744c78334162851d2a2f285c7e603e31b49aa2 F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26 F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce -F ext/session/sessionG.test 388b4f311176411301c35f90f0bf2cb7c6c3dec9 +F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60 F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596 F ext/session/sessionfault.test d52cbb7bee48cc8ee80335e07eb72fcb6b15eb40 -F ext/session/sqlite3session.c 8ed9c3acf81b12d9d6fcb61b198d851c06046555 +F ext/session/sessionfault2.test 2667fec1452e46abb5ce6c9f99483de8e0559032 +F ext/session/sqlite3session.c 2fc72bd989c424a15802da766c7ebd8eed47bcf6 F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1481,7 +1482,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 ea917c14b940f95b20b91dae77567dc25a651ef6 -R 703150f896b886ff9303fa6318e268aa -U drh -Z 55b5826bc78e3fc677b5c1348287f2c3 +P 84dc41e2df1092e9724a535b670343181a9cd0dd +R 6c1e5637abee98a737c22aa1d2e2c831 +U dan +Z ca2c22d2a622b0edd20f5f5ca6a19e56 diff --git a/manifest.uuid b/manifest.uuid index fe7a39a337..35597317e7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -84dc41e2df1092e9724a535b670343181a9cd0dd \ No newline at end of file +195f3340ee4d870420e4f58d44300bab5436b920 \ No newline at end of file From 0d0a2abc6a6e8d97647db3297e36dd8228050257 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 31 Mar 2016 15:08:10 +0000 Subject: [PATCH 549/570] Add another OOM test to this branch. FossilOrigin-Name: 49763fc3ae2fb6117b0443ea28661568467f9bf2 --- ext/session/sessionfault2.test | 31 +++++++++++++++++++++++++++++++ manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/ext/session/sessionfault2.test b/ext/session/sessionfault2.test index 2fc0780227..6b257cf41b 100644 --- a/ext/session/sessionfault2.test +++ b/ext/session/sessionfault2.test @@ -71,5 +71,36 @@ do_faultsim_test 1 -faults oom-p* -prep { } } +#------------------------------------------------------------------------- +# OOM when applying a changeset for which one of the tables has a name +# 99 bytes in size. This happens to cause an extra malloc in within the +# sessions_strm permutation. +# +reset_db +set nm [string repeat t 99] +do_execsql_test 2.0.0 [string map "%TBL% $nm" { + CREATE TABLE %TBL%(a PRIMARY KEY, b UNIQUE); +}] +faultsim_save_and_close + +faultsim_restore_and_reopen +do_test 1.0.1 { + set ::C [changeset_from_sql [string map "%TBL% $nm" { + INSERT INTO %TBL% VALUES(1, 2); + INSERT INTO %TBL% VALUES(3, 4); + }]] + set {} {} +} {} + +proc xConflict args { return "OMIT" } +do_faultsim_test 2 -faults oom-p* -prep { + faultsim_restore_and_reopen +} -body { + sqlite3changeset_apply db $::C xConflict +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + faultsim_integrity_check +} + finish_test diff --git a/manifest b/manifest index cdbeeaf1de..61906ced3a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sfurther\stests\sfor\sthe\scode\son\sthis\sbranch.\sFix\sa\sproblem\sin\sOOM\shandling. -D 2016-03-31T10:50:26.149 +C Add\sanother\sOOM\stest\sto\sthis\sbranch. +D 2016-03-31T15:08:10.284 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc cde766eb7c27a7ca42000e66c5f0c37a17a05998 @@ -290,7 +290,7 @@ F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60 F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596 F ext/session/sessionfault.test d52cbb7bee48cc8ee80335e07eb72fcb6b15eb40 -F ext/session/sessionfault2.test 2667fec1452e46abb5ce6c9f99483de8e0559032 +F ext/session/sessionfault2.test ac1dfd77a0fb0ea310aee40a16645ef1b66d3f88 F ext/session/sqlite3session.c 2fc72bd989c424a15802da766c7ebd8eed47bcf6 F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce @@ -1482,7 +1482,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 84dc41e2df1092e9724a535b670343181a9cd0dd -R 6c1e5637abee98a737c22aa1d2e2c831 +P 195f3340ee4d870420e4f58d44300bab5436b920 +R 553c882c4eb73691c7e02bdd576b9d70 U dan -Z ca2c22d2a622b0edd20f5f5ca6a19e56 +Z 5ef40d72349254975dc55c844d6daff8 diff --git a/manifest.uuid b/manifest.uuid index 35597317e7..9ba171f6ba 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -195f3340ee4d870420e4f58d44300bab5436b920 \ No newline at end of file +49763fc3ae2fb6117b0443ea28661568467f9bf2 \ No newline at end of file From 5996a7798796241fb749bb1ffd3a2a2ca55b5993 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 31 Mar 2016 20:40:28 +0000 Subject: [PATCH 550/570] Enhance the query planner so that IS and IS NULL operators are able to drive an index on a LEFT OUTER JOIN. FossilOrigin-Name: c648539b52ca28c0b2cb61208e2c32b1d29626a1 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 14 ++++++++++++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index c602040523..985501bcf7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Updates\sfor\sthe\sMSVC\smakefiles. -D 2016-03-30T16:23:06.801 +C Enhance\sthe\squery\splanner\sso\sthat\sIS\sand\sIS\sNULL\soperators\sare\sable\sto\sdrive\nan\sindex\son\sa\sLEFT\sOUTER\sJOIN. +D 2016-03-31T20:40:28.501 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc cde766eb7c27a7ca42000e66c5f0c37a17a05998 @@ -453,7 +453,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 -F src/where.c fe7925faafbe9a458972035c0bb4753d672f04ed +F src/where.c 99cc6270fc3915201e2a90bbac3768f007a89c44 F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34 F src/wherecode.c 863aedf086131743763c1960637fde904eadc442 F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a @@ -1480,7 +1480,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 64d75cbe2c45af67124fa7ce5688d91cc6ddb755 -R 77269b95e931ac6cca96bcd2fa718a38 -U mistachkin -Z 37f983898af724eda9f571ecd8a4d862 +P 7cf0cab730e2d570c82dd789279ad6501ac598c8 +R 208d59c6eb413bba3e66e70033cda029 +U drh +Z d36ae30a27c8e5f7b17afdd33be692aa diff --git a/manifest.uuid b/manifest.uuid index 2aa68317b9..c1ba66c050 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7cf0cab730e2d570c82dd789279ad6501ac598c8 \ No newline at end of file +c648539b52ca28c0b2cb61208e2c32b1d29626a1 \ No newline at end of file diff --git a/src/where.c b/src/where.c index cf23aa62a4..4f7ee66ff7 100644 --- a/src/where.c +++ b/src/where.c @@ -2201,8 +2201,6 @@ static int whereLoopAddBtreeIndex( assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); if( pNew->wsFlags & WHERE_BTM_LIMIT ){ opMask = WO_LT|WO_LE; - }else if( /*pProbe->tnum<=0 ||*/ (pSrc->fg.jointype & JT_LEFT)!=0 ){ - opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE; }else{ opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; } @@ -2240,6 +2238,18 @@ static int whereLoopAddBtreeIndex( ** to mix with a lower range bound from some other source */ if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; + /* Do not allow IS constraints from the WHERE clause to be used by the + ** right table of a LEFT JOIN. Only constraints in the ON clause are + ** allowed */ + if( (pSrc->fg.jointype & JT_LEFT)!=0 + && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) + && (eOp & (WO_IS|WO_ISNULL))!=0 + ){ + testcase( eOp & WO_IS ); + testcase( eOp & WO_ISNULL ); + continue; + } + pNew->wsFlags = saved_wsFlags; pNew->u.btree.nEq = saved_nEq; pNew->nLTerm = saved_nLTerm; From 2779989110c659236dae61affe032469da518444 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 31 Mar 2016 22:53:37 +0000 Subject: [PATCH 551/570] Update the clean target in the MSVC makefile. FossilOrigin-Name: 69f4d83210f6425b2c0d699b397ef4fa4422d438 --- Makefile.msc | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 84c2eac2f4..7fa9555c35 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -2089,7 +2089,7 @@ clean: del /Q mptester.exe wordcount.exe rbu.exe srcck1.exe 2>NUL del /Q sqlite3.c sqlite3-*.c 2>NUL del /Q sqlite3rc.h 2>NUL - del /Q shell.c sqlite3ext.h 2>NUL + del /Q shell.c sqlite3ext.h sqlite3session.h 2>NUL del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL del /Q sqlite-*-output.vsix 2>NUL del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe 2>NUL diff --git a/manifest b/manifest index 985501bcf7..6ccaa6e08d 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Enhance\sthe\squery\splanner\sso\sthat\sIS\sand\sIS\sNULL\soperators\sare\sable\sto\sdrive\nan\sindex\son\sa\sLEFT\sOUTER\sJOIN. -D 2016-03-31T20:40:28.501 +C Update\sthe\sclean\starget\sin\sthe\sMSVC\smakefile. +D 2016-03-31T22:53:37.345 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc cde766eb7c27a7ca42000e66c5f0c37a17a05998 +F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 5d234da9b5dae329fab75ff75884cfe0a9cb3fda F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -1480,7 +1480,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 7cf0cab730e2d570c82dd789279ad6501ac598c8 -R 208d59c6eb413bba3e66e70033cda029 -U drh -Z d36ae30a27c8e5f7b17afdd33be692aa +P c648539b52ca28c0b2cb61208e2c32b1d29626a1 +R 6ae456c611a2dfae066ef8a6f11a421b +U mistachkin +Z 730dfc7c7e8862f73161aa001e93b9d4 diff --git a/manifest.uuid b/manifest.uuid index c1ba66c050..c52f6651c2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c648539b52ca28c0b2cb61208e2c32b1d29626a1 \ No newline at end of file +69f4d83210f6425b2c0d699b397ef4fa4422d438 \ No newline at end of file From f6661a88963aa939d1c377954cbf34de98902476 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 1 Apr 2016 12:35:22 +0000 Subject: [PATCH 552/570] When reading an sqlite_stat1 table with missing entries for some indexes, set the default for the missing indexes after all other indexes are set so that the default values are more in line with indexes that are actually in the stat1 table. FossilOrigin-Name: a62340dc0507e36f6dec05b1fda68d8399ec62ec --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/analyze.c | 29 ++++++++++++++++------------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index 6ccaa6e08d..51885512ec 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\sclean\starget\sin\sthe\sMSVC\smakefile. -D 2016-03-31T22:53:37.345 +C When\sreading\san\ssqlite_stat1\stable\swith\smissing\sentries\sfor\ssome\sindexes,\nset\sthe\sdefault\sfor\sthe\smissing\sindexes\safter\sall\sother\sindexes\sare\sset\nso\sthat\sthe\sdefault\svalues\sare\smore\sin\sline\swith\sindexes\sthat\sare\sactually\nin\sthe\sstat1\stable. +D 2016-04-01T12:35:22.357 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -311,7 +311,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 1bb0709b3048e24217b80ec6bd78a3e99a47c01b -F src/analyze.c ab57b6763dd4c6170a20673d14882c033affd188 +F src/analyze.c 39b21e4d9ad8a647e9834aa5ba99a74fb6c98879 F src/attach.c 771153bd1f4ab0b97a44a13dde2c7e5e1efeba22 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce @@ -1480,7 +1480,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 c648539b52ca28c0b2cb61208e2c32b1d29626a1 -R 6ae456c611a2dfae066ef8a6f11a421b -U mistachkin -Z 730dfc7c7e8862f73161aa001e93b9d4 +P 69f4d83210f6425b2c0d699b397ef4fa4422d438 +R 7562b4ce09688850a9cd06c483af68bc +U drh +Z f4c65a7a3ea821b7d157bc63d7456b83 diff --git a/manifest.uuid b/manifest.uuid index c52f6651c2..0b71e7ae1c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -69f4d83210f6425b2c0d699b397ef4fa4422d438 \ No newline at end of file +a62340dc0507e36f6dec05b1fda68d8399ec62ec \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index cd59ae681d..423ef0d714 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1835,31 +1835,34 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); - sqlite3DefaultRowEst(pIdx); + pIdx->aiRowLogEst[0] = 0; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 sqlite3DeleteIndexSamples(db, pIdx); pIdx->aSample = 0; #endif } - /* Check to make sure the sqlite_stat1 table exists */ + /* Load new statistics out of the sqlite_stat1 table */ sInfo.db = db; sInfo.zDatabase = db->aDb[iDb].zName; - if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){ - return SQLITE_ERROR; + if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)!=0 ){ + zSql = sqlite3MPrintf(db, + "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase); + if( zSql==0 ){ + rc = SQLITE_NOMEM_BKPT; + }else{ + rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); + sqlite3DbFree(db, zSql); + } } - /* Load new statistics out of the sqlite_stat1 table */ - zSql = sqlite3MPrintf(db, - "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase); - if( zSql==0 ){ - rc = SQLITE_NOMEM_BKPT; - }else{ - rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); - sqlite3DbFree(db, zSql); + /* Set appropriate defaults on all indexes not in the sqlite_stat1 table */ + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ + Index *pIdx = sqliteHashData(i); + if( pIdx->aiRowLogEst[0]==0 ) sqlite3DefaultRowEst(pIdx); } - /* Load the statistics from the sqlite_stat4 table. */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ From 076b6468f5cc83332ebe0aa1a65c42f43756c575 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 1 Apr 2016 17:54:07 +0000 Subject: [PATCH 553/570] Preupdate hook documentation fixes. No changes to code. FossilOrigin-Name: 59814f35d13db1f6379b9ae218b5432bc03c6197 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqlite.h.in | 13 +++++++------ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 51885512ec..d573902ae9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\sreading\san\ssqlite_stat1\stable\swith\smissing\sentries\sfor\ssome\sindexes,\nset\sthe\sdefault\sfor\sthe\smissing\sindexes\safter\sall\sother\sindexes\sare\sset\nso\sthat\sthe\sdefault\svalues\sare\smore\sin\sline\swith\sindexes\sthat\sare\sactually\nin\sthe\sstat1\stable. -D 2016-04-01T12:35:22.357 +C Preupdate\shook\sdocumentation\sfixes.\s\sNo\schanges\sto\scode. +D 2016-04-01T17:54:07.826 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -375,7 +375,7 @@ F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 7849cee0a01952a9c93cd28989daedfa57731143 F src/shell.c cd3f82fdc5c895b817a375b7ab8319cb41f447ce -F src/sqlite.h.in 843a0dfcf8c5e961cfafa62009fed0867b88241e +F src/sqlite.h.in c46a7b85d3f37371cacea8f98ec825f5e52c420c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 F src/sqliteInt.h 594bf31a7a0cc788688ca947e562576e23bd7904 @@ -1480,7 +1480,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 69f4d83210f6425b2c0d699b397ef4fa4422d438 -R 7562b4ce09688850a9cd06c483af68bc +P a62340dc0507e36f6dec05b1fda68d8399ec62ec +R 17cbd88111da841c5ced2fa2ee956e9f U drh -Z f4c65a7a3ea821b7d157bc63d7456b83 +Z dfefbe59c009b860b7f7e89f1f29dda4 diff --git a/manifest.uuid b/manifest.uuid index 0b71e7ae1c..c694118307 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a62340dc0507e36f6dec05b1fda68d8399ec62ec \ No newline at end of file +59814f35d13db1f6379b9ae218b5432bc03c6197 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 35de70ff7f..b5f0e7f98e 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -5187,7 +5187,7 @@ void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); ** ^The sqlite3_update_hook() interface registers a callback function ** with the [database connection] identified by the first argument ** to be invoked whenever a row is updated, inserted or deleted in -** a rowid table. +** a [rowid table]. ** ^Any callback set by a previous call to this function ** for the same database connection is overridden. ** @@ -7917,13 +7917,13 @@ int sqlite3_db_cacheflush(sqlite3*); /* ** CAPI3REF: The pre-update hook. -** EXPERIMENTAL ** ** ^These interfaces are only available if SQLite is compiled using the -** [SQLITE_ENABLE_UPDATE_HOOK] compile-time option. +** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option. ** ** ^The [sqlite3_preupdate_hook()] interface registers a callback function -** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation. +** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation +** on a [rowid table]. ** ^At most one preupdate hook may be registered at a time on a single ** [database connection]; each call to [sqlite3_preupdate_hook()] overrides ** the previous setting. @@ -7932,8 +7932,9 @@ int sqlite3_db_cacheflush(sqlite3*); ** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as ** the first parameter to callbacks. ** -** ^The preupdate hook only fires for changes to real tables; the preupdate -** hook is not invoked for changes to virtual tables. +** ^The preupdate hook only fires for changes to [rowid tables]; the preupdate +** hook is not invoked for changes to [virtual tables] or [WITHOUT ROWID] +** tables. ** ** ^The second parameter to the preupdate callback is a pointer to ** the [database connection] that registered the preupdate hook. From 899c5c9d348f3fb0c74fa7f21b06fb0e2ef67f60 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sun, 3 Apr 2016 20:50:02 +0000 Subject: [PATCH 554/570] Replace the new fprintf() calls. FossilOrigin-Name: f76c3a0ca40989fe9401c3b6f662f8e6ef2a730c --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/shell.c | 29 ++++++++++++++++------------- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 9b4d901476..375fb5cce3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\supdates\sfrom\strunk. -D 2016-04-03T20:45:04.922 +C Replace\sthe\snew\sfprintf()\scalls. +D 2016-04-03T20:50:02.891 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -13,7 +13,7 @@ F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 42f7eb1fb2b06ddd6c6adab3e4388cc0a237ba40 F autoconf/Makefile.msc dc0d0500e4a827cb3891d08d846dd6dd40241b51 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 -F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1 w autoconf/README +F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1 F autoconf/configure.ac d807b567f73a2b0986ccdd206b782cecb4d08fff F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 @@ -374,7 +374,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 7849cee0a01952a9c93cd28989daedfa57731143 -F src/shell.c c8a75d0d77c3fe691e0f5f970ddc5e49908ebe97 +F src/shell.c e126f647f63da3d5d820f012359b89075cd7de99 F src/sqlite.h.in c46a7b85d3f37371cacea8f98ec825f5e52c420c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 @@ -1010,7 +1010,7 @@ F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0 F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7 F test/savepoint7.test db3db281486c925095f305aad09fe806e5188ff3 -F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2 w test/savepoint3.test +F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2 F test/scanstatus.test 5253c219e331318a437f436268e0e82345700285 F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481 F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5 @@ -1376,7 +1376,7 @@ F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 F test/whereI.test eab5b226bbc344ac70d7dc09b963a064860ae6d7 F test/whereJ.test 55a3221706a7ab706293f17cc8f96da563bf0767 F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b -F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864 w test/where8m.test +F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864 F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c @@ -1480,7 +1480,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 5cbab63756f6f276996f39d16d70b178581f63cd 59814f35d13db1f6379b9ae218b5432bc03c6197 -R 7b729d340f074699d469d04257844002 +P 566b551e5a81440a5c8ff865ceb4422c76d67cf7 +R c328759cdfd1946a4f3790cce9b56b06 U mistachkin -Z ad64521de5ede9ab99c45ca3b47e617d +Z fca762cd11972041ea0ef005e2621264 diff --git a/manifest.uuid b/manifest.uuid index 3b86cc6a51..ed8ee7667b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -566b551e5a81440a5c8ff865ceb4422c76d67cf7 \ No newline at end of file +f76c3a0ca40989fe9401c3b6f662f8e6ef2a730c \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 925de30c4f..9cec288024 100644 --- a/src/shell.c +++ b/src/shell.c @@ -2038,7 +2038,7 @@ static char zHelp[] = ** Print help information for the ".sessions" command */ void session_help(ShellState *p){ - fprintf(p->out, + raw_printf(p->out, ".session ?NAME? SUBCOMMAND ?ARGS...?\n" "If ?NAME? is omitted, the first defined session is used.\n" "Subcommands:\n" @@ -3902,11 +3902,11 @@ static int do_meta_command(char *zLine, ShellState *p){ if( nCmd!=2 ) goto session_syntax_error; if( pSession->p==0 ){ session_not_open: - fprintf(stderr, "ERROR: No sessions are open\n"); + raw_printf(stderr, "ERROR: No sessions are open\n"); }else{ rc = sqlite3session_attach(pSession->p, azCmd[1]); if( rc ){ - fprintf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc); + raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc); rc = 0; } } @@ -3922,7 +3922,7 @@ static int do_meta_command(char *zLine, ShellState *p){ if( pSession->p==0 ) goto session_not_open; out = fopen(azCmd[1], "wb"); if( out==0 ){ - fprintf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]); + utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]); }else{ int szChng; void *pChng; @@ -3937,7 +3937,7 @@ static int do_meta_command(char *zLine, ShellState *p){ } if( pChng && fwrite(pChng, szChng, 1, out)!=1 ){ - fprintf(stderr, "ERROR: Failed to write entire %d-byte output\n", + raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n", szChng); } sqlite3_free(pChng); @@ -3965,7 +3965,8 @@ static int do_meta_command(char *zLine, ShellState *p){ ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); if( p->nSession ){ ii = sqlite3session_enable(pSession->p, ii); - fprintf(p->out, "session %s enable flag = %d\n", pSession->zName, ii); + utf8_printf(p->out, "session %s enable flag = %d\n", + pSession->zName, ii); } }else @@ -3983,7 +3984,7 @@ static int do_meta_command(char *zLine, ShellState *p){ nByte = sizeof(pSession->azFilter[0])*(nCmd-1); pSession->azFilter = sqlite3_malloc( nByte ); if( pSession->azFilter==0 ){ - fprintf(stderr, "Error: out or memory\n"); + raw_printf(stderr, "Error: out or memory\n"); exit(1); } for(ii=1; iinSession ){ ii = sqlite3session_indirect(pSession->p, ii); - fprintf(p->out, "session %s indirect flag = %d\n", pSession->zName,ii); + utf8_printf(p->out, "session %s indirect flag = %d\n", + pSession->zName, ii); } }else @@ -4014,7 +4016,8 @@ static int do_meta_command(char *zLine, ShellState *p){ if( nCmd!=1 ) goto session_syntax_error; if( p->nSession ){ ii = sqlite3session_isempty(pSession->p); - fprintf(p->out, "session %s isempty flag = %d\n", pSession->zName, ii); + utf8_printf(p->out, "session %s isempty flag = %d\n", + pSession->zName, ii); } }else @@ -4023,7 +4026,7 @@ static int do_meta_command(char *zLine, ShellState *p){ */ if( strcmp(azCmd[0],"list")==0 ){ for(i=0; inSession; i++){ - fprintf(p->out, "%d %s\n", i, p->aSession[i].zName); + utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName); } }else @@ -4038,18 +4041,18 @@ static int do_meta_command(char *zLine, ShellState *p){ if( zName[0]==0 ) goto session_syntax_error; for(i=0; inSession; i++){ if( strcmp(p->aSession[i].zName,zName)==0 ){ - fprintf(stderr, "Session \"%s\" already exists\n", zName); + utf8_printf(stderr, "Session \"%s\" already exists\n", zName); goto meta_command_exit; } } if( p->nSession>=ArraySize(p->aSession) ){ - fprintf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession)); + raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession)); goto meta_command_exit; } pSession = &p->aSession[p->nSession]; rc = sqlite3session_create(p->db, azCmd[1], &pSession->p); if( rc ){ - fprintf(stderr, "Cannot open session: error code=%d\n", rc); + raw_printf(stderr, "Cannot open session: error code=%d\n", rc); rc = 0; goto meta_command_exit; } From 5daed673b8910f58c23f8d4e27dabd2d73fb2941 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sun, 3 Apr 2016 22:44:16 +0000 Subject: [PATCH 555/570] Revise and enhance the Win32 string conversion routines. FossilOrigin-Name: 345860c92195544aad44ea9b0d14c9ebbd50adf2 --- manifest | 12 ++-- manifest.uuid | 2 +- src/os_win.c | 152 ++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 117 insertions(+), 49 deletions(-) diff --git a/manifest b/manifest index 375fb5cce3..0687355cf6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Replace\sthe\snew\sfprintf()\scalls. -D 2016-04-03T20:50:02.891 +C Revise\sand\senhance\sthe\sWin32\sstring\sconversion\sroutines. +D 2016-04-03T22:44:16.657 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -358,7 +358,7 @@ F src/os.h 91ff889115ecd01f436d3611f7f5ea4dc12d92f1 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c b1ccb273771f41dbdbe0ba7c1ad63c38ad5972ec -F src/os_win.c ff870d89f4cb088a04cbf5ea0cbd9ff1b089ff4a +F src/os_win.c 01ae58949a28edaecd5645abbe29ac9d2ee983fd F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 38718a019ca762ba4f6795425d5a54db70d1790d F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 @@ -1480,7 +1480,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 566b551e5a81440a5c8ff865ceb4422c76d67cf7 -R c328759cdfd1946a4f3790cce9b56b06 +P f76c3a0ca40989fe9401c3b6f662f8e6ef2a730c +R 9a8e623b20453c0fbff989d22019add7 U mistachkin -Z fca762cd11972041ea0ef005e2621264 +Z 149573e0b667520348654eca6c5f3228 diff --git a/manifest.uuid b/manifest.uuid index ed8ee7667b..280e3ae958 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f76c3a0ca40989fe9401c3b6f662f8e6ef2a730c \ No newline at end of file +345860c92195544aad44ea9b0d14c9ebbd50adf2 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index f64a7d43a7..9508c97a14 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -1635,50 +1635,50 @@ void sqlite3MemSetDefault(void){ ** ** Space to hold the returned string is obtained from malloc. */ -static LPWSTR winUtf8ToUnicode(const char *zFilename){ +static LPWSTR winUtf8ToUnicode(const char *zText){ int nChar; - LPWSTR zWideFilename; + LPWSTR zWideText; - nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); + nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0); if( nChar==0 ){ return 0; } - zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) ); - if( zWideFilename==0 ){ + zWideText = sqlite3MallocZero( nChar*sizeof(WCHAR) ); + if( zWideText==0 ){ return 0; } - nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, + nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText, nChar); if( nChar==0 ){ - sqlite3_free(zWideFilename); - zWideFilename = 0; + sqlite3_free(zWideText); + zWideText = 0; } - return zWideFilename; + return zWideText; } /* ** Convert Microsoft Unicode to UTF-8. Space to hold the returned string is ** obtained from sqlite3_malloc(). */ -static char *winUnicodeToUtf8(LPCWSTR zWideFilename){ +static char *winUnicodeToUtf8(LPCWSTR zWideText){ int nByte; - char *zFilename; + char *zText; - nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); + nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0); if( nByte == 0 ){ return 0; } - zFilename = sqlite3MallocZero( nByte ); - if( zFilename==0 ){ + zText = sqlite3MallocZero( nByte ); + if( zText==0 ){ return 0; } - nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, + nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte, 0, 0); if( nByte == 0 ){ - sqlite3_free(zFilename); - zFilename = 0; + sqlite3_free(zText); + zText = 0; } - return zFilename; + return zText; } /* @@ -1688,12 +1688,12 @@ static char *winUnicodeToUtf8(LPCWSTR zWideFilename){ ** Space to hold the returned string is obtained ** from sqlite3_malloc. */ -static LPWSTR winMbcsToUnicode(const char *zFilename){ +static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){ int nByte; LPWSTR zMbcsFilename; - int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; + int codepage = useAnsi ? CP_ACP : CP_OEMCP; - nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL, + nByte = osMultiByteToWideChar(codepage, 0, zText, -1, NULL, 0)*sizeof(WCHAR); if( nByte==0 ){ return 0; @@ -1702,7 +1702,7 @@ static LPWSTR winMbcsToUnicode(const char *zFilename){ if( zMbcsFilename==0 ){ return 0; } - nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, + nByte = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsFilename, nByte); if( nByte==0 ){ sqlite3_free(zMbcsFilename); @@ -1718,60 +1718,128 @@ static LPWSTR winMbcsToUnicode(const char *zFilename){ ** Space to hold the returned string is obtained from ** sqlite3_malloc(). */ -static char *winUnicodeToMbcs(LPCWSTR zWideFilename){ +static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi){ int nByte; - char *zFilename; - int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; + char *zText; + int codepage = useAnsi ? CP_ACP : CP_OEMCP; - nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); + nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, 0, 0, 0, 0); if( nByte == 0 ){ return 0; } - zFilename = sqlite3MallocZero( nByte ); - if( zFilename==0 ){ + zText = sqlite3MallocZero( nByte ); + if( zText==0 ){ return 0; } - nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, + nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, zText, nByte, 0, 0); if( nByte == 0 ){ - sqlite3_free(zFilename); - zFilename = 0; + sqlite3_free(zText); + zText = 0; } - return zFilename; + return zText; } /* ** Convert multibyte character string to UTF-8. Space to hold the ** returned string is obtained from sqlite3_malloc(). */ -char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){ - char *zFilenameUtf8; +char *sqlite3_win32_mbcs_to_utf8(const char *zText){ + char *zTextUtf8; LPWSTR zTmpWide; - zTmpWide = winMbcsToUnicode(zFilename); + zTmpWide = winMbcsToUnicode(zText, osAreFileApisANSI()); if( zTmpWide==0 ){ return 0; } - zFilenameUtf8 = winUnicodeToUtf8(zTmpWide); + zTextUtf8 = winUnicodeToUtf8(zTmpWide); sqlite3_free(zTmpWide); - return zFilenameUtf8; + return zTextUtf8; +} + +/* +** Convert multibyte character string to UTF-8 using the ANSI codepage. +** Space to hold the returned string is obtained from sqlite3_malloc(). +*/ +char *sqlite3_win32_mbcs_to_utf8_via_ansi(const char *zText){ + char *zTextUtf8; + LPWSTR zTmpWide; + + zTmpWide = winMbcsToUnicode(zText, 1); + if( zTmpWide==0 ){ + return 0; + } + zTextUtf8 = winUnicodeToUtf8(zTmpWide); + sqlite3_free(zTmpWide); + return zTextUtf8; +} + +/* +** Convert multibyte character string to UTF-8 using the OEM codepage. +** Space to hold the returned string is obtained from sqlite3_malloc(). +*/ +char *sqlite3_win32_mbcs_to_utf8_via_oem(const char *zText){ + char *zTextUtf8; + LPWSTR zTmpWide; + + zTmpWide = winMbcsToUnicode(zText, 0); + if( zTmpWide==0 ){ + return 0; + } + zTextUtf8 = winUnicodeToUtf8(zTmpWide); + sqlite3_free(zTmpWide); + return zTextUtf8; } /* ** Convert UTF-8 to multibyte character string. Space to hold the ** returned string is obtained from sqlite3_malloc(). */ -char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){ - char *zFilenameMbcs; +char *sqlite3_win32_utf8_to_mbcs(const char *zText){ + char *zTextMbcs; LPWSTR zTmpWide; - zTmpWide = winUtf8ToUnicode(zFilename); + zTmpWide = winUtf8ToUnicode(zText); if( zTmpWide==0 ){ return 0; } - zFilenameMbcs = winUnicodeToMbcs(zTmpWide); + zTextMbcs = winUnicodeToMbcs(zTmpWide, osAreFileApisANSI()); sqlite3_free(zTmpWide); - return zFilenameMbcs; + return zTextMbcs; +} + +/* +** Convert UTF-8 to multibyte character string using the ANSI codepage. +** Space to hold the returned string is obtained from sqlite3_malloc(). +*/ +char *sqlite3_win32_utf8_to_mbcs_via_ansi(const char *zText){ + char *zTextMbcs; + LPWSTR zTmpWide; + + zTmpWide = winUtf8ToUnicode(zText); + if( zTmpWide==0 ){ + return 0; + } + zTextMbcs = winUnicodeToMbcs(zTmpWide, 1); + sqlite3_free(zTmpWide); + return zTextMbcs; +} + +/* +** Convert UTF-8 to multibyte character string using the OEM codepage. +** Space to hold the returned string is obtained from sqlite3_malloc(). +*/ +char *sqlite3_win32_utf8_to_mbcs_via_oem(const char *zText){ + char *zTextMbcs; + LPWSTR zTmpWide; + + zTmpWide = winUtf8ToUnicode(zText); + if( zTmpWide==0 ){ + return 0; + } + zTextMbcs = winUnicodeToMbcs(zTmpWide, 0); + sqlite3_free(zTmpWide); + return zTextMbcs; } /* From 12931203457ed2162284173cf048d79895ab8d43 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 4 Apr 2016 02:05:46 +0000 Subject: [PATCH 556/570] More refactoring and cleanup work on the Win32 string conversion and utility routines. FossilOrigin-Name: 02ccb444a3d0b9a52ffd04cae9d9b6f654128c35 --- manifest | 12 +-- manifest.uuid | 2 +- src/os_win.c | 235 +++++++++++++++++++++++++++++--------------------- 3 files changed, 142 insertions(+), 107 deletions(-) diff --git a/manifest b/manifest index 0687355cf6..1ff9f109e9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Revise\sand\senhance\sthe\sWin32\sstring\sconversion\sroutines. -D 2016-04-03T22:44:16.657 +C More\srefactoring\sand\scleanup\swork\son\sthe\sWin32\sstring\sconversion\sand\sutility\sroutines. +D 2016-04-04T02:05:46.170 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -358,7 +358,7 @@ F src/os.h 91ff889115ecd01f436d3611f7f5ea4dc12d92f1 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c b1ccb273771f41dbdbe0ba7c1ad63c38ad5972ec -F src/os_win.c 01ae58949a28edaecd5645abbe29ac9d2ee983fd +F src/os_win.c b3ba9573d8d893e70a6a8015bbee572ecf7ffbef F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 38718a019ca762ba4f6795425d5a54db70d1790d F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56 @@ -1480,7 +1480,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 f76c3a0ca40989fe9401c3b6f662f8e6ef2a730c -R 9a8e623b20453c0fbff989d22019add7 +P 345860c92195544aad44ea9b0d14c9ebbd50adf2 +R 8daf8efac2ee8825007360be7ce04871 U mistachkin -Z 149573e0b667520348654eca6c5f3228 +Z a69ce6a98d15b1e2f1ce825b8343a90e diff --git a/manifest.uuid b/manifest.uuid index 280e3ae958..d7da1c1daf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -345860c92195544aad44ea9b0d14c9ebbd50adf2 \ No newline at end of file +02ccb444a3d0b9a52ffd04cae9d9b6f654128c35 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index 9508c97a14..4aca70b6c9 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -1306,6 +1306,12 @@ void sqlite3_win32_write_debug(const char *zBuf, int nBuf){ int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */ if( nMin<-1 ) nMin = -1; /* all negative values become -1. */ assert( nMin==-1 || nMin==0 || nMin0 ){ memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); @@ -1631,9 +1637,9 @@ void sqlite3MemSetDefault(void){ #endif /* SQLITE_WIN32_MALLOC */ /* -** Convert a UTF-8 string to Microsoft Unicode (UTF-16?). +** Convert a UTF-8 string to Microsoft Unicode. ** -** Space to hold the returned string is obtained from malloc. +** Space to hold the returned string is obtained from sqlite3_malloc(). */ static LPWSTR winUtf8ToUnicode(const char *zText){ int nChar; @@ -1657,8 +1663,9 @@ static LPWSTR winUtf8ToUnicode(const char *zText){ } /* -** Convert Microsoft Unicode to UTF-8. Space to hold the returned string is -** obtained from sqlite3_malloc(). +** Convert a Microsoft Unicode string to UTF-8. +** +** Space to hold the returned string is obtained from sqlite3_malloc(). */ static char *winUnicodeToUtf8(LPCWSTR zWideText){ int nByte; @@ -1682,15 +1689,14 @@ static char *winUnicodeToUtf8(LPCWSTR zWideText){ } /* -** Convert an ANSI string to Microsoft Unicode, based on the -** current codepage settings for file apis. +** Convert an ANSI string to Microsoft Unicode, using the ANSI or OEM +** code page. ** -** Space to hold the returned string is obtained -** from sqlite3_malloc. +** Space to hold the returned string is obtained from sqlite3_malloc(). */ static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){ int nByte; - LPWSTR zMbcsFilename; + LPWSTR zMbcsText; int codepage = useAnsi ? CP_ACP : CP_OEMCP; nByte = osMultiByteToWideChar(codepage, 0, zText, -1, NULL, @@ -1698,25 +1704,24 @@ static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){ if( nByte==0 ){ return 0; } - zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) ); - if( zMbcsFilename==0 ){ + zMbcsText = sqlite3MallocZero( nByte*sizeof(WCHAR) ); + if( zMbcsText==0 ){ return 0; } - nByte = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsFilename, + nByte = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText, nByte); if( nByte==0 ){ - sqlite3_free(zMbcsFilename); - zMbcsFilename = 0; + sqlite3_free(zMbcsText); + zMbcsText = 0; } - return zMbcsFilename; + return zMbcsText; } /* -** Convert Microsoft Unicode to multi-byte character string, based on the -** user's ANSI codepage. +** Convert a Microsoft Unicode string to a multi-byte character string, +** using the ANSI or OEM code page. ** -** Space to hold the returned string is obtained from -** sqlite3_malloc(). +** Space to hold the returned string is obtained from sqlite3_malloc(). */ static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi){ int nByte; @@ -1741,105 +1746,135 @@ static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi){ } /* -** Convert multibyte character string to UTF-8. Space to hold the -** returned string is obtained from sqlite3_malloc(). +** Convert a multi-byte character string to UTF-8. +** +** Space to hold the returned string is obtained from sqlite3_malloc(). +*/ +static char *winMbcsToUtf8(const char *zText, int useAnsi){ + char *zTextUtf8; + LPWSTR zTmpWide; + + zTmpWide = winMbcsToUnicode(zText, useAnsi); + if( zTmpWide==0 ){ + return 0; + } + zTextUtf8 = winUnicodeToUtf8(zTmpWide); + sqlite3_free(zTmpWide); + return zTextUtf8; +} + +/* +** Convert a UTF-8 string to a multi-byte character string. +** +** Space to hold the returned string is obtained from sqlite3_malloc(). +*/ +static char *winUtf8ToMbcs(const char *zText, int useAnsi){ + char *zTextMbcs; + LPWSTR zTmpWide; + + zTmpWide = winUtf8ToUnicode(zText); + if( zTmpWide==0 ){ + return 0; + } + zTextMbcs = winUnicodeToMbcs(zTmpWide, useAnsi); + sqlite3_free(zTmpWide); + return zTextMbcs; +} + +/* +** This is a public wrapper for the winUtf8ToUnicode() function. +*/ +LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !zText ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return winUtf8ToUnicode(zText); +} + +/* +** This is a public wrapper for the winUnicodeToUtf8() function. +*/ +char *sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !zWideText ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return winUnicodeToUtf8(zWideText); +} + +/* +** This is a public wrapper for the winMbcsToUtf8() function. */ char *sqlite3_win32_mbcs_to_utf8(const char *zText){ - char *zTextUtf8; - LPWSTR zTmpWide; - - zTmpWide = winMbcsToUnicode(zText, osAreFileApisANSI()); - if( zTmpWide==0 ){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !zText ){ + (void)SQLITE_MISUSE_BKPT; return 0; } - zTextUtf8 = winUnicodeToUtf8(zTmpWide); - sqlite3_free(zTmpWide); - return zTextUtf8; +#endif +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return winMbcsToUtf8(zText, osAreFileApisANSI()); } /* -** Convert multibyte character string to UTF-8 using the ANSI codepage. -** Space to hold the returned string is obtained from sqlite3_malloc(). +** This is a public wrapper for the winMbcsToUtf8() function. */ -char *sqlite3_win32_mbcs_to_utf8_via_ansi(const char *zText){ - char *zTextUtf8; - LPWSTR zTmpWide; - - zTmpWide = winMbcsToUnicode(zText, 1); - if( zTmpWide==0 ){ +char *sqlite3_win32_mbcs_to_utf8_v2(const char *zText, int useAnsi){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !zText ){ + (void)SQLITE_MISUSE_BKPT; return 0; } - zTextUtf8 = winUnicodeToUtf8(zTmpWide); - sqlite3_free(zTmpWide); - return zTextUtf8; +#endif +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return winMbcsToUtf8(zText, useAnsi); } /* -** Convert multibyte character string to UTF-8 using the OEM codepage. -** Space to hold the returned string is obtained from sqlite3_malloc(). -*/ -char *sqlite3_win32_mbcs_to_utf8_via_oem(const char *zText){ - char *zTextUtf8; - LPWSTR zTmpWide; - - zTmpWide = winMbcsToUnicode(zText, 0); - if( zTmpWide==0 ){ - return 0; - } - zTextUtf8 = winUnicodeToUtf8(zTmpWide); - sqlite3_free(zTmpWide); - return zTextUtf8; -} - -/* -** Convert UTF-8 to multibyte character string. Space to hold the -** returned string is obtained from sqlite3_malloc(). +** This is a public wrapper for the winUtf8ToMbcs() function. */ char *sqlite3_win32_utf8_to_mbcs(const char *zText){ - char *zTextMbcs; - LPWSTR zTmpWide; - - zTmpWide = winUtf8ToUnicode(zText); - if( zTmpWide==0 ){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !zText ){ + (void)SQLITE_MISUSE_BKPT; return 0; } - zTextMbcs = winUnicodeToMbcs(zTmpWide, osAreFileApisANSI()); - sqlite3_free(zTmpWide); - return zTextMbcs; +#endif +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return winUtf8ToMbcs(zText, osAreFileApisANSI()); } /* -** Convert UTF-8 to multibyte character string using the ANSI codepage. -** Space to hold the returned string is obtained from sqlite3_malloc(). +** This is a public wrapper for the winUtf8ToMbcs() function. */ -char *sqlite3_win32_utf8_to_mbcs_via_ansi(const char *zText){ - char *zTextMbcs; - LPWSTR zTmpWide; - - zTmpWide = winUtf8ToUnicode(zText); - if( zTmpWide==0 ){ +char *sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !zText ){ + (void)SQLITE_MISUSE_BKPT; return 0; } - zTextMbcs = winUnicodeToMbcs(zTmpWide, 1); - sqlite3_free(zTmpWide); - return zTextMbcs; -} - -/* -** Convert UTF-8 to multibyte character string using the OEM codepage. -** Space to hold the returned string is obtained from sqlite3_malloc(). -*/ -char *sqlite3_win32_utf8_to_mbcs_via_oem(const char *zText){ - char *zTextMbcs; - LPWSTR zTmpWide; - - zTmpWide = winUtf8ToUnicode(zText); - if( zTmpWide==0 ){ - return 0; - } - zTextMbcs = winUnicodeToMbcs(zTmpWide, 0); - sqlite3_free(zTmpWide); - return zTextMbcs; +#endif +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return winUtf8ToMbcs(zText, useAnsi); } /* @@ -1941,7 +1976,7 @@ static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){ if( dwLen > 0 ){ /* allocate a buffer and convert to UTF8 */ sqlite3BeginBenignMalloc(); - zOut = sqlite3_win32_mbcs_to_utf8(zTemp); + zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI()); sqlite3EndBenignMalloc(); /* free the system buffer allocated by FormatMessage */ osLocalFree(zTemp); @@ -4386,7 +4421,7 @@ static char *winConvertToUtf8Filename(const void *zFilename){ } #ifdef SQLITE_WIN32_HAS_ANSI else{ - zConverted = sqlite3_win32_mbcs_to_utf8(zFilename); + zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI()); } #endif /* caller will handle out of memory */ @@ -4407,7 +4442,7 @@ static void *winConvertFromUtf8Filename(const char *zFilename){ } #ifdef SQLITE_WIN32_HAS_ANSI else{ - zConverted = sqlite3_win32_utf8_to_mbcs(zFilename); + zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI()); } #endif /* caller will handle out of memory */ @@ -4608,7 +4643,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(), "winGetTempname3", 0); } - zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath); + zUtf8 = winMbcsToUtf8(zMbcsPath, osAreFileApisANSI()); if( zUtf8 ){ sqlite3_snprintf(nMax, zBuf, "%s", zUtf8); sqlite3_free(zUtf8); @@ -5386,7 +5421,7 @@ static int winFullPathname( "winFullPathname4", zRelative); } sqlite3_free(zConverted); - zOut = sqlite3_win32_mbcs_to_utf8(zTemp); + zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI()); sqlite3_free(zTemp); } #endif From 1fe36bb8a81b9b547eda6cbd96b143e952e61424 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 4 Apr 2016 02:16:44 +0000 Subject: [PATCH 557/570] Experimental changes to the command line shell to make it work better with Unicode on Windows. FossilOrigin-Name: 74183a5f803999e1d4e288851c72519c3c53f6b5 --- manifest | 14 +-- manifest.uuid | 2 +- src/shell.c | 268 +++++++++++++++++++++++++++-------------------- test/shell1.test | 47 ++++++--- 4 files changed, 194 insertions(+), 137 deletions(-) diff --git a/manifest b/manifest index 1ff9f109e9..8b566a8537 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C More\srefactoring\sand\scleanup\swork\son\sthe\sWin32\sstring\sconversion\sand\sutility\sroutines. -D 2016-04-04T02:05:46.170 +C Experimental\schanges\sto\sthe\scommand\sline\sshell\sto\smake\sit\swork\sbetter\swith\sUnicode\son\sWindows. +D 2016-04-04T02:16:44.372 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -374,7 +374,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 7849cee0a01952a9c93cd28989daedfa57731143 -F src/shell.c e126f647f63da3d5d820f012359b89075cd7de99 +F src/shell.c cfe5edc196c7ab109b6ea728a69dc9346e03f4f7 F src/sqlite.h.in c46a7b85d3f37371cacea8f98ec825f5e52c420c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 @@ -1049,7 +1049,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test dff5b20ad989770aface6d714491121172dfe8b0 +F test/shell1.test 95b172b3854413a566e1e16da0a9aeae25966f4c F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b F test/shell3.test da513d522ef6f01cee8475dcf8332bff8982b3dd F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9 @@ -1480,7 +1480,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 345860c92195544aad44ea9b0d14c9ebbd50adf2 -R 8daf8efac2ee8825007360be7ce04871 +P 02ccb444a3d0b9a52ffd04cae9d9b6f654128c35 +R 12b05bab5737c52c6e35683f2e505d88 U mistachkin -Z a69ce6a98d15b1e2f1ce825b8343a90e +Z 02f8d2df1ede1dbca37f29a3d0ba1aa0 diff --git a/manifest.uuid b/manifest.uuid index d7da1c1daf..828cd80a90 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -02ccb444a3d0b9a52ffd04cae9d9b6f654128c35 \ No newline at end of file +74183a5f803999e1d4e288851c72519c3c53f6b5 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 9cec288024..5ac2f4a480 100644 --- a/src/shell.c +++ b/src/shell.c @@ -90,7 +90,7 @@ #else -# define shell_read_history(X) +# define shell_read_history(X) # define shell_write_history(X) # define shell_stifle_history(X) @@ -136,6 +136,15 @@ #define IsDigit(X) isdigit((unsigned char)X) #define ToLower(X) (char)tolower((unsigned char)X) +#if defined(_WIN32) || defined(WIN32) +#include + +/* string conversion routines only needed on Win32 */ +extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR); +extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int); +extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int); +#endif + /* On Windows, we normally run with output mode of TEXT so that \n characters ** are automatically translated into \r\n. However, this behavior needs ** to be disabled in some cases (ex: when generating CSV output and when @@ -143,17 +152,17 @@ ** routines take care of that. */ #if defined(_WIN32) || defined(WIN32) -static void setBinaryMode(FILE *out){ - fflush(out); - _setmode(_fileno(out), _O_BINARY); +static void setBinaryMode(FILE *file, int isOutput){ + if( isOutput ) fflush(file); + _setmode(_fileno(file), _O_BINARY); } -static void setTextMode(FILE *out){ - fflush(out); - _setmode(_fileno(out), _O_TEXT); +static void setTextMode(FILE *file, int isOutput){ + if( isOutput ) fflush(file); + _setmode(_fileno(file), _O_TEXT); } #else -# define setBinaryMode(X) -# define setTextMode(X) +# define setBinaryMode(X,Y) +# define setTextMode(X,Y) #endif @@ -204,7 +213,7 @@ static void beginTimer(void){ /* Return the difference of two time_structs in seconds */ static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ - return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + + return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + (double)(pEnd->tv_sec - pStart->tv_sec); } @@ -229,8 +238,6 @@ static void endTimer(void){ #elif (defined(_WIN32) || defined(WIN32)) -#include - /* Saved resource information for the beginning of an operation */ static HANDLE hProcess; static FILETIME ftKernelBegin; @@ -261,7 +268,7 @@ static int hasTimer(void){ if( NULL != getProcessTimesAddr ){ return 1; } - FreeLibrary(hinstLib); + FreeLibrary(hinstLib); } } } @@ -307,7 +314,7 @@ static void endTimer(void){ #define HAS_TIMER hasTimer() #else -#define BEGIN_TIMER +#define BEGIN_TIMER #define END_TIMER #define HAS_TIMER 0 #endif @@ -371,9 +378,8 @@ void utf8_printf(FILE *out, const char *zFormat, ...){ va_list ap; va_start(ap, zFormat); if( stdout_is_console && (out==stdout || out==stderr) ){ - extern char *sqlite3_win32_utf8_to_mbcs(const char*); char *z1 = sqlite3_vmprintf(zFormat, ap); - char *z2 = sqlite3_win32_utf8_to_mbcs(z1); + char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0); sqlite3_free(z1); fputs(z2, out); sqlite3_free(z2); @@ -449,8 +455,8 @@ static int isNumber(const char *z, int *realnum){ } /* -** A global char* and an SQL function to access its current value -** from within an SQL statement. This program used to use the +** A global char* and an SQL function to access its current value +** from within an SQL statement. This program used to use the ** sqlite_exec_printf() API to substitue a string into an SQL statement. ** The correct way to do this with sqlite3 is to use the bind API, but ** since the shell is built around the callback paradigm it would be a lot @@ -516,11 +522,10 @@ static char *local_getline(char *zLine, FILE *in){ } } #if defined(_WIN32) || defined(WIN32) - /* For interactive input on Windows systems, translate the + /* For interactive input on Windows systems, translate the ** multi-byte characterset characters into UTF-8. */ if( stdin_is_interactive ){ - extern char *sqlite3_win32_mbcs_to_utf8(const char*); - char *zTrans = sqlite3_win32_mbcs_to_utf8(zLine); + char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0); if( zTrans ){ int nTrans = strlen30(zTrans)+1; if( nTrans>nLine ){ @@ -586,7 +591,7 @@ struct OpenSession { #endif /* -** Shell output mode information from before ".explain on", +** Shell output mode information from before ".explain on", ** saved so that it can be restored by ".explain off" */ typedef struct SavedModeInfo SavedModeInfo; @@ -723,7 +728,7 @@ static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ static void output_quoted_string(FILE *out, const char *z){ int i; int nSingle = 0; - setBinaryMode(out); + setBinaryMode(out, 1); for(i=0; z[i]; i++){ if( z[i]=='\'' ) nSingle++; } @@ -746,7 +751,7 @@ static void output_quoted_string(FILE *out, const char *z){ } raw_printf(out,"'"); } - setTextMode(out); + setTextMode(out, 1); } /* @@ -788,11 +793,11 @@ static void output_html_string(FILE *out, const char *z){ int i; if( z==0 ) z = ""; while( *z ){ - for(i=0; z[i] - && z[i]!='<' - && z[i]!='&' - && z[i]!='>' - && z[i]!='\"' + for(i=0; z[i] + && z[i]!='<' + && z[i]!='&' + && z[i]!='>' + && z[i]!='\"' && z[i]!='\''; i++){} if( i>0 ){ @@ -820,22 +825,22 @@ static void output_html_string(FILE *out, const char *z){ ** array, then the string must be quoted for CSV. */ static const char needCsvQuote[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; /* @@ -852,8 +857,8 @@ static void output_csv(ShellState *p, const char *z, int bSep){ int i; int nSep = strlen30(p->colSeparator); for(i=0; z[i]; i++){ - if( needCsvQuote[((unsigned char*)z)[i]] - || (z[i]==p->colSeparator[0] && + if( needCsvQuote[((unsigned char*)z)[i]] + || (z[i]==p->colSeparator[0] && (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){ i = 0; break; @@ -1063,7 +1068,7 @@ static int shell_callback( break; } case MODE_Csv: { - setBinaryMode(p->out); + setBinaryMode(p->out, 1); if( p->cnt++==0 && p->showHeader ){ for(i=0; iout, "%s", p->rowSeparator); } - setTextMode(p->out); + setTextMode(p->out, 1); break; } case MODE_Insert: { @@ -1189,7 +1194,7 @@ static void set_table_name(ShellState *p, const char *zName){ ** added to zIn, and the result returned in memory obtained from malloc(). ** zIn, if it was not NULL, is freed. ** -** If the third argument, quote, is not '\0', then it is used as a +** If the third argument, quote, is not '\0', then it is used as a ** quote character for zAppend. */ static char *appendText(char *zIn, char const *zAppend, char quote){ @@ -1236,7 +1241,7 @@ static char *appendText(char *zIn, char const *zAppend, char quote){ ** semicolon terminator to the end of that line. ** ** If the number of columns is 1 and that column contains text "--" -** then write the semicolon on a separate line. That way, if a +** then write the semicolon on a separate line. That way, if a ** "--" comment occurs at the end of the statement, the comment ** won't consume the semicolon terminator. */ @@ -1266,7 +1271,7 @@ static int run_table_dump_query( } z = (const char*)sqlite3_column_text(pSelect, 0); utf8_printf(p->out, "%s", z); - for(i=1; iout, ",%s", sqlite3_column_text(pSelect, i)); } if( z==0 ) z = ""; @@ -1275,7 +1280,7 @@ static int run_table_dump_query( raw_printf(p->out, "\n;\n"); }else{ raw_printf(p->out, ";\n"); - } + } rc = sqlite3_step(pSelect); } rc = sqlite3_finalize(pSelect); @@ -1334,7 +1339,7 @@ static void displayLinuxIoStats(FILE *out){ } } fclose(in); -} +} #endif @@ -1350,7 +1355,7 @@ static int display_stats( int iHiwtr; if( pArg && pArg->out ){ - + iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset); raw_printf(pArg->out, @@ -1434,18 +1439,18 @@ static int display_stats( raw_printf(pArg->out, "Page cache hits: %d\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1); - raw_printf(pArg->out, "Page cache misses: %d\n", iCur); + raw_printf(pArg->out, "Page cache misses: %d\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1); - raw_printf(pArg->out, "Page cache writes: %d\n", iCur); + raw_printf(pArg->out, "Page cache writes: %d\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n", - iCur); + iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", - iCur); + iCur); } if( pArg && pArg->out && db && pArg->pStmt ){ @@ -1507,7 +1512,7 @@ static void display_scanstats( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain); utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain); rEstLoop *= rEst; - raw_printf(pArg->out, + raw_printf(pArg->out, " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n", nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst ); @@ -1534,7 +1539,7 @@ static int str_in_array(const char *zStr, const char **azArray){ /* ** If compiled statement pSql appears to be an EXPLAIN statement, allocate ** and populate the ShellState.aiIndent[] array with the number of -** spaces each opcode should be indented before it is output. +** spaces each opcode should be indented before it is output. ** ** The indenting rules are: ** @@ -1639,12 +1644,12 @@ static void explain_data_delete(ShellState *p){ } /* -** Execute a statement or set of statements. Print -** any result rows/columns depending on the current mode +** Execute a statement or set of statements. Print +** any result rows/columns depending on the current mode ** set via the supplied callback. ** -** This is very similar to SQLite's built-in sqlite3_exec() -** function except it takes a slightly different callback +** This is very similar to SQLite's built-in sqlite3_exec() +** function except it takes a slightly different callback ** and callback data argument. */ static int shell_exec( @@ -1716,7 +1721,7 @@ static int shell_exec( ){ pArg->cMode = MODE_Explain; } - + /* If the shell is currently in ".explain" mode, gather the extra ** data required to add indents to the output.*/ if( pArg->cMode==MODE_Explain ){ @@ -1742,7 +1747,7 @@ static int shell_exec( char **azVals = &azCols[nCol]; /* Results */ int *aiTypes = (int *)&azVals[nCol]; /* Result types */ int i, x; - assert(sizeof(int) <= sizeof(char *)); + assert(sizeof(int) <= sizeof(char *)); /* save off ptrs to column names */ for(i=0; idb==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ - utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", + utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", p->zDbFilename, sqlite3_errmsg(p->db)); if( keepAlive ) return; exit(1); @@ -2345,7 +2350,7 @@ static void output_file_close(FILE *f){ /* ** Try to open an output file. The names "stdout" and "stderr" are -** recognized and do the right thing. NULL is returned if the output +** recognized and do the right thing. NULL is returned if the output ** filename is "off". */ static FILE *output_file_open(const char *zFile){ @@ -2534,7 +2539,7 @@ static void tryToCloneData( sqlite3 *newDb, const char *zTable ){ - sqlite3_stmt *pQuery = 0; + sqlite3_stmt *pQuery = 0; sqlite3_stmt *pInsert = 0; char *zQuery = 0; char *zInsert = 0; @@ -2838,9 +2843,9 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ utf8_printf(p->out, "%-20s %u", aField[i].zName, val); switch( ofst ){ case 56: { - if( val==1 ) raw_printf(p->out, " (utf8)"); - if( val==2 ) raw_printf(p->out, " (utf16le)"); - if( val==3 ) raw_printf(p->out, " (utf16be)"); + if( val==1 ) raw_printf(p->out, " (utf8)"); + if( val==2 ) raw_printf(p->out, " (utf16le)"); + if( val==3 ) raw_printf(p->out, " (utf16be)"); } } raw_printf(p->out, "\n"); @@ -2900,9 +2905,9 @@ static int do_meta_command(char *zLine, ShellState *p){ if( zLine[h]=='\'' || zLine[h]=='"' ){ int delim = zLine[h++]; azArg[nArg++] = &zLine[h]; - while( zLine[h] && zLine[h]!=delim ){ + while( zLine[h] && zLine[h]!=delim ){ if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++; - h++; + h++; } if( zLine[h]==delim ){ zLine[h++] = 0; @@ -2989,9 +2994,9 @@ static int do_meta_command(char *zLine, ShellState *p){ if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){ if( nArg==2 ){ if( booleanValue(azArg[1]) ){ - setBinaryMode(p->out); + setBinaryMode(p->out, 1); }else{ - setTextMode(p->out); + setTextMode(p->out, 1); } }else{ raw_printf(stderr, "Usage: .binary on|off\n"); @@ -3063,11 +3068,11 @@ static int do_meta_command(char *zLine, ShellState *p){ sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); p->nErr = 0; if( nArg==1 ){ - run_schema_dump_query(p, + run_schema_dump_query(p, "SELECT name, type, sql FROM sqlite_master " "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'" ); - run_schema_dump_query(p, + run_schema_dump_query(p, "SELECT name, type, sql FROM sqlite_master " "WHERE name=='sqlite_sequence'" ); @@ -3116,7 +3121,7 @@ static int do_meta_command(char *zLine, ShellState *p){ }else{ raw_printf(stderr, "Usage: .eqp on|off\n"); rc = 1; - } + } }else if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ @@ -3498,7 +3503,7 @@ static int do_meta_command(char *zLine, ShellState *p){ open_db(p, 0); if( nArg==1 ){ for(i=0; idb, aLimit[i].limitCode, -1)); } }else if( nArg>3 ){ @@ -3935,7 +3940,7 @@ static int do_meta_command(char *zLine, ShellState *p){ printf("Error: error code %d\n", rc); rc = 0; } - if( pChng + if( pChng && fwrite(pChng, szChng, 1, out)!=1 ){ raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n", szChng); @@ -3988,7 +3993,7 @@ static int do_meta_command(char *zLine, ShellState *p){ exit(1); } for(ii=1; iiazFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]); + pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]); } pSession->nFilter = ii-1; } @@ -4321,9 +4326,9 @@ static int do_meta_command(char *zLine, ShellState *p){ /* sqlite3_test_control(int, db, int) */ case SQLITE_TESTCTRL_OPTIMIZATIONS: - case SQLITE_TESTCTRL_RESERVE: + case SQLITE_TESTCTRL_RESERVE: if( nArg==3 ){ - int opt = (int)strtol(azArg[2], 0, 0); + int opt = (int)strtol(azArg[2], 0, 0); rc2 = sqlite3_test_control(testctrl, p->db, opt); raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); } else { @@ -4347,7 +4352,7 @@ static int do_meta_command(char *zLine, ShellState *p){ break; /* sqlite3_test_control(int, uint) */ - case SQLITE_TESTCTRL_PENDING_BYTE: + case SQLITE_TESTCTRL_PENDING_BYTE: if( nArg==3 ){ unsigned int opt = (unsigned int)integerValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, opt); @@ -4357,13 +4362,13 @@ static int do_meta_command(char *zLine, ShellState *p){ " int option\n", azArg[1]); } break; - + /* sqlite3_test_control(int, int) */ - case SQLITE_TESTCTRL_ASSERT: - case SQLITE_TESTCTRL_ALWAYS: - case SQLITE_TESTCTRL_NEVER_CORRUPT: + case SQLITE_TESTCTRL_ASSERT: + case SQLITE_TESTCTRL_ALWAYS: + case SQLITE_TESTCTRL_NEVER_CORRUPT: if( nArg==3 ){ - int opt = booleanValue(azArg[2]); + int opt = booleanValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, opt); raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); } else { @@ -4374,9 +4379,9 @@ static int do_meta_command(char *zLine, ShellState *p){ /* sqlite3_test_control(int, char *) */ #ifdef SQLITE_N_KEYWORD - case SQLITE_TESTCTRL_ISKEYWORD: + case SQLITE_TESTCTRL_ISKEYWORD: if( nArg==3 ){ - const char *opt = azArg[2]; + const char *opt = azArg[2]; rc2 = sqlite3_test_control(testctrl, opt); raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); } else { @@ -4389,7 +4394,7 @@ static int do_meta_command(char *zLine, ShellState *p){ case SQLITE_TESTCTRL_IMPOSTER: if( nArg==5 ){ - rc2 = sqlite3_test_control(testctrl, p->db, + rc2 = sqlite3_test_control(testctrl, p->db, azArg[2], integerValue(azArg[3]), integerValue(azArg[4])); @@ -4399,10 +4404,10 @@ static int do_meta_command(char *zLine, ShellState *p){ } break; - case SQLITE_TESTCTRL_BITVEC_TEST: - case SQLITE_TESTCTRL_FAULT_INSTALL: - case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: - case SQLITE_TESTCTRL_SCRATCHMALLOC: + case SQLITE_TESTCTRL_BITVEC_TEST: + case SQLITE_TESTCTRL_FAULT_INSTALL: + case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: + case SQLITE_TESTCTRL_SCRATCHMALLOC: default: utf8_printf(stderr, "Error: CLI support for testctrl %s not implemented\n", @@ -4416,7 +4421,7 @@ static int do_meta_command(char *zLine, ShellState *p){ open_db(p, 0); sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); }else - + if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){ if( nArg==2 ){ enableTimer = booleanValue(azArg[1]); @@ -4429,7 +4434,7 @@ static int do_meta_command(char *zLine, ShellState *p){ rc = 1; } }else - + if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){ open_db(p, 0); if( nArg!=2 ){ @@ -4509,7 +4514,7 @@ static int do_meta_command(char *zLine, ShellState *p){ raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n"); rc = 1; goto meta_command_exit; - } + } }else #endif /* SQLITE_USER_AUTHENTICATION */ @@ -4741,7 +4746,7 @@ static int process_input(ShellState *p, FILE *in){ if( rc || zErrMsg ){ char zPrefix[100]; if( in!=0 || !stdin_is_interactive ){ - sqlite3_snprintf(sizeof(zPrefix), zPrefix, + sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error: near line %d:", startline); }else{ sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:"); @@ -4883,7 +4888,7 @@ static void process_sqliterc( /* ** Show available command line options */ -static const char zOptions[] = +static const char zOptions[] = " -ascii set output mode to 'ascii'\n" " -bail stop after hitting an error\n" " -batch force batch I/O\n" @@ -4920,7 +4925,7 @@ static const char zOptions[] = ; static void usage(int showDetail){ utf8_printf(stderr, - "Usage: %s [OPTIONS] FILENAME [SQL]\n" + "Usage: %s [OPTIONS] FILENAME [SQL]\n" "FILENAME is the name of an SQLite database. A new database is created\n" "if the file does not previously exist.\n", Argv0); if( showDetail ){ @@ -4982,7 +4987,20 @@ static char *cmdline_option_value(int argc, char **argv, int i){ return argv[i]; } +#ifndef SQLITE_SHELL_IS_UTF8 +# if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER) +# define SQLITE_SHELL_IS_UTF8 (0) +# else +# define SQLITE_SHELL_IS_UTF8 (1) +# endif +#endif + +#if SQLITE_SHELL_IS_UTF8 int SQLITE_CDECL main(int argc, char **argv){ +#else +int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ + char **argv = 0; +#endif char *zErrMsg = 0; ShellState data; const char *zInitFile = 0; @@ -4993,6 +5011,9 @@ int SQLITE_CDECL main(int argc, char **argv){ int nCmd = 0; char **azCmd = 0; + setBinaryMode(stdin, 0); + setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ + #if USE_SYSTEM_SQLITE+0!=1 if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){ utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", @@ -5000,10 +5021,23 @@ int SQLITE_CDECL main(int argc, char **argv){ exit(1); } #endif - setBinaryMode(stdin); - setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ - Argv0 = argv[0]; main_init(&data); +#if !SQLITE_SHELL_IS_UTF8 + sqlite3_initialize(); + argv = sqlite3_malloc64(sizeof(argv[0])*argc); + if( argv==0 ){ + raw_printf(stderr, "out of memory\n"); + exit(1); + } + for(i=0; i Date: Mon, 4 Apr 2016 02:33:34 +0000 Subject: [PATCH 558/570] Refinements to the previous check-in. FossilOrigin-Name: b36dfdff787dc4a107b2c3fcbb98bfc4922872d8 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c | 7 ++++--- test/shell1.test | 4 ++-- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 8b566a8537..050c3442d2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Experimental\schanges\sto\sthe\scommand\sline\sshell\sto\smake\sit\swork\sbetter\swith\sUnicode\son\sWindows. -D 2016-04-04T02:16:44.372 +C Refinements\sto\sthe\sprevious\scheck-in. +D 2016-04-04T02:33:34.200 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -374,7 +374,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 7849cee0a01952a9c93cd28989daedfa57731143 -F src/shell.c cfe5edc196c7ab109b6ea728a69dc9346e03f4f7 +F src/shell.c ba8974732ad24dc8bffc9d9dae8a729edaf45b0d F src/sqlite.h.in c46a7b85d3f37371cacea8f98ec825f5e52c420c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 @@ -1049,7 +1049,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test 95b172b3854413a566e1e16da0a9aeae25966f4c +F test/shell1.test b110f092f64193c7235abd07bab79f1a59f494b1 F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b F test/shell3.test da513d522ef6f01cee8475dcf8332bff8982b3dd F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9 @@ -1480,7 +1480,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 02ccb444a3d0b9a52ffd04cae9d9b6f654128c35 -R 12b05bab5737c52c6e35683f2e505d88 +P 74183a5f803999e1d4e288851c72519c3c53f6b5 +R dc99ab499cebc95aed1812a7f9308be8 U mistachkin -Z 02f8d2df1ede1dbca37f29a3d0ba1aa0 +Z 71f87a99a345de92d46f0c5169631d32 diff --git a/manifest.uuid b/manifest.uuid index 828cd80a90..08c1c3a431 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -74183a5f803999e1d4e288851c72519c3c53f6b5 \ No newline at end of file +b36dfdff787dc4a107b2c3fcbb98bfc4922872d8 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 5ac2f4a480..c0827fa267 100644 --- a/src/shell.c +++ b/src/shell.c @@ -4999,7 +4999,7 @@ static char *cmdline_option_value(int argc, char **argv, int i){ int SQLITE_CDECL main(int argc, char **argv){ #else int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ - char **argv = 0; + char **argv; #endif char *zErrMsg = 0; ShellState data; @@ -5013,6 +5013,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ setBinaryMode(stdin, 0); setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ + stdin_is_interactive = isatty(0); + stdout_is_console = isatty(1); #if USE_SYSTEM_SQLITE+0!=1 if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){ @@ -5037,9 +5039,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ } } #endif + assert( argc>=1 && argv && argv[0] ); Argv0 = argv[0]; - stdin_is_interactive = isatty(0); - stdout_is_console = isatty(1); /* Make sure we have a valid signal handler early, before anything ** else is done. diff --git a/test/shell1.test b/test/shell1.test index 9ff988604e..476af064a5 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -911,7 +911,7 @@ do_test shell1-5.0 { } {} do_test shell1-6.0 { - # The file name here is the word "test" in Chinese. + # The base file name here is the word "test" in Chinese. # In UTF-8, it is encoded as: \xE6\xB5\x8B\xE8\xAF\x95 set fileName \u6D4B\u8BD5; append fileName .db set x [catchcmdex $fileName "CREATE TABLE t1(x);\n.schema\n"] @@ -924,7 +924,7 @@ do_test shell1-6.0 { error "failed with mismatch: $res" } if {![file exists $fileName]} { - error "file \"$fileName\" (MBCS) does not exist" + error "file \"$fileName\" (Unicode) does not exist" } forcedelete $fileName } {} From 51b55a3ee6673631f15f752fb038737ccef34b5f Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2016 12:38:05 +0000 Subject: [PATCH 559/570] Fix harmless compiler warnings. FossilOrigin-Name: 0213d6af84965676626c2fb4d78b4c74675207cc --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/analyze.c | 2 +- src/shell.c | 8 +++++--- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index d573902ae9..16451fe15f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Preupdate\shook\sdocumentation\sfixes.\s\sNo\schanges\sto\scode. -D 2016-04-01T17:54:07.826 +C Fix\sharmless\scompiler\swarnings. +D 2016-04-04T12:38:05.153 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -311,7 +311,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 1bb0709b3048e24217b80ec6bd78a3e99a47c01b -F src/analyze.c 39b21e4d9ad8a647e9834aa5ba99a74fb6c98879 +F src/analyze.c 37fedc80ac966ce1745811746e68e4d8fa64c7fe F src/attach.c 771153bd1f4ab0b97a44a13dde2c7e5e1efeba22 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce @@ -374,7 +374,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 7849cee0a01952a9c93cd28989daedfa57731143 -F src/shell.c cd3f82fdc5c895b817a375b7ab8319cb41f447ce +F src/shell.c faa783401b0c25e52e4054a7292a78ab2f76d210 F src/sqlite.h.in c46a7b85d3f37371cacea8f98ec825f5e52c420c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 @@ -1480,7 +1480,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 a62340dc0507e36f6dec05b1fda68d8399ec62ec -R 17cbd88111da841c5ced2fa2ee956e9f +P 59814f35d13db1f6379b9ae218b5432bc03c6197 +R 5dc90b5728244567537e2c75af0c4605 U drh -Z dfefbe59c009b860b7f7e89f1f29dda4 +Z 8cacf12e28835de4a8d101570828c9f0 diff --git a/manifest.uuid b/manifest.uuid index c694118307..61153ada1f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -59814f35d13db1f6379b9ae218b5432bc03c6197 \ No newline at end of file +0213d6af84965676626c2fb4d78b4c74675207cc \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 423ef0d714..3a81c93245 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1826,7 +1826,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ analysisInfo sInfo; HashElem *i; char *zSql; - int rc; + int rc = SQLITE_OK; assert( iDb>=0 && iDbnDb ); assert( db->aDb[iDb].pBt!=0 ); diff --git a/src/shell.c b/src/shell.c index 2ce2f292dc..58a0d7aa51 100644 --- a/src/shell.c +++ b/src/shell.c @@ -2140,17 +2140,19 @@ static void session_close(OpenSession *pSession){ #endif /* -** Close all OpenSession objects and release all assocaited resources. +** Close all OpenSession objects and release all associated resources. */ -static void session_close_all(ShellState *p){ #if defined(SQLITE_ENABLE_SESSION) +static void session_close_all(ShellState *p){ int i; for(i=0; inSession; i++){ session_close(&p->aSession[i]); } p->nSession = 0; -#endif } +#else +# define session_close_all(X) +#endif /* ** Implementation of the xFilter function for an open session. Omit From 5fd0c12049e0f69581f3bb5cbc98302a8d5db4ca Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2016 13:46:24 +0000 Subject: [PATCH 560/570] Minor performance optimization in the comparison opcodes of the VDBE. FossilOrigin-Name: e375fe52cea7903c11ecef71c3452c67a96b663e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 12 +++++++----- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 16451fe15f..deae1a11e9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarnings. -D 2016-04-04T12:38:05.153 +C Minor\sperformance\soptimization\sin\sthe\scomparison\sopcodes\sof\sthe\sVDBE. +D 2016-04-04T13:46:24.704 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -439,7 +439,7 @@ F src/update.c 3e67ab3c0814635f355fb1f8ab010a2b9e016e7d F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 8873d696c9ccc4206058c402e09e101f1b81561a F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 -F src/vdbe.c 0f0e4a6255f9a5272857a818314d081db26bcd90 +F src/vdbe.c 936166d3dc5aa00364877603f545707896c1519e F src/vdbe.h c16ba943d407baa1c7085eefea73a063fc631863 F src/vdbeInt.h ddb157974436d87652de7dc641f7191496d9a8cd F src/vdbeapi.c ba85b78fe08dc4a9ce747e62c89a2b4a4547e74c @@ -1480,7 +1480,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 59814f35d13db1f6379b9ae218b5432bc03c6197 -R 5dc90b5728244567537e2c75af0c4605 +P 0213d6af84965676626c2fb4d78b4c74675207cc +R 20833b687cd0398f4e539411826fc13a U drh -Z 8cacf12e28835de4a8d101570828c9f0 +Z 68baca12d82e219ae03586c49d91929a diff --git a/manifest.uuid b/manifest.uuid index 61153ada1f..b3dbcfbd15 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0213d6af84965676626c2fb4d78b4c74675207cc \ No newline at end of file +e375fe52cea7903c11ecef71c3452c67a96b663e \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 84a5087e01..f5b00d824a 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2016,11 +2016,13 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ /* Neither operand is NULL. Do a comparison. */ affinity = pOp->p5 & SQLITE_AFF_MASK; if( affinity>=SQLITE_AFF_NUMERIC ){ - if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ - applyNumericAffinity(pIn1,0); - } - if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ - applyNumericAffinity(pIn3,0); + if( (flags1 | flags3)&MEM_Str ){ + if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ + applyNumericAffinity(pIn1,0); + } + if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ + applyNumericAffinity(pIn3,0); + } } }else if( affinity==SQLITE_AFF_TEXT ){ if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){ From 49e1125b69c36bfeee34424792ad7ffe0a8ed060 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 4 Apr 2016 15:47:46 +0000 Subject: [PATCH 561/570] Add and enhance the new tests. FossilOrigin-Name: f4cbd18db47af4af990d7891dcc831e92b3f17e0 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/shell1.test | 24 +++++++++++++++++++++--- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 050c3442d2..451d4e5fdc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Refinements\sto\sthe\sprevious\scheck-in. -D 2016-04-04T02:33:34.200 +C Add\sand\senhance\sthe\snew\stests. +D 2016-04-04T15:47:46.571 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -1049,7 +1049,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test b110f092f64193c7235abd07bab79f1a59f494b1 +F test/shell1.test a216486c6aeae4d3e75e37d64e4b6c8974108750 F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b F test/shell3.test da513d522ef6f01cee8475dcf8332bff8982b3dd F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9 @@ -1480,7 +1480,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 74183a5f803999e1d4e288851c72519c3c53f6b5 -R dc99ab499cebc95aed1812a7f9308be8 +P b36dfdff787dc4a107b2c3fcbb98bfc4922872d8 +R 37b07e38c129266922b712e67867cec6 U mistachkin -Z 71f87a99a345de92d46f0c5169631d32 +Z 3608507dbf100776dbeda9a8b2f0dd8b diff --git a/manifest.uuid b/manifest.uuid index 08c1c3a431..6c13ec95df 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b36dfdff787dc4a107b2c3fcbb98bfc4922872d8 \ No newline at end of file +f4cbd18db47af4af990d7891dcc831e92b3f17e0 \ No newline at end of file diff --git a/test/shell1.test b/test/shell1.test index 476af064a5..36b61c819e 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -910,10 +910,13 @@ do_test shell1-5.0 { } } {} +# The string used here is the word "test" in Chinese. +# In UTF-8, it is encoded as: \xE6\xB5\x8B\xE8\xAF\x95 +set test \u6D4B\u8BD5 + do_test shell1-6.0 { - # The base file name here is the word "test" in Chinese. - # In UTF-8, it is encoded as: \xE6\xB5\x8B\xE8\xAF\x95 - set fileName \u6D4B\u8BD5; append fileName .db + set fileName $test; append fileName .db + catch {forcedelete $fileName} set x [catchcmdex $fileName "CREATE TABLE t1(x);\n.schema\n"] set code [lindex $x 0] set res [string trim [lindex $x 1]] @@ -929,4 +932,19 @@ do_test shell1-6.0 { forcedelete $fileName } {} +do_test shell1-6.1 { + catch {forcedelete test3.db} + set x [catchcmdex test3.db \ + "CREATE TABLE [encoding convertto utf-8 $test](x);\n.schema\n"] + set code [lindex $x 0] + set res [string trim [lindex $x 1]] + if {$code ne "0"} { + error "failed with error: $res" + } + if {$res ne "CREATE TABLE ${test}(x);"} { + error "failed with mismatch: $res" + } + forcedelete test3.db +} {} + finish_test From 455684a03611dbc3a1de4f7e27036cf27f848c5b Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 4 Apr 2016 16:40:44 +0000 Subject: [PATCH 562/570] Test that the view name is passed to the authorization callback when a SELECT statement is run on a view. FossilOrigin-Name: 8627a4cd6d64bd076b56c1e8ccc3b1dfc1b4c07d --- manifest | 15 +++++++-------- manifest.uuid | 2 +- test/auth.test | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index c98d80b73d..9c351dc120 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\ssqlite3session_apply()\sand\ssqlite3session_apply_strm()\sso\sthat\nconflicts\sare\sretried\sbefore\sthe\sxConflict()\scallback\sis\sinvoked,\sas\slong\nas\sthe\s"apply"\soperation\sis\smaking\sforward\sprogress. -D 2016-04-04T14:57:25.972 +C Test\sthat\sthe\sview\sname\sis\spassed\sto\sthe\sauthorization\scallback\swhen\sa\sSELECT\sstatement\sis\srun\son\sa\sview. +D 2016-04-04T16:40:44.335 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -497,7 +497,7 @@ F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d F test/attach3.test 359eb65d00102cdfcef6fa4e81dc1648f8f80b27 F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0 -F test/auth.test 855233ef26eb3601b6886567ea4e326c72959360 +F test/auth.test 872a122b3977c1d1bb9fd637dc20016e5c01880f F test/auth2.test 264c6af53cad9aba5218c68bbe18036e39007bfa F test/auth3.test 5cfa94ed90c6617c42b7ba4b133fd79678b251c7 F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7 @@ -1482,8 +1482,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 e375fe52cea7903c11ecef71c3452c67a96b663e 49763fc3ae2fb6117b0443ea28661568467f9bf2 -R 29983b81bb4a270732770d4dd854ff08 -T +closed 49763fc3ae2fb6117b0443ea28661568467f9bf2 -U drh -Z eb92f633faf3f47383a6550496ee5fc7 +P 42a219668413e18dae917b03b04a21d108cc44be +R 27f4603d27093d983cb0f53232a8c10f +U dan +Z 39b2019f8e2190d9694d9394017c15aa diff --git a/manifest.uuid b/manifest.uuid index 586be52a36..3507c72f05 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -42a219668413e18dae917b03b04a21d108cc44be \ No newline at end of file +8627a4cd6d64bd076b56c1e8ccc3b1dfc1b4c07d \ No newline at end of file diff --git a/test/auth.test b/test/auth.test index f3c2fa79e8..d9e12edc3c 100644 --- a/test/auth.test +++ b/test/auth.test @@ -2432,8 +2432,53 @@ do_test auth-6.3 { execsql {SELECT rowid, * FROM t6} } {101 1 2 3 4 5 6 7 8} +#------------------------------------------------------------------------- +# Test that view names are included as zArg4. +# +do_execsql_test auth-7.1 { + CREATE TABLE t7(a, b, c); + CREATE VIEW v7 AS SELECT * FROM t7; +} {} +set ::authargs [list] +proc auth {args} { + eval lappend ::authargs [lrange $args 0 4] + return SQLITE_OK +} + +do_test auth-7.2 { + execsql {SELECT a, c FROM v7} + set ::authargs +} [list \ + SQLITE_SELECT {} {} {} {} \ + SQLITE_READ t7 a main v7 \ + SQLITE_READ t7 b main v7 \ + SQLITE_READ t7 c main v7 \ + SQLITE_READ v7 a main {} \ + SQLITE_READ v7 c main {} \ + SQLITE_SELECT {} {} {} v7 \ +] + +set ::authargs [list] +do_test auth-7.3 { + execsql {SELECT a, c FROM t7} + set ::authargs +} [list \ + SQLITE_SELECT {} {} {} {} \ + SQLITE_READ t7 a main {} \ + SQLITE_READ t7 c main {} \ +] + +set ::authargs [list] +do_test auth-7.4 { + execsql {SELECT a, c FROM t7 AS v7} + set ::authargs +} [list \ + SQLITE_SELECT {} {} {} {} \ + SQLITE_READ t7 a main {} \ + SQLITE_READ t7 c main {} \ +] + + rename proc {} rename proc_real proc - - finish_test From de613c6d4a60a53d5a4d7fd6fa37450608ca26c1 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2016 17:23:10 +0000 Subject: [PATCH 563/570] Add the ".auth ON|OFF" command to the command-line shell. FossilOrigin-Name: 65c7bcc42786a254966c531ba9062abb8fc8c5bf --- manifest | 14 ++++++------ manifest.uuid | 2 +- src/shell.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 9c351dc120..f50d302e4f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Test\sthat\sthe\sview\sname\sis\spassed\sto\sthe\sauthorization\scallback\swhen\sa\sSELECT\sstatement\sis\srun\son\sa\sview. -D 2016-04-04T16:40:44.335 +C Add\sthe\s".auth\sON|OFF"\scommand\sto\sthe\scommand-line\sshell. +D 2016-04-04T17:23:10.395 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -376,7 +376,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 7849cee0a01952a9c93cd28989daedfa57731143 -F src/shell.c faa783401b0c25e52e4054a7292a78ab2f76d210 +F src/shell.c e0996a0be612c8d2630fdf8bcedf4c4260a29734 F src/sqlite.h.in c46a7b85d3f37371cacea8f98ec825f5e52c420c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 @@ -1482,7 +1482,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 42a219668413e18dae917b03b04a21d108cc44be -R 27f4603d27093d983cb0f53232a8c10f -U dan -Z 39b2019f8e2190d9694d9394017c15aa +P 8627a4cd6d64bd076b56c1e8ccc3b1dfc1b4c07d +R 327fee759e5533f8bd09762659f3f70b +U drh +Z ff39f0b57606b297cab9fa07bc83cd18 diff --git a/manifest.uuid b/manifest.uuid index 3507c72f05..8a44ee2cd4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8627a4cd6d64bd076b56c1e8ccc3b1dfc1b4c07d \ No newline at end of file +65c7bcc42786a254966c531ba9062abb8fc8c5bf \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 58a0d7aa51..809d9d0459 100644 --- a/src/shell.c +++ b/src/shell.c @@ -887,6 +887,52 @@ static void interrupt_handler(int NotUsed){ } #endif +/* +** When the ".auth ON" is set, the following authorizer callback is +** invoked. It always returns SQLITE_OK. +*/ +static int shellAuth( + void *pClientData, + int op, + const char *zA1, + const char *zA2, + const char *zA3, + const char *zA4 +){ + ShellState *p = (ShellState*)pClientData; + static const char *azAction[] = { 0, + "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX", + "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW", + "CREATE_TRIGGER", "CREATE_VIEW", "DELETE", + "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX", + "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW", + "DROP_TRIGGER", "DROP_VIEW", "INSERT", + "PRAGMA", "READ", "SELECT", + "TRANSACTION", "UPDATE", "ATTACH", + "DETACH", "ALTER_TABLE", "REINDEX", + "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE", + "FUNCTION", "SAVEPOINT", "RECURSIVE" + }; + int i; + const char *az[4]; + az[0] = zA1; + az[1] = zA2; + az[2] = zA3; + az[3] = zA4; + raw_printf(p->out, "authorizer: %s", azAction[op]); + for(i=0; i<4; i++){ + raw_printf(p->out, " "); + if( az[i] ){ + output_c_string(p->out, az[i]); + }else{ + raw_printf(p->out, "NULL"); + } + } + raw_printf(p->out, "\n"); + return SQLITE_OK; +} + + /* ** This is the callback routine that the shell ** invokes for each row of a query result. @@ -1958,6 +2004,7 @@ static int run_schema_dump_query( ** Text of a help message */ static char zHelp[] = + ".auth ON|OFF Show authorizer callbacks\n" ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" ".bail on|off Stop after hitting an error. Default OFF\n" ".binary on|off Turn binary output on or off. Default OFF\n" @@ -2923,6 +2970,21 @@ static int do_meta_command(char *zLine, ShellState *p){ if( nArg==0 ) return 0; /* no tokens, no error */ n = strlen30(azArg[0]); c = azArg[0][0]; + + if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){ + if( nArg!=2 ){ + raw_printf(stderr, "Usage: .auth ON|OFF\n"); + rc = 1; + goto meta_command_exit; + } + open_db(p, 0); + if( booleanValue(azArg[1]) ){ + sqlite3_set_authorizer(p->db, shellAuth, p); + }else{ + sqlite3_set_authorizer(p->db, 0, 0); + } + }else + if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0) || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0) ){ From 48dcf2b60b85295a91223a665d8cca7230c9fab4 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 4 Apr 2016 17:59:37 +0000 Subject: [PATCH 564/570] Improve error messages from the 'shell1-5.0' test. FossilOrigin-Name: cefd36ff7b7f142bcebdb16b4d24ae274cdf2709 --- manifest | 15 +++++++-------- manifest.uuid | 2 +- test/shell1.test | 7 ++++++- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 1346fe76ed..9cdd24ac24 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\shandling\sof\sUTF8\sby\sthe\scommand-line\sshell. -D 2016-04-04T17:34:54.498 +C Improve\serror\smessages\sfrom\sthe\s'shell1-5.0'\stest. +D 2016-04-04T17:59:37.790 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -1051,7 +1051,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test a216486c6aeae4d3e75e37d64e4b6c8974108750 +F test/shell1.test b3df199cef9bc722d4078c893a7093d31174ea11 F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b F test/shell3.test da513d522ef6f01cee8475dcf8332bff8982b3dd F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9 @@ -1482,8 +1482,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 65c7bcc42786a254966c531ba9062abb8fc8c5bf f4cbd18db47af4af990d7891dcc831e92b3f17e0 -R 6a3470f790b8def5155325c3cfdf4cee -T +closed f4cbd18db47af4af990d7891dcc831e92b3f17e0 -U drh -Z cd8719efec0532e424e0fef6159fe981 +P 4534ebf15fbcd6fe2028957b7aa591b6cd5da95f +R f892094f49f405a0a06a581ad52203d2 +U mistachkin +Z b9fa5f032554b733f702cb8290f0ece6 diff --git a/manifest.uuid b/manifest.uuid index cf9bd49e8e..27bdbd69e6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4534ebf15fbcd6fe2028957b7aa591b6cd5da95f \ No newline at end of file +cefd36ff7b7f142bcebdb16b4d24ae274cdf2709 \ No newline at end of file diff --git a/test/shell1.test b/test/shell1.test index 36b61c819e..9dd0f42093 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -905,7 +905,12 @@ do_test shell1-5.0 { error "failed with error: $res" } if {$res ne "$oldChar\n"} { - error "failed with byte $hex mismatch" + if {[llength $res] > 0} { + set got [format %02X [scan $res %c]] + } else { + set got + } + error "failed with byte $hex mismatch, got $got" } } } {} From 73a6bb5851f9f7998573f9c60d10465af04992bd Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2016 18:04:56 +0000 Subject: [PATCH 565/570] Fix documentation typos. Comment changes only. No changes to code. FossilOrigin-Name: d5fc2f7f90f8cbd53810c7a445b0e9c9a0e39182 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/sqlite.h.in | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 9cdd24ac24..d2d4f94a79 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\serror\smessages\sfrom\sthe\s'shell1-5.0'\stest. -D 2016-04-04T17:59:37.790 +C Fix\sdocumentation\stypos.\s\sComment\schanges\sonly.\s\sNo\schanges\sto\scode. +D 2016-04-04T18:04:56.616 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -377,7 +377,7 @@ F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c 7849cee0a01952a9c93cd28989daedfa57731143 F src/shell.c b7922fa264f8c8d72a5ec6dd0b091e15a93c4de5 -F src/sqlite.h.in c46a7b85d3f37371cacea8f98ec825f5e52c420c +F src/sqlite.h.in 7f437b068314f053e6417d452c59f08d05092591 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 F src/sqliteInt.h 594bf31a7a0cc788688ca947e562576e23bd7904 @@ -1482,7 +1482,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 4534ebf15fbcd6fe2028957b7aa591b6cd5da95f -R f892094f49f405a0a06a581ad52203d2 -U mistachkin -Z b9fa5f032554b733f702cb8290f0ece6 +P cefd36ff7b7f142bcebdb16b4d24ae274cdf2709 +R febb375a1eed9f049740185e3c47f862 +U drh +Z 64b7ed851fe55fe722cd357618c3eec9 diff --git a/manifest.uuid b/manifest.uuid index 27bdbd69e6..0654e5fabc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cefd36ff7b7f142bcebdb16b4d24ae274cdf2709 \ No newline at end of file +d5fc2f7f90f8cbd53810c7a445b0e9c9a0e39182 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index b5f0e7f98e..b28e1ba14a 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6761,7 +6761,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); ** database file in rollback mode databases. Any pages written as part of ** transaction rollback or database recovery operations are not included. ** If an IO or other error occurs while writing a page to disk, the effect -** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined). ^The +** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. ** ** @@ -7137,7 +7137,7 @@ typedef struct sqlite3_backup sqlite3_backup; ** must be different or else sqlite3_backup_init(D,N,S,M) will fail with ** an error. ** -** ^A call to sqlite3_backup_init() will fail, returning SQLITE_ERROR, if +** ^A call to sqlite3_backup_init() will fail, returning NULL, if ** there is already a read or read-write transaction open on the ** destination database. ** From cca6698408920f5c9062f07aee14acab9d3668f0 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 5 Apr 2016 13:19:19 +0000 Subject: [PATCH 566/570] Do not allow pointer arithmetic to move a pointer across a memory allocation boundary. FossilOrigin-Name: 85b979319bcb8ec301ae39b36ad60348e4515be7 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index d2d4f94a79..22ecbfaa94 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sdocumentation\stypos.\s\sComment\schanges\sonly.\s\sNo\schanges\sto\scode. -D 2016-04-04T18:04:56.616 +C Do\snot\sallow\spointer\sarithmetic\sto\smove\sa\spointer\sacross\sa\smemory\sallocation\nboundary. +D 2016-04-05T13:19:19.622 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -319,7 +319,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 577fb5674e2f0aa0a38246afc19e1885a0b8c9b0 +F src/btree.c 2b5504ac632a0d7a1cac94eacee3042f1d79de38 F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 39faaaeecb77eb3936d4bd5024e865e3836ca323 @@ -1482,7 +1482,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 cefd36ff7b7f142bcebdb16b4d24ae274cdf2709 -R febb375a1eed9f049740185e3c47f862 +P d5fc2f7f90f8cbd53810c7a445b0e9c9a0e39182 +R 1653d2df23c45643b8fad503f203cef3 U drh -Z 64b7ed851fe55fe722cd357618c3eec9 +Z 587fa086f1daad23618d760100c57f67 diff --git a/manifest.uuid b/manifest.uuid index 0654e5fabc..88c7d9f709 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d5fc2f7f90f8cbd53810c7a445b0e9c9a0e39182 \ No newline at end of file +85b979319bcb8ec301ae39b36ad60348e4515be7 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index bf99597095..079fd0b9e4 100644 --- a/src/btree.c +++ b/src/btree.c @@ -6545,8 +6545,8 @@ static int pageInsertArray( u8 *pSlot; sz = cachedCellSize(pCArray, i); if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){ + if( (pData - pBegin)apCell[i] will never overlap on a well-formed From 1c715f67b9765e14d06288a1deb890170972ae4a Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 5 Apr 2016 13:35:43 +0000 Subject: [PATCH 567/570] Use SQLITE_WITHIN() for pointer range comparisons in some testing code. FossilOrigin-Name: 7cacf4e954c8de5af5efb56d8271a5ac1edc1c04 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 22ecbfaa94..5a24a606e7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sallow\spointer\sarithmetic\sto\smove\sa\spointer\sacross\sa\smemory\sallocation\nboundary. -D 2016-04-05T13:19:19.622 +C Use\sSQLITE_WITHIN()\sfor\spointer\srange\scomparisons\sin\ssome\stesting\scode. +D 2016-04-05T13:35:43.174 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -319,7 +319,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 2b5504ac632a0d7a1cac94eacee3042f1d79de38 +F src/btree.c 556203aab543e91f4e20cc273a507ed712c8da26 F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 39faaaeecb77eb3936d4bd5024e865e3836ca323 @@ -1482,7 +1482,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 d5fc2f7f90f8cbd53810c7a445b0e9c9a0e39182 -R 1653d2df23c45643b8fad503f203cef3 +P 85b979319bcb8ec301ae39b36ad60348e4515be7 +R 78bf202733e4247e84509df93eee1af7 U drh -Z 587fa086f1daad23618d760100c57f67 +Z b9b3193def70d2175e83a878eda9a91d diff --git a/manifest.uuid b/manifest.uuid index 88c7d9f709..b976ec3fb2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -85b979319bcb8ec301ae39b36ad60348e4515be7 \ No newline at end of file +7cacf4e954c8de5af5efb56d8271a5ac1edc1c04 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 079fd0b9e4..e5be8e0ef8 100644 --- a/src/btree.c +++ b/src/btree.c @@ -6708,7 +6708,7 @@ static int editPage( for(i=0; iapCell[i+iNew]; int iOff = get2byteAligned(&pPg->aCellIdx[i*2]); - if( pCell>=aData && pCell<&aData[pPg->pBt->usableSize] ){ + if( SQLITE_WITHIN(pCell, aData, &aData[pPg->pBt->usableSize]) ){ pCell = &pTmp[pCell - aData]; } assert( 0==memcmp(pCell, &aData[iOff], From 868f0398e4f4bf40e66a3802733e87d06c2cde0a Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 5 Apr 2016 14:01:34 +0000 Subject: [PATCH 568/570] Remove an unnecessary conditional from the index builder. FossilOrigin-Name: 87e5f5a6c60e37e943b3ce80617e81b09852515e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/build.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 5a24a606e7..50d38b0ed6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\sSQLITE_WITHIN()\sfor\spointer\srange\scomparisons\sin\ssome\stesting\scode. -D 2016-04-05T13:35:43.174 +C Remove\san\sunnecessary\sconditional\sfrom\sthe\sindex\sbuilder. +D 2016-04-05T14:01:34.379 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -322,7 +322,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 556203aab543e91f4e20cc273a507ed712c8da26 F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 39faaaeecb77eb3936d4bd5024e865e3836ca323 +F src/build.c ab763de47337f1acf03de6b36cbc13c90d20b932 F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -1482,7 +1482,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 85b979319bcb8ec301ae39b36ad60348e4515be7 -R 78bf202733e4247e84509df93eee1af7 +P 7cacf4e954c8de5af5efb56d8271a5ac1edc1c04 +R 5ad558ecd8aa9ab49f6924d29c53367a U drh -Z b9b3193def70d2175e83a878eda9a91d +Z 440953881a474ce081fa2537f4e8dbc0 diff --git a/manifest.uuid b/manifest.uuid index b976ec3fb2..43b1d36ebe 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7cacf4e954c8de5af5efb56d8271a5ac1edc1c04 \ No newline at end of file +87e5f5a6c60e37e943b3ce80617e81b09852515e \ No newline at end of file diff --git a/src/build.c b/src/build.c index d4d0c173cc..41ded1f8e4 100644 --- a/src/build.c +++ b/src/build.c @@ -2786,7 +2786,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); assert( pKey!=0 || db->mallocFailed || pParse->nErr ); - if( IsUniqueIndex(pIndex) && pKey!=0 ){ + if( IsUniqueIndex(pIndex) /*&& pKey!=0*/ ){ int j2 = sqlite3VdbeCurrentAddr(v) + 3; sqlite3VdbeGoto(v, j2); addr2 = sqlite3VdbeCurrentAddr(v); From aed11f2072815a6220ff0261c1c9a0aebb3c96b1 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 5 Apr 2016 14:02:16 +0000 Subject: [PATCH 569/570] Make sure "0" intended as a NULL pointer is cast to a pointer when used in a varargs functions parameter. FossilOrigin-Name: ed128e8b826cd9620b7146d01d461ed28b9a672d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/test_malloc.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 50d38b0ed6..056d33d3a7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunnecessary\sconditional\sfrom\sthe\sindex\sbuilder. -D 2016-04-05T14:01:34.379 +C Make\ssure\s"0"\sintended\sas\sa\sNULL\spointer\sis\scast\sto\sa\spointer\swhen\sused\nin\sa\svarargs\sfunctions\sparameter. +D 2016-04-05T14:02:16.715 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -411,7 +411,7 @@ F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5 F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202 F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd -F src/test_malloc.c 96df9381a1ff1f6d3805ff7231b9baf1386aaabf +F src/test_malloc.c 94c18e88d6df6d471a0d04ddb809f833d1739950 F src/test_multiplex.c 6a9de820fcaaf506c59aa14bc8693822333cea48 F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3 F src/test_mutex.c dbdfaff8580071f2212a0deae3325a93a737819c @@ -1482,7 +1482,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 7cacf4e954c8de5af5efb56d8271a5ac1edc1c04 -R 5ad558ecd8aa9ab49f6924d29c53367a +P 87e5f5a6c60e37e943b3ce80617e81b09852515e +R a877aa3d312b2b09cc17cdd970ec6cc3 U drh -Z 440953881a474ce081fa2537f4e8dbc0 +Z 781d8f18c7a4bdfd2f2083091977b2ca diff --git a/manifest.uuid b/manifest.uuid index 43b1d36ebe..ef7f23a7aa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -87e5f5a6c60e37e943b3ce80617e81b09852515e \ No newline at end of file +ed128e8b826cd9620b7146d01d461ed28b9a672d \ No newline at end of file diff --git a/src/test_malloc.c b/src/test_malloc.c index aaa640b03a..e6be663998 100644 --- a/src/test_malloc.c +++ b/src/test_malloc.c @@ -1093,7 +1093,7 @@ static int test_db_config_lookaside( if( Tcl_GetIntFromObj(interp, objv[3], &sz) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[4], &cnt) ) return TCL_ERROR; if( bufid==0 ){ - rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, 0, sz, cnt); + rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, (void*)0, sz, cnt); }else if( bufid>=1 && bufid<=2 && sz*cnt<=sizeof(azBuf[0]) ){ rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, azBuf[bufid], sz,cnt); }else{ From 60de73e83d397b8d581f31e312310398b66cb4e3 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 5 Apr 2016 15:59:23 +0000 Subject: [PATCH 570/570] Incorrect version of build.c checked in at [87e5f5a6c60e3] (because I neglected to press the "Save" button on the text editor). There is no change to the logic, just improved presentation. FossilOrigin-Name: cf569f9f2fab1828e4bfced111fd9a6ee23ea8c0 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/build.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 056d33d3a7..9328401ca9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\s"0"\sintended\sas\sa\sNULL\spointer\sis\scast\sto\sa\spointer\swhen\sused\nin\sa\svarargs\sfunctions\sparameter. -D 2016-04-05T14:02:16.715 +C Incorrect\sversion\sof\sbuild.c\schecked\sin\sat\s[87e5f5a6c60e3]\s(because\sI\nneglected\sto\spress\sthe\s"Save"\sbutton\son\sthe\stext\seditor).\s\sThere\sis\sno\schange\nto\sthe\slogic,\sjust\simproved\spresentation. +D 2016-04-05T15:59:23.006 F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc fe57d7e3e74fa383fd01ced796c0ffd966fc094a @@ -322,7 +322,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 556203aab543e91f4e20cc273a507ed712c8da26 F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c ab763de47337f1acf03de6b36cbc13c90d20b932 +F src/build.c c5cf206191880f88142352629d53fed174fc10bd F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -1482,7 +1482,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 87e5f5a6c60e37e943b3ce80617e81b09852515e -R a877aa3d312b2b09cc17cdd970ec6cc3 +P ed128e8b826cd9620b7146d01d461ed28b9a672d +R 27e5e4c2995b5324778005dedfa90fe5 U drh -Z 781d8f18c7a4bdfd2f2083091977b2ca +Z ed5acb084f4d8b134ae4eeee3cdc81ad diff --git a/manifest.uuid b/manifest.uuid index ef7f23a7aa..cf9761250d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ed128e8b826cd9620b7146d01d461ed28b9a672d \ No newline at end of file +cf569f9f2fab1828e4bfced111fd9a6ee23ea8c0 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 41ded1f8e4..e7a6824fb2 100644 --- a/src/build.c +++ b/src/build.c @@ -2762,6 +2762,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ tnum = pIndex->tnum; } pKey = sqlite3KeyInfoOfIndex(pParse, pIndex); + assert( pKey!=0 || db->mallocFailed || pParse->nErr ); /* Open the sorter cursor if we are to use one. */ iSorter = pParse->nTab++; @@ -2785,8 +2786,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); - assert( pKey!=0 || db->mallocFailed || pParse->nErr ); - if( IsUniqueIndex(pIndex) /*&& pKey!=0*/ ){ + if( IsUniqueIndex(pIndex) ){ int j2 = sqlite3VdbeCurrentAddr(v) + 3; sqlite3VdbeGoto(v, j2); addr2 = sqlite3VdbeCurrentAddr(v);