0
0
mirror of https://github.com/tursodatabase/libsql.git synced 2025-03-13 08:28:02 +00:00

Add the pcache module from the experimental branch. Also change things so that most of the built-in SQL functions are kept in single static hash-table, rather than creating and populating a separate hash table for each open database connection. (CVS 5566)

FossilOrigin-Name: cb494e10d71852024647aaa254203579ad438ea9
This commit is contained in:
danielk1977
2008-08-20 14:49:23 +00:00
parent 2b300d5d6f
commit 8c0a791a58
29 changed files with 2204 additions and 1637 deletions

@ -157,12 +157,12 @@ NAWK = @AWK@
#
OBJS0 = alter.lo analyze.lo attach.lo auth.lo bitvec.lo btmutex.lo \
btree.lo build.lo callback.lo complete.lo date.lo \
delete.lo expr.lo fault.lo func.lo global.lo \
delete.lo expr.lo fault.lo func2.lo global.lo \
hash.lo journal.lo insert.lo loadext.lo \
main.lo malloc.lo mem1.lo mem2.lo mem3.lo mem4.lo mem5.lo mem6.lo \
mutex.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \
opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \
pager.lo parse.lo pragma.lo prepare.lo printf.lo random.lo \
pager.lo parse.lo pcache.lo pragma.lo prepare.lo printf.lo random.lo \
select.lo status.lo table.lo tokenize.lo trigger.lo update.lo \
util.lo vacuum.lo \
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbefifo.lo vdbemem.lo \
@ -197,7 +197,6 @@ SRC = \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
$(TOP)/src/fault.c \
$(TOP)/src/func.c \
$(TOP)/src/global.c \
$(TOP)/src/hash.c \
$(TOP)/src/hash.h \
@ -228,6 +227,8 @@ SRC = \
$(TOP)/src/pager.c \
$(TOP)/src/pager.h \
$(TOP)/src/parse.y \
$(TOP)/src/pcache.c \
$(TOP)/src/pcache.h \
$(TOP)/src/pragma.c \
$(TOP)/src/prepare.c \
$(TOP)/src/printf.c \
@ -261,6 +262,7 @@ SRC = \
# Generated source code files
#
SRC += \
func2.c \
keywordhash.h \
opcodes.c \
opcodes.h \
@ -322,6 +324,7 @@ TESTSRC2 = \
$(TOP)/src/os_unix.c \
$(TOP)/src/os_win.c \
$(TOP)/src/pager.c \
$(TOP)/src/pcache.c \
$(TOP)/src/pragma.c \
$(TOP)/src/prepare.c \
$(TOP)/src/printf.c \
@ -515,8 +518,8 @@ expr.lo: $(TOP)/src/expr.c $(HDR)
fault.lo: $(TOP)/src/fault.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/fault.c
func.lo: $(TOP)/src/func.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/func.c
func2.lo: func2.c $(HDR)
$(LTCOMPILE) -c func2.c
global.lo: $(TOP)/src/global.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/global.c
@ -575,6 +578,9 @@ mutex_w32.lo: $(TOP)/src/mutex_w32.c $(HDR)
pager.lo: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h
$(LTCOMPILE) -c $(TOP)/src/pager.c
pcache.lo: $(TOP)/src/pcache.c $(HDR) $(TOP)/src/pcache.h
$(LTCOMPILE) -c $(TOP)/src/pcache.c
opcodes.lo: opcodes.c
$(LTCOMPILE) -c opcodes.c
@ -607,6 +613,11 @@ parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/addopcodes.awk
mv parse.h parse.h.temp
$(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h
func2.c: $(TOP)/src/func.c $(HDR)
$(BCC) -o mkfunction$(BEXE) $(OPTS) $(TOP)/tool/mkfunction.c -I$(TOP)/src -I.
cat $(TOP)/src/func.c > func2.c
./mkfunction$(BEXE) >> func2.c
pragma.lo: $(TOP)/src/pragma.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/pragma.c

18
main.mk

@ -50,7 +50,7 @@ TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP) -I$(TOP)/ext/rtree
#
LIBOBJ+= alter.o analyze.o attach.o auth.o bitvec.o btmutex.o btree.o build.o \
callback.o complete.o date.o delete.o \
expr.o fault.o func.o global.o hash.o insert.o journal.o loadext.o \
expr.o fault.o func2.o global.o hash.o insert.o journal.o loadext.o \
main.o malloc.o mem1.o mem2.o mem3.o mem4.o mem5.o mem6.o \
mutex.o mutex_os2.o mutex_unix.o mutex_w32.o \
opcodes.o os.o os_os2.o os_unix.o os_win.o \
@ -58,7 +58,7 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o bitvec.o btmutex.o btree.o build.o \
select.o status.o table.o $(TCLOBJ) tokenize.o trigger.o \
update.o util.o vacuum.o \
vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbefifo.o vdbemem.o \
where.o utf.o legacy.o vtab.o rtree.o icu.o
where.o utf.o legacy.o vtab.o rtree.o icu.o pcache.o
EXTOBJ = icu.o
EXTOBJ += fts1.o \
@ -98,7 +98,6 @@ SRC = \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
$(TOP)/src/fault.c \
$(TOP)/src/func.c \
$(TOP)/src/global.c \
$(TOP)/src/hash.c \
$(TOP)/src/hash.h \
@ -155,6 +154,7 @@ SRC = \
$(TOP)/src/vdbeblob.c \
$(TOP)/src/vdbefifo.c \
$(TOP)/src/vdbemem.c \
$(TOP)/src/pcache.c \
$(TOP)/src/vdbeInt.h \
$(TOP)/src/vtab.c \
$(TOP)/src/where.c
@ -204,6 +204,7 @@ SRC += \
opcodes.h \
parse.c \
parse.h \
func2.c \
sqlite3.h
@ -241,10 +242,10 @@ TESTSRC = \
TESTSRC2 = \
$(TOP)/src/attach.c $(TOP)/src/btree.c $(TOP)/src/build.c $(TOP)/src/date.c \
$(TOP)/src/expr.c $(TOP)/src/func.c $(TOP)/src/insert.c $(TOP)/src/os.c \
$(TOP)/src/expr.c func2.c $(TOP)/src/insert.c $(TOP)/src/os.c \
$(TOP)/src/os_os2.c $(TOP)/src/os_unix.c $(TOP)/src/os_win.c \
$(TOP)/src/pager.c $(TOP)/src/pragma.c $(TOP)/src/prepare.c \
$(TOP)/src/printf.c $(TOP)/src/random.c \
$(TOP)/src/printf.c $(TOP)/src/random.c $(TOP)/src/pcache.c \
$(TOP)/src/select.c $(TOP)/src/tokenize.c \
$(TOP)/src/utf.c $(TOP)/src/util.c $(TOP)/src/vdbeapi.c $(TOP)/src/vdbeaux.c \
$(TOP)/src/vdbe.c $(TOP)/src/vdbemem.c $(TOP)/src/where.c parse.c
@ -262,6 +263,7 @@ HDR = \
$(TOP)/src/os.h \
$(TOP)/src/os_common.h \
$(TOP)/src/pager.h \
$(TOP)/src/pcache.h \
parse.h \
sqlite3.h \
$(TOP)/src/sqlite3ext.h \
@ -360,6 +362,10 @@ opcodes.c: opcodes.h $(TOP)/mkopcodec.awk
opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk
cat parse.h $(TOP)/src/vdbe.c |$(NAWK) -f $(TOP)/mkopcodeh.awk >opcodes.h
func2.c: $(TOP)/src/func.c $(HDR)
$(BCC) -o mkfunction $(OPTS) $(TOP)/tool/mkfunction.c -I$(TOP)/src -I.
cat $(TOP)/src/func.c > func2.c
./mkfunction >> func2.c
# Rules to build parse.c and parse.h - the outputs of lemon.
#
@ -502,4 +508,4 @@ clean:
rm -f *.da *.bb *.bbg gmon.out
rm -rf tsrc target_source
rm -f testloadext.dll libtestloadext.so
rm -f sqlite3.c fts?amal.c
rm -f sqlite3.c fts?amal.c tclsqlite3.c func2.c

