1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-10 01:02:56 +03:00

Merge all the latest trunk enhancements into the sessions branch.

FossilOrigin-Name: 94fd5bb6da5ef4d850c2ed4ad38afabc5569dae6
This commit is contained in:
drh
2011-03-18 12:35:36 +00:00
45 changed files with 2358 additions and 556 deletions

View File

@@ -3133,7 +3133,7 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
int jj;
nodeGetCell(&tree, &node, ii, &cell);
sqlite3_snprintf(512-nCell,&zCell[nCell],"%d", cell.iRowid);
sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid);
nCell = strlen(zCell);
for(jj=0; jj<tree.nDim*2; jj++){
sqlite3_snprintf(512-nCell,&zCell[nCell]," %f",(double)cell.aCoord[jj].f);

34
ext/rtree/rtreeB.test Normal file
View File

@@ -0,0 +1,34 @@
# 2011 March 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.
#
#***********************************************************************
# Make sure the rtreenode() testing function can handle entries with
# 64-bit rowids.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
ifcapable !rtree { finish_test ; return }
do_test rtreeB-1.1 {
db eval {
CREATE VIRTUAL TABLE t1 USING rtree(ii, x0, y0, x1, y1);
INSERT INTO t1 VALUES(1073741824, 0.0, 0.0, 100.0, 100.0);
INSERT INTO t1 VALUES(2147483646, 0.0, 0.0, 200.0, 200.0);
INSERT INTO t1 VALUES(4294967296, 0.0, 0.0, 300.0, 300.0);
INSERT INTO t1 VALUES(8589934592, 20.0, 20.0, 150.0, 150.0);
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}}}
finish_test

0
install-sh Normal file → Executable file
View File

103
manifest
View File

@@ -1,5 +1,8 @@
C Change\sto\sthe\ssession\smodule\sto\suse\suser-defined\sprimary\skeys\sinstead\sof\srowids\swhen\scollecting\schanges.
D 2011-03-17T19:20:27
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
C Merge\sall\sthe\slatest\strunk\senhancements\sinto\sthe\ssessions\sbranch.
D 2011-03-18T12:35:36.113
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -81,7 +84,7 @@ F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9
F ext/icu/icu.c 850e9a36567bbcce6bd85a4b68243cad8e3c2de2
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 05b293c85403cf39bb5af0e7c010b0cafeab5e47
F ext/rtree/rtree.c 115b499415ddef9be75615ced99b11232826e64d
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test dbd4250ac0ad367a262eb9676f7e3080b0368206
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
@@ -93,6 +96,7 @@ F ext/rtree/rtree7.test bcb647b42920b3b5d025846689147778485cc318
F ext/rtree/rtree8.test 9772e16da71e17e02bdebf0a5188590f289ab37d
F ext/rtree/rtree9.test df9843d1a9195249c8d3b4ea6aedda2d5c73e9c2
F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf
F ext/rtree/rtreeB.test b1916a9cecb86b02529c4cc5a546e8d6e7ff10da
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0
@@ -101,7 +105,7 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F ext/session/sqlite3session.c 4183792547af5b5d3ec1c8a3f858beb172682503
F ext/session/sqlite3session.h 63045871564085669b5cb1fb92e6efc2e1b1120a
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
@@ -123,66 +127,66 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 6728d6d48d55b449af76a3e51c0808849cb32a2e
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff
F src/btree.c ca9f44866554f634c12806635bc5b063d70bca9b
F src/btree.c 43302cc4f3de6479b90fa6bb271b65d86333d00e
F src/btree.h e2f2cd9933bf30724f53ffa12c4c5a3a864bbd6e
F src/btreeInt.h 20f73dc93b1eeb83afd7259fbc6bd7dcf2df7fe4
F src/build.c 00a327120d81ace6267e714ae8010c997d55de5d
F src/callback.c a1d1b1c9c85415dff013af033e2fed9c8382d33b
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 7deec4534f3b5a0c3b4a4cbadf809d321f64f9c4
F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01
F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b
F src/delete.c 3c0925e958a77804a004222baa1a2a8ad855306b
F src/expr.c 8e2c607b3be87a35c75a1f5dac50c10666b083c0
F src/expr.c 00817c672af554321fd67c44325afd7cef0e4648
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 17950a28f28b23e8ad3feaac5fc88c324d2f600a
F src/func.c cb41f614edc43b00bfeb030f9768e80eaff47edd
F src/fkey.c 418b840007c873975fd0d071746d952f8bca20ce
F src/func.c 3a8cb2fb2de3e3aed7f39106daf4878d9d17fcce
F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c c56a64b1488921794c3855d54acfe4674c7cea0c
F src/insert.c b0d4150ae6d6fae7c3e8b69b65bcf37988d80ac0
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 3c09359bbc8d6eae238a77e6a5cb2cbf1a41edb5
F src/malloc.c 92d59a007d7a42857d4e9454aa25b6b703286be1
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206
F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
F src/mem3.c 9b237d911ba9904142a804be727cc6664873f8a3
F src/mem5.c 6fe00f46997bebb690397cb029719f711e7640e3
F src/mem5.c 72e0bc40f535ac38a11712aed01d0014f9300732
F src/memjournal.c 0ebce851677a7ac035ba1512a7e65851b34530c6
F src/mutex.c 6949180803ff05a7d0e2b9334a95b4fb5a00e23f
F src/mutex.h fe2ef5e1c4dae531d5a544f9241f19c56d26803d
F src/mutex_noop.c d5cfbca87168c661a0b118cd8e329a908e453151
F src/mutex_os2.c 6a62583e374ba3ac1a3fcc0da2bfdac7d3942689
F src/mutex_os2.c f5d09e85b914643c230aa97db709fc0db370d93c
F src/mutex_unix.c b4f4e923bb8de93ec3f251fadb50855f23df9579
F src/mutex_w32.c 3ade5ae71449d1d023f0ebb3184c2ae6aa9307e4
F src/mutex_w32.c 5e54f3ba275bcb5d00248b8c23107df2e2f73e33
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
F src/os.c 22ac61d06e72a0dac900400147333b07b13d8e1d
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
F src/os_os2.c 2e452c9f2ca507623ad351c33a8a8b27849b1863
F src/os_unix.c 64a2e0ebbb19765f97993b3920f795e6f38fd923
F src/os_win.c 9abdcdd925416d854eabb0996c96debd92abfef5
F src/os_os2.c 2596fd2d5d0976c6c0c628d0c3c7c4e7a724f4cf
F src/os_unix.c 919972244dd7267815f9fc176b662390ff0b2348
F src/os_win.c 24d72407a90551969744cf9bcbb1b4c72c5fa845
F src/pager.c 6aa906b60a59664ba58d3f746164bb010d407ce1
F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
F src/pcache1.c d548e31beafa792d1994b663a29a5303569efc4e
F src/pragma.c a83f320497aee18eda60fc8d854df5897906c2b1
F src/prepare.c 395b3fab1b93f45b6aa194b23ebc201221c47b99
F src/printf.c df2ff3bb5409e8958136933342c46464fbd017e7
F src/pragma.c 4221eb822d7cdb1fb69be555b189e15e5a24b6b5
F src/prepare.c eb4944d9f7bfa13eb42a7416ed9aaed4de4d0bf3
F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
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 992c54d9bd451a041fb0b74fb5cd3b14db98e544
F src/shell.c 4a5e0ad845475c84881f0b25b1abba2ddaab0a72
F src/sqlite.h.in 208dc372c9b8d89ca962babcb7cb0c1b16d32bc4
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
F src/sqliteInt.h db209477de559911d7f14c1d208cbf2bc46e9224
F src/sqliteInt.h d65b832eb82bd3f04cd27a750698c7f4b3d9273a
F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44
F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -200,7 +204,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 9f025a7f3686c94e82dc6d6bd3cbf0f89cd67487
F src/test_config.c 62f0f8f934b1d5c7e4cd4f506ae453a1117b47d7
F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5
@@ -225,26 +229,27 @@ F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
F src/test_thread.c bedd05cad673dba53326f3aa468cc803038896c0
F src/test_vfs.c 2ed8853c1e51ac6f9ea091f7ce4e0d618bba8b86
F src/test_vfstrace.c f5c3b3b893d81a580d0f577e6d9bcfc1fd496136
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
F src/trigger.c b8bedb9c0084ceb51a40f54fcca2ce048c8de852
F src/update.c 18a862e3e08377a5afb26d6f16182a8f700a1ca7
F src/trigger.c 95d2ff4b2996fabe886c9764b5978980e29f4afa
F src/update.c aa39db6c39a1e234e8badf49768e1389dbb34650
F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685
F src/util.c ab1c92426494f499f42b9e307537b03e923d75c1
F src/util.c cd997077bad039efc0597eb027c929658f93c018
F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f
F src/vdbe.c fbf11bd681fd2313aaf59fb2fd7f02cd8324a88a
F src/vdbe.c 94cd191b1b20b0124e09b056bbce3d09f79821b3
F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2
F src/vdbeInt.h 20d13da932eed0667a2e2383a9cb0f80099a5fd3
F src/vdbeapi.c 3066456f64fb10c9c5151c684b5f5e8d67a5f4f2
F src/vdbeaux.c 896844f9bf663202b3afa8c139e2caddcf855765
F src/vdbeapi.c 988ee9420acf8c130d644e6d7282893efe927bbd
F src/vdbeaux.c ce48afec3f218b755f7b0ef1bef54a4be44cd833
F src/vdbeblob.c 18955f0ee6b133cd08e1592010cb9a6b11e9984c
F src/vdbemem.c 0fa2ed786cd207d5b988afef3562a8e663a75b50
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5
F src/vtab.c b297e8fa656ab5e66244ab15680d68db0adbec30
F src/wal.c 5386fb5e13c2daa8ab9062597fdc17bd849da371
F src/wal.c 7334009b396285b658a95a3b6bc6d2b016a1f794
F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c bf8c0f584a2c9becb9110c37e151f9d4f73fbf7e
F src/where.c a6e89fe7e56ab7e633be6fdebdddd857e9e5bc99
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 51756962d522e474338e9b2ebb26e7364d4aa125
@@ -257,7 +262,8 @@ F test/analyze.test c1eb87067fc16ece7c07e823d6395fd831b270c5
F test/analyze2.test 8f2b1534d43f5547ce9a6b736c021d4192c75be3
F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b
F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045
F test/analyze5.test 0618d2fe8982a5dae1d4e92152acc8ecbaf52be2
F test/analyze5.test adc89b92fc9fee5ca1cb0bc8512f3206ad0fe5aa
F test/analyze6.test 1ba1aea8fad25a77ffd71f24522d1bb9ecc949fc
F test/async.test ad4ba51b77cd118911a3fe1356b0809da9c108c3
F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
@@ -381,7 +387,7 @@ F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
F test/exclusive.test 53e1841b422e554cecf0160f937c473d6d0e3062
F test/exclusive2.test 343d55130c12c67b8bf10407acec043a6c26c86b
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/expr.test 620a636cf7b7d4e5834a0b9d83a4da372e24a7b7
F test/expr.test 19e8ac40313e2282a47b586d11c4892040990d3a
F test/fallocate.test 43dc34b8c24be6baffadc3b4401ee15710ce83c6
F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e
F test/filefmt.test f178cfc29501a14565954c961b226e61877dd32c
@@ -488,7 +494,7 @@ F test/incrblobfault.test 917c0292224c64a56ef7215fd633a3a82f805be0
F test/incrvacuum.test 453d1e490d8f5ad2c9b3a54282a0690d6ae56462
F test/incrvacuum2.test 9e22a794899c91b7d8c8e12eaacac8df249faafe
F test/incrvacuum_ioerr.test 57d2f5777ab13fa03b87b262a4ea1bad5cfc0291
F test/index.test df7c00c6edd9504ab71c83a9514f1c5ca0fa54d8
F test/index.test b5429732b3b983fa810e3ac867d7ca85dae35097
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
F test/index3.test 423a25c789fc8cc51aaf2a4370bbdde2d9e9eed7
F test/indexedby.test be501e381b82b2f8ab406309ba7aac46e221f4ad
@@ -560,6 +566,7 @@ F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
F test/mallocK.test d79968641d1b70d88f6c01bdb9a7eb4a55582cc9
F test/malloc_common.tcl 660b82ab528521cc4a48ff6df05ca3b6a00d47c5
F test/manydb.test b3d3bc4c25657e7f68d157f031eb4db7b3df0d3c
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test 0825155b2290e900264daaaf0334b6dfe69ea498
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
F test/memsubsys1.test 679db68394a5692791737b150852173b3e2fea10
@@ -584,8 +591,9 @@ F test/notify2.test 195a467e021f74197be2c4fb02d6dee644b8d8db
F test/notify3.test d60923e186e0900f4812a845fcdfd8eea096e33a
F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
F test/null.test a8b09b8ed87852742343b33441a9240022108993
F test/omitunique.test bbb2ec4345d9125d9ee21cd9488d97a163020d5f
F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
F test/oserror.test 5775264a41039856d211168713d916949227fedd
F test/oserror.test d1f085bdbac20456fccdf5877f52016453654fc3
F test/pager1.test d8672fd0af5f4f9b99b06283d00f01547809bebe
F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
@@ -600,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
@@ -888,12 +896,12 @@ 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
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
F tool/omittest.tcl 71c6f21afa2df91dd299ed317d5751fb628795fe
F tool/omittest.tcl 4f4cc66bb7ca6a5b8f61ee37b6333f60fb8a746a
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/shell1.test f608a009b04c490fd360c5ded458a6f98b4e7ec4
@@ -913,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 526545c49f64d9063d1b888cfc14ece62fa3c13c
R cab2f9d8485568249e1bae732085445e
U dan
Z 0451d1109f54d52c16342adf23f8ece9
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-----

View File

@@ -1 +1 @@
6614cfcb9c41da71ddec3c44a3de0d4d849e1cdd
94fd5bb6da5ef4d850c2ed4ad38afabc5569dae6

View File

