Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 56e4b6f968 | |||
| 7ee841f506 | |||
| 80b1ff487f | |||
| a34b0794e0 | |||
| 058d3c4477 | |||
| fdd4af7e7b | |||
| d7ae9475a8 | |||
| dd71a0753e | |||
| 6ebcbcd48b | |||
| 9b9a61f715 | |||
| fb7b4f204b | |||
| b3dc0431c7 | |||
| 66a01c4554 | |||
| 6f65beb084 | |||
| 7a5b729aa7 | |||
| ec88191019 | |||
| e1b6c821d6 | |||
| b2292faf9c | |||
| 5cfe9a78f9 | |||
| 19aca9eddb | |||
| 85a5dfef26 | |||
| 82ab315f73 | |||
| 3ec28d5d81 | |||
| e1175bd650 | |||
| 0c3ab2d6ac | |||
| 73003316a2 | |||
| bde845ce70 | |||
| 4cf73f61fb | |||
| 5d7f6e84f1 | |||
| 8c8ec4fd3e | |||
| 2d97242175 | |||
| 0e93442494 | |||
| 9c46d69216 | |||
| a8734da09b | |||
| 90ddc11b77 | |||
| 0aaa1c038e | |||
| 6951f39c72 | |||
| 805e7d5b42 | |||
| 06d55ce8f3 | |||
| 24b8cb36bc | |||
| afcfc0eecb | |||
| ea024eee62 | |||
| ca69323478 | |||
| 52e50d6aaa | |||
| 0f156745bd | |||
| f4ed02a34f | |||
| 463ff298d6 | |||
| 5d5398b089 | |||
| f3a5a57ddb | |||
| 1832890357 | |||
| 97117601d2 | |||
| f9ec81c84d | |||
| 45041e263a | |||
| 3e5c826219 | |||
| 4e0e4d7a9e | |||
| 064cf76bb1 | |||
| a38518d673 |
@@ -156,6 +156,20 @@ sqlite$(EXE): $(TOP)/src/shell.c libsqlite.a sqlite.h
|
||||
$(TCCX) $(READLINE_FLAGS) -o sqlite$(EXE) $(TOP)/src/shell.c \
|
||||
libsqlite.a $(LIBREADLINE) $(THREADLIB)
|
||||
|
||||
sqlite_analyzer$(EXE): $(TOP)/src/tclsqlite.c libsqlite.a $(TESTSRC) \
|
||||
$(TOP)/tool/spaceanal.tcl
|
||||
sed \
|
||||
-e '/^#/d' \
|
||||
-e 's,\\,\\\\,g' \
|
||||
-e 's,",\\",g' \
|
||||
-e 's,^,",' \
|
||||
-e 's,$$,\\n",' \
|
||||
$(TOP)/tool/spaceanal.tcl >spaceanal_tcl.h
|
||||
$(TCCX) $(TCL_FLAGS) -DTCLSH=2 -DSQLITE_TEST=1 -static -o \
|
||||
sqlite_analyzer$(EXE) $(TESTSRC) $(TOP)/src/tclsqlite.c \
|
||||
libsqlite.a $(LIBTCL)
|
||||
|
||||
|
||||
# This target creates a directory named "tsrc" and fills it with
|
||||
# copies of all of the C source code and header files needed to
|
||||
# build on the target system. Some of the C source code and header
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
C Get\sthe\stemp_store\sand\sdefault_temp_store\spragmas\sworking.\s\sUpdate\sthe\ndocumentation.\s\sAlso\sfix\sa\smalloc\sproblem\sthat\spopped\sup\sduring\sthe\sregression\ntesting.\s(CVS\s1302)
|
||||
D 2004-04-23T17:04:44
|
||||
C Fix\sa\sdate\sround-off\sproblem\sin\sstrftime().\s\sTicket\s#2153.\s(CVS\s3575)
|
||||
D 2007-01-08T16:20:29
|
||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
F VERSION 4328de2a5fb5000699b907ca405cb9d84ba4e097
|
||||
F VERSION 028d738f543b0e6a47f215b2adb7eb90fb5b9f3a
|
||||
F aclocal.m4 7daea4c35e88de30d5a3f6f7a2ab99720e803bbd
|
||||
F art/SQLite.eps 9b43cc99cfd2be687d386faea6862ea68d6a72b2
|
||||
F art/SQLite.gif 1bbb94484963f1382e27e1c5e86dd0c1061eba2b
|
||||
@@ -15,61 +15,61 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
|
||||
F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
||||
F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
|
||||
F main.mk 1b27efb94be53a96c4333584a00a59fcc87ddc37
|
||||
F publish.sh 1cd5c982388560fa91eedf6a338e210f713b35c8
|
||||
F main.mk 7dfbd08ac90b15debd84ebd2606f0dbab739a4ab
|
||||
F publish.sh 28c743e8ef922b726a05c84a8e597a6cf04cf554
|
||||
F spec.template a38492f1c1dd349fc24cb0565e08afc53045304b
|
||||
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
|
||||
F sqlite.def fc4f5734786fe4743cfe2aa98eb2da4b089edb5f
|
||||
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
|
||||
F src/attach.c b01db0d3211f673d8e670abf7eaad04591d40d14
|
||||
F src/auth.c 4fa3b05bd19445d1c474d6751c4a508d6ea0abe1
|
||||
F src/attach.c 026702566f941bf2bb158a0aaa86bfeb65910aa6
|
||||
F src/auth.c 8d678ab13950801e10fd09781a7c1ed3bfeffb7c
|
||||
F src/btree.c 08a05b925b348c05d79b9b062b79e50d565678de
|
||||
F src/btree.h 41cb3ff6ebc3f6da2d0a074e39ff8c7a2287469f
|
||||
F src/btree_rb.c 99feb3ff835106d018a483a1ce403e5cf9c718bc
|
||||
F src/build.c 76fbca30081decd6615dee34b48c927ed5063752
|
||||
F src/btree_rb.c af40501eedd7b673ffd5e02f3a4702c76596d64a
|
||||
F src/build.c ee7905531ed592bd68b484f0821fc3cd007e1576
|
||||
F src/copy.c 750e13828c3e4a293123e36aaa7cf0f22466248a
|
||||
F src/date.c f055419d602bde622c70f831350b6b52f2235de0
|
||||
F src/date.c 3f080b6f46c6a96891987b439449e4096c98f925
|
||||
F src/delete.c 82001c74882319f94dab5f6b92a27311b31092ae
|
||||
F src/encode.c fc8c51f0b61bc803ccdec092e130bebe762b0a2f
|
||||
F src/expr.c 8c3f5603c3e98b1c146d18076ba3e82cdbb59c11
|
||||
F src/func.c 34fead7a33e82095f6412d3fafd379d47864b3be
|
||||
F src/expr.c 6bb3961c0391f2efe788fcfde3c2ff2ff283d5a8
|
||||
F src/func.c ab5c57f0ebb975e66cc13f09141247c2f7a2c293
|
||||
F src/hash.c 9b56ef3b291e25168f630d5643a4264ec011c70e
|
||||
F src/hash.h 3247573ab95b9dd90bcca0307a75d9a16da1ccc7
|
||||
F src/insert.c c0485ee2d1b99322894e2d1e0b576fd05ed75616
|
||||
F src/main.c 94dd355768e2a389e184a069b6880f4bac100307
|
||||
F src/main.c 7802ab78b2f2e66750be2192b2c1334c99bc10a5
|
||||
F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
|
||||
F src/os.c 5f11382733805d4529ec2a30800e117f30995ea8
|
||||
F src/os.c 617db07b13113ec093786b2278767ab46217d140
|
||||
F src/os.h 250a3789be609adfee5c5aa20137ce8683276f24
|
||||
F src/pager.c b246986e5ba31b15aa3cf91d3b9ec2e608aceb8e
|
||||
F src/pager.c e44cb43e9cd2e7a06818c4f8ff5aa697f7edf8cd
|
||||
F src/pager.h 82332878799280145639a48d88cdb4058925e3f6
|
||||
F src/parse.y 023720cb8c3bef74e51738bca78335d0dc6d2cfd
|
||||
F src/pragma.c f9c157b0591419d2d3407dac90222020d2a6d822
|
||||
F src/printf.c 8c58b7b6d4069eec6ebe2d46bdbc3a89a367bf95
|
||||
F src/printf.c 378ec63d9303993eef24814a56a9fc7260aacbea
|
||||
F src/random.c 775913e0b7fbd6295d21f12a7bd35b46387c44b2
|
||||
F src/select.c 3833e2b64cc6d249385ee44e13bf49c9ae5b903d
|
||||
F src/shell.c 920af040d3a33ea8919c82cee45b424ad841cee0
|
||||
F src/sqlite.h.in 35bec264dfb4965bbfeb7e75221f8658f210c30d
|
||||
F src/sqliteInt.h 235ce244b62bb26cc9ab394fb7a0724dd4e65c83
|
||||
F src/table.c d845cb101b5afc1f7fea083c99e3d2fa7998d895
|
||||
F src/tclsqlite.c 819d92d305756c4ea57de023c387d2fa8a256aff
|
||||
F src/test1.c 9aa62b89d420e6763b5e7ae89a47f6cf87370477
|
||||
F src/select.c a1c18cab14b49f28ed7629a53fe02adeb13083d2
|
||||
F src/shell.c 46a1757c152bba687f647b571693bfa223d3354d
|
||||
F src/sqlite.h.in b1414cc6686c77917024d8196efa4531e76cf194
|
||||
F src/sqliteInt.h 311de2338da566e996ea3f4846d489e3856be7a3
|
||||
F src/table.c eea34544be947e4939ba9e46391d5da998f90b84
|
||||
F src/tclsqlite.c 2daaaa41378fbaf167905363197e1d44464b6eb6
|
||||
F src/test1.c 4ae20bc125b1a7d7824cccca55d538d81f0b4949
|
||||
F src/test2.c 75819b0f2c63c6a0fd6995445881f2eb94036996
|
||||
F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5
|
||||
F src/test4.c 6e3e31acfaf21d66420fc35fda5b17dc0000cc8d
|
||||
F src/tokenize.c 6676b946fd8825b67ab52140af4fdc57a70bda48
|
||||
F src/trigger.c a9927b57c865b6f3df3fb5e40c9824d722660ded
|
||||
F src/update.c 4c50328ebc127852bde8e2950eb8933234802c21
|
||||
F src/util.c 122bc174f6c8c2eb6a9127d9f13c4c74f83b85e4
|
||||
F src/vacuum.c a4e8464c9f6d60659c5343e9d62c742463227820
|
||||
F src/vdbe.c 7c33f761fdc799633468766fb53eda4301daa6b3
|
||||
F src/update.c bd391079138e67d09c9af34528ca4137c29242d1
|
||||
F src/util.c c2de22342aae2cc954d3c88ef40a2ece7cee6905
|
||||
F src/vacuum.c 12de02a8dec2b3f8d30ea496b66a0f989322a2c4
|
||||
F src/vdbe.c 59100995dae315d1c756a8a754b1dd1a228751d7
|
||||
F src/vdbe.h ac987945e4dd6f987bca534c6005899f089fc270
|
||||
F src/vdbeInt.h b40ff02ce39fd076e6ff3369e19c1bbfe1986682
|
||||
F src/vdbeaux.c e2cdd1ab63604a390612c73e26bdd2ef910e9438
|
||||
F src/where.c b58764861a96bab3f1d294200f9e53519b92c274
|
||||
F src/vdbeaux.c 14ff0eb6ed9d5998f927433c91b0a3d13d81f4f6
|
||||
F src/where.c ce4968e37382808ec76a47385384ee21ad9e979e
|
||||
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
|
||||
F test/attach.test ba8261d38da6b6a7d4f78ec543c548c4418582ef
|
||||
F test/attach2.test ce61e6185b3cd891cc0e9a4c868fcc65eb92fc55
|
||||
F test/auth.test 5c4d95cdaf539c0c236e20ce1f71a93e7dde9185
|
||||
F test/auth.test 3bd865e3069af8aa703158ff69cfc5e57b29033b
|
||||
F test/bigfile.test ea904b853ce2d703b16c5ce90e2b54951bc1ae81
|
||||
F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
|
||||
F test/bind.test 56a57043b42c4664ca705f6050e56717a8a6699a
|
||||
@@ -83,37 +83,39 @@ F test/capi2.test ec96e0e235d87b53cbaef3d8e3e0f8ccf32c71ca
|
||||
F test/conflict.test 0911bb2f079046914a6e9c3341b36658c4e2103e
|
||||
F test/copy.test f07ea8d60878da7a67416ab62f78e9706b9d3c45
|
||||
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/date.test aed5030482ebc02bd8d386c6c86a29f694ab068d
|
||||
F test/date.test aa4bc2aae379bed3f838ea73de0cde1c352c5545
|
||||
F test/delete.test 92256384f1801760180ded129f7427884cf28886
|
||||
F test/expr.test ad985242e140f87eeef329d98257b8369a2066dc
|
||||
F test/fkey1.test d65c824459916249bee501532d6154ddab0b5db7
|
||||
F test/format3.test 149cc166c97923fa60def047e90dd3fb32bba916
|
||||
F test/func.test 000515779001ac6899eec4b54e65c6e2501279d4
|
||||
F test/func.test 56b12001d4d8239c6af2864e3d64916cf5dad711
|
||||
F test/hook.test 1a67ce0cd64a6455d016962542f2822458dccc49
|
||||
F test/in.test 0de39b02ceeca90993b096822fb5a884661c5b47
|
||||
F test/index.test 9295deefbdb6dedbe01be8905f0c448fe5bd4079
|
||||
F test/index.test 491d721e9b442a51b118894323f2885a2187a8dd
|
||||
F test/insert.test a17b7f7017097afb2727aa5b67ceeb7ab0a120a1
|
||||
F test/insert2.test c288375a64dad3295044714f0dfed4a193cf067f
|
||||
F test/interrupt.test 9142ce4448605127640eda5e283952f75f67ed91
|
||||
F test/interrupt.test 0d50985f1aa6c39fe2cca4cf4a272c79ff1648e8
|
||||
F test/intpkey.test 9320af48415c594afd4e15f8ef0daa272e05502e
|
||||
F test/ioerr.test 5dbaf09f96b56ee01cf3edd762b96eb4ad2c9ca4
|
||||
F test/join.test 9ef6aabaac9de51d5fc41e68d1f4355da05a84cd
|
||||
F test/join2.test c97e4c5aa65dea462145529e58212a709b4722b8
|
||||
F test/join3_28.test dbfbca6e102d30205e7c1854b0d4fdfcd04de938
|
||||
F test/join4_28.test aa3dba47dcc9c835ac505111ff3d925f0657ef15
|
||||
F test/lastinsert.test 31382f88b9b0270333ac9e4a17f2c2f4732da718
|
||||
F test/laststmtchanges.test cabd11bdfbaf73a4486c50b58297d9c2038ccc18
|
||||
F test/limit.test e28ce938ddacefdff860d082be45e1e5e2801441
|
||||
F test/limit.test c6365450f3180170c0fa1b0bf1ae48522c33b731
|
||||
F test/lock.test 226ef831dad60ad4d200dc83e25479ba952aac7e
|
||||
F test/main.test 6a851b5992c4881a725a3d9647e629199df8de9d
|
||||
F test/malloc.test 2cfcffb7c858640e01e6520ee1cd54ca57d98e80
|
||||
F test/memdb.test 6ece25c7c0e6500199d3662607a3edca081abb2a
|
||||
F test/memleak.test 4d5d374c8ea1fc5ac634aed58cac1047848ce65e
|
||||
F test/minmax.test 9dcf52f713b1b9e61d0a88a51eb8bb2e3c52d0ab
|
||||
F test/minmax.test 9dc011a23b897718004b38f4f99e0171f9d5a3fe
|
||||
F test/misc1.test 0b98d493b0cf55cb5f53e1f3df8107c166eecb5a
|
||||
F test/misc2.test 10c2ce26407d37411b96273e552d5095393732be
|
||||
F test/misc3.test 3b5e369514a3ba3f919fb7eafa7d027440b5079e
|
||||
F test/misuse.test 1095f26d1aed406c65e1d2eba651c4bb7c38cbff
|
||||
F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0
|
||||
F test/null.test c14d0f4739f21e929b8115b72bf0c765b6bb1721
|
||||
F test/null.test 675e6823d72d4866d2aca6bf5b7259c9cd713703
|
||||
F test/pager.test 331519008889d45f6df6697395e5bce6ee602fd9
|
||||
F test/pragma.test 24a3f7a697b45cb90d664ebce5566bec7ac41571
|
||||
F test/printf.test 46b3d07d59d871d0831b4a657f6dfcafe0574850
|
||||
@@ -121,7 +123,7 @@ F test/progress.test 701b6115c2613128ececdfe1398a1bd0e1a4cfb3 x
|
||||
F test/quick.test 5a6bccf5c02f16841a79fbac7409a02138880c10
|
||||
F test/quote.test 08f23385c685d3dc7914ec760d492cacea7f6e3d
|
||||
F test/rowid.test 77f7e8c7ca626a15ff91a536595b695cfce7c845
|
||||
F test/select1.test 0d708cec567104653ec9aa49fecf3444a2e7d150
|
||||
F test/select1.test 1eab1f8aa85b8d4e3474c0769fb81313548929ab
|
||||
F test/select2.test aceea74fd895b9d007512f72499db589735bd8e4
|
||||
F test/select3.test 445a1a3dde4e2fd32541b311f55da5e2f8079d76
|
||||
F test/select4.test e7e9a32fa745246cb99fadbeb63af4843a17925b
|
||||
@@ -131,14 +133,14 @@ F test/sort.test ba07b107c16070208e6aab3cadea66ba079d85ba
|
||||
F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f
|
||||
F test/table.test 371a1fc1c470982b2f68f9732f903a5d96f949c4
|
||||
F test/tableapi.test e0c4cce61e58343caa84dab33fa6823cb35fe1e1
|
||||
F test/tclsqlite.test a684fc191b81e6cded8a81263663d5a130fbb013
|
||||
F test/tclsqlite.test 0089f84fc4f007d0d396f4d0c231d4c6dd99a48b
|
||||
F test/temptable.test a770ba6308d7f7332fce985086b8e06bed6430c2
|
||||
F test/tester.tcl 2f1d43df1311c9dc06acaa7a82e87bfea85dea5f
|
||||
F test/thread1.test 53f050d5be6932d9430df7756edd379366508ff6
|
||||
F test/threadtest1.c f7f896e62ed46feae1dc411114a48c15a0f82ee2
|
||||
F test/threadtest2.c d94ca4114fd1504f7e0ae724bcd83d4b40931d86
|
||||
F test/trans.test 0cb8256daff1ae0da75321e00125338c6681158d
|
||||
F test/trigger1.test 4538c1c7d6bbca5dfe619ea6e1682b07ece95b21
|
||||
F test/trigger1.test d2d38d8a81a2c4a033b27965aaf28a0b7aa99f31
|
||||
F test/trigger2.test 0767ab30cb5a2c8402c8524f3d566b410b6f5263
|
||||
F test/trigger3.test a95ccace88291449f5eae7139ec438a42f90654d
|
||||
F test/trigger4.test 542afce45774e8f8e1130b96b8675f414d6e4bd8
|
||||
@@ -146,10 +148,10 @@ F test/unique.test 0e38d4cc7affeef2527720d1dafd1f6870f02f2b
|
||||
F test/update.test b29bd9061a1150426dab6959806fcc73a41b1217
|
||||
F test/vacuum.test a2a44544df719666efb51afbfeb6062fd59a672a
|
||||
F test/version.test 92adee5d98cf6e3eb0d1cf5186952e8114931bf6
|
||||
F test/view.test 1ee12c6f8f4791a2c0655120d5562a49400cfe53
|
||||
F test/view.test ac151928890d17716d5c1f7acc5924af61a7dacf
|
||||
F test/where.test cb3a2ed062ce4b5f08aff2d08027c6a46d68c47b
|
||||
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
|
||||
F tool/lemon.c 38a39c623df325bcbd67152d6f92e09edbee8b83
|
||||
F tool/lemon.c db6a3bfaf3388c0f7aea3adb5e05acddcd427016
|
||||
F tool/lempar.c 0b5e7a58634e0d448929b8e85f7981c2aa708d57
|
||||
F tool/memleak.awk b744b6109566206c746d826f6ecdba34662216bc
|
||||
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
|
||||
@@ -159,6 +161,7 @@ F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
|
||||
F tool/showdb.c 3559eac5a3b46e9b558d50856946b25e77633236
|
||||
F tool/showjournal.c ec3b171be148656827c4949fbfb8ab4370822f87
|
||||
F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b
|
||||
F tool/spaceanal.tcl fec9907072011cd2b8b956fe7322cf6c50429ba9
|
||||
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
|
||||
@@ -188,7 +191,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
||||
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||
P 1e84f70fb98755651e0c04dc2cf0114e2e6fe39c
|
||||
R 49661129e558c10c6a80ceab2ff48aff
|
||||
P e6a18741a47a4288fa9c4fef93443b19aff20fb9
|
||||
R 9093355d0bd0fe007078e08b28b0c272
|
||||
U drh
|
||||
Z 3af77926e38ece4579fe3c33c425d46c
|
||||
Z 0fe8caf53c43ccf6073cf4d684d73e3a
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
7ace576215367101904677bd69951755ee9cb1a1
|
||||
47fee16ba9bd8ab2820fe97e89480528114825cd
|
||||
+32
-40
@@ -11,42 +11,49 @@
|
||||
#
|
||||
srcdir=`echo "$0" | sed 's%\(^.*\)/[^/][^/]*$%\1%'`
|
||||
|
||||
# Get the makefile.
|
||||
# Clear out the build directory "doc"
|
||||
#
|
||||
cp $srcdir/Makefile.linux-gcc ./Makefile
|
||||
chmod +x $srcdir/install-sh
|
||||
#rm -rf doc
|
||||
#make doc
|
||||
|
||||
# Start building stuff.
|
||||
# Get the current version number - needed to help build filenames
|
||||
#
|
||||
VERS=`cat $srcdir/VERSION`
|
||||
VERSW=`sed 's/\./_/g' $srcdir/VERSION`
|
||||
|
||||
# Start by building an sqlite shell for linux.
|
||||
#
|
||||
make clean
|
||||
make sqlite
|
||||
strip sqlite
|
||||
mv sqlite sqlite.bin
|
||||
mv sqlite sqlite-$VERS.bin
|
||||
rm -f sqlite.bin.gz
|
||||
gzip sqlite.bin
|
||||
gzip sqlite-$VERS.bin
|
||||
mv sqlite-$VERS.bin.gz doc
|
||||
|
||||
# Build the tclsqlite.so shared library for import into tclsh or wish
|
||||
# under Linux
|
||||
#
|
||||
make target_source
|
||||
rm sqlite_source.zip
|
||||
rm -f doc/sqlite-source-$VERSW.zip
|
||||
cd tsrc
|
||||
zip ../sqlite_source.zip *
|
||||
zip ../doc/sqlite-source-$VERSW.zip *
|
||||
rm shell.c
|
||||
TCLDIR=/home/drh/tcltk/8.2linux
|
||||
TCLSTUBLIB=$TCLDIR/libtclstub8.2g.a
|
||||
OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1'
|
||||
gcc -fPIC $OPTS -O2 -I. -I$TCLDIR -shared *.c $TCLSTUBLIB -o tclsqlite.so
|
||||
strip tclsqlite.so
|
||||
mv tclsqlite.so ..
|
||||
mv tclsqlite.so tclsqlite-$VERS.so
|
||||
gzip tclsqlite-$VERS.so
|
||||
mv tclsqlite-$VERS.so.gz ../doc
|
||||
rm tclsqlite.c
|
||||
gcc -fPIC -DNDEBUG=1 -O2 -I. -shared *.c -o sqlite.so
|
||||
strip sqlite.so
|
||||
mv sqlite.so ..
|
||||
mv sqlite.so sqlite-$VERS.so
|
||||
gzip sqlite-$VERS.so
|
||||
mv sqlite-$VERS.so.gz ../doc
|
||||
cd ..
|
||||
rm -f tclsqlite.so.gz sqlite.so.gz
|
||||
gzip tclsqlite.so
|
||||
gzip sqlite.so
|
||||
|
||||
# Build the tclsqlite.dll shared library that can be imported into tclsh
|
||||
# or wish on windows.
|
||||
@@ -76,7 +83,7 @@ i386-mingw32msvc-dllwrap \
|
||||
--target i386-mingw32 \
|
||||
-dllname tclsqlite.dll -lmsvcrt *.o $TCLSTUBLIB
|
||||
i386-mingw32msvc-strip tclsqlite.dll
|
||||
mv tclsqlite.dll ..
|
||||
#mv tclsqlite.dll ../tclsqlite-$VERSW.dll
|
||||
rm tclsqlite.o
|
||||
cat >sqlite.def <<\END_OF_FILE
|
||||
EXPORTS
|
||||
@@ -133,11 +140,9 @@ i386-mingw32msvc-dllwrap \
|
||||
--target i386-mingw32 \
|
||||
-dllname sqlite.dll -lmsvcrt *.o
|
||||
i386-mingw32msvc-strip sqlite.dll
|
||||
mv sqlite.dll sqlite.def ..
|
||||
zip ../doc/tclsqlite-$VERSW.zip tclsqlite.dll
|
||||
zip ../doc/sqlitedll-$VERSW.zip sqlite.dll sqlite.def
|
||||
cd ..
|
||||
rm -f tclsqlite.zip sqlitedll.zip
|
||||
zip tclsqlite.zip tclsqlite.dll
|
||||
zip sqlitedll.zip sqlite.dll sqlite.def
|
||||
|
||||
# Build the sqlite.exe executable for windows.
|
||||
#
|
||||
@@ -146,22 +151,19 @@ cd tsrc
|
||||
rm tclsqlite.c
|
||||
OPTS='-DSTATIC_BUILD=1 -DNDEBUG=1'
|
||||
i386-mingw32msvc-gcc -O2 $OPTS -I. -I$TCLDIR *.c -o sqlite.exe
|
||||
mv sqlite.exe ..
|
||||
zip ../doc/sqlite-$VERSW.zip sqlite.exe
|
||||
cd ..
|
||||
rm -f sqlite.zip
|
||||
zip sqlite.zip sqlite.exe
|
||||
|
||||
# Construct a tarball of the source tree
|
||||
#
|
||||
ORIGIN=`pwd`
|
||||
cd $srcdir
|
||||
cd ..
|
||||
EXCLUDE=`find sqlite -print | grep CVS | sed 's,sqlite/, --exclude sqlite/,'`
|
||||
tar czf $ORIGIN/sqlite.tar.gz $EXCLUDE sqlite
|
||||
mv sqlite_v2 sqlite-$VERS
|
||||
EXCLUDE=`find sqlite-$VERS -print | grep CVS | sed 's,^, --exclude ,'`
|
||||
tar czf $ORIGIN/doc/sqlite-$VERS.tar.gz $EXCLUDE sqlite-$VERS
|
||||
mv sqlite-$VERS sqlite_v2
|
||||
cd $ORIGIN
|
||||
vers=`cat $srcdir/VERSION`
|
||||
rm -f sqlite-$vers.tar.gz
|
||||
ln sqlite.tar.gz sqlite-$vers.tar.gz
|
||||
|
||||
#
|
||||
# Build RPMS (binary) and Source RPM
|
||||
@@ -179,24 +181,14 @@ mkdir $HOME/rpm/SRPMS
|
||||
mkdir $HOME/rpm/SPECS
|
||||
|
||||
# create the spec file from the template
|
||||
sed s/SQLITE_VERSION/$vers/g $srcdir/spec.template > $HOME/rpm/SPECS/sqlite.spec
|
||||
sed s/SQLITE_VERSION/$VERS/g $srcdir/spec.template > $HOME/rpm/SPECS/sqlite.spec
|
||||
|
||||
# copy the source tarball to the rpm directory
|
||||
cp sqlite-$vers.tar.gz $HOME/rpm/SOURCES/.
|
||||
cp doc/sqlite-$VERS.tar.gz $HOME/rpm/SOURCES/.
|
||||
|
||||
# build all the rpms
|
||||
rpm -ba $HOME/rpm/SPECS/sqlite.spec >& rpm-$vers.log
|
||||
|
||||
# copy the RPMs into the build directory.
|
||||
ln $HOME/rpm/RPMS/i386/sqlite*-$vers*.rpm .
|
||||
ln $HOME/rpm/SRPMS/sqlite-$vers*.rpm .
|
||||
|
||||
|
||||
# Build the website
|
||||
#
|
||||
cp $srcdir/../historical/* .
|
||||
rm -rf doc
|
||||
make doc
|
||||
ln sqlite.bin.gz sqlite.zip sqlite*.tar.gz tclsqlite.so.gz tclsqlite.zip doc
|
||||
ln sqlitedll.zip sqlite.so.gz sqlite_source.zip doc
|
||||
ln *.rpm doc
|
||||
mv $HOME/rpm/RPMS/i386/sqlite*-$VERS*.rpm doc
|
||||
mv $HOME/rpm/SRPMS/sqlite-$VERS*.rpm doc
|
||||
|
||||
+10
-7
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file contains code used to implement the ATTACH and DETACH commands.
|
||||
**
|
||||
** $Id: attach.c,v 1.10 2004/02/12 18:46:39 drh Exp $
|
||||
** $Id: attach.c,v 1.10.2.1 2004/05/07 01:46:01 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -137,15 +137,17 @@ void sqliteDetach(Parse *pParse, Token *pDbname){
|
||||
int i;
|
||||
sqlite *db;
|
||||
Vdbe *v;
|
||||
Db *pDb;
|
||||
|
||||
v = sqliteGetVdbe(pParse);
|
||||
sqliteVdbeAddOp(v, OP_Halt, 0, 0);
|
||||
if( pParse->explain ) return;
|
||||
db = pParse->db;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( db->aDb[i].pBt==0 || db->aDb[i].zName==0 ) continue;
|
||||
if( strlen(db->aDb[i].zName)!=pDbname->n ) continue;
|
||||
if( sqliteStrNICmp(db->aDb[i].zName, pDbname->z, pDbname->n)==0 ) break;
|
||||
pDb = &db->aDb[i];
|
||||
if( pDb->pBt==0 || pDb->zName==0 ) continue;
|
||||
if( strlen(pDb->zName)!=pDbname->n ) continue;
|
||||
if( sqliteStrNICmp(pDb->zName, pDbname->z, pDbname->n)==0 ) break;
|
||||
}
|
||||
if( i>=db->nDb ){
|
||||
sqliteErrorMsg(pParse, "no such database: %T", pDbname);
|
||||
@@ -160,10 +162,11 @@ void sqliteDetach(Parse *pParse, Token *pDbname){
|
||||
return;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_AUTHORIZATION */
|
||||
sqliteBtreeClose(db->aDb[i].pBt);
|
||||
db->aDb[i].pBt = 0;
|
||||
sqliteFree(db->aDb[i].zName);
|
||||
sqliteBtreeClose(pDb->pBt);
|
||||
pDb->pBt = 0;
|
||||
sqliteFree(pDb->zName);
|
||||
sqliteResetInternalSchema(db, i);
|
||||
if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
|
||||
db->nDb--;
|
||||
if( i<db->nDb ){
|
||||
db->aDb[i] = db->aDb[db->nDb];
|
||||
|
||||
+6
-6
@@ -14,7 +14,7 @@
|
||||
** systems that do not need this facility may omit it by recompiling
|
||||
** the library with -DSQLITE_OMIT_AUTHORIZATION=1
|
||||
**
|
||||
** $Id: auth.c,v 1.12 2004/02/22 18:40:57 drh Exp $
|
||||
** $Id: auth.c,v 1.12.2.2 2004/09/09 13:54:30 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -111,6 +111,7 @@ void sqliteAuthRead(
|
||||
const char *zCol; /* Name of the column of the table */
|
||||
int iSrc; /* Index in pTabList->a[] of table being read */
|
||||
const char *zDBase; /* Name of database being accessed */
|
||||
TriggerStack *pStack; /* The stack of current triggers */
|
||||
|
||||
if( db->xAuth==0 ) return;
|
||||
assert( pExpr->op==TK_COLUMN );
|
||||
@@ -119,15 +120,14 @@ void sqliteAuthRead(
|
||||
}
|
||||
if( iSrc>=0 && iSrc<pTabList->nSrc ){
|
||||
pTab = pTabList->a[iSrc].pTab;
|
||||
}else{
|
||||
}else if( (pStack = pParse->trigStack)!=0 ){
|
||||
/* This must be an attempt to read the NEW or OLD pseudo-tables
|
||||
** of a trigger.
|
||||
*/
|
||||
TriggerStack *pStack; /* The stack of current triggers */
|
||||
pStack = pParse->trigStack;
|
||||
assert( pStack!=0 );
|
||||
assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
|
||||
pTab = pStack->pTab;
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
if( pTab==0 ) return;
|
||||
if( pExpr->iColumn>=0 ){
|
||||
@@ -174,7 +174,7 @@ int sqliteAuthCheck(
|
||||
sqlite *db = pParse->db;
|
||||
int rc;
|
||||
|
||||
if( db->xAuth==0 ){
|
||||
if( db->init.busy || db->xAuth==0 ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree_rb.c,v 1.24 2004/02/29 00:11:31 drh Exp $
|
||||
** $Id: btree_rb.c,v 1.24.2.1 2004/06/26 14:40:05 drh Exp $
|
||||
**
|
||||
** This file implements an in-core database using Red-Black balanced
|
||||
** binary trees.
|
||||
@@ -311,7 +311,7 @@ static char *append_node(char * orig, BtRbNode *pNode, int indent)
|
||||
static void print_node(BtRbNode *pNode)
|
||||
{
|
||||
char * str = append_node(0, pNode, 0);
|
||||
printf(str);
|
||||
printf("%s", str);
|
||||
|
||||
/* Suppress a warning message about print_node() being unused */
|
||||
(void)print_node;
|
||||
|
||||
+4
-4
@@ -23,7 +23,7 @@
|
||||
** ROLLBACK
|
||||
** PRAGMA
|
||||
**
|
||||
** $Id: build.c,v 1.176 2004/04/23 17:04:44 drh Exp $
|
||||
** $Id: build.c,v 1.176.2.3 2004/08/28 14:53:34 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -1034,7 +1034,7 @@ void sqliteCreateView(
|
||||
sEnd.z += sEnd.n;
|
||||
}
|
||||
sEnd.n = 0;
|
||||
n = ((int)sEnd.z) - (int)pBegin->z;
|
||||
n = sEnd.z - pBegin->z;
|
||||
z = pBegin->z;
|
||||
while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; }
|
||||
sEnd.z = &z[n-1];
|
||||
@@ -1537,7 +1537,7 @@ void sqliteCreateIndex(
|
||||
if( pName && !db->init.busy ){
|
||||
Index *pISameName; /* Another index with the same name */
|
||||
Table *pTSameName; /* A table with same name as the index */
|
||||
zName = sqliteStrNDup(pName->z, pName->n);
|
||||
zName = sqliteTableNameFromToken(pName);
|
||||
if( zName==0 ) goto exit_create_index;
|
||||
if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
|
||||
sqliteErrorMsg(pParse, "index %s already exists", zName);
|
||||
@@ -1557,7 +1557,7 @@ void sqliteCreateIndex(
|
||||
sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0);
|
||||
if( zName==0 ) goto exit_create_index;
|
||||
}else{
|
||||
zName = sqliteStrNDup(pName->z, pName->n);
|
||||
zName = sqliteTableNameFromToken(pName);
|
||||
}
|
||||
|
||||
/* Check for authorization to create an index.
|
||||
|
||||
+10
-8
@@ -16,7 +16,7 @@
|
||||
** sqliteRegisterDateTimeFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
**
|
||||
** $Id: date.c,v 1.16 2004/02/29 01:08:18 drh Exp $
|
||||
** $Id: date.c,v 1.16.2.4 2007/01/08 16:20:29 drh Exp $
|
||||
**
|
||||
** NOTES:
|
||||
**
|
||||
@@ -800,18 +800,20 @@ static void strftimeFunc(sqlite_func *context, int argc, const char **argv){
|
||||
case 'H': sprintf(&z[j],"%02d",x.h); j+=2; break;
|
||||
case 'W': /* Fall thru */
|
||||
case 'j': {
|
||||
int n;
|
||||
int n; /* Number of days since 1st day of year */
|
||||
DateTime y = x;
|
||||
y.validJD = 0;
|
||||
y.M = 1;
|
||||
y.D = 1;
|
||||
computeJD(&y);
|
||||
n = x.rJD - y.rJD + 1;
|
||||
n = x.rJD - y.rJD + 0.5;
|
||||
if( zFmt[i]=='W' ){
|
||||
sprintf(&z[j],"%02d",(n+6)/7);
|
||||
int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
|
||||
wd = ((int)(x.rJD+0.5)) % 7;
|
||||
sprintf(&z[j],"%02d",(n+7-wd)/7);
|
||||
j += 2;
|
||||
}else{
|
||||
sprintf(&z[j],"%03d",n);
|
||||
sprintf(&z[j],"%03d",n+1);
|
||||
j += 3;
|
||||
}
|
||||
break;
|
||||
@@ -824,7 +826,7 @@ static void strftimeFunc(sqlite_func *context, int argc, const char **argv){
|
||||
j += strlen(&z[j]);
|
||||
break;
|
||||
}
|
||||
case 'S': sprintf(&z[j],"%02d",(int)(x.s+0.5)); j+=2; break;
|
||||
case 'S': sprintf(&z[j],"%02d",(int)x.s); j+=2; break;
|
||||
case 'w': z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break;
|
||||
case 'Y': sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break;
|
||||
case '%': z[j++] = '%'; break;
|
||||
@@ -847,19 +849,18 @@ static void strftimeFunc(sqlite_func *context, int argc, const char **argv){
|
||||
** external linkage.
|
||||
*/
|
||||
void sqliteRegisterDateTimeFunctions(sqlite *db){
|
||||
#ifndef SQLITE_OMIT_DATETIME_FUNCS
|
||||
static struct {
|
||||
char *zName;
|
||||
int nArg;
|
||||
int dataType;
|
||||
void (*xFunc)(sqlite_func*,int,const char**);
|
||||
} aFuncs[] = {
|
||||
#ifndef SQLITE_OMIT_DATETIME_FUNCS
|
||||
{ "julianday", -1, SQLITE_NUMERIC, juliandayFunc },
|
||||
{ "date", -1, SQLITE_TEXT, dateFunc },
|
||||
{ "time", -1, SQLITE_TEXT, timeFunc },
|
||||
{ "datetime", -1, SQLITE_TEXT, datetimeFunc },
|
||||
{ "strftime", -1, SQLITE_TEXT, strftimeFunc },
|
||||
#endif
|
||||
};
|
||||
int i;
|
||||
|
||||
@@ -870,4 +871,5 @@ void sqliteRegisterDateTimeFunctions(sqlite *db){
|
||||
sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+6
-3
@@ -12,7 +12,7 @@
|
||||
** This file contains routines used for analyzing expressions and
|
||||
** for generating VDBE code that evaluates expressions in SQLite.
|
||||
**
|
||||
** $Id: expr.c,v 1.114 2004/04/23 17:04:45 drh Exp $
|
||||
** $Id: expr.c,v 1.114.2.4 2004/11/20 20:42:10 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -124,7 +124,7 @@ Expr *sqliteExprDup(Expr *p){
|
||||
if( pNew==0 ) return 0;
|
||||
memcpy(pNew, p, sizeof(*pNew));
|
||||
if( p->token.z!=0 ){
|
||||
pNew->token.z = sqliteStrDup(p->token.z);
|
||||
pNew->token.z = sqliteStrNDup(p->token.z, p->token.n);
|
||||
pNew->token.dyn = 1;
|
||||
}else{
|
||||
assert( pNew->token.z==0 );
|
||||
@@ -155,7 +155,10 @@ ExprList *sqliteExprListDup(ExprList *p){
|
||||
if( pNew==0 ) return 0;
|
||||
pNew->nExpr = pNew->nAlloc = p->nExpr;
|
||||
pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
|
||||
if( pItem==0 ) return 0; /* Leaks memory after a malloc failure */
|
||||
if( pItem==0 ){
|
||||
sqliteFree(pNew);
|
||||
return 0;
|
||||
}
|
||||
for(i=0; i<p->nExpr; i++, pItem++){
|
||||
Expr *pNewExpr, *pOldExpr;
|
||||
pItem->pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr);
|
||||
|
||||
+25
-13
@@ -16,7 +16,7 @@
|
||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
**
|
||||
** $Id: func.c,v 1.43 2004/02/25 22:51:06 rdc Exp $
|
||||
** $Id: func.c,v 1.43.2.3 2004/07/18 23:03:11 drh Exp $
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
@@ -157,20 +157,20 @@ static void roundFunc(sqlite_func *context, int argc, const char **argv){
|
||||
** Implementation of the upper() and lower() SQL functions.
|
||||
*/
|
||||
static void upperFunc(sqlite_func *context, int argc, const char **argv){
|
||||
char *z;
|
||||
unsigned char *z;
|
||||
int i;
|
||||
if( argc<1 || argv[0]==0 ) return;
|
||||
z = sqlite_set_result_string(context, argv[0], -1);
|
||||
z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
|
||||
if( z==0 ) return;
|
||||
for(i=0; z[i]; i++){
|
||||
if( islower(z[i]) ) z[i] = toupper(z[i]);
|
||||
}
|
||||
}
|
||||
static void lowerFunc(sqlite_func *context, int argc, const char **argv){
|
||||
char *z;
|
||||
unsigned char *z;
|
||||
int i;
|
||||
if( argc<1 || argv[0]==0 ) return;
|
||||
z = sqlite_set_result_string(context, argv[0], -1);
|
||||
z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
|
||||
if( z==0 ) return;
|
||||
for(i=0; z[i]; i++){
|
||||
if( isupper(z[i]) ) z[i] = tolower(z[i]);
|
||||
@@ -517,26 +517,28 @@ static void minmaxStep(sqlite_func *context, int argc, const char **argv){
|
||||
int mask; /* 0 for min() or 0xffffffff for max() */
|
||||
|
||||
assert( argc==2 );
|
||||
if( argv[0]==0 ) return; /* Ignore NULL values */
|
||||
if( argv[1][0]=='n' ){
|
||||
xCompare = sqliteCompare;
|
||||
}else{
|
||||
xCompare = strcmp;
|
||||
}
|
||||
mask = (int)sqlite_user_data(context);
|
||||
assert( mask==0 || mask==-1 );
|
||||
p = sqlite_aggregate_context(context, sizeof(*p));
|
||||
if( p==0 || argc<1 || argv[0]==0 ) return;
|
||||
if( p==0 || argc<1 ) return;
|
||||
if( p->z==0 || (xCompare(argv[0],p->z)^mask)<0 ){
|
||||
int len;
|
||||
if( !p->zBuf[0] ){
|
||||
if( p->zBuf[0] ){
|
||||
sqliteFree(p->z);
|
||||
}
|
||||
len = strlen(argv[0]);
|
||||
if( len < sizeof(p->zBuf)-1 ){
|
||||
p->z = &p->zBuf[1];
|
||||
p->zBuf[0] = 1;
|
||||
p->zBuf[0] = 0;
|
||||
}else{
|
||||
p->z = sqliteMalloc( len+1 );
|
||||
p->zBuf[0] = 0;
|
||||
p->zBuf[0] = 1;
|
||||
if( p->z==0 ) return;
|
||||
}
|
||||
strcpy(p->z, argv[0]);
|
||||
@@ -545,10 +547,10 @@ static void minmaxStep(sqlite_func *context, int argc, const char **argv){
|
||||
static void minMaxFinalize(sqlite_func *context){
|
||||
MinMaxCtx *p;
|
||||
p = sqlite_aggregate_context(context, sizeof(*p));
|
||||
if( p && p->z ){
|
||||
if( p && p->z && p->zBuf[0]<2 ){
|
||||
sqlite_set_result_string(context, p->z, strlen(p->z));
|
||||
}
|
||||
if( p && !p->zBuf[0] ){
|
||||
if( p && p->zBuf[0] ){
|
||||
sqliteFree(p->z);
|
||||
}
|
||||
}
|
||||
@@ -621,7 +623,12 @@ void sqliteRegisterBuiltinFunctions(sqlite *db){
|
||||
int i;
|
||||
|
||||
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
|
||||
void *pArg = aFuncs[i].argType==2 ? (void*)(-1) : db;
|
||||
void *pArg;
|
||||
switch( aFuncs[i].argType ){
|
||||
case 0: pArg = 0; break;
|
||||
case 1: pArg = db; break;
|
||||
case 2: pArg = (void*)(-1); break;
|
||||
}
|
||||
sqlite_create_function(db, aFuncs[i].zName,
|
||||
aFuncs[i].nArg, aFuncs[i].xFunc, pArg);
|
||||
if( aFuncs[i].xFunc ){
|
||||
@@ -629,7 +636,12 @@ void sqliteRegisterBuiltinFunctions(sqlite *db){
|
||||
}
|
||||
}
|
||||
for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
|
||||
void *pArg = aAggs[i].argType==2 ? (void*)(-1) : db;
|
||||
void *pArg;
|
||||
switch( aAggs[i].argType ){
|
||||
case 0: pArg = 0; break;
|
||||
case 1: pArg = db; break;
|
||||
case 2: pArg = (void*)(-1); break;
|
||||
}
|
||||
sqlite_create_aggregate(db, aAggs[i].zName,
|
||||
aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, pArg);
|
||||
sqlite_function_type(db, aAggs[i].zName, aAggs[i].dataType);
|
||||
|
||||
+68
-64
@@ -14,7 +14,7 @@
|
||||
** other files are for internal use by SQLite and should not be
|
||||
** accessed by users of the library.
|
||||
**
|
||||
** $Id: main.c,v 1.164 2004/04/23 17:04:45 drh Exp $
|
||||
** $Id: main.c,v 1.164.2.2 2004/06/26 14:40:05 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -189,10 +189,13 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
|
||||
BtCursor *curMain;
|
||||
int size;
|
||||
Table *pTab;
|
||||
char *azArg[6];
|
||||
char const *azArg[6];
|
||||
char zDbNum[30];
|
||||
int meta[SQLITE_N_BTREE_META];
|
||||
InitData initData;
|
||||
char const *zMasterSchema;
|
||||
char const *zMasterName;
|
||||
char *zSql = 0;
|
||||
|
||||
/*
|
||||
** The master database table has a structure like this
|
||||
@@ -216,62 +219,38 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
|
||||
")"
|
||||
;
|
||||
|
||||
/* The following SQL will read the schema from the master tables.
|
||||
** The first version works with SQLite file formats 2 or greater.
|
||||
** The second version is for format 1 files.
|
||||
**
|
||||
** Beginning with file format 2, the rowid for new table entries
|
||||
** (including entries in sqlite_master) is an increasing integer.
|
||||
** So for file format 2 and later, we can play back sqlite_master
|
||||
** and all the CREATE statements will appear in the right order.
|
||||
** But with file format 1, table entries were random and so we
|
||||
** have to make sure the CREATE TABLEs occur before their corresponding
|
||||
** CREATE INDEXs. (We don't have to deal with CREATE VIEW or
|
||||
** CREATE TRIGGER in file format 1 because those constructs did
|
||||
** not exist then.)
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
|
||||
/* zMasterSchema and zInitScript are set to point at the master schema
|
||||
** and initialisation script appropriate for the database being
|
||||
** initialised. zMasterName is the name of the master table.
|
||||
*/
|
||||
static char init_script[] =
|
||||
"SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master "
|
||||
"UNION ALL "
|
||||
"SELECT type, name, rootpage, sql, 0 FROM sqlite_master";
|
||||
static char older_init_script[] =
|
||||
"SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master "
|
||||
"UNION ALL "
|
||||
"SELECT type, name, rootpage, sql, 0 FROM sqlite_master "
|
||||
"WHERE type='table' "
|
||||
"UNION ALL "
|
||||
"SELECT type, name, rootpage, sql, 0 FROM sqlite_master "
|
||||
"WHERE type='index'";
|
||||
if( iDb==1 ){
|
||||
zMasterSchema = temp_master_schema;
|
||||
zMasterName = TEMP_MASTER_NAME;
|
||||
}else{
|
||||
zMasterSchema = master_schema;
|
||||
zMasterName = MASTER_NAME;
|
||||
}
|
||||
|
||||
|
||||
assert( iDb>=0 && iDb!=1 && iDb<db->nDb );
|
||||
|
||||
/* Construct the schema tables: sqlite_master and sqlite_temp_master
|
||||
/* Construct the schema table.
|
||||
*/
|
||||
sqliteSafetyOff(db);
|
||||
azArg[0] = "table";
|
||||
azArg[1] = MASTER_NAME;
|
||||
azArg[1] = zMasterName;
|
||||
azArg[2] = "2";
|
||||
azArg[3] = master_schema;
|
||||
azArg[3] = zMasterSchema;
|
||||
sprintf(zDbNum, "%d", iDb);
|
||||
azArg[4] = zDbNum;
|
||||
azArg[5] = 0;
|
||||
initData.db = db;
|
||||
initData.pzErrMsg = pzErrMsg;
|
||||
sqliteInitCallback(&initData, 5, azArg, 0);
|
||||
pTab = sqliteFindTable(db, MASTER_NAME, "main");
|
||||
sqliteInitCallback(&initData, 5, (char **)azArg, 0);
|
||||
pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName);
|
||||
if( pTab ){
|
||||
pTab->readOnly = 1;
|
||||
}
|
||||
if( iDb==0 ){
|
||||
azArg[1] = TEMP_MASTER_NAME;
|
||||
azArg[3] = temp_master_schema;
|
||||
azArg[4] = "1";
|
||||
sqliteInitCallback(&initData, 5, azArg, 0);
|
||||
pTab = sqliteFindTable(db, TEMP_MASTER_NAME, "temp");
|
||||
if( pTab ){
|
||||
pTab->readOnly = 1;
|
||||
}
|
||||
}else{
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
sqliteSafetyOn(db);
|
||||
|
||||
@@ -320,7 +299,7 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
|
||||
sqliteSetString(pzErrMsg, "unsupported file format", (char*)0);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
}else if( db->file_format!=meta[2] || db->file_format<4 ){
|
||||
}else if( iDb!=1 && (db->file_format!=meta[2] || db->file_format<4) ){
|
||||
assert( db->file_format>=4 );
|
||||
if( meta[2]==0 ){
|
||||
sqliteSetString(pzErrMsg, "cannot attach empty database: ",
|
||||
@@ -340,18 +319,35 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
|
||||
*/
|
||||
assert( db->init.busy );
|
||||
sqliteSafetyOff(db);
|
||||
if( iDb==0 ){
|
||||
rc = sqlite_exec(db,
|
||||
db->file_format>=2 ? init_script : older_init_script,
|
||||
sqliteInitCallback, &initData, 0);
|
||||
}else{
|
||||
char *zSql = 0;
|
||||
|
||||
/* The following SQL will read the schema from the master tables.
|
||||
** The first version works with SQLite file formats 2 or greater.
|
||||
** The second version is for format 1 files.
|
||||
**
|
||||
** Beginning with file format 2, the rowid for new table entries
|
||||
** (including entries in sqlite_master) is an increasing integer.
|
||||
** So for file format 2 and later, we can play back sqlite_master
|
||||
** and all the CREATE statements will appear in the right order.
|
||||
** But with file format 1, table entries were random and so we
|
||||
** have to make sure the CREATE TABLEs occur before their corresponding
|
||||
** CREATE INDEXs. (We don't have to deal with CREATE VIEW or
|
||||
** CREATE TRIGGER in file format 1 because those constructs did
|
||||
** not exist then.)
|
||||
*/
|
||||
if( db->file_format>=2 ){
|
||||
sqliteSetString(&zSql,
|
||||
"SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
|
||||
db->aDb[iDb].zName, "\".sqlite_master", (char*)0);
|
||||
rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
|
||||
sqliteFree(zSql);
|
||||
"SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
|
||||
db->aDb[iDb].zName, "\".", zMasterName, (char*)0);
|
||||
}else{
|
||||
sqliteSetString(&zSql,
|
||||
"SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
|
||||
db->aDb[iDb].zName, "\".", zMasterName,
|
||||
" WHERE type IN ('table', 'index')"
|
||||
" ORDER BY CASE type WHEN 'table' THEN 0 ELSE 1 END", (char*)0);
|
||||
}
|
||||
rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
|
||||
|
||||
sqliteFree(zSql);
|
||||
sqliteSafetyOn(db);
|
||||
sqliteBtreeCloseCursor(curMain);
|
||||
if( sqlite_malloc_failed ){
|
||||
@@ -361,9 +357,6 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
DbSetProperty(db, iDb, DB_SchemaLoaded);
|
||||
if( iDb==0 ){
|
||||
DbSetProperty(db, 1, DB_SchemaLoaded);
|
||||
}
|
||||
}else{
|
||||
sqliteResetInternalSchema(db, iDb);
|
||||
}
|
||||
@@ -391,13 +384,24 @@ int sqliteInit(sqlite *db, char **pzErrMsg){
|
||||
rc = SQLITE_OK;
|
||||
db->init.busy = 1;
|
||||
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
|
||||
if( DbHasProperty(db, i, DB_SchemaLoaded) ) continue;
|
||||
assert( i!=1 ); /* Should have been initialized together with 0 */
|
||||
if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
|
||||
rc = sqliteInitOne(db, i, pzErrMsg);
|
||||
if( rc ){
|
||||
sqliteResetInternalSchema(db, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Once all the other databases have been initialised, load the schema
|
||||
** for the TEMP database. This is loaded last, as the TEMP database
|
||||
** schema may contain references to objects in other databases.
|
||||
*/
|
||||
if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
|
||||
rc = sqliteInitOne(db, 1, pzErrMsg);
|
||||
if( rc ){
|
||||
sqliteResetInternalSchema(db, 1);
|
||||
}
|
||||
}
|
||||
|
||||
db->init.busy = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
db->flags |= SQLITE_Initialized;
|
||||
@@ -869,7 +873,7 @@ static int sqliteDefaultBusyCallback(
|
||||
static const short int totals[] =
|
||||
{ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228, 287};
|
||||
# define NDELAY (sizeof(delays)/sizeof(delays[0]))
|
||||
int timeout = (int)Timeout;
|
||||
int timeout = (int)(long)Timeout;
|
||||
int delay, prior;
|
||||
|
||||
if( count <= NDELAY ){
|
||||
@@ -886,7 +890,7 @@ static int sqliteDefaultBusyCallback(
|
||||
sqliteOsSleep(delay);
|
||||
return 1;
|
||||
#else
|
||||
int timeout = (int)Timeout;
|
||||
int timeout = (int)(long)Timeout;
|
||||
if( (count+1)*1000 > timeout ){
|
||||
return 0;
|
||||
}
|
||||
@@ -939,7 +943,7 @@ void sqlite_progress_handler(
|
||||
*/
|
||||
void sqlite_busy_timeout(sqlite *db, int ms){
|
||||
if( ms>0 ){
|
||||
sqlite_busy_handler(db, sqliteDefaultBusyCallback, (void*)ms);
|
||||
sqlite_busy_handler(db, sqliteDefaultBusyCallback, (void*)(long)ms);
|
||||
}else{
|
||||
sqlite_busy_handler(db, 0, 0);
|
||||
}
|
||||
|
||||
@@ -464,6 +464,11 @@ int sqliteOsOpenReadWrite(
|
||||
id->dirfd = -1;
|
||||
id->fd = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644);
|
||||
if( id->fd<0 ){
|
||||
#ifdef EISDIR
|
||||
if( errno==EISDIR ){
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
#endif
|
||||
id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
|
||||
if( id->fd<0 ){
|
||||
return SQLITE_CANTOPEN;
|
||||
@@ -773,6 +778,13 @@ int sqliteOsOpenDirectory(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** If the following global variable points to a string which is the
|
||||
** name of a directory, then that directory will be used to store
|
||||
** temporary files.
|
||||
*/
|
||||
const char *sqlite_temp_directory = 0;
|
||||
|
||||
/*
|
||||
** Create a temporary file name in zBuf. zBuf must be big enough to
|
||||
** hold at least SQLITE_TEMPNAME_SIZE characters.
|
||||
@@ -780,6 +792,7 @@ int sqliteOsOpenDirectory(
|
||||
int sqliteOsTempFileName(char *zBuf){
|
||||
#if OS_UNIX
|
||||
static const char *azDirs[] = {
|
||||
0,
|
||||
"/var/tmp",
|
||||
"/usr/tmp",
|
||||
"/tmp",
|
||||
@@ -792,7 +805,9 @@ int sqliteOsTempFileName(char *zBuf){
|
||||
int i, j;
|
||||
struct stat buf;
|
||||
const char *zDir = ".";
|
||||
azDirs[0] = sqlite_temp_directory;
|
||||
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
|
||||
if( azDirs[i]==0 ) continue;
|
||||
if( stat(azDirs[i], &buf) ) continue;
|
||||
if( !S_ISDIR(buf.st_mode) ) continue;
|
||||
if( access(azDirs[i], 07) ) continue;
|
||||
@@ -815,12 +830,18 @@ int sqliteOsTempFileName(char *zBuf){
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
int i, j;
|
||||
const char *zDir;
|
||||
char zTempPath[SQLITE_TEMPNAME_SIZE];
|
||||
GetTempPath(SQLITE_TEMPNAME_SIZE-30, zTempPath);
|
||||
for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
|
||||
zTempPath[i] = 0;
|
||||
if( sqlite_temp_directory==0 ){
|
||||
GetTempPath(SQLITE_TEMPNAME_SIZE-30, zTempPath);
|
||||
for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
|
||||
zTempPath[i] = 0;
|
||||
zDir = zTempPath;
|
||||
}else{
|
||||
zDir = sqlite_temp_directory;
|
||||
}
|
||||
for(;;){
|
||||
sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath);
|
||||
sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zDir);
|
||||
j = strlen(zBuf);
|
||||
sqliteRandomness(15, &zBuf[j]);
|
||||
for(i=0; i<15; i++, j++){
|
||||
@@ -836,13 +857,16 @@ int sqliteOsTempFileName(char *zBuf){
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
int i, j;
|
||||
char *zDir;
|
||||
char zTempPath[SQLITE_TEMPNAME_SIZE];
|
||||
char zdirName[32];
|
||||
CInfoPBRec infoRec;
|
||||
Str31 dirName;
|
||||
memset(&infoRec, 0, sizeof(infoRec));
|
||||
memset(zTempPath, 0, SQLITE_TEMPNAME_SIZE);
|
||||
if( FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder,
|
||||
if( sqlite_temp_directory!=0 ){
|
||||
zDir = sqlite_temp_directory;
|
||||
}else if( FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder,
|
||||
&(infoRec.dirInfo.ioVRefNum), &(infoRec.dirInfo.ioDrParID)) == noErr ){
|
||||
infoRec.dirInfo.ioNamePtr = dirName;
|
||||
do{
|
||||
@@ -859,11 +883,14 @@ int sqliteOsTempFileName(char *zBuf){
|
||||
break;
|
||||
}
|
||||
} while( infoRec.dirInfo.ioDrDirID != fsRtDirID );
|
||||
zDir = zTempPath;
|
||||
}
|
||||
if( *zTempPath == 0 )
|
||||
if( zDir[0]==0 ){
|
||||
getcwd(zTempPath, SQLITE_TEMPNAME_SIZE-24);
|
||||
zDir = zTempPath;
|
||||
}
|
||||
for(;;){
|
||||
sprintf(zBuf, "%s"TEMP_FILE_PREFIX, zTempPath);
|
||||
sprintf(zBuf, "%s"TEMP_FILE_PREFIX, zDir);
|
||||
j = strlen(zBuf);
|
||||
sqliteRandomness(15, &zBuf[j]);
|
||||
for(i=0; i<15; i++, j++){
|
||||
@@ -1089,6 +1116,10 @@ int sqliteOsSeek(OsFile *id, off_t offset){
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SQLITE_NOSYNC
|
||||
# define fsync(X) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Make sure all writes to a particular file are committed to disk.
|
||||
**
|
||||
@@ -1747,6 +1778,7 @@ char *sqliteOsFullPathname(const char *zRelative){
|
||||
sqliteSetString(&zFull, zRelative, (char*)0);
|
||||
}else{
|
||||
char zBuf[5000];
|
||||
zBuf[0] = 0;
|
||||
sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative,
|
||||
(char*)0);
|
||||
}
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@
|
||||
** file simultaneously, or one process from reading the database while
|
||||
** another is writing.
|
||||
**
|
||||
** @(#) $Id: pager.c,v 1.101 2004/02/25 02:20:41 drh Exp $
|
||||
** @(#) $Id: pager.c,v 1.101.2.1 2005/12/19 17:37:10 drh Exp $
|
||||
*/
|
||||
#include "os.h" /* Must be first to enable large file support */
|
||||
#include "sqliteInt.h"
|
||||
@@ -1929,7 +1929,7 @@ void sqlitepager_dont_write(Pager *pPager, Pgno pgno){
|
||||
|
||||
pPg = pager_lookup(pPager, pgno);
|
||||
pPg->alwaysRollback = 1;
|
||||
if( pPg && pPg->dirty ){
|
||||
if( pPg && pPg->dirty && !pPager->ckptInUse ){
|
||||
if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
|
||||
/* If this pages is the last page in the file and the file has grown
|
||||
** during the current transaction, then do NOT mark the page as clean.
|
||||
|
||||
+6
-3
@@ -227,6 +227,7 @@ static int vxprintf(
|
||||
int nsd; /* Number of significant digits returned */
|
||||
#endif
|
||||
|
||||
func(arg,"",0);
|
||||
count = length = 0;
|
||||
bufpt = 0;
|
||||
for(; (c=(*fmt))!=0; ++fmt){
|
||||
@@ -673,9 +674,11 @@ static void mout(void *arg, const char *zNewText, int nNewChar){
|
||||
}
|
||||
}
|
||||
}
|
||||
if( pM->zText && nNewChar>0 ){
|
||||
memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
|
||||
pM->nChar += nNewChar;
|
||||
if( pM->zText ){
|
||||
if( nNewChar>0 ){
|
||||
memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
|
||||
pM->nChar += nNewChar;
|
||||
}
|
||||
pM->zText[pM->nChar] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
+50
-28
@@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle SELECT statements in SQLite.
|
||||
**
|
||||
** $Id: select.c,v 1.161 2004/03/13 14:00:36 drh Exp $
|
||||
** $Id: select.c,v 1.161.2.4 2004/07/20 01:45:49 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -364,6 +364,30 @@ void sqliteAddKeyType(Vdbe *v, ExprList *pEList){
|
||||
sqliteVdbeChangeP3(v, -1, zType, P3_DYNAMIC);
|
||||
}
|
||||
|
||||
/*
|
||||
** Add code to implement the OFFSET and LIMIT
|
||||
*/
|
||||
static void codeLimiter(
|
||||
Vdbe *v, /* Generate code into this VM */
|
||||
Select *p, /* The SELECT statement being coded */
|
||||
int iContinue, /* Jump here to skip the current record */
|
||||
int iBreak, /* Jump here to end the loop */
|
||||
int nPop /* Number of times to pop stack when jumping */
|
||||
){
|
||||
if( p->iOffset>=0 ){
|
||||
int addr = sqliteVdbeCurrentAddr(v) + 2;
|
||||
if( nPop>0 ) addr++;
|
||||
sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr);
|
||||
if( nPop>0 ){
|
||||
sqliteVdbeAddOp(v, OP_Pop, nPop, 0);
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
|
||||
}
|
||||
if( p->iLimit>=0 ){
|
||||
sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine generates the code for the inside of the inner loop
|
||||
** of a SELECT.
|
||||
@@ -388,6 +412,7 @@ static int selectInnerLoop(
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int i;
|
||||
int hasDistinct; /* True if the DISTINCT keyword is present */
|
||||
|
||||
if( v==0 ) return 0;
|
||||
assert( pEList!=0 );
|
||||
@@ -395,15 +420,9 @@ static int selectInnerLoop(
|
||||
/* If there was a LIMIT clause on the SELECT statement, then do the check
|
||||
** to see if this row should be output.
|
||||
*/
|
||||
if( pOrderBy==0 ){
|
||||
if( p->iOffset>=0 ){
|
||||
int addr = sqliteVdbeCurrentAddr(v);
|
||||
sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+2);
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
|
||||
}
|
||||
if( p->iLimit>=0 ){
|
||||
sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
|
||||
}
|
||||
hasDistinct = distinct>=0 && pEList && pEList->nExpr>0;
|
||||
if( pOrderBy==0 && !hasDistinct ){
|
||||
codeLimiter(v, p, iContinue, iBreak, 0);
|
||||
}
|
||||
|
||||
/* Pull the requested columns.
|
||||
@@ -423,7 +442,7 @@ static int selectInnerLoop(
|
||||
** and this row has been seen before, then do not make this row
|
||||
** part of the result.
|
||||
*/
|
||||
if( distinct>=0 && pEList && pEList->nExpr>0 ){
|
||||
if( hasDistinct ){
|
||||
#if NULL_ALWAYS_DISTINCT
|
||||
sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7);
|
||||
#endif
|
||||
@@ -434,6 +453,9 @@ static int selectInnerLoop(
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
|
||||
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||
sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0);
|
||||
if( pOrderBy==0 ){
|
||||
codeLimiter(v, p, iContinue, iBreak, nColumn);
|
||||
}
|
||||
}
|
||||
|
||||
switch( eDest ){
|
||||
@@ -570,14 +592,7 @@ static void generateSortTail(
|
||||
if( eDest==SRT_Sorter ) return;
|
||||
sqliteVdbeAddOp(v, OP_Sort, 0, 0);
|
||||
addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end1);
|
||||
if( p->iOffset>=0 ){
|
||||
sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+4);
|
||||
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
|
||||
}
|
||||
if( p->iLimit>=0 ){
|
||||
sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, end2);
|
||||
}
|
||||
codeLimiter(v, p, addr, end2, 1);
|
||||
switch( eDest ){
|
||||
case SRT_Callback: {
|
||||
sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0);
|
||||
@@ -810,8 +825,9 @@ Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
|
||||
}else{
|
||||
char zBuf[30];
|
||||
sprintf(zBuf, "column%d", i+1);
|
||||
pTab->aCol[i].zName = sqliteStrDup(zBuf);
|
||||
aCol[i].zName = sqliteStrDup(zBuf);
|
||||
}
|
||||
sqliteDequote(aCol[i].zName);
|
||||
}
|
||||
pTab->iPKey = -1;
|
||||
return pTab;
|
||||
@@ -943,11 +959,11 @@ static int fillInColumnList(Parse *pParse, Select *p){
|
||||
/* This expression is a "*" or a "TABLE.*" and needs to be
|
||||
** expanded. */
|
||||
int tableSeen = 0; /* Set to 1 when TABLE matches */
|
||||
Token *pName; /* text of name of TABLE */
|
||||
char *zTName; /* text of name of TABLE */
|
||||
if( pE->op==TK_DOT && pE->pLeft ){
|
||||
pName = &pE->pLeft->token;
|
||||
zTName = sqliteTableNameFromToken(&pE->pLeft->token);
|
||||
}else{
|
||||
pName = 0;
|
||||
zTName = 0;
|
||||
}
|
||||
for(i=0; i<pTabList->nSrc; i++){
|
||||
Table *pTab = pTabList->a[i].pTab;
|
||||
@@ -955,9 +971,8 @@ static int fillInColumnList(Parse *pParse, Select *p){
|
||||
if( zTabName==0 || zTabName[0]==0 ){
|
||||
zTabName = pTab->zName;
|
||||
}
|
||||
if( pName && (zTabName==0 || zTabName[0]==0 ||
|
||||
sqliteStrNICmp(pName->z, zTabName, pName->n)!=0 ||
|
||||
zTabName[pName->n]!=0) ){
|
||||
if( zTName && (zTabName==0 || zTabName[0]==0 ||
|
||||
sqliteStrICmp(zTName, zTabName)!=0) ){
|
||||
continue;
|
||||
}
|
||||
tableSeen = 1;
|
||||
@@ -1002,13 +1017,14 @@ static int fillInColumnList(Parse *pParse, Select *p){
|
||||
}
|
||||
}
|
||||
if( !tableSeen ){
|
||||
if( pName ){
|
||||
sqliteErrorMsg(pParse, "no such table: %T", pName);
|
||||
if( zTName ){
|
||||
sqliteErrorMsg(pParse, "no such table: %s", zTName);
|
||||
}else{
|
||||
sqliteErrorMsg(pParse, "no tables specified");
|
||||
}
|
||||
rc = 1;
|
||||
}
|
||||
sqliteFree(zTName);
|
||||
}
|
||||
}
|
||||
sqliteExprListDelete(pEList);
|
||||
@@ -1916,6 +1932,12 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
||||
}else{
|
||||
sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
|
||||
sqliteVdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, pIdx->zName, P3_STATIC);
|
||||
if( seekOp==OP_Rewind ){
|
||||
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||
sqliteVdbeAddOp(v, OP_MakeKey, 1, 0);
|
||||
sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
|
||||
seekOp = OP_MoveTo;
|
||||
}
|
||||
sqliteVdbeAddOp(v, seekOp, base+1, 0);
|
||||
sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0);
|
||||
sqliteVdbeAddOp(v, OP_Close, base+1, 0);
|
||||
|
||||
+3
-3
@@ -12,7 +12,7 @@
|
||||
** This file contains code to implement the "sqlite" command line
|
||||
** utility for accessing SQLite databases.
|
||||
**
|
||||
** $Id: shell.c,v 1.93 2004/03/17 23:42:13 drh Exp $
|
||||
** $Id: shell.c,v 1.93.2.1 2005/02/16 03:53:11 drh Exp $
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -591,7 +591,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
sqlite_exec(p->db,
|
||||
"SELECT name, type, sql FROM sqlite_master "
|
||||
"WHERE type!='meta' AND sql NOT NULL "
|
||||
"ORDER BY substr(type,2,1), name",
|
||||
"ORDER BY substr(type,2,1), rowid",
|
||||
dump_callback, p, &zErrMsg
|
||||
);
|
||||
}else{
|
||||
@@ -600,7 +600,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
sqlite_exec_printf(p->db,
|
||||
"SELECT name, type, sql FROM sqlite_master "
|
||||
"WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOT NULL "
|
||||
"ORDER BY substr(type,2,1), name",
|
||||
"ORDER BY substr(type,2,1), rowid",
|
||||
dump_callback, p, &zErrMsg, azArg[i]
|
||||
);
|
||||
}
|
||||
|
||||
+21
-3
@@ -12,7 +12,7 @@
|
||||
** This header file defines the interface that the SQLite library
|
||||
** presents to client programs.
|
||||
**
|
||||
** @(#) $Id: sqlite.h.in,v 1.60 2004/03/14 22:12:35 drh Exp $
|
||||
** @(#) $Id: sqlite.h.in,v 1.60.2.1 2004/10/06 15:52:36 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITE_H_
|
||||
#define _SQLITE_H_
|
||||
@@ -28,7 +28,11 @@ extern "C" {
|
||||
/*
|
||||
** The version of the SQLite library.
|
||||
*/
|
||||
#define SQLITE_VERSION "--VERS--"
|
||||
#ifdef SQLITE_VERSION
|
||||
# undef SQLITE_VERSION
|
||||
#else
|
||||
# define SQLITE_VERSION "--VERS--"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The version string is also compiled into the library so that a program
|
||||
@@ -479,9 +483,23 @@ int sqlite_function_type(
|
||||
int datatype /* The datatype for this function */
|
||||
);
|
||||
#define SQLITE_NUMERIC (-1)
|
||||
#define SQLITE_TEXT (-2)
|
||||
/* #define SQLITE_TEXT (-2) // See below */
|
||||
#define SQLITE_ARGS (-3)
|
||||
|
||||
/*
|
||||
** SQLite version 3 defines SQLITE_TEXT differently. To allow both
|
||||
** version 2 and version 3 to be included, undefine them both if a
|
||||
** conflict is seen. Define SQLITE2_TEXT to be the version 2 value.
|
||||
*/
|
||||
#ifdef SQLITE_TEXT
|
||||
# undef SQLITE_TEXT
|
||||
#else
|
||||
# define SQLITE_TEXT (-2)
|
||||
#endif
|
||||
#define SQLITE2_TEXT (-2)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** The user function implementations call one of the following four routines
|
||||
** in order to return their results. The first parameter to each of these
|
||||
|
||||
+8
-4
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.220 2004/02/25 13:47:33 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.220.2.2 2005/06/06 15:07:03 drh Exp $
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "sqlite.h"
|
||||
@@ -102,6 +102,9 @@
|
||||
#ifndef UINT16_TYPE
|
||||
# define UINT16_TYPE unsigned short int
|
||||
#endif
|
||||
#ifndef INT16_TYPE
|
||||
# define INT16_TYPE short int
|
||||
#endif
|
||||
#ifndef UINT8_TYPE
|
||||
# define UINT8_TYPE unsigned char
|
||||
#endif
|
||||
@@ -117,6 +120,7 @@
|
||||
#endif
|
||||
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
|
||||
typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
|
||||
typedef INT16_TYPE i16; /* 2-byte signed integer */
|
||||
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
|
||||
typedef UINT8_TYPE i8; /* 1-byte signed integer */
|
||||
typedef INTPTR_TYPE ptr; /* Big enough to hold a pointer */
|
||||
@@ -762,8 +766,8 @@ struct IdList {
|
||||
** now be identified by a database name, a dot, then the table name: ID.ID.
|
||||
*/
|
||||
struct SrcList {
|
||||
u16 nSrc; /* Number of tables or subqueries in the FROM clause */
|
||||
u16 nAlloc; /* Number of entries allocated in a[] below */
|
||||
i16 nSrc; /* Number of tables or subqueries in the FROM clause */
|
||||
i16 nAlloc; /* Number of entries allocated in a[] below */
|
||||
struct SrcList_item {
|
||||
char *zDatabase; /* Name of database holding this table */
|
||||
char *zName; /* Name of the table */
|
||||
@@ -1116,7 +1120,7 @@ void sqliteRealToSortable(double r, char *);
|
||||
#endif
|
||||
char *sqliteMPrintf(const char*, ...);
|
||||
char *sqliteVMPrintf(const char*, va_list);
|
||||
void sqliteSetString(char **, const char *, ...);
|
||||
void sqliteSetString(char **, ...);
|
||||
void sqliteSetNString(char **, ...);
|
||||
void sqliteErrorMsg(Parse*, const char*, ...);
|
||||
void sqliteDequote(char*);
|
||||
|
||||
+2
-2
@@ -31,7 +31,7 @@ typedef struct TabResult {
|
||||
int nAlloc;
|
||||
int nRow;
|
||||
int nColumn;
|
||||
int nData;
|
||||
long nData;
|
||||
int rc;
|
||||
} TabResult;
|
||||
|
||||
@@ -196,7 +196,7 @@ void sqlite_free_table(
|
||||
int i, n;
|
||||
azResult--;
|
||||
if( azResult==0 ) return;
|
||||
n = (int)azResult[0];
|
||||
n = (int)(long)azResult[0];
|
||||
for(i=1; i<n; i++){ if( azResult[i] ) free(azResult[i]); }
|
||||
free(azResult);
|
||||
}
|
||||
|
||||
+67
-12
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** A TCL Interface to SQLite
|
||||
**
|
||||
** $Id: tclsqlite.c,v 1.59 2004/02/25 22:51:06 rdc Exp $
|
||||
** $Id: tclsqlite.c,v 1.59.2.1 2004/06/19 11:57:40 drh Exp $
|
||||
*/
|
||||
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
|
||||
|
||||
@@ -1165,12 +1165,18 @@ int Et_AppInit(Tcl_Interp *interp){
|
||||
return Sqlite_Init(interp);
|
||||
}
|
||||
#endif
|
||||
/***************************************************************************
|
||||
** The remaining code is only included if the TCLSH macro is defined to
|
||||
** be an integer greater than 0
|
||||
*/
|
||||
#if defined(TCLSH) && TCLSH>0
|
||||
|
||||
/*
|
||||
** If the macro TCLSH is defined and is one, then put in code for the
|
||||
** "main" routine that will initialize Tcl.
|
||||
** "main" routine that implement a interactive shell into which the user
|
||||
** can type TCL commands.
|
||||
*/
|
||||
#if defined(TCLSH) && TCLSH==1
|
||||
#if TCLSH==1
|
||||
static char zMainloop[] =
|
||||
"set line {}\n"
|
||||
"while {![eof stdin]} {\n"
|
||||
@@ -1193,27 +1199,39 @@ static char zMainloop[] =
|
||||
"}\n"
|
||||
"}\n"
|
||||
;
|
||||
#endif /* TCLSH==1 */
|
||||
|
||||
#define TCLSH_MAIN main /* Needed to fake out mktclapp */
|
||||
int TCLSH_MAIN(int argc, char **argv){
|
||||
Tcl_Interp *interp;
|
||||
Tcl_FindExecutable(argv[0]);
|
||||
interp = Tcl_CreateInterp();
|
||||
int Libsqlite_Init( Tcl_Interp *interp) {
|
||||
#ifdef TCL_THREADS
|
||||
if (Thread_Init(interp) == TCL_ERROR) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
#endif
|
||||
Sqlite_Init(interp);
|
||||
#ifdef SQLITE_TEST
|
||||
{
|
||||
extern int Sqlitetest1_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest2_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest3_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest4_Init(Tcl_Interp*);
|
||||
extern int Md5_Init(Tcl_Interp*);
|
||||
Sqlitetest1_Init(interp);
|
||||
Sqlitetest2_Init(interp);
|
||||
Sqlitetest3_Init(interp);
|
||||
Sqlitetest4_Init(interp);
|
||||
Md5_Init(interp);
|
||||
Tcl_StaticPackage(interp, "sqlite", Libsqlite_Init, Libsqlite_Init);
|
||||
}
|
||||
#endif
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#define TCLSH_MAIN main /* Needed to fake out mktclapp */
|
||||
#if TCLSH==1
|
||||
int TCLSH_MAIN(int argc, char **argv){
|
||||
#ifndef TCL_THREADS
|
||||
Tcl_Interp *interp;
|
||||
Tcl_FindExecutable(argv[0]);
|
||||
interp = Tcl_CreateInterp();
|
||||
Libsqlite_Init(interp);
|
||||
if( argc>=2 ){
|
||||
int i;
|
||||
Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
|
||||
@@ -1226,13 +1244,50 @@ int TCLSH_MAIN(int argc, char **argv){
|
||||
const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
|
||||
if( zInfo==0 ) zInfo = interp->result;
|
||||
fprintf(stderr,"%s: %s\n", *argv, zInfo);
|
||||
return 1;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}else{
|
||||
Tcl_GlobalEval(interp, zMainloop);
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
Tcl_Main(argc, argv, Libsqlite_Init);
|
||||
#endif /* TCL_THREADS */
|
||||
return 0;
|
||||
}
|
||||
#endif /* TCLSH==1 */
|
||||
|
||||
|
||||
/*
|
||||
** If the macro TCLSH is set to 2, then implement a space analysis tool.
|
||||
*/
|
||||
#if TCLSH==2
|
||||
static char zAnalysis[] =
|
||||
#include "spaceanal_tcl.h"
|
||||
;
|
||||
|
||||
int main(int argc, char **argv){
|
||||
Tcl_Interp *interp;
|
||||
int i;
|
||||
Tcl_FindExecutable(argv[0]);
|
||||
interp = Tcl_CreateInterp();
|
||||
Libsqlite_Init(interp);
|
||||
Tcl_SetVar(interp,"argv0",argv[0],TCL_GLOBAL_ONLY);
|
||||
Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
|
||||
for(i=1; i<argc; i++){
|
||||
Tcl_SetVar(interp, "argv", argv[i],
|
||||
TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
|
||||
}
|
||||
if( Tcl_GlobalEval(interp, zAnalysis)!=TCL_OK ){
|
||||
const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
|
||||
if( zInfo==0 ) zInfo = interp->result;
|
||||
fprintf(stderr,"%s: %s\n", *argv, zInfo);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* TCLSH==2 */
|
||||
|
||||
#endif /* TCLSH */
|
||||
|
||||
#endif /* !defined(NO_TCL) */
|
||||
#endif /* NO_TCL */
|
||||
|
||||
+4
-1
@@ -13,7 +13,7 @@
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test1.c,v 1.36 2004/02/22 17:49:34 drh Exp $
|
||||
** $Id: test1.c,v 1.36.2.1 2004/05/07 00:57:06 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
@@ -975,6 +975,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
extern int sqlite_interrupt_count;
|
||||
extern int sqlite_open_file_count;
|
||||
extern int sqlite_current_time;
|
||||
extern int sqlite_temp_directory;
|
||||
static struct {
|
||||
char *zName;
|
||||
Tcl_CmdProc *xProc;
|
||||
@@ -1020,5 +1021,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
(char*)&sqlite_current_time, TCL_LINK_INT);
|
||||
Tcl_LinkVar(interp, "sqlite_static_bind_value",
|
||||
(char*)&sqlite_static_bind_value, TCL_LINK_STRING);
|
||||
Tcl_LinkVar(interp, "sqlite_temp_directory",
|
||||
(char*)&sqlite_temp_directory, TCL_LINK_STRING);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
+17
-10
@@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle UPDATE statements.
|
||||
**
|
||||
** $Id: update.c,v 1.70 2004/02/22 20:05:02 drh Exp $
|
||||
** $Id: update.c,v 1.70.2.1 2004/04/29 16:16:29 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -32,7 +32,8 @@ void sqliteUpdate(
|
||||
){
|
||||
int i, j; /* Loop counters */
|
||||
Table *pTab; /* The table to be updated */
|
||||
int addr; /* VDBE instruction address of the start of the loop */
|
||||
int loopStart; /* VDBE instruction address of the start of the loop */
|
||||
int jumpInst; /* Addr of VDBE instruction to jump out of loop */
|
||||
WhereInfo *pWInfo; /* Information about the WHERE clause */
|
||||
Vdbe *v; /* The virtual database engine */
|
||||
Index *pIdx; /* For looping over indices */
|
||||
@@ -49,6 +50,7 @@ void sqliteUpdate(
|
||||
Expr *pRecnoExpr; /* Expression defining the new record number */
|
||||
int openAll; /* True if all indices need to be opened */
|
||||
int isView; /* Trying to update a view */
|
||||
int iStackDepth; /* Index of memory cell holding stack depth */
|
||||
AuthContext sContext; /* The authorization context */
|
||||
|
||||
int before_triggers; /* True if there are any BEFORE triggers */
|
||||
@@ -62,6 +64,7 @@ void sqliteUpdate(
|
||||
if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
|
||||
db = pParse->db;
|
||||
assert( pTabList->nSrc==1 );
|
||||
iStackDepth = pParse->nMem++;
|
||||
|
||||
/* Locate the table which we want to update.
|
||||
*/
|
||||
@@ -248,7 +251,11 @@ void sqliteUpdate(
|
||||
/* The top of the update loop for when there are triggers.
|
||||
*/
|
||||
sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
|
||||
addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
|
||||
sqliteVdbeAddOp(v, OP_StackDepth, 0, 0);
|
||||
sqliteVdbeAddOp(v, OP_MemStore, iStackDepth, 1);
|
||||
loopStart = sqliteVdbeAddOp(v, OP_MemLoad, iStackDepth, 0);
|
||||
sqliteVdbeAddOp(v, OP_StackReset, 0, 0);
|
||||
jumpInst = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
|
||||
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
|
||||
|
||||
/* Open a cursor and make it point to the record that is
|
||||
@@ -295,7 +302,7 @@ void sqliteUpdate(
|
||||
/* Fire the BEFORE and INSTEAD OF triggers
|
||||
*/
|
||||
if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab,
|
||||
newIdx, oldIdx, onError, addr) ){
|
||||
newIdx, oldIdx, onError, loopStart) ){
|
||||
goto update_cleanup;
|
||||
}
|
||||
}
|
||||
@@ -336,10 +343,10 @@ void sqliteUpdate(
|
||||
*/
|
||||
if( !row_triggers_exist ){
|
||||
sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
|
||||
addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
|
||||
jumpInst = loopStart = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
|
||||
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_NotExists, iCur, addr);
|
||||
sqliteVdbeAddOp(v, OP_NotExists, iCur, loopStart);
|
||||
|
||||
/* If the record number will change, push the record number as it
|
||||
** will be after the update. (The old record number is currently
|
||||
@@ -368,7 +375,7 @@ void sqliteUpdate(
|
||||
/* Do constraint checks
|
||||
*/
|
||||
sqliteGenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1,
|
||||
onError, addr);
|
||||
onError, loopStart);
|
||||
|
||||
/* Delete the old indices for the current record.
|
||||
*/
|
||||
@@ -404,7 +411,7 @@ void sqliteUpdate(
|
||||
pParse->nTab = iCur;
|
||||
}
|
||||
if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab,
|
||||
newIdx, oldIdx, onError, addr) ){
|
||||
newIdx, oldIdx, onError, loopStart) ){
|
||||
goto update_cleanup;
|
||||
}
|
||||
}
|
||||
@@ -412,8 +419,8 @@ void sqliteUpdate(
|
||||
/* Repeat the above with the next record to be updated, until
|
||||
** all record selected by the WHERE clause have been updated.
|
||||
*/
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
|
||||
sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, loopStart);
|
||||
sqliteVdbeChangeP2(v, jumpInst, sqliteVdbeCurrentAddr(v));
|
||||
sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
|
||||
|
||||
/* Close all tables if there were no FOR EACH ROW triggers */
|
||||
|
||||
+8
-9
@@ -14,7 +14,7 @@
|
||||
** This file contains functions for allocating memory, comparing
|
||||
** strings, and stuff like that.
|
||||
**
|
||||
** $Id: util.c,v 1.74 2004/02/22 17:49:34 drh Exp $
|
||||
** $Id: util.c,v 1.74.2.2 2005/06/06 15:07:03 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <stdarg.h>
|
||||
@@ -330,15 +330,15 @@ char *sqliteStrNDup(const char *z, int n){
|
||||
** point to that string. The 1st argument must either be NULL or
|
||||
** point to memory obtained from sqliteMalloc().
|
||||
*/
|
||||
void sqliteSetString(char **pz, const char *zFirst, ...){
|
||||
void sqliteSetString(char **pz, ...){
|
||||
va_list ap;
|
||||
int nByte;
|
||||
const char *z;
|
||||
char *zResult;
|
||||
|
||||
if( pz==0 ) return;
|
||||
nByte = strlen(zFirst) + 1;
|
||||
va_start(ap, zFirst);
|
||||
nByte = 1;
|
||||
va_start(ap, pz);
|
||||
while( (z = va_arg(ap, const char*))!=0 ){
|
||||
nByte += strlen(z);
|
||||
}
|
||||
@@ -348,9 +348,8 @@ void sqliteSetString(char **pz, const char *zFirst, ...){
|
||||
if( zResult==0 ){
|
||||
return;
|
||||
}
|
||||
strcpy(zResult, zFirst);
|
||||
zResult += strlen(zResult);
|
||||
va_start(ap, zFirst);
|
||||
*zResult = 0;
|
||||
va_start(ap, pz);
|
||||
while( (z = va_arg(ap, const char*))!=0 ){
|
||||
strcpy(zResult, z);
|
||||
zResult += strlen(zResult);
|
||||
@@ -504,14 +503,14 @@ int sqliteStrICmp(const char *zLeft, const char *zRight){
|
||||
a = (unsigned char *)zLeft;
|
||||
b = (unsigned char *)zRight;
|
||||
while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
|
||||
return *a - *b;
|
||||
return UpperToLower[*a] - UpperToLower[*b];
|
||||
}
|
||||
int sqliteStrNICmp(const char *zLeft, const char *zRight, int N){
|
||||
register unsigned char *a, *b;
|
||||
a = (unsigned char *)zLeft;
|
||||
b = (unsigned char *)zRight;
|
||||
while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
|
||||
return N<0 ? 0 : *a - *b;
|
||||
return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+20
-35
@@ -14,7 +14,7 @@
|
||||
** Most of the code in this file may be omitted by defining the
|
||||
** SQLITE_OMIT_VACUUM macro.
|
||||
**
|
||||
** $Id: vacuum.c,v 1.13 2004/03/10 18:57:32 drh Exp $
|
||||
** $Id: vacuum.c,v 1.13.2.5 2005/02/14 00:25:48 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -163,24 +163,6 @@ static int vacuumCallback1(void *pArg, int argc, char **argv, char **NotUsed){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This callback is used to transfer PRAGMA settings from one database
|
||||
** to the other. The value in argv[0] should be passed to a pragma
|
||||
** identified by ((vacuumStruct*)pArg)->zPragma.
|
||||
*/
|
||||
static int vacuumCallback3(void *pArg, int argc, char **argv, char **NotUsed){
|
||||
vacuumStruct *p = (vacuumStruct*)pArg;
|
||||
char zBuf[200];
|
||||
assert( argc==1 );
|
||||
if( argv==0 ) return 0;
|
||||
assert( argv[0]!=0 );
|
||||
assert( strlen(p->zPragma)<100 );
|
||||
assert( strlen(argv[0])<30 );
|
||||
sprintf(zBuf,"PRAGMA %s=%s;", p->zPragma, argv[0]);
|
||||
p->rc = execsql(p->pzErrMsg, p->dbNew, zBuf);
|
||||
return p->rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate a random name of 20 character in length.
|
||||
*/
|
||||
@@ -226,19 +208,14 @@ int sqliteRunVacuum(char **pzErrMsg, sqlite *db){
|
||||
char *zErrMsg; /* Error message */
|
||||
vacuumStruct sVac; /* Information passed to callbacks */
|
||||
|
||||
/* These are all of the pragmas that need to be transferred over
|
||||
** to the new database */
|
||||
static const char *zPragma[] = {
|
||||
"default_synchronous",
|
||||
"default_cache_size",
|
||||
/* "default_temp_store", */
|
||||
};
|
||||
|
||||
if( db->flags & SQLITE_InTrans ){
|
||||
sqliteSetString(pzErrMsg, "cannot VACUUM from within a transaction",
|
||||
(char*)0);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
if( db->flags & SQLITE_Interrupt ){
|
||||
return SQLITE_INTERRUPT;
|
||||
}
|
||||
memset(&sVac, 0, sizeof(sVac));
|
||||
|
||||
/* Get the full pathname of the database file and create two
|
||||
@@ -280,13 +257,6 @@ int sqliteRunVacuum(char **pzErrMsg, sqlite *db){
|
||||
sVac.dbOld = db;
|
||||
sVac.dbNew = dbNew;
|
||||
sVac.pzErrMsg = pzErrMsg;
|
||||
for(i=0; rc==SQLITE_OK && i<sizeof(zPragma)/sizeof(zPragma[0]); i++){
|
||||
char zBuf[200];
|
||||
assert( strlen(zPragma[i])<100 );
|
||||
sprintf(zBuf, "PRAGMA %s;", zPragma[i]);
|
||||
sVac.zPragma = zPragma[i];
|
||||
rc = sqlite_exec(db, zBuf, vacuumCallback3, &sVac, &zErrMsg);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite_exec(db,
|
||||
"SELECT type, name, sql FROM sqlite_master "
|
||||
@@ -296,6 +266,17 @@ int sqliteRunVacuum(char **pzErrMsg, sqlite *db){
|
||||
"WHERE sql NOT NULL AND type=='view'",
|
||||
vacuumCallback1, &sVac, &zErrMsg);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
int meta1[SQLITE_N_BTREE_META];
|
||||
int meta2[SQLITE_N_BTREE_META];
|
||||
sqliteBtreeGetMeta(db->aDb[0].pBt, meta1);
|
||||
sqliteBtreeGetMeta(dbNew->aDb[0].pBt, meta2);
|
||||
meta2[1] = meta1[1]+1;
|
||||
meta2[3] = meta1[3];
|
||||
meta2[4] = meta1[4];
|
||||
meta2[6] = meta1[6];
|
||||
rc = sqliteBtreeUpdateMeta(dbNew->aDb[0].pBt, meta2);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqliteBtreeCopyFile(db->aDb[0].pBt, dbNew->aDb[0].pBt);
|
||||
sqlite_exec(db, "COMMIT", 0, 0, 0);
|
||||
@@ -308,13 +289,17 @@ end_of_vacuum:
|
||||
zErrMsg, (char*)0);
|
||||
}
|
||||
sqlite_exec(db, "ROLLBACK", 0, 0, 0);
|
||||
if( (dbNew && (dbNew->flags & SQLITE_Interrupt))
|
||||
|| (db->flags & SQLITE_Interrupt) ){
|
||||
rc = SQLITE_INTERRUPT;
|
||||
}
|
||||
if( dbNew ) sqlite_close(dbNew);
|
||||
sqliteOsDelete(zTemp);
|
||||
sqliteFree(zTemp);
|
||||
sqliteFree(sVac.s1.z);
|
||||
sqliteFree(sVac.s2.z);
|
||||
if( zErrMsg ) sqlite_freemem(zErrMsg);
|
||||
if( rc==SQLITE_ABORT ) sVac.rc = SQLITE_ERROR;
|
||||
if( rc==SQLITE_ABORT && sVac.rc!=SQLITE_INTERRUPT ) sVac.rc = SQLITE_ERROR;
|
||||
return sVac.rc;
|
||||
#endif
|
||||
}
|
||||
|
||||
+41
-7
@@ -43,7 +43,7 @@
|
||||
** in this file for details. If in doubt, do not deviate from existing
|
||||
** commenting and indentation practices when changing or adding code.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.268 2004/03/03 01:51:25 drh Exp $
|
||||
** $Id: vdbe.c,v 1.268.2.5 2006/10/24 11:26:44 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -62,7 +62,7 @@ int sqlite_search_count = 0;
|
||||
/*
|
||||
** When this global variable is positive, it gets decremented once before
|
||||
** each instruction in the VDBE. When reaches zero, the SQLITE_Interrupt
|
||||
** of the db.flags field is set in order to simulate and interrupt.
|
||||
** of the db.flags field is set in order to simulate an interrupt.
|
||||
**
|
||||
** This facility is used for testing purposes only. It does not function
|
||||
** in an ordinary build.
|
||||
@@ -2937,9 +2937,7 @@ case OP_PutStrKey: {
|
||||
if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
|
||||
if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
|
||||
if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
|
||||
if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
|
||||
pC->nextRowidValid = 0;
|
||||
}
|
||||
pC->nextRowidValid = 0;
|
||||
}
|
||||
if( pTos->flags & MEM_Null ){
|
||||
pTos->z = 0;
|
||||
@@ -4545,6 +4543,10 @@ case OP_AggGet: {
|
||||
pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
|
||||
pTos->flags |= MEM_Ephem;
|
||||
}
|
||||
if( pTos->flags & MEM_AggCtx ){
|
||||
Release(pTos);
|
||||
pTos->flags = MEM_Null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4695,8 +4697,9 @@ case OP_SetNext: {
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
assert( pSet->prev );
|
||||
pSet->prev = sqliteHashNext(pSet->prev);
|
||||
if( pSet->prev ){
|
||||
pSet->prev = sqliteHashNext(pSet->prev);
|
||||
}
|
||||
if( pSet->prev==0 ){
|
||||
break;
|
||||
}else{
|
||||
@@ -4723,6 +4726,36 @@ case OP_Vacuum: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: StackDepth * * *
|
||||
**
|
||||
** Push an integer onto the stack which is the depth of the stack prior
|
||||
** to that integer being pushed.
|
||||
*/
|
||||
case OP_StackDepth: {
|
||||
int depth = (&pTos[1]) - p->aStack;
|
||||
pTos++;
|
||||
pTos->i = depth;
|
||||
pTos->flags = MEM_Int;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: StackReset * * *
|
||||
**
|
||||
** Pop a single integer off of the stack. Then pop the stack
|
||||
** as many times as necessary to get the depth of the stack down
|
||||
** to the value of the integer that was popped.
|
||||
*/
|
||||
case OP_StackReset: {
|
||||
int depth, goal;
|
||||
assert( pTos>=p->aStack );
|
||||
Integerify(pTos);
|
||||
goal = pTos->i;
|
||||
depth = (&pTos[1]) - p->aStack;
|
||||
assert( goal<depth );
|
||||
popStack(&pTos, depth-goal);
|
||||
break;
|
||||
}
|
||||
|
||||
/* An other opcode is illegal...
|
||||
*/
|
||||
default: {
|
||||
@@ -4835,6 +4868,7 @@ default: {
|
||||
/* If we reach this point, it means that execution is finished.
|
||||
*/
|
||||
vdbe_halt:
|
||||
CHECK_FOR_INTERRUPT
|
||||
if( rc ){
|
||||
p->rc = rc;
|
||||
rc = SQLITE_ERROR;
|
||||
|
||||
+2
-2
@@ -511,7 +511,7 @@ void sqliteVdbePrintOp(FILE *pOut, int pc, Op *pOp){
|
||||
char *zP3;
|
||||
char zPtr[40];
|
||||
if( pOp->p3type==P3_POINTER ){
|
||||
sprintf(zPtr, "ptr(%#x)", (int)pOp->p3);
|
||||
sprintf(zPtr, "ptr(%#lx)", (long)pOp->p3);
|
||||
zP3 = zPtr;
|
||||
}else{
|
||||
zP3 = pOp->p3;
|
||||
@@ -565,7 +565,7 @@ int sqliteVdbeList(
|
||||
sprintf(p->zArgv[2],"%d", p->aOp[i].p1);
|
||||
sprintf(p->zArgv[3],"%d", p->aOp[i].p2);
|
||||
if( p->aOp[i].p3type==P3_POINTER ){
|
||||
sprintf(p->aStack[4].zShort, "ptr(%#x)", (int)p->aOp[i].p3);
|
||||
sprintf(p->aStack[4].zShort, "ptr(%#lx)", (long)p->aOp[i].p3);
|
||||
p->zArgv[4] = p->aStack[4].zShort;
|
||||
}else{
|
||||
p->zArgv[4] = p->aOp[i].p3;
|
||||
|
||||
+46
-15
@@ -12,7 +12,7 @@
|
||||
** This module contains C code that generates VDBE code used to process
|
||||
** the WHERE clause of SQL statements.
|
||||
**
|
||||
** $Id: where.c,v 1.89 2004/02/22 20:05:02 drh Exp $
|
||||
** $Id: where.c,v 1.89.2.2 2004/07/19 19:30:50 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -46,7 +46,7 @@ struct ExprInfo {
|
||||
typedef struct ExprMaskSet ExprMaskSet;
|
||||
struct ExprMaskSet {
|
||||
int n; /* Number of assigned cursor values */
|
||||
int ix[32]; /* Cursor assigned to each bit */
|
||||
int ix[31]; /* Cursor assigned to each bit */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -123,7 +123,9 @@ static int exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
|
||||
unsigned int mask = 0;
|
||||
if( p==0 ) return 0;
|
||||
if( p->op==TK_COLUMN ){
|
||||
return getMask(pMaskSet, p->iTable);
|
||||
mask = getMask(pMaskSet, p->iTable);
|
||||
if( mask==0 ) mask = -1;
|
||||
return mask;
|
||||
}
|
||||
if( p->pRight ){
|
||||
mask = exprTableUsage(pMaskSet, p->pRight);
|
||||
@@ -269,6 +271,35 @@ static Index *findSortingIndex(
|
||||
return pMatch;
|
||||
}
|
||||
|
||||
/*
|
||||
** Disable a term in the WHERE clause. Except, do not disable the term
|
||||
** if it controls a LEFT OUTER JOIN and it did not originate in the ON
|
||||
** or USING clause of that join.
|
||||
**
|
||||
** Consider the term t2.z='ok' in the following queries:
|
||||
**
|
||||
** (1) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok'
|
||||
** (2) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'
|
||||
** (3) SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'
|
||||
**
|
||||
** The t2.z='ok' is disabled in the in (2) because it did not originate
|
||||
** in the ON clause. The term is disabled in (3) because it is not part
|
||||
** of a LEFT OUTER JOIN. In (1), the term is not disabled.
|
||||
**
|
||||
** Disabling a term causes that term to not be tested in the inner loop
|
||||
** of the join. Disabling is an optimization. We would get the correct
|
||||
** results if nothing were ever disabled, but joins might run a little
|
||||
** slower. The trick is to disable as much as we can without disabling
|
||||
** too much. If we disabled in (1), we'd get the wrong answer.
|
||||
** See ticket #813.
|
||||
*/
|
||||
static void disableTerm(WhereLevel *pLevel, Expr **ppExpr){
|
||||
Expr *pExpr = *ppExpr;
|
||||
if( pLevel->iLeftJoin==0 || ExprHasProperty(pExpr, EP_FromJoin) ){
|
||||
*ppExpr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate the beginning of the loop used for WHERE clause processing.
|
||||
** The return value is a pointer to an (opaque) structure that contains
|
||||
@@ -736,7 +767,7 @@ WhereInfo *sqliteWhereBegin(
|
||||
}else{
|
||||
sqliteExprCode(pParse, aExpr[k].p->pLeft);
|
||||
}
|
||||
aExpr[k].p = 0;
|
||||
disableTerm(pLevel, &aExpr[k].p);
|
||||
cont = pLevel->cont = sqliteVdbeMakeLabel(v);
|
||||
sqliteVdbeAddOp(v, OP_MustBeInt, 1, brk);
|
||||
haveKey = 0;
|
||||
@@ -760,7 +791,7 @@ WhereInfo *sqliteWhereBegin(
|
||||
){
|
||||
if( pX->op==TK_EQ ){
|
||||
sqliteExprCode(pParse, pX->pRight);
|
||||
aExpr[k].p = 0;
|
||||
disableTerm(pLevel, &aExpr[k].p);
|
||||
break;
|
||||
}
|
||||
if( pX->op==TK_IN && nColumn==1 ){
|
||||
@@ -777,7 +808,7 @@ WhereInfo *sqliteWhereBegin(
|
||||
pLevel->inOp = OP_Next;
|
||||
pLevel->inP1 = pX->iTable;
|
||||
}
|
||||
aExpr[k].p = 0;
|
||||
disableTerm(pLevel, &aExpr[k].p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -787,7 +818,7 @@ WhereInfo *sqliteWhereBegin(
|
||||
&& aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
|
||||
){
|
||||
sqliteExprCode(pParse, aExpr[k].p->pLeft);
|
||||
aExpr[k].p = 0;
|
||||
disableTerm(pLevel, &aExpr[k].p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -854,7 +885,7 @@ WhereInfo *sqliteWhereBegin(
|
||||
sqliteVdbeAddOp(v, OP_ForceInt,
|
||||
aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT, brk);
|
||||
sqliteVdbeAddOp(v, OP_MoveTo, iCur, brk);
|
||||
aExpr[k].p = 0;
|
||||
disableTerm(pLevel, &aExpr[k].p);
|
||||
}else{
|
||||
sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
|
||||
}
|
||||
@@ -876,7 +907,7 @@ WhereInfo *sqliteWhereBegin(
|
||||
}else{
|
||||
testOp = OP_Gt;
|
||||
}
|
||||
aExpr[k].p = 0;
|
||||
disableTerm(pLevel, &aExpr[k].p);
|
||||
}
|
||||
start = sqliteVdbeCurrentAddr(v);
|
||||
pLevel->op = OP_Next;
|
||||
@@ -931,7 +962,7 @@ WhereInfo *sqliteWhereBegin(
|
||||
&& aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j]
|
||||
){
|
||||
sqliteExprCode(pParse, aExpr[k].p->pRight);
|
||||
aExpr[k].p = 0;
|
||||
disableTerm(pLevel, &aExpr[k].p);
|
||||
break;
|
||||
}
|
||||
if( aExpr[k].idxRight==iCur
|
||||
@@ -940,7 +971,7 @@ WhereInfo *sqliteWhereBegin(
|
||||
&& aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
|
||||
){
|
||||
sqliteExprCode(pParse, aExpr[k].p->pLeft);
|
||||
aExpr[k].p = 0;
|
||||
disableTerm(pLevel, &aExpr[k].p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -977,7 +1008,7 @@ WhereInfo *sqliteWhereBegin(
|
||||
){
|
||||
sqliteExprCode(pParse, pExpr->pRight);
|
||||
leFlag = pExpr->op==TK_LE;
|
||||
aExpr[k].p = 0;
|
||||
disableTerm(pLevel, &aExpr[k].p);
|
||||
break;
|
||||
}
|
||||
if( aExpr[k].idxRight==iCur
|
||||
@@ -987,7 +1018,7 @@ WhereInfo *sqliteWhereBegin(
|
||||
){
|
||||
sqliteExprCode(pParse, pExpr->pLeft);
|
||||
leFlag = pExpr->op==TK_GE;
|
||||
aExpr[k].p = 0;
|
||||
disableTerm(pLevel, &aExpr[k].p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1036,7 +1067,7 @@ WhereInfo *sqliteWhereBegin(
|
||||
){
|
||||
sqliteExprCode(pParse, pExpr->pRight);
|
||||
geFlag = pExpr->op==TK_GE;
|
||||
aExpr[k].p = 0;
|
||||
disableTerm(pLevel, &aExpr[k].p);
|
||||
break;
|
||||
}
|
||||
if( aExpr[k].idxRight==iCur
|
||||
@@ -1046,7 +1077,7 @@ WhereInfo *sqliteWhereBegin(
|
||||
){
|
||||
sqliteExprCode(pParse, pExpr->pLeft);
|
||||
geFlag = pExpr->op==TK_LE;
|
||||
aExpr[k].p = 0;
|
||||
disableTerm(pLevel, &aExpr[k].p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -12,7 +12,7 @@
|
||||
# focus of this script is testing the ATTACH and DETACH commands
|
||||
# and related functionality.
|
||||
#
|
||||
# $Id: auth.test,v 1.12 2003/12/07 00:24:35 drh Exp $
|
||||
# $Id: auth.test,v 1.12.2.1 2004/09/09 13:54:31 drh Exp $
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
@@ -36,6 +36,12 @@ do_test auth-1.1.1 {
|
||||
do_test auth-1.1.2 {
|
||||
db errorcode
|
||||
} {23}
|
||||
do_test auth-1.1.3 {
|
||||
# Ticket #896.
|
||||
catchsql {
|
||||
SELECT x;
|
||||
}
|
||||
} {1 {no such column: x}}
|
||||
do_test auth-1.2 {
|
||||
execsql {SELECT name FROM sqlite_master}
|
||||
} {}
|
||||
|
||||
+15
-2
@@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing date and time functions.
|
||||
#
|
||||
# $Id: date.test,v 1.7 2004/02/29 01:08:18 drh Exp $
|
||||
# $Id: date.test,v 1.7.2.1 2004/07/18 22:25:16 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -95,7 +95,20 @@ datetest 3.7 {strftime('%M','2003-10-31 12:34:56.432')} 34
|
||||
datetest 3.8 {strftime('%s','2003-10-31 12:34:56.432')} 1067603696
|
||||
datetest 3.9 {strftime('%S','2003-10-31 12:34:56.432')} 56
|
||||
datetest 3.10 {strftime('%w','2003-10-31 12:34:56.432')} 5
|
||||
datetest 3.11 {strftime('%W','2003-10-31 12:34:56.432')} 44
|
||||
datetest 3.11.1 {strftime('%W','2003-10-31 12:34:56.432')} 43
|
||||
datetest 3.11.2 {strftime('%W','2004-01-01')} 00
|
||||
datetest 3.11.3 {strftime('%W','2004-01-02')} 00
|
||||
datetest 3.11.4 {strftime('%W','2004-01-03')} 00
|
||||
datetest 3.11.5 {strftime('%W','2004-01-04')} 00
|
||||
datetest 3.11.6 {strftime('%W','2004-01-05')} 01
|
||||
datetest 3.11.7 {strftime('%W','2004-01-06')} 01
|
||||
datetest 3.11.8 {strftime('%W','2004-01-07')} 01
|
||||
datetest 3.11.9 {strftime('%W','2004-01-08')} 01
|
||||
datetest 3.11.10 {strftime('%W','2004-01-09')} 01
|
||||
datetest 3.11.11 {strftime('%W','2004-07-18')} 28
|
||||
datetest 3.11.12 {strftime('%W','2004-12-31')} 52
|
||||
datetest 3.11.13 {strftime('%W','2007-12-31')} 53
|
||||
datetest 3.11.14 {strftime('%W','2007-01-01')} 01
|
||||
datetest 3.12 {strftime('%Y','2003-10-31 12:34:56.432')} 2003
|
||||
datetest 3.13 {strftime('%%','2003-10-31 12:34:56.432')} %
|
||||
datetest 3.14 {strftime('%_','2003-10-31 12:34:56.432')} NULL
|
||||
|
||||
+6
-1
@@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing built-in functions.
|
||||
#
|
||||
# $Id: func.test,v 1.16 2002/11/04 19:32:26 drh Exp $
|
||||
# $Id: func.test,v 1.16.2.2 2004/07/18 21:14:05 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -264,6 +264,11 @@ do_test func-8.3 {
|
||||
SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
|
||||
}
|
||||
} {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
|
||||
do_test func-8.4 {
|
||||
execsql {
|
||||
SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
|
||||
}
|
||||
} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
|
||||
|
||||
# How do you test the random() function in a meaningful, deterministic way?
|
||||
#
|
||||
|
||||
+16
-1
@@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the CREATE INDEX statement.
|
||||
#
|
||||
# $Id: index.test,v 1.24 2003/09/27 00:41:28 drh Exp $
|
||||
# $Id: index.test,v 1.24.2.1 2004/07/20 00:50:30 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -515,4 +515,19 @@ do_test index-15.2 {
|
||||
} {8 5 2 1 3 6 11 9 10 4 7}
|
||||
integrity_check index-15.1
|
||||
|
||||
# Drop index with a quoted name. Ticket #695.
|
||||
#
|
||||
do_test index-16.1 {
|
||||
execsql {
|
||||
CREATE INDEX "t6i2" ON t6(c);
|
||||
DROP INDEX "t6i2";
|
||||
}
|
||||
} {}
|
||||
do_test index-16.2 {
|
||||
execsql {
|
||||
DROP INDEX "t6i1";
|
||||
}
|
||||
} {}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+9
-7
@@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is the sqlite_interrupt() API.
|
||||
#
|
||||
# $Id: interrupt.test,v 1.4 2004/02/18 16:57:23 drh Exp $
|
||||
# $Id: interrupt.test,v 1.4.2.1 2004/05/10 20:27:42 drh Exp $
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
@@ -37,12 +37,13 @@ proc cksum {{db db}} {
|
||||
# and checks to make sure SQLITE_INTERRUPT is returned. Eventually,
|
||||
# the routine completes successfully.
|
||||
#
|
||||
proc interrupt_test {testid sql result {initcnt 0}} {
|
||||
proc interrupt_test {testid sql result {initcnt 0} {maxcnt 1000000}} {
|
||||
set orig_sum [cksum]
|
||||
set i $initcnt
|
||||
while 1 {
|
||||
global sqlite_interrupt_count
|
||||
while {$i<$maxcnt} {
|
||||
incr i
|
||||
set ::sqlite_interrupt_count $i
|
||||
set sqlite_interrupt_count $i
|
||||
do_test $testid.$i.1 [format {
|
||||
set ::r [catchsql %s]
|
||||
set ::code [db errorcode]
|
||||
@@ -52,14 +53,14 @@ proc interrupt_test {testid sql result {initcnt 0}} {
|
||||
do_test $testid.$i.2 {
|
||||
cksum
|
||||
} $orig_sum
|
||||
} else {
|
||||
} elseif {$sqlite_interrupt_count>0} {
|
||||
do_test $testid.$i.99 {
|
||||
set ::r
|
||||
} [list 0 $result]
|
||||
break
|
||||
}
|
||||
}
|
||||
set ::sqlite_interrupt_count 0
|
||||
set sqlite_interrupt_count 0
|
||||
}
|
||||
|
||||
do_test interrupt-1.1 {
|
||||
@@ -68,7 +69,7 @@ do_test interrupt-1.1 {
|
||||
SELECT name FROM sqlite_master;
|
||||
}
|
||||
} {t1}
|
||||
interrupt_test interrupt-1.2 {DROP TABLE t1} {}
|
||||
interrupt_test interrupt-1.2 {DROP TABLE t1} {} 1 14
|
||||
do_test interrupt-1.3 {
|
||||
execsql {
|
||||
SELECT name FROM sqlite_master;
|
||||
@@ -162,4 +163,5 @@ for {set i 1} {$i<$max_count-5} {incr i 1} {
|
||||
} {1 interrupted}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# 2002 May 24
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
# This file implements tests for joins, including outer joins, where
|
||||
# there are a large number of tables involved in the join.
|
||||
#
|
||||
# $Id: join3_28.test,v 1.1.2.1 2004/07/22 16:08:39 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
catch {unset result}
|
||||
set result {}
|
||||
for {set N 1} {$N<=40} {incr N} {
|
||||
lappend result $N
|
||||
do_test join3-1.$N {
|
||||
execsql "CREATE TABLE t${N}(x);"
|
||||
execsql "INSERT INTO t$N VALUES($N)"
|
||||
set sql "SELECT * FROM t1"
|
||||
for {set i 2} {$i<=$N} {incr i} {append sql ", t$i"}
|
||||
execsql $sql
|
||||
} $result
|
||||
}
|
||||
|
||||
finish_test
|
||||
@@ -0,0 +1,77 @@
|
||||
# 2002 May 24
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
# This file implements tests for left outer joins containing WHERE
|
||||
# clauses that restrict the scope of the left term of the join.
|
||||
#
|
||||
# $Id: join4_28.test,v 1.1.2.1 2004/07/22 16:08:39 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_test join4-1.1 {
|
||||
execsql {
|
||||
create temp table t1(a integer, b varchar(10));
|
||||
insert into t1 values(1,'one');
|
||||
insert into t1 values(2,'two');
|
||||
insert into t1 values(3,'three');
|
||||
insert into t1 values(4,'four');
|
||||
|
||||
create temp table t2(x integer, y varchar(10), z varchar(10));
|
||||
insert into t2 values(2,'niban','ok');
|
||||
insert into t2 values(4,'yonban','err');
|
||||
}
|
||||
execsql {
|
||||
select * from t1 left outer join t2 on t1.a=t2.x where t2.z='ok'
|
||||
}
|
||||
} {2 two 2 niban ok}
|
||||
do_test join4-1.2 {
|
||||
execsql {
|
||||
select * from t1 left outer join t2 on t1.a=t2.x and t2.z='ok'
|
||||
}
|
||||
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
|
||||
do_test join4-1.3 {
|
||||
execsql {
|
||||
create index i2 on t2(z);
|
||||
}
|
||||
execsql {
|
||||
select * from t1 left outer join t2 on t1.a=t2.x where t2.z='ok'
|
||||
}
|
||||
} {2 two 2 niban ok}
|
||||
do_test join4-1.4 {
|
||||
execsql {
|
||||
select * from t1 left outer join t2 on t1.a=t2.x and t2.z='ok'
|
||||
}
|
||||
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
|
||||
do_test join4-1.5 {
|
||||
execsql {
|
||||
select * from t1 left outer join t2 on t1.a=t2.x where t2.z>='ok'
|
||||
}
|
||||
} {2 two 2 niban ok}
|
||||
do_test join4-1.4 {
|
||||
execsql {
|
||||
select * from t1 left outer join t2 on t1.a=t2.x and t2.z>='ok'
|
||||
}
|
||||
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
|
||||
do_test join4-1.6 {
|
||||
execsql {
|
||||
select * from t1 left outer join t2 on t1.a=t2.x where t2.z IN ('ok')
|
||||
}
|
||||
} {2 two 2 niban ok}
|
||||
do_test join4-1.7 {
|
||||
execsql {
|
||||
select * from t1 left outer join t2 on t1.a=t2.x and t2.z IN ('ok')
|
||||
}
|
||||
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
|
||||
|
||||
|
||||
finish_test
|
||||
+21
-1
@@ -12,7 +12,7 @@
|
||||
# focus of this file is testing the LIMIT ... OFFSET ... clause
|
||||
# of SELECT statements.
|
||||
#
|
||||
# $Id: limit.test,v 1.11 2004/03/08 13:26:18 drh Exp $
|
||||
# $Id: limit.test,v 1.11.2.1 2004/07/19 23:33:04 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -294,4 +294,24 @@ do_test limit-7.12 {
|
||||
}
|
||||
} {30}
|
||||
|
||||
# Tests for limit in conjunction with distinct. The distinct should
|
||||
# occur before both the limit and the offset. Ticket #749.
|
||||
#
|
||||
do_test limit-8.1 {
|
||||
execsql {
|
||||
SELECT DISTINCT round(x/100) FROM t3 LIMIT 5;
|
||||
}
|
||||
} {0 1 2 3 4}
|
||||
do_test limit-8.2 {
|
||||
execsql {
|
||||
SELECT DISTINCT round(x/100) FROM t3 LIMIT 5 OFFSET 5;
|
||||
}
|
||||
} {5 6 7 8 9}
|
||||
do_test limit-8.3 {
|
||||
execsql {
|
||||
SELECT DISTINCT round(x/100) FROM t3 LIMIT 5 OFFSET 25;
|
||||
}
|
||||
} {25 26 27 28 29}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+82
-2
@@ -13,7 +13,7 @@
|
||||
# aggregate min() and max() functions and which are handled as
|
||||
# as a special case.
|
||||
#
|
||||
# $Id: minmax.test,v 1.9 2004/03/13 14:00:37 drh Exp $
|
||||
# $Id: minmax.test,v 1.9.2.2 2004/07/18 21:14:05 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -68,7 +68,7 @@ do_test minmax-1.5 {
|
||||
} {1}
|
||||
do_test minmax-1.6 {
|
||||
set sqlite_search_count
|
||||
} {1}
|
||||
} {2}
|
||||
do_test minmax-1.7 {
|
||||
set sqlite_search_count 0
|
||||
execsql {SELECT max(x) FROM t1}
|
||||
@@ -276,4 +276,84 @@ do_test minmax-9.2 {
|
||||
}
|
||||
} {{}}
|
||||
|
||||
# If there is a NULL in an aggregate max() or min(), ignore it. An
|
||||
# aggregate min() or max() will only return NULL if all values are NULL.
|
||||
#
|
||||
do_test minmax-10.1 {
|
||||
execsql {
|
||||
CREATE TABLE t6(x);
|
||||
INSERT INTO t6 VALUES(1);
|
||||
INSERT INTO t6 VALUES(2);
|
||||
INSERT INTO t6 VALUES(NULL);
|
||||
SELECT coalesce(min(x),-1) FROM t6;
|
||||
}
|
||||
} {1}
|
||||
do_test minmax-10.2 {
|
||||
execsql {
|
||||
SELECT max(x) FROM t6;
|
||||
}
|
||||
} {2}
|
||||
do_test minmax-10.3 {
|
||||
execsql {
|
||||
CREATE INDEX i6 ON t6(x);
|
||||
SELECT coalesce(min(x),-1) FROM t6;
|
||||
}
|
||||
} {1}
|
||||
do_test minmax-10.4 {
|
||||
execsql {
|
||||
SELECT max(x) FROM t6;
|
||||
}
|
||||
} {2}
|
||||
do_test minmax-10.5 {
|
||||
execsql {
|
||||
DELETE FROM t6 WHERE x NOT NULL;
|
||||
SELECT count(*) FROM t6;
|
||||
}
|
||||
} 1
|
||||
do_test minmax-10.6 {
|
||||
execsql {
|
||||
SELECT count(x) FROM t6;
|
||||
}
|
||||
} 0
|
||||
do_test minmax-10.7 {
|
||||
execsql {
|
||||
SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6);
|
||||
}
|
||||
} {{} {}}
|
||||
do_test minmax-10.8 {
|
||||
execsql {
|
||||
SELECT min(x), max(x) FROM t6;
|
||||
}
|
||||
} {{} {}}
|
||||
do_test minmax-10.9 {
|
||||
execsql {
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
SELECT count(*) FROM t6;
|
||||
}
|
||||
} 1024
|
||||
do_test minmax-10.10 {
|
||||
execsql {
|
||||
SELECT count(x) FROM t6;
|
||||
}
|
||||
} 0
|
||||
do_test minmax-10.11 {
|
||||
execsql {
|
||||
SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6);
|
||||
}
|
||||
} {{} {}}
|
||||
do_test minmax-10.12 {
|
||||
execsql {
|
||||
SELECT min(x), max(x) FROM t6;
|
||||
}
|
||||
} {{} {}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -94,6 +94,7 @@ do_test null-2.8 {
|
||||
} {1 0 0 1 0 0 0}
|
||||
|
||||
# Check to see that NULL values are ignored in aggregate functions.
|
||||
# (except for min().)
|
||||
#
|
||||
do_test null-3.1 {
|
||||
execsql {
|
||||
|
||||
+7
-2
@@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the SELECT statement.
|
||||
#
|
||||
# $Id: select1.test,v 1.30 2002/06/02 16:09:03 drh Exp $
|
||||
# $Id: select1.test,v 1.30.2.3 2004/07/20 01:45:49 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -612,11 +612,16 @@ do_test select1-11.3 {
|
||||
SELECT * FROM t3 AS x, t4 AS y;
|
||||
}
|
||||
} {x.a 1 x.b 2 y.a 3 y.b 4}
|
||||
do_test select1-11.4 {
|
||||
do_test select1-11.4.1 {
|
||||
execsql {
|
||||
SELECT t3.*, t4.b FROM t3, t4;
|
||||
}
|
||||
} {1 2 4}
|
||||
do_test select1-11.4.2 {
|
||||
execsql {
|
||||
SELECT "t3".*, t4.b FROM t3, t4;
|
||||
}
|
||||
} {1 2 4}
|
||||
do_test select1-11.5 {
|
||||
execsql2 {
|
||||
SELECT t3.*, t4.b FROM t3, t4;
|
||||
|
||||
+3
-1
@@ -15,7 +15,7 @@
|
||||
# interface is pretty well tested. This file contains some addition
|
||||
# tests for fringe issues that the main test suite does not cover.
|
||||
#
|
||||
# $Id: tclsqlite.test,v 1.20 2004/02/25 22:51:06 rdc Exp $
|
||||
# $Id: tclsqlite.test,v 1.20.2.2 2006/10/24 11:26:44 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -72,6 +72,7 @@ do_test tcl-1.6 {
|
||||
} {1 {syntax error in expression "x*"}}
|
||||
|
||||
if {[sqlite -encoding]=="UTF-8" && [sqlite -tcl-uses-utf]} {
|
||||
catch {unset ::result}
|
||||
do_test tcl-2.1 {
|
||||
execsql "CREATE TABLE t\u0123x(a int, b\u1235 float)"
|
||||
execsql "PRAGMA table_info(t\u0123x)"
|
||||
@@ -88,6 +89,7 @@ if {[sqlite -encoding]=="iso8859" && [sqlite -tcl-uses-utf]} {
|
||||
execsql "CREATE TABLE t\251x(a int, b\306 float)"
|
||||
execsql "PRAGMA table_info(t\251x)"
|
||||
} "0 a int 0 {} 0 1 b\306 float 0 {} 0"
|
||||
unset -nocomplain result
|
||||
do_test tcl-2.2 {
|
||||
execsql "INSERT INTO t\251x VALUES(1,2.3)"
|
||||
db eval "SELECT * FROM t\251x" result break
|
||||
|
||||
@@ -412,5 +412,116 @@ do_test trigger-9.2 {
|
||||
}
|
||||
} {1 2 1 3 99 99 1 3}
|
||||
|
||||
execsql {
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t3;
|
||||
DROP TABLE t4;
|
||||
}
|
||||
|
||||
# Skip the remaining tests if we have a codec. The ATTACH command
|
||||
# will not work right on these tests when there is a codec.
|
||||
#
|
||||
if {[sqlite -has-codec]} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Ticket #764. At one stage TEMP triggers would fail to re-install when the
|
||||
# schema was reloaded. The following tests ensure that TEMP triggers are
|
||||
# correctly re-installed.
|
||||
#
|
||||
# Also verify that references within trigger programs are resolved at
|
||||
# statement compile time, not trigger installation time. This means, for
|
||||
# example, that you can drop and re-create tables referenced by triggers.
|
||||
do_test trigger-10.0 {
|
||||
file delete -force test2.db
|
||||
file delete -force test2.db-journal
|
||||
sqlite db2 test2.db
|
||||
execsql {CREATE TABLE t3(a, b, c);} db2
|
||||
db2 close
|
||||
execsql {
|
||||
ATTACH 'test2.db' AS aux;
|
||||
}
|
||||
} {}
|
||||
do_test trigger-10.1 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE temp TABLE t2(a, b, c);
|
||||
CREATE TABLE insert_log(db, a, b, c);
|
||||
}
|
||||
} {}
|
||||
do_test trigger-10.2 {
|
||||
execsql {
|
||||
CREATE TEMP TRIGGER trig1 AFTER INSERT ON t1 BEGIN
|
||||
INSERT INTO insert_log VALUES('main', new.a, new.b, new.c);
|
||||
END;
|
||||
CREATE TEMP TRIGGER trig2 AFTER INSERT ON t2 BEGIN
|
||||
INSERT INTO insert_log VALUES('temp', new.a, new.b, new.c);
|
||||
END;
|
||||
CREATE TEMP TRIGGER trig3 AFTER INSERT ON t3 BEGIN
|
||||
INSERT INTO insert_log VALUES('aux', new.a, new.b, new.c);
|
||||
END;
|
||||
}
|
||||
} {}
|
||||
do_test trigger-10.3 {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
INSERT INTO t2 VALUES(4, 5, 6);
|
||||
INSERT INTO t3 VALUES(7, 8, 9);
|
||||
}
|
||||
} {}
|
||||
do_test trigger-10.4 {
|
||||
execsql {
|
||||
SELECT * FROM insert_log;
|
||||
}
|
||||
} {main 1 2 3 temp 4 5 6 aux 7 8 9}
|
||||
do_test trigger-10.5 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
INSERT INTO t2 VALUES(4, 5, 6);
|
||||
INSERT INTO t3 VALUES(7, 8, 9);
|
||||
ROLLBACK;
|
||||
}
|
||||
} {}
|
||||
do_test trigger-10.6 {
|
||||
execsql {
|
||||
SELECT * FROM insert_log;
|
||||
}
|
||||
} {main 1 2 3 temp 4 5 6 aux 7 8 9}
|
||||
do_test trigger-10.7 {
|
||||
execsql {
|
||||
DELETE FROM insert_log;
|
||||
INSERT INTO t1 VALUES(11, 12, 13);
|
||||
INSERT INTO t2 VALUES(14, 15, 16);
|
||||
INSERT INTO t3 VALUES(17, 18, 19);
|
||||
}
|
||||
} {}
|
||||
do_test trigger-10.8 {
|
||||
execsql {
|
||||
SELECT * FROM insert_log;
|
||||
}
|
||||
} {main 11 12 13 temp 14 15 16 aux 17 18 19}
|
||||
do_test trigger-10.8 {
|
||||
# Drop and re-create the insert_log table in a different database. Note
|
||||
# that we can change the column names because the trigger programs don't
|
||||
# use them explicitly.
|
||||
execsql {
|
||||
DROP TABLE insert_log;
|
||||
CREATE temp TABLE insert_log(db, d, e, f);
|
||||
}
|
||||
} {}
|
||||
do_test trigger-10.10 {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(21, 22, 23);
|
||||
INSERT INTO t2 VALUES(24, 25, 26);
|
||||
INSERT INTO t3 VALUES(27, 28, 29);
|
||||
}
|
||||
} {}
|
||||
do_test trigger-10.11 {
|
||||
execsql {
|
||||
SELECT * FROM insert_log;
|
||||
}
|
||||
} {main 21 22 23 temp 24 25 26 aux 27 28 29}
|
||||
|
||||
finish_test
|
||||
|
||||
+19
-1
@@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing VIEW statements.
|
||||
#
|
||||
# $Id: view.test,v 1.16 2003/05/31 16:21:13 drh Exp $
|
||||
# $Id: view.test,v 1.16.2.1 2004/07/20 00:20:47 drh Exp $
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
@@ -385,5 +385,23 @@ do_test view-9.6 {
|
||||
}
|
||||
} {3 4 4 2 5 1}
|
||||
|
||||
# Tables with columns having peculiar quoted names used in views
|
||||
# Ticket #756.
|
||||
#
|
||||
do_test view-10.1 {
|
||||
execsql {
|
||||
CREATE TABLE t3("9" integer, [4] text);
|
||||
INSERT INTO t3 VALUES(1,2);
|
||||
CREATE VIEW v_t3_a AS SELECT a.[9] FROM t3 AS a;
|
||||
CREATE VIEW v_t3_b AS SELECT "4" FROM t3;
|
||||
SELECT * FROM v_t3_a;
|
||||
}
|
||||
} {1}
|
||||
do_test view-10.2 {
|
||||
execsql {
|
||||
SELECT * FROM v_t3_b;
|
||||
}
|
||||
} {2}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+9
-14
@@ -12,13 +12,6 @@
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern void qsort();
|
||||
extern double strtod();
|
||||
extern long strtol();
|
||||
extern void free();
|
||||
extern int access();
|
||||
extern int atoi();
|
||||
|
||||
#ifndef __WIN32__
|
||||
# if defined(_WIN32) || defined(WIN32)
|
||||
# define __WIN32__
|
||||
@@ -40,7 +33,6 @@ extern void *malloc();
|
||||
/******** From the file "action.h" *************************************/
|
||||
struct action *Action_new();
|
||||
struct action *Action_sort();
|
||||
void Action_add();
|
||||
|
||||
/********* From the file "assert.h" ************************************/
|
||||
void myassert();
|
||||
@@ -374,7 +366,7 @@ struct action *ap2;
|
||||
struct action *Action_sort(ap)
|
||||
struct action *ap;
|
||||
{
|
||||
ap = (struct action *)msort(ap,&ap->next,actioncmp);
|
||||
ap = (struct action *)msort((char *)ap,(char **)&ap->next,actioncmp);
|
||||
return ap;
|
||||
}
|
||||
|
||||
@@ -811,7 +803,7 @@ struct state *stp; /* The state from which successors are computed */
|
||||
|
||||
/* The state "newstp" is reached from the state "stp" by a shift action
|
||||
** on the symbol "sp" */
|
||||
Action_add(&stp->ap,SHIFT,sp,newstp);
|
||||
Action_add(&stp->ap,SHIFT,sp,(char *)newstp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -912,7 +904,7 @@ struct lemon *lemp;
|
||||
if( SetFind(cfp->fws,j) ){
|
||||
/* Add a reduce action to the state "stp" which will reduce by the
|
||||
** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
|
||||
Action_add(&stp->ap,REDUCE,lemp->symbols[j],cfp->rp);
|
||||
Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1188,14 +1180,14 @@ struct lemon *lemp;
|
||||
|
||||
/* Sort the configuration list */
|
||||
void Configlist_sort(){
|
||||
current = (struct config *)msort(current,&(current->next),Configcmp);
|
||||
current = (struct config *)msort((char *)current,(char **)&(current->next),Configcmp);
|
||||
currentend = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sort the basis configuration list */
|
||||
void Configlist_sortbasis(){
|
||||
basis = (struct config *)msort(current,&(current->bp),Configcmp);
|
||||
basis = (struct config *)msort((char *)current,(char **)&(current->bp),Configcmp);
|
||||
basisend = 0;
|
||||
return;
|
||||
}
|
||||
@@ -1447,6 +1439,7 @@ char **argv;
|
||||
fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
|
||||
}
|
||||
exit(lem.errorcnt + lem.nconflict);
|
||||
return (lem.errorcnt + lem.nconflict);
|
||||
}
|
||||
/******************** From the file "msort.c" *******************************/
|
||||
/*
|
||||
@@ -2876,7 +2869,7 @@ struct symbol *sp;
|
||||
struct lemon *lemp;
|
||||
int *lineno;
|
||||
{
|
||||
char *cp;
|
||||
char *cp = 0;
|
||||
|
||||
int linecnt = 0;
|
||||
if( sp->type==TERMINAL ){
|
||||
@@ -2890,6 +2883,8 @@ int *lineno;
|
||||
cp = lemp->vardest;
|
||||
if( cp==0 ) return;
|
||||
fprintf(out,"#line %d \"%s\"\n{",lemp->vardestln,lemp->filename);
|
||||
}else{
|
||||
assert( 0 ); /* Cannot happen */
|
||||
}
|
||||
for(; *cp; cp++){
|
||||
if( *cp=='$' && cp[1]=='$' ){
|
||||
|
||||
@@ -0,0 +1,436 @@
|
||||
# Run this TCL script using "testfixture" in order get a report that shows
|
||||
# how much disk space is used by a particular data to actually store data
|
||||
# versus how much space is unused.
|
||||
#
|
||||
|
||||
# Get the name of the database to analyze
|
||||
#
|
||||
if {[llength $argv]!=1} {
|
||||
puts stderr "Usage: $argv0 database-name"
|
||||
exit 1
|
||||
}
|
||||
set file_to_analyze [lindex $argv 0]
|
||||
if {![file exists $file_to_analyze]} {
|
||||
puts stderr "No such file: $file_to_analyze"
|
||||
exit 1
|
||||
}
|
||||
if {![file readable $file_to_analyze]} {
|
||||
puts stderr "File is not readable: $file_to_analyze"
|
||||
exit 1
|
||||
}
|
||||
if {[file size $file_to_analyze]<2048} {
|
||||
puts stderr "Empty or malformed database: $file_to_analyze"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Open the database
|
||||
#
|
||||
sqlite db [lindex $argv 0]
|
||||
set DB [btree_open [lindex $argv 0]]
|
||||
|
||||
# In-memory database for collecting statistics
|
||||
#
|
||||
sqlite mem :memory:
|
||||
set tabledef\
|
||||
{CREATE TABLE space_used(
|
||||
name clob, -- Name of a table or index in the database file
|
||||
tblname clob, -- Name of associated table
|
||||
is_index boolean, -- TRUE if it is an index, false for a table
|
||||
nentry int, -- Number of entries in the BTree
|
||||
payload int, -- Total amount of data stored in this table or index
|
||||
mx_payload int, -- Maximum payload size
|
||||
n_ovfl int, -- Number of entries that overflow
|
||||
pri_pages int, -- Number of primary pages used
|
||||
ovfl_pages int, -- Number of overflow pages used
|
||||
pri_unused int, -- Number of unused bytes on primary pages
|
||||
ovfl_unused int -- Number of unused bytes on overflow pages
|
||||
);}
|
||||
mem eval $tabledef
|
||||
|
||||
# This query will be used to find the root page number for every index and
|
||||
# table in the database.
|
||||
#
|
||||
set sql {
|
||||
SELECT name, tbl_name, type, rootpage
|
||||
FROM sqlite_master WHERE type IN ('table','index')
|
||||
UNION ALL
|
||||
SELECT 'sqlite_master', 'sqlite_master', 'table', 2
|
||||
ORDER BY 1
|
||||
}
|
||||
|
||||
# Analyze every table in the database, one at a time.
|
||||
#
|
||||
foreach {name tblname type rootpage} [db eval $sql] {
|
||||
puts stderr "Analyzing $name..."
|
||||
set cursor [btree_cursor $DB $rootpage 0]
|
||||
set go [btree_first $cursor]
|
||||
set size 0
|
||||
catch {unset pg_used}
|
||||
set unused_ovfl 0
|
||||
set n_overflow 0
|
||||
set cnt_ovfl 0
|
||||
set n_entry 0
|
||||
set mx_size 0
|
||||
set pg_used($rootpage) 1016
|
||||
while {$go==0} {
|
||||
incr n_entry
|
||||
set payload [btree_payload_size $cursor]
|
||||
incr size $payload
|
||||
set stat [btree_cursor_dump $cursor]
|
||||
set pgno [lindex $stat 0]
|
||||
set freebytes [lindex $stat 4]
|
||||
set pg_used($pgno) $freebytes
|
||||
if {$payload>236} {
|
||||
# if {[lindex $stat 8]==0} {error "overflow is empty with $payload"}
|
||||
set n [expr {($payload-236+1019)/1020}]
|
||||
incr n_overflow $n
|
||||
incr cnt_ovfl
|
||||
incr unused_ovfl [expr {$n*1020+236-$payload}]
|
||||
} else {
|
||||
# if {[lindex $stat 8]!=0} {error "overflow not empty with $payload"}
|
||||
}
|
||||
if {$payload>$mx_size} {set mx_size $payload}
|
||||
set go [btree_next $cursor]
|
||||
}
|
||||
btree_close_cursor $cursor
|
||||
set n_primary [llength [array names pg_used]]
|
||||
set unused_primary 0
|
||||
foreach x [array names pg_used] {incr unused_primary $pg_used($x)}
|
||||
regsub -all ' $name '' name
|
||||
set sql "INSERT INTO space_used VALUES('$name'"
|
||||
regsub -all ' $tblname '' tblname
|
||||
append sql ",'$tblname',[expr {$type=="index"}],$n_entry"
|
||||
append sql ",$size,$mx_size,$cnt_ovfl,"
|
||||
append sql "$n_primary,$n_overflow,$unused_primary,$unused_ovfl);"
|
||||
mem eval $sql
|
||||
}
|
||||
|
||||
# Generate a single line of output in the statistics section of the
|
||||
# report.
|
||||
#
|
||||
proc statline {title value {extra {}}} {
|
||||
set len [string length $title]
|
||||
set dots [string range {......................................} $len end]
|
||||
set len [string length $value]
|
||||
set sp2 [string range { } $len end]
|
||||
if {$extra ne ""} {
|
||||
set extra " $extra"
|
||||
}
|
||||
puts "$title$dots $value$sp2$extra"
|
||||
}
|
||||
|
||||
# Generate a formatted percentage value for $num/$denom
|
||||
#
|
||||
proc percent {num denom} {
|
||||
if {$denom==0.0} {return ""}
|
||||
set v [expr {$num*100.0/$denom}]
|
||||
if {$v>1.0 && $v<99.0} {
|
||||
return [format %4.1f%% $v]
|
||||
} elseif {$v<0.1 || $v>99.9} {
|
||||
return [format %6.3f%% $v]
|
||||
} else {
|
||||
return [format %5.2f%% $v]
|
||||
}
|
||||
}
|
||||
|
||||
# Generate a subreport that covers some subset of the database.
|
||||
# the $where clause determines which subset to analyze.
|
||||
#
|
||||
proc subreport {title where} {
|
||||
set hit 0
|
||||
mem eval "SELECT sum(nentry) AS nentry, \
|
||||
sum(payload) AS payload, \
|
||||
sum(CASE is_index WHEN 1 THEN 0 ELSE payload-4*nentry END) \
|
||||
AS data, \
|
||||
max(mx_payload) AS mx_payload, \
|
||||
sum(n_ovfl) as n_ovfl, \
|
||||
sum(pri_pages) AS pri_pages, \
|
||||
sum(ovfl_pages) AS ovfl_pages, \
|
||||
sum(pri_unused) AS pri_unused, \
|
||||
sum(ovfl_unused) AS ovfl_unused \
|
||||
FROM space_used WHERE $where" {} {set hit 1}
|
||||
if {!$hit} {return 0}
|
||||
puts ""
|
||||
set len [string length $title]
|
||||
incr len 5
|
||||
set stars "***********************************"
|
||||
append stars $stars
|
||||
set stars [string range $stars $len end]
|
||||
puts "*** $title $stars"
|
||||
puts ""
|
||||
statline "Percentage of total database" \
|
||||
[percent [expr {$pri_pages+$ovfl_pages}] $::file_pgcnt]
|
||||
statline "Number of entries" $nentry
|
||||
set storage [expr {($pri_pages+$ovfl_pages)*1024}]
|
||||
statline "Bytes of storage consumed" $storage
|
||||
statline "Bytes of payload" $payload [percent $payload $storage]
|
||||
statline "Bytes of data" $data [percent $data $storage]
|
||||
set key [expr {$payload-$data}]
|
||||
statline "Bytes of key" $key [percent $key $storage]
|
||||
set avgpay [expr {$nentry>0?$payload/$nentry:0}]
|
||||
statline "Average payload per entry" $avgpay
|
||||
set avgunused [expr {$nentry>0?($pri_unused+$ovfl_unused)/$nentry:0}]
|
||||
statline "Average unused bytes per entry" $avgunused
|
||||
statline "Average fanout" \
|
||||
[format %.2f [expr {$pri_pages==0?0:($nentry+0.0)/$pri_pages}]]
|
||||
statline "Maximum payload per entry" $mx_payload
|
||||
statline "Entries that use overflow" $n_ovfl [percent $n_ovfl $nentry]
|
||||
statline "Total pages used" [set allpgs [expr {$pri_pages+$ovfl_pages}]]
|
||||
statline "Primary pages used" $pri_pages ;# [percent $pri_pages $allpgs]
|
||||
statline "Overflow pages used" $ovfl_pages ;# [percent $ovfl_pages $allpgs]
|
||||
statline "Unused bytes on primary pages" $pri_unused \
|
||||
[percent $pri_unused [expr {$pri_pages*1024}]]
|
||||
statline "Unused bytes on overflow pages" $ovfl_unused \
|
||||
[percent $ovfl_unused [expr {$ovfl_pages*1024}]]
|
||||
set allunused [expr {$ovfl_unused+$pri_unused}]
|
||||
statline "Unused bytes on all pages" $allunused \
|
||||
[percent $allunused [expr {$allpgs*1024}]]
|
||||
return 1
|
||||
}
|
||||
|
||||
# Output summary statistics:
|
||||
#
|
||||
puts "/** Disk-Space Utilization Report For $file_to_analyze"
|
||||
puts "*** As of [clock format [clock seconds] -format {%Y-%b-%d %H:%M:%S}]"
|
||||
puts ""
|
||||
set fsize [file size [lindex $argv 0]]
|
||||
set file_pgcnt [expr {$fsize/1024}]
|
||||
set usedcnt [mem eval {SELECT sum(pri_pages+ovfl_pages) FROM space_used}]
|
||||
set freecnt [expr {$file_pgcnt-$usedcnt-1}]
|
||||
set freecnt2 [lindex [btree_get_meta $DB] 0]
|
||||
statline {Pages in the whole file (measured)} $file_pgcnt
|
||||
set file_pgcnt2 [expr {$usedcnt+$freecnt2+1}]
|
||||
statline {Pages in the whole file (calculated)} $file_pgcnt2
|
||||
statline {Pages that store data} $usedcnt [percent $usedcnt $file_pgcnt]
|
||||
statline {Pages on the freelist (per header)}\
|
||||
$freecnt2 [percent $freecnt2 $file_pgcnt]
|
||||
statline {Pages on the freelist (calculated)}\
|
||||
$freecnt [percent $freecnt $file_pgcnt]
|
||||
statline {Header pages} 1 [percent 1 $file_pgcnt]
|
||||
|
||||
set ntable [db eval {SELECT count(*)+1 FROM sqlite_master WHERE type='table'}]
|
||||
statline {Number of tables in the database} $ntable
|
||||
set nindex [db eval {SELECT count(*) FROM sqlite_master WHERE type='index'}]
|
||||
set autoindex [db eval {SELECT count(*) FROM sqlite_master
|
||||
WHERE type='index' AND name LIKE '(% autoindex %)'}]
|
||||
set manindex [expr {$nindex-$autoindex}]
|
||||
statline {Number of indices} $nindex
|
||||
statline {Number of named indices} $manindex [percent $manindex $nindex]
|
||||
statline {Automatically generated indices} $autoindex \
|
||||
[percent $autoindex $nindex]
|
||||
|
||||
set bytes_data [mem eval "SELECT sum(payload-4*nentry) FROM space_used
|
||||
WHERE NOT is_index AND name!='sqlite_master'"]
|
||||
set total_payload [mem eval "SELECT sum(payload) FROM space_used"]
|
||||
statline "Size of the file in bytes" $fsize
|
||||
statline "Bytes of payload stored" $total_payload \
|
||||
[percent $total_payload $fsize]
|
||||
statline "Bytes of user data stored" $bytes_data \
|
||||
[percent $bytes_data $fsize]
|
||||
|
||||
# Output table rankings
|
||||
#
|
||||
puts ""
|
||||
puts "*** Page counts for all tables with their indices ********************"
|
||||
puts ""
|
||||
mem eval {SELECT tblname, count(*) AS cnt, sum(pri_pages+ovfl_pages) AS size
|
||||
FROM space_used GROUP BY tblname ORDER BY size DESC, tblname} {} {
|
||||
statline [string toupper $tblname] $size [percent $size $file_pgcnt]
|
||||
}
|
||||
|
||||
# Output subreports
|
||||
#
|
||||
if {$nindex>0} {
|
||||
subreport {All tables and indices} 1
|
||||
}
|
||||
subreport {All tables} {NOT is_index}
|
||||
if {$nindex>0} {
|
||||
subreport {All indices} {is_index}
|
||||
}
|
||||
foreach tbl [mem eval {SELECT name FROM space_used WHERE NOT is_index
|
||||
ORDER BY name}] {
|
||||
regsub ' $tbl '' qn
|
||||
set name [string toupper $tbl]
|
||||
set n [mem eval "SELECT count(*) FROM space_used WHERE tblname='$qn'"]
|
||||
if {$n>1} {
|
||||
subreport "Table $name and all its indices" "tblname='$qn'"
|
||||
subreport "Table $name w/o any indices" "name='$qn'"
|
||||
subreport "Indices of table $name" "tblname='$qn' AND is_index"
|
||||
} else {
|
||||
subreport "Table $name" "name='$qn'"
|
||||
}
|
||||
}
|
||||
|
||||
# Output instructions on what the numbers above mean.
|
||||
#
|
||||
puts {
|
||||
*** Definitions ******************************************************
|
||||
|
||||
Number of pages in the whole file
|
||||
|
||||
The number of 1024-byte pages that go into forming the complete database
|
||||
|
||||
Pages that store data
|
||||
|
||||
The number of pages that store data, either as primary B*Tree pages or
|
||||
as overflow pages. The number at the right is the data pages divided by
|
||||
the total number of pages in the file.
|
||||
|
||||
Pages on the freelist
|
||||
|
||||
The number of pages that are not currently in use but are reserved for
|
||||
future use. The percentage at the right is the number of freelist pages
|
||||
divided by the total number of pages in the file.
|
||||
|
||||
Header pages
|
||||
|
||||
The number of pages of header overhead in the database. This value is
|
||||
always 1. The percentage at the right is the number of header pages
|
||||
divided by the total number of pages in the file.
|
||||
|
||||
Number of tables in the database
|
||||
|
||||
The number of tables in the database, including the SQLITE_MASTER table
|
||||
used to store schema information.
|
||||
|
||||
Number of indices
|
||||
|
||||
The total number of indices in the database.
|
||||
|
||||
Number of named indices
|
||||
|
||||
The number of indices created using an explicit CREATE INDEX statement.
|
||||
|
||||
Automatically generated indices
|
||||
|
||||
The number of indices used to implement PRIMARY KEY or UNIQUE constraints
|
||||
on tables.
|
||||
|
||||
Size of the file in bytes
|
||||
|
||||
The total amount of disk space used by the entire database files.
|
||||
|
||||
Bytes of payload stored
|
||||
|
||||
The total number of bytes of payload stored in the database. Payload
|
||||
includes both key and data. The content of the SQLITE_MASTER table is
|
||||
counted when computing this number. The percentage at the right shows
|
||||
the payload divided by the total file size.
|
||||
|
||||
Bytes of user data stored
|
||||
|
||||
The total number of bytes of data stored in the database, not counting
|
||||
the database schema information stored in the SQLITE_MASTER table. The
|
||||
percentage at the right is the user data size divided by the total file
|
||||
size.
|
||||
|
||||
Percentage of total database
|
||||
|
||||
The amount of the complete database file that is devoted to storing
|
||||
information described by this category.
|
||||
|
||||
Number of entries
|
||||
|
||||
The total number of B*Tree key/value pairs stored under this category.
|
||||
|
||||
Bytes of storage consumed
|
||||
|
||||
The total amount of disk space required to store all B*Tree entries
|
||||
under this category. The is the total number of pages used times
|
||||
the pages size (1024).
|
||||
|
||||
Bytes of payload
|
||||
|
||||
The amount of payload stored under this category. Payload is the sum
|
||||
of keys and data. Each table entry has 4 bytes of key and an arbitrary
|
||||
amount of data. Each index entry has 4 or more bytes of key and no
|
||||
data. The percentage at the right is the bytes of payload divided by
|
||||
the bytes of storage consumed.
|
||||
|
||||
Bytes of data
|
||||
|
||||
The amount of data stored under this category. The data space reported
|
||||
includes formatting information such as nul-terminators and field-lengths
|
||||
that are stored with the data. The percentage at the right is the bytes
|
||||
of data divided by bytes of storage consumed.
|
||||
|
||||
Bytes of key
|
||||
|
||||
The sum of the sizes of all keys under this category. The percentage at
|
||||
the right is the bytes of key divided by the bytes of storage consumed.
|
||||
|
||||
Average payload per entry
|
||||
|
||||
The average amount of payload on each entry. This is just the bytes of
|
||||
payload divided by the number of entries.
|
||||
|
||||
Average unused bytes per entry
|
||||
|
||||
The average amount of free space remaining on all pages under this
|
||||
category on a per-entry basis. This is the number of unused bytes on
|
||||
all pages divided by the number of entries.
|
||||
|
||||
Maximum payload per entry
|
||||
|
||||
The largest payload size of any entry.
|
||||
|
||||
Entries that use overflow
|
||||
|
||||
Up to 236 bytes of payload for each entry are stored directly in the
|
||||
primary B*Tree page. Any additional payload is stored on a linked list
|
||||
of overflow pages. This is the number of entries that exceed 236 bytes
|
||||
in size. The value to the right is the number of entries that overflow
|
||||
divided by the total number of entries.
|
||||
|
||||
Total pages used
|
||||
|
||||
This is the number of 1024 byte pages used to hold all information in
|
||||
the current category. This is the sum of primary and overflow pages.
|
||||
|
||||
Primary pages used
|
||||
|
||||
This is the number of primary B*Tree pages used.
|
||||
|
||||
Overflow pages used
|
||||
|
||||
The total number of overflow pages used for this category.
|
||||
|
||||
Unused bytes on primary pages
|
||||
|
||||
The total number of bytes of unused space on all primary pages. The
|
||||
percentage at the right is the number of unused bytes divided by the
|
||||
total number of bytes on primary pages.
|
||||
|
||||
Unused bytes on overflow pages
|
||||
|
||||
The total number of bytes of unused space on all overflow pages. The
|
||||
percentage at the right is the number of unused bytes divided by the
|
||||
total number of bytes on overflow pages.
|
||||
|
||||
Unused bytes on all pages
|
||||
|
||||
The total number of bytes of unused space on all primary and overflow
|
||||
pages. The percentage at the right is the number of unused bytes
|
||||
divided by the total number of bytes.
|
||||
}
|
||||
|
||||
# Output the database
|
||||
#
|
||||
puts "**********************************************************************"
|
||||
puts "The entire text of this report can be sourced into any SQL database"
|
||||
puts "engine for further analysis. All of the text above is an SQL comment."
|
||||
puts "The data used to generate this report follows:"
|
||||
puts "*/"
|
||||
puts "BEGIN;"
|
||||
puts $tabledef
|
||||
unset -nocomplain x
|
||||
mem eval {SELECT * FROM space_used} x {
|
||||
puts -nonewline "INSERT INTO space_used VALUES("
|
||||
regsub ' $x(name) '' qn
|
||||
regsub ' $x(tblname) '' qtn
|
||||
puts -nonewline "'$qn','$qtn',"
|
||||
puts -nonewline "$x(is_index),$x(nentry),$x(payload),$x(mx_payload),"
|
||||
puts -nonewline "$x(n_ovfl),$x(pri_pages),$x(ovfl_pages),$x(pri_unused),"
|
||||
puts "$x(ovfl_unused));"
|
||||
}
|
||||
puts "COMMIT;"
|
||||
Reference in New Issue
Block a user