@ -1,7 +1,7 @@
C Do\snot\sflatten\sthe\sright\sterm\sof\sa\sLEFT\sjoin.\s\sTicket\s#3300.\s(CVS\s5565)
D 2008-08-14T00:19:49
C Add\sthe\spcache\smodule\sfrom\sthe\sexperimental\sbranch.\sAlso\schange\sthings\sso\sthat\smost\sof\sthe\sbuilt-in\sSQL\sfunctions\sare\skept\sin\ssingle\sstatic\shash-table,\srather\sthan\screating\sand\spopulating\sa\sseparate\shash\stable\sfor\seach\sopen\sdatabase\sconnection.\s(CVS\s5566)
D 2008-08-20T14:49:24
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 2713ea64947be3b35f35d9a3158bb8299c90b019
F Makefile.in e277c1f6dee97c18ef2f64db608da63eea4cc933
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F README b974cdc3f9f12b87e851b04e75996d720ebf81ac
F VERSION 1d5b2c9192236ed2c6bad659a7c2d1662e39e7b9
@ -76,7 +76,7 @@ F ext/rtree/rtree_util.tcl ee0a0311eb12175319d78bfb37302320496cee6e
F ext/rtree/viewrtree.tcl 09526398dae87a5a87c5aac2b3854dbaf8376869
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
F ltmain.sh 09fe5815427dc7d0abb188bbcdf0e34896577210
F main.mk eace65a99d12045ca496069dc707405a63197006
F main.mk ec8a5d47c4cb447dc666472528a7e8da91384a57
F mkdll.sh 79d1ed6ae221c10589dd969f130f8a3cccfffbb7
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
@ -96,17 +96,17 @@ F src/attach.c a85c14612e7e3410e0c3d2e0241832fa9688bd14
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
F src/bitvec.c 95c86bd18d8fedf0533f5af196192546e10a7e7d
F src/btmutex.c 709cad2cdca0afd013f0f612363810e53f59ec53
F src/btree.c c38431aed9dcdf62916c9009d6f9971e588189fe
F src/btree.c c536edea3dd8a9f5f56101ca66cd5dfe699a5d7b
F src/btree.h 6371c5e599fab391a150c96afbc10062b276d107
F src/btreeInt.h ab18c7b4980314e9e4b402e5dcde09f3c2545576
F src/build.c 931ed94fd3bbd67b6ac9d5ac6a45dc01e9f01726
F src/callback.c c9f75a4c403f166af3761df47d78a806587d63af
F src/callback.c 1b1a5c580cdf7d83db24001bf8e5c09e2b08658f
F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c
F src/date.c 52a54811218a76da6235420f532ece841159a96d
F src/delete.c 0d115c173863b3c688c3083ef7857c7f2e9f7a18
F src/expr.c 278d3950f55e04a2486e7b8dede3713a2ed6c0e1
F src/fault.c 3638519d1e0b82bccfafcb9f5ff491918b28f8e1
F src/func.c 54efe220cc1ef3859a4b738011621b63a0d697c5
F src/func.c d97ff7b72f3ddcd88970048e2894954a3f5b01d8
F src/global.c b9c96ee2317a6e1391763c7db1098a6473a91863
F src/hash.c eb64e48f3781100e5934f759fbe72a63a8fe78cb
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
@ -115,8 +115,8 @@ F src/insert.c 89cd9af52a5ea6fb7d0cfc9c3b935d6406c360c4
F src/journal.c cffd2cd214e58c0e99c3ff632b3bee6c7cbb260e
F src/legacy.c aac57bd984e666059011ea01ec4383892a253be3
F src/loadext.c eb1fe4f44d7c8ff53fc0c6a4388ab79fbd34cd64
F src/main.c c5ed24ad2b27bc93aea580a17f370a19897165f6
F src/malloc.c 22c68fc62f0c2df0f1deb8cd9a5ea968f995cac2
F src/main.c c900d0f46ddb127866ba272a2124ce56dd8592dd
F src/malloc.c 56918cddc4da7a0590eef4a2497e97b781f5c25f
F src/md5.c 008216bbb5d34c6fbab5357aa68575ad8a31516a
F src/mem1.c 3a7fe31d8290baa3bb203af72f7dfd6323966bcd
F src/mem2.c 7256327b96927020824e06ffb3443b99a28da047
@ -135,9 +135,11 @@ F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60
F src/os_os2.c 676ed273b17bd260f905df81375c9f9950d85517
F src/os_unix.c fe0dbc35bcd3de49e46b132abfc0f45d6dd6a864
F src/os_win.c aefe9ee26430678a19a058a874e4e2bd91398142
F src/pager.c b6a366f2343e7f127d7e70dbe76cd664336143cd
F src/pager.h 588c1ac195228b2da45c4e5f7ab6c2fd253d1751
F src/pager.c 9f813a8f26680ff510335e2bbd01910b2a77277b
F src/pager.h fb9376af5ba8e1eb78ee3b4f15eb0f60658ffd65
F src/parse.y 84003422b2862f82bd187dfa2399557fd1f4ecbe
F src/pcache.c c1a9abb5e2aa3d1d52a2995c8e0a36535d4d1bc2
F src/pcache.h 71ade7a84ed87d9d20507315260b1d91808d7c9a
F src/pragma.c 6e207b4f69901089758c02c02e0bf86ed12a4d8f
F src/prepare.c fceb567b359daaa6c6e2a4d04a01dec01ac0c907
F src/printf.c 2e984b2507291a7e16d89dc9bb60582904f6247d
@ -146,19 +148,19 @@ F src/select.c defdb8cdf7d2d8e1e0df117e50af6378fdaf1329
F src/shell.c d83b578a8ccdd3e0e7fef4388a0887ce9f810967
F src/sqlite.h.in 54e51c22e2294c5989156b0aec87aa44168ac1f0
F src/sqlite3ext.h 1e3887c9bd3ae66cb599e922824b04cd0d0f2c3e
F src/sqliteInt.h 7c68cacc760e8038ba6221c4d9ee3a7f0580e181
F src/sqliteInt.h e49782bc45092732795297d83331b1855eb234b3
F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
F src/status.c 8caa772cd9310bc297280f7cf0ede4d69ed5b801
F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
F src/tclsqlite.c ec46084184f033ba396a9ee7b5514b695083d0f3
F src/test1.c 0ae2203b03dec8ecf8ad731038df47ba27bfe68c
F src/test2.c 7a634c1e044be3ea5845e65155fdd1cab13936cb
F src/test1.c f92039530f6a6253ec8d3bfeaa54205a0036bbb6
F src/test2.c 9601907ac0bab60f2f81695c3a6e9249621ae741
F src/test3.c e85b7ce5c28c3ce7fbdbf7f98e1467b19786c62b
F src/test4.c 41056378671e7b00e6305fa9ac6fa27e6f96f406
F src/test5.c 162a1cea2105a2c460a3f39fa6919617b562a288
F src/test6.c 0a0304a69cfa4962a429d084c6d451ff9e4fb572
F src/test7.c 475b1fa7e3275408b40a3cbdc9508cbdc41ffa02
F src/test8.c 7da151778887275c7f62b972363c78a5609f2bd8
F src/test8.c 2f821eabefc73e4fd90ea24501d105e74b8e76d2
F src/test9.c 904ebe0ed1472d6bad17a81e2ecbfc20017dc237
F src/test_async.c da9f58f49faccd3a26ba89f58de125862351b6e2
F src/test_autoext.c f53b0cdf7bf5f08100009572a5d65cdb540bd0ad
@ -191,7 +193,7 @@ F src/vdbeaux.c 3e2e1f36c25eae32bdd605456c8be99f73e71eaf
F src/vdbeblob.c f93110888ddc246215e9ba1f831d3d375bfd8355
F src/vdbefifo.c 20fda2a7c4c0bcee1b90eb7e545fefcdbf2e1de7
F src/vdbemem.c c37b2a266a49eaf0c0f5080157f9f1a908fdaac3
F src/vtab.c 9c1bbb54d8b29a3412bff4eee32e9be309d85727
F src/vtab.c edf8edb55dc93ec4bfe8b3f10213cf6c025edb9c
F src/where.c a800184a2d023b15d6f2758b7a6c7ab011258fee
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@ -368,9 +370,9 @@ F test/insert4.test 6e382eaf7295a4463e6f29ea20fcd8e63d097eeb
F test/insert5.test 1f93cbe9742110119133d7e8e3ccfe6d7c249766
F test/interrupt.test 42e7cf98646fd9cb4a3b131a93ed3c50b9e149f1
F test/intpkey.test 537669fd535f62632ca64828e435b9e54e8d677f
F test/io.test 23c52939ebf90f00d9cbd819ced6daa9f21445fa
F test/io.test 92cedb5eff70064f9fcf4ec51e86591b1f0ad130
F test/ioerr.test b42f249c9181b5864e53fdae38ef75475d71c66f
F test/ioerr2.test 5598405c48842c6c0187daad9eb49eff2c54f80d
F test/ioerr2.test 988bda4d8d6fa1593765a514bf7a24adb3240da9
F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
F test/ioerr4.test fc6eddfec2efc2f1ed217b9eae4c1c1d3516ce86
F test/ioerr5.test fe59ee3e3d45a121bcdb8f462b718076e66b4ca7
@ -417,7 +419,7 @@ F test/malloc_common.tcl e082fe4791dad22b49d2ad3f7dcf1dcbee1a4cec
F test/manydb.test 8de36b8d33aab5ef295b11d9e95310aeded31af8
F test/memdb.test a67bda4ff90a38f2b19f6c7f95aa7289e051d893
F test/memleak.test d2d2a1ff7105d32dc3fdf691458cf6cba58c7217
F test/memsubsys1.test 3cfd3237dbbceaf65673be7265c58d8a34d63cbb
F test/memsubsys1.test bd578712272a3c327873b388396e351586d29e61
F test/memsubsys2.test 72a731225997ad5e8df89fdbeae9224616b6aecc
F test/minmax.test 722d80816f7e096bf2c04f4111f1a6c1ba65453d
F test/minmax2.test 33504c01a03bd99226144e4b03f7631a274d66e0
@ -430,16 +432,16 @@ F test/misc5.test 6a5c1e3217a95b0db05ff9a0f1ecb5ce9043ffef
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test fd424ff93a83bb6a31463eb043c588777d8215a8
F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
F test/mutex1.test 7f5e21fd11fe22de079e5dcd394ee4f6c257e68e
F test/mutex1.test 3f7c86418b85404f5c5d921f5d8023684bb3ac49
F test/mutex2.test 56f282f436596e9febdc6e0db2c507432b6724bb
F test/nan.test 14c41572ff52dbc740b1c3303dd313a90dc6084c
F test/notnull.test 44d600f916b770def8b095a9962dbe3be5a70d82
F test/null.test a8b09b8ed87852742343b33441a9240022108993
F test/openv2.test f5dd6b23e4dce828eb211649b600763c42a668df
F test/pager.test 60303481b22b240c18d6dd1b64edcecc2f4b5a97
F test/pager2.test c025f91b75fe65e85febda64d9416428b8a5cab5
F test/pager.test 1e1832795e9e07a359c959ffdddcf7275a88f54c
F test/pager2.test 070983b89a308adaba525a2f9c1ba0592c72fa3d
F test/pager3.test 2323bf27fd5bd887b580247e5bce500ceee994b4
F test/pageropt.test 6df72c441db0a037b7ec6990d16311c24fbea77b
F test/pageropt.test 3ee6578891baaca967f0bd349e4abfa736229e1a
F test/pagesize.test e0a8b3fe80f8b8e808d94a00734c7a18c76c407e
F test/permutations.test 4ad59e4489255b025aac0cc661789d35a83d87ec
F test/pragma.test 2c675ed9a288094ed62bf55b35fbc749e25670fb
@ -471,7 +473,7 @@ F test/selectB.test 31e81ac9af7d224850e0706350f070ecb92fcbc7
F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c
F test/shared.test b9f3bbd3ba727c5f1f8c815b7d0199262aacf214
F test/shared2.test 0ee9de8964d70e451936a48c41cb161d9134ccf4
F test/shared3.test 987316be601e2349e6a340a6d5f8ed981e507931
F test/shared3.test 9c880afc081d797da514ef64bccf36f3fce2f09c
F test/shared4.test d0fadacb50bb6981b2fb9dc6d1da30fa1edddf83
F test/shared_err.test 776ab7196ecda8b07a075e115b0725806991e151
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
@ -527,7 +529,7 @@ F test/tkt2285.test cca17be61cf600b397188e77e7143844d2b977e9
F test/tkt2332.test fc955609b958ca86dfa102832243370a0cc84070
F test/tkt2339.test 73bd17818924cd2ac442e5fd9916b58565739450
F test/tkt2391.test ab7a11be7402da8b51a5be603425367aa0684567
F test/tkt2409.test 20318bf6acd9b834b4420548f277b8e3a7420cd1
F test/tkt2409.test 695269f90bbd30285fb1dd1499e8cc0d827a647d
F test/tkt2450.test 77ed94863f2049c1420288ddfea2d41e5e0971d6
F test/tkt2640.test 28134f5d1e05658ef182520cf0b680fa3de5211b
F test/tkt2643.test 3f3ebb743da00d4fed4fcf6daed92a0e18e57813
@ -601,9 +603,10 @@ F tool/lempar.c 4d115ee7c0c8a749d5b22abed731abb4e6546a5f
F tool/memleak.awk 4e7690a51bf3ed757e611273d43fe3f65b510133
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
F tool/memleak3.tcl 7707006ee908cffff210c98158788d85bb3fcdbf
F tool/mkfunction.c a785a1970027bc7a833aa8afb43d6786a33c11ae
F tool/mkkeywordhash.c ef93810fc41fb3d3dbacf9a33a29be88ea99ffa9
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
F tool/mksqlite3c.tcl bc5a951735e78eb37cd47f539b2400318c436872
F tool/mksqlite3c.tcl 5b4b6f974d9d761477dfb24e2a0c578b27419ef5
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
F tool/omittest.tcl 5a25ea687df5da8dd9b94bf1683f5cf2c210e51d
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
@ -618,7 +621,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
P a519cdb2f46fffe16e666f161479a22463616cb3
R 4f817c5e785c5409dbaded5f21e587f1
U drh
Z 3d91f3841f779b95c0adaebee822ab63
P 8947c72f93d0b79c8061a3bfd5ab595edfb155a5
R 10a01c477903bc3de835b14e423b9901
U danielk1977
Z 0dd70edbac3b8ebacf6c1d5a239b80f0