@@ -4901,11 +4901,9 @@ static int allocateBtreePage(
u32 i;
int dist;
closest = 0;
dist = get4byte(&aData[8]) - nearby;
if( dist<0 ) dist = -dist;
dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby);
for(i=1; i<k; i++){
int d2 = get4byte(&aData[8+i*4]) - nearby;
if( d2<0 ) d2 = -d2;
int d2 = sqlite3AbsInt32(get4byte(&aData[8+i*4]) - nearby);
if( d2<dist ){
closest = i;
dist = d2;
@@ -6179,9 +6177,7 @@ static int balance_nonroot(
}
}
if( minI>i ){
int t;
MemPage *pT;
t = apNew[i]->pgno;
pT = apNew[i];
apNew[i] = apNew[minI];
apNew[minI] = pT;

View File

@@ -302,6 +302,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
"OMIT_TRUNCATE_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_UNIQUE_ENFORCEMENT
"OMIT_UNIQUE_ENFORCEMENT",
#endif
#ifdef SQLITE_OMIT_UTF16
"OMIT_UTF16",
#endif

View File

@@ -389,6 +389,7 @@ Expr *sqlite3ExprAlloc(
if( op!=TK_INTEGER || pToken->z==0
|| sqlite3GetInt32(pToken->z, &iValue)==0 ){
nExtra = pToken->n+1;
assert( iValue>=0 );
}
}
pNew = sqlite3DbMallocZero(db, sizeof(Expr)+nExtra);
@@ -614,6 +615,8 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
*/
void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p==0 ) return;
/* Sanity check: Assert that the IntValue is non-negative if it exists */
assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
sqlite3ExprDelete(db, p->pLeft);
sqlite3ExprDelete(db, p->pRight);
@@ -1223,13 +1226,6 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){
}
default: break;
}
if( rc ){
assert( ExprHasAnyProperty(p, EP_Reduced|EP_TokenOnly)
|| (p->flags2 & EP2_MallocedToken)==0 );
p->op = TK_INTEGER;
p->flags |= EP_IntValue;
p->u.iValue = *pValue;
}
return rc;
}
@@ -1954,6 +1950,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
Vdbe *v = pParse->pVdbe;
if( pExpr->flags & EP_IntValue ){
int i = pExpr->u.iValue;
assert( i>=0 );
if( negFlag ) i = -i;
sqlite3VdbeAddOp2(v, OP_Integer, i, iMem);
}else{
@@ -1964,7 +1961,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
if( c==0 || (c==2 && negFlag) ){
char *zV;
if( negFlag ){ value = -value; }
if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
zV = dup8bytes(v, (char*)&value);
sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
}else{

View File

@@ -687,7 +687,6 @@ void sqlite3FkCheck(
int regNew /* New row data is stored here */
){
sqlite3 *db = pParse->db; /* Database handle */
Vdbe *v; /* VM to write code to */
FKey *pFKey; /* Used to iterate through FKs */
int iDb; /* Index of database containing pTab */
const char *zDb; /* Name of database containing pTab */
@@ -699,7 +698,6 @@ void sqlite3FkCheck(
/* If foreign-keys are disabled, this function is a no-op. */
if( (db->flags&SQLITE_ForeignKeys)==0 ) return;
v = sqlite3GetVdbe(pParse);
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
zDb = db->aDb[iDb].zName;

View File

@@ -1239,13 +1239,8 @@ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
if( type==SQLITE_INTEGER ){
i64 v = sqlite3_value_int64(argv[0]);
p->rSum += v;
if( (p->approx|p->overflow)==0 ){
i64 iNewSum = p->iSum + v;
int s1 = (int)(p->iSum >> (sizeof(i64)*8-1));
int s2 = (int)(v >> (sizeof(i64)*8-1));
int s3 = (int)(iNewSum >> (sizeof(i64)*8-1));
p->overflow = ((s1&s2&~s3) | (~s1&~s2&s3))?1:0;
p->iSum = iNewSum;
if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){
p->overflow = 1;
}
}else{
p->rSum += sqlite3_value_double(argv[0]);

View File

@@ -465,7 +465,6 @@ void sqlite3Insert(
int regIns; /* Block of regs holding rowid+data being inserted */
int regRowid; /* registers holding insert rowid */
int regData; /* register holding first column to insert */
int regRecord; /* Holds the assemblied row record */
int regEof = 0; /* Register recording end of SELECT data */
int *aRegIdx = 0; /* One register allocated to each index */
@@ -794,7 +793,6 @@ void sqlite3Insert(
/* Allocate registers for holding the rowid of the new row,
** the content of the new row, and the assemblied row record.
*/
regRecord = ++pParse->nMem;
regRowid = regIns = pParse->nMem+1;
pParse->nMem += pTab->nCol + 1;
if( IsVirtual(pTab) ){
@@ -1188,7 +1186,7 @@ void sqlite3GenerateConstraintChecks(
case OE_Rollback:
case OE_Fail: {
char *zMsg;
j1 = sqlite3VdbeAddOp3(v, OP_HaltIfNull,
sqlite3VdbeAddOp3(v, OP_HaltIfNull,
SQLITE_CONSTRAINT, onError, regData+i);
zMsg = sqlite3MPrintf(pParse->db, "%s.%s may not be NULL",
pTab->zName, pTab->aCol[i].zName);
@@ -1320,8 +1318,9 @@ void sqlite3GenerateConstraintChecks(
*/
for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
int regIdx;
#ifndef SQLITE_OMIT_UNIQUE_ENFORCEMENT
int regR;
#endif
if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */
/* Create a key for accessing the index entry */
@@ -1339,6 +1338,11 @@ void sqlite3GenerateConstraintChecks(
sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0);
sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1);
#ifdef SQLITE_OMIT_UNIQUE_ENFORCEMENT
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
continue; /* Treat pIdx as if it is not a UNIQUE index */
#else
/* Find out what action to take in case there is an indexing conflict */
onError = pIdx->onError;
if( onError==OE_None ){
@@ -1412,6 +1416,7 @@ void sqlite3GenerateConstraintChecks(
}
sqlite3VdbeJumpHere(v, j3);
sqlite3ReleaseTempReg(pParse, regR);
#endif
}
if( pbMayReplace ){

View File

@@ -375,6 +375,13 @@ int sqlite3_config(int op, ...){
sqlite3GlobalConfig.nHeap = va_arg(ap, int);
sqlite3GlobalConfig.mnReq = va_arg(ap, int);
if( sqlite3GlobalConfig.mnReq<1 ){
sqlite3GlobalConfig.mnReq = 1;
}else if( sqlite3GlobalConfig.mnReq>(1<<12) ){
/* cap min request size at 2^12 */
sqlite3GlobalConfig.mnReq = (1<<12);
}
if( sqlite3GlobalConfig.pHeap==0 ){
/* If the heap pointer is NULL, then restore the malloc implementation
** back to NULL pointers too. This will cause the malloc to go

View File

@@ -442,7 +442,7 @@ static int memsys5Roundup(int n){
*/
static int memsys5Log(int iValue){
int iLog;
for(iLog=0; (1<<iLog)<iValue; iLog++);
for(iLog=0; (iLog<((sizeof(int)*8)-1)) && (1<<iLog)<iValue; iLog++);
return iLog;
}
@@ -473,6 +473,7 @@ static int memsys5Init(void *NotUsed){
zByte = (u8*)sqlite3GlobalConfig.pHeap;
assert( zByte!=0 ); /* sqlite3_config() does not allow otherwise */
/* boundaries on sqlite3GlobalConfig.mnReq are enforced in sqlite3_config() */
nMinLog = memsys5Log(sqlite3GlobalConfig.mnReq);
mem5.szAtom = (1<<nMinLog);
while( (int)sizeof(Mem5Link)>mem5.szAtom ){

View File

@@ -31,11 +31,16 @@
struct sqlite3_mutex {
HMTX mutex; /* Mutex controlling the lock */
int id; /* Mutex type */
int nRef; /* Number of references */
TID owner; /* Thread holding this mutex */
#ifdef SQLITE_DEBUG
int trace; /* True to trace changes */
#endif
};
#define OS2_MUTEX_INITIALIZER 0,0,0,0
#ifdef SQLITE_DEBUG
#define SQLITE3_MUTEX_INITIALIZER { 0, 0, 0 }
#else
#define SQLITE3_MUTEX_INITIALIZER { 0, 0 }
#endif
/*
** Initialize and deinitialize the mutex subsystem.
@@ -51,11 +56,14 @@ static int os2MutexEnd(void){ return SQLITE_OK; }
** to sqlite3_mutex_alloc() is one of these integer constants:
**
** <ul>
** <li> SQLITE_MUTEX_FAST 0
** <li> SQLITE_MUTEX_RECURSIVE 1
** <li> SQLITE_MUTEX_STATIC_MASTER 2
** <li> SQLITE_MUTEX_STATIC_MEM 3
** <li> SQLITE_MUTEX_STATIC_PRNG 4
** <li> SQLITE_MUTEX_FAST
** <li> SQLITE_MUTEX_RECURSIVE
** <li> SQLITE_MUTEX_STATIC_MASTER
** <li> SQLITE_MUTEX_STATIC_MEM
** <li> SQLITE_MUTEX_STATIC_MEM2
** <li> SQLITE_MUTEX_STATIC_PRNG
** <li> SQLITE_MUTEX_STATIC_LRU
** <li> SQLITE_MUTEX_STATIC_LRU2
** </ul>
**
** The first two constants cause sqlite3_mutex_alloc() to create
@@ -69,7 +77,7 @@ static int os2MutexEnd(void){ return SQLITE_OK; }
** might return such a mutex in response to SQLITE_MUTEX_FAST.
**
** The other allowed parameters to sqlite3_mutex_alloc() each return
** a pointer to a static preexisting mutex. Three static mutexes are
** a pointer to a static preexisting mutex. Six static mutexes are
** used by the current version of SQLite. Future versions of SQLite
** may add additional static mutexes. Static mutexes are for internal
** use by SQLite only. Applications that use SQLite mutexes should
@@ -99,13 +107,13 @@ static sqlite3_mutex *os2MutexAlloc(int iType){
}
default: {
static volatile int isInit = 0;
static sqlite3_mutex staticMutexes[] = {
{ OS2_MUTEX_INITIALIZER, },
{ OS2_MUTEX_INITIALIZER, },
{ OS2_MUTEX_INITIALIZER, },
{ OS2_MUTEX_INITIALIZER, },
{ OS2_MUTEX_INITIALIZER, },
{ OS2_MUTEX_INITIALIZER, },
static sqlite3_mutex staticMutexes[6] = {
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER,
};
if ( !isInit ){
APIRET rc;
@@ -151,9 +159,14 @@ static sqlite3_mutex *os2MutexAlloc(int iType){
** SQLite is careful to deallocate every mutex that it allocates.
*/
static void os2MutexFree(sqlite3_mutex *p){
if( p==0 ) return;
assert( p->nRef==0 );
#ifdef SQLITE_DEBUG
TID tid;
PID pid;
ULONG ulCount;
DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
assert( ulCount==0 );
assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
#endif
DosCloseMutexSem( p->mutex );
sqlite3_free( p );
}
@@ -168,26 +181,29 @@ static int os2MutexHeld(sqlite3_mutex *p){
PID pid;
ULONG ulCount;
PTIB ptib;
if( p!=0 ) {
DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
} else {
if( ulCount==0 || ( ulCount>1 && p->id!=SQLITE_MUTEX_RECURSIVE ) )
return 0;
DosGetInfoBlocks(&ptib, NULL);
tid = ptib->tib_ptib2->tib2_ultid;
}
return p==0 || (p->nRef!=0 && p->owner==tid);
return tid==ptib->tib_ptib2->tib2_ultid;
}
static int os2MutexNotheld(sqlite3_mutex *p){
TID tid;
PID pid;
ULONG ulCount;
PTIB ptib;
if( p!= 0 ) {
DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
} else {
if( ulCount==0 )
return 1;
DosGetInfoBlocks(&ptib, NULL);
tid = ptib->tib_ptib2->tib2_ultid;
}
return p==0 || p->nRef==0 || p->owner!=tid;
return tid!=ptib->tib_ptib2->tib2_ultid;
}
static void os2MutexTrace(sqlite3_mutex *p, char *pAction){
TID tid;
PID pid;
ULONG ulCount;
DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
printf("%s mutex %p (%d) with nRef=%ld\n", pAction, (void*)p, p->trace, ulCount);
}
#endif
@@ -203,32 +219,21 @@ static int os2MutexNotheld(sqlite3_mutex *p){
** more than once, the behavior is undefined.
*/
static void os2MutexEnter(sqlite3_mutex *p){
TID tid;
PID holder1;
ULONG holder2;
if( p==0 ) return;
assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT);
DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
p->owner = tid;
p->nRef++;
#ifdef SQLITE_DEBUG
if( p->trace ) os2MutexTrace(p, "enter");
#endif
}
static int os2MutexTry(sqlite3_mutex *p){
int rc;
TID tid;
PID holder1;
ULONG holder2;
if( p==0 ) return SQLITE_OK;
int rc = SQLITE_BUSY;
assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR) {
DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
p->owner = tid;
p->nRef++;
if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR ) {
rc = SQLITE_OK;
} else {
rc = SQLITE_BUSY;
#ifdef SQLITE_DEBUG
if( p->trace ) os2MutexTrace(p, "try");
#endif
}
return rc;
}
@@ -239,19 +244,14 @@ static int os2MutexTry(sqlite3_mutex *p){
** is not currently allocated. SQLite will never do either.
*/
static void os2MutexLeave(sqlite3_mutex *p){
TID tid;
PID holder1;
ULONG holder2;
if( p==0 ) return;
assert( p->nRef>0 );
DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
assert( p->owner==tid );
p->nRef--;
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
assert( os2MutexHeld(p) );
DosReleaseMutexSem(p->mutex);
#ifdef SQLITE_DEBUG
if( p->trace ) os2MutexTrace(p, "leave");
#endif
}
sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
static const sqlite3_mutex_methods sMutex = {
os2MutexInit,
os2MutexEnd,
@@ -263,6 +263,9 @@ sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
#ifdef SQLITE_DEBUG
os2MutexHeld,
os2MutexNotheld
#else
0,
0
#endif
};

View File

@@ -280,7 +280,7 @@ static int winMutexTry(sqlite3_mutex *p){
#endif
#ifdef SQLITE_DEBUG
if( rc==SQLITE_OK && p->trace ){
printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
}
#endif
return rc;

View File

@@ -647,18 +647,22 @@ char *convertCpPathToUtf8( const char *in ){
*/
static const sqlite3_io_methods os2IoMethod = {
1, /* iVersion */
os2Close,
os2Read,
os2Write,
os2Truncate,
os2Sync,
os2FileSize,
os2Lock,
os2Unlock,
os2CheckReservedLock,
os2FileControl,
os2SectorSize,
os2DeviceCharacteristics
os2Close, /* xClose */
os2Read, /* xRead */
os2Write, /* xWrite */
os2Truncate, /* xTruncate */
os2Sync, /* xSync */
os2FileSize, /* xFileSize */
os2Lock, /* xLock */
os2Unlock, /* xUnlock */
os2CheckReservedLock, /* xCheckReservedLock */
os2FileControl, /* xFileControl */
os2SectorSize, /* xSectorSize */
os2DeviceCharacteristics, /* xDeviceCharacteristics */
0, /* xShmMap */
0, /* xShmLock */
0, /* xShmBarrier */
0 /* xShmUnmap */
};
/***************************************************************************
@@ -750,100 +754,137 @@ static int os2FullPathname(
*/
static int os2Open(
sqlite3_vfs *pVfs, /* Not used */
const char *zName, /* Name of the file */
const char *zName, /* Name of the file (UTF-8) */
sqlite3_file *id, /* Write the SQLite file handle here */
int flags, /* Open mode flags */
int *pOutFlags /* Status return flags */
){
HFILE h;
ULONG ulFileAttribute = FILE_NORMAL;
ULONG ulOpenFlags = 0;
ULONG ulOpenMode = 0;
ULONG ulAction = 0;
ULONG rc;
os2File *pFile = (os2File*)id;
APIRET rc = NO_ERROR;
ULONG ulAction;
const char *zUtf8Name = zName;
char *zNameCp;
char zTmpname[CCHMAXPATH+1]; /* Buffer to hold name of temp file */
char zTmpname[CCHMAXPATH];
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
int isCreate = (flags & SQLITE_OPEN_CREATE);
int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
#ifndef NDEBUG
int isReadonly = (flags & SQLITE_OPEN_READONLY);
int eType = (flags & 0xFFFFFF00);
int isOpenJournal = (isCreate && (
eType==SQLITE_OPEN_MASTER_JOURNAL
|| eType==SQLITE_OPEN_MAIN_JOURNAL
|| eType==SQLITE_OPEN_WAL
));
#endif
UNUSED_PARAMETER(pVfs);
assert( id!=0 );
/* Check the following statements are true:
**
** (a) Exactly one of the READWRITE and READONLY flags must be set, and
** (b) if CREATE is set, then READWRITE must also be set, and
** (c) if EXCLUSIVE is set, then CREATE must also be set.
** (d) if DELETEONCLOSE is set, then CREATE must also be set.
*/
assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
assert(isCreate==0 || isReadWrite);
assert(isExclusive==0 || isCreate);
assert(isDelete==0 || isCreate);
/* The main DB, main journal, WAL file and master journal are never
** automatically deleted. Nor are they ever temporary files. */
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
/* Assert that the upper layer has set one of the "file-type" flags. */
assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
|| eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
|| eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
memset( pFile, 0, sizeof(*pFile) );
pFile->pMethod = &os2IoMethod;
/* If the second argument to this function is NULL, generate a
** temporary file name to use
*/
if( !zName ){
int rc = getTempname(CCHMAXPATH+1, zTmpname);
if( !zUtf8Name ){
assert(isDelete && !isOpenJournal);
rc = getTempname(CCHMAXPATH, zTmpname);
if( rc!=SQLITE_OK ){
return rc;
}
zName = zTmpname;
zUtf8Name = zTmpname;
}
memset( pFile, 0, sizeof(*pFile) );
OSTRACE(( "OPEN want %d\n", flags ));
if( flags & SQLITE_OPEN_READWRITE ){
if( isReadWrite ){
ulOpenMode |= OPEN_ACCESS_READWRITE;
OSTRACE(( "OPEN read/write\n" ));
}else{
ulOpenMode |= OPEN_ACCESS_READONLY;
OSTRACE(( "OPEN read only\n" ));
}
if( flags & SQLITE_OPEN_CREATE ){
ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
OSTRACE(( "OPEN open new/create\n" ));
}else{
ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW;
OSTRACE(( "OPEN open existing\n" ));
}
if( flags & SQLITE_OPEN_MAIN_DB ){
ulOpenMode |= OPEN_SHARE_DENYNONE;
OSTRACE(( "OPEN share read/write\n" ));
}else{
ulOpenMode |= OPEN_SHARE_DENYWRITE;
OSTRACE(( "OPEN share read only\n" ));
}
if( flags & SQLITE_OPEN_DELETEONCLOSE ){
char pathUtf8[CCHMAXPATH];
#ifdef NDEBUG /* when debugging we want to make sure it is deleted */
ulFileAttribute = FILE_HIDDEN;
#endif
os2FullPathname( pVfs, zName, CCHMAXPATH, pathUtf8 );
pFile->pathToDel = convertUtf8PathToCp( pathUtf8 );
OSTRACE(( "OPEN hidden/delete on close file attributes\n" ));
}else{
pFile->pathToDel = NULL;
OSTRACE(( "OPEN normal file attribute\n" ));
}
/* always open in random access mode for possibly better speed */
/* Open in random access mode for possibly better speed. Allow full
** sharing because file locks will provide exclusive access when needed.
*/
ulOpenMode |= OPEN_FLAGS_RANDOM;
ulOpenMode |= OPEN_FLAGS_FAIL_ON_ERROR;
ulOpenMode |= OPEN_FLAGS_NOINHERIT;
ulOpenMode |= OPEN_SHARE_DENYNONE;
zNameCp = convertUtf8PathToCp( zName );
/* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
** created. SQLite doesn't use it to indicate "exclusive access"
** as it is usually understood.
*/
if( isExclusive ){
/* Creates a new file, only if it does not already exist. */
/* If the file exists, it fails. */
ulOpenFlags |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
}else if( isCreate ){
/* Open existing file, or create if it doesn't exist */
ulOpenFlags |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
}else{
/* Opens a file, only if it exists. */
ulOpenFlags |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
}
/* For DELETEONCLOSE, save a pointer to the converted filename */
if( isDelete ){
char pathUtf8[CCHMAXPATH];
os2FullPathname( pVfs, zUtf8Name, CCHMAXPATH, pathUtf8 );
pFile->pathToDel = convertUtf8PathToCp( pathUtf8 );
}
zNameCp = convertUtf8PathToCp( zUtf8Name );
rc = DosOpen( (PSZ)zNameCp,
&h,
&ulAction,
0L,
ulFileAttribute,
FILE_NORMAL,
ulOpenFlags,
ulOpenMode,
(PEAOP2)NULL );
free( zNameCp );
if( rc != NO_ERROR ){
OSTRACE(( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulAttr=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
rc, zName, ulAction, ulFileAttribute, ulOpenFlags, ulOpenMode ));
OSTRACE(( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
rc, zUtf8Name, ulAction, ulOpenFlags, ulOpenMode ));
if( pFile->pathToDel )
free( pFile->pathToDel );
pFile->pathToDel = NULL;
if( flags & SQLITE_OPEN_READWRITE ){
OSTRACE(( "OPEN %d Invalid handle\n",
((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE) ));
if( isReadWrite ){
return os2Open( pVfs, zName, id,
((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE),
((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
pOutFlags );
}else{
return SQLITE_CANTOPEN;
@@ -851,10 +892,9 @@ static int os2Open(
}
if( pOutFlags ){
*pOutFlags = flags & SQLITE_OPEN_READWRITE ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY;
*pOutFlags = isReadWrite ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY;
}
pFile->pMethod = &os2IoMethod;
pFile->h = h;
OpenCounter(+1);
OSTRACE(( "OPEN %d pOutFlags=%d\n", pFile->h, pOutFlags ));
@@ -869,13 +909,16 @@ static int os2Delete(
const char *zFilename, /* Name of file to delete */
int syncDir /* Not used on os2 */
){
APIRET rc = NO_ERROR;
char *zFilenameCp = convertUtf8PathToCp( zFilename );
APIRET rc;
char *zFilenameCp;
SimulateIOError( return SQLITE_IOERR_DELETE );
zFilenameCp = convertUtf8PathToCp( zFilename );
rc = DosDelete( (PSZ)zFilenameCp );
free( zFilenameCp );
OSTRACE(( "DELETE \"%s\"\n", zFilename ));
return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR_DELETE;
return (rc == NO_ERROR ||
rc == ERROR_FILE_NOT_FOUND ||
rc == ERROR_PATH_NOT_FOUND ) ? SQLITE_OK : SQLITE_IOERR_DELETE;
}
/*
@@ -940,7 +983,7 @@ static void *os2DlOpen(sqlite3_vfs *pVfs, const char *zFilename){
static void os2DlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
/* no-op */
}
static void *os2DlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
static void (*os2DlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
PFN pfn;
APIRET rc;
rc = DosQueryProcAddr((HMODULE)pHandle, 0L, zSymbol, &pfn);
@@ -952,7 +995,7 @@ static void *os2DlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
strncat(_zSymbol, zSymbol, 255);
rc = DosQueryProcAddr((HMODULE)pHandle, 0L, _zSymbol, &pfn);
}
return rc != NO_ERROR ? 0 : (void*)pfn;
return rc != NO_ERROR ? 0 : (void(*)(void))pfn;
}
static void os2DlClose(sqlite3_vfs *pVfs, void *pHandle){
DosFreeModule((HMODULE)pHandle);
@@ -1056,10 +1099,11 @@ int sqlite3_current_time = 0;
int os2CurrentTime( sqlite3_vfs *pVfs, double *prNow ){
double now;
SHORT minute; /* needs to be able to cope with negative timezone offset */
USHORT second, hour,
USHORT hundredths, second, hour,
day, month, year;
DATETIME dt;
DosGetDateTime( &dt );
hundredths = (USHORT)dt.hundredths;
second = (USHORT)dt.seconds;
minute = (SHORT)dt.minutes + dt.timezone;
hour = (USHORT)dt.hours;
@@ -1079,6 +1123,7 @@ int os2CurrentTime( sqlite3_vfs *pVfs, double *prNow ){
now += (hour + 12.0)/24.0;
now += minute/1440.0;
now += second/86400.0;
now += hundredths/8640000.0;
*prNow = now;
#ifdef SQLITE_TEST
if( sqlite3_current_time ){
@@ -1088,6 +1133,22 @@ int os2CurrentTime( sqlite3_vfs *pVfs, double *prNow ){
return 0;
}
/*
** Find the current time (in Universal Coordinated Time). Write into *piNow
** the current time and date as a Julian Day number times 86_400_000. In
** other words, write into *piNow the number of milliseconds since the Julian
** epoch of noon in Greenwich on November 24, 4714 B.C according to the
** proleptic Gregorian calendar.
**
** On success, return 0. Return 1 if the time and date cannot be found.
*/
static int os2CurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
double now;
os2CurrentTime(pVfs, &now);
*piNow = now * 86400000;
return 0;
}
static int os2GetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
return 0;
}
@@ -1097,7 +1158,7 @@ static int os2GetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
*/
int sqlite3_os_init(void){
static sqlite3_vfs os2Vfs = {
1, /* iVersion */
3, /* iVersion */
sizeof(os2File), /* szOsFile */
CCHMAXPATH, /* mxPathname */
0, /* pNext */
@@ -1116,6 +1177,10 @@ int sqlite3_os_init(void){
os2Sleep, /* xSleep */
os2CurrentTime, /* xCurrentTime */
os2GetLastError, /* xGetLastError */
os2CurrentTimeInt64 /* xCurrentTimeInt64 */
0, /* xSetSystemCall */
0, /* xGetSystemCall */
0, /* xNextSystemCall */
};
sqlite3_vfs_register(&os2Vfs, 1);
initUconvObjects();

File diff suppressed because it is too large Load Diff

View File

@@ -2746,7 +2746,7 @@ static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
*/
int sqlite3_os_init(void){
static sqlite3_vfs winVfs = {
2, /* iVersion */
3, /* iVersion */
sizeof(winFile), /* szOsFile */
MAX_PATH, /* mxPathname */
0, /* pNext */
@@ -2765,6 +2765,9 @@ int sqlite3_os_init(void){
winCurrentTime, /* xCurrentTime */
winGetLastError, /* xGetLastError */
winCurrentTimeInt64, /* xCurrentTimeInt64 */
0, /* xSetSystemCall */
0, /* xGetSystemCall */
0, /* xNextSystemCall */
};
#ifndef SQLITE_OMIT_WAL

View File

@@ -384,8 +384,7 @@ void sqlite3Pragma(
sqlite3VdbeChangeP1(v, addr+1, iDb);
sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE);
}else{
int size = sqlite3Atoi(zRight);
if( size<0 ) size = -size;
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);
@@ -694,8 +693,7 @@ void sqlite3Pragma(
if( !zRight ){
returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
}else{
int size = sqlite3Atoi(zRight);
if( size<0 ) size = -size;
int size = sqlite3AbsInt32(sqlite3Atoi(zRight));
pDb->pSchema->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
}

View File

@@ -141,7 +141,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
int meta[5];
InitData initData;
char const *zMasterSchema;
char const *zMasterName = SCHEMA_TABLE(iDb);
char const *zMasterName;
int openedTransaction = 0;
/*
@@ -278,9 +278,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
pDb->pSchema->enc = ENC(db);
if( pDb->pSchema->cache_size==0 ){
size = meta[BTREE_DEFAULT_CACHE_SIZE-1];
size = sqlite3AbsInt32(meta[BTREE_DEFAULT_CACHE_SIZE-1]);
if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; }
if( size<0 ) size = -size;
pDb->pSchema->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
}

View File

@@ -400,7 +400,11 @@ void sqlite3VXPrintf(
v = va_arg(ap,int);
}
if( v<0 ){
if( v==SMALLEST_INT64 ){
longvalue = ((u64)1)<<63;
}else{
longvalue = -v;
}
prefix = '-';
}else{
longvalue = v;

View File

@@ -419,6 +419,7 @@ struct callback_data {
** .explain ON */
char outfile[FILENAME_MAX]; /* Filename for *out */
const char *zDbFilename; /* name of the database file */
const char *zVfs; /* Name of VFS to use */
sqlite3_stmt *pStmt; /* Current statement if any. */
FILE *pLog; /* Write log output here */
};
@@ -2172,29 +2173,45 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}else
if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){
static const struct {
const char *zCtrlName; /* Name of a test-control option */
int ctrlCode; /* Integer code for that option */
} aCtrl[] = {
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE },
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE },
{ "prng_reset", SQLITE_TESTCTRL_PRNG_RESET },
{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST },
{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL },
{ "benign_malloc_hooks", SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS },
{ "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE },
{ "assert", SQLITE_TESTCTRL_ASSERT },
{ "always", SQLITE_TESTCTRL_ALWAYS },
{ "reserve", SQLITE_TESTCTRL_RESERVE },
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS },
{ "iskeyword", SQLITE_TESTCTRL_ISKEYWORD },
{ "pghdrsz", SQLITE_TESTCTRL_PGHDRSZ },
{ "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
};
int testctrl = -1;
int rc = 0;
int i, n;
open_db(p);
/* convert testctrl text option to value. allow only the first
** three characters of the option to be used or the numerical
** value. */
if( strncmp( azArg[1], "prng_save", 6 )==0 ) testctrl = SQLITE_TESTCTRL_PRNG_SAVE;
else if( strncmp( azArg[1], "prng_restore", 10 )==0 ) testctrl = SQLITE_TESTCTRL_PRNG_RESTORE;
else if( strncmp( azArg[1], "prng_reset", 10 )==0 ) testctrl = SQLITE_TESTCTRL_PRNG_RESET;
else if( strncmp( azArg[1], "bitvec_test", 6 )==3 ) testctrl = SQLITE_TESTCTRL_BITVEC_TEST;
else if( strncmp( azArg[1], "fault_install", 6 )==3 ) testctrl = SQLITE_TESTCTRL_FAULT_INSTALL;
else if( strncmp( azArg[1], "benign_malloc_hooks", 3 )==0 ) testctrl = SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS;
else if( strncmp( azArg[1], "pending_byte", 3 )==0 ) testctrl = SQLITE_TESTCTRL_PENDING_BYTE;
else if( strncmp( azArg[1], "assert", 3 )==0 ) testctrl = SQLITE_TESTCTRL_ASSERT;
else if( strncmp( azArg[1], "always", 3 )==0 ) testctrl = SQLITE_TESTCTRL_ALWAYS;
else if( strncmp( azArg[1], "reserve", 3 )==0 ) testctrl = SQLITE_TESTCTRL_RESERVE;
else if( strncmp( azArg[1], "optimizations", 3 )==0 ) testctrl = SQLITE_TESTCTRL_OPTIMIZATIONS;
else if( strncmp( azArg[1], "iskeyword", 3 )==0 ) testctrl = SQLITE_TESTCTRL_ISKEYWORD;
else if( strncmp( azArg[1], "pghdrsz", 3 )==0 ) testctrl = SQLITE_TESTCTRL_PGHDRSZ;
else if( strncmp( azArg[1], "scratchmalloc", 3 )==0 ) testctrl = SQLITE_TESTCTRL_SCRATCHMALLOC;
else testctrl = atoi(azArg[1]);
/* convert testctrl text option to value. allow any unique prefix
** of the option name, or a numerical value. */
n = strlen(azArg[1]);
for(i=0; i<sizeof(aCtrl)/sizeof(aCtrl[0]); i++){
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n)==0 ){
if( testctrl<0 ){
testctrl = aCtrl[i].ctrlCode;
}else{
fprintf(stderr, "ambiguous option name: \"%s\"\n", azArg[i]);
testctrl = -1;
break;
}
}
}
if( testctrl<0 ) testctrl = atoi(azArg[1]);
if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){
fprintf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]);
}else{
@@ -2208,7 +2225,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){
rc = sqlite3_test_control(testctrl, p->db, opt);
printf("%d (0x%08x)\n", rc, rc);
} else {
fprintf(stderr,"Error: testctrl %s takes a single int option\n", azArg[1]);
fprintf(stderr,"Error: testctrl %s takes a single int option\n",
azArg[1]);
}
break;
@@ -2232,7 +2250,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){
rc = sqlite3_test_control(testctrl, opt);
printf("%d (0x%08x)\n", rc, rc);
} else {
fprintf(stderr,"Error: testctrl %s takes a single unsigned int option\n", azArg[1]);
fprintf(stderr,"Error: testctrl %s takes a single unsigned"
" int option\n", azArg[1]);
}
break;
@@ -2244,7 +2263,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){
rc = sqlite3_test_control(testctrl, opt);
printf("%d (0x%08x)\n", rc, rc);
} else {
fprintf(stderr,"Error: testctrl %s takes a single int option\n", azArg[1]);
fprintf(stderr,"Error: testctrl %s takes a single int option\n",
azArg[1]);
}
break;
@@ -2256,7 +2276,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){
rc = sqlite3_test_control(testctrl, opt);
printf("%d (0x%08x)\n", rc, rc);
} else {
fprintf(stderr,"Error: testctrl %s takes a single char * option\n", azArg[1]);
fprintf(stderr,"Error: testctrl %s takes a single char * option\n",
azArg[1]);
}
break;
#endif
@@ -2266,7 +2287,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){
case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
case SQLITE_TESTCTRL_SCRATCHMALLOC:
default:
fprintf(stderr,"Error: CLI support for testctrl %s not implemented\n", azArg[1]);
fprintf(stderr,"Error: CLI support for testctrl %s not implemented\n",
azArg[1]);
break;
}
}
@@ -2277,7 +2299,9 @@ static int do_meta_command(char *zLine, struct callback_data *p){
sqlite3_busy_timeout(p->db, atoi(azArg[1]));
}else
if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 && nArg==2 ){
if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0
&& nArg==2
){
enableTimer = booleanValue(azArg[1]);
}else
@@ -2464,7 +2488,9 @@ static int process_input(struct callback_data *p, FILE *in){
}
}
if( zSql ){
if( !_all_whitespace(zSql) ) fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);
if( !_all_whitespace(zSql) ){
fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);
}
free(zSql);
}
free(zLine);
@@ -2600,6 +2626,10 @@ static const char zOptions[] =
" -stats print memory stats before each finalize\n"
" -nullvalue 'text' set text string for NULL values\n"
" -version show SQLite version\n"
" -vfs NAME use NAME as the default VFS\n"
#ifdef SQLITE_ENABLE_VFSTRACE
" -vfstrace enable tracing of all VFS calls\n"
#endif
;
static void usage(int showDetail){
fprintf(stderr,
@@ -2684,6 +2714,25 @@ int main(int argc, char **argv){
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
#endif
#ifdef SQLITE_ENABLE_VFSTRACE
}else if( strcmp(argv[i],"-vfstrace")==0 ){
extern int vfstrace_register(
const char *zTraceName,
const char *zOldVfsName,
int (*xOut)(const char*,void*),
void *pOutArg,
int makeDefault
);
vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
#endif
}else if( strcmp(argv[i],"-vfs")==0 ){
sqlite3_vfs *pVfs = sqlite3_vfs_find(argv[++i]);
if( pVfs ){
sqlite3_vfs_register(pVfs, 1);
}else{
fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]);
exit(1);
}
}
}
if( i<argc ){
@@ -2792,6 +2841,10 @@ int main(int argc, char **argv){
stdin_is_interactive = 0;
}else if( strcmp(z,"-heap")==0 ){
i++;
}else if( strcmp(z,"-vfs")==0 ){
i++;
}else if( strcmp(z,"-vfstrace")==0 ){
i++;
}else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
usage(1);
}else{

View File

@@ -893,10 +893,22 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** date and time if that method is available (if iVersion is 2 or
** greater and the function pointer is not NULL) and will fall back
** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
**
** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces
** are not used by the SQLite core. These optional interfaces are provided
** by some VFSes to facilitate testing of the VFS code. By overriding
** system calls with functions under its control, a test program can
** simulate faults and error conditions that would otherwise be difficult
** or impossible to induce. The set of system calls that can be overridden
** varies from one VFS to another, and from one version of the same VFS to the
** next. Applications that use these interfaces must be prepared for any
** or all of these interfaces to be NULL or for their behavior to change
** from one release to the next. Applications must not attempt to access
** any of these methods if the iVersion of the VFS is less than 3.
*/
typedef struct sqlite3_vfs sqlite3_vfs;
struct sqlite3_vfs {
int iVersion; /* Structure version number (currently 2) */
int iVersion; /* Structure version number (currently 3) */
int szOsFile; /* Size of subclassed sqlite3_file */
int mxPathname; /* Maximum file pathname length */
sqlite3_vfs *pNext; /* Next registered VFS */
@@ -922,6 +934,13 @@ struct sqlite3_vfs {
int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
/*
** The methods above are in versions 1 and 2 of the sqlite_vfs object.
** Those below are for version 3 and greater.
*/
int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, void *pFunc);
void *(*xGetSystemCall)(sqlite3_vfs*, const char *zName);
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
** value will increment whenever this happens.
*/
@@ -1341,7 +1360,9 @@ struct sqlite3_mem_methods {
** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory
** allocator is engaged to handle all of SQLites memory allocation needs.
** The first pointer (the memory pointer) must be aligned to an 8-byte
** boundary or subsequent behavior of SQLite will be undefined.</dd>
** boundary or subsequent behavior of SQLite will be undefined.
** The minimum allocation size is capped at 2^12. Reasonable values
** for the minimum allocation size are 2^5 through 2^8.</dd>
**
** <dt>SQLITE_CONFIG_MUTEX</dt>
** <dd> ^(This option takes a single argument which is a pointer to an

View File

@@ -1629,7 +1629,7 @@ struct Expr {
u16 flags; /* Various flags. EP_* See below */
union {
char *zToken; /* Token value. Zero terminated and dequoted */
int iValue; /* Integer value if EP_IntValue */
int iValue; /* Non-negative integer value if EP_IntValue */
} u;
/* If the EP_TokenOnly flag is set in the Expr.flags mask, then no
@@ -2911,6 +2911,10 @@ Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*);
int sqlite3CheckCollSeq(Parse *, CollSeq *);
int sqlite3CheckObjectName(Parse *, const char *);
void sqlite3VdbeSetChanges(sqlite3 *, int);
int sqlite3AddInt64(i64*,i64);
int sqlite3SubInt64(i64*,i64);
int sqlite3MulInt64(i64*,i64);
int sqlite3AbsInt32(int);
const void *sqlite3ValueText(sqlite3_value*, u8);
int sqlite3ValueBytes(sqlite3_value*, u8);

View File

@@ -475,6 +475,12 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double",
Tcl_SetVar2(interp, "sqlite_options", "truncate_opt", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_UNIQUE_ENFORCEMENT
Tcl_SetVar2(interp, "sqlite_options", "unique_enforcement", "0", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "unique_enforcement", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_UTF16
Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
#else

770
src/test_vfstrace.c Normal file
View File

@@ -0,0 +1,770 @@
/*
** 2011 March 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 contains code implements a VFS shim that writes diagnostic
** output for each VFS call, similar to "strace".
*/
#include <stdlib.h>
#include <string.h>
#include "sqlite3.h"
/*
** An instance of this structure is attached to the each trace VFS to
** provide auxiliary information.
*/
typedef struct vfstrace_info vfstrace_info;
struct vfstrace_info {
sqlite3_vfs *pRootVfs; /* The underlying real VFS */
int (*xOut)(const char*, void*); /* Send output here */
void *pOutArg; /* First argument to xOut */
const char *zVfsName; /* Name of this trace-VFS */
sqlite3_vfs *pTraceVfs; /* Pointer back to the trace VFS */
};
/*
** The sqlite3_file object for the trace VFS
*/
typedef struct vfstrace_file vfstrace_file;
struct vfstrace_file {
sqlite3_file base; /* Base class. Must be first */
vfstrace_info *pInfo; /* The trace-VFS to which this file belongs */
const char *zFName; /* Base name of the file */
sqlite3_file *pReal; /* The real underlying file */
};
/*
** Method declarations for vfstrace_file.
*/
static int vfstraceClose(sqlite3_file*);
static int vfstraceRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int vfstraceWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
static int vfstraceTruncate(sqlite3_file*, sqlite3_int64 size);
static int vfstraceSync(sqlite3_file*, int flags);
static int vfstraceFileSize(sqlite3_file*, sqlite3_int64 *pSize);
static int vfstraceLock(sqlite3_file*, int);
static int vfstraceUnlock(sqlite3_file*, int);
static int vfstraceCheckReservedLock(sqlite3_file*, int *);
static int vfstraceFileControl(sqlite3_file*, int op, void *pArg);
static int vfstraceSectorSize(sqlite3_file*);
static int vfstraceDeviceCharacteristics(sqlite3_file*);
static int vfstraceShmLock(sqlite3_file*,int,int,int);
static int vfstraceShmMap(sqlite3_file*,int,int,int, void volatile **);
static void vfstraceShmBarrier(sqlite3_file*);
static int vfstraceShmUnmap(sqlite3_file*,int);
/*
** Method declarations for vfstrace_vfs.
*/
static int vfstraceOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int vfstraceDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int vfstraceAccess(sqlite3_vfs*, const char *zName, int flags, int *);
static int vfstraceFullPathname(sqlite3_vfs*, const char *zName, int, char *);
static void *vfstraceDlOpen(sqlite3_vfs*, const char *zFilename);
static void vfstraceDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void (*vfstraceDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
static void vfstraceDlClose(sqlite3_vfs*, void*);
static int vfstraceRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int vfstraceSleep(sqlite3_vfs*, int microseconds);
static int vfstraceCurrentTime(sqlite3_vfs*, double*);
static int vfstraceGetLastError(sqlite3_vfs*, int, char*);
static int vfstraceCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
static int vfstraceSetSystemCall(sqlite3_vfs*, const char *zName, void *pFunc);
static void *vfstraceGetSystemCall(sqlite3_vfs*, const char *zName);
static const char *vfstraceNextSystemCall(sqlite3_vfs*, const char *zName);
/*
** Return a pointer to the tail of the pathname. Examples:
**
** /home/drh/xyzzy.txt -> xyzzy.txt
** xyzzy.txt -> xyzzy.txt
*/
static const char *fileTail(const char *z){
int i;
if( z==0 ) return 0;
i = strlen(z)-1;
while( i>0 && z[i-1]!='/' ){ i--; }
return &z[i];
}
/*
** Send trace output defined by zFormat and subsequent arguments.
*/
static void vfstrace_printf(
vfstrace_info *pInfo,
const char *zFormat,
...
){
va_list ap;
char *zMsg;
va_start(ap, zFormat);
zMsg = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
pInfo->xOut(zMsg, pInfo->pOutArg);
sqlite3_free(zMsg);
}
/*
** Convert value rc into a string and print it using zFormat. zFormat
** should have exactly one %s
*/
static void vfstrace_print_errcode(
vfstrace_info *pInfo,
const char *zFormat,
int rc
){
char zBuf[50];
char *zVal;
switch( rc ){
case SQLITE_OK: zVal = "SQLITE_OK"; break;
case SQLITE_ERROR: zVal = "SQLITE_ERROR"; break;
case SQLITE_PERM: zVal = "SQLITE_PERM"; break;
case SQLITE_ABORT: zVal = "SQLITE_ABORT"; break;
case SQLITE_BUSY: zVal = "SQLITE_BUSY"; break;
case SQLITE_NOMEM: zVal = "SQLITE_NOMEM"; break;
case SQLITE_READONLY: zVal = "SQLITE_READONLY"; break;
case SQLITE_INTERRUPT: zVal = "SQLITE_INTERRUPT"; break;
case SQLITE_IOERR: zVal = "SQLITE_IOERR"; break;
case SQLITE_CORRUPT: zVal = "SQLITE_CORRUPT"; break;
case SQLITE_FULL: zVal = "SQLITE_FULL"; break;
case SQLITE_CANTOPEN: zVal = "SQLITE_CANTOPEN"; break;
case SQLITE_PROTOCOL: zVal = "SQLITE_PROTOCOL"; break;
case SQLITE_EMPTY: zVal = "SQLITE_EMPTY"; break;
case SQLITE_SCHEMA: zVal = "SQLITE_SCHEMA"; break;
case SQLITE_CONSTRAINT: zVal = "SQLITE_CONSTRAINT"; break;
case SQLITE_MISMATCH: zVal = "SQLITE_MISMATCH"; break;
case SQLITE_MISUSE: zVal = "SQLITE_MISUSE"; break;
case SQLITE_NOLFS: zVal = "SQLITE_NOLFS"; break;
case SQLITE_IOERR_READ: zVal = "SQLITE_IOERR_READ"; break;
case SQLITE_IOERR_SHORT_READ: zVal = "SQLITE_IOERR_SHORT_READ"; break;
case SQLITE_IOERR_WRITE: zVal = "SQLITE_IOERR_WRITE"; break;
case SQLITE_IOERR_FSYNC: zVal = "SQLITE_IOERR_FSYNC"; break;
case SQLITE_IOERR_DIR_FSYNC: zVal = "SQLITE_IOERR_DIR_FSYNC"; break;
case SQLITE_IOERR_TRUNCATE: zVal = "SQLITE_IOERR_TRUNCATE"; break;
case SQLITE_IOERR_FSTAT: zVal = "SQLITE_IOERR_FSTAT"; break;
case SQLITE_IOERR_UNLOCK: zVal = "SQLITE_IOERR_UNLOCK"; break;
case SQLITE_IOERR_RDLOCK: zVal = "SQLITE_IOERR_RDLOCK"; break;
case SQLITE_IOERR_DELETE: zVal = "SQLITE_IOERR_DELETE"; break;
case SQLITE_IOERR_BLOCKED: zVal = "SQLITE_IOERR_BLOCKED"; break;
case SQLITE_IOERR_NOMEM: zVal = "SQLITE_IOERR_NOMEM"; break;
case SQLITE_IOERR_ACCESS: zVal = "SQLITE_IOERR_ACCESS"; break;
case SQLITE_IOERR_CHECKRESERVEDLOCK:
zVal = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
case SQLITE_IOERR_LOCK: zVal = "SQLITE_IOERR_LOCK"; break;
case SQLITE_IOERR_CLOSE: zVal = "SQLITE_IOERR_CLOSE"; break;
case SQLITE_IOERR_DIR_CLOSE: zVal = "SQLITE_IOERR_DIR_CLOSE"; break;
case SQLITE_IOERR_SHMOPEN: zVal = "SQLITE_IOERR_SHMOPEN"; break;
case SQLITE_IOERR_SHMSIZE: zVal = "SQLITE_IOERR_SHMSIZE"; break;
case SQLITE_IOERR_SHMLOCK: zVal = "SQLITE_IOERR_SHMLOCK"; break;
case SQLITE_LOCKED_SHAREDCACHE: zVal = "SQLITE_LOCKED_SHAREDCACHE"; break;
case SQLITE_BUSY_RECOVERY: zVal = "SQLITE_BUSY_RECOVERY"; break;
case SQLITE_CANTOPEN_NOTEMPDIR: zVal = "SQLITE_CANTOPEN_NOTEMPDIR"; break;
default: {
sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
zVal = zBuf;
break;
}
}
vfstrace_printf(pInfo, zFormat, zVal);
}
/*
** Append to a buffer.
*/
static void strappend(char *z, int *pI, const char *zAppend){
int i = *pI;
while( zAppend[0] ){ z[i++] = *(zAppend++); }
z[i] = 0;
*pI = i;
}
/*
** Close an vfstrace-file.
*/
static int vfstraceClose(sqlite3_file *pFile){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
vfstrace_printf(pInfo, "%s.xClose(%s)", pInfo->zVfsName, p->zFName);
rc = p->pReal->pMethods->xClose(p->pReal);
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
if( rc==SQLITE_OK ){
sqlite3_free((void*)p->base.pMethods);
p->base.pMethods = 0;
}
return rc;
}
/*
** Read data from an vfstrace-file.
*/
static int vfstraceRead(
sqlite3_file *pFile,
void *zBuf,
int iAmt,
sqlite_int64 iOfst
){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
vfstrace_printf(pInfo, "%s.xRead(%s,n=%d,ofst=%lld)",
pInfo->zVfsName, p->zFName, iAmt, iOfst);
rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
return rc;
}
/*
** Write data to an vfstrace-file.
*/
static int vfstraceWrite(
sqlite3_file *pFile,
const void *zBuf,
int iAmt,
sqlite_int64 iOfst
){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
vfstrace_printf(pInfo, "%s.xWrite(%s,n=%d,ofst=%lld)",
pInfo->zVfsName, p->zFName, iAmt, iOfst);
rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
return rc;
}
/*
** Truncate an vfstrace-file.
*/
static int vfstraceTruncate(sqlite3_file *pFile, sqlite_int64 size){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
vfstrace_printf(pInfo, "%s.xTruncate(%s,%lld)", pInfo->zVfsName, p->zFName,
size);
rc = p->pReal->pMethods->xTruncate(p->pReal, size);
vfstrace_printf(pInfo, " -> %d\n", rc);
return rc;
}
/*
** Sync an vfstrace-file.
*/
static int vfstraceSync(sqlite3_file *pFile, int flags){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
int i;
char zBuf[100];
memcpy(zBuf, "|0", 3);
i = 0;
if( flags & SQLITE_SYNC_FULL ) strappend(zBuf, &i, "|FULL");
else if( flags & SQLITE_SYNC_NORMAL ) strappend(zBuf, &i, "|NORMAL");
if( flags & SQLITE_SYNC_DATAONLY ) strappend(zBuf, &i, "|DATAONLY");
if( flags & ~(SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY) ){
sqlite3_snprintf(sizeof(zBuf)-i, &zBuf[i], "|0x%x", flags);
}
vfstrace_printf(pInfo, "%s.xSync(%s,%s)", pInfo->zVfsName, p->zFName,
&zBuf[1]);
rc = p->pReal->pMethods->xSync(p->pReal, flags);
vfstrace_printf(pInfo, " -> %d\n", rc);
return rc;
}
/*
** Return the current file-size of an vfstrace-file.
*/
static int vfstraceFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
vfstrace_printf(pInfo, "%s.xFileSize(%s)", pInfo->zVfsName, p->zFName);
rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
vfstrace_print_errcode(pInfo, " -> %s,", rc);
vfstrace_printf(pInfo, " size=%lld\n", *pSize);
return rc;
}
/*
** Return the name of a lock.
*/
static const char *lockName(int eLock){
const char *azLockNames[] = {
"NONE", "SHARED", "RESERVED", "PENDING", "EXCLUSIVE"
};
if( eLock<0 || eLock>=sizeof(azLockNames)/sizeof(azLockNames[0]) ){
return "???";
}else{
return azLockNames[eLock];
}
}
/*
** Lock an vfstrace-file.
*/
static int vfstraceLock(sqlite3_file *pFile, int eLock){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
vfstrace_printf(pInfo, "%s.xLock(%s,%s)", pInfo->zVfsName, p->zFName,
lockName(eLock));
rc = p->pReal->pMethods->xLock(p->pReal, eLock);
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
return rc;
}
/*
** Unlock an vfstrace-file.
*/
static int vfstraceUnlock(sqlite3_file *pFile, int eLock){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
vfstrace_printf(pInfo, "%s.xUnlock(%s,%s)", pInfo->zVfsName, p->zFName,
lockName(eLock));
rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
return rc;
}
/*
** Check if another file-handle holds a RESERVED lock on an vfstrace-file.
*/
static int vfstraceCheckReservedLock(sqlite3_file *pFile, int *pResOut){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
vfstrace_printf(pInfo, "%s.xCheckReservedLock(%s,%d)",
pInfo->zVfsName, p->zFName);
rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
vfstrace_print_errcode(pInfo, " -> %s", rc);
vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
return rc;
}
/*
** File control method. For custom operations on an vfstrace-file.
*/
static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
char zBuf[100];
char *zOp;
switch( op ){
case SQLITE_FCNTL_LOCKSTATE: zOp = "LOCKSTATE"; break;
case SQLITE_GET_LOCKPROXYFILE: zOp = "GET_LOCKPROXYFILE"; break;
case SQLITE_SET_LOCKPROXYFILE: zOp = "SET_LOCKPROXYFILE"; break;
case SQLITE_LAST_ERRNO: zOp = "LAST_ERRNO"; break;
case SQLITE_FCNTL_SIZE_HINT: {
sqlite3_snprintf(sizeof(zBuf), zBuf, "SIZE_HINT,%lld",
*(sqlite3_int64*)pArg);
zOp = zBuf;
break;
}
case SQLITE_FCNTL_CHUNK_SIZE: {
sqlite3_snprintf(sizeof(zBuf), zBuf, "CHUNK_SIZE,%d", *(int*)pArg);
zOp = zBuf;
break;
}
case SQLITE_FCNTL_FILE_POINTER: zOp = "FILE_POINTER"; break;
case SQLITE_FCNTL_SYNC_OMITTED: zOp = "SYNC_OMITTED"; break;
case 0xca093fa0: zOp = "DB_UNCHANGED"; break;
default: {
sqlite3_snprintf(sizeof zBuf, zBuf, "%d", op);
zOp = zBuf;
break;
}
}
vfstrace_printf(pInfo, "%s.xFileControl(%s,%s)",
pInfo->zVfsName, p->zFName, zOp);
rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
return rc;
}
/*
** Return the sector-size in bytes for an vfstrace-file.
*/
static int vfstraceSectorSize(sqlite3_file *pFile){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
vfstrace_printf(pInfo, "%s.xSectorSize(%s)", pInfo->zVfsName, p->zFName);
rc = p->pReal->pMethods->xSectorSize(p->pReal);
vfstrace_printf(pInfo, " -> %d\n", rc);
return rc;
}
/*
** Return the device characteristic flags supported by an vfstrace-file.
*/
static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
vfstrace_printf(pInfo, "%s.xDeviceCharacteristics(%s)",
pInfo->zVfsName, p->zFName);
rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
vfstrace_printf(pInfo, " -> 0x%08x\n", rc);
return rc;
}
/*
** Shared-memory operations.
*/
static int vfstraceShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
char zLck[100];
int i = 0;
memcpy(zLck, "|0", 3);
if( flags & SQLITE_SHM_UNLOCK ) strappend(zLck, &i, "|UNLOCK");
if( flags & SQLITE_SHM_LOCK ) strappend(zLck, &i, "|LOCK");
if( flags & SQLITE_SHM_SHARED ) strappend(zLck, &i, "|SHARED");
if( flags & SQLITE_SHM_EXCLUSIVE ) strappend(zLck, &i, "|EXCLUSIVE");
if( flags & ~(0xf) ){
sqlite3_snprintf(sizeof(zLck)-i, &zLck[i], "|0x%x", flags);
}
vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d,n=%d,%s)",
pInfo->zVfsName, p->zFName, ofst, n, &zLck[1]);
rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
return rc;
}
static int vfstraceShmMap(
sqlite3_file *pFile,
int iRegion,
int szRegion,
int isWrite,
void volatile **pp
){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
vfstrace_printf(pInfo, "%s.xShmMap(%s,iRegion=%d,szRegion=%d,isWrite=%d,*)",
pInfo->zVfsName, p->zFName, iRegion, szRegion, isWrite);
rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
return rc;
}
static void vfstraceShmBarrier(sqlite3_file *pFile){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
vfstrace_printf(pInfo, "%s.xShmBarrier(%s)\n", pInfo->zVfsName, p->zFName);
p->pReal->pMethods->xShmBarrier(p->pReal);
}
static int vfstraceShmUnmap(sqlite3_file *pFile, int delFlag){
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = p->pInfo;
int rc;
vfstrace_printf(pInfo, "%s.xShmUnmap(%s,delFlag=%d)",
pInfo->zVfsName, p->zFName, delFlag);
rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
return rc;
}
/*
** Open an vfstrace file handle.
*/
static int vfstraceOpen(
sqlite3_vfs *pVfs,
const char *zName,
sqlite3_file *pFile,
int flags,
int *pOutFlags
){
int rc;
vfstrace_file *p = (vfstrace_file *)pFile;
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
p->pInfo = pInfo;
p->zFName = zName ? fileTail(zName) : "<temp>";
p->pReal = (sqlite3_file *)&p[1];
rc = pRoot->xOpen(pRoot, zName, p->pReal, flags, pOutFlags);
vfstrace_printf(pInfo, "%s.xOpen(%s,flags=0x%x)",
pInfo->zVfsName, p->zFName, flags);
if( p->pReal->pMethods ){
sqlite3_io_methods *pNew = sqlite3_malloc( sizeof(*pNew) );
const sqlite3_io_methods *pSub = p->pReal->pMethods;
memset(pNew, 0, sizeof(*pNew));
pNew->iVersion = pSub->iVersion;
pNew->xClose = vfstraceClose;
pNew->xRead = vfstraceRead;
pNew->xWrite = vfstraceWrite;
pNew->xTruncate = vfstraceTruncate;
pNew->xSync = vfstraceSync;
pNew->xFileSize = vfstraceFileSize;
pNew->xLock = vfstraceLock;
pNew->xUnlock = vfstraceUnlock;
pNew->xCheckReservedLock = vfstraceCheckReservedLock;
pNew->xFileControl = vfstraceFileControl;
pNew->xSectorSize = vfstraceSectorSize;
pNew->xDeviceCharacteristics = vfstraceDeviceCharacteristics;
if( pNew->iVersion>=2 ){
pNew->xShmMap = pSub->xShmMap ? vfstraceShmMap : 0;
pNew->xShmLock = pSub->xShmLock ? vfstraceShmLock : 0;
pNew->xShmBarrier = pSub->xShmBarrier ? vfstraceShmBarrier : 0;
pNew->xShmUnmap = pSub->xShmUnmap ? vfstraceShmUnmap : 0;
}
pFile->pMethods = pNew;
}
vfstrace_print_errcode(pInfo, " -> %s", rc);
if( pOutFlags ){
vfstrace_printf(pInfo, ", outFlags=0x%x\n", *pOutFlags);
}else{
vfstrace_printf(pInfo, "\n");
}
return rc;
}
/*
** Delete the file located at zPath. If the dirSync argument is true,
** ensure the file-system modifications are synced to disk before
** returning.
*/
static int vfstraceDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
int rc;
vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)",
pInfo->zVfsName, zPath, dirSync);
rc = pRoot->xDelete(pRoot, zPath, dirSync);
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
return rc;
}
/*
** Test for access permissions. Return true if the requested permission
** is available, or false otherwise.
*/
static int vfstraceAccess(
sqlite3_vfs *pVfs,
const char *zPath,
int flags,
int *pResOut
){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
int rc;
vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)",
pInfo->zVfsName, zPath, flags);
rc = pRoot->xAccess(pRoot, zPath, flags, pResOut);
vfstrace_print_errcode(pInfo, " -> %s", rc);
vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
return rc;
}
/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (DEVSYM_MAX_PATHNAME+1) bytes.
*/
static int vfstraceFullPathname(
sqlite3_vfs *pVfs,
const char *zPath,
int nOut,
char *zOut
){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
int rc;
vfstrace_printf(pInfo, "%s.xFullPathname(\"%s\")",
pInfo->zVfsName, zPath);
rc = pRoot->xFullPathname(pRoot, zPath, nOut, zOut);
vfstrace_print_errcode(pInfo, " -> %s", rc);
vfstrace_printf(pInfo, ", out=\"%.*s\"\n", nOut, zOut);
return rc;
}
/*
** Open the dynamic library located at zPath and return a handle.
*/
static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
vfstrace_printf(pInfo, "%s.xDlOpen(\"%s\")\n", pInfo->zVfsName, zPath);
return pRoot->xDlOpen(pRoot, zPath);
}
/*
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
** utf-8 string describing the most recent error encountered associated
** with dynamic libraries.
*/
static void vfstraceDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
vfstrace_printf(pInfo, "%s.xDlError(%d)", pInfo->zVfsName, nByte);
pRoot->xDlError(pRoot, nByte, zErrMsg);
vfstrace_printf(pInfo, " -> \"%s\"", zErrMsg);
}
/*
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
*/
static void (*vfstraceDlSym(sqlite3_vfs *pVfs,void *p,const char *zSym))(void){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
vfstrace_printf(pInfo, "%s.xDlSym(\"%s\")\n", pInfo->zVfsName, zSym);
return pRoot->xDlSym(pRoot, p, zSym);
}
/*
** Close the dynamic library handle pHandle.
*/
static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
vfstrace_printf(pInfo, "%s.xDlOpen()\n", pInfo->zVfsName);
pRoot->xDlClose(pRoot, pHandle);
}
/*
** Populate the buffer pointed to by zBufOut with nByte bytes of
** random data.
*/
static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
vfstrace_printf(pInfo, "%s.xRandomness(%d)\n", pInfo->zVfsName, nByte);
return pRoot->xRandomness(pRoot, nByte, zBufOut);
}
/*
** Sleep for nMicro microseconds. Return the number of microseconds
** actually slept.
*/
static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
return pRoot->xSleep(pRoot, nMicro);
}
/*
** Return the current time as a Julian Day number in *pTimeOut.
*/
static int vfstraceCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
return pRoot->xCurrentTime(pRoot, pTimeOut);
}
static int vfstraceCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
return pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
}
/*
** Return th3 emost recent error code and message
*/
static int vfstraceGetLastError(sqlite3_vfs *pVfs, int iErr, char *zErr){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
return pRoot->xGetLastError(pRoot, iErr, zErr);
}
/*
** Override system calls.
*/
static int vfstraceSetSystemCall(
sqlite3_vfs *pVfs,
const char *zName,
void *pFunc
){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
return pRoot->xSetSystemCall(pRoot, zName, pFunc);
}
static void *vfstraceGetSystemCall(sqlite3_vfs *pVfs, const char *zName){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
return pRoot->xGetSystemCall(pRoot, zName);
}
static const char *vfstraceNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
return pRoot->xNextSystemCall(pRoot, zName);
}
/*
** Clients invoke this routine to construct a new trace-vfs shim.
**
** Return SQLITE_OK on success.
**
** SQLITE_NOMEM is returned in the case of a memory allocation error.
** SQLITE_NOTFOUND is returned if zOldVfsName does not exist.
*/
int vfstrace_register(
const char *zTraceName, /* Name of the newly constructed VFS */
const char *zOldVfsName, /* Name of the underlying VFS */
int (*xOut)(const char*,void*), /* Output routine. ex: fputs */
void *pOutArg, /* 2nd argument to xOut. ex: stderr */
int makeDefault /* True to make the new VFS the default */
){
sqlite3_vfs *pNew;
sqlite3_vfs *pRoot;
vfstrace_info *pInfo;
int nName;
int nByte;
pRoot = sqlite3_vfs_find(zOldVfsName);
if( pRoot==0 ) return SQLITE_NOTFOUND;
nName = strlen(zTraceName);
nByte = sizeof(*pNew) + sizeof(*pInfo) + nName + 1;
pNew = sqlite3_malloc( nByte );
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, nByte);
pInfo = (vfstrace_info*)&pNew[1];
pNew->iVersion = pRoot->iVersion;
pNew->szOsFile = pRoot->szOsFile + sizeof(vfstrace_file);
pNew->mxPathname = pRoot->mxPathname;
pNew->zName = (char*)&pInfo[1];
memcpy((char*)&pInfo[1], zTraceName, nName+1);
pNew->pAppData = pInfo;
pNew->xOpen = vfstraceOpen;
pNew->xDelete = vfstraceDelete;
pNew->xAccess = vfstraceAccess;
pNew->xFullPathname = vfstraceFullPathname;
pNew->xDlOpen = pRoot->xDlOpen==0 ? 0 : vfstraceDlOpen;
pNew->xDlError = pRoot->xDlError==0 ? 0 : vfstraceDlError;
pNew->xDlSym = pRoot->xDlSym==0 ? 0 : vfstraceDlSym;
pNew->xDlClose = pRoot->xDlClose==0 ? 0 : vfstraceDlClose;
pNew->xRandomness = vfstraceRandomness;
pNew->xSleep = vfstraceSleep;
pNew->xCurrentTime = vfstraceCurrentTime;
pNew->xGetLastError = pRoot->xGetLastError==0 ? 0 : vfstraceGetLastError;
if( pNew->iVersion>=2 ){
pNew->xCurrentTimeInt64 = pRoot->xCurrentTimeInt64==0 ? 0 :
vfstraceCurrentTimeInt64;
if( pNew->iVersion>=3 ){
pNew->xSetSystemCall = pRoot->xSetSystemCall==0 ? 0 :
vfstraceSetSystemCall;
pNew->xGetSystemCall = pRoot->xGetSystemCall==0 ? 0 :
vfstraceGetSystemCall;
pNew->xNextSystemCall = pRoot->xNextSystemCall==0 ? 0 :
vfstraceNextSystemCall;
}
}
pInfo->pRootVfs = pRoot;
pInfo->xOut = xOut;
pInfo->pOutArg = pOutArg;
pInfo->zVfsName = pNew->zName;
pInfo->pTraceVfs = pNew;
vfstrace_printf(pInfo, "%s.enabled_for(\"%s\")\n",
pInfo->zVfsName, pRoot->zName);
return sqlite3_vfs_register(pNew, makeDefault);
}