@ -1 +1 @@
8947c72f93d0b79c8061a3bfd5ab595edfb155a5
cb494e10d71852024647aaa254203579ad438ea9

@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.497 2008/08/13 19:11:48 drh Exp $
** $Id: btree.c,v 1.498 2008/08/20 14:49:24 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
@ -1132,18 +1132,19 @@ static void releasePage(MemPage *pPage){
** reaches zero. We need to unref the pParent pointer when that
** happens.
*/
static void pageDestructor(DbPage *pData, int pageSize){
static void pageDestructor(DbPage *pData){
MemPage *pPage;
assert( (pageSize & 7)==0 );
pPage = (MemPage *)sqlite3PagerGetExtra(pData);
assert( pPage->isInit==0 || sqlite3_mutex_held(pPage->pBt->mutex) );
if( pPage->pParent ){
MemPage *pParent = pPage->pParent;
assert( pParent->pBt==pPage->pBt );
pPage->pParent = 0;
releasePage(pParent);
if( pPage ){
assert( pPage->isInit==0 || sqlite3_mutex_held(pPage->pBt->mutex) );
if( pPage->pParent ){
MemPage *pParent = pPage->pParent;
assert( pParent->pBt==pPage->pBt );
pPage->pParent = 0;
releasePage(pParent);
}
pPage->isInit = 0;
}
pPage->isInit = 0;
}
/*
@ -1287,7 +1288,7 @@ int sqlite3BtreeOpen(
}
pBt->busyHdr.xFunc = sqlite3BtreeInvokeBusyHandler;
pBt->busyHdr.pArg = pBt;
rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, pageDestructor,
EXTRA_SIZE, flags, vfsFlags);
if( rc==SQLITE_OK ){
rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
@ -1298,7 +1299,7 @@ int sqlite3BtreeOpen(
sqlite3PagerSetBusyhandler(pBt->pPager, &pBt->busyHdr);
p->pBt = pBt;
sqlite3PagerSetDestructor(pBt->pPager, pageDestructor);
/* sqlite3PagerSetDestructor(pBt->pPager, pageDestructor); */
sqlite3PagerSetReiniter(pBt->pPager, pageReinit);
pBt->pCursor = 0;
pBt->pPage1 = 0;
@ -3488,6 +3489,7 @@ void sqlite3BtreeMoveToParent(BtCursor *pCur){
assert( !sqlite3BtreeIsRootPage(pPage) );
pParent = pPage->pParent;
assert( pParent!=0 );
assert( pPage->pDbPage->nRef>0 );
idxParent = pPage->idxParent;
sqlite3PagerRef(pParent->pDbPage);
releasePage(pPage);

@ -13,7 +13,7 @@
** This file contains functions used to access the internal hash tables
** of user defined functions and collation sequences.
**
** $Id: callback.c,v 1.26 2008/07/28 19:34:53 drh Exp $
** $Id: callback.c,v 1.27 2008/08/20 14:49:24 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -222,6 +222,44 @@ CollSeq *sqlite3FindCollSeq(
return pColl;
}
/* During the search for the best function definition, this procedure
** is called to test how well the function passed as the first argument
** matches the request for a function with nArg arguments in a system
** that uses encoding enc. The value returned indicates how well the
** request is matched. A higher value indicates a better match.
**
** The returned value is always between 1 and 6, as follows:
**
** 1: A variable arguments function that prefers UTF-8 when a UTF-16
** encoding is requested, or vice versa.
** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
** requested, or vice versa.
** 3: A variable arguments function using the same text encoding.
** 4: A function with the exact number of arguments requested that
** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
** 5: A function with the exact number of arguments requested that
** prefers UTF-16LE when UTF-16BE is requested, or vice versa.
** 6: An exact match.
**
*/
static int matchQuality(FuncDef *p, int nArg, u8 enc){
int match = 0;
if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
match = 1;
if( p->nArg==nArg || nArg==-1 ){
match = 4;
}
if( enc==p->iPrefEnc ){
match += 2;
}
else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) ||
(enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){
match += 1;
}
}
return match;
}
/*
** Locate a user function given a name, a number of arguments and a flag
** indicating whether the function prefers UTF-16 over UTF-8. Return a
@ -261,39 +299,26 @@ FuncDef *sqlite3FindFunction(
pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName);
for(p=pFirst; p; p=p->pNext){
/* During the search for the best function definition, bestmatch is set
** as follows to indicate the quality of the match with the definition
** pointed to by pBest:
**
** 0: pBest is NULL. No match has been found.
** 1: A variable arguments function that prefers UTF-8 when a UTF-16
** encoding is requested, or vice versa.
** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
** requested, or vice versa.
** 3: A variable arguments function using the same text encoding.
** 4: A function with the exact number of arguments requested that
** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
** 5: A function with the exact number of arguments requested that
** prefers UTF-16LE when UTF-16BE is requested, or vice versa.
** 6: An exact match.
**
** A larger value of 'matchqual' indicates a more desirable match.
*/
if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
int match = 1; /* Quality of this match */
if( p->nArg==nArg || nArg==-1 ){
match = 4;
}
if( enc==p->iPrefEnc ){
match += 2;
}
else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) ||
(enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){
match += 1;
}
int match = matchQuality(p, nArg, enc);
if( match>bestmatch ){
pBest = p;
bestmatch = match;
}
}
/* If the createFlag parameter is false and no match was found amongst
** the custom functions stored in sqlite3.aFunc, try to find a built-in
** function to use.
*/
if( !createFlag && !pBest ){
FuncDef *aFunc;
int nFunc;
int i;
nFunc = sqlite3GetBuiltinFunction(zName, nName, &aFunc);
for(i=0; i<nFunc; i++){
int match = matchQuality(&aFunc[i], nArg, enc);
if( match>bestmatch ){
pBest = p;
pBest = &aFunc[i];
bestmatch = match;
}
}
@ -304,7 +329,8 @@ FuncDef *sqlite3FindFunction(
** new entry to the hash table and return it.
*/
if( createFlag && bestmatch<6 &&
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName))!=0 ){
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
pBest->zName = (char *)&pBest[1];
pBest->nArg = nArg;
pBest->pNext = pFirst;
pBest->iPrefEnc = enc;

@ -16,15 +16,17 @@
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.196 2008/07/28 19:34:53 drh Exp $
** $Id: func.c,v 1.197 2008/08/20 14:49:24 danielk1977 Exp $
*/
#ifndef CREATE_BUILTIN_HASHTABLE
#include "sqliteInt.h"
#include <ctype.h>
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"
/*
** Return the collating function associated with a function.
*/
@ -1214,107 +1216,12 @@ static void groupConcatFinalize(sqlite3_context *context){
** external linkage.
*/
void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
static const struct {
char *zName;
signed char nArg;
u8 argType; /* 1: 0, 2: 1, 3: 2,... N: N-1. */
u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */
u8 needCollSeq;
void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
} aFuncs[] = {
{ "min", -1, 0, SQLITE_UTF8, 1, minmaxFunc },
{ "min", 0, 0, SQLITE_UTF8, 1, 0 },
{ "max", -1, 1, SQLITE_UTF8, 1, minmaxFunc },
{ "max", 0, 1, SQLITE_UTF8, 1, 0 },
{ "typeof", 1, 0, SQLITE_UTF8, 0, typeofFunc },
{ "length", 1, 0, SQLITE_UTF8, 0, lengthFunc },
{ "substr", 2, 0, SQLITE_UTF8, 0, substrFunc },
{ "substr", 3, 0, SQLITE_UTF8, 0, substrFunc },
{ "abs", 1, 0, SQLITE_UTF8, 0, absFunc },
{ "round", 1, 0, SQLITE_UTF8, 0, roundFunc },
{ "round", 2, 0, SQLITE_UTF8, 0, roundFunc },
{ "upper", 1, 0, SQLITE_UTF8, 0, upperFunc },
{ "lower", 1, 0, SQLITE_UTF8, 0, lowerFunc },
{ "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc },
{ "coalesce", 0, 0, SQLITE_UTF8, 0, 0 },
{ "coalesce", 1, 0, SQLITE_UTF8, 0, 0 },
{ "hex", 1, 0, SQLITE_UTF8, 0, hexFunc },
{ "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc },
{ "random", -1, 0, SQLITE_UTF8, 0, randomFunc },
{ "randomblob", 1, 0, SQLITE_UTF8, 0, randomBlob },
{ "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc },
{ "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
{ "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc },
{ "last_insert_rowid", 0, 0, SQLITE_UTF8, 0, last_insert_rowid },
{ "changes", 0, 0, SQLITE_UTF8, 0, changes },
{ "total_changes", 0, 0, SQLITE_UTF8, 0, total_changes },
{ "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc },
{ "ltrim", 1, 1, SQLITE_UTF8, 0, trimFunc },
{ "ltrim", 2, 1, SQLITE_UTF8, 0, trimFunc },
{ "rtrim", 1, 2, SQLITE_UTF8, 0, trimFunc },
{ "rtrim", 2, 2, SQLITE_UTF8, 0, trimFunc },
{ "trim", 1, 3, SQLITE_UTF8, 0, trimFunc },
{ "trim", 2, 3, SQLITE_UTF8, 0, trimFunc },
{ "zeroblob", 1, 0, SQLITE_UTF8, 0, zeroblobFunc },
#ifdef SQLITE_SOUNDEX
{ "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc},
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
{ "load_extension", 1, 0, SQLITE_UTF8, 0, loadExt },
{ "load_extension", 2, 0, SQLITE_UTF8, 0, loadExt },
#endif
};
static const struct {
char *zName;
signed char nArg;
u8 argType;
u8 needCollSeq;
void (*xStep)(sqlite3_context*,int,sqlite3_value**);
void (*xFinalize)(sqlite3_context*);
} aAggs[] = {
{ "min", 1, 0, 1, minmaxStep, minMaxFinalize },
{ "max", 1, 1, 1, minmaxStep, minMaxFinalize },
{ "sum", 1, 0, 0, sumStep, sumFinalize },
{ "total", 1, 0, 0, sumStep, totalFinalize },
{ "avg", 1, 0, 0, sumStep, avgFinalize },
{ "count", 0, 0, 0, countStep, countFinalize },
{ "count", 1, 0, 0, countStep, countFinalize },
{ "group_concat", -1, 0, 0, groupConcatStep, groupConcatFinalize },
};
int i;
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
void *pArg;
u8 argType = aFuncs[i].argType;
pArg = SQLITE_INT_TO_PTR(argType);
sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0);
if( aFuncs[i].needCollSeq ){
FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName,
strlen(aFuncs[i].zName), aFuncs[i].nArg, aFuncs[i].eTextRep, 0);
if( pFunc && aFuncs[i].needCollSeq ){
pFunc->needCollSeq = 1;
}
}
}
#ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions(db);
#endif
#ifndef SQLITE_OMIT_PARSER
sqlite3AttachFunctions(db);
#endif
for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
void *pArg = SQLITE_INT_TO_PTR(aAggs[i].argType);
sqlite3CreateFunc(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8,
pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize);
if( aAggs[i].needCollSeq ){
FuncDef *pFunc = sqlite3FindFunction( db, aAggs[i].zName,
strlen(aAggs[i].zName), aAggs[i].nArg, SQLITE_UTF8, 0);
if( pFunc && aAggs[i].needCollSeq ){
pFunc->needCollSeq = 1;
}
}
}
sqlite3RegisterDateTimeFunctions(db);
if( !db->mallocFailed ){
int rc = sqlite3_overload_function(db, "MATCH", 2);
@ -1326,11 +1233,6 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
#ifdef SQLITE_SSE
(void)sqlite3SseFunctions(db);
#endif
#ifdef SQLITE_CASE_SENSITIVE_LIKE
sqlite3RegisterLikeFunctions(db, 1);
#else
sqlite3RegisterLikeFunctions(db, 0);
#endif
}
/*
@ -1397,3 +1299,126 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
*pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0;
return 1;
}
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
** used to create the literal values used for the FuncDef structures in
** the global aBuiltinFunc[] array (see below).
**
** FUNCTION(zName, nArg, iArg, bNC, xFunc)
** Used to create a scalar function definition of a function zName
** implemented by C function xFunc that accepts nArg arguments. The
** value passed as iArg is cast to a (void*) and made available
** as the user-data (sqlite3_user_data()) for the function. If
** argument bNC is true, then the FuncDef.needCollate flag is set.
**
** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
** Used to create an aggregate function definition implemented by
** the C functions xStep and xFinal. The first four parameters
** are interpreted in the same way as the first 4 parameters to
** FUNCTION().
**
** LIKEFUNC(zName, nArg, pArg, flags)
** Used to create a scalar function definition of a function zName
** that accepts nArg arguments and is implemented by a call to C
** function likeFunc. Argument pArg is cast to a (void *) and made
** available as the function user-data (sqlite3_user_data()). The
** FuncDef.flags variable is set to the value passed as the flags
** parameter.
**
** See below for examples.
*/
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_UTF8, bNC, 0, SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName}
#define LIKEFUNC(zName, nArg, arg, flags) \
{nArg, SQLITE_UTF8, 0, flags, (void *)arg, 0, likeFunc, 0, 0, #zName}
#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
{nArg, SQLITE_UTF8, nc, 0, SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal, #zName}
#endif
/*
** This array of FuncDef structures contains most of the "built-in" functions
** and aggregates. Function users (the other routines in the SQL compiler)
** call the following function to access the FuncDef structures stored in
** this array:
**
** int sqlite3GetBuiltinFunction(const char *z, int n, FuncDef **paFunc);
**
** The caller passes the name of the required function and its length
** in parameters z and n, respectively. The value returned is the number
** of FuncDef structures found in the aBuiltinFunc[] array that match
** the requested name. If no match is found, 0 is returned. *paFunc is
** set to point at a static array containing that subset of aBuiltinFunc[]
** before returning.
**
** The implementation of sqlite3GetBuiltinFunction() is generated by
** the program found in tool/mkfunction.c, which is compiled and executed
** as part of the build process. The routine generated by this program
** assumes that if there are two or more entries in the aBuiltinFunc[]
** array with the same name (i.e. two versions of the "max" function),
** then they must be stored in adjacent slots.
*/
static FuncDef aBuiltinFunc[] = {
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
FUNCTION(rtrim, 1, 2, 0, trimFunc ),
FUNCTION(rtrim, 2, 2, 0, trimFunc ),
FUNCTION(trim, 1, 3, 0, trimFunc ),
FUNCTION(trim, 2, 3, 0, trimFunc ),
FUNCTION(min, -1, 0, 1, minmaxFunc ),
FUNCTION(min, 0, 0, 1, 0 ),
AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
FUNCTION(max, -1, 1, 1, minmaxFunc ),
FUNCTION(max, 0, 1, 1, 0 ),
AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
FUNCTION(typeof, 1, 0, 0, typeofFunc ),
FUNCTION(length, 1, 0, 0, lengthFunc ),
FUNCTION(substr, 2, 0, 0, substrFunc ),
FUNCTION(substr, 3, 0, 0, substrFunc ),
FUNCTION(abs, 1, 0, 0, absFunc ),
FUNCTION(round, 1, 0, 0, roundFunc ),
FUNCTION(round, 2, 0, 0, roundFunc ),
FUNCTION(upper, 1, 0, 0, upperFunc ),
FUNCTION(lower, 1, 0, 0, lowerFunc ),
FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, -1, 0, 0, ifnullFunc ),
FUNCTION(coalesce, 0, 0, 0, 0 ),
FUNCTION(hex, 1, 0, 0, hexFunc ),
FUNCTION(ifnull, 2, 0, 1, ifnullFunc ),
FUNCTION(random, -1, 0, 0, randomFunc ),
FUNCTION(randomblob, 1, 0, 0, randomBlob ),
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
FUNCTION(quote, 1, 0, 0, quoteFunc ),
FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
FUNCTION(changes, 0, 0, 0, changes ),
FUNCTION(total_changes, 0, 0, 0, total_changes ),
FUNCTION(replace, 3, 0, 0, replaceFunc ),
FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
#ifdef SQLITE_SOUNDEX
FUNCTION(soundex, 1, 0, 0, soundexFunc ),
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
FUNCTION(load_extension, 1, 0, 0, loadExt ),
FUNCTION(load_extension, 2, 0, 0, loadExt ),
#endif
AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
AGGREGATE(count, 0, 0, 0, countStep, countFinalize ),
AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
AGGREGATE(group_concat, -1, 0, 0, groupConcatStep, groupConcatFinalize),
LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
#ifdef SQLITE_CASE_SENSITIVE_LIKE
LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
#else
LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
#endif
};

@ -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.488 2008/08/12 15:21:12 drh Exp $
** $Id: main.c,v 1.489 2008/08/20 14:49:24 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -148,6 +148,11 @@ int sqlite3_initialize(void){
if( sqlite3Config.isInit==0 && inProgress==0 ){
inProgress = 1;
rc = sqlite3_os_init();
if( rc==SQLITE_OK ){
rc = sqlite3PcacheInitialize();
sqlite3PCacheBufferSetup(sqlite3Config.pPage, sqlite3Config.szPage,
sqlite3Config.nPage);
}
inProgress = 0;
sqlite3Config.isInit = (rc==SQLITE_OK ? 1 : 0);
}
@ -193,6 +198,7 @@ int sqlite3_initialize(void){
*/
int sqlite3_shutdown(void){
sqlite3Config.isMallocInit = 0;
sqlite3PcacheShutdown();
if( sqlite3Config.isInit ){
sqlite3_os_end();
}

@ -12,7 +12,7 @@
**
** Memory allocation functions used throughout sqlite.
**
** $Id: malloc.c,v 1.34 2008/08/05 17:53:23 drh Exp $
** $Id: malloc.c,v 1.35 2008/08/20 14:49:24 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
@ -382,6 +382,7 @@ void sqlite3ScratchFree(void *p){
** and that memory is of the right size and is not completely
** consumed. Otherwise, failover to sqlite3Malloc().
*/
#if 0
void *sqlite3PageMalloc(int n){
void *p;
assert( n>0 );
@ -462,6 +463,7 @@ void sqlite3PageFree(void *p){
}
}
}
#endif
/*
** TRUE if p is a lookaside memory allocation from db

File diff suppressed because it is too large Load Diff

@ -13,7 +13,7 @@
** subsystem. The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
** @(#) $Id: pager.h,v 1.77 2008/07/16 18:17:56 danielk1977 Exp $
** @(#) $Id: pager.h,v 1.78 2008/08/20 14:49:25 danielk1977 Exp $
*/
#ifndef _PAGER_H_
@ -70,7 +70,7 @@ typedef struct PgHdr DbPage;
** See source code comments for a detailed description of the following
** routines:
*/
int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int);
int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, void(*)(DbPage*), int,int,int);
void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler);
void sqlite3PagerSetDestructor(Pager*, void(*)(DbPage*,int));
void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int));
@ -113,6 +113,7 @@ int sqlite3PagerJournalMode(Pager *, int);
i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
void *sqlite3PagerTempSpace(Pager*);
int sqlite3PagerSync(Pager *pPager);
void sqlite3PagerAlwaysRollback(Pager *pPager);
#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
int sqlite3PagerReleaseMemory(int);

1132
src/pcache.c Normal file

File diff suppressed because it is too large Load Diff

175
src/pcache.h Normal file

@ -0,0 +1,175 @@
/*
** 2008 August 05
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the sqlite page cache
** subsystem.
**
** @(#) $Id: pcache.h,v 1.1 2008/08/20 14:49:25 danielk1977 Exp $
*/
#ifndef _PCACHE_H_
typedef struct PgHdr PgHdr;
typedef struct PCache PCache;
/*
** Every page in the cache is controlled by an instance of the following
** structure.
*/
struct PgHdr {
u32 flags; /* PGHDR flags defined below */
void *pData; /* Content of this page */
void *pExtra; /* Extra content */
PgHdr *pDirty; /* Transient list of dirty pages */
Pgno pgno; /* Page number for this page */
Pager *pPager;
#ifdef SQLITE_CHECK_PAGES
u32 pageHash;
#endif
/*** Public data is above. All that follows is private to pcache.c ***/
PCache *pCache; /* Cache that owns this page */
PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */
PgHdr *pNext, *pPrev; /* List of clean or dirty pages */
PgHdr *pNextLru, *pPrevLru; /* Part of global LRU list */
int nRef; /* Number of users of this page */
void *apSave[2]; /* Journal entries for in-memory databases */
};
/* Bit values for PgHdr.flags */
#define PGHDR_IN_JOURNAL 0x001 /* Page is in rollback journal */
#define PGHDR_IN_STMTJRNL 0x002 /* Page is in the statement journal */
#define PGHDR_DIRTY 0x004 /* Page has changed */
#define PGHDR_NEED_SYNC 0x008 /* Peed to fsync this page */
#define PGHDR_ALWAYS_ROLLBACK 0x010 /* Force writing to journal */
#define PGHDR_NEED_READ 0x020 /* Content is unread */
#define PGHDR_IS_INIT 0x040 /* pData is initialized */
#define PGHDR_REUSE_UNLIKELY 0x080 /* Hint: Reuse is unlikely */
/* Initialize and shutdown the page cache subsystem */
int sqlite3PcacheInitialize(void);
void sqlite3PcacheShutdown(void);
/* Page cache buffer management:
** These routines implement SQLITE_CONFIG_PAGECACHE.
*/
void sqlite3PCacheBufferSetup(void *, int sz, int n);
void *sqlite3PCacheMalloc(int sz);
void sqlite3PCacheFree(void*);
/* Create a new pager cache.
** Under memory stress, invoke xStress to try to make pages clean.
** Only clean and unpinned pages can be reclaimed.
*/
void sqlite3PcacheOpen(
int szPage, /* Size of every page */
int szExtra, /* Extra space associated with each page */
int bPurgeable, /* True if pages are on backing store */
void (*xDestroy)(PgHdr *), /* Called to destroy a page */
int (*xStress)(void*), /* Call to try to make pages clean */
void *pStress, /* Argument to xStress */
PCache *pToInit /* Preallocated space for the PCache */
);
/* Modify the page-size after the cache has been created. */
void sqlite3PcacheSetPageSize(PCache *, int);
/* Return the size in bytes of a PCache object. Used to preallocate
** storage space.
*/
int sqlite3PcacheSize(void);
/* One release per successful fetch. Page is pinned until released.
** Reference counted.
*/
int sqlite3PcacheFetch(PCache*, Pgno, int createFlag, PgHdr**);
void sqlite3PcacheRelease(PgHdr*);
void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */
void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */
void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */
void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */
/* Change a page number. Used by incr-vacuum. */
void sqlite3PcacheMove(PgHdr*, Pgno);
/* Set a global maximum page count for all page caches.
** If the sum of individual cache maxes exceed the global max, the
** individuals are scaled down proportionally.
*/
void sqlite3PcacheGlobalMax(int N);
/* Remove all pages with pgno>x. Reset the cache if x==0 */
void sqlite3PcacheTruncate(PCache*, Pgno x);
/* Routines used to implement transactions on memory-only databases. */
int sqlite3PcachePreserve(PgHdr*, int); /* Preserve current page content */
void sqlite3PcacheCommit(PCache*, int); /* Drop preserved copy */
void sqlite3PcacheRollback(PCache*, int); /* Rollback to preserved copy */
/* Get a list of all dirty pages in the cache, sorted by page number */
PgHdr *sqlite3PcacheDirtyList(PCache*);
/* Query the cache for a dirty page with a zero ref-count */
PgHdr *sqlite3PcacheDirtyPage(PCache *);
/* Reset and close the cache object */
void sqlite3PcacheClose(PCache*);
/* Set flags on all pages in the page cache */
void sqlite3PcacheSetFlags(PCache*, int andMask, int orMask);
/* Assert flags settings on all pages. Debugging only */
void sqlite3PcacheAssertFlags(PCache*, int trueMask, int falseMask);
/* Return true if the number of dirty pages is 0 or 1 */
int sqlite3PcacheZeroOrOneDirtyPages(PCache*);
/* Discard the contents of the cache */
int sqlite3PcacheClear(PCache*);
/* Return the total number of outstanding page references */
int sqlite3PcacheRefCount(PCache*);
/* Increment the reference count of an existing page */
void sqlite3PcacheRef(PgHdr*);
/* Return the total number of pages stored in the cache */
int sqlite3PcachePagecount(PCache*);
/* Iterate through all pages currently stored in the cache. This interface
** is only available if SQLITE_CHECK_PAGES is defined when the library is
** built.
*/
void sqlite3PcacheIterate(PCache *pCache, void (*xIter)(PgHdr *));
/* Set and get the suggested cache-size for the specified pager-cache. If
** a global maximum on the number of pages cached by the system is
** configured via the sqlite3PcacheGlobalMax() API, then the suggested
** cache-sizes are not used at all.
**
** If no global maximum is configured, then the system attempts to limit
** the total number of pages cached by purgeable pager-caches to the sum
** of the suggested cache-sizes.
*/
int sqlite3PcacheGetCachesize(PCache *);
void sqlite3PcacheSetCachesize(PCache *, int);
/* Lock and unlock a pager-cache object. The PcacheLock() function may
** block if the lock is temporarily available. While a pager-cache is locked,
** the system guarantees that any configured xStress() callback will not
** be invoked by any thread other than the one holding the lock.
*/
void sqlite3PcacheLock(PCache *);
void sqlite3PcacheUnlock(PCache *);
#endif /* _PCACHE_H_ */

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.755 2008/08/13 19:11:48 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.756 2008/08/20 14:49:25 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -482,6 +482,7 @@ typedef struct WhereLevel WhereLevel;
#include "btree.h"
#include "vdbe.h"
#include "pager.h"
#include "pcache.h"
#include "os.h"
#include "mutex.h"
@ -757,7 +758,7 @@ struct FuncDef {
void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */
void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */
void (*xFinalize)(sqlite3_context*); /* Aggregate finializer */
char zName[1]; /* SQL name of the function. MUST BE LAST */
char *zName; /* SQL name of the function. */
};
/*
@ -1932,6 +1933,7 @@ int sqlite3IsNaN(double);
void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
char *sqlite3MPrintf(sqlite3*,const char*, ...);
char *sqlite3MAppendf(sqlite3 *, char *, const char *, ...);
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
@ -2081,6 +2083,7 @@ Select *sqlite3SelectDup(sqlite3*,Select*);
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int);
void sqlite3RegisterBuiltinFunctions(sqlite3*);
void sqlite3RegisterDateTimeFunctions(sqlite3*);
int sqlite3GetBuiltinFunction(const char *, int, FuncDef **);
#ifdef SQLITE_DEBUG
int sqlite3SafetyOn(sqlite3*);
int sqlite3SafetyOff(sqlite3*);

@ -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.318 2008/08/12 15:04:59 danielk1977 Exp $
** $Id: test1.c,v 1.319 2008/08/20 14:49:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@ -4686,7 +4686,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
extern int sqlite3_pager_readdb_count;
extern int sqlite3_pager_writedb_count;
extern int sqlite3_pager_writej_count;
extern int sqlite3_pager_pgfree_count;
#if SQLITE_OS_UNIX && defined(SQLITE_TEST) && SQLITE_THREADSAFE
extern int threadsOverrideEachOthersLocks;
#endif
@ -4733,8 +4732,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
(char*)&sqlite3_pager_writedb_count, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite3_pager_writej_count",
(char*)&sqlite3_pager_writej_count, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite3_pager_pgfree_count",
(char*)&sqlite3_pager_pgfree_count, TCL_LINK_INT);
#ifndef SQLITE_OMIT_UTF16
Tcl_LinkVar(interp, "unaligned_string_counter",
(char*)&unaligned_string_counter, TCL_LINK_INT);

@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
** $Id: test2.c,v 1.59 2008/07/12 14:52:20 drh Exp $
** $Id: test2.c,v 1.60 2008/08/20 14:49:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@ -78,7 +78,7 @@ static int pager_open(
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
rc = sqlite3PagerOpen(sqlite3_vfs_find(0), &pPager, argv[1], 0, 0,
rc = sqlite3PagerOpen(sqlite3_vfs_find(0), &pPager, argv[1], 0, 0, 0,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
@ -382,6 +382,26 @@ static int page_lookup(
return TCL_OK;
}
/*
** Usage: pcache_global_max NPAGE
*/
static int pcache_global_max(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
const char **argv /* Text of each argument */
){
int nPage;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" NPAGE\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], &nPage) ) return TCL_ERROR;
sqlite3PcacheGlobalMax(nPage);
return TCL_OK;
}
/*
** Usage: pager_truncate ID PGNO
*/
@ -630,6 +650,7 @@ int Sqlitetest2_Init(Tcl_Interp *interp){
{ "page_write", (Tcl_CmdProc*)page_write },
{ "page_number", (Tcl_CmdProc*)page_number },
{ "pager_truncate", (Tcl_CmdProc*)pager_truncate },
{ "pcache_global_max", (Tcl_CmdProc*)pcache_global_max },
#ifndef SQLITE_OMIT_DISKIO
{ "fake_big_file", (Tcl_CmdProc*)fake_big_file },
#endif

@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
** $Id: test8.c,v 1.73 2008/08/12 14:48:41 danielk1977 Exp $
** $Id: test8.c,v 1.74 2008/08/20 14:49:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@ -96,8 +96,7 @@ static int simulateVtabError(echo_vtab *p, const char *zMethod){
const char *zErr;
char zVarname[128];
zVarname[127] = '\0';
sqlite3_snprintf(127, zVarname,
"echo_module_fail(%s,%s)", zMethod, p->zTableName);
snprintf(zVarname, 127, "echo_module_fail(%s,%s)", zMethod, p->zTableName);
zErr = Tcl_GetVar(p->interp, zVarname, TCL_GLOBAL_ONLY);
if( zErr ){
p->base.zErrMsg = sqlite3_mprintf("echo-vtab-error: %s", zErr);

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to help implement virtual tables.
**
** $Id: vtab.c,v 1.74 2008/08/02 03:50:39 drh Exp $
** $Id: vtab.c,v 1.75 2008/08/20 14:49:25 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"
@ -807,6 +807,7 @@ FuncDef *sqlite3VtabOverloadFunction(
return pDef;
}
*pNew = *pDef;
pNew->zName = (char *)&pNew[1];
memcpy(pNew->zName, pDef->zName, strlen(pDef->zName)+1);
pNew->xFunc = xFunc;
pNew->pUserData = pArg;

@ -13,7 +13,7 @@
# IO traffic generated by SQLite (making sure SQLite is not writing out
# more database pages than it has to, stuff like that).
#
# $Id: io.test,v 1.17 2008/07/30 17:28:04 drh Exp $
# $Id: io.test,v 1.18 2008/08/20 14:49:25 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -383,6 +383,7 @@ ifcapable pager_pragmas {
execsql { CREATE TABLE abc(a, b) }
nSync
execsql {
PRAGMA temp_store = memory;
PRAGMA cache_size = 10;
BEGIN;
INSERT INTO abc VALUES('hello', 'world');

@ -15,7 +15,7 @@
# The tests in this file use special facilities that are only
# available in the SQLite test fixture.
#
# $Id: ioerr2.test,v 1.8 2008/07/08 15:59:52 danielk1977 Exp $
# $Id: ioerr2.test,v 1.9 2008/08/20 14:49:25 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -115,11 +115,12 @@ foreach bPersist [list 0 1] {
do_test ioerr2-5 {
execsql {
CREATE TABLE t2 AS SELECT * FROM t1;
PRAGMA temp_store = memory;
}
set ::sqlite_io_error_persist 0
set ::go 1
set rc [catch {
for {set ::N 1} {$::N<200} {incr ::N} {
for {set ::N 2} {$::N<200} {incr ::N} {
db eval {SELECT * FROM t1 WHERE rowid IN (1, 5, 10, 15, 20)} {
set ::sqlite_io_error_hit 0
set ::sqlite_io_error_pending $::N

@ -11,7 +11,7 @@
#
# This file contains tests of the memory allocation subsystem
#
# $Id: memsubsys1.test,v 1.9 2008/08/12 15:21:12 drh Exp $
# $Id: memsubsys1.test,v 1.10 2008/08/20 14:49:25 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -60,6 +60,8 @@ proc reset_highwater_marks {} {
sqlite3_status SQLITE_STATUS_PARSER_STACK 1
}
set xtra_size 256
# Test 1: Both PAGECACHE and SCRATCH are shut down.
#
db close
@ -81,7 +83,7 @@ set max_pagecache [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 1024 20
sqlite3_config_pagecache [expr 1024+$xtra_size] 20
sqlite3_initialize
reset_highwater_marks
build_test_db memsubsys1-2 {PRAGMA page_size=1024}
@ -89,8 +91,11 @@ build_test_db memsubsys1-2 {PRAGMA page_size=1024}
do_test memsubsys1-2.3 {
set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
expr {$pg_used*1024 + $pg_ovfl}
} $max_pagecache
expr {
($pg_used*1024 + $pg_ovfl) < $max_pagecache &&
($pg_used*(1024+$xtra_size) + $pg_ovfl) >= $max_pagecache
}
} 1
do_test memsubsys1-2.4 {
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} 19
@ -103,7 +108,7 @@ do_test memsubsys1-2.5 {
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 512 20
sqlite3_config_pagecache [expr 512+$xtra_size] 20
sqlite3_initialize
reset_highwater_marks
build_test_db memsubsys1-3.1 {PRAGMA page_size=1024}
@ -119,7 +124,7 @@ do_test memsubsys1-3.1.5 {
} 0
db close
sqlite3_shutdown
sqlite3_config_pagecache 2048 20
sqlite3_config_pagecache [expr 2048+$xtra_size] 20
sqlite3_initialize
reset_highwater_marks
build_test_db memsubsys1-3.2 {PRAGMA page_size=2048}
@ -138,7 +143,7 @@ do_test memsubsys1-3.2.5 {
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 1024 50
sqlite3_config_pagecache [expr 1024+$xtra_size] 50
sqlite3_config_scratch 6000 2
sqlite3_initialize
reset_highwater_marks
@ -150,8 +155,11 @@ do_test memsubsys1-4.3 {
do_test memsubsys1-4.4 {
set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
expr {$pg_used*1024 + $pg_ovfl}
} $max_pagecache
expr {
($pg_used*1024 + $pg_ovfl) < $max_pagecache &&
($pg_used*(1024+$xtra_size) + $pg_ovfl) >= $max_pagecache
}
} 1
do_test memsubsys1-4.5 {
set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
expr {$maxreq<7000}
@ -165,7 +173,7 @@ do_test memsubsys1-4.6 {
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 4096 24
sqlite3_config_pagecache [expr 4096+$xtra_size] 24
sqlite3_config_scratch 6000 2
sqlite3_initialize
reset_highwater_marks
@ -191,7 +199,7 @@ do_test memsubsys1-5.6 {
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 4096 24
sqlite3_config_pagecache [expr 4096+$xtra_size] 24
sqlite3_config_scratch 25000 1
sqlite3_initialize
reset_highwater_marks
@ -202,7 +210,8 @@ do_test memsubsys1-6.3 {
} 23
do_test memsubsys1-6.4 {
set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
} 4096
expr {$maxreq>4096 && $maxreq<(4096+$xtra_size)}
} 1
do_test memsubsys1-6.5 {
set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 1
@ -216,14 +225,13 @@ do_test memsubsys1-6.6 {
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 4096 24
sqlite3_config_pagecache [expr 4096+$xtra_size] 24
sqlite3_config_scratch 25000 1
sqlite3_initialize
pcache_global_max 15
reset_highwater_marks
build_test_db memsubsys1-7 {
PRAGMA page_size=4096;
PRAGMA cache_size=10;
PRAGMA temp_cache_size=10;
}
#show_memstats
do_test memsubsys1-7.3 {
@ -243,6 +251,7 @@ do_test memsubsys1-7.6 {
do_test memsubsys1-7.7 {
set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
} 0
pcache_global_max 0
db close
sqlite3_shutdown

@ -9,7 +9,7 @@
#
#***********************************************************************
#
# $Id: mutex1.test,v 1.10 2008/07/15 00:27:35 drh Exp $
# $Id: mutex1.test,v 1.11 2008/08/20 14:49:25 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -96,8 +96,8 @@ set enable_shared_cache [sqlite3_enable_shared_cache 1]
ifcapable threadsafe {
foreach {mode mutexes} {
singlethread {}
multithread {fast static_master static_mem static_prng}
serialized {fast recursive static_master static_mem static_prng}
multithread {fast static_lru static_master static_mem static_mem2 static_prng }
serialized {fast recursive static_lru static_master static_mem static_mem2 static_prng }
} {
ifcapable memorymanage {
if {$mode ne "singlethread"} {

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this script is page cache subsystem.
#
# $Id: pager.test,v 1.30 2007/08/24 16:29:24 drh Exp $
# $Id: pager.test,v 1.31 2008/08/20 14:49:25 danielk1977 Exp $
set testdir [file dirname $argv0]
@ -76,13 +76,13 @@ do_test pager-2.3.4 {
expr {$::gx!=""}
} {1}
do_test pager-2.3.5 {
page_unref $::gx
pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.3.6 {
expr {$::g1==$::gx}
} {1}
do_test pager-2.3.7 {
page_unref $::gx
pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.4 {
@ -184,6 +184,7 @@ do_test pager-2.29 {
page_read $::g1
} {Page-One}
do_test pager-2.99 {
page_unref $::g1
pager_close $::p1
} {}
@ -214,6 +215,7 @@ do_test pager-3.5 {
page_unref $gx
}
pager_commit $::p1
page_unref $::g(1)
} {}
for {set i 2} {$i<=20} {incr i} {
do_test pager-3.6.[expr {$i-1}] [subst {
@ -427,6 +429,7 @@ ifcapable memorydb {
}
do_test pager-4.99 {
page_unref $::g1
pager_close $::p1
} {}

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this script is page cache subsystem.
#
# $Id: pager2.test,v 1.6 2007/03/23 18:12:07 danielk1977 Exp $
# $Id: pager2.test,v 1.7 2008/08/20 14:49:25 danielk1977 Exp $
set testdir [file dirname $argv0]
@ -75,6 +75,7 @@ do_test pager2-2.3.3 {
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager2-2.3.4 {
set ::gx [page_lookup $::p1 1]
page_unref $::gx
expr {$::gx!=""}
} {1}
do_test pager2-2.3.5 {
@ -84,7 +85,6 @@ do_test pager2-2.3.6 {
expr {$::g1==$::gx}
} {1}
do_test pager2-2.3.7 {
page_unref $::gx
pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager2-2.4 {
@ -181,9 +181,9 @@ do_test pager2-2.29 {
set ::g1 [page_get $::p1 1]
page_read $::g1
} {Page-One}
#do_test pager2-2.99 {
# pager_close $::p1
#} {}
do_test pager2-2.99 {
page_unref $::g1
} {}
#do_test pager2-3.1 {
# set v [catch {
@ -212,6 +212,7 @@ do_test pager2-3.5 {
page_unref $gx
}
pager_commit $::p1
page_unref $::g(1)
} {}
for {set i 2} {$i<=20} {incr i} {
do_test pager2-3.6.[expr {$i-1}] [subst {
@ -337,6 +338,7 @@ for {set i 1} {$i<20} {incr i} {
}
set res
} {}
breakpoint
do_test pager2-4.5.$i.5 {
page_write $g1 "Page-1 v$i"
lrange [pager_stats $p1] 8 9
@ -398,6 +400,7 @@ for {set i 1} {$i<20} {incr i} {
}
do_test pager2-4.99 {
page_unref $::g1
pager_close $::p1
} {}

@ -12,7 +12,7 @@
# The focus of the tests in this file are to verify that the
# pager optimizations implemented in version 3.3.14 work.
#
# $Id: pageropt.test,v 1.4 2008/04/14 01:00:58 drh Exp $
# $Id: pageropt.test,v 1.5 2008/08/20 14:49:25 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -39,12 +39,10 @@ proc pagercount_sql {sql {db db}} {
set sqlite3_pager_readdb_count 0
set sqlite3_pager_writedb_count 0
set sqlite3_pager_writej_count 0
set sqlite3_pager_pgfree_count 0
set r [$db eval $sql]
set cnt [list $sqlite3_pager_readdb_count \
$sqlite3_pager_writedb_count \
$sqlite3_pager_writej_count \
$sqlite3_pager_pgfree_count]
$sqlite3_pager_writej_count ]
return [concat $cnt $r]
}
@ -59,12 +57,12 @@ do_test pageropt-1.1 {
pagercount_sql {
CREATE TABLE t1(x);
}
} {0 2 0 0}
} {0 2 0}
do_test pageropt-1.2 {
pagercount_sql {
INSERT INTO t1 VALUES(randomblob(5000));
}
} {0 6 2 0}
} {0 6 2}
# Verify that values remain in cache on for subsequent reads.
# We should not have to go back to disk.
@ -73,7 +71,7 @@ do_test pageropt-1.3 {
pagercount_sql {
SELECT length(x) FROM t1
}
} {0 0 0 0 5000}
} {0 0 0 5000}
# If another thread reads the database, the original cache
# remains valid.
@ -84,7 +82,7 @@ do_test pageropt-1.4 {
pagercount_sql {
SELECT hex(x) FROM t1
}
} [list 0 0 0 0 $blobcontent]
} [list 0 0 0 $blobcontent]
# But if the other thread modifies the database, then the cache
# must refill.
@ -94,12 +92,12 @@ do_test pageropt-1.5 {
pagercount_sql {
SELECT hex(x) FROM t1
}
} [list 6 0 0 6 $blobcontent]
} [list 6 0 0 $blobcontent]
do_test pageropt-1.6 {
pagercount_sql {
SELECT hex(x) FROM t1
}
} [list 0 0 0 0 $blobcontent]
} [list 0 0 0 $blobcontent]
# Verify that the last page of an overflow chain is not read from
# disk when deleting a row. The one row of t1(x) has four pages
@ -117,7 +115,7 @@ do_test pageropt-2.1 {
pagercount_sql {
DELETE FROM t1 WHERE rowid=1
}
} {5 3 3 0}
} {5 3 3}
# When pulling pages off of the freelist, there is no reason
# to actually bring in the old content.
@ -128,12 +126,12 @@ do_test pageropt-2.2 {
pagercount_sql {
INSERT INTO t1 VALUES(randomblob(1500));
}
} {3 4 3 0}
} {3 4 3}
do_test pageropt-2.3 {
pagercount_sql {
INSERT INTO t1 VALUES(randomblob(1500));
}
} {0 4 3 0}
} {0 4 3}
# Note the new optimization that when pulling the very last page off of the
# freelist we do not read the content of that page.
@ -142,7 +140,7 @@ do_test pageropt-2.4 {
pagercount_sql {
INSERT INTO t1 VALUES(randomblob(1500));
}
} {0 5 3 0}
} {0 5 3}
# Appending a large quantity of data does not involve writing much
# to the journal file.
@ -151,7 +149,7 @@ do_test pageropt-3.1 {
pagercount_sql {
INSERT INTO t2 SELECT * FROM t1;
}
} {1 7 2 0}
} {1 7 2}
# Once again, we do not need to read the last page of an overflow chain
# while deleting.
@ -160,12 +158,12 @@ do_test pageropt-3.2 {
pagercount_sql {
DROP TABLE t2;
}
} {0 2 3 0}
} {0 2 3}
do_test pageropt-3.3 {
pagercount_sql {
DELETE FROM t1;
}
} {0 3 3 0}
} {0 3 3}
# There are now 11 pages on the freelist. Move them all into an
# overflow chain by inserting a single large record. Starting from
@ -180,7 +178,7 @@ do_test pageropt-4.1 {
pagercount_sql {
INSERT INTO t1 VALUES(randomblob(11300))
}
} {3 13 3 0}
} {3 13 3}
# Now we delete that big entries starting from a cold cache and an
# empty freelist. The first 10 of the 11 pages overflow chain have
@ -194,7 +192,7 @@ do_test pageropt-4.2 {
pagercount_sql {
DELETE FROM t1
}
} {12 3 3 0}
} {12 3 3}
sqlite3_soft_heap_limit $soft_limit
catch {db2 close}

@ -9,7 +9,7 @@
#
#***********************************************************************
#
# $Id: shared3.test,v 1.3 2008/06/23 09:50:52 danielk1977 Exp $
# $Id: shared3.test,v 1.4 2008/08/20 14:49:25 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -86,9 +86,11 @@ do_test shared3-2.7 {
catchsql {select count(*) from sqlite_master} db3
} {0 1}
do_test shared3-2.8 {
db3 close
execsql {
INSERT INTO t1 VALUES(10, randomblob(10000))
} db1
sqlite3 db3 $alternative_name
# If the pager-cache is really still limited to 10 pages, then the INSERT
# statement above should have caused the pager to grab an exclusive lock

@ -16,7 +16,7 @@
# any statement other than a COMMIT, an I/O error is returned instead
# of SQLITE_BUSY.
#
# $Id: tkt2409.test,v 1.3 2007/09/12 17:01:45 danielk1977 Exp $
# $Id: tkt2409.test,v 1.4 2008/08/20 14:49:25 danielk1977 Exp $
# Test Outline:
#
@ -25,6 +25,11 @@
# Verify that the transaction is automatically rolled back
# and SQLITE_IOERR_BLOCKED is returned
#
# UPDATE: As of the pcache modifications, failing to upgrade to
# an exclusive lock when attempting a cache-spill is no longer an
# error. The pcache module allocates more space and keeps working
# in memory if this occurs.
#
# tkt-2409-2.*: Cause a cache-spill while updating the change-counter
# during a database COMMIT. Verify that the transaction is not
# rolled back and SQLITE_BUSY is returned.
@ -32,9 +37,14 @@
# tkt-2409-3.*: Similar to 2409-1.*, but using many INSERT statements
# within a transaction instead of just one.
#
# UPDATE: Again, pcache now just keeps working in main memory.
#
# tkt-2409-4.*: Similar to 2409-1.*, but rig it so that the
# INSERT statement starts a statement transaction. Verify that
# SQLOTE_BUSY is returned and the transaction is not rolled back.
# SQLITE_BUSY is returned and the transaction is not rolled back.
#
# UPDATE: This time, SQLITE_BUSY is not returned. pcache just uses
# more malloc()'d memory.
#
set testdir [file dirname $argv0]
@ -69,6 +79,8 @@ proc unread_lock_db {} {
}
}
pcache_global_max 10
# Open the db handle used by [read_lock_db].
#
sqlite3 db2 test.db
@ -86,11 +98,11 @@ do_test tkt2409-1.1 {
BEGIN;
INSERT INTO t1 VALUES($::zShort, $::zLong);
}
} {1 {disk I/O error}}
} {0 {}}
do_test tkt2409-1.2 {
sqlite3_errcode $::DB
} {SQLITE_IOERR+11}
} {SQLITE_OK}
# Check the integrity of the cache.
#
@ -103,8 +115,7 @@ integrity_check tkt2409-1.3
do_test tkt2409-1.4 {
unread_lock_db
catchsql { ROLLBACK }
} {1 {cannot rollback - no transaction is active}}
} {0 {}}
set ::zShort [string repeat 0123456789 1]
set ::zLong [string repeat 0123456789 1500]
@ -139,6 +150,7 @@ do_test tkt2409-2.3 {
}
} {0 {}}
do_test tkt2409-3.1 {
db close
set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
@ -154,11 +166,11 @@ do_test tkt2409-3.1 {
BEGIN;
INSERT INTO t1 SELECT $::zShort, $::zLong;
}
} {1 {database is locked}}
} {0 {}}
do_test tkt2409-3.2 {
sqlite3_errcode $::DB
} {SQLITE_BUSY}
} {SQLITE_OK}
# Check the integrity of the cache.
#
@ -197,11 +209,11 @@ do_test tkt2409-4.1 {
read_lock_db
execsql BEGIN
catchsql $sql
} {1 {disk I/O error}}
} {0 {}}
do_test tkt2409-4.2 {
sqlite3_errcode $::DB
} {SQLITE_IOERR+11}
} {SQLITE_OK}
# Check the integrity of the cache.
#
@ -209,8 +221,9 @@ integrity_check tkt2409-4.3
do_test tkt2409-4.4 {
catchsql { ROLLBACK }
} {1 {cannot rollback - no transaction is active}}
} {0 {}}
pcache_global_max 0
unread_lock_db
db2 close

181
tool/mkfunction.c Normal file

@ -0,0 +1,181 @@
/*
** This file contains a standalone program used to generate C code that
** implements a static hash table to store the definitions of built-in
** SQL functions in SQLite.
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
/*
** The SQLite source file "func.c" is included below.
**
** By defining the 4 macros and typedef below before including "func.c",
** most of the code is excluded. What is left is an array of constant
** strings, aBuiltinFunc[], containing the names of SQLite's built-in
** SQL functions. i.e.:
**
** const char aBuiltinFunc[] = { "like", "glob", "min", "max" ... };
**
** The data from aBuiltinFunc[] is used by this program to create the
** static hash table.
*/
#define CREATE_BUILTIN_HASHTABLE 1
#define FUNCTION(zName,w,x,y,z) #zName
#define AGGREGATE(zName,v,w,x,y,z) #zName
#define LIKEFUNC(zName,x,y,z) #zName
#define FuncDef const char *
#include "func.c"
/* The number of buckets in the static hash table. */
#define HASHSIZE 127
typedef unsigned char u8;
/* An array to map all upper-case characters into their corresponding
** lower-case character.
*/
static const u8 sqlite3UpperToLower[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
252,253,254,255
};
#define UpperToLower sqlite3UpperToLower
int sqlite3StrICmp(const char *zLeft, const char *zRight){
register unsigned char *a, *b;
a = (unsigned char *)zLeft;
b = (unsigned char *)zRight;
while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
return UpperToLower[*a] - UpperToLower[*b];
}
static int hashstring(const char *zName){
int ii;
unsigned int iKey = 0;
for(ii=0; zName[ii]; ii++){
iKey = (iKey<<3) + (u8)sqlite3UpperToLower[(u8)zName[ii]];
}
iKey = iKey%HASHSIZE;
return iKey;
}
static void printarray(const char *zName, u8 *aArray, int nArray){
int ii;
printf(" static u8 %s[%d] = {", zName, nArray);
for(ii=0; ii<nArray; ii++){
if( (ii%16)==0 ){
printf("\n ");
}
printf("%d, ", aArray[ii]);
}
printf("\n };\n");
}
int main(int argc, char **argv){
int nFunc; /* Number of entries in the aBuiltinFunc array */
u8 anFunc[256];
u8 aHash[HASHSIZE];
u8 aNext[256];
int ii;
int iHead;
nFunc = (sizeof(aBuiltinFunc)/sizeof(const char *));
assert(nFunc<256);
memset(aHash, (unsigned char)nFunc, sizeof(aHash));
memset(aNext, (unsigned char)nFunc, sizeof(aNext));
memset(anFunc, 0, sizeof(anFunc));
iHead = -1;
for(ii=0; ii<nFunc; ii++){
int iHash;
if( iHead>=0 && 0==sqlite3StrICmp(aBuiltinFunc[ii], aBuiltinFunc[iHead]) ){
anFunc[iHead]++;
continue;
}else{
/* The routine generated by this program assumes that if there are
** two or more entries in the aBuiltinFunc[] array with the same
** name (i.e. two versions of the "max" function), then they must
** be stored in adjacent slots. The following block detects the
** problem if this is not the case.
*/
int jj;
for(jj=0; jj<ii; jj++){
if( 0==sqlite3StrICmp(aBuiltinFunc[ii], aBuiltinFunc[jj]) ){
fprintf(stderr, "Error in func.c\n");
return -1;
}
}
iHead = ii;
anFunc[iHead] = 1;
}
iHash = hashstring(aBuiltinFunc[ii]);
if( aHash[iHash]!=nFunc ){
int iNext = aHash[iHash];
while( aNext[iNext]!=nFunc ){
iNext = aNext[iNext];
}
aNext[iNext] = ii;
}else{
aHash[iHash] = ii;
}
}
printf(
"int sqlite3GetBuiltinFunction(\n"
" const char *zName, \n"
" int nName, \n"
" FuncDef **paFunc\n"
"){\n"
);
printarray("aHash", aHash, HASHSIZE);
printarray("anFunc", anFunc, nFunc);
printarray("aNext", aNext, nFunc);
printf(" FuncDef *pNoFunc = &aBuiltinFunc[%d];\n", nFunc);
printf(
" unsigned int iKey = 0; /* Hash of case-insensitive string zName. */\n"
" int ii;\n"
" FuncDef *pFunc;\n"
"\n"
" /* Generate the hash of zName */\n"
" for(ii=0; ii<nName; ii++){\n"
" iKey = (iKey<<3) + (u8)sqlite3UpperToLower[(u8)zName[ii]];\n"
" }\n"
" iKey = iKey%%127;\n"
"\n"
" pFunc = &aBuiltinFunc[iKey = aHash[iKey]];\n"
" while( pFunc!=pNoFunc && sqlite3StrNICmp(pFunc->zName, zName, nName) ){\n"
" pFunc = &aBuiltinFunc[iKey = aNext[iKey]];\n"
" }\n"
"\n"
" *paFunc = pFunc;\n"
" return anFunc[iKey];\n"
"}\n"
);
return 0;
}

@ -101,6 +101,7 @@ foreach hdr {
os_os2.h
pager.h
parse.h
pcache.h
rtree.h
sqlite3ext.h
sqlite3.h
@ -231,6 +232,7 @@ foreach file {
os_win.c
bitvec.c
pcache.c
pager.c
btmutex.c
@ -252,7 +254,7 @@ foreach file {
build.c
callback.c
delete.c
func.c
func2.c
insert.c
legacy.c
loadext.c