View File

@@ -262,7 +262,6 @@ void sqlite3FinishTrigger(
int iDb; /* Database containing the trigger */
Token nameToken; /* Trigger name for error reporting */
pTrig = pParse->pNewTrigger;
pParse->pNewTrigger = 0;
if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup;
zName = pTrig->zName;

View File

@@ -128,7 +128,6 @@ void sqlite3Update(
int regNew;
int regOld = 0;
int regRowSet = 0; /* Rowset of rows to be updated */
int regRec; /* Register used for new table record to insert */
memset(&sContext, 0, sizeof(sContext));
db = pParse->db;
@@ -286,7 +285,6 @@ void sqlite3Update(
}
regNew = pParse->nMem + 1;
pParse->nMem += pTab->nCol;
regRec = ++pParse->nMem;
/* Start the view context. */
if( isView ){
@@ -396,7 +394,7 @@ void sqlite3Update(
pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
);
for(i=0; i<pTab->nCol; i++){
if( aXRef[i]<0 || oldmask==0xffffffff || (oldmask & (1<<i)) ){
if( aXRef[i]<0 || oldmask==0xffffffff || (i<32 && (oldmask & (1<<i))) ){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOld+i);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);

View File

@@ -441,14 +441,17 @@ static int compare2pow63(const char *zNum, int incr){
/*
** Convert zNum to a 64-bit signed integer and write
** the value of the integer into *pNum.
** If zNum is exactly 9223372036854665808, return 2.
** This is a special case as the context will determine
** if it is too big (used as a negative).
** If zNum is not an integer or is an integer that
** is too large to be expressed with 64 bits,
** then return 1. Otherwise return 0.
** Convert zNum to a 64-bit signed integer.
**
** If the zNum value is representable as a 64-bit twos-complement
** integer, then write that value into *pNum and return 0.
**
** If zNum is exactly 9223372036854665808, return 2. This special
** case is broken out because while 9223372036854665808 cannot be a
** signed 64-bit integer, its negative -9223372036854665808 can be.
**
** If zNum is too big for a 64-bit integer and is not
** 9223372036854665808 then return 1.
**
** length is the number of bytes in the string (bytes, not characters).
** The string is not necessarily zero-terminated. The encoding is
@@ -456,7 +459,7 @@ static int compare2pow63(const char *zNum, int incr){
*/
int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
int incr = (enc==SQLITE_UTF8?1:2);
i64 v = 0;
u64 u = 0;
int neg = 0; /* assume positive */
int i;
int c = 0;
@@ -464,20 +467,26 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
const char *zEnd = zNum + length;
if( enc==SQLITE_UTF16BE ) zNum++;
while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
if( zNum>=zEnd ) goto do_atoi_calc;
if( zNum<zEnd ){
if( *zNum=='-' ){
neg = 1;
zNum+=incr;
}else if( *zNum=='+' ){
zNum+=incr;
}
do_atoi_calc:
}
zStart = zNum;
while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */
for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
v = v*10 + c - '0';
u = u*10 + c - '0';
}
if( u>LARGEST_INT64 ){
*pNum = SMALLEST_INT64;
}else if( neg ){
*pNum = -(i64)u;
}else{
*pNum = (i64)u;
}
*pNum = neg ? -v : v;
testcase( i==18 );
testcase( i==19 );
testcase( i==20 );
@@ -487,14 +496,25 @@ do_atoi_calc:
return 1;
}else if( i<19*incr ){
/* Less than 19 digits, so we know that it fits in 64 bits */
assert( u<=LARGEST_INT64 );
return 0;
}else{
/* 19-digit numbers must be no larger than 9223372036854775807 if positive
** or 9223372036854775808 if negative. Note that 9223372036854665808
** is 2^63. Return 1 if to large */
c=compare2pow63(zNum, incr);
if( c==0 && neg==0 ) return 2; /* too big, exactly 9223372036854665808 */
return c<neg ? 0 : 1;
/* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */
c = compare2pow63(zNum, incr);
if( c<0 ){
/* zNum is less than 9223372036854775808 so it fits */
assert( u<=LARGEST_INT64 );
return 0;
}else if( c>0 ){
/* zNum is greater than 9223372036854775808 so it overflows */
return 1;
}else{
/* zNum is exactly 9223372036854775808. Fits if negative. The
** special case 2 overflow if positive */
assert( u-1==LARGEST_INT64 );
assert( (*pNum)==SMALLEST_INT64 );
return neg ? 0 : 2;
}
}
}
@@ -1060,3 +1080,71 @@ int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
return 1;
}
}
/*
** Attempt to add, substract, or multiply the 64-bit signed value iB against
** the other 64-bit signed integer at *pA and store the result in *pA.
** Return 0 on success. Or if the operation would have resulted in an
** overflow, leave *pA unchanged and return 1.
*/
int sqlite3AddInt64(i64 *pA, i64 iB){
i64 iA = *pA;
testcase( iA==0 ); testcase( iA==1 );
testcase( iB==-1 ); testcase( iB==0 );
if( iB>=0 ){
testcase( iA>0 && LARGEST_INT64 - iA == iB );
testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 );
if( iA>0 && LARGEST_INT64 - iA < iB ) return 1;
*pA += iB;
}else{
testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 );
testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 );
if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
*pA += iB;
}
return 0;
}
int sqlite3SubInt64(i64 *pA, i64 iB){
testcase( iB==SMALLEST_INT64+1 );
if( iB==SMALLEST_INT64 ){
testcase( (*pA)==(-1) ); testcase( (*pA)==0 );
if( (*pA)>=0 ) return 1;
*pA -= iB;
return 0;
}else{
return sqlite3AddInt64(pA, -iB);
}
}
#define TWOPOWER32 (((i64)1)<<32)
#define TWOPOWER31 (((i64)1)<<31)
int sqlite3MulInt64(i64 *pA, i64 iB){
i64 iA = *pA;
i64 iA1, iA0, iB1, iB0, r;
iA1 = iA/TWOPOWER32;
iA0 = iA % TWOPOWER32;
iB1 = iB/TWOPOWER32;
iB0 = iB % TWOPOWER32;
if( iA1*iB1 != 0 ) return 1;
assert( iA1*iB0==0 || iA0*iB1==0 );
r = iA1*iB0 + iA0*iB1;
testcase( r==(-TWOPOWER31)-1 );
testcase( r==(-TWOPOWER31) );
testcase( r==TWOPOWER31 );
testcase( r==TWOPOWER31-1 );
if( r<(-TWOPOWER31) || r>=TWOPOWER31 ) return 1;
r *= TWOPOWER32;
if( sqlite3AddInt64(&r, iA0*iB0) ) return 1;
*pA = r;
return 0;
}
/*
** Compute the absolute value of a 32-bit signed integer, of possible. Or
** if the integer has a value of -2147483648, return +2147483647
*/
int sqlite3AbsInt32(int x){
if( x>=0 ) return x;
if( x==(int)0x80000000 ) return 0x7fffffff;
return -x;
}

View File

@@ -1246,19 +1246,12 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
iA = pIn1->u.i;
iB = pIn2->u.i;
switch( pOp->opcode ){
case OP_Add: iB += iA; break;
case OP_Subtract: iB -= iA; break;
case OP_Multiply: iB *= iA; break;
case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break;
case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break;
case OP_Multiply: if( sqlite3MulInt64(&iB,iA) ) goto fp_math; break;
case OP_Divide: {
if( iA==0 ) goto arithmetic_result_is_null;
/* Dividing the largest possible negative 64-bit integer (1<<63) by
** -1 returns an integer too large to store in a 64-bit data-type. On
** some architectures, the value overflows to (1<<63). On others,
** a SIGFPE is issued. The following statement normalizes this
** behavior so that all architectures behave as if integer
** overflow occurred.
*/
if( iA==-1 && iB==SMALLEST_INT64 ) iA = 1;
if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math;
iB /= iA;
break;
}
@@ -1272,6 +1265,7 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
pOut->u.i = iB;
MemSetTypeFlag(pOut, MEM_Int);
}else{
fp_math:
rA = sqlite3VdbeRealValue(pIn1);
rB = sqlite3VdbeRealValue(pIn2);
switch( pOp->opcode ){
@@ -1466,8 +1460,10 @@ case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */
case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */
case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */
case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
i64 a;
i64 b;
i64 iA;
u64 uA;
i64 iB;
u8 op;
pIn1 = &aMem[pOp->p1];
pIn2 = &aMem[pOp->p2];
@@ -1476,16 +1472,38 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
sqlite3VdbeMemSetNull(pOut);
break;
}
a = sqlite3VdbeIntValue(pIn2);
b = sqlite3VdbeIntValue(pIn1);
switch( pOp->opcode ){
case OP_BitAnd: a &= b; break;
case OP_BitOr: a |= b; break;
case OP_ShiftLeft: a <<= b; break;
default: assert( pOp->opcode==OP_ShiftRight );
a >>= b; break;
iA = sqlite3VdbeIntValue(pIn2);
iB = sqlite3VdbeIntValue(pIn1);
op = pOp->opcode;
if( op==OP_BitAnd ){
iA &= iB;
}else if( op==OP_BitOr ){
iA |= iB;
}else if( iB!=0 ){
assert( op==OP_ShiftRight || op==OP_ShiftLeft );
/* If shifting by a negative amount, shift in the other direction */
if( iB<0 ){
assert( OP_ShiftRight==OP_ShiftLeft+1 );
op = 2*OP_ShiftLeft + 1 - op;
iB = iB>(-64) ? -iB : 64;
}
pOut->u.i = a;
if( iB>=64 ){
iA = (iA>=0 || op==OP_ShiftLeft) ? 0 : -1;
}else{
memcpy(&uA, &iA, sizeof(uA));
if( op==OP_ShiftLeft ){
uA <<= iB;
}else{
uA >>= iB;
/* Sign-extend on a right shift of a negative number */
if( iA<0 ) uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-iB);
}
memcpy(&iA, &uA, sizeof(iA));
}
}
pOut->u.i = iA;
MemSetTypeFlag(pOut, MEM_Int);
break;
}
@@ -2411,7 +2429,6 @@ case OP_MakeRecord: {
*/
nData = 0; /* Number of bytes of data space */
nHdr = 0; /* Number of bytes of header space */
nByte = 0; /* Data space required for this record */
nZero = 0; /* Number of zero bytes at the end of the record */
nField = pOp->p1;
zAffinity = pOp->p4.z;
@@ -3685,7 +3702,6 @@ case OP_NewRowid: { /* out2-prerelease */
** and try again, up to 100 times.
*/
assert( pC->isTable );
cnt = 0;
#ifdef SQLITE_32BIT_ROWID
# define MAX_ROWID 0x7fffffff

View File

@@ -702,13 +702,11 @@ static const Mem *columnNullValue(void){
*/
static Mem *columnMem(sqlite3_stmt *pStmt, int i){
Vdbe *pVm;
int vals;
Mem *pOut;
pVm = (Vdbe *)pStmt;
if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
sqlite3_mutex_enter(pVm->db->mutex);
vals = sqlite3_data_count(pStmt);
pOut = &pVm->pResultSet[i];
}else{
/* If the value passed as the second argument is out of range, return

View File

@@ -75,6 +75,7 @@ const char *sqlite3_sql(sqlite3_stmt *pStmt){
void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
Vdbe tmp, *pTmp;
char *zTmp;
assert( pA->db==pB->db );
tmp = *pA;
*pA = *pB;
*pB = tmp;
@@ -1517,7 +1518,7 @@ int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
*/
static void closeAllCursors(Vdbe *p){
if( p->pFrame ){
VdbeFrame *pFrame = p->pFrame;
VdbeFrame *pFrame;
for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
sqlite3VdbeFrameRestore(pFrame);
}
@@ -2497,7 +2498,13 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
if( file_format>=4 && (i&1)==i ){
return 8+(u32)i;
}
u = i<0 ? -i : i;
if( i<0 ){
if( i<(-MAX_6BYTE) ) return 6;
/* Previous test prevents: u = -(-9223372036854775808) */
u = -i;
}else{
u = i;
}
if( u<=127 ) return 1;
if( u<=32767 ) return 2;
if( u<=8388607 ) return 3;

View File

@@ -367,7 +367,7 @@ i64 sqlite3VdbeIntValue(Mem *pMem){
}else if( flags & MEM_Real ){
return doubleToInt64(pMem->r);
}else if( flags & (MEM_Str|MEM_Blob) ){
i64 value;
i64 value = 0;
assert( pMem->z || pMem->n==0 );
testcase( pMem->z==0 );
sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
@@ -1077,9 +1077,14 @@ int sqlite3ValueFromExpr(
/* This branch happens for multiple negative signs. Ex: -(-5) */
if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){
sqlite3VdbeMemNumerify(pVal);
pVal->u.i = -1 * pVal->u.i;
/* (double)-1 In case of SQLITE_OMIT_FLOATING_POINT... */
pVal->r = (double)-1 * pVal->r;
if( pVal->u.i==SMALLEST_INT64 ){
pVal->flags &= MEM_Int;
pVal->flags |= MEM_Real;
pVal->r = (double)LARGEST_INT64;
}else{
pVal->u.i = -pVal->u.i;
}
pVal->r = -pVal->r;
sqlite3ValueApplyAffinity(pVal, affinity, enc);
}
}else if( op==TK_NULL ){

View File

@@ -1649,7 +1649,6 @@ static int walCheckpoint(
}
assert( pIter );
mxPage = pWal->hdr.nPage;
if( eMode!=SQLITE_CHECKPOINT_PASSIVE ) xBusy = xBusyCall;
/* Compute in mxSafeFrame the index of the last frame of the WAL that is

View File

@@ -2520,7 +2520,8 @@ range_est_fallback:
** an equality constraint x=VALUE and where that VALUE occurs in
** the histogram data. This only works when x is the left-most
** column of an index and sqlite_stat2 histogram data is available
** for that index.
** for that index. When pExpr==NULL that means the constraint is
** "x IS NULL" instead of "x=VALUE".
**
** Write the estimated row count into *pnRow and return SQLITE_OK.
** If unable to make an estimate, leave *pnRow unchanged and return
@@ -2545,8 +2546,12 @@ int whereEqualScanEst(
assert( p->aSample!=0 );
aff = p->pTable->aCol[p->aiColumn[0]].affinity;
if( pExpr ){
rc = valueFromExpr(pParse, pExpr, aff, &pRhs);
if( rc ) goto whereEqualScanEst_cancel;
}else{
pRhs = sqlite3ValueNew(pParse->db);
}
if( pRhs==0 ) return SQLITE_NOTFOUND;
rc = whereRangeRegion(pParse, p, pRhs, 0, &iLower);
if( rc ) goto whereEqualScanEst_cancel;
@@ -2935,7 +2940,9 @@ static void bestBtreeIndex(
** VALUE and how common that value is according to the histogram.
*/
if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 ){
if( pFirstTerm->eOperator==WO_EQ ){
if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
testcase( pFirstTerm->eOperator==WO_EQ );
testcase( pFirstTerm->pOperator==WO_ISNULL );
whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
}else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){
whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &nRow);
@@ -4001,7 +4008,13 @@ static Bitmask codeOneLoopStart(
/* Record the instruction used to terminate the loop. Disable
** WHERE clause terms made redundant by the index range scan.
*/
pLevel->op = bRev ? OP_Prev : OP_Next;
if( pLevel->plan.wsFlags & WHERE_UNIQUE ){
pLevel->op = OP_Noop;
}else if( bRev ){
pLevel->op = OP_Prev;
}else{
pLevel->op = OP_Next;
}
pLevel->p1 = iIdxCur;
}else
@@ -4047,7 +4060,6 @@ static Bitmask codeOneLoopStart(
**
*/
WhereClause *pOrWc; /* The OR-clause broken out into subterms */
WhereTerm *pFinal; /* Final subterm within the OR-clause. */
SrcList *pOrTab; /* Shortened table list or OR-clause generation */
int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
@@ -4063,7 +4075,6 @@ static Bitmask codeOneLoopStart(
assert( pTerm->eOperator==WO_OR );
assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
pOrWc = &pTerm->u.pOrInfo->wc;
pFinal = &pOrWc->a[pOrWc->nTerm-1];
pLevel->op = OP_Return;
pLevel->p1 = regReturn;
@@ -4172,7 +4183,6 @@ static Bitmask codeOneLoopStart(
** the use of indices become tests that are evaluated against each row of
** the relevant input tables.
*/
k = 0;
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
Expr *pE;
testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
@@ -4190,7 +4200,6 @@ static Bitmask codeOneLoopStart(
continue;
}
sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
k = 1;
pTerm->wtFlags |= TERM_CODED;
}
@@ -4498,8 +4507,6 @@ WhereInfo *sqlite3WhereBegin(
** clause.
*/
notReady = ~(Bitmask)0;
pTabItem = pTabList->a;
pLevel = pWInfo->a;
andFlags = ~0;
WHERETRACE(("*** Optimizer Start ***\n"));
for(i=iFrom=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
@@ -4610,8 +4617,8 @@ WhereInfo *sqlite3WhereBegin(
** (1) The table must not depend on other tables that have not
** yet run.
**
** (2) A full-table-scan plan cannot supercede another plan unless
** it is an "optimal" plan as defined above.
** (2) A full-table-scan plan cannot supercede indexed plan unless
** the full-table-scan is an "optimal" plan as defined above.
**
** (3) All tables have an INDEXED BY clause or this table lacks an
** INDEXED BY clause or this table uses the specific
@@ -4627,6 +4634,7 @@ WhereInfo *sqlite3WhereBegin(
*/
if( (sCost.used&notReady)==0 /* (1) */
&& (bestJ<0 || (notIndexed&m)!=0 /* (2) */
|| (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
|| (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)
&& (nUnconstrained==0 || pTabItem->pIndex==0 /* (3) */
|| NEVER((sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))

View File

@@ -164,6 +164,8 @@ foreach {testid where index rows} {
301 {y=1} t1y 50
302 {y=0.1} t1y 50
400 {x IS NULL} t1x 400
} {
# Verify that the expected index is used with the expected row count
do_test analyze5-1.${testid}a {
@@ -190,5 +192,48 @@ foreach {testid where index rows} {
} {ok}
}
# Increase the number of NULLs in column x
#
db eval {
UPDATE t1 SET x=NULL;
UPDATE t1 SET x=rowid
WHERE rowid IN (SELECT rowid FROM t1 ORDER BY random() LIMIT 5);
ANALYZE;
}
# Verify that range queries generate the correct row count estimates
#
foreach {testid where index rows} {
500 {x IS NULL AND u='charlie'} t1u 20
501 {x=1 AND u='charlie'} t1x 5
502 {x IS NULL} {} 100
503 {x=1} t1x 50
504 {x IS NOT NULL} t1x 25
} {
# Verify that the expected index is used with the expected row count
do_test analyze5-1.${testid}a {
set x [lindex [eqp "SELECT * FROM t1 WHERE $where"] 3]
set idx {}
regexp {INDEX (t1.) } $x all idx
regexp {~([0-9]+) rows} $x all nrow
list $idx $nrow
} [list $index $rows]
# Verify that the same result is achieved regardless of whether or not
# the index is used
do_test analyze5-1.${testid}b {
set w2 [string map {y +y z +z} $where]
set a1 [db eval "SELECT rowid FROM t1 NOT INDEXED WHERE $w2\
ORDER BY +rowid"]
set a2 [db eval "SELECT rowid FROM t1 WHERE $where ORDER BY +rowid"]
if {$a1==$a2} {
set res ok
} else {
set res "a1=\[$a1\] a2=\[$a2\]"
}
set res
} {ok}
}
finish_test

74
test/analyze6.test Normal file
View File

@@ -0,0 +1,74 @@
# 2011 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.
#
#***********************************************************************
#
# This file implements tests for SQLite library. The focus of the tests
# in this file a corner-case query planner optimization involving the
# join order of two tables of different sizes.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !stat2 {
finish_test
return
}
set testprefix analyze6
proc eqp {sql {db db}} {
uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db
}
do_test analyze6-1.0 {
db eval {
CREATE TABLE cat(x INT);
CREATE UNIQUE INDEX catx ON cat(x);
/* Give cat 16 unique integers */
INSERT INTO cat VALUES(1);
INSERT INTO cat VALUES(2);
INSERT INTO cat SELECT x+2 FROM cat;
INSERT INTO cat SELECT x+4 FROM cat;
INSERT INTO cat SELECT x+8 FROM cat;
CREATE TABLE ev(y INT);
CREATE INDEX evy ON ev(y);
/* ev will hold 32 copies of 16 integers found in cat */
INSERT INTO ev SELECT x FROM cat;
INSERT INTO ev SELECT x FROM cat;
INSERT INTO ev SELECT y FROM ev;
INSERT INTO ev SELECT y FROM ev;
INSERT INTO ev SELECT y FROM ev;
INSERT INTO ev SELECT y FROM ev;
ANALYZE;
SELECT count(*) FROM cat;
SELECT count(*) FROM ev;
}
} {16 512}
# The lowest cost plan is to scan CAT and for each integer there, do a single
# lookup of the first corresponding entry in EV then read off the equal values
# in EV. (Prior to the 2011-03-04 enhancement to where.c, this query would
# have used EV for the outer loop instead of CAT - which was about 3x slower.)
#
do_test analyze6-1.1 {
eqp {SELECT count(*) FROM ev, cat WHERE x=y}
} {0 0 1 {SCAN TABLE cat (~16 rows)} 0 1 0 {SEARCH TABLE ev USING COVERING INDEX evy (y=?) (~32 rows)}}
# The same plan is chosen regardless of the order of the tables in the
# FROM clause.
#
do_test analyze6-1.2 {
eqp {SELECT count(*) FROM cat, ev WHERE x=y}
} {0 0 0 {SCAN TABLE cat (~16 rows)} 0 1 1 {SEARCH TABLE ev USING COVERING INDEX evy (y=?) (~32 rows)}}
finish_test

View File

@@ -82,8 +82,18 @@ test_expr expr-1.43 {i1=1, i2=2} {i1&i2} {0}
test_expr expr-1.43b {i1=1, i2=2} {4&5} {4}
test_expr expr-1.44 {i1=1} {~i1} {-2}
test_expr expr-1.44b {i1=NULL} {~i1} {{}}
test_expr expr-1.45 {i1=1, i2=3} {i1<<i2} {8}
test_expr expr-1.46 {i1=32, i2=3} {i1>>i2} {4}
test_expr expr-1.45a {i1=1, i2=3} {i1<<i2} {8}
test_expr expr-1.45b {i1=1, i2=-3} {i1>>i2} {8}
test_expr expr-1.45c {i1=1, i2=0} {i1<<i2} {1}
test_expr expr-1.45d {i1=1, i2=62} {i1<<i2} {4611686018427387904}
test_expr expr-1.45e {i1=1, i2=63} {i1<<i2} {-9223372036854775808}
test_expr expr-1.45f {i1=1, i2=64} {i1<<i2} {0}
test_expr expr-1.45g {i1=32, i2=-9223372036854775808} {i1>>i2} {0}
test_expr expr-1.46a {i1=32, i2=3} {i1>>i2} {4}
test_expr expr-1.46b {i1=32, i2=6} {i1>>i2} {0}
test_expr expr-1.46c {i1=-32, i2=3} {i1>>i2} {-4}
test_expr expr-1.46d {i1=-32, i2=100} {i1>>i2} {-1}
test_expr expr-1.46e {i1=32, i2=-3} {i1>>i2} {256}
test_expr expr-1.47 {i1=9999999999, i2=8888888888} {i1<i2} 0
test_expr expr-1.48 {i1=9999999999, i2=8888888888} {i1=i2} 0
test_expr expr-1.49 {i1=9999999999, i2=8888888888} {i1>i2} 1
@@ -154,10 +164,10 @@ ifcapable floatingpoint {
}
if {[working_64bit_int]} {
test_expr expr-1.106 {i1=0} {(1<<63)/-1} -9223372036854775808
test_expr expr-1.106 {i1=0} {-9223372036854775808/-1} 9.22337203685478e+18
}
test_expr expr-1.107 {i1=0} {(1<<63)%-1} 0
test_expr expr-1.107 {i1=0} {-9223372036854775808%-1} 0
test_expr expr-1.108 {i1=0} {1%0} {{}}
test_expr expr-1.109 {i1=0} {1/0} {{}}
@@ -190,6 +200,107 @@ test_expr expr-1.125 {i1=6, i2=NULL} \
test_expr expr-1.126 {i1=8, i2=8} \
{CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} no
ifcapable floatingpoint {if {[working_64bit_int]} {
test_expr expr-1.200\
{i1=9223372036854775806, i2=1} {i1+i2} 9223372036854775807
test_expr expr-1.201\
{i1=9223372036854775806, i2=2} {i1+i2} 9.22337203685478e+18
test_expr expr-1.202\
{i1=9223372036854775806, i2=100000} {i1+i2} 9.22337203685488e+18
test_expr expr-1.203\
{i1=9223372036854775807, i2=0} {i1+i2} 9223372036854775807
test_expr expr-1.204\
{i1=9223372036854775807, i2=1} {i1+i2} 9.22337203685478e+18
test_expr expr-1.205\
{i2=9223372036854775806, i1=1} {i1+i2} 9223372036854775807
test_expr expr-1.206\
{i2=9223372036854775806, i1=2} {i1+i2} 9.22337203685478e+18
test_expr expr-1.207\
{i2=9223372036854775806, i1=100000} {i1+i2} 9.22337203685488e+18
test_expr expr-1.208\
{i2=9223372036854775807, i1=0} {i1+i2} 9223372036854775807
test_expr expr-1.209\
{i2=9223372036854775807, i1=1} {i1+i2} 9.22337203685478e+18
test_expr expr-1.210\
{i1=-9223372036854775807, i2=-1} {i1+i2} -9223372036854775808
test_expr expr-1.211\
{i1=-9223372036854775807, i2=-2} {i1+i2} -9.22337203685478e+18
test_expr expr-1.212\
{i1=-9223372036854775807, i2=-100000} {i1+i2} -9.22337203685488e+18
test_expr expr-1.213\
{i1=-9223372036854775808, i2=0} {i1+i2} -9223372036854775808
test_expr expr-1.214\
{i1=-9223372036854775808, i2=-1} {i1+i2} -9.22337203685478e+18
test_expr expr-1.215\
{i2=-9223372036854775807, i1=-1} {i1+i2} -9223372036854775808
test_expr expr-1.216\
{i2=-9223372036854775807, i1=-2} {i1+i2} -9.22337203685478e+18
test_expr expr-1.217\
{i2=-9223372036854775807, i1=-100000} {i1+i2} -9.22337203685488e+18
test_expr expr-1.218\
{i2=-9223372036854775808, i1=0} {i1+i2} -9223372036854775808
test_expr expr-1.219\
{i2=-9223372036854775808, i1=-1} {i1+i2} -9.22337203685478e+18
test_expr expr-1.220\
{i1=9223372036854775806, i2=-1} {i1-i2} 9223372036854775807
test_expr expr-1.221\
{i1=9223372036854775806, i2=-2} {i1-i2} 9.22337203685478e+18
test_expr expr-1.222\
{i1=9223372036854775806, i2=-100000} {i1-i2} 9.22337203685488e+18
test_expr expr-1.223\
{i1=9223372036854775807, i2=0} {i1-i2} 9223372036854775807
test_expr expr-1.224\
{i1=9223372036854775807, i2=-1} {i1-i2} 9.22337203685478e+18
test_expr expr-1.225\
{i2=-9223372036854775806, i1=1} {i1-i2} 9223372036854775807
test_expr expr-1.226\
{i2=-9223372036854775806, i1=2} {i1-i2} 9.22337203685478e+18
test_expr expr-1.227\
{i2=-9223372036854775806, i1=100000} {i1-i2} 9.22337203685488e+18
test_expr expr-1.228\
{i2=-9223372036854775807, i1=0} {i1-i2} 9223372036854775807
test_expr expr-1.229\
{i2=-9223372036854775807, i1=1} {i1-i2} 9.22337203685478e+18
test_expr expr-1.230\
{i1=-9223372036854775807, i2=1} {i1-i2} -9223372036854775808
test_expr expr-1.231\
{i1=-9223372036854775807, i2=2} {i1-i2} -9.22337203685478e+18
test_expr expr-1.232\
{i1=-9223372036854775807, i2=100000} {i1-i2} -9.22337203685488e+18
test_expr expr-1.233\
{i1=-9223372036854775808, i2=0} {i1-i2} -9223372036854775808
test_expr expr-1.234\
{i1=-9223372036854775808, i2=1} {i1-i2} -9.22337203685478e+18
test_expr expr-1.235\
{i2=9223372036854775807, i1=-1} {i1-i2} -9223372036854775808
test_expr expr-1.236\
{i2=9223372036854775807, i1=-2} {i1-i2} -9.22337203685478e+18
test_expr expr-1.237\
{i2=9223372036854775807, i1=-100000} {i1-i2} -9.22337203685488e+18
test_expr expr-1.238\
{i2=9223372036854775807, i1=0} {i1-i2} -9223372036854775807
test_expr expr-1.239\
{i2=9223372036854775807, i1=-1} {i1-i2} -9223372036854775808
test_expr expr-1.250\
{i1=4294967296, i2=2147483648} {i1*i2} 9.22337203685478e+18
test_expr expr-1.251\
{i1=4294967296, i2=2147483647} {i1*i2} 9223372032559808512
test_expr expr-1.252\
{i1=-4294967296, i2=2147483648} {i1*i2} -9223372036854775808
test_expr expr-1.253\
{i1=-4294967296, i2=2147483647} {i1*i2} -9223372032559808512
test_expr expr-1.254\
{i1=4294967296, i2=-2147483648} {i1*i2} -9223372036854775808
test_expr expr-1.255\
{i1=4294967296, i2=-2147483647} {i1*i2} -9223372032559808512
test_expr expr-1.256\
{i1=-4294967296, i2=-2147483648} {i1*i2} 9.22337203685478e+18
test_expr expr-1.257\
{i1=-4294967296, i2=-2147483647} {i1*i2} 9223372032559808512
}}
ifcapable floatingpoint {
test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11

View File

@@ -354,7 +354,7 @@ do_test index-11.1 {
}
set sqlite_search_count 0
concat [execsql {SELECT c FROM t3 WHERE b==10}] $sqlite_search_count
} {0.1 3}
} {0.1 2}
integrity_check index-11.2

66
test/mem5.test Normal file
View File

@@ -0,0 +1,66 @@
# 2011 March 9
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests of the mem5 allocation subsystem.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !mem5 {
finish_test
return
}
# The tests in this file configure the lookaside allocator after a
# connection is opened. This will not work if there is any "presql"
# configured (SQL run within the [sqlite3] wrapper in tester.tcl).
if {[info exists ::G(perm:presql)]} {
finish_test
return
}
do_test mem5-1.1 {
catch {db close}
sqlite3_shutdown
sqlite3_config_heap 25000000 0
sqlite3_config_lookaside 0 0
sqlite3_initialize
} {SQLITE_OK}
# try with min request size = 2^30
do_test mem5-1.2 {
catch {db close}
sqlite3_shutdown
sqlite3_config_heap 1 1073741824
sqlite3_config_lookaside 0 0
sqlite3_initialize
} {SQLITE_NOMEM}
# try with min request size = 2^30+1
# previously this was causing the memsys5Log() func to infinitely loop.
do_test mem5-1.3 {
catch {db close}
sqlite3_shutdown
sqlite3_config_heap 1 1073741825
sqlite3_config_lookaside 0 0
sqlite3_initialize
} {SQLITE_NOMEM}
do_test mem5-1.4 {
catch {db close}
sqlite3_shutdown
sqlite3_config_heap 0 0
sqlite3_config_lookaside 0 0
sqlite3_initialize
} {SQLITE_OK}
finish_test

170
test/omitunique.test Normal file
View File

@@ -0,0 +1,170 @@
# 2011 March 10
#
# 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 SQLITE_OMIT_UNIQUE_ENFORCEMENT
# compiler option.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set uniq_enforced 1
ifcapable !unique_enforcement {
set uniq_enforced 0
}
# table with UNIQUE keyword on column
do_test omitunique-1.1 {
catchsql { CREATE TABLE t1(a TEXT UNIQUE); }
} {0 {}}
# table with UNIQUE clause on column
do_test omitunique-1.2 {
catchsql { CREATE TABLE t2(a TEXT, UNIQUE(a)); }
} {0 {}}
# table with UNIQUE index on column
do_test omitunique-1.3 {
catchsql {
CREATE TABLE t3(a TEXT);
CREATE UNIQUE INDEX t3a ON t3(a);
}
} {0 {}}
# table with regular index on column
do_test omitunique-1.4 {
catchsql {
CREATE TABLE t4(a TEXT);
CREATE INDEX t4a ON t4(a);
}
} {0 {}}
# table with no index on column
do_test omitunique-1.5 {
catchsql { CREATE TABLE t5(a TEXT); }
} {0 {}}
# run our tests using several table/index forms
foreach {j tbl uniq cnt qp_est stat_enforce stat_omit } {
1 {t1} 1 1 1 {2 1} {9 9}
2 {t2} 1 1 1 {2 1} {9 9}
3 {t3} 1 1 1 {2 1} {9 9}
4 {t4} 0 9 10 {9 9} {9 9}
5 {t5} 0 9 100000 9 9
} {
do_test omitunique-2.0.$j.1 {
catchsql [ subst {INSERT INTO $tbl (a) VALUES('abc'); }]
} {0 {}}
do_test omitunique-2.0.$j.2 {
catchsql [ subst {INSERT INTO $tbl (a) VALUES('123'); }]
} {0 {}}
# check various INSERT commands
foreach {i cmd err} {
1 {INSERT} 1
2 {INSERT OR IGNORE} 0
3 {INSERT OR REPLACE} 0
4 {REPLACE} 0
5 {INSERT OR FAIL} 1
6 {INSERT OR ABORT} 1
7 {INSERT OR ROLLBACK} 1
} {
ifcapable explain {
set x [execsql [ subst { EXPLAIN $cmd INTO $tbl (a) VALUES('abc'); }]]
ifcapable unique_enforcement {
do_test omitunique-2.1.$j.$i.1 {
regexp { IsUnique } $x
} $uniq
}
ifcapable !unique_enforcement {
do_test omitunique-2.1.$j.$i.1 {
regexp { IsUnique } $x
} {0}
}
}
if { $uniq_enforced==0 || $uniq==0 || $err==0 } {
set msg {0 {}}
} {
set msg {1 {column a is not unique}}
}
do_test omitunique-2.1.$j.$i.3 {
catchsql [ subst {$cmd INTO $tbl (a) VALUES('abc'); }]
} $msg
}
# end foreach cmd
# check UPDATE command
ifcapable explain {
set x [execsql [ subst { EXPLAIN UPDATE $tbl SET a='abc'; }]]
ifcapable unique_enforcement {
do_test omitunique-2.2.$j.1 {
regexp { IsUnique } $x
} $uniq
}
ifcapable !unique_enforcement {
do_test omitunique-2.2.$j.1 {
regexp { IsUnique } $x
} {0}
}
}
if { $uniq_enforced==0 || $uniq==0 } {
set msg {0 {}}
} {
set msg {1 {column a is not unique}}
}
do_test omitunique-2.2.$j.3 {
catchsql [ subst { UPDATE $tbl SET a='abc'; }]
} $msg
# check record counts
do_test omitunique-2.3.$j {
execsql [ subst { SELECT count(*) FROM $tbl WHERE a='abc'; }]
} $cnt
# make sure the query planner row estimate not affected because of omit enforcement
ifcapable explain {
do_test omitunique-2.4.$j {
set x [ execsql [ subst { EXPLAIN QUERY PLAN SELECT count(*) FROM $tbl WHERE a='abc'; }]]
set y [ subst {~$qp_est row} ]
regexp $y $x
} {1}
}
# make sure we omit extra OP_Next opcodes when the UNIQUE constraints
# mean there will only be a single pass through the code
ifcapable explain {
set x [execsql [ subst { EXPLAIN SELECT * FROM $tbl WHERE a='abc'; }]]
do_test omitunique-2.5.$j {
if { [ regexp { Next } $x ] } { expr { 0 } } { expr { 1 } }
} $uniq
}
# make sure analyze index stats correct
ifcapable analyze {
if { $uniq_enforced==0 } {
set msg [ list $stat_omit ]
} {
set msg [ list $stat_enforce ]
}
do_test omitunique-2.6.$j {
execsql [ subst { ANALYZE $tbl; } ]
execsql [ subst { SELECT stat FROM sqlite_stat1 WHERE tbl='$tbl'; } ]
} $msg
}
}
# end foreach tbl
finish_test

View File

@@ -56,7 +56,7 @@ do_test 1.1.2 {
catch { for {set i 0} {$i < 2000} {incr i} { dbh_$i close } }
} {1}
do_re_test 1.1.3 { lindex $::log 0 } {^os_unix.c: open.*test.db$}
do_re_test 1.1.3 { lindex $::log 0 } {^os_unix.c:\d+: \(\d+\) open\(.*test.db\) - }
# Test a failure in open() due to the path being a directory.
@@ -67,7 +67,7 @@ do_test 1.2.1 {
list [catch { sqlite3 dbh dir.db } msg] $msg
} {1 {unable to open database file}}
do_re_test 1.2.2 { lindex $::log 0 } {^os_unix.c: open.*dir.db$}
do_re_test 1.2.2 { lindex $::log 0 } {^os_unix.c:\d+: \(\d+\) open\(.*dir.db\) - }
# Test a failure in open() due to the path not existing.
#
@@ -76,7 +76,7 @@ do_test 1.3.1 {
list [catch { sqlite3 dbh /x/y/z/test.db } msg] $msg
} {1 {unable to open database file}}
do_re_test 1.3.2 { lindex $::log 0 } {^os_unix.c: open.*test.db$}
do_re_test 1.3.2 { lindex $::log 0 } {^os_unix.c:\d+: \(\d+\) open\(.*test.db\) - }
# Test a failure in open() due to the path not existing.
#
@@ -85,7 +85,7 @@ do_test 1.4.1 {
list [catch { sqlite3 dbh /root/test.db } msg] $msg
} {1 {unable to open database file}}
do_re_test 1.4.2 { lindex $::log 0 } {^os_unix.c: open.*test.db$}
do_re_test 1.4.2 { lindex $::log 0 } {^os_unix.c:\d*: \(\d+\) open\(.*test.db\) - }
#--------------------------------------------------------------------------
# Tests oserror-1.* test failures in the unlink() system call.
@@ -98,7 +98,7 @@ do_test 2.1.1 {
catchsql { SELECT * FROM sqlite_master } dbh
} {1 {disk I/O error}}
do_re_test 2.1.2 { lindex $::log 0 } {^os_unix.c: unlink.*test.db-wal$}
do_re_test 2.1.2 { lindex $::log 0 } {^os_unix.c:\d+: \(\d+\) unlink\(.*test.db-wal\) - }
do_test 2.1.3 {
dbh close
forcedelete test.db-wal
@@ -109,4 +109,3 @@ sqlite3_shutdown
test_sqlite3_log
sqlite3_initialize
finish_test

0
test/progress.test Executable file → Normal file
View File

0
tool/mkopts.tcl Executable file → Normal file
View File

View File

@@ -202,6 +202,7 @@ proc main {argv} {
SQLITE_OMIT_TRACE \
SQLITE_OMIT_TRIGGER \
SQLITE_OMIT_TRUNCATE_OPTIMIZATION \
SQLITE_OMIT_UNIQUE_ENFORCEMENT \
SQLITE_OMIT_UTF16 \
SQLITE_OMIT_VACUUM \
SQLITE_OMIT_VIEW \