From a1784c5cf861d050ef48c5036ec0595afc8d23ea Mon Sep 17 00:00:00 2001 From: mtollari Date: Fri, 9 Sep 2016 14:25:28 +0000 Subject: [PATCH] Predisposizione cartelle progetto Campo e caricamento files librerie git-svn-id: svn://10.65.10.50/branches/R_10_00@23238 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- SQLite3/LibX86/sqlite3.def | 205 + SQLite3/LibX86/sqlite3.dll | Bin 0 -> 599419 bytes SQLite3/LibX86/sqlite3.exp | Bin 0 -> 28975 bytes SQLite3/LibX86/sqlite3.lib | Bin 0 -> 48640 bytes SQLite3/include/shell.c | 4814 + SQLite3/include/sqlite3.c | 161623 +++++++++++++++ SQLite3/include/sqlite3.h | 7860 + SQLite3/include/sqlite3ext.h | 527 + doc/Stampe1.doc | Bin 0 -> 47104 bytes doc/Stampe2.doc | Bin 0 -> 46080 bytes doc/Stampe3.doc | Bin 0 -> 133632 bytes doc/classi.doc | Bin 0 -> 44032 bytes doc/clastree.doc | Bin 0 -> 34816 bytes doc/cpp.doc | Bin 0 -> 90112 bytes doc/frmintro.doc | Bin 0 -> 55296 bytes doc/frmlanguage.doc | Bin 0 -> 131072 bytes doc/lezione1.doc | Bin 0 -> 39424 bytes doc/lezione2.doc | Bin 0 -> 30208 bytes doc/umlanguage.doc | Bin 0 -> 117248 bytes wx28X/BuildCVS.txt | 262 + wx28X/Makefile.in | 30500 +++ wx28X/acinclude.m4 | 839 + wx28X/aclocal.m4 | 24 + wx28X/art/addbookm.xpm | 24 + wx28X/art/back.xpm | 21 + wx28X/art/cdrom.xpm | 57 + wx28X/art/copy.xpm | 44 + wx28X/art/cross.xpm | 17 + wx28X/art/cut.xpm | 46 + wx28X/art/deffile.xpm | 54 + wx28X/art/delbookm.xpm | 24 + wx28X/art/delete.xpm | 42 + wx28X/art/dir_up.xpm | 52 + wx28X/art/down.xpm | 21 + wx28X/art/exefile.xpm | 73 + wx28X/art/fileopen.xpm | 57 + wx28X/art/filesave.xpm | 42 + wx28X/art/filesaveas.xpm | 44 + wx28X/art/find.xpm | 62 + wx28X/art/findrepl.xpm | 63 + wx28X/art/floppy.xpm | 39 + wx28X/art/folder.xpm | 43 + wx28X/art/folder_open.xpm | 52 + wx28X/art/forward.xpm | 21 + wx28X/art/harddisk.xpm | 60 + wx28X/art/helpicon.xpm | 44 + wx28X/art/home.xpm | 24 + wx28X/art/htmbook.xpm | 25 + wx28X/art/htmfoldr.xpm | 25 + wx28X/art/htmoptns.xpm | 20 + wx28X/art/htmpage.xpm | 23 + wx28X/art/htmsidep.xpm | 27 + wx28X/art/listview.xpm | 25 + wx28X/art/missimg.xpm | 43 + wx28X/art/new.xpm | 50 + wx28X/art/new_dir.xpm | 43 + wx28X/art/paste.xpm | 46 + wx28X/art/print.xpm | 60 + wx28X/art/quit.xpm | 90 + wx28X/art/redo.xpm | 58 + wx28X/art/removable.xpm | 44 + wx28X/art/repview.xpm | 24 + wx28X/art/tick.xpm | 17 + wx28X/art/tipicon.xpm | 47 + wx28X/art/toparent.xpm | 21 + wx28X/art/undo.xpm | 58 + wx28X/art/up.xpm | 21 + wx28X/art/wxwin.ico | Bin 0 -> 1078 bytes wx28X/art/wxwin16x16.png | Bin 0 -> 1241 bytes wx28X/art/wxwin16x16.xpm | 25 + wx28X/art/wxwin32x32.png | Bin 0 -> 1267 bytes wx28X/art/wxwin32x32.xpm | 41 + wx28X/autoconf_inc.m4 | 976 + wx28X/autogen.sh | 3 + wx28X/build/README.txt | 27 + .../ac_raf_func_which_getservbyname_r.m4 | 78 + .../aclocal/ax_func_which_gethostbyname_r.m4 | 155 + wx28X/build/aclocal/bakefile-dllar.m4 | 483 + wx28X/build/aclocal/bakefile-lang.m4 | 316 + wx28X/build/aclocal/bakefile.m4 | 1176 + wx28X/build/aclocal/cppunit.m4 | 81 + wx28X/build/aclocal/gst-element-check.m4 | 23 + wx28X/build/aclocal/gtk-2.0.m4 | 196 + wx28X/build/aclocal/gtk.m4 | 194 + wx28X/build/aclocal/pkg.m4 | 156 + wx28X/build/aclocal/sdl.m4 | 181 + wx28X/build/autoconf_prepend-include/Makefile | 26 + .../build/autoconf_prepend-include/README.txt | 22 + .../autoconf/autoconf.m4f | 10079 + .../autoconf_prepend-include/autoconf/c.m4 | 1219 + .../autoconf/general.m4 | 2521 + .../autoconf_prepend-include/autoconf/libs.m4 | 498 + .../autoconf/status.m4 | 1604 + wx28X/build/autogen.mk | 66 + wx28X/build/bakefiles/.bakefile_gen.state | Bin 0 -> 891768 bytes wx28X/build/bakefiles/Bakefiles.bkgen | 271 + wx28X/build/bakefiles/Bakefiles.local.bkgen | 4 + wx28X/build/bakefiles/README | 43 + wx28X/build/bakefiles/build_cfg.bkl | 59 + wx28X/build/bakefiles/common.bkl | 792 + wx28X/build/bakefiles/common_contrib.bkl | 50 + wx28X/build/bakefiles/common_samples.bkl | 19 + .../build/bakefiles/common_samples_intree.bkl | 121 + .../bakefiles/common_samples_outoftree.bkl | 43 + wx28X/build/bakefiles/config.bkl | 519 + wx28X/build/bakefiles/expat.bkl | 48 + wx28X/build/bakefiles/files.bkl | 3492 + .../bakefiles/formats/FORMATS.bkmanifest | 28 + wx28X/build/bakefiles/formats/README | 6 + wx28X/build/bakefiles/formats/cbx_unix.bkl | 21 + wx28X/build/bakefiles/formats/cbx_unix.empy | 77 + wx28X/build/bakefiles/formats/rpmspec.bkl | 24 + wx28X/build/bakefiles/formats/rpmspec.empy | 5 + wx28X/build/bakefiles/jpeg.bkl | 80 + wx28X/build/bakefiles/mac_bundles.bkl | 81 + wx28X/build/bakefiles/make_dist.mk | 846 + wx28X/build/bakefiles/monolithic.bkl | 43 + wx28X/build/bakefiles/multilib.bkl | 315 + wx28X/build/bakefiles/odbc.bkl | 45 + wx28X/build/bakefiles/opengl.bkl | 42 + wx28X/build/bakefiles/plugins.bkl | 16 + wx28X/build/bakefiles/plugins_deps.bkl | 21 + wx28X/build/bakefiles/png.bkl | 51 + wx28X/build/bakefiles/regex.bkl | 54 + wx28X/build/bakefiles/tiff.bkl | 89 + wx28X/build/bakefiles/version.bkl | 85 + wx28X/build/bakefiles/wx.bkl | 265 + .../wxpresets/bakefile_quickstart.txt | 269 + .../build/bakefiles/wxpresets/presets/wx.bkl | 67 + .../bakefiles/wxpresets/presets/wx_unix.bkl | 136 + .../bakefiles/wxpresets/presets/wx_win32.bkl | 370 + .../bakefiles/wxpresets/sample/configure.in | 48 + .../bakefiles/wxpresets/sample/minimal.bkl | 19 + .../bakefiles/wxpresets/sample/minimal.cpp | 182 + wx28X/build/bakefiles/wxwin.py | 158 + wx28X/build/bakefiles/zlib.bkl | 49 + wx28X/build/msw/config.bcc | 206 + wx28X/build/msw/config.dmc | 55 + wx28X/build/msw/config.dms | 132 + wx28X/build/msw/config.gcc | 143 + wx28X/build/msw/config.vc | 145 + wx28X/build/msw/config.wat | 136 + .../wxprec_advlib-466edbbe.ipch | Bin 0 -> 393216 bytes .../wxprec_auilib-35a8d62.ipch | Bin 0 -> 393216 bytes .../wxprec_baselib-b511031e.ipch | Bin 0 -> 393216 bytes .../wxprec_corelib-fe85372c.ipch | Bin 0 -> 393216 bytes wx28X/build/msw/makefile.bcc | 12296 ++ wx28X/build/msw/makefile.dmc | 2694 + wx28X/build/msw/makefile.dms | 11418 + wx28X/build/msw/makefile.gcc | 12425 ++ wx28X/build/msw/makefile.vc | 12851 ++ wx28X/build/msw/makefile.wat | 12643 ++ wx28X/build/msw/vc_msw/adv/CL.read.1.tlog | Bin 0 -> 68286 bytes wx28X/build/msw/vc_msw/adv/CL.write.1.tlog | Bin 0 -> 9708 bytes .../build/msw/vc_msw/adv/Lib-link.read.1.tlog | Bin 0 -> 5654 bytes .../msw/vc_msw/adv/Lib-link.write.1.tlog | Bin 0 -> 2812 bytes .../vc_msw/adv/ResolveAssemblyReference.cache | Bin 0 -> 1079 bytes wx28X/build/msw/vc_msw/adv/aboutdlg.obj | Bin 0 -> 30866 bytes wx28X/build/msw/vc_msw/adv/aboutdlgg.obj | Bin 0 -> 300114 bytes wx28X/build/msw/vc_msw/adv/adv.lastbuildstate | 2 + wx28X/build/msw/vc_msw/adv/adv.write.1.tlog | 0 wx28X/build/msw/vc_msw/adv/animatecmn.obj | Bin 0 -> 126412 bytes wx28X/build/msw/vc_msw/adv/animateg.obj | Bin 0 -> 283262 bytes wx28X/build/msw/vc_msw/adv/bmpcboxg.obj | Bin 0 -> 206543 bytes wx28X/build/msw/vc_msw/adv/calctrl.obj | Bin 0 -> 405041 bytes wx28X/build/msw/vc_msw/adv/cl.command.1.tlog | Bin 0 -> 29152 bytes .../msw/vc_msw/adv/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../msw/vc_msw/adv/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../msw/vc_msw/adv/custombuild.write.1.tlog | Bin 0 -> 364 bytes wx28X/build/msw/vc_msw/adv/datavcmn.obj | Bin 0 -> 278223 bytes wx28X/build/msw/vc_msw/adv/datavgen.obj | Bin 0 -> 507462 bytes wx28X/build/msw/vc_msw/adv/datectlg.obj | Bin 0 -> 3521 bytes wx28X/build/msw/vc_msw/adv/datectrl.obj | Bin 0 -> 143911 bytes wx28X/build/msw/vc_msw/adv/dummy.obj | Bin 0 -> 423558 bytes wx28X/build/msw/vc_msw/adv/grid.obj | Bin 0 -> 1347937 bytes wx28X/build/msw/vc_msw/adv/gridctrl.obj | Bin 0 -> 224383 bytes wx28X/build/msw/vc_msw/adv/gridsel.obj | Bin 0 -> 63272 bytes wx28X/build/msw/vc_msw/adv/helpext.obj | Bin 0 -> 133694 bytes wx28X/build/msw/vc_msw/adv/hyperlink.obj | Bin 0 -> 212391 bytes wx28X/build/msw/vc_msw/adv/joystick.obj | Bin 0 -> 56348 bytes wx28X/build/msw/vc_msw/adv/laywin.obj | Bin 0 -> 69770 bytes wx28X/build/msw/vc_msw/adv/lib.command.1.tlog | Bin 0 -> 4238 bytes wx28X/build/msw/vc_msw/adv/odcombo.obj | Bin 0 -> 305939 bytes wx28X/build/msw/vc_msw/adv/propdlg.obj | Bin 0 -> 213903 bytes wx28X/build/msw/vc_msw/adv/sashwin.obj | Bin 0 -> 169832 bytes wx28X/build/msw/vc_msw/adv/sound.obj | Bin 0 -> 43745 bytes wx28X/build/msw/vc_msw/adv/splash.obj | Bin 0 -> 228457 bytes wx28X/build/msw/vc_msw/adv/taskbar.obj | Bin 0 -> 134969 bytes wx28X/build/msw/vc_msw/adv/taskbarcmn.obj | Bin 0 -> 15597 bytes wx28X/build/msw/vc_msw/adv/tipdlg.obj | Bin 0 -> 321275 bytes wx28X/build/msw/vc_msw/adv/wizard.obj | Bin 0 -> 384488 bytes wx28X/build/msw/vc_msw/adv/wx_adv.log | 79 + wx28X/build/msw/vc_msw/aui/CL.read.1.tlog | Bin 0 -> 48500 bytes wx28X/build/msw/vc_msw/aui/CL.write.1.tlog | Bin 0 -> 2474 bytes .../build/msw/vc_msw/aui/Lib-link.read.1.tlog | Bin 0 -> 1594 bytes .../msw/vc_msw/aui/Lib-link.write.1.tlog | Bin 0 -> 802 bytes wx28X/build/msw/vc_msw/aui/aui.lastbuildstate | 2 + wx28X/build/msw/vc_msw/aui/aui.write.1.tlog | 0 wx28X/build/msw/vc_msw/aui/auibar.obj | Bin 0 -> 534307 bytes wx28X/build/msw/vc_msw/aui/auibook.obj | Bin 0 -> 663470 bytes wx28X/build/msw/vc_msw/aui/cl.command.1.tlog | Bin 0 -> 7488 bytes .../msw/vc_msw/aui/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../msw/vc_msw/aui/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../msw/vc_msw/aui/custombuild.write.1.tlog | Bin 0 -> 364 bytes wx28X/build/msw/vc_msw/aui/dockart.obj | Bin 0 -> 147398 bytes wx28X/build/msw/vc_msw/aui/dummy.obj | Bin 0 -> 423558 bytes wx28X/build/msw/vc_msw/aui/floatpane.obj | Bin 0 -> 132841 bytes wx28X/build/msw/vc_msw/aui/framemanager.obj | Bin 0 -> 539294 bytes wx28X/build/msw/vc_msw/aui/lib.command.1.tlog | Bin 0 -> 1178 bytes wx28X/build/msw/vc_msw/aui/tabmdi.obj | Bin 0 -> 284563 bytes wx28X/build/msw/vc_msw/aui/wx_aui.log | 39 + wx28X/build/msw/vc_msw/base/CL.read.1.tlog | Bin 0 -> 117638 bytes wx28X/build/msw/vc_msw/base/CL.write.1.tlog | Bin 0 -> 30800 bytes .../msw/vc_msw/base/Lib-link.read.1.tlog | Bin 0 -> 18334 bytes .../msw/vc_msw/base/Lib-link.write.1.tlog | Bin 0 -> 9084 bytes .../base/ResolveAssemblyReference.cache | Bin 0 -> 818 bytes wx28X/build/msw/vc_msw/base/appbase.obj | Bin 0 -> 74994 bytes wx28X/build/msw/vc_msw/base/arcall.obj | Bin 0 -> 13698 bytes wx28X/build/msw/vc_msw/base/arcfind.obj | Bin 0 -> 8243 bytes wx28X/build/msw/vc_msw/base/archive.obj | Bin 0 -> 29330 bytes .../build/msw/vc_msw/base/base.lastbuildstate | 2 + wx28X/build/msw/vc_msw/base/base.write.1.tlog | 0 wx28X/build/msw/vc_msw/base/basemsw.obj | Bin 0 -> 5491 bytes wx28X/build/msw/vc_msw/base/cl.command.1.tlog | Bin 0 -> 100784 bytes wx28X/build/msw/vc_msw/base/clntdata.obj | Bin 0 -> 7716 bytes wx28X/build/msw/vc_msw/base/cmdline.obj | Bin 0 -> 153555 bytes wx28X/build/msw/vc_msw/base/config.obj | Bin 0 -> 74980 bytes wx28X/build/msw/vc_msw/base/convauto.obj | Bin 0 -> 30964 bytes wx28X/build/msw/vc_msw/base/crashrpt.obj | Bin 0 -> 38364 bytes .../vc_msw/base/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../msw/vc_msw/base/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../msw/vc_msw/base/custombuild.write.1.tlog | Bin 0 -> 364 bytes wx28X/build/msw/vc_msw/base/datetime.obj | Bin 0 -> 299656 bytes wx28X/build/msw/vc_msw/base/datstrm.obj | Bin 0 -> 75576 bytes wx28X/build/msw/vc_msw/base/dde.obj | Bin 0 -> 206400 bytes wx28X/build/msw/vc_msw/base/debughlp.obj | Bin 0 -> 81416 bytes wx28X/build/msw/vc_msw/base/dir.obj | Bin 0 -> 39082 bytes wx28X/build/msw/vc_msw/base/dircmn.obj | Bin 0 -> 59792 bytes wx28X/build/msw/vc_msw/base/dlmsw.obj | Bin 0 -> 50362 bytes wx28X/build/msw/vc_msw/base/dummy.obj | Bin 0 -> 383074 bytes wx28X/build/msw/vc_msw/base/dynarray.obj | Bin 0 -> 132712 bytes wx28X/build/msw/vc_msw/base/dynlib.obj | Bin 0 -> 60338 bytes wx28X/build/msw/vc_msw/base/dynload.obj | Bin 0 -> 123022 bytes wx28X/build/msw/vc_msw/base/encconv.obj | Bin 0 -> 50967 bytes wx28X/build/msw/vc_msw/base/event.obj | Bin 0 -> 80676 bytes wx28X/build/msw/vc_msw/base/extended.obj | Bin 0 -> 8690 bytes wx28X/build/msw/vc_msw/base/ffile.obj | Bin 0 -> 28742 bytes wx28X/build/msw/vc_msw/base/file.obj | Bin 0 -> 46985 bytes wx28X/build/msw/vc_msw/base/fileback.obj | Bin 0 -> 39943 bytes wx28X/build/msw/vc_msw/base/fileconf.obj | Bin 0 -> 225941 bytes wx28X/build/msw/vc_msw/base/filefn.obj | Bin 0 -> 136404 bytes wx28X/build/msw/vc_msw/base/filename.obj | Bin 0 -> 256400 bytes wx28X/build/msw/vc_msw/base/filesys.obj | Bin 0 -> 213639 bytes wx28X/build/msw/vc_msw/base/filtall.obj | Bin 0 -> 7792 bytes wx28X/build/msw/vc_msw/base/filtfind.obj | Bin 0 -> 4694 bytes wx28X/build/msw/vc_msw/base/fmapbase.obj | Bin 0 -> 131888 bytes wx28X/build/msw/vc_msw/base/fs_arc.obj | Bin 0 -> 196952 bytes wx28X/build/msw/vc_msw/base/fs_filter.obj | Bin 0 -> 45155 bytes wx28X/build/msw/vc_msw/base/fs_mem.obj | Bin 0 -> 73656 bytes wx28X/build/msw/vc_msw/base/hash.obj | Bin 0 -> 33845 bytes wx28X/build/msw/vc_msw/base/hashmap.obj | Bin 0 -> 7450 bytes wx28X/build/msw/vc_msw/base/init.obj | Bin 0 -> 52690 bytes wx28X/build/msw/vc_msw/base/intl.obj | Bin 0 -> 352860 bytes wx28X/build/msw/vc_msw/base/ipcbase.obj | Bin 0 -> 23233 bytes .../build/msw/vc_msw/base/lib.command.1.tlog | Bin 0 -> 13812 bytes wx28X/build/msw/vc_msw/base/list.obj | Bin 0 -> 81825 bytes wx28X/build/msw/vc_msw/base/log.obj | Bin 0 -> 101869 bytes wx28X/build/msw/vc_msw/base/longlong.obj | Bin 0 -> 52398 bytes wx28X/build/msw/vc_msw/base/main.obj | Bin 0 -> 25682 bytes wx28X/build/msw/vc_msw/base/memory.obj | Bin 0 -> 2205 bytes wx28X/build/msw/vc_msw/base/mimecmn.obj | Bin 0 -> 150698 bytes wx28X/build/msw/vc_msw/base/mimetype.obj | Bin 0 -> 117639 bytes wx28X/build/msw/vc_msw/base/module.obj | Bin 0 -> 55103 bytes wx28X/build/msw/vc_msw/base/msgout.obj | Bin 0 -> 18628 bytes wx28X/build/msw/vc_msw/base/mslu.obj | Bin 0 -> 2691 bytes wx28X/build/msw/vc_msw/base/mstream.obj | Bin 0 -> 31988 bytes wx28X/build/msw/vc_msw/base/object.obj | Bin 0 -> 29980 bytes wx28X/build/msw/vc_msw/base/platinfo.obj | Bin 0 -> 45954 bytes wx28X/build/msw/vc_msw/base/power.obj | Bin 0 -> 6417 bytes wx28X/build/msw/vc_msw/base/powercmn.obj | Bin 0 -> 8984 bytes wx28X/build/msw/vc_msw/base/process.obj | Bin 0 -> 36645 bytes wx28X/build/msw/vc_msw/base/regconf.obj | Bin 0 -> 80987 bytes wx28X/build/msw/vc_msw/base/regex.obj | Bin 0 -> 48215 bytes wx28X/build/msw/vc_msw/base/registry.obj | Bin 0 -> 146349 bytes wx28X/build/msw/vc_msw/base/snglinst.obj | Bin 0 -> 9382 bytes wx28X/build/msw/vc_msw/base/sstream.obj | Bin 0 -> 26185 bytes wx28X/build/msw/vc_msw/base/stackwalk.obj | Bin 0 -> 49824 bytes wx28X/build/msw/vc_msw/base/stdpaths.obj | Bin 0 -> 60405 bytes wx28X/build/msw/vc_msw/base/stdpbase.obj | Bin 0 -> 48981 bytes wx28X/build/msw/vc_msw/base/stopwatch.obj | Bin 0 -> 15433 bytes wx28X/build/msw/vc_msw/base/strconv.obj | Bin 0 -> 153790 bytes wx28X/build/msw/vc_msw/base/stream.obj | Bin 0 -> 120030 bytes wx28X/build/msw/vc_msw/base/string.obj | Bin 0 -> 170809 bytes wx28X/build/msw/vc_msw/base/sysopt.obj | Bin 0 -> 25813 bytes wx28X/build/msw/vc_msw/base/tarstrm.obj | Bin 0 -> 318399 bytes wx28X/build/msw/vc_msw/base/textbuf.obj | Bin 0 -> 40882 bytes wx28X/build/msw/vc_msw/base/textfile.obj | Bin 0 -> 57183 bytes wx28X/build/msw/vc_msw/base/thread.obj | Bin 0 -> 123795 bytes wx28X/build/msw/vc_msw/base/tokenzr.obj | Bin 0 -> 37957 bytes wx28X/build/msw/vc_msw/base/txtstrm.obj | Bin 0 -> 70026 bytes wx28X/build/msw/vc_msw/base/uri.obj | Bin 0 -> 92727 bytes wx28X/build/msw/vc_msw/base/utils.obj | Bin 0 -> 103318 bytes wx28X/build/msw/vc_msw/base/utilscmn.obj | Bin 0 -> 104956 bytes wx28X/build/msw/vc_msw/base/utilsexc.obj | Bin 0 -> 69369 bytes wx28X/build/msw/vc_msw/base/variant.obj | Bin 0 -> 338545 bytes wx28X/build/msw/vc_msw/base/volume.obj | Bin 0 -> 80235 bytes wx28X/build/msw/vc_msw/base/wfstream.obj | Bin 0 -> 96178 bytes wx28X/build/msw/vc_msw/base/wx_base.log | 214 + wx28X/build/msw/vc_msw/base/wxchar.obj | Bin 0 -> 7473 bytes wx28X/build/msw/vc_msw/base/xti.obj | Bin 0 -> 2193 bytes wx28X/build/msw/vc_msw/base/xtistrm.obj | Bin 0 -> 2205 bytes wx28X/build/msw/vc_msw/base/zipstrm.obj | Bin 0 -> 401760 bytes wx28X/build/msw/vc_msw/base/zstream.obj | Bin 0 -> 94930 bytes wx28X/build/msw/vc_msw/core/CL.read.1.tlog | Bin 0 -> 241138 bytes wx28X/build/msw/vc_msw/core/CL.write.1.tlog | Bin 0 -> 81024 bytes .../msw/vc_msw/core/Lib-link.read.1.tlog | Bin 0 -> 47070 bytes .../msw/vc_msw/core/Lib-link.write.1.tlog | Bin 0 -> 23322 bytes wx28X/build/msw/vc_msw/core/accel.obj | Bin 0 -> 28262 bytes wx28X/build/msw/vc_msw/core/access.obj | Bin 0 -> 2205 bytes wx28X/build/msw/vc_msw/core/accesscmn.obj | Bin 0 -> 2213 bytes wx28X/build/msw/vc_msw/core/anidecod.obj | Bin 0 -> 121490 bytes wx28X/build/msw/vc_msw/core/app.obj | Bin 0 -> 138812 bytes wx28X/build/msw/vc_msw/core/appcmn.obj | Bin 0 -> 117500 bytes wx28X/build/msw/vc_msw/core/artprov.obj | Bin 0 -> 154153 bytes wx28X/build/msw/vc_msw/core/artstd.obj | Bin 0 -> 288781 bytes wx28X/build/msw/vc_msw/core/automtn.obj | Bin 0 -> 70262 bytes wx28X/build/msw/vc_msw/core/bitmap.obj | Bin 0 -> 184579 bytes wx28X/build/msw/vc_msw/core/bmpbase.obj | Bin 0 -> 87752 bytes wx28X/build/msw/vc_msw/core/bmpbuttn.obj | Bin 0 -> 248218 bytes wx28X/build/msw/vc_msw/core/bookctrl.obj | Bin 0 -> 114162 bytes wx28X/build/msw/vc_msw/core/brush.obj | Bin 0 -> 80158 bytes wx28X/build/msw/vc_msw/core/busyinfo.obj | Bin 0 -> 130786 bytes wx28X/build/msw/vc_msw/core/button.obj | Bin 0 -> 144287 bytes wx28X/build/msw/vc_msw/core/buttonbar.obj | Bin 0 -> 2213 bytes wx28X/build/msw/vc_msw/core/caret.obj | Bin 0 -> 10225 bytes wx28X/build/msw/vc_msw/core/checkbox.obj | Bin 0 -> 127495 bytes wx28X/build/msw/vc_msw/core/checklst.obj | Bin 0 -> 146640 bytes wx28X/build/msw/vc_msw/core/choicbkg.obj | Bin 0 -> 199926 bytes wx28X/build/msw/vc_msw/core/choiccmn.obj | Bin 0 -> 63720 bytes wx28X/build/msw/vc_msw/core/choicdgg.obj | Bin 0 -> 264298 bytes wx28X/build/msw/vc_msw/core/choice.obj | Bin 0 -> 156149 bytes wx28X/build/msw/vc_msw/core/cl.command.1.tlog | Bin 0 -> 252530 bytes wx28X/build/msw/vc_msw/core/clipbrd.obj | Bin 0 -> 87501 bytes wx28X/build/msw/vc_msw/core/clipcmn.obj | Bin 0 -> 25340 bytes wx28X/build/msw/vc_msw/core/clrpickercmn.obj | Bin 0 -> 184746 bytes wx28X/build/msw/vc_msw/core/clrpickerg.obj | Bin 0 -> 163811 bytes wx28X/build/msw/vc_msw/core/cmdproc.obj | Bin 0 -> 75988 bytes wx28X/build/msw/vc_msw/core/cmndata.obj | Bin 0 -> 168842 bytes wx28X/build/msw/vc_msw/core/collpaneg.obj | Bin 0 -> 193263 bytes wx28X/build/msw/vc_msw/core/colordlg.obj | Bin 0 -> 109252 bytes wx28X/build/msw/vc_msw/core/colour.obj | Bin 0 -> 24321 bytes wx28X/build/msw/vc_msw/core/colourcmn.obj | Bin 0 -> 58913 bytes wx28X/build/msw/vc_msw/core/combo.obj | Bin 0 -> 281532 bytes wx28X/build/msw/vc_msw/core/combobox.obj | Bin 0 -> 176140 bytes wx28X/build/msw/vc_msw/core/combocmn.obj | Bin 0 -> 370549 bytes wx28X/build/msw/vc_msw/core/combog.obj | Bin 0 -> 5737 bytes wx28X/build/msw/vc_msw/core/containr.obj | Bin 0 -> 58389 bytes wx28X/build/msw/vc_msw/core/control.obj | Bin 0 -> 133936 bytes .../build/msw/vc_msw/core/core.lastbuildstate | 2 + wx28X/build/msw/vc_msw/core/core.write.1.tlog | 0 wx28X/build/msw/vc_msw/core/cshelp.obj | Bin 0 -> 251099 bytes wx28X/build/msw/vc_msw/core/ctrlcmn.obj | Bin 0 -> 105128 bytes wx28X/build/msw/vc_msw/core/ctrlsub.obj | Bin 0 -> 85486 bytes wx28X/build/msw/vc_msw/core/cursor.obj | Bin 0 -> 71886 bytes .../vc_msw/core/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../msw/vc_msw/core/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../msw/vc_msw/core/custombuild.write.1.tlog | Bin 0 -> 364 bytes wx28X/build/msw/vc_msw/core/data.obj | Bin 0 -> 2193 bytes wx28X/build/msw/vc_msw/core/datacmn.obj | Bin 0 -> 12873 bytes wx28X/build/msw/vc_msw/core/dataobj.obj | Bin 0 -> 133265 bytes wx28X/build/msw/vc_msw/core/dc.obj | Bin 0 -> 329271 bytes wx28X/build/msw/vc_msw/core/dcbase.obj | Bin 0 -> 208585 bytes wx28X/build/msw/vc_msw/core/dcbufcmn.obj | Bin 0 -> 32634 bytes wx28X/build/msw/vc_msw/core/dcclient.obj | Bin 0 -> 151272 bytes wx28X/build/msw/vc_msw/core/dcgraph.obj | Bin 0 -> 2205 bytes wx28X/build/msw/vc_msw/core/dcmemory.obj | Bin 0 -> 108440 bytes wx28X/build/msw/vc_msw/core/dcprint.obj | Bin 0 -> 153247 bytes wx28X/build/msw/vc_msw/core/dcpsg.obj | Bin 0 -> 2201 bytes wx28X/build/msw/vc_msw/core/dcscreen.obj | Bin 0 -> 90843 bytes wx28X/build/msw/vc_msw/core/dialog.obj | Bin 0 -> 130191 bytes wx28X/build/msw/vc_msw/core/dialup.obj | Bin 0 -> 139578 bytes wx28X/build/msw/vc_msw/core/dib.obj | Bin 0 -> 53509 bytes wx28X/build/msw/vc_msw/core/dirctrlg.obj | Bin 0 -> 401199 bytes wx28X/build/msw/vc_msw/core/dirdlg.obj | Bin 0 -> 120762 bytes wx28X/build/msw/vc_msw/core/display.obj | Bin 0 -> 93024 bytes wx28X/build/msw/vc_msw/core/dlgcmn.obj | Bin 0 -> 226554 bytes wx28X/build/msw/vc_msw/core/dndcmn.obj | Bin 0 -> 3671 bytes wx28X/build/msw/vc_msw/core/dobjcmn.obj | Bin 0 -> 120474 bytes wx28X/build/msw/vc_msw/core/docmdi.obj | Bin 0 -> 118326 bytes wx28X/build/msw/vc_msw/core/docview.obj | Bin 0 -> 414574 bytes wx28X/build/msw/vc_msw/core/dpycmn.obj | Bin 0 -> 72004 bytes wx28X/build/msw/vc_msw/core/dragimag.obj | Bin 0 -> 142589 bytes wx28X/build/msw/vc_msw/core/dragimgg.obj | Bin 0 -> 178086 bytes wx28X/build/msw/vc_msw/core/dropsrc.obj | Bin 0 -> 47336 bytes wx28X/build/msw/vc_msw/core/droptgt.obj | Bin 0 -> 46497 bytes wx28X/build/msw/vc_msw/core/dseldlg.obj | Bin 0 -> 68196 bytes wx28X/build/msw/vc_msw/core/dummy.obj | Bin 0 -> 423582 bytes wx28X/build/msw/vc_msw/core/effects.obj | Bin 0 -> 123733 bytes wx28X/build/msw/vc_msw/core/enhmeta.obj | Bin 0 -> 147763 bytes wx28X/build/msw/vc_msw/core/event.obj | Bin 0 -> 479991 bytes wx28X/build/msw/vc_msw/core/evtloop.obj | Bin 0 -> 44502 bytes wx28X/build/msw/vc_msw/core/evtloopcmn.obj | Bin 0 -> 17890 bytes wx28X/build/msw/vc_msw/core/fddlgcmn.obj | Bin 0 -> 90904 bytes wx28X/build/msw/vc_msw/core/fdrepdlg.obj | Bin 0 -> 147387 bytes wx28X/build/msw/vc_msw/core/filedlg.obj | Bin 0 -> 155911 bytes wx28X/build/msw/vc_msw/core/filepickercmn.obj | Bin 0 -> 222071 bytes wx28X/build/msw/vc_msw/core/filepickerg.obj | Bin 0 -> 155219 bytes wx28X/build/msw/vc_msw/core/fldlgcmn.obj | Bin 0 -> 135511 bytes wx28X/build/msw/vc_msw/core/font.obj | Bin 0 -> 142951 bytes wx28X/build/msw/vc_msw/core/fontcmn.obj | Bin 0 -> 106336 bytes wx28X/build/msw/vc_msw/core/fontdlg.obj | Bin 0 -> 105477 bytes wx28X/build/msw/vc_msw/core/fontenum.obj | Bin 0 -> 31046 bytes wx28X/build/msw/vc_msw/core/fontenumcmn.obj | Bin 0 -> 26134 bytes wx28X/build/msw/vc_msw/core/fontmap.obj | Bin 0 -> 196002 bytes wx28X/build/msw/vc_msw/core/fontpickercmn.obj | Bin 0 -> 182919 bytes wx28X/build/msw/vc_msw/core/fontpickerg.obj | Bin 0 -> 207163 bytes wx28X/build/msw/vc_msw/core/fontutil.obj | Bin 0 -> 53523 bytes wx28X/build/msw/vc_msw/core/frame.obj | Bin 0 -> 166419 bytes wx28X/build/msw/vc_msw/core/framecmn.obj | Bin 0 -> 165835 bytes wx28X/build/msw/vc_msw/core/fs_mem.obj | Bin 0 -> 32270 bytes wx28X/build/msw/vc_msw/core/gauge95.obj | Bin 0 -> 96771 bytes wx28X/build/msw/vc_msw/core/gaugecmn.obj | Bin 0 -> 60912 bytes wx28X/build/msw/vc_msw/core/gbsizer.obj | Bin 0 -> 90308 bytes wx28X/build/msw/vc_msw/core/gdicmn.obj | Bin 0 -> 226021 bytes wx28X/build/msw/vc_msw/core/gdiimage.obj | Bin 0 -> 142588 bytes wx28X/build/msw/vc_msw/core/gdiobj.obj | Bin 0 -> 2325 bytes wx28X/build/msw/vc_msw/core/geometry.obj | Bin 0 -> 29067 bytes wx28X/build/msw/vc_msw/core/gifdecod.obj | Bin 0 -> 72814 bytes wx28X/build/msw/vc_msw/core/graphcmn.obj | Bin 0 -> 2205 bytes wx28X/build/msw/vc_msw/core/graphics.obj | Bin 0 -> 2381 bytes wx28X/build/msw/vc_msw/core/gsockmsw.obj | Bin 0 -> 14996 bytes wx28X/build/msw/vc_msw/core/helpbase.obj | Bin 0 -> 6196 bytes wx28X/build/msw/vc_msw/core/helpchm.obj | Bin 0 -> 67762 bytes wx28X/build/msw/vc_msw/core/helpwin.obj | Bin 0 -> 50952 bytes wx28X/build/msw/vc_msw/core/icon.obj | Bin 0 -> 63261 bytes wx28X/build/msw/vc_msw/core/iconbndl.obj | Bin 0 -> 69923 bytes wx28X/build/msw/vc_msw/core/imagall.obj | Bin 0 -> 71791 bytes wx28X/build/msw/vc_msw/core/imagbmp.obj | Bin 0 -> 122935 bytes wx28X/build/msw/vc_msw/core/image.obj | Bin 0 -> 317052 bytes wx28X/build/msw/vc_msw/core/imagfill.obj | Bin 0 -> 2205 bytes wx28X/build/msw/vc_msw/core/imaggif.obj | Bin 0 -> 34948 bytes wx28X/build/msw/vc_msw/core/imagiff.obj | Bin 0 -> 2205 bytes wx28X/build/msw/vc_msw/core/imagjpeg.obj | Bin 0 -> 50036 bytes wx28X/build/msw/vc_msw/core/imaglist.obj | Bin 0 -> 153162 bytes wx28X/build/msw/vc_msw/core/imagpcx.obj | Bin 0 -> 66846 bytes wx28X/build/msw/vc_msw/core/imagpng.obj | Bin 0 -> 74816 bytes wx28X/build/msw/vc_msw/core/imagpnm.obj | Bin 0 -> 40053 bytes wx28X/build/msw/vc_msw/core/imagtga.obj | Bin 0 -> 49107 bytes wx28X/build/msw/vc_msw/core/imagtiff.obj | Bin 0 -> 55809 bytes wx28X/build/msw/vc_msw/core/imagxpm.obj | Bin 0 -> 72334 bytes wx28X/build/msw/vc_msw/core/iniconf.obj | Bin 0 -> 75095 bytes wx28X/build/msw/vc_msw/core/layout.obj | Bin 0 -> 45590 bytes wx28X/build/msw/vc_msw/core/lboxcmn.obj | Bin 0 -> 79673 bytes .../build/msw/vc_msw/core/lib.command.1.tlog | Bin 0 -> 35656 bytes wx28X/build/msw/vc_msw/core/listbkg.obj | Bin 0 -> 193148 bytes wx28X/build/msw/vc_msw/core/listbox.obj | Bin 0 -> 278161 bytes wx28X/build/msw/vc_msw/core/listctrl.obj | Bin 0 -> 383930 bytes wx28X/build/msw/vc_msw/core/listctrlcmn.obj | Bin 0 -> 20895 bytes wx28X/build/msw/vc_msw/core/logg.obj | Bin 0 -> 447888 bytes wx28X/build/msw/vc_msw/core/main.obj | Bin 0 -> 18303 bytes wx28X/build/msw/vc_msw/core/matrix.obj | Bin 0 -> 40304 bytes wx28X/build/msw/vc_msw/core/mdi.obj | Bin 0 -> 256424 bytes wx28X/build/msw/vc_msw/core/menu.obj | Bin 0 -> 208806 bytes wx28X/build/msw/vc_msw/core/menucmn.obj | Bin 0 -> 246296 bytes wx28X/build/msw/vc_msw/core/menuitem.obj | Bin 0 -> 59831 bytes wx28X/build/msw/vc_msw/core/metafile.obj | Bin 0 -> 3041 bytes wx28X/build/msw/vc_msw/core/minifram.obj | Bin 0 -> 73568 bytes wx28X/build/msw/vc_msw/core/msgdlg.obj | Bin 0 -> 96997 bytes wx28X/build/msw/vc_msw/core/msgout.obj | Bin 0 -> 14710 bytes wx28X/build/msw/vc_msw/core/mslu.obj | Bin 0 -> 2193 bytes wx28X/build/msw/vc_msw/core/nativdlg.obj | Bin 0 -> 363633 bytes wx28X/build/msw/vc_msw/core/nbkbase.obj | Bin 0 -> 47839 bytes wx28X/build/msw/vc_msw/core/notebook.obj | Bin 0 -> 378580 bytes wx28X/build/msw/vc_msw/core/numdlgg.obj | Bin 0 -> 185547 bytes wx28X/build/msw/vc_msw/core/oleutils.obj | Bin 0 -> 21596 bytes wx28X/build/msw/vc_msw/core/overlaycmn.obj | Bin 0 -> 116863 bytes wx28X/build/msw/vc_msw/core/ownerdrw.obj | Bin 0 -> 174820 bytes wx28X/build/msw/vc_msw/core/palette.obj | Bin 0 -> 35399 bytes wx28X/build/msw/vc_msw/core/panelg.obj | Bin 0 -> 87274 bytes wx28X/build/msw/vc_msw/core/paper.obj | Bin 0 -> 180589 bytes wx28X/build/msw/vc_msw/core/pen.obj | Bin 0 -> 70843 bytes wx28X/build/msw/vc_msw/core/pickerbase.obj | Bin 0 -> 157396 bytes wx28X/build/msw/vc_msw/core/popupcmn.obj | Bin 0 -> 142410 bytes wx28X/build/msw/vc_msw/core/popupwin.obj | Bin 0 -> 15215 bytes wx28X/build/msw/vc_msw/core/printdlg.obj | Bin 0 -> 207515 bytes wx28X/build/msw/vc_msw/core/printps.obj | Bin 0 -> 2205 bytes wx28X/build/msw/vc_msw/core/printwin.obj | Bin 0 -> 60126 bytes wx28X/build/msw/vc_msw/core/prntbase.obj | Bin 0 -> 640758 bytes wx28X/build/msw/vc_msw/core/prntdlgg.obj | Bin 0 -> 351908 bytes wx28X/build/msw/vc_msw/core/progdlgg.obj | Bin 0 -> 215537 bytes wx28X/build/msw/vc_msw/core/quantize.obj | Bin 0 -> 44970 bytes wx28X/build/msw/vc_msw/core/radiobox.obj | Bin 0 -> 201398 bytes wx28X/build/msw/vc_msw/core/radiobut.obj | Bin 0 -> 106387 bytes wx28X/build/msw/vc_msw/core/radiocmn.obj | Bin 0 -> 42953 bytes wx28X/build/msw/vc_msw/core/region.obj | Bin 0 -> 74516 bytes wx28X/build/msw/vc_msw/core/rendcmn.obj | Bin 0 -> 45361 bytes wx28X/build/msw/vc_msw/core/renderer.obj | Bin 0 -> 118194 bytes wx28X/build/msw/vc_msw/core/renderg.obj | Bin 0 -> 235193 bytes wx28X/build/msw/vc_msw/core/rgncmn.obj | Bin 0 -> 117152 bytes wx28X/build/msw/vc_msw/core/scrlwing.obj | Bin 0 -> 179761 bytes wx28X/build/msw/vc_msw/core/scrolbar.obj | Bin 0 -> 110641 bytes wx28X/build/msw/vc_msw/core/selstore.obj | Bin 0 -> 17994 bytes wx28X/build/msw/vc_msw/core/settcmn.obj | Bin 0 -> 4159 bytes wx28X/build/msw/vc_msw/core/settings.obj | Bin 0 -> 62164 bytes wx28X/build/msw/vc_msw/core/sizer.obj | Bin 0 -> 285924 bytes wx28X/build/msw/vc_msw/core/slider95.obj | Bin 0 -> 150328 bytes wx28X/build/msw/vc_msw/core/spinbutt.obj | Bin 0 -> 126217 bytes wx28X/build/msw/vc_msw/core/spinctlg.obj | Bin 0 -> 2213 bytes wx28X/build/msw/vc_msw/core/spinctrl.obj | Bin 0 -> 166377 bytes wx28X/build/msw/vc_msw/core/splitter.obj | Bin 0 -> 174885 bytes wx28X/build/msw/vc_msw/core/srchcmn.obj | Bin 0 -> 6153 bytes wx28X/build/msw/vc_msw/core/srchctlg.obj | Bin 0 -> 387417 bytes wx28X/build/msw/vc_msw/core/statbar.obj | Bin 0 -> 113475 bytes wx28X/build/msw/vc_msw/core/statbmp.obj | Bin 0 -> 149126 bytes wx28X/build/msw/vc_msw/core/statbox.obj | Bin 0 -> 239794 bytes wx28X/build/msw/vc_msw/core/statbr95.obj | Bin 0 -> 103773 bytes wx28X/build/msw/vc_msw/core/statline.obj | Bin 0 -> 93977 bytes wx28X/build/msw/vc_msw/core/stattext.obj | Bin 0 -> 100715 bytes wx28X/build/msw/vc_msw/core/statusbr.obj | Bin 0 -> 112859 bytes wx28X/build/msw/vc_msw/core/stockitem.obj | Bin 0 -> 46649 bytes wx28X/build/msw/vc_msw/core/tabctrl.obj | Bin 0 -> 2197 bytes wx28X/build/msw/vc_msw/core/tbar95.obj | Bin 0 -> 323023 bytes wx28X/build/msw/vc_msw/core/tbarbase.obj | Bin 0 -> 234041 bytes wx28X/build/msw/vc_msw/core/textcmn.obj | Bin 0 -> 141836 bytes wx28X/build/msw/vc_msw/core/textctrl.obj | Bin 0 -> 383341 bytes wx28X/build/msw/vc_msw/core/textdlgg.obj | Bin 0 -> 216852 bytes wx28X/build/msw/vc_msw/core/tglbtn.obj | Bin 0 -> 94855 bytes wx28X/build/msw/vc_msw/core/timer.obj | Bin 0 -> 65470 bytes wx28X/build/msw/vc_msw/core/timercmn.obj | Bin 0 -> 23018 bytes wx28X/build/msw/vc_msw/core/tipwin.obj | Bin 0 -> 110487 bytes wx28X/build/msw/vc_msw/core/toolbkg.obj | Bin 0 -> 204004 bytes wx28X/build/msw/vc_msw/core/tooltip.obj | Bin 0 -> 46694 bytes wx28X/build/msw/vc_msw/core/toplevel.obj | Bin 0 -> 180712 bytes wx28X/build/msw/vc_msw/core/toplvcmn.obj | Bin 0 -> 141989 bytes wx28X/build/msw/vc_msw/core/treebase.obj | Bin 0 -> 125056 bytes wx28X/build/msw/vc_msw/core/treebkg.obj | Bin 0 -> 246312 bytes wx28X/build/msw/vc_msw/core/treectlg.obj | Bin 0 -> 481132 bytes wx28X/build/msw/vc_msw/core/treectrl.obj | Bin 0 -> 369264 bytes wx28X/build/msw/vc_msw/core/utilscmn.obj | Bin 0 -> 207441 bytes wx28X/build/msw/vc_msw/core/utilsgui.obj | Bin 0 -> 46716 bytes wx28X/build/msw/vc_msw/core/uuid.obj | Bin 0 -> 10019 bytes wx28X/build/msw/vc_msw/core/uxtheme.obj | Bin 0 -> 60471 bytes wx28X/build/msw/vc_msw/core/valgen.obj | Bin 0 -> 42807 bytes wx28X/build/msw/vc_msw/core/validate.obj | Bin 0 -> 16328 bytes wx28X/build/msw/vc_msw/core/valtext.obj | Bin 0 -> 54089 bytes wx28X/build/msw/vc_msw/core/vlbox.obj | Bin 0 -> 243920 bytes wx28X/build/msw/vc_msw/core/volume.obj | Bin 0 -> 49339 bytes wx28X/build/msw/vc_msw/core/vscroll.obj | Bin 0 -> 40333 bytes wx28X/build/msw/vc_msw/core/wincmn.obj | Bin 0 -> 370472 bytes wx28X/build/msw/vc_msw/core/window.obj | Bin 0 -> 678070 bytes wx28X/build/msw/vc_msw/core/wx_core.log | 499 + wx28X/build/msw/vc_msw/core/xpmdecod.obj | Bin 0 -> 110435 bytes wx28X/build/msw/vc_msw/dbgrid/CL.read.1.tlog | Bin 0 -> 38498 bytes wx28X/build/msw/vc_msw/dbgrid/CL.write.1.tlog | Bin 0 -> 678 bytes .../msw/vc_msw/dbgrid/Lib-link.read.1.tlog | Bin 0 -> 584 bytes .../msw/vc_msw/dbgrid/Lib-link.write.1.tlog | Bin 0 -> 308 bytes .../build/msw/vc_msw/dbgrid/cl.command.1.tlog | Bin 0 -> 2182 bytes .../vc_msw/dbgrid/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../msw/vc_msw/dbgrid/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../vc_msw/dbgrid/custombuild.write.1.tlog | Bin 0 -> 364 bytes .../msw/vc_msw/dbgrid/dbgrid.lastbuildstate | 2 + wx28X/build/msw/vc_msw/dbgrid/dbgrid.obj | Bin 0 -> 147193 bytes .../msw/vc_msw/dbgrid/dbgrid.write.1.tlog | 0 wx28X/build/msw/vc_msw/dbgrid/dummy.obj | Bin 0 -> 423582 bytes .../msw/vc_msw/dbgrid/lib.command.1.tlog | Bin 0 -> 424 bytes wx28X/build/msw/vc_msw/dbgrid/wx_dbgrid.log | 5 + wx28X/build/msw/vc_msw/gl/CL.read.1.tlog | Bin 0 -> 37392 bytes wx28X/build/msw/vc_msw/gl/CL.write.1.tlog | Bin 0 -> 640 bytes .../build/msw/vc_msw/gl/Lib-link.read.1.tlog | Bin 0 -> 560 bytes .../build/msw/vc_msw/gl/Lib-link.write.1.tlog | Bin 0 -> 288 bytes wx28X/build/msw/vc_msw/gl/cl.command.1.tlog | Bin 0 -> 2130 bytes .../msw/vc_msw/gl/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../msw/vc_msw/gl/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../msw/vc_msw/gl/custombuild.write.1.tlog | Bin 0 -> 364 bytes wx28X/build/msw/vc_msw/gl/dummy.obj | Bin 0 -> 423554 bytes wx28X/build/msw/vc_msw/gl/gl.lastbuildstate | 2 + wx28X/build/msw/vc_msw/gl/gl.write.1.tlog | 0 wx28X/build/msw/vc_msw/gl/glcanvas.obj | Bin 0 -> 2169 bytes wx28X/build/msw/vc_msw/gl/lib.command.1.tlog | Bin 0 -> 392 bytes wx28X/build/msw/vc_msw/gl/wx_gl.log | 28 + wx28X/build/msw/vc_msw/html/CL.read.1.tlog | Bin 0 -> 124068 bytes wx28X/build/msw/vc_msw/html/CL.write.1.tlog | Bin 0 -> 8890 bytes .../msw/vc_msw/html/Lib-link.read.1.tlog | Bin 0 -> 5342 bytes .../msw/vc_msw/html/Lib-link.write.1.tlog | Bin 0 -> 2660 bytes wx28X/build/msw/vc_msw/html/cl.command.1.tlog | Bin 0 -> 26942 bytes .../vc_msw/html/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../msw/vc_msw/html/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../msw/vc_msw/html/custombuild.write.1.tlog | Bin 0 -> 364 bytes wx28X/build/msw/vc_msw/html/dummy.obj | Bin 0 -> 423566 bytes wx28X/build/msw/vc_msw/html/helpbest.obj | Bin 0 -> 68440 bytes wx28X/build/msw/vc_msw/html/helpctrl.obj | Bin 0 -> 205208 bytes wx28X/build/msw/vc_msw/html/helpdata.obj | Bin 0 -> 223568 bytes wx28X/build/msw/vc_msw/html/helpdlg.obj | Bin 0 -> 182601 bytes wx28X/build/msw/vc_msw/html/helpfrm.obj | Bin 0 -> 137806 bytes wx28X/build/msw/vc_msw/html/helpwnd.obj | Bin 0 -> 839677 bytes .../build/msw/vc_msw/html/html.lastbuildstate | 2 + wx28X/build/msw/vc_msw/html/html.write.1.tlog | 0 wx28X/build/msw/vc_msw/html/htmlcell.obj | Bin 0 -> 193538 bytes wx28X/build/msw/vc_msw/html/htmlfilt.obj | Bin 0 -> 82775 bytes wx28X/build/msw/vc_msw/html/htmllbox.obj | Bin 0 -> 282609 bytes wx28X/build/msw/vc_msw/html/htmlpars.obj | Bin 0 -> 206727 bytes wx28X/build/msw/vc_msw/html/htmltag.obj | Bin 0 -> 65057 bytes wx28X/build/msw/vc_msw/html/htmlwin.obj | Bin 0 -> 611372 bytes wx28X/build/msw/vc_msw/html/htmprint.obj | Bin 0 -> 233131 bytes .../build/msw/vc_msw/html/lib.command.1.tlog | Bin 0 -> 4028 bytes wx28X/build/msw/vc_msw/html/m_dflist.obj | Bin 0 -> 60129 bytes wx28X/build/msw/vc_msw/html/m_fonts.obj | Bin 0 -> 177604 bytes wx28X/build/msw/vc_msw/html/m_hline.obj | Bin 0 -> 83147 bytes wx28X/build/msw/vc_msw/html/m_image.obj | Bin 0 -> 274016 bytes wx28X/build/msw/vc_msw/html/m_layout.obj | Bin 0 -> 179919 bytes wx28X/build/msw/vc_msw/html/m_links.obj | Bin 0 -> 129538 bytes wx28X/build/msw/vc_msw/html/m_list.obj | Bin 0 -> 98774 bytes wx28X/build/msw/vc_msw/html/m_pre.obj | Bin 0 -> 97979 bytes wx28X/build/msw/vc_msw/html/m_style.obj | Bin 0 -> 48960 bytes wx28X/build/msw/vc_msw/html/m_tables.obj | Bin 0 -> 141608 bytes wx28X/build/msw/vc_msw/html/winpars.obj | Bin 0 -> 214501 bytes wx28X/build/msw/vc_msw/html/wx_html.log | 75 + wx28X/build/msw/vc_msw/media/CL.read.1.tlog | Bin 0 -> 45476 bytes wx28X/build/msw/vc_msw/media/CL.write.1.tlog | Bin 0 -> 2318 bytes .../msw/vc_msw/media/Lib-link.read.1.tlog | Bin 0 -> 1512 bytes .../msw/vc_msw/media/Lib-link.write.1.tlog | Bin 0 -> 766 bytes wx28X/build/msw/vc_msw/media/activex.obj | Bin 0 -> 259094 bytes .../build/msw/vc_msw/media/cl.command.1.tlog | Bin 0 -> 6594 bytes .../vc_msw/media/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../msw/vc_msw/media/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../msw/vc_msw/media/custombuild.write.1.tlog | Bin 0 -> 364 bytes wx28X/build/msw/vc_msw/media/dummy.obj | Bin 0 -> 423570 bytes .../build/msw/vc_msw/media/lib.command.1.tlog | Bin 0 -> 1150 bytes .../msw/vc_msw/media/media.lastbuildstate | 2 + .../build/msw/vc_msw/media/media.write.1.tlog | 0 wx28X/build/msw/vc_msw/media/mediactrl_am.obj | Bin 0 -> 84854 bytes wx28X/build/msw/vc_msw/media/mediactrl_qt.obj | Bin 0 -> 166020 bytes .../msw/vc_msw/media/mediactrl_wmp10.obj | Bin 0 -> 93174 bytes wx28X/build/msw/vc_msw/media/mediactrlcmn.obj | Bin 0 -> 128218 bytes wx28X/build/msw/vc_msw/media/wx_media.log | 37 + wx28X/build/msw/vc_msw/net/CL.read.1.tlog | Bin 0 -> 44044 bytes wx28X/build/msw/vc_msw/net/CL.write.1.tlog | Bin 0 -> 4576 bytes .../build/msw/vc_msw/net/Lib-link.read.1.tlog | Bin 0 -> 2734 bytes .../msw/vc_msw/net/Lib-link.write.1.tlog | Bin 0 -> 1368 bytes wx28X/build/msw/vc_msw/net/cl.command.1.tlog | Bin 0 -> 14348 bytes .../msw/vc_msw/net/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../msw/vc_msw/net/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../msw/vc_msw/net/custombuild.write.1.tlog | Bin 0 -> 364 bytes wx28X/build/msw/vc_msw/net/dummy.obj | Bin 0 -> 383070 bytes wx28X/build/msw/vc_msw/net/fs_inet.obj | Bin 0 -> 84736 bytes wx28X/build/msw/vc_msw/net/ftp.obj | Bin 0 -> 137838 bytes wx28X/build/msw/vc_msw/net/gsocket.obj | Bin 0 -> 60495 bytes wx28X/build/msw/vc_msw/net/http.obj | Bin 0 -> 140352 bytes wx28X/build/msw/vc_msw/net/lib.command.1.tlog | Bin 0 -> 2020 bytes wx28X/build/msw/vc_msw/net/net.lastbuildstate | 2 + wx28X/build/msw/vc_msw/net/net.write.1.tlog | 0 wx28X/build/msw/vc_msw/net/protocol.obj | Bin 0 -> 48974 bytes wx28X/build/msw/vc_msw/net/sckaddr.obj | Bin 0 -> 55846 bytes wx28X/build/msw/vc_msw/net/sckfile.obj | Bin 0 -> 32669 bytes wx28X/build/msw/vc_msw/net/sckipc.obj | Bin 0 -> 112641 bytes wx28X/build/msw/vc_msw/net/sckstrm.obj | Bin 0 -> 27256 bytes wx28X/build/msw/vc_msw/net/socket.obj | Bin 0 -> 135524 bytes wx28X/build/msw/vc_msw/net/url.obj | Bin 0 -> 84638 bytes wx28X/build/msw/vc_msw/net/urlmsw.obj | Bin 0 -> 2193 bytes wx28X/build/msw/vc_msw/net/wx_net.log | 49 + wx28X/build/msw/vc_msw/odbc/CL.read.1.tlog | Bin 0 -> 28902 bytes wx28X/build/msw/vc_msw/odbc/CL.write.1.tlog | Bin 0 -> 1082 bytes .../msw/vc_msw/odbc/Lib-link.read.1.tlog | Bin 0 -> 758 bytes .../msw/vc_msw/odbc/Lib-link.write.1.tlog | Bin 0 -> 392 bytes wx28X/build/msw/vc_msw/odbc/cl.command.1.tlog | Bin 0 -> 3322 bytes .../vc_msw/odbc/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../msw/vc_msw/odbc/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../msw/vc_msw/odbc/custombuild.write.1.tlog | Bin 0 -> 364 bytes wx28X/build/msw/vc_msw/odbc/db.obj | Bin 0 -> 216829 bytes wx28X/build/msw/vc_msw/odbc/dbtable.obj | Bin 0 -> 190577 bytes wx28X/build/msw/vc_msw/odbc/dummy.obj | Bin 0 -> 383074 bytes .../build/msw/vc_msw/odbc/lib.command.1.tlog | Bin 0 -> 546 bytes .../build/msw/vc_msw/odbc/odbc.lastbuildstate | 2 + wx28X/build/msw/vc_msw/odbc/odbc.write.1.tlog | 0 wx28X/build/msw/vc_msw/odbc/wx_odbc.log | 31 + wx28X/build/msw/vc_msw/qa/CL.read.1.tlog | Bin 0 -> 40896 bytes wx28X/build/msw/vc_msw/qa/CL.write.1.tlog | Bin 0 -> 1088 bytes .../build/msw/vc_msw/qa/Lib-link.read.1.tlog | Bin 0 -> 758 bytes .../build/msw/vc_msw/qa/Lib-link.write.1.tlog | Bin 0 -> 386 bytes wx28X/build/msw/vc_msw/qa/cl.command.1.tlog | Bin 0 -> 3218 bytes .../msw/vc_msw/qa/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../msw/vc_msw/qa/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../msw/vc_msw/qa/custombuild.write.1.tlog | Bin 0 -> 364 bytes wx28X/build/msw/vc_msw/qa/dbgrptg.obj | Bin 0 -> 381155 bytes wx28X/build/msw/vc_msw/qa/debugrpt.obj | Bin 0 -> 202407 bytes wx28X/build/msw/vc_msw/qa/dummy.obj | Bin 0 -> 423554 bytes wx28X/build/msw/vc_msw/qa/lib.command.1.tlog | Bin 0 -> 540 bytes wx28X/build/msw/vc_msw/qa/qa.lastbuildstate | 2 + wx28X/build/msw/vc_msw/qa/qa.write.1.tlog | 0 wx28X/build/msw/vc_msw/qa/wx_qa.log | 31 + .../build/msw/vc_msw/richtext/CL.read.1.tlog | Bin 0 -> 83532 bytes .../build/msw/vc_msw/richtext/CL.write.1.tlog | Bin 0 -> 4244 bytes .../msw/vc_msw/richtext/Lib-link.read.1.tlog | Bin 0 -> 2632 bytes .../msw/vc_msw/richtext/Lib-link.write.1.tlog | Bin 0 -> 1328 bytes .../msw/vc_msw/richtext/cl.command.1.tlog | Bin 0 -> 11398 bytes .../richtext/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../vc_msw/richtext/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../vc_msw/richtext/custombuild.write.1.tlog | Bin 0 -> 364 bytes wx28X/build/msw/vc_msw/richtext/dummy.obj | Bin 0 -> 423594 bytes .../msw/vc_msw/richtext/lib.command.1.tlog | Bin 0 -> 2076 bytes .../vc_msw/richtext/richtext.lastbuildstate | 2 + .../msw/vc_msw/richtext/richtext.write.1.tlog | 0 .../msw/vc_msw/richtext/richtextbuffer.obj | Bin 0 -> 1194838 bytes .../msw/vc_msw/richtext/richtextctrl.obj | Bin 0 -> 719252 bytes .../msw/vc_msw/richtext/richtextformatdlg.obj | Bin 0 -> 1309378 bytes .../msw/vc_msw/richtext/richtexthtml.obj | Bin 0 -> 159238 bytes .../msw/vc_msw/richtext/richtextprint.obj | Bin 0 -> 233566 bytes .../msw/vc_msw/richtext/richtextstyledlg.obj | Bin 0 -> 454121 bytes .../msw/vc_msw/richtext/richtextstyles.obj | Bin 0 -> 453084 bytes .../msw/vc_msw/richtext/richtextsymboldlg.obj | Bin 0 -> 500054 bytes .../build/msw/vc_msw/richtext/richtextxml.obj | Bin 0 -> 431541 bytes .../build/msw/vc_msw/richtext/wx_richtext.log | 45 + wx28X/build/msw/vc_msw/wxexpat/CL.read.1.tlog | Bin 0 -> 21478 bytes .../build/msw/vc_msw/wxexpat/CL.write.1.tlog | Bin 0 -> 1086 bytes .../msw/vc_msw/wxexpat/Lib-link.read.1.tlog | Bin 0 -> 822 bytes .../msw/vc_msw/wxexpat/Lib-link.write.1.tlog | Bin 0 -> 412 bytes .../msw/vc_msw/wxexpat/cl.command.1.tlog | Bin 0 -> 2252 bytes .../msw/vc_msw/wxexpat/lib.command.1.tlog | Bin 0 -> 598 bytes wx28X/build/msw/vc_msw/wxexpat/wx_wxexpat.log | 24 + .../msw/vc_msw/wxexpat/wxexpat.lastbuildstate | 2 + wx28X/build/msw/vc_msw/wxexpat/xmlparse.obj | Bin 0 -> 164900 bytes wx28X/build/msw/vc_msw/wxexpat/xmlrole.obj | Bin 0 -> 57663 bytes wx28X/build/msw/vc_msw/wxexpat/xmltok.obj | Bin 0 -> 244582 bytes wx28X/build/msw/vc_msw/wxjpeg/CL.read.1.tlog | Bin 0 -> 92398 bytes wx28X/build/msw/vc_msw/wxjpeg/CL.write.1.tlog | Bin 0 -> 15600 bytes .../msw/vc_msw/wxjpeg/Lib-link.read.1.tlog | Bin 0 -> 10104 bytes .../msw/vc_msw/wxjpeg/Lib-link.write.1.tlog | Bin 0 -> 5008 bytes .../build/msw/vc_msw/wxjpeg/cl.command.1.tlog | Bin 0 -> 31926 bytes wx28X/build/msw/vc_msw/wxjpeg/jcapimin.obj | Bin 0 -> 12259 bytes wx28X/build/msw/vc_msw/wxjpeg/jcapistd.obj | Bin 0 -> 7400 bytes wx28X/build/msw/vc_msw/wxjpeg/jccoefct.obj | Bin 0 -> 13028 bytes wx28X/build/msw/vc_msw/wxjpeg/jccolor.obj | Bin 0 -> 15230 bytes wx28X/build/msw/vc_msw/wxjpeg/jcdctmgr.obj | Bin 0 -> 14383 bytes wx28X/build/msw/vc_msw/wxjpeg/jchuff.obj | Bin 0 -> 22755 bytes wx28X/build/msw/vc_msw/wxjpeg/jcinit.obj | Bin 0 -> 5548 bytes wx28X/build/msw/vc_msw/wxjpeg/jcmainct.obj | Bin 0 -> 7229 bytes wx28X/build/msw/vc_msw/wxjpeg/jcmarker.obj | Bin 0 -> 21299 bytes wx28X/build/msw/vc_msw/wxjpeg/jcmaster.obj | Bin 0 -> 16408 bytes wx28X/build/msw/vc_msw/wxjpeg/jcomapi.obj | Bin 0 -> 6661 bytes wx28X/build/msw/vc_msw/wxjpeg/jcparam.obj | Bin 0 -> 20284 bytes wx28X/build/msw/vc_msw/wxjpeg/jcphuff.obj | Bin 0 -> 21486 bytes wx28X/build/msw/vc_msw/wxjpeg/jcprepct.obj | Bin 0 -> 11826 bytes wx28X/build/msw/vc_msw/wxjpeg/jcsample.obj | Bin 0 -> 16575 bytes wx28X/build/msw/vc_msw/wxjpeg/jctrans.obj | Bin 0 -> 13353 bytes wx28X/build/msw/vc_msw/wxjpeg/jdapimin.obj | Bin 0 -> 13768 bytes wx28X/build/msw/vc_msw/wxjpeg/jdapistd.obj | Bin 0 -> 10386 bytes wx28X/build/msw/vc_msw/wxjpeg/jdatadst.obj | Bin 0 -> 7066 bytes wx28X/build/msw/vc_msw/wxjpeg/jdatasrc.obj | Bin 0 -> 7644 bytes wx28X/build/msw/vc_msw/wxjpeg/jdcoefct.obj | Bin 0 -> 19772 bytes wx28X/build/msw/vc_msw/wxjpeg/jdcolor.obj | Bin 0 -> 13749 bytes wx28X/build/msw/vc_msw/wxjpeg/jddctmgr.obj | Bin 0 -> 9026 bytes wx28X/build/msw/vc_msw/wxjpeg/jdhuff.obj | Bin 0 -> 16616 bytes wx28X/build/msw/vc_msw/wxjpeg/jdinput.obj | Bin 0 -> 12769 bytes wx28X/build/msw/vc_msw/wxjpeg/jdmainct.obj | Bin 0 -> 14485 bytes wx28X/build/msw/vc_msw/wxjpeg/jdmarker.obj | Bin 0 -> 36524 bytes wx28X/build/msw/vc_msw/wxjpeg/jdmaster.obj | Bin 0 -> 14623 bytes wx28X/build/msw/vc_msw/wxjpeg/jdmerge.obj | Bin 0 -> 12584 bytes wx28X/build/msw/vc_msw/wxjpeg/jdphuff.obj | Bin 0 -> 17885 bytes wx28X/build/msw/vc_msw/wxjpeg/jdpostct.obj | Bin 0 -> 10124 bytes wx28X/build/msw/vc_msw/wxjpeg/jdsample.obj | Bin 0 -> 15280 bytes wx28X/build/msw/vc_msw/wxjpeg/jdtrans.obj | Bin 0 -> 6396 bytes wx28X/build/msw/vc_msw/wxjpeg/jerror.obj | Bin 0 -> 33197 bytes wx28X/build/msw/vc_msw/wxjpeg/jfdctflt.obj | Bin 0 -> 5535 bytes wx28X/build/msw/vc_msw/wxjpeg/jfdctfst.obj | Bin 0 -> 6813 bytes wx28X/build/msw/vc_msw/wxjpeg/jfdctint.obj | Bin 0 -> 5424 bytes wx28X/build/msw/vc_msw/wxjpeg/jidctflt.obj | Bin 0 -> 8602 bytes wx28X/build/msw/vc_msw/wxjpeg/jidctfst.obj | Bin 0 -> 7456 bytes wx28X/build/msw/vc_msw/wxjpeg/jidctint.obj | Bin 0 -> 7968 bytes wx28X/build/msw/vc_msw/wxjpeg/jidctred.obj | Bin 0 -> 9853 bytes wx28X/build/msw/vc_msw/wxjpeg/jmemmgr.obj | Bin 0 -> 21668 bytes wx28X/build/msw/vc_msw/wxjpeg/jmemnobs.obj | Bin 0 -> 7759 bytes wx28X/build/msw/vc_msw/wxjpeg/jquant1.obj | Bin 0 -> 23956 bytes wx28X/build/msw/vc_msw/wxjpeg/jquant2.obj | Bin 0 -> 29557 bytes wx28X/build/msw/vc_msw/wxjpeg/jutils.obj | Bin 0 -> 6837 bytes .../msw/vc_msw/wxjpeg/lib.command.1.tlog | Bin 0 -> 7728 bytes wx28X/build/msw/vc_msw/wxjpeg/wx_wxjpeg.log | 114 + .../msw/vc_msw/wxjpeg/wxjpeg.lastbuildstate | 2 + wx28X/build/msw/vc_msw/wxpng/CL.read.1.tlog | Bin 0 -> 43216 bytes wx28X/build/msw/vc_msw/wxpng/CL.write.1.tlog | Bin 0 -> 5582 bytes .../msw/vc_msw/wxpng/Lib-link.read.1.tlog | Bin 0 -> 3738 bytes .../msw/vc_msw/wxpng/Lib-link.write.1.tlog | Bin 0 -> 1852 bytes .../build/msw/vc_msw/wxpng/cl.command.1.tlog | Bin 0 -> 11426 bytes .../build/msw/vc_msw/wxpng/lib.command.1.tlog | Bin 0 -> 2810 bytes wx28X/build/msw/vc_msw/wxpng/png.obj | Bin 0 -> 27430 bytes wx28X/build/msw/vc_msw/wxpng/pngerror.obj | Bin 0 -> 14849 bytes wx28X/build/msw/vc_msw/wxpng/pnggccrd.obj | Bin 0 -> 3367 bytes wx28X/build/msw/vc_msw/wxpng/pngget.obj | Bin 0 -> 37310 bytes wx28X/build/msw/vc_msw/wxpng/pngmem.obj | Bin 0 -> 13326 bytes wx28X/build/msw/vc_msw/wxpng/pngpread.obj | Bin 0 -> 39266 bytes wx28X/build/msw/vc_msw/wxpng/pngread.obj | Bin 0 -> 37212 bytes wx28X/build/msw/vc_msw/wxpng/pngrio.obj | Bin 0 -> 7913 bytes wx28X/build/msw/vc_msw/wxpng/pngrtran.obj | Bin 0 -> 69227 bytes wx28X/build/msw/vc_msw/wxpng/pngrutil.obj | Bin 0 -> 86182 bytes wx28X/build/msw/vc_msw/wxpng/pngset.obj | Bin 0 -> 43718 bytes wx28X/build/msw/vc_msw/wxpng/pngtrans.obj | Bin 0 -> 17837 bytes wx28X/build/msw/vc_msw/wxpng/pngvcrd.obj | Bin 0 -> 3367 bytes wx28X/build/msw/vc_msw/wxpng/pngwio.obj | Bin 0 -> 9035 bytes wx28X/build/msw/vc_msw/wxpng/pngwrite.obj | Bin 0 -> 41494 bytes wx28X/build/msw/vc_msw/wxpng/pngwtran.obj | Bin 0 -> 13602 bytes wx28X/build/msw/vc_msw/wxpng/pngwutil.obj | Bin 0 -> 69563 bytes wx28X/build/msw/vc_msw/wxpng/wx_wxpng.log | 52 + .../msw/vc_msw/wxpng/wxpng.lastbuildstate | 2 + .../build/msw/vc_msw/wxpng/wxpng.write.1.tlog | 0 wx28X/build/msw/vc_msw/wxprec_advlib.pch | Bin 0 -> 23003136 bytes wx28X/build/msw/vc_msw/wxprec_auilib.pch | Bin 0 -> 23003136 bytes wx28X/build/msw/vc_msw/wxprec_baselib.pch | Bin 0 -> 16187392 bytes wx28X/build/msw/vc_msw/wxprec_corelib.pch | Bin 0 -> 23003136 bytes wx28X/build/msw/vc_msw/wxprec_dbgridlib.pch | Bin 0 -> 23003136 bytes wx28X/build/msw/vc_msw/wxprec_gllib.pch | Bin 0 -> 23003136 bytes wx28X/build/msw/vc_msw/wxprec_htmllib.pch | Bin 0 -> 23003136 bytes wx28X/build/msw/vc_msw/wxprec_medialib.pch | Bin 0 -> 23003136 bytes wx28X/build/msw/vc_msw/wxprec_netlib.pch | Bin 0 -> 16187392 bytes wx28X/build/msw/vc_msw/wxprec_odbclib.pch | Bin 0 -> 16187392 bytes wx28X/build/msw/vc_msw/wxprec_qalib.pch | Bin 0 -> 23003136 bytes wx28X/build/msw/vc_msw/wxprec_richtextlib.pch | Bin 0 -> 23003136 bytes wx28X/build/msw/vc_msw/wxprec_xmllib.pch | Bin 0 -> 16187392 bytes wx28X/build/msw/vc_msw/wxprec_xrclib.pch | Bin 0 -> 23003136 bytes wx28X/build/msw/vc_msw/wxregex/CL.read.1.tlog | Bin 0 -> 13414 bytes .../build/msw/vc_msw/wxregex/CL.write.1.tlog | Bin 0 -> 1388 bytes .../msw/vc_msw/wxregex/Lib-link.read.1.tlog | Bin 0 -> 1044 bytes .../msw/vc_msw/wxregex/Lib-link.write.1.tlog | Bin 0 -> 522 bytes .../msw/vc_msw/wxregex/cl.command.1.tlog | Bin 0 -> 3038 bytes .../vc_msw/wxregex/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../vc_msw/wxregex/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../vc_msw/wxregex/custombuild.write.1.tlog | Bin 0 -> 364 bytes .../msw/vc_msw/wxregex/lib.command.1.tlog | Bin 0 -> 770 bytes wx28X/build/msw/vc_msw/wxregex/regcomp.obj | Bin 0 -> 215720 bytes wx28X/build/msw/vc_msw/wxregex/regerror.obj | Bin 0 -> 13856 bytes wx28X/build/msw/vc_msw/wxregex/regexec.obj | Bin 0 -> 53656 bytes wx28X/build/msw/vc_msw/wxregex/regfree.obj | Bin 0 -> 5530 bytes wx28X/build/msw/vc_msw/wxregex/wx_wxregex.log | 28 + .../msw/vc_msw/wxregex/wxregex.lastbuildstate | 2 + wx28X/build/msw/vc_msw/wxtiff/CL.read.1.tlog | Bin 0 -> 447032 bytes wx28X/build/msw/vc_msw/wxtiff/CL.write.1.tlog | Bin 0 -> 12294 bytes .../msw/vc_msw/wxtiff/Lib-link.read.1.tlog | Bin 0 -> 8010 bytes .../msw/vc_msw/wxtiff/Lib-link.write.1.tlog | Bin 0 -> 3972 bytes .../build/msw/vc_msw/wxtiff/cl.command.1.tlog | Bin 0 -> 25344 bytes .../msw/vc_msw/wxtiff/lib.command.1.tlog | Bin 0 -> 6184 bytes wx28X/build/msw/vc_msw/wxtiff/tif_aux.obj | Bin 0 -> 26513 bytes wx28X/build/msw/vc_msw/wxtiff/tif_close.obj | Bin 0 -> 19419 bytes wx28X/build/msw/vc_msw/wxtiff/tif_codec.obj | Bin 0 -> 23113 bytes wx28X/build/msw/vc_msw/wxtiff/tif_color.obj | Bin 0 -> 26727 bytes .../build/msw/vc_msw/wxtiff/tif_compress.obj | Bin 0 -> 31782 bytes wx28X/build/msw/vc_msw/wxtiff/tif_dir.obj | Bin 0 -> 67183 bytes wx28X/build/msw/vc_msw/wxtiff/tif_dirinfo.obj | Bin 0 -> 44159 bytes wx28X/build/msw/vc_msw/wxtiff/tif_dirread.obj | Bin 0 -> 66843 bytes .../build/msw/vc_msw/wxtiff/tif_dirwrite.obj | Bin 0 -> 55369 bytes .../build/msw/vc_msw/wxtiff/tif_dumpmode.obj | Bin 0 -> 21790 bytes wx28X/build/msw/vc_msw/wxtiff/tif_error.obj | Bin 0 -> 17806 bytes .../build/msw/vc_msw/wxtiff/tif_extension.obj | Bin 0 -> 22220 bytes wx28X/build/msw/vc_msw/wxtiff/tif_fax3.obj | Bin 0 -> 82550 bytes wx28X/build/msw/vc_msw/wxtiff/tif_fax3sm.obj | Bin 0 -> 101233 bytes wx28X/build/msw/vc_msw/wxtiff/tif_flush.obj | Bin 0 -> 19021 bytes .../build/msw/vc_msw/wxtiff/tif_getimage.obj | Bin 0 -> 117898 bytes wx28X/build/msw/vc_msw/wxtiff/tif_jpeg.obj | Bin 0 -> 16573 bytes wx28X/build/msw/vc_msw/wxtiff/tif_luv.obj | Bin 0 -> 84443 bytes wx28X/build/msw/vc_msw/wxtiff/tif_lzw.obj | Bin 0 -> 31987 bytes wx28X/build/msw/vc_msw/wxtiff/tif_next.obj | Bin 0 -> 20532 bytes wx28X/build/msw/vc_msw/wxtiff/tif_open.obj | Bin 0 -> 30549 bytes .../build/msw/vc_msw/wxtiff/tif_packbits.obj | Bin 0 -> 25001 bytes .../build/msw/vc_msw/wxtiff/tif_pixarlog.obj | Bin 0 -> 16585 bytes wx28X/build/msw/vc_msw/wxtiff/tif_predict.obj | Bin 0 -> 38553 bytes wx28X/build/msw/vc_msw/wxtiff/tif_print.obj | Bin 0 -> 52817 bytes wx28X/build/msw/vc_msw/wxtiff/tif_read.obj | Bin 0 -> 41472 bytes wx28X/build/msw/vc_msw/wxtiff/tif_strip.obj | Bin 0 -> 27055 bytes wx28X/build/msw/vc_msw/wxtiff/tif_swab.obj | Bin 0 -> 22327 bytes wx28X/build/msw/vc_msw/wxtiff/tif_thunder.obj | Bin 0 -> 22438 bytes wx28X/build/msw/vc_msw/wxtiff/tif_tile.obj | Bin 0 -> 27474 bytes wx28X/build/msw/vc_msw/wxtiff/tif_version.obj | Bin 0 -> 17338 bytes wx28X/build/msw/vc_msw/wxtiff/tif_warning.obj | Bin 0 -> 17820 bytes wx28X/build/msw/vc_msw/wxtiff/tif_win32.obj | Bin 0 -> 33973 bytes wx28X/build/msw/vc_msw/wxtiff/tif_write.obj | Bin 0 -> 38192 bytes wx28X/build/msw/vc_msw/wxtiff/tif_zip.obj | Bin 0 -> 16573 bytes wx28X/build/msw/vc_msw/wxtiff/wx_wxtiff.log | 90 + .../msw/vc_msw/wxtiff/wxtiff.lastbuildstate | 2 + wx28X/build/msw/vc_msw/wxzlib/CL.read.1.tlog | Bin 0 -> 16014 bytes wx28X/build/msw/vc_msw/wxzlib/CL.write.1.tlog | Bin 0 -> 3996 bytes .../msw/vc_msw/wxzlib/Lib-link.read.1.tlog | Bin 0 -> 2708 bytes .../msw/vc_msw/wxzlib/Lib-link.write.1.tlog | Bin 0 -> 1344 bytes wx28X/build/msw/vc_msw/wxzlib/adler32.obj | Bin 0 -> 4359 bytes .../build/msw/vc_msw/wxzlib/cl.command.1.tlog | Bin 0 -> 7726 bytes wx28X/build/msw/vc_msw/wxzlib/compress.obj | Bin 0 -> 3999 bytes wx28X/build/msw/vc_msw/wxzlib/crc32.obj | Bin 0 -> 18773 bytes wx28X/build/msw/vc_msw/wxzlib/deflate.obj | Bin 0 -> 31253 bytes wx28X/build/msw/vc_msw/wxzlib/gzio.obj | Bin 0 -> 27616 bytes wx28X/build/msw/vc_msw/wxzlib/infback.obj | Bin 0 -> 18303 bytes wx28X/build/msw/vc_msw/wxzlib/inffast.obj | Bin 0 -> 6846 bytes wx28X/build/msw/vc_msw/wxzlib/inflate.obj | Bin 0 -> 32905 bytes wx28X/build/msw/vc_msw/wxzlib/inftrees.obj | Bin 0 -> 6945 bytes .../msw/vc_msw/wxzlib/lib.command.1.tlog | Bin 0 -> 2032 bytes wx28X/build/msw/vc_msw/wxzlib/trees.obj | Bin 0 -> 30411 bytes wx28X/build/msw/vc_msw/wxzlib/uncompr.obj | Bin 0 -> 2989 bytes wx28X/build/msw/vc_msw/wxzlib/wx_wxzlib.log | 42 + .../msw/vc_msw/wxzlib/wxzlib.lastbuildstate | 2 + wx28X/build/msw/vc_msw/wxzlib/zutil.obj | Bin 0 -> 6631 bytes wx28X/build/msw/vc_msw/xml/CL.read.1.tlog | Bin 0 -> 26878 bytes wx28X/build/msw/vc_msw/xml/CL.write.1.tlog | Bin 0 -> 1056 bytes .../build/msw/vc_msw/xml/Lib-link.read.1.tlog | Bin 0 -> 746 bytes .../msw/vc_msw/xml/Lib-link.write.1.tlog | Bin 0 -> 384 bytes wx28X/build/msw/vc_msw/xml/cl.command.1.tlog | Bin 0 -> 3292 bytes .../msw/vc_msw/xml/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../msw/vc_msw/xml/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../msw/vc_msw/xml/custombuild.write.1.tlog | Bin 0 -> 364 bytes wx28X/build/msw/vc_msw/xml/dummy.obj | Bin 0 -> 383070 bytes wx28X/build/msw/vc_msw/xml/lib.command.1.tlog | Bin 0 -> 532 bytes wx28X/build/msw/vc_msw/xml/wx_xml.log | 31 + wx28X/build/msw/vc_msw/xml/xml.lastbuildstate | 2 + wx28X/build/msw/vc_msw/xml/xml.obj | Bin 0 -> 137408 bytes wx28X/build/msw/vc_msw/xml/xml.write.1.tlog | 0 wx28X/build/msw/vc_msw/xml/xtixml.obj | Bin 0 -> 2197 bytes wx28X/build/msw/vc_msw/xrc/CL.read.1.tlog | Bin 0 -> 182608 bytes wx28X/build/msw/vc_msw/xrc/CL.write.1.tlog | Bin 0 -> 20178 bytes .../build/msw/vc_msw/xrc/Lib-link.read.1.tlog | Bin 0 -> 12030 bytes .../msw/vc_msw/xrc/Lib-link.write.1.tlog | Bin 0 -> 5970 bytes wx28X/build/msw/vc_msw/xrc/cl.command.1.tlog | Bin 0 -> 61124 bytes .../msw/vc_msw/xrc/custombuild.command.1.tlog | Bin 0 -> 544 bytes .../msw/vc_msw/xrc/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../msw/vc_msw/xrc/custombuild.write.1.tlog | Bin 0 -> 364 bytes wx28X/build/msw/vc_msw/xrc/dummy.obj | Bin 0 -> 423558 bytes wx28X/build/msw/vc_msw/xrc/lib.command.1.tlog | Bin 0 -> 9114 bytes wx28X/build/msw/vc_msw/xrc/wx_xrc.log | 143 + wx28X/build/msw/vc_msw/xrc/xh_animatctrl.obj | Bin 0 -> 148580 bytes wx28X/build/msw/vc_msw/xrc/xh_bmp.obj | Bin 0 -> 48747 bytes wx28X/build/msw/vc_msw/xrc/xh_bmpbt.obj | Bin 0 -> 158609 bytes wx28X/build/msw/vc_msw/xrc/xh_bmpcbox.obj | Bin 0 -> 187260 bytes wx28X/build/msw/vc_msw/xrc/xh_bttn.obj | Bin 0 -> 117173 bytes wx28X/build/msw/vc_msw/xrc/xh_cald.obj | Bin 0 -> 132477 bytes wx28X/build/msw/vc_msw/xrc/xh_chckb.obj | Bin 0 -> 118898 bytes wx28X/build/msw/vc_msw/xrc/xh_chckl.obj | Bin 0 -> 55261 bytes wx28X/build/msw/vc_msw/xrc/xh_choic.obj | Bin 0 -> 136277 bytes wx28X/build/msw/vc_msw/xrc/xh_choicbk.obj | Bin 0 -> 147406 bytes wx28X/build/msw/vc_msw/xrc/xh_clrpicker.obj | Bin 0 -> 118059 bytes wx28X/build/msw/vc_msw/xrc/xh_collpane.obj | Bin 0 -> 122848 bytes wx28X/build/msw/vc_msw/xrc/xh_combo.obj | Bin 0 -> 148301 bytes wx28X/build/msw/vc_msw/xrc/xh_datectrl.obj | Bin 0 -> 116466 bytes wx28X/build/msw/vc_msw/xrc/xh_dirpicker.obj | Bin 0 -> 175343 bytes wx28X/build/msw/vc_msw/xrc/xh_dlg.obj | Bin 0 -> 121966 bytes wx28X/build/msw/vc_msw/xrc/xh_filepicker.obj | Bin 0 -> 177320 bytes wx28X/build/msw/vc_msw/xrc/xh_fontpicker.obj | Bin 0 -> 134119 bytes wx28X/build/msw/vc_msw/xrc/xh_frame.obj | Bin 0 -> 108702 bytes wx28X/build/msw/vc_msw/xrc/xh_gauge.obj | Bin 0 -> 116355 bytes wx28X/build/msw/vc_msw/xrc/xh_gdctl.obj | Bin 0 -> 46766 bytes wx28X/build/msw/vc_msw/xrc/xh_grid.obj | Bin 0 -> 39654 bytes wx28X/build/msw/vc_msw/xrc/xh_html.obj | Bin 0 -> 149043 bytes wx28X/build/msw/vc_msw/xrc/xh_htmllbox.obj | Bin 0 -> 124067 bytes wx28X/build/msw/vc_msw/xrc/xh_hyperlink.obj | Bin 0 -> 128850 bytes wx28X/build/msw/vc_msw/xrc/xh_listb.obj | Bin 0 -> 51010 bytes wx28X/build/msw/vc_msw/xrc/xh_listbk.obj | Bin 0 -> 145422 bytes wx28X/build/msw/vc_msw/xrc/xh_listc.obj | Bin 0 -> 115907 bytes wx28X/build/msw/vc_msw/xrc/xh_mdi.obj | Bin 0 -> 124868 bytes wx28X/build/msw/vc_msw/xrc/xh_menu.obj | Bin 0 -> 109403 bytes wx28X/build/msw/vc_msw/xrc/xh_notbk.obj | Bin 0 -> 59791 bytes wx28X/build/msw/vc_msw/xrc/xh_odcombo.obj | Bin 0 -> 174292 bytes wx28X/build/msw/vc_msw/xrc/xh_panel.obj | Bin 0 -> 90651 bytes wx28X/build/msw/vc_msw/xrc/xh_propdlg.obj | Bin 0 -> 149073 bytes wx28X/build/msw/vc_msw/xrc/xh_radbt.obj | Bin 0 -> 109277 bytes wx28X/build/msw/vc_msw/xrc/xh_radbx.obj | Bin 0 -> 158658 bytes wx28X/build/msw/vc_msw/xrc/xh_scrol.obj | Bin 0 -> 116595 bytes wx28X/build/msw/vc_msw/xrc/xh_scwin.obj | Bin 0 -> 106063 bytes wx28X/build/msw/vc_msw/xrc/xh_sizer.obj | Bin 0 -> 208049 bytes wx28X/build/msw/vc_msw/xrc/xh_slidr.obj | Bin 0 -> 133236 bytes wx28X/build/msw/vc_msw/xrc/xh_spin.obj | Bin 0 -> 142755 bytes wx28X/build/msw/vc_msw/xrc/xh_split.obj | Bin 0 -> 108493 bytes wx28X/build/msw/vc_msw/xrc/xh_statbar.obj | Bin 0 -> 48309 bytes wx28X/build/msw/vc_msw/xrc/xh_stbmp.obj | Bin 0 -> 141303 bytes wx28X/build/msw/vc_msw/xrc/xh_stbox.obj | Bin 0 -> 115651 bytes wx28X/build/msw/vc_msw/xrc/xh_stlin.obj | Bin 0 -> 116826 bytes wx28X/build/msw/vc_msw/xrc/xh_sttxt.obj | Bin 0 -> 116475 bytes wx28X/build/msw/vc_msw/xrc/xh_text.obj | Bin 0 -> 160892 bytes wx28X/build/msw/vc_msw/xrc/xh_tglbtn.obj | Bin 0 -> 108430 bytes wx28X/build/msw/vc_msw/xrc/xh_toolb.obj | Bin 0 -> 130780 bytes wx28X/build/msw/vc_msw/xrc/xh_tree.obj | Bin 0 -> 137863 bytes wx28X/build/msw/vc_msw/xrc/xh_treebk.obj | Bin 0 -> 160116 bytes wx28X/build/msw/vc_msw/xrc/xh_unkwn.obj | Bin 0 -> 129470 bytes wx28X/build/msw/vc_msw/xrc/xh_wizrd.obj | Bin 0 -> 180149 bytes wx28X/build/msw/vc_msw/xrc/xmlres.obj | Bin 0 -> 491808 bytes wx28X/build/msw/vc_msw/xrc/xmlrsall.obj | Bin 0 -> 36004 bytes wx28X/build/msw/vc_msw/xrc/xrc.lastbuildstate | 2 + wx28X/build/msw/vc_msw/xrc/xrc.write.1.tlog | 0 wx28X/build/msw/vc_mswd/adv/CL.read.1.tlog | Bin 0 -> 66048 bytes wx28X/build/msw/vc_mswd/adv/CL.write.1.tlog | Bin 0 -> 9386 bytes .../msw/vc_mswd/adv/Lib-link.read.1.tlog | Bin 0 -> 5546 bytes .../msw/vc_mswd/adv/Lib-link.write.1.tlog | Bin 0 -> 2756 bytes wx28X/build/msw/vc_mswd/adv/aboutdlg.obj | Bin 0 -> 32220 bytes wx28X/build/msw/vc_mswd/adv/aboutdlgg.obj | Bin 0 -> 287587 bytes .../build/msw/vc_mswd/adv/adv.lastbuildstate | 2 + wx28X/build/msw/vc_mswd/adv/adv.write.1.tlog | 0 wx28X/build/msw/vc_mswd/adv/animatecmn.obj | Bin 0 -> 127395 bytes wx28X/build/msw/vc_mswd/adv/animateg.obj | Bin 0 -> 272616 bytes wx28X/build/msw/vc_mswd/adv/bmpcboxg.obj | Bin 0 -> 201034 bytes wx28X/build/msw/vc_mswd/adv/calctrl.obj | Bin 0 -> 382567 bytes wx28X/build/msw/vc_mswd/adv/cl.command.1.tlog | Bin 0 -> 29800 bytes .../vc_mswd/adv/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../msw/vc_mswd/adv/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../msw/vc_mswd/adv/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswd/adv/datavcmn.obj | Bin 0 -> 262419 bytes wx28X/build/msw/vc_mswd/adv/datavgen.obj | Bin 0 -> 499240 bytes wx28X/build/msw/vc_mswd/adv/datectlg.obj | Bin 0 -> 3115 bytes wx28X/build/msw/vc_mswd/adv/datectrl.obj | Bin 0 -> 138157 bytes wx28X/build/msw/vc_mswd/adv/dummy.obj | Bin 0 -> 423448 bytes wx28X/build/msw/vc_mswd/adv/grid.obj | Bin 0 -> 1277932 bytes wx28X/build/msw/vc_mswd/adv/gridctrl.obj | Bin 0 -> 211955 bytes wx28X/build/msw/vc_mswd/adv/gridsel.obj | Bin 0 -> 65137 bytes wx28X/build/msw/vc_mswd/adv/helpext.obj | Bin 0 -> 125925 bytes wx28X/build/msw/vc_mswd/adv/hyperlink.obj | Bin 0 -> 204082 bytes wx28X/build/msw/vc_mswd/adv/joystick.obj | Bin 0 -> 52147 bytes wx28X/build/msw/vc_mswd/adv/laywin.obj | Bin 0 -> 71095 bytes .../build/msw/vc_mswd/adv/lib.command.1.tlog | Bin 0 -> 4240 bytes wx28X/build/msw/vc_mswd/adv/odcombo.obj | Bin 0 -> 299760 bytes wx28X/build/msw/vc_mswd/adv/propdlg.obj | Bin 0 -> 206132 bytes wx28X/build/msw/vc_mswd/adv/sashwin.obj | Bin 0 -> 165209 bytes wx28X/build/msw/vc_mswd/adv/sound.obj | Bin 0 -> 47869 bytes wx28X/build/msw/vc_mswd/adv/splash.obj | Bin 0 -> 228564 bytes wx28X/build/msw/vc_mswd/adv/taskbar.obj | Bin 0 -> 134900 bytes wx28X/build/msw/vc_mswd/adv/taskbarcmn.obj | Bin 0 -> 15775 bytes wx28X/build/msw/vc_mswd/adv/tipdlg.obj | Bin 0 -> 303217 bytes wx28X/build/msw/vc_mswd/adv/wizard.obj | Bin 0 -> 356730 bytes wx28X/build/msw/vc_mswd/adv/wx_adv.log | 81 + wx28X/build/msw/vc_mswd/base/CL.read.1.tlog | Bin 0 -> 234234 bytes wx28X/build/msw/vc_mswd/base/CL.write.1.tlog | Bin 0 -> 60894 bytes .../msw/vc_mswd/base/Lib-link.read.1.tlog | Bin 0 -> 36666 bytes .../msw/vc_mswd/base/Lib-link.write.1.tlog | Bin 0 -> 18166 bytes wx28X/build/msw/vc_mswd/base/appbase.obj | Bin 0 -> 129517 bytes wx28X/build/msw/vc_mswd/base/arcall.obj | Bin 0 -> 16882 bytes wx28X/build/msw/vc_mswd/base/arcfind.obj | Bin 0 -> 7447 bytes wx28X/build/msw/vc_mswd/base/archive.obj | Bin 0 -> 27550 bytes .../msw/vc_mswd/base/base.lastbuildstate | 2 + .../build/msw/vc_mswd/base/base.write.1.tlog | 0 wx28X/build/msw/vc_mswd/base/basemsw.obj | Bin 0 -> 4704 bytes .../build/msw/vc_mswd/base/cl.command.1.tlog | Bin 0 -> 206546 bytes wx28X/build/msw/vc_mswd/base/clntdata.obj | Bin 0 -> 8467 bytes wx28X/build/msw/vc_mswd/base/cmdline.obj | Bin 0 -> 165391 bytes wx28X/build/msw/vc_mswd/base/config.obj | Bin 0 -> 76579 bytes wx28X/build/msw/vc_mswd/base/convauto.obj | Bin 0 -> 30982 bytes wx28X/build/msw/vc_mswd/base/crashrpt.obj | Bin 0 -> 37546 bytes .../vc_mswd/base/custombuild.command.1.tlog | Bin 0 -> 1078 bytes .../msw/vc_mswd/base/custombuild.read.1.tlog | Bin 0 -> 346 bytes .../msw/vc_mswd/base/custombuild.write.1.tlog | Bin 0 -> 718 bytes wx28X/build/msw/vc_mswd/base/datetime.obj | Bin 0 -> 307314 bytes wx28X/build/msw/vc_mswd/base/datstrm.obj | Bin 0 -> 69062 bytes wx28X/build/msw/vc_mswd/base/dde.obj | Bin 0 -> 195407 bytes wx28X/build/msw/vc_mswd/base/debughlp.obj | Bin 0 -> 74217 bytes wx28X/build/msw/vc_mswd/base/dir.obj | Bin 0 -> 41710 bytes wx28X/build/msw/vc_mswd/base/dircmn.obj | Bin 0 -> 59082 bytes wx28X/build/msw/vc_mswd/base/dlmsw.obj | Bin 0 -> 52790 bytes wx28X/build/msw/vc_mswd/base/dummy.obj | Bin 0 -> 383348 bytes wx28X/build/msw/vc_mswd/base/dynarray.obj | Bin 0 -> 124413 bytes wx28X/build/msw/vc_mswd/base/dynlib.obj | Bin 0 -> 62392 bytes wx28X/build/msw/vc_mswd/base/dynload.obj | Bin 0 -> 114933 bytes wx28X/build/msw/vc_mswd/base/encconv.obj | Bin 0 -> 55470 bytes wx28X/build/msw/vc_mswd/base/event.obj | Bin 0 -> 93800 bytes wx28X/build/msw/vc_mswd/base/extended.obj | Bin 0 -> 8303 bytes wx28X/build/msw/vc_mswd/base/ffile.obj | Bin 0 -> 28396 bytes wx28X/build/msw/vc_mswd/base/file.obj | Bin 0 -> 41677 bytes wx28X/build/msw/vc_mswd/base/fileback.obj | Bin 0 -> 39073 bytes wx28X/build/msw/vc_mswd/base/fileconf.obj | Bin 0 -> 222079 bytes wx28X/build/msw/vc_mswd/base/filefn.obj | Bin 0 -> 130323 bytes wx28X/build/msw/vc_mswd/base/filename.obj | Bin 0 -> 250774 bytes wx28X/build/msw/vc_mswd/base/filesys.obj | Bin 0 -> 200500 bytes wx28X/build/msw/vc_mswd/base/filtall.obj | Bin 0 -> 11197 bytes wx28X/build/msw/vc_mswd/base/filtfind.obj | Bin 0 -> 4154 bytes wx28X/build/msw/vc_mswd/base/fmapbase.obj | Bin 0 -> 109050 bytes wx28X/build/msw/vc_mswd/base/fs_arc.obj | Bin 0 -> 190789 bytes wx28X/build/msw/vc_mswd/base/fs_filter.obj | Bin 0 -> 46578 bytes wx28X/build/msw/vc_mswd/base/fs_mem.obj | Bin 0 -> 70738 bytes wx28X/build/msw/vc_mswd/base/hash.obj | Bin 0 -> 31657 bytes wx28X/build/msw/vc_mswd/base/hashmap.obj | Bin 0 -> 6982 bytes wx28X/build/msw/vc_mswd/base/init.obj | Bin 0 -> 56251 bytes wx28X/build/msw/vc_mswd/base/intl.obj | Bin 0 -> 305391 bytes wx28X/build/msw/vc_mswd/base/ipcbase.obj | Bin 0 -> 22934 bytes .../build/msw/vc_mswd/base/lib.command.1.tlog | Bin 0 -> 27982 bytes wx28X/build/msw/vc_mswd/base/list.obj | Bin 0 -> 86198 bytes wx28X/build/msw/vc_mswd/base/log.obj | Bin 0 -> 104541 bytes wx28X/build/msw/vc_mswd/base/longlong.obj | Bin 0 -> 54001 bytes wx28X/build/msw/vc_mswd/base/main.obj | Bin 0 -> 25790 bytes wx28X/build/msw/vc_mswd/base/memory.obj | Bin 0 -> 2223 bytes wx28X/build/msw/vc_mswd/base/mimecmn.obj | Bin 0 -> 143015 bytes wx28X/build/msw/vc_mswd/base/mimetype.obj | Bin 0 -> 113389 bytes wx28X/build/msw/vc_mswd/base/module.obj | Bin 0 -> 51913 bytes wx28X/build/msw/vc_mswd/base/msgout.obj | Bin 0 -> 17231 bytes wx28X/build/msw/vc_mswd/base/mslu.obj | Bin 0 -> 2645 bytes wx28X/build/msw/vc_mswd/base/mstream.obj | Bin 0 -> 30140 bytes wx28X/build/msw/vc_mswd/base/object.obj | Bin 0 -> 33663 bytes wx28X/build/msw/vc_mswd/base/platinfo.obj | Bin 0 -> 40646 bytes wx28X/build/msw/vc_mswd/base/power.obj | Bin 0 -> 5062 bytes wx28X/build/msw/vc_mswd/base/powercmn.obj | Bin 0 -> 8687 bytes wx28X/build/msw/vc_mswd/base/process.obj | Bin 0 -> 35684 bytes wx28X/build/msw/vc_mswd/base/regconf.obj | Bin 0 -> 81540 bytes wx28X/build/msw/vc_mswd/base/regex.obj | Bin 0 -> 53934 bytes wx28X/build/msw/vc_mswd/base/registry.obj | Bin 0 -> 135129 bytes wx28X/build/msw/vc_mswd/base/snglinst.obj | Bin 0 -> 13515 bytes wx28X/build/msw/vc_mswd/base/sstream.obj | Bin 0 -> 27299 bytes wx28X/build/msw/vc_mswd/base/stackwalk.obj | Bin 0 -> 46966 bytes wx28X/build/msw/vc_mswd/base/stdpaths.obj | Bin 0 -> 78558 bytes wx28X/build/msw/vc_mswd/base/stdpbase.obj | Bin 0 -> 49476 bytes wx28X/build/msw/vc_mswd/base/stopwatch.obj | Bin 0 -> 13743 bytes wx28X/build/msw/vc_mswd/base/strconv.obj | Bin 0 -> 155083 bytes wx28X/build/msw/vc_mswd/base/stream.obj | Bin 0 -> 114282 bytes wx28X/build/msw/vc_mswd/base/string.obj | Bin 0 -> 191097 bytes wx28X/build/msw/vc_mswd/base/sysopt.obj | Bin 0 -> 28424 bytes wx28X/build/msw/vc_mswd/base/tarstrm.obj | Bin 0 -> 302899 bytes wx28X/build/msw/vc_mswd/base/textbuf.obj | Bin 0 -> 42610 bytes wx28X/build/msw/vc_mswd/base/textfile.obj | Bin 0 -> 57291 bytes wx28X/build/msw/vc_mswd/base/thread.obj | Bin 0 -> 128763 bytes wx28X/build/msw/vc_mswd/base/tokenzr.obj | Bin 0 -> 38702 bytes wx28X/build/msw/vc_mswd/base/txtstrm.obj | Bin 0 -> 62145 bytes wx28X/build/msw/vc_mswd/base/uri.obj | Bin 0 -> 95870 bytes wx28X/build/msw/vc_mswd/base/utils.obj | Bin 0 -> 101867 bytes wx28X/build/msw/vc_mswd/base/utilscmn.obj | Bin 0 -> 98531 bytes wx28X/build/msw/vc_mswd/base/utilsexc.obj | Bin 0 -> 73773 bytes wx28X/build/msw/vc_mswd/base/variant.obj | Bin 0 -> 343171 bytes wx28X/build/msw/vc_mswd/base/volume.obj | Bin 0 -> 95526 bytes wx28X/build/msw/vc_mswd/base/wfstream.obj | Bin 0 -> 85841 bytes wx28X/build/msw/vc_mswd/base/wx_base.log | 215 + wx28X/build/msw/vc_mswd/base/wxchar.obj | Bin 0 -> 8328 bytes wx28X/build/msw/vc_mswd/base/xti.obj | Bin 0 -> 2211 bytes wx28X/build/msw/vc_mswd/base/xtistrm.obj | Bin 0 -> 2223 bytes wx28X/build/msw/vc_mswd/base/zipstrm.obj | Bin 0 -> 392916 bytes wx28X/build/msw/vc_mswd/base/zstream.obj | Bin 0 -> 89156 bytes wx28X/build/msw/vc_mswd/core/CL.read.1.tlog | Bin 0 -> 473478 bytes wx28X/build/msw/vc_mswd/core/CL.write.1.tlog | Bin 0 -> 160234 bytes .../msw/vc_mswd/core/Lib-link.read.1.tlog | Bin 0 -> 94138 bytes .../msw/vc_mswd/core/Lib-link.write.1.tlog | Bin 0 -> 46642 bytes wx28X/build/msw/vc_mswd/core/accel.obj | Bin 0 -> 28932 bytes wx28X/build/msw/vc_mswd/core/access.obj | Bin 0 -> 2223 bytes wx28X/build/msw/vc_mswd/core/accesscmn.obj | Bin 0 -> 2231 bytes wx28X/build/msw/vc_mswd/core/anidecod.obj | Bin 0 -> 118442 bytes wx28X/build/msw/vc_mswd/core/app.obj | Bin 0 -> 140187 bytes wx28X/build/msw/vc_mswd/core/appcmn.obj | Bin 0 -> 112192 bytes wx28X/build/msw/vc_mswd/core/artprov.obj | Bin 0 -> 149558 bytes wx28X/build/msw/vc_mswd/core/artstd.obj | Bin 0 -> 158073 bytes wx28X/build/msw/vc_mswd/core/automtn.obj | Bin 0 -> 68154 bytes wx28X/build/msw/vc_mswd/core/bitmap.obj | Bin 0 -> 185329 bytes wx28X/build/msw/vc_mswd/core/bmpbase.obj | Bin 0 -> 81490 bytes wx28X/build/msw/vc_mswd/core/bmpbuttn.obj | Bin 0 -> 245351 bytes wx28X/build/msw/vc_mswd/core/bookctrl.obj | Bin 0 -> 117079 bytes wx28X/build/msw/vc_mswd/core/brush.obj | Bin 0 -> 80815 bytes wx28X/build/msw/vc_mswd/core/busyinfo.obj | Bin 0 -> 125837 bytes wx28X/build/msw/vc_mswd/core/button.obj | Bin 0 -> 135657 bytes wx28X/build/msw/vc_mswd/core/buttonbar.obj | Bin 0 -> 2231 bytes wx28X/build/msw/vc_mswd/core/caret.obj | Bin 0 -> 13337 bytes wx28X/build/msw/vc_mswd/core/checkbox.obj | Bin 0 -> 123843 bytes wx28X/build/msw/vc_mswd/core/checklst.obj | Bin 0 -> 147617 bytes wx28X/build/msw/vc_mswd/core/choicbkg.obj | Bin 0 -> 190643 bytes wx28X/build/msw/vc_mswd/core/choiccmn.obj | Bin 0 -> 63671 bytes wx28X/build/msw/vc_mswd/core/choicdgg.obj | Bin 0 -> 248406 bytes wx28X/build/msw/vc_mswd/core/choice.obj | Bin 0 -> 153599 bytes .../build/msw/vc_mswd/core/cl.command.1.tlog | Bin 0 -> 517770 bytes wx28X/build/msw/vc_mswd/core/clipbrd.obj | Bin 0 -> 85336 bytes wx28X/build/msw/vc_mswd/core/clipcmn.obj | Bin 0 -> 20690 bytes wx28X/build/msw/vc_mswd/core/clrpickercmn.obj | Bin 0 -> 174225 bytes wx28X/build/msw/vc_mswd/core/clrpickerg.obj | Bin 0 -> 155094 bytes wx28X/build/msw/vc_mswd/core/cmdproc.obj | Bin 0 -> 74336 bytes wx28X/build/msw/vc_mswd/core/cmndata.obj | Bin 0 -> 159976 bytes wx28X/build/msw/vc_mswd/core/collpaneg.obj | Bin 0 -> 180091 bytes wx28X/build/msw/vc_mswd/core/colordlg.obj | Bin 0 -> 104820 bytes wx28X/build/msw/vc_mswd/core/colour.obj | Bin 0 -> 25463 bytes wx28X/build/msw/vc_mswd/core/colourcmn.obj | Bin 0 -> 57284 bytes wx28X/build/msw/vc_mswd/core/combo.obj | Bin 0 -> 286844 bytes wx28X/build/msw/vc_mswd/core/combobox.obj | Bin 0 -> 169248 bytes wx28X/build/msw/vc_mswd/core/combocmn.obj | Bin 0 -> 360108 bytes wx28X/build/msw/vc_mswd/core/combog.obj | Bin 0 -> 5499 bytes wx28X/build/msw/vc_mswd/core/containr.obj | Bin 0 -> 58149 bytes wx28X/build/msw/vc_mswd/core/control.obj | Bin 0 -> 129288 bytes .../msw/vc_mswd/core/core.lastbuildstate | 2 + .../build/msw/vc_mswd/core/core.write.1.tlog | 0 wx28X/build/msw/vc_mswd/core/cshelp.obj | Bin 0 -> 237909 bytes wx28X/build/msw/vc_mswd/core/ctrlcmn.obj | Bin 0 -> 105178 bytes wx28X/build/msw/vc_mswd/core/ctrlsub.obj | Bin 0 -> 86442 bytes wx28X/build/msw/vc_mswd/core/cursor.obj | Bin 0 -> 70522 bytes .../vc_mswd/core/custombuild.command.1.tlog | Bin 0 -> 1078 bytes .../msw/vc_mswd/core/custombuild.read.1.tlog | Bin 0 -> 346 bytes .../msw/vc_mswd/core/custombuild.write.1.tlog | Bin 0 -> 718 bytes wx28X/build/msw/vc_mswd/core/data.obj | Bin 0 -> 2211 bytes wx28X/build/msw/vc_mswd/core/datacmn.obj | Bin 0 -> 12754 bytes wx28X/build/msw/vc_mswd/core/dataobj.obj | Bin 0 -> 150492 bytes wx28X/build/msw/vc_mswd/core/dc.obj | Bin 0 -> 331900 bytes wx28X/build/msw/vc_mswd/core/dcbase.obj | Bin 0 -> 212729 bytes wx28X/build/msw/vc_mswd/core/dcbufcmn.obj | Bin 0 -> 28128 bytes wx28X/build/msw/vc_mswd/core/dcclient.obj | Bin 0 -> 150005 bytes wx28X/build/msw/vc_mswd/core/dcgraph.obj | Bin 0 -> 2223 bytes wx28X/build/msw/vc_mswd/core/dcmemory.obj | Bin 0 -> 110900 bytes wx28X/build/msw/vc_mswd/core/dcprint.obj | Bin 0 -> 157538 bytes wx28X/build/msw/vc_mswd/core/dcpsg.obj | Bin 0 -> 2219 bytes wx28X/build/msw/vc_mswd/core/dcscreen.obj | Bin 0 -> 92518 bytes wx28X/build/msw/vc_mswd/core/dialog.obj | Bin 0 -> 126629 bytes wx28X/build/msw/vc_mswd/core/dialup.obj | Bin 0 -> 141045 bytes wx28X/build/msw/vc_mswd/core/dib.obj | Bin 0 -> 61768 bytes wx28X/build/msw/vc_mswd/core/dirctrlg.obj | Bin 0 -> 385430 bytes wx28X/build/msw/vc_mswd/core/dirdlg.obj | Bin 0 -> 132339 bytes wx28X/build/msw/vc_mswd/core/display.obj | Bin 0 -> 93734 bytes wx28X/build/msw/vc_mswd/core/dlgcmn.obj | Bin 0 -> 213396 bytes wx28X/build/msw/vc_mswd/core/dndcmn.obj | Bin 0 -> 3698 bytes wx28X/build/msw/vc_mswd/core/dobjcmn.obj | Bin 0 -> 117912 bytes wx28X/build/msw/vc_mswd/core/docmdi.obj | Bin 0 -> 116767 bytes wx28X/build/msw/vc_mswd/core/docview.obj | Bin 0 -> 388832 bytes wx28X/build/msw/vc_mswd/core/dpycmn.obj | Bin 0 -> 65417 bytes wx28X/build/msw/vc_mswd/core/dragimag.obj | Bin 0 -> 144348 bytes wx28X/build/msw/vc_mswd/core/dragimgg.obj | Bin 0 -> 177707 bytes wx28X/build/msw/vc_mswd/core/dropsrc.obj | Bin 0 -> 46350 bytes wx28X/build/msw/vc_mswd/core/droptgt.obj | Bin 0 -> 60027 bytes wx28X/build/msw/vc_mswd/core/dseldlg.obj | Bin 0 -> 67917 bytes wx28X/build/msw/vc_mswd/core/dummy.obj | Bin 0 -> 423880 bytes wx28X/build/msw/vc_mswd/core/effects.obj | Bin 0 -> 122641 bytes wx28X/build/msw/vc_mswd/core/enhmeta.obj | Bin 0 -> 151295 bytes wx28X/build/msw/vc_mswd/core/event.obj | Bin 0 -> 450292 bytes wx28X/build/msw/vc_mswd/core/evtloop.obj | Bin 0 -> 43016 bytes wx28X/build/msw/vc_mswd/core/evtloopcmn.obj | Bin 0 -> 18738 bytes wx28X/build/msw/vc_mswd/core/fddlgcmn.obj | Bin 0 -> 89379 bytes wx28X/build/msw/vc_mswd/core/fdrepdlg.obj | Bin 0 -> 145360 bytes wx28X/build/msw/vc_mswd/core/filedlg.obj | Bin 0 -> 154809 bytes .../build/msw/vc_mswd/core/filepickercmn.obj | Bin 0 -> 217649 bytes wx28X/build/msw/vc_mswd/core/filepickerg.obj | Bin 0 -> 153872 bytes wx28X/build/msw/vc_mswd/core/fldlgcmn.obj | Bin 0 -> 136615 bytes wx28X/build/msw/vc_mswd/core/font.obj | Bin 0 -> 137235 bytes wx28X/build/msw/vc_mswd/core/fontcmn.obj | Bin 0 -> 101647 bytes wx28X/build/msw/vc_mswd/core/fontdlg.obj | Bin 0 -> 101372 bytes wx28X/build/msw/vc_mswd/core/fontenum.obj | Bin 0 -> 28517 bytes wx28X/build/msw/vc_mswd/core/fontenumcmn.obj | Bin 0 -> 21564 bytes wx28X/build/msw/vc_mswd/core/fontmap.obj | Bin 0 -> 189415 bytes .../build/msw/vc_mswd/core/fontpickercmn.obj | Bin 0 -> 174297 bytes wx28X/build/msw/vc_mswd/core/fontpickerg.obj | Bin 0 -> 197848 bytes wx28X/build/msw/vc_mswd/core/fontutil.obj | Bin 0 -> 53028 bytes wx28X/build/msw/vc_mswd/core/frame.obj | Bin 0 -> 162096 bytes wx28X/build/msw/vc_mswd/core/framecmn.obj | Bin 0 -> 162498 bytes wx28X/build/msw/vc_mswd/core/fs_mem.obj | Bin 0 -> 30107 bytes wx28X/build/msw/vc_mswd/core/gauge95.obj | Bin 0 -> 90939 bytes wx28X/build/msw/vc_mswd/core/gaugecmn.obj | Bin 0 -> 57560 bytes wx28X/build/msw/vc_mswd/core/gbsizer.obj | Bin 0 -> 95373 bytes wx28X/build/msw/vc_mswd/core/gdicmn.obj | Bin 0 -> 220437 bytes wx28X/build/msw/vc_mswd/core/gdiimage.obj | Bin 0 -> 124182 bytes wx28X/build/msw/vc_mswd/core/gdiobj.obj | Bin 0 -> 2343 bytes wx28X/build/msw/vc_mswd/core/geometry.obj | Bin 0 -> 27368 bytes wx28X/build/msw/vc_mswd/core/gifdecod.obj | Bin 0 -> 71985 bytes wx28X/build/msw/vc_mswd/core/graphcmn.obj | Bin 0 -> 2227 bytes wx28X/build/msw/vc_mswd/core/graphics.obj | Bin 0 -> 2403 bytes wx28X/build/msw/vc_mswd/core/gsockmsw.obj | Bin 0 -> 13302 bytes wx28X/build/msw/vc_mswd/core/helpbase.obj | Bin 0 -> 5950 bytes wx28X/build/msw/vc_mswd/core/helpchm.obj | Bin 0 -> 66835 bytes wx28X/build/msw/vc_mswd/core/helpwin.obj | Bin 0 -> 52228 bytes wx28X/build/msw/vc_mswd/core/icon.obj | Bin 0 -> 65495 bytes wx28X/build/msw/vc_mswd/core/iconbndl.obj | Bin 0 -> 69969 bytes wx28X/build/msw/vc_mswd/core/imagall.obj | Bin 0 -> 69001 bytes wx28X/build/msw/vc_mswd/core/imagbmp.obj | Bin 0 -> 121495 bytes wx28X/build/msw/vc_mswd/core/image.obj | Bin 0 -> 320780 bytes wx28X/build/msw/vc_mswd/core/imagfill.obj | Bin 0 -> 2227 bytes wx28X/build/msw/vc_mswd/core/imaggif.obj | Bin 0 -> 32453 bytes wx28X/build/msw/vc_mswd/core/imagiff.obj | Bin 0 -> 2223 bytes wx28X/build/msw/vc_mswd/core/imagjpeg.obj | Bin 0 -> 46442 bytes wx28X/build/msw/vc_mswd/core/imaglist.obj | Bin 0 -> 154461 bytes wx28X/build/msw/vc_mswd/core/imagpcx.obj | Bin 0 -> 65383 bytes wx28X/build/msw/vc_mswd/core/imagpng.obj | Bin 0 -> 75604 bytes wx28X/build/msw/vc_mswd/core/imagpnm.obj | Bin 0 -> 38513 bytes wx28X/build/msw/vc_mswd/core/imagtga.obj | Bin 0 -> 51223 bytes wx28X/build/msw/vc_mswd/core/imagtiff.obj | Bin 0 -> 50334 bytes wx28X/build/msw/vc_mswd/core/imagxpm.obj | Bin 0 -> 71818 bytes wx28X/build/msw/vc_mswd/core/iniconf.obj | Bin 0 -> 79822 bytes wx28X/build/msw/vc_mswd/core/layout.obj | Bin 0 -> 55210 bytes wx28X/build/msw/vc_mswd/core/lboxcmn.obj | Bin 0 -> 78721 bytes .../build/msw/vc_mswd/core/lib.command.1.tlog | Bin 0 -> 72222 bytes wx28X/build/msw/vc_mswd/core/listbkg.obj | Bin 0 -> 184342 bytes wx28X/build/msw/vc_mswd/core/listbox.obj | Bin 0 -> 279454 bytes wx28X/build/msw/vc_mswd/core/listctrl.obj | Bin 0 -> 369935 bytes wx28X/build/msw/vc_mswd/core/listctrlcmn.obj | Bin 0 -> 20665 bytes wx28X/build/msw/vc_mswd/core/logg.obj | Bin 0 -> 425340 bytes wx28X/build/msw/vc_mswd/core/main.obj | Bin 0 -> 19674 bytes wx28X/build/msw/vc_mswd/core/matrix.obj | Bin 0 -> 44568 bytes wx28X/build/msw/vc_mswd/core/mdi.obj | Bin 0 -> 245685 bytes wx28X/build/msw/vc_mswd/core/menu.obj | Bin 0 -> 212783 bytes wx28X/build/msw/vc_mswd/core/menucmn.obj | Bin 0 -> 243163 bytes wx28X/build/msw/vc_mswd/core/menuitem.obj | Bin 0 -> 60245 bytes wx28X/build/msw/vc_mswd/core/metafile.obj | Bin 0 -> 2983 bytes wx28X/build/msw/vc_mswd/core/minifram.obj | Bin 0 -> 70974 bytes wx28X/build/msw/vc_mswd/core/msgdlg.obj | Bin 0 -> 97302 bytes wx28X/build/msw/vc_mswd/core/msgout.obj | Bin 0 -> 16181 bytes wx28X/build/msw/vc_mswd/core/mslu.obj | Bin 0 -> 2211 bytes wx28X/build/msw/vc_mswd/core/nativdlg.obj | Bin 0 -> 346344 bytes wx28X/build/msw/vc_mswd/core/nbkbase.obj | Bin 0 -> 42322 bytes wx28X/build/msw/vc_mswd/core/notebook.obj | Bin 0 -> 370986 bytes wx28X/build/msw/vc_mswd/core/numdlgg.obj | Bin 0 -> 177740 bytes wx28X/build/msw/vc_mswd/core/oleutils.obj | Bin 0 -> 44616 bytes wx28X/build/msw/vc_mswd/core/overlaycmn.obj | Bin 0 -> 117044 bytes wx28X/build/msw/vc_mswd/core/ownerdrw.obj | Bin 0 -> 175433 bytes wx28X/build/msw/vc_mswd/core/palette.obj | Bin 0 -> 36175 bytes wx28X/build/msw/vc_mswd/core/panelg.obj | Bin 0 -> 83881 bytes wx28X/build/msw/vc_mswd/core/paper.obj | Bin 0 -> 155893 bytes wx28X/build/msw/vc_mswd/core/pen.obj | Bin 0 -> 66901 bytes wx28X/build/msw/vc_mswd/core/pickerbase.obj | Bin 0 -> 153043 bytes wx28X/build/msw/vc_mswd/core/popupcmn.obj | Bin 0 -> 138939 bytes wx28X/build/msw/vc_mswd/core/popupwin.obj | Bin 0 -> 13963 bytes wx28X/build/msw/vc_mswd/core/printdlg.obj | Bin 0 -> 216498 bytes wx28X/build/msw/vc_mswd/core/printps.obj | Bin 0 -> 2227 bytes wx28X/build/msw/vc_mswd/core/printwin.obj | Bin 0 -> 56454 bytes wx28X/build/msw/vc_mswd/core/prntbase.obj | Bin 0 -> 592615 bytes wx28X/build/msw/vc_mswd/core/prntdlgg.obj | Bin 0 -> 325150 bytes wx28X/build/msw/vc_mswd/core/progdlgg.obj | Bin 0 -> 203798 bytes wx28X/build/msw/vc_mswd/core/quantize.obj | Bin 0 -> 42751 bytes wx28X/build/msw/vc_mswd/core/radiobox.obj | Bin 0 -> 199344 bytes wx28X/build/msw/vc_mswd/core/radiobut.obj | Bin 0 -> 103919 bytes wx28X/build/msw/vc_mswd/core/radiocmn.obj | Bin 0 -> 46487 bytes wx28X/build/msw/vc_mswd/core/region.obj | Bin 0 -> 75177 bytes wx28X/build/msw/vc_mswd/core/rendcmn.obj | Bin 0 -> 45307 bytes wx28X/build/msw/vc_mswd/core/renderer.obj | Bin 0 -> 112264 bytes wx28X/build/msw/vc_mswd/core/renderg.obj | Bin 0 -> 230145 bytes wx28X/build/msw/vc_mswd/core/rgncmn.obj | Bin 0 -> 117801 bytes wx28X/build/msw/vc_mswd/core/scrlwing.obj | Bin 0 -> 174538 bytes wx28X/build/msw/vc_mswd/core/scrolbar.obj | Bin 0 -> 104113 bytes wx28X/build/msw/vc_mswd/core/selstore.obj | Bin 0 -> 18810 bytes wx28X/build/msw/vc_mswd/core/settcmn.obj | Bin 0 -> 3983 bytes wx28X/build/msw/vc_mswd/core/settings.obj | Bin 0 -> 58347 bytes wx28X/build/msw/vc_mswd/core/sizer.obj | Bin 0 -> 285065 bytes wx28X/build/msw/vc_mswd/core/slider95.obj | Bin 0 -> 144233 bytes wx28X/build/msw/vc_mswd/core/spinbutt.obj | Bin 0 -> 116464 bytes wx28X/build/msw/vc_mswd/core/spinctlg.obj | Bin 0 -> 2231 bytes wx28X/build/msw/vc_mswd/core/spinctrl.obj | Bin 0 -> 161727 bytes wx28X/build/msw/vc_mswd/core/splitter.obj | Bin 0 -> 168650 bytes wx28X/build/msw/vc_mswd/core/srchcmn.obj | Bin 0 -> 5603 bytes wx28X/build/msw/vc_mswd/core/srchctlg.obj | Bin 0 -> 369568 bytes wx28X/build/msw/vc_mswd/core/statbar.obj | Bin 0 -> 111930 bytes wx28X/build/msw/vc_mswd/core/statbmp.obj | Bin 0 -> 147189 bytes wx28X/build/msw/vc_mswd/core/statbox.obj | Bin 0 -> 237425 bytes wx28X/build/msw/vc_mswd/core/statbr95.obj | Bin 0 -> 104991 bytes wx28X/build/msw/vc_mswd/core/statline.obj | Bin 0 -> 89067 bytes wx28X/build/msw/vc_mswd/core/stattext.obj | Bin 0 -> 95487 bytes wx28X/build/msw/vc_mswd/core/statusbr.obj | Bin 0 -> 112744 bytes wx28X/build/msw/vc_mswd/core/stockitem.obj | Bin 0 -> 43977 bytes wx28X/build/msw/vc_mswd/core/tabctrl.obj | Bin 0 -> 2219 bytes wx28X/build/msw/vc_mswd/core/tbar95.obj | Bin 0 -> 336742 bytes wx28X/build/msw/vc_mswd/core/tbarbase.obj | Bin 0 -> 229767 bytes wx28X/build/msw/vc_mswd/core/textcmn.obj | Bin 0 -> 129959 bytes wx28X/build/msw/vc_mswd/core/textctrl.obj | Bin 0 -> 362085 bytes wx28X/build/msw/vc_mswd/core/textdlgg.obj | Bin 0 -> 207255 bytes wx28X/build/msw/vc_mswd/core/tglbtn.obj | Bin 0 -> 89747 bytes wx28X/build/msw/vc_mswd/core/timer.obj | Bin 0 -> 60409 bytes wx28X/build/msw/vc_mswd/core/timercmn.obj | Bin 0 -> 22226 bytes wx28X/build/msw/vc_mswd/core/tipwin.obj | Bin 0 -> 110225 bytes wx28X/build/msw/vc_mswd/core/toolbkg.obj | Bin 0 -> 194898 bytes wx28X/build/msw/vc_mswd/core/tooltip.obj | Bin 0 -> 46180 bytes wx28X/build/msw/vc_mswd/core/toplevel.obj | Bin 0 -> 177708 bytes wx28X/build/msw/vc_mswd/core/toplvcmn.obj | Bin 0 -> 138528 bytes wx28X/build/msw/vc_mswd/core/treebase.obj | Bin 0 -> 121492 bytes wx28X/build/msw/vc_mswd/core/treebkg.obj | Bin 0 -> 240191 bytes wx28X/build/msw/vc_mswd/core/treectlg.obj | Bin 0 -> 479829 bytes wx28X/build/msw/vc_mswd/core/treectrl.obj | Bin 0 -> 383991 bytes wx28X/build/msw/vc_mswd/core/utilscmn.obj | Bin 0 -> 200063 bytes wx28X/build/msw/vc_mswd/core/utilsgui.obj | Bin 0 -> 48156 bytes wx28X/build/msw/vc_mswd/core/uuid.obj | Bin 0 -> 7975 bytes wx28X/build/msw/vc_mswd/core/uxtheme.obj | Bin 0 -> 54026 bytes wx28X/build/msw/vc_mswd/core/valgen.obj | Bin 0 -> 49509 bytes wx28X/build/msw/vc_mswd/core/validate.obj | Bin 0 -> 15581 bytes wx28X/build/msw/vc_mswd/core/valtext.obj | Bin 0 -> 51878 bytes wx28X/build/msw/vc_mswd/core/vlbox.obj | Bin 0 -> 254021 bytes wx28X/build/msw/vc_mswd/core/volume.obj | Bin 0 -> 62591 bytes wx28X/build/msw/vc_mswd/core/vscroll.obj | Bin 0 -> 37928 bytes wx28X/build/msw/vc_mswd/core/wincmn.obj | Bin 0 -> 386490 bytes wx28X/build/msw/vc_mswd/core/window.obj | Bin 0 -> 730372 bytes wx28X/build/msw/vc_mswd/core/wx_core.log | 501 + wx28X/build/msw/vc_mswd/core/xpmdecod.obj | Bin 0 -> 89489 bytes wx28X/build/msw/vc_mswd/html/CL.read.1.tlog | Bin 0 -> 124120 bytes wx28X/build/msw/vc_mswd/html/CL.write.1.tlog | Bin 0 -> 8992 bytes .../msw/vc_mswd/html/Lib-link.read.1.tlog | Bin 0 -> 5442 bytes .../msw/vc_mswd/html/Lib-link.write.1.tlog | Bin 0 -> 2712 bytes .../build/msw/vc_mswd/html/cl.command.1.tlog | Bin 0 -> 27742 bytes .../vc_mswd/html/custombuild.command.1.tlog | Bin 0 -> 548 bytes .../msw/vc_mswd/html/custombuild.read.1.tlog | Bin 0 -> 178 bytes .../msw/vc_mswd/html/custombuild.write.1.tlog | Bin 0 -> 368 bytes wx28X/build/msw/vc_mswd/html/dummy.obj | Bin 0 -> 423864 bytes wx28X/build/msw/vc_mswd/html/helpbest.obj | Bin 0 -> 69637 bytes wx28X/build/msw/vc_mswd/html/helpctrl.obj | Bin 0 -> 191984 bytes wx28X/build/msw/vc_mswd/html/helpdata.obj | Bin 0 -> 219357 bytes wx28X/build/msw/vc_mswd/html/helpdlg.obj | Bin 0 -> 174965 bytes wx28X/build/msw/vc_mswd/html/helpfrm.obj | Bin 0 -> 134468 bytes wx28X/build/msw/vc_mswd/html/helpwnd.obj | Bin 0 -> 798881 bytes .../msw/vc_mswd/html/html.lastbuildstate | 2 + .../build/msw/vc_mswd/html/html.write.1.tlog | 0 wx28X/build/msw/vc_mswd/html/htmlcell.obj | Bin 0 -> 185279 bytes wx28X/build/msw/vc_mswd/html/htmlfilt.obj | Bin 0 -> 78789 bytes wx28X/build/msw/vc_mswd/html/htmllbox.obj | Bin 0 -> 268222 bytes wx28X/build/msw/vc_mswd/html/htmlpars.obj | Bin 0 -> 177743 bytes wx28X/build/msw/vc_mswd/html/htmltag.obj | Bin 0 -> 66680 bytes wx28X/build/msw/vc_mswd/html/htmlwin.obj | Bin 0 -> 583239 bytes wx28X/build/msw/vc_mswd/html/htmprint.obj | Bin 0 -> 212782 bytes .../build/msw/vc_mswd/html/lib.command.1.tlog | Bin 0 -> 4130 bytes wx28X/build/msw/vc_mswd/html/m_dflist.obj | Bin 0 -> 55481 bytes wx28X/build/msw/vc_mswd/html/m_fonts.obj | Bin 0 -> 165988 bytes wx28X/build/msw/vc_mswd/html/m_hline.obj | Bin 0 -> 75971 bytes wx28X/build/msw/vc_mswd/html/m_image.obj | Bin 0 -> 268740 bytes wx28X/build/msw/vc_mswd/html/m_layout.obj | Bin 0 -> 174456 bytes wx28X/build/msw/vc_mswd/html/m_links.obj | Bin 0 -> 116215 bytes wx28X/build/msw/vc_mswd/html/m_list.obj | Bin 0 -> 92057 bytes wx28X/build/msw/vc_mswd/html/m_pre.obj | Bin 0 -> 91593 bytes wx28X/build/msw/vc_mswd/html/m_style.obj | Bin 0 -> 40114 bytes wx28X/build/msw/vc_mswd/html/m_tables.obj | Bin 0 -> 132749 bytes wx28X/build/msw/vc_mswd/html/winpars.obj | Bin 0 -> 200874 bytes wx28X/build/msw/vc_mswd/html/wx_html.log | 77 + wx28X/build/msw/vc_mswd/net/CL.read.1.tlog | Bin 0 -> 42972 bytes wx28X/build/msw/vc_mswd/net/CL.write.1.tlog | Bin 0 -> 4422 bytes .../msw/vc_mswd/net/Lib-link.read.1.tlog | Bin 0 -> 2682 bytes .../msw/vc_mswd/net/Lib-link.write.1.tlog | Bin 0 -> 1340 bytes wx28X/build/msw/vc_mswd/net/cl.command.1.tlog | Bin 0 -> 14660 bytes .../vc_mswd/net/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../msw/vc_mswd/net/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../msw/vc_mswd/net/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswd/net/dummy.obj | Bin 0 -> 383200 bytes wx28X/build/msw/vc_mswd/net/fs_inet.obj | Bin 0 -> 82899 bytes wx28X/build/msw/vc_mswd/net/ftp.obj | Bin 0 -> 130388 bytes wx28X/build/msw/vc_mswd/net/gsocket.obj | Bin 0 -> 53925 bytes wx28X/build/msw/vc_mswd/net/http.obj | Bin 0 -> 134669 bytes .../build/msw/vc_mswd/net/lib.command.1.tlog | Bin 0 -> 2022 bytes .../build/msw/vc_mswd/net/net.lastbuildstate | 2 + wx28X/build/msw/vc_mswd/net/net.write.1.tlog | 0 wx28X/build/msw/vc_mswd/net/protocol.obj | Bin 0 -> 48509 bytes wx28X/build/msw/vc_mswd/net/sckaddr.obj | Bin 0 -> 50329 bytes wx28X/build/msw/vc_mswd/net/sckfile.obj | Bin 0 -> 31265 bytes wx28X/build/msw/vc_mswd/net/sckipc.obj | Bin 0 -> 110355 bytes wx28X/build/msw/vc_mswd/net/sckstrm.obj | Bin 0 -> 25930 bytes wx28X/build/msw/vc_mswd/net/socket.obj | Bin 0 -> 126153 bytes wx28X/build/msw/vc_mswd/net/url.obj | Bin 0 -> 78377 bytes wx28X/build/msw/vc_mswd/net/urlmsw.obj | Bin 0 -> 2175 bytes wx28X/build/msw/vc_mswd/net/wx_net.log | 51 + .../build/msw/vc_mswd/wxexpat/CL.read.1.tlog | Bin 0 -> 42854 bytes .../build/msw/vc_mswd/wxexpat/CL.write.1.tlog | Bin 0 -> 2146 bytes .../msw/vc_mswd/wxexpat/Lib-link.read.1.tlog | Bin 0 -> 1642 bytes .../msw/vc_mswd/wxexpat/Lib-link.write.1.tlog | Bin 0 -> 822 bytes .../msw/vc_mswd/wxexpat/cl.command.1.tlog | Bin 0 -> 4466 bytes .../msw/vc_mswd/wxexpat/lib.command.1.tlog | Bin 0 -> 1210 bytes .../build/msw/vc_mswd/wxexpat/wx_wxexpat.log | 25 + .../vc_mswd/wxexpat/wxexpat.lastbuildstate | 2 + wx28X/build/msw/vc_mswd/wxexpat/xmlparse.obj | Bin 0 -> 158017 bytes wx28X/build/msw/vc_mswd/wxexpat/xmlrole.obj | Bin 0 -> 48694 bytes wx28X/build/msw/vc_mswd/wxexpat/xmltok.obj | Bin 0 -> 256655 bytes wx28X/build/msw/vc_mswd/wxjpeg/CL.read.1.tlog | Bin 0 -> 183270 bytes .../build/msw/vc_mswd/wxjpeg/CL.write.1.tlog | Bin 0 -> 30830 bytes .../msw/vc_mswd/wxjpeg/Lib-link.read.1.tlog | Bin 0 -> 20206 bytes .../msw/vc_mswd/wxjpeg/Lib-link.write.1.tlog | Bin 0 -> 10014 bytes .../msw/vc_mswd/wxjpeg/cl.command.1.tlog | Bin 0 -> 63482 bytes wx28X/build/msw/vc_mswd/wxjpeg/jcapimin.obj | Bin 0 -> 10642 bytes wx28X/build/msw/vc_mswd/wxjpeg/jcapistd.obj | Bin 0 -> 7082 bytes wx28X/build/msw/vc_mswd/wxjpeg/jccoefct.obj | Bin 0 -> 11648 bytes wx28X/build/msw/vc_mswd/wxjpeg/jccolor.obj | Bin 0 -> 13275 bytes wx28X/build/msw/vc_mswd/wxjpeg/jcdctmgr.obj | Bin 0 -> 12088 bytes wx28X/build/msw/vc_mswd/wxjpeg/jchuff.obj | Bin 0 -> 19761 bytes wx28X/build/msw/vc_mswd/wxjpeg/jcinit.obj | Bin 0 -> 5461 bytes wx28X/build/msw/vc_mswd/wxjpeg/jcmainct.obj | Bin 0 -> 6513 bytes wx28X/build/msw/vc_mswd/wxjpeg/jcmarker.obj | Bin 0 -> 17006 bytes wx28X/build/msw/vc_mswd/wxjpeg/jcmaster.obj | Bin 0 -> 16594 bytes wx28X/build/msw/vc_mswd/wxjpeg/jcomapi.obj | Bin 0 -> 6076 bytes wx28X/build/msw/vc_mswd/wxjpeg/jcparam.obj | Bin 0 -> 18697 bytes wx28X/build/msw/vc_mswd/wxjpeg/jcphuff.obj | Bin 0 -> 18764 bytes wx28X/build/msw/vc_mswd/wxjpeg/jcprepct.obj | Bin 0 -> 10265 bytes wx28X/build/msw/vc_mswd/wxjpeg/jcsample.obj | Bin 0 -> 14238 bytes wx28X/build/msw/vc_mswd/wxjpeg/jctrans.obj | Bin 0 -> 12083 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdapimin.obj | Bin 0 -> 12562 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdapistd.obj | Bin 0 -> 9612 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdatadst.obj | Bin 0 -> 6116 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdatasrc.obj | Bin 0 -> 6561 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdcoefct.obj | Bin 0 -> 18816 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdcolor.obj | Bin 0 -> 12384 bytes wx28X/build/msw/vc_mswd/wxjpeg/jddctmgr.obj | Bin 0 -> 8477 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdhuff.obj | Bin 0 -> 16070 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdinput.obj | Bin 0 -> 11461 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdmainct.obj | Bin 0 -> 12449 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdmarker.obj | Bin 0 -> 36604 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdmaster.obj | Bin 0 -> 14009 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdmerge.obj | Bin 0 -> 11600 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdphuff.obj | Bin 0 -> 17074 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdpostct.obj | Bin 0 -> 9094 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdsample.obj | Bin 0 -> 13484 bytes wx28X/build/msw/vc_mswd/wxjpeg/jdtrans.obj | Bin 0 -> 6417 bytes wx28X/build/msw/vc_mswd/wxjpeg/jerror.obj | Bin 0 -> 16108 bytes wx28X/build/msw/vc_mswd/wxjpeg/jfdctflt.obj | Bin 0 -> 5855 bytes wx28X/build/msw/vc_mswd/wxjpeg/jfdctfst.obj | Bin 0 -> 5283 bytes wx28X/build/msw/vc_mswd/wxjpeg/jfdctint.obj | Bin 0 -> 5636 bytes wx28X/build/msw/vc_mswd/wxjpeg/jidctflt.obj | Bin 0 -> 9115 bytes wx28X/build/msw/vc_mswd/wxjpeg/jidctfst.obj | Bin 0 -> 8705 bytes wx28X/build/msw/vc_mswd/wxjpeg/jidctint.obj | Bin 0 -> 9268 bytes wx28X/build/msw/vc_mswd/wxjpeg/jidctred.obj | Bin 0 -> 9759 bytes wx28X/build/msw/vc_mswd/wxjpeg/jmemmgr.obj | Bin 0 -> 21239 bytes wx28X/build/msw/vc_mswd/wxjpeg/jmemnobs.obj | Bin 0 -> 6650 bytes wx28X/build/msw/vc_mswd/wxjpeg/jquant1.obj | Bin 0 -> 20262 bytes wx28X/build/msw/vc_mswd/wxjpeg/jquant2.obj | Bin 0 -> 26693 bytes wx28X/build/msw/vc_mswd/wxjpeg/jutils.obj | Bin 0 -> 5848 bytes .../msw/vc_mswd/wxjpeg/lib.command.1.tlog | Bin 0 -> 15642 bytes wx28X/build/msw/vc_mswd/wxjpeg/wx_wxjpeg.log | 115 + .../msw/vc_mswd/wxjpeg/wxjpeg.lastbuildstate | 2 + wx28X/build/msw/vc_mswd/wxpng/CL.read.1.tlog | Bin 0 -> 86090 bytes wx28X/build/msw/vc_mswd/wxpng/CL.write.1.tlog | Bin 0 -> 11026 bytes .../msw/vc_mswd/wxpng/Lib-link.read.1.tlog | Bin 0 -> 7474 bytes .../msw/vc_mswd/wxpng/Lib-link.write.1.tlog | Bin 0 -> 3702 bytes .../build/msw/vc_mswd/wxpng/cl.command.1.tlog | Bin 0 -> 22646 bytes .../msw/vc_mswd/wxpng/lib.command.1.tlog | Bin 0 -> 5690 bytes wx28X/build/msw/vc_mswd/wxpng/png.obj | Bin 0 -> 22947 bytes wx28X/build/msw/vc_mswd/wxpng/pngerror.obj | Bin 0 -> 12007 bytes wx28X/build/msw/vc_mswd/wxpng/pnggccrd.obj | Bin 0 -> 3368 bytes wx28X/build/msw/vc_mswd/wxpng/pngget.obj | Bin 0 -> 28972 bytes wx28X/build/msw/vc_mswd/wxpng/pngmem.obj | Bin 0 -> 11735 bytes wx28X/build/msw/vc_mswd/wxpng/pngpread.obj | Bin 0 -> 38766 bytes wx28X/build/msw/vc_mswd/wxpng/pngread.obj | Bin 0 -> 35568 bytes wx28X/build/msw/vc_mswd/wxpng/pngrio.obj | Bin 0 -> 6914 bytes wx28X/build/msw/vc_mswd/wxpng/pngrtran.obj | Bin 0 -> 88534 bytes wx28X/build/msw/vc_mswd/wxpng/pngrutil.obj | Bin 0 -> 68213 bytes wx28X/build/msw/vc_mswd/wxpng/pngset.obj | Bin 0 -> 35206 bytes wx28X/build/msw/vc_mswd/wxpng/pngtrans.obj | Bin 0 -> 17571 bytes wx28X/build/msw/vc_mswd/wxpng/pngvcrd.obj | Bin 0 -> 3368 bytes wx28X/build/msw/vc_mswd/wxpng/pngwio.obj | Bin 0 -> 7792 bytes wx28X/build/msw/vc_mswd/wxpng/pngwrite.obj | Bin 0 -> 35324 bytes wx28X/build/msw/vc_mswd/wxpng/pngwtran.obj | Bin 0 -> 16610 bytes wx28X/build/msw/vc_mswd/wxpng/pngwutil.obj | Bin 0 -> 61667 bytes wx28X/build/msw/vc_mswd/wxpng/wx_wxpng.log | 53 + .../msw/vc_mswd/wxpng/wxpng.lastbuildstate | 2 + .../msw/vc_mswd/wxpng/wxpng.write.1.tlog | 0 wx28X/build/msw/vc_mswd/wxprec_advlib.pch | Bin 0 -> 25165824 bytes wx28X/build/msw/vc_mswd/wxprec_baselib.pch | Bin 0 -> 16777216 bytes wx28X/build/msw/vc_mswd/wxprec_corelib.pch | Bin 0 -> 25165824 bytes wx28X/build/msw/vc_mswd/wxprec_htmllib.pch | Bin 0 -> 25165824 bytes wx28X/build/msw/vc_mswd/wxprec_netlib.pch | Bin 0 -> 16711680 bytes .../build/msw/vc_mswd/wxregex/CL.read.1.tlog | Bin 0 -> 26558 bytes .../build/msw/vc_mswd/wxregex/CL.write.1.tlog | Bin 0 -> 2742 bytes .../msw/vc_mswd/wxregex/Lib-link.read.1.tlog | Bin 0 -> 2086 bytes .../msw/vc_mswd/wxregex/Lib-link.write.1.tlog | Bin 0 -> 1042 bytes .../msw/vc_mswd/wxregex/cl.command.1.tlog | Bin 0 -> 6042 bytes .../wxregex/custombuild.command.1.tlog | Bin 0 -> 1078 bytes .../vc_mswd/wxregex/custombuild.read.1.tlog | Bin 0 -> 346 bytes .../vc_mswd/wxregex/custombuild.write.1.tlog | Bin 0 -> 718 bytes .../msw/vc_mswd/wxregex/lib.command.1.tlog | Bin 0 -> 1558 bytes wx28X/build/msw/vc_mswd/wxregex/regcomp.obj | Bin 0 -> 180197 bytes wx28X/build/msw/vc_mswd/wxregex/regerror.obj | Bin 0 -> 8997 bytes wx28X/build/msw/vc_mswd/wxregex/regexec.obj | Bin 0 -> 48774 bytes wx28X/build/msw/vc_mswd/wxregex/regfree.obj | Bin 0 -> 5474 bytes .../build/msw/vc_mswd/wxregex/wx_wxregex.log | 32 + .../vc_mswd/wxregex/wxregex.lastbuildstate | 2 + wx28X/build/msw/vc_mswd/wxtiff/CL.read.1.tlog | Bin 0 -> 892938 bytes .../build/msw/vc_mswd/wxtiff/CL.write.1.tlog | Bin 0 -> 24306 bytes .../msw/vc_mswd/wxtiff/Lib-link.read.1.tlog | Bin 0 -> 16018 bytes .../msw/vc_mswd/wxtiff/Lib-link.write.1.tlog | Bin 0 -> 7942 bytes .../msw/vc_mswd/wxtiff/cl.command.1.tlog | Bin 0 -> 50266 bytes .../msw/vc_mswd/wxtiff/lib.command.1.tlog | Bin 0 -> 12510 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_aux.obj | Bin 0 -> 26265 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_close.obj | Bin 0 -> 19261 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_codec.obj | Bin 0 -> 20790 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_color.obj | Bin 0 -> 26080 bytes .../build/msw/vc_mswd/wxtiff/tif_compress.obj | Bin 0 -> 27171 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_dir.obj | Bin 0 -> 63099 bytes .../build/msw/vc_mswd/wxtiff/tif_dirinfo.obj | Bin 0 -> 32624 bytes .../build/msw/vc_mswd/wxtiff/tif_dirread.obj | Bin 0 -> 59359 bytes .../build/msw/vc_mswd/wxtiff/tif_dirwrite.obj | Bin 0 -> 52306 bytes .../build/msw/vc_mswd/wxtiff/tif_dumpmode.obj | Bin 0 -> 20530 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_error.obj | Bin 0 -> 17722 bytes .../msw/vc_mswd/wxtiff/tif_extension.obj | Bin 0 -> 20666 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_fax3.obj | Bin 0 -> 80000 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_fax3sm.obj | Bin 0 -> 101234 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_flush.obj | Bin 0 -> 18683 bytes .../build/msw/vc_mswd/wxtiff/tif_getimage.obj | Bin 0 -> 114880 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_jpeg.obj | Bin 0 -> 16574 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_luv.obj | Bin 0 -> 75088 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_lzw.obj | Bin 0 -> 30825 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_next.obj | Bin 0 -> 20370 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_open.obj | Bin 0 -> 28356 bytes .../build/msw/vc_mswd/wxtiff/tif_packbits.obj | Bin 0 -> 23993 bytes .../build/msw/vc_mswd/wxtiff/tif_pixarlog.obj | Bin 0 -> 16586 bytes .../build/msw/vc_mswd/wxtiff/tif_predict.obj | Bin 0 -> 36690 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_print.obj | Bin 0 -> 38633 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_read.obj | Bin 0 -> 35419 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_strip.obj | Bin 0 -> 24803 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_swab.obj | Bin 0 -> 21318 bytes .../build/msw/vc_mswd/wxtiff/tif_thunder.obj | Bin 0 -> 21646 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_tile.obj | Bin 0 -> 25249 bytes .../build/msw/vc_mswd/wxtiff/tif_version.obj | Bin 0 -> 17275 bytes .../build/msw/vc_mswd/wxtiff/tif_warning.obj | Bin 0 -> 17740 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_win32.obj | Bin 0 -> 30537 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_write.obj | Bin 0 -> 33774 bytes wx28X/build/msw/vc_mswd/wxtiff/tif_zip.obj | Bin 0 -> 16574 bytes wx28X/build/msw/vc_mswd/wxtiff/wx_wxtiff.log | 91 + .../msw/vc_mswd/wxtiff/wxtiff.lastbuildstate | 2 + wx28X/build/msw/vc_mswd/wxzlib/CL.read.1.tlog | Bin 0 -> 31782 bytes .../build/msw/vc_mswd/wxzlib/CL.write.1.tlog | Bin 0 -> 7894 bytes .../msw/vc_mswd/wxzlib/Lib-link.read.1.tlog | Bin 0 -> 5414 bytes .../msw/vc_mswd/wxzlib/Lib-link.write.1.tlog | Bin 0 -> 2686 bytes wx28X/build/msw/vc_mswd/wxzlib/adler32.obj | Bin 0 -> 4156 bytes .../msw/vc_mswd/wxzlib/cl.command.1.tlog | Bin 0 -> 15306 bytes wx28X/build/msw/vc_mswd/wxzlib/compress.obj | Bin 0 -> 3456 bytes wx28X/build/msw/vc_mswd/wxzlib/crc32.obj | Bin 0 -> 18338 bytes wx28X/build/msw/vc_mswd/wxzlib/deflate.obj | Bin 0 -> 32549 bytes wx28X/build/msw/vc_mswd/wxzlib/gzio.obj | Bin 0 -> 23921 bytes wx28X/build/msw/vc_mswd/wxzlib/infback.obj | Bin 0 -> 17679 bytes wx28X/build/msw/vc_mswd/wxzlib/inffast.obj | Bin 0 -> 7184 bytes wx28X/build/msw/vc_mswd/wxzlib/inflate.obj | Bin 0 -> 31027 bytes wx28X/build/msw/vc_mswd/wxzlib/inftrees.obj | Bin 0 -> 7106 bytes .../msw/vc_mswd/wxzlib/lib.command.1.tlog | Bin 0 -> 4114 bytes wx28X/build/msw/vc_mswd/wxzlib/trees.obj | Bin 0 -> 33599 bytes wx28X/build/msw/vc_mswd/wxzlib/uncompr.obj | Bin 0 -> 2746 bytes wx28X/build/msw/vc_mswd/wxzlib/wx_wxzlib.log | 43 + .../msw/vc_mswd/wxzlib/wxzlib.lastbuildstate | 2 + wx28X/build/msw/vc_mswd/wxzlib/zutil.obj | Bin 0 -> 5440 bytes wx28X/build/msw/vc_mswddll/adv/CL.read.1.tlog | Bin 0 -> 66204 bytes .../build/msw/vc_mswddll/adv/CL.write.1.tlog | Bin 0 -> 10094 bytes wx28X/build/msw/vc_mswddll/adv/aboutdlg.obj | Bin 0 -> 78721 bytes wx28X/build/msw/vc_mswddll/adv/aboutdlgg.obj | Bin 0 -> 174934 bytes .../msw/vc_mswddll/adv/adv.Build.CppClean.log | 62 + .../msw/vc_mswddll/adv/adv.dll.embed.manifest | 15 + .../vc_mswddll/adv/adv.dll.embed.manifest.res | Bin 0 -> 748 bytes .../adv/adv.dll.intermediate.manifest | 15 + .../msw/vc_mswddll/adv/adv.lastbuildstate | 2 + .../build/msw/vc_mswddll/adv/adv.write.1.tlog | 3 + .../build/msw/vc_mswddll/adv/adv_manifest.rc | Bin 0 -> 224 bytes wx28X/build/msw/vc_mswddll/adv/animatecmn.obj | Bin 0 -> 159088 bytes wx28X/build/msw/vc_mswddll/adv/animateg.obj | Bin 0 -> 232340 bytes wx28X/build/msw/vc_mswddll/adv/bmpcboxg.obj | Bin 0 -> 135814 bytes wx28X/build/msw/vc_mswddll/adv/calctrl.obj | Bin 0 -> 247326 bytes .../msw/vc_mswddll/adv/cl.command.1.tlog | Bin 0 -> 34012 bytes .../vc_mswddll/adv/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../vc_mswddll/adv/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../vc_mswddll/adv/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswddll/adv/datavcmn.obj | Bin 0 -> 241949 bytes wx28X/build/msw/vc_mswddll/adv/datavgen.obj | Bin 0 -> 463928 bytes wx28X/build/msw/vc_mswddll/adv/datectlg.obj | Bin 0 -> 33384 bytes wx28X/build/msw/vc_mswddll/adv/datectrl.obj | Bin 0 -> 75225 bytes wx28X/build/msw/vc_mswddll/adv/dummy.obj | Bin 0 -> 420733 bytes wx28X/build/msw/vc_mswddll/adv/grid.obj | Bin 0 -> 1268167 bytes wx28X/build/msw/vc_mswddll/adv/gridctrl.obj | Bin 0 -> 375266 bytes wx28X/build/msw/vc_mswddll/adv/gridsel.obj | Bin 0 -> 313549 bytes wx28X/build/msw/vc_mswddll/adv/helpext.obj | Bin 0 -> 74951 bytes wx28X/build/msw/vc_mswddll/adv/hyperlink.obj | Bin 0 -> 102149 bytes wx28X/build/msw/vc_mswddll/adv/joystick.obj | Bin 0 -> 43554 bytes wx28X/build/msw/vc_mswddll/adv/laywin.obj | Bin 0 -> 121184 bytes .../vc_mswddll/adv/link-cvtres.read.1.tlog | 1 + .../vc_mswddll/adv/link-cvtres.write.1.tlog | 1 + .../adv/link.3868-cvtres.read.1.tlog | 1 + .../adv/link.3868-cvtres.write.1.tlog | 1 + .../msw/vc_mswddll/adv/link.3868.read.1.tlog | 1 + .../msw/vc_mswddll/adv/link.3868.write.1.tlog | 1 + .../msw/vc_mswddll/adv/link.command.1.tlog | Bin 0 -> 7406 bytes .../build/msw/vc_mswddll/adv/link.read.1.tlog | Bin 0 -> 10920 bytes .../msw/vc_mswddll/adv/link.write.1.tlog | Bin 0 -> 4080 bytes .../msw/vc_mswddll/adv/mt.command.1.tlog | Bin 0 -> 390 bytes wx28X/build/msw/vc_mswddll/adv/mt.read.1.tlog | Bin 0 -> 146 bytes .../build/msw/vc_mswddll/adv/mt.write.1.tlog | Bin 0 -> 274 bytes wx28X/build/msw/vc_mswddll/adv/odcombo.obj | Bin 0 -> 167300 bytes wx28X/build/msw/vc_mswddll/adv/propdlg.obj | Bin 0 -> 109370 bytes .../msw/vc_mswddll/adv/rc.command.1.tlog | Bin 0 -> 2138 bytes wx28X/build/msw/vc_mswddll/adv/rc.read.1.tlog | Bin 0 -> 458 bytes .../build/msw/vc_mswddll/adv/rc.write.1.tlog | Bin 0 -> 432 bytes wx28X/build/msw/vc_mswddll/adv/sashwin.obj | Bin 0 -> 150542 bytes wx28X/build/msw/vc_mswddll/adv/sound.obj | Bin 0 -> 45356 bytes wx28X/build/msw/vc_mswddll/adv/splash.obj | Bin 0 -> 77384 bytes wx28X/build/msw/vc_mswddll/adv/taskbar.obj | Bin 0 -> 66400 bytes wx28X/build/msw/vc_mswddll/adv/taskbarcmn.obj | Bin 0 -> 31424 bytes wx28X/build/msw/vc_mswddll/adv/tipdlg.obj | Bin 0 -> 123409 bytes wx28X/build/msw/vc_mswddll/adv/version.res | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswddll/adv/wizard.obj | Bin 0 -> 190155 bytes wx28X/build/msw/vc_mswddll/adv/wx_adv.log | 139 + wx28X/build/msw/vc_mswddll/aui/CL.read.1.tlog | Bin 0 -> 47214 bytes .../build/msw/vc_mswddll/aui/CL.write.1.tlog | Bin 0 -> 2580 bytes .../msw/vc_mswddll/aui/aui.Build.CppClean.log | 42 + .../msw/vc_mswddll/aui/aui.dll.embed.manifest | 15 + .../vc_mswddll/aui/aui.dll.embed.manifest.res | Bin 0 -> 748 bytes .../aui/aui.dll.intermediate.manifest | 15 + .../msw/vc_mswddll/aui/aui.lastbuildstate | 2 + .../build/msw/vc_mswddll/aui/aui.write.1.tlog | 3 + .../build/msw/vc_mswddll/aui/aui_manifest.rc | Bin 0 -> 224 bytes wx28X/build/msw/vc_mswddll/aui/auibar.obj | Bin 0 -> 518172 bytes wx28X/build/msw/vc_mswddll/aui/auibook.obj | Bin 0 -> 701628 bytes .../msw/vc_mswddll/aui/cl.command.1.tlog | Bin 0 -> 8748 bytes .../vc_mswddll/aui/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../vc_mswddll/aui/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../vc_mswddll/aui/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswddll/aui/dockart.obj | Bin 0 -> 283639 bytes wx28X/build/msw/vc_mswddll/aui/dummy.obj | Bin 0 -> 420733 bytes wx28X/build/msw/vc_mswddll/aui/floatpane.obj | Bin 0 -> 268130 bytes .../build/msw/vc_mswddll/aui/framemanager.obj | Bin 0 -> 747141 bytes .../vc_mswddll/aui/link-cvtres.read.1.tlog | 1 + .../vc_mswddll/aui/link-cvtres.write.1.tlog | 1 + .../aui/link.1208-cvtres.read.1.tlog | 1 + .../aui/link.1208-cvtres.write.1.tlog | 1 + .../msw/vc_mswddll/aui/link.1208.read.1.tlog | 1 + .../msw/vc_mswddll/aui/link.1208.write.1.tlog | 1 + .../msw/vc_mswddll/aui/link.command.1.tlog | Bin 0 -> 4170 bytes .../build/msw/vc_mswddll/aui/link.read.1.tlog | Bin 0 -> 6786 bytes .../msw/vc_mswddll/aui/link.write.1.tlog | Bin 0 -> 1988 bytes .../msw/vc_mswddll/aui/mt.command.1.tlog | Bin 0 -> 390 bytes wx28X/build/msw/vc_mswddll/aui/mt.read.1.tlog | Bin 0 -> 146 bytes .../build/msw/vc_mswddll/aui/mt.write.1.tlog | Bin 0 -> 274 bytes .../msw/vc_mswddll/aui/rc.command.1.tlog | Bin 0 -> 2138 bytes wx28X/build/msw/vc_mswddll/aui/rc.read.1.tlog | Bin 0 -> 458 bytes .../build/msw/vc_mswddll/aui/rc.write.1.tlog | Bin 0 -> 432 bytes wx28X/build/msw/vc_mswddll/aui/tabmdi.obj | Bin 0 -> 449985 bytes wx28X/build/msw/vc_mswddll/aui/version.res | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswddll/aui/wx_aui.log | 77 + .../build/msw/vc_mswddll/base/CL.read.1.tlog | Bin 0 -> 115686 bytes .../build/msw/vc_mswddll/base/CL.write.1.tlog | Bin 0 -> 32058 bytes wx28X/build/msw/vc_mswddll/base/appbase.obj | Bin 0 -> 492063 bytes wx28X/build/msw/vc_mswddll/base/arcall.obj | Bin 0 -> 515403 bytes wx28X/build/msw/vc_mswddll/base/arcfind.obj | Bin 0 -> 311603 bytes wx28X/build/msw/vc_mswddll/base/archive.obj | Bin 0 -> 319657 bytes .../msw/vc_mswddll/base/base.lastbuildstate | 2 + .../msw/vc_mswddll/base/base.write.1.tlog | 3 + wx28X/build/msw/vc_mswddll/base/basemsw.obj | Bin 0 -> 29426 bytes .../msw/vc_mswddll/base/cl.command.1.tlog | Bin 0 -> 114482 bytes wx28X/build/msw/vc_mswddll/base/clntdata.obj | Bin 0 -> 11533 bytes wx28X/build/msw/vc_mswddll/base/cmdline.obj | Bin 0 -> 404893 bytes wx28X/build/msw/vc_mswddll/base/config.obj | Bin 0 -> 127217 bytes wx28X/build/msw/vc_mswddll/base/convauto.obj | Bin 0 -> 39697 bytes wx28X/build/msw/vc_mswddll/base/crashrpt.obj | Bin 0 -> 83131 bytes .../base/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../vc_mswddll/base/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../vc_mswddll/base/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswddll/base/datetime.obj | Bin 0 -> 451115 bytes wx28X/build/msw/vc_mswddll/base/datstrm.obj | Bin 0 -> 87049 bytes wx28X/build/msw/vc_mswddll/base/dde.obj | Bin 0 -> 417238 bytes wx28X/build/msw/vc_mswddll/base/debughlp.obj | Bin 0 -> 115386 bytes wx28X/build/msw/vc_mswddll/base/dir.obj | Bin 0 -> 48270 bytes wx28X/build/msw/vc_mswddll/base/dircmn.obj | Bin 0 -> 312027 bytes wx28X/build/msw/vc_mswddll/base/dlmsw.obj | Bin 0 -> 89370 bytes wx28X/build/msw/vc_mswddll/base/dummy.obj | Bin 0 -> 1728513 bytes wx28X/build/msw/vc_mswddll/base/dynarray.obj | Bin 0 -> 133667 bytes wx28X/build/msw/vc_mswddll/base/dynlib.obj | Bin 0 -> 331188 bytes wx28X/build/msw/vc_mswddll/base/dynload.obj | Bin 0 -> 196246 bytes wx28X/build/msw/vc_mswddll/base/encconv.obj | Bin 0 -> 61034 bytes wx28X/build/msw/vc_mswddll/base/event.obj | Bin 0 -> 113503 bytes wx28X/build/msw/vc_mswddll/base/extended.obj | Bin 0 -> 8347 bytes wx28X/build/msw/vc_mswddll/base/ffile.obj | Bin 0 -> 46895 bytes wx28X/build/msw/vc_mswddll/base/file.obj | Bin 0 -> 299688 bytes wx28X/build/msw/vc_mswddll/base/fileback.obj | Bin 0 -> 71146 bytes wx28X/build/msw/vc_mswddll/base/fileconf.obj | Bin 0 -> 351684 bytes wx28X/build/msw/vc_mswddll/base/filefn.obj | Bin 0 -> 400428 bytes wx28X/build/msw/vc_mswddll/base/filename.obj | Bin 0 -> 592576 bytes wx28X/build/msw/vc_mswddll/base/filesys.obj | Bin 0 -> 597489 bytes wx28X/build/msw/vc_mswddll/base/filtall.obj | Bin 0 -> 48043 bytes wx28X/build/msw/vc_mswddll/base/filtfind.obj | Bin 0 -> 4455 bytes wx28X/build/msw/vc_mswddll/base/fmapbase.obj | Bin 0 -> 253404 bytes wx28X/build/msw/vc_mswddll/base/fs_arc.obj | Bin 0 -> 693495 bytes wx28X/build/msw/vc_mswddll/base/fs_filter.obj | Bin 0 -> 375434 bytes wx28X/build/msw/vc_mswddll/base/fs_mem.obj | Bin 0 -> 407314 bytes wx28X/build/msw/vc_mswddll/base/hash.obj | Bin 0 -> 33897 bytes wx28X/build/msw/vc_mswddll/base/hashmap.obj | Bin 0 -> 7581 bytes wx28X/build/msw/vc_mswddll/base/init.obj | Bin 0 -> 60775 bytes wx28X/build/msw/vc_mswddll/base/intl.obj | Bin 0 -> 622765 bytes wx28X/build/msw/vc_mswddll/base/ipcbase.obj | Bin 0 -> 35588 bytes .../vc_mswddll/base/link-cvtres.read.1.tlog | 1 + .../vc_mswddll/base/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswddll/base/link.command.1.tlog | Bin 0 -> 16980 bytes .../msw/vc_mswddll/base/link.read.1.tlog | Bin 0 -> 23198 bytes .../msw/vc_mswddll/base/link.write.1.tlog | Bin 0 -> 10344 bytes wx28X/build/msw/vc_mswddll/base/list.obj | Bin 0 -> 91889 bytes wx28X/build/msw/vc_mswddll/base/log.obj | Bin 0 -> 417376 bytes wx28X/build/msw/vc_mswddll/base/longlong.obj | Bin 0 -> 71213 bytes wx28X/build/msw/vc_mswddll/base/main.obj | Bin 0 -> 230272 bytes wx28X/build/msw/vc_mswddll/base/memory.obj | Bin 0 -> 2351 bytes wx28X/build/msw/vc_mswddll/base/mimecmn.obj | Bin 0 -> 229545 bytes wx28X/build/msw/vc_mswddll/base/mimetype.obj | Bin 0 -> 226393 bytes wx28X/build/msw/vc_mswddll/base/module.obj | Bin 0 -> 59047 bytes wx28X/build/msw/vc_mswddll/base/msgout.obj | Bin 0 -> 40118 bytes wx28X/build/msw/vc_mswddll/base/mslu.obj | Bin 0 -> 2808 bytes wx28X/build/msw/vc_mswddll/base/mstream.obj | Bin 0 -> 35679 bytes .../msw/vc_mswddll/base/mt.command.1.tlog | Bin 0 -> 492 bytes .../build/msw/vc_mswddll/base/mt.read.1.tlog | Bin 0 -> 180 bytes .../build/msw/vc_mswddll/base/mt.write.1.tlog | Bin 0 -> 342 bytes wx28X/build/msw/vc_mswddll/base/object.obj | Bin 0 -> 38630 bytes wx28X/build/msw/vc_mswddll/base/platinfo.obj | Bin 0 -> 63296 bytes wx28X/build/msw/vc_mswddll/base/power.obj | Bin 0 -> 15187 bytes wx28X/build/msw/vc_mswddll/base/powercmn.obj | Bin 0 -> 19076 bytes wx28X/build/msw/vc_mswddll/base/process.obj | Bin 0 -> 44175 bytes .../msw/vc_mswddll/base/rc.command.1.tlog | Bin 0 -> 2372 bytes .../build/msw/vc_mswddll/base/rc.read.1.tlog | Bin 0 -> 526 bytes .../build/msw/vc_mswddll/base/rc.write.1.tlog | Bin 0 -> 502 bytes wx28X/build/msw/vc_mswddll/base/regconf.obj | Bin 0 -> 111883 bytes wx28X/build/msw/vc_mswddll/base/regex.obj | Bin 0 -> 59782 bytes wx28X/build/msw/vc_mswddll/base/registry.obj | Bin 0 -> 185437 bytes wx28X/build/msw/vc_mswddll/base/snglinst.obj | Bin 0 -> 16006 bytes wx28X/build/msw/vc_mswddll/base/sstream.obj | Bin 0 -> 47009 bytes wx28X/build/msw/vc_mswddll/base/stackwalk.obj | Bin 0 -> 116301 bytes wx28X/build/msw/vc_mswddll/base/stdpaths.obj | Bin 0 -> 366304 bytes wx28X/build/msw/vc_mswddll/base/stdpbase.obj | Bin 0 -> 322770 bytes wx28X/build/msw/vc_mswddll/base/stopwatch.obj | Bin 0 -> 14406 bytes wx28X/build/msw/vc_mswddll/base/strconv.obj | Bin 0 -> 166208 bytes wx28X/build/msw/vc_mswddll/base/stream.obj | Bin 0 -> 218102 bytes wx28X/build/msw/vc_mswddll/base/string.obj | Bin 0 -> 200099 bytes wx28X/build/msw/vc_mswddll/base/sysopt.obj | Bin 0 -> 38665 bytes wx28X/build/msw/vc_mswddll/base/tarstrm.obj | Bin 0 -> 570543 bytes wx28X/build/msw/vc_mswddll/base/textbuf.obj | Bin 0 -> 109129 bytes wx28X/build/msw/vc_mswddll/base/textfile.obj | Bin 0 -> 378965 bytes wx28X/build/msw/vc_mswddll/base/thread.obj | Bin 0 -> 156728 bytes wx28X/build/msw/vc_mswddll/base/tokenzr.obj | Bin 0 -> 53724 bytes wx28X/build/msw/vc_mswddll/base/txtstrm.obj | Bin 0 -> 80868 bytes wx28X/build/msw/vc_mswddll/base/uri.obj | Bin 0 -> 104364 bytes wx28X/build/msw/vc_mswddll/base/utils.obj | Bin 0 -> 268037 bytes wx28X/build/msw/vc_mswddll/base/utilscmn.obj | Bin 0 -> 257625 bytes wx28X/build/msw/vc_mswddll/base/utilsexc.obj | Bin 0 -> 400100 bytes wx28X/build/msw/vc_mswddll/base/variant.obj | Bin 0 -> 604023 bytes wx28X/build/msw/vc_mswddll/base/version.res | Bin 0 -> 1040 bytes wx28X/build/msw/vc_mswddll/base/volume.obj | Bin 0 -> 147187 bytes wx28X/build/msw/vc_mswddll/base/wfstream.obj | Bin 0 -> 117143 bytes wx28X/build/msw/vc_mswddll/base/wx_base.log | 325 + .../wxbase28d_vc_custom.Build.CppClean.log | 127 + .../wxbase28d_vc_custom.dll.embed.manifest | 15 + ...wxbase28d_vc_custom.dll.embed.manifest.res | Bin 0 -> 748 bytes ...ase28d_vc_custom.dll.intermediate.manifest | 15 + .../base/wxbase28d_vc_custom_manifest.rc | Bin 0 -> 258 bytes wx28X/build/msw/vc_mswddll/base/wxchar.obj | Bin 0 -> 8745 bytes wx28X/build/msw/vc_mswddll/base/xti.obj | Bin 0 -> 2343 bytes wx28X/build/msw/vc_mswddll/base/xtistrm.obj | Bin 0 -> 2355 bytes wx28X/build/msw/vc_mswddll/base/zipstrm.obj | Bin 0 -> 820315 bytes wx28X/build/msw/vc_mswddll/base/zstream.obj | Bin 0 -> 99199 bytes .../build/msw/vc_mswddll/core/CL.read.1.tlog | Bin 0 -> 233068 bytes .../build/msw/vc_mswddll/core/CL.write.1.tlog | Bin 0 -> 84210 bytes wx28X/build/msw/vc_mswddll/core/accel.obj | Bin 0 -> 26116 bytes wx28X/build/msw/vc_mswddll/core/access.obj | Bin 0 -> 2367 bytes wx28X/build/msw/vc_mswddll/core/accesscmn.obj | Bin 0 -> 2371 bytes wx28X/build/msw/vc_mswddll/core/anidecod.obj | Bin 0 -> 125847 bytes wx28X/build/msw/vc_mswddll/core/app.obj | Bin 0 -> 157634 bytes wx28X/build/msw/vc_mswddll/core/appcmn.obj | Bin 0 -> 117088 bytes wx28X/build/msw/vc_mswddll/core/artprov.obj | Bin 0 -> 214888 bytes wx28X/build/msw/vc_mswddll/core/artstd.obj | Bin 0 -> 154890 bytes wx28X/build/msw/vc_mswddll/core/automtn.obj | Bin 0 -> 65912 bytes wx28X/build/msw/vc_mswddll/core/bitmap.obj | Bin 0 -> 193587 bytes wx28X/build/msw/vc_mswddll/core/bmpbase.obj | Bin 0 -> 73929 bytes wx28X/build/msw/vc_mswddll/core/bmpbuttn.obj | Bin 0 -> 245591 bytes wx28X/build/msw/vc_mswddll/core/bookctrl.obj | Bin 0 -> 307800 bytes wx28X/build/msw/vc_mswddll/core/brush.obj | Bin 0 -> 79843 bytes wx28X/build/msw/vc_mswddll/core/busyinfo.obj | Bin 0 -> 120539 bytes wx28X/build/msw/vc_mswddll/core/button.obj | Bin 0 -> 130145 bytes wx28X/build/msw/vc_mswddll/core/buttonbar.obj | Bin 0 -> 2371 bytes wx28X/build/msw/vc_mswddll/core/caret.obj | Bin 0 -> 41309 bytes wx28X/build/msw/vc_mswddll/core/checkbox.obj | Bin 0 -> 117328 bytes wx28X/build/msw/vc_mswddll/core/checklst.obj | Bin 0 -> 137869 bytes wx28X/build/msw/vc_mswddll/core/choicbkg.obj | Bin 0 -> 351231 bytes wx28X/build/msw/vc_mswddll/core/choiccmn.obj | Bin 0 -> 57570 bytes wx28X/build/msw/vc_mswddll/core/choicdgg.obj | Bin 0 -> 250236 bytes wx28X/build/msw/vc_mswddll/core/choice.obj | Bin 0 -> 140186 bytes .../msw/vc_mswddll/core/cl.command.1.tlog | Bin 0 -> 293844 bytes wx28X/build/msw/vc_mswddll/core/clipbrd.obj | Bin 0 -> 138054 bytes wx28X/build/msw/vc_mswddll/core/clipcmn.obj | Bin 0 -> 26350 bytes .../msw/vc_mswddll/core/clrpickercmn.obj | Bin 0 -> 190640 bytes .../build/msw/vc_mswddll/core/clrpickerg.obj | Bin 0 -> 189343 bytes wx28X/build/msw/vc_mswddll/core/cmdproc.obj | Bin 0 -> 64056 bytes wx28X/build/msw/vc_mswddll/core/cmndata.obj | Bin 0 -> 271032 bytes wx28X/build/msw/vc_mswddll/core/collpaneg.obj | Bin 0 -> 180431 bytes wx28X/build/msw/vc_mswddll/core/colordlg.obj | Bin 0 -> 100070 bytes wx28X/build/msw/vc_mswddll/core/colour.obj | Bin 0 -> 24034 bytes wx28X/build/msw/vc_mswddll/core/colourcmn.obj | Bin 0 -> 45787 bytes wx28X/build/msw/vc_mswddll/core/combo.obj | Bin 0 -> 346082 bytes wx28X/build/msw/vc_mswddll/core/combobox.obj | Bin 0 -> 171085 bytes wx28X/build/msw/vc_mswddll/core/combocmn.obj | Bin 0 -> 448612 bytes wx28X/build/msw/vc_mswddll/core/combog.obj | Bin 0 -> 273956 bytes wx28X/build/msw/vc_mswddll/core/containr.obj | Bin 0 -> 50104 bytes wx28X/build/msw/vc_mswddll/core/control.obj | Bin 0 -> 388797 bytes .../vc_mswddll/core/core.Build.CppClean.log | 262 + .../vc_mswddll/core/core.dll.embed.manifest | 15 + .../core/core.dll.embed.manifest.res | Bin 0 -> 748 bytes .../core/core.dll.intermediate.manifest | 15 + .../msw/vc_mswddll/core/core.lastbuildstate | 2 + .../msw/vc_mswddll/core/core.write.1.tlog | 3 + .../msw/vc_mswddll/core/core_manifest.rc | Bin 0 -> 228 bytes wx28X/build/msw/vc_mswddll/core/cshelp.obj | Bin 0 -> 313973 bytes wx28X/build/msw/vc_mswddll/core/ctrlcmn.obj | Bin 0 -> 97716 bytes wx28X/build/msw/vc_mswddll/core/ctrlsub.obj | Bin 0 -> 78024 bytes wx28X/build/msw/vc_mswddll/core/cursor.obj | Bin 0 -> 68418 bytes .../core/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../vc_mswddll/core/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../vc_mswddll/core/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswddll/core/data.obj | Bin 0 -> 2351 bytes wx28X/build/msw/vc_mswddll/core/datacmn.obj | Bin 0 -> 12453 bytes wx28X/build/msw/vc_mswddll/core/dataobj.obj | Bin 0 -> 157644 bytes wx28X/build/msw/vc_mswddll/core/dc.obj | Bin 0 -> 310282 bytes wx28X/build/msw/vc_mswddll/core/dcbase.obj | Bin 0 -> 212930 bytes wx28X/build/msw/vc_mswddll/core/dcbufcmn.obj | Bin 0 -> 143131 bytes wx28X/build/msw/vc_mswddll/core/dcclient.obj | Bin 0 -> 145708 bytes wx28X/build/msw/vc_mswddll/core/dcgraph.obj | Bin 0 -> 2367 bytes wx28X/build/msw/vc_mswddll/core/dcmemory.obj | Bin 0 -> 112379 bytes wx28X/build/msw/vc_mswddll/core/dcprint.obj | Bin 0 -> 283512 bytes wx28X/build/msw/vc_mswddll/core/dcpsg.obj | Bin 0 -> 2359 bytes wx28X/build/msw/vc_mswddll/core/dcscreen.obj | Bin 0 -> 93371 bytes wx28X/build/msw/vc_mswddll/core/dialog.obj | Bin 0 -> 130531 bytes wx28X/build/msw/vc_mswddll/core/dialup.obj | Bin 0 -> 130107 bytes wx28X/build/msw/vc_mswddll/core/dib.obj | Bin 0 -> 68908 bytes wx28X/build/msw/vc_mswddll/core/dirctrlg.obj | Bin 0 -> 536771 bytes wx28X/build/msw/vc_mswddll/core/dirdlg.obj | Bin 0 -> 125069 bytes wx28X/build/msw/vc_mswddll/core/display.obj | Bin 0 -> 96976 bytes wx28X/build/msw/vc_mswddll/core/dlgcmn.obj | Bin 0 -> 192627 bytes wx28X/build/msw/vc_mswddll/core/dndcmn.obj | Bin 0 -> 36743 bytes wx28X/build/msw/vc_mswddll/core/dobjcmn.obj | Bin 0 -> 139078 bytes wx28X/build/msw/vc_mswddll/core/docmdi.obj | Bin 0 -> 234471 bytes wx28X/build/msw/vc_mswddll/core/docview.obj | Bin 0 -> 497462 bytes wx28X/build/msw/vc_mswddll/core/dpycmn.obj | Bin 0 -> 77696 bytes wx28X/build/msw/vc_mswddll/core/dragimag.obj | Bin 0 -> 480630 bytes wx28X/build/msw/vc_mswddll/core/dragimgg.obj | Bin 0 -> 524421 bytes wx28X/build/msw/vc_mswddll/core/dropsrc.obj | Bin 0 -> 62019 bytes wx28X/build/msw/vc_mswddll/core/droptgt.obj | Bin 0 -> 91066 bytes wx28X/build/msw/vc_mswddll/core/dseldlg.obj | Bin 0 -> 61732 bytes wx28X/build/msw/vc_mswddll/core/dummy.obj | Bin 0 -> 3439156 bytes wx28X/build/msw/vc_mswddll/core/effects.obj | Bin 0 -> 133807 bytes wx28X/build/msw/vc_mswddll/core/enhmeta.obj | Bin 0 -> 187737 bytes wx28X/build/msw/vc_mswddll/core/event.obj | Bin 0 -> 469789 bytes wx28X/build/msw/vc_mswddll/core/evtloop.obj | Bin 0 -> 49646 bytes .../build/msw/vc_mswddll/core/evtloopcmn.obj | Bin 0 -> 28802 bytes wx28X/build/msw/vc_mswddll/core/fddlgcmn.obj | Bin 0 -> 138819 bytes wx28X/build/msw/vc_mswddll/core/fdrepdlg.obj | Bin 0 -> 159847 bytes wx28X/build/msw/vc_mswddll/core/filedlg.obj | Bin 0 -> 135521 bytes .../msw/vc_mswddll/core/filepickercmn.obj | Bin 0 -> 243308 bytes .../build/msw/vc_mswddll/core/filepickerg.obj | Bin 0 -> 223454 bytes wx28X/build/msw/vc_mswddll/core/fldlgcmn.obj | Bin 0 -> 133910 bytes wx28X/build/msw/vc_mswddll/core/font.obj | Bin 0 -> 138495 bytes wx28X/build/msw/vc_mswddll/core/fontcmn.obj | Bin 0 -> 91667 bytes wx28X/build/msw/vc_mswddll/core/fontdlg.obj | Bin 0 -> 115193 bytes wx28X/build/msw/vc_mswddll/core/fontenum.obj | Bin 0 -> 31650 bytes .../build/msw/vc_mswddll/core/fontenumcmn.obj | Bin 0 -> 22029 bytes wx28X/build/msw/vc_mswddll/core/fontmap.obj | Bin 0 -> 191520 bytes .../msw/vc_mswddll/core/fontpickercmn.obj | Bin 0 -> 198363 bytes .../build/msw/vc_mswddll/core/fontpickerg.obj | Bin 0 -> 245539 bytes wx28X/build/msw/vc_mswddll/core/fontutil.obj | Bin 0 -> 39258 bytes wx28X/build/msw/vc_mswddll/core/frame.obj | Bin 0 -> 156743 bytes wx28X/build/msw/vc_mswddll/core/framecmn.obj | Bin 0 -> 159017 bytes wx28X/build/msw/vc_mswddll/core/fs_mem.obj | Bin 0 -> 29990 bytes wx28X/build/msw/vc_mswddll/core/gauge95.obj | Bin 0 -> 84770 bytes wx28X/build/msw/vc_mswddll/core/gaugecmn.obj | Bin 0 -> 54485 bytes wx28X/build/msw/vc_mswddll/core/gbsizer.obj | Bin 0 -> 106166 bytes wx28X/build/msw/vc_mswddll/core/gdicmn.obj | Bin 0 -> 206004 bytes wx28X/build/msw/vc_mswddll/core/gdiimage.obj | Bin 0 -> 135387 bytes wx28X/build/msw/vc_mswddll/core/gdiobj.obj | Bin 0 -> 2479 bytes wx28X/build/msw/vc_mswddll/core/geometry.obj | Bin 0 -> 109710 bytes wx28X/build/msw/vc_mswddll/core/gifdecod.obj | Bin 0 -> 72152 bytes wx28X/build/msw/vc_mswddll/core/graphcmn.obj | Bin 0 -> 2367 bytes wx28X/build/msw/vc_mswddll/core/graphics.obj | Bin 0 -> 2535 bytes wx28X/build/msw/vc_mswddll/core/gsockmsw.obj | Bin 0 -> 13510 bytes wx28X/build/msw/vc_mswddll/core/helpbase.obj | Bin 0 -> 18861 bytes wx28X/build/msw/vc_mswddll/core/helpchm.obj | Bin 0 -> 59843 bytes wx28X/build/msw/vc_mswddll/core/helpwin.obj | Bin 0 -> 47973 bytes wx28X/build/msw/vc_mswddll/core/icon.obj | Bin 0 -> 49701 bytes wx28X/build/msw/vc_mswddll/core/iconbndl.obj | Bin 0 -> 59978 bytes wx28X/build/msw/vc_mswddll/core/imagall.obj | Bin 0 -> 64450 bytes wx28X/build/msw/vc_mswddll/core/imagbmp.obj | Bin 0 -> 174062 bytes wx28X/build/msw/vc_mswddll/core/image.obj | Bin 0 -> 286120 bytes wx28X/build/msw/vc_mswddll/core/imagfill.obj | Bin 0 -> 2367 bytes wx28X/build/msw/vc_mswddll/core/imaggif.obj | Bin 0 -> 58070 bytes wx28X/build/msw/vc_mswddll/core/imagiff.obj | Bin 0 -> 2367 bytes wx28X/build/msw/vc_mswddll/core/imagjpeg.obj | Bin 0 -> 40286 bytes wx28X/build/msw/vc_mswddll/core/imaglist.obj | Bin 0 -> 156664 bytes wx28X/build/msw/vc_mswddll/core/imagpcx.obj | Bin 0 -> 57836 bytes wx28X/build/msw/vc_mswddll/core/imagpng.obj | Bin 0 -> 66718 bytes wx28X/build/msw/vc_mswddll/core/imagpnm.obj | Bin 0 -> 32919 bytes wx28X/build/msw/vc_mswddll/core/imagtga.obj | Bin 0 -> 44689 bytes wx28X/build/msw/vc_mswddll/core/imagtiff.obj | Bin 0 -> 43778 bytes wx28X/build/msw/vc_mswddll/core/imagxpm.obj | Bin 0 -> 59237 bytes wx28X/build/msw/vc_mswddll/core/iniconf.obj | Bin 0 -> 64670 bytes wx28X/build/msw/vc_mswddll/core/layout.obj | Bin 0 -> 55200 bytes wx28X/build/msw/vc_mswddll/core/lboxcmn.obj | Bin 0 -> 69946 bytes .../vc_mswddll/core/link-cvtres.read.1.tlog | 1 + .../vc_mswddll/core/link-cvtres.write.1.tlog | 1 + .../core/link.1340-cvtres.read.1.tlog | 1 + .../core/link.1340-cvtres.write.1.tlog | 1 + .../msw/vc_mswddll/core/link.1340.read.1.tlog | 1 + .../vc_mswddll/core/link.1340.write.1.tlog | 1 + .../msw/vc_mswddll/core/link.command.1.tlog | Bin 0 -> 40842 bytes .../msw/vc_mswddll/core/link.read.1.tlog | Bin 0 -> 53702 bytes .../msw/vc_mswddll/core/link.write.1.tlog | Bin 0 -> 25240 bytes wx28X/build/msw/vc_mswddll/core/listbkg.obj | Bin 0 -> 445543 bytes wx28X/build/msw/vc_mswddll/core/listbox.obj | Bin 0 -> 267377 bytes wx28X/build/msw/vc_mswddll/core/listctrl.obj | Bin 0 -> 403831 bytes .../build/msw/vc_mswddll/core/listctrlcmn.obj | Bin 0 -> 204652 bytes wx28X/build/msw/vc_mswddll/core/logg.obj | Bin 0 -> 500551 bytes wx28X/build/msw/vc_mswddll/core/main.obj | Bin 0 -> 16644 bytes wx28X/build/msw/vc_mswddll/core/matrix.obj | Bin 0 -> 46517 bytes wx28X/build/msw/vc_mswddll/core/mdi.obj | Bin 0 -> 242334 bytes wx28X/build/msw/vc_mswddll/core/menu.obj | Bin 0 -> 205335 bytes wx28X/build/msw/vc_mswddll/core/menucmn.obj | Bin 0 -> 232889 bytes wx28X/build/msw/vc_mswddll/core/menuitem.obj | Bin 0 -> 53720 bytes wx28X/build/msw/vc_mswddll/core/metafile.obj | Bin 0 -> 52397 bytes wx28X/build/msw/vc_mswddll/core/minifram.obj | Bin 0 -> 70489 bytes wx28X/build/msw/vc_mswddll/core/msgdlg.obj | Bin 0 -> 91315 bytes wx28X/build/msw/vc_mswddll/core/msgout.obj | Bin 0 -> 19731 bytes wx28X/build/msw/vc_mswddll/core/mslu.obj | Bin 0 -> 2351 bytes .../msw/vc_mswddll/core/mt.command.1.tlog | Bin 0 -> 402 bytes .../build/msw/vc_mswddll/core/mt.read.1.tlog | Bin 0 -> 150 bytes .../build/msw/vc_mswddll/core/mt.write.1.tlog | Bin 0 -> 282 bytes wx28X/build/msw/vc_mswddll/core/nativdlg.obj | Bin 0 -> 358791 bytes wx28X/build/msw/vc_mswddll/core/nbkbase.obj | Bin 0 -> 270492 bytes wx28X/build/msw/vc_mswddll/core/notebook.obj | Bin 0 -> 477694 bytes wx28X/build/msw/vc_mswddll/core/numdlgg.obj | Bin 0 -> 237216 bytes wx28X/build/msw/vc_mswddll/core/oleutils.obj | Bin 0 -> 35512 bytes .../build/msw/vc_mswddll/core/overlaycmn.obj | Bin 0 -> 121328 bytes wx28X/build/msw/vc_mswddll/core/ownerdrw.obj | Bin 0 -> 168051 bytes wx28X/build/msw/vc_mswddll/core/palette.obj | Bin 0 -> 33186 bytes wx28X/build/msw/vc_mswddll/core/panelg.obj | Bin 0 -> 77192 bytes wx28X/build/msw/vc_mswddll/core/paper.obj | Bin 0 -> 204236 bytes wx28X/build/msw/vc_mswddll/core/pen.obj | Bin 0 -> 65003 bytes .../build/msw/vc_mswddll/core/pickerbase.obj | Bin 0 -> 165358 bytes wx28X/build/msw/vc_mswddll/core/popupcmn.obj | Bin 0 -> 156470 bytes wx28X/build/msw/vc_mswddll/core/popupwin.obj | Bin 0 -> 74560 bytes wx28X/build/msw/vc_mswddll/core/printdlg.obj | Bin 0 -> 262369 bytes wx28X/build/msw/vc_mswddll/core/printps.obj | Bin 0 -> 2367 bytes wx28X/build/msw/vc_mswddll/core/printwin.obj | Bin 0 -> 179934 bytes wx28X/build/msw/vc_mswddll/core/prntbase.obj | Bin 0 -> 631285 bytes wx28X/build/msw/vc_mswddll/core/prntdlgg.obj | Bin 0 -> 509256 bytes wx28X/build/msw/vc_mswddll/core/progdlgg.obj | Bin 0 -> 200253 bytes wx28X/build/msw/vc_mswddll/core/quantize.obj | Bin 0 -> 43027 bytes wx28X/build/msw/vc_mswddll/core/radiobox.obj | Bin 0 -> 192777 bytes wx28X/build/msw/vc_mswddll/core/radiobut.obj | Bin 0 -> 96293 bytes wx28X/build/msw/vc_mswddll/core/radiocmn.obj | Bin 0 -> 146034 bytes .../msw/vc_mswddll/core/rc.command.1.tlog | Bin 0 -> 2234 bytes .../build/msw/vc_mswddll/core/rc.read.1.tlog | Bin 0 -> 466 bytes .../build/msw/vc_mswddll/core/rc.write.1.tlog | Bin 0 -> 442 bytes wx28X/build/msw/vc_mswddll/core/region.obj | Bin 0 -> 74076 bytes wx28X/build/msw/vc_mswddll/core/rendcmn.obj | Bin 0 -> 102787 bytes wx28X/build/msw/vc_mswddll/core/renderer.obj | Bin 0 -> 232769 bytes wx28X/build/msw/vc_mswddll/core/renderg.obj | Bin 0 -> 339577 bytes wx28X/build/msw/vc_mswddll/core/rgncmn.obj | Bin 0 -> 119506 bytes wx28X/build/msw/vc_mswddll/core/scrlwing.obj | Bin 0 -> 170205 bytes wx28X/build/msw/vc_mswddll/core/scrolbar.obj | Bin 0 -> 96599 bytes wx28X/build/msw/vc_mswddll/core/selstore.obj | Bin 0 -> 25608 bytes wx28X/build/msw/vc_mswddll/core/settcmn.obj | Bin 0 -> 4329 bytes wx28X/build/msw/vc_mswddll/core/settings.obj | Bin 0 -> 56816 bytes wx28X/build/msw/vc_mswddll/core/sizer.obj | Bin 0 -> 307240 bytes wx28X/build/msw/vc_mswddll/core/slider95.obj | Bin 0 -> 139921 bytes wx28X/build/msw/vc_mswddll/core/spinbutt.obj | Bin 0 -> 115678 bytes wx28X/build/msw/vc_mswddll/core/spinctlg.obj | Bin 0 -> 2371 bytes wx28X/build/msw/vc_mswddll/core/spinctrl.obj | Bin 0 -> 201356 bytes wx28X/build/msw/vc_mswddll/core/splitter.obj | Bin 0 -> 241711 bytes wx28X/build/msw/vc_mswddll/core/srchcmn.obj | Bin 0 -> 111248 bytes wx28X/build/msw/vc_mswddll/core/srchctlg.obj | Bin 0 -> 372619 bytes wx28X/build/msw/vc_mswddll/core/statbar.obj | Bin 0 -> 99719 bytes wx28X/build/msw/vc_mswddll/core/statbmp.obj | Bin 0 -> 138254 bytes wx28X/build/msw/vc_mswddll/core/statbox.obj | Bin 0 -> 419604 bytes wx28X/build/msw/vc_mswddll/core/statbr95.obj | Bin 0 -> 94124 bytes wx28X/build/msw/vc_mswddll/core/statline.obj | Bin 0 -> 85740 bytes wx28X/build/msw/vc_mswddll/core/stattext.obj | Bin 0 -> 91085 bytes wx28X/build/msw/vc_mswddll/core/statusbr.obj | Bin 0 -> 104907 bytes wx28X/build/msw/vc_mswddll/core/stockitem.obj | Bin 0 -> 33585 bytes wx28X/build/msw/vc_mswddll/core/tabctrl.obj | Bin 0 -> 2359 bytes wx28X/build/msw/vc_mswddll/core/tbar95.obj | Bin 0 -> 338081 bytes wx28X/build/msw/vc_mswddll/core/tbarbase.obj | Bin 0 -> 221998 bytes wx28X/build/msw/vc_mswddll/core/textcmn.obj | Bin 0 -> 110756 bytes wx28X/build/msw/vc_mswddll/core/textctrl.obj | Bin 0 -> 363087 bytes wx28X/build/msw/vc_mswddll/core/textdlgg.obj | Bin 0 -> 218220 bytes wx28X/build/msw/vc_mswddll/core/tglbtn.obj | Bin 0 -> 85349 bytes wx28X/build/msw/vc_mswddll/core/timer.obj | Bin 0 -> 51542 bytes wx28X/build/msw/vc_mswddll/core/timercmn.obj | Bin 0 -> 19762 bytes wx28X/build/msw/vc_mswddll/core/tipwin.obj | Bin 0 -> 119171 bytes wx28X/build/msw/vc_mswddll/core/toolbkg.obj | Bin 0 -> 353749 bytes wx28X/build/msw/vc_mswddll/core/tooltip.obj | Bin 0 -> 33573 bytes wx28X/build/msw/vc_mswddll/core/toplevel.obj | Bin 0 -> 183073 bytes wx28X/build/msw/vc_mswddll/core/toplvcmn.obj | Bin 0 -> 150718 bytes wx28X/build/msw/vc_mswddll/core/treebase.obj | Bin 0 -> 305599 bytes wx28X/build/msw/vc_mswddll/core/treebkg.obj | Bin 0 -> 533943 bytes wx28X/build/msw/vc_mswddll/core/treectlg.obj | Bin 0 -> 686398 bytes wx28X/build/msw/vc_mswddll/core/treectrl.obj | Bin 0 -> 577704 bytes wx28X/build/msw/vc_mswddll/core/utilscmn.obj | Bin 0 -> 419258 bytes wx28X/build/msw/vc_mswddll/core/utilsgui.obj | Bin 0 -> 34992 bytes wx28X/build/msw/vc_mswddll/core/uuid.obj | Bin 0 -> 11955 bytes wx28X/build/msw/vc_mswddll/core/uxtheme.obj | Bin 0 -> 49739 bytes wx28X/build/msw/vc_mswddll/core/valgen.obj | Bin 0 -> 179240 bytes wx28X/build/msw/vc_mswddll/core/validate.obj | Bin 0 -> 15748 bytes wx28X/build/msw/vc_mswddll/core/valtext.obj | Bin 0 -> 45447 bytes wx28X/build/msw/vc_mswddll/core/version.res | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswddll/core/vlbox.obj | Bin 0 -> 299228 bytes wx28X/build/msw/vc_mswddll/core/volume.obj | Bin 0 -> 62306 bytes wx28X/build/msw/vc_mswddll/core/vscroll.obj | Bin 0 -> 98411 bytes wx28X/build/msw/vc_mswddll/core/wincmn.obj | Bin 0 -> 556264 bytes wx28X/build/msw/vc_mswddll/core/window.obj | Bin 0 -> 1123699 bytes wx28X/build/msw/vc_mswddll/core/wx_core.log | 755 + wx28X/build/msw/vc_mswddll/core/xpmdecod.obj | Bin 0 -> 73933 bytes .../msw/vc_mswddll/dbgrid/CL.read.1.tlog | Bin 0 -> 37688 bytes .../msw/vc_mswddll/dbgrid/CL.write.1.tlog | Bin 0 -> 718 bytes .../msw/vc_mswddll/dbgrid/cl.command.1.tlog | Bin 0 -> 2554 bytes .../dbgrid/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../vc_mswddll/dbgrid/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../dbgrid/custombuild.write.1.tlog | Bin 0 -> 352 bytes .../dbgrid/dbgrid.Build.CppClean.log | 37 + .../dbgrid/dbgrid.dll.embed.manifest | 15 + .../dbgrid/dbgrid.dll.embed.manifest.res | Bin 0 -> 748 bytes .../dbgrid/dbgrid.dll.intermediate.manifest | 15 + .../vc_mswddll/dbgrid/dbgrid.lastbuildstate | 2 + wx28X/build/msw/vc_mswddll/dbgrid/dbgrid.obj | Bin 0 -> 124311 bytes .../msw/vc_mswddll/dbgrid/dbgrid.write.1.tlog | 3 + .../msw/vc_mswddll/dbgrid/dbgrid_manifest.rc | Bin 0 -> 236 bytes wx28X/build/msw/vc_mswddll/dbgrid/dummy.obj | Bin 0 -> 420753 bytes .../vc_mswddll/dbgrid/link-cvtres.read.1.tlog | 1 + .../dbgrid/link-cvtres.write.1.tlog | 1 + .../dbgrid/link.5000-cvtres.read.1.tlog | 1 + .../dbgrid/link.5000-cvtres.write.1.tlog | 1 + .../vc_mswddll/dbgrid/link.5000.read.1.tlog | 1 + .../vc_mswddll/dbgrid/link.5000.write.1.tlog | 1 + .../msw/vc_mswddll/dbgrid/link.command.1.tlog | Bin 0 -> 3354 bytes .../msw/vc_mswddll/dbgrid/link.read.1.tlog | Bin 0 -> 5822 bytes .../msw/vc_mswddll/dbgrid/link.write.1.tlog | Bin 0 -> 1450 bytes .../msw/vc_mswddll/dbgrid/mt.command.1.tlog | Bin 0 -> 426 bytes .../msw/vc_mswddll/dbgrid/mt.read.1.tlog | Bin 0 -> 158 bytes .../msw/vc_mswddll/dbgrid/mt.write.1.tlog | Bin 0 -> 298 bytes .../msw/vc_mswddll/dbgrid/rc.command.1.tlog | Bin 0 -> 2234 bytes .../msw/vc_mswddll/dbgrid/rc.read.1.tlog | Bin 0 -> 482 bytes .../msw/vc_mswddll/dbgrid/rc.write.1.tlog | Bin 0 -> 462 bytes wx28X/build/msw/vc_mswddll/dbgrid/version.res | Bin 0 -> 1052 bytes .../build/msw/vc_mswddll/dbgrid/wx_dbgrid.log | 59 + wx28X/build/msw/vc_mswddll/gl/CL.read.1.tlog | Bin 0 -> 36638 bytes wx28X/build/msw/vc_mswddll/gl/CL.write.1.tlog | Bin 0 -> 680 bytes .../build/msw/vc_mswddll/gl/cl.command.1.tlog | Bin 0 -> 2486 bytes .../vc_mswddll/gl/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../msw/vc_mswddll/gl/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../vc_mswddll/gl/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswddll/gl/dummy.obj | Bin 0 -> 420721 bytes .../msw/vc_mswddll/gl/gl.Build.CppClean.log | 35 + .../msw/vc_mswddll/gl/gl.dll.embed.manifest | 15 + .../vc_mswddll/gl/gl.dll.embed.manifest.res | Bin 0 -> 748 bytes .../gl/gl.dll.intermediate.manifest | 15 + .../build/msw/vc_mswddll/gl/gl.lastbuildstate | 2 + wx28X/build/msw/vc_mswddll/gl/gl.write.1.tlog | 0 wx28X/build/msw/vc_mswddll/gl/gl_manifest.rc | Bin 0 -> 220 bytes wx28X/build/msw/vc_mswddll/gl/glcanvas.obj | Bin 0 -> 2255 bytes .../msw/vc_mswddll/gl/link-cvtres.read.1.tlog | 1 + .../vc_mswddll/gl/link-cvtres.write.1.tlog | 1 + .../gl/link.5640-cvtres.read.1.tlog | 1 + .../gl/link.5640-cvtres.write.1.tlog | 1 + .../msw/vc_mswddll/gl/link.5640.read.1.tlog | 1 + .../msw/vc_mswddll/gl/link.5640.write.1.tlog | 1 + .../msw/vc_mswddll/gl/link.command.1.tlog | Bin 0 -> 3218 bytes .../build/msw/vc_mswddll/gl/link.read.1.tlog | Bin 0 -> 5544 bytes .../build/msw/vc_mswddll/gl/link.write.1.tlog | Bin 0 -> 1442 bytes .../build/msw/vc_mswddll/gl/mt.command.1.tlog | Bin 0 -> 378 bytes wx28X/build/msw/vc_mswddll/gl/mt.read.1.tlog | Bin 0 -> 142 bytes wx28X/build/msw/vc_mswddll/gl/mt.write.1.tlog | Bin 0 -> 266 bytes .../build/msw/vc_mswddll/gl/rc.command.1.tlog | Bin 0 -> 2106 bytes wx28X/build/msw/vc_mswddll/gl/rc.read.1.tlog | Bin 0 -> 450 bytes wx28X/build/msw/vc_mswddll/gl/rc.write.1.tlog | Bin 0 -> 422 bytes wx28X/build/msw/vc_mswddll/gl/version.res | Bin 0 -> 1044 bytes wx28X/build/msw/vc_mswddll/gl/wx_gl.log | 59 + .../build/msw/vc_mswddll/html/CL.read.1.tlog | Bin 0 -> 119176 bytes .../build/msw/vc_mswddll/html/CL.write.1.tlog | Bin 0 -> 9248 bytes .../msw/vc_mswddll/html/cl.command.1.tlog | Bin 0 -> 31492 bytes .../html/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../vc_mswddll/html/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../vc_mswddll/html/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswddll/html/dummy.obj | Bin 0 -> 420741 bytes wx28X/build/msw/vc_mswddll/html/helpbest.obj | Bin 0 -> 371406 bytes wx28X/build/msw/vc_mswddll/html/helpctrl.obj | Bin 0 -> 412318 bytes wx28X/build/msw/vc_mswddll/html/helpdata.obj | Bin 0 -> 232113 bytes wx28X/build/msw/vc_mswddll/html/helpdlg.obj | Bin 0 -> 388745 bytes wx28X/build/msw/vc_mswddll/html/helpfrm.obj | Bin 0 -> 366883 bytes wx28X/build/msw/vc_mswddll/html/helpwnd.obj | Bin 0 -> 803223 bytes .../vc_mswddll/html/html.Build.CppClean.log | 60 + .../vc_mswddll/html/html.dll.embed.manifest | 15 + .../html/html.dll.embed.manifest.res | Bin 0 -> 748 bytes .../html/html.dll.intermediate.manifest | 15 + .../msw/vc_mswddll/html/html.lastbuildstate | 2 + .../msw/vc_mswddll/html/html.write.1.tlog | 3 + .../msw/vc_mswddll/html/html_manifest.rc | Bin 0 -> 228 bytes wx28X/build/msw/vc_mswddll/html/htmlcell.obj | Bin 0 -> 339020 bytes wx28X/build/msw/vc_mswddll/html/htmlfilt.obj | Bin 0 -> 271997 bytes wx28X/build/msw/vc_mswddll/html/htmllbox.obj | Bin 0 -> 366868 bytes wx28X/build/msw/vc_mswddll/html/htmlpars.obj | Bin 0 -> 140820 bytes wx28X/build/msw/vc_mswddll/html/htmltag.obj | Bin 0 -> 64159 bytes wx28X/build/msw/vc_mswddll/html/htmlwin.obj | Bin 0 -> 488494 bytes wx28X/build/msw/vc_mswddll/html/htmprint.obj | Bin 0 -> 468827 bytes .../vc_mswddll/html/link-cvtres.read.1.tlog | 1 + .../vc_mswddll/html/link-cvtres.write.1.tlog | 1 + .../html/link.3040-cvtres.read.1.tlog | 1 + .../html/link.3040-cvtres.write.1.tlog | 1 + .../msw/vc_mswddll/html/link.3040.read.1.tlog | 1 + .../vc_mswddll/html/link.3040.write.1.tlog | 1 + .../msw/vc_mswddll/html/link.command.1.tlog | Bin 0 -> 7192 bytes .../msw/vc_mswddll/html/link.read.1.tlog | Bin 0 -> 10612 bytes .../msw/vc_mswddll/html/link.write.1.tlog | Bin 0 -> 3934 bytes wx28X/build/msw/vc_mswddll/html/m_dflist.obj | Bin 0 -> 158162 bytes wx28X/build/msw/vc_mswddll/html/m_fonts.obj | Bin 0 -> 213959 bytes wx28X/build/msw/vc_mswddll/html/m_hline.obj | Bin 0 -> 164613 bytes wx28X/build/msw/vc_mswddll/html/m_image.obj | Bin 0 -> 331035 bytes wx28X/build/msw/vc_mswddll/html/m_layout.obj | Bin 0 -> 302205 bytes wx28X/build/msw/vc_mswddll/html/m_links.obj | Bin 0 -> 170546 bytes wx28X/build/msw/vc_mswddll/html/m_list.obj | Bin 0 -> 182656 bytes wx28X/build/msw/vc_mswddll/html/m_pre.obj | Bin 0 -> 161702 bytes wx28X/build/msw/vc_mswddll/html/m_style.obj | Bin 0 -> 154445 bytes wx28X/build/msw/vc_mswddll/html/m_tables.obj | Bin 0 -> 211072 bytes .../msw/vc_mswddll/html/mt.command.1.tlog | Bin 0 -> 402 bytes .../build/msw/vc_mswddll/html/mt.read.1.tlog | Bin 0 -> 150 bytes .../build/msw/vc_mswddll/html/mt.write.1.tlog | Bin 0 -> 282 bytes .../msw/vc_mswddll/html/rc.command.1.tlog | Bin 0 -> 2170 bytes .../build/msw/vc_mswddll/html/rc.read.1.tlog | Bin 0 -> 466 bytes .../build/msw/vc_mswddll/html/rc.write.1.tlog | Bin 0 -> 442 bytes wx28X/build/msw/vc_mswddll/html/version.res | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswddll/html/winpars.obj | Bin 0 -> 322425 bytes wx28X/build/msw/vc_mswddll/html/wx_html.log | 134 + .../build/msw/vc_mswddll/media/CL.read.1.tlog | Bin 0 -> 44454 bytes .../msw/vc_mswddll/media/CL.write.1.tlog | Bin 0 -> 2410 bytes wx28X/build/msw/vc_mswddll/media/activex.obj | Bin 0 -> 220362 bytes .../msw/vc_mswddll/media/cl.command.1.tlog | Bin 0 -> 7698 bytes .../media/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../vc_mswddll/media/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../vc_mswddll/media/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswddll/media/dummy.obj | Bin 0 -> 420749 bytes .../vc_mswddll/media/link-cvtres.read.1.tlog | 1 + .../vc_mswddll/media/link-cvtres.write.1.tlog | 1 + .../media/link.1076-cvtres.read.1.tlog | 1 + .../media/link.1076-cvtres.write.1.tlog | 1 + .../vc_mswddll/media/link.1076.read.1.tlog | 1 + .../vc_mswddll/media/link.1076.write.1.tlog | 1 + .../msw/vc_mswddll/media/link.command.1.tlog | Bin 0 -> 4106 bytes .../msw/vc_mswddll/media/link.read.1.tlog | Bin 0 -> 6650 bytes .../msw/vc_mswddll/media/link.write.1.tlog | Bin 0 -> 1978 bytes .../vc_mswddll/media/media.Build.CppClean.log | 41 + .../vc_mswddll/media/media.dll.embed.manifest | 15 + .../media/media.dll.embed.manifest.res | Bin 0 -> 748 bytes .../media/media.dll.intermediate.manifest | 15 + .../msw/vc_mswddll/media/media.lastbuildstate | 2 + .../msw/vc_mswddll/media/media.write.1.tlog | 3 + .../msw/vc_mswddll/media/media_manifest.rc | Bin 0 -> 232 bytes .../msw/vc_mswddll/media/mediactrl_am.obj | Bin 0 -> 133247 bytes .../msw/vc_mswddll/media/mediactrl_qt.obj | Bin 0 -> 203216 bytes .../msw/vc_mswddll/media/mediactrl_wmp10.obj | Bin 0 -> 125971 bytes .../msw/vc_mswddll/media/mediactrlcmn.obj | Bin 0 -> 104652 bytes .../msw/vc_mswddll/media/mt.command.1.tlog | Bin 0 -> 414 bytes .../build/msw/vc_mswddll/media/mt.read.1.tlog | Bin 0 -> 154 bytes .../msw/vc_mswddll/media/mt.write.1.tlog | Bin 0 -> 290 bytes .../msw/vc_mswddll/media/rc.command.1.tlog | Bin 0 -> 2202 bytes .../build/msw/vc_mswddll/media/rc.read.1.tlog | Bin 0 -> 474 bytes .../msw/vc_mswddll/media/rc.write.1.tlog | Bin 0 -> 452 bytes wx28X/build/msw/vc_mswddll/media/version.res | Bin 0 -> 1052 bytes wx28X/build/msw/vc_mswddll/media/wx_media.log | 74 + wx28X/build/msw/vc_mswddll/net/CL.read.1.tlog | Bin 0 -> 43406 bytes .../build/msw/vc_mswddll/net/CL.write.1.tlog | Bin 0 -> 4864 bytes .../msw/vc_mswddll/net/cl.command.1.tlog | Bin 0 -> 16688 bytes .../vc_mswddll/net/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../vc_mswddll/net/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../vc_mswddll/net/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswddll/net/dummy.obj | Bin 0 -> 380813 bytes wx28X/build/msw/vc_mswddll/net/fs_inet.obj | Bin 0 -> 159945 bytes wx28X/build/msw/vc_mswddll/net/ftp.obj | Bin 0 -> 207867 bytes wx28X/build/msw/vc_mswddll/net/gsocket.obj | Bin 0 -> 54080 bytes wx28X/build/msw/vc_mswddll/net/http.obj | Bin 0 -> 180100 bytes .../vc_mswddll/net/link-cvtres.read.1.tlog | 1 + .../vc_mswddll/net/link-cvtres.write.1.tlog | 1 + .../net/link.4276-cvtres.read.1.tlog | 1 + .../net/link.4276-cvtres.write.1.tlog | 1 + .../msw/vc_mswddll/net/link.4276.read.1.tlog | 1 + .../msw/vc_mswddll/net/link.4276.write.1.tlog | 1 + .../msw/vc_mswddll/net/link.command.1.tlog | Bin 0 -> 4410 bytes .../build/msw/vc_mswddll/net/link.read.1.tlog | Bin 0 -> 7104 bytes .../msw/vc_mswddll/net/link.write.1.tlog | Bin 0 -> 2350 bytes .../msw/vc_mswddll/net/mt.command.1.tlog | Bin 0 -> 390 bytes wx28X/build/msw/vc_mswddll/net/mt.read.1.tlog | Bin 0 -> 274 bytes .../build/msw/vc_mswddll/net/mt.write.1.tlog | Bin 0 -> 274 bytes .../msw/vc_mswddll/net/net.Build.CppClean.log | 48 + .../msw/vc_mswddll/net/net.dll.embed.manifest | 15 + .../vc_mswddll/net/net.dll.embed.manifest.res | Bin 0 -> 748 bytes .../net/net.dll.intermediate.manifest | 15 + .../msw/vc_mswddll/net/net.lastbuildstate | 2 + .../build/msw/vc_mswddll/net/net.write.1.tlog | 6 + .../build/msw/vc_mswddll/net/net_manifest.rc | Bin 0 -> 224 bytes wx28X/build/msw/vc_mswddll/net/protocol.obj | Bin 0 -> 131768 bytes .../msw/vc_mswddll/net/rc.command.1.tlog | Bin 0 -> 2202 bytes wx28X/build/msw/vc_mswddll/net/rc.read.1.tlog | Bin 0 -> 458 bytes .../build/msw/vc_mswddll/net/rc.write.1.tlog | Bin 0 -> 432 bytes wx28X/build/msw/vc_mswddll/net/sckaddr.obj | Bin 0 -> 63714 bytes wx28X/build/msw/vc_mswddll/net/sckfile.obj | Bin 0 -> 51687 bytes wx28X/build/msw/vc_mswddll/net/sckipc.obj | Bin 0 -> 112745 bytes wx28X/build/msw/vc_mswddll/net/sckstrm.obj | Bin 0 -> 46168 bytes wx28X/build/msw/vc_mswddll/net/socket.obj | Bin 0 -> 115333 bytes wx28X/build/msw/vc_mswddll/net/url.obj | Bin 0 -> 157721 bytes wx28X/build/msw/vc_mswddll/net/urlmsw.obj | Bin 0 -> 2271 bytes wx28X/build/msw/vc_mswddll/net/version.res | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswddll/net/wx_net.log | 51 + .../build/msw/vc_mswddll/odbc/CL.read.1.tlog | Bin 0 -> 28816 bytes .../build/msw/vc_mswddll/odbc/CL.write.1.tlog | Bin 0 -> 1132 bytes .../msw/vc_mswddll/odbc/cl.command.1.tlog | Bin 0 -> 3868 bytes .../odbc/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../vc_mswddll/odbc/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../vc_mswddll/odbc/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswddll/odbc/db.obj | Bin 0 -> 238250 bytes wx28X/build/msw/vc_mswddll/odbc/dbtable.obj | Bin 0 -> 249576 bytes wx28X/build/msw/vc_mswddll/odbc/dummy.obj | Bin 0 -> 380817 bytes .../vc_mswddll/odbc/link-cvtres.read.1.tlog | 1 + .../vc_mswddll/odbc/link-cvtres.write.1.tlog | 1 + .../odbc/link.4432-cvtres.read.1.tlog | 1 + .../odbc/link.4432-cvtres.write.1.tlog | 1 + .../msw/vc_mswddll/odbc/link.4432.read.1.tlog | 1 + .../vc_mswddll/odbc/link.4432.write.1.tlog | 1 + .../msw/vc_mswddll/odbc/link.command.1.tlog | Bin 0 -> 2836 bytes .../msw/vc_mswddll/odbc/link.read.1.tlog | Bin 0 -> 5304 bytes .../msw/vc_mswddll/odbc/link.write.1.tlog | Bin 0 -> 1348 bytes .../msw/vc_mswddll/odbc/mt.command.1.tlog | Bin 0 -> 402 bytes .../build/msw/vc_mswddll/odbc/mt.read.1.tlog | Bin 0 -> 150 bytes .../build/msw/vc_mswddll/odbc/mt.write.1.tlog | Bin 0 -> 282 bytes .../vc_mswddll/odbc/odbc.Build.CppClean.log | 38 + .../vc_mswddll/odbc/odbc.dll.embed.manifest | 15 + .../odbc/odbc.dll.embed.manifest.res | Bin 0 -> 748 bytes .../odbc/odbc.dll.intermediate.manifest | 15 + .../msw/vc_mswddll/odbc/odbc.lastbuildstate | 2 + .../msw/vc_mswddll/odbc/odbc.write.1.tlog | 3 + .../msw/vc_mswddll/odbc/odbc_manifest.rc | Bin 0 -> 228 bytes .../msw/vc_mswddll/odbc/rc.command.1.tlog | Bin 0 -> 2234 bytes .../build/msw/vc_mswddll/odbc/rc.read.1.tlog | Bin 0 -> 466 bytes .../build/msw/vc_mswddll/odbc/rc.write.1.tlog | Bin 0 -> 442 bytes wx28X/build/msw/vc_mswddll/odbc/version.res | Bin 0 -> 1052 bytes wx28X/build/msw/vc_mswddll/odbc/wx_odbc.log | 59 + wx28X/build/msw/vc_mswddll/qa/CL.read.1.tlog | Bin 0 -> 39954 bytes wx28X/build/msw/vc_mswddll/qa/CL.write.1.tlog | Bin 0 -> 1138 bytes .../build/msw/vc_mswddll/qa/cl.command.1.tlog | Bin 0 -> 3752 bytes .../vc_mswddll/qa/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../msw/vc_mswddll/qa/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../vc_mswddll/qa/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswddll/qa/dbgrptg.obj | Bin 0 -> 217647 bytes wx28X/build/msw/vc_mswddll/qa/debugrpt.obj | Bin 0 -> 156521 bytes wx28X/build/msw/vc_mswddll/qa/dummy.obj | Bin 0 -> 420721 bytes .../msw/vc_mswddll/qa/link-cvtres.read.1.tlog | 1 + .../vc_mswddll/qa/link-cvtres.write.1.tlog | 1 + .../qa/link.1424-cvtres.read.1.tlog | 1 + .../qa/link.1424-cvtres.write.1.tlog | 1 + .../msw/vc_mswddll/qa/link.1424.read.1.tlog | 1 + .../msw/vc_mswddll/qa/link.1424.write.1.tlog | 1 + .../msw/vc_mswddll/qa/link.command.1.tlog | Bin 0 -> 3810 bytes .../build/msw/vc_mswddll/qa/link.read.1.tlog | Bin 0 -> 6070 bytes .../build/msw/vc_mswddll/qa/link.write.1.tlog | Bin 0 -> 1712 bytes .../build/msw/vc_mswddll/qa/mt.command.1.tlog | Bin 0 -> 378 bytes wx28X/build/msw/vc_mswddll/qa/mt.read.1.tlog | Bin 0 -> 142 bytes wx28X/build/msw/vc_mswddll/qa/mt.write.1.tlog | Bin 0 -> 266 bytes .../msw/vc_mswddll/qa/qa.Build.CppClean.log | 38 + .../msw/vc_mswddll/qa/qa.dll.embed.manifest | 15 + .../vc_mswddll/qa/qa.dll.embed.manifest.res | Bin 0 -> 748 bytes .../qa/qa.dll.intermediate.manifest | 15 + .../build/msw/vc_mswddll/qa/qa.lastbuildstate | 2 + wx28X/build/msw/vc_mswddll/qa/qa.write.1.tlog | 3 + wx28X/build/msw/vc_mswddll/qa/qa_manifest.rc | Bin 0 -> 220 bytes .../build/msw/vc_mswddll/qa/rc.command.1.tlog | Bin 0 -> 2106 bytes wx28X/build/msw/vc_mswddll/qa/rc.read.1.tlog | Bin 0 -> 450 bytes wx28X/build/msw/vc_mswddll/qa/rc.write.1.tlog | Bin 0 -> 422 bytes wx28X/build/msw/vc_mswddll/qa/version.res | Bin 0 -> 1044 bytes wx28X/build/msw/vc_mswddll/qa/wx_qa.log | 69 + .../msw/vc_mswddll/richtext/CL.read.1.tlog | Bin 0 -> 80578 bytes .../msw/vc_mswddll/richtext/CL.write.1.tlog | Bin 0 -> 4392 bytes .../msw/vc_mswddll/richtext/cl.command.1.tlog | Bin 0 -> 13298 bytes .../richtext/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../richtext/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../richtext/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswddll/richtext/dummy.obj | Bin 0 -> 420773 bytes .../richtext/link-cvtres.read.1.tlog | 1 + .../richtext/link-cvtres.write.1.tlog | 1 + .../richtext/link.1992-cvtres.read.1.tlog | 1 + .../richtext/link.1992-cvtres.write.1.tlog | 1 + .../vc_mswddll/richtext/link.1992.read.1.tlog | 1 + .../richtext/link.1992.write.1.tlog | 1 + .../vc_mswddll/richtext/link.command.1.tlog | Bin 0 -> 5700 bytes .../msw/vc_mswddll/richtext/link.read.1.tlog | Bin 0 -> 8304 bytes .../msw/vc_mswddll/richtext/link.write.1.tlog | Bin 0 -> 2772 bytes .../msw/vc_mswddll/richtext/mt.command.1.tlog | Bin 0 -> 450 bytes .../msw/vc_mswddll/richtext/mt.read.1.tlog | Bin 0 -> 166 bytes .../msw/vc_mswddll/richtext/mt.write.1.tlog | Bin 0 -> 314 bytes .../msw/vc_mswddll/richtext/rc.command.1.tlog | Bin 0 -> 2298 bytes .../msw/vc_mswddll/richtext/rc.read.1.tlog | Bin 0 -> 498 bytes .../msw/vc_mswddll/richtext/rc.write.1.tlog | Bin 0 -> 482 bytes .../richtext/richtext.Build.CppClean.log | 45 + .../richtext/richtext.dll.embed.manifest | 15 + .../richtext/richtext.dll.embed.manifest.res | Bin 0 -> 748 bytes .../richtext.dll.intermediate.manifest | 15 + .../richtext/richtext.lastbuildstate | 2 + .../vc_mswddll/richtext/richtext.write.1.tlog | 3 + .../vc_mswddll/richtext/richtext_manifest.rc | Bin 0 -> 244 bytes .../vc_mswddll/richtext/richtextbuffer.obj | Bin 0 -> 1577159 bytes .../msw/vc_mswddll/richtext/richtextctrl.obj | Bin 0 -> 1087813 bytes .../vc_mswddll/richtext/richtextformatdlg.obj | Bin 0 -> 1730366 bytes .../msw/vc_mswddll/richtext/richtexthtml.obj | Bin 0 -> 751005 bytes .../msw/vc_mswddll/richtext/richtextprint.obj | Bin 0 -> 661646 bytes .../vc_mswddll/richtext/richtextstyledlg.obj | Bin 0 -> 961655 bytes .../vc_mswddll/richtext/richtextstyles.obj | Bin 0 -> 921930 bytes .../vc_mswddll/richtext/richtextsymboldlg.obj | Bin 0 -> 790706 bytes .../msw/vc_mswddll/richtext/richtextxml.obj | Bin 0 -> 882200 bytes .../build/msw/vc_mswddll/richtext/version.res | Bin 0 -> 1056 bytes .../msw/vc_mswddll/richtext/wx_richtext.log | 90 + .../msw/vc_mswddll/wxexpat/CL.read.1.tlog | Bin 0 -> 21378 bytes .../msw/vc_mswddll/wxexpat/CL.write.1.tlog | Bin 0 -> 1068 bytes .../vc_mswddll/wxexpat/Lib-link.read.1.tlog | Bin 0 -> 846 bytes .../vc_mswddll/wxexpat/Lib-link.write.1.tlog | Bin 0 -> 422 bytes .../msw/vc_mswddll/wxexpat/cl.command.1.tlog | Bin 0 -> 2240 bytes .../msw/vc_mswddll/wxexpat/lib.command.1.tlog | Bin 0 -> 690 bytes .../msw/vc_mswddll/wxexpat/wx_wxexpat.log | 25 + .../vc_mswddll/wxexpat/wxexpat.lastbuildstate | 2 + .../wxexpat/wxexpatd.Build.CppClean.log | 13 + .../build/msw/vc_mswddll/wxexpat/xmlparse.obj | Bin 0 -> 157997 bytes .../build/msw/vc_mswddll/wxexpat/xmlrole.obj | Bin 0 -> 48670 bytes wx28X/build/msw/vc_mswddll/wxexpat/xmltok.obj | Bin 0 -> 256619 bytes .../msw/vc_mswddll/wxjpeg/CL.read.1.tlog | Bin 0 -> 90874 bytes .../msw/vc_mswddll/wxjpeg/CL.write.1.tlog | Bin 0 -> 15324 bytes .../vc_mswddll/wxjpeg/Lib-link.read.1.tlog | Bin 0 -> 10472 bytes .../vc_mswddll/wxjpeg/Lib-link.write.1.tlog | Bin 0 -> 5190 bytes .../msw/vc_mswddll/wxjpeg/cl.command.1.tlog | Bin 0 -> 31834 bytes .../build/msw/vc_mswddll/wxjpeg/jcapimin.obj | Bin 0 -> 10622 bytes .../build/msw/vc_mswddll/wxjpeg/jcapistd.obj | Bin 0 -> 7062 bytes .../build/msw/vc_mswddll/wxjpeg/jccoefct.obj | Bin 0 -> 11628 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jccolor.obj | Bin 0 -> 13251 bytes .../build/msw/vc_mswddll/wxjpeg/jcdctmgr.obj | Bin 0 -> 12068 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jchuff.obj | Bin 0 -> 19741 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jcinit.obj | Bin 0 -> 5441 bytes .../build/msw/vc_mswddll/wxjpeg/jcmainct.obj | Bin 0 -> 6493 bytes .../build/msw/vc_mswddll/wxjpeg/jcmarker.obj | Bin 0 -> 16986 bytes .../build/msw/vc_mswddll/wxjpeg/jcmaster.obj | Bin 0 -> 16574 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jcomapi.obj | Bin 0 -> 6052 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jcparam.obj | Bin 0 -> 18673 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jcphuff.obj | Bin 0 -> 18740 bytes .../build/msw/vc_mswddll/wxjpeg/jcprepct.obj | Bin 0 -> 10245 bytes .../build/msw/vc_mswddll/wxjpeg/jcsample.obj | Bin 0 -> 14218 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jctrans.obj | Bin 0 -> 12059 bytes .../build/msw/vc_mswddll/wxjpeg/jdapimin.obj | Bin 0 -> 12542 bytes .../build/msw/vc_mswddll/wxjpeg/jdapistd.obj | Bin 0 -> 9592 bytes .../build/msw/vc_mswddll/wxjpeg/jdatadst.obj | Bin 0 -> 6096 bytes .../build/msw/vc_mswddll/wxjpeg/jdatasrc.obj | Bin 0 -> 6541 bytes .../build/msw/vc_mswddll/wxjpeg/jdcoefct.obj | Bin 0 -> 18796 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jdcolor.obj | Bin 0 -> 12360 bytes .../build/msw/vc_mswddll/wxjpeg/jddctmgr.obj | Bin 0 -> 8457 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jdhuff.obj | Bin 0 -> 16046 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jdinput.obj | Bin 0 -> 11437 bytes .../build/msw/vc_mswddll/wxjpeg/jdmainct.obj | Bin 0 -> 12429 bytes .../build/msw/vc_mswddll/wxjpeg/jdmarker.obj | Bin 0 -> 36584 bytes .../build/msw/vc_mswddll/wxjpeg/jdmaster.obj | Bin 0 -> 13989 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jdmerge.obj | Bin 0 -> 11576 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jdphuff.obj | Bin 0 -> 17050 bytes .../build/msw/vc_mswddll/wxjpeg/jdpostct.obj | Bin 0 -> 9074 bytes .../build/msw/vc_mswddll/wxjpeg/jdsample.obj | Bin 0 -> 13464 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jdtrans.obj | Bin 0 -> 6393 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jerror.obj | Bin 0 -> 16088 bytes .../build/msw/vc_mswddll/wxjpeg/jfdctflt.obj | Bin 0 -> 5835 bytes .../build/msw/vc_mswddll/wxjpeg/jfdctfst.obj | Bin 0 -> 5263 bytes .../build/msw/vc_mswddll/wxjpeg/jfdctint.obj | Bin 0 -> 5616 bytes .../build/msw/vc_mswddll/wxjpeg/jidctflt.obj | Bin 0 -> 9095 bytes .../build/msw/vc_mswddll/wxjpeg/jidctfst.obj | Bin 0 -> 8685 bytes .../build/msw/vc_mswddll/wxjpeg/jidctint.obj | Bin 0 -> 9248 bytes .../build/msw/vc_mswddll/wxjpeg/jidctred.obj | Bin 0 -> 9735 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jmemmgr.obj | Bin 0 -> 21211 bytes .../build/msw/vc_mswddll/wxjpeg/jmemnobs.obj | Bin 0 -> 6626 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jquant1.obj | Bin 0 -> 20238 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jquant2.obj | Bin 0 -> 26669 bytes wx28X/build/msw/vc_mswddll/wxjpeg/jutils.obj | Bin 0 -> 5828 bytes .../msw/vc_mswddll/wxjpeg/lib.command.1.tlog | Bin 0 -> 8336 bytes .../build/msw/vc_mswddll/wxjpeg/wx_wxjpeg.log | 115 + .../vc_mswddll/wxjpeg/wxjpeg.lastbuildstate | 2 + .../wxjpeg/wxjpegd.Build.CppClean.log | 56 + .../build/msw/vc_mswddll/wxpng/CL.read.1.tlog | Bin 0 -> 42876 bytes .../msw/vc_mswddll/wxpng/CL.write.1.tlog | Bin 0 -> 5480 bytes .../msw/vc_mswddll/wxpng/Lib-link.read.1.tlog | Bin 0 -> 3874 bytes .../vc_mswddll/wxpng/Lib-link.write.1.tlog | Bin 0 -> 1918 bytes .../msw/vc_mswddll/wxpng/cl.command.1.tlog | Bin 0 -> 11358 bytes .../msw/vc_mswddll/wxpng/lib.command.1.tlog | Bin 0 -> 3070 bytes wx28X/build/msw/vc_mswddll/wxpng/png.obj | Bin 0 -> 22931 bytes wx28X/build/msw/vc_mswddll/wxpng/pngerror.obj | Bin 0 -> 11995 bytes wx28X/build/msw/vc_mswddll/wxpng/pnggccrd.obj | Bin 0 -> 3356 bytes wx28X/build/msw/vc_mswddll/wxpng/pngget.obj | Bin 0 -> 28956 bytes wx28X/build/msw/vc_mswddll/wxpng/pngmem.obj | Bin 0 -> 11719 bytes wx28X/build/msw/vc_mswddll/wxpng/pngpread.obj | Bin 0 -> 38754 bytes wx28X/build/msw/vc_mswddll/wxpng/pngread.obj | Bin 0 -> 35552 bytes wx28X/build/msw/vc_mswddll/wxpng/pngrio.obj | Bin 0 -> 6898 bytes wx28X/build/msw/vc_mswddll/wxpng/pngrtran.obj | Bin 0 -> 88522 bytes wx28X/build/msw/vc_mswddll/wxpng/pngrutil.obj | Bin 0 -> 68201 bytes wx28X/build/msw/vc_mswddll/wxpng/pngset.obj | Bin 0 -> 35194 bytes wx28X/build/msw/vc_mswddll/wxpng/pngtrans.obj | Bin 0 -> 17559 bytes wx28X/build/msw/vc_mswddll/wxpng/pngvcrd.obj | Bin 0 -> 3348 bytes wx28X/build/msw/vc_mswddll/wxpng/pngwio.obj | Bin 0 -> 7776 bytes wx28X/build/msw/vc_mswddll/wxpng/pngwrite.obj | Bin 0 -> 35312 bytes wx28X/build/msw/vc_mswddll/wxpng/pngwtran.obj | Bin 0 -> 16598 bytes wx28X/build/msw/vc_mswddll/wxpng/pngwutil.obj | Bin 0 -> 61655 bytes wx28X/build/msw/vc_mswddll/wxpng/wx_wxpng.log | 53 + .../msw/vc_mswddll/wxpng/wxpng.lastbuildstate | 2 + .../msw/vc_mswddll/wxpng/wxpng.write.1.tlog | 0 .../wxpng/wxpngd.Build.CppClean.log | 28 + wx28X/build/msw/vc_mswddll/wxprec_advdll.pch | Bin 0 -> 22740992 bytes wx28X/build/msw/vc_mswddll/wxprec_auidll.pch | Bin 0 -> 22740992 bytes wx28X/build/msw/vc_mswddll/wxprec_basedll.pch | Bin 0 -> 16842752 bytes wx28X/build/msw/vc_mswddll/wxprec_coredll.pch | Bin 0 -> 25493504 bytes .../build/msw/vc_mswddll/wxprec_dbgriddll.pch | Bin 0 -> 22675456 bytes wx28X/build/msw/vc_mswddll/wxprec_gldll.pch | Bin 0 -> 22740992 bytes wx28X/build/msw/vc_mswddll/wxprec_htmldll.pch | Bin 0 -> 22675456 bytes .../build/msw/vc_mswddll/wxprec_mediadll.pch | Bin 0 -> 22675456 bytes wx28X/build/msw/vc_mswddll/wxprec_netdll.pch | Bin 0 -> 16646144 bytes wx28X/build/msw/vc_mswddll/wxprec_odbcdll.pch | Bin 0 -> 16646144 bytes wx28X/build/msw/vc_mswddll/wxprec_qadll.pch | Bin 0 -> 22740992 bytes .../msw/vc_mswddll/wxprec_richtextdll.pch | Bin 0 -> 22740992 bytes wx28X/build/msw/vc_mswddll/wxprec_xmldll.pch | Bin 0 -> 16646144 bytes wx28X/build/msw/vc_mswddll/wxprec_xrcdll.pch | Bin 0 -> 22740992 bytes .../msw/vc_mswddll/wxregex/CL.read.1.tlog | Bin 0 -> 13138 bytes .../msw/vc_mswddll/wxregex/CL.write.1.tlog | Bin 0 -> 1364 bytes .../vc_mswddll/wxregex/Lib-link.read.1.tlog | Bin 0 -> 1076 bytes .../vc_mswddll/wxregex/Lib-link.write.1.tlog | Bin 0 -> 536 bytes .../msw/vc_mswddll/wxregex/cl.command.1.tlog | Bin 0 -> 3030 bytes .../wxregex/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../wxregex/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../wxregex/custombuild.write.1.tlog | Bin 0 -> 352 bytes .../msw/vc_mswddll/wxregex/lib.command.1.tlog | Bin 0 -> 874 bytes .../build/msw/vc_mswddll/wxregex/regcomp.obj | Bin 0 -> 179661 bytes .../build/msw/vc_mswddll/wxregex/regerror.obj | Bin 0 -> 8973 bytes .../build/msw/vc_mswddll/wxregex/regexec.obj | Bin 0 -> 48714 bytes .../build/msw/vc_mswddll/wxregex/regfree.obj | Bin 0 -> 5450 bytes .../msw/vc_mswddll/wxregex/wx_wxregex.log | 32 + .../vc_mswddll/wxregex/wxregex.lastbuildstate | 2 + .../wxregex/wxregexd.Build.CppClean.log | 19 + .../msw/vc_mswddll/wxtiff/CL.read.1.tlog | Bin 0 -> 445908 bytes .../msw/vc_mswddll/wxtiff/CL.write.1.tlog | Bin 0 -> 12084 bytes .../vc_mswddll/wxtiff/Lib-link.read.1.tlog | Bin 0 -> 8290 bytes .../vc_mswddll/wxtiff/Lib-link.write.1.tlog | Bin 0 -> 4110 bytes .../msw/vc_mswddll/wxtiff/cl.command.1.tlog | Bin 0 -> 25204 bytes .../msw/vc_mswddll/wxtiff/lib.command.1.tlog | Bin 0 -> 6660 bytes wx28X/build/msw/vc_mswddll/wxtiff/tif_aux.obj | Bin 0 -> 26241 bytes .../build/msw/vc_mswddll/wxtiff/tif_close.obj | Bin 0 -> 19237 bytes .../build/msw/vc_mswddll/wxtiff/tif_codec.obj | Bin 0 -> 20766 bytes .../build/msw/vc_mswddll/wxtiff/tif_color.obj | Bin 0 -> 26056 bytes .../msw/vc_mswddll/wxtiff/tif_compress.obj | Bin 0 -> 27147 bytes wx28X/build/msw/vc_mswddll/wxtiff/tif_dir.obj | Bin 0 -> 63075 bytes .../msw/vc_mswddll/wxtiff/tif_dirinfo.obj | Bin 0 -> 32600 bytes .../msw/vc_mswddll/wxtiff/tif_dirread.obj | Bin 0 -> 59335 bytes .../msw/vc_mswddll/wxtiff/tif_dirwrite.obj | Bin 0 -> 52282 bytes .../msw/vc_mswddll/wxtiff/tif_dumpmode.obj | Bin 0 -> 20506 bytes .../build/msw/vc_mswddll/wxtiff/tif_error.obj | Bin 0 -> 17698 bytes .../msw/vc_mswddll/wxtiff/tif_extension.obj | Bin 0 -> 20642 bytes .../build/msw/vc_mswddll/wxtiff/tif_fax3.obj | Bin 0 -> 79972 bytes .../msw/vc_mswddll/wxtiff/tif_fax3sm.obj | Bin 0 -> 101218 bytes .../build/msw/vc_mswddll/wxtiff/tif_flush.obj | Bin 0 -> 18659 bytes .../msw/vc_mswddll/wxtiff/tif_getimage.obj | Bin 0 -> 114856 bytes .../build/msw/vc_mswddll/wxtiff/tif_jpeg.obj | Bin 0 -> 16550 bytes wx28X/build/msw/vc_mswddll/wxtiff/tif_luv.obj | Bin 0 -> 75060 bytes wx28X/build/msw/vc_mswddll/wxtiff/tif_lzw.obj | Bin 0 -> 30797 bytes .../build/msw/vc_mswddll/wxtiff/tif_next.obj | Bin 0 -> 20346 bytes .../build/msw/vc_mswddll/wxtiff/tif_open.obj | Bin 0 -> 28332 bytes .../msw/vc_mswddll/wxtiff/tif_packbits.obj | Bin 0 -> 23969 bytes .../msw/vc_mswddll/wxtiff/tif_pixarlog.obj | Bin 0 -> 16562 bytes .../msw/vc_mswddll/wxtiff/tif_predict.obj | Bin 0 -> 36662 bytes .../build/msw/vc_mswddll/wxtiff/tif_print.obj | Bin 0 -> 38609 bytes .../build/msw/vc_mswddll/wxtiff/tif_read.obj | Bin 0 -> 35395 bytes .../build/msw/vc_mswddll/wxtiff/tif_strip.obj | Bin 0 -> 24779 bytes .../build/msw/vc_mswddll/wxtiff/tif_swab.obj | Bin 0 -> 21294 bytes .../msw/vc_mswddll/wxtiff/tif_thunder.obj | Bin 0 -> 21622 bytes .../build/msw/vc_mswddll/wxtiff/tif_tile.obj | Bin 0 -> 25225 bytes .../msw/vc_mswddll/wxtiff/tif_version.obj | Bin 0 -> 17251 bytes .../msw/vc_mswddll/wxtiff/tif_warning.obj | Bin 0 -> 17716 bytes .../build/msw/vc_mswddll/wxtiff/tif_win32.obj | Bin 0 -> 30513 bytes .../build/msw/vc_mswddll/wxtiff/tif_write.obj | Bin 0 -> 33750 bytes wx28X/build/msw/vc_mswddll/wxtiff/tif_zip.obj | Bin 0 -> 16550 bytes .../build/msw/vc_mswddll/wxtiff/wx_wxtiff.log | 91 + .../vc_mswddll/wxtiff/wxtiff.lastbuildstate | 2 + .../wxtiff/wxtiffd.Build.CppClean.log | 45 + .../msw/vc_mswddll/wxzlib/CL.read.1.tlog | Bin 0 -> 15770 bytes .../msw/vc_mswddll/wxzlib/CL.write.1.tlog | Bin 0 -> 3924 bytes .../vc_mswddll/wxzlib/Lib-link.read.1.tlog | Bin 0 -> 2804 bytes .../vc_mswddll/wxzlib/Lib-link.write.1.tlog | Bin 0 -> 1390 bytes wx28X/build/msw/vc_mswddll/wxzlib/adler32.obj | Bin 0 -> 4144 bytes .../msw/vc_mswddll/wxzlib/cl.command.1.tlog | Bin 0 -> 7678 bytes .../build/msw/vc_mswddll/wxzlib/compress.obj | Bin 0 -> 3444 bytes wx28X/build/msw/vc_mswddll/wxzlib/crc32.obj | Bin 0 -> 18322 bytes wx28X/build/msw/vc_mswddll/wxzlib/deflate.obj | Bin 0 -> 32533 bytes wx28X/build/msw/vc_mswddll/wxzlib/gzio.obj | Bin 0 -> 23909 bytes wx28X/build/msw/vc_mswddll/wxzlib/infback.obj | Bin 0 -> 17659 bytes wx28X/build/msw/vc_mswddll/wxzlib/inffast.obj | Bin 0 -> 7168 bytes wx28X/build/msw/vc_mswddll/wxzlib/inflate.obj | Bin 0 -> 31007 bytes .../build/msw/vc_mswddll/wxzlib/inftrees.obj | Bin 0 -> 7094 bytes .../msw/vc_mswddll/wxzlib/lib.command.1.tlog | Bin 0 -> 2232 bytes wx28X/build/msw/vc_mswddll/wxzlib/trees.obj | Bin 0 -> 33583 bytes wx28X/build/msw/vc_mswddll/wxzlib/uncompr.obj | Bin 0 -> 2734 bytes .../build/msw/vc_mswddll/wxzlib/wx_wxzlib.log | 43 + .../vc_mswddll/wxzlib/wxzlib.lastbuildstate | 2 + .../wxzlib/wxzlibd.Build.CppClean.log | 22 + wx28X/build/msw/vc_mswddll/wxzlib/zutil.obj | Bin 0 -> 5428 bytes wx28X/build/msw/vc_mswddll/xml/CL.read.1.tlog | Bin 0 -> 26600 bytes .../build/msw/vc_mswddll/xml/CL.write.1.tlog | Bin 0 -> 1106 bytes .../msw/vc_mswddll/xml/cl.command.1.tlog | Bin 0 -> 3832 bytes .../vc_mswddll/xml/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../vc_mswddll/xml/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../vc_mswddll/xml/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswddll/xml/dummy.obj | Bin 0 -> 380813 bytes .../vc_mswddll/xml/link-cvtres.read.1.tlog | 1 + .../vc_mswddll/xml/link-cvtres.write.1.tlog | 1 + .../xml/link.3680-cvtres.read.1.tlog | 1 + .../xml/link.3680-cvtres.write.1.tlog | 1 + .../msw/vc_mswddll/xml/link.3680.read.1.tlog | 1 + .../msw/vc_mswddll/xml/link.3680.write.1.tlog | 1 + .../msw/vc_mswddll/xml/link.command.1.tlog | Bin 0 -> 2802 bytes .../build/msw/vc_mswddll/xml/link.read.1.tlog | Bin 0 -> 5272 bytes .../msw/vc_mswddll/xml/link.write.1.tlog | Bin 0 -> 1326 bytes .../msw/vc_mswddll/xml/mt.command.1.tlog | Bin 0 -> 390 bytes wx28X/build/msw/vc_mswddll/xml/mt.read.1.tlog | Bin 0 -> 146 bytes .../build/msw/vc_mswddll/xml/mt.write.1.tlog | Bin 0 -> 274 bytes .../msw/vc_mswddll/xml/rc.command.1.tlog | Bin 0 -> 2202 bytes wx28X/build/msw/vc_mswddll/xml/rc.read.1.tlog | Bin 0 -> 458 bytes .../build/msw/vc_mswddll/xml/rc.write.1.tlog | Bin 0 -> 432 bytes wx28X/build/msw/vc_mswddll/xml/version.res | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswddll/xml/wx_xml.log | 59 + .../msw/vc_mswddll/xml/xml.Build.CppClean.log | 38 + .../msw/vc_mswddll/xml/xml.dll.embed.manifest | 15 + .../vc_mswddll/xml/xml.dll.embed.manifest.res | Bin 0 -> 748 bytes .../xml/xml.dll.intermediate.manifest | 15 + .../msw/vc_mswddll/xml/xml.lastbuildstate | 2 + wx28X/build/msw/vc_mswddll/xml/xml.obj | Bin 0 -> 141644 bytes .../build/msw/vc_mswddll/xml/xml.write.1.tlog | 3 + .../build/msw/vc_mswddll/xml/xml_manifest.rc | Bin 0 -> 224 bytes wx28X/build/msw/vc_mswddll/xml/xtixml.obj | Bin 0 -> 2279 bytes wx28X/build/msw/vc_mswddll/xrc/CL.read.1.tlog | Bin 0 -> 174974 bytes .../build/msw/vc_mswddll/xrc/CL.write.1.tlog | Bin 0 -> 20984 bytes .../msw/vc_mswddll/xrc/cl.command.1.tlog | Bin 0 -> 71384 bytes .../vc_mswddll/xrc/custombuild.command.1.tlog | Bin 0 -> 532 bytes .../vc_mswddll/xrc/custombuild.read.1.tlog | Bin 0 -> 170 bytes .../vc_mswddll/xrc/custombuild.write.1.tlog | Bin 0 -> 352 bytes wx28X/build/msw/vc_mswddll/xrc/dummy.obj | Bin 0 -> 420733 bytes .../vc_mswddll/xrc/link-cvtres.read.1.tlog | 1 + .../vc_mswddll/xrc/link-cvtres.write.1.tlog | 1 + .../xrc/link.4340-cvtres.read.1.tlog | 1 + .../xrc/link.4340-cvtres.write.1.tlog | 1 + .../msw/vc_mswddll/xrc/link.4340.read.1.tlog | 1 + .../msw/vc_mswddll/xrc/link.4340.write.1.tlog | 1 + .../msw/vc_mswddll/xrc/link.command.1.tlog | Bin 0 -> 12274 bytes .../build/msw/vc_mswddll/xrc/link.read.1.tlog | Bin 0 -> 17520 bytes .../msw/vc_mswddll/xrc/link.write.1.tlog | Bin 0 -> 7074 bytes .../msw/vc_mswddll/xrc/mt.command.1.tlog | Bin 0 -> 390 bytes wx28X/build/msw/vc_mswddll/xrc/mt.read.1.tlog | Bin 0 -> 146 bytes .../build/msw/vc_mswddll/xrc/mt.write.1.tlog | Bin 0 -> 274 bytes .../msw/vc_mswddll/xrc/rc.command.1.tlog | Bin 0 -> 2138 bytes wx28X/build/msw/vc_mswddll/xrc/rc.read.1.tlog | Bin 0 -> 458 bytes .../build/msw/vc_mswddll/xrc/rc.write.1.tlog | Bin 0 -> 432 bytes wx28X/build/msw/vc_mswddll/xrc/version.res | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswddll/xrc/wx_xrc.log | 223 + .../msw/vc_mswddll/xrc/xh_animatctrl.obj | Bin 0 -> 86973 bytes wx28X/build/msw/vc_mswddll/xrc/xh_bmp.obj | Bin 0 -> 76244 bytes wx28X/build/msw/vc_mswddll/xrc/xh_bmpbt.obj | Bin 0 -> 98244 bytes wx28X/build/msw/vc_mswddll/xrc/xh_bmpcbox.obj | Bin 0 -> 103253 bytes wx28X/build/msw/vc_mswddll/xrc/xh_bttn.obj | Bin 0 -> 86062 bytes wx28X/build/msw/vc_mswddll/xrc/xh_cald.obj | Bin 0 -> 86077 bytes wx28X/build/msw/vc_mswddll/xrc/xh_chckb.obj | Bin 0 -> 86044 bytes wx28X/build/msw/vc_mswddll/xrc/xh_chckl.obj | Bin 0 -> 103321 bytes wx28X/build/msw/vc_mswddll/xrc/xh_choic.obj | Bin 0 -> 94057 bytes wx28X/build/msw/vc_mswddll/xrc/xh_choicbk.obj | Bin 0 -> 101587 bytes .../build/msw/vc_mswddll/xrc/xh_clrpicker.obj | Bin 0 -> 86892 bytes .../build/msw/vc_mswddll/xrc/xh_collpane.obj | Bin 0 -> 89945 bytes wx28X/build/msw/vc_mswddll/xrc/xh_combo.obj | Bin 0 -> 99307 bytes .../build/msw/vc_mswddll/xrc/xh_datectrl.obj | Bin 0 -> 85461 bytes .../build/msw/vc_mswddll/xrc/xh_dirpicker.obj | Bin 0 -> 89406 bytes wx28X/build/msw/vc_mswddll/xrc/xh_dlg.obj | Bin 0 -> 98211 bytes .../msw/vc_mswddll/xrc/xh_filepicker.obj | Bin 0 -> 91728 bytes .../msw/vc_mswddll/xrc/xh_fontpicker.obj | Bin 0 -> 88555 bytes wx28X/build/msw/vc_mswddll/xrc/xh_frame.obj | Bin 0 -> 100257 bytes wx28X/build/msw/vc_mswddll/xrc/xh_gauge.obj | Bin 0 -> 88269 bytes wx28X/build/msw/vc_mswddll/xrc/xh_gdctl.obj | Bin 0 -> 92565 bytes wx28X/build/msw/vc_mswddll/xrc/xh_grid.obj | Bin 0 -> 86399 bytes wx28X/build/msw/vc_mswddll/xrc/xh_html.obj | Bin 0 -> 98870 bytes .../build/msw/vc_mswddll/xrc/xh_htmllbox.obj | Bin 0 -> 105121 bytes .../build/msw/vc_mswddll/xrc/xh_hyperlink.obj | Bin 0 -> 86239 bytes wx28X/build/msw/vc_mswddll/xrc/xh_listb.obj | Bin 0 -> 97534 bytes wx28X/build/msw/vc_mswddll/xrc/xh_listbk.obj | Bin 0 -> 101131 bytes wx28X/build/msw/vc_mswddll/xrc/xh_listc.obj | Bin 0 -> 90064 bytes wx28X/build/msw/vc_mswddll/xrc/xh_mdi.obj | Bin 0 -> 114074 bytes wx28X/build/msw/vc_mswddll/xrc/xh_menu.obj | Bin 0 -> 116990 bytes wx28X/build/msw/vc_mswddll/xrc/xh_notbk.obj | Bin 0 -> 103452 bytes wx28X/build/msw/vc_mswddll/xrc/xh_odcombo.obj | Bin 0 -> 104322 bytes wx28X/build/msw/vc_mswddll/xrc/xh_panel.obj | Bin 0 -> 80945 bytes wx28X/build/msw/vc_mswddll/xrc/xh_propdlg.obj | Bin 0 -> 112638 bytes wx28X/build/msw/vc_mswddll/xrc/xh_radbt.obj | Bin 0 -> 84520 bytes wx28X/build/msw/vc_mswddll/xrc/xh_radbx.obj | Bin 0 -> 106148 bytes wx28X/build/msw/vc_mswddll/xrc/xh_scrol.obj | Bin 0 -> 85944 bytes wx28X/build/msw/vc_mswddll/xrc/xh_scwin.obj | Bin 0 -> 87580 bytes wx28X/build/msw/vc_mswddll/xrc/xh_sizer.obj | Bin 0 -> 181244 bytes wx28X/build/msw/vc_mswddll/xrc/xh_slidr.obj | Bin 0 -> 97254 bytes wx28X/build/msw/vc_mswddll/xrc/xh_spin.obj | Bin 0 -> 110136 bytes wx28X/build/msw/vc_mswddll/xrc/xh_split.obj | Bin 0 -> 93081 bytes wx28X/build/msw/vc_mswddll/xrc/xh_statbar.obj | Bin 0 -> 87663 bytes wx28X/build/msw/vc_mswddll/xrc/xh_stbmp.obj | Bin 0 -> 84884 bytes wx28X/build/msw/vc_mswddll/xrc/xh_stbox.obj | Bin 0 -> 83635 bytes wx28X/build/msw/vc_mswddll/xrc/xh_stlin.obj | Bin 0 -> 83450 bytes wx28X/build/msw/vc_mswddll/xrc/xh_sttxt.obj | Bin 0 -> 85933 bytes wx28X/build/msw/vc_mswddll/xrc/xh_text.obj | Bin 0 -> 96455 bytes wx28X/build/msw/vc_mswddll/xrc/xh_tglbtn.obj | Bin 0 -> 84365 bytes wx28X/build/msw/vc_mswddll/xrc/xh_toolb.obj | Bin 0 -> 119133 bytes wx28X/build/msw/vc_mswddll/xrc/xh_tree.obj | Bin 0 -> 96407 bytes wx28X/build/msw/vc_mswddll/xrc/xh_treebk.obj | Bin 0 -> 135390 bytes wx28X/build/msw/vc_mswddll/xrc/xh_unkwn.obj | Bin 0 -> 95473 bytes wx28X/build/msw/vc_mswddll/xrc/xh_wizrd.obj | Bin 0 -> 104215 bytes wx28X/build/msw/vc_mswddll/xrc/xmlres.obj | Bin 0 -> 397522 bytes wx28X/build/msw/vc_mswddll/xrc/xmlrsall.obj | Bin 0 -> 355664 bytes .../msw/vc_mswddll/xrc/xrc.Build.CppClean.log | 92 + .../msw/vc_mswddll/xrc/xrc.dll.embed.manifest | 15 + .../vc_mswddll/xrc/xrc.dll.embed.manifest.res | Bin 0 -> 748 bytes .../xrc/xrc.dll.intermediate.manifest | 15 + .../msw/vc_mswddll/xrc/xrc.lastbuildstate | 2 + .../build/msw/vc_mswddll/xrc/xrc.write.1.tlog | 3 + .../build/msw/vc_mswddll/xrc/xrc_manifest.rc | Bin 0 -> 224 bytes wx28X/build/msw/vc_mswdll/adv/CL.read.1.tlog | Bin 0 -> 199592 bytes wx28X/build/msw/vc_mswdll/adv/CL.write.1.tlog | Bin 0 -> 30164 bytes .../adv/ResolveAssemblyReference.cache | Bin 0 -> 1611 bytes wx28X/build/msw/vc_mswdll/adv/aboutdlg.obj | Bin 0 -> 79178 bytes wx28X/build/msw/vc_mswdll/adv/aboutdlgg.obj | Bin 0 -> 179946 bytes .../msw/vc_mswdll/adv/adv.Build.CppClean.log | 1 + .../adv/adv.dll.intermediate.manifest | 15 + .../msw/vc_mswdll/adv/adv.lastbuildstate | 2 + .../build/msw/vc_mswdll/adv/adv.write.1.tlog | 9 + wx28X/build/msw/vc_mswdll/adv/animatecmn.obj | Bin 0 -> 171975 bytes wx28X/build/msw/vc_mswdll/adv/animateg.obj | Bin 0 -> 251931 bytes wx28X/build/msw/vc_mswdll/adv/bmpcboxg.obj | Bin 0 -> 145542 bytes wx28X/build/msw/vc_mswdll/adv/calctrl.obj | Bin 0 -> 261306 bytes .../build/msw/vc_mswdll/adv/cl.command.1.tlog | Bin 0 -> 99548 bytes .../vc_mswdll/adv/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../msw/vc_mswdll/adv/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../vc_mswdll/adv/custombuild.write.1.tlog | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/adv/datavcmn.obj | Bin 0 -> 264184 bytes wx28X/build/msw/vc_mswdll/adv/datavgen.obj | Bin 0 -> 489642 bytes wx28X/build/msw/vc_mswdll/adv/datectlg.obj | Bin 0 -> 34643 bytes wx28X/build/msw/vc_mswdll/adv/datectrl.obj | Bin 0 -> 81651 bytes wx28X/build/msw/vc_mswdll/adv/dummy.obj | Bin 0 -> 420238 bytes wx28X/build/msw/vc_mswdll/adv/grid.obj | Bin 0 -> 1339421 bytes wx28X/build/msw/vc_mswdll/adv/gridctrl.obj | Bin 0 -> 395811 bytes wx28X/build/msw/vc_mswdll/adv/gridsel.obj | Bin 0 -> 316527 bytes wx28X/build/msw/vc_mswdll/adv/helpext.obj | Bin 0 -> 82611 bytes wx28X/build/msw/vc_mswdll/adv/hyperlink.obj | Bin 0 -> 113200 bytes wx28X/build/msw/vc_mswdll/adv/joystick.obj | Bin 0 -> 50606 bytes wx28X/build/msw/vc_mswdll/adv/laywin.obj | Bin 0 -> 129189 bytes .../msw/vc_mswdll/adv/link-cvtres.read.1.tlog | 1 + .../vc_mswdll/adv/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswdll/adv/link.command.1.tlog | Bin 0 -> 21110 bytes .../build/msw/vc_mswdll/adv/link.read.1.tlog | Bin 0 -> 30356 bytes .../build/msw/vc_mswdll/adv/link.write.1.tlog | Bin 0 -> 11038 bytes .../build/msw/vc_mswdll/adv/mt.command.1.tlog | Bin 0 -> 1258 bytes wx28X/build/msw/vc_mswdll/adv/mt.read.1.tlog | Bin 0 -> 1830 bytes wx28X/build/msw/vc_mswdll/adv/mt.write.1.tlog | Bin 0 -> 750 bytes wx28X/build/msw/vc_mswdll/adv/odcombo.obj | Bin 0 -> 175615 bytes wx28X/build/msw/vc_mswdll/adv/propdlg.obj | Bin 0 -> 112064 bytes .../build/msw/vc_mswdll/adv/rc.command.1.tlog | Bin 0 -> 4506 bytes wx28X/build/msw/vc_mswdll/adv/rc.read.1.tlog | Bin 0 -> 644 bytes wx28X/build/msw/vc_mswdll/adv/rc.write.1.tlog | Bin 0 -> 534 bytes wx28X/build/msw/vc_mswdll/adv/sashwin.obj | Bin 0 -> 156507 bytes wx28X/build/msw/vc_mswdll/adv/sound.obj | Bin 0 -> 43847 bytes wx28X/build/msw/vc_mswdll/adv/splash.obj | Bin 0 -> 83992 bytes wx28X/build/msw/vc_mswdll/adv/taskbar.obj | Bin 0 -> 69728 bytes wx28X/build/msw/vc_mswdll/adv/taskbarcmn.obj | Bin 0 -> 32852 bytes wx28X/build/msw/vc_mswdll/adv/tipdlg.obj | Bin 0 -> 131646 bytes wx28X/build/msw/vc_mswdll/adv/version.res | Bin 0 -> 1044 bytes wx28X/build/msw/vc_mswdll/adv/wizard.obj | Bin 0 -> 203032 bytes wx28X/build/msw/vc_mswdll/adv/wx_adv.log | 95 + wx28X/build/msw/vc_mswdll/aui/CL.read.1.tlog | Bin 0 -> 142264 bytes wx28X/build/msw/vc_mswdll/aui/CL.write.1.tlog | Bin 0 -> 7702 bytes .../aui/ResolveAssemblyReference.cache | Bin 0 -> 1604 bytes .../aui/aui.dll.intermediate.manifest | 15 + .../msw/vc_mswdll/aui/aui.lastbuildstate | 2 + .../build/msw/vc_mswdll/aui/aui.write.1.tlog | 9 + wx28X/build/msw/vc_mswdll/aui/auibar.obj | Bin 0 -> 548553 bytes wx28X/build/msw/vc_mswdll/aui/auibook.obj | Bin 0 -> 740546 bytes .../build/msw/vc_mswdll/aui/cl.command.1.tlog | Bin 0 -> 25596 bytes .../vc_mswdll/aui/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../msw/vc_mswdll/aui/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../vc_mswdll/aui/custombuild.write.1.tlog | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/aui/dockart.obj | Bin 0 -> 282466 bytes wx28X/build/msw/vc_mswdll/aui/dummy.obj | Bin 0 -> 420238 bytes wx28X/build/msw/vc_mswdll/aui/floatpane.obj | Bin 0 -> 269594 bytes .../build/msw/vc_mswdll/aui/framemanager.obj | Bin 0 -> 780888 bytes .../msw/vc_mswdll/aui/link-cvtres.read.1.tlog | 1 + .../vc_mswdll/aui/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswdll/aui/link.command.1.tlog | Bin 0 -> 11596 bytes .../build/msw/vc_mswdll/aui/link.read.1.tlog | Bin 0 -> 18110 bytes .../build/msw/vc_mswdll/aui/link.write.1.tlog | Bin 0 -> 4842 bytes .../build/msw/vc_mswdll/aui/mt.command.1.tlog | Bin 0 -> 1258 bytes wx28X/build/msw/vc_mswdll/aui/mt.read.1.tlog | Bin 0 -> 1830 bytes wx28X/build/msw/vc_mswdll/aui/mt.write.1.tlog | Bin 0 -> 750 bytes .../build/msw/vc_mswdll/aui/rc.command.1.tlog | Bin 0 -> 4506 bytes wx28X/build/msw/vc_mswdll/aui/rc.read.1.tlog | Bin 0 -> 644 bytes wx28X/build/msw/vc_mswdll/aui/rc.write.1.tlog | Bin 0 -> 534 bytes wx28X/build/msw/vc_mswdll/aui/tabmdi.obj | Bin 0 -> 456995 bytes wx28X/build/msw/vc_mswdll/aui/version.res | Bin 0 -> 1044 bytes wx28X/build/msw/vc_mswdll/aui/wx_aui.log | 53 + wx28X/build/msw/vc_mswdll/base/CL.read.1.tlog | Bin 0 -> 344566 bytes .../build/msw/vc_mswdll/base/CL.write.1.tlog | Bin 0 -> 95806 bytes .../base/ResolveAssemblyReference.cache | Bin 0 -> 1084 bytes wx28X/build/msw/vc_mswdll/base/appbase.obj | Bin 0 -> 379017 bytes wx28X/build/msw/vc_mswdll/base/arcall.obj | Bin 0 -> 512921 bytes wx28X/build/msw/vc_mswdll/base/arcfind.obj | Bin 0 -> 303989 bytes wx28X/build/msw/vc_mswdll/base/archive.obj | Bin 0 -> 313298 bytes .../base/base.dll.intermediate.manifest | 15 + .../msw/vc_mswdll/base/base.lastbuildstate | 2 + .../msw/vc_mswdll/base/base.write.1.tlog | 9 + wx28X/build/msw/vc_mswdll/base/basemsw.obj | Bin 0 -> 32154 bytes .../msw/vc_mswdll/base/cl.command.1.tlog | Bin 0 -> 335260 bytes wx28X/build/msw/vc_mswdll/base/clntdata.obj | Bin 0 -> 11186 bytes wx28X/build/msw/vc_mswdll/base/cmdline.obj | Bin 0 -> 388032 bytes wx28X/build/msw/vc_mswdll/base/config.obj | Bin 0 -> 124136 bytes wx28X/build/msw/vc_mswdll/base/convauto.obj | Bin 0 -> 40938 bytes wx28X/build/msw/vc_mswdll/base/crashrpt.obj | Bin 0 -> 82728 bytes .../vc_mswdll/base/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../vc_mswdll/base/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../vc_mswdll/base/custombuild.write.1.tlog | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/base/datetime.obj | Bin 0 -> 439156 bytes wx28X/build/msw/vc_mswdll/base/datstrm.obj | Bin 0 -> 94170 bytes wx28X/build/msw/vc_mswdll/base/dde.obj | Bin 0 -> 429900 bytes wx28X/build/msw/vc_mswdll/base/debughlp.obj | Bin 0 -> 121407 bytes wx28X/build/msw/vc_mswdll/base/dir.obj | Bin 0 -> 45835 bytes wx28X/build/msw/vc_mswdll/base/dircmn.obj | Bin 0 -> 305978 bytes wx28X/build/msw/vc_mswdll/base/dlmsw.obj | Bin 0 -> 84076 bytes wx28X/build/msw/vc_mswdll/base/dummy.obj | Bin 0 -> 1700670 bytes wx28X/build/msw/vc_mswdll/base/dynarray.obj | Bin 0 -> 141970 bytes wx28X/build/msw/vc_mswdll/base/dynlib.obj | Bin 0 -> 321913 bytes wx28X/build/msw/vc_mswdll/base/dynload.obj | Bin 0 -> 202031 bytes wx28X/build/msw/vc_mswdll/base/encconv.obj | Bin 0 -> 56972 bytes wx28X/build/msw/vc_mswdll/base/event.obj | Bin 0 -> 100778 bytes wx28X/build/msw/vc_mswdll/base/extended.obj | Bin 0 -> 8714 bytes wx28X/build/msw/vc_mswdll/base/ffile.obj | Bin 0 -> 48247 bytes wx28X/build/msw/vc_mswdll/base/file.obj | Bin 0 -> 295673 bytes wx28X/build/msw/vc_mswdll/base/fileback.obj | Bin 0 -> 72698 bytes wx28X/build/msw/vc_mswdll/base/fileconf.obj | Bin 0 -> 354677 bytes wx28X/build/msw/vc_mswdll/base/filefn.obj | Bin 0 -> 400535 bytes wx28X/build/msw/vc_mswdll/base/filename.obj | Bin 0 -> 588102 bytes wx28X/build/msw/vc_mswdll/base/filesys.obj | Bin 0 -> 600811 bytes wx28X/build/msw/vc_mswdll/base/filtall.obj | Bin 0 -> 50520 bytes wx28X/build/msw/vc_mswdll/base/filtfind.obj | Bin 0 -> 4990 bytes wx28X/build/msw/vc_mswdll/base/fmapbase.obj | Bin 0 -> 274676 bytes wx28X/build/msw/vc_mswdll/base/fs_arc.obj | Bin 0 -> 536455 bytes wx28X/build/msw/vc_mswdll/base/fs_filter.obj | Bin 0 -> 366695 bytes wx28X/build/msw/vc_mswdll/base/fs_mem.obj | Bin 0 -> 402797 bytes wx28X/build/msw/vc_mswdll/base/hash.obj | Bin 0 -> 36346 bytes wx28X/build/msw/vc_mswdll/base/hashmap.obj | Bin 0 -> 8048 bytes wx28X/build/msw/vc_mswdll/base/init.obj | Bin 0 -> 57656 bytes wx28X/build/msw/vc_mswdll/base/intl.obj | Bin 0 -> 661205 bytes wx28X/build/msw/vc_mswdll/base/ipcbase.obj | Bin 0 -> 36275 bytes .../vc_mswdll/base/link-cvtres.read.1.tlog | 1 + .../vc_mswdll/base/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswdll/base/link.command.1.tlog | Bin 0 -> 48980 bytes .../build/msw/vc_mswdll/base/link.read.1.tlog | Bin 0 -> 67264 bytes .../msw/vc_mswdll/base/link.write.1.tlog | Bin 0 -> 29442 bytes wx28X/build/msw/vc_mswdll/base/list.obj | Bin 0 -> 88064 bytes wx28X/build/msw/vc_mswdll/base/log.obj | Bin 0 -> 404059 bytes wx28X/build/msw/vc_mswdll/base/longlong.obj | Bin 0 -> 70558 bytes wx28X/build/msw/vc_mswdll/base/main.obj | Bin 0 -> 222744 bytes wx28X/build/msw/vc_mswdll/base/memory.obj | Bin 0 -> 2332 bytes wx28X/build/msw/vc_mswdll/base/mimecmn.obj | Bin 0 -> 232344 bytes wx28X/build/msw/vc_mswdll/base/mimetype.obj | Bin 0 -> 225319 bytes wx28X/build/msw/vc_mswdll/base/module.obj | Bin 0 -> 64471 bytes wx28X/build/msw/vc_mswdll/base/msgout.obj | Bin 0 -> 41755 bytes wx28X/build/msw/vc_mswdll/base/mslu.obj | Bin 0 -> 2853 bytes wx28X/build/msw/vc_mswdll/base/mstream.obj | Bin 0 -> 36417 bytes .../msw/vc_mswdll/base/mt.command.1.tlog | Bin 0 -> 1264 bytes wx28X/build/msw/vc_mswdll/base/mt.read.1.tlog | Bin 0 -> 1824 bytes .../build/msw/vc_mswdll/base/mt.write.1.tlog | Bin 0 -> 744 bytes wx28X/build/msw/vc_mswdll/base/object.obj | Bin 0 -> 36603 bytes wx28X/build/msw/vc_mswdll/base/platinfo.obj | Bin 0 -> 68601 bytes wx28X/build/msw/vc_mswdll/base/power.obj | Bin 0 -> 17281 bytes wx28X/build/msw/vc_mswdll/base/powercmn.obj | Bin 0 -> 20036 bytes wx28X/build/msw/vc_mswdll/base/process.obj | Bin 0 -> 45693 bytes .../msw/vc_mswdll/base/rc.command.1.tlog | Bin 0 -> 4698 bytes wx28X/build/msw/vc_mswdll/base/rc.read.1.tlog | Bin 0 -> 644 bytes .../build/msw/vc_mswdll/base/rc.write.1.tlog | Bin 0 -> 540 bytes wx28X/build/msw/vc_mswdll/base/regconf.obj | Bin 0 -> 111013 bytes wx28X/build/msw/vc_mswdll/base/regex.obj | Bin 0 -> 53936 bytes wx28X/build/msw/vc_mswdll/base/registry.obj | Bin 0 -> 195924 bytes wx28X/build/msw/vc_mswdll/base/snglinst.obj | Bin 0 -> 11706 bytes wx28X/build/msw/vc_mswdll/base/sstream.obj | Bin 0 -> 46412 bytes wx28X/build/msw/vc_mswdll/base/stackwalk.obj | Bin 0 -> 116337 bytes wx28X/build/msw/vc_mswdll/base/stdpaths.obj | Bin 0 -> 342461 bytes wx28X/build/msw/vc_mswdll/base/stdpbase.obj | Bin 0 -> 315822 bytes wx28X/build/msw/vc_mswdll/base/stopwatch.obj | Bin 0 -> 16031 bytes wx28X/build/msw/vc_mswdll/base/strconv.obj | Bin 0 -> 165938 bytes wx28X/build/msw/vc_mswdll/base/stream.obj | Bin 0 -> 222107 bytes wx28X/build/msw/vc_mswdll/base/string.obj | Bin 0 -> 179806 bytes wx28X/build/msw/vc_mswdll/base/sysopt.obj | Bin 0 -> 36484 bytes wx28X/build/msw/vc_mswdll/base/tarstrm.obj | Bin 0 -> 581864 bytes wx28X/build/msw/vc_mswdll/base/textbuf.obj | Bin 0 -> 105443 bytes wx28X/build/msw/vc_mswdll/base/textfile.obj | Bin 0 -> 369725 bytes wx28X/build/msw/vc_mswdll/base/thread.obj | Bin 0 -> 154301 bytes wx28X/build/msw/vc_mswdll/base/tokenzr.obj | Bin 0 -> 51049 bytes wx28X/build/msw/vc_mswdll/base/txtstrm.obj | Bin 0 -> 89307 bytes wx28X/build/msw/vc_mswdll/base/uri.obj | Bin 0 -> 101177 bytes wx28X/build/msw/vc_mswdll/base/utils.obj | Bin 0 -> 265113 bytes wx28X/build/msw/vc_mswdll/base/utilscmn.obj | Bin 0 -> 263793 bytes wx28X/build/msw/vc_mswdll/base/utilsexc.obj | Bin 0 -> 397733 bytes wx28X/build/msw/vc_mswdll/base/variant.obj | Bin 0 -> 596364 bytes wx28X/build/msw/vc_mswdll/base/version.res | Bin 0 -> 1040 bytes wx28X/build/msw/vc_mswdll/base/volume.obj | Bin 0 -> 129896 bytes wx28X/build/msw/vc_mswdll/base/wfstream.obj | Bin 0 -> 129671 bytes wx28X/build/msw/vc_mswdll/base/wx_base.log | 25 + wx28X/build/msw/vc_mswdll/base/wxchar.obj | Bin 0 -> 7823 bytes wx28X/build/msw/vc_mswdll/base/xti.obj | Bin 0 -> 2320 bytes wx28X/build/msw/vc_mswdll/base/xtistrm.obj | Bin 0 -> 2332 bytes wx28X/build/msw/vc_mswdll/base/zipstrm.obj | Bin 0 -> 811071 bytes wx28X/build/msw/vc_mswdll/base/zstream.obj | Bin 0 -> 106461 bytes wx28X/build/msw/vc_mswdll/core/CL.read.1.tlog | Bin 0 -> 702358 bytes .../build/msw/vc_mswdll/core/CL.write.1.tlog | Bin 0 -> 251712 bytes .../core/ResolveAssemblyReference.cache | Bin 0 -> 1250 bytes wx28X/build/msw/vc_mswdll/core/accel.obj | Bin 0 -> 28389 bytes wx28X/build/msw/vc_mswdll/core/access.obj | Bin 0 -> 2344 bytes wx28X/build/msw/vc_mswdll/core/accesscmn.obj | Bin 0 -> 2352 bytes wx28X/build/msw/vc_mswdll/core/anidecod.obj | Bin 0 -> 150205 bytes wx28X/build/msw/vc_mswdll/core/app.obj | Bin 0 -> 157089 bytes wx28X/build/msw/vc_mswdll/core/appcmn.obj | Bin 0 -> 121849 bytes wx28X/build/msw/vc_mswdll/core/artprov.obj | Bin 0 -> 238623 bytes wx28X/build/msw/vc_mswdll/core/artstd.obj | Bin 0 -> 288927 bytes wx28X/build/msw/vc_mswdll/core/automtn.obj | Bin 0 -> 69514 bytes wx28X/build/msw/vc_mswdll/core/bitmap.obj | Bin 0 -> 200750 bytes wx28X/build/msw/vc_mswdll/core/bmpbase.obj | Bin 0 -> 81141 bytes wx28X/build/msw/vc_mswdll/core/bmpbuttn.obj | Bin 0 -> 254907 bytes wx28X/build/msw/vc_mswdll/core/bookctrl.obj | Bin 0 -> 328861 bytes wx28X/build/msw/vc_mswdll/core/brush.obj | Bin 0 -> 87173 bytes wx28X/build/msw/vc_mswdll/core/busyinfo.obj | Bin 0 -> 127331 bytes wx28X/build/msw/vc_mswdll/core/button.obj | Bin 0 -> 139756 bytes wx28X/build/msw/vc_mswdll/core/buttonbar.obj | Bin 0 -> 2352 bytes wx28X/build/msw/vc_mswdll/core/caret.obj | Bin 0 -> 36802 bytes wx28X/build/msw/vc_mswdll/core/checkbox.obj | Bin 0 -> 121819 bytes wx28X/build/msw/vc_mswdll/core/checklst.obj | Bin 0 -> 141167 bytes wx28X/build/msw/vc_mswdll/core/choicbkg.obj | Bin 0 -> 380267 bytes wx28X/build/msw/vc_mswdll/core/choiccmn.obj | Bin 0 -> 59678 bytes wx28X/build/msw/vc_mswdll/core/choicdgg.obj | Bin 0 -> 274395 bytes wx28X/build/msw/vc_mswdll/core/choice.obj | Bin 0 -> 145431 bytes .../msw/vc_mswdll/core/cl.command.1.tlog | Bin 0 -> 860644 bytes wx28X/build/msw/vc_mswdll/core/clipbrd.obj | Bin 0 -> 157386 bytes wx28X/build/msw/vc_mswdll/core/clipcmn.obj | Bin 0 -> 28210 bytes .../build/msw/vc_mswdll/core/clrpickercmn.obj | Bin 0 -> 210222 bytes wx28X/build/msw/vc_mswdll/core/clrpickerg.obj | Bin 0 -> 208055 bytes wx28X/build/msw/vc_mswdll/core/cmdproc.obj | Bin 0 -> 71033 bytes wx28X/build/msw/vc_mswdll/core/cmndata.obj | Bin 0 -> 288546 bytes wx28X/build/msw/vc_mswdll/core/collpaneg.obj | Bin 0 -> 202901 bytes wx28X/build/msw/vc_mswdll/core/colordlg.obj | Bin 0 -> 107785 bytes wx28X/build/msw/vc_mswdll/core/colour.obj | Bin 0 -> 24659 bytes wx28X/build/msw/vc_mswdll/core/colourcmn.obj | Bin 0 -> 46281 bytes wx28X/build/msw/vc_mswdll/core/combo.obj | Bin 0 -> 352798 bytes wx28X/build/msw/vc_mswdll/core/combobox.obj | Bin 0 -> 182131 bytes wx28X/build/msw/vc_mswdll/core/combocmn.obj | Bin 0 -> 472104 bytes wx28X/build/msw/vc_mswdll/core/combog.obj | Bin 0 -> 283113 bytes wx28X/build/msw/vc_mswdll/core/containr.obj | Bin 0 -> 52477 bytes wx28X/build/msw/vc_mswdll/core/control.obj | Bin 0 -> 416402 bytes .../core/core.dll.intermediate.manifest | 15 + .../msw/vc_mswdll/core/core.lastbuildstate | 2 + .../msw/vc_mswdll/core/core.write.1.tlog | 9 + wx28X/build/msw/vc_mswdll/core/cshelp.obj | Bin 0 -> 347500 bytes wx28X/build/msw/vc_mswdll/core/ctrlcmn.obj | Bin 0 -> 102018 bytes wx28X/build/msw/vc_mswdll/core/ctrlsub.obj | Bin 0 -> 79129 bytes wx28X/build/msw/vc_mswdll/core/cursor.obj | Bin 0 -> 73077 bytes .../vc_mswdll/core/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../vc_mswdll/core/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../vc_mswdll/core/custombuild.write.1.tlog | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/core/data.obj | Bin 0 -> 2332 bytes wx28X/build/msw/vc_mswdll/core/datacmn.obj | Bin 0 -> 13110 bytes wx28X/build/msw/vc_mswdll/core/dataobj.obj | Bin 0 -> 143042 bytes wx28X/build/msw/vc_mswdll/core/dc.obj | Bin 0 -> 308206 bytes wx28X/build/msw/vc_mswdll/core/dcbase.obj | Bin 0 -> 218966 bytes wx28X/build/msw/vc_mswdll/core/dcbufcmn.obj | Bin 0 -> 149117 bytes wx28X/build/msw/vc_mswdll/core/dcclient.obj | Bin 0 -> 151758 bytes wx28X/build/msw/vc_mswdll/core/dcgraph.obj | Bin 0 -> 2344 bytes wx28X/build/msw/vc_mswdll/core/dcmemory.obj | Bin 0 -> 113758 bytes wx28X/build/msw/vc_mswdll/core/dcprint.obj | Bin 0 -> 289984 bytes wx28X/build/msw/vc_mswdll/core/dcpsg.obj | Bin 0 -> 2340 bytes wx28X/build/msw/vc_mswdll/core/dcscreen.obj | Bin 0 -> 95128 bytes wx28X/build/msw/vc_mswdll/core/dialog.obj | Bin 0 -> 132111 bytes wx28X/build/msw/vc_mswdll/core/dialup.obj | Bin 0 -> 132217 bytes wx28X/build/msw/vc_mswdll/core/dib.obj | Bin 0 -> 58577 bytes wx28X/build/msw/vc_mswdll/core/dirctrlg.obj | Bin 0 -> 568895 bytes wx28X/build/msw/vc_mswdll/core/dirdlg.obj | Bin 0 -> 121692 bytes wx28X/build/msw/vc_mswdll/core/display.obj | Bin 0 -> 99823 bytes wx28X/build/msw/vc_mswdll/core/dlgcmn.obj | Bin 0 -> 211928 bytes wx28X/build/msw/vc_mswdll/core/dndcmn.obj | Bin 0 -> 41481 bytes wx28X/build/msw/vc_mswdll/core/dobjcmn.obj | Bin 0 -> 150489 bytes wx28X/build/msw/vc_mswdll/core/docmdi.obj | Bin 0 -> 239203 bytes wx28X/build/msw/vc_mswdll/core/docview.obj | Bin 0 -> 534151 bytes wx28X/build/msw/vc_mswdll/core/dpycmn.obj | Bin 0 -> 79670 bytes wx28X/build/msw/vc_mswdll/core/dragimag.obj | Bin 0 -> 505107 bytes wx28X/build/msw/vc_mswdll/core/dragimgg.obj | Bin 0 -> 541059 bytes wx28X/build/msw/vc_mswdll/core/dropsrc.obj | Bin 0 -> 68928 bytes wx28X/build/msw/vc_mswdll/core/droptgt.obj | Bin 0 -> 80791 bytes wx28X/build/msw/vc_mswdll/core/dseldlg.obj | Bin 0 -> 65998 bytes wx28X/build/msw/vc_mswdll/core/dummy.obj | Bin 0 -> 3698815 bytes wx28X/build/msw/vc_mswdll/core/effects.obj | Bin 0 -> 144838 bytes wx28X/build/msw/vc_mswdll/core/enhmeta.obj | Bin 0 -> 199828 bytes wx28X/build/msw/vc_mswdll/core/event.obj | Bin 0 -> 522940 bytes wx28X/build/msw/vc_mswdll/core/evtloop.obj | Bin 0 -> 50647 bytes wx28X/build/msw/vc_mswdll/core/evtloopcmn.obj | Bin 0 -> 28621 bytes wx28X/build/msw/vc_mswdll/core/fddlgcmn.obj | Bin 0 -> 148614 bytes wx28X/build/msw/vc_mswdll/core/fdrepdlg.obj | Bin 0 -> 170652 bytes wx28X/build/msw/vc_mswdll/core/filedlg.obj | Bin 0 -> 139751 bytes .../msw/vc_mswdll/core/filepickercmn.obj | Bin 0 -> 256514 bytes .../build/msw/vc_mswdll/core/filepickerg.obj | Bin 0 -> 235521 bytes wx28X/build/msw/vc_mswdll/core/fldlgcmn.obj | Bin 0 -> 136140 bytes wx28X/build/msw/vc_mswdll/core/font.obj | Bin 0 -> 144702 bytes wx28X/build/msw/vc_mswdll/core/fontcmn.obj | Bin 0 -> 98855 bytes wx28X/build/msw/vc_mswdll/core/fontdlg.obj | Bin 0 -> 118068 bytes wx28X/build/msw/vc_mswdll/core/fontenum.obj | Bin 0 -> 36625 bytes .../build/msw/vc_mswdll/core/fontenumcmn.obj | Bin 0 -> 28855 bytes wx28X/build/msw/vc_mswdll/core/fontmap.obj | Bin 0 -> 202680 bytes .../msw/vc_mswdll/core/fontpickercmn.obj | Bin 0 -> 216983 bytes .../build/msw/vc_mswdll/core/fontpickerg.obj | Bin 0 -> 263054 bytes wx28X/build/msw/vc_mswdll/core/fontutil.obj | Bin 0 -> 41770 bytes wx28X/build/msw/vc_mswdll/core/frame.obj | Bin 0 -> 163972 bytes wx28X/build/msw/vc_mswdll/core/framecmn.obj | Bin 0 -> 165844 bytes wx28X/build/msw/vc_mswdll/core/fs_mem.obj | Bin 0 -> 32658 bytes wx28X/build/msw/vc_mswdll/core/gauge95.obj | Bin 0 -> 91910 bytes wx28X/build/msw/vc_mswdll/core/gaugecmn.obj | Bin 0 -> 58051 bytes wx28X/build/msw/vc_mswdll/core/gbsizer.obj | Bin 0 -> 103787 bytes wx28X/build/msw/vc_mswdll/core/gdicmn.obj | Bin 0 -> 217710 bytes wx28X/build/msw/vc_mswdll/core/gdiimage.obj | Bin 0 -> 180116 bytes wx28X/build/msw/vc_mswdll/core/gdiobj.obj | Bin 0 -> 2460 bytes wx28X/build/msw/vc_mswdll/core/geometry.obj | Bin 0 -> 108851 bytes wx28X/build/msw/vc_mswdll/core/gifdecod.obj | Bin 0 -> 77374 bytes wx28X/build/msw/vc_mswdll/core/graphcmn.obj | Bin 0 -> 2348 bytes wx28X/build/msw/vc_mswdll/core/graphics.obj | Bin 0 -> 2516 bytes wx28X/build/msw/vc_mswdll/core/gsockmsw.obj | Bin 0 -> 15205 bytes wx28X/build/msw/vc_mswdll/core/helpbase.obj | Bin 0 -> 19722 bytes wx28X/build/msw/vc_mswdll/core/helpchm.obj | Bin 0 -> 68504 bytes wx28X/build/msw/vc_mswdll/core/helpwin.obj | Bin 0 -> 54684 bytes wx28X/build/msw/vc_mswdll/core/icon.obj | Bin 0 -> 53132 bytes wx28X/build/msw/vc_mswdll/core/iconbndl.obj | Bin 0 -> 67492 bytes wx28X/build/msw/vc_mswdll/core/imagall.obj | Bin 0 -> 106347 bytes wx28X/build/msw/vc_mswdll/core/imagbmp.obj | Bin 0 -> 194511 bytes wx28X/build/msw/vc_mswdll/core/image.obj | Bin 0 -> 295262 bytes wx28X/build/msw/vc_mswdll/core/imagfill.obj | Bin 0 -> 2348 bytes wx28X/build/msw/vc_mswdll/core/imaggif.obj | Bin 0 -> 69381 bytes wx28X/build/msw/vc_mswdll/core/imagiff.obj | Bin 0 -> 2344 bytes wx28X/build/msw/vc_mswdll/core/imagjpeg.obj | Bin 0 -> 48780 bytes wx28X/build/msw/vc_mswdll/core/imaglist.obj | Bin 0 -> 162461 bytes wx28X/build/msw/vc_mswdll/core/imagpcx.obj | Bin 0 -> 67059 bytes wx28X/build/msw/vc_mswdll/core/imagpng.obj | Bin 0 -> 73330 bytes wx28X/build/msw/vc_mswdll/core/imagpnm.obj | Bin 0 -> 39262 bytes wx28X/build/msw/vc_mswdll/core/imagtga.obj | Bin 0 -> 47534 bytes wx28X/build/msw/vc_mswdll/core/imagtiff.obj | Bin 0 -> 54869 bytes wx28X/build/msw/vc_mswdll/core/imagxpm.obj | Bin 0 -> 67194 bytes wx28X/build/msw/vc_mswdll/core/iniconf.obj | Bin 0 -> 64716 bytes wx28X/build/msw/vc_mswdll/core/layout.obj | Bin 0 -> 50349 bytes wx28X/build/msw/vc_mswdll/core/lboxcmn.obj | Bin 0 -> 73265 bytes .../vc_mswdll/core/link-cvtres.read.1.tlog | 1 + .../vc_mswdll/core/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswdll/core/link.command.1.tlog | Bin 0 -> 119416 bytes .../build/msw/vc_mswdll/core/link.read.1.tlog | Bin 0 -> 157072 bytes .../msw/vc_mswdll/core/link.write.1.tlog | Bin 0 -> 73702 bytes wx28X/build/msw/vc_mswdll/core/listbkg.obj | Bin 0 -> 490271 bytes wx28X/build/msw/vc_mswdll/core/listbox.obj | Bin 0 -> 272929 bytes wx28X/build/msw/vc_mswdll/core/listctrl.obj | Bin 0 -> 441824 bytes .../build/msw/vc_mswdll/core/listctrlcmn.obj | Bin 0 -> 226238 bytes wx28X/build/msw/vc_mswdll/core/logg.obj | Bin 0 -> 553135 bytes wx28X/build/msw/vc_mswdll/core/main.obj | Bin 0 -> 16177 bytes wx28X/build/msw/vc_mswdll/core/matrix.obj | Bin 0 -> 42570 bytes wx28X/build/msw/vc_mswdll/core/mdi.obj | Bin 0 -> 256756 bytes wx28X/build/msw/vc_mswdll/core/menu.obj | Bin 0 -> 207956 bytes wx28X/build/msw/vc_mswdll/core/menucmn.obj | Bin 0 -> 244577 bytes wx28X/build/msw/vc_mswdll/core/menuitem.obj | Bin 0 -> 54771 bytes wx28X/build/msw/vc_mswdll/core/metafile.obj | Bin 0 -> 69095 bytes wx28X/build/msw/vc_mswdll/core/minifram.obj | Bin 0 -> 73901 bytes wx28X/build/msw/vc_mswdll/core/msgdlg.obj | Bin 0 -> 95024 bytes wx28X/build/msw/vc_mswdll/core/msgout.obj | Bin 0 -> 19840 bytes wx28X/build/msw/vc_mswdll/core/mslu.obj | Bin 0 -> 2332 bytes .../msw/vc_mswdll/core/mt.command.1.tlog | Bin 0 -> 1288 bytes wx28X/build/msw/vc_mswdll/core/mt.read.1.tlog | Bin 0 -> 1848 bytes .../build/msw/vc_mswdll/core/mt.write.1.tlog | Bin 0 -> 768 bytes wx28X/build/msw/vc_mswdll/core/nativdlg.obj | Bin 0 -> 391947 bytes wx28X/build/msw/vc_mswdll/core/nbkbase.obj | Bin 0 -> 293502 bytes wx28X/build/msw/vc_mswdll/core/notebook.obj | Bin 0 -> 509860 bytes wx28X/build/msw/vc_mswdll/core/numdlgg.obj | Bin 0 -> 257989 bytes wx28X/build/msw/vc_mswdll/core/oleutils.obj | Bin 0 -> 17860 bytes wx28X/build/msw/vc_mswdll/core/overlaycmn.obj | Bin 0 -> 127356 bytes wx28X/build/msw/vc_mswdll/core/ownerdrw.obj | Bin 0 -> 171086 bytes wx28X/build/msw/vc_mswdll/core/palette.obj | Bin 0 -> 35695 bytes wx28X/build/msw/vc_mswdll/core/panelg.obj | Bin 0 -> 82183 bytes wx28X/build/msw/vc_mswdll/core/paper.obj | Bin 0 -> 232349 bytes wx28X/build/msw/vc_mswdll/core/pen.obj | Bin 0 -> 71558 bytes wx28X/build/msw/vc_mswdll/core/pickerbase.obj | Bin 0 -> 174618 bytes wx28X/build/msw/vc_mswdll/core/popupcmn.obj | Bin 0 -> 164124 bytes wx28X/build/msw/vc_mswdll/core/popupwin.obj | Bin 0 -> 79372 bytes wx28X/build/msw/vc_mswdll/core/printdlg.obj | Bin 0 -> 262255 bytes wx28X/build/msw/vc_mswdll/core/printps.obj | Bin 0 -> 2348 bytes wx28X/build/msw/vc_mswdll/core/printwin.obj | Bin 0 -> 188500 bytes wx28X/build/msw/vc_mswdll/core/prntbase.obj | Bin 0 -> 686635 bytes wx28X/build/msw/vc_mswdll/core/prntdlgg.obj | Bin 0 -> 566349 bytes wx28X/build/msw/vc_mswdll/core/progdlgg.obj | Bin 0 -> 215442 bytes wx28X/build/msw/vc_mswdll/core/quantize.obj | Bin 0 -> 46577 bytes wx28X/build/msw/vc_mswdll/core/radiobox.obj | Bin 0 -> 200745 bytes wx28X/build/msw/vc_mswdll/core/radiobut.obj | Bin 0 -> 100297 bytes wx28X/build/msw/vc_mswdll/core/radiocmn.obj | Bin 0 -> 153756 bytes .../msw/vc_mswdll/core/rc.command.1.tlog | Bin 0 -> 4734 bytes wx28X/build/msw/vc_mswdll/core/rc.read.1.tlog | Bin 0 -> 644 bytes .../build/msw/vc_mswdll/core/rc.write.1.tlog | Bin 0 -> 540 bytes wx28X/build/msw/vc_mswdll/core/region.obj | Bin 0 -> 79667 bytes wx28X/build/msw/vc_mswdll/core/rendcmn.obj | Bin 0 -> 106179 bytes wx28X/build/msw/vc_mswdll/core/renderer.obj | Bin 0 -> 248617 bytes wx28X/build/msw/vc_mswdll/core/renderg.obj | Bin 0 -> 357242 bytes wx28X/build/msw/vc_mswdll/core/rgncmn.obj | Bin 0 -> 123346 bytes wx28X/build/msw/vc_mswdll/core/scrlwing.obj | Bin 0 -> 177882 bytes wx28X/build/msw/vc_mswdll/core/scrolbar.obj | Bin 0 -> 104297 bytes wx28X/build/msw/vc_mswdll/core/selstore.obj | Bin 0 -> 25319 bytes wx28X/build/msw/vc_mswdll/core/settcmn.obj | Bin 0 -> 4504 bytes wx28X/build/msw/vc_mswdll/core/settings.obj | Bin 0 -> 59059 bytes wx28X/build/msw/vc_mswdll/core/sizer.obj | Bin 0 -> 317832 bytes wx28X/build/msw/vc_mswdll/core/slider95.obj | Bin 0 -> 149712 bytes wx28X/build/msw/vc_mswdll/core/spinbutt.obj | Bin 0 -> 130690 bytes wx28X/build/msw/vc_mswdll/core/spinctlg.obj | Bin 0 -> 2352 bytes wx28X/build/msw/vc_mswdll/core/spinctrl.obj | Bin 0 -> 217977 bytes wx28X/build/msw/vc_mswdll/core/splitter.obj | Bin 0 -> 258190 bytes wx28X/build/msw/vc_mswdll/core/srchcmn.obj | Bin 0 -> 116909 bytes wx28X/build/msw/vc_mswdll/core/srchctlg.obj | Bin 0 -> 408086 bytes wx28X/build/msw/vc_mswdll/core/statbar.obj | Bin 0 -> 102776 bytes wx28X/build/msw/vc_mswdll/core/statbmp.obj | Bin 0 -> 146318 bytes wx28X/build/msw/vc_mswdll/core/statbox.obj | Bin 0 -> 446422 bytes wx28X/build/msw/vc_mswdll/core/statbr95.obj | Bin 0 -> 95692 bytes wx28X/build/msw/vc_mswdll/core/statline.obj | Bin 0 -> 92971 bytes wx28X/build/msw/vc_mswdll/core/stattext.obj | Bin 0 -> 97732 bytes wx28X/build/msw/vc_mswdll/core/statusbr.obj | Bin 0 -> 109711 bytes wx28X/build/msw/vc_mswdll/core/stockitem.obj | Bin 0 -> 36280 bytes wx28X/build/msw/vc_mswdll/core/tabctrl.obj | Bin 0 -> 2340 bytes wx28X/build/msw/vc_mswdll/core/tbar95.obj | Bin 0 -> 336110 bytes wx28X/build/msw/vc_mswdll/core/tbarbase.obj | Bin 0 -> 237561 bytes wx28X/build/msw/vc_mswdll/core/textcmn.obj | Bin 0 -> 125513 bytes wx28X/build/msw/vc_mswdll/core/textctrl.obj | Bin 0 -> 391490 bytes wx28X/build/msw/vc_mswdll/core/textdlgg.obj | Bin 0 -> 237812 bytes wx28X/build/msw/vc_mswdll/core/tglbtn.obj | Bin 0 -> 92522 bytes wx28X/build/msw/vc_mswdll/core/timer.obj | Bin 0 -> 55405 bytes wx28X/build/msw/vc_mswdll/core/timercmn.obj | Bin 0 -> 20939 bytes wx28X/build/msw/vc_mswdll/core/tipwin.obj | Bin 0 -> 126709 bytes wx28X/build/msw/vc_mswdll/core/toolbkg.obj | Bin 0 -> 382239 bytes wx28X/build/msw/vc_mswdll/core/tooltip.obj | Bin 0 -> 36250 bytes wx28X/build/msw/vc_mswdll/core/toplevel.obj | Bin 0 -> 184804 bytes wx28X/build/msw/vc_mswdll/core/toplvcmn.obj | Bin 0 -> 157970 bytes wx28X/build/msw/vc_mswdll/core/treebase.obj | Bin 0 -> 321789 bytes wx28X/build/msw/vc_mswdll/core/treebkg.obj | Bin 0 -> 564680 bytes wx28X/build/msw/vc_mswdll/core/treectlg.obj | Bin 0 -> 708770 bytes wx28X/build/msw/vc_mswdll/core/treectrl.obj | Bin 0 -> 588521 bytes wx28X/build/msw/vc_mswdll/core/utilscmn.obj | Bin 0 -> 447357 bytes wx28X/build/msw/vc_mswdll/core/utilsgui.obj | Bin 0 -> 34918 bytes wx28X/build/msw/vc_mswdll/core/uuid.obj | Bin 0 -> 13934 bytes wx28X/build/msw/vc_mswdll/core/uxtheme.obj | Bin 0 -> 50386 bytes wx28X/build/msw/vc_mswdll/core/valgen.obj | Bin 0 -> 185945 bytes wx28X/build/msw/vc_mswdll/core/validate.obj | Bin 0 -> 16730 bytes wx28X/build/msw/vc_mswdll/core/valtext.obj | Bin 0 -> 49400 bytes wx28X/build/msw/vc_mswdll/core/version.res | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/core/vlbox.obj | Bin 0 -> 300702 bytes wx28X/build/msw/vc_mswdll/core/volume.obj | Bin 0 -> 53061 bytes wx28X/build/msw/vc_mswdll/core/vscroll.obj | Bin 0 -> 104395 bytes wx28X/build/msw/vc_mswdll/core/wincmn.obj | Bin 0 -> 563476 bytes wx28X/build/msw/vc_mswdll/core/window.obj | Bin 0 -> 1120019 bytes wx28X/build/msw/vc_mswdll/core/wx_core.log | 24 + wx28X/build/msw/vc_mswdll/core/xpmdecod.obj | Bin 0 -> 99836 bytes .../build/msw/vc_mswdll/dbgrid/CL.read.1.tlog | Bin 0 -> 113458 bytes .../msw/vc_mswdll/dbgrid/CL.write.1.tlog | Bin 0 -> 2134 bytes .../dbgrid/ResolveAssemblyReference.cache | Bin 0 -> 1420 bytes .../msw/vc_mswdll/dbgrid/cl.command.1.tlog | Bin 0 -> 7474 bytes .../dbgrid/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../vc_mswdll/dbgrid/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../vc_mswdll/dbgrid/custombuild.write.1.tlog | Bin 0 -> 1048 bytes .../dbgrid/dbgrid.dll.intermediate.manifest | 15 + .../vc_mswdll/dbgrid/dbgrid.lastbuildstate | 2 + wx28X/build/msw/vc_mswdll/dbgrid/dbgrid.obj | Bin 0 -> 128442 bytes .../msw/vc_mswdll/dbgrid/dbgrid.write.1.tlog | 9 + wx28X/build/msw/vc_mswdll/dbgrid/dummy.obj | Bin 0 -> 420262 bytes .../vc_mswdll/dbgrid/link-cvtres.read.1.tlog | 1 + .../vc_mswdll/dbgrid/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswdll/dbgrid/link.command.1.tlog | Bin 0 -> 9128 bytes .../msw/vc_mswdll/dbgrid/link.read.1.tlog | Bin 0 -> 15132 bytes .../msw/vc_mswdll/dbgrid/link.write.1.tlog | Bin 0 -> 3180 bytes .../msw/vc_mswdll/dbgrid/mt.command.1.tlog | Bin 0 -> 1348 bytes .../build/msw/vc_mswdll/dbgrid/mt.read.1.tlog | Bin 0 -> 1884 bytes .../msw/vc_mswdll/dbgrid/mt.write.1.tlog | Bin 0 -> 804 bytes .../msw/vc_mswdll/dbgrid/rc.command.1.tlog | Bin 0 -> 4614 bytes .../build/msw/vc_mswdll/dbgrid/rc.read.1.tlog | Bin 0 -> 644 bytes .../msw/vc_mswdll/dbgrid/rc.write.1.tlog | Bin 0 -> 552 bytes wx28X/build/msw/vc_mswdll/dbgrid/version.res | Bin 0 -> 1052 bytes .../build/msw/vc_mswdll/dbgrid/wx_dbgrid.log | 41 + wx28X/build/msw/vc_mswdll/gl/CL.read.1.tlog | Bin 0 -> 110280 bytes wx28X/build/msw/vc_mswdll/gl/CL.write.1.tlog | Bin 0 -> 2020 bytes .../build/msw/vc_mswdll/gl/cl.command.1.tlog | Bin 0 -> 7270 bytes .../vc_mswdll/gl/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../msw/vc_mswdll/gl/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../msw/vc_mswdll/gl/custombuild.write.1.tlog | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/gl/dummy.obj | Bin 0 -> 420230 bytes .../vc_mswdll/gl/gl.dll.intermediate.manifest | 15 + .../build/msw/vc_mswdll/gl/gl.lastbuildstate | 2 + wx28X/build/msw/vc_mswdll/gl/gl.write.1.tlog | 0 wx28X/build/msw/vc_mswdll/gl/glcanvas.obj | Bin 0 -> 2233 bytes .../msw/vc_mswdll/gl/link-cvtres.read.1.tlog | 1 + .../msw/vc_mswdll/gl/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswdll/gl/link.command.1.tlog | Bin 0 -> 8820 bytes wx28X/build/msw/vc_mswdll/gl/link.read.1.tlog | Bin 0 -> 14732 bytes .../build/msw/vc_mswdll/gl/link.write.1.tlog | Bin 0 -> 3248 bytes .../build/msw/vc_mswdll/gl/mt.command.1.tlog | Bin 0 -> 1228 bytes wx28X/build/msw/vc_mswdll/gl/mt.read.1.tlog | Bin 0 -> 1812 bytes wx28X/build/msw/vc_mswdll/gl/mt.write.1.tlog | Bin 0 -> 732 bytes .../build/msw/vc_mswdll/gl/rc.command.1.tlog | Bin 0 -> 4470 bytes wx28X/build/msw/vc_mswdll/gl/rc.read.1.tlog | Bin 0 -> 644 bytes wx28X/build/msw/vc_mswdll/gl/rc.write.1.tlog | Bin 0 -> 528 bytes wx28X/build/msw/vc_mswdll/gl/version.res | Bin 0 -> 1044 bytes wx28X/build/msw/vc_mswdll/gl/wx_gl.log | 41 + wx28X/build/msw/vc_mswdll/html/CL.read.1.tlog | Bin 0 -> 359912 bytes .../build/msw/vc_mswdll/html/CL.write.1.tlog | Bin 0 -> 27634 bytes .../msw/vc_mswdll/html/cl.command.1.tlog | Bin 0 -> 92172 bytes .../vc_mswdll/html/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../vc_mswdll/html/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../vc_mswdll/html/custombuild.write.1.tlog | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/html/dummy.obj | Bin 0 -> 420250 bytes wx28X/build/msw/vc_mswdll/html/helpbest.obj | Bin 0 -> 396158 bytes wx28X/build/msw/vc_mswdll/html/helpctrl.obj | Bin 0 -> 446099 bytes wx28X/build/msw/vc_mswdll/html/helpdata.obj | Bin 0 -> 261042 bytes wx28X/build/msw/vc_mswdll/html/helpdlg.obj | Bin 0 -> 414676 bytes wx28X/build/msw/vc_mswdll/html/helpfrm.obj | Bin 0 -> 392500 bytes wx28X/build/msw/vc_mswdll/html/helpwnd.obj | Bin 0 -> 840052 bytes .../html/html.dll.intermediate.manifest | 15 + .../msw/vc_mswdll/html/html.lastbuildstate | 2 + .../msw/vc_mswdll/html/html.write.1.tlog | 9 + wx28X/build/msw/vc_mswdll/html/htmlcell.obj | Bin 0 -> 362328 bytes wx28X/build/msw/vc_mswdll/html/htmlfilt.obj | Bin 0 -> 296617 bytes wx28X/build/msw/vc_mswdll/html/htmllbox.obj | Bin 0 -> 392725 bytes wx28X/build/msw/vc_mswdll/html/htmlpars.obj | Bin 0 -> 176335 bytes wx28X/build/msw/vc_mswdll/html/htmltag.obj | Bin 0 -> 65304 bytes wx28X/build/msw/vc_mswdll/html/htmlwin.obj | Bin 0 -> 531752 bytes wx28X/build/msw/vc_mswdll/html/htmprint.obj | Bin 0 -> 501505 bytes .../vc_mswdll/html/link-cvtres.read.1.tlog | 1 + .../vc_mswdll/html/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswdll/html/link.command.1.tlog | Bin 0 -> 20464 bytes .../build/msw/vc_mswdll/html/link.read.1.tlog | Bin 0 -> 29406 bytes .../msw/vc_mswdll/html/link.write.1.tlog | Bin 0 -> 10584 bytes wx28X/build/msw/vc_mswdll/html/m_dflist.obj | Bin 0 -> 169912 bytes wx28X/build/msw/vc_mswdll/html/m_fonts.obj | Bin 0 -> 236791 bytes wx28X/build/msw/vc_mswdll/html/m_hline.obj | Bin 0 -> 176835 bytes wx28X/build/msw/vc_mswdll/html/m_image.obj | Bin 0 -> 357835 bytes wx28X/build/msw/vc_mswdll/html/m_layout.obj | Bin 0 -> 325821 bytes wx28X/build/msw/vc_mswdll/html/m_links.obj | Bin 0 -> 188688 bytes wx28X/build/msw/vc_mswdll/html/m_list.obj | Bin 0 -> 196383 bytes wx28X/build/msw/vc_mswdll/html/m_pre.obj | Bin 0 -> 174432 bytes wx28X/build/msw/vc_mswdll/html/m_style.obj | Bin 0 -> 166241 bytes wx28X/build/msw/vc_mswdll/html/m_tables.obj | Bin 0 -> 222583 bytes .../msw/vc_mswdll/html/mt.command.1.tlog | Bin 0 -> 1288 bytes wx28X/build/msw/vc_mswdll/html/mt.read.1.tlog | Bin 0 -> 1848 bytes .../build/msw/vc_mswdll/html/mt.write.1.tlog | Bin 0 -> 768 bytes .../msw/vc_mswdll/html/rc.command.1.tlog | Bin 0 -> 4542 bytes wx28X/build/msw/vc_mswdll/html/rc.read.1.tlog | Bin 0 -> 644 bytes .../build/msw/vc_mswdll/html/rc.write.1.tlog | Bin 0 -> 540 bytes wx28X/build/msw/vc_mswdll/html/version.res | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/html/winpars.obj | Bin 0 -> 352426 bytes wx28X/build/msw/vc_mswdll/html/wx_html.log | 91 + .../build/msw/vc_mswdll/media/CL.read.1.tlog | Bin 0 -> 133854 bytes .../build/msw/vc_mswdll/media/CL.write.1.tlog | Bin 0 -> 7196 bytes wx28X/build/msw/vc_mswdll/media/activex.obj | Bin 0 -> 213402 bytes .../msw/vc_mswdll/media/cl.command.1.tlog | Bin 0 -> 22538 bytes .../media/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../vc_mswdll/media/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../vc_mswdll/media/custombuild.write.1.tlog | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/media/dummy.obj | Bin 0 -> 420258 bytes .../vc_mswdll/media/link-cvtres.read.1.tlog | 1 + .../vc_mswdll/media/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswdll/media/link.command.1.tlog | Bin 0 -> 11372 bytes .../msw/vc_mswdll/media/link.read.1.tlog | Bin 0 -> 17630 bytes .../msw/vc_mswdll/media/link.write.1.tlog | Bin 0 -> 4768 bytes .../media/media.dll.intermediate.manifest | 15 + .../msw/vc_mswdll/media/media.lastbuildstate | 2 + .../msw/vc_mswdll/media/media.write.1.tlog | 9 + .../msw/vc_mswdll/media/mediactrl_am.obj | Bin 0 -> 119521 bytes .../msw/vc_mswdll/media/mediactrl_qt.obj | Bin 0 -> 205079 bytes .../msw/vc_mswdll/media/mediactrl_wmp10.obj | Bin 0 -> 128014 bytes .../msw/vc_mswdll/media/mediactrlcmn.obj | Bin 0 -> 111927 bytes .../msw/vc_mswdll/media/mt.command.1.tlog | Bin 0 -> 1318 bytes .../build/msw/vc_mswdll/media/mt.read.1.tlog | Bin 0 -> 1866 bytes .../build/msw/vc_mswdll/media/mt.write.1.tlog | Bin 0 -> 786 bytes .../msw/vc_mswdll/media/rc.command.1.tlog | Bin 0 -> 4578 bytes .../build/msw/vc_mswdll/media/rc.read.1.tlog | Bin 0 -> 644 bytes .../build/msw/vc_mswdll/media/rc.write.1.tlog | Bin 0 -> 546 bytes wx28X/build/msw/vc_mswdll/media/version.res | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/media/wx_media.log | 51 + wx28X/build/msw/vc_mswdll/net/CL.read.1.tlog | Bin 0 -> 129544 bytes wx28X/build/msw/vc_mswdll/net/CL.write.1.tlog | Bin 0 -> 14236 bytes .../build/msw/vc_mswdll/net/cl.command.1.tlog | Bin 0 -> 48864 bytes .../vc_mswdll/net/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../msw/vc_mswdll/net/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../vc_mswdll/net/custombuild.write.1.tlog | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/net/dummy.obj | Bin 0 -> 380478 bytes wx28X/build/msw/vc_mswdll/net/fs_inet.obj | Bin 0 -> 174183 bytes wx28X/build/msw/vc_mswdll/net/ftp.obj | Bin 0 -> 230605 bytes wx28X/build/msw/vc_mswdll/net/gsocket.obj | Bin 0 -> 60598 bytes wx28X/build/msw/vc_mswdll/net/http.obj | Bin 0 -> 202593 bytes .../msw/vc_mswdll/net/link-cvtres.read.1.tlog | 1 + .../vc_mswdll/net/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswdll/net/link.command.1.tlog | Bin 0 -> 12310 bytes .../build/msw/vc_mswdll/net/link.read.1.tlog | Bin 0 -> 19738 bytes .../build/msw/vc_mswdll/net/link.write.1.tlog | Bin 0 -> 5904 bytes .../build/msw/vc_mswdll/net/mt.command.1.tlog | Bin 0 -> 1264 bytes wx28X/build/msw/vc_mswdll/net/mt.read.1.tlog | Bin 0 -> 1836 bytes wx28X/build/msw/vc_mswdll/net/mt.write.1.tlog | Bin 0 -> 756 bytes .../net/net.dll.intermediate.manifest | 15 + .../msw/vc_mswdll/net/net.lastbuildstate | 2 + .../build/msw/vc_mswdll/net/net.write.1.tlog | 9 + wx28X/build/msw/vc_mswdll/net/protocol.obj | Bin 0 -> 148704 bytes .../build/msw/vc_mswdll/net/rc.command.1.tlog | Bin 0 -> 4698 bytes wx28X/build/msw/vc_mswdll/net/rc.read.1.tlog | Bin 0 -> 644 bytes wx28X/build/msw/vc_mswdll/net/rc.write.1.tlog | Bin 0 -> 534 bytes wx28X/build/msw/vc_mswdll/net/sckaddr.obj | Bin 0 -> 71496 bytes wx28X/build/msw/vc_mswdll/net/sckfile.obj | Bin 0 -> 55410 bytes wx28X/build/msw/vc_mswdll/net/sckipc.obj | Bin 0 -> 117993 bytes wx28X/build/msw/vc_mswdll/net/sckstrm.obj | Bin 0 -> 48519 bytes wx28X/build/msw/vc_mswdll/net/socket.obj | Bin 0 -> 125381 bytes wx28X/build/msw/vc_mswdll/net/url.obj | Bin 0 -> 174035 bytes wx28X/build/msw/vc_mswdll/net/urlmsw.obj | Bin 0 -> 2253 bytes wx28X/build/msw/vc_mswdll/net/version.res | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/net/wx_net.log | 62 + wx28X/build/msw/vc_mswdll/odbc/CL.read.1.tlog | Bin 0 -> 85938 bytes .../build/msw/vc_mswdll/odbc/CL.write.1.tlog | Bin 0 -> 3374 bytes .../msw/vc_mswdll/odbc/cl.command.1.tlog | Bin 0 -> 11324 bytes .../vc_mswdll/odbc/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../vc_mswdll/odbc/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../vc_mswdll/odbc/custombuild.write.1.tlog | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/odbc/db.obj | Bin 0 -> 262124 bytes wx28X/build/msw/vc_mswdll/odbc/dbtable.obj | Bin 0 -> 242212 bytes wx28X/build/msw/vc_mswdll/odbc/dummy.obj | Bin 0 -> 380482 bytes .../vc_mswdll/odbc/link-cvtres.read.1.tlog | 1 + .../vc_mswdll/odbc/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswdll/odbc/link.command.1.tlog | Bin 0 -> 7664 bytes .../build/msw/vc_mswdll/odbc/link.read.1.tlog | Bin 0 -> 13668 bytes .../msw/vc_mswdll/odbc/link.write.1.tlog | Bin 0 -> 2914 bytes .../msw/vc_mswdll/odbc/mt.command.1.tlog | Bin 0 -> 1294 bytes wx28X/build/msw/vc_mswdll/odbc/mt.read.1.tlog | Bin 0 -> 1854 bytes .../build/msw/vc_mswdll/odbc/mt.write.1.tlog | Bin 0 -> 774 bytes .../odbc/odbc.dll.intermediate.manifest | 15 + .../msw/vc_mswdll/odbc/odbc.lastbuildstate | 2 + .../msw/vc_mswdll/odbc/odbc.write.1.tlog | 9 + .../msw/vc_mswdll/odbc/rc.command.1.tlog | Bin 0 -> 4734 bytes wx28X/build/msw/vc_mswdll/odbc/rc.read.1.tlog | Bin 0 -> 644 bytes .../build/msw/vc_mswdll/odbc/rc.write.1.tlog | Bin 0 -> 540 bytes wx28X/build/msw/vc_mswdll/odbc/version.res | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/odbc/wx_odbc.log | 42 + wx28X/build/msw/vc_mswdll/qa/CL.read.1.tlog | Bin 0 -> 120320 bytes wx28X/build/msw/vc_mswdll/qa/CL.write.1.tlog | Bin 0 -> 3392 bytes .../qa/ResolveAssemblyReference.cache | Bin 0 -> 1250 bytes .../build/msw/vc_mswdll/qa/cl.command.1.tlog | Bin 0 -> 10976 bytes .../vc_mswdll/qa/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../msw/vc_mswdll/qa/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../msw/vc_mswdll/qa/custombuild.write.1.tlog | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/qa/dbgrptg.obj | Bin 0 -> 234563 bytes wx28X/build/msw/vc_mswdll/qa/debugrpt.obj | Bin 0 -> 182913 bytes wx28X/build/msw/vc_mswdll/qa/dummy.obj | Bin 0 -> 420230 bytes .../msw/vc_mswdll/qa/link-cvtres.read.1.tlog | 1 + .../msw/vc_mswdll/qa/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswdll/qa/link.command.1.tlog | Bin 0 -> 10564 bytes wx28X/build/msw/vc_mswdll/qa/link.read.1.tlog | Bin 0 -> 16028 bytes .../build/msw/vc_mswdll/qa/link.write.1.tlog | Bin 0 -> 4046 bytes .../build/msw/vc_mswdll/qa/mt.command.1.tlog | Bin 0 -> 1228 bytes wx28X/build/msw/vc_mswdll/qa/mt.read.1.tlog | Bin 0 -> 1812 bytes wx28X/build/msw/vc_mswdll/qa/mt.write.1.tlog | Bin 0 -> 732 bytes .../vc_mswdll/qa/qa.dll.intermediate.manifest | 15 + .../build/msw/vc_mswdll/qa/qa.lastbuildstate | 2 + wx28X/build/msw/vc_mswdll/qa/qa.write.1.tlog | 9 + .../build/msw/vc_mswdll/qa/rc.command.1.tlog | Bin 0 -> 4470 bytes wx28X/build/msw/vc_mswdll/qa/rc.read.1.tlog | Bin 0 -> 644 bytes wx28X/build/msw/vc_mswdll/qa/rc.write.1.tlog | Bin 0 -> 528 bytes wx28X/build/msw/vc_mswdll/qa/version.res | Bin 0 -> 1044 bytes wx28X/build/msw/vc_mswdll/qa/wx_qa.log | 47 + .../msw/vc_mswdll/richtext/CL.read.1.tlog | Bin 0 -> 243184 bytes .../msw/vc_mswdll/richtext/CL.write.1.tlog | Bin 0 -> 13126 bytes .../richtext/ResolveAssemblyReference.cache | Bin 0 -> 1946 bytes .../msw/vc_mswdll/richtext/cl.command.1.tlog | Bin 0 -> 38970 bytes .../richtext/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../richtext/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../richtext/custombuild.write.1.tlog | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/richtext/dummy.obj | Bin 0 -> 420282 bytes .../richtext/link-cvtres.read.1.tlog | 1 + .../richtext/link-cvtres.write.1.tlog | 1 + .../vc_mswdll/richtext/link.command.1.tlog | Bin 0 -> 16008 bytes .../msw/vc_mswdll/richtext/link.read.1.tlog | Bin 0 -> 22414 bytes .../msw/vc_mswdll/richtext/link.write.1.tlog | Bin 0 -> 7054 bytes .../msw/vc_mswdll/richtext/mt.command.1.tlog | Bin 0 -> 1408 bytes .../msw/vc_mswdll/richtext/mt.read.1.tlog | Bin 0 -> 1920 bytes .../msw/vc_mswdll/richtext/mt.write.1.tlog | Bin 0 -> 840 bytes .../msw/vc_mswdll/richtext/rc.command.1.tlog | Bin 0 -> 4686 bytes .../msw/vc_mswdll/richtext/rc.read.1.tlog | Bin 0 -> 644 bytes .../msw/vc_mswdll/richtext/rc.write.1.tlog | Bin 0 -> 564 bytes .../richtext.dll.intermediate.manifest | 15 + .../richtext/richtext.lastbuildstate | 2 + .../vc_mswdll/richtext/richtext.write.1.tlog | 9 + .../msw/vc_mswdll/richtext/richtextbuffer.obj | Bin 0 -> 1608343 bytes .../msw/vc_mswdll/richtext/richtextctrl.obj | Bin 0 -> 1107466 bytes .../vc_mswdll/richtext/richtextformatdlg.obj | Bin 0 -> 1807981 bytes .../msw/vc_mswdll/richtext/richtexthtml.obj | Bin 0 -> 810797 bytes .../msw/vc_mswdll/richtext/richtextprint.obj | Bin 0 -> 697793 bytes .../vc_mswdll/richtext/richtextstyledlg.obj | Bin 0 -> 1015820 bytes .../msw/vc_mswdll/richtext/richtextstyles.obj | Bin 0 -> 976568 bytes .../vc_mswdll/richtext/richtextsymboldlg.obj | Bin 0 -> 820900 bytes .../msw/vc_mswdll/richtext/richtextxml.obj | Bin 0 -> 946073 bytes .../build/msw/vc_mswdll/richtext/version.res | Bin 0 -> 1056 bytes .../msw/vc_mswdll/richtext/wx_richtext.log | 61 + .../msw/vc_mswdll/wxexpat/CL.read.1.tlog | Bin 0 -> 64180 bytes .../msw/vc_mswdll/wxexpat/CL.write.1.tlog | Bin 0 -> 3188 bytes .../vc_mswdll/wxexpat/Lib-link.read.1.tlog | Bin 0 -> 2510 bytes .../vc_mswdll/wxexpat/Lib-link.write.1.tlog | Bin 0 -> 1246 bytes .../msw/vc_mswdll/wxexpat/cl.command.1.tlog | Bin 0 -> 6746 bytes .../msw/vc_mswdll/wxexpat/lib.command.1.tlog | Bin 0 -> 1868 bytes .../msw/vc_mswdll/wxexpat/wx_wxexpat.log | 17 + .../vc_mswdll/wxexpat/wxexpat.lastbuildstate | 2 + .../build/msw/vc_mswdll/wxexpat/xmlparse.obj | Bin 0 -> 164884 bytes wx28X/build/msw/vc_mswdll/wxexpat/xmlrole.obj | Bin 0 -> 57643 bytes wx28X/build/msw/vc_mswdll/wxexpat/xmltok.obj | Bin 0 -> 244550 bytes .../build/msw/vc_mswdll/wxjpeg/CL.read.1.tlog | Bin 0 -> 273380 bytes .../msw/vc_mswdll/wxjpeg/CL.write.1.tlog | Bin 0 -> 45784 bytes .../msw/vc_mswdll/wxjpeg/Lib-link.read.1.tlog | Bin 0 -> 31044 bytes .../vc_mswdll/wxjpeg/Lib-link.write.1.tlog | Bin 0 -> 15378 bytes .../msw/vc_mswdll/wxjpeg/cl.command.1.tlog | Bin 0 -> 95682 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jcapimin.obj | Bin 0 -> 12235 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jcapistd.obj | Bin 0 -> 7376 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jccoefct.obj | Bin 0 -> 13004 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jccolor.obj | Bin 0 -> 15210 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jcdctmgr.obj | Bin 0 -> 14355 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jchuff.obj | Bin 0 -> 22731 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jcinit.obj | Bin 0 -> 5524 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jcmainct.obj | Bin 0 -> 7205 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jcmarker.obj | Bin 0 -> 21275 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jcmaster.obj | Bin 0 -> 16384 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jcomapi.obj | Bin 0 -> 6641 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jcparam.obj | Bin 0 -> 20264 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jcphuff.obj | Bin 0 -> 21462 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jcprepct.obj | Bin 0 -> 11802 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jcsample.obj | Bin 0 -> 16551 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jctrans.obj | Bin 0 -> 13333 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdapimin.obj | Bin 0 -> 13744 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdapistd.obj | Bin 0 -> 10362 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdatadst.obj | Bin 0 -> 7042 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdatasrc.obj | Bin 0 -> 7620 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdcoefct.obj | Bin 0 -> 19748 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdcolor.obj | Bin 0 -> 13729 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jddctmgr.obj | Bin 0 -> 9002 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdhuff.obj | Bin 0 -> 16592 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdinput.obj | Bin 0 -> 12749 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdmainct.obj | Bin 0 -> 14461 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdmarker.obj | Bin 0 -> 36500 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdmaster.obj | Bin 0 -> 14599 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdmerge.obj | Bin 0 -> 12564 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdphuff.obj | Bin 0 -> 17861 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdpostct.obj | Bin 0 -> 10100 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdsample.obj | Bin 0 -> 15256 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jdtrans.obj | Bin 0 -> 6376 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jerror.obj | Bin 0 -> 33173 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jfdctflt.obj | Bin 0 -> 5511 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jfdctfst.obj | Bin 0 -> 6785 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jfdctint.obj | Bin 0 -> 5396 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jidctflt.obj | Bin 0 -> 8578 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jidctfst.obj | Bin 0 -> 7432 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jidctint.obj | Bin 0 -> 7944 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jidctred.obj | Bin 0 -> 9829 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jmemmgr.obj | Bin 0 -> 21648 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jmemnobs.obj | Bin 0 -> 7735 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jquant1.obj | Bin 0 -> 23936 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jquant2.obj | Bin 0 -> 29537 bytes wx28X/build/msw/vc_mswdll/wxjpeg/jutils.obj | Bin 0 -> 6813 bytes .../msw/vc_mswdll/wxjpeg/lib.command.1.tlog | Bin 0 -> 24376 bytes .../build/msw/vc_mswdll/wxjpeg/wx_wxjpeg.log | 17 + .../vc_mswdll/wxjpeg/wxjpeg.lastbuildstate | 2 + .../build/msw/vc_mswdll/wxpng/CL.read.1.tlog | Bin 0 -> 128794 bytes .../build/msw/vc_mswdll/wxpng/CL.write.1.tlog | Bin 0 -> 16368 bytes .../msw/vc_mswdll/wxpng/Lib-link.read.1.tlog | Bin 0 -> 11482 bytes .../msw/vc_mswdll/wxpng/Lib-link.write.1.tlog | Bin 0 -> 5678 bytes .../msw/vc_mswdll/wxpng/cl.command.1.tlog | Bin 0 -> 34240 bytes .../msw/vc_mswdll/wxpng/lib.command.1.tlog | Bin 0 -> 8868 bytes wx28X/build/msw/vc_mswdll/wxpng/png.obj | Bin 0 -> 27406 bytes wx28X/build/msw/vc_mswdll/wxpng/pngerror.obj | Bin 0 -> 14829 bytes wx28X/build/msw/vc_mswdll/wxpng/pnggccrd.obj | Bin 0 -> 3351 bytes wx28X/build/msw/vc_mswdll/wxpng/pngget.obj | Bin 0 -> 37290 bytes wx28X/build/msw/vc_mswdll/wxpng/pngmem.obj | Bin 0 -> 13306 bytes wx28X/build/msw/vc_mswdll/wxpng/pngpread.obj | Bin 0 -> 39246 bytes wx28X/build/msw/vc_mswdll/wxpng/pngread.obj | Bin 0 -> 37192 bytes wx28X/build/msw/vc_mswdll/wxpng/pngrio.obj | Bin 0 -> 7897 bytes wx28X/build/msw/vc_mswdll/wxpng/pngrtran.obj | Bin 0 -> 69211 bytes wx28X/build/msw/vc_mswdll/wxpng/pngrutil.obj | Bin 0 -> 86162 bytes wx28X/build/msw/vc_mswdll/wxpng/pngset.obj | Bin 0 -> 43698 bytes wx28X/build/msw/vc_mswdll/wxpng/pngtrans.obj | Bin 0 -> 17821 bytes wx28X/build/msw/vc_mswdll/wxpng/pngvcrd.obj | Bin 0 -> 3343 bytes wx28X/build/msw/vc_mswdll/wxpng/pngwio.obj | Bin 0 -> 9019 bytes wx28X/build/msw/vc_mswdll/wxpng/pngwrite.obj | Bin 0 -> 41478 bytes wx28X/build/msw/vc_mswdll/wxpng/pngwtran.obj | Bin 0 -> 13586 bytes wx28X/build/msw/vc_mswdll/wxpng/pngwutil.obj | Bin 0 -> 69543 bytes wx28X/build/msw/vc_mswdll/wxpng/wx_wxpng.log | 17 + .../msw/vc_mswdll/wxpng/wxpng.lastbuildstate | 2 + .../msw/vc_mswdll/wxpng/wxpng.write.1.tlog | 0 wx28X/build/msw/vc_mswdll/wxprec_advdll.pch | Bin 0 -> 22151168 bytes wx28X/build/msw/vc_mswdll/wxprec_auidll.pch | Bin 0 -> 22151168 bytes wx28X/build/msw/vc_mswdll/wxprec_basedll.pch | Bin 0 -> 16318464 bytes wx28X/build/msw/vc_mswdll/wxprec_coredll.pch | Bin 0 -> 23396352 bytes .../build/msw/vc_mswdll/wxprec_dbgriddll.pch | Bin 0 -> 22151168 bytes wx28X/build/msw/vc_mswdll/wxprec_gldll.pch | Bin 0 -> 22151168 bytes wx28X/build/msw/vc_mswdll/wxprec_htmldll.pch | Bin 0 -> 22151168 bytes wx28X/build/msw/vc_mswdll/wxprec_mediadll.pch | Bin 0 -> 22151168 bytes wx28X/build/msw/vc_mswdll/wxprec_netdll.pch | Bin 0 -> 16121856 bytes wx28X/build/msw/vc_mswdll/wxprec_odbcdll.pch | Bin 0 -> 16121856 bytes wx28X/build/msw/vc_mswdll/wxprec_qadll.pch | Bin 0 -> 22151168 bytes .../msw/vc_mswdll/wxprec_richtextdll.pch | Bin 0 -> 22151168 bytes wx28X/build/msw/vc_mswdll/wxprec_xmldll.pch | Bin 0 -> 16121856 bytes wx28X/build/msw/vc_mswdll/wxprec_xrcdll.pch | Bin 0 -> 22151168 bytes .../msw/vc_mswdll/wxregex/CL.read.1.tlog | Bin 0 -> 39528 bytes .../msw/vc_mswdll/wxregex/CL.write.1.tlog | Bin 0 -> 4072 bytes .../vc_mswdll/wxregex/Lib-link.read.1.tlog | Bin 0 -> 3192 bytes .../vc_mswdll/wxregex/Lib-link.write.1.tlog | Bin 0 -> 1584 bytes .../msw/vc_mswdll/wxregex/cl.command.1.tlog | Bin 0 -> 9102 bytes .../wxregex/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../vc_mswdll/wxregex/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../wxregex/custombuild.write.1.tlog | Bin 0 -> 1048 bytes .../msw/vc_mswdll/wxregex/lib.command.1.tlog | Bin 0 -> 2410 bytes wx28X/build/msw/vc_mswdll/wxregex/regcomp.obj | Bin 0 -> 215648 bytes .../build/msw/vc_mswdll/wxregex/regerror.obj | Bin 0 -> 13812 bytes wx28X/build/msw/vc_mswdll/wxregex/regexec.obj | Bin 0 -> 53612 bytes wx28X/build/msw/vc_mswdll/wxregex/regfree.obj | Bin 0 -> 5490 bytes .../msw/vc_mswdll/wxregex/wx_wxregex.log | 19 + .../vc_mswdll/wxregex/wxregex.lastbuildstate | 2 + .../build/msw/vc_mswdll/wxtiff/CL.read.1.tlog | Bin 0 -> 1338282 bytes .../msw/vc_mswdll/wxtiff/CL.write.1.tlog | Bin 0 -> 36108 bytes .../msw/vc_mswdll/wxtiff/Lib-link.read.1.tlog | Bin 0 -> 24586 bytes .../vc_mswdll/wxtiff/Lib-link.write.1.tlog | Bin 0 -> 12182 bytes .../msw/vc_mswdll/wxtiff/cl.command.1.tlog | Bin 0 -> 75958 bytes .../msw/vc_mswdll/wxtiff/lib.command.1.tlog | Bin 0 -> 19458 bytes wx28X/build/msw/vc_mswdll/wxtiff/tif_aux.obj | Bin 0 -> 26485 bytes .../build/msw/vc_mswdll/wxtiff/tif_close.obj | Bin 0 -> 19395 bytes .../build/msw/vc_mswdll/wxtiff/tif_codec.obj | Bin 0 -> 23089 bytes .../build/msw/vc_mswdll/wxtiff/tif_color.obj | Bin 0 -> 26703 bytes .../msw/vc_mswdll/wxtiff/tif_compress.obj | Bin 0 -> 31758 bytes wx28X/build/msw/vc_mswdll/wxtiff/tif_dir.obj | Bin 0 -> 67159 bytes .../msw/vc_mswdll/wxtiff/tif_dirinfo.obj | Bin 0 -> 44135 bytes .../msw/vc_mswdll/wxtiff/tif_dirread.obj | Bin 0 -> 66819 bytes .../msw/vc_mswdll/wxtiff/tif_dirwrite.obj | Bin 0 -> 55345 bytes .../msw/vc_mswdll/wxtiff/tif_dumpmode.obj | Bin 0 -> 21766 bytes .../build/msw/vc_mswdll/wxtiff/tif_error.obj | Bin 0 -> 17782 bytes .../msw/vc_mswdll/wxtiff/tif_extension.obj | Bin 0 -> 22196 bytes wx28X/build/msw/vc_mswdll/wxtiff/tif_fax3.obj | Bin 0 -> 82522 bytes .../build/msw/vc_mswdll/wxtiff/tif_fax3sm.obj | Bin 0 -> 101217 bytes .../build/msw/vc_mswdll/wxtiff/tif_flush.obj | Bin 0 -> 18997 bytes .../msw/vc_mswdll/wxtiff/tif_getimage.obj | Bin 0 -> 117874 bytes wx28X/build/msw/vc_mswdll/wxtiff/tif_jpeg.obj | Bin 0 -> 16549 bytes wx28X/build/msw/vc_mswdll/wxtiff/tif_luv.obj | Bin 0 -> 84419 bytes wx28X/build/msw/vc_mswdll/wxtiff/tif_lzw.obj | Bin 0 -> 31959 bytes wx28X/build/msw/vc_mswdll/wxtiff/tif_next.obj | Bin 0 -> 20508 bytes wx28X/build/msw/vc_mswdll/wxtiff/tif_open.obj | Bin 0 -> 30525 bytes .../msw/vc_mswdll/wxtiff/tif_packbits.obj | Bin 0 -> 24977 bytes .../msw/vc_mswdll/wxtiff/tif_pixarlog.obj | Bin 0 -> 16561 bytes .../msw/vc_mswdll/wxtiff/tif_predict.obj | Bin 0 -> 38525 bytes .../build/msw/vc_mswdll/wxtiff/tif_print.obj | Bin 0 -> 52793 bytes wx28X/build/msw/vc_mswdll/wxtiff/tif_read.obj | Bin 0 -> 41448 bytes .../build/msw/vc_mswdll/wxtiff/tif_strip.obj | Bin 0 -> 27031 bytes wx28X/build/msw/vc_mswdll/wxtiff/tif_swab.obj | Bin 0 -> 22303 bytes .../msw/vc_mswdll/wxtiff/tif_thunder.obj | Bin 0 -> 22414 bytes wx28X/build/msw/vc_mswdll/wxtiff/tif_tile.obj | Bin 0 -> 27450 bytes .../msw/vc_mswdll/wxtiff/tif_version.obj | Bin 0 -> 17314 bytes .../msw/vc_mswdll/wxtiff/tif_warning.obj | Bin 0 -> 17796 bytes .../build/msw/vc_mswdll/wxtiff/tif_win32.obj | Bin 0 -> 33949 bytes .../build/msw/vc_mswdll/wxtiff/tif_write.obj | Bin 0 -> 38168 bytes wx28X/build/msw/vc_mswdll/wxtiff/tif_zip.obj | Bin 0 -> 16549 bytes .../build/msw/vc_mswdll/wxtiff/wx_wxtiff.log | 17 + .../vc_mswdll/wxtiff/wxtiff.lastbuildstate | 2 + .../build/msw/vc_mswdll/wxzlib/CL.read.1.tlog | Bin 0 -> 47716 bytes .../msw/vc_mswdll/wxzlib/CL.write.1.tlog | Bin 0 -> 11720 bytes .../msw/vc_mswdll/wxzlib/Lib-link.read.1.tlog | Bin 0 -> 8312 bytes .../vc_mswdll/wxzlib/Lib-link.write.1.tlog | Bin 0 -> 4114 bytes wx28X/build/msw/vc_mswdll/wxzlib/adler32.obj | Bin 0 -> 4351 bytes .../msw/vc_mswdll/wxzlib/cl.command.1.tlog | Bin 0 -> 23150 bytes wx28X/build/msw/vc_mswdll/wxzlib/compress.obj | Bin 0 -> 3987 bytes wx28X/build/msw/vc_mswdll/wxzlib/crc32.obj | Bin 0 -> 18757 bytes wx28X/build/msw/vc_mswdll/wxzlib/deflate.obj | Bin 0 -> 31241 bytes wx28X/build/msw/vc_mswdll/wxzlib/gzio.obj | Bin 0 -> 27604 bytes wx28X/build/msw/vc_mswdll/wxzlib/infback.obj | Bin 0 -> 18283 bytes wx28X/build/msw/vc_mswdll/wxzlib/inffast.obj | Bin 0 -> 6826 bytes wx28X/build/msw/vc_mswdll/wxzlib/inflate.obj | Bin 0 -> 32885 bytes wx28X/build/msw/vc_mswdll/wxzlib/inftrees.obj | Bin 0 -> 6929 bytes .../msw/vc_mswdll/wxzlib/lib.command.1.tlog | Bin 0 -> 6404 bytes wx28X/build/msw/vc_mswdll/wxzlib/trees.obj | Bin 0 -> 30395 bytes wx28X/build/msw/vc_mswdll/wxzlib/uncompr.obj | Bin 0 -> 2977 bytes .../build/msw/vc_mswdll/wxzlib/wx_wxzlib.log | 17 + .../vc_mswdll/wxzlib/wxzlib.lastbuildstate | 2 + wx28X/build/msw/vc_mswdll/wxzlib/zutil.obj | Bin 0 -> 6619 bytes wx28X/build/msw/vc_mswdll/xml/CL.read.1.tlog | Bin 0 -> 79926 bytes wx28X/build/msw/vc_mswdll/xml/CL.write.1.tlog | Bin 0 -> 3296 bytes .../build/msw/vc_mswdll/xml/cl.command.1.tlog | Bin 0 -> 11216 bytes .../vc_mswdll/xml/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../msw/vc_mswdll/xml/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../vc_mswdll/xml/custombuild.write.1.tlog | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/xml/dummy.obj | Bin 0 -> 380478 bytes .../msw/vc_mswdll/xml/link-cvtres.read.1.tlog | 1 + .../vc_mswdll/xml/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswdll/xml/link.command.1.tlog | Bin 0 -> 7586 bytes .../build/msw/vc_mswdll/xml/link.read.1.tlog | Bin 0 -> 13614 bytes .../build/msw/vc_mswdll/xml/link.write.1.tlog | Bin 0 -> 2872 bytes .../build/msw/vc_mswdll/xml/mt.command.1.tlog | Bin 0 -> 1264 bytes wx28X/build/msw/vc_mswdll/xml/mt.read.1.tlog | Bin 0 -> 1836 bytes wx28X/build/msw/vc_mswdll/xml/mt.write.1.tlog | Bin 0 -> 756 bytes .../build/msw/vc_mswdll/xml/rc.command.1.tlog | Bin 0 -> 4698 bytes wx28X/build/msw/vc_mswdll/xml/rc.read.1.tlog | Bin 0 -> 644 bytes wx28X/build/msw/vc_mswdll/xml/rc.write.1.tlog | Bin 0 -> 534 bytes wx28X/build/msw/vc_mswdll/xml/version.res | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/xml/wx_xml.log | 42 + .../xml/xml.dll.intermediate.manifest | 15 + .../msw/vc_mswdll/xml/xml.lastbuildstate | 2 + wx28X/build/msw/vc_mswdll/xml/xml.obj | Bin 0 -> 154213 bytes .../build/msw/vc_mswdll/xml/xml.write.1.tlog | 9 + wx28X/build/msw/vc_mswdll/xml/xtixml.obj | Bin 0 -> 2261 bytes wx28X/build/msw/vc_mswdll/xrc/CL.read.1.tlog | Bin 0 -> 528618 bytes wx28X/build/msw/vc_mswdll/xrc/CL.write.1.tlog | Bin 0 -> 62714 bytes .../build/msw/vc_mswdll/xrc/cl.command.1.tlog | Bin 0 -> 208904 bytes .../vc_mswdll/xrc/custombuild.command.1.tlog | Bin 0 -> 1588 bytes .../msw/vc_mswdll/xrc/custombuild.read.1.tlog | Bin 0 -> 510 bytes .../vc_mswdll/xrc/custombuild.write.1.tlog | Bin 0 -> 1048 bytes wx28X/build/msw/vc_mswdll/xrc/dummy.obj | Bin 0 -> 420238 bytes .../msw/vc_mswdll/xrc/link-cvtres.read.1.tlog | 1 + .../vc_mswdll/xrc/link-cvtres.write.1.tlog | 1 + .../msw/vc_mswdll/xrc/link.command.1.tlog | Bin 0 -> 35428 bytes .../build/msw/vc_mswdll/xrc/link.read.1.tlog | Bin 0 -> 49920 bytes .../build/msw/vc_mswdll/xrc/link.write.1.tlog | Bin 0 -> 19916 bytes .../build/msw/vc_mswdll/xrc/mt.command.1.tlog | Bin 0 -> 1258 bytes wx28X/build/msw/vc_mswdll/xrc/mt.read.1.tlog | Bin 0 -> 1830 bytes wx28X/build/msw/vc_mswdll/xrc/mt.write.1.tlog | Bin 0 -> 750 bytes .../build/msw/vc_mswdll/xrc/rc.command.1.tlog | Bin 0 -> 4506 bytes wx28X/build/msw/vc_mswdll/xrc/rc.read.1.tlog | Bin 0 -> 644 bytes wx28X/build/msw/vc_mswdll/xrc/rc.write.1.tlog | Bin 0 -> 534 bytes wx28X/build/msw/vc_mswdll/xrc/version.res | Bin 0 -> 1044 bytes wx28X/build/msw/vc_mswdll/xrc/wx_xrc.log | 153 + .../build/msw/vc_mswdll/xrc/xh_animatctrl.obj | Bin 0 -> 96624 bytes wx28X/build/msw/vc_mswdll/xrc/xh_bmp.obj | Bin 0 -> 93353 bytes wx28X/build/msw/vc_mswdll/xrc/xh_bmpbt.obj | Bin 0 -> 108038 bytes wx28X/build/msw/vc_mswdll/xrc/xh_bmpcbox.obj | Bin 0 -> 112585 bytes wx28X/build/msw/vc_mswdll/xrc/xh_bttn.obj | Bin 0 -> 95706 bytes wx28X/build/msw/vc_mswdll/xrc/xh_cald.obj | Bin 0 -> 95951 bytes wx28X/build/msw/vc_mswdll/xrc/xh_chckb.obj | Bin 0 -> 95636 bytes wx28X/build/msw/vc_mswdll/xrc/xh_chckl.obj | Bin 0 -> 110921 bytes wx28X/build/msw/vc_mswdll/xrc/xh_choic.obj | Bin 0 -> 101313 bytes wx28X/build/msw/vc_mswdll/xrc/xh_choicbk.obj | Bin 0 -> 109861 bytes .../build/msw/vc_mswdll/xrc/xh_clrpicker.obj | Bin 0 -> 96667 bytes wx28X/build/msw/vc_mswdll/xrc/xh_collpane.obj | Bin 0 -> 99773 bytes wx28X/build/msw/vc_mswdll/xrc/xh_combo.obj | Bin 0 -> 107134 bytes wx28X/build/msw/vc_mswdll/xrc/xh_datectrl.obj | Bin 0 -> 94913 bytes .../build/msw/vc_mswdll/xrc/xh_dirpicker.obj | Bin 0 -> 99223 bytes wx28X/build/msw/vc_mswdll/xrc/xh_dlg.obj | Bin 0 -> 106643 bytes .../build/msw/vc_mswdll/xrc/xh_filepicker.obj | Bin 0 -> 102017 bytes .../build/msw/vc_mswdll/xrc/xh_fontpicker.obj | Bin 0 -> 98318 bytes wx28X/build/msw/vc_mswdll/xrc/xh_frame.obj | Bin 0 -> 109794 bytes wx28X/build/msw/vc_mswdll/xrc/xh_gauge.obj | Bin 0 -> 97262 bytes wx28X/build/msw/vc_mswdll/xrc/xh_gdctl.obj | Bin 0 -> 102453 bytes wx28X/build/msw/vc_mswdll/xrc/xh_grid.obj | Bin 0 -> 95387 bytes wx28X/build/msw/vc_mswdll/xrc/xh_html.obj | Bin 0 -> 107959 bytes wx28X/build/msw/vc_mswdll/xrc/xh_htmllbox.obj | Bin 0 -> 112715 bytes .../build/msw/vc_mswdll/xrc/xh_hyperlink.obj | Bin 0 -> 96084 bytes wx28X/build/msw/vc_mswdll/xrc/xh_listb.obj | Bin 0 -> 105415 bytes wx28X/build/msw/vc_mswdll/xrc/xh_listbk.obj | Bin 0 -> 109366 bytes wx28X/build/msw/vc_mswdll/xrc/xh_listc.obj | Bin 0 -> 100783 bytes wx28X/build/msw/vc_mswdll/xrc/xh_mdi.obj | Bin 0 -> 124977 bytes wx28X/build/msw/vc_mswdll/xrc/xh_menu.obj | Bin 0 -> 133535 bytes wx28X/build/msw/vc_mswdll/xrc/xh_notbk.obj | Bin 0 -> 111971 bytes wx28X/build/msw/vc_mswdll/xrc/xh_odcombo.obj | Bin 0 -> 112817 bytes wx28X/build/msw/vc_mswdll/xrc/xh_panel.obj | Bin 0 -> 89636 bytes wx28X/build/msw/vc_mswdll/xrc/xh_propdlg.obj | Bin 0 -> 124824 bytes wx28X/build/msw/vc_mswdll/xrc/xh_radbt.obj | Bin 0 -> 93987 bytes wx28X/build/msw/vc_mswdll/xrc/xh_radbx.obj | Bin 0 -> 112064 bytes wx28X/build/msw/vc_mswdll/xrc/xh_scrol.obj | Bin 0 -> 95540 bytes wx28X/build/msw/vc_mswdll/xrc/xh_scwin.obj | Bin 0 -> 96705 bytes wx28X/build/msw/vc_mswdll/xrc/xh_sizer.obj | Bin 0 -> 206301 bytes wx28X/build/msw/vc_mswdll/xrc/xh_slidr.obj | Bin 0 -> 107665 bytes wx28X/build/msw/vc_mswdll/xrc/xh_spin.obj | Bin 0 -> 125704 bytes wx28X/build/msw/vc_mswdll/xrc/xh_split.obj | Bin 0 -> 103609 bytes wx28X/build/msw/vc_mswdll/xrc/xh_statbar.obj | Bin 0 -> 97704 bytes wx28X/build/msw/vc_mswdll/xrc/xh_stbmp.obj | Bin 0 -> 94090 bytes wx28X/build/msw/vc_mswdll/xrc/xh_stbox.obj | Bin 0 -> 92681 bytes wx28X/build/msw/vc_mswdll/xrc/xh_stlin.obj | Bin 0 -> 92695 bytes wx28X/build/msw/vc_mswdll/xrc/xh_sttxt.obj | Bin 0 -> 95571 bytes wx28X/build/msw/vc_mswdll/xrc/xh_text.obj | Bin 0 -> 107189 bytes wx28X/build/msw/vc_mswdll/xrc/xh_tglbtn.obj | Bin 0 -> 93746 bytes wx28X/build/msw/vc_mswdll/xrc/xh_toolb.obj | Bin 0 -> 128883 bytes wx28X/build/msw/vc_mswdll/xrc/xh_tree.obj | Bin 0 -> 106775 bytes wx28X/build/msw/vc_mswdll/xrc/xh_treebk.obj | Bin 0 -> 143732 bytes wx28X/build/msw/vc_mswdll/xrc/xh_unkwn.obj | Bin 0 -> 107871 bytes wx28X/build/msw/vc_mswdll/xrc/xh_wizrd.obj | Bin 0 -> 113408 bytes wx28X/build/msw/vc_mswdll/xrc/xmlres.obj | Bin 0 -> 449835 bytes wx28X/build/msw/vc_mswdll/xrc/xmlrsall.obj | Bin 0 -> 632728 bytes .../xrc/xrc.dll.intermediate.manifest | 15 + .../msw/vc_mswdll/xrc/xrc.lastbuildstate | 2 + .../build/msw/vc_mswdll/xrc/xrc.write.1.tlog | 9 + wx28X/build/msw/wx.dsw | 244 + wx28X/build/msw/wx_adv.dsp | 1313 + wx28X/build/msw/wx_adv.vcxproj | 2097 + wx28X/build/msw/wx_adv.vcxproj.filters | 250 + wx28X/build/msw/wx_adv.vcxproj.user | 3 + wx28X/build/msw/wx_aui.dsp | 1034 + wx28X/build/msw/wx_aui.vcxproj | 1375 + wx28X/build/msw/wx_aui.vcxproj.filters | 85 + wx28X/build/msw/wx_aui.vcxproj.user | 3 + wx28X/build/msw/wx_base.dsp | 1851 + wx28X/build/msw/wx_base.vcxproj | 4309 + wx28X/build/msw/wx_base.vcxproj.filters | 697 + wx28X/build/msw/wx_base.vcxproj.user | 3 + wx28X/build/msw/wx_core.dsp | 9685 + wx28X/build/msw/wx_core.vcxproj | 11782 ++ wx28X/build/msw/wx_core.vcxproj.filters | 2278 + wx28X/build/msw/wx_core.vcxproj.user | 3 + wx28X/build/msw/wx_dbgrid.dsp | 986 + wx28X/build/msw/wx_dbgrid.vcxproj | 1196 + wx28X/build/msw/wx_dbgrid.vcxproj.filters | 49 + wx28X/build/msw/wx_dbgrid.vcxproj.user | 3 + wx28X/build/msw/wx_dll.dsw | 479 + wx28X/build/msw/wx_dll.sdf | Bin 0 -> 124211200 bytes wx28X/build/msw/wx_dll.sln | 708 + wx28X/build/msw/wx_dll.suo | Bin 0 -> 81920 bytes wx28X/build/msw/wx_gl.dsp | 982 + wx28X/build/msw/wx_gl.vcxproj | 1199 + wx28X/build/msw/wx_gl.vcxproj.filters | 46 + wx28X/build/msw/wx_gl.vcxproj.user | 3 + wx28X/build/msw/wx_html.dsp | 1158 + wx28X/build/msw/wx_html.vcxproj | 1998 + wx28X/build/msw/wx_html.vcxproj.filters | 178 + wx28X/build/msw/wx_html.vcxproj.user | 3 + wx28X/build/msw/wx_media.dsp | 1006 + wx28X/build/msw/wx_media.vcxproj | 1336 + wx28X/build/msw/wx_media.vcxproj.filters | 64 + wx28X/build/msw/wx_media.vcxproj.user | 3 + wx28X/build/msw/wx_net.dsp | 1074 + wx28X/build/msw/wx_net.vcxproj | 1578 + wx28X/build/msw/wx_net.vcxproj.filters | 115 + wx28X/build/msw/wx_net.vcxproj.user | 3 + wx28X/build/msw/wx_odbc.dsp | 998 + wx28X/build/msw/wx_odbc.vcxproj | 1229 + wx28X/build/msw/wx_odbc.vcxproj.filters | 58 + wx28X/build/msw/wx_odbc.vcxproj.user | 3 + wx28X/build/msw/wx_qa.dsp | 994 + wx28X/build/msw/wx_qa.vcxproj | 1239 + wx28X/build/msw/wx_qa.vcxproj.filters | 55 + wx28X/build/msw/wx_qa.vcxproj.user | 3 + wx28X/build/msw/wx_richtext.dsp | 1054 + wx28X/build/msw/wx_richtext.vcxproj | 1485 + wx28X/build/msw/wx_richtext.vcxproj.filters | 100 + wx28X/build/msw/wx_richtext.vcxproj.user | 3 + wx28X/build/msw/wx_wxexpat.dsp | 451 + wx28X/build/msw/wx_wxexpat.vcxproj | 805 + wx28X/build/msw/wx_wxexpat.vcxproj.filters | 19 + wx28X/build/msw/wx_wxexpat.vcxproj.user | 3 + wx28X/build/msw/wx_wxjpeg.dsp | 623 + wx28X/build/msw/wx_wxjpeg.vcxproj | 2267 + wx28X/build/msw/wx_wxjpeg.vcxproj.filters | 148 + wx28X/build/msw/wx_wxjpeg.vcxproj.user | 3 + wx28X/build/msw/wx_wxpng.dsp | 507 + wx28X/build/msw/wx_wxpng.vcxproj | 1286 + wx28X/build/msw/wx_wxpng.vcxproj.filters | 61 + wx28X/build/msw/wx_wxpng.vcxproj.user | 3 + wx28X/build/msw/wx_wxregex.dsp | 896 + wx28X/build/msw/wx_wxregex.vcxproj | 983 + wx28X/build/msw/wx_wxregex.vcxproj.filters | 36 + wx28X/build/msw/wx_wxregex.vcxproj.user | 3 + wx28X/build/msw/wx_wxtiff.dsp | 579 + wx28X/build/msw/wx_wxtiff.vcxproj | 1893 + wx28X/build/msw/wx_wxtiff.vcxproj.filters | 115 + wx28X/build/msw/wx_wxtiff.vcxproj.user | 3 + wx28X/build/msw/wx_wxzlib.dsp | 487 + wx28X/build/msw/wx_wxzlib.vcxproj | 903 + wx28X/build/msw/wx_wxzlib.vcxproj.filters | 46 + wx28X/build/msw/wx_wxzlib.vcxproj.user | 3 + wx28X/build/msw/wx_xml.dsp | 998 + wx28X/build/msw/wx_xml.vcxproj | 1228 + wx28X/build/msw/wx_xml.vcxproj.filters | 58 + wx28X/build/msw/wx_xml.vcxproj.user | 3 + wx28X/build/msw/wx_xrc.dsp | 1430 + wx28X/build/msw/wx_xrc.vcxproj | 3115 + wx28X/build/msw/wx_xrc.vcxproj.filters | 382 + wx28X/build/msw/wx_xrc.vcxproj.user | 3 + wx28X/build/script/makedocs.vc | 342 + wx28X/build/script/rebuild-makefiles.sh | 202 + wx28X/build/script/win_docs.bat | 112 + wx28X/build/script/word_macro.txt | 47 + wx28X/build/script/wxwidgets.iss | 61 + wx28X/build/tools/build-wxwidgets.py | 509 + wx28X/build/tools/builder.py | 235 + wx28X/build/tools/create-archive.py | 218 + wx28X/build/update-setup-h | 88 + wx28X/build/wince/missing/AGL/agl.h | 1 + wx28X/build/wince/missing/ATSUnicode.h | 1 + wx28X/build/wince/missing/Appearance.h | 1 + .../build/wince/missing/AvailabilityMacros.h | 1 + wx28X/build/wince/missing/CFString.h | 1 + wx28X/build/wince/missing/Carbon/Carbon.h | 1 + wx28X/build/wince/missing/CodeFragments.h | 1 + .../build/wince/missing/ControlDefinitions.h | 1 + wx28X/build/wince/missing/Controls.h | 1 + .../wince/missing/CoreFoundation/CFBase.h | 1 + .../wince/missing/CoreFoundation/CFString.h | 1 + .../CoreFoundation/CFStringEncodingExt.h | 1 + .../missing/CoreFoundation/CoreFoundation.h | 1 + wx28X/build/wince/missing/CoreServices.h | 1 + .../wince/missing/CoreServices/CoreServices.h | 1 + wx28X/build/wince/missing/DateTime.h | 1 + wx28X/build/wince/missing/Debugging.h | 1 + wx28X/build/wince/missing/DriverServices.h | 1 + wx28X/build/wince/missing/FixMath.h | 1 + wx28X/build/wince/missing/Folders.h | 1 + wx28X/build/wince/missing/GL/glx.h | 1 + wx28X/build/wince/missing/Gestalt.h | 1 + wx28X/build/wince/missing/InternetConfig.h | 1 + wx28X/build/wince/missing/LowMem.h | 1 + wx28X/build/wince/missing/MacHeaders.c | 1 + wx28X/build/wince/missing/MoreFilesX.h | 1 + wx28X/build/wince/missing/OpenGL/gl.h | 1 + wx28X/build/wince/missing/OpenGL/glx.h | 1 + wx28X/build/wince/missing/OpenTptInternet.h | 1 + wx28X/build/wince/missing/OpenTransport.h | 1 + .../wince/missing/OpenTransportProviders.h | 1 + wx28X/build/wince/missing/PMApplication.h | 1 + wx28X/build/wince/missing/PalmOS.h | 1 + wx28X/build/wince/missing/Printing.h | 1 + wx28X/build/wince/missing/Quickdraw.h | 1 + wx28X/build/wince/missing/StringMgr.h | 1 + wx28X/build/wince/missing/SystemMgr.h | 1 + wx28X/build/wince/missing/TextCommon.h | 1 + .../wince/missing/TextEncodingConverter.h | 1 + wx28X/build/wince/missing/TimeMgr.h | 1 + wx28X/build/wince/missing/Timer.h | 1 + wx28X/build/wince/missing/Xm/VendorSP.h | 1 + wx28X/build/wince/missing/Xm/Xm.h | 1 + wx28X/build/wince/missing/_mingw.h | 1 + wx28X/build/wince/missing/agl.h | 1 + wx28X/build/wince/missing/alloc.h | 1 + wx28X/build/wince/missing/ansi_prefix.mach.h | 1 + wx28X/build/wince/missing/clib.h | 1 + wx28X/build/wince/missing/dir.h | 1 + wx28X/build/wince/missing/dirent.h | 1 + wx28X/build/wince/missing/dl.h | 1 + wx28X/build/wince/missing/dlfcn.h | 1 + wx28X/build/wince/missing/expat_config.h | 1 + wx28X/build/wince/missing/ext/hash_map | 1 + wx28X/build/wince/missing/ext/hash_set | 1 + wx28X/build/wince/missing/fab.h | 1 + wx28X/build/wince/missing/fp.h | 1 + wx28X/build/wince/missing/gdk/gdk.h | 1 + wx28X/build/wince/missing/gdk/gdkx.h | 1 + wx28X/build/wince/missing/grp.h | 1 + wx28X/build/wince/missing/gsocket.h | 1 + wx28X/build/wince/missing/hash_map | 1 + wx28X/build/wince/missing/hash_set | 1 + wx28X/build/wince/missing/iconv.h | 1 + wx28X/build/wince/missing/langinfo.h | 1 + wx28X/build/wince/missing/m68881.h | 1 + wx28X/build/wince/missing/machine/ansi.h | 1 + wx28X/build/wince/missing/mem.h | 1 + wx28X/build/wince/missing/mgraph.hpp | 1 + wx28X/build/wince/missing/msl_c_version.h | 1 + wx28X/build/wince/missing/os2.h | 1 + wx28X/build/wince/missing/os2def.h | 1 + wx28X/build/wince/missing/pango/pango.h | 1 + wx28X/build/wince/missing/pmapi.h | 1 + wx28X/build/wince/missing/pmstddlg.h | 1 + wx28X/build/wince/missing/pngusr.h | 1 + wx28X/build/wince/missing/print.h | 1 + wx28X/build/wince/missing/pwd.h | 1 + wx28X/build/wince/missing/stdint.h | 1 + wx28X/build/wince/missing/strings.h | 1 + wx28X/build/wince/missing/sys/cygwin.h | 1 + wx28X/build/wince/missing/sys/hash_set | 1 + wx28X/build/wince/missing/sys/ioctl.h | 1 + wx28X/build/wince/missing/sys/minmax.h | 1 + wx28X/build/wince/missing/sys/select.h | 1 + wx28X/build/wince/missing/sys/socket.h | 1 + wx28X/build/wince/missing/sys/time.h | 1 + wx28X/build/wince/missing/sys/un.h | 1 + wx28X/build/wince/missing/sys/unistd.h | 1 + wx28X/build/wince/missing/tcpustd.h | 1 + wx28X/build/wince/missing/unistd.h | 1 + wx28X/build/wince/missing/unix.h | 1 + wx28X/build/wince/missing/unixio.h | 1 + wx28X/build/wince/missing/utils.h | 1 + wx28X/build/wince/missing/values.h | 1 + wx28X/build/wince/missing/w32api.h | 1 + wx28X/build/wince/missing/wcstr.h | 1 + wx28X/build/wince/missing/widec.h | 1 + wx28X/build/wince/missing/wtime.h | 1 + wx28X/build/wince/wx.vcw | 77 + wx28X/build/wince/wx_gl.vcp | 2944 + wx28X/build/wince/wx_mono.vcp | 7057 + wx28X/build/wince/wx_wxexpat.vcp | 1518 + wx28X/build/wince/wx_wxjpeg.vcp | 1690 + wx28X/build/wince/wx_wxpng.vcp | 1574 + wx28X/build/wince/wx_wxzlib.vcp | 1554 + wx28X/config.guess | 1441 + wx28X/config.sub | 1552 + wx28X/configure | 52858 +++++ wx28X/configure.in | 8544 + wx28X/contrib/Makefile.in | 18 + wx28X/contrib/build/deprecated/deprecated.bkl | 57 + wx28X/contrib/build/deprecated/deprecated.dsp | 558 + wx28X/contrib/build/deprecated/deprecated.dsw | 16 + wx28X/contrib/build/deprecated/deprecated.vcp | 1903 + wx28X/contrib/build/deprecated/deprecated.vcw | 17 + wx28X/contrib/build/deprecated/makefile.bcc | 369 + wx28X/contrib/build/deprecated/makefile.dmc | 84 + wx28X/contrib/build/deprecated/makefile.dms | 298 + wx28X/contrib/build/deprecated/makefile.gcc | 367 + wx28X/contrib/build/deprecated/makefile.vc | 492 + wx28X/contrib/build/deprecated/makefile.wat | 405 + wx28X/contrib/build/fl/fl.bkl | 67 + wx28X/contrib/build/fl/fl.dsp | 593 + wx28X/contrib/build/fl/fl.dsw | 16 + wx28X/contrib/build/fl/fl.vcp | 1938 + wx28X/contrib/build/fl/fl.vcw | 17 + wx28X/contrib/build/fl/makefile.bcc | 424 + wx28X/contrib/build/fl/makefile.dmc | 115 + wx28X/contrib/build/fl/makefile.dms | 350 + wx28X/contrib/build/fl/makefile.gcc | 421 + wx28X/contrib/build/fl/makefile.vc | 541 + wx28X/contrib/build/fl/makefile.wat | 458 + wx28X/contrib/build/foldbar/foldbar.bkl | 36 + wx28X/contrib/build/foldbar/foldbar.dsp | 537 + wx28X/contrib/build/foldbar/foldbar.dsw | 16 + wx28X/contrib/build/foldbar/foldbar.vcp | 1882 + wx28X/contrib/build/foldbar/foldbar.vcw | 17 + wx28X/contrib/build/foldbar/makefile.bcc | 313 + wx28X/contrib/build/foldbar/makefile.dmc | 59 + wx28X/contrib/build/foldbar/makefile.dms | 266 + wx28X/contrib/build/foldbar/makefile.gcc | 310 + wx28X/contrib/build/foldbar/makefile.vc | 429 + wx28X/contrib/build/foldbar/makefile.wat | 347 + wx28X/contrib/build/gizmos/gizmos.bkl | 66 + wx28X/contrib/build/gizmos/gizmos.dsp | 553 + wx28X/contrib/build/gizmos/gizmos.dsw | 28 + wx28X/contrib/build/gizmos/gizmos.vcw | 29 + wx28X/contrib/build/gizmos/gizmos_gizmos.dsp | 549 + wx28X/contrib/build/gizmos/gizmos_gizmos.vcp | 1894 + .../build/gizmos/gizmos_gizmos_xrc.dsp | 529 + .../build/gizmos/gizmos_gizmos_xrc.vcp | 1874 + wx28X/contrib/build/gizmos/makefile.bcc | 415 + wx28X/contrib/build/gizmos/makefile.dmc | 93 + wx28X/contrib/build/gizmos/makefile.dms | 351 + wx28X/contrib/build/gizmos/makefile.gcc | 412 + wx28X/contrib/build/gizmos/makefile.vc | 560 + wx28X/contrib/build/gizmos/makefile.wat | 463 + wx28X/contrib/build/mmedia/makefile.bcc | 449 + wx28X/contrib/build/mmedia/makefile.dmc | 127 + wx28X/contrib/build/mmedia/makefile.dms | 368 + wx28X/contrib/build/mmedia/makefile.gcc | 446 + wx28X/contrib/build/mmedia/makefile.vc | 565 + wx28X/contrib/build/mmedia/makefile.wat | 483 + wx28X/contrib/build/mmedia/mmedia.bkl | 91 + wx28X/contrib/build/mmedia/mmedia.dsp | 605 + wx28X/contrib/build/mmedia/mmedia.dsw | 16 + wx28X/contrib/build/mmedia/mmedia.vcp | 1950 + wx28X/contrib/build/mmedia/mmedia.vcw | 17 + wx28X/contrib/build/net/makefile.bcc | 313 + wx28X/contrib/build/net/makefile.dmc | 59 + wx28X/contrib/build/net/makefile.dms | 266 + wx28X/contrib/build/net/makefile.gcc | 310 + wx28X/contrib/build/net/makefile.vc | 430 + wx28X/contrib/build/net/makefile.wat | 347 + wx28X/contrib/build/net/net.bkl | 39 + wx28X/contrib/build/net/net.dsp | 537 + wx28X/contrib/build/net/net.dsw | 16 + wx28X/contrib/build/net/net.vcp | 1882 + wx28X/contrib/build/net/net.vcw | 17 + wx28X/contrib/build/ogl/makefile.bcc | 384 + wx28X/contrib/build/ogl/makefile.dmc | 95 + wx28X/contrib/build/ogl/makefile.dms | 320 + wx28X/contrib/build/ogl/makefile.gcc | 381 + wx28X/contrib/build/ogl/makefile.vc | 501 + wx28X/contrib/build/ogl/makefile.wat | 418 + wx28X/contrib/build/ogl/ogl.bkl | 57 + wx28X/contrib/build/ogl/ogl.dsp | 573 + wx28X/contrib/build/ogl/ogl.dsw | 16 + wx28X/contrib/build/ogl/ogl.vcp | 1918 + wx28X/contrib/build/ogl/ogl.vcw | 17 + wx28X/contrib/build/plot/makefile.bcc | 296 + wx28X/contrib/build/plot/makefile.dmc | 51 + wx28X/contrib/build/plot/makefile.dms | 254 + wx28X/contrib/build/plot/makefile.gcc | 294 + wx28X/contrib/build/plot/makefile.vc | 413 + wx28X/contrib/build/plot/makefile.wat | 331 + wx28X/contrib/build/plot/plot.bkl | 39 + wx28X/contrib/build/plot/plot.dsp | 529 + wx28X/contrib/build/plot/plot.dsw | 16 + wx28X/contrib/build/plot/plot.vcp | 1874 + wx28X/contrib/build/plot/plot.vcw | 17 + wx28X/contrib/build/stc/makefile.bcc | 955 + wx28X/contrib/build/stc/makefile.dmc | 375 + wx28X/contrib/build/stc/makefile.dms | 736 + wx28X/contrib/build/stc/makefile.gcc | 953 + wx28X/contrib/build/stc/makefile.vc | 1071 + wx28X/contrib/build/stc/makefile.wat | 989 + wx28X/contrib/build/stc/stc.bkl | 125 + wx28X/contrib/build/stc/stc.dsp | 855 + wx28X/contrib/build/stc/stc.dsw | 16 + wx28X/contrib/build/stc/stc.vcp | 2200 + wx28X/contrib/build/stc/stc.vcw | 17 + wx28X/contrib/build/svg/makefile.bcc | 296 + wx28X/contrib/build/svg/makefile.dmc | 51 + wx28X/contrib/build/svg/makefile.dms | 254 + wx28X/contrib/build/svg/makefile.gcc | 293 + wx28X/contrib/build/svg/makefile.vc | 413 + wx28X/contrib/build/svg/makefile.wat | 330 + wx28X/contrib/build/svg/svg.bkl | 32 + wx28X/contrib/build/svg/svg.dsp | 529 + wx28X/contrib/build/svg/svg.dsw | 16 + wx28X/contrib/build/svg/svg.vcp | 1874 + wx28X/contrib/build/svg/svg.vcw | 17 + wx28X/contrib/include/wx/applet/applet.h | 85 + wx28X/contrib/include/wx/applet/echovar.h | 136 + wx28X/contrib/include/wx/applet/ifelsevar.h | 135 + wx28X/contrib/include/wx/applet/loadpage.h | 112 + wx28X/contrib/include/wx/applet/plugin.h | 63 + wx28X/contrib/include/wx/applet/prepecho.h | 60 + wx28X/contrib/include/wx/applet/prepifelse.h | 60 + wx28X/contrib/include/wx/applet/prepinclude.h | 66 + wx28X/contrib/include/wx/applet/window.h | 231 + wx28X/contrib/include/wx/deprecated/expr.h | 68 + wx28X/contrib/include/wx/deprecated/prop.h | 344 + .../contrib/include/wx/deprecated/propform.h | 328 + .../contrib/include/wx/deprecated/proplist.h | 593 + .../contrib/include/wx/deprecated/resource.h | 211 + wx28X/contrib/include/wx/deprecated/setup.h | 71 + .../contrib/include/wx/deprecated/tbarsmpl.h | 172 + wx28X/contrib/include/wx/deprecated/treelay.h | 151 + wx28X/contrib/include/wx/deprecated/wxexpr.h | 281 + wx28X/contrib/include/wx/fl/antiflickpl.h | 82 + wx28X/contrib/include/wx/fl/bardragpl.h | 169 + wx28X/contrib/include/wx/fl/barhintspl.h | 111 + wx28X/contrib/include/wx/fl/cbcustom.h | 50 + wx28X/contrib/include/wx/fl/controlbar.h | 2270 + wx28X/contrib/include/wx/fl/dynbarhnd.h | 18 + wx28X/contrib/include/wx/fl/dyntbar.h | 273 + wx28X/contrib/include/wx/fl/dyntbarhnd.h | 37 + wx28X/contrib/include/wx/fl/fldefs.h | 46 + wx28X/contrib/include/wx/fl/frmview.h | 145 + wx28X/contrib/include/wx/fl/garbagec.h | 89 + wx28X/contrib/include/wx/fl/gcupdatesmgr.h | 125 + wx28X/contrib/include/wx/fl/hintanimpl.h | 138 + wx28X/contrib/include/wx/fl/newbmpbtn.h | 211 + wx28X/contrib/include/wx/fl/panedrawpl.h | 157 + wx28X/contrib/include/wx/fl/rowdragpl.h | 227 + wx28X/contrib/include/wx/fl/rowlayoutpl.h | 122 + wx28X/contrib/include/wx/fl/toolwnd.h | 302 + wx28X/contrib/include/wx/fl/updatesmgr.h | 66 + wx28X/contrib/include/wx/foldbar/captionbar.h | 476 + .../contrib/include/wx/foldbar/doc_mainpage.h | 79 + .../contrib/include/wx/foldbar/foldpanelbar.h | 290 + .../include/wx/foldbar/foldpanelitem.h | 260 + wx28X/contrib/include/wx/gizmos/dynamicsash.h | 202 + wx28X/contrib/include/wx/gizmos/editlbox.h | 67 + wx28X/contrib/include/wx/gizmos/gizmos.h | 20 + wx28X/contrib/include/wx/gizmos/ledctrl.h | 80 + wx28X/contrib/include/wx/gizmos/multicell.h | 174 + wx28X/contrib/include/wx/gizmos/splittree.h | 243 + wx28X/contrib/include/wx/gizmos/statpict.h | 138 + wx28X/contrib/include/wx/gizmos/xh_statpict.h | 39 + wx28X/contrib/include/wx/mmedia/cdbase.h | 71 + wx28X/contrib/include/wx/mmedia/cdunix.h | 55 + wx28X/contrib/include/wx/mmedia/cdwin.h | 59 + wx28X/contrib/include/wx/mmedia/defs.h | 15 + .../contrib/include/wx/mmedia/internal/g72x.h | 123 + wx28X/contrib/include/wx/mmedia/sndaiff.h | 44 + wx28X/contrib/include/wx/mmedia/sndbase.h | 169 + wx28X/contrib/include/wx/mmedia/sndcodec.h | 30 + wx28X/contrib/include/wx/mmedia/sndcpcm.h | 52 + wx28X/contrib/include/wx/mmedia/sndesd.h | 51 + wx28X/contrib/include/wx/mmedia/sndfile.h | 127 + wx28X/contrib/include/wx/mmedia/sndg72x.h | 83 + wx28X/contrib/include/wx/mmedia/sndmsad.h | 102 + wx28X/contrib/include/wx/mmedia/sndoss.h | 53 + wx28X/contrib/include/wx/mmedia/sndpcm.h | 55 + wx28X/contrib/include/wx/mmedia/sndulaw.h | 65 + wx28X/contrib/include/wx/mmedia/sndwav.h | 62 + wx28X/contrib/include/wx/mmedia/sndwin.h | 67 + wx28X/contrib/include/wx/mmedia/vidbase.h | 108 + wx28X/contrib/include/wx/mmedia/vidwin.h | 104 + wx28X/contrib/include/wx/mmedia/vidxanm.h | 134 + wx28X/contrib/include/wx/net/email.h | 40 + wx28X/contrib/include/wx/net/msg.h | 79 + wx28X/contrib/include/wx/net/smapi.h | 52 + wx28X/contrib/include/wx/net/web.h | 33 + wx28X/contrib/include/wx/ogl/basic.h | 757 + wx28X/contrib/include/wx/ogl/basicp.h | 220 + wx28X/contrib/include/wx/ogl/bmpshape.h | 48 + wx28X/contrib/include/wx/ogl/canvas.h | 85 + wx28X/contrib/include/wx/ogl/composit.h | 235 + wx28X/contrib/include/wx/ogl/constrnt.h | 87 + wx28X/contrib/include/wx/ogl/divided.h | 72 + wx28X/contrib/include/wx/ogl/drawn.h | 221 + wx28X/contrib/include/wx/ogl/drawnp.h | 209 + wx28X/contrib/include/wx/ogl/lines.h | 296 + wx28X/contrib/include/wx/ogl/linesp.h | 86 + wx28X/contrib/include/wx/ogl/mfutils.h | 414 + wx28X/contrib/include/wx/ogl/misc.h | 109 + wx28X/contrib/include/wx/ogl/ogl.h | 45 + wx28X/contrib/include/wx/ogl/ogldiag.h | 125 + wx28X/contrib/include/wx/plot/plot.h | 458 + wx28X/contrib/include/wx/plot/plot_dwn.bmp | Bin 0 -> 334 bytes wx28X/contrib/include/wx/plot/plot_dwn.xpm | 32 + wx28X/contrib/include/wx/plot/plot_enl.bmp | Bin 0 -> 358 bytes wx28X/contrib/include/wx/plot/plot_enl.xpm | 34 + wx28X/contrib/include/wx/plot/plot_shr.bmp | Bin 0 -> 358 bytes wx28X/contrib/include/wx/plot/plot_shr.xpm | 34 + wx28X/contrib/include/wx/plot/plot_up.bmp | Bin 0 -> 334 bytes wx28X/contrib/include/wx/plot/plot_up.xpm | 32 + wx28X/contrib/include/wx/plot/plot_zin.bmp | Bin 0 -> 334 bytes wx28X/contrib/include/wx/plot/plot_zin.xpm | 32 + wx28X/contrib/include/wx/plot/plot_zot.bmp | Bin 0 -> 334 bytes wx28X/contrib/include/wx/plot/plot_zot.xpm | 32 + wx28X/contrib/include/wx/plot/wxplot.rc | 8 + wx28X/contrib/include/wx/stc/stc.h | 3621 + wx28X/contrib/include/wx/svg/dcsvg.h | 320 + wx28X/contrib/lib/dummy | 1 + wx28X/contrib/samples/Makefile.in | 10 + wx28X/contrib/samples/applet/about.html | 10 + wx28X/contrib/samples/applet/applet.cpp | 156 + wx28X/contrib/samples/applet/applet.h | 77 + wx28X/contrib/samples/applet/applet.rc | 2 + wx28X/contrib/samples/applet/combobox.cpp | 173 + wx28X/contrib/samples/applet/combobox.h | 97 + wx28X/contrib/samples/applet/dialogs.wdr | Bin 0 -> 4005 bytes wx28X/contrib/samples/applet/dialogs_wdr.cpp | 102 + wx28X/contrib/samples/applet/dialogs_wdr.h | 38 + wx28X/contrib/samples/applet/index.html | 21 + .../contrib/samples/applet/monitorapplet.cpp | 218 + wx28X/contrib/samples/applet/monitorapplet.h | 112 + wx28X/contrib/samples/applet/monitors.c | 3572 + wx28X/contrib/samples/deprecated/Makefile.in | 10 + .../samples/deprecated/proplist/Makefile.in | 198 + .../samples/deprecated/proplist/cross.bmp | Bin 0 -> 198 bytes .../samples/deprecated/proplist/makefile.bcc | 254 + .../samples/deprecated/proplist/makefile.dmc | 45 + .../samples/deprecated/proplist/makefile.dms | 213 + .../samples/deprecated/proplist/makefile.gcc | 254 + .../samples/deprecated/proplist/makefile.unx | 23 + .../samples/deprecated/proplist/makefile.vc | 360 + .../samples/deprecated/proplist/makefile.wat | 283 + .../samples/deprecated/proplist/proplist.bkl | 17 + .../samples/deprecated/proplist/proplist.cpp | 414 + .../samples/deprecated/proplist/proplist.dsp | 480 + .../samples/deprecated/proplist/proplist.h | 124 + .../samples/deprecated/proplist/proplist.pro | 17 + .../samples/deprecated/proplist/proplist.rc | 5 + .../samples/deprecated/proplist/proplist.vcp | 1826 + .../samples/deprecated/proplist/proplist.vcw | 17 + .../deprecated/proplist/proplistM5.xml | 3685 + .../samples/deprecated/proplist/tick.bmp | Bin 0 -> 198 bytes .../samples/deprecated/resource/Makefile.in | 198 + .../samples/deprecated/resource/descrip.mms | 47 + .../samples/deprecated/resource/dialog1.h | 14 + .../samples/deprecated/resource/dialog1.wxr | 26 + .../samples/deprecated/resource/makefile.bcc | 254 + .../samples/deprecated/resource/makefile.dmc | 45 + .../samples/deprecated/resource/makefile.dms | 213 + .../samples/deprecated/resource/makefile.gcc | 254 + .../samples/deprecated/resource/makefile.unx | 35 + .../samples/deprecated/resource/makefile.vc | 360 + .../samples/deprecated/resource/makefile.vms | 38 + .../samples/deprecated/resource/makefile.wat | 283 + .../samples/deprecated/resource/menu1.wxr | 13 + .../samples/deprecated/resource/resource.bkl | 18 + .../samples/deprecated/resource/resource.cpp | 217 + .../samples/deprecated/resource/resource.dsp | 480 + .../samples/deprecated/resource/resource.h | 65 + .../samples/deprecated/resource/resource.pro | 17 + .../samples/deprecated/resource/resource.rc | 10 + .../samples/deprecated/resource/resource.vcp | 1826 + .../samples/deprecated/resource/resource.vcw | 17 + .../deprecated/resource/resourceM5.xml | 3685 + .../samples/deprecated/treelay/Makefile.in | 198 + .../samples/deprecated/treelay/makefile.bcc | 254 + .../samples/deprecated/treelay/makefile.dmc | 45 + .../samples/deprecated/treelay/makefile.dms | 213 + .../samples/deprecated/treelay/makefile.gcc | 254 + .../samples/deprecated/treelay/makefile.unx | 23 + .../samples/deprecated/treelay/makefile.vc | 360 + .../samples/deprecated/treelay/makefile.wat | 283 + .../samples/deprecated/treelay/mondrian.ico | Bin 0 -> 766 bytes .../samples/deprecated/treelay/treelay.bkl | 18 + .../samples/deprecated/treelay/treelay.cpp | 223 + .../samples/deprecated/treelay/treelay.dsp | 480 + .../samples/deprecated/treelay/treelay.h | 55 + .../samples/deprecated/treelay/treelay.pro | 17 + .../samples/deprecated/treelay/treelay.rc | 3 + .../samples/deprecated/treelay/treelay.vcp | 1826 + .../samples/deprecated/treelay/treelay.vcw | 17 + .../samples/deprecated/treelay/treelayM5.xml | 3685 + wx28X/contrib/samples/fl/Makefile.in | 479 + .../contrib/samples/fl/bitmaps/bookmarks.bmp | Bin 0 -> 1650 bytes .../contrib/samples/fl/bitmaps/class_icon.bmp | Bin 0 -> 214 bytes .../samples/fl/bitmaps/class_icon1.bmp | Bin 0 -> 246 bytes wx28X/contrib/samples/fl/bitmaps/copy.bmp | Bin 0 -> 1318 bytes wx28X/contrib/samples/fl/bitmaps/cut.bmp | Bin 0 -> 1318 bytes .../contrib/samples/fl/bitmaps/file_icon.bmp | Bin 0 -> 1334 bytes .../samples/fl/bitmaps/folder_icon.bmp | Bin 0 -> 1318 bytes .../contrib/samples/fl/bitmaps/help_icon.bmp | Bin 0 -> 214 bytes wx28X/contrib/samples/fl/bitmaps/new.bmp | Bin 0 -> 1582 bytes wx28X/contrib/samples/fl/bitmaps/nextmark.bmp | Bin 0 -> 1734 bytes wx28X/contrib/samples/fl/bitmaps/open.bmp | Bin 0 -> 1318 bytes wx28X/contrib/samples/fl/bitmaps/paste.bmp | Bin 0 -> 1318 bytes wx28X/contrib/samples/fl/bitmaps/prevmark.bmp | Bin 0 -> 1734 bytes wx28X/contrib/samples/fl/bitmaps/res_icon.bmp | Bin 0 -> 214 bytes wx28X/contrib/samples/fl/bitmaps/save.bmp | Bin 0 -> 1318 bytes wx28X/contrib/samples/fl/bitmaps/saveall.bmp | Bin 0 -> 1318 bytes wx28X/contrib/samples/fl/bitmaps/search.bmp | Bin 0 -> 370 bytes .../contrib/samples/fl/bitmaps/start95_dp.bmp | Bin 0 -> 3918 bytes .../contrib/samples/fl/bitmaps/start95_pr.bmp | Bin 0 -> 4086 bytes wx28X/contrib/samples/fl/bitmaps/tile.bmp | Bin 0 -> 1894 bytes wx28X/contrib/samples/fl/fl.bkl | 51 + wx28X/contrib/samples/fl/fl.vcw | 65 + wx28X/contrib/samples/fl/fl_demo1.cpp | 261 + wx28X/contrib/samples/fl/fl_demo1.h | 72 + wx28X/contrib/samples/fl/fl_demo1.rc | 3 + wx28X/contrib/samples/fl/fl_demo2.cpp | 984 + wx28X/contrib/samples/fl/fl_demo2.h | 160 + wx28X/contrib/samples/fl/fl_demo2.rc | 3 + wx28X/contrib/samples/fl/fl_fl_demo1.dsp | 480 + wx28X/contrib/samples/fl/fl_fl_demo1.vcp | 1826 + wx28X/contrib/samples/fl/fl_fl_demo2.dsp | 480 + wx28X/contrib/samples/fl/fl_fl_demo2.vcp | 1826 + wx28X/contrib/samples/fl/fl_fl_sample1.dsp | 480 + wx28X/contrib/samples/fl/fl_fl_sample1.vcp | 1826 + wx28X/contrib/samples/fl/fl_fl_sample2.dsp | 480 + wx28X/contrib/samples/fl/fl_fl_sample2.vcp | 1826 + wx28X/contrib/samples/fl/fl_fl_sample3.dsp | 480 + wx28X/contrib/samples/fl/fl_fl_sample3.vcp | 1826 + wx28X/contrib/samples/fl/fl_sample1.cpp | 197 + wx28X/contrib/samples/fl/fl_sample1.rc | 3 + wx28X/contrib/samples/fl/fl_sample2.cpp | 195 + wx28X/contrib/samples/fl/fl_sample2.rc | 3 + wx28X/contrib/samples/fl/fl_sample3.cpp | 338 + wx28X/contrib/samples/fl/fl_sample3.rc | 3 + wx28X/contrib/samples/fl/makefile.bcc | 361 + wx28X/contrib/samples/fl/makefile.dmc | 113 + wx28X/contrib/samples/fl/makefile.dms | 271 + wx28X/contrib/samples/fl/makefile.gcc | 346 + wx28X/contrib/samples/fl/makefile.vc | 543 + wx28X/contrib/samples/fl/makefile.wat | 403 + .../samples/foldbar/extended/Makefile.in | 211 + .../samples/foldbar/extended/extended.bkl | 20 + .../samples/foldbar/extended/extended.cpp | 540 + .../samples/foldbar/extended/extended.dsp | 480 + .../samples/foldbar/extended/extended.h | 106 + .../samples/foldbar/extended/extended.rc | 1 + .../samples/foldbar/extended/extended.vcp | 1826 + .../samples/foldbar/extended/extended.vcw | 17 + .../samples/foldbar/extended/makefile.bcc | 266 + .../samples/foldbar/extended/makefile.dmc | 45 + .../samples/foldbar/extended/makefile.dms | 225 + .../samples/foldbar/extended/makefile.gcc | 266 + .../samples/foldbar/extended/makefile.vc | 372 + .../samples/foldbar/extended/makefile.wat | 298 + .../samples/foldbar/foldpanelbar/Makefile.in | 211 + .../foldbar/foldpanelbar/foldpanelbartest.cpp | 243 + .../foldbar/foldpanelbar/foldpanelbartest.rc | 1 + .../samples/foldbar/foldpanelbar/foldtest.bkl | 20 + .../samples/foldbar/foldpanelbar/foldtest.dsp | 492 + .../samples/foldbar/foldpanelbar/foldtest.vcp | 1838 + .../samples/foldbar/foldpanelbar/foldtest.vcw | 17 + .../foldbar/foldpanelbar/foldtestpanel.cpp | 165 + .../foldbar/foldpanelbar/foldtestpanel.h | 111 + .../foldbar/foldpanelbar/layouttest.cpp | 141 + .../samples/foldbar/foldpanelbar/layouttest.h | 97 + .../samples/foldbar/foldpanelbar/makefile.bcc | 266 + .../samples/foldbar/foldpanelbar/makefile.dmc | 57 + .../samples/foldbar/foldpanelbar/makefile.dms | 222 + .../samples/foldbar/foldpanelbar/makefile.gcc | 266 + .../samples/foldbar/foldpanelbar/makefile.vc | 372 + .../samples/foldbar/foldpanelbar/makefile.wat | 295 + .../samples/foldbar/foldpanelbar/test.cpp | 207 + .../samples/foldbar/foldpanelbar/test.h | 111 + wx28X/contrib/samples/gizmos/Makefile.in | 10 + .../samples/gizmos/dynsash/Makefile.in | 202 + .../samples/gizmos/dynsash/dynsash.bkl | 17 + .../samples/gizmos/dynsash/dynsash.cpp | 114 + .../samples/gizmos/dynsash/dynsash.dsp | 480 + .../samples/gizmos/dynsash/dynsash.vcp | 1826 + .../samples/gizmos/dynsash/dynsash.vcw | 17 + .../samples/gizmos/dynsash/makefile.bcc | 258 + .../samples/gizmos/dynsash/makefile.dmc | 45 + .../samples/gizmos/dynsash/makefile.dms | 217 + .../samples/gizmos/dynsash/makefile.gcc | 258 + .../samples/gizmos/dynsash/makefile.vc | 364 + .../samples/gizmos/dynsash/makefile.wat | 288 + .../samples/gizmos/dynsash_switch/Makefile.in | 202 + .../gizmos/dynsash_switch/dynsash_switch.bkl | 16 + .../gizmos/dynsash_switch/dynsash_switch.cpp | 263 + .../gizmos/dynsash_switch/dynsash_switch.dsp | 480 + .../gizmos/dynsash_switch/dynsash_switch.vcp | 1826 + .../gizmos/dynsash_switch/dynsash_switch.vcw | 17 + .../gizmos/dynsash_switch/makefile.bcc | 254 + .../gizmos/dynsash_switch/makefile.dmc | 46 + .../gizmos/dynsash_switch/makefile.dms | 213 + .../gizmos/dynsash_switch/makefile.gcc | 254 + .../samples/gizmos/dynsash_switch/makefile.vc | 360 + .../gizmos/dynsash_switch/makefile.wat | 283 + .../samples/gizmos/editlbox/Makefile.in | 198 + .../samples/gizmos/editlbox/editlbox.bkl | 16 + .../samples/gizmos/editlbox/editlbox.dsp | 480 + .../samples/gizmos/editlbox/editlbox.vcp | 1826 + .../samples/gizmos/editlbox/editlbox.vcw | 17 + .../samples/gizmos/editlbox/makefile.bcc | 254 + .../samples/gizmos/editlbox/makefile.dmc | 45 + .../samples/gizmos/editlbox/makefile.dms | 213 + .../samples/gizmos/editlbox/makefile.gcc | 253 + .../samples/gizmos/editlbox/makefile.vc | 360 + .../samples/gizmos/editlbox/makefile.wat | 283 + .../contrib/samples/gizmos/editlbox/test.cpp | 64 + wx28X/contrib/samples/gizmos/led/Makefile.in | 197 + wx28X/contrib/samples/gizmos/led/led.bkl | 16 + wx28X/contrib/samples/gizmos/led/led.cpp | 380 + wx28X/contrib/samples/gizmos/led/led.dsp | 480 + wx28X/contrib/samples/gizmos/led/led.vcp | 1826 + wx28X/contrib/samples/gizmos/led/led.vcw | 17 + wx28X/contrib/samples/gizmos/led/makefile.bcc | 254 + wx28X/contrib/samples/gizmos/led/makefile.dmc | 45 + wx28X/contrib/samples/gizmos/led/makefile.dms | 213 + wx28X/contrib/samples/gizmos/led/makefile.gcc | 253 + wx28X/contrib/samples/gizmos/led/makefile.vc | 360 + wx28X/contrib/samples/gizmos/led/makefile.wat | 283 + .../samples/gizmos/multicell/Makefile.in | 198 + .../samples/gizmos/multicell/makefile.bcc | 254 + .../samples/gizmos/multicell/makefile.dmc | 45 + .../samples/gizmos/multicell/makefile.dms | 213 + .../samples/gizmos/multicell/makefile.gcc | 254 + .../samples/gizmos/multicell/makefile.sl | 15 + .../samples/gizmos/multicell/makefile.unx | 24 + .../samples/gizmos/multicell/makefile.vc | 360 + .../samples/gizmos/multicell/makefile.wat | 283 + .../samples/gizmos/multicell/mtest.cpp | 211 + .../samples/gizmos/multicell/multicell.bkl | 16 + .../samples/gizmos/multicell/multicell.dsp | 480 + .../samples/gizmos/multicell/multicell.vcp | 1826 + .../samples/gizmos/multicell/multicell.vcw | 17 + .../samples/gizmos/multicell/multicell.vpj | 18 + .../samples/gizmos/splittree/Makefile.in | 198 + .../samples/gizmos/splittree/makefile.bcc | 254 + .../samples/gizmos/splittree/makefile.dmc | 45 + .../samples/gizmos/splittree/makefile.dms | 213 + .../samples/gizmos/splittree/makefile.gcc | 254 + .../samples/gizmos/splittree/makefile.sl | 18 + .../samples/gizmos/splittree/makefile.unx | 35 + .../samples/gizmos/splittree/makefile.va | 26 + .../samples/gizmos/splittree/makefile.vc | 360 + .../samples/gizmos/splittree/makefile.wat | 283 + .../samples/gizmos/splittree/mondrian.ico | Bin 0 -> 766 bytes .../samples/gizmos/splittree/mondrian.xpm | 44 + .../samples/gizmos/splittree/splittree.bkl | 16 + .../samples/gizmos/splittree/splittree.dsp | 480 + .../samples/gizmos/splittree/splittree.vcp | 1826 + .../samples/gizmos/splittree/splittree.vcw | 17 + .../contrib/samples/gizmos/splittree/tree.cpp | 289 + wx28X/contrib/samples/gizmos/splittree/tree.h | 108 + wx28X/contrib/samples/mmedia/Makefile.in | 203 + wx28X/contrib/samples/mmedia/descrip.mms | 30 + wx28X/contrib/samples/mmedia/eject.xpm | 24 + wx28X/contrib/samples/mmedia/makefile.bcc | 257 + wx28X/contrib/samples/mmedia/makefile.dmc | 49 + wx28X/contrib/samples/mmedia/makefile.dms | 216 + wx28X/contrib/samples/mmedia/makefile.gcc | 257 + wx28X/contrib/samples/mmedia/makefile.vc | 363 + wx28X/contrib/samples/mmedia/makefile.wat | 287 + wx28X/contrib/samples/mmedia/mmbman.cpp | 531 + wx28X/contrib/samples/mmedia/mmbman.h | 80 + wx28X/contrib/samples/mmedia/mmboard.bkl | 23 + wx28X/contrib/samples/mmedia/mmboard.cpp | 592 + wx28X/contrib/samples/mmedia/mmboard.dsp | 484 + wx28X/contrib/samples/mmedia/mmboard.h | 53 + wx28X/contrib/samples/mmedia/mmboard.rc | 6 + wx28X/contrib/samples/mmedia/mmboard.rc0 | 6 + wx28X/contrib/samples/mmedia/mmboard.vcp | 1830 + wx28X/contrib/samples/mmedia/mmboard.vcw | 17 + wx28X/contrib/samples/mmedia/mondrian.ico | Bin 0 -> 766 bytes wx28X/contrib/samples/mmedia/mondrian.xpm | 44 + wx28X/contrib/samples/mmedia/mondros2.ico | Bin 0 -> 996 bytes wx28X/contrib/samples/mmedia/pause.xpm | 23 + wx28X/contrib/samples/mmedia/play.xpm | 23 + wx28X/contrib/samples/mmedia/stop.xpm | 23 + wx28X/contrib/samples/ogl/Makefile.in | 12 + wx28X/contrib/samples/ogl/ogledit/Makefile.in | 210 + .../samples/ogl/ogledit/bitmaps/arrow.xpm | 44 + .../samples/ogl/ogledit/bitmaps/tool1.xpm | 44 + .../samples/ogl/ogledit/bitmaps/tool2.xpm | 44 + .../samples/ogl/ogledit/bitmaps/tool3.xpm | 44 + .../samples/ogl/ogledit/bitmaps/tool4.xpm | 44 + wx28X/contrib/samples/ogl/ogledit/doc.cpp | 622 + wx28X/contrib/samples/ogl/ogledit/doc.h | 185 + .../contrib/samples/ogl/ogledit/makefile.bcc | 266 + .../contrib/samples/ogl/ogledit/makefile.dmc | 57 + .../contrib/samples/ogl/ogledit/makefile.dms | 222 + .../contrib/samples/ogl/ogledit/makefile.gcc | 266 + .../contrib/samples/ogl/ogledit/makefile.unx | 38 + wx28X/contrib/samples/ogl/ogledit/makefile.vc | 372 + .../contrib/samples/ogl/ogledit/makefile.vms | 44 + .../contrib/samples/ogl/ogledit/makefile.wat | 295 + wx28X/contrib/samples/ogl/ogledit/ogl.ico | Bin 0 -> 766 bytes wx28X/contrib/samples/ogl/ogledit/ogl.xpm | 45 + wx28X/contrib/samples/ogl/ogledit/ogledit.bkl | 22 + wx28X/contrib/samples/ogl/ogledit/ogledit.cpp | 210 + wx28X/contrib/samples/ogl/ogledit/ogledit.dsp | 492 + wx28X/contrib/samples/ogl/ogledit/ogledit.h | 75 + wx28X/contrib/samples/ogl/ogledit/ogledit.rc | 4 + wx28X/contrib/samples/ogl/ogledit/ogledit.vcp | 1838 + wx28X/contrib/samples/ogl/ogledit/ogledit.vcw | 17 + wx28X/contrib/samples/ogl/ogledit/palette.cpp | 103 + wx28X/contrib/samples/ogl/ogledit/palette.h | 62 + wx28X/contrib/samples/ogl/ogledit/view.cpp | 329 + wx28X/contrib/samples/ogl/ogledit/view.h | 73 + wx28X/contrib/samples/ogl/studio/Makefile.in | 259 + .../samples/ogl/studio/bitmaps/alignb.xpm | 24 + .../samples/ogl/studio/bitmaps/alignl.xpm | 24 + .../samples/ogl/studio/bitmaps/alignr.xpm | 24 + .../samples/ogl/studio/bitmaps/alignt.xpm | 24 + .../samples/ogl/studio/bitmaps/arrow.bmp | Bin 0 -> 382 bytes .../samples/ogl/studio/bitmaps/arrow.xpm | 31 + .../samples/ogl/studio/bitmaps/copy.xpm | 44 + .../samples/ogl/studio/bitmaps/copysize.xpm | 24 + .../samples/ogl/studio/bitmaps/cut.xpm | 46 + .../samples/ogl/studio/bitmaps/cutpoint.xpm | 25 + .../samples/ogl/studio/bitmaps/file1.ico | Bin 0 -> 1718 bytes .../samples/ogl/studio/bitmaps/folder1.ico | Bin 0 -> 1718 bytes .../samples/ogl/studio/bitmaps/help.xpm | 71 + .../samples/ogl/studio/bitmaps/helpcs.xpm | 24 + .../samples/ogl/studio/bitmaps/horiz.xpm | 24 + .../samples/ogl/studio/bitmaps/linearrow.xpm | 25 + .../samples/ogl/studio/bitmaps/new.xpm | 52 + .../samples/ogl/studio/bitmaps/newpoint.xpm | 25 + .../samples/ogl/studio/bitmaps/open.xpm | 57 + .../samples/ogl/studio/bitmaps/paste.xpm | 46 + .../samples/ogl/studio/bitmaps/preview.xpm | 51 + .../samples/ogl/studio/bitmaps/print.xpm | 56 + .../samples/ogl/studio/bitmaps/redo.xpm | 58 + .../samples/ogl/studio/bitmaps/save.xpm | 42 + .../samples/ogl/studio/bitmaps/straight.xpm | 24 + .../samples/ogl/studio/bitmaps/texttool.bmp | Bin 0 -> 382 bytes .../samples/ogl/studio/bitmaps/texttool.xpm | 31 + .../samples/ogl/studio/bitmaps/tick.bmp | Bin 0 -> 220 bytes .../samples/ogl/studio/bitmaps/tick.xpm | Bin 0 -> 6121 bytes .../samples/ogl/studio/bitmaps/undo.xpm | 58 + .../samples/ogl/studio/bitmaps/vert.xpm | 24 + .../contrib/samples/ogl/studio/cspalette.cpp | 202 + wx28X/contrib/samples/ogl/studio/cspalette.h | 50 + wx28X/contrib/samples/ogl/studio/csprint.cpp | 320 + wx28X/contrib/samples/ogl/studio/dialogs.cpp | 532 + wx28X/contrib/samples/ogl/studio/dialogs.h | 249 + wx28X/contrib/samples/ogl/studio/doc.cpp | 593 + wx28X/contrib/samples/ogl/studio/doc.h | 133 + wx28X/contrib/samples/ogl/studio/mainfrm.cpp | 279 + wx28X/contrib/samples/ogl/studio/mainfrm.h | 54 + wx28X/contrib/samples/ogl/studio/makefile.bcc | 306 + wx28X/contrib/samples/ogl/studio/makefile.dmc | 85 + wx28X/contrib/samples/ogl/studio/makefile.dms | 258 + wx28X/contrib/samples/ogl/studio/makefile.gcc | 306 + wx28X/contrib/samples/ogl/studio/makefile.unx | 56 + wx28X/contrib/samples/ogl/studio/makefile.vc | 412 + wx28X/contrib/samples/ogl/studio/makefile.wat | 338 + .../samples/ogl/studio/manual/alignb.bmp | Bin 0 -> 238 bytes .../samples/ogl/studio/manual/alignl.bmp | Bin 0 -> 238 bytes .../samples/ogl/studio/manual/alignr.bmp | Bin 0 -> 238 bytes .../samples/ogl/studio/manual/alignt.bmp | Bin 0 -> 238 bytes .../samples/ogl/studio/manual/arrow.bmp | Bin 0 -> 382 bytes .../samples/ogl/studio/manual/back.gif | Bin 0 -> 225 bytes .../samples/ogl/studio/manual/bullet.bmp | Bin 0 -> 138 bytes .../samples/ogl/studio/manual/contents.gif | Bin 0 -> 996 bytes .../samples/ogl/studio/manual/copy.bmp | Bin 0 -> 1318 bytes .../samples/ogl/studio/manual/copysize.bmp | Bin 0 -> 238 bytes .../contrib/samples/ogl/studio/manual/cut.bmp | Bin 0 -> 1318 bytes .../samples/ogl/studio/manual/cutpoint.bmp | Bin 0 -> 238 bytes .../samples/ogl/studio/manual/forward.gif | Bin 0 -> 164 bytes .../samples/ogl/studio/manual/help.bmp | Bin 0 -> 1318 bytes .../samples/ogl/studio/manual/helpcs.bmp | Bin 0 -> 1318 bytes .../samples/ogl/studio/manual/horiz.bmp | Bin 0 -> 238 bytes .../samples/ogl/studio/manual/linearrow.bmp | Bin 0 -> 238 bytes .../contrib/samples/ogl/studio/manual/new.bmp | Bin 0 -> 1318 bytes .../samples/ogl/studio/manual/newpoint.bmp | Bin 0 -> 238 bytes .../samples/ogl/studio/manual/open.bmp | Bin 0 -> 1318 bytes .../samples/ogl/studio/manual/paste.bmp | Bin 0 -> 1318 bytes .../samples/ogl/studio/manual/pointsize.bmp | Bin 0 -> 538 bytes .../samples/ogl/studio/manual/preview.bmp | Bin 0 -> 1318 bytes .../samples/ogl/studio/manual/print.bmp | Bin 0 -> 1318 bytes .../samples/ogl/studio/manual/redo.bmp | Bin 0 -> 1318 bytes .../samples/ogl/studio/manual/save.bmp | Bin 0 -> 1318 bytes .../samples/ogl/studio/manual/straight.bmp | Bin 0 -> 238 bytes .../samples/ogl/studio/manual/studio.cnt | 34 + .../samples/ogl/studio/manual/studio.hlp | Bin 0 -> 22901 bytes .../samples/ogl/studio/manual/studio.hpj | 23 + .../samples/ogl/studio/manual/studio.tex | 381 + .../samples/ogl/studio/manual/tex2rtf.ini | 20 + .../samples/ogl/studio/manual/texttool.bmp | Bin 0 -> 382 bytes .../samples/ogl/studio/manual/tick.bmp | Bin 0 -> 220 bytes .../samples/ogl/studio/manual/toback.bmp | Bin 0 -> 238 bytes .../samples/ogl/studio/manual/tofront.bmp | Bin 0 -> 238 bytes .../samples/ogl/studio/manual/tool1.bmp | Bin 0 -> 382 bytes .../samples/ogl/studio/manual/tool2.bmp | Bin 0 -> 382 bytes .../samples/ogl/studio/manual/tool3.bmp | Bin 0 -> 382 bytes .../samples/ogl/studio/manual/tool4.bmp | Bin 0 -> 382 bytes .../samples/ogl/studio/manual/undo.bmp | Bin 0 -> 1318 bytes .../contrib/samples/ogl/studio/manual/up.gif | Bin 0 -> 137 bytes .../samples/ogl/studio/manual/vert.bmp | Bin 0 -> 238 bytes .../samples/ogl/studio/manual/zoom.bmp | Bin 0 -> 790 bytes wx28X/contrib/samples/ogl/studio/project.cpp | 88 + wx28X/contrib/samples/ogl/studio/project.h | 41 + wx28X/contrib/samples/ogl/studio/shapes.cpp | 1197 + wx28X/contrib/samples/ogl/studio/shapes.h | 264 + wx28X/contrib/samples/ogl/studio/studio.bkl | 37 + wx28X/contrib/samples/ogl/studio/studio.cpp | 502 + wx28X/contrib/samples/ogl/studio/studio.dsp | 516 + wx28X/contrib/samples/ogl/studio/studio.h | 177 + wx28X/contrib/samples/ogl/studio/studio.ico | Bin 0 -> 766 bytes wx28X/contrib/samples/ogl/studio/studio.rc | 18 + wx28X/contrib/samples/ogl/studio/studio.vcp | 1862 + wx28X/contrib/samples/ogl/studio/studio.vcw | 17 + wx28X/contrib/samples/ogl/studio/studio.xpm | 44 + .../samples/ogl/studio/studio_resources.h | 44 + .../samples/ogl/studio/studio_resources.wxr | 191 + wx28X/contrib/samples/ogl/studio/symbols.cpp | 217 + wx28X/contrib/samples/ogl/studio/symbols.h | 71 + wx28X/contrib/samples/ogl/studio/view.cpp | 1038 + wx28X/contrib/samples/ogl/studio/view.h | 137 + wx28X/contrib/samples/plot/Makefile.in | 198 + wx28X/contrib/samples/plot/makefile.bcc | 253 + wx28X/contrib/samples/plot/makefile.dmc | 45 + wx28X/contrib/samples/plot/makefile.dms | 213 + wx28X/contrib/samples/plot/makefile.gcc | 253 + wx28X/contrib/samples/plot/makefile.vc | 359 + wx28X/contrib/samples/plot/makefile.wat | 283 + wx28X/contrib/samples/plot/plot.bkl | 17 + wx28X/contrib/samples/plot/plot.cpp | 204 + wx28X/contrib/samples/plot/plot.dsp | 480 + wx28X/contrib/samples/plot/plot.rc | 2 + wx28X/contrib/samples/plot/plot.vcp | 1826 + wx28X/contrib/samples/plot/plot.vcw | 17 + wx28X/contrib/samples/stc/Makefile.in | 218 + wx28X/contrib/samples/stc/defsext.h | 107 + wx28X/contrib/samples/stc/edit.cpp | 834 + wx28X/contrib/samples/stc/edit.h | 172 + wx28X/contrib/samples/stc/makefile.bcc | 265 + wx28X/contrib/samples/stc/makefile.dmc | 57 + wx28X/contrib/samples/stc/makefile.dms | 225 + wx28X/contrib/samples/stc/makefile.gcc | 265 + wx28X/contrib/samples/stc/makefile.vc | 371 + wx28X/contrib/samples/stc/makefile.wat | 295 + wx28X/contrib/samples/stc/mondrian.ico | Bin 0 -> 766 bytes wx28X/contrib/samples/stc/mondrian.xpm | 44 + wx28X/contrib/samples/stc/prefs.cpp | 378 + wx28X/contrib/samples/stc/prefs.h | 152 + wx28X/contrib/samples/stc/stctest.bkl | 24 + wx28X/contrib/samples/stc/stctest.cpp | 683 + wx28X/contrib/samples/stc/stctest.dsp | 488 + wx28X/contrib/samples/stc/stctest.rc | 4 + wx28X/contrib/samples/stc/stctest.vcp | 1834 + wx28X/contrib/samples/stc/stctest.vcw | 17 + wx28X/contrib/samples/svg/Makefile.in | 198 + wx28X/contrib/samples/svg/SVGlogo24.bmp | Bin 0 -> 9270 bytes wx28X/contrib/samples/svg/SVGlogo24.xpm | 310 + wx28X/contrib/samples/svg/bitmaps/help.xpm | 71 + wx28X/contrib/samples/svg/bitmaps/new.xpm | 52 + wx28X/contrib/samples/svg/bitmaps/save.xpm | 42 + wx28X/contrib/samples/svg/makefile.bcc | 253 + wx28X/contrib/samples/svg/makefile.dmc | 45 + wx28X/contrib/samples/svg/makefile.dms | 213 + wx28X/contrib/samples/svg/makefile.gcc | 253 + wx28X/contrib/samples/svg/makefile.vc | 359 + wx28X/contrib/samples/svg/makefile.wat | 283 + wx28X/contrib/samples/svg/mondrian.ico | Bin 0 -> 766 bytes wx28X/contrib/samples/svg/mondrian.xpm | 44 + wx28X/contrib/samples/svg/svgtest.bkl | 15 + wx28X/contrib/samples/svg/svgtest.cpp | 629 + wx28X/contrib/samples/svg/svgtest.dsp | 480 + wx28X/contrib/samples/svg/svgtest.rc | 11 + wx28X/contrib/samples/svg/svgtest.vcp | 1826 + wx28X/contrib/samples/svg/svgtest.vcw | 17 + wx28X/contrib/src/Makefile.in | 18 + wx28X/contrib/src/applet/applet.cpp | 81 + wx28X/contrib/src/applet/appletwindow.cpp | 833 + wx28X/contrib/src/applet/echovar.cpp | 222 + wx28X/contrib/src/applet/ifelsevar.cpp | 232 + wx28X/contrib/src/applet/loadpage.cpp | 72 + wx28X/contrib/src/applet/makefile | 33 + wx28X/contrib/src/applet/plugin.cpp | 65 + wx28X/contrib/src/applet/prepecho.cpp | 128 + wx28X/contrib/src/applet/prepifelse.cpp | 441 + wx28X/contrib/src/applet/prepinclude.cpp | 173 + wx28X/contrib/src/deprecated/Makefile.in | 387 + wx28X/contrib/src/deprecated/cwlex_yy.c | 1216 + wx28X/contrib/src/deprecated/cwy_tab.c | 549 + wx28X/contrib/src/deprecated/descrip.mms | 102 + wx28X/contrib/src/deprecated/doslex.c | 1336 + wx28X/contrib/src/deprecated/dosyacc.c | 552 + wx28X/contrib/src/deprecated/lexer.l | 194 + wx28X/contrib/src/deprecated/parser.y | 186 + wx28X/contrib/src/deprecated/prop.cpp | 1169 + wx28X/contrib/src/deprecated/propform.cpp | 759 + wx28X/contrib/src/deprecated/proplist.cpp | 1819 + wx28X/contrib/src/deprecated/resource.cpp | 3297 + wx28X/contrib/src/deprecated/tbarsmpl.cpp | 1007 + wx28X/contrib/src/deprecated/treelay.cpp | 469 + wx28X/contrib/src/deprecated/wxexpr.cpp | 1281 + wx28X/contrib/src/fl/Makefile.in | 437 + wx28X/contrib/src/fl/antiflickpl.cpp | 229 + wx28X/contrib/src/fl/bardragpl.cpp | 934 + wx28X/contrib/src/fl/barhintspl.cpp | 567 + wx28X/contrib/src/fl/cbcustom.cpp | 195 + wx28X/contrib/src/fl/controlbar.cpp | 3519 + wx28X/contrib/src/fl/dyntbar.cpp | 614 + wx28X/contrib/src/fl/dyntbarhnd.cpp | 43 + wx28X/contrib/src/fl/files.lst | 19 + wx28X/contrib/src/fl/frmview.cpp | 442 + wx28X/contrib/src/fl/garbagec.cpp | 216 + wx28X/contrib/src/fl/gcupdatesmgr.cpp | 406 + wx28X/contrib/src/fl/hintanimpl.cpp | 393 + wx28X/contrib/src/fl/makedocs.vc | 107 + wx28X/contrib/src/fl/newbmpbtn.cpp | 851 + wx28X/contrib/src/fl/panedrawpl.cpp | 1284 + wx28X/contrib/src/fl/rowdragpl.cpp | 1451 + wx28X/contrib/src/fl/rowlayoutpl.cpp | 1220 + wx28X/contrib/src/fl/toolwnd.cpp | 1108 + wx28X/contrib/src/fl/updatesmgr.cpp | 288 + wx28X/contrib/src/foldbar/Makefile.in | 328 + wx28X/contrib/src/foldbar/captionbar.cpp | 433 + wx28X/contrib/src/foldbar/foldpanelbar.cpp | 373 + wx28X/contrib/src/foldbar/foldpanelitem.cpp | 251 + .../src/foldbar/icon_collapsed.old.xpm | 22 + wx28X/contrib/src/foldbar/icon_collapsed.xpm | 36 + .../contrib/src/foldbar/icon_expanded.old.xpm | 22 + wx28X/contrib/src/foldbar/icon_expanded.xpm | 36 + wx28X/contrib/src/foldbar/icon_theresmore.xpm | 30 + wx28X/contrib/src/gizmos/Makefile.in | 505 + wx28X/contrib/src/gizmos/dynamicsash.cpp | 1471 + wx28X/contrib/src/gizmos/editlbox.cpp | 270 + wx28X/contrib/src/gizmos/eldel.xpm | 22 + wx28X/contrib/src/gizmos/eldown.xpm | 21 + wx28X/contrib/src/gizmos/eledit.xpm | 22 + wx28X/contrib/src/gizmos/elnew.xpm | 24 + wx28X/contrib/src/gizmos/elup.xpm | 21 + wx28X/contrib/src/gizmos/ledctrl.cpp | 392 + wx28X/contrib/src/gizmos/makedocs.vc | 108 + wx28X/contrib/src/gizmos/multicell.cpp | 653 + wx28X/contrib/src/gizmos/multicell.txt | 130 + wx28X/contrib/src/gizmos/multicell_todo.txt | 2 + wx28X/contrib/src/gizmos/splittree.cpp | 793 + wx28X/contrib/src/gizmos/statpict.cpp | 148 + wx28X/contrib/src/gizmos/statpict.txt | 34 + wx28X/contrib/src/gizmos/xh_statpict.cpp | 52 + wx28X/contrib/src/mmedia/Makefile.in | 503 + wx28X/contrib/src/mmedia/cdbase.cpp | 66 + wx28X/contrib/src/mmedia/cdunix.cpp | 219 + wx28X/contrib/src/mmedia/cdwin.cpp | 223 + wx28X/contrib/src/mmedia/g711.cpp | 285 + wx28X/contrib/src/mmedia/g721.cpp | 175 + wx28X/contrib/src/mmedia/g723_24.cpp | 159 + wx28X/contrib/src/mmedia/g723_40.cpp | 179 + wx28X/contrib/src/mmedia/g72x.cpp | 611 + wx28X/contrib/src/mmedia/makedocs.vc | 107 + wx28X/contrib/src/mmedia/sndaiff.cpp | 206 + wx28X/contrib/src/mmedia/sndbase.cpp | 141 + wx28X/contrib/src/mmedia/sndcodec.cpp | 45 + wx28X/contrib/src/mmedia/sndcpcm.cpp | 446 + wx28X/contrib/src/mmedia/sndesd.cpp | 359 + wx28X/contrib/src/mmedia/sndfile.cpp | 426 + wx28X/contrib/src/mmedia/sndg72x.cpp | 307 + wx28X/contrib/src/mmedia/sndmsad.cpp | 387 + wx28X/contrib/src/mmedia/sndoss.cpp | 386 + wx28X/contrib/src/mmedia/sndpcm.cpp | 96 + wx28X/contrib/src/mmedia/sndulaw.cpp | 184 + wx28X/contrib/src/mmedia/sndwav.cpp | 420 + wx28X/contrib/src/mmedia/sndwin.cpp | 780 + wx28X/contrib/src/mmedia/vidbase.cpp | 72 + wx28X/contrib/src/mmedia/vidwin.cpp | 248 + wx28X/contrib/src/mmedia/vidxanm.cpp | 511 + wx28X/contrib/src/net/Makefile.in | 330 + wx28X/contrib/src/net/email.cpp | 122 + wx28X/contrib/src/net/readme.txt | 10 + wx28X/contrib/src/net/smapi.cpp | 497 + wx28X/contrib/src/net/web.cpp | 25 + wx28X/contrib/src/ogl/Makefile.in | 397 + wx28X/contrib/src/ogl/basic.cpp | 3286 + wx28X/contrib/src/ogl/basic2.cpp | 1892 + wx28X/contrib/src/ogl/bmpshape.cpp | 108 + wx28X/contrib/src/ogl/canvas.cpp | 510 + wx28X/contrib/src/ogl/composit.cpp | 1774 + wx28X/contrib/src/ogl/constrnt.cpp | 620 + wx28X/contrib/src/ogl/divided.cpp | 701 + wx28X/contrib/src/ogl/drawn.cpp | 2486 + wx28X/contrib/src/ogl/lines.cpp | 2505 + wx28X/contrib/src/ogl/makedocs.vc | 107 + wx28X/contrib/src/ogl/mfutils.cpp | 1083 + wx28X/contrib/src/ogl/ogldiag.cpp | 742 + wx28X/contrib/src/ogl/oglmisc.cpp | 893 + wx28X/contrib/src/plot/Makefile.in | 311 + wx28X/contrib/src/plot/plot.cpp | 1194 + wx28X/contrib/src/stc/Makefile.in | 956 + wx28X/contrib/src/stc/PlatWX.cpp | 1581 + wx28X/contrib/src/stc/PlatWX.h | 8 + wx28X/contrib/src/stc/README.txt | 55 + wx28X/contrib/src/stc/ScintillaWX.cpp | 1151 + wx28X/contrib/src/stc/ScintillaWX.h | 196 + wx28X/contrib/src/stc/gen_iface.py | 896 + wx28X/contrib/src/stc/scintilla/License.txt | 20 + wx28X/contrib/src/stc/scintilla/README.txt | 7 + .../src/stc/scintilla/include/Accessor.h | 78 + .../src/stc/scintilla/include/KeyWords.h | 82 + .../src/stc/scintilla/include/Platform.h | 517 + .../src/stc/scintilla/include/PropSet.h | 114 + .../src/stc/scintilla/include/SString.h | 280 + .../src/stc/scintilla/include/SciLexer.h | 1074 + .../src/stc/scintilla/include/Scintilla.h | 780 + .../src/stc/scintilla/include/Scintilla.iface | 3013 + .../stc/scintilla/include/ScintillaWidget.h | 59 + .../stc/scintilla/include/WindowAccessor.h | 57 + .../src/stc/scintilla/src/AutoComplete.cxx | 174 + .../src/stc/scintilla/src/AutoComplete.h | 70 + .../contrib/src/stc/scintilla/src/CallTip.cxx | 314 + wx28X/contrib/src/stc/scintilla/src/CallTip.h | 79 + .../src/stc/scintilla/src/CellBuffer.cxx | 1120 + .../src/stc/scintilla/src/CellBuffer.h | 250 + .../src/stc/scintilla/src/CharClassify.cxx | 43 + .../src/stc/scintilla/src/CharClassify.h | 25 + .../stc/scintilla/src/ContractionState.cxx | 289 + .../src/stc/scintilla/src/ContractionState.h | 65 + .../src/stc/scintilla/src/Document.cxx | 1577 + .../contrib/src/stc/scintilla/src/Document.h | 305 + .../stc/scintilla/src/DocumentAccessor.cxx | 187 + .../src/stc/scintilla/src/DocumentAccessor.h | 67 + .../contrib/src/stc/scintilla/src/Editor.cxx | 7298 + wx28X/contrib/src/stc/scintilla/src/Editor.h | 582 + .../src/stc/scintilla/src/ExternalLexer.cxx | 259 + .../src/stc/scintilla/src/ExternalLexer.h | 95 + .../src/stc/scintilla/src/Indicator.cxx | 77 + .../contrib/src/stc/scintilla/src/Indicator.h | 22 + .../contrib/src/stc/scintilla/src/KeyMap.cxx | 148 + wx28X/contrib/src/stc/scintilla/src/KeyMap.h | 43 + .../src/stc/scintilla/src/KeyWords.cxx | 221 + .../contrib/src/stc/scintilla/src/LexAPDL.cxx | 136 + .../contrib/src/stc/scintilla/src/LexAU3.cxx | 891 + .../contrib/src/stc/scintilla/src/LexAVE.cxx | 225 + .../contrib/src/stc/scintilla/src/LexAda.cxx | 520 + .../contrib/src/stc/scintilla/src/LexAsm.cxx | 177 + .../contrib/src/stc/scintilla/src/LexAsn1.cxx | 181 + .../contrib/src/stc/scintilla/src/LexBaan.cxx | 189 + .../contrib/src/stc/scintilla/src/LexBash.cxx | 663 + .../src/stc/scintilla/src/LexBasic.cxx | 369 + .../src/stc/scintilla/src/LexBullant.cxx | 225 + .../contrib/src/stc/scintilla/src/LexCLW.cxx | 675 + .../contrib/src/stc/scintilla/src/LexCPP.cxx | 461 + .../contrib/src/stc/scintilla/src/LexCSS.cxx | 303 + .../contrib/src/stc/scintilla/src/LexCaml.cxx | 399 + .../contrib/src/stc/scintilla/src/LexConf.cxx | 184 + .../src/stc/scintilla/src/LexCrontab.cxx | 218 + .../src/stc/scintilla/src/LexCsound.cxx | 207 + .../src/stc/scintilla/src/LexEScript.cxx | 270 + .../src/stc/scintilla/src/LexEiffel.cxx | 234 + .../src/stc/scintilla/src/LexErlang.cxx | 522 + .../src/stc/scintilla/src/LexFlagship.cxx | 226 + .../src/stc/scintilla/src/LexForth.cxx | 348 + .../src/stc/scintilla/src/LexFortran.cxx | 452 + .../src/stc/scintilla/src/LexGui4Cli.cxx | 309 + .../contrib/src/stc/scintilla/src/LexHTML.cxx | 2042 + .../src/stc/scintilla/src/LexHaskell.cxx | 263 + .../contrib/src/stc/scintilla/src/LexInno.cxx | 290 + .../contrib/src/stc/scintilla/src/LexKix.cxx | 122 + .../contrib/src/stc/scintilla/src/LexLisp.cxx | 275 + .../contrib/src/stc/scintilla/src/LexLout.cxx | 208 + .../contrib/src/stc/scintilla/src/LexLua.cxx | 357 + .../src/stc/scintilla/src/LexMMIXAL.cxx | 183 + .../contrib/src/stc/scintilla/src/LexMPT.cxx | 182 + .../src/stc/scintilla/src/LexMSSQL.cxx | 359 + .../src/stc/scintilla/src/LexMatlab.cxx | 225 + .../src/stc/scintilla/src/LexMetapost.cxx | 320 + .../contrib/src/stc/scintilla/src/LexNsis.cxx | 647 + .../contrib/src/stc/scintilla/src/LexOpal.cxx | 518 + .../src/stc/scintilla/src/LexOthers.cxx | 1140 + wx28X/contrib/src/stc/scintilla/src/LexPB.cxx | 358 + .../contrib/src/stc/scintilla/src/LexPOV.cxx | 312 + wx28X/contrib/src/stc/scintilla/src/LexPS.cxx | 343 + .../src/stc/scintilla/src/LexPascal.cxx | 369 + .../contrib/src/stc/scintilla/src/LexPerl.cxx | 1232 + .../src/stc/scintilla/src/LexPython.cxx | 449 + .../src/stc/scintilla/src/LexRebol.cxx | 319 + .../contrib/src/stc/scintilla/src/LexRuby.cxx | 1542 + .../contrib/src/stc/scintilla/src/LexSQL.cxx | 342 + .../src/stc/scintilla/src/LexScriptol.cxx | 404 + .../src/stc/scintilla/src/LexSmalltalk.cxx | 317 + .../src/stc/scintilla/src/LexSpecman.cxx | 286 + .../src/stc/scintilla/src/LexSpice.cxx | 221 + .../src/stc/scintilla/src/LexTADS3.cxx | 837 + .../contrib/src/stc/scintilla/src/LexTCL.cxx | 362 + .../contrib/src/stc/scintilla/src/LexTeX.cxx | 288 + wx28X/contrib/src/stc/scintilla/src/LexVB.cxx | 270 + .../contrib/src/stc/scintilla/src/LexVHDL.cxx | 473 + .../src/stc/scintilla/src/LexVerilog.cxx | 299 + .../contrib/src/stc/scintilla/src/LexYAML.cxx | 305 + .../src/stc/scintilla/src/LineMarker.cxx | 301 + .../src/stc/scintilla/src/LineMarker.h | 54 + .../contrib/src/stc/scintilla/src/PropSet.cxx | 1170 + .../src/stc/scintilla/src/RESearch.cxx | 788 + .../contrib/src/stc/scintilla/src/RESearch.h | 65 + wx28X/contrib/src/stc/scintilla/src/SVector.h | 127 + .../src/stc/scintilla/src/ScintillaBase.cxx | 727 + .../src/stc/scintilla/src/ScintillaBase.h | 93 + wx28X/contrib/src/stc/scintilla/src/Style.cxx | 154 + wx28X/contrib/src/stc/scintilla/src/Style.h | 56 + .../src/stc/scintilla/src/StyleContext.cxx | 51 + .../src/stc/scintilla/src/StyleContext.h | 169 + .../src/stc/scintilla/src/UniConversion.cxx | 76 + .../src/stc/scintilla/src/UniConversion.h | 12 + .../src/stc/scintilla/src/ViewStyle.cxx | 297 + .../contrib/src/stc/scintilla/src/ViewStyle.h | 108 + .../src/stc/scintilla/src/WindowAccessor.cxx | 178 + wx28X/contrib/src/stc/scintilla/src/XPM.cxx | 322 + wx28X/contrib/src/stc/scintilla/src/XPM.h | 72 + wx28X/contrib/src/stc/stc.cpp | 3427 + wx28X/contrib/src/stc/stc.cpp.in | 1065 + wx28X/contrib/src/stc/stc.h.in | 542 + wx28X/contrib/src/stc/stcM8.xml | 7164 + wx28X/contrib/src/stc/stc_cw.h | 4 + wx28X/contrib/src/stc/stc_cw_d.h | 4 + wx28X/contrib/src/stc/stc_cwc.h | 4 + wx28X/contrib/src/stc/stc_cwc_d.h | 4 + wx28X/contrib/src/svg/Makefile.in | 309 + wx28X/contrib/src/svg/README.TXT | 21 + wx28X/contrib/src/svg/dcsvg.cpp | 869 + wx28X/contrib/src/svg/makedocs.vc | 106 + wx28X/contrib/utils/Makefile.in | 10 + wx28X/contrib/utils/convertrc/Makefile.in | 193 + wx28X/contrib/utils/convertrc/convert.cpp | 221 + wx28X/contrib/utils/convertrc/convert.h | 50 + wx28X/contrib/utils/convertrc/convertrc.bkl | 23 + wx28X/contrib/utils/convertrc/convertrc.dsp | 492 + wx28X/contrib/utils/convertrc/convertrc.vcp | 1838 + wx28X/contrib/utils/convertrc/convertrc.vcw | 17 + wx28X/contrib/utils/convertrc/makefile.bcc | 269 + wx28X/contrib/utils/convertrc/makefile.dmc | 57 + wx28X/contrib/utils/convertrc/makefile.dms | 226 + wx28X/contrib/utils/convertrc/makefile.gcc | 269 + wx28X/contrib/utils/convertrc/makefile.vc | 375 + wx28X/contrib/utils/convertrc/makefile.wat | 300 + wx28X/contrib/utils/convertrc/rc2wxr.cpp | 797 + wx28X/contrib/utils/convertrc/rc2wxr.h | 47 + wx28X/contrib/utils/convertrc/rc2xml.cpp | 1425 + wx28X/contrib/utils/convertrc/rc2xml.h | 96 + wx28X/contrib/utils/convertrc/wxconvert.rc | 1 + wx28X/contrib/utils/convertrc/wxr2xml.cpp | 832 + wx28X/contrib/utils/convertrc/wxr2xml.h | 78 + wx28X/demos/Makefile.in | 73 + wx28X/demos/bombs/Makefile.in | 205 + wx28X/demos/bombs/bombs.bkl | 13 + wx28X/demos/bombs/bombs.cpp | 327 + wx28X/demos/bombs/bombs.dsp | 488 + wx28X/demos/bombs/bombs.h | 129 + wx28X/demos/bombs/bombs.ico | Bin 0 -> 1078 bytes wx28X/demos/bombs/bombs.pro | 21 + wx28X/demos/bombs/bombs.rc | 3 + wx28X/demos/bombs/bombs.vcp | 1834 + wx28X/demos/bombs/bombs.vcw | 17 + wx28X/demos/bombs/bombs.xpm | 44 + wx28X/demos/bombs/bombs1.cpp | 350 + wx28X/demos/bombs/bombsM5.xml | 3811 + wx28X/demos/bombs/descrip.mms | 49 + wx28X/demos/bombs/game.cpp | 134 + wx28X/demos/bombs/game.h | 115 + wx28X/demos/bombs/makefile.bcc | 261 + wx28X/demos/bombs/makefile.dmc | 53 + wx28X/demos/bombs/makefile.dms | 219 + wx28X/demos/bombs/makefile.gcc | 261 + wx28X/demos/bombs/makefile.unx | 35 + wx28X/demos/bombs/makefile.vc | 367 + wx28X/demos/bombs/makefile.wat | 290 + wx28X/demos/bombs/readme.txt | 78 + wx28X/demos/dbbrowse/Makefile.in | 272 + wx28X/demos/dbbrowse/bitmaps/col.ico | Bin 0 -> 1078 bytes wx28X/demos/dbbrowse/bitmaps/col.xpm | 25 + wx28X/demos/dbbrowse/bitmaps/d_closed.ico | Bin 0 -> 318 bytes wx28X/demos/dbbrowse/bitmaps/d_closed.xpm | 26 + wx28X/demos/dbbrowse/bitmaps/d_open.ico | Bin 0 -> 318 bytes wx28X/demos/dbbrowse/bitmaps/d_open.xpm | 26 + wx28X/demos/dbbrowse/bitmaps/dsn.ico | Bin 0 -> 318 bytes wx28X/demos/dbbrowse/bitmaps/dsn.xpm | 25 + wx28X/demos/dbbrowse/bitmaps/dsnclose.ico | Bin 0 -> 318 bytes wx28X/demos/dbbrowse/bitmaps/dsnclose.xpm | 26 + wx28X/demos/dbbrowse/bitmaps/dsnopen.ico | Bin 0 -> 318 bytes wx28X/demos/dbbrowse/bitmaps/dsnopen.xpm | 26 + wx28X/demos/dbbrowse/bitmaps/f_closed.ico | Bin 0 -> 1718 bytes wx28X/demos/dbbrowse/bitmaps/f_closed.xpm | 134 + wx28X/demos/dbbrowse/bitmaps/f_open.ico | Bin 0 -> 1718 bytes wx28X/demos/dbbrowse/bitmaps/f_open.xpm | 78 + wx28X/demos/dbbrowse/bitmaps/key.ico | Bin 0 -> 318 bytes wx28X/demos/dbbrowse/bitmaps/key.xpm | 33 + wx28X/demos/dbbrowse/bitmaps/keyf.ico | Bin 0 -> 318 bytes wx28X/demos/dbbrowse/bitmaps/keyf.xpm | 34 + wx28X/demos/dbbrowse/bitmaps/logo.ico | Bin 0 -> 318 bytes wx28X/demos/dbbrowse/bitmaps/logo.xpm | 66 + wx28X/demos/dbbrowse/bitmaps/pgmctrl.bmp | Bin 0 -> 274 bytes wx28X/demos/dbbrowse/bitmaps/pgmctrl.ico | Bin 0 -> 1078 bytes wx28X/demos/dbbrowse/bitmaps/pgmctrl.xpm | 26 + wx28X/demos/dbbrowse/bitmaps/tab.ico | Bin 0 -> 318 bytes wx28X/demos/dbbrowse/bitmaps/tab.xpm | 27 + wx28X/demos/dbbrowse/bitmaps/view.ico | Bin 0 -> 318 bytes wx28X/demos/dbbrowse/bitmaps/view.xpm | 26 + wx28X/demos/dbbrowse/browsedb.cpp | 497 + wx28X/demos/dbbrowse/browsedb.h | 78 + wx28X/demos/dbbrowse/dbbrowse.bkl | 85 + wx28X/demos/dbbrowse/dbbrowse.cpp | 322 + wx28X/demos/dbbrowse/dbbrowse.dsp | 508 + wx28X/demos/dbbrowse/dbbrowse.h | 53 + wx28X/demos/dbbrowse/dbbrowse.rc | 15 + wx28X/demos/dbbrowse/dbbrowse.vcp | 1854 + wx28X/demos/dbbrowse/dbbrowse.vcw | 17 + wx28X/demos/dbbrowse/dbbrowseM5.xml | 4063 + wx28X/demos/dbbrowse/dbgrid.cpp | 424 + wx28X/demos/dbbrowse/dbgrid.h | 66 + wx28X/demos/dbbrowse/dbtree.cpp | 435 + wx28X/demos/dbbrowse/dbtree.h | 88 + wx28X/demos/dbbrowse/de/dbbrowse.mo | Bin 0 -> 9847 bytes wx28X/demos/dbbrowse/de/dbbrowse.po | 934 + wx28X/demos/dbbrowse/de/de.po | 1643 + wx28X/demos/dbbrowse/de/help.mo | Bin 0 -> 4222 bytes wx28X/demos/dbbrowse/de/help.po | 287 + wx28X/demos/dbbrowse/de/mo.cmd | 3 + wx28X/demos/dbbrowse/de/mo_de.cmd | 2 + wx28X/demos/dbbrowse/de/wxstd.mo | Bin 0 -> 17128 bytes wx28X/demos/dbbrowse/de/xget.cfg | 16 + wx28X/demos/dbbrowse/de/xget.cmd | 2 + wx28X/demos/dbbrowse/dlguser.cpp | 136 + wx28X/demos/dbbrowse/dlguser.h | 39 + wx28X/demos/dbbrowse/doc.cpp | 327 + wx28X/demos/dbbrowse/doc.h | 93 + wx28X/demos/dbbrowse/dummy.cpp | 30 + wx28X/demos/dbbrowse/fr/wxstd.mo | Bin 0 -> 1923 bytes wx28X/demos/dbbrowse/fr/xget.cfg | 16 + wx28X/demos/dbbrowse/help.cz/wxstd.mo | Bin 0 -> 23320 bytes wx28X/demos/dbbrowse/help.de/compiler.htm | 50 + wx28X/demos/dbbrowse/help.de/dbbrowse.hhc | 68 + wx28X/demos/dbbrowse/help.de/dbbrowse.hhk | 31 + wx28X/demos/dbbrowse/help.de/dbbrowse.hhp | 22 + wx28X/demos/dbbrowse/help.de/dbbrowse.htm | 24 + wx28X/demos/dbbrowse/help.de/getcol.htm | 118 + wx28X/demos/dbbrowse/help.de/getcolsh.htm | 50 + wx28X/demos/dbbrowse/help.de/icons.htm | 41 + wx28X/demos/dbbrowse/help.de/picgrams.htm | 37 + wx28X/demos/dbbrowse/help.de/problems.htm | 84 + wx28X/demos/dbbrowse/help.de/remstar.htm | 15 + wx28X/demos/dbbrowse/help.de/sample.htm | 25 + wx28X/demos/dbbrowse/help.de/startprm.htm | 24 + wx28X/demos/dbbrowse/help.de/todo.htm | 75 + wx28X/demos/dbbrowse/help.de/wxdb.htm | 26 + wx28X/demos/dbbrowse/help.de/wxtable.htm | 15 + wx28X/demos/dbbrowse/help.png/col.png | Bin 0 -> 1000 bytes wx28X/demos/dbbrowse/help.png/d_closed.png | Bin 0 -> 1206 bytes wx28X/demos/dbbrowse/help.png/d_open.png | Bin 0 -> 1211 bytes wx28X/demos/dbbrowse/help.png/dsn.png | Bin 0 -> 1011 bytes wx28X/demos/dbbrowse/help.png/dsnclose.png | Bin 0 -> 1023 bytes wx28X/demos/dbbrowse/help.png/dsnopen.png | Bin 0 -> 1024 bytes wx28X/demos/dbbrowse/help.png/f_closed.png | Bin 0 -> 1180 bytes wx28X/demos/dbbrowse/help.png/f_open.png | Bin 0 -> 1085 bytes wx28X/demos/dbbrowse/help.png/gnu.png | Bin 0 -> 458 bytes wx28X/demos/dbbrowse/help.png/gtk.png | Bin 0 -> 1158 bytes wx28X/demos/dbbrowse/help.png/imbau.png | Bin 0 -> 1647 bytes wx28X/demos/dbbrowse/help.png/kde.png | Bin 0 -> 458 bytes wx28X/demos/dbbrowse/help.png/key.png | Bin 0 -> 1037 bytes wx28X/demos/dbbrowse/help.png/keyf.png | Bin 0 -> 1038 bytes wx28X/demos/dbbrowse/help.png/linux.png | Bin 0 -> 412 bytes wx28X/demos/dbbrowse/help.png/logo.png | Bin 0 -> 1103 bytes wx28X/demos/dbbrowse/help.png/motif.png | Bin 0 -> 421 bytes wx28X/demos/dbbrowse/help.png/msvc.png | Bin 0 -> 491 bytes wx28X/demos/dbbrowse/help.png/odbc.png | Bin 0 -> 426 bytes wx28X/demos/dbbrowse/help.png/pgmctrl.png | Bin 0 -> 287 bytes wx28X/demos/dbbrowse/help.png/redh.png | Bin 0 -> 380 bytes wx28X/demos/dbbrowse/help.png/remstar.png | Bin 0 -> 743 bytes wx28X/demos/dbbrowse/help.png/server.png | Bin 0 -> 360 bytes wx28X/demos/dbbrowse/help.png/suse.png | Bin 0 -> 365 bytes wx28X/demos/dbbrowse/help.png/tab.png | Bin 0 -> 1013 bytes wx28X/demos/dbbrowse/help.png/view.png | Bin 0 -> 1026 bytes wx28X/demos/dbbrowse/help.png/winnt.png | Bin 0 -> 433 bytes wx28X/demos/dbbrowse/help.png/wins.png | Bin 0 -> 372 bytes wx28X/demos/dbbrowse/help.std/compiler.htm | 50 + wx28X/demos/dbbrowse/help.std/dbbrowse.hhc | 68 + wx28X/demos/dbbrowse/help.std/dbbrowse.hhk | 31 + wx28X/demos/dbbrowse/help.std/dbbrowse.hhp | 22 + wx28X/demos/dbbrowse/help.std/dbbrowse.htm | 24 + wx28X/demos/dbbrowse/help.std/getcol.htm | 118 + wx28X/demos/dbbrowse/help.std/getcolsh.htm | 50 + wx28X/demos/dbbrowse/help.std/icons.htm | 40 + wx28X/demos/dbbrowse/help.std/picgrams.htm | 38 + wx28X/demos/dbbrowse/help.std/problems.htm | 85 + wx28X/demos/dbbrowse/help.std/remstar.htm | 15 + wx28X/demos/dbbrowse/help.std/sample.htm | 25 + wx28X/demos/dbbrowse/help.std/startprm.htm | 24 + wx28X/demos/dbbrowse/help.std/todo.htm | 75 + wx28X/demos/dbbrowse/help.std/wxdb.htm | 26 + wx28X/demos/dbbrowse/help.std/wxtable.htm | 15 + wx28X/demos/dbbrowse/makefile.bcc | 314 + wx28X/demos/dbbrowse/makefile.dmc | 81 + wx28X/demos/dbbrowse/makefile.dms | 273 + wx28X/demos/dbbrowse/makefile.gcc | 316 + wx28X/demos/dbbrowse/makefile.vc | 420 + wx28X/demos/dbbrowse/makefile.wat | 351 + wx28X/demos/dbbrowse/pgmctrl.cpp | 294 + wx28X/demos/dbbrowse/pgmctrl.h | 74 + wx28X/demos/dbbrowse/std.h | 33 + wx28X/demos/dbbrowse/tabpgwin.cpp | 1182 + wx28X/demos/dbbrowse/tabpgwin.h | 268 + wx28X/demos/demos.bkl | 19 + wx28X/demos/forty/Makefile.in | 250 + wx28X/demos/forty/about.htm | 110 + wx28X/demos/forty/canvas.cpp | 270 + wx28X/demos/forty/canvas.h | 58 + wx28X/demos/forty/card.cpp | 552 + wx28X/demos/forty/card.h | 74 + wx28X/demos/forty/cards.ico | Bin 0 -> 766 bytes wx28X/demos/forty/forty-icons.r | 2742 + wx28X/demos/forty/forty.bkl | 31 + wx28X/demos/forty/forty.cpp | 377 + wx28X/demos/forty/forty.dsp | 508 + wx28X/demos/forty/forty.h | 92 + wx28X/demos/forty/forty.pro | 21 + wx28X/demos/forty/forty.r | 27 + wx28X/demos/forty/forty.rc | 6 + wx28X/demos/forty/forty.vcp | 1854 + wx28X/demos/forty/forty.vcw | 17 + wx28X/demos/forty/forty.xpm | 43 + wx28X/demos/forty/fortyM5.xml | 4079 + wx28X/demos/forty/game.cpp | 979 + wx28X/demos/forty/game.h | 136 + wx28X/demos/forty/makefile.bcc | 297 + wx28X/demos/forty/makefile.dmc | 77 + wx28X/demos/forty/makefile.dms | 252 + wx28X/demos/forty/makefile.gcc | 297 + wx28X/demos/forty/makefile.unx | 35 + wx28X/demos/forty/makefile.vc | 403 + wx28X/demos/forty/makefile.wat | 329 + wx28X/demos/forty/makemac6.mcp | Bin 0 -> 207085 bytes wx28X/demos/forty/pictures.xpm | 60 + wx28X/demos/forty/pile.cpp | 292 + wx28X/demos/forty/pile.h | 81 + wx28X/demos/forty/playerdg.cpp | 139 + wx28X/demos/forty/playerdg.h | 41 + wx28X/demos/forty/readme.txt | 86 + wx28X/demos/forty/scoredg.cpp | 209 + wx28X/demos/forty/scoredg.h | 34 + wx28X/demos/forty/scorefil.cpp | 143 + wx28X/demos/forty/scorefil.h | 35 + wx28X/demos/forty/symbols.xpm | 93 + wx28X/demos/fractal/Makefile.in | 198 + wx28X/demos/fractal/fractal.bkl | 16 + wx28X/demos/fractal/fractal.cpp | 258 + wx28X/demos/fractal/fractal.dsp | 480 + wx28X/demos/fractal/fractal.pro | 21 + wx28X/demos/fractal/fractal.rc | 4 + wx28X/demos/fractal/fractal.vcp | 1826 + wx28X/demos/fractal/fractal.vcw | 17 + wx28X/demos/fractal/fractalM5.xml | 3685 + wx28X/demos/fractal/makefile.bcc | 253 + wx28X/demos/fractal/makefile.dmc | 45 + wx28X/demos/fractal/makefile.dms | 213 + wx28X/demos/fractal/makefile.gcc | 253 + wx28X/demos/fractal/makefile.unx | 35 + wx28X/demos/fractal/makefile.vc | 359 + wx28X/demos/fractal/makefile.wat | 282 + wx28X/demos/fractal/mondrian.ico | Bin 0 -> 766 bytes wx28X/demos/life/Makefile.in | 221 + wx28X/demos/life/bitmaps/center.bmp | Bin 0 -> 246 bytes wx28X/demos/life/bitmaps/center.xpm | 22 + wx28X/demos/life/bitmaps/east.bmp | Bin 0 -> 246 bytes wx28X/demos/life/bitmaps/east.xpm | 22 + wx28X/demos/life/bitmaps/info.bmp | Bin 0 -> 246 bytes wx28X/demos/life/bitmaps/info.xpm | 24 + wx28X/demos/life/bitmaps/life.bmp | Bin 0 -> 5666 bytes wx28X/demos/life/bitmaps/life.xpm | 81 + wx28X/demos/life/bitmaps/north.bmp | Bin 0 -> 246 bytes wx28X/demos/life/bitmaps/north.xpm | 22 + wx28X/demos/life/bitmaps/open.bmp | Bin 0 -> 1318 bytes wx28X/demos/life/bitmaps/open.xpm | 57 + wx28X/demos/life/bitmaps/play.bmp | Bin 0 -> 246 bytes wx28X/demos/life/bitmaps/play.xpm | 24 + wx28X/demos/life/bitmaps/reset.bmp | Bin 0 -> 774 bytes wx28X/demos/life/bitmaps/reset.xpm | 52 + wx28X/demos/life/bitmaps/south.bmp | Bin 0 -> 246 bytes wx28X/demos/life/bitmaps/south.xpm | 22 + wx28X/demos/life/bitmaps/stop.bmp | Bin 0 -> 246 bytes wx28X/demos/life/bitmaps/stop.xpm | 24 + wx28X/demos/life/bitmaps/west.bmp | Bin 0 -> 246 bytes wx28X/demos/life/bitmaps/west.xpm | 22 + wx28X/demos/life/bitmaps/zoomin.bmp | Bin 0 -> 246 bytes wx28X/demos/life/bitmaps/zoomin.xpm | 23 + wx28X/demos/life/bitmaps/zoomout.bmp | Bin 0 -> 246 bytes wx28X/demos/life/bitmaps/zoomout.xpm | 23 + wx28X/demos/life/breeder.lif | 2523 + wx28X/demos/life/dialogs.cpp | 213 + wx28X/demos/life/dialogs.h | 71 + wx28X/demos/life/game.cpp | 1503 + wx28X/demos/life/game.h | 178 + wx28X/demos/life/life.bkl | 24 + wx28X/demos/life/life.cpp | 1127 + wx28X/demos/life/life.dsp | 492 + wx28X/demos/life/life.h | 172 + wx28X/demos/life/life.pro | 21 + wx28X/demos/life/life.rc | 17 + wx28X/demos/life/life.vcp | 1838 + wx28X/demos/life/life.vcw | 17 + wx28X/demos/life/lifeM5.xml | 3847 + wx28X/demos/life/makefile.bcc | 269 + wx28X/demos/life/makefile.dmc | 61 + wx28X/demos/life/makefile.dms | 228 + wx28X/demos/life/makefile.gcc | 269 + wx28X/demos/life/makefile.unx | 35 + wx28X/demos/life/makefile.vc | 375 + wx28X/demos/life/makefile.wat | 298 + wx28X/demos/life/mondrian.ico | Bin 0 -> 766 bytes wx28X/demos/life/mondrian.xpm | 44 + wx28X/demos/life/reader.cpp | 87 + wx28X/demos/life/reader.h | 54 + wx28X/demos/life/samples.inc | 222 + .../demos/life/setup/wince/Common/breeder.lif | 2523 + wx28X/demos/life/setup/wince/Common/life.htp | 1 + wx28X/demos/life/setup/wince/build.bat | 55 + wx28X/demos/life/setup/wince/install.ini | 14 + wx28X/demos/life/setup/wince/life.ico | Bin 0 -> 766 bytes wx28X/demos/life/setup/wince/life.inf | 191 + wx28X/demos/life/setup/wince/readme.txt | 21 + wx28X/demos/life/setup/wince/register.bat | 34 + wx28X/demos/makefile.bcc | 113 + wx28X/demos/makefile.dmc | 88 + wx28X/demos/makefile.dms | 79 + wx28X/demos/makefile.gcc | 75 + wx28X/demos/makefile.vc | 92 + wx28X/demos/makefile.wat | 112 + wx28X/demos/poem/Makefile.in | 213 + wx28X/demos/poem/corner1.ico | Bin 0 -> 766 bytes wx28X/demos/poem/corner1.xpm | 42 + wx28X/demos/poem/corner2.ico | Bin 0 -> 766 bytes wx28X/demos/poem/corner2.xpm | 42 + wx28X/demos/poem/corner3.ico | Bin 0 -> 766 bytes wx28X/demos/poem/corner3.xpm | 42 + wx28X/demos/poem/corner4.ico | Bin 0 -> 766 bytes wx28X/demos/poem/corner4.xpm | 42 + wx28X/demos/poem/makefile.bcc | 261 + wx28X/demos/poem/makefile.dmc | 49 + wx28X/demos/poem/makefile.dms | 223 + wx28X/demos/poem/makefile.gcc | 261 + wx28X/demos/poem/makefile.unx | 35 + wx28X/demos/poem/makefile.vc | 367 + wx28X/demos/poem/makefile.wat | 291 + wx28X/demos/poem/poem.bkl | 20 + wx28X/demos/poem/poem.dsp | 480 + wx28X/demos/poem/poem.pro | 21 + wx28X/demos/poem/poem.vcp | 1826 + wx28X/demos/poem/poem.vcw | 17 + wx28X/demos/poem/poemM5.xml | 3685 + wx28X/demos/poem/wxpoem.cpp | 1075 + wx28X/demos/poem/wxpoem.dat | 2532 + wx28X/demos/poem/wxpoem.h | 109 + wx28X/demos/poem/wxpoem.ico | Bin 0 -> 766 bytes wx28X/demos/poem/wxpoem.idx | 137 + wx28X/demos/poem/wxpoem.rc | 4 + wx28X/demos/poem/wxpoem.txt | 121 + wx28X/demos/poem/wxpoem.xpm | 47 + wx28X/descrip.mms | 250 + wx28X/difflast.pl | 82 + wx28X/docs/base/readme.txt | 139 + wx28X/docs/changes.txt | 3781 + wx28X/docs/cocoa/readme.txt | 20 + wx28X/docs/gtk/changes.txt | 4 + wx28X/docs/gtk/licence.txt | 53 + wx28X/docs/gtk/readme.txt | 71 + wx28X/docs/htmlhelp/wx.chm | Bin 0 -> 3263055 bytes wx28X/docs/licence.txt | 53 + wx28X/docs/mac/readme.txt | 24 + wx28X/docs/mgl/readme.txt | 21 + wx28X/docs/microwin/readme.txt | 334 + wx28X/docs/motif/readme.txt | 50 + wx28X/docs/msw/install.txt | 869 + wx28X/docs/msw/readme.txt | 8 + wx28X/docs/msw/wince/readme.txt | 160 + wx28X/docs/os2/readme.txt | 30 + wx28X/docs/palmos/readme.txt | 128 + wx28X/docs/readme.txt | 160 + wx28X/docs/univ/readme.txt | 144 + wx28X/docs/wine/changes.txt | 12 + wx28X/docs/wine/licence.txt | 53 + wx28X/docs/wine/readme.txt | 23 + wx28X/docs/x11/readme.txt | 70 + wx28X/include/msvc/wx/setup.h | 249 + wx28X/include/wx/aboutdlg.h | 161 + wx28X/include/wx/accel.h | 170 + wx28X/include/wx/access.h | 377 + wx28X/include/wx/afterstd.h | 71 + wx28X/include/wx/anidecod.h | 77 + wx28X/include/wx/animate.h | 124 + wx28X/include/wx/animdecod.h | 146 + wx28X/include/wx/app.h | 708 + wx28X/include/wx/apptrait.h | 272 + wx28X/include/wx/archive.h | 381 + wx28X/include/wx/arrimpl.cpp | 120 + wx28X/include/wx/arrstr.h | 377 + wx28X/include/wx/artprov.h | 204 + wx28X/include/wx/aui/aui.h | 23 + wx28X/include/wx/aui/auibar.h | 685 + wx28X/include/wx/aui/auibook.h | 753 + wx28X/include/wx/aui/dockart.h | 173 + wx28X/include/wx/aui/floatpane.h | 81 + wx28X/include/wx/aui/framemanager.h | 856 + wx28X/include/wx/aui/tabmdi.h | 269 + wx28X/include/wx/beforestd.h | 75 + wx28X/include/wx/bitmap.h | 241 + wx28X/include/wx/bmpbuttn.h | 122 + wx28X/include/wx/bmpcbox.h | 49 + wx28X/include/wx/bookctrl.h | 403 + wx28X/include/wx/brush.h | 54 + wx28X/include/wx/buffer.h | 314 + wx28X/include/wx/build.h | 149 + wx28X/include/wx/busyinfo.h | 21 + wx28X/include/wx/button.h | 106 + wx28X/include/wx/calctrl.h | 232 + wx28X/include/wx/caret.h | 252 + wx28X/include/wx/checkbox.h | 156 + wx28X/include/wx/checklst.h | 64 + wx28X/include/wx/chkconf.h | 1871 + wx28X/include/wx/choicdlg.h | 22 + wx28X/include/wx/choice.h | 88 + wx28X/include/wx/choicebk.h | 154 + wx28X/include/wx/clipbrd.h | 145 + wx28X/include/wx/clntdata.h | 273 + wx28X/include/wx/clrpicker.h | 200 + wx28X/include/wx/cmdline.h | 239 + wx28X/include/wx/cmdproc.h | 144 + wx28X/include/wx/cmndata.h | 454 + wx28X/include/wx/collpane.h | 104 + wx28X/include/wx/colordlg.h | 41 + wx28X/include/wx/colour.h | 154 + wx28X/include/wx/combo.h | 757 + wx28X/include/wx/combobox.h | 97 + wx28X/include/wx/confbase.h | 359 + wx28X/include/wx/config.h | 33 + wx28X/include/wx/containr.h | 142 + wx28X/include/wx/control.h | 117 + wx28X/include/wx/convauto.h | 108 + wx28X/include/wx/cpp.h | 57 + wx28X/include/wx/cppunit.h | 129 + wx28X/include/wx/cshelp.h | 244 + wx28X/include/wx/ctrlsub.h | 210 + wx28X/include/wx/cursor.h | 79 + wx28X/include/wx/dataobj.h | 540 + wx28X/include/wx/dataview.h | 480 + wx28X/include/wx/datectrl.h | 112 + wx28X/include/wx/dateevt.h | 69 + wx28X/include/wx/datetime.h | 2137 + wx28X/include/wx/datstrm.h | 170 + wx28X/include/wx/db.h | 853 + wx28X/include/wx/dbgrid.h | 177 + wx28X/include/wx/dbkeyg.h | 41 + wx28X/include/wx/dbtable.h | 377 + wx28X/include/wx/dc.h | 1008 + wx28X/include/wx/dcbuffer.h | 276 + wx28X/include/wx/dcclient.h | 42 + wx28X/include/wx/dcgraph.h | 190 + wx28X/include/wx/dcmemory.h | 76 + wx28X/include/wx/dcmirror.h | 287 + wx28X/include/wx/dcprint.h | 33 + wx28X/include/wx/dcps.h | 18 + wx28X/include/wx/dcscreen.h | 42 + wx28X/include/wx/dde.h | 32 + wx28X/include/wx/debug.h | 316 + wx28X/include/wx/debugrpt.h | 235 + wx28X/include/wx/defs.h | 2907 + wx28X/include/wx/dialog.h | 167 + wx28X/include/wx/dialup.h | 201 + wx28X/include/wx/dir.h | 161 + wx28X/include/wx/dirctrl.h | 18 + wx28X/include/wx/dirdlg.h | 141 + wx28X/include/wx/display.h | 128 + wx28X/include/wx/display_impl.h | 110 + wx28X/include/wx/dlimpexp.h | 275 + wx28X/include/wx/dnd.h | 267 + wx28X/include/wx/docmdi.h | 107 + wx28X/include/wx/docview.h | 675 + wx28X/include/wx/dragimag.h | 54 + wx28X/include/wx/dynarray.h | 1044 + wx28X/include/wx/dynlib.h | 359 + wx28X/include/wx/dynload.h | 153 + wx28X/include/wx/effects.h | 75 + wx28X/include/wx/encconv.h | 159 + wx28X/include/wx/encinfo.h | 74 + wx28X/include/wx/event.h | 3121 + wx28X/include/wx/evtloop.h | 229 + wx28X/include/wx/except.h | 30 + wx28X/include/wx/fdrepdlg.h | 195 + wx28X/include/wx/features.h | 64 + wx28X/include/wx/ffile.h | 115 + wx28X/include/wx/file.h | 201 + wx28X/include/wx/fileconf.h | 246 + wx28X/include/wx/filedlg.h | 226 + wx28X/include/wx/filefn.h | 770 + wx28X/include/wx/filename.h | 547 + wx28X/include/wx/filepicker.h | 398 + wx28X/include/wx/filesys.h | 300 + wx28X/include/wx/flags.h | 165 + wx28X/include/wx/fmappriv.h | 74 + wx28X/include/wx/font.h | 251 + wx28X/include/wx/fontdlg.h | 118 + wx28X/include/wx/fontenc.h | 151 + wx28X/include/wx/fontenum.h | 88 + wx28X/include/wx/fontmap.h | 290 + wx28X/include/wx/fontpicker.h | 223 + wx28X/include/wx/fontutil.h | 242 + wx28X/include/wx/frame.h | 262 + wx28X/include/wx/fs_arc.h | 56 + wx28X/include/wx/fs_filter.h | 41 + wx28X/include/wx/fs_inet.h | 33 + wx28X/include/wx/fs_mem.h | 127 + wx28X/include/wx/fs_zip.h | 23 + wx28X/include/wx/gauge.h | 126 + wx28X/include/wx/gbsizer.h | 303 + wx28X/include/wx/gdicmn.h | 755 + wx28X/include/wx/gdiobj.h | 51 + wx28X/include/wx/generic/aboutdlgg.h | 87 + wx28X/include/wx/generic/accel.h | 50 + wx28X/include/wx/generic/animate.h | 178 + wx28X/include/wx/generic/bmpcbox.h | 170 + wx28X/include/wx/generic/busyinfo.h | 42 + wx28X/include/wx/generic/buttonbar.h | 123 + wx28X/include/wx/generic/calctrl.h | 324 + wx28X/include/wx/generic/caret.h | 95 + wx28X/include/wx/generic/choicdgg.h | 320 + wx28X/include/wx/generic/clrpickerg.h | 98 + wx28X/include/wx/generic/collpaneg.h | 105 + wx28X/include/wx/generic/colour.h | 75 + wx28X/include/wx/generic/colrdlgg.h | 120 + wx28X/include/wx/generic/combo.h | 140 + wx28X/include/wx/generic/dataview.h | 311 + wx28X/include/wx/generic/datectrl.h | 91 + wx28X/include/wx/generic/dcpsg.h | 154 + wx28X/include/wx/generic/dirctrlg.h | 295 + wx28X/include/wx/generic/dirdlgg.h | 89 + wx28X/include/wx/generic/dragimgg.h | 271 + wx28X/include/wx/generic/fdrepdlg.h | 71 + wx28X/include/wx/generic/filedlgg.h | 307 + wx28X/include/wx/generic/filepickerg.h | 213 + wx28X/include/wx/generic/fontdlgg.h | 120 + wx28X/include/wx/generic/fontpickerg.h | 82 + wx28X/include/wx/generic/grid.h | 2307 + wx28X/include/wx/generic/gridctrl.h | 158 + wx28X/include/wx/generic/gridsel.h | 88 + wx28X/include/wx/generic/helpext.h | 166 + wx28X/include/wx/generic/icon.h | 56 + wx28X/include/wx/generic/imaglist.h | 82 + wx28X/include/wx/generic/laywin.h | 222 + wx28X/include/wx/generic/listctrl.h | 280 + wx28X/include/wx/generic/logg.h | 129 + wx28X/include/wx/generic/mask.h | 54 + wx28X/include/wx/generic/mdig.h | 335 + wx28X/include/wx/generic/msgdlgg.h | 44 + wx28X/include/wx/generic/notebook.h | 160 + wx28X/include/wx/generic/numdlgg.h | 79 + wx28X/include/wx/generic/paletteg.h | 49 + wx28X/include/wx/generic/panelg.h | 95 + wx28X/include/wx/generic/printps.h | 68 + wx28X/include/wx/generic/prntdlgg.h | 256 + wx28X/include/wx/generic/progdlgg.h | 172 + wx28X/include/wx/generic/propdlg.h | 163 + wx28X/include/wx/generic/region.h | 79 + wx28X/include/wx/generic/sashwin.h | 261 + wx28X/include/wx/generic/scrolwin.h | 27 + wx28X/include/wx/generic/spinctlg.h | 183 + wx28X/include/wx/generic/splash.h | 92 + wx28X/include/wx/generic/splitter.h | 406 + wx28X/include/wx/generic/srchctlg.h | 275 + wx28X/include/wx/generic/statline.h | 62 + wx28X/include/wx/generic/statusbr.h | 107 + wx28X/include/wx/generic/tabg.h | 363 + wx28X/include/wx/generic/textdlgg.h | 113 + wx28X/include/wx/generic/timer.h | 45 + wx28X/include/wx/generic/treectlg.h | 383 + wx28X/include/wx/generic/wizard.h | 142 + wx28X/include/wx/geometry.h | 814 + wx28X/include/wx/gifdecod.h | 110 + wx28X/include/wx/glcanvas.h | 86 + wx28X/include/wx/graphics.h | 735 + wx28X/include/wx/grid.h | 18 + wx28X/include/wx/gsocket.h | 184 + wx28X/include/wx/hash.h | 630 + wx28X/include/wx/hashmap.h | 739 + wx28X/include/wx/hashset.h | 135 + wx28X/include/wx/help.h | 48 + wx28X/include/wx/helpbase.h | 106 + wx28X/include/wx/helphtml.h | 20 + wx28X/include/wx/helpwin.h | 22 + wx28X/include/wx/html/forcelnk.h | 62 + wx28X/include/wx/html/helpctrl.h | 153 + wx28X/include/wx/html/helpdata.h | 266 + wx28X/include/wx/html/helpdlg.h | 90 + wx28X/include/wx/html/helpfrm.h | 147 + wx28X/include/wx/html/helpwnd.h | 300 + wx28X/include/wx/html/htmlcell.h | 673 + wx28X/include/wx/html/htmldefs.h | 104 + wx28X/include/wx/html/htmlfilt.h | 82 + wx28X/include/wx/html/htmlpars.h | 283 + wx28X/include/wx/html/htmlproc.h | 58 + wx28X/include/wx/html/htmltag.h | 148 + wx28X/include/wx/html/htmlwin.h | 651 + wx28X/include/wx/html/htmprint.h | 305 + wx28X/include/wx/html/m_templ.h | 84 + wx28X/include/wx/html/webkit.h | 231 + wx28X/include/wx/html/winpars.h | 292 + wx28X/include/wx/htmllbox.h | 325 + wx28X/include/wx/hyperlink.h | 231 + wx28X/include/wx/icon.h | 53 + wx28X/include/wx/iconbndl.h | 69 + wx28X/include/wx/iconloc.h | 81 + wx28X/include/wx/imagbmp.h | 165 + wx28X/include/wx/image.h | 454 + wx28X/include/wx/imaggif.h | 48 + wx28X/include/wx/imagiff.h | 44 + wx28X/include/wx/imagjpeg.h | 48 + wx28X/include/wx/imaglist.h | 55 + wx28X/include/wx/imagpcx.h | 47 + wx28X/include/wx/imagpng.h | 60 + wx28X/include/wx/imagpnm.h | 46 + wx28X/include/wx/imagtga.h | 46 + wx28X/include/wx/imagtiff.h | 49 + wx28X/include/wx/imagxpm.h | 45 + wx28X/include/wx/init.h | 105 + wx28X/include/wx/intl.h | 632 + wx28X/include/wx/iosfwrap.h | 26 + wx28X/include/wx/ioswrap.h | 26 + wx28X/include/wx/ipc.h | 45 + wx28X/include/wx/ipcbase.h | 163 + wx28X/include/wx/isql.h | 248 + wx28X/include/wx/isqlext.h | 1178 + wx28X/include/wx/joystick.h | 38 + wx28X/include/wx/layout.h | 191 + wx28X/include/wx/laywin.h | 18 + wx28X/include/wx/link.h | 32 + wx28X/include/wx/list.h | 1308 + wx28X/include/wx/listbase.h | 491 + wx28X/include/wx/listbook.h | 152 + wx28X/include/wx/listbox.h | 166 + wx28X/include/wx/listctrl.h | 110 + wx28X/include/wx/listimpl.cpp | 39 + wx28X/include/wx/log.h | 653 + wx28X/include/wx/longlong.h | 1080 + wx28X/include/wx/math.h | 140 + wx28X/include/wx/matrix.h | 235 + wx28X/include/wx/mdi.h | 40 + wx28X/include/wx/mediactrl.h | 422 + wx28X/include/wx/memconf.h | 54 + wx28X/include/wx/memory.h | 373 + wx28X/include/wx/memtext.h | 54 + wx28X/include/wx/menu.h | 555 + wx28X/include/wx/menuitem.h | 203 + wx28X/include/wx/metafile.h | 62 + wx28X/include/wx/mimetype.h | 453 + wx28X/include/wx/minifram.h | 43 + wx28X/include/wx/module.h | 103 + wx28X/include/wx/msgdlg.h | 79 + wx28X/include/wx/msgout.h | 113 + wx28X/include/wx/mstream.h | 92 + wx28X/include/wx/msw/accel.h | 46 + wx28X/include/wx/msw/amd64.manifest | 22 + wx28X/include/wx/msw/app.h | 147 + wx28X/include/wx/msw/apptbase.h | 46 + wx28X/include/wx/msw/apptrait.h | 45 + wx28X/include/wx/msw/bitmap.h | 282 + wx28X/include/wx/msw/blank.cur | Bin 0 -> 326 bytes wx28X/include/wx/msw/bmpbuttn.h | 73 + wx28X/include/wx/msw/brush.h | 60 + wx28X/include/wx/msw/bullseye.cur | Bin 0 -> 326 bytes wx28X/include/wx/msw/button.h | 82 + wx28X/include/wx/msw/caret.h | 64 + wx28X/include/wx/msw/cdrom.ico | Bin 0 -> 1718 bytes wx28X/include/wx/msw/checkbox.h | 86 + wx28X/include/wx/msw/checklst.h | 96 + wx28X/include/wx/msw/child.ico | Bin 0 -> 1078 bytes wx28X/include/wx/msw/chkconf.h | 387 + wx28X/include/wx/msw/choice.h | 135 + wx28X/include/wx/msw/clipbrd.h | 98 + wx28X/include/wx/msw/colordlg.h | 56 + wx28X/include/wx/msw/colour.h | 88 + wx28X/include/wx/msw/colours.bmp | Bin 0 -> 122 bytes wx28X/include/wx/msw/combo.h | 111 + wx28X/include/wx/msw/combobox.h | 138 + wx28X/include/wx/msw/computer.ico | Bin 0 -> 1718 bytes wx28X/include/wx/msw/control.h | 141 + wx28X/include/wx/msw/crashrpt.h | 120 + wx28X/include/wx/msw/cross.cur | Bin 0 -> 326 bytes wx28X/include/wx/msw/csquery.bmp | Bin 0 -> 206 bytes wx28X/include/wx/msw/cursor.h | 47 + wx28X/include/wx/msw/datectrl.h | 70 + wx28X/include/wx/msw/dc.h | 345 + wx28X/include/wx/msw/dcclient.h | 118 + wx28X/include/wx/msw/dcmemory.h | 45 + wx28X/include/wx/msw/dcprint.h | 70 + wx28X/include/wx/msw/dcscreen.h | 40 + wx28X/include/wx/msw/dde.h | 144 + wx28X/include/wx/msw/debughlp.h | 228 + wx28X/include/wx/msw/dialog.h | 140 + wx28X/include/wx/msw/dib.h | 255 + wx28X/include/wx/msw/dirdlg.h | 35 + wx28X/include/wx/msw/dragimag.h | 274 + wx28X/include/wx/msw/drive.ico | Bin 0 -> 1718 bytes wx28X/include/wx/msw/enhmeta.h | 196 + wx28X/include/wx/msw/evtloop.h | 69 + wx28X/include/wx/msw/fdrepdlg.h | 62 + wx28X/include/wx/msw/file1.ico | Bin 0 -> 1718 bytes wx28X/include/wx/msw/filedlg.h | 55 + wx28X/include/wx/msw/floppy.ico | Bin 0 -> 1718 bytes wx28X/include/wx/msw/folder1.ico | Bin 0 -> 1718 bytes wx28X/include/wx/msw/folder2.ico | Bin 0 -> 1718 bytes wx28X/include/wx/msw/font.h | 148 + wx28X/include/wx/msw/fontdlg.h | 46 + wx28X/include/wx/msw/fontenum.h | 40 + wx28X/include/wx/msw/frame.h | 172 + wx28X/include/wx/msw/gauge95.h | 70 + wx28X/include/wx/msw/gccpriv.h | 127 + wx28X/include/wx/msw/gdiimage.h | 189 + wx28X/include/wx/msw/genrcdefs.h | 43 + wx28X/include/wx/msw/glcanvas.h | 128 + wx28X/include/wx/msw/gsockmsw.h | 145 + wx28X/include/wx/msw/hand.cur | Bin 0 -> 326 bytes wx28X/include/wx/msw/helpbest.h | 129 + wx28X/include/wx/msw/helpchm.h | 60 + wx28X/include/wx/msw/helpwin.h | 56 + wx28X/include/wx/msw/htmlhelp.h | 465 + wx28X/include/wx/msw/ia64.manifest | 22 + wx28X/include/wx/msw/icon.h | 95 + wx28X/include/wx/msw/imaglist.h | 206 + wx28X/include/wx/msw/iniconf.h | 101 + wx28X/include/wx/msw/joystick.h | 90 + wx28X/include/wx/msw/libraries.h | 27 + wx28X/include/wx/msw/listbox.h | 183 + wx28X/include/wx/msw/listctrl.h | 449 + wx28X/include/wx/msw/magnif1.cur | Bin 0 -> 326 bytes wx28X/include/wx/msw/mdi.h | 238 + wx28X/include/wx/msw/mdi.ico | Bin 0 -> 1078 bytes wx28X/include/wx/msw/menu.h | 241 + wx28X/include/wx/msw/menuitem.h | 100 + wx28X/include/wx/msw/metafile.h | 171 + wx28X/include/wx/msw/microwin.h | 235 + wx28X/include/wx/msw/mimetype.h | 122 + wx28X/include/wx/msw/minifram.h | 52 + wx28X/include/wx/msw/missing.h | 495 + wx28X/include/wx/msw/msgdlg.h | 42 + wx28X/include/wx/msw/mslu.h | 23 + wx28X/include/wx/msw/msvcrt.h | 69 + wx28X/include/wx/msw/notebook.h | 254 + wx28X/include/wx/msw/ole/access.h | 68 + wx28X/include/wx/msw/ole/activex.h | 221 + wx28X/include/wx/msw/ole/automtn.h | 101 + wx28X/include/wx/msw/ole/dataform.h | 68 + wx28X/include/wx/msw/ole/dataobj.h | 79 + wx28X/include/wx/msw/ole/dataobj2.h | 146 + wx28X/include/wx/msw/ole/dropsrc.h | 79 + wx28X/include/wx/msw/ole/droptgt.h | 72 + wx28X/include/wx/msw/ole/oleutils.h | 256 + wx28X/include/wx/msw/ole/uuid.h | 92 + wx28X/include/wx/msw/palette.h | 58 + wx28X/include/wx/msw/pbrush.cur | Bin 0 -> 326 bytes wx28X/include/wx/msw/pen.h | 132 + wx28X/include/wx/msw/pencil.cur | Bin 0 -> 326 bytes wx28X/include/wx/msw/pntleft.cur | Bin 0 -> 326 bytes wx28X/include/wx/msw/pntright.cur | Bin 0 -> 326 bytes wx28X/include/wx/msw/popupwin.h | 45 + wx28X/include/wx/msw/printdlg.h | 124 + wx28X/include/wx/msw/printwin.h | 66 + wx28X/include/wx/msw/private.h | 953 + wx28X/include/wx/msw/question.ico | Bin 0 -> 2238 bytes wx28X/include/wx/msw/radiobox.h | 175 + wx28X/include/wx/msw/radiobut.h | 70 + wx28X/include/wx/msw/rcdefs.h | 15 + wx28X/include/wx/msw/regconf.h | 116 + wx28X/include/wx/msw/region.h | 104 + wx28X/include/wx/msw/registry.h | 247 + wx28X/include/wx/msw/removble.ico | Bin 0 -> 1718 bytes wx28X/include/wx/msw/rightarr.cur | Bin 0 -> 326 bytes wx28X/include/wx/msw/roller.cur | Bin 0 -> 326 bytes wx28X/include/wx/msw/scrolbar.h | 72 + wx28X/include/wx/msw/seh.h | 74 + wx28X/include/wx/msw/setup.h | 1361 + wx28X/include/wx/msw/setup0.h | 1361 + wx28X/include/wx/msw/setup_microwin.h | 1179 + wx28X/include/wx/msw/slider95.h | 137 + wx28X/include/wx/msw/sound.h | 52 + wx28X/include/wx/msw/spinbutt.h | 72 + wx28X/include/wx/msw/spinctrl.h | 142 + wx28X/include/wx/msw/stackwalk.h | 103 + wx28X/include/wx/msw/statbmp.h | 90 + wx28X/include/wx/msw/statbox.h | 73 + wx28X/include/wx/msw/statbr95.h | 76 + wx28X/include/wx/msw/statline.h | 52 + wx28X/include/wx/msw/stattext.h | 56 + wx28X/include/wx/msw/std.ico | Bin 0 -> 1078 bytes wx28X/include/wx/msw/stdpaths.h | 53 + wx28X/include/wx/msw/subwin.h | 195 + wx28X/include/wx/msw/tabctrl.h | 160 + wx28X/include/wx/msw/taskbar.h | 82 + wx28X/include/wx/msw/tbar95.h | 156 + wx28X/include/wx/msw/textctrl.h | 291 + wx28X/include/wx/msw/tglbtn.h | 60 + wx28X/include/wx/msw/timer.h | 40 + wx28X/include/wx/msw/tooltip.h | 71 + wx28X/include/wx/msw/toplevel.h | 197 + wx28X/include/wx/msw/treectrl.h | 315 + wx28X/include/wx/msw/uxtheme.h | 230 + wx28X/include/wx/msw/uxthemep.h | 169 + wx28X/include/wx/msw/wince/checklst.h | 95 + wx28X/include/wx/msw/wince/chkconf.h | 100 + wx28X/include/wx/msw/wince/choicece.h | 142 + wx28X/include/wx/msw/wince/helpwce.h | 58 + wx28X/include/wx/msw/wince/libraries.h | 59 + wx28X/include/wx/msw/wince/missing.h | 140 + wx28X/include/wx/msw/wince/net.h | 21 + wx28X/include/wx/msw/wince/resources.h | 25 + wx28X/include/wx/msw/wince/setup.h | 1295 + wx28X/include/wx/msw/wince/smartphone.rc | 67 + wx28X/include/wx/msw/wince/tbarwce.h | 168 + wx28X/include/wx/msw/wince/textctrlce.h | 236 + wx28X/include/wx/msw/wince/time.h | 53 + wx28X/include/wx/msw/wince/wince.rc | 26 + wx28X/include/wx/msw/window.h | 601 + wx28X/include/wx/msw/winundef.h | 490 + wx28X/include/wx/msw/wrapcctl.h | 62 + wx28X/include/wx/msw/wrapcdlg.h | 28 + wx28X/include/wx/msw/wrapshl.h | 90 + wx28X/include/wx/msw/wrapwin.h | 99 + wx28X/include/wx/msw/wx.manifest | 46 + wx28X/include/wx/msw/wx.rc | 119 + wx28X/include/wx/notebook.h | 183 + wx28X/include/wx/numdlg.h | 23 + wx28X/include/wx/object.h | 569 + wx28X/include/wx/odcombo.h | 393 + wx28X/include/wx/overlay.h | 97 + wx28X/include/wx/ownerdrw.h | 184 + wx28X/include/wx/palette.h | 59 + wx28X/include/wx/panel.h | 18 + wx28X/include/wx/paper.h | 122 + wx28X/include/wx/pen.h | 40 + wx28X/include/wx/pickerbase.h | 189 + wx28X/include/wx/platform.h | 664 + wx28X/include/wx/platinfo.h | 313 + wx28X/include/wx/popupwin.h | 192 + wx28X/include/wx/power.h | 111 + wx28X/include/wx/print.h | 39 + wx28X/include/wx/printdlg.h | 122 + wx28X/include/wx/private/browserhack28.h | 20 + wx28X/include/wx/private/fileback.h | 83 + wx28X/include/wx/private/filename.h | 56 + wx28X/include/wx/private/fontmgr.h | 255 + wx28X/include/wx/private/overlay.h | 72 + wx28X/include/wx/private/socketevtdispatch.h | 67 + wx28X/include/wx/prntbase.h | 665 + wx28X/include/wx/process.h | 172 + wx28X/include/wx/progdlg.h | 36 + wx28X/include/wx/propdlg.h | 19 + wx28X/include/wx/protocol/file.h | 37 + wx28X/include/wx/protocol/ftp.h | 182 + wx28X/include/wx/protocol/http.h | 91 + wx28X/include/wx/protocol/protocol.h | 131 + wx28X/include/wx/ptr_scpd.h | 222 + wx28X/include/wx/quantize.h | 76 + wx28X/include/wx/radiobox.h | 181 + wx28X/include/wx/radiobut.h | 61 + wx28X/include/wx/rawbmp.h | 713 + wx28X/include/wx/recguard.h | 53 + wx28X/include/wx/regex.h | 166 + wx28X/include/wx/region.h | 300 + wx28X/include/wx/renderer.h | 436 + wx28X/include/wx/richtext/richtextbuffer.h | 2398 + .../include/wx/richtext/richtextbulletspage.h | 217 + wx28X/include/wx/richtext/richtextctrl.h | 984 + wx28X/include/wx/richtext/richtextfontpage.h | 167 + wx28X/include/wx/richtext/richtextformatdlg.h | 327 + wx28X/include/wx/richtext/richtexthtml.h | 148 + .../include/wx/richtext/richtextindentspage.h | 165 + .../wx/richtext/richtextliststylepage.h | 276 + wx28X/include/wx/richtext/richtextprint.h | 247 + wx28X/include/wx/richtext/richtextstyledlg.h | 241 + wx28X/include/wx/richtext/richtextstylepage.h | 91 + wx28X/include/wx/richtext/richtextstyles.h | 683 + wx28X/include/wx/richtext/richtextsymboldlg.h | 370 + wx28X/include/wx/richtext/richtexttabspage.h | 129 + wx28X/include/wx/richtext/richtextxml.h | 79 + wx28X/include/wx/sashwin.h | 18 + wx28X/include/wx/sckaddr.h | 193 + wx28X/include/wx/sckipc.h | 150 + wx28X/include/wx/sckstrm.h | 72 + wx28X/include/wx/scopeguard.h | 373 + wx28X/include/wx/scrolbar.h | 80 + wx28X/include/wx/scrolwin.h | 314 + wx28X/include/wx/selstore.h | 104 + wx28X/include/wx/settings.h | 214 + wx28X/include/wx/setup_inc.h | 1198 + wx28X/include/wx/setup_redirect.h | 18 + wx28X/include/wx/sizer.h | 1092 + wx28X/include/wx/slider.h | 151 + wx28X/include/wx/snglinst.h | 65 + wx28X/include/wx/socket.h | 335 + wx28X/include/wx/sound.h | 98 + wx28X/include/wx/spinbutt.h | 129 + wx28X/include/wx/spinctrl.h | 83 + wx28X/include/wx/splash.h | 18 + wx28X/include/wx/splitter.h | 47 + wx28X/include/wx/srchctrl.h | 91 + wx28X/include/wx/sstream.h | 103 + wx28X/include/wx/stack.h | 44 + wx28X/include/wx/stackwalk.h | 156 + wx28X/include/wx/statbmp.h | 74 + wx28X/include/wx/statbox.h | 74 + wx28X/include/wx/statline.h | 103 + wx28X/include/wx/stattext.h | 69 + wx28X/include/wx/statusbr.h | 174 + wx28X/include/wx/stdpaths.h | 179 + wx28X/include/wx/stockitem.h | 73 + wx28X/include/wx/stopwatch.h | 102 + wx28X/include/wx/strconv.h | 553 + wx28X/include/wx/stream.h | 609 + wx28X/include/wx/string.h | 1653 + wx28X/include/wx/sysopt.h | 71 + wx28X/include/wx/tab.h | 22 + wx28X/include/wx/tabctrl.h | 34 + wx28X/include/wx/tarstrm.h | 352 + wx28X/include/wx/taskbar.h | 124 + wx28X/include/wx/tbarbase.h | 607 + wx28X/include/wx/textbuf.h | 208 + wx28X/include/wx/textctrl.h | 601 + wx28X/include/wx/textdlg.h | 23 + wx28X/include/wx/textfile.h | 62 + wx28X/include/wx/tglbtn.h | 51 + wx28X/include/wx/thread.h | 764 + wx28X/include/wx/thrimpl.cpp | 332 + wx28X/include/wx/timer.h | 201 + wx28X/include/wx/tipdlg.h | 84 + wx28X/include/wx/tipwin.h | 98 + wx28X/include/wx/tokenzr.h | 135 + wx28X/include/wx/toolbar.h | 93 + wx28X/include/wx/toolbook.h | 163 + wx28X/include/wx/tooltip.h | 39 + wx28X/include/wx/toplevel.h | 375 + wx28X/include/wx/treebase.h | 426 + wx28X/include/wx/treebook.h | 283 + wx28X/include/wx/treectrl.h | 459 + wx28X/include/wx/txtstrm.h | 160 + wx28X/include/wx/types.h | 93 + wx28X/include/wx/univ/app.h | 21 + wx28X/include/wx/univ/bmpbuttn.h | 72 + wx28X/include/wx/univ/button.h | 139 + wx28X/include/wx/univ/checkbox.h | 150 + wx28X/include/wx/univ/checklst.h | 114 + wx28X/include/wx/univ/chkconf.h | 117 + wx28X/include/wx/univ/choice.h | 64 + wx28X/include/wx/univ/colschem.h | 103 + wx28X/include/wx/univ/combobox.h | 167 + wx28X/include/wx/univ/control.h | 102 + wx28X/include/wx/univ/dialog.h | 88 + wx28X/include/wx/univ/frame.h | 92 + wx28X/include/wx/univ/gauge.h | 75 + wx28X/include/wx/univ/inpcons.h | 153 + wx28X/include/wx/univ/inphand.h | 116 + wx28X/include/wx/univ/listbox.h | 300 + wx28X/include/wx/univ/menu.h | 282 + wx28X/include/wx/univ/menuitem.h | 135 + wx28X/include/wx/univ/notebook.h | 257 + wx28X/include/wx/univ/radiobox.h | 151 + wx28X/include/wx/univ/radiobut.h | 76 + wx28X/include/wx/univ/renderer.h | 932 + wx28X/include/wx/univ/scrarrow.h | 112 + wx28X/include/wx/univ/scrolbar.h | 283 + wx28X/include/wx/univ/scrthumb.h | 140 + wx28X/include/wx/univ/scrtimer.h | 51 + wx28X/include/wx/univ/setup.h | 1328 + wx28X/include/wx/univ/setup0.h | 1328 + wx28X/include/wx/univ/slider.h | 226 + wx28X/include/wx/univ/spinbutt.h | 122 + wx28X/include/wx/univ/statbmp.h | 74 + wx28X/include/wx/univ/statbox.h | 65 + wx28X/include/wx/univ/statline.h | 56 + wx28X/include/wx/univ/stattext.h | 66 + wx28X/include/wx/univ/statusbr.h | 110 + wx28X/include/wx/univ/stdrend.h | 352 + wx28X/include/wx/univ/textctrl.h | 534 + wx28X/include/wx/univ/tglbtn.h | 70 + wx28X/include/wx/univ/theme.h | 202 + wx28X/include/wx/univ/toolbar.h | 138 + wx28X/include/wx/univ/toplevel.h | 197 + wx28X/include/wx/univ/window.h | 287 + wx28X/include/wx/unix/apptbase.h | 54 + wx28X/include/wx/unix/apptrait.h | 55 + wx28X/include/wx/unix/execute.h | 79 + wx28X/include/wx/unix/fontutil.h | 37 + wx28X/include/wx/unix/gsockunx.h | 145 + wx28X/include/wx/unix/joystick.h | 95 + wx28X/include/wx/unix/mimetype.h | 215 + wx28X/include/wx/unix/pipe.h | 114 + wx28X/include/wx/unix/private.h | 47 + wx28X/include/wx/unix/sound.h | 161 + wx28X/include/wx/unix/stackwalk.h | 97 + wx28X/include/wx/unix/stdpaths.h | 56 + wx28X/include/wx/unix/taskbarx11.h | 46 + wx28X/include/wx/unix/utilsx11.h | 53 + wx28X/include/wx/uri.h | 151 + wx28X/include/wx/url.h | 129 + wx28X/include/wx/utils.h | 747 + wx28X/include/wx/valgen.h | 69 + wx28X/include/wx/validate.h | 98 + wx28X/include/wx/valtext.h | 122 + wx28X/include/wx/variant.h | 423 + wx28X/include/wx/vector.h | 212 + wx28X/include/wx/version.h | 91 + wx28X/include/wx/vidmode.h | 73 + wx28X/include/wx/vlbox.h | 296 + wx28X/include/wx/vms_x_fix.h | 1213 + wx28X/include/wx/volume.h | 146 + wx28X/include/wx/vscroll.h | 223 + wx28X/include/wx/wave.h | 36 + wx28X/include/wx/wfstream.h | 204 + wx28X/include/wx/window.h | 1671 + wx28X/include/wx/wizard.h | 323 + wx28X/include/wx/wupdlock.h | 37 + wx28X/include/wx/wx.h | 105 + wx28X/include/wx/wx_cw.h | 65 + wx28X/include/wx/wx_cw_cm.h | 88 + wx28X/include/wx/wx_cw_d.h | 46 + wx28X/include/wx/wx_cwc.h | 49 + wx28X/include/wx/wx_cwc_d.h | 38 + wx28X/include/wx/wx_cwcocoa.h | 66 + wx28X/include/wx/wx_cwcocoa_cm.h | 85 + wx28X/include/wx/wx_cwcocoa_d.h | 47 + wx28X/include/wx/wx_cwu_d.h | 46 + wx28X/include/wx/wxchar.h | 1413 + wx28X/include/wx/wxhtml.h | 22 + wx28X/include/wx/wxprec.h | 70 + wx28X/include/wx/wxshlb_cw.h | 65 + wx28X/include/wx/wxshlb_cw_d.h | 46 + wx28X/include/wx/wxshlb_cwc.h | 45 + wx28X/include/wx/wxshlb_cwc_d.h | 38 + wx28X/include/wx/wxshlba_cw.h | 65 + wx28X/include/wx/wxshlba_cw_d.h | 46 + wx28X/include/wx/wxshlba_cwc.h | 45 + wx28X/include/wx/wxshlba_cwc_d.h | 38 + wx28X/include/wx/xml/xml.h | 272 + wx28X/include/wx/xpmdecod.h | 47 + wx28X/include/wx/xpmhand.h | 25 + wx28X/include/wx/xrc/xh_all.h | 74 + wx28X/include/wx/xrc/xh_animatctrl.h | 30 + wx28X/include/wx/xrc/xh_bmp.h | 40 + wx28X/include/wx/xrc/xh_bmpbt.h | 30 + wx28X/include/wx/xrc/xh_bmpcbox.h | 36 + wx28X/include/wx/xrc/xh_bttn.h | 30 + wx28X/include/wx/xrc/xh_cald.h | 30 + wx28X/include/wx/xrc/xh_chckb.h | 31 + wx28X/include/wx/xrc/xh_chckl.h | 34 + wx28X/include/wx/xrc/xh_choic.h | 34 + wx28X/include/wx/xrc/xh_choicbk.h | 34 + wx28X/include/wx/xrc/xh_clrpicker.h | 30 + wx28X/include/wx/xrc/xh_collpane.h | 36 + wx28X/include/wx/xrc/xh_combo.h | 34 + wx28X/include/wx/xrc/xh_datectrl.h | 30 + wx28X/include/wx/xrc/xh_dirpicker.h | 30 + wx28X/include/wx/xrc/xh_dlg.h | 30 + wx28X/include/wx/xrc/xh_filepicker.h | 30 + wx28X/include/wx/xrc/xh_fontpicker.h | 30 + wx28X/include/wx/xrc/xh_frame.h | 30 + wx28X/include/wx/xrc/xh_gauge.h | 34 + wx28X/include/wx/xrc/xh_gdctl.h | 30 + wx28X/include/wx/xrc/xh_grid.h | 31 + wx28X/include/wx/xrc/xh_html.h | 30 + wx28X/include/wx/xrc/xh_htmllbox.h | 34 + wx28X/include/wx/xrc/xh_hyperlink.h | 37 + wx28X/include/wx/xrc/xh_listb.h | 34 + wx28X/include/wx/xrc/xh_listbk.h | 34 + wx28X/include/wx/xrc/xh_listc.h | 30 + wx28X/include/wx/xrc/xh_mdi.h | 35 + wx28X/include/wx/xrc/xh_menu.h | 43 + wx28X/include/wx/xrc/xh_notbk.h | 35 + wx28X/include/wx/xrc/xh_odcombo.h | 35 + wx28X/include/wx/xrc/xh_panel.h | 30 + wx28X/include/wx/xrc/xh_propdlg.h | 38 + wx28X/include/wx/xrc/xh_radbt.h | 30 + wx28X/include/wx/xrc/xh_radbx.h | 43 + wx28X/include/wx/xrc/xh_richtext.h | 30 + wx28X/include/wx/xrc/xh_scrol.h | 36 + wx28X/include/wx/xrc/xh_scwin.h | 30 + wx28X/include/wx/xrc/xh_sizer.h | 80 + wx28X/include/wx/xrc/xh_slidr.h | 36 + wx28X/include/wx/xrc/xh_spin.h | 61 + wx28X/include/wx/xrc/xh_split.h | 30 + wx28X/include/wx/xrc/xh_statbar.h | 30 + wx28X/include/wx/xrc/xh_stbmp.h | 30 + wx28X/include/wx/xrc/xh_stbox.h | 30 + wx28X/include/wx/xrc/xh_stlin.h | 30 + wx28X/include/wx/xrc/xh_sttxt.h | 30 + wx28X/include/wx/xrc/xh_text.h | 30 + wx28X/include/wx/xrc/xh_tglbtn.h | 30 + wx28X/include/wx/xrc/xh_toolb.h | 36 + wx28X/include/wx/xrc/xh_tree.h | 30 + wx28X/include/wx/xrc/xh_treebk.h | 83 + wx28X/include/wx/xrc/xh_unkwn.h | 30 + wx28X/include/wx/xrc/xh_wizrd.h | 37 + wx28X/include/wx/xrc/xmlres.h | 528 + wx28X/include/wx/xti.h | 2102 + wx28X/include/wx/xtistrm.h | 429 + wx28X/include/wx/xtixml.h | 106 + wx28X/include/wx/zipstrm.h | 574 + wx28X/include/wx/zstream.h | 146 + wx28X/include/wx_pb.h | 20 + wx28X/install-sh | 250 + wx28X/lib/VMS_GTK2.OPT | 16 + wx28X/lib/VMS_X11_UNIV.OPT | 12 + wx28X/lib/_sc/Readme.txt | 22 + wx28X/lib/_sc/shell32_sc.def | 16 + wx28X/lib/_sc/winmm32_sc.def | 12 + wx28X/lib/_sc/wsock32_sc.def | 33 + wx28X/lib/abicheck.sh | 77 + wx28X/lib/dummy | 1 + wx28X/lib/expected_abi | 22667 ++ wx28X/lib/vc_dll/msw/wx/msw/rcdefs.h | 44 + wx28X/lib/vc_dll/msw/wx/setup.h | 1361 + wx28X/lib/vc_dll/mswd/wx/msw/rcdefs.h | 44 + wx28X/lib/vc_dll/mswd/wx/setup.h | 1361 + wx28X/lib/vc_dll/wxbase28.exp | Bin 0 -> 1246012 bytes wx28X/lib/vc_dll/wxbase28.lib | Bin 0 -> 2108854 bytes wx28X/lib/vc_dll/wxbase28_net.exp | Bin 0 -> 83866 bytes wx28X/lib/vc_dll/wxbase28_net.lib | Bin 0 -> 142006 bytes wx28X/lib/vc_dll/wxbase28_net_vc_custom.dll | Bin 0 -> 199680 bytes wx28X/lib/vc_dll/wxbase28_net_vc_custom.pdb | Bin 0 -> 1536000 bytes wx28X/lib/vc_dll/wxbase28_odbc.exp | Bin 0 -> 43153 bytes wx28X/lib/vc_dll/wxbase28_odbc.lib | Bin 0 -> 75578 bytes wx28X/lib/vc_dll/wxbase28_odbc_vc_custom.dll | Bin 0 -> 172544 bytes wx28X/lib/vc_dll/wxbase28_odbc_vc_custom.pdb | Bin 0 -> 1470464 bytes wx28X/lib/vc_dll/wxbase28_vc_custom.dll | Bin 0 -> 1238016 bytes wx28X/lib/vc_dll/wxbase28_vc_custom.pdb | Bin 0 -> 1912832 bytes wx28X/lib/vc_dll/wxbase28_xml.exp | Bin 0 -> 15130 bytes wx28X/lib/vc_dll/wxbase28_xml.lib | Bin 0 -> 26796 bytes wx28X/lib/vc_dll/wxbase28_xml_vc_custom.dll | Bin 0 -> 158208 bytes wx28X/lib/vc_dll/wxbase28_xml_vc_custom.pdb | Bin 0 -> 1445888 bytes wx28X/lib/vc_dll/wxbase28d.exp | Bin 0 -> 1252425 bytes wx28X/lib/vc_dll/wxbase28d.lib | Bin 0 -> 2126206 bytes wx28X/lib/vc_dll/wxbase28d_net.exp | Bin 0 -> 83869 bytes wx28X/lib/vc_dll/wxbase28d_net.lib | Bin 0 -> 142438 bytes wx28X/lib/vc_dll/wxbase28d_net_vc_custom.dll | Bin 0 -> 651776 bytes wx28X/lib/vc_dll/wxbase28d_net_vc_custom.idb | Bin 0 -> 1166336 bytes wx28X/lib/vc_dll/wxbase28d_net_vc_custom.ilk | Bin 0 -> 2151944 bytes wx28X/lib/vc_dll/wxbase28d_net_vc_custom.pdb | Bin 0 -> 4550656 bytes wx28X/lib/vc_dll/wxbase28d_odbc.exp | Bin 0 -> 43318 bytes wx28X/lib/vc_dll/wxbase28d_odbc.lib | Bin 0 -> 76118 bytes wx28X/lib/vc_dll/wxbase28d_odbc_vc_custom.dll | Bin 0 -> 619520 bytes wx28X/lib/vc_dll/wxbase28d_odbc_vc_custom.idb | Bin 0 -> 1068032 bytes wx28X/lib/vc_dll/wxbase28d_odbc_vc_custom.ilk | Bin 0 -> 1439896 bytes wx28X/lib/vc_dll/wxbase28d_odbc_vc_custom.pdb | Bin 0 -> 4198400 bytes wx28X/lib/vc_dll/wxbase28d_vc_custom.dll | Bin 0 -> 2592256 bytes wx28X/lib/vc_dll/wxbase28d_vc_custom.idb | Bin 0 -> 1756160 bytes wx28X/lib/vc_dll/wxbase28d_vc_custom.ilk | Bin 0 -> 7394920 bytes wx28X/lib/vc_dll/wxbase28d_vc_custom.pdb | Bin 0 -> 10055680 bytes wx28X/lib/vc_dll/wxbase28d_xml.exp | Bin 0 -> 15131 bytes wx28X/lib/vc_dll/wxbase28d_xml.lib | Bin 0 -> 26890 bytes wx28X/lib/vc_dll/wxbase28d_xml_vc_custom.dll | Bin 0 -> 608768 bytes wx28X/lib/vc_dll/wxbase28d_xml_vc_custom.idb | Bin 0 -> 1035264 bytes wx28X/lib/vc_dll/wxbase28d_xml_vc_custom.ilk | Bin 0 -> 1141728 bytes wx28X/lib/vc_dll/wxbase28d_xml_vc_custom.pdb | Bin 0 -> 3895296 bytes wx28X/lib/vc_dll/wxexpat.lib | Bin 0 -> 474962 bytes wx28X/lib/vc_dll/wxexpat.pdb | Bin 0 -> 86016 bytes wx28X/lib/vc_dll/wxexpatd.idb | Bin 0 -> 166912 bytes wx28X/lib/vc_dll/wxexpatd.lib | Bin 0 -> 467954 bytes wx28X/lib/vc_dll/wxexpatd.pdb | Bin 0 -> 86016 bytes wx28X/lib/vc_dll/wxjpeg.lib | Bin 0 -> 663290 bytes wx28X/lib/vc_dll/wxjpeg.pdb | Bin 0 -> 102400 bytes wx28X/lib/vc_dll/wxjpegd.idb | Bin 0 -> 125952 bytes wx28X/lib/vc_dll/wxjpegd.lib | Bin 0 -> 582548 bytes wx28X/lib/vc_dll/wxjpegd.pdb | Bin 0 -> 102400 bytes wx28X/lib/vc_dll/wxmsw28_adv.exp | Bin 0 -> 531257 bytes wx28X/lib/vc_dll/wxmsw28_adv.lib | Bin 0 -> 888150 bytes wx28X/lib/vc_dll/wxmsw28_adv_vc_custom.dll | Bin 0 -> 736768 bytes wx28X/lib/vc_dll/wxmsw28_adv_vc_custom.pdb | Bin 0 -> 2338816 bytes wx28X/lib/vc_dll/wxmsw28_aui.exp | Bin 0 -> 223771 bytes wx28X/lib/vc_dll/wxmsw28_aui.lib | Bin 0 -> 377516 bytes wx28X/lib/vc_dll/wxmsw28_aui_vc_custom.dll | Bin 0 -> 369664 bytes wx28X/lib/vc_dll/wxmsw28_aui_vc_custom.pdb | Bin 0 -> 2093056 bytes wx28X/lib/vc_dll/wxmsw28_core.exp | Bin 0 -> 2426796 bytes wx28X/lib/vc_dll/wxmsw28_core.lib | Bin 0 -> 4084730 bytes wx28X/lib/vc_dll/wxmsw28_core_vc_custom.dll | Bin 0 -> 2926592 bytes wx28X/lib/vc_dll/wxmsw28_core_vc_custom.pdb | Bin 0 -> 2740224 bytes wx28X/lib/vc_dll/wxmsw28_dbgrid.exp | Bin 0 -> 14530 bytes wx28X/lib/vc_dll/wxmsw28_dbgrid.lib | Bin 0 -> 25910 bytes wx28X/lib/vc_dll/wxmsw28_dbgrid_vc_custom.dll | Bin 0 -> 83456 bytes wx28X/lib/vc_dll/wxmsw28_dbgrid_vc_custom.pdb | Bin 0 -> 2027520 bytes wx28X/lib/vc_dll/wxmsw28_gl_vc_custom.dll | Bin 0 -> 34304 bytes wx28X/lib/vc_dll/wxmsw28_gl_vc_custom.pdb | Bin 0 -> 1970176 bytes wx28X/lib/vc_dll/wxmsw28_html.exp | Bin 0 -> 206894 bytes wx28X/lib/vc_dll/wxmsw28_html.lib | Bin 0 -> 348376 bytes wx28X/lib/vc_dll/wxmsw28_html_vc_custom.dll | Bin 0 -> 543232 bytes wx28X/lib/vc_dll/wxmsw28_html_vc_custom.pdb | Bin 0 -> 2330624 bytes wx28X/lib/vc_dll/wxmsw28_media.exp | Bin 0 -> 58053 bytes wx28X/lib/vc_dll/wxmsw28_media.lib | Bin 0 -> 99476 bytes wx28X/lib/vc_dll/wxmsw28_media_vc_custom.dll | Bin 0 -> 174592 bytes wx28X/lib/vc_dll/wxmsw28_media_vc_custom.pdb | Bin 0 -> 2076672 bytes wx28X/lib/vc_dll/wxmsw28_qa.exp | Bin 0 -> 10630 bytes wx28X/lib/vc_dll/wxmsw28_qa.lib | Bin 0 -> 18820 bytes wx28X/lib/vc_dll/wxmsw28_qa_vc_custom.dll | Bin 0 -> 137728 bytes wx28X/lib/vc_dll/wxmsw28_qa_vc_custom.pdb | Bin 0 -> 2060288 bytes wx28X/lib/vc_dll/wxmsw28_richtext.exp | Bin 0 -> 490386 bytes wx28X/lib/vc_dll/wxmsw28_richtext.lib | Bin 0 -> 833768 bytes .../lib/vc_dll/wxmsw28_richtext_vc_custom.dll | Bin 0 -> 795136 bytes .../lib/vc_dll/wxmsw28_richtext_vc_custom.pdb | Bin 0 -> 2330624 bytes wx28X/lib/vc_dll/wxmsw28_xrc.exp | Bin 0 -> 181623 bytes wx28X/lib/vc_dll/wxmsw28_xrc.lib | Bin 0 -> 301358 bytes wx28X/lib/vc_dll/wxmsw28_xrc_vc_custom.dll | Bin 0 -> 546816 bytes wx28X/lib/vc_dll/wxmsw28_xrc_vc_custom.pdb | Bin 0 -> 2420736 bytes wx28X/lib/vc_dll/wxmsw28d_adv.exp | Bin 0 -> 531752 bytes wx28X/lib/vc_dll/wxmsw28d_adv.lib | Bin 0 -> 891458 bytes wx28X/lib/vc_dll/wxmsw28d_adv_vc_custom.dll | Bin 0 -> 1434112 bytes wx28X/lib/vc_dll/wxmsw28d_adv_vc_custom.idb | Bin 0 -> 2051072 bytes wx28X/lib/vc_dll/wxmsw28d_adv_vc_custom.ilk | Bin 0 -> 7262728 bytes wx28X/lib/vc_dll/wxmsw28d_adv_vc_custom.pdb | Bin 0 -> 7434240 bytes wx28X/lib/vc_dll/wxmsw28d_aui.exp | Bin 0 -> 223772 bytes wx28X/lib/vc_dll/wxmsw28d_aui.lib | Bin 0 -> 378584 bytes wx28X/lib/vc_dll/wxmsw28d_aui_vc_custom.dll | Bin 0 -> 892928 bytes wx28X/lib/vc_dll/wxmsw28d_aui_vc_custom.idb | Bin 0 -> 1756160 bytes wx28X/lib/vc_dll/wxmsw28d_aui_vc_custom.ilk | Bin 0 -> 3984820 bytes wx28X/lib/vc_dll/wxmsw28d_aui_vc_custom.pdb | Bin 0 -> 5623808 bytes wx28X/lib/vc_dll/wxmsw28d_core.exp | Bin 0 -> 2438255 bytes wx28X/lib/vc_dll/wxmsw28d_core.lib | Bin 0 -> 4116204 bytes wx28X/lib/vc_dll/wxmsw28d_core_vc_custom.dll | Bin 0 -> 5196288 bytes wx28X/lib/vc_dll/wxmsw28d_core_vc_custom.idb | Bin 0 -> 3435520 bytes wx28X/lib/vc_dll/wxmsw28d_core_vc_custom.ilk | Bin 0 -> 15281604 bytes wx28X/lib/vc_dll/wxmsw28d_core_vc_custom.pdb | Bin 0 -> 16642048 bytes wx28X/lib/vc_dll/wxmsw28d_dbgrid.exp | Bin 0 -> 14533 bytes wx28X/lib/vc_dll/wxmsw28d_dbgrid.lib | Bin 0 -> 25998 bytes .../lib/vc_dll/wxmsw28d_dbgrid_vc_custom.dll | Bin 0 -> 465408 bytes .../lib/vc_dll/wxmsw28d_dbgrid_vc_custom.idb | Bin 0 -> 1682432 bytes .../lib/vc_dll/wxmsw28d_dbgrid_vc_custom.ilk | Bin 0 -> 1279684 bytes .../lib/vc_dll/wxmsw28d_dbgrid_vc_custom.pdb | Bin 0 -> 4485120 bytes wx28X/lib/vc_dll/wxmsw28d_gl_vc_custom.dll | Bin 0 -> 385024 bytes wx28X/lib/vc_dll/wxmsw28d_gl_vc_custom.idb | Bin 0 -> 1616896 bytes wx28X/lib/vc_dll/wxmsw28d_gl_vc_custom.ilk | Bin 0 -> 930332 bytes wx28X/lib/vc_dll/wxmsw28d_gl_vc_custom.pdb | Bin 0 -> 4124672 bytes wx28X/lib/vc_dll/wxmsw28d_html.exp | Bin 0 -> 207889 bytes wx28X/lib/vc_dll/wxmsw28d_html.lib | Bin 0 -> 350962 bytes wx28X/lib/vc_dll/wxmsw28d_html_vc_custom.dll | Bin 0 -> 1142784 bytes wx28X/lib/vc_dll/wxmsw28d_html_vc_custom.idb | Bin 0 -> 2116608 bytes wx28X/lib/vc_dll/wxmsw28d_html_vc_custom.ilk | Bin 0 -> 7220460 bytes wx28X/lib/vc_dll/wxmsw28d_html_vc_custom.pdb | Bin 0 -> 6770688 bytes wx28X/lib/vc_dll/wxmsw28d_media.exp | Bin 0 -> 57932 bytes wx28X/lib/vc_dll/wxmsw28d_media.lib | Bin 0 -> 99532 bytes wx28X/lib/vc_dll/wxmsw28d_media_vc_custom.dll | Bin 0 -> 617472 bytes wx28X/lib/vc_dll/wxmsw28d_media_vc_custom.idb | Bin 0 -> 1723392 bytes wx28X/lib/vc_dll/wxmsw28d_media_vc_custom.ilk | Bin 0 -> 2197996 bytes wx28X/lib/vc_dll/wxmsw28d_media_vc_custom.pdb | Bin 0 -> 5132288 bytes wx28X/lib/vc_dll/wxmsw28d_qa.exp | Bin 0 -> 10633 bytes wx28X/lib/vc_dll/wxmsw28d_qa.lib | Bin 0 -> 18888 bytes wx28X/lib/vc_dll/wxmsw28d_qa_vc_custom.dll | Bin 0 -> 512000 bytes wx28X/lib/vc_dll/wxmsw28d_qa_vc_custom.idb | Bin 0 -> 1723392 bytes wx28X/lib/vc_dll/wxmsw28d_qa_vc_custom.ilk | Bin 0 -> 2619852 bytes wx28X/lib/vc_dll/wxmsw28d_qa_vc_custom.pdb | Bin 0 -> 4616192 bytes wx28X/lib/vc_dll/wxmsw28d_richtext.exp | Bin 0 -> 490387 bytes wx28X/lib/vc_dll/wxmsw28d_richtext.lib | Bin 0 -> 835782 bytes .../vc_dll/wxmsw28d_richtext_vc_custom.dll | Bin 0 -> 1546752 bytes .../vc_dll/wxmsw28d_richtext_vc_custom.idb | Bin 0 -> 2067456 bytes .../vc_dll/wxmsw28d_richtext_vc_custom.ilk | Bin 0 -> 7270156 bytes .../vc_dll/wxmsw28d_richtext_vc_custom.pdb | Bin 0 -> 7163904 bytes wx28X/lib/vc_dll/wxmsw28d_xrc.exp | Bin 0 -> 181626 bytes wx28X/lib/vc_dll/wxmsw28d_xrc.lib | Bin 0 -> 302188 bytes wx28X/lib/vc_dll/wxmsw28d_xrc_vc_custom.dll | Bin 0 -> 1120768 bytes wx28X/lib/vc_dll/wxmsw28d_xrc_vc_custom.idb | Bin 0 -> 2460672 bytes wx28X/lib/vc_dll/wxmsw28d_xrc_vc_custom.ilk | Bin 0 -> 7867316 bytes wx28X/lib/vc_dll/wxmsw28d_xrc_vc_custom.pdb | Bin 0 -> 6893568 bytes wx28X/lib/vc_dll/wxpng.lib | Bin 0 -> 586204 bytes wx28X/lib/vc_dll/wxpng.pdb | Bin 0 -> 77824 bytes wx28X/lib/vc_dll/wxpngd.idb | Bin 0 -> 84992 bytes wx28X/lib/vc_dll/wxpngd.lib | Bin 0 -> 512962 bytes wx28X/lib/vc_dll/wxpngd.pdb | Bin 0 -> 77824 bytes wx28X/lib/vc_dll/wxregex.lib | Bin 0 -> 356688 bytes wx28X/lib/vc_dll/wxregex.pdb | Bin 0 -> 77824 bytes wx28X/lib/vc_dll/wxregexd.idb | Bin 0 -> 109568 bytes wx28X/lib/vc_dll/wxregexd.lib | Bin 0 -> 243652 bytes wx28X/lib/vc_dll/wxregexd.pdb | Bin 0 -> 77824 bytes wx28X/lib/vc_dll/wxtiff.lib | Bin 0 -> 1401276 bytes wx28X/lib/vc_dll/wxtiff.pdb | Bin 0 -> 102400 bytes wx28X/lib/vc_dll/wxtiffd.idb | Bin 0 -> 322560 bytes wx28X/lib/vc_dll/wxtiffd.lib | Bin 0 -> 1246586 bytes wx28X/lib/vc_dll/wxtiffd.pdb | Bin 0 -> 102400 bytes wx28X/lib/vc_dll/wxzlib.lib | Bin 0 -> 197362 bytes wx28X/lib/vc_dll/wxzlib.pdb | Bin 0 -> 69632 bytes wx28X/lib/vc_dll/wxzlibd.idb | Bin 0 -> 76800 bytes wx28X/lib/vc_dll/wxzlibd.lib | Bin 0 -> 190608 bytes wx28X/lib/vc_dll/wxzlibd.pdb | Bin 0 -> 69632 bytes wx28X/lib/vc_lib/msw/wx/msw/rcdefs.h | 44 + wx28X/lib/vc_lib/msw/wx/setup.h | 1361 + wx28X/lib/vc_lib/mswd/wx/msw/rcdefs.h | 44 + wx28X/lib/vc_lib/mswd/wx/setup.h | 1361 + wx28X/lib/vc_lib/wxbase28.lib | Bin 0 -> 8370594 bytes wx28X/lib/vc_lib/wxbase28.pdb | Bin 0 -> 1929216 bytes wx28X/lib/vc_lib/wxbase28_net.lib | Bin 0 -> 1405482 bytes wx28X/lib/vc_lib/wxbase28_net.pdb | Bin 0 -> 1568768 bytes wx28X/lib/vc_lib/wxbase28_odbc.lib | Bin 0 -> 845062 bytes wx28X/lib/vc_lib/wxbase28_odbc.pdb | Bin 0 -> 1470464 bytes wx28X/lib/vc_lib/wxbase28_xml.lib | Bin 0 -> 550356 bytes wx28X/lib/vc_lib/wxbase28_xml.pdb | Bin 0 -> 1445888 bytes wx28X/lib/vc_lib/wxbase28d.idb | Bin 0 -> 2550784 bytes wx28X/lib/vc_lib/wxbase28d.lib | Bin 0 -> 8223764 bytes wx28X/lib/vc_lib/wxbase28d.pdb | Bin 0 -> 2199552 bytes wx28X/lib/vc_lib/wxbase28d_net.idb | Bin 0 -> 1166336 bytes wx28X/lib/vc_lib/wxbase28d_net.lib | Bin 0 -> 1351178 bytes wx28X/lib/vc_lib/wxbase28d_net.pdb | Bin 0 -> 1552384 bytes wx28X/lib/vc_lib/wxexpat.lib | Bin 0 -> 475022 bytes wx28X/lib/vc_lib/wxexpat.pdb | Bin 0 -> 86016 bytes wx28X/lib/vc_lib/wxexpatd.idb | Bin 0 -> 183296 bytes wx28X/lib/vc_lib/wxexpatd.lib | Bin 0 -> 468024 bytes wx28X/lib/vc_lib/wxexpatd.pdb | Bin 0 -> 86016 bytes wx28X/lib/vc_lib/wxjpeg.lib | Bin 0 -> 664224 bytes wx28X/lib/vc_lib/wxjpeg.pdb | Bin 0 -> 102400 bytes wx28X/lib/vc_lib/wxjpegd.idb | Bin 0 -> 207872 bytes wx28X/lib/vc_lib/wxjpegd.lib | Bin 0 -> 583398 bytes wx28X/lib/vc_lib/wxjpegd.pdb | Bin 0 -> 102400 bytes wx28X/lib/vc_lib/wxmsw28_adv.lib | Bin 0 -> 7036078 bytes wx28X/lib/vc_lib/wxmsw28_adv.pdb | Bin 0 -> 2355200 bytes wx28X/lib/vc_lib/wxmsw28_aui.lib | Bin 0 -> 2897784 bytes wx28X/lib/vc_lib/wxmsw28_aui.pdb | Bin 0 -> 2093056 bytes wx28X/lib/vc_lib/wxmsw28_core.lib | Bin 0 -> 31212938 bytes wx28X/lib/vc_lib/wxmsw28_core.pdb | Bin 0 -> 2756608 bytes wx28X/lib/vc_lib/wxmsw28_dbgrid.lib | Bin 0 -> 604210 bytes wx28X/lib/vc_lib/wxmsw28_dbgrid.pdb | Bin 0 -> 2035712 bytes wx28X/lib/vc_lib/wxmsw28_gl.lib | Bin 0 -> 441756 bytes wx28X/lib/vc_lib/wxmsw28_gl.pdb | Bin 0 -> 1970176 bytes wx28X/lib/vc_lib/wxmsw28_html.lib | Bin 0 -> 5588102 bytes wx28X/lib/vc_lib/wxmsw28_html.pdb | Bin 0 -> 2347008 bytes wx28X/lib/vc_lib/wxmsw28_media.lib | Bin 0 -> 1253796 bytes wx28X/lib/vc_lib/wxmsw28_media.pdb | Bin 0 -> 2084864 bytes wx28X/lib/vc_lib/wxmsw28_qa.lib | Bin 0 -> 1073868 bytes wx28X/lib/vc_lib/wxmsw28_qa.pdb | Bin 0 -> 2060288 bytes wx28X/lib/vc_lib/wxmsw28_richtext.lib | Bin 0 -> 6266424 bytes wx28X/lib/vc_lib/wxmsw28_richtext.pdb | Bin 0 -> 2322432 bytes wx28X/lib/vc_lib/wxmsw28_xrc.lib | Bin 0 -> 7974502 bytes wx28X/lib/vc_lib/wxmsw28_xrc.pdb | Bin 0 -> 2412544 bytes wx28X/lib/vc_lib/wxmsw28d_adv.idb | Bin 0 -> 2051072 bytes wx28X/lib/vc_lib/wxmsw28d_adv.lib | Bin 0 -> 6793330 bytes wx28X/lib/vc_lib/wxmsw28d_adv.pdb | Bin 0 -> 2347008 bytes wx28X/lib/vc_lib/wxmsw28d_core.idb | Bin 0 -> 5688320 bytes wx28X/lib/vc_lib/wxmsw28d_core.lib | Bin 0 -> 30286192 bytes wx28X/lib/vc_lib/wxmsw28d_core.pdb | Bin 0 -> 3018752 bytes wx28X/lib/vc_lib/wxmsw28d_html.idb | Bin 0 -> 2108416 bytes wx28X/lib/vc_lib/wxmsw28d_html.lib | Bin 0 -> 5294890 bytes wx28X/lib/vc_lib/wxmsw28d_html.pdb | Bin 0 -> 2338816 bytes wx28X/lib/vc_lib/wxpng.lib | Bin 0 -> 586474 bytes wx28X/lib/vc_lib/wxpng.pdb | Bin 0 -> 77824 bytes wx28X/lib/vc_lib/wxpngd.idb | Bin 0 -> 117760 bytes wx28X/lib/vc_lib/wxpngd.lib | Bin 0 -> 513146 bytes wx28X/lib/vc_lib/wxpngd.pdb | Bin 0 -> 77824 bytes wx28X/lib/vc_lib/wxregex.lib | Bin 0 -> 356876 bytes wx28X/lib/vc_lib/wxregex.pdb | Bin 0 -> 77824 bytes wx28X/lib/vc_lib/wxregexd.idb | Bin 0 -> 142336 bytes wx28X/lib/vc_lib/wxregexd.lib | Bin 0 -> 244284 bytes wx28X/lib/vc_lib/wxregexd.pdb | Bin 0 -> 77824 bytes wx28X/lib/vc_lib/wxtiff.lib | Bin 0 -> 1402018 bytes wx28X/lib/vc_lib/wxtiff.pdb | Bin 0 -> 102400 bytes wx28X/lib/vc_lib/wxtiffd.idb | Bin 0 -> 379904 bytes wx28X/lib/vc_lib/wxtiffd.lib | Bin 0 -> 1247330 bytes wx28X/lib/vc_lib/wxtiffd.pdb | Bin 0 -> 102400 bytes wx28X/lib/vc_lib/wxzlib.lib | Bin 0 -> 197502 bytes wx28X/lib/vc_lib/wxzlib.pdb | Bin 0 -> 69632 bytes wx28X/lib/vc_lib/wxzlibd.idb | Bin 0 -> 101376 bytes wx28X/lib/vc_lib/wxzlibd.lib | Bin 0 -> 190748 bytes wx28X/lib/vc_lib/wxzlibd.pdb | Bin 0 -> 69632 bytes wx28X/lib/vms.opt | 11 + wx28X/lib/vms_gtk.opt | 15 + wx28X/lib/watcom/makeit.bat | 1 + wx28X/lib/watcom/odbc.txt | 63 + wx28X/lib/watcom/odbc32.lib | Bin 0 -> 36352 bytes wx28X/lib/watcom/readme.txt | 13 + wx28X/locale/Makefile | 66 + wx28X/locale/af.po | 7001 + wx28X/locale/ca.po | 7172 + wx28X/locale/cs.po | 6978 + wx28X/locale/da.po | 7424 + wx28X/locale/de.po | 6988 + wx28X/locale/el.po | 7167 + wx28X/locale/es.po | 6947 + wx28X/locale/eu.po | 6738 + wx28X/locale/fi.po | 7100 + wx28X/locale/fr.po | 6905 + wx28X/locale/gl_ES.po | 7304 + wx28X/locale/hi.po | 6991 + wx28X/locale/hu.po | 6972 + wx28X/locale/id.po | 7183 + wx28X/locale/it.po | 6829 + wx28X/locale/ja.po | 7183 + wx28X/locale/lv.po | 6759 + wx28X/locale/ms.po | 6831 + wx28X/locale/msw/it.po | 17 + wx28X/locale/nb.po | 6981 + wx28X/locale/nl.po | 7363 + wx28X/locale/pl.po | 7024 + wx28X/locale/pt.po | 6833 + wx28X/locale/pt_BR.po | 6908 + wx28X/locale/ru.po | 6984 + wx28X/locale/sk.po | 6759 + wx28X/locale/sl.po | 8157 + wx28X/locale/sq.po | 6923 + wx28X/locale/sv.po | 6879 + wx28X/locale/tr.po | 7233 + wx28X/locale/uk.po | 6794 + wx28X/locale/vi.po | 6737 + wx28X/locale/wxstd.po | 6631 + wx28X/locale/zh_CN.po | 6895 + wx28X/locale/zh_TW.po | 6884 + wx28X/mkinstalldirs | 40 + wx28X/regen | 19 + wx28X/samples/Info.plist | 36 + wx28X/samples/Makefile.in | 11 + wx28X/samples/access/Makefile.in | 197 + wx28X/samples/access/access.bkl | 13 + wx28X/samples/access/access.dsp | 480 + wx28X/samples/access/access.vcp | 1826 + wx28X/samples/access/access.vcw | 17 + wx28X/samples/access/accesstest.cpp | 1113 + wx28X/samples/access/accesstest.rc | 3 + wx28X/samples/access/accesstestM5.xml | 3677 + wx28X/samples/access/accesstestW7.xml | 1968 + wx28X/samples/access/descrip.mms | 47 + wx28X/samples/access/makefile.bcc | 253 + wx28X/samples/access/makefile.dmc | 45 + wx28X/samples/access/makefile.dms | 213 + wx28X/samples/access/makefile.gcc | 253 + wx28X/samples/access/makefile.unx | 71 + wx28X/samples/access/makefile.vc | 359 + wx28X/samples/access/makefile.wat | 282 + wx28X/samples/access/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/access/mondrian.xpm | 44 + wx28X/samples/animate/Makefile.in | 214 + wx28X/samples/animate/anitest.bkl | 20 + wx28X/samples/animate/anitest.cpp | 324 + wx28X/samples/animate/anitest.dsp | 480 + wx28X/samples/animate/anitest.h | 53 + wx28X/samples/animate/anitest.vcp | 1826 + wx28X/samples/animate/anitest.vcw | 17 + wx28X/samples/animate/hourglass.ani | Bin 0 -> 45182 bytes wx28X/samples/animate/makefile.bcc | 261 + wx28X/samples/animate/makefile.dmc | 49 + wx28X/samples/animate/makefile.dms | 223 + wx28X/samples/animate/makefile.gcc | 261 + wx28X/samples/animate/makefile.unx | 71 + wx28X/samples/animate/makefile.vc | 367 + wx28X/samples/animate/makefile.wat | 291 + wx28X/samples/animate/throbber.gif | Bin 0 -> 2704 bytes wx28X/samples/artprov/Makefile.in | 201 + wx28X/samples/artprov/artbrows.cpp | 208 + wx28X/samples/artprov/artbrows.h | 43 + wx28X/samples/artprov/artprov.bkl | 13 + wx28X/samples/artprov/artprov.dsp | 484 + wx28X/samples/artprov/artprov.pro | 17 + wx28X/samples/artprov/artprov.vcp | 1830 + wx28X/samples/artprov/artprov.vcw | 17 + wx28X/samples/artprov/artprovM5.xml | 3739 + wx28X/samples/artprov/arttest.cpp | 222 + wx28X/samples/artprov/arttest.rc | 3 + wx28X/samples/artprov/error.xpm | 58 + wx28X/samples/artprov/info.xpm | 63 + wx28X/samples/artprov/makefile.bcc | 257 + wx28X/samples/artprov/makefile.dmc | 49 + wx28X/samples/artprov/makefile.dms | 216 + wx28X/samples/artprov/makefile.gcc | 257 + wx28X/samples/artprov/makefile.unx | 75 + wx28X/samples/artprov/makefile.vc | 363 + wx28X/samples/artprov/makefile.wat | 286 + wx28X/samples/artprov/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/artprov/mondrian.xpm | 44 + wx28X/samples/artprov/null.xpm | 30 + wx28X/samples/artprov/question.xpm | 75 + wx28X/samples/artprov/warning.xpm | 63 + wx28X/samples/aui/Makefile.in | 213 + wx28X/samples/aui/auidemo.bkl | 17 + wx28X/samples/aui/auidemo.cpp | 1687 + wx28X/samples/aui/auidemo.dsp | 480 + wx28X/samples/aui/auidemo.vcp | 1826 + wx28X/samples/aui/auidemo.vcw | 17 + wx28X/samples/aui/descrip.mms | 47 + wx28X/samples/aui/makefile.bcc | 269 + wx28X/samples/aui/makefile.dmc | 45 + wx28X/samples/aui/makefile.dms | 229 + wx28X/samples/aui/makefile.gcc | 269 + wx28X/samples/aui/makefile.unx | 71 + wx28X/samples/aui/makefile.vc | 375 + wx28X/samples/aui/makefile.wat | 302 + wx28X/samples/calendar/Makefile.in | 210 + wx28X/samples/calendar/calendar.bkl | 16 + wx28X/samples/calendar/calendar.cpp | 711 + wx28X/samples/calendar/calendar.dsp | 480 + wx28X/samples/calendar/calendar.pro | 17 + wx28X/samples/calendar/calendar.rc | 2 + wx28X/samples/calendar/calendar.vcp | 1826 + wx28X/samples/calendar/calendar.vcw | 17 + wx28X/samples/calendar/calendarM5.xml | 3685 + wx28X/samples/calendar/descrip.mms | 47 + wx28X/samples/calendar/makefile.bcc | 265 + wx28X/samples/calendar/makefile.dmc | 45 + wx28X/samples/calendar/makefile.dms | 225 + wx28X/samples/calendar/makefile.gcc | 265 + wx28X/samples/calendar/makefile.sl | 14 + wx28X/samples/calendar/makefile.unx | 71 + wx28X/samples/calendar/makefile.vc | 371 + wx28X/samples/calendar/makefile.wat | 297 + wx28X/samples/caret/Makefile.in | 197 + wx28X/samples/caret/caret.bkl | 13 + wx28X/samples/caret/caret.cpp | 487 + wx28X/samples/caret/caret.dsp | 480 + wx28X/samples/caret/caret.pro | 17 + wx28X/samples/caret/caret.rc | 2 + wx28X/samples/caret/caret.vcp | 1826 + wx28X/samples/caret/caret.vcw | 17 + wx28X/samples/caret/caretM5.xml | 3685 + wx28X/samples/caret/descrip.mms | 47 + wx28X/samples/caret/makefile.bcc | 253 + wx28X/samples/caret/makefile.dmc | 45 + wx28X/samples/caret/makefile.dms | 213 + wx28X/samples/caret/makefile.gcc | 253 + wx28X/samples/caret/makefile.unx | 71 + wx28X/samples/caret/makefile.vc | 359 + wx28X/samples/caret/makefile.wat | 282 + wx28X/samples/caret/mondrian.xpm | 44 + wx28X/samples/checklst/Makefile.in | 197 + wx28X/samples/checklst/checklst.bkl | 13 + wx28X/samples/checklst/checklst.cpp | 545 + wx28X/samples/checklst/checklst.dsp | 480 + wx28X/samples/checklst/checklst.pro | 17 + wx28X/samples/checklst/checklst.rc | 1 + wx28X/samples/checklst/checklst.rcO | 4 + wx28X/samples/checklst/checklst.vcp | 1826 + wx28X/samples/checklst/checklst.vcw | 17 + wx28X/samples/checklst/checklstM5.xml | 3685 + wx28X/samples/checklst/descrip.mms | 47 + wx28X/samples/checklst/makefile.bcc | 253 + wx28X/samples/checklst/makefile.dmc | 45 + wx28X/samples/checklst/makefile.dms | 213 + wx28X/samples/checklst/makefile.gcc | 253 + wx28X/samples/checklst/makefile.unx | 71 + wx28X/samples/checklst/makefile.va | 45 + wx28X/samples/checklst/makefile.vc | 359 + wx28X/samples/checklst/makefile.wat | 282 + wx28X/samples/checklst/mondrian.xpm | 44 + wx28X/samples/checklst/mondros2.ico | Bin 0 -> 996 bytes wx28X/samples/collpane/Makefile.in | 202 + wx28X/samples/collpane/collpane.bkl | 14 + wx28X/samples/collpane/collpane.cpp | 296 + wx28X/samples/collpane/collpane.dsp | 480 + wx28X/samples/collpane/collpane.vcp | 1826 + wx28X/samples/collpane/collpane.vcw | 17 + wx28X/samples/collpane/makefile.bcc | 257 + wx28X/samples/collpane/makefile.dmc | 45 + wx28X/samples/collpane/makefile.dms | 217 + wx28X/samples/collpane/makefile.gcc | 257 + wx28X/samples/collpane/makefile.unx | 71 + wx28X/samples/collpane/makefile.vc | 363 + wx28X/samples/collpane/makefile.wat | 287 + wx28X/samples/combo/Makefile.in | 214 + wx28X/samples/combo/combo.bkl | 23 + wx28X/samples/combo/combo.cpp | 1235 + wx28X/samples/combo/combo.dsp | 480 + wx28X/samples/combo/combo.vcp | 1826 + wx28X/samples/combo/combo.vcw | 17 + wx28X/samples/combo/dropbuth.png | Bin 0 -> 371 bytes wx28X/samples/combo/dropbutn.png | Bin 0 -> 237 bytes wx28X/samples/combo/dropbutp.png | Bin 0 -> 366 bytes wx28X/samples/combo/makefile.bcc | 261 + wx28X/samples/combo/makefile.dmc | 49 + wx28X/samples/combo/makefile.dms | 223 + wx28X/samples/combo/makefile.gcc | 261 + wx28X/samples/combo/makefile.unx | 71 + wx28X/samples/combo/makefile.vc | 367 + wx28X/samples/combo/makefile.wat | 291 + wx28X/samples/config/Makefile.in | 197 + wx28X/samples/config/config.bkl | 13 + wx28X/samples/config/config.dsp | 480 + wx28X/samples/config/config.pro | 17 + wx28X/samples/config/config.vcp | 1826 + wx28X/samples/config/config.vcw | 17 + wx28X/samples/config/configM5.xml | 3685 + wx28X/samples/config/conftest.cpp | 266 + wx28X/samples/config/conftest.rc | 2 + wx28X/samples/config/descrip.mms | 47 + wx28X/samples/config/makefile.bcc | 253 + wx28X/samples/config/makefile.dmc | 45 + wx28X/samples/config/makefile.dms | 213 + wx28X/samples/config/makefile.gcc | 253 + wx28X/samples/config/makefile.unx | 71 + wx28X/samples/config/makefile.vc | 359 + wx28X/samples/config/makefile.wat | 282 + wx28X/samples/console/Makefile.in | 133 + wx28X/samples/console/console.bkl | 18 + wx28X/samples/console/console.cpp | 4522 + wx28X/samples/console/console.dsp | 443 + wx28X/samples/console/console.pro | 14 + wx28X/samples/console/makefile.bcc | 213 + wx28X/samples/console/makefile.dmc | 46 + wx28X/samples/console/makefile.dms | 213 + wx28X/samples/console/makefile.gcc | 212 + wx28X/samples/console/makefile.unx | 71 + wx28X/samples/console/makefile.vc | 296 + wx28X/samples/console/makefile.wat | 278 + wx28X/samples/console/testdata.fc | 6 + wx28X/samples/controls/Makefile.in | 209 + wx28X/samples/controls/controls.bkl | 19 + wx28X/samples/controls/controls.cpp | 1978 + wx28X/samples/controls/controls.dsp | 480 + wx28X/samples/controls/controls.pro | 17 + wx28X/samples/controls/controls.rc | 10 + wx28X/samples/controls/controls.vcp | 1826 + wx28X/samples/controls/controls.vcw | 17 + wx28X/samples/controls/controlsM5.xml | 3685 + wx28X/samples/controls/controlsW7.xml | 1968 + wx28X/samples/controls/descrip.mms | 47 + wx28X/samples/controls/icons/choice.bmp | Bin 0 -> 1334 bytes wx28X/samples/controls/icons/choice.xpm | 27 + wx28X/samples/controls/icons/combo.bmp | Bin 0 -> 1334 bytes wx28X/samples/controls/icons/combo.xpm | 27 + wx28X/samples/controls/icons/gauge.bmp | Bin 0 -> 1334 bytes wx28X/samples/controls/icons/gauge.xpm | 27 + wx28X/samples/controls/icons/list.bmp | Bin 0 -> 1334 bytes wx28X/samples/controls/icons/list.xpm | 27 + wx28X/samples/controls/icons/radio.bmp | Bin 0 -> 1334 bytes wx28X/samples/controls/icons/radio.xpm | 27 + wx28X/samples/controls/icons/stattext.xpm | 24 + wx28X/samples/controls/icons/text.bmp | Bin 0 -> 1334 bytes wx28X/samples/controls/icons/text.xpm | 27 + wx28X/samples/controls/makefile.bcc | 257 + wx28X/samples/controls/makefile.dmc | 49 + wx28X/samples/controls/makefile.dms | 219 + wx28X/samples/controls/makefile.gcc | 257 + wx28X/samples/controls/makefile.unx | 71 + wx28X/samples/controls/makefile.vc | 363 + wx28X/samples/controls/makefile.wat | 286 + wx28X/samples/controls/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/controls/mondrian.xpm | 44 + wx28X/samples/controls/test2.bmp | Bin 0 -> 12342 bytes wx28X/samples/dataview/Makefile.in | 202 + wx28X/samples/dataview/dataview.bkl | 14 + wx28X/samples/dataview/dataview.cpp | 712 + wx28X/samples/dataview/dataview.dsp | 480 + wx28X/samples/dataview/dataview.vcp | 1826 + wx28X/samples/dataview/dataview.vcw | 17 + wx28X/samples/dataview/makefile.bcc | 257 + wx28X/samples/dataview/makefile.dmc | 45 + wx28X/samples/dataview/makefile.dms | 217 + wx28X/samples/dataview/makefile.gcc | 257 + wx28X/samples/dataview/makefile.unx | 71 + wx28X/samples/dataview/makefile.vc | 363 + wx28X/samples/dataview/makefile.wat | 287 + wx28X/samples/dataview/null.xpm | 30 + wx28X/samples/db/Makefile.in | 223 + wx28X/samples/db/db.bkl | 24 + wx28X/samples/db/db.dsp | 484 + wx28X/samples/db/db.pro | 17 + wx28X/samples/db/db.vcp | 1830 + wx28X/samples/db/db.vcw | 17 + wx28X/samples/db/db.xpm | 48 + wx28X/samples/db/dbM5.xml | 3727 + wx28X/samples/db/dbtest.cpp | 3433 + wx28X/samples/db/dbtest.h | 696 + wx28X/samples/db/dbtest.ico | Bin 0 -> 766 bytes wx28X/samples/db/dbtest.rc | 3 + wx28X/samples/db/descrip.mms | 48 + wx28X/samples/db/listdb.cpp | 518 + wx28X/samples/db/listdb.h | 131 + wx28X/samples/db/makefile.bcc | 282 + wx28X/samples/db/makefile.dmc | 49 + wx28X/samples/db/makefile.dms | 243 + wx28X/samples/db/makefile.gcc | 284 + wx28X/samples/db/makefile.unx | 75 + wx28X/samples/db/makefile.vc | 388 + wx28X/samples/db/makefile.wat | 319 + wx28X/samples/debugrpt/Makefile.in | 204 + wx28X/samples/debugrpt/debugrpt.bkl | 14 + wx28X/samples/debugrpt/debugrpt.cpp | 398 + wx28X/samples/debugrpt/debugrpt.dsp | 480 + wx28X/samples/debugrpt/debugrpt.vcp | 1826 + wx28X/samples/debugrpt/debugrpt.vcw | 17 + wx28X/samples/debugrpt/makefile.bcc | 261 + wx28X/samples/debugrpt/makefile.dmc | 45 + wx28X/samples/debugrpt/makefile.dms | 221 + wx28X/samples/debugrpt/makefile.gcc | 261 + wx28X/samples/debugrpt/makefile.unx | 71 + wx28X/samples/debugrpt/makefile.vc | 367 + wx28X/samples/debugrpt/makefile.wat | 292 + wx28X/samples/dialogs/Makefile.in | 258 + wx28X/samples/dialogs/descrip.mms | 47 + wx28X/samples/dialogs/dialogs.bkl | 44 + wx28X/samples/dialogs/dialogs.cpp | 1701 + wx28X/samples/dialogs/dialogs.dsp | 748 + wx28X/samples/dialogs/dialogs.h | 354 + wx28X/samples/dialogs/dialogs.ico | Bin 0 -> 1078 bytes wx28X/samples/dialogs/dialogs.pro | 17 + wx28X/samples/dialogs/dialogs.rc | 4 + wx28X/samples/dialogs/dialogs.rcO | 4 + wx28X/samples/dialogs/dialogs.vcp | 1826 + wx28X/samples/dialogs/dialogs.vcw | 17 + wx28X/samples/dialogs/dialogsM5.xml | 3685 + wx28X/samples/dialogs/dialogsW7.xml | 1969 + wx28X/samples/dialogs/makefile.bcc | 289 + wx28X/samples/dialogs/makefile.dmc | 65 + wx28X/samples/dialogs/makefile.dms | 252 + wx28X/samples/dialogs/makefile.gcc | 291 + wx28X/samples/dialogs/makefile.mgl | 15 + wx28X/samples/dialogs/makefile.unx | 71 + wx28X/samples/dialogs/makefile.va | 45 + wx28X/samples/dialogs/makefile.vc | 395 + wx28X/samples/dialogs/makefile.wat | 324 + wx28X/samples/dialogs/tips.txt | 18 + wx28X/samples/dialup/Makefile.in | 199 + wx28X/samples/dialup/descrip.mms | 47 + wx28X/samples/dialup/dialup.bkl | 15 + wx28X/samples/dialup/dialup.dsp | 480 + wx28X/samples/dialup/dialup.pro | 17 + wx28X/samples/dialup/dialup.vcp | 1826 + wx28X/samples/dialup/dialup.vcw | 17 + wx28X/samples/dialup/makefile.bcc | 253 + wx28X/samples/dialup/makefile.dmc | 45 + wx28X/samples/dialup/makefile.dms | 213 + wx28X/samples/dialup/makefile.gcc | 253 + wx28X/samples/dialup/makefile.unx | 71 + wx28X/samples/dialup/makefile.vc | 359 + wx28X/samples/dialup/makefile.wat | 282 + wx28X/samples/dialup/nettest.cpp | 343 + wx28X/samples/dialup/nettest.rc | 2 + wx28X/samples/display/Makefile.in | 197 + wx28X/samples/display/display.bkl | 12 + wx28X/samples/display/display.cpp | 432 + wx28X/samples/display/display.dsp | 480 + wx28X/samples/display/display.pro | 17 + wx28X/samples/display/display.vcp | 1826 + wx28X/samples/display/display.vcw | 17 + wx28X/samples/display/makefile.bcc | 253 + wx28X/samples/display/makefile.dmc | 45 + wx28X/samples/display/makefile.dms | 213 + wx28X/samples/display/makefile.gcc | 253 + wx28X/samples/display/makefile.unx | 71 + wx28X/samples/display/makefile.vc | 359 + wx28X/samples/display/makefile.wat | 282 + wx28X/samples/dnd/Makefile.in | 208 + wx28X/samples/dnd/d_and_d.txt | 167 + wx28X/samples/dnd/descrip.mms | 47 + wx28X/samples/dnd/dnd.bkl | 17 + wx28X/samples/dnd/dnd.cpp | 2007 + wx28X/samples/dnd/dnd.dsp | 480 + wx28X/samples/dnd/dnd.pro | 17 + wx28X/samples/dnd/dnd.rc | 5 + wx28X/samples/dnd/dnd.vcp | 1826 + wx28X/samples/dnd/dnd.vcw | 17 + wx28X/samples/dnd/dndM5.xml | 3685 + wx28X/samples/dnd/dndM7.mcp | Bin 0 -> 286241 bytes wx28X/samples/dnd/dndW7.xml | 1968 + wx28X/samples/dnd/dnd_copy.cur | Bin 0 -> 326 bytes wx28X/samples/dnd/dnd_copy.xpm | 45 + wx28X/samples/dnd/dnd_move.cur | Bin 0 -> 326 bytes wx28X/samples/dnd/dnd_move.xpm | 44 + wx28X/samples/dnd/dnd_none.cur | Bin 0 -> 326 bytes wx28X/samples/dnd/dnd_none.xpm | 45 + wx28X/samples/dnd/makefile.bcc | 257 + wx28X/samples/dnd/makefile.dmc | 49 + wx28X/samples/dnd/makefile.dms | 219 + wx28X/samples/dnd/makefile.gcc | 257 + wx28X/samples/dnd/makefile.unx | 71 + wx28X/samples/dnd/makefile.vc | 363 + wx28X/samples/dnd/makefile.wat | 286 + wx28X/samples/dnd/wxwin.png | Bin 0 -> 1119 bytes wx28X/samples/docview/Makefile.in | 204 + wx28X/samples/docview/chart.ico | Bin 0 -> 766 bytes wx28X/samples/docview/chart.r | 2611 + wx28X/samples/docview/descrip.mms | 49 + wx28X/samples/docview/doc.cpp | 371 + wx28X/samples/docview/doc.h | 106 + wx28X/samples/docview/doc.ico | Bin 0 -> 766 bytes wx28X/samples/docview/doc.r | 2588 + wx28X/samples/docview/docview.bkl | 14 + wx28X/samples/docview/docview.cpp | 277 + wx28X/samples/docview/docview.dsp | 488 + wx28X/samples/docview/docview.h | 62 + wx28X/samples/docview/docview.pro | 17 + wx28X/samples/docview/docview.r | 50 + wx28X/samples/docview/docview.rc | 5 + wx28X/samples/docview/docview.vcp | 1834 + wx28X/samples/docview/docview.vcw | 17 + wx28X/samples/docview/docviewM5.xml | 4009 + wx28X/samples/docview/docviewM7.mcp | Bin 0 -> 479015 bytes wx28X/samples/docview/docviewW7.xml | 2028 + wx28X/samples/docview/makefile.bcc | 261 + wx28X/samples/docview/makefile.dmc | 53 + wx28X/samples/docview/makefile.dms | 219 + wx28X/samples/docview/makefile.gcc | 261 + wx28X/samples/docview/makefile.unx | 79 + wx28X/samples/docview/makefile.vc | 367 + wx28X/samples/docview/makefile.vms | 44 + wx28X/samples/docview/makefile.wat | 290 + wx28X/samples/docview/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/docview/mondrian.r | 2667 + wx28X/samples/docview/mondrian.xpm | 44 + wx28X/samples/docview/notepad.ico | Bin 0 -> 766 bytes wx28X/samples/docview/view.cpp | 282 + wx28X/samples/docview/view.h | 75 + wx28X/samples/docvwmdi/Makefile.in | 205 + wx28X/samples/docvwmdi/chart.ico | Bin 0 -> 766 bytes wx28X/samples/docvwmdi/doc.cpp | 362 + wx28X/samples/docvwmdi/doc.h | 107 + wx28X/samples/docvwmdi/doc.ico | Bin 0 -> 766 bytes wx28X/samples/docvwmdi/docview.cpp | 231 + wx28X/samples/docvwmdi/docview.h | 61 + wx28X/samples/docvwmdi/docview.rc | 6 + wx28X/samples/docvwmdi/docvwmdi.bkl | 13 + wx28X/samples/docvwmdi/docvwmdi.dsp | 488 + wx28X/samples/docvwmdi/docvwmdi.pro | 17 + wx28X/samples/docvwmdi/docvwmdi.vcp | 1834 + wx28X/samples/docvwmdi/docvwmdi.vcw | 17 + wx28X/samples/docvwmdi/docvwmdiM5.xml | 3793 + wx28X/samples/docvwmdi/makefile.bcc | 261 + wx28X/samples/docvwmdi/makefile.dmc | 53 + wx28X/samples/docvwmdi/makefile.dms | 219 + wx28X/samples/docvwmdi/makefile.gcc | 261 + wx28X/samples/docvwmdi/makefile.unx | 79 + wx28X/samples/docvwmdi/makefile.vc | 367 + wx28X/samples/docvwmdi/makefile.wat | 290 + wx28X/samples/docvwmdi/notepad.ico | Bin 0 -> 766 bytes wx28X/samples/docvwmdi/view.cpp | 261 + wx28X/samples/docvwmdi/view.h | 77 + wx28X/samples/dragimag/Makefile.in | 209 + wx28X/samples/dragimag/backgrnd.png | Bin 0 -> 16672 bytes wx28X/samples/dragimag/dragicon.ico | Bin 0 -> 766 bytes wx28X/samples/dragimag/dragicon.xpm | 44 + wx28X/samples/dragimag/dragimag.bkl | 17 + wx28X/samples/dragimag/dragimag.cpp | 509 + wx28X/samples/dragimag/dragimag.dsp | 480 + wx28X/samples/dragimag/dragimag.h | 191 + wx28X/samples/dragimag/dragimag.pro | 17 + wx28X/samples/dragimag/dragimag.rc | 5 + wx28X/samples/dragimag/dragimag.vcp | 1826 + wx28X/samples/dragimag/dragimag.vcw | 17 + wx28X/samples/dragimag/dragimagM5.xml | 3685 + wx28X/samples/dragimag/makefile.bcc | 257 + wx28X/samples/dragimag/makefile.dmc | 49 + wx28X/samples/dragimag/makefile.dms | 219 + wx28X/samples/dragimag/makefile.gcc | 257 + wx28X/samples/dragimag/makefile.sl | 14 + wx28X/samples/dragimag/makefile.unx | 71 + wx28X/samples/dragimag/makefile.va | 25 + wx28X/samples/dragimag/makefile.vc | 363 + wx28X/samples/dragimag/makefile.wat | 286 + wx28X/samples/dragimag/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/dragimag/mondrian.xpm | 44 + wx28X/samples/dragimag/shape01.png | Bin 0 -> 2784 bytes wx28X/samples/dragimag/shape02.png | Bin 0 -> 2333 bytes wx28X/samples/dragimag/shape03.png | Bin 0 -> 2501 bytes wx28X/samples/drawing/Makefile.in | 209 + wx28X/samples/drawing/descrip.mms | 47 + wx28X/samples/drawing/drawing.bkl | 17 + wx28X/samples/drawing/drawing.cpp | 1602 + wx28X/samples/drawing/drawing.dsp | 480 + wx28X/samples/drawing/drawing.pro | 17 + wx28X/samples/drawing/drawing.rc | 3 + wx28X/samples/drawing/drawing.vcp | 1826 + wx28X/samples/drawing/drawing.vcw | 17 + wx28X/samples/drawing/drawingM5.xml | 3685 + wx28X/samples/drawing/image.bmp | Bin 0 -> 19254 bytes wx28X/samples/drawing/makefile.bcc | 257 + wx28X/samples/drawing/makefile.dmc | 49 + wx28X/samples/drawing/makefile.dms | 219 + wx28X/samples/drawing/makefile.gcc | 257 + wx28X/samples/drawing/makefile.unx | 71 + wx28X/samples/drawing/makefile.vc | 363 + wx28X/samples/drawing/makefile.wat | 286 + wx28X/samples/drawing/mask.bmp | Bin 0 -> 1024 bytes wx28X/samples/drawing/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/drawing/mondrian.xpm | 44 + wx28X/samples/drawing/pat35.bmp | Bin 0 -> 190 bytes wx28X/samples/drawing/pat36.bmp | Bin 0 -> 190 bytes wx28X/samples/drawing/pat4.bmp | Bin 0 -> 630 bytes wx28X/samples/drawing/smile.xpm | 42 + wx28X/samples/dynamic/Makefile.in | 197 + wx28X/samples/dynamic/dynamic.bkl | 13 + wx28X/samples/dynamic/dynamic.cpp | 174 + wx28X/samples/dynamic/dynamic.dsp | 480 + wx28X/samples/dynamic/dynamic.pro | 17 + wx28X/samples/dynamic/dynamic.rc | 3 + wx28X/samples/dynamic/dynamic.vcp | 1826 + wx28X/samples/dynamic/dynamic.vcw | 17 + wx28X/samples/dynamic/dynamicM5.xml | 3685 + wx28X/samples/dynamic/makefile.bcc | 253 + wx28X/samples/dynamic/makefile.dmc | 45 + wx28X/samples/dynamic/makefile.dms | 213 + wx28X/samples/dynamic/makefile.gcc | 253 + wx28X/samples/dynamic/makefile.unx | 71 + wx28X/samples/dynamic/makefile.vc | 359 + wx28X/samples/dynamic/makefile.wat | 282 + wx28X/samples/dynamic/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/dynamic/mondrian.xpm | 44 + wx28X/samples/erase/Erase.icc | 17 + wx28X/samples/erase/Makefile.in | 197 + wx28X/samples/erase/descrip.mms | 47 + wx28X/samples/erase/erase.bkl | 13 + wx28X/samples/erase/erase.cpp | 357 + wx28X/samples/erase/erase.dsp | 480 + wx28X/samples/erase/erase.pro | 17 + wx28X/samples/erase/erase.rc | 6 + wx28X/samples/erase/erase.rc0 | 6 + wx28X/samples/erase/erase.rc4 | 6 + wx28X/samples/erase/erase.vcp | 1826 + wx28X/samples/erase/erase.vcw | 17 + wx28X/samples/erase/eraseM5.xml | 3677 + wx28X/samples/erase/makefile.bcc | 253 + wx28X/samples/erase/makefile.dmc | 45 + wx28X/samples/erase/makefile.dms | 213 + wx28X/samples/erase/makefile.gcc | 253 + wx28X/samples/erase/makefile.sl | 18 + wx28X/samples/erase/makefile.unx | 71 + wx28X/samples/erase/makefile.va | 45 + wx28X/samples/erase/makefile.vc | 359 + wx28X/samples/erase/makefile.wat | 282 + wx28X/samples/erase/makemac6.mcp | Bin 0 -> 845 bytes wx28X/samples/erase/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/erase/mondrian.xpm | 45 + wx28X/samples/erase/mondros2.ico | Bin 0 -> 996 bytes wx28X/samples/event/Makefile.in | 197 + wx28X/samples/event/event.bkl | 13 + wx28X/samples/event/event.cpp | 385 + wx28X/samples/event/event.dsp | 480 + wx28X/samples/event/event.pro | 17 + wx28X/samples/event/event.rc | 2 + wx28X/samples/event/event.vcp | 1826 + wx28X/samples/event/event.vcw | 17 + wx28X/samples/event/eventM5.xml | 3685 + wx28X/samples/event/makefile.bcc | 253 + wx28X/samples/event/makefile.dmc | 45 + wx28X/samples/event/makefile.dms | 213 + wx28X/samples/event/makefile.gcc | 253 + wx28X/samples/event/makefile.sl | 14 + wx28X/samples/event/makefile.unx | 71 + wx28X/samples/event/makefile.vc | 359 + wx28X/samples/event/makefile.wat | 282 + wx28X/samples/except/Makefile.in | 197 + wx28X/samples/except/except.bkl | 14 + wx28X/samples/except/except.cpp | 493 + wx28X/samples/except/except.dsp | 480 + wx28X/samples/except/except.vcp | 1826 + wx28X/samples/except/except.vcw | 17 + wx28X/samples/except/makefile.bcc | 253 + wx28X/samples/except/makefile.dmc | 45 + wx28X/samples/except/makefile.dms | 213 + wx28X/samples/except/makefile.gcc | 253 + wx28X/samples/except/makefile.unx | 71 + wx28X/samples/except/makefile.vc | 359 + wx28X/samples/except/makefile.wat | 282 + wx28X/samples/exec/Makefile.in | 197 + wx28X/samples/exec/exec.bkl | 13 + wx28X/samples/exec/exec.cpp | 1230 + wx28X/samples/exec/exec.dsp | 480 + wx28X/samples/exec/exec.pro | 17 + wx28X/samples/exec/exec.rc | 5 + wx28X/samples/exec/exec.vcp | 1826 + wx28X/samples/exec/exec.vcw | 17 + wx28X/samples/exec/execM5.xml | 3685 + wx28X/samples/exec/makefile.bcc | 253 + wx28X/samples/exec/makefile.dmc | 45 + wx28X/samples/exec/makefile.dms | 213 + wx28X/samples/exec/makefile.gcc | 253 + wx28X/samples/exec/makefile.sl | 14 + wx28X/samples/exec/makefile.unx | 71 + wx28X/samples/exec/makefile.vc | 359 + wx28X/samples/exec/makefile.wat | 282 + wx28X/samples/font/Makefile.in | 197 + wx28X/samples/font/descrip.mms | 47 + wx28X/samples/font/font.bkl | 13 + wx28X/samples/font/font.cpp | 935 + wx28X/samples/font/font.dsp | 480 + wx28X/samples/font/font.pro | 17 + wx28X/samples/font/font.rc | 4 + wx28X/samples/font/font.vcp | 1826 + wx28X/samples/font/font.vcw | 17 + wx28X/samples/font/fontM5.xml | 3685 + wx28X/samples/font/makefile.bcc | 253 + wx28X/samples/font/makefile.dmc | 45 + wx28X/samples/font/makefile.dms | 213 + wx28X/samples/font/makefile.gcc | 253 + wx28X/samples/font/makefile.unx | 71 + wx28X/samples/font/makefile.vc | 359 + wx28X/samples/font/makefile.wat | 282 + wx28X/samples/font/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/grid/Makefile.in | 210 + wx28X/samples/grid/bitmap1.bmp | Bin 0 -> 406 bytes wx28X/samples/grid/bitmap2.bmp | Bin 0 -> 238 bytes wx28X/samples/grid/grid.bkl | 16 + wx28X/samples/grid/grid.dsp | 480 + wx28X/samples/grid/grid.vcp | 1826 + wx28X/samples/grid/grid.vcw | 17 + wx28X/samples/grid/griddemo.cpp | 1471 + wx28X/samples/grid/griddemo.h | 266 + wx28X/samples/grid/griddemo.pro | 17 + wx28X/samples/grid/griddemo.rc | 2 + wx28X/samples/grid/griddemoM5.xml | 3685 + wx28X/samples/grid/griddemoM7.mcp | Bin 0 -> 478591 bytes wx28X/samples/grid/makefile.bcc | 265 + wx28X/samples/grid/makefile.dmc | 45 + wx28X/samples/grid/makefile.dms | 225 + wx28X/samples/grid/makefile.gcc | 265 + wx28X/samples/grid/makefile.sl | 14 + wx28X/samples/grid/makefile.unx | 71 + wx28X/samples/grid/makefile.vc | 371 + wx28X/samples/grid/makefile.wat | 297 + wx28X/samples/help/Makefile.in | 230 + wx28X/samples/help/back.gif | Bin 0 -> 978 bytes wx28X/samples/help/bullet.bmp | Bin 0 -> 138 bytes wx28X/samples/help/contents.gif | Bin 0 -> 996 bytes wx28X/samples/help/cshelp.txt | 9 + wx28X/samples/help/demo.cpp | 719 + wx28X/samples/help/demo.rc | 2 + wx28X/samples/help/doc.chm | Bin 0 -> 13506 bytes wx28X/samples/help/doc.cnt | 8 + wx28X/samples/help/doc.h | 7 + wx28X/samples/help/doc.hhc | 35 + wx28X/samples/help/doc.hhk | 31 + wx28X/samples/help/doc.hhp | 33 + wx28X/samples/help/doc.hlp | Bin 0 -> 10603 bytes wx28X/samples/help/doc.hpj | 21 + wx28X/samples/help/doc.tex | 59 + wx28X/samples/help/doc.zip | Bin 0 -> 5468 bytes wx28X/samples/help/doc/ClassGraph.class | Bin 0 -> 87 bytes wx28X/samples/help/doc/ClassGraphPanel.class | Bin 0 -> 148 bytes wx28X/samples/help/doc/ClassLayout.class | Bin 0 -> 1690 bytes wx28X/samples/help/doc/HIER.html | 9 + wx28X/samples/help/doc/HIERjava.html | 15 + wx28X/samples/help/doc/NavigatorButton.class | Bin 0 -> 1576 bytes wx28X/samples/help/doc/USE_HELP.html | 38 + wx28X/samples/help/doc/aindex.html | 21 + wx28X/samples/help/doc/down.gif | Bin 0 -> 994 bytes wx28X/samples/help/doc/dxxgifs.tex | 4 + wx28X/samples/help/doc/icon1.gif | Bin 0 -> 114 bytes wx28X/samples/help/doc/icon2.gif | Bin 0 -> 114 bytes wx28X/samples/help/doc/index.html | 21 + wx28X/samples/help/doc/logo.gif | Bin 0 -> 994 bytes wx28X/samples/help/doc/wx.htm | 64 + wx28X/samples/help/doc/wx204.htm | 33 + wx28X/samples/help/doc/wx34.htm | 647 + .../samples/help/doc/wxExtHelpController.html | 180 + wx28X/samples/help/doc/wxhelp.map | 10 + wx28X/samples/help/forward.gif | Bin 0 -> 959 bytes wx28X/samples/help/help.bkl | 60 + wx28X/samples/help/help.dsp | 480 + wx28X/samples/help/help.pro | 17 + wx28X/samples/help/help.vcp | 1826 + wx28X/samples/help/help.vcw | 17 + wx28X/samples/help/helpM5.xml | 3685 + wx28X/samples/help/makefile.bcc | 269 + wx28X/samples/help/makefile.dmc | 53 + wx28X/samples/help/makefile.dms | 233 + wx28X/samples/help/makefile.gcc | 269 + wx28X/samples/help/makefile.unx | 71 + wx28X/samples/help/makefile.vc | 375 + wx28X/samples/help/makefile.wat | 300 + wx28X/samples/help/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/help/mondrian.xpm | 44 + wx28X/samples/help/tex2rtf.ini | 22 + wx28X/samples/help/up.gif | Bin 0 -> 998 bytes wx28X/samples/htlbox/Makefile.in | 201 + wx28X/samples/htlbox/htlbox.bkl | 14 + wx28X/samples/htlbox/htlbox.cpp | 635 + wx28X/samples/htlbox/htlbox.dsp | 480 + wx28X/samples/htlbox/htlbox.rc | 2 + wx28X/samples/htlbox/htlbox.vcp | 1826 + wx28X/samples/htlbox/htlbox.vcw | 17 + wx28X/samples/htlbox/makefile.bcc | 257 + wx28X/samples/htlbox/makefile.dmc | 45 + wx28X/samples/htlbox/makefile.dms | 217 + wx28X/samples/htlbox/makefile.gcc | 257 + wx28X/samples/htlbox/makefile.unx | 71 + wx28X/samples/htlbox/makefile.vc | 363 + wx28X/samples/htlbox/makefile.wat | 287 + wx28X/samples/htlbox/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/htlbox/mondrian.xpm | 44 + wx28X/samples/htlbox/results | 7 + wx28X/samples/html/Makefile.in | 84 + wx28X/samples/html/about/Makefile.in | 214 + wx28X/samples/html/about/about.bkl | 24 + wx28X/samples/html/about/about.cpp | 162 + wx28X/samples/html/about/about.dsp | 480 + wx28X/samples/html/about/about.pro | 21 + wx28X/samples/html/about/about.rc | 2 + wx28X/samples/html/about/about.vcp | 1826 + wx28X/samples/html/about/about.vcw | 17 + wx28X/samples/html/about/aboutM5.xml | 3685 + wx28X/samples/html/about/aboutmac6.mcp | Bin 0 -> 204585 bytes wx28X/samples/html/about/data/about.htm | 34 + wx28X/samples/html/about/data/logo.png | Bin 0 -> 7637 bytes wx28X/samples/html/about/makefile.bcc | 261 + wx28X/samples/html/about/makefile.dmc | 49 + wx28X/samples/html/about/makefile.dms | 223 + wx28X/samples/html/about/makefile.gcc | 261 + wx28X/samples/html/about/makefile.unx | 71 + wx28X/samples/html/about/makefile.vc | 367 + wx28X/samples/html/about/makefile.wat | 291 + wx28X/samples/html/help/Makefile.in | 214 + wx28X/samples/html/help/help.bkl | 33 + wx28X/samples/html/help/help.cpp | 192 + wx28X/samples/html/help/help.dsp | 480 + wx28X/samples/html/help/help.pro | 21 + wx28X/samples/html/help/help.rc | 1 + wx28X/samples/html/help/help.vcp | 1826 + wx28X/samples/html/help/help.vcw | 17 + wx28X/samples/html/help/helpM5.xml | 3685 + wx28X/samples/html/help/helpfiles/Index.hhk | 71 + wx28X/samples/html/help/helpfiles/another.hhc | 18 + wx28X/samples/html/help/helpfiles/another.hhp | 6 + wx28X/samples/html/help/helpfiles/another.htm | 24 + wx28X/samples/html/help/helpfiles/book1.htm | 4 + wx28X/samples/html/help/helpfiles/book2.htm | 5 + .../samples/html/help/helpfiles/contents.hhc | 27 + wx28X/samples/html/help/helpfiles/main.htm | 5 + wx28X/samples/html/help/helpfiles/page2-b.htm | 5 + wx28X/samples/html/help/helpfiles/testing.hhp | 15 + wx28X/samples/html/help/makefile.bcc | 261 + wx28X/samples/html/help/makefile.dmc | 49 + wx28X/samples/html/help/makefile.dms | 223 + wx28X/samples/html/help/makefile.gcc | 261 + wx28X/samples/html/help/makefile.unx | 71 + wx28X/samples/html/help/makefile.vc | 367 + wx28X/samples/html/help/makefile.wat | 291 + wx28X/samples/html/help/makemac6.mcp | Bin 0 -> 204073 bytes wx28X/samples/html/helpview/Makefile.in | 214 + wx28X/samples/html/helpview/helpview.bkl | 20 + wx28X/samples/html/helpview/helpview.cpp | 119 + wx28X/samples/html/helpview/helpview.dsp | 480 + wx28X/samples/html/helpview/helpview.ico | Bin 0 -> 1078 bytes wx28X/samples/html/helpview/helpview.pro | 21 + wx28X/samples/html/helpview/helpview.rc | 5 + wx28X/samples/html/helpview/helpview.vcp | 1826 + wx28X/samples/html/helpview/helpview.vcw | 17 + wx28X/samples/html/helpview/helpviewM5.xml | 3685 + wx28X/samples/html/helpview/makefile.bcc | 261 + wx28X/samples/html/helpview/makefile.dmc | 49 + wx28X/samples/html/helpview/makefile.dms | 223 + wx28X/samples/html/helpview/makefile.gcc | 261 + wx28X/samples/html/helpview/makefile.unx | 71 + wx28X/samples/html/helpview/makefile.vc | 367 + wx28X/samples/html/helpview/makefile.wat | 291 + wx28X/samples/html/helpview/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/html/helpview/test.zip | Bin 0 -> 3292 bytes wx28X/samples/html/html_samples.bkl | 22 + wx28X/samples/html/htmlctrl/Makefile.in | 198 + wx28X/samples/html/htmlctrl/htmlctrl.bkl | 14 + wx28X/samples/html/htmlctrl/htmlctrl.cpp | 258 + wx28X/samples/html/htmlctrl/makefile.unx | 71 + wx28X/samples/html/makefile.bcc | 133 + wx28X/samples/html/makefile.dmc | 108 + wx28X/samples/html/makefile.dms | 95 + wx28X/samples/html/makefile.gcc | 83 + wx28X/samples/html/makefile.unx | 75 + wx28X/samples/html/makefile.vc | 108 + wx28X/samples/html/makefile.wat | 128 + wx28X/samples/html/printing/Makefile.in | 218 + wx28X/samples/html/printing/logo6.gif | Bin 0 -> 3818 bytes wx28X/samples/html/printing/makefile.bcc | 261 + wx28X/samples/html/printing/makefile.dmc | 49 + wx28X/samples/html/printing/makefile.dms | 223 + wx28X/samples/html/printing/makefile.gcc | 261 + wx28X/samples/html/printing/makefile.unx | 71 + wx28X/samples/html/printing/makefile.vc | 367 + wx28X/samples/html/printing/makefile.wat | 292 + wx28X/samples/html/printing/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/html/printing/printing.bkl | 20 + wx28X/samples/html/printing/printing.cpp | 277 + wx28X/samples/html/printing/printing.dsp | 480 + wx28X/samples/html/printing/printing.pro | 21 + wx28X/samples/html/printing/printing.rc | 3 + wx28X/samples/html/printing/printing.vcp | 1826 + wx28X/samples/html/printing/printing.vcw | 17 + wx28X/samples/html/printing/printingM5.xml | 3685 + wx28X/samples/html/printing/test.htm | 189 + wx28X/samples/html/test/8859_2.htm | 14 + wx28X/samples/html/test/Makefile.in | 217 + wx28X/samples/html/test/cp1250.htm | 19 + wx28X/samples/html/test/f.html | 2445 + wx28X/samples/html/test/fft.html | 119 + wx28X/samples/html/test/foo.png | Bin 0 -> 410 bytes wx28X/samples/html/test/i18n.gif | Bin 0 -> 2292 bytes wx28X/samples/html/test/imagemap.htm | 20 + wx28X/samples/html/test/imagemap.png | Bin 0 -> 1186 bytes wx28X/samples/html/test/listtest.htm | 28 + wx28X/samples/html/test/makefile.bcc | 265 + wx28X/samples/html/test/makefile.dmc | 49 + wx28X/samples/html/test/makefile.dms | 227 + wx28X/samples/html/test/makefile.gcc | 265 + wx28X/samples/html/test/makefile.unx | 71 + wx28X/samples/html/test/makefile.vc | 371 + wx28X/samples/html/test/makefile.wat | 296 + wx28X/samples/html/test/makemac6.mcp | Bin 0 -> 204121 bytes wx28X/samples/html/test/pic.png | Bin 0 -> 21461 bytes wx28X/samples/html/test/pic2.bmp | Bin 0 -> 20902 bytes wx28X/samples/html/test/regres.htm | 20 + wx28X/samples/html/test/subsup.html | 42 + wx28X/samples/html/test/tables.htm | 192 + wx28X/samples/html/test/test.bkl | 25 + wx28X/samples/html/test/test.cpp | 376 + wx28X/samples/html/test/test.dsp | 480 + wx28X/samples/html/test/test.htm | 354 + wx28X/samples/html/test/test.pro | 21 + wx28X/samples/html/test/test.rc | 2 + wx28X/samples/html/test/test.vcp | 1826 + wx28X/samples/html/test/test.vcw | 17 + wx28X/samples/html/test/testM5.xml | 3685 + wx28X/samples/html/virtual/Makefile.in | 214 + wx28X/samples/html/virtual/makefile.bcc | 261 + wx28X/samples/html/virtual/makefile.dmc | 49 + wx28X/samples/html/virtual/makefile.dms | 223 + wx28X/samples/html/virtual/makefile.gcc | 261 + wx28X/samples/html/virtual/makefile.unx | 71 + wx28X/samples/html/virtual/makefile.vc | 367 + wx28X/samples/html/virtual/makefile.wat | 291 + wx28X/samples/html/virtual/start.htm | 12 + wx28X/samples/html/virtual/virtual.bkl | 20 + wx28X/samples/html/virtual/virtual.cpp | 230 + wx28X/samples/html/virtual/virtual.dsp | 480 + wx28X/samples/html/virtual/virtual.pro | 21 + wx28X/samples/html/virtual/virtual.rc | 2 + wx28X/samples/html/virtual/virtual.vcp | 1826 + wx28X/samples/html/virtual/virtual.vcw | 17 + wx28X/samples/html/virtual/virtualM5.xml | 3685 + wx28X/samples/html/virtual/virtualmac6.mcp | Bin 0 -> 309797 bytes wx28X/samples/html/widget/Makefile.in | 214 + wx28X/samples/html/widget/makefile.bcc | 261 + wx28X/samples/html/widget/makefile.dmc | 49 + wx28X/samples/html/widget/makefile.dms | 223 + wx28X/samples/html/widget/makefile.gcc | 261 + wx28X/samples/html/widget/makefile.unx | 71 + wx28X/samples/html/widget/makefile.vc | 367 + wx28X/samples/html/widget/makefile.wat | 291 + wx28X/samples/html/widget/start.htm | 28 + wx28X/samples/html/widget/widget.bkl | 20 + wx28X/samples/html/widget/widget.cpp | 233 + wx28X/samples/html/widget/widget.dsp | 480 + wx28X/samples/html/widget/widget.pro | 21 + wx28X/samples/html/widget/widget.rc | 2 + wx28X/samples/html/widget/widget.vcp | 1826 + wx28X/samples/html/widget/widget.vcw | 17 + wx28X/samples/html/widget/widgetM5.xml | 3685 + wx28X/samples/html/zip/Makefile.in | 213 + wx28X/samples/html/zip/makefile.bcc | 261 + wx28X/samples/html/zip/makefile.dmc | 49 + wx28X/samples/html/zip/makefile.dms | 223 + wx28X/samples/html/zip/makefile.gcc | 261 + wx28X/samples/html/zip/makefile.unx | 71 + wx28X/samples/html/zip/makefile.vc | 367 + wx28X/samples/html/zip/makefile.wat | 291 + wx28X/samples/html/zip/pages.zip | Bin 0 -> 62123 bytes wx28X/samples/html/zip/start.htm | 9 + wx28X/samples/html/zip/zip.bkl | 20 + wx28X/samples/html/zip/zip.cpp | 180 + wx28X/samples/html/zip/zip.dsp | 480 + wx28X/samples/html/zip/zip.pro | 21 + wx28X/samples/html/zip/zip.rc | 2 + wx28X/samples/html/zip/zip.vcp | 1826 + wx28X/samples/html/zip/zip.vcw | 17 + wx28X/samples/html/zip/zipM5.xml | 3685 + wx28X/samples/image/Makefile.in | 209 + wx28X/samples/image/cmyk.jpg | Bin 0 -> 22701 bytes wx28X/samples/image/descrip.mms | 47 + wx28X/samples/image/horse.bmp | Bin 0 -> 60722 bytes wx28X/samples/image/horse.cur | Bin 0 -> 326 bytes wx28X/samples/image/horse.gif | Bin 0 -> 46200 bytes wx28X/samples/image/horse.ico | Bin 0 -> 1078 bytes wx28X/samples/image/horse.jpg | Bin 0 -> 6213 bytes wx28X/samples/image/horse.pcx | Bin 0 -> 48942 bytes wx28X/samples/image/horse.png | Bin 0 -> 68852 bytes wx28X/samples/image/horse.pnm | 13 + wx28X/samples/image/horse.tga | Bin 0 -> 40786 bytes wx28X/samples/image/horse.tif | Bin 0 -> 41902 bytes wx28X/samples/image/horse.xpm | 460 + wx28X/samples/image/horse3.ani | Bin 0 -> 17268 bytes wx28X/samples/image/horse_ag.pnm | 40003 ++++ wx28X/samples/image/horse_rg.pnm | 17 + wx28X/samples/image/image.bkl | 23 + wx28X/samples/image/image.cpp | 1177 + wx28X/samples/image/image.dsp | 480 + wx28X/samples/image/image.pro | 17 + wx28X/samples/image/image.rc | 3 + wx28X/samples/image/image.rco | 2 + wx28X/samples/image/image.vcp | 1826 + wx28X/samples/image/image.vcw | 17 + wx28X/samples/image/imageM5.xml | 3685 + wx28X/samples/image/makefile.bcc | 257 + wx28X/samples/image/makefile.dmc | 49 + wx28X/samples/image/makefile.dms | 219 + wx28X/samples/image/makefile.gcc | 257 + wx28X/samples/image/makefile.unx | 71 + wx28X/samples/image/makefile.va | 45 + wx28X/samples/image/makefile.vc | 363 + wx28X/samples/image/makefile.wat | 286 + wx28X/samples/image/makemac6.mcp | Bin 0 -> 204247 bytes wx28X/samples/image/smile.xbm | 15 + wx28X/samples/image/smile.xpm | 42 + wx28X/samples/image/toucan.png | Bin 0 -> 12901 bytes wx28X/samples/internat/Makefile.in | 330 + wx28X/samples/internat/ar/internat.mo | Bin 0 -> 2902 bytes wx28X/samples/internat/ar/internat.po | 160 + wx28X/samples/internat/bg/internat.mo | Bin 0 -> 1410 bytes wx28X/samples/internat/bg/internat.po | 79 + wx28X/samples/internat/cs/internat.mo | Bin 0 -> 1861 bytes wx28X/samples/internat/cs/internat.po | 144 + wx28X/samples/internat/de/internat.mo | Bin 0 -> 1417 bytes wx28X/samples/internat/de/internat.po | 79 + wx28X/samples/internat/fr/internat.mo | Bin 0 -> 1370 bytes wx28X/samples/internat/fr/internat.po | 77 + wx28X/samples/internat/internat.bkl | 31 + wx28X/samples/internat/internat.cpp | 436 + wx28X/samples/internat/internat.dsp | 480 + wx28X/samples/internat/internat.pro | 17 + wx28X/samples/internat/internat.rc | 3 + wx28X/samples/internat/internat.vcp | 1826 + wx28X/samples/internat/internat.vcw | 17 + wx28X/samples/internat/internatM5.xml | 3685 + wx28X/samples/internat/ja/internat.mo | Bin 0 -> 2988 bytes wx28X/samples/internat/ja/internat.po | 146 + .../samples/internat/ja_JP.EUC-JP/internat.mo | Bin 0 -> 1496 bytes .../samples/internat/ja_JP.EUC-JP/internat.po | 85 + wx28X/samples/internat/ka/internat.mo | Bin 0 -> 1942 bytes wx28X/samples/internat/ka/internat.po | 78 + wx28X/samples/internat/makefile.bcc | 297 + wx28X/samples/internat/makefile.dmc | 89 + wx28X/samples/internat/makefile.dms | 279 + wx28X/samples/internat/makefile.gcc | 297 + wx28X/samples/internat/makefile.unx | 71 + wx28X/samples/internat/makefile.vc | 403 + wx28X/samples/internat/makefile.vms | 38 + wx28X/samples/internat/makefile.wat | 326 + wx28X/samples/internat/makemac6.mcp | Bin 0 -> 213507 bytes wx28X/samples/internat/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/internat/mondrian.xpm | 44 + wx28X/samples/internat/pl/internat.mo | Bin 0 -> 2602 bytes wx28X/samples/internat/pl/internat.po | 152 + wx28X/samples/internat/readme.txt | 86 + wx28X/samples/internat/ru/internat.mo | Bin 0 -> 2305 bytes wx28X/samples/internat/ru/internat.po | 138 + wx28X/samples/internat/sv/internat.mo | Bin 0 -> 2624 bytes wx28X/samples/internat/sv/internat.po | 153 + wx28X/samples/ipc/Makefile.in | 264 + wx28X/samples/ipc/client.b32 | 16 + wx28X/samples/ipc/client.cpp | 479 + wx28X/samples/ipc/client.g95 | 16 + wx28X/samples/ipc/client.h | 107 + wx28X/samples/ipc/client.pro | 13 + wx28X/samples/ipc/client.rc | 2 + wx28X/samples/ipc/client.vc | 20 + wx28X/samples/ipc/client.wat | 15 + wx28X/samples/ipc/ipc.bkl | 20 + wx28X/samples/ipc/ipc.vcw | 29 + wx28X/samples/ipc/ipc_ipcclient.dsp | 480 + wx28X/samples/ipc/ipc_ipcclient.vcp | 1826 + wx28X/samples/ipc/ipc_ipcserver.dsp | 480 + wx28X/samples/ipc/ipc_ipcserver.vcp | 1826 + wx28X/samples/ipc/ipcsetup.h | 28 + wx28X/samples/ipc/makefile.bcc | 283 + wx28X/samples/ipc/makefile.dmc | 61 + wx28X/samples/ipc/makefile.dms | 230 + wx28X/samples/ipc/makefile.gcc | 278 + wx28X/samples/ipc/makefile.unx | 81 + wx28X/samples/ipc/makefile.vc | 408 + wx28X/samples/ipc/makefile.wat | 315 + wx28X/samples/ipc/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/ipc/mondrian.xpm | 44 + wx28X/samples/ipc/server.b32 | 16 + wx28X/samples/ipc/server.cpp | 418 + wx28X/samples/ipc/server.g95 | 16 + wx28X/samples/ipc/server.h | 103 + wx28X/samples/ipc/server.pro | 13 + wx28X/samples/ipc/server.rc | 3 + wx28X/samples/ipc/server.vc | 20 + wx28X/samples/ipc/server.wat | 15 + wx28X/samples/joytest/Makefile.in | 210 + wx28X/samples/joytest/buttonpress.wav | Bin 0 -> 8024 bytes wx28X/samples/joytest/chart.ico | Bin 0 -> 766 bytes wx28X/samples/joytest/joytest.bkl | 16 + wx28X/samples/joytest/joytest.cpp | 201 + wx28X/samples/joytest/joytest.dsp | 480 + wx28X/samples/joytest/joytest.h | 55 + wx28X/samples/joytest/joytest.ico | Bin 0 -> 766 bytes wx28X/samples/joytest/joytest.pro | 20 + wx28X/samples/joytest/joytest.rc | 5 + wx28X/samples/joytest/joytest.vcp | 1826 + wx28X/samples/joytest/joytest.vcw | 17 + wx28X/samples/joytest/joytestM5.xml | 3685 + wx28X/samples/joytest/makefile.bcc | 265 + wx28X/samples/joytest/makefile.dmc | 45 + wx28X/samples/joytest/makefile.dms | 225 + wx28X/samples/joytest/makefile.gcc | 265 + wx28X/samples/joytest/makefile.sl | 14 + wx28X/samples/joytest/makefile.unx | 71 + wx28X/samples/joytest/makefile.vc | 371 + wx28X/samples/joytest/makefile.wat | 297 + wx28X/samples/joytest/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/keyboard/Makefile.in | 197 + wx28X/samples/keyboard/keyboard.bkl | 13 + wx28X/samples/keyboard/keyboard.cpp | 515 + wx28X/samples/keyboard/keyboard.dsp | 480 + wx28X/samples/keyboard/keyboard.pro | 16 + wx28X/samples/keyboard/keyboard.rc | 1 + wx28X/samples/keyboard/keyboard.vcp | 1826 + wx28X/samples/keyboard/keyboard.vcw | 17 + wx28X/samples/keyboard/keyboardM5.xml | 3685 + wx28X/samples/keyboard/makefile.bcc | 253 + wx28X/samples/keyboard/makefile.dmc | 45 + wx28X/samples/keyboard/makefile.dms | 213 + wx28X/samples/keyboard/makefile.gcc | 253 + wx28X/samples/keyboard/makefile.unx | 71 + wx28X/samples/keyboard/makefile.vc | 359 + wx28X/samples/keyboard/makefile.wat | 282 + wx28X/samples/layout/Makefile.in | 197 + wx28X/samples/layout/expt.cpp | 161 + wx28X/samples/layout/layout.bkl | 13 + wx28X/samples/layout/layout.cpp | 660 + wx28X/samples/layout/layout.dsp | 480 + wx28X/samples/layout/layout.h | 141 + wx28X/samples/layout/layout.pro | 17 + wx28X/samples/layout/layout.rc | 1 + wx28X/samples/layout/layout.vcp | 1826 + wx28X/samples/layout/layout.vcw | 17 + wx28X/samples/layout/layoutM5.xml | 3739 + wx28X/samples/layout/makefile.bcc | 253 + wx28X/samples/layout/makefile.dmc | 45 + wx28X/samples/layout/makefile.dms | 213 + wx28X/samples/layout/makefile.gcc | 253 + wx28X/samples/layout/makefile.unx | 71 + wx28X/samples/layout/makefile.vc | 359 + wx28X/samples/layout/makefile.vms | 41 + wx28X/samples/layout/makefile.wat | 282 + wx28X/samples/listbox/Makefile.in | 197 + wx28X/samples/listbox/lboxtest.cpp | 744 + wx28X/samples/listbox/lboxtestM5.xml | 3685 + wx28X/samples/listbox/listbox.bkl | 12 + wx28X/samples/listbox/listbox.dsp | 480 + wx28X/samples/listbox/listbox.vcp | 1826 + wx28X/samples/listbox/listbox.vcw | 17 + wx28X/samples/listbox/makefile.bcc | 253 + wx28X/samples/listbox/makefile.dmc | 45 + wx28X/samples/listbox/makefile.dms | 213 + wx28X/samples/listbox/makefile.gcc | 253 + wx28X/samples/listbox/makefile.unx | 71 + wx28X/samples/listbox/makefile.vc | 359 + wx28X/samples/listbox/makefile.wat | 282 + wx28X/samples/listctrl/Makefile.in | 197 + wx28X/samples/listctrl/bitmaps/small1.ico | Bin 0 -> 318 bytes wx28X/samples/listctrl/bitmaps/small1.xpm | 28 + wx28X/samples/listctrl/bitmaps/toolbrai.ico | Bin 0 -> 766 bytes wx28X/samples/listctrl/bitmaps/toolbrai.xpm | 42 + wx28X/samples/listctrl/bitmaps/toolchar.ico | Bin 0 -> 766 bytes wx28X/samples/listctrl/bitmaps/toolchar.xpm | 42 + wx28X/samples/listctrl/bitmaps/toolchec.ico | Bin 0 -> 766 bytes wx28X/samples/listctrl/bitmaps/toolchec.xpm | 54 + wx28X/samples/listctrl/bitmaps/tooldata.ico | Bin 0 -> 766 bytes wx28X/samples/listctrl/bitmaps/tooldata.xpm | 41 + wx28X/samples/listctrl/bitmaps/toolgame.ico | Bin 0 -> 766 bytes wx28X/samples/listctrl/bitmaps/toolgame.xpm | 41 + wx28X/samples/listctrl/bitmaps/toolnote.ico | Bin 0 -> 766 bytes wx28X/samples/listctrl/bitmaps/toolnote.xpm | 43 + wx28X/samples/listctrl/bitmaps/tooltime.ico | Bin 0 -> 766 bytes wx28X/samples/listctrl/bitmaps/tooltime.xpm | 42 + wx28X/samples/listctrl/bitmaps/tooltodo.ico | Bin 0 -> 766 bytes wx28X/samples/listctrl/bitmaps/tooltodo.xpm | 194 + wx28X/samples/listctrl/bitmaps/toolword.ico | Bin 0 -> 766 bytes wx28X/samples/listctrl/bitmaps/toolword.xpm | 41 + wx28X/samples/listctrl/listctrl.bkl | 13 + wx28X/samples/listctrl/listctrl.dsp | 480 + wx28X/samples/listctrl/listctrl.pro | 17 + wx28X/samples/listctrl/listctrl.vcp | 1826 + wx28X/samples/listctrl/listctrl.vcw | 17 + wx28X/samples/listctrl/listctrlM5.xml | 3685 + wx28X/samples/listctrl/listtest.cpp | 1162 + wx28X/samples/listctrl/listtest.h | 212 + wx28X/samples/listctrl/listtest.rc | 16 + wx28X/samples/listctrl/makefile.bcc | 253 + wx28X/samples/listctrl/makefile.dmc | 45 + wx28X/samples/listctrl/makefile.dms | 213 + wx28X/samples/listctrl/makefile.gcc | 253 + wx28X/samples/listctrl/makefile.unx | 71 + wx28X/samples/listctrl/makefile.vc | 359 + wx28X/samples/listctrl/makefile.wat | 282 + wx28X/samples/listctrl/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/listctrl/mondrian.xpm | 44 + wx28X/samples/makefile.bcc | 863 + wx28X/samples/makefile.dmc | 838 + wx28X/samples/makefile.dms | 679 + wx28X/samples/makefile.gcc | 382 + wx28X/samples/makefile.vc | 692 + wx28X/samples/makefile.wat | 712 + wx28X/samples/mdi/Makefile.in | 196 + wx28X/samples/mdi/bitmaps/copy.xpm | 44 + wx28X/samples/mdi/bitmaps/cut.xpm | 46 + wx28X/samples/mdi/bitmaps/help.xpm | 71 + wx28X/samples/mdi/bitmaps/new.xpm | 52 + wx28X/samples/mdi/bitmaps/open.xpm | 57 + wx28X/samples/mdi/bitmaps/paste.xpm | 46 + wx28X/samples/mdi/bitmaps/preview.xpm | 51 + wx28X/samples/mdi/bitmaps/print.xpm | 56 + wx28X/samples/mdi/bitmaps/save.xpm | 42 + wx28X/samples/mdi/chart.ico | Bin 0 -> 766 bytes wx28X/samples/mdi/chart.xpm | 45 + wx28X/samples/mdi/descrip.mms | 47 + wx28X/samples/mdi/makefile.bcc | 253 + wx28X/samples/mdi/makefile.dmc | 45 + wx28X/samples/mdi/makefile.dms | 213 + wx28X/samples/mdi/makefile.gcc | 253 + wx28X/samples/mdi/makefile.sl | 18 + wx28X/samples/mdi/makefile.unx | 71 + wx28X/samples/mdi/makefile.vc | 359 + wx28X/samples/mdi/makefile.vms | 38 + wx28X/samples/mdi/makefile.wat | 282 + wx28X/samples/mdi/mdi.bkl | 13 + wx28X/samples/mdi/mdi.cpp | 531 + wx28X/samples/mdi/mdi.dsp | 480 + wx28X/samples/mdi/mdi.h | 99 + wx28X/samples/mdi/mdi.pro | 17 + wx28X/samples/mdi/mdi.rc | 4 + wx28X/samples/mdi/mdi.vcp | 1826 + wx28X/samples/mdi/mdi.vcw | 17 + wx28X/samples/mdi/mdiM5.xml | 3685 + wx28X/samples/mediaplayer/Makefile.in | 202 + wx28X/samples/mediaplayer/makefile.bcc | 257 + wx28X/samples/mediaplayer/makefile.dmc | 45 + wx28X/samples/mediaplayer/makefile.dms | 219 + wx28X/samples/mediaplayer/makefile.gcc | 259 + wx28X/samples/mediaplayer/makefile.unx | 71 + wx28X/samples/mediaplayer/makefile.vc | 363 + wx28X/samples/mediaplayer/makefile.wat | 289 + wx28X/samples/mediaplayer/mediaplayer.bkl | 15 + wx28X/samples/mediaplayer/mediaplayer.cpp | 1845 + wx28X/samples/mediaplayer/mediaplayer.dsp | 480 + wx28X/samples/mediaplayer/mediaplayer.vcp | 1826 + wx28X/samples/mediaplayer/mediaplayer.vcw | 17 + wx28X/samples/memcheck/Makefile.in | 197 + wx28X/samples/memcheck/makefile.bcc | 253 + wx28X/samples/memcheck/makefile.dmc | 45 + wx28X/samples/memcheck/makefile.dms | 213 + wx28X/samples/memcheck/makefile.gcc | 253 + wx28X/samples/memcheck/makefile.unx | 71 + wx28X/samples/memcheck/makefile.vc | 359 + wx28X/samples/memcheck/makefile.wat | 282 + wx28X/samples/memcheck/memcheck.bkl | 13 + wx28X/samples/memcheck/memcheck.cpp | 135 + wx28X/samples/memcheck/memcheck.dsp | 480 + wx28X/samples/memcheck/memcheck.pro | 17 + wx28X/samples/memcheck/memcheck.rc | 3 + wx28X/samples/memcheck/memcheck.vcp | 1826 + wx28X/samples/memcheck/memcheck.vcw | 17 + wx28X/samples/memcheck/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/memcheck/mondrian.xpm | 44 + wx28X/samples/menu/MENU.RCO | 3 + wx28X/samples/menu/Makefile.in | 197 + wx28X/samples/menu/copy.xpm | 44 + wx28X/samples/menu/descrip.mms | 47 + wx28X/samples/menu/makefile.bcc | 253 + wx28X/samples/menu/makefile.dmc | 45 + wx28X/samples/menu/makefile.dms | 213 + wx28X/samples/menu/makefile.gcc | 253 + wx28X/samples/menu/makefile.unx | 71 + wx28X/samples/menu/makefile.va | 45 + wx28X/samples/menu/makefile.vc | 359 + wx28X/samples/menu/makefile.wat | 282 + wx28X/samples/menu/menu.bkl | 13 + wx28X/samples/menu/menu.cpp | 1112 + wx28X/samples/menu/menu.dsp | 480 + wx28X/samples/menu/menu.pro | 17 + wx28X/samples/menu/menu.rc | 1 + wx28X/samples/menu/menu.vcp | 1826 + wx28X/samples/menu/menu.vcw | 17 + wx28X/samples/menu/menuM5.xml | 3685 + wx28X/samples/menu/mondros2.ico | Bin 0 -> 996 bytes wx28X/samples/mfc/Makefile.in | 197 + wx28X/samples/mfc/makefile.bcc | 253 + wx28X/samples/mfc/makefile.dmc | 45 + wx28X/samples/mfc/makefile.dms | 213 + wx28X/samples/mfc/makefile.gcc | 253 + wx28X/samples/mfc/makefile.unx | 71 + wx28X/samples/mfc/makefile.vc | 359 + wx28X/samples/mfc/makefile.wat | 282 + wx28X/samples/mfc/mfc.bkl | 13 + wx28X/samples/mfc/mfc.dsp | 480 + wx28X/samples/mfc/mfc.pro | 17 + wx28X/samples/mfc/mfc.vcp | 1826 + wx28X/samples/mfc/mfc.vcw | 17 + wx28X/samples/mfc/mfctest.cpp | 389 + wx28X/samples/mfc/mfctest.h | 58 + wx28X/samples/mfc/mfctest.ico | Bin 0 -> 1078 bytes wx28X/samples/mfc/mfctest.rc | 108 + wx28X/samples/mfc/resource.h | 18 + wx28X/samples/mfc/stdafx.h | 7 + wx28X/samples/minifram/Makefile.in | 197 + wx28X/samples/minifram/bitmaps/copy.xpm | 44 + wx28X/samples/minifram/bitmaps/cut.xpm | 46 + wx28X/samples/minifram/bitmaps/help.xpm | 71 + wx28X/samples/minifram/bitmaps/new.xpm | 52 + wx28X/samples/minifram/bitmaps/open.xpm | 57 + wx28X/samples/minifram/bitmaps/preview.xpm | 51 + wx28X/samples/minifram/bitmaps/print.xpm | 56 + wx28X/samples/minifram/bitmaps/save.xpm | 42 + wx28X/samples/minifram/makefile.bcc | 253 + wx28X/samples/minifram/makefile.dmc | 45 + wx28X/samples/minifram/makefile.dms | 213 + wx28X/samples/minifram/makefile.gcc | 253 + wx28X/samples/minifram/makefile.sl | 14 + wx28X/samples/minifram/makefile.unx | 71 + wx28X/samples/minifram/makefile.vc | 359 + wx28X/samples/minifram/makefile.wat | 282 + wx28X/samples/minifram/minifram.bkl | 13 + wx28X/samples/minifram/minifram.cpp | 244 + wx28X/samples/minifram/minifram.dsp | 480 + wx28X/samples/minifram/minifram.h | 54 + wx28X/samples/minifram/minifram.pro | 17 + wx28X/samples/minifram/minifram.rc | 4 + wx28X/samples/minifram/minifram.vcp | 1826 + wx28X/samples/minifram/minifram.vcw | 17 + wx28X/samples/minifram/miniframM5.xml | 3685 + wx28X/samples/minifram/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/minifram/mondrian.xpm | 44 + wx28X/samples/minimal/Info.plist | 36 + wx28X/samples/minimal/Makefile.in | 197 + wx28X/samples/minimal/Minimal.icc | 17 + wx28X/samples/minimal/MinimalClassicM8.xml | 5073 + wx28X/samples/minimal/MinimalM8.xml | 10595 + wx28X/samples/minimal/descrip.mms | 75 + wx28X/samples/minimal/makefile.bcc | 253 + wx28X/samples/minimal/makefile.dmc | 45 + wx28X/samples/minimal/makefile.dms | 213 + wx28X/samples/minimal/makefile.gcc | 253 + wx28X/samples/minimal/makefile.mic | 85 + wx28X/samples/minimal/makefile.sl | 18 + wx28X/samples/minimal/makefile.unx | 71 + wx28X/samples/minimal/makefile.va | 45 + wx28X/samples/minimal/makefile.vc | 359 + wx28X/samples/minimal/makefile.wat | 282 + wx28X/samples/minimal/minimal.bkl | 15 + wx28X/samples/minimal/minimal.cpp | 199 + wx28X/samples/minimal/minimal.dsp | 480 + wx28X/samples/minimal/minimal.plc | 39 + wx28X/samples/minimal/minimal.pro | 17 + wx28X/samples/minimal/minimal.rc | 3 + wx28X/samples/minimal/minimal.rc4 | 6 + wx28X/samples/minimal/minimal.rcO | 6 + wx28X/samples/minimal/minimal.vcp | 1826 + wx28X/samples/minimal/minimal.vcw | 17 + .../minimal/minimal.xcode/project.pbxproj | 825 + .../minimal/minimal.xcodeproj/project.pbxproj | 679 + wx28X/samples/minimal/minimalW7.xml | 1968 + wx28X/samples/minimal/mondrian.icns | Bin 0 -> 41904 bytes wx28X/samples/minimal/mondrian.r | 2675 + wx28X/samples/minimal/mondros2.ico | Bin 0 -> 996 bytes wx28X/samples/mobile/Makefile.in | 53 + wx28X/samples/mobile/makefile.bcc | 73 + wx28X/samples/mobile/makefile.dmc | 48 + wx28X/samples/mobile/makefile.dms | 47 + wx28X/samples/mobile/makefile.gcc | 59 + wx28X/samples/mobile/makefile.unx | 50 + wx28X/samples/mobile/makefile.vc | 60 + wx28X/samples/mobile/makefile.wat | 80 + wx28X/samples/mobile/mobile_samples.bkl | 15 + wx28X/samples/mobile/styles/Makefile.in | 210 + wx28X/samples/mobile/styles/makefile.bcc | 257 + wx28X/samples/mobile/styles/makefile.dmc | 49 + wx28X/samples/mobile/styles/makefile.dms | 219 + wx28X/samples/mobile/styles/makefile.gcc | 257 + wx28X/samples/mobile/styles/makefile.unx | 71 + wx28X/samples/mobile/styles/makefile.vc | 363 + wx28X/samples/mobile/styles/makefile.wat | 286 + wx28X/samples/mobile/styles/marble.jpg | Bin 0 -> 8055 bytes wx28X/samples/mobile/styles/styles.bkl | 20 + wx28X/samples/mobile/styles/styles.cpp | 104 + wx28X/samples/mobile/styles/styles.dsp | 480 + wx28X/samples/mobile/styles/styles.h | 63 + wx28X/samples/mobile/styles/styles.vcp | 1826 + wx28X/samples/mobile/styles/styles.vcw | 17 + wx28X/samples/mobile/wxedit/Makefile.in | 198 + wx28X/samples/mobile/wxedit/makefile.bcc | 253 + wx28X/samples/mobile/wxedit/makefile.dmc | 45 + wx28X/samples/mobile/wxedit/makefile.dms | 213 + wx28X/samples/mobile/wxedit/makefile.gcc | 253 + wx28X/samples/mobile/wxedit/makefile.unx | 71 + wx28X/samples/mobile/wxedit/makefile.vc | 359 + wx28X/samples/mobile/wxedit/makefile.wat | 282 + wx28X/samples/mobile/wxedit/wxedit.bkl | 14 + wx28X/samples/mobile/wxedit/wxedit.cpp | 419 + wx28X/samples/mobile/wxedit/wxedit.dsp | 480 + wx28X/samples/mobile/wxedit/wxedit.h | 100 + wx28X/samples/mobile/wxedit/wxedit.vcp | 1826 + wx28X/samples/mobile/wxedit/wxedit.vcw | 17 + wx28X/samples/multimon/Makefile.in | 201 + wx28X/samples/multimon/makefile.bcc | 253 + wx28X/samples/multimon/makefile.dmc | 45 + wx28X/samples/multimon/makefile.dms | 213 + wx28X/samples/multimon/makefile.gcc | 253 + wx28X/samples/multimon/makefile.unx | 71 + wx28X/samples/multimon/makefile.vc | 359 + wx28X/samples/multimon/makefile.wat | 283 + wx28X/samples/multimon/multimon.bkl | 12 + wx28X/samples/multimon/multimon.dsp | 480 + wx28X/samples/multimon/multimon.vcp | 1826 + wx28X/samples/multimon/multimon.vcw | 17 + wx28X/samples/multimon/multimon_test.cpp | 52 + wx28X/samples/nativdlg/Makefile.in | 197 + wx28X/samples/nativdlg/dialog1.rc | 69 + wx28X/samples/nativdlg/makefile.bcc | 253 + wx28X/samples/nativdlg/makefile.dmc | 45 + wx28X/samples/nativdlg/makefile.dms | 213 + wx28X/samples/nativdlg/makefile.gcc | 253 + wx28X/samples/nativdlg/makefile.unx | 71 + wx28X/samples/nativdlg/makefile.vc | 359 + wx28X/samples/nativdlg/makefile.vms | 38 + wx28X/samples/nativdlg/makefile.wat | 282 + wx28X/samples/nativdlg/nativdlg.bkl | 13 + wx28X/samples/nativdlg/nativdlg.cpp | 110 + wx28X/samples/nativdlg/nativdlg.dsp | 480 + wx28X/samples/nativdlg/nativdlg.h | 42 + wx28X/samples/nativdlg/nativdlg.pro | 17 + wx28X/samples/nativdlg/nativdlg.rc | 4 + wx28X/samples/nativdlg/nativdlg.vcp | 1826 + wx28X/samples/nativdlg/nativdlg.vcw | 17 + wx28X/samples/nativdlg/resource.h | 25 + wx28X/samples/notebook/Makefile.in | 197 + wx28X/samples/notebook/makefile.bcc | 253 + wx28X/samples/notebook/makefile.dmc | 45 + wx28X/samples/notebook/makefile.dms | 213 + wx28X/samples/notebook/makefile.gcc | 253 + wx28X/samples/notebook/makefile.sl | 14 + wx28X/samples/notebook/makefile.unx | 71 + wx28X/samples/notebook/makefile.va | 45 + wx28X/samples/notebook/makefile.vc | 359 + wx28X/samples/notebook/makefile.wat | 282 + wx28X/samples/notebook/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/notebook/mondros2.ico | Bin 0 -> 996 bytes wx28X/samples/notebook/notebook.bkl | 12 + wx28X/samples/notebook/notebook.cpp | 963 + wx28X/samples/notebook/notebook.dsp | 480 + wx28X/samples/notebook/notebook.h | 178 + wx28X/samples/notebook/notebook.pro | 17 + wx28X/samples/notebook/notebook.rcO | 4 + wx28X/samples/notebook/notebook.vcp | 1826 + wx28X/samples/notebook/notebook.vcw | 17 + wx28X/samples/notebook/notebookM5.xml | 3685 + wx28X/samples/oleauto/Makefile.in | 197 + wx28X/samples/oleauto/makefile.bcc | 253 + wx28X/samples/oleauto/makefile.dmc | 45 + wx28X/samples/oleauto/makefile.dms | 213 + wx28X/samples/oleauto/makefile.gcc | 253 + wx28X/samples/oleauto/makefile.unx | 71 + wx28X/samples/oleauto/makefile.vc | 359 + wx28X/samples/oleauto/makefile.wat | 282 + wx28X/samples/oleauto/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/oleauto/mondrian.xpm | 44 + wx28X/samples/oleauto/oleauto.bkl | 13 + wx28X/samples/oleauto/oleauto.cpp | 217 + wx28X/samples/oleauto/oleauto.dsp | 480 + wx28X/samples/oleauto/oleauto.pro | 17 + wx28X/samples/oleauto/oleauto.rc | 3 + wx28X/samples/oleauto/oleauto.vcp | 1826 + wx28X/samples/oleauto/oleauto.vcw | 17 + wx28X/samples/opengl/Makefile.in | 58 + wx28X/samples/opengl/cube/Makefile.in | 200 + wx28X/samples/opengl/cube/cube.bkl | 20 + wx28X/samples/opengl/cube/cube.cpp | 528 + wx28X/samples/opengl/cube/cube.dsp | 480 + wx28X/samples/opengl/cube/cube.h | 104 + wx28X/samples/opengl/cube/cube.pro | 24 + wx28X/samples/opengl/cube/cube.rc | 3 + wx28X/samples/opengl/cube/cube.vcp | 1826 + wx28X/samples/opengl/cube/cube.vcw | 17 + wx28X/samples/opengl/cube/makefile.bcc | 258 + wx28X/samples/opengl/cube/makefile.dmc | 25 + wx28X/samples/opengl/cube/makefile.dms | 218 + wx28X/samples/opengl/cube/makefile.gcc | 258 + wx28X/samples/opengl/cube/makefile.unx | 71 + wx28X/samples/opengl/cube/makefile.vc | 364 + wx28X/samples/opengl/cube/makefile.wat | 288 + wx28X/samples/opengl/cube/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/opengl/isosurf/Makefile.in | 213 + wx28X/samples/opengl/isosurf/isosurf.bkl | 25 + wx28X/samples/opengl/isosurf/isosurf.cpp | 479 + wx28X/samples/opengl/isosurf/isosurf.dat.gz | Bin 0 -> 65537 bytes wx28X/samples/opengl/isosurf/isosurf.dsp | 480 + wx28X/samples/opengl/isosurf/isosurf.h | 66 + wx28X/samples/opengl/isosurf/isosurf.pro | 24 + wx28X/samples/opengl/isosurf/isosurf.vcp | 1826 + wx28X/samples/opengl/isosurf/isosurf.vcw | 17 + wx28X/samples/opengl/isosurf/makefile.bcc | 262 + wx28X/samples/opengl/isosurf/makefile.dmc | 29 + wx28X/samples/opengl/isosurf/makefile.dms | 224 + wx28X/samples/opengl/isosurf/makefile.gcc | 262 + wx28X/samples/opengl/isosurf/makefile.unx | 71 + wx28X/samples/opengl/isosurf/makefile.vc | 368 + wx28X/samples/opengl/isosurf/makefile.wat | 292 + wx28X/samples/opengl/isosurf/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/opengl/makefile.bcc | 83 + wx28X/samples/opengl/makefile.dmc | 58 + wx28X/samples/opengl/makefile.dms | 55 + wx28X/samples/opengl/makefile.gcc | 63 + wx28X/samples/opengl/makefile.unx | 54 + wx28X/samples/opengl/makefile.vc | 68 + wx28X/samples/opengl/makefile.wat | 88 + wx28X/samples/opengl/opengl_samples.bkl | 17 + wx28X/samples/opengl/penguin/Makefile.in | 229 + wx28X/samples/opengl/penguin/dxfrenderer.cpp | 676 + wx28X/samples/opengl/penguin/dxfrenderer.h | 79 + wx28X/samples/opengl/penguin/makefile.bcc | 277 + wx28X/samples/opengl/penguin/makefile.dmc | 29 + wx28X/samples/opengl/penguin/makefile.dms | 231 + wx28X/samples/opengl/penguin/makefile.gcc | 277 + wx28X/samples/opengl/penguin/makefile.unx | 89 + wx28X/samples/opengl/penguin/makefile.vc | 384 + wx28X/samples/opengl/penguin/makefile.wat | 307 + wx28X/samples/opengl/penguin/penguin.bkl | 30 + wx28X/samples/opengl/penguin/penguin.cpp | 307 + wx28X/samples/opengl/penguin/penguin.dsp | 488 + wx28X/samples/opengl/penguin/penguin.dxf.gz | Bin 0 -> 11835 bytes wx28X/samples/opengl/penguin/penguin.h | 107 + wx28X/samples/opengl/penguin/penguin.pro | 24 + wx28X/samples/opengl/penguin/penguin.rc | 3 + wx28X/samples/opengl/penguin/penguin.vcp | 1834 + wx28X/samples/opengl/penguin/penguin.vcw | 17 + wx28X/samples/opengl/penguin/trackball.c | 324 + wx28X/samples/opengl/penguin/trackball.h | 78 + wx28X/samples/ownerdrw/Makefile.in | 209 + wx28X/samples/ownerdrw/bell.bmp | Bin 0 -> 370 bytes wx28X/samples/ownerdrw/info.bmp | Bin 0 -> 246 bytes wx28X/samples/ownerdrw/info_mono.bmp | Bin 0 -> 1334 bytes wx28X/samples/ownerdrw/makefile.bcc | 257 + wx28X/samples/ownerdrw/makefile.dmc | 49 + wx28X/samples/ownerdrw/makefile.dms | 219 + wx28X/samples/ownerdrw/makefile.gcc | 257 + wx28X/samples/ownerdrw/makefile.unx | 71 + wx28X/samples/ownerdrw/makefile.vc | 363 + wx28X/samples/ownerdrw/makefile.wat | 286 + wx28X/samples/ownerdrw/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/ownerdrw/nosound.bmp | Bin 0 -> 370 bytes wx28X/samples/ownerdrw/nosound.png | Bin 0 -> 275 bytes wx28X/samples/ownerdrw/ownerdrw.bkl | 17 + wx28X/samples/ownerdrw/ownerdrw.cpp | 364 + wx28X/samples/ownerdrw/ownerdrw.dsp | 480 + wx28X/samples/ownerdrw/ownerdrw.pro | 17 + wx28X/samples/ownerdrw/ownerdrw.rc | 9 + wx28X/samples/ownerdrw/ownerdrw.vcp | 1826 + wx28X/samples/ownerdrw/ownerdrw.vcw | 17 + wx28X/samples/ownerdrw/sound.bmp | Bin 0 -> 370 bytes wx28X/samples/ownerdrw/sound.png | Bin 0 -> 227 bytes wx28X/samples/png/Makefile.in | 196 + wx28X/samples/png/julian.png | Bin 0 -> 5439 bytes wx28X/samples/png/makefile.bcc | 253 + wx28X/samples/png/makefile.dmc | 45 + wx28X/samples/png/makefile.dms | 213 + wx28X/samples/png/makefile.gcc | 253 + wx28X/samples/png/makefile.unx | 71 + wx28X/samples/png/makefile.vc | 359 + wx28X/samples/png/makefile.wat | 282 + wx28X/samples/png/png.bkl | 13 + wx28X/samples/png/png.dsp | 480 + wx28X/samples/png/png.pro | 17 + wx28X/samples/png/png.vcp | 1826 + wx28X/samples/png/png.vcw | 17 + wx28X/samples/png/pngM5.xml | 3685 + wx28X/samples/png/pngdemo.cpp | 210 + wx28X/samples/png/pngdemo.h | 55 + wx28X/samples/png/pngdemo.rc | 2 + wx28X/samples/popup/Makefile.in | 197 + wx28X/samples/popup/makefile.bcc | 253 + wx28X/samples/popup/makefile.dmc | 45 + wx28X/samples/popup/makefile.dms | 213 + wx28X/samples/popup/makefile.gcc | 253 + wx28X/samples/popup/makefile.unx | 71 + wx28X/samples/popup/makefile.vc | 359 + wx28X/samples/popup/makefile.wat | 282 + wx28X/samples/popup/popup.bkl | 11 + wx28X/samples/popup/popup.cpp | 482 + wx28X/samples/popup/popup.dsp | 480 + wx28X/samples/popup/popup.vcp | 1826 + wx28X/samples/popup/popup.vcw | 17 + wx28X/samples/power/Makefile.in | 197 + wx28X/samples/power/makefile.bcc | 253 + wx28X/samples/power/makefile.dmc | 45 + wx28X/samples/power/makefile.dms | 213 + wx28X/samples/power/makefile.gcc | 253 + wx28X/samples/power/makefile.unx | 71 + wx28X/samples/power/makefile.vc | 359 + wx28X/samples/power/makefile.wat | 282 + wx28X/samples/power/power.bkl | 13 + wx28X/samples/power/power.cpp | 199 + wx28X/samples/power/power.dsp | 480 + wx28X/samples/power/power.vcp | 1826 + wx28X/samples/power/power.vcw | 17 + wx28X/samples/printing/Makefile.in | 197 + wx28X/samples/printing/folder.xpm | 81 + wx28X/samples/printing/makefile.bcc | 253 + wx28X/samples/printing/makefile.dmc | 45 + wx28X/samples/printing/makefile.dms | 213 + wx28X/samples/printing/makefile.gcc | 253 + wx28X/samples/printing/makefile.unx | 71 + wx28X/samples/printing/makefile.vc | 359 + wx28X/samples/printing/makefile.wat | 282 + wx28X/samples/printing/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/printing/mondrian.xpm | 44 + wx28X/samples/printing/printing.bkl | 13 + wx28X/samples/printing/printing.cpp | 691 + wx28X/samples/printing/printing.dsp | 480 + wx28X/samples/printing/printing.h | 103 + wx28X/samples/printing/printing.pro | 17 + wx28X/samples/printing/printing.rc | 3 + wx28X/samples/printing/printing.vcp | 1826 + wx28X/samples/printing/printing.vcw | 17 + wx28X/samples/printing/printingM5.xml | 3685 + wx28X/samples/propsize/Makefile.in | 197 + wx28X/samples/propsize/makefile.bcc | 253 + wx28X/samples/propsize/makefile.dmc | 45 + wx28X/samples/propsize/makefile.dms | 213 + wx28X/samples/propsize/makefile.gcc | 253 + wx28X/samples/propsize/makefile.sl | 14 + wx28X/samples/propsize/makefile.unx | 71 + wx28X/samples/propsize/makefile.vc | 359 + wx28X/samples/propsize/makefile.wat | 282 + wx28X/samples/propsize/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/propsize/mondrian.xpm | 44 + wx28X/samples/propsize/propsize.bkl | 13 + wx28X/samples/propsize/propsize.cpp | 251 + wx28X/samples/propsize/propsize.dsp | 480 + wx28X/samples/propsize/propsize.pro | 17 + wx28X/samples/propsize/propsize.rc | 5 + wx28X/samples/propsize/propsize.vcp | 1826 + wx28X/samples/propsize/propsize.vcw | 17 + wx28X/samples/propsize/propsizeM5.xml | 3685 + wx28X/samples/regtest/Makefile.in | 197 + wx28X/samples/regtest/key1.ico | Bin 0 -> 1718 bytes wx28X/samples/regtest/key2.ico | Bin 0 -> 1718 bytes wx28X/samples/regtest/key3.ico | Bin 0 -> 1718 bytes wx28X/samples/regtest/makefile.bcc | 253 + wx28X/samples/regtest/makefile.dmc | 45 + wx28X/samples/regtest/makefile.dms | 213 + wx28X/samples/regtest/makefile.gcc | 253 + wx28X/samples/regtest/makefile.unx | 71 + wx28X/samples/regtest/makefile.vc | 359 + wx28X/samples/regtest/makefile.wat | 282 + wx28X/samples/regtest/registry.ico | Bin 0 -> 1078 bytes wx28X/samples/regtest/regtest.bkl | 13 + wx28X/samples/regtest/regtest.cpp | 1343 + wx28X/samples/regtest/regtest.dsp | 480 + wx28X/samples/regtest/regtest.pro | 17 + wx28X/samples/regtest/regtest.rc | 9 + wx28X/samples/regtest/regtest.vcp | 1826 + wx28X/samples/regtest/regtest.vcw | 17 + wx28X/samples/regtest/regtestM5.xml | 3685 + wx28X/samples/regtest/value1.ico | Bin 0 -> 318 bytes wx28X/samples/regtest/value2.ico | Bin 0 -> 318 bytes wx28X/samples/render/Makefile.in | 242 + wx28X/samples/render/makefile.bcc | 293 + wx28X/samples/render/makefile.dmc | 45 + wx28X/samples/render/makefile.dms | 249 + wx28X/samples/render/makefile.gcc | 295 + wx28X/samples/render/makefile.unx | 92 + wx28X/samples/render/makefile.vc | 417 + wx28X/samples/render/makefile.wat | 335 + wx28X/samples/render/renddll.cpp | 64 + wx28X/samples/render/render.bkl | 27 + wx28X/samples/render/render.cpp | 367 + wx28X/samples/render/render.vcw | 29 + wx28X/samples/render/render_renddll.dsp | 260 + wx28X/samples/render/render_renddll.vcp | 938 + wx28X/samples/render/render_render.dsp | 480 + wx28X/samples/render/render_render.vcp | 1826 + wx28X/samples/richtext/Makefile.in | 213 + wx28X/samples/richtext/bitmaps/alignleft.xpm | 24 + wx28X/samples/richtext/bitmaps/alignright.xpm | 24 + wx28X/samples/richtext/bitmaps/bold.xpm | 24 + wx28X/samples/richtext/bitmaps/centre.xpm | 24 + wx28X/samples/richtext/bitmaps/copy.xpm | 45 + wx28X/samples/richtext/bitmaps/cut.xpm | 47 + wx28X/samples/richtext/bitmaps/font.xpm | 25 + wx28X/samples/richtext/bitmaps/idea.xpm | 47 + wx28X/samples/richtext/bitmaps/indentless.xpm | 25 + wx28X/samples/richtext/bitmaps/indentmore.xpm | 25 + wx28X/samples/richtext/bitmaps/italic.xpm | 25 + wx28X/samples/richtext/bitmaps/open.xpm | 58 + wx28X/samples/richtext/bitmaps/paste.xpm | 47 + wx28X/samples/richtext/bitmaps/redo.xpm | 59 + wx28X/samples/richtext/bitmaps/save.xpm | 43 + wx28X/samples/richtext/bitmaps/smiley.xpm | 42 + wx28X/samples/richtext/bitmaps/underline.xpm | 25 + wx28X/samples/richtext/bitmaps/undo.xpm | 59 + wx28X/samples/richtext/bitmaps/zebra.xpm | 409 + wx28X/samples/richtext/makefile.bcc | 269 + wx28X/samples/richtext/makefile.dmc | 45 + wx28X/samples/richtext/makefile.dms | 229 + wx28X/samples/richtext/makefile.gcc | 269 + wx28X/samples/richtext/makefile.unx | 71 + wx28X/samples/richtext/makefile.vc | 375 + wx28X/samples/richtext/makefile.wat | 302 + wx28X/samples/richtext/readme.txt | 100 + wx28X/samples/richtext/richtext.bkl | 19 + wx28X/samples/richtext/richtext.cpp | 1591 + wx28X/samples/richtext/richtext.dsp | 480 + wx28X/samples/richtext/richtext.vcp | 1826 + wx28X/samples/richtext/richtext.vcw | 17 + wx28X/samples/richtext/todo.txt | 124 + wx28X/samples/rotate/Makefile.in | 209 + wx28X/samples/rotate/duck.png | Bin 0 -> 7754 bytes wx28X/samples/rotate/makefile.bcc | 257 + wx28X/samples/rotate/makefile.dmc | 49 + wx28X/samples/rotate/makefile.dms | 219 + wx28X/samples/rotate/makefile.gcc | 257 + wx28X/samples/rotate/makefile.unx | 71 + wx28X/samples/rotate/makefile.vc | 363 + wx28X/samples/rotate/makefile.wat | 286 + wx28X/samples/rotate/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/rotate/rotate.bkl | 19 + wx28X/samples/rotate/rotate.cpp | 277 + wx28X/samples/rotate/rotate.dsp | 480 + wx28X/samples/rotate/rotate.pro | 17 + wx28X/samples/rotate/rotate.rc | 3 + wx28X/samples/rotate/rotate.vcp | 1826 + wx28X/samples/rotate/rotate.vcw | 17 + wx28X/samples/rotate/rotateM5.xml | 3685 + wx28X/samples/sample.ico | Bin 0 -> 1078 bytes wx28X/samples/sample.r | 2679 + wx28X/samples/sample.rc | 32 + wx28X/samples/sample.xpm | 44 + wx28X/samples/samples.bkl | 99 + wx28X/samples/samples.dsw | 953 + wx28X/samples/sashtest/Makefile.in | 210 + wx28X/samples/sashtest/makefile.bcc | 265 + wx28X/samples/sashtest/makefile.dmc | 45 + wx28X/samples/sashtest/makefile.dms | 225 + wx28X/samples/sashtest/makefile.gcc | 265 + wx28X/samples/sashtest/makefile.sl | 14 + wx28X/samples/sashtest/makefile.unx | 71 + wx28X/samples/sashtest/makefile.vc | 371 + wx28X/samples/sashtest/makefile.wat | 297 + wx28X/samples/sashtest/sashtest.bkl | 16 + wx28X/samples/sashtest/sashtest.cpp | 375 + wx28X/samples/sashtest/sashtest.dsp | 480 + wx28X/samples/sashtest/sashtest.h | 77 + wx28X/samples/sashtest/sashtest.ico | Bin 0 -> 766 bytes wx28X/samples/sashtest/sashtest.pro | 17 + wx28X/samples/sashtest/sashtest.rc | 9 + wx28X/samples/sashtest/sashtest.vcp | 1826 + wx28X/samples/sashtest/sashtest.vcw | 17 + wx28X/samples/sashtest/sashtestM5.xml | 3685 + wx28X/samples/scroll/Makefile.in | 197 + wx28X/samples/scroll/makefile.bcc | 253 + wx28X/samples/scroll/makefile.dmc | 45 + wx28X/samples/scroll/makefile.dms | 213 + wx28X/samples/scroll/makefile.gcc | 253 + wx28X/samples/scroll/makefile.unx | 71 + wx28X/samples/scroll/makefile.va | 45 + wx28X/samples/scroll/makefile.vc | 359 + wx28X/samples/scroll/makefile.wat | 282 + wx28X/samples/scroll/mondros2.ico | Bin 0 -> 996 bytes wx28X/samples/scroll/scroll.bkl | 13 + wx28X/samples/scroll/scroll.cpp | 1161 + wx28X/samples/scroll/scroll.dsp | 480 + wx28X/samples/scroll/scroll.pro | 17 + wx28X/samples/scroll/scroll.rc | 2 + wx28X/samples/scroll/scroll.vcp | 1826 + wx28X/samples/scroll/scroll.vcw | 17 + wx28X/samples/scroll/scrollM5.xml | 3685 + wx28X/samples/scrollsub/Makefile.in | 197 + wx28X/samples/scrollsub/makefile.bcc | 253 + wx28X/samples/scrollsub/makefile.dmc | 45 + wx28X/samples/scrollsub/makefile.dms | 213 + wx28X/samples/scrollsub/makefile.gcc | 253 + wx28X/samples/scrollsub/makefile.unx | 71 + wx28X/samples/scrollsub/makefile.vc | 359 + wx28X/samples/scrollsub/makefile.wat | 282 + wx28X/samples/scrollsub/scrollsub.bkl | 13 + wx28X/samples/scrollsub/scrollsub.cpp | 458 + wx28X/samples/scrollsub/scrollsub.dsp | 480 + wx28X/samples/scrollsub/scrollsub.pro | 17 + wx28X/samples/scrollsub/scrollsub.rc | 2 + wx28X/samples/scrollsub/scrollsub.vcp | 1826 + wx28X/samples/scrollsub/scrollsub.vcw | 17 + wx28X/samples/scrollsub/scrollsubM5.xml | 3685 + wx28X/samples/shaped/Makefile.in | 209 + wx28X/samples/shaped/descrip.mms | 47 + wx28X/samples/shaped/makefile.bcc | 257 + wx28X/samples/shaped/makefile.dmc | 49 + wx28X/samples/shaped/makefile.dms | 219 + wx28X/samples/shaped/makefile.gcc | 257 + wx28X/samples/shaped/makefile.sl | 14 + wx28X/samples/shaped/makefile.unx | 71 + wx28X/samples/shaped/makefile.vc | 363 + wx28X/samples/shaped/makefile.wat | 286 + wx28X/samples/shaped/shaped.bkl | 17 + wx28X/samples/shaped/shaped.cpp | 234 + wx28X/samples/shaped/shaped.dsp | 480 + wx28X/samples/shaped/shaped.rc | 2 + wx28X/samples/shaped/shaped.vcp | 1826 + wx28X/samples/shaped/shaped.vcw | 17 + wx28X/samples/shaped/shapedM5.xml | 3685 + wx28X/samples/shaped/star.png | Bin 0 -> 2405 bytes wx28X/samples/sockets/Makefile.in | 264 + wx28X/samples/sockets/client.b32 | 16 + wx28X/samples/sockets/client.cpp | 645 + wx28X/samples/sockets/client.g95 | 16 + wx28X/samples/sockets/client.pro | 13 + wx28X/samples/sockets/client.rc | 3 + wx28X/samples/sockets/client.vc | 18 + wx28X/samples/sockets/client.wat | 15 + wx28X/samples/sockets/connect.ico | Bin 0 -> 766 bytes wx28X/samples/sockets/makefile.bcc | 283 + wx28X/samples/sockets/makefile.dmc | 61 + wx28X/samples/sockets/makefile.dms | 230 + wx28X/samples/sockets/makefile.gcc | 278 + wx28X/samples/sockets/makefile.unx | 81 + wx28X/samples/sockets/makefile.vc | 408 + wx28X/samples/sockets/makefile.wat | 315 + wx28X/samples/sockets/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/sockets/mondrian.xpm | 44 + wx28X/samples/sockets/server.b32 | 16 + wx28X/samples/sockets/server.cpp | 417 + wx28X/samples/sockets/server.g95 | 16 + wx28X/samples/sockets/server.pro | 13 + wx28X/samples/sockets/server.rc | 4 + wx28X/samples/sockets/server.vc | 18 + wx28X/samples/sockets/server.wat | 15 + wx28X/samples/sockets/sockets.bkl | 22 + wx28X/samples/sockets/sockets.vcw | 29 + wx28X/samples/sockets/sockets_client.dsp | 480 + wx28X/samples/sockets/sockets_client.vcp | 1826 + wx28X/samples/sockets/sockets_server.dsp | 480 + wx28X/samples/sockets/sockets_server.vcp | 1826 + wx28X/samples/sound/9000g.wav | Bin 0 -> 55852 bytes wx28X/samples/sound/Makefile.in | 222 + wx28X/samples/sound/cuckoo.wav | Bin 0 -> 7944 bytes wx28X/samples/sound/doggrowl.wav | Bin 0 -> 25044 bytes wx28X/samples/sound/makefile.bcc | 269 + wx28X/samples/sound/makefile.dmc | 49 + wx28X/samples/sound/makefile.dms | 231 + wx28X/samples/sound/makefile.gcc | 269 + wx28X/samples/sound/makefile.unx | 71 + wx28X/samples/sound/makefile.vc | 375 + wx28X/samples/sound/makefile.wat | 301 + wx28X/samples/sound/sound.bkl | 24 + wx28X/samples/sound/sound.cpp | 1101 + wx28X/samples/sound/sound.dsp | 480 + wx28X/samples/sound/sound.rc | 3 + wx28X/samples/sound/sound.vcp | 1826 + wx28X/samples/sound/sound.vcw | 17 + wx28X/samples/sound/tinkalink2.wav | Bin 0 -> 80170 bytes wx28X/samples/splash/Makefile.in | 226 + wx28X/samples/splash/makefile.bcc | 273 + wx28X/samples/splash/makefile.dmc | 49 + wx28X/samples/splash/makefile.dms | 237 + wx28X/samples/splash/makefile.gcc | 275 + wx28X/samples/splash/makefile.unx | 71 + wx28X/samples/splash/makefile.vc | 379 + wx28X/samples/splash/makefile.wat | 308 + wx28X/samples/splash/mobile.xpm | 243 + wx28X/samples/splash/press.mpg | Bin 0 -> 117656 bytes wx28X/samples/splash/press.pov | 88 + wx28X/samples/splash/splash.bkl | 23 + wx28X/samples/splash/splash.cpp | 246 + wx28X/samples/splash/splash.dsp | 480 + wx28X/samples/splash/splash.png | Bin 0 -> 160969 bytes wx28X/samples/splash/splash.pov | 108 + wx28X/samples/splash/splash.vcp | 1826 + wx28X/samples/splash/splash.vcw | 17 + wx28X/samples/splitter/Makefile.in | 197 + wx28X/samples/splitter/makefile.bcc | 253 + wx28X/samples/splitter/makefile.dmc | 45 + wx28X/samples/splitter/makefile.dms | 213 + wx28X/samples/splitter/makefile.gcc | 253 + wx28X/samples/splitter/makefile.sl | 14 + wx28X/samples/splitter/makefile.unx | 71 + wx28X/samples/splitter/makefile.vc | 359 + wx28X/samples/splitter/makefile.wat | 282 + wx28X/samples/splitter/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/splitter/splitter.bkl | 13 + wx28X/samples/splitter/splitter.cpp | 491 + wx28X/samples/splitter/splitter.dsp | 480 + wx28X/samples/splitter/splitter.pro | 17 + wx28X/samples/splitter/splitter.rc | 6 + wx28X/samples/splitter/splitter.vcp | 1826 + wx28X/samples/splitter/splitter.vcw | 17 + wx28X/samples/splitter/splitterM5.xml | 3685 + wx28X/samples/statbar/Makefile.in | 197 + wx28X/samples/statbar/green.xpm | 25 + wx28X/samples/statbar/makefile.bcc | 253 + wx28X/samples/statbar/makefile.dmc | 45 + wx28X/samples/statbar/makefile.dms | 213 + wx28X/samples/statbar/makefile.gcc | 253 + wx28X/samples/statbar/makefile.sl | 14 + wx28X/samples/statbar/makefile.unx | 71 + wx28X/samples/statbar/makefile.vc | 359 + wx28X/samples/statbar/makefile.wat | 282 + wx28X/samples/statbar/red.xpm | 25 + wx28X/samples/statbar/statbar.bkl | 13 + wx28X/samples/statbar/statbar.cpp | 734 + wx28X/samples/statbar/statbar.dsp | 480 + wx28X/samples/statbar/statbar.pro | 17 + wx28X/samples/statbar/statbar.rc | 1 + wx28X/samples/statbar/statbar.vcp | 1826 + wx28X/samples/statbar/statbar.vcw | 17 + wx28X/samples/statbar/statbarM5.xml | 3685 + wx28X/samples/taskbar/Makefile.in | 210 + wx28X/samples/taskbar/makefile.bcc | 265 + wx28X/samples/taskbar/makefile.dmc | 45 + wx28X/samples/taskbar/makefile.dms | 225 + wx28X/samples/taskbar/makefile.gcc | 265 + wx28X/samples/taskbar/makefile.unx | 71 + wx28X/samples/taskbar/makefile.vc | 371 + wx28X/samples/taskbar/makefile.wat | 297 + wx28X/samples/taskbar/smile.xpm | 42 + wx28X/samples/taskbar/taskbar.bkl | 15 + wx28X/samples/taskbar/taskbar.dsp | 480 + wx28X/samples/taskbar/taskbar.pro | 17 + wx28X/samples/taskbar/taskbar.vcp | 1826 + wx28X/samples/taskbar/taskbar.vcw | 17 + wx28X/samples/taskbar/taskbarM5.xml | 3685 + wx28X/samples/taskbar/tbtest.cpp | 206 + wx28X/samples/taskbar/tbtest.h | 63 + wx28X/samples/text/Makefile.in | 197 + wx28X/samples/text/makefile.bcc | 253 + wx28X/samples/text/makefile.dmc | 45 + wx28X/samples/text/makefile.dms | 213 + wx28X/samples/text/makefile.gcc | 253 + wx28X/samples/text/makefile.unx | 71 + wx28X/samples/text/makefile.vc | 359 + wx28X/samples/text/makefile.wat | 282 + wx28X/samples/text/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/text/mondrian.xpm | 44 + wx28X/samples/text/text.bkl | 13 + wx28X/samples/text/text.cpp | 1851 + wx28X/samples/text/text.dsp | 480 + wx28X/samples/text/text.pro | 17 + wx28X/samples/text/text.rc | 3 + wx28X/samples/text/text.vcp | 1826 + wx28X/samples/text/text.vcw | 17 + wx28X/samples/text/textM5.xml | 3685 + wx28X/samples/thread/Makefile.in | 197 + wx28X/samples/thread/makefile.bcc | 253 + wx28X/samples/thread/makefile.dmc | 45 + wx28X/samples/thread/makefile.dms | 213 + wx28X/samples/thread/makefile.gcc | 253 + wx28X/samples/thread/makefile.sl | 14 + wx28X/samples/thread/makefile.unx | 71 + wx28X/samples/thread/makefile.vc | 359 + wx28X/samples/thread/makefile.wat | 282 + wx28X/samples/thread/thread.bkl | 13 + wx28X/samples/thread/thread.cpp | 790 + wx28X/samples/thread/thread.dsp | 480 + wx28X/samples/thread/thread.pro | 17 + wx28X/samples/thread/thread.rc | 2 + wx28X/samples/thread/thread.vcp | 1826 + wx28X/samples/thread/thread.vcw | 17 + wx28X/samples/thread/threadM5.xml | 3677 + wx28X/samples/toolbar/Makefile.in | 197 + wx28X/samples/toolbar/bitmaps/copy.bmp | Bin 0 -> 1318 bytes wx28X/samples/toolbar/bitmaps/copy.xpm | 44 + wx28X/samples/toolbar/bitmaps/cut.bmp | Bin 0 -> 1318 bytes wx28X/samples/toolbar/bitmaps/cut.xpm | 46 + wx28X/samples/toolbar/bitmaps/help.bmp | Bin 0 -> 1318 bytes wx28X/samples/toolbar/bitmaps/help.xpm | 71 + wx28X/samples/toolbar/bitmaps/new.bmp | Bin 0 -> 1318 bytes wx28X/samples/toolbar/bitmaps/new.xpm | 52 + wx28X/samples/toolbar/bitmaps/open.bmp | Bin 0 -> 1318 bytes wx28X/samples/toolbar/bitmaps/open.xpm | 57 + wx28X/samples/toolbar/bitmaps/page.bmp | Bin 0 -> 714 bytes wx28X/samples/toolbar/bitmaps/paste.bmp | Bin 0 -> 1318 bytes wx28X/samples/toolbar/bitmaps/preview.bmp | Bin 0 -> 1318 bytes wx28X/samples/toolbar/bitmaps/preview.xpm | 46 + wx28X/samples/toolbar/bitmaps/print.bmp | Bin 0 -> 1318 bytes wx28X/samples/toolbar/bitmaps/print.xpm | 56 + wx28X/samples/toolbar/bitmaps/save.bmp | Bin 0 -> 1318 bytes wx28X/samples/toolbar/bitmaps/save.xpm | 42 + wx28X/samples/toolbar/makefile.bcc | 253 + wx28X/samples/toolbar/makefile.dmc | 45 + wx28X/samples/toolbar/makefile.dms | 213 + wx28X/samples/toolbar/makefile.gcc | 253 + wx28X/samples/toolbar/makefile.sl | 14 + wx28X/samples/toolbar/makefile.unx | 71 + wx28X/samples/toolbar/makefile.va | 45 + wx28X/samples/toolbar/makefile.vc | 359 + wx28X/samples/toolbar/makefile.wat | 282 + wx28X/samples/toolbar/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/toolbar/mondrian.xpm | 44 + wx28X/samples/toolbar/mondros2.ico | Bin 0 -> 996 bytes wx28X/samples/toolbar/toolbar.bkl | 13 + wx28X/samples/toolbar/toolbar.cpp | 896 + wx28X/samples/toolbar/toolbar.dsp | 480 + wx28X/samples/toolbar/toolbar.pro | 17 + wx28X/samples/toolbar/toolbar.rc | 12 + wx28X/samples/toolbar/toolbar.rco | 13 + wx28X/samples/toolbar/toolbar.vcp | 1826 + wx28X/samples/toolbar/toolbar.vcw | 17 + wx28X/samples/toolbar/toolbarM5.xml | 3685 + wx28X/samples/treectrl/Makefile.in | 197 + wx28X/samples/treectrl/icon1.xpm | 79 + wx28X/samples/treectrl/icon2.xpm | 53 + wx28X/samples/treectrl/icon3.xpm | 79 + wx28X/samples/treectrl/icon4.xpm | 43 + wx28X/samples/treectrl/icon5.xpm | 79 + wx28X/samples/treectrl/makefile.bcc | 253 + wx28X/samples/treectrl/makefile.dmc | 45 + wx28X/samples/treectrl/makefile.dms | 213 + wx28X/samples/treectrl/makefile.gcc | 253 + wx28X/samples/treectrl/makefile.unx | 71 + wx28X/samples/treectrl/makefile.vc | 359 + wx28X/samples/treectrl/makefile.wat | 282 + wx28X/samples/treectrl/treectrl.bkl | 13 + wx28X/samples/treectrl/treectrl.dsp | 480 + wx28X/samples/treectrl/treectrl.vcp | 1826 + wx28X/samples/treectrl/treectrl.vcw | 17 + wx28X/samples/treectrl/treetest.cpp | 1309 + wx28X/samples/treectrl/treetest.h | 293 + wx28X/samples/treectrl/treetestM5.xml | 3685 + wx28X/samples/typetest/Makefile.in | 197 + wx28X/samples/typetest/makefile.bcc | 253 + wx28X/samples/typetest/makefile.dmc | 45 + wx28X/samples/typetest/makefile.dms | 213 + wx28X/samples/typetest/makefile.gcc | 253 + wx28X/samples/typetest/makefile.sl | 14 + wx28X/samples/typetest/makefile.unx | 71 + wx28X/samples/typetest/makefile.vc | 359 + wx28X/samples/typetest/makefile.wat | 282 + wx28X/samples/typetest/mondrian.ico | Bin 0 -> 766 bytes wx28X/samples/typetest/mondrian.xpm | 44 + wx28X/samples/typetest/typetest.bkl | 13 + wx28X/samples/typetest/typetest.cpp | 1083 + wx28X/samples/typetest/typetest.dsp | 480 + wx28X/samples/typetest/typetest.h | 88 + wx28X/samples/typetest/typetest.pro | 17 + wx28X/samples/typetest/typetest.rc | 3 + wx28X/samples/typetest/typetest.vcp | 1826 + wx28X/samples/typetest/typetest.vcw | 17 + wx28X/samples/typetest/typetestM5.xml | 3685 + wx28X/samples/validate/Makefile.in | 197 + wx28X/samples/validate/makefile.bcc | 253 + wx28X/samples/validate/makefile.dmc | 45 + wx28X/samples/validate/makefile.dms | 213 + wx28X/samples/validate/makefile.gcc | 253 + wx28X/samples/validate/makefile.unx | 71 + wx28X/samples/validate/makefile.vc | 359 + wx28X/samples/validate/makefile.wat | 282 + wx28X/samples/validate/validate.bkl | 13 + wx28X/samples/validate/validate.cpp | 241 + wx28X/samples/validate/validate.dsp | 480 + wx28X/samples/validate/validate.h | 85 + wx28X/samples/validate/validate.vcp | 1826 + wx28X/samples/validate/validate.vcw | 17 + wx28X/samples/validate/validateM5.xml | 3685 + wx28X/samples/vscroll/Makefile.in | 197 + wx28X/samples/vscroll/makefile.bcc | 253 + wx28X/samples/vscroll/makefile.dmc | 45 + wx28X/samples/vscroll/makefile.dms | 213 + wx28X/samples/vscroll/makefile.gcc | 253 + wx28X/samples/vscroll/makefile.unx | 71 + wx28X/samples/vscroll/makefile.vc | 359 + wx28X/samples/vscroll/makefile.wat | 282 + wx28X/samples/vscroll/vscroll.bkl | 12 + wx28X/samples/vscroll/vscroll.dsp | 480 + wx28X/samples/vscroll/vscroll.vcp | 1826 + wx28X/samples/vscroll/vscroll.vcw | 17 + wx28X/samples/vscroll/vstest.cpp | 289 + wx28X/samples/widgets/Makefile.in | 298 + wx28X/samples/widgets/bmpcombobox.cpp | 910 + wx28X/samples/widgets/button.cpp | 465 + wx28X/samples/widgets/checkbox.cpp | 316 + wx28X/samples/widgets/clrpicker.cpp | 235 + wx28X/samples/widgets/combobox.cpp | 597 + wx28X/samples/widgets/datepick.cpp | 249 + wx28X/samples/widgets/dirctrl.cpp | 335 + wx28X/samples/widgets/dirpicker.cpp | 243 + wx28X/samples/widgets/filepicker.cpp | 304 + wx28X/samples/widgets/fontpicker.cpp | 243 + wx28X/samples/widgets/gauge.cpp | 469 + wx28X/samples/widgets/hyperlnk.cpp | 326 + wx28X/samples/widgets/icons/bmpbtn.xpm | 37 + wx28X/samples/widgets/icons/bmpcombobox.xpm | 54 + wx28X/samples/widgets/icons/button.xpm | 54 + wx28X/samples/widgets/icons/checkbox.xpm | 54 + wx28X/samples/widgets/icons/choicebk.xpm | 54 + wx28X/samples/widgets/icons/clrpicker.xpm | 193 + wx28X/samples/widgets/icons/combobox.xpm | 54 + wx28X/samples/widgets/icons/datepick.xpm | 200 + wx28X/samples/widgets/icons/dirctrl.xpm | 54 + wx28X/samples/widgets/icons/dirpicker.xpm | 213 + wx28X/samples/widgets/icons/filepicker.xpm | 214 + wx28X/samples/widgets/icons/fontpicker.xpm | 185 + wx28X/samples/widgets/icons/gauge.xpm | 54 + wx28X/samples/widgets/icons/hyperlnk.xpm | 54 + wx28X/samples/widgets/icons/listbook.xpm | 54 + wx28X/samples/widgets/icons/listbox.xpm | 54 + wx28X/samples/widgets/icons/notebook.xpm | 54 + wx28X/samples/widgets/icons/odcombobox.xpm | 54 + wx28X/samples/widgets/icons/radiobox.xpm | 54 + wx28X/samples/widgets/icons/scrolbar.xpm | 54 + wx28X/samples/widgets/icons/slider.xpm | 54 + wx28X/samples/widgets/icons/spinbtn.xpm | 40 + wx28X/samples/widgets/icons/statbox.xpm | 54 + wx28X/samples/widgets/icons/stattext.xpm | 54 + wx28X/samples/widgets/icons/text.xpm | 54 + wx28X/samples/widgets/icons/toggle.xpm | 54 + wx28X/samples/widgets/listbox.cpp | 549 + wx28X/samples/widgets/makefile.bcc | 353 + wx28X/samples/widgets/makefile.dmc | 133 + wx28X/samples/widgets/makefile.dms | 291 + wx28X/samples/widgets/makefile.gcc | 353 + wx28X/samples/widgets/makefile.mic | 87 + wx28X/samples/widgets/makefile.unx | 159 + wx28X/samples/widgets/makefile.vc | 459 + wx28X/samples/widgets/makefile.wat | 385 + wx28X/samples/widgets/notebook.cpp | 769 + wx28X/samples/widgets/odcombobox.cpp | 834 + wx28X/samples/widgets/radiobox.cpp | 527 + wx28X/samples/widgets/searchctrl.cpp | 225 + wx28X/samples/widgets/slider.cpp | 721 + wx28X/samples/widgets/spinbtn.cpp | 445 + wx28X/samples/widgets/static.cpp | 442 + wx28X/samples/widgets/textctrl.cpp | 926 + wx28X/samples/widgets/toggle.cpp | 211 + wx28X/samples/widgets/widgets.bkl | 41 + wx28X/samples/widgets/widgets.cpp | 985 + wx28X/samples/widgets/widgets.dsp | 568 + wx28X/samples/widgets/widgets.h | 195 + wx28X/samples/widgets/widgets.pro | 19 + wx28X/samples/widgets/widgets.vcp | 1914 + wx28X/samples/widgets/widgets.vcw | 17 + wx28X/samples/widgets/widgetsM5.xml | 4225 + wx28X/samples/wizard/Makefile.in | 210 + wx28X/samples/wizard/makefile.bcc | 265 + wx28X/samples/wizard/makefile.dmc | 45 + wx28X/samples/wizard/makefile.dms | 225 + wx28X/samples/wizard/makefile.gcc | 265 + wx28X/samples/wizard/makefile.sl | 14 + wx28X/samples/wizard/makefile.unx | 71 + wx28X/samples/wizard/makefile.vc | 371 + wx28X/samples/wizard/makefile.wat | 297 + wx28X/samples/wizard/wizard.bkl | 16 + wx28X/samples/wizard/wizard.cpp | 480 + wx28X/samples/wizard/wizard.dsp | 480 + wx28X/samples/wizard/wizard.pro | 17 + wx28X/samples/wizard/wizard.rc | 2 + wx28X/samples/wizard/wizard.vcp | 1826 + wx28X/samples/wizard/wizard.vcw | 17 + wx28X/samples/wizard/wizardM5.xml | 3685 + wx28X/samples/wizard/wiztest.xpm | 295 + wx28X/samples/wizard/wiztest2.xpm | 502 + wx28X/samples/xrc/Makefile.in | 237 + wx28X/samples/xrc/custclas.cpp | 149 + wx28X/samples/xrc/custclas.h | 89 + wx28X/samples/xrc/derivdlg.cpp | 110 + wx28X/samples/xrc/derivdlg.h | 63 + wx28X/samples/xrc/descrip.mms | 81 + wx28X/samples/xrc/makefile.bcc | 285 + wx28X/samples/xrc/makefile.dmc | 61 + wx28X/samples/xrc/makefile.dms | 244 + wx28X/samples/xrc/makefile.gcc | 285 + wx28X/samples/xrc/makefile.unx | 83 + wx28X/samples/xrc/makefile.vc | 391 + wx28X/samples/xrc/makefile.wat | 318 + wx28X/samples/xrc/myframe.cpp | 316 + wx28X/samples/xrc/myframe.h | 62 + wx28X/samples/xrc/rc/appicon.ico | Bin 0 -> 1078 bytes wx28X/samples/xrc/rc/appicon.xpm | 52 + wx28X/samples/xrc/rc/artprov.xpm | 23 + wx28X/samples/xrc/rc/artprov.xrc | 67 + wx28X/samples/xrc/rc/basicdlg.xpm | 24 + wx28X/samples/xrc/rc/basicdlg.xrc | 44 + wx28X/samples/xrc/rc/controls.xpm | 25 + wx28X/samples/xrc/rc/controls.xrc | 1243 + wx28X/samples/xrc/rc/custclas.xpm | 26 + wx28X/samples/xrc/rc/custclas.xrc | 42 + wx28X/samples/xrc/rc/derivdlg.xpm | 25 + wx28X/samples/xrc/rc/derivdlg.xrc | 78 + wx28X/samples/xrc/rc/fileopen.gif | Bin 0 -> 949 bytes wx28X/samples/xrc/rc/filesave.gif | Bin 0 -> 927 bytes wx28X/samples/xrc/rc/frame.xrc | 27 + wx28X/samples/xrc/rc/fuzzy.gif | Bin 0 -> 116 bytes wx28X/samples/xrc/rc/menu.xrc | 84 + wx28X/samples/xrc/rc/platform.xpm | 28 + wx28X/samples/xrc/rc/platform.xrc | 145 + wx28X/samples/xrc/rc/quotes.gif | Bin 0 -> 82 bytes wx28X/samples/xrc/rc/resource.xrc | 154 + wx28X/samples/xrc/rc/stop.xpm | 164 + wx28X/samples/xrc/rc/throbber.gif | Bin 0 -> 2704 bytes wx28X/samples/xrc/rc/toolbar.xrc | 51 + wx28X/samples/xrc/rc/uncenter.xpm | 24 + wx28X/samples/xrc/rc/uncenter.xrc | 47 + wx28X/samples/xrc/rc/update.gif | Bin 0 -> 124 bytes wx28X/samples/xrc/rc/variable.xpm | 21 + wx28X/samples/xrc/rc/variable.xrc | 59 + wx28X/samples/xrc/xrcdemo.bkl | 36 + wx28X/samples/xrc/xrcdemo.cpp | 141 + wx28X/samples/xrc/xrcdemo.dsp | 492 + wx28X/samples/xrc/xrcdemo.h | 46 + wx28X/samples/xrc/xrcdemo.rc | 2 + wx28X/samples/xrc/xrcdemo.vcp | 1838 + wx28X/samples/xrc/xrcdemo.vcw | 17 + wx28X/setup.h.in | 1239 + wx28X/setup.h_vms | 1268 + wx28X/src/Wxwindll.icc | 314 + wx28X/src/aui/auibar.cpp | 2682 + wx28X/src/aui/auibook.cpp | 4610 + wx28X/src/aui/descrip.mms | 72 + wx28X/src/aui/dockart.cpp | 771 + wx28X/src/aui/floatpane.cpp | 323 + wx28X/src/aui/framemanager.cpp | 4683 + wx28X/src/aui/tabmdi.cpp | 837 + wx28X/src/common/accesscmn.cpp | 26 + wx28X/src/common/anidecod.cpp | 345 + wx28X/src/common/animatecmn.cpp | 103 + wx28X/src/common/appbase.cpp | 846 + wx28X/src/common/appcmn.cpp | 691 + wx28X/src/common/arcall.cpp | 41 + wx28X/src/common/arcfind.cpp | 43 + wx28X/src/common/archive.cpp | 98 + wx28X/src/common/artprov.cpp | 354 + wx28X/src/common/artstd.cpp | 267 + wx28X/src/common/base.rc | 49 + wx28X/src/common/bmpbase.cpp | 211 + wx28X/src/common/bookctrl.cpp | 497 + wx28X/src/common/choiccmn.cpp | 55 + wx28X/src/common/clipcmn.cpp | 63 + wx28X/src/common/clntdata.cpp | 83 + wx28X/src/common/clrpickercmn.cpp | 149 + wx28X/src/common/cmdline.cpp | 1246 + wx28X/src/common/cmdproc.cpp | 325 + wx28X/src/common/cmndata.cpp | 660 + wx28X/src/common/colourcmn.cpp | 126 + wx28X/src/common/combocmn.cpp | 2340 + wx28X/src/common/config.cpp | 490 + wx28X/src/common/containr.cpp | 678 + wx28X/src/common/convauto.cpp | 214 + wx28X/src/common/cshelp.cpp | 512 + wx28X/src/common/ctrlcmn.cpp | 188 + wx28X/src/common/ctrlsub.cpp | 197 + wx28X/src/common/datacmn.cpp | 83 + wx28X/src/common/datavcmn.cpp | 911 + wx28X/src/common/datetime.cpp | 4615 + wx28X/src/common/datstrm.cpp | 745 + wx28X/src/common/db.cpp | 4524 + wx28X/src/common/dbgrid.cpp | 727 + wx28X/src/common/dbtable.cpp | 2946 + wx28X/src/common/dcbase.cpp | 1174 + wx28X/src/common/dcbufcmn.cpp | 95 + wx28X/src/common/dcgraph.cpp | 1034 + wx28X/src/common/debugrpt.cpp | 698 + wx28X/src/common/descrip.mms | 583 + wx28X/src/common/dircmn.cpp | 357 + wx28X/src/common/dlgcmn.cpp | 565 + wx28X/src/common/dndcmn.cpp | 31 + wx28X/src/common/dobjcmn.cpp | 517 + wx28X/src/common/docmdi.cpp | 206 + wx28X/src/common/docview.cpp | 2491 + wx28X/src/common/dpycmn.cpp | 269 + wx28X/src/common/dseldlg.cpp | 55 + wx28X/src/common/dummy.cpp | 32 + wx28X/src/common/dynarray.cpp | 527 + wx28X/src/common/dynlib.cpp | 323 + wx28X/src/common/dynload.cpp | 362 + wx28X/src/common/effects.cpp | 124 + wx28X/src/common/emptydmy.cpp | 3 + wx28X/src/common/encconv.cpp | 531 + wx28X/src/common/event.cpp | 1499 + wx28X/src/common/evtloopcmn.cpp | 172 + wx28X/src/common/execcmn.cpp | 122 + wx28X/src/common/extended.c | 196 + wx28X/src/common/fddlgcmn.cpp | 102 + wx28X/src/common/ffile.cpp | 256 + wx28X/src/common/file.cpp | 559 + wx28X/src/common/fileback.cpp | 338 + wx28X/src/common/fileconf.cpp | 2131 + wx28X/src/common/filefn.cpp | 2123 + wx28X/src/common/filename.cpp | 2558 + wx28X/src/common/filepickercmn.cpp | 224 + wx28X/src/common/filesys.cpp | 700 + wx28X/src/common/filtall.cpp | 36 + wx28X/src/common/filtfind.cpp | 43 + wx28X/src/common/fldlgcmn.cpp | 348 + wx28X/src/common/fmapbase.cpp | 737 + wx28X/src/common/fontcmn.cpp | 784 + wx28X/src/common/fontenumcmn.cpp | 131 + wx28X/src/common/fontmap.cpp | 519 + wx28X/src/common/fontmgrcmn.cpp | 348 + wx28X/src/common/fontpickercmn.cpp | 181 + wx28X/src/common/framecmn.cpp | 590 + wx28X/src/common/fs_arc.cpp | 533 + wx28X/src/common/fs_filter.cpp | 92 + wx28X/src/common/fs_inet.cpp | 167 + wx28X/src/common/fs_mem.cpp | 288 + wx28X/src/common/ftp.cpp | 1021 + wx28X/src/common/gaugecmn.cpp | 156 + wx28X/src/common/gbsizer.cpp | 784 + wx28X/src/common/gdicmn.cpp | 871 + wx28X/src/common/geometry.cpp | 364 + wx28X/src/common/gifdecod.cpp | 933 + wx28X/src/common/glob.inc | 367 + wx28X/src/common/graphcmn.cpp | 776 + wx28X/src/common/hash.cpp | 1077 + wx28X/src/common/hashmap.cpp | 152 + wx28X/src/common/helpbase.cpp | 28 + wx28X/src/common/http.cpp | 422 + wx28X/src/common/iconbndl.cpp | 142 + wx28X/src/common/imagall.cpp | 64 + wx28X/src/common/imagbmp.cpp | 1383 + wx28X/src/common/image.cpp | 3126 + wx28X/src/common/imagfill.cpp | 325 + wx28X/src/common/imaggif.cpp | 105 + wx28X/src/common/imagiff.cpp | 794 + wx28X/src/common/imagjpeg.cpp | 480 + wx28X/src/common/imagpcx.cpp | 500 + wx28X/src/common/imagpng.cpp | 869 + wx28X/src/common/imagpnm.cpp | 201 + wx28X/src/common/imagtga.cpp | 750 + wx28X/src/common/imagtiff.cpp | 525 + wx28X/src/common/imagxpm.cpp | 224 + wx28X/src/common/init.cpp | 505 + wx28X/src/common/intl.cpp | 3784 + wx28X/src/common/ipcbase.cpp | 87 + wx28X/src/common/layout.cpp | 1026 + wx28X/src/common/lboxcmn.cpp | 147 + wx28X/src/common/list.cpp | 768 + wx28X/src/common/listctrlcmn.cpp | 54 + wx28X/src/common/log.cpp | 838 + wx28X/src/common/longlong.cpp | 1363 + wx28X/src/common/matrix.cpp | 601 + wx28X/src/common/mediactrlcmn.cpp | 559 + wx28X/src/common/memory.cpp | 1148 + wx28X/src/common/menucmn.cpp | 1173 + wx28X/src/common/mimecmn.cpp | 752 + wx28X/src/common/module.cpp | 202 + wx28X/src/common/msgout.cpp | 222 + wx28X/src/common/mstream.cpp | 174 + wx28X/src/common/nbkbase.cpp | 84 + wx28X/src/common/object.cpp | 390 + wx28X/src/common/overlaycmn.cpp | 197 + wx28X/src/common/paper.cpp | 376 + wx28X/src/common/pickerbase.cpp | 175 + wx28X/src/common/platinfo.cpp | 336 + wx28X/src/common/popupcmn.cpp | 623 + wx28X/src/common/powercmn.cpp | 59 + wx28X/src/common/prntbase.cpp | 1869 + wx28X/src/common/process.cpp | 172 + wx28X/src/common/protocol.cpp | 215 + wx28X/src/common/quantize.cpp | 1654 + wx28X/src/common/radiocmn.cpp | 304 + wx28X/src/common/regex.cpp | 689 + wx28X/src/common/rendcmn.cpp | 208 + wx28X/src/common/rgncmn.cpp | 192 + wx28X/src/common/sckaddr.cpp | 349 + wx28X/src/common/sckfile.cpp | 57 + wx28X/src/common/sckipc.cpp | 769 + wx28X/src/common/sckstrm.cpp | 135 + wx28X/src/common/settcmn.cpp | 88 + wx28X/src/common/sizer.cpp | 2265 + wx28X/src/common/socket.cpp | 1420 + wx28X/src/common/socketevtdispatch.cpp | 339 + wx28X/src/common/srchcmn.cpp | 42 + wx28X/src/common/sstream.cpp | 235 + wx28X/src/common/statbar.cpp | 368 + wx28X/src/common/stdpbase.cpp | 172 + wx28X/src/common/stockitem.cpp | 278 + wx28X/src/common/stopwatch.cpp | 372 + wx28X/src/common/strconv.cpp | 3742 + wx28X/src/common/stream.cpp | 1388 + wx28X/src/common/string.cpp | 2659 + wx28X/src/common/sysopt.cpp | 111 + wx28X/src/common/tarstrm.cpp | 1534 + wx28X/src/common/taskbarcmn.cpp | 54 + wx28X/src/common/tbarbase.cpp | 746 + wx28X/src/common/textbuf.cpp | 284 + wx28X/src/common/textcmn.cpp | 553 + wx28X/src/common/textfile.cpp | 295 + wx28X/src/common/timercmn.cpp | 88 + wx28X/src/common/tokenzr.cpp | 229 + wx28X/src/common/toplvcmn.cpp | 431 + wx28X/src/common/treebase.cpp | 239 + wx28X/src/common/txtstrm.cpp | 520 + wx28X/src/common/unictabl.inc | 872 + wx28X/src/common/uri.cpp | 1295 + wx28X/src/common/url.cpp | 533 + wx28X/src/common/utilscmn.cpp | 1417 + wx28X/src/common/valgen.cpp | 591 + wx28X/src/common/validate.cpp | 45 + wx28X/src/common/valtext.cpp | 344 + wx28X/src/common/variant.cpp | 2040 + wx28X/src/common/wfstream.cpp | 418 + wx28X/src/common/wincmn.cpp | 3255 + wx28X/src/common/wxchar.cpp | 2293 + wx28X/src/common/xpmdecod.cpp | 833 + wx28X/src/common/xti.cpp | 767 + wx28X/src/common/xtistrm.cpp | 847 + wx28X/src/common/xtixml.cpp | 538 + wx28X/src/common/zipstrm.cpp | 2425 + wx28X/src/common/zstream.cpp | 428 + wx28X/src/cwcopysetup.bat | 32 + wx28X/src/cwdcopysetup.bat | 32 + wx28X/src/cygnus.bat | 11 + wx28X/src/expat/COPYING | 22 + wx28X/src/expat/Changes | 107 + wx28X/src/expat/MANIFEST | 92 + wx28X/src/expat/Makefile.in | 173 + wx28X/src/expat/README | 112 + wx28X/src/expat/aclocal.m4 | 6035 + wx28X/src/expat/bcb5/README.txt | 86 + wx28X/src/expat/bcb5/elements.bpf | 4 + wx28X/src/expat/bcb5/elements.bpr | 149 + wx28X/src/expat/bcb5/elements.mak | 186 + wx28X/src/expat/bcb5/expat.bpf | 6 + wx28X/src/expat/bcb5/expat.bpr | 140 + wx28X/src/expat/bcb5/expat.mak | 187 + wx28X/src/expat/bcb5/expat_static.bpf | 5 + wx28X/src/expat/bcb5/expat_static.bpr | 143 + wx28X/src/expat/bcb5/expat_static.mak | 189 + wx28X/src/expat/bcb5/expatw.bpf | 6 + wx28X/src/expat/bcb5/expatw.bpr | 146 + wx28X/src/expat/bcb5/expatw.mak | 187 + wx28X/src/expat/bcb5/expatw_static.bpf | 5 + wx28X/src/expat/bcb5/expatw_static.bpr | 152 + wx28X/src/expat/bcb5/expatw_static.mak | 190 + wx28X/src/expat/bcb5/libexpat_mtd.def | 133 + wx28X/src/expat/bcb5/libexpatw_mtd.def | 133 + wx28X/src/expat/bcb5/makefile.mak | 37 + wx28X/src/expat/bcb5/outline.bpf | 4 + wx28X/src/expat/bcb5/outline.bpr | 132 + wx28X/src/expat/bcb5/outline.mak | 186 + wx28X/src/expat/bcb5/setup.bat | 9 + wx28X/src/expat/bcb5/xmlwf.bpf | 7 + wx28X/src/expat/bcb5/xmlwf.bpr | 136 + wx28X/src/expat/bcb5/xmlwf.mak | 187 + wx28X/src/expat/configure | 10129 + wx28X/src/expat/configure.in | 127 + wx28X/src/expat/conftools/PrintPath | 116 + .../expat/conftools/ac_c_bigendian_cross.m4 | 81 + wx28X/src/expat/conftools/config.guess | 1344 + wx28X/src/expat/conftools/config.sub | 1507 + wx28X/src/expat/conftools/expat.m4 | 43 + wx28X/src/expat/conftools/install-sh | 251 + wx28X/src/expat/conftools/libtool.m4 | 3573 + wx28X/src/expat/conftools/ltmain.sh | 4984 + wx28X/src/expat/conftools/mkinstalldirs | 40 + wx28X/src/expat/doc/reference.html | 1896 + wx28X/src/expat/doc/style.css | 51 + wx28X/src/expat/doc/valid-xhtml10.png | Bin 0 -> 2414 bytes wx28X/src/expat/doc/xmlwf.1 | 251 + wx28X/src/expat/doc/xmlwf.sgml | 473 + wx28X/src/expat/examples/elements.c | 50 + wx28X/src/expat/examples/outline.c | 90 + wx28X/src/expat/expat.dsp | 110 + wx28X/src/expat/expat_config.h.in | 89 + wx28X/src/expat/lib/ascii.h | 85 + wx28X/src/expat/lib/asciitab.h | 36 + wx28X/src/expat/lib/dosconfig.h | 25 + wx28X/src/expat/lib/expat.h | 918 + wx28X/src/expat/lib/iasciitab.h | 37 + wx28X/src/expat/lib/internal.h | 77 + wx28X/src/expat/lib/latin1tab.h | 36 + wx28X/src/expat/lib/macconfig.h | 104 + wx28X/src/expat/lib/nametab.h | 150 + wx28X/src/expat/lib/os2config.h | 26 + wx28X/src/expat/lib/utf8tab.h | 37 + wx28X/src/expat/lib/winconfig.h | 30 + wx28X/src/expat/lib/xmlparse.c | 5711 + wx28X/src/expat/lib/xmlrole.c | 1325 + wx28X/src/expat/lib/xmlrole.h | 114 + wx28X/src/expat/lib/xmltok.c | 1636 + wx28X/src/expat/lib/xmltok.h | 315 + wx28X/src/expat/lib/xmltok_impl.c | 1779 + wx28X/src/expat/lib/xmltok_impl.h | 46 + wx28X/src/expat/lib/xmltok_ns.c | 106 + wx28X/src/expat/vms/README.vms | 23 + wx28X/src/expat/vms/descrip.mms | 69 + wx28X/src/expat/vms/expat_config.h | 61 + wx28X/src/expat/win32/MANIFEST.txt | 29 + wx28X/src/expat/win32/expat.iss | 61 + wx28X/src/expat/xmlwf/codepage.c | 68 + wx28X/src/expat/xmlwf/codepage.h | 6 + wx28X/src/expat/xmlwf/ct.c | 147 + wx28X/src/expat/xmlwf/filemap.h | 17 + wx28X/src/expat/xmlwf/readfilemap.c | 78 + wx28X/src/expat/xmlwf/unixfilemap.c | 58 + wx28X/src/expat/xmlwf/win32filemap.c | 96 + wx28X/src/expat/xmlwf/xmlfile.c | 231 + wx28X/src/expat/xmlwf/xmlfile.h | 10 + wx28X/src/expat/xmlwf/xmlmime.c | 163 + wx28X/src/expat/xmlwf/xmlmime.h | 19 + wx28X/src/expat/xmlwf/xmltchar.h | 36 + wx28X/src/expat/xmlwf/xmlurl.h | 13 + wx28X/src/expat/xmlwf/xmlwf.c | 842 + wx28X/src/expat/xmlwf/xmlwin32url.cxx | 395 + wx28X/src/generic/aboutdlgg.cpp | 258 + wx28X/src/generic/accel.cpp | 220 + wx28X/src/generic/animateg.cpp | 690 + wx28X/src/generic/bmpcboxg.cpp | 477 + wx28X/src/generic/busyinfo.cpp | 135 + wx28X/src/generic/buttonbar.cpp | 555 + wx28X/src/generic/calctrl.cpp | 1838 + wx28X/src/generic/caret.cpp | 310 + wx28X/src/generic/choicbkg.cpp | 332 + wx28X/src/generic/choicdgg.cpp | 556 + wx28X/src/generic/clrpickerg.cpp | 188 + wx28X/src/generic/collpaneg.cpp | 307 + wx28X/src/generic/colour.cpp | 72 + wx28X/src/generic/colrdlgg.cpp | 586 + wx28X/src/generic/combog.cpp | 489 + wx28X/src/generic/datavgen.cpp | 1911 + wx28X/src/generic/datectlg.cpp | 545 + wx28X/src/generic/dbgrptg.cpp | 525 + wx28X/src/generic/dcpsg.cpp | 2262 + wx28X/src/generic/descrip.mms | 276 + wx28X/src/generic/dirctrlg.cpp | 1700 + wx28X/src/generic/dirdlgg.cpp | 369 + wx28X/src/generic/dragimgg.cpp | 574 + wx28X/src/generic/fdrepdlg.cpp | 291 + wx28X/src/generic/filedlgg.cpp | 1645 + wx28X/src/generic/filepickerg.cpp | 86 + wx28X/src/generic/fontdlgg.cpp | 623 + wx28X/src/generic/fontpickerg.cpp | 120 + wx28X/src/generic/graphicc.cpp | 1615 + wx28X/src/generic/grid.cpp | 11472 + wx28X/src/generic/gridctrl.cpp | 418 + wx28X/src/generic/gridsel.cpp | 1177 + wx28X/src/generic/helpext.cpp | 485 + wx28X/src/generic/htmllbox.cpp | 682 + wx28X/src/generic/hyperlink.cpp | 285 + wx28X/src/generic/icon.cpp | 45 + wx28X/src/generic/imaglist.cpp | 278 + wx28X/src/generic/laywin.cpp | 341 + wx28X/src/generic/listbkg.cpp | 416 + wx28X/src/generic/listctrl.cpp | 5976 + wx28X/src/generic/logg.cpp | 1229 + wx28X/src/generic/mask.cpp | 76 + wx28X/src/generic/mdig.cpp | 820 + wx28X/src/generic/msgdlgg.cpp | 159 + wx28X/src/generic/notebook.cpp | 762 + wx28X/src/generic/numdlgg.cpp | 181 + wx28X/src/generic/odcombo.cpp | 1126 + wx28X/src/generic/paletteg.cpp | 145 + wx28X/src/generic/panelg.cpp | 180 + wx28X/src/generic/printps.cpp | 370 + wx28X/src/generic/prntdlgg.cpp | 1102 + wx28X/src/generic/progdlgg.cpp | 673 + wx28X/src/generic/propdlg.cpp | 226 + wx28X/src/generic/regiong.cpp | 1919 + wx28X/src/generic/renderg.cpp | 678 + wx28X/src/generic/sashwin.cpp | 708 + wx28X/src/generic/scrlwing.cpp | 1542 + wx28X/src/generic/selstore.cpp | 216 + wx28X/src/generic/spinctlg.cpp | 391 + wx28X/src/generic/splash.cpp | 202 + wx28X/src/generic/splitter.cpp | 1064 + wx28X/src/generic/srchctlg.cpp | 1216 + wx28X/src/generic/statline.cpp | 88 + wx28X/src/generic/statusbr.cpp | 488 + wx28X/src/generic/tabg.cpp | 1290 + wx28X/src/generic/textdlgg.cpp | 185 + wx28X/src/generic/timer.cpp | 283 + wx28X/src/generic/tipdlg.cpp | 347 + wx28X/src/generic/tipwin.cpp | 380 + wx28X/src/generic/toolbkg.cpp | 442 + wx28X/src/generic/treebkg.cpp | 794 + wx28X/src/generic/treectlg.cpp | 3823 + wx28X/src/generic/vlbox.cpp | 653 + wx28X/src/generic/vscroll.cpp | 519 + wx28X/src/generic/wizard.cpp | 882 + wx28X/src/html/chm.cpp | 914 + wx28X/src/html/descrip.mms | 96 + wx28X/src/html/helpctrl.cpp | 442 + wx28X/src/html/helpdata.cpp | 1077 + wx28X/src/html/helpdlg.cpp | 132 + wx28X/src/html/helpfrm.cpp | 241 + wx28X/src/html/helpwnd.cpp | 1774 + wx28X/src/html/htmlcell.cpp | 1609 + wx28X/src/html/htmlctrl/webkit/webkit.mm | 892 + wx28X/src/html/htmlfilt.cpp | 223 + wx28X/src/html/htmlpars.cpp | 961 + wx28X/src/html/htmltag.cpp | 521 + wx28X/src/html/htmlwin.cpp | 1683 + wx28X/src/html/htmprint.cpp | 728 + wx28X/src/html/m_dflist.cpp | 86 + wx28X/src/html/m_fonts.cpp | 322 + wx28X/src/html/m_hline.cpp | 111 + wx28X/src/html/m_image.cpp | 735 + wx28X/src/html/m_layout.cpp | 474 + wx28X/src/html/m_links.cpp | 107 + wx28X/src/html/m_list.cpp | 307 + wx28X/src/html/m_pre.cpp | 144 + wx28X/src/html/m_style.cpp | 46 + wx28X/src/html/m_tables.cpp | 799 + wx28X/src/html/winpars.cpp | 853 + wx28X/src/iodbc/AUTHORS | 4 + wx28X/src/iodbc/COPYING | 482 + wx28X/src/iodbc/Changes.log | 67 + wx28X/src/iodbc/IAFA-PACKAGE | 40 + wx28X/src/iodbc/INSTALL | 182 + wx28X/src/iodbc/NEWS | 8 + wx28X/src/iodbc/README | 187 + wx28X/src/iodbc/autoconfig | 230 + wx28X/src/iodbc/catalog.c | 987 + wx28X/src/iodbc/config.h | 100 + wx28X/src/iodbc/connect.c | 1241 + wx28X/src/iodbc/dlf.c | 612 + wx28X/src/iodbc/dlf.h | 55 + wx28X/src/iodbc/dlproc.c | 119 + wx28X/src/iodbc/dlproc.h | 55 + wx28X/src/iodbc/execute.c | 768 + wx28X/src/iodbc/fetch.c | 649 + wx28X/src/iodbc/hdbc.c | 811 + wx28X/src/iodbc/hdbc.h | 93 + wx28X/src/iodbc/henv.c | 89 + wx28X/src/iodbc/henv.ci | 117 + wx28X/src/iodbc/henv.h | 160 + wx28X/src/iodbc/herr.c | 378 + wx28X/src/iodbc/herr.ci | 124 + wx28X/src/iodbc/herr.h | 153 + wx28X/src/iodbc/hstmt.c | 600 + wx28X/src/iodbc/hstmt.h | 75 + wx28X/src/iodbc/info.c | 521 + wx28X/src/iodbc/iodbc.h | 66 + wx28X/src/iodbc/isql.h | 235 + wx28X/src/iodbc/isqlext.h | 1177 + wx28X/src/iodbc/itrace.c | 117 + wx28X/src/iodbc/itrace.h | 124 + wx28X/src/iodbc/misc.c | 413 + wx28X/src/iodbc/prepare.c | 525 + wx28X/src/iodbc/result.c | 523 + wx28X/src/iodbc/shrsub.exp | 64 + wx28X/src/jpeg/MAKEFILE.VA | 335 + wx28X/src/jpeg/README | 385 + wx28X/src/jpeg/ansi2knr.1 | 36 + wx28X/src/jpeg/ansi2knr.c | 693 + wx28X/src/jpeg/change.log | 217 + wx28X/src/jpeg/jcapimin.c | 280 + wx28X/src/jpeg/jcapistd.c | 161 + wx28X/src/jpeg/jccoefct.c | 449 + wx28X/src/jpeg/jccolor.c | 459 + wx28X/src/jpeg/jcdctmgr.c | 387 + wx28X/src/jpeg/jchuff.c | 909 + wx28X/src/jpeg/jchuff.h | 47 + wx28X/src/jpeg/jcinit.c | 72 + wx28X/src/jpeg/jcmainct.c | 293 + wx28X/src/jpeg/jcmarker.c | 664 + wx28X/src/jpeg/jcmaster.c | 590 + wx28X/src/jpeg/jcomapi.c | 106 + wx28X/src/jpeg/jconfig.h | 109 + wx28X/src/jpeg/jconfig.vc | 45 + wx28X/src/jpeg/jcparam.c | 610 + wx28X/src/jpeg/jcphuff.c | 833 + wx28X/src/jpeg/jcprepct.c | 354 + wx28X/src/jpeg/jcsample.c | 519 + wx28X/src/jpeg/jctrans.c | 402 + wx28X/src/jpeg/jdapimin.c | 395 + wx28X/src/jpeg/jdapistd.c | 275 + wx28X/src/jpeg/jdatadst.c | 151 + wx28X/src/jpeg/jdatasrc.c | 212 + wx28X/src/jpeg/jdcoefct.c | 745 + wx28X/src/jpeg/jdcolor.c | 410 + wx28X/src/jpeg/jdct.h | 176 + wx28X/src/jpeg/jddctmgr.c | 269 + wx28X/src/jpeg/jdhuff.c | 651 + wx28X/src/jpeg/jdhuff.h | 201 + wx28X/src/jpeg/jdinput.c | 385 + wx28X/src/jpeg/jdmainct.c | 529 + wx28X/src/jpeg/jdmarker.c | 1360 + wx28X/src/jpeg/jdmaster.c | 557 + wx28X/src/jpeg/jdmerge.c | 399 + wx28X/src/jpeg/jdphuff.c | 668 + wx28X/src/jpeg/jdpostct.c | 290 + wx28X/src/jpeg/jdsample.c | 478 + wx28X/src/jpeg/jdtrans.c | 143 + wx28X/src/jpeg/jerror.c | 252 + wx28X/src/jpeg/jerror.h | 291 + wx28X/src/jpeg/jfdctflt.c | 168 + wx28X/src/jpeg/jfdctfst.c | 224 + wx28X/src/jpeg/jfdctint.c | 283 + wx28X/src/jpeg/jidctflt.c | 242 + wx28X/src/jpeg/jidctfst.c | 368 + wx28X/src/jpeg/jidctint.c | 389 + wx28X/src/jpeg/jidctred.c | 398 + wx28X/src/jpeg/jinclude.h | 91 + wx28X/src/jpeg/jmemansi.c | 167 + wx28X/src/jpeg/jmemdos.c | 638 + wx28X/src/jpeg/jmemdosa.asm | 379 + wx28X/src/jpeg/jmemmac.c | 289 + wx28X/src/jpeg/jmemmgr.c | 1118 + wx28X/src/jpeg/jmemname.c | 276 + wx28X/src/jpeg/jmemnobs.c | 109 + wx28X/src/jpeg/jmemsys.h | 198 + wx28X/src/jpeg/jmorecfg.h | 420 + wx28X/src/jpeg/jpeg.dsp | 872 + wx28X/src/jpeg/jpegM8.xml | 3328 + wx28X/src/jpeg/jpeg_CW_Prefix.h | 6 + wx28X/src/jpeg/jpegint.h | 400 + wx28X/src/jpeg/jpeglib.h | 1096 + wx28X/src/jpeg/jpegtran.1 | 238 + wx28X/src/jpeg/jpegtran.c | 504 + wx28X/src/jpeg/jquant1.c | 856 + wx28X/src/jpeg/jquant2.c | 1310 + wx28X/src/jpeg/jutils.c | 179 + wx28X/src/jpeg/jversion.h | 14 + wx28X/src/jpeg/makefile.unx | 36 + wx28X/src/jpeg/makefile.vc | 201 + wx28X/src/makeb32.env | 173 + wx28X/src/makebcc.env | 34 + wx28X/src/makefile.va | 35 + wx28X/src/makefile.vc | 35 + wx28X/src/makeg95.env | 437 + wx28X/src/makelib.b32 | 32 + wx28X/src/makelib.bcc | 37 + wx28X/src/makelib.g95 | 24 + wx28X/src/makelib.vc | 49 + wx28X/src/makemsc.env | 72 + wx28X/src/makeprog.b32 | 118 + wx28X/src/makeprog.bcc | 35 + wx28X/src/makeprog.g95 | 32 + wx28X/src/makeprog.sl | 28 + wx28X/src/makeprog.va | 59 + wx28X/src/makeprog.vc | 79 + wx28X/src/makesl.env | 53 + wx28X/src/makeva.env | 200 + wx28X/src/makevc.env | 335 + wx28X/src/mingegcs.bat | 17 + wx28X/src/mingw32.bat | 16 + wx28X/src/msw/aboutdlg.cpp | 70 + wx28X/src/msw/accel.cpp | 160 + wx28X/src/msw/app.cpp | 809 + wx28X/src/msw/basemsw.cpp | 73 + wx28X/src/msw/bitmap.cpp | 1809 + wx28X/src/msw/bmpbuttn.cpp | 646 + wx28X/src/msw/brush.cpp | 327 + wx28X/src/msw/button.cpp | 890 + wx28X/src/msw/caret.cpp | 188 + wx28X/src/msw/checkbox.cpp | 588 + wx28X/src/msw/checklst.cpp | 546 + wx28X/src/msw/choice.cpp | 802 + wx28X/src/msw/clipbrd.cpp | 931 + wx28X/src/msw/colordlg.cpp | 224 + wx28X/src/msw/colour.cpp | 90 + wx28X/src/msw/combo.cpp | 920 + wx28X/src/msw/combobox.cpp | 808 + wx28X/src/msw/control.cpp | 483 + wx28X/src/msw/crashrpt.cpp | 383 + wx28X/src/msw/cursor.cpp | 407 + wx28X/src/msw/data.cpp | 18 + wx28X/src/msw/datectrl.cpp | 368 + wx28X/src/msw/dc.cpp | 2780 + wx28X/src/msw/dcclient.cpp | 357 + wx28X/src/msw/dcmemory.cpp | 194 + wx28X/src/msw/dcprint.cpp | 484 + wx28X/src/msw/dcscreen.cpp | 38 + wx28X/src/msw/dde.cpp | 1095 + wx28X/src/msw/debughlp.cpp | 767 + wx28X/src/msw/dialog.cpp | 497 + wx28X/src/msw/dialup.cpp | 1338 + wx28X/src/msw/dib.cpp | 814 + wx28X/src/msw/dir.cpp | 404 + wx28X/src/msw/dirdlg.cpp | 251 + wx28X/src/msw/display.cpp | 1047 + wx28X/src/msw/dlmsw.cpp | 339 + wx28X/src/msw/dragimag.cpp | 458 + wx28X/src/msw/enhmeta.cpp | 527 + wx28X/src/msw/evtloop.cpp | 296 + wx28X/src/msw/fdrepdlg.cpp | 546 + wx28X/src/msw/filedlg.cpp | 568 + wx28X/src/msw/font.cpp | 1122 + wx28X/src/msw/fontdlg.cpp | 131 + wx28X/src/msw/fontenum.cpp | 292 + wx28X/src/msw/fontutil.cpp | 294 + wx28X/src/msw/frame.cpp | 1163 + wx28X/src/msw/gauge95.cpp | 280 + wx28X/src/msw/gdiimage.cpp | 609 + wx28X/src/msw/gdiobj.cpp | 60 + wx28X/src/msw/glcanvas.cpp | 665 + wx28X/src/msw/graphics.cpp | 1680 + wx28X/src/msw/gsocket.cpp | 1569 + wx28X/src/msw/gsockmsw.cpp | 487 + wx28X/src/msw/helpbest.cpp | 103 + wx28X/src/msw/helpchm.cpp | 252 + wx28X/src/msw/helpwin.cpp | 126 + wx28X/src/msw/icon.cpp | 158 + wx28X/src/msw/imaglist.cpp | 402 + wx28X/src/msw/iniconf.cpp | 457 + wx28X/src/msw/joystick.cpp | 627 + wx28X/src/msw/listbox.cpp | 878 + wx28X/src/msw/listctrl.cpp | 3237 + wx28X/src/msw/main.cpp | 409 + wx28X/src/msw/makebase.b32 | 456 + wx28X/src/msw/makebase.vc | 264 + wx28X/src/msw/makefile.mic | 356 + wx28X/src/msw/makefile.sl | 914 + wx28X/src/msw/mdi.cpp | 1500 + wx28X/src/msw/mediactrl.cpp | 4172 + wx28X/src/msw/mediactrl_am.cpp | 2273 + wx28X/src/msw/mediactrl_qt.cpp | 1312 + wx28X/src/msw/mediactrl_wmp10.cpp | 1516 + wx28X/src/msw/menu.cpp | 1397 + wx28X/src/msw/menuitem.cpp | 446 + wx28X/src/msw/metafile.cpp | 533 + wx28X/src/msw/microwin.c | 365 + wx28X/src/msw/mimetype.cpp | 850 + wx28X/src/msw/minifram.cpp | 25 + wx28X/src/msw/msgdlg.cpp | 154 + wx28X/src/msw/mslu.cpp | 248 + wx28X/src/msw/nativdlg.cpp | 330 + wx28X/src/msw/notebook.cpp | 1454 + wx28X/src/msw/ole/access.cpp | 2014 + wx28X/src/msw/ole/activex.cpp | 1158 + wx28X/src/msw/ole/automtn.cpp | 969 + wx28X/src/msw/ole/dataobj.cpp | 1343 + wx28X/src/msw/ole/dropsrc.cpp | 248 + wx28X/src/msw/ole/droptgt.cpp | 575 + wx28X/src/msw/ole/oleutils.cpp | 322 + wx28X/src/msw/ole/uuid.cpp | 184 + wx28X/src/msw/ownerdrw.cpp | 487 + wx28X/src/msw/palette.cpp | 164 + wx28X/src/msw/pen.cpp | 387 + wx28X/src/msw/penwin.cpp | 114 + wx28X/src/msw/popupwin.cpp | 113 + wx28X/src/msw/power.cpp | 112 + wx28X/src/msw/printdlg.cpp | 1175 + wx28X/src/msw/printwin.cpp | 447 + wx28X/src/msw/radiobox.cpp | 886 + wx28X/src/msw/radiobut.cpp | 349 + wx28X/src/msw/regconf.cpp | 731 + wx28X/src/msw/region.cpp | 468 + wx28X/src/msw/registry.cpp | 1428 + wx28X/src/msw/renderer.cpp | 709 + wx28X/src/msw/salford.lnk | 152 + wx28X/src/msw/scrolbar.cpp | 342 + wx28X/src/msw/settings.cpp | 498 + wx28X/src/msw/slider95.cpp | 686 + wx28X/src/msw/snglinst.cpp | 130 + wx28X/src/msw/sound.cpp | 209 + wx28X/src/msw/spinbutt.cpp | 340 + wx28X/src/msw/spinctrl.cpp | 720 + wx28X/src/msw/stackwalk.cpp | 414 + wx28X/src/msw/statbmp.cpp | 345 + wx28X/src/msw/statbox.cpp | 570 + wx28X/src/msw/statbr95.cpp | 417 + wx28X/src/msw/statline.cpp | 131 + wx28X/src/msw/stattext.cpp | 222 + wx28X/src/msw/stdpaths.cpp | 344 + wx28X/src/msw/tabctrl.cpp | 432 + wx28X/src/msw/taskbar.cpp | 327 + wx28X/src/msw/tbar95.cpp | 1848 + wx28X/src/msw/textctrl.cpp | 2967 + wx28X/src/msw/tglbtn.cpp | 170 + wx28X/src/msw/thread.cpp | 1408 + wx28X/src/msw/timer.cpp | 262 + wx28X/src/msw/tooltip.cpp | 464 + wx28X/src/msw/toplevel.cpp | 1287 + wx28X/src/msw/treectrl.cpp | 3161 + wx28X/src/msw/urlmsw.cpp | 249 + wx28X/src/msw/utils.cpp | 1576 + wx28X/src/msw/utilsexc.cpp | 1003 + wx28X/src/msw/utilsgui.cpp | 503 + wx28X/src/msw/uxtheme.cpp | 177 + wx28X/src/msw/version.rc | 62 + wx28X/src/msw/volume.cpp | 608 + wx28X/src/msw/wince/checklst.cpp | 425 + wx28X/src/msw/wince/choicece.cpp | 588 + wx28X/src/msw/wince/clean_vcp.py | 49 + wx28X/src/msw/wince/crt.cpp | 72 + wx28X/src/msw/wince/filedlgwce.cpp | 133 + wx28X/src/msw/wince/filefnwce.cpp | 211 + wx28X/src/msw/wince/helpwce.cpp | 123 + wx28X/src/msw/wince/menuce.cpp | 277 + wx28X/src/msw/wince/net.cpp | 243 + wx28X/src/msw/wince/tbarwce.cpp | 655 + wx28X/src/msw/wince/textctrlce.cpp | 1214 + wx28X/src/msw/wince/time.cpp | 762 + wx28X/src/msw/window.cpp | 6891 + wx28X/src/msw/winestub.c | 45 + wx28X/src/ntwxwin.mak | 3 + wx28X/src/png/ANNOUNCE | 29 + wx28X/src/png/CHANGES | 1373 + wx28X/src/png/INSTALL | 167 + wx28X/src/png/KNOWNBUG | 11 + wx28X/src/png/LICENSE | 109 + wx28X/src/png/MAKEFILE.VA | 139 + wx28X/src/png/README | 260 + wx28X/src/png/TODO | 24 + wx28X/src/png/Y2KINFO | 55 + wx28X/src/png/ansi2knr.1 | 36 + wx28X/src/png/ansi2knr.c | 695 + wx28X/src/png/configure | 13 + wx28X/src/png/example.c | 808 + wx28X/src/png/libpng.3 | 4016 + wx28X/src/png/libpng.txt | 2958 + wx28X/src/png/libpngpf.3 | 1096 + wx28X/src/png/makefile.unx | 30 + wx28X/src/png/makefile.vc | 31 + wx28X/src/png/png.5 | 74 + wx28X/src/png/png.c | 826 + wx28X/src/png/png.dsp | 160 + wx28X/src/png/png.h | 3364 + wx28X/src/png/pngM8.xml | 2760 + wx28X/src/png/pngasmrd.h | 11 + wx28X/src/png/pngbar.jpg | Bin 0 -> 2498 bytes wx28X/src/png/pngbar.png | Bin 0 -> 2399 bytes wx28X/src/png/pngconf.h | 1394 + wx28X/src/png/pngerror.c | 295 + wx28X/src/png/pnggccrd.c | 5408 + wx28X/src/png/pngget.c | 934 + wx28X/src/png/pngmem.c | 595 + wx28X/src/png/pngnow.png | Bin 0 -> 2069 bytes wx28X/src/png/pngpread.c | 1573 + wx28X/src/png/pngread.c | 1453 + wx28X/src/png/pngrio.c | 161 + wx28X/src/png/pngrtran.c | 4177 + wx28X/src/png/pngrutil.c | 3124 + wx28X/src/png/pngset.c | 1219 + wx28X/src/png/pngtest.c | 1554 + wx28X/src/png/pngtest.png | Bin 0 -> 8574 bytes wx28X/src/png/pngtrans.c | 644 + wx28X/src/png/pngvcrd.c | 3903 + wx28X/src/png/pngwio.c | 228 + wx28X/src/png/pngwrite.c | 1464 + wx28X/src/png/pngwtran.c | 563 + wx28X/src/png/pngwutil.c | 2726 + wx28X/src/png/projects/beos/x86-shared.proj | Bin 0 -> 7699 bytes wx28X/src/png/projects/beos/x86-shared.txt | 22 + wx28X/src/png/projects/beos/x86-static.proj | Bin 0 -> 7699 bytes wx28X/src/png/projects/beos/x86-static.txt | 22 + wx28X/src/png/projects/cbuilder5/libpng.bpf | 22 + wx28X/src/png/projects/cbuilder5/libpng.bpg | 25 + wx28X/src/png/projects/cbuilder5/libpng.bpr | 157 + wx28X/src/png/projects/cbuilder5/libpng.cpp | 29 + .../png/projects/cbuilder5/libpng.readme.txt | 25 + .../src/png/projects/cbuilder5/libpngstat.bpf | 22 + .../src/png/projects/cbuilder5/libpngstat.bpr | 109 + .../png/projects/cbuilder5/zlib.readme.txt | 14 + wx28X/src/png/projects/netware.txt | 6 + wx28X/src/png/projects/visualc6/README.txt | 64 + wx28X/src/png/projects/visualc6/libpng.dsp | 507 + wx28X/src/png/projects/visualc6/pngtest.dsp | 314 + wx28X/src/png/projects/wince.txt | 6 + wx28X/src/png/scripts/SCOPTIONS.ppc | 7 + wx28X/src/png/scripts/descrip.mms | 52 + wx28X/src/png/scripts/libpng-config-body.in | 96 + wx28X/src/png/scripts/libpng-config-head.in | 21 + wx28X/src/png/scripts/libpng.icc | 44 + wx28X/src/png/scripts/libpng.pc.in | 11 + wx28X/src/png/scripts/makefile.32sunu | 235 + wx28X/src/png/scripts/makefile.64sunu | 236 + wx28X/src/png/scripts/makefile.acorn | 51 + wx28X/src/png/scripts/makefile.aix | 111 + wx28X/src/png/scripts/makefile.amiga | 48 + wx28X/src/png/scripts/makefile.atari | 51 + wx28X/src/png/scripts/makefile.bc32 | 151 + wx28X/src/png/scripts/makefile.beos | 210 + wx28X/src/png/scripts/makefile.bor | 162 + wx28X/src/png/scripts/makefile.cygwin | 315 + wx28X/src/png/scripts/makefile.darwin | 216 + wx28X/src/png/scripts/makefile.dec | 196 + wx28X/src/png/scripts/makefile.dj2 | 55 + wx28X/src/png/scripts/makefile.freebsd | 48 + wx28X/src/png/scripts/makefile.gcc | 66 + wx28X/src/png/scripts/makefile.gcmmx | 260 + wx28X/src/png/scripts/makefile.hp64 | 216 + wx28X/src/png/scripts/makefile.hpgcc | 228 + wx28X/src/png/scripts/makefile.hpux | 213 + wx28X/src/png/scripts/makefile.ibmc | 71 + wx28X/src/png/scripts/makefile.intel | 114 + wx28X/src/png/scripts/makefile.knr | 99 + wx28X/src/png/scripts/makefile.linux | 234 + wx28X/src/png/scripts/makefile.macosx | 190 + wx28X/src/png/scripts/makefile.mips | 83 + wx28X/src/png/scripts/makefile.msc | 86 + wx28X/src/png/scripts/makefile.ne12bsd | 44 + wx28X/src/png/scripts/makefile.netbsd | 44 + wx28X/src/png/scripts/makefile.openbsd | 72 + wx28X/src/png/scripts/makefile.os2 | 69 + wx28X/src/png/scripts/makefile.sco | 212 + wx28X/src/png/scripts/makefile.sggcc | 224 + wx28X/src/png/scripts/makefile.sgi | 230 + wx28X/src/png/scripts/makefile.so9 | 234 + wx28X/src/png/scripts/makefile.solaris | 231 + wx28X/src/png/scripts/makefile.std | 89 + wx28X/src/png/scripts/makefile.sunos | 93 + wx28X/src/png/scripts/makefile.tc3 | 89 + wx28X/src/png/scripts/makefile.vcawin32 | 103 + wx28X/src/png/scripts/makefile.vcwin32 | 99 + wx28X/src/png/scripts/makefile.watcom | 109 + wx28X/src/png/scripts/makevms.com | 144 + wx28X/src/png/scripts/pngos2.def | 248 + wx28X/src/png/scripts/pngw32.def | 227 + wx28X/src/png/scripts/pngw32.rc | 95 + wx28X/src/png/scripts/smakefile.ppc | 30 + wx28X/src/regex/COPYRIGHT | 86 + wx28X/src/regex/README | 41 + wx28X/src/regex/re_syntax.n | 970 + wx28X/src/regex/regc_color.c | 778 + wx28X/src/regex/regc_cvec.c | 208 + wx28X/src/regex/regc_lex.c | 1061 + wx28X/src/regex/regc_locale.c | 1178 + wx28X/src/regex/regc_nfa.c | 1582 + wx28X/src/regex/regcomp.c | 2179 + wx28X/src/regex/regcustom.h | 126 + wx28X/src/regex/rege_dfa.c | 683 + wx28X/src/regex/regerror.c | 109 + wx28X/src/regex/regerrs.h | 18 + wx28X/src/regex/regex.dsp | 378 + wx28X/src/regex/regex.h | 337 + wx28X/src/regex/regexM8.xml | 2418 + wx28X/src/regex/regexec.c | 1038 + wx28X/src/regex/regfree.c | 53 + wx28X/src/regex/regfronts.c | 83 + wx28X/src/regex/regguts.h | 416 + wx28X/src/regex/splice.sh | 69 + wx28X/src/regex/tclUniData.c | 904 + wx28X/src/richtext/richtextbuffer.cpp | 9757 + wx28X/src/richtext/richtextbulletspage.cpp | 964 + wx28X/src/richtext/richtextctrl.cpp | 3706 + wx28X/src/richtext/richtextdialogs.pjd | 14780 ++ wx28X/src/richtext/richtextfontpage.cpp | 862 + wx28X/src/richtext/richtextformatdlg.cpp | 659 + wx28X/src/richtext/richtexthtml.cpp | 660 + wx28X/src/richtext/richtextindentspage.cpp | 727 + wx28X/src/richtext/richtextliststylepage.cpp | 1361 + wx28X/src/richtext/richtextprint.cpp | 707 + wx28X/src/richtext/richtextstyledlg.cpp | 885 + wx28X/src/richtext/richtextstylepage.cpp | 305 + wx28X/src/richtext/richtextstyles.cpp | 1265 + wx28X/src/richtext/richtextsymboldlg.cpp | 1308 + wx28X/src/richtext/richtexttabspage.cpp | 361 + wx28X/src/richtext/richtextxml.cpp | 1358 + wx28X/src/tiff/COPYRIGHT | 21 + wx28X/src/tiff/MAKEFILE.VA | 230 + wx28X/src/tiff/Makefile.lcc | 129 + wx28X/src/tiff/README | 61 + wx28X/src/tiff/TODO | 7 + wx28X/src/tiff/VERSION | 1 + wx28X/src/tiff/fax3sm_winnt.c | 1046 + wx28X/src/tiff/libtiff.def | 102 + wx28X/src/tiff/makefile.vc | 93 + wx28X/src/tiff/mkg3states.c | 436 + wx28X/src/tiff/mkspans.c | 72 + wx28X/src/tiff/mkversion.c | 148 + wx28X/src/tiff/port.h | 61 + wx28X/src/tiff/t4.h | 285 + wx28X/src/tiff/tif_acorn.c | 519 + wx28X/src/tiff/tif_apple.c | 274 + wx28X/src/tiff/tif_atari.c | 243 + wx28X/src/tiff/tif_aux.c | 248 + wx28X/src/tiff/tif_close.c | 80 + wx28X/src/tiff/tif_codec.c | 150 + wx28X/src/tiff/tif_color.c | 268 + wx28X/src/tiff/tif_compress.c | 235 + wx28X/src/tiff/tif_dir.c | 1435 + wx28X/src/tiff/tif_dir.h | 267 + wx28X/src/tiff/tif_dirinfo.c | 486 + wx28X/src/tiff/tif_dirread.c | 1518 + wx28X/src/tiff/tif_dirwrite.c | 1256 + wx28X/src/tiff/tif_dumpmode.c | 118 + wx28X/src/tiff/tif_error.c | 49 + wx28X/src/tiff/tif_extension.c | 112 + wx28X/src/tiff/tif_fax3.c | 1527 + wx28X/src/tiff/tif_fax3.h | 525 + wx28X/src/tiff/tif_fax3sm.c | 1046 + wx28X/src/tiff/tif_flush.c | 67 + wx28X/src/tiff/tif_getimage.c | 2585 + wx28X/src/tiff/tif_jpeg.c | 1673 + wx28X/src/tiff/tif_luv.c | 1597 + wx28X/src/tiff/tif_lzw.c | 745 + wx28X/src/tiff/tif_msdos.c | 179 + wx28X/src/tiff/tif_next.c | 142 + wx28X/src/tiff/tif_ojpeg.c | 2630 + wx28X/src/tiff/tif_open.c | 495 + wx28X/src/tiff/tif_os2.c | 338 + wx28X/src/tiff/tif_packbits.c | 300 + wx28X/src/tiff/tif_pixarlog.c | 1328 + wx28X/src/tiff/tif_predict.c | 464 + wx28X/src/tiff/tif_predict.h | 61 + wx28X/src/tiff/tif_print.c | 613 + wx28X/src/tiff/tif_read.c | 637 + wx28X/src/tiff/tif_strip.c | 254 + wx28X/src/tiff/tif_swab.c | 217 + wx28X/src/tiff/tif_thunder.c | 156 + wx28X/src/tiff/tif_tile.c | 257 + wx28X/src/tiff/tif_unix.c | 228 + wx28X/src/tiff/tif_version.c | 33 + wx28X/src/tiff/tif_vms.c | 588 + wx28X/src/tiff/tif_warning.c | 49 + wx28X/src/tiff/tif_win3.c | 225 + wx28X/src/tiff/tif_win32.c | 329 + wx28X/src/tiff/tif_write.c | 703 + wx28X/src/tiff/tif_zip.c | 368 + wx28X/src/tiff/tiff.dsp | 696 + wx28X/src/tiff/tiff.h | 482 + wx28X/src/tiff/tiffM8.xml | 3330 + wx28X/src/tiff/tiff_CW_Prefix.h | 12 + wx28X/src/tiff/tiffcomp.h | 225 + wx28X/src/tiff/tiffconf.h | 153 + wx28X/src/tiff/tiffio.h | 477 + wx28X/src/tiff/tiffiop.h | 289 + wx28X/src/tiff/tiffvers.h | 9 + wx28X/src/tiff/uvcode.h | 173 + wx28X/src/univ/bmpbuttn.cpp | 155 + wx28X/src/univ/button.cpp | 466 + wx28X/src/univ/checkbox.cpp | 367 + wx28X/src/univ/checklst.cpp | 303 + wx28X/src/univ/choice.cpp | 94 + wx28X/src/univ/colschem.cpp | 102 + wx28X/src/univ/combobox.cpp | 559 + wx28X/src/univ/control.cpp | 140 + wx28X/src/univ/ctrlrend.cpp | 532 + wx28X/src/univ/descrip.mms | 150 + wx28X/src/univ/dialog.cpp | 222 + wx28X/src/univ/framuniv.cpp | 328 + wx28X/src/univ/gauge.cpp | 128 + wx28X/src/univ/inpcons.cpp | 114 + wx28X/src/univ/inphand.cpp | 61 + wx28X/src/univ/listbox.cpp | 1579 + wx28X/src/univ/menu.cpp | 2605 + wx28X/src/univ/notebook.cpp | 1463 + wx28X/src/univ/radiobox.cpp | 526 + wx28X/src/univ/radiobut.cpp | 179 + wx28X/src/univ/scrarrow.cpp | 301 + wx28X/src/univ/scrolbar.cpp | 1207 + wx28X/src/univ/scrthumb.cpp | 291 + wx28X/src/univ/slider.cpp | 1101 + wx28X/src/univ/spinbutt.cpp | 436 + wx28X/src/univ/statbmp.cpp | 108 + wx28X/src/univ/statbox.cpp | 121 + wx28X/src/univ/statline.cpp | 85 + wx28X/src/univ/stattext.cpp | 94 + wx28X/src/univ/statusbr.cpp | 326 + wx28X/src/univ/stdrend.cpp | 1267 + wx28X/src/univ/textctrl.cpp | 5011 + wx28X/src/univ/tglbtn.cpp | 98 + wx28X/src/univ/theme.cpp | 204 + wx28X/src/univ/themes/gtk.cpp | 2739 + wx28X/src/univ/themes/metal.cpp | 548 + wx28X/src/univ/themes/mono.cpp | 1104 + wx28X/src/univ/themes/win32.cpp | 3779 + wx28X/src/univ/toolbar.cpp | 967 + wx28X/src/univ/topluniv.cpp | 961 + wx28X/src/univ/winuniv.cpp | 1449 + wx28X/src/unix/baseunix.cpp | 83 + wx28X/src/unix/descrip.mms | 120 + wx28X/src/unix/dialup.cpp | 828 + wx28X/src/unix/dir.cpp | 334 + wx28X/src/unix/displayx11.cpp | 426 + wx28X/src/unix/dlunix.cpp | 461 + wx28X/src/unix/fontenum.cpp | 362 + wx28X/src/unix/fontutil.cpp | 1441 + wx28X/src/unix/gsocket.cpp | 2299 + wx28X/src/unix/joystick.cpp | 496 + wx28X/src/unix/mediactrl.cpp | 1607 + wx28X/src/unix/mimetype.cpp | 3011 + wx28X/src/unix/snglinst.cpp | 398 + wx28X/src/unix/sound.cpp | 722 + wx28X/src/unix/sound_sdl.cpp | 335 + wx28X/src/unix/stackwalk.cpp | 309 + wx28X/src/unix/stdpaths.cpp | 220 + wx28X/src/unix/taskbarx11.cpp | 346 + wx28X/src/unix/threadpsx.cpp | 1746 + wx28X/src/unix/utilsunx.cpp | 1362 + wx28X/src/unix/utilsx11.cpp | 847 + wx28X/src/version.mak | 24 + wx28X/src/wxJpeg.icc | 59 + wx28X/src/wxPng.icc | 28 + wx28X/src/wxTiff.icc | 47 + wx28X/src/wxWin.icc | 281 + wx28X/src/wxWindowsClassicM8.xml | 39547 ++++ wx28X/src/wxWindowsM8.xml | 66645 ++++++ wx28X/src/wxWindowsW7.xml | 20334 ++ wx28X/src/wxXpm.icc | 32 + wx28X/src/wxZlib.icc | 26 + wx28X/src/xml/descrip.mms | 68 + wx28X/src/xml/xml.cpp | 960 + wx28X/src/xrc/descrip.mms | 144 + wx28X/src/xrc/xh_animatctrl.cpp | 57 + wx28X/src/xrc/xh_bmp.cpp | 64 + wx28X/src/xrc/xh_bmpbt.cpp | 72 + wx28X/src/xrc/xh_bmpcbox.cpp | 103 + wx28X/src/xrc/xh_bttn.cpp | 63 + wx28X/src/xrc/xh_cald.cpp | 67 + wx28X/src/xrc/xh_chckb.cpp | 61 + wx28X/src/xrc/xh_chckl.cpp | 121 + wx28X/src/xrc/xh_choic.cpp | 87 + wx28X/src/xrc/xh_choicbk.cpp | 127 + wx28X/src/xrc/xh_clrpicker.cpp | 55 + wx28X/src/xrc/xh_collpane.cpp | 101 + wx28X/src/xrc/xh_combo.cpp | 94 + wx28X/src/xrc/xh_datectrl.cpp | 57 + wx28X/src/xrc/xh_dirpicker.cpp | 57 + wx28X/src/xrc/xh_dlg.cpp | 93 + wx28X/src/xrc/xh_filepicker.cpp | 60 + wx28X/src/xrc/xh_fontpicker.cpp | 60 + wx28X/src/xrc/xh_frame.cpp | 99 + wx28X/src/xrc/xh_gauge.cpp | 75 + wx28X/src/xrc/xh_gdctl.cpp | 64 + wx28X/src/xrc/xh_grid.cpp | 51 + wx28X/src/xrc/xh_html.cpp | 81 + wx28X/src/xrc/xh_htmllbox.cpp | 86 + wx28X/src/xrc/xh_hyperlink.cpp | 88 + wx28X/src/xrc/xh_listb.cpp | 94 + wx28X/src/xrc/xh_listbk.cpp | 127 + wx28X/src/xrc/xh_listc.cpp | 77 + wx28X/src/xrc/xh_mdi.cpp | 139 + wx28X/src/xrc/xh_menu.cpp | 162 + wx28X/src/xrc/xh_notbk.cpp | 133 + wx28X/src/xrc/xh_odcombo.cpp | 117 + wx28X/src/xrc/xh_panel.cpp | 61 + wx28X/src/xrc/xh_propdlg.cpp | 150 + wx28X/src/xrc/xh_radbt.cpp | 66 + wx28X/src/xrc/xh_radbx.cpp | 142 + wx28X/src/xrc/xh_richtext.cpp | 63 + wx28X/src/xrc/xh_scrol.cpp | 63 + wx28X/src/xrc/xh_scwin.cpp | 72 + wx28X/src/xrc/xh_sizer.cpp | 455 + wx28X/src/xrc/xh_slidr.cpp | 94 + wx28X/src/xrc/xh_spin.cpp | 104 + wx28X/src/xrc/xh_split.cpp | 113 + wx28X/src/xrc/xh_statbar.cpp | 108 + wx28X/src/xrc/xh_stbmp.cpp | 55 + wx28X/src/xrc/xh_stbox.cpp | 55 + wx28X/src/xrc/xh_stlin.cpp | 53 + wx28X/src/xrc/xh_sttxt.cpp | 63 + wx28X/src/xrc/xh_text.cpp | 79 + wx28X/src/xrc/xh_tglbtn.cpp | 57 + wx28X/src/xrc/xh_toolb.cpp | 181 + wx28X/src/xrc/xh_tree.cpp | 66 + wx28X/src/xrc/xh_treebk.cpp | 141 + wx28X/src/xrc/xh_unkwn.cpp | 109 + wx28X/src/xrc/xh_wizrd.cpp | 104 + wx28X/src/xrc/xmlres.cpp | 1789 + wx28X/src/xrc/xmlrsall.cpp | 187 + wx28X/src/zlib/ChangeLog | 855 + wx28X/src/zlib/FAQ | 339 + wx28X/src/zlib/INDEX | 51 + wx28X/src/zlib/README | 125 + wx28X/src/zlib/adler32.c | 149 + wx28X/src/zlib/algorithm.txt | 209 + wx28X/src/zlib/compress.c | 79 + wx28X/src/zlib/crc32.c | 423 + wx28X/src/zlib/crc32.h | 441 + wx28X/src/zlib/deflate.c | 1736 + wx28X/src/zlib/deflate.h | 331 + wx28X/src/zlib/example.c | 565 + wx28X/src/zlib/gzio.c | 1026 + wx28X/src/zlib/infback.c | 623 + wx28X/src/zlib/inffast.c | 318 + wx28X/src/zlib/inffast.h | 11 + wx28X/src/zlib/inffixed.h | 94 + wx28X/src/zlib/inflate.c | 1368 + wx28X/src/zlib/inflate.h | 115 + wx28X/src/zlib/inftrees.c | 329 + wx28X/src/zlib/inftrees.h | 55 + wx28X/src/zlib/minigzip.c | 322 + wx28X/src/zlib/trees.c | 1219 + wx28X/src/zlib/trees.h | 128 + wx28X/src/zlib/uncompr.c | 61 + wx28X/src/zlib/zconf.h | 332 + wx28X/src/zlib/zlib.3 | 159 + wx28X/src/zlib/zlib.dsp | 137 + wx28X/src/zlib/zlib.h | 1357 + wx28X/src/zlib/zlibM8.xml | 2236 + wx28X/src/zlib/zutil.c | 318 + wx28X/src/zlib/zutil.h | 269 + wx28X/unins000.dat | Bin 0 -> 350231 bytes wx28X/unins000.exe | Bin 0 -> 673610 bytes wx28X/utils/HelpGen/Makefile.in | 7 + wx28X/utils/HelpGen/src/HelpGen.cpp | 2383 + wx28X/utils/HelpGen/src/HelpGenM5.mcp | Bin 0 -> 188867 bytes wx28X/utils/HelpGen/src/Makefile.in | 139 + wx28X/utils/HelpGen/src/cjparser.cpp | 2289 + wx28X/utils/HelpGen/src/cjparser.h | 130 + wx28X/utils/HelpGen/src/docripper.cpp | 559 + wx28X/utils/HelpGen/src/docripper.h | 157 + wx28X/utils/HelpGen/src/helpgen.bkl | 23 + wx28X/utils/HelpGen/src/helpgen.dsp | 471 + wx28X/utils/HelpGen/src/ifcontext.cpp | 290 + wx28X/utils/HelpGen/src/ifcontext.h | 101 + wx28X/utils/HelpGen/src/makefile.bcc | 229 + wx28X/utils/HelpGen/src/makefile.dmc | 70 + wx28X/utils/HelpGen/src/makefile.dms | 218 + wx28X/utils/HelpGen/src/makefile.gcc | 226 + wx28X/utils/HelpGen/src/makefile.vc | 312 + wx28X/utils/HelpGen/src/makefile.wat | 290 + wx28X/utils/HelpGen/src/markup.cpp | 46 + wx28X/utils/HelpGen/src/markup.h | 51 + wx28X/utils/HelpGen/src/ripper_main.cpp | 157 + wx28X/utils/HelpGen/src/scriptbinder.cpp | 617 + wx28X/utils/HelpGen/src/scriptbinder.h | 373 + wx28X/utils/HelpGen/src/sourcepainter.cpp | 679 + wx28X/utils/HelpGen/src/sourcepainter.h | 101 + wx28X/utils/HelpGen/src/srcparser.cpp | 703 + wx28X/utils/HelpGen/src/srcparser.h | 769 + wx28X/utils/HelpGen/src/wx_extra_imps.cpp | 64 + wx28X/utils/HelpGen/src/wxstlac.h | 673 + wx28X/utils/HelpGen/src/wxstllst.h | 561 + wx28X/utils/HelpGen/src/wxstlvec.h | 783 + wx28X/utils/HelpHTML/README | 58 + wx28X/utils/HelpHTML/html2wxhelp | 44 + wx28X/utils/HelpHTML/striphelpids | 17 + wx28X/utils/Makefile.in | 83 + wx28X/utils/emulator/Makefile.in | 7 + wx28X/utils/emulator/artwork/ipaq01.png | Bin 0 -> 128835 bytes wx28X/utils/emulator/artwork/ipaq02.png | Bin 0 -> 70980 bytes wx28X/utils/emulator/src/Makefile.in | 176 + wx28X/utils/emulator/src/bluegradient.jpg | Bin 0 -> 2477 bytes wx28X/utils/emulator/src/default.wxe | 33 + wx28X/utils/emulator/src/emulator.bkl | 25 + wx28X/utils/emulator/src/emulator.bmp | Bin 0 -> 630 bytes wx28X/utils/emulator/src/emulator.cpp | 607 + wx28X/utils/emulator/src/emulator.dsp | 480 + wx28X/utils/emulator/src/emulator.h | 164 + wx28X/utils/emulator/src/emulator.ico | Bin 0 -> 3638 bytes wx28X/utils/emulator/src/emulator.rc | 3 + wx28X/utils/emulator/src/emulator.vcp | 1826 + wx28X/utils/emulator/src/emulator.vcw | 17 + wx28X/utils/emulator/src/emulator.xpm | 52 + wx28X/utils/emulator/src/ipaq.wxe | 33 + wx28X/utils/emulator/src/ipaq01.jpg | Bin 0 -> 20022 bytes wx28X/utils/emulator/src/makefile.bcc | 257 + wx28X/utils/emulator/src/makefile.dmc | 49 + wx28X/utils/emulator/src/makefile.dms | 219 + wx28X/utils/emulator/src/makefile.gcc | 257 + wx28X/utils/emulator/src/makefile.vc | 363 + wx28X/utils/emulator/src/makefile.wat | 286 + wx28X/utils/emulator/src/mondrian.ico | Bin 0 -> 766 bytes wx28X/utils/emulator/src/mondrian.xpm | 44 + wx28X/utils/helpview/Makefile.in | 7 + wx28X/utils/helpview/src/HelpviewM7.mcp | Bin 0 -> 605959 bytes wx28X/utils/helpview/src/Makefile.in | 230 + wx28X/utils/helpview/src/bitmaps/helpback.xpm | 21 + wx28X/utils/helpview/src/bitmaps/helpbook.xpm | 25 + wx28X/utils/helpview/src/bitmaps/helpdown.xpm | 21 + .../helpview/src/bitmaps/helpforward.xpm | 21 + wx28X/utils/helpview/src/bitmaps/helpicon.xpm | 41 + wx28X/utils/helpview/src/bitmaps/helpopen.xpm | 57 + .../helpview/src/bitmaps/helpoptions.xpm | 21 + wx28X/utils/helpview/src/bitmaps/helppage.xpm | 23 + .../helpview/src/bitmaps/helpsidepanel.xpm | 35 + wx28X/utils/helpview/src/bitmaps/helpup.xpm | 21 + .../helpview/src/bitmaps/helpuplevel.xpm | 21 + wx28X/utils/helpview/src/client.cpp | 297 + wx28X/utils/helpview/src/client.dsp | 167 + wx28X/utils/helpview/src/client.h | 86 + wx28X/utils/helpview/src/client.rc | 1 + wx28X/utils/helpview/src/helpview-docicon.r | 138 + wx28X/utils/helpview/src/helpview-icon.r | 138 + wx28X/utils/helpview/src/helpview.bkl | 31 + wx28X/utils/helpview/src/helpview.cpp | 525 + wx28X/utils/helpview/src/helpview.dsp | 480 + wx28X/utils/helpview/src/helpview.h | 94 + wx28X/utils/helpview/src/helpview.ico | Bin 0 -> 1078 bytes wx28X/utils/helpview/src/helpview.r | 37 + wx28X/utils/helpview/src/helpview.rc | 5 + wx28X/utils/helpview/src/helpview.vcp | 1826 + wx28X/utils/helpview/src/helpview.vcw | 17 + wx28X/utils/helpview/src/helpviewM5.xml | 3835 + wx28X/utils/helpview/src/makefile.bcc | 265 + wx28X/utils/helpview/src/makefile.dmc | 49 + wx28X/utils/helpview/src/makefile.dms | 227 + wx28X/utils/helpview/src/makefile.gcc | 265 + wx28X/utils/helpview/src/makefile.vc | 371 + wx28X/utils/helpview/src/makefile.wat | 296 + wx28X/utils/helpview/src/readme.txt | 35 + wx28X/utils/helpview/src/remhelp.cpp | 405 + wx28X/utils/helpview/src/remhelp.h | 93 + wx28X/utils/helpview/src/test.zip | Bin 0 -> 3292 bytes wx28X/utils/hhp2cached/Makefile.in | 180 + wx28X/utils/hhp2cached/hhp2cached.bkl | 25 + wx28X/utils/hhp2cached/hhp2cached.cpp | 42 + wx28X/utils/hhp2cached/hhp2cached.dsp | 480 + wx28X/utils/hhp2cached/hhp2cached.rc | 1 + wx28X/utils/hhp2cached/hhp2cached.vcp | 1826 + wx28X/utils/hhp2cached/hhp2cached.vcw | 17 + wx28X/utils/hhp2cached/makefile.bcc | 257 + wx28X/utils/hhp2cached/makefile.dmc | 45 + wx28X/utils/hhp2cached/makefile.dms | 217 + wx28X/utils/hhp2cached/makefile.gcc | 257 + wx28X/utils/hhp2cached/makefile.vc | 363 + wx28X/utils/hhp2cached/makefile.wat | 287 + wx28X/utils/makefile.bcc | 93 + wx28X/utils/makefile.dmc | 68 + wx28X/utils/makefile.dms | 63 + wx28X/utils/makefile.gcc | 67 + wx28X/utils/makefile.vc | 76 + wx28X/utils/makefile.wat | 96 + wx28X/utils/nplugin/lib/dummy | 1 + wx28X/utils/nplugin/makefile.vc | 32 + wx28X/utils/nplugin/samples/gui/gui.cpp | 181 + wx28X/utils/nplugin/samples/gui/gui.h | 59 + wx28X/utils/nplugin/samples/gui/index.html | 34 + wx28X/utils/nplugin/samples/gui/makefile.vc | 70 + wx28X/utils/nplugin/samples/gui/npgui32.rc | 44 + wx28X/utils/nplugin/samples/simple/index.html | 34 + .../utils/nplugin/samples/simple/makefile.vc | 70 + .../nplugin/samples/simple/npsimple32.rc | 44 + wx28X/utils/nplugin/samples/simple/simple.cpp | 169 + wx28X/utils/nplugin/src/makefile.vc | 78 + wx28X/utils/nplugin/src/npapi.h | 258 + wx28X/utils/nplugin/src/npapp.cpp | 278 + wx28X/utils/nplugin/src/npapp.h | 91 + wx28X/utils/nplugin/src/npframe.cpp | 293 + wx28X/utils/nplugin/src/npframe.h | 81 + wx28X/utils/nplugin/src/npshell.cpp | 282 + wx28X/utils/nplugin/src/npupp.h | 799 + wx28X/utils/nplugin/src/npwin.cpp | 186 + wx28X/utils/tex2rtf/Makefile.in | 7 + wx28X/utils/tex2rtf/src/Makefile.in | 266 + wx28X/utils/tex2rtf/src/bmputils.h | 244 + wx28X/utils/tex2rtf/src/htmlutil.cpp | 3455 + wx28X/utils/tex2rtf/src/makefile.bcc | 341 + wx28X/utils/tex2rtf/src/makefile.dmc | 114 + wx28X/utils/tex2rtf/src/makefile.dms | 274 + wx28X/utils/tex2rtf/src/makefile.gcc | 335 + wx28X/utils/tex2rtf/src/makefile.unx | 24 + wx28X/utils/tex2rtf/src/makefile.vc | 464 + wx28X/utils/tex2rtf/src/makefile.wat | 374 + wx28X/utils/tex2rtf/src/makengui.nt | 98 + wx28X/utils/tex2rtf/src/maths.cpp | 24 + wx28X/utils/tex2rtf/src/readshg.cpp | 159 + wx28X/utils/tex2rtf/src/readshg.h | 64 + wx28X/utils/tex2rtf/src/rtfutils.cpp | 5342 + wx28X/utils/tex2rtf/src/rtfutils.h | 60 + wx28X/utils/tex2rtf/src/symbols.h | 22 + wx28X/utils/tex2rtf/src/table.cpp | 155 + wx28X/utils/tex2rtf/src/table.h | 36 + wx28X/utils/tex2rtf/src/tex2any.cpp | 3796 + wx28X/utils/tex2rtf/src/tex2any.h | 1070 + wx28X/utils/tex2rtf/src/tex2rtf.bkl | 38 + wx28X/utils/tex2rtf/src/tex2rtf.cpp | 1379 + wx28X/utils/tex2rtf/src/tex2rtf.h | 182 + wx28X/utils/tex2rtf/src/tex2rtf.ico | Bin 0 -> 766 bytes wx28X/utils/tex2rtf/src/tex2rtf.ini | 22 + wx28X/utils/tex2rtf/src/tex2rtf.rc | 4 + wx28X/utils/tex2rtf/src/tex2rtf.vcp | 1854 + wx28X/utils/tex2rtf/src/tex2rtf.vcw | 17 + wx28X/utils/tex2rtf/src/tex2rtf.xpm | 42 + wx28X/utils/tex2rtf/src/tex2rtf_tex2rtf.dsp | 471 + .../utils/tex2rtf/src/tex2rtf_tex2rtf_gui.dsp | 508 + wx28X/utils/tex2rtf/src/texutils.cpp | 1833 + wx28X/utils/tex2rtf/src/wxhlpblk.h | 30 + wx28X/utils/tex2rtf/src/xlputils.cpp | 1211 + wx28X/utils/tex2rtf/tools/suppresswarnings.sh | 3 + wx28X/utils/utils.bkl | 30 + .../utils/wxOLE/samples/servlet/mondrian.xpm | 44 + wx28X/utils/wxOLE/samples/servlet/servlet.cpp | 130 + .../wxOLE/samples/servlet/servlet.gnorba | 13 + wx28X/utils/wxrc/Makefile.in | 135 + wx28X/utils/wxrc/makefile.bcc | 210 + wx28X/utils/wxrc/makefile.dmc | 42 + wx28X/utils/wxrc/makefile.dms | 206 + wx28X/utils/wxrc/makefile.gcc | 207 + wx28X/utils/wxrc/makefile.vc | 293 + wx28X/utils/wxrc/makefile.wat | 273 + wx28X/utils/wxrc/mondrian.ico | Bin 0 -> 766 bytes wx28X/utils/wxrc/wxrc.bkl | 31 + wx28X/utils/wxrc/wxrc.cpp | 943 + wx28X/utils/wxrc/wxrc.dsp | 443 + wx28X/utils/wxrc/wxrc.rc | 2 + wx28X/version-script.in | 215 + wx28X/wx-config-inplace.in | 39 + wx28X/wx-config.in | 1280 + wx28X/wx.url | 2 + wx28X/wxBase.spec | 152 + wx28X/wxGTK.spec | 704 + wx28X/wxMGL.spec | 104 + wx28X/wxMotif.spec | 397 + wx28X/wxX11.spec | 429 + wx28X/wxwin.m4 | 366 + wxPG/propgrid/CHANGES.txt | 1104 + wxPG/propgrid/Makefile.in | 351 + wxPG/propgrid/README.txt | 96 + wxPG/propgrid/build/Bakefiles.bkgen | 31 + wxPG/propgrid/build/GNUMakefile | 377 + wxPG/propgrid/build/autoconf_inc.m4 | 146 + wxPG/propgrid/build/config.guess | 1465 + wxPG/propgrid/build/config.sub | 1579 + wxPG/propgrid/build/configure.ac | 90 + wxPG/propgrid/build/makefile.bcc | 401 + wxPG/propgrid/build/makefile.gcc | 489 + wxPG/propgrid/build/makefile.vc | 405 + wxPG/propgrid/build/makefile.wat | 537 + wxPG/propgrid/build/propgrid.bkl | 190 + wxPG/propgrid/build/propgrid.dsw | 31 + wxPG/propgrid/build/propgrid_propgrid.dsp | 528 + .../build/propgrid_propgrid_vc10.vcxproj | 869 + .../propgrid_propgrid_vc10.vcxproj.filters | 68 + .../build/propgrid_propgrid_vc10.vcxproj.user | 3 + .../build/propgrid_propgrid_vc7.vcproj | 1030 + .../build/propgrid_propgrid_vc8.vcproj | 2813 + .../build/propgrid_propgrid_vc9.vcproj | 2797 + .../build/propgrid_propgridsample.dsp | 508 + .../propgrid_propgridsample.vcxproj.filters | 47 + .../propgrid_propgridsample.vcxproj.user | 3 + .../propgrid_propgridsample_vc10.vcxproj | 935 + .../propgrid_propgridsample_vc10.vcxproj.user | 3 + .../build/propgrid_propgridsample_vc7.vcproj | 1068 + .../build/propgrid_propgridsample_vc8.vcproj | 3111 + .../build/propgrid_propgridsample_vc9.vcproj | 2999 + wxPG/propgrid/build/propgrid_vc10.sdf | Bin 0 -> 45830144 bytes wxPG/propgrid/build/propgrid_vc10.sln | 95 + wxPG/propgrid/build/propgrid_vc10.suo | Bin 0 -> 71680 bytes wxPG/propgrid/build/propgrid_vc7.sln | 98 + wxPG/propgrid/build/propgrid_vc8.sln | 179 + wxPG/propgrid/build/propgrid_vc9.sln | 179 + .../build/vcmsw_dll/propgrid/CL.read.1.tlog | Bin 0 -> 518626 bytes .../build/vcmsw_dll/propgrid/CL.write.1.tlog | Bin 0 -> 2858 bytes .../build/vcmsw_dll/propgrid/advprops.obj | Bin 0 -> 729917 bytes .../vcmsw_dll/propgrid/cl.command.1.tlog | Bin 0 -> 12230 bytes .../build/vcmsw_dll/propgrid/editors.obj | Bin 0 -> 611764 bytes .../build/vcmsw_dll/propgrid/extras.obj | Bin 0 -> 26069 bytes .../vcmsw_dll/propgrid/link.command.1.tlog | Bin 0 -> 5930 bytes .../build/vcmsw_dll/propgrid/link.read.1.tlog | Bin 0 -> 10810 bytes .../vcmsw_dll/propgrid/link.write.1.tlog | Bin 0 -> 2302 bytes .../build/vcmsw_dll/propgrid/manager.obj | Bin 0 -> 457531 bytes .../vcmsw_dll/propgrid/mt.command.1.tlog | Bin 0 -> 918 bytes .../build/vcmsw_dll/propgrid/mt.read.1.tlog | Bin 0 -> 1314 bytes .../build/vcmsw_dll/propgrid/mt.write.1.tlog | Bin 0 -> 594 bytes .../build/vcmsw_dll/propgrid/odcombo.obj | Bin 0 -> 469814 bytes .../propgrid.dll.intermediate.manifest | 15 + .../propgrid/propgrid.lastbuildstate | 2 + .../build/vcmsw_dll/propgrid/propgrid.obj | Bin 0 -> 954195 bytes .../vcmsw_dll/propgrid/propgrid.write.1.tlog | 9 + .../propgrid/propgrid_propgrid_vc10.log | 28 + .../build/vcmsw_dll/propgrid/props.obj | Bin 0 -> 773187 bytes .../build/vcmswd_dll/propgrid/CL.read.1.tlog | Bin 0 -> 256532 bytes .../build/vcmswd_dll/propgrid/CL.write.1.tlog | Bin 0 -> 2856 bytes .../build/vcmswd_dll/propgrid/advprops.obj | Bin 0 -> 1408363 bytes .../vcmswd_dll/propgrid/cl.command.1.tlog | Bin 0 -> 6774 bytes .../build/vcmswd_dll/propgrid/editors.obj | Bin 0 -> 1247171 bytes .../build/vcmswd_dll/propgrid/extras.obj | Bin 0 -> 102654 bytes .../propgrid/link-cvtres.read.1.tlog | 1 + .../propgrid/link-cvtres.write.1.tlog | 1 + .../propgrid/link.5356-cvtres.read.1.tlog | 1 + .../propgrid/link.5356-cvtres.write.1.tlog | 1 + .../vcmswd_dll/propgrid/link.5356.read.1.tlog | 1 + .../propgrid/link.5356.write.1.tlog | 1 + .../vcmswd_dll/propgrid/link.command.1.tlog | Bin 0 -> 3328 bytes .../vcmswd_dll/propgrid/link.read.1.tlog | Bin 0 -> 6428 bytes .../vcmswd_dll/propgrid/link.write.1.tlog | Bin 0 -> 1562 bytes .../build/vcmswd_dll/propgrid/manager.obj | Bin 0 -> 1006579 bytes .../vcmswd_dll/propgrid/mt.command.1.tlog | Bin 0 -> 450 bytes .../build/vcmswd_dll/propgrid/mt.read.1.tlog | Bin 0 -> 174 bytes .../build/vcmswd_dll/propgrid/mt.write.1.tlog | Bin 0 -> 330 bytes .../build/vcmswd_dll/propgrid/odcombo.obj | Bin 0 -> 983021 bytes .../propgrid/propgrid.Build.CppClean.log | 35 + .../propgrid/propgrid.dll.embed.manifest | 15 + .../propgrid/propgrid.dll.embed.manifest.res | Bin 0 -> 748 bytes .../propgrid.dll.intermediate.manifest | 15 + .../propgrid/propgrid.lastbuildstate | 2 + .../build/vcmswd_dll/propgrid/propgrid.obj | Bin 0 -> 2060343 bytes .../vcmswd_dll/propgrid/propgrid.write.1.tlog | 3 + .../vcmswd_dll/propgrid/propgrid_manifest.rc | Bin 0 -> 238 bytes .../propgrid/propgrid_propgrid_vc10.log | 53 + .../build/vcmswd_dll/propgrid/props.obj | Bin 0 -> 1458769 bytes .../vcmswd_dll/propgrid/rc.command.1.tlog | Bin 0 -> 630 bytes .../build/vcmswd_dll/propgrid/rc.read.1.tlog | Bin 0 -> 302 bytes .../build/vcmswd_dll/propgrid/rc.write.1.tlog | Bin 0 -> 310 bytes wxPG/propgrid/build_wx26/makefile.bcc | 401 + wxPG/propgrid/build_wx26/makefile.gcc | 489 + wxPG/propgrid/build_wx26/makefile.vc | 405 + wxPG/propgrid/build_wx26/makefile.wat | 537 + wxPG/propgrid/build_wx26/propgrid.dsw | 31 + wxPG/propgrid/build_wx26/propgrid.sln | 179 + .../propgrid/build_wx26/propgrid_propgrid.dsp | 528 + .../build_wx26/propgrid_propgrid.vcproj | 2797 + .../build_wx26/propgrid_propgridsample.dsp | 508 + .../build_wx26/propgrid_propgridsample.vcproj | 2999 + wxPG/propgrid/configure | 6840 + wxPG/propgrid/docs/Doxyfile | 207 + wxPG/propgrid/docs/html/annotated.htm | 138 + wxPG/propgrid/docs/html/classes.htm | 72 + .../html/classwxArrayEditorDialog-members.htm | 102 + .../docs/html/classwxArrayEditorDialog.htm | 174 + .../docs/html/classwxArrayEditorDialog.png | Bin 0 -> 660 bytes .../classwxArrayStringProperty-members.htm | 259 + .../docs/html/classwxArrayStringProperty.htm | 136 + .../docs/html/classwxArrayStringProperty.png | Bin 0 -> 536 bytes .../html/classwxBaseEnumProperty-members.htm | 261 + .../docs/html/classwxBaseEnumProperty.htm | 363 + .../docs/html/classwxBaseEnumProperty.png | Bin 0 -> 1529 bytes .../docs/html/classwxBoolProperty-members.htm | 254 + .../docs/html/classwxBoolProperty.htm | 100 + .../docs/html/classwxBoolProperty.png | Bin 0 -> 449 bytes .../html/classwxColourProperty-members.htm | 69 + .../docs/html/classwxColourProperty.htm | 75 + .../classwxColourPropertyValue-members.htm | 79 + .../docs/html/classwxColourPropertyValue.htm | 139 + .../html/classwxCursorProperty-members.htm | 266 + .../docs/html/classwxCursorProperty.htm | 94 + .../docs/html/classwxCursorProperty.png | Bin 0 -> 911 bytes .../html/classwxCustomProperty-members.htm | 256 + .../docs/html/classwxCustomProperty.htm | 346 + .../docs/html/classwxCustomProperty.png | Bin 0 -> 475 bytes .../docs/html/classwxDateProperty-members.htm | 263 + .../docs/html/classwxDateProperty.htm | 274 + .../docs/html/classwxDateProperty.png | Bin 0 -> 462 bytes .../docs/html/classwxDirProperty-members.htm | 259 + .../propgrid/docs/html/classwxDirProperty.htm | 105 + .../propgrid/docs/html/classwxDirProperty.png | Bin 0 -> 708 bytes .../html/classwxEditEnumProperty-members.htm | 273 + .../docs/html/classwxEditEnumProperty.htm | 104 + .../docs/html/classwxEditEnumProperty.png | Bin 0 -> 937 bytes .../docs/html/classwxEnumProperty-members.htm | 268 + .../docs/html/classwxEnumProperty.htm | 148 + .../docs/html/classwxEnumProperty.png | Bin 0 -> 1532 bytes .../docs/html/classwxFileProperty-members.htm | 261 + .../docs/html/classwxFileProperty.htm | 300 + .../docs/html/classwxFileProperty.png | Bin 0 -> 701 bytes .../html/classwxFlagsProperty-members.htm | 263 + .../docs/html/classwxFlagsProperty.htm | 356 + .../docs/html/classwxFlagsProperty.png | Bin 0 -> 478 bytes .../html/classwxFloatProperty-members.htm | 256 + .../docs/html/classwxFloatProperty.htm | 182 + .../docs/html/classwxFloatProperty.png | Bin 0 -> 463 bytes .../docs/html/classwxFontProperty-members.htm | 254 + .../docs/html/classwxFontProperty.htm | 311 + .../docs/html/classwxFontProperty.png | Bin 0 -> 455 bytes .../html/classwxImageFileProperty-members.htm | 265 + .../docs/html/classwxImageFileProperty.htm | 225 + .../docs/html/classwxImageFileProperty.png | Bin 0 -> 700 bytes .../docs/html/classwxIntProperty-members.htm | 257 + .../propgrid/docs/html/classwxIntProperty.htm | 250 + .../propgrid/docs/html/classwxIntProperty.png | Bin 0 -> 434 bytes .../classwxLongStringProperty-members.htm | 256 + .../docs/html/classwxLongStringProperty.htm | 190 + .../docs/html/classwxLongStringProperty.png | Bin 0 -> 709 bytes .../classwxMultiChoiceProperty-members.htm | 262 + .../docs/html/classwxMultiChoiceProperty.htm | 323 + .../docs/html/classwxMultiChoiceProperty.png | Bin 0 -> 527 bytes ...asswxPGArrayStringEditorDialog-members.htm | 109 + .../html/classwxPGArrayStringEditorDialog.htm | 115 + .../html/classwxPGArrayStringEditorDialog.png | Bin 0 -> 653 bytes .../classwxPGAttributeStorage-members.htm | 78 + .../docs/html/classwxPGAttributeStorage.htm | 101 + .../docs/html/classwxPGCell-members.htm | 89 + wxPG/propgrid/docs/html/classwxPGCell.htm | 132 + wxPG/propgrid/docs/html/classwxPGCell.png | Bin 0 -> 438 bytes .../html/classwxPGCellRenderer-members.htm | 82 + .../docs/html/classwxPGCellRenderer.htm | 248 + .../docs/html/classwxPGCellRenderer.png | Bin 0 -> 541 bytes .../html/classwxPGCheckBoxEditor-members.htm | 87 + .../docs/html/classwxPGCheckBoxEditor.htm | 197 + .../docs/html/classwxPGCheckBoxEditor.png | Bin 0 -> 481 bytes ...classwxPGChoiceAndButtonEditor-members.htm | 90 + .../html/classwxPGChoiceAndButtonEditor.htm | 112 + .../html/classwxPGChoiceAndButtonEditor.png | Bin 0 -> 737 bytes .../html/classwxPGChoiceEditor-members.htm | 88 + .../docs/html/classwxPGChoiceEditor.htm | 294 + .../docs/html/classwxPGChoiceEditor.png | Bin 0 -> 1003 bytes .../html/classwxPGChoiceEntry-members.htm | 97 + .../docs/html/classwxPGChoiceEntry.htm | 106 + .../docs/html/classwxPGChoiceEntry.png | Bin 0 -> 433 bytes .../docs/html/classwxPGChoices-members.htm | 118 + wxPG/propgrid/docs/html/classwxPGChoices.htm | 891 + .../html/classwxPGChoicesData-members.htm | 76 + .../docs/html/classwxPGChoicesData.htm | 88 + .../html/classwxPGComboBoxEditor-members.htm | 90 + .../docs/html/classwxPGComboBoxEditor.htm | 267 + .../docs/html/classwxPGComboBoxEditor.png | Bin 0 -> 677 bytes .../html/classwxPGCommonValue-members.htm | 76 + .../docs/html/classwxPGCommonValue.htm | 96 + .../html/classwxPGDefaultRenderer-members.htm | 82 + .../docs/html/classwxPGDefaultRenderer.htm | 136 + .../docs/html/classwxPGDefaultRenderer.png | Bin 0 -> 539 bytes .../html/classwxPGEditableState-members.htm | 72 + .../docs/html/classwxPGEditableState.htm | 327 + .../docs/html/classwxPGEditableState.png | Bin 0 -> 516 bytes .../docs/html/classwxPGEditor-members.htm | 85 + wxPG/propgrid/docs/html/classwxPGEditor.htm | 644 + wxPG/propgrid/docs/html/classwxPGEditor.png | Bin 0 -> 1587 bytes .../classwxPGEditorDialogAdapter-members.htm | 75 + .../html/classwxPGEditorDialogAdapter.htm | 104 + .../html/classwxPGEditorDialogAdapter.png | Bin 0 -> 893 bytes .../classwxPGFileDialogAdapter-members.htm | 75 + .../docs/html/classwxPGFileDialogAdapter.htm | 88 + .../docs/html/classwxPGFileDialogAdapter.png | Bin 0 -> 633 bytes .../html/classwxPGGlobalVarsClass-members.htm | 93 + .../docs/html/classwxPGGlobalVarsClass.htm | 121 + .../classwxPGInDialogValidator-members.htm | 72 + .../docs/html/classwxPGInDialogValidator.htm | 86 + ...asswxPGLongStringDialogAdapter-members.htm | 75 + .../html/classwxPGLongStringDialogAdapter.htm | 88 + .../html/classwxPGLongStringDialogAdapter.png | Bin 0 -> 689 bytes .../html/classwxPGMEditableState-members.htm | 78 + .../docs/html/classwxPGMEditableState.htm | 172 + .../docs/html/classwxPGMEditableState.png | Bin 0 -> 509 bytes .../html/classwxPGMultiButton-members.htm | 78 + .../docs/html/classwxPGMultiButton.htm | 186 + .../docs/html/classwxPGPaintData-members.htm | 73 + .../docs/html/classwxPGPropArgCls-members.htm | 84 + .../docs/html/classwxPGPropArgCls.htm | 126 + .../docs/html/classwxPGProperty-members.htm | 252 + wxPG/propgrid/docs/html/classwxPGProperty.htm | 2851 + wxPG/propgrid/docs/html/classwxPGProperty.png | Bin 0 -> 4224 bytes .../html/classwxPGPropertyDataExt-members.htm | 21 + .../docs/html/classwxPGPropertyDataExt.htm | 42 + .../classwxPGPropertyWithChildren-members.htm | 179 + .../html/classwxPGPropertyWithChildren.htm | 3729 + .../html/classwxPGPropertyWithChildren.png | Bin 0 -> 1245 bytes .../html/classwxPGRootProperty-members.htm | 255 + .../docs/html/classwxPGRootProperty.htm | 237 + .../docs/html/classwxPGRootProperty.png | Bin 0 -> 479 bytes .../html/classwxPGStringTokenizer-members.htm | 77 + .../docs/html/classwxPGStringTokenizer.htm | 91 + ...asswxPGTextCtrlAndButtonEditor-members.htm | 91 + .../html/classwxPGTextCtrlAndButtonEditor.htm | 112 + .../html/classwxPGTextCtrlAndButtonEditor.png | Bin 0 -> 763 bytes .../html/classwxPGTextCtrlEditor-members.htm | 89 + .../docs/html/classwxPGTextCtrlEditor.htm | 192 + .../docs/html/classwxPGTextCtrlEditor.png | Bin 0 -> 769 bytes .../docs/html/classwxPGVIterator-members.htm | 79 + .../propgrid/docs/html/classwxPGVIterator.htm | 101 + .../html/classwxPGVIteratorBase-members.htm | 75 + .../docs/html/classwxPGVIteratorBase.htm | 92 + .../html/classwxPGValidationInfo-members.htm | 79 + .../html/classwxPGVariantData-members.htm | 71 + .../docs/html/classwxPGVariantData.htm | 97 + .../docs/html/classwxPGWindowList-members.htm | 75 + .../docs/html/classwxPGWindowList.htm | 87 + .../html/classwxPropertyCategory-members.htm | 262 + .../docs/html/classwxPropertyCategory.htm | 261 + .../docs/html/classwxPropertyCategory.png | Bin 0 -> 516 bytes ...lasswxPropertyContainerMethods-members.htm | 184 + .../html/classwxPropertyContainerMethods.htm | 3474 + .../html/classwxPropertyContainerMethods.png | Bin 0 -> 1002 bytes .../docs/html/classwxPropertyGrid-members.htm | 393 + .../docs/html/classwxPropertyGrid.htm | 3350 + .../docs/html/classwxPropertyGrid.png | Bin 0 -> 570 bytes ...asswxPropertyGridConstIterator-members.htm | 93 + .../html/classwxPropertyGridConstIterator.htm | 120 + .../html/classwxPropertyGridConstIterator.png | Bin 0 -> 658 bytes .../html/classwxPropertyGridEvent-members.htm | 109 + .../docs/html/classwxPropertyGridEvent.htm | 520 + ...asswxPropertyGridHitTestResult-members.htm | 79 + .../html/classwxPropertyGridHitTestResult.htm | 192 + .../classwxPropertyGridInterface-members.htm | 227 + .../html/classwxPropertyGridInterface.htm | 2909 + .../html/classwxPropertyGridInterface.png | Bin 0 -> 929 bytes .../classwxPropertyGridIterator-members.htm | 91 + .../docs/html/classwxPropertyGridIterator.htm | 115 + .../docs/html/classwxPropertyGridIterator.png | Bin 0 -> 622 bytes ...lasswxPropertyGridIteratorBase-members.htm | 79 + .../html/classwxPropertyGridIteratorBase.htm | 139 + .../html/classwxPropertyGridIteratorBase.png | Bin 0 -> 826 bytes .../classwxPropertyGridManager-members.htm | 285 + .../docs/html/classwxPropertyGridManager.htm | 1512 + .../docs/html/classwxPropertyGridManager.png | Bin 0 -> 625 bytes .../html/classwxPropertyGridPage-members.htm | 312 + .../docs/html/classwxPropertyGridPage.htm | 290 + .../docs/html/classwxPropertyGridPage.png | Bin 0 -> 782 bytes .../classwxPropertyGridPopulator-members.htm | 87 + .../html/classwxPropertyGridPopulator.htm | 391 + .../html/classwxPropertyGridState-members.htm | 138 + .../docs/html/classwxPropertyGridState.htm | 567 + .../docs/html/classwxPropertyGridState.png | Bin 0 -> 574 bytes .../html/classwxStringProperty-members.htm | 254 + .../docs/html/classwxStringProperty.htm | 106 + .../docs/html/classwxStringProperty.png | Bin 0 -> 478 bytes .../classwxSystemColourProperty-members.htm | 282 + .../docs/html/classwxSystemColourProperty.htm | 503 + .../docs/html/classwxSystemColourProperty.png | Bin 0 -> 991 bytes .../docs/html/classwxUIntProperty-members.htm | 258 + .../docs/html/classwxUIntProperty.htm | 207 + .../docs/html/classwxUIntProperty.png | Bin 0 -> 441 bytes wxPG/propgrid/docs/html/deprecated.htm | 189 + wxPG/propgrid/docs/html/doxygen.css | 545 + wxPG/propgrid/docs/html/doxygen.png | Bin 0 -> 1281 bytes wxPG/propgrid/docs/html/functions.htm | 178 + wxPG/propgrid/docs/html/functions_0x62.htm | 115 + wxPG/propgrid/docs/html/functions_0x63.htm | 208 + wxPG/propgrid/docs/html/functions_0x64.htm | 218 + wxPG/propgrid/docs/html/functions_0x65.htm | 154 + wxPG/propgrid/docs/html/functions_0x66.htm | 113 + wxPG/propgrid/docs/html/functions_0x67.htm | 615 + wxPG/propgrid/docs/html/functions_0x68.htm | 140 + wxPG/propgrid/docs/html/functions_0x69.htm | 225 + wxPG/propgrid/docs/html/functions_0x6c.htm | 112 + wxPG/propgrid/docs/html/functions_0x6d.htm | 154 + wxPG/propgrid/docs/html/functions_0x6e.htm | 112 + wxPG/propgrid/docs/html/functions_0x6f.htm | 165 + wxPG/propgrid/docs/html/functions_0x70.htm | 136 + wxPG/propgrid/docs/html/functions_0x72.htm | 154 + wxPG/propgrid/docs/html/functions_0x73.htm | 429 + wxPG/propgrid/docs/html/functions_0x74.htm | 109 + wxPG/propgrid/docs/html/functions_0x75.htm | 119 + wxPG/propgrid/docs/html/functions_0x76.htm | 122 + wxPG/propgrid/docs/html/functions_0x77.htm | 145 + wxPG/propgrid/docs/html/functions_0x7e.htm | 133 + wxPG/propgrid/docs/html/functions_enum.htm | 82 + wxPG/propgrid/docs/html/functions_eval.htm | 100 + wxPG/propgrid/docs/html/functions_func.htm | 175 + .../docs/html/functions_func_0x62.htm | 115 + .../docs/html/functions_func_0x63.htm | 205 + .../docs/html/functions_func_0x64.htm | 215 + .../docs/html/functions_func_0x65.htm | 148 + .../docs/html/functions_func_0x66.htm | 113 + .../docs/html/functions_func_0x67.htm | 615 + .../docs/html/functions_func_0x68.htm | 140 + .../docs/html/functions_func_0x69.htm | 225 + .../docs/html/functions_func_0x6c.htm | 112 + .../docs/html/functions_func_0x6d.htm | 109 + .../docs/html/functions_func_0x6e.htm | 112 + .../docs/html/functions_func_0x6f.htm | 165 + .../docs/html/functions_func_0x70.htm | 130 + .../docs/html/functions_func_0x72.htm | 154 + .../docs/html/functions_func_0x73.htm | 414 + .../docs/html/functions_func_0x74.htm | 109 + .../docs/html/functions_func_0x75.htm | 119 + .../docs/html/functions_func_0x76.htm | 122 + .../docs/html/functions_func_0x77.htm | 145 + .../docs/html/functions_func_0x7e.htm | 133 + wxPG/propgrid/docs/html/functions_vars.htm | 136 + wxPG/propgrid/docs/html/group__attrids.htm | 496 + .../docs/html/group__iteratorflags.htm | 134 + .../docs/html/group__miscellaneous.htm | 190 + wxPG/propgrid/docs/html/group__pgactions.htm | 84 + wxPG/propgrid/docs/html/group__propflags.htm | 206 + wxPG/propgrid/docs/html/group__vfbflags.htm | 119 + wxPG/propgrid/docs/html/group__wndflags.htm | 270 + wxPG/propgrid/docs/html/hierarchy.htm | 169 + wxPG/propgrid/docs/html/index.htm | 1170 + wxPG/propgrid/docs/html/modules.htm | 69 + wxPG/propgrid/docs/html/pages.htm | 64 + .../html/structwxPGChoiceInfo-members.htm | 70 + .../docs/html/structwxPGChoiceInfo.htm | 78 + .../docs/html/structwxPGPaintData-members.htm | 19 + .../docs/html/structwxPGPaintData.htm | 152 + .../docs/html/structwxPGValidationInfo.htm | 134 + ...uctwxPropertyGridHitTestResult-members.htm | 20 + .../structwxPropertyGridHitTestResult.htm | 125 + wxPG/propgrid/docs/html/tab_b.gif | Bin 0 -> 35 bytes wxPG/propgrid/docs/html/tab_l.gif | Bin 0 -> 706 bytes wxPG/propgrid/docs/html/tab_r.gif | Bin 0 -> 2585 bytes wxPG/propgrid/docs/html/tabs.css | 105 + wxPG/propgrid/include/wx/propgrid/advprops.h | 505 + wxPG/propgrid/include/wx/propgrid/editors.h | 606 + wxPG/propgrid/include/wx/propgrid/extras.h | 20 + wxPG/propgrid/include/wx/propgrid/manager.h | 946 + wxPG/propgrid/include/wx/propgrid/odcombo.h | 1104 + .../include/wx/propgrid/pg_dox_mainpage.h | 1688 + wxPG/propgrid/include/wx/propgrid/propdev.h | 252 + wxPG/propgrid/include/wx/propgrid/propgrid.h | 8755 + wxPG/propgrid/include/wx/propgrid/props.h | 1203 + .../include/wx/propgrid/xh_propgrid.h | 55 + wxPG/propgrid/lib/filler.txt | 1 + .../lib/vc_dll/wxcode_msw28_propgrid.dll | Bin 0 -> 658432 bytes .../lib/vc_dll/wxcode_msw28_propgrid.exp | Bin 0 -> 480570 bytes .../lib/vc_dll/wxcode_msw28_propgrid.lib | Bin 0 -> 811496 bytes .../lib/vc_dll/wxcode_msw28d_propgrid.dll | Bin 0 -> 1499648 bytes .../lib/vc_dll/wxcode_msw28d_propgrid.exp | Bin 0 -> 480571 bytes .../lib/vc_dll/wxcode_msw28d_propgrid.idb | Bin 0 -> 2681856 bytes .../lib/vc_dll/wxcode_msw28d_propgrid.ilk | Bin 0 -> 6778724 bytes .../lib/vc_dll/wxcode_msw28d_propgrid.lib | Bin 0 -> 813558 bytes .../lib/vc_dll/wxcode_msw28d_propgrid.pdb | Bin 0 -> 5918720 bytes wxPG/propgrid/locale/fi.mo | Bin 0 -> 2059 bytes wxPG/propgrid/locale/fi.po | 158 + wxPG/propgrid/locale/it.mo | Bin 0 -> 2147 bytes wxPG/propgrid/locale/it.po | 155 + wxPG/propgrid/locale/pl.mo | Bin 0 -> 2062 bytes wxPG/propgrid/locale/pl.po | 154 + wxPG/propgrid/locale/propgrid.pot | 162 + wxPG/propgrid/patch_wx26/include/wx/variant.h | 422 + .../propgrid-patch-wxvariant-README.txt | 26 + .../patch_wx26/src/common/variant.cpp | 2032 + wxPG/propgrid/samples/minimal.cpp | 90 + wxPG/propgrid/samples/propgridsample.cpp | 3665 + wxPG/propgrid/samples/propgridsample.h | 270 + wxPG/propgrid/samples/propgridsample_temp.cpp | 411 + wxPG/propgrid/samples/sample.ico | Bin 0 -> 1078 bytes wxPG/propgrid/samples/sample.rc | 32 + wxPG/propgrid/samples/sample.xrc | 119 + wxPG/propgrid/samples/sampleprops.cpp | 623 + wxPG/propgrid/samples/sampleprops.h | 142 + wxPG/propgrid/samples/tests.cpp | 1519 + wxPG/propgrid/src/advprops.cpp | 2207 + wxPG/propgrid/src/editors.cpp | 2579 + wxPG/propgrid/src/extras.cpp | 23 + wxPG/propgrid/src/manager.cpp | 1893 + wxPG/propgrid/src/odcombo.cpp | 3867 + wxPG/propgrid/src/propgrid.cpp | 13718 ++ wxPG/propgrid/src/props.cpp | 2944 + wxPG/propgrid/src/xh_propgrid.cpp | 333 + wxPG/uninstall-propgrid.exe | Bin 0 -> 53293 bytes wxPG/wxPG.zip | Bin 0 -> 25473887 bytes 9931 files changed, 3105918 insertions(+) create mode 100644 SQLite3/LibX86/sqlite3.def create mode 100644 SQLite3/LibX86/sqlite3.dll create mode 100644 SQLite3/LibX86/sqlite3.exp create mode 100644 SQLite3/LibX86/sqlite3.lib create mode 100644 SQLite3/include/shell.c create mode 100644 SQLite3/include/sqlite3.c create mode 100644 SQLite3/include/sqlite3.h create mode 100644 SQLite3/include/sqlite3ext.h create mode 100644 doc/Stampe1.doc create mode 100644 doc/Stampe2.doc create mode 100644 doc/Stampe3.doc create mode 100644 doc/classi.doc create mode 100644 doc/clastree.doc create mode 100644 doc/cpp.doc create mode 100644 doc/frmintro.doc create mode 100644 doc/frmlanguage.doc create mode 100644 doc/lezione1.doc create mode 100644 doc/lezione2.doc create mode 100644 doc/umlanguage.doc create mode 100644 wx28X/BuildCVS.txt create mode 100644 wx28X/Makefile.in create mode 100644 wx28X/acinclude.m4 create mode 100644 wx28X/aclocal.m4 create mode 100644 wx28X/art/addbookm.xpm create mode 100644 wx28X/art/back.xpm create mode 100644 wx28X/art/cdrom.xpm create mode 100644 wx28X/art/copy.xpm create mode 100644 wx28X/art/cross.xpm create mode 100644 wx28X/art/cut.xpm create mode 100644 wx28X/art/deffile.xpm create mode 100644 wx28X/art/delbookm.xpm create mode 100644 wx28X/art/delete.xpm create mode 100644 wx28X/art/dir_up.xpm create mode 100644 wx28X/art/down.xpm create mode 100644 wx28X/art/exefile.xpm create mode 100644 wx28X/art/fileopen.xpm create mode 100644 wx28X/art/filesave.xpm create mode 100644 wx28X/art/filesaveas.xpm create mode 100644 wx28X/art/find.xpm create mode 100644 wx28X/art/findrepl.xpm create mode 100644 wx28X/art/floppy.xpm create mode 100644 wx28X/art/folder.xpm create mode 100644 wx28X/art/folder_open.xpm create mode 100644 wx28X/art/forward.xpm create mode 100644 wx28X/art/harddisk.xpm create mode 100644 wx28X/art/helpicon.xpm create mode 100644 wx28X/art/home.xpm create mode 100644 wx28X/art/htmbook.xpm create mode 100644 wx28X/art/htmfoldr.xpm create mode 100644 wx28X/art/htmoptns.xpm create mode 100644 wx28X/art/htmpage.xpm create mode 100644 wx28X/art/htmsidep.xpm create mode 100644 wx28X/art/listview.xpm create mode 100644 wx28X/art/missimg.xpm create mode 100644 wx28X/art/new.xpm create mode 100644 wx28X/art/new_dir.xpm create mode 100644 wx28X/art/paste.xpm create mode 100644 wx28X/art/print.xpm create mode 100644 wx28X/art/quit.xpm create mode 100644 wx28X/art/redo.xpm create mode 100644 wx28X/art/removable.xpm create mode 100644 wx28X/art/repview.xpm create mode 100644 wx28X/art/tick.xpm create mode 100644 wx28X/art/tipicon.xpm create mode 100644 wx28X/art/toparent.xpm create mode 100644 wx28X/art/undo.xpm create mode 100644 wx28X/art/up.xpm create mode 100644 wx28X/art/wxwin.ico create mode 100644 wx28X/art/wxwin16x16.png create mode 100644 wx28X/art/wxwin16x16.xpm create mode 100644 wx28X/art/wxwin32x32.png create mode 100644 wx28X/art/wxwin32x32.xpm create mode 100644 wx28X/autoconf_inc.m4 create mode 100644 wx28X/autogen.sh create mode 100644 wx28X/build/README.txt create mode 100644 wx28X/build/aclocal/ac_raf_func_which_getservbyname_r.m4 create mode 100644 wx28X/build/aclocal/ax_func_which_gethostbyname_r.m4 create mode 100644 wx28X/build/aclocal/bakefile-dllar.m4 create mode 100644 wx28X/build/aclocal/bakefile-lang.m4 create mode 100644 wx28X/build/aclocal/bakefile.m4 create mode 100644 wx28X/build/aclocal/cppunit.m4 create mode 100644 wx28X/build/aclocal/gst-element-check.m4 create mode 100644 wx28X/build/aclocal/gtk-2.0.m4 create mode 100644 wx28X/build/aclocal/gtk.m4 create mode 100644 wx28X/build/aclocal/pkg.m4 create mode 100644 wx28X/build/aclocal/sdl.m4 create mode 100644 wx28X/build/autoconf_prepend-include/Makefile create mode 100644 wx28X/build/autoconf_prepend-include/README.txt create mode 100644 wx28X/build/autoconf_prepend-include/autoconf/autoconf.m4f create mode 100644 wx28X/build/autoconf_prepend-include/autoconf/c.m4 create mode 100644 wx28X/build/autoconf_prepend-include/autoconf/general.m4 create mode 100644 wx28X/build/autoconf_prepend-include/autoconf/libs.m4 create mode 100644 wx28X/build/autoconf_prepend-include/autoconf/status.m4 create mode 100644 wx28X/build/autogen.mk create mode 100644 wx28X/build/bakefiles/.bakefile_gen.state create mode 100644 wx28X/build/bakefiles/Bakefiles.bkgen create mode 100644 wx28X/build/bakefiles/Bakefiles.local.bkgen create mode 100644 wx28X/build/bakefiles/README create mode 100644 wx28X/build/bakefiles/build_cfg.bkl create mode 100644 wx28X/build/bakefiles/common.bkl create mode 100644 wx28X/build/bakefiles/common_contrib.bkl create mode 100644 wx28X/build/bakefiles/common_samples.bkl create mode 100644 wx28X/build/bakefiles/common_samples_intree.bkl create mode 100644 wx28X/build/bakefiles/common_samples_outoftree.bkl create mode 100644 wx28X/build/bakefiles/config.bkl create mode 100644 wx28X/build/bakefiles/expat.bkl create mode 100644 wx28X/build/bakefiles/files.bkl create mode 100644 wx28X/build/bakefiles/formats/FORMATS.bkmanifest create mode 100644 wx28X/build/bakefiles/formats/README create mode 100644 wx28X/build/bakefiles/formats/cbx_unix.bkl create mode 100644 wx28X/build/bakefiles/formats/cbx_unix.empy create mode 100644 wx28X/build/bakefiles/formats/rpmspec.bkl create mode 100644 wx28X/build/bakefiles/formats/rpmspec.empy create mode 100644 wx28X/build/bakefiles/jpeg.bkl create mode 100644 wx28X/build/bakefiles/mac_bundles.bkl create mode 100644 wx28X/build/bakefiles/make_dist.mk create mode 100644 wx28X/build/bakefiles/monolithic.bkl create mode 100644 wx28X/build/bakefiles/multilib.bkl create mode 100644 wx28X/build/bakefiles/odbc.bkl create mode 100644 wx28X/build/bakefiles/opengl.bkl create mode 100644 wx28X/build/bakefiles/plugins.bkl create mode 100644 wx28X/build/bakefiles/plugins_deps.bkl create mode 100644 wx28X/build/bakefiles/png.bkl create mode 100644 wx28X/build/bakefiles/regex.bkl create mode 100644 wx28X/build/bakefiles/tiff.bkl create mode 100644 wx28X/build/bakefiles/version.bkl create mode 100644 wx28X/build/bakefiles/wx.bkl create mode 100644 wx28X/build/bakefiles/wxpresets/bakefile_quickstart.txt create mode 100644 wx28X/build/bakefiles/wxpresets/presets/wx.bkl create mode 100644 wx28X/build/bakefiles/wxpresets/presets/wx_unix.bkl create mode 100644 wx28X/build/bakefiles/wxpresets/presets/wx_win32.bkl create mode 100644 wx28X/build/bakefiles/wxpresets/sample/configure.in create mode 100644 wx28X/build/bakefiles/wxpresets/sample/minimal.bkl create mode 100644 wx28X/build/bakefiles/wxpresets/sample/minimal.cpp create mode 100644 wx28X/build/bakefiles/wxwin.py create mode 100644 wx28X/build/bakefiles/zlib.bkl create mode 100644 wx28X/build/msw/config.bcc create mode 100644 wx28X/build/msw/config.dmc create mode 100644 wx28X/build/msw/config.dms create mode 100644 wx28X/build/msw/config.gcc create mode 100644 wx28X/build/msw/config.vc create mode 100644 wx28X/build/msw/config.wat create mode 100644 wx28X/build/msw/ipch/wx_adv-309285d6/wxprec_advlib-466edbbe.ipch create mode 100644 wx28X/build/msw/ipch/wx_aui-8af46bfa/wxprec_auilib-35a8d62.ipch create mode 100644 wx28X/build/msw/ipch/wx_base-f1ff18f6/wxprec_baselib-b511031e.ipch create mode 100644 wx28X/build/msw/ipch/wx_core-69f9cec4/wxprec_corelib-fe85372c.ipch create mode 100644 wx28X/build/msw/makefile.bcc create mode 100644 wx28X/build/msw/makefile.dmc create mode 100644 wx28X/build/msw/makefile.dms create mode 100644 wx28X/build/msw/makefile.gcc create mode 100644 wx28X/build/msw/makefile.vc create mode 100644 wx28X/build/msw/makefile.wat create mode 100644 wx28X/build/msw/vc_msw/adv/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/adv/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/adv/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/adv/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/adv/ResolveAssemblyReference.cache create mode 100644 wx28X/build/msw/vc_msw/adv/aboutdlg.obj create mode 100644 wx28X/build/msw/vc_msw/adv/aboutdlgg.obj create mode 100644 wx28X/build/msw/vc_msw/adv/adv.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/adv/adv.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/adv/animatecmn.obj create mode 100644 wx28X/build/msw/vc_msw/adv/animateg.obj create mode 100644 wx28X/build/msw/vc_msw/adv/bmpcboxg.obj create mode 100644 wx28X/build/msw/vc_msw/adv/calctrl.obj create mode 100644 wx28X/build/msw/vc_msw/adv/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/adv/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/adv/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/adv/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/adv/datavcmn.obj create mode 100644 wx28X/build/msw/vc_msw/adv/datavgen.obj create mode 100644 wx28X/build/msw/vc_msw/adv/datectlg.obj create mode 100644 wx28X/build/msw/vc_msw/adv/datectrl.obj create mode 100644 wx28X/build/msw/vc_msw/adv/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/adv/grid.obj create mode 100644 wx28X/build/msw/vc_msw/adv/gridctrl.obj create mode 100644 wx28X/build/msw/vc_msw/adv/gridsel.obj create mode 100644 wx28X/build/msw/vc_msw/adv/helpext.obj create mode 100644 wx28X/build/msw/vc_msw/adv/hyperlink.obj create mode 100644 wx28X/build/msw/vc_msw/adv/joystick.obj create mode 100644 wx28X/build/msw/vc_msw/adv/laywin.obj create mode 100644 wx28X/build/msw/vc_msw/adv/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/adv/odcombo.obj create mode 100644 wx28X/build/msw/vc_msw/adv/propdlg.obj create mode 100644 wx28X/build/msw/vc_msw/adv/sashwin.obj create mode 100644 wx28X/build/msw/vc_msw/adv/sound.obj create mode 100644 wx28X/build/msw/vc_msw/adv/splash.obj create mode 100644 wx28X/build/msw/vc_msw/adv/taskbar.obj create mode 100644 wx28X/build/msw/vc_msw/adv/taskbarcmn.obj create mode 100644 wx28X/build/msw/vc_msw/adv/tipdlg.obj create mode 100644 wx28X/build/msw/vc_msw/adv/wizard.obj create mode 100644 wx28X/build/msw/vc_msw/adv/wx_adv.log create mode 100644 wx28X/build/msw/vc_msw/aui/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/aui/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/aui/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/aui/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/aui/aui.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/aui/aui.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/aui/auibar.obj create mode 100644 wx28X/build/msw/vc_msw/aui/auibook.obj create mode 100644 wx28X/build/msw/vc_msw/aui/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/aui/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/aui/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/aui/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/aui/dockart.obj create mode 100644 wx28X/build/msw/vc_msw/aui/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/aui/floatpane.obj create mode 100644 wx28X/build/msw/vc_msw/aui/framemanager.obj create mode 100644 wx28X/build/msw/vc_msw/aui/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/aui/tabmdi.obj create mode 100644 wx28X/build/msw/vc_msw/aui/wx_aui.log create mode 100644 wx28X/build/msw/vc_msw/base/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/base/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/base/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/base/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/base/ResolveAssemblyReference.cache create mode 100644 wx28X/build/msw/vc_msw/base/appbase.obj create mode 100644 wx28X/build/msw/vc_msw/base/arcall.obj create mode 100644 wx28X/build/msw/vc_msw/base/arcfind.obj create mode 100644 wx28X/build/msw/vc_msw/base/archive.obj create mode 100644 wx28X/build/msw/vc_msw/base/base.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/base/base.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/base/basemsw.obj create mode 100644 wx28X/build/msw/vc_msw/base/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/base/clntdata.obj create mode 100644 wx28X/build/msw/vc_msw/base/cmdline.obj create mode 100644 wx28X/build/msw/vc_msw/base/config.obj create mode 100644 wx28X/build/msw/vc_msw/base/convauto.obj create mode 100644 wx28X/build/msw/vc_msw/base/crashrpt.obj create mode 100644 wx28X/build/msw/vc_msw/base/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/base/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/base/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/base/datetime.obj create mode 100644 wx28X/build/msw/vc_msw/base/datstrm.obj create mode 100644 wx28X/build/msw/vc_msw/base/dde.obj create mode 100644 wx28X/build/msw/vc_msw/base/debughlp.obj create mode 100644 wx28X/build/msw/vc_msw/base/dir.obj create mode 100644 wx28X/build/msw/vc_msw/base/dircmn.obj create mode 100644 wx28X/build/msw/vc_msw/base/dlmsw.obj create mode 100644 wx28X/build/msw/vc_msw/base/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/base/dynarray.obj create mode 100644 wx28X/build/msw/vc_msw/base/dynlib.obj create mode 100644 wx28X/build/msw/vc_msw/base/dynload.obj create mode 100644 wx28X/build/msw/vc_msw/base/encconv.obj create mode 100644 wx28X/build/msw/vc_msw/base/event.obj create mode 100644 wx28X/build/msw/vc_msw/base/extended.obj create mode 100644 wx28X/build/msw/vc_msw/base/ffile.obj create mode 100644 wx28X/build/msw/vc_msw/base/file.obj create mode 100644 wx28X/build/msw/vc_msw/base/fileback.obj create mode 100644 wx28X/build/msw/vc_msw/base/fileconf.obj create mode 100644 wx28X/build/msw/vc_msw/base/filefn.obj create mode 100644 wx28X/build/msw/vc_msw/base/filename.obj create mode 100644 wx28X/build/msw/vc_msw/base/filesys.obj create mode 100644 wx28X/build/msw/vc_msw/base/filtall.obj create mode 100644 wx28X/build/msw/vc_msw/base/filtfind.obj create mode 100644 wx28X/build/msw/vc_msw/base/fmapbase.obj create mode 100644 wx28X/build/msw/vc_msw/base/fs_arc.obj create mode 100644 wx28X/build/msw/vc_msw/base/fs_filter.obj create mode 100644 wx28X/build/msw/vc_msw/base/fs_mem.obj create mode 100644 wx28X/build/msw/vc_msw/base/hash.obj create mode 100644 wx28X/build/msw/vc_msw/base/hashmap.obj create mode 100644 wx28X/build/msw/vc_msw/base/init.obj create mode 100644 wx28X/build/msw/vc_msw/base/intl.obj create mode 100644 wx28X/build/msw/vc_msw/base/ipcbase.obj create mode 100644 wx28X/build/msw/vc_msw/base/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/base/list.obj create mode 100644 wx28X/build/msw/vc_msw/base/log.obj create mode 100644 wx28X/build/msw/vc_msw/base/longlong.obj create mode 100644 wx28X/build/msw/vc_msw/base/main.obj create mode 100644 wx28X/build/msw/vc_msw/base/memory.obj create mode 100644 wx28X/build/msw/vc_msw/base/mimecmn.obj create mode 100644 wx28X/build/msw/vc_msw/base/mimetype.obj create mode 100644 wx28X/build/msw/vc_msw/base/module.obj create mode 100644 wx28X/build/msw/vc_msw/base/msgout.obj create mode 100644 wx28X/build/msw/vc_msw/base/mslu.obj create mode 100644 wx28X/build/msw/vc_msw/base/mstream.obj create mode 100644 wx28X/build/msw/vc_msw/base/object.obj create mode 100644 wx28X/build/msw/vc_msw/base/platinfo.obj create mode 100644 wx28X/build/msw/vc_msw/base/power.obj create mode 100644 wx28X/build/msw/vc_msw/base/powercmn.obj create mode 100644 wx28X/build/msw/vc_msw/base/process.obj create mode 100644 wx28X/build/msw/vc_msw/base/regconf.obj create mode 100644 wx28X/build/msw/vc_msw/base/regex.obj create mode 100644 wx28X/build/msw/vc_msw/base/registry.obj create mode 100644 wx28X/build/msw/vc_msw/base/snglinst.obj create mode 100644 wx28X/build/msw/vc_msw/base/sstream.obj create mode 100644 wx28X/build/msw/vc_msw/base/stackwalk.obj create mode 100644 wx28X/build/msw/vc_msw/base/stdpaths.obj create mode 100644 wx28X/build/msw/vc_msw/base/stdpbase.obj create mode 100644 wx28X/build/msw/vc_msw/base/stopwatch.obj create mode 100644 wx28X/build/msw/vc_msw/base/strconv.obj create mode 100644 wx28X/build/msw/vc_msw/base/stream.obj create mode 100644 wx28X/build/msw/vc_msw/base/string.obj create mode 100644 wx28X/build/msw/vc_msw/base/sysopt.obj create mode 100644 wx28X/build/msw/vc_msw/base/tarstrm.obj create mode 100644 wx28X/build/msw/vc_msw/base/textbuf.obj create mode 100644 wx28X/build/msw/vc_msw/base/textfile.obj create mode 100644 wx28X/build/msw/vc_msw/base/thread.obj create mode 100644 wx28X/build/msw/vc_msw/base/tokenzr.obj create mode 100644 wx28X/build/msw/vc_msw/base/txtstrm.obj create mode 100644 wx28X/build/msw/vc_msw/base/uri.obj create mode 100644 wx28X/build/msw/vc_msw/base/utils.obj create mode 100644 wx28X/build/msw/vc_msw/base/utilscmn.obj create mode 100644 wx28X/build/msw/vc_msw/base/utilsexc.obj create mode 100644 wx28X/build/msw/vc_msw/base/variant.obj create mode 100644 wx28X/build/msw/vc_msw/base/volume.obj create mode 100644 wx28X/build/msw/vc_msw/base/wfstream.obj create mode 100644 wx28X/build/msw/vc_msw/base/wx_base.log create mode 100644 wx28X/build/msw/vc_msw/base/wxchar.obj create mode 100644 wx28X/build/msw/vc_msw/base/xti.obj create mode 100644 wx28X/build/msw/vc_msw/base/xtistrm.obj create mode 100644 wx28X/build/msw/vc_msw/base/zipstrm.obj create mode 100644 wx28X/build/msw/vc_msw/base/zstream.obj create mode 100644 wx28X/build/msw/vc_msw/core/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/core/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/core/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/core/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/core/accel.obj create mode 100644 wx28X/build/msw/vc_msw/core/access.obj create mode 100644 wx28X/build/msw/vc_msw/core/accesscmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/anidecod.obj create mode 100644 wx28X/build/msw/vc_msw/core/app.obj create mode 100644 wx28X/build/msw/vc_msw/core/appcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/artprov.obj create mode 100644 wx28X/build/msw/vc_msw/core/artstd.obj create mode 100644 wx28X/build/msw/vc_msw/core/automtn.obj create mode 100644 wx28X/build/msw/vc_msw/core/bitmap.obj create mode 100644 wx28X/build/msw/vc_msw/core/bmpbase.obj create mode 100644 wx28X/build/msw/vc_msw/core/bmpbuttn.obj create mode 100644 wx28X/build/msw/vc_msw/core/bookctrl.obj create mode 100644 wx28X/build/msw/vc_msw/core/brush.obj create mode 100644 wx28X/build/msw/vc_msw/core/busyinfo.obj create mode 100644 wx28X/build/msw/vc_msw/core/button.obj create mode 100644 wx28X/build/msw/vc_msw/core/buttonbar.obj create mode 100644 wx28X/build/msw/vc_msw/core/caret.obj create mode 100644 wx28X/build/msw/vc_msw/core/checkbox.obj create mode 100644 wx28X/build/msw/vc_msw/core/checklst.obj create mode 100644 wx28X/build/msw/vc_msw/core/choicbkg.obj create mode 100644 wx28X/build/msw/vc_msw/core/choiccmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/choicdgg.obj create mode 100644 wx28X/build/msw/vc_msw/core/choice.obj create mode 100644 wx28X/build/msw/vc_msw/core/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/core/clipbrd.obj create mode 100644 wx28X/build/msw/vc_msw/core/clipcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/clrpickercmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/clrpickerg.obj create mode 100644 wx28X/build/msw/vc_msw/core/cmdproc.obj create mode 100644 wx28X/build/msw/vc_msw/core/cmndata.obj create mode 100644 wx28X/build/msw/vc_msw/core/collpaneg.obj create mode 100644 wx28X/build/msw/vc_msw/core/colordlg.obj create mode 100644 wx28X/build/msw/vc_msw/core/colour.obj create mode 100644 wx28X/build/msw/vc_msw/core/colourcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/combo.obj create mode 100644 wx28X/build/msw/vc_msw/core/combobox.obj create mode 100644 wx28X/build/msw/vc_msw/core/combocmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/combog.obj create mode 100644 wx28X/build/msw/vc_msw/core/containr.obj create mode 100644 wx28X/build/msw/vc_msw/core/control.obj create mode 100644 wx28X/build/msw/vc_msw/core/core.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/core/core.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/core/cshelp.obj create mode 100644 wx28X/build/msw/vc_msw/core/ctrlcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/ctrlsub.obj create mode 100644 wx28X/build/msw/vc_msw/core/cursor.obj create mode 100644 wx28X/build/msw/vc_msw/core/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/core/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/core/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/core/data.obj create mode 100644 wx28X/build/msw/vc_msw/core/datacmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/dataobj.obj create mode 100644 wx28X/build/msw/vc_msw/core/dc.obj create mode 100644 wx28X/build/msw/vc_msw/core/dcbase.obj create mode 100644 wx28X/build/msw/vc_msw/core/dcbufcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/dcclient.obj create mode 100644 wx28X/build/msw/vc_msw/core/dcgraph.obj create mode 100644 wx28X/build/msw/vc_msw/core/dcmemory.obj create mode 100644 wx28X/build/msw/vc_msw/core/dcprint.obj create mode 100644 wx28X/build/msw/vc_msw/core/dcpsg.obj create mode 100644 wx28X/build/msw/vc_msw/core/dcscreen.obj create mode 100644 wx28X/build/msw/vc_msw/core/dialog.obj create mode 100644 wx28X/build/msw/vc_msw/core/dialup.obj create mode 100644 wx28X/build/msw/vc_msw/core/dib.obj create mode 100644 wx28X/build/msw/vc_msw/core/dirctrlg.obj create mode 100644 wx28X/build/msw/vc_msw/core/dirdlg.obj create mode 100644 wx28X/build/msw/vc_msw/core/display.obj create mode 100644 wx28X/build/msw/vc_msw/core/dlgcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/dndcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/dobjcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/docmdi.obj create mode 100644 wx28X/build/msw/vc_msw/core/docview.obj create mode 100644 wx28X/build/msw/vc_msw/core/dpycmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/dragimag.obj create mode 100644 wx28X/build/msw/vc_msw/core/dragimgg.obj create mode 100644 wx28X/build/msw/vc_msw/core/dropsrc.obj create mode 100644 wx28X/build/msw/vc_msw/core/droptgt.obj create mode 100644 wx28X/build/msw/vc_msw/core/dseldlg.obj create mode 100644 wx28X/build/msw/vc_msw/core/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/core/effects.obj create mode 100644 wx28X/build/msw/vc_msw/core/enhmeta.obj create mode 100644 wx28X/build/msw/vc_msw/core/event.obj create mode 100644 wx28X/build/msw/vc_msw/core/evtloop.obj create mode 100644 wx28X/build/msw/vc_msw/core/evtloopcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/fddlgcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/fdrepdlg.obj create mode 100644 wx28X/build/msw/vc_msw/core/filedlg.obj create mode 100644 wx28X/build/msw/vc_msw/core/filepickercmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/filepickerg.obj create mode 100644 wx28X/build/msw/vc_msw/core/fldlgcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/font.obj create mode 100644 wx28X/build/msw/vc_msw/core/fontcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/fontdlg.obj create mode 100644 wx28X/build/msw/vc_msw/core/fontenum.obj create mode 100644 wx28X/build/msw/vc_msw/core/fontenumcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/fontmap.obj create mode 100644 wx28X/build/msw/vc_msw/core/fontpickercmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/fontpickerg.obj create mode 100644 wx28X/build/msw/vc_msw/core/fontutil.obj create mode 100644 wx28X/build/msw/vc_msw/core/frame.obj create mode 100644 wx28X/build/msw/vc_msw/core/framecmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/fs_mem.obj create mode 100644 wx28X/build/msw/vc_msw/core/gauge95.obj create mode 100644 wx28X/build/msw/vc_msw/core/gaugecmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/gbsizer.obj create mode 100644 wx28X/build/msw/vc_msw/core/gdicmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/gdiimage.obj create mode 100644 wx28X/build/msw/vc_msw/core/gdiobj.obj create mode 100644 wx28X/build/msw/vc_msw/core/geometry.obj create mode 100644 wx28X/build/msw/vc_msw/core/gifdecod.obj create mode 100644 wx28X/build/msw/vc_msw/core/graphcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/graphics.obj create mode 100644 wx28X/build/msw/vc_msw/core/gsockmsw.obj create mode 100644 wx28X/build/msw/vc_msw/core/helpbase.obj create mode 100644 wx28X/build/msw/vc_msw/core/helpchm.obj create mode 100644 wx28X/build/msw/vc_msw/core/helpwin.obj create mode 100644 wx28X/build/msw/vc_msw/core/icon.obj create mode 100644 wx28X/build/msw/vc_msw/core/iconbndl.obj create mode 100644 wx28X/build/msw/vc_msw/core/imagall.obj create mode 100644 wx28X/build/msw/vc_msw/core/imagbmp.obj create mode 100644 wx28X/build/msw/vc_msw/core/image.obj create mode 100644 wx28X/build/msw/vc_msw/core/imagfill.obj create mode 100644 wx28X/build/msw/vc_msw/core/imaggif.obj create mode 100644 wx28X/build/msw/vc_msw/core/imagiff.obj create mode 100644 wx28X/build/msw/vc_msw/core/imagjpeg.obj create mode 100644 wx28X/build/msw/vc_msw/core/imaglist.obj create mode 100644 wx28X/build/msw/vc_msw/core/imagpcx.obj create mode 100644 wx28X/build/msw/vc_msw/core/imagpng.obj create mode 100644 wx28X/build/msw/vc_msw/core/imagpnm.obj create mode 100644 wx28X/build/msw/vc_msw/core/imagtga.obj create mode 100644 wx28X/build/msw/vc_msw/core/imagtiff.obj create mode 100644 wx28X/build/msw/vc_msw/core/imagxpm.obj create mode 100644 wx28X/build/msw/vc_msw/core/iniconf.obj create mode 100644 wx28X/build/msw/vc_msw/core/layout.obj create mode 100644 wx28X/build/msw/vc_msw/core/lboxcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/core/listbkg.obj create mode 100644 wx28X/build/msw/vc_msw/core/listbox.obj create mode 100644 wx28X/build/msw/vc_msw/core/listctrl.obj create mode 100644 wx28X/build/msw/vc_msw/core/listctrlcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/logg.obj create mode 100644 wx28X/build/msw/vc_msw/core/main.obj create mode 100644 wx28X/build/msw/vc_msw/core/matrix.obj create mode 100644 wx28X/build/msw/vc_msw/core/mdi.obj create mode 100644 wx28X/build/msw/vc_msw/core/menu.obj create mode 100644 wx28X/build/msw/vc_msw/core/menucmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/menuitem.obj create mode 100644 wx28X/build/msw/vc_msw/core/metafile.obj create mode 100644 wx28X/build/msw/vc_msw/core/minifram.obj create mode 100644 wx28X/build/msw/vc_msw/core/msgdlg.obj create mode 100644 wx28X/build/msw/vc_msw/core/msgout.obj create mode 100644 wx28X/build/msw/vc_msw/core/mslu.obj create mode 100644 wx28X/build/msw/vc_msw/core/nativdlg.obj create mode 100644 wx28X/build/msw/vc_msw/core/nbkbase.obj create mode 100644 wx28X/build/msw/vc_msw/core/notebook.obj create mode 100644 wx28X/build/msw/vc_msw/core/numdlgg.obj create mode 100644 wx28X/build/msw/vc_msw/core/oleutils.obj create mode 100644 wx28X/build/msw/vc_msw/core/overlaycmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/ownerdrw.obj create mode 100644 wx28X/build/msw/vc_msw/core/palette.obj create mode 100644 wx28X/build/msw/vc_msw/core/panelg.obj create mode 100644 wx28X/build/msw/vc_msw/core/paper.obj create mode 100644 wx28X/build/msw/vc_msw/core/pen.obj create mode 100644 wx28X/build/msw/vc_msw/core/pickerbase.obj create mode 100644 wx28X/build/msw/vc_msw/core/popupcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/popupwin.obj create mode 100644 wx28X/build/msw/vc_msw/core/printdlg.obj create mode 100644 wx28X/build/msw/vc_msw/core/printps.obj create mode 100644 wx28X/build/msw/vc_msw/core/printwin.obj create mode 100644 wx28X/build/msw/vc_msw/core/prntbase.obj create mode 100644 wx28X/build/msw/vc_msw/core/prntdlgg.obj create mode 100644 wx28X/build/msw/vc_msw/core/progdlgg.obj create mode 100644 wx28X/build/msw/vc_msw/core/quantize.obj create mode 100644 wx28X/build/msw/vc_msw/core/radiobox.obj create mode 100644 wx28X/build/msw/vc_msw/core/radiobut.obj create mode 100644 wx28X/build/msw/vc_msw/core/radiocmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/region.obj create mode 100644 wx28X/build/msw/vc_msw/core/rendcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/renderer.obj create mode 100644 wx28X/build/msw/vc_msw/core/renderg.obj create mode 100644 wx28X/build/msw/vc_msw/core/rgncmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/scrlwing.obj create mode 100644 wx28X/build/msw/vc_msw/core/scrolbar.obj create mode 100644 wx28X/build/msw/vc_msw/core/selstore.obj create mode 100644 wx28X/build/msw/vc_msw/core/settcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/settings.obj create mode 100644 wx28X/build/msw/vc_msw/core/sizer.obj create mode 100644 wx28X/build/msw/vc_msw/core/slider95.obj create mode 100644 wx28X/build/msw/vc_msw/core/spinbutt.obj create mode 100644 wx28X/build/msw/vc_msw/core/spinctlg.obj create mode 100644 wx28X/build/msw/vc_msw/core/spinctrl.obj create mode 100644 wx28X/build/msw/vc_msw/core/splitter.obj create mode 100644 wx28X/build/msw/vc_msw/core/srchcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/srchctlg.obj create mode 100644 wx28X/build/msw/vc_msw/core/statbar.obj create mode 100644 wx28X/build/msw/vc_msw/core/statbmp.obj create mode 100644 wx28X/build/msw/vc_msw/core/statbox.obj create mode 100644 wx28X/build/msw/vc_msw/core/statbr95.obj create mode 100644 wx28X/build/msw/vc_msw/core/statline.obj create mode 100644 wx28X/build/msw/vc_msw/core/stattext.obj create mode 100644 wx28X/build/msw/vc_msw/core/statusbr.obj create mode 100644 wx28X/build/msw/vc_msw/core/stockitem.obj create mode 100644 wx28X/build/msw/vc_msw/core/tabctrl.obj create mode 100644 wx28X/build/msw/vc_msw/core/tbar95.obj create mode 100644 wx28X/build/msw/vc_msw/core/tbarbase.obj create mode 100644 wx28X/build/msw/vc_msw/core/textcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/textctrl.obj create mode 100644 wx28X/build/msw/vc_msw/core/textdlgg.obj create mode 100644 wx28X/build/msw/vc_msw/core/tglbtn.obj create mode 100644 wx28X/build/msw/vc_msw/core/timer.obj create mode 100644 wx28X/build/msw/vc_msw/core/timercmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/tipwin.obj create mode 100644 wx28X/build/msw/vc_msw/core/toolbkg.obj create mode 100644 wx28X/build/msw/vc_msw/core/tooltip.obj create mode 100644 wx28X/build/msw/vc_msw/core/toplevel.obj create mode 100644 wx28X/build/msw/vc_msw/core/toplvcmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/treebase.obj create mode 100644 wx28X/build/msw/vc_msw/core/treebkg.obj create mode 100644 wx28X/build/msw/vc_msw/core/treectlg.obj create mode 100644 wx28X/build/msw/vc_msw/core/treectrl.obj create mode 100644 wx28X/build/msw/vc_msw/core/utilscmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/utilsgui.obj create mode 100644 wx28X/build/msw/vc_msw/core/uuid.obj create mode 100644 wx28X/build/msw/vc_msw/core/uxtheme.obj create mode 100644 wx28X/build/msw/vc_msw/core/valgen.obj create mode 100644 wx28X/build/msw/vc_msw/core/validate.obj create mode 100644 wx28X/build/msw/vc_msw/core/valtext.obj create mode 100644 wx28X/build/msw/vc_msw/core/vlbox.obj create mode 100644 wx28X/build/msw/vc_msw/core/volume.obj create mode 100644 wx28X/build/msw/vc_msw/core/vscroll.obj create mode 100644 wx28X/build/msw/vc_msw/core/wincmn.obj create mode 100644 wx28X/build/msw/vc_msw/core/window.obj create mode 100644 wx28X/build/msw/vc_msw/core/wx_core.log create mode 100644 wx28X/build/msw/vc_msw/core/xpmdecod.obj create mode 100644 wx28X/build/msw/vc_msw/dbgrid/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/dbgrid/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/dbgrid/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/dbgrid/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/dbgrid/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/dbgrid/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/dbgrid/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/dbgrid/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/dbgrid/dbgrid.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/dbgrid/dbgrid.obj create mode 100644 wx28X/build/msw/vc_msw/dbgrid/dbgrid.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/dbgrid/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/dbgrid/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/dbgrid/wx_dbgrid.log create mode 100644 wx28X/build/msw/vc_msw/gl/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/gl/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/gl/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/gl/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/gl/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/gl/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/gl/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/gl/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/gl/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/gl/gl.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/gl/gl.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/gl/glcanvas.obj create mode 100644 wx28X/build/msw/vc_msw/gl/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/gl/wx_gl.log create mode 100644 wx28X/build/msw/vc_msw/html/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/html/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/html/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/html/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/html/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/html/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/html/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/html/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/html/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/html/helpbest.obj create mode 100644 wx28X/build/msw/vc_msw/html/helpctrl.obj create mode 100644 wx28X/build/msw/vc_msw/html/helpdata.obj create mode 100644 wx28X/build/msw/vc_msw/html/helpdlg.obj create mode 100644 wx28X/build/msw/vc_msw/html/helpfrm.obj create mode 100644 wx28X/build/msw/vc_msw/html/helpwnd.obj create mode 100644 wx28X/build/msw/vc_msw/html/html.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/html/html.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/html/htmlcell.obj create mode 100644 wx28X/build/msw/vc_msw/html/htmlfilt.obj create mode 100644 wx28X/build/msw/vc_msw/html/htmllbox.obj create mode 100644 wx28X/build/msw/vc_msw/html/htmlpars.obj create mode 100644 wx28X/build/msw/vc_msw/html/htmltag.obj create mode 100644 wx28X/build/msw/vc_msw/html/htmlwin.obj create mode 100644 wx28X/build/msw/vc_msw/html/htmprint.obj create mode 100644 wx28X/build/msw/vc_msw/html/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/html/m_dflist.obj create mode 100644 wx28X/build/msw/vc_msw/html/m_fonts.obj create mode 100644 wx28X/build/msw/vc_msw/html/m_hline.obj create mode 100644 wx28X/build/msw/vc_msw/html/m_image.obj create mode 100644 wx28X/build/msw/vc_msw/html/m_layout.obj create mode 100644 wx28X/build/msw/vc_msw/html/m_links.obj create mode 100644 wx28X/build/msw/vc_msw/html/m_list.obj create mode 100644 wx28X/build/msw/vc_msw/html/m_pre.obj create mode 100644 wx28X/build/msw/vc_msw/html/m_style.obj create mode 100644 wx28X/build/msw/vc_msw/html/m_tables.obj create mode 100644 wx28X/build/msw/vc_msw/html/winpars.obj create mode 100644 wx28X/build/msw/vc_msw/html/wx_html.log create mode 100644 wx28X/build/msw/vc_msw/media/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/media/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/media/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/media/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/media/activex.obj create mode 100644 wx28X/build/msw/vc_msw/media/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/media/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/media/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/media/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/media/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/media/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/media/media.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/media/media.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/media/mediactrl_am.obj create mode 100644 wx28X/build/msw/vc_msw/media/mediactrl_qt.obj create mode 100644 wx28X/build/msw/vc_msw/media/mediactrl_wmp10.obj create mode 100644 wx28X/build/msw/vc_msw/media/mediactrlcmn.obj create mode 100644 wx28X/build/msw/vc_msw/media/wx_media.log create mode 100644 wx28X/build/msw/vc_msw/net/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/net/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/net/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/net/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/net/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/net/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/net/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/net/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/net/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/net/fs_inet.obj create mode 100644 wx28X/build/msw/vc_msw/net/ftp.obj create mode 100644 wx28X/build/msw/vc_msw/net/gsocket.obj create mode 100644 wx28X/build/msw/vc_msw/net/http.obj create mode 100644 wx28X/build/msw/vc_msw/net/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/net/net.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/net/net.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/net/protocol.obj create mode 100644 wx28X/build/msw/vc_msw/net/sckaddr.obj create mode 100644 wx28X/build/msw/vc_msw/net/sckfile.obj create mode 100644 wx28X/build/msw/vc_msw/net/sckipc.obj create mode 100644 wx28X/build/msw/vc_msw/net/sckstrm.obj create mode 100644 wx28X/build/msw/vc_msw/net/socket.obj create mode 100644 wx28X/build/msw/vc_msw/net/url.obj create mode 100644 wx28X/build/msw/vc_msw/net/urlmsw.obj create mode 100644 wx28X/build/msw/vc_msw/net/wx_net.log create mode 100644 wx28X/build/msw/vc_msw/odbc/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/odbc/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/odbc/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/odbc/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/odbc/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/odbc/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/odbc/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/odbc/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/odbc/db.obj create mode 100644 wx28X/build/msw/vc_msw/odbc/dbtable.obj create mode 100644 wx28X/build/msw/vc_msw/odbc/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/odbc/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/odbc/odbc.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/odbc/odbc.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/odbc/wx_odbc.log create mode 100644 wx28X/build/msw/vc_msw/qa/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/qa/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/qa/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/qa/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/qa/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/qa/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/qa/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/qa/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/qa/dbgrptg.obj create mode 100644 wx28X/build/msw/vc_msw/qa/debugrpt.obj create mode 100644 wx28X/build/msw/vc_msw/qa/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/qa/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/qa/qa.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/qa/qa.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/qa/wx_qa.log create mode 100644 wx28X/build/msw/vc_msw/richtext/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/richtext/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/richtext/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/richtext/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/richtext/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/richtext/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/richtext/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/richtext/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/richtext/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/richtext/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/richtext/richtext.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/richtext/richtext.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/richtext/richtextbuffer.obj create mode 100644 wx28X/build/msw/vc_msw/richtext/richtextctrl.obj create mode 100644 wx28X/build/msw/vc_msw/richtext/richtextformatdlg.obj create mode 100644 wx28X/build/msw/vc_msw/richtext/richtexthtml.obj create mode 100644 wx28X/build/msw/vc_msw/richtext/richtextprint.obj create mode 100644 wx28X/build/msw/vc_msw/richtext/richtextstyledlg.obj create mode 100644 wx28X/build/msw/vc_msw/richtext/richtextstyles.obj create mode 100644 wx28X/build/msw/vc_msw/richtext/richtextsymboldlg.obj create mode 100644 wx28X/build/msw/vc_msw/richtext/richtextxml.obj create mode 100644 wx28X/build/msw/vc_msw/richtext/wx_richtext.log create mode 100644 wx28X/build/msw/vc_msw/wxexpat/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxexpat/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxexpat/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxexpat/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxexpat/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxexpat/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxexpat/wx_wxexpat.log create mode 100644 wx28X/build/msw/vc_msw/wxexpat/wxexpat.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/wxexpat/xmlparse.obj create mode 100644 wx28X/build/msw/vc_msw/wxexpat/xmlrole.obj create mode 100644 wx28X/build/msw/vc_msw/wxexpat/xmltok.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jcapimin.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jcapistd.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jccoefct.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jccolor.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jcdctmgr.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jchuff.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jcinit.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jcmainct.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jcmarker.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jcmaster.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jcomapi.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jcparam.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jcphuff.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jcprepct.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jcsample.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jctrans.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdapimin.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdapistd.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdatadst.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdatasrc.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdcoefct.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdcolor.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jddctmgr.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdhuff.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdinput.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdmainct.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdmarker.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdmaster.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdmerge.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdphuff.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdpostct.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdsample.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jdtrans.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jerror.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jfdctflt.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jfdctfst.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jfdctint.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jidctflt.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jidctfst.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jidctint.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jidctred.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jmemmgr.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jmemnobs.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jquant1.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jquant2.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/jutils.obj create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/wx_wxjpeg.log create mode 100644 wx28X/build/msw/vc_msw/wxjpeg/wxjpeg.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/wxpng/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxpng/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxpng/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxpng/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxpng/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxpng/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxpng/png.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngerror.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pnggccrd.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngget.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngmem.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngpread.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngread.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngrio.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngrtran.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngrutil.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngset.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngtrans.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngvcrd.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngwio.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngwrite.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngwtran.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/pngwutil.obj create mode 100644 wx28X/build/msw/vc_msw/wxpng/wx_wxpng.log create mode 100644 wx28X/build/msw/vc_msw/wxpng/wxpng.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/wxpng/wxpng.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxprec_advlib.pch create mode 100644 wx28X/build/msw/vc_msw/wxprec_auilib.pch create mode 100644 wx28X/build/msw/vc_msw/wxprec_baselib.pch create mode 100644 wx28X/build/msw/vc_msw/wxprec_corelib.pch create mode 100644 wx28X/build/msw/vc_msw/wxprec_dbgridlib.pch create mode 100644 wx28X/build/msw/vc_msw/wxprec_gllib.pch create mode 100644 wx28X/build/msw/vc_msw/wxprec_htmllib.pch create mode 100644 wx28X/build/msw/vc_msw/wxprec_medialib.pch create mode 100644 wx28X/build/msw/vc_msw/wxprec_netlib.pch create mode 100644 wx28X/build/msw/vc_msw/wxprec_odbclib.pch create mode 100644 wx28X/build/msw/vc_msw/wxprec_qalib.pch create mode 100644 wx28X/build/msw/vc_msw/wxprec_richtextlib.pch create mode 100644 wx28X/build/msw/vc_msw/wxprec_xmllib.pch create mode 100644 wx28X/build/msw/vc_msw/wxprec_xrclib.pch create mode 100644 wx28X/build/msw/vc_msw/wxregex/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxregex/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxregex/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxregex/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxregex/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxregex/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxregex/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxregex/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxregex/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxregex/regcomp.obj create mode 100644 wx28X/build/msw/vc_msw/wxregex/regerror.obj create mode 100644 wx28X/build/msw/vc_msw/wxregex/regexec.obj create mode 100644 wx28X/build/msw/vc_msw/wxregex/regfree.obj create mode 100644 wx28X/build/msw/vc_msw/wxregex/wx_wxregex.log create mode 100644 wx28X/build/msw/vc_msw/wxregex/wxregex.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/wxtiff/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxtiff/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxtiff/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxtiff/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxtiff/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxtiff/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_aux.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_close.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_codec.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_color.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_compress.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_dir.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_dirinfo.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_dirread.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_dirwrite.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_dumpmode.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_error.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_extension.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_fax3.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_fax3sm.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_flush.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_getimage.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_jpeg.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_luv.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_lzw.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_next.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_open.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_packbits.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_pixarlog.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_predict.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_print.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_read.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_strip.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_swab.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_thunder.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_tile.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_version.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_warning.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_win32.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_write.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/tif_zip.obj create mode 100644 wx28X/build/msw/vc_msw/wxtiff/wx_wxtiff.log create mode 100644 wx28X/build/msw/vc_msw/wxtiff/wxtiff.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/wxzlib/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxzlib/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxzlib/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxzlib/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxzlib/adler32.obj create mode 100644 wx28X/build/msw/vc_msw/wxzlib/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxzlib/compress.obj create mode 100644 wx28X/build/msw/vc_msw/wxzlib/crc32.obj create mode 100644 wx28X/build/msw/vc_msw/wxzlib/deflate.obj create mode 100644 wx28X/build/msw/vc_msw/wxzlib/gzio.obj create mode 100644 wx28X/build/msw/vc_msw/wxzlib/infback.obj create mode 100644 wx28X/build/msw/vc_msw/wxzlib/inffast.obj create mode 100644 wx28X/build/msw/vc_msw/wxzlib/inflate.obj create mode 100644 wx28X/build/msw/vc_msw/wxzlib/inftrees.obj create mode 100644 wx28X/build/msw/vc_msw/wxzlib/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/wxzlib/trees.obj create mode 100644 wx28X/build/msw/vc_msw/wxzlib/uncompr.obj create mode 100644 wx28X/build/msw/vc_msw/wxzlib/wx_wxzlib.log create mode 100644 wx28X/build/msw/vc_msw/wxzlib/wxzlib.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/wxzlib/zutil.obj create mode 100644 wx28X/build/msw/vc_msw/xml/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xml/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xml/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xml/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xml/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xml/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xml/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xml/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xml/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/xml/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xml/wx_xml.log create mode 100644 wx28X/build/msw/vc_msw/xml/xml.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/xml/xml.obj create mode 100644 wx28X/build/msw/vc_msw/xml/xml.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xml/xtixml.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xrc/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xrc/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xrc/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xrc/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xrc/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xrc/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xrc/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xrc/dummy.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_msw/xrc/wx_xrc.log create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_animatctrl.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_bmp.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_bmpbt.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_bmpcbox.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_bttn.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_cald.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_chckb.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_chckl.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_choic.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_choicbk.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_clrpicker.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_collpane.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_combo.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_datectrl.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_dirpicker.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_dlg.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_filepicker.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_fontpicker.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_frame.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_gauge.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_gdctl.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_grid.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_html.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_htmllbox.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_hyperlink.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_listb.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_listbk.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_listc.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_mdi.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_menu.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_notbk.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_odcombo.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_panel.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_propdlg.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_radbt.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_radbx.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_scrol.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_scwin.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_sizer.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_slidr.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_spin.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_split.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_statbar.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_stbmp.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_stbox.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_stlin.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_sttxt.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_text.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_tglbtn.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_toolb.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_tree.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_treebk.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_unkwn.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xh_wizrd.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xmlres.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xmlrsall.obj create mode 100644 wx28X/build/msw/vc_msw/xrc/xrc.lastbuildstate create mode 100644 wx28X/build/msw/vc_msw/xrc/xrc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/adv/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/adv/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/adv/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/adv/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/adv/aboutdlg.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/aboutdlgg.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/adv.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswd/adv/adv.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/adv/animatecmn.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/animateg.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/bmpcboxg.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/calctrl.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/adv/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/adv/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/adv/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/adv/datavcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/datavgen.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/datectlg.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/datectrl.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/dummy.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/grid.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/gridctrl.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/gridsel.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/helpext.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/hyperlink.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/joystick.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/laywin.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/adv/odcombo.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/propdlg.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/sashwin.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/sound.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/splash.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/taskbar.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/taskbarcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/tipdlg.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/wizard.obj create mode 100644 wx28X/build/msw/vc_mswd/adv/wx_adv.log create mode 100644 wx28X/build/msw/vc_mswd/base/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/base/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/base/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/base/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/base/appbase.obj create mode 100644 wx28X/build/msw/vc_mswd/base/arcall.obj create mode 100644 wx28X/build/msw/vc_mswd/base/arcfind.obj create mode 100644 wx28X/build/msw/vc_mswd/base/archive.obj create mode 100644 wx28X/build/msw/vc_mswd/base/base.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswd/base/base.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/base/basemsw.obj create mode 100644 wx28X/build/msw/vc_mswd/base/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/base/clntdata.obj create mode 100644 wx28X/build/msw/vc_mswd/base/cmdline.obj create mode 100644 wx28X/build/msw/vc_mswd/base/config.obj create mode 100644 wx28X/build/msw/vc_mswd/base/convauto.obj create mode 100644 wx28X/build/msw/vc_mswd/base/crashrpt.obj create mode 100644 wx28X/build/msw/vc_mswd/base/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/base/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/base/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/base/datetime.obj create mode 100644 wx28X/build/msw/vc_mswd/base/datstrm.obj create mode 100644 wx28X/build/msw/vc_mswd/base/dde.obj create mode 100644 wx28X/build/msw/vc_mswd/base/debughlp.obj create mode 100644 wx28X/build/msw/vc_mswd/base/dir.obj create mode 100644 wx28X/build/msw/vc_mswd/base/dircmn.obj create mode 100644 wx28X/build/msw/vc_mswd/base/dlmsw.obj create mode 100644 wx28X/build/msw/vc_mswd/base/dummy.obj create mode 100644 wx28X/build/msw/vc_mswd/base/dynarray.obj create mode 100644 wx28X/build/msw/vc_mswd/base/dynlib.obj create mode 100644 wx28X/build/msw/vc_mswd/base/dynload.obj create mode 100644 wx28X/build/msw/vc_mswd/base/encconv.obj create mode 100644 wx28X/build/msw/vc_mswd/base/event.obj create mode 100644 wx28X/build/msw/vc_mswd/base/extended.obj create mode 100644 wx28X/build/msw/vc_mswd/base/ffile.obj create mode 100644 wx28X/build/msw/vc_mswd/base/file.obj create mode 100644 wx28X/build/msw/vc_mswd/base/fileback.obj create mode 100644 wx28X/build/msw/vc_mswd/base/fileconf.obj create mode 100644 wx28X/build/msw/vc_mswd/base/filefn.obj create mode 100644 wx28X/build/msw/vc_mswd/base/filename.obj create mode 100644 wx28X/build/msw/vc_mswd/base/filesys.obj create mode 100644 wx28X/build/msw/vc_mswd/base/filtall.obj create mode 100644 wx28X/build/msw/vc_mswd/base/filtfind.obj create mode 100644 wx28X/build/msw/vc_mswd/base/fmapbase.obj create mode 100644 wx28X/build/msw/vc_mswd/base/fs_arc.obj create mode 100644 wx28X/build/msw/vc_mswd/base/fs_filter.obj create mode 100644 wx28X/build/msw/vc_mswd/base/fs_mem.obj create mode 100644 wx28X/build/msw/vc_mswd/base/hash.obj create mode 100644 wx28X/build/msw/vc_mswd/base/hashmap.obj create mode 100644 wx28X/build/msw/vc_mswd/base/init.obj create mode 100644 wx28X/build/msw/vc_mswd/base/intl.obj create mode 100644 wx28X/build/msw/vc_mswd/base/ipcbase.obj create mode 100644 wx28X/build/msw/vc_mswd/base/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/base/list.obj create mode 100644 wx28X/build/msw/vc_mswd/base/log.obj create mode 100644 wx28X/build/msw/vc_mswd/base/longlong.obj create mode 100644 wx28X/build/msw/vc_mswd/base/main.obj create mode 100644 wx28X/build/msw/vc_mswd/base/memory.obj create mode 100644 wx28X/build/msw/vc_mswd/base/mimecmn.obj create mode 100644 wx28X/build/msw/vc_mswd/base/mimetype.obj create mode 100644 wx28X/build/msw/vc_mswd/base/module.obj create mode 100644 wx28X/build/msw/vc_mswd/base/msgout.obj create mode 100644 wx28X/build/msw/vc_mswd/base/mslu.obj create mode 100644 wx28X/build/msw/vc_mswd/base/mstream.obj create mode 100644 wx28X/build/msw/vc_mswd/base/object.obj create mode 100644 wx28X/build/msw/vc_mswd/base/platinfo.obj create mode 100644 wx28X/build/msw/vc_mswd/base/power.obj create mode 100644 wx28X/build/msw/vc_mswd/base/powercmn.obj create mode 100644 wx28X/build/msw/vc_mswd/base/process.obj create mode 100644 wx28X/build/msw/vc_mswd/base/regconf.obj create mode 100644 wx28X/build/msw/vc_mswd/base/regex.obj create mode 100644 wx28X/build/msw/vc_mswd/base/registry.obj create mode 100644 wx28X/build/msw/vc_mswd/base/snglinst.obj create mode 100644 wx28X/build/msw/vc_mswd/base/sstream.obj create mode 100644 wx28X/build/msw/vc_mswd/base/stackwalk.obj create mode 100644 wx28X/build/msw/vc_mswd/base/stdpaths.obj create mode 100644 wx28X/build/msw/vc_mswd/base/stdpbase.obj create mode 100644 wx28X/build/msw/vc_mswd/base/stopwatch.obj create mode 100644 wx28X/build/msw/vc_mswd/base/strconv.obj create mode 100644 wx28X/build/msw/vc_mswd/base/stream.obj create mode 100644 wx28X/build/msw/vc_mswd/base/string.obj create mode 100644 wx28X/build/msw/vc_mswd/base/sysopt.obj create mode 100644 wx28X/build/msw/vc_mswd/base/tarstrm.obj create mode 100644 wx28X/build/msw/vc_mswd/base/textbuf.obj create mode 100644 wx28X/build/msw/vc_mswd/base/textfile.obj create mode 100644 wx28X/build/msw/vc_mswd/base/thread.obj create mode 100644 wx28X/build/msw/vc_mswd/base/tokenzr.obj create mode 100644 wx28X/build/msw/vc_mswd/base/txtstrm.obj create mode 100644 wx28X/build/msw/vc_mswd/base/uri.obj create mode 100644 wx28X/build/msw/vc_mswd/base/utils.obj create mode 100644 wx28X/build/msw/vc_mswd/base/utilscmn.obj create mode 100644 wx28X/build/msw/vc_mswd/base/utilsexc.obj create mode 100644 wx28X/build/msw/vc_mswd/base/variant.obj create mode 100644 wx28X/build/msw/vc_mswd/base/volume.obj create mode 100644 wx28X/build/msw/vc_mswd/base/wfstream.obj create mode 100644 wx28X/build/msw/vc_mswd/base/wx_base.log create mode 100644 wx28X/build/msw/vc_mswd/base/wxchar.obj create mode 100644 wx28X/build/msw/vc_mswd/base/xti.obj create mode 100644 wx28X/build/msw/vc_mswd/base/xtistrm.obj create mode 100644 wx28X/build/msw/vc_mswd/base/zipstrm.obj create mode 100644 wx28X/build/msw/vc_mswd/base/zstream.obj create mode 100644 wx28X/build/msw/vc_mswd/core/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/core/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/core/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/core/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/core/accel.obj create mode 100644 wx28X/build/msw/vc_mswd/core/access.obj create mode 100644 wx28X/build/msw/vc_mswd/core/accesscmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/anidecod.obj create mode 100644 wx28X/build/msw/vc_mswd/core/app.obj create mode 100644 wx28X/build/msw/vc_mswd/core/appcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/artprov.obj create mode 100644 wx28X/build/msw/vc_mswd/core/artstd.obj create mode 100644 wx28X/build/msw/vc_mswd/core/automtn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/bitmap.obj create mode 100644 wx28X/build/msw/vc_mswd/core/bmpbase.obj create mode 100644 wx28X/build/msw/vc_mswd/core/bmpbuttn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/bookctrl.obj create mode 100644 wx28X/build/msw/vc_mswd/core/brush.obj create mode 100644 wx28X/build/msw/vc_mswd/core/busyinfo.obj create mode 100644 wx28X/build/msw/vc_mswd/core/button.obj create mode 100644 wx28X/build/msw/vc_mswd/core/buttonbar.obj create mode 100644 wx28X/build/msw/vc_mswd/core/caret.obj create mode 100644 wx28X/build/msw/vc_mswd/core/checkbox.obj create mode 100644 wx28X/build/msw/vc_mswd/core/checklst.obj create mode 100644 wx28X/build/msw/vc_mswd/core/choicbkg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/choiccmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/choicdgg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/choice.obj create mode 100644 wx28X/build/msw/vc_mswd/core/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/core/clipbrd.obj create mode 100644 wx28X/build/msw/vc_mswd/core/clipcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/clrpickercmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/clrpickerg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/cmdproc.obj create mode 100644 wx28X/build/msw/vc_mswd/core/cmndata.obj create mode 100644 wx28X/build/msw/vc_mswd/core/collpaneg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/colordlg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/colour.obj create mode 100644 wx28X/build/msw/vc_mswd/core/colourcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/combo.obj create mode 100644 wx28X/build/msw/vc_mswd/core/combobox.obj create mode 100644 wx28X/build/msw/vc_mswd/core/combocmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/combog.obj create mode 100644 wx28X/build/msw/vc_mswd/core/containr.obj create mode 100644 wx28X/build/msw/vc_mswd/core/control.obj create mode 100644 wx28X/build/msw/vc_mswd/core/core.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswd/core/core.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/core/cshelp.obj create mode 100644 wx28X/build/msw/vc_mswd/core/ctrlcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/ctrlsub.obj create mode 100644 wx28X/build/msw/vc_mswd/core/cursor.obj create mode 100644 wx28X/build/msw/vc_mswd/core/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/core/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/core/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/core/data.obj create mode 100644 wx28X/build/msw/vc_mswd/core/datacmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dataobj.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dc.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dcbase.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dcbufcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dcclient.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dcgraph.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dcmemory.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dcprint.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dcpsg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dcscreen.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dialog.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dialup.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dib.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dirctrlg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dirdlg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/display.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dlgcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dndcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dobjcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/docmdi.obj create mode 100644 wx28X/build/msw/vc_mswd/core/docview.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dpycmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dragimag.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dragimgg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dropsrc.obj create mode 100644 wx28X/build/msw/vc_mswd/core/droptgt.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dseldlg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/dummy.obj create mode 100644 wx28X/build/msw/vc_mswd/core/effects.obj create mode 100644 wx28X/build/msw/vc_mswd/core/enhmeta.obj create mode 100644 wx28X/build/msw/vc_mswd/core/event.obj create mode 100644 wx28X/build/msw/vc_mswd/core/evtloop.obj create mode 100644 wx28X/build/msw/vc_mswd/core/evtloopcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/fddlgcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/fdrepdlg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/filedlg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/filepickercmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/filepickerg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/fldlgcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/font.obj create mode 100644 wx28X/build/msw/vc_mswd/core/fontcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/fontdlg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/fontenum.obj create mode 100644 wx28X/build/msw/vc_mswd/core/fontenumcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/fontmap.obj create mode 100644 wx28X/build/msw/vc_mswd/core/fontpickercmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/fontpickerg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/fontutil.obj create mode 100644 wx28X/build/msw/vc_mswd/core/frame.obj create mode 100644 wx28X/build/msw/vc_mswd/core/framecmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/fs_mem.obj create mode 100644 wx28X/build/msw/vc_mswd/core/gauge95.obj create mode 100644 wx28X/build/msw/vc_mswd/core/gaugecmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/gbsizer.obj create mode 100644 wx28X/build/msw/vc_mswd/core/gdicmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/gdiimage.obj create mode 100644 wx28X/build/msw/vc_mswd/core/gdiobj.obj create mode 100644 wx28X/build/msw/vc_mswd/core/geometry.obj create mode 100644 wx28X/build/msw/vc_mswd/core/gifdecod.obj create mode 100644 wx28X/build/msw/vc_mswd/core/graphcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/graphics.obj create mode 100644 wx28X/build/msw/vc_mswd/core/gsockmsw.obj create mode 100644 wx28X/build/msw/vc_mswd/core/helpbase.obj create mode 100644 wx28X/build/msw/vc_mswd/core/helpchm.obj create mode 100644 wx28X/build/msw/vc_mswd/core/helpwin.obj create mode 100644 wx28X/build/msw/vc_mswd/core/icon.obj create mode 100644 wx28X/build/msw/vc_mswd/core/iconbndl.obj create mode 100644 wx28X/build/msw/vc_mswd/core/imagall.obj create mode 100644 wx28X/build/msw/vc_mswd/core/imagbmp.obj create mode 100644 wx28X/build/msw/vc_mswd/core/image.obj create mode 100644 wx28X/build/msw/vc_mswd/core/imagfill.obj create mode 100644 wx28X/build/msw/vc_mswd/core/imaggif.obj create mode 100644 wx28X/build/msw/vc_mswd/core/imagiff.obj create mode 100644 wx28X/build/msw/vc_mswd/core/imagjpeg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/imaglist.obj create mode 100644 wx28X/build/msw/vc_mswd/core/imagpcx.obj create mode 100644 wx28X/build/msw/vc_mswd/core/imagpng.obj create mode 100644 wx28X/build/msw/vc_mswd/core/imagpnm.obj create mode 100644 wx28X/build/msw/vc_mswd/core/imagtga.obj create mode 100644 wx28X/build/msw/vc_mswd/core/imagtiff.obj create mode 100644 wx28X/build/msw/vc_mswd/core/imagxpm.obj create mode 100644 wx28X/build/msw/vc_mswd/core/iniconf.obj create mode 100644 wx28X/build/msw/vc_mswd/core/layout.obj create mode 100644 wx28X/build/msw/vc_mswd/core/lboxcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/core/listbkg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/listbox.obj create mode 100644 wx28X/build/msw/vc_mswd/core/listctrl.obj create mode 100644 wx28X/build/msw/vc_mswd/core/listctrlcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/logg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/main.obj create mode 100644 wx28X/build/msw/vc_mswd/core/matrix.obj create mode 100644 wx28X/build/msw/vc_mswd/core/mdi.obj create mode 100644 wx28X/build/msw/vc_mswd/core/menu.obj create mode 100644 wx28X/build/msw/vc_mswd/core/menucmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/menuitem.obj create mode 100644 wx28X/build/msw/vc_mswd/core/metafile.obj create mode 100644 wx28X/build/msw/vc_mswd/core/minifram.obj create mode 100644 wx28X/build/msw/vc_mswd/core/msgdlg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/msgout.obj create mode 100644 wx28X/build/msw/vc_mswd/core/mslu.obj create mode 100644 wx28X/build/msw/vc_mswd/core/nativdlg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/nbkbase.obj create mode 100644 wx28X/build/msw/vc_mswd/core/notebook.obj create mode 100644 wx28X/build/msw/vc_mswd/core/numdlgg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/oleutils.obj create mode 100644 wx28X/build/msw/vc_mswd/core/overlaycmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/ownerdrw.obj create mode 100644 wx28X/build/msw/vc_mswd/core/palette.obj create mode 100644 wx28X/build/msw/vc_mswd/core/panelg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/paper.obj create mode 100644 wx28X/build/msw/vc_mswd/core/pen.obj create mode 100644 wx28X/build/msw/vc_mswd/core/pickerbase.obj create mode 100644 wx28X/build/msw/vc_mswd/core/popupcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/popupwin.obj create mode 100644 wx28X/build/msw/vc_mswd/core/printdlg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/printps.obj create mode 100644 wx28X/build/msw/vc_mswd/core/printwin.obj create mode 100644 wx28X/build/msw/vc_mswd/core/prntbase.obj create mode 100644 wx28X/build/msw/vc_mswd/core/prntdlgg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/progdlgg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/quantize.obj create mode 100644 wx28X/build/msw/vc_mswd/core/radiobox.obj create mode 100644 wx28X/build/msw/vc_mswd/core/radiobut.obj create mode 100644 wx28X/build/msw/vc_mswd/core/radiocmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/region.obj create mode 100644 wx28X/build/msw/vc_mswd/core/rendcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/renderer.obj create mode 100644 wx28X/build/msw/vc_mswd/core/renderg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/rgncmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/scrlwing.obj create mode 100644 wx28X/build/msw/vc_mswd/core/scrolbar.obj create mode 100644 wx28X/build/msw/vc_mswd/core/selstore.obj create mode 100644 wx28X/build/msw/vc_mswd/core/settcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/settings.obj create mode 100644 wx28X/build/msw/vc_mswd/core/sizer.obj create mode 100644 wx28X/build/msw/vc_mswd/core/slider95.obj create mode 100644 wx28X/build/msw/vc_mswd/core/spinbutt.obj create mode 100644 wx28X/build/msw/vc_mswd/core/spinctlg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/spinctrl.obj create mode 100644 wx28X/build/msw/vc_mswd/core/splitter.obj create mode 100644 wx28X/build/msw/vc_mswd/core/srchcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/srchctlg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/statbar.obj create mode 100644 wx28X/build/msw/vc_mswd/core/statbmp.obj create mode 100644 wx28X/build/msw/vc_mswd/core/statbox.obj create mode 100644 wx28X/build/msw/vc_mswd/core/statbr95.obj create mode 100644 wx28X/build/msw/vc_mswd/core/statline.obj create mode 100644 wx28X/build/msw/vc_mswd/core/stattext.obj create mode 100644 wx28X/build/msw/vc_mswd/core/statusbr.obj create mode 100644 wx28X/build/msw/vc_mswd/core/stockitem.obj create mode 100644 wx28X/build/msw/vc_mswd/core/tabctrl.obj create mode 100644 wx28X/build/msw/vc_mswd/core/tbar95.obj create mode 100644 wx28X/build/msw/vc_mswd/core/tbarbase.obj create mode 100644 wx28X/build/msw/vc_mswd/core/textcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/textctrl.obj create mode 100644 wx28X/build/msw/vc_mswd/core/textdlgg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/tglbtn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/timer.obj create mode 100644 wx28X/build/msw/vc_mswd/core/timercmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/tipwin.obj create mode 100644 wx28X/build/msw/vc_mswd/core/toolbkg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/tooltip.obj create mode 100644 wx28X/build/msw/vc_mswd/core/toplevel.obj create mode 100644 wx28X/build/msw/vc_mswd/core/toplvcmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/treebase.obj create mode 100644 wx28X/build/msw/vc_mswd/core/treebkg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/treectlg.obj create mode 100644 wx28X/build/msw/vc_mswd/core/treectrl.obj create mode 100644 wx28X/build/msw/vc_mswd/core/utilscmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/utilsgui.obj create mode 100644 wx28X/build/msw/vc_mswd/core/uuid.obj create mode 100644 wx28X/build/msw/vc_mswd/core/uxtheme.obj create mode 100644 wx28X/build/msw/vc_mswd/core/valgen.obj create mode 100644 wx28X/build/msw/vc_mswd/core/validate.obj create mode 100644 wx28X/build/msw/vc_mswd/core/valtext.obj create mode 100644 wx28X/build/msw/vc_mswd/core/vlbox.obj create mode 100644 wx28X/build/msw/vc_mswd/core/volume.obj create mode 100644 wx28X/build/msw/vc_mswd/core/vscroll.obj create mode 100644 wx28X/build/msw/vc_mswd/core/wincmn.obj create mode 100644 wx28X/build/msw/vc_mswd/core/window.obj create mode 100644 wx28X/build/msw/vc_mswd/core/wx_core.log create mode 100644 wx28X/build/msw/vc_mswd/core/xpmdecod.obj create mode 100644 wx28X/build/msw/vc_mswd/html/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/html/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/html/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/html/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/html/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/html/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/html/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/html/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/html/dummy.obj create mode 100644 wx28X/build/msw/vc_mswd/html/helpbest.obj create mode 100644 wx28X/build/msw/vc_mswd/html/helpctrl.obj create mode 100644 wx28X/build/msw/vc_mswd/html/helpdata.obj create mode 100644 wx28X/build/msw/vc_mswd/html/helpdlg.obj create mode 100644 wx28X/build/msw/vc_mswd/html/helpfrm.obj create mode 100644 wx28X/build/msw/vc_mswd/html/helpwnd.obj create mode 100644 wx28X/build/msw/vc_mswd/html/html.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswd/html/html.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/html/htmlcell.obj create mode 100644 wx28X/build/msw/vc_mswd/html/htmlfilt.obj create mode 100644 wx28X/build/msw/vc_mswd/html/htmllbox.obj create mode 100644 wx28X/build/msw/vc_mswd/html/htmlpars.obj create mode 100644 wx28X/build/msw/vc_mswd/html/htmltag.obj create mode 100644 wx28X/build/msw/vc_mswd/html/htmlwin.obj create mode 100644 wx28X/build/msw/vc_mswd/html/htmprint.obj create mode 100644 wx28X/build/msw/vc_mswd/html/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/html/m_dflist.obj create mode 100644 wx28X/build/msw/vc_mswd/html/m_fonts.obj create mode 100644 wx28X/build/msw/vc_mswd/html/m_hline.obj create mode 100644 wx28X/build/msw/vc_mswd/html/m_image.obj create mode 100644 wx28X/build/msw/vc_mswd/html/m_layout.obj create mode 100644 wx28X/build/msw/vc_mswd/html/m_links.obj create mode 100644 wx28X/build/msw/vc_mswd/html/m_list.obj create mode 100644 wx28X/build/msw/vc_mswd/html/m_pre.obj create mode 100644 wx28X/build/msw/vc_mswd/html/m_style.obj create mode 100644 wx28X/build/msw/vc_mswd/html/m_tables.obj create mode 100644 wx28X/build/msw/vc_mswd/html/winpars.obj create mode 100644 wx28X/build/msw/vc_mswd/html/wx_html.log create mode 100644 wx28X/build/msw/vc_mswd/net/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/net/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/net/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/net/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/net/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/net/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/net/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/net/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/net/dummy.obj create mode 100644 wx28X/build/msw/vc_mswd/net/fs_inet.obj create mode 100644 wx28X/build/msw/vc_mswd/net/ftp.obj create mode 100644 wx28X/build/msw/vc_mswd/net/gsocket.obj create mode 100644 wx28X/build/msw/vc_mswd/net/http.obj create mode 100644 wx28X/build/msw/vc_mswd/net/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/net/net.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswd/net/net.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/net/protocol.obj create mode 100644 wx28X/build/msw/vc_mswd/net/sckaddr.obj create mode 100644 wx28X/build/msw/vc_mswd/net/sckfile.obj create mode 100644 wx28X/build/msw/vc_mswd/net/sckipc.obj create mode 100644 wx28X/build/msw/vc_mswd/net/sckstrm.obj create mode 100644 wx28X/build/msw/vc_mswd/net/socket.obj create mode 100644 wx28X/build/msw/vc_mswd/net/url.obj create mode 100644 wx28X/build/msw/vc_mswd/net/urlmsw.obj create mode 100644 wx28X/build/msw/vc_mswd/net/wx_net.log create mode 100644 wx28X/build/msw/vc_mswd/wxexpat/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxexpat/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxexpat/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxexpat/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxexpat/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxexpat/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxexpat/wx_wxexpat.log create mode 100644 wx28X/build/msw/vc_mswd/wxexpat/wxexpat.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswd/wxexpat/xmlparse.obj create mode 100644 wx28X/build/msw/vc_mswd/wxexpat/xmlrole.obj create mode 100644 wx28X/build/msw/vc_mswd/wxexpat/xmltok.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jcapimin.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jcapistd.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jccoefct.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jccolor.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jcdctmgr.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jchuff.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jcinit.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jcmainct.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jcmarker.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jcmaster.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jcomapi.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jcparam.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jcphuff.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jcprepct.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jcsample.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jctrans.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdapimin.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdapistd.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdatadst.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdatasrc.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdcoefct.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdcolor.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jddctmgr.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdhuff.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdinput.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdmainct.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdmarker.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdmaster.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdmerge.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdphuff.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdpostct.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdsample.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jdtrans.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jerror.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jfdctflt.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jfdctfst.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jfdctint.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jidctflt.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jidctfst.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jidctint.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jidctred.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jmemmgr.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jmemnobs.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jquant1.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jquant2.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/jutils.obj create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/wx_wxjpeg.log create mode 100644 wx28X/build/msw/vc_mswd/wxjpeg/wxjpeg.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswd/wxpng/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxpng/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxpng/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxpng/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxpng/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxpng/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxpng/png.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngerror.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pnggccrd.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngget.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngmem.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngpread.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngread.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngrio.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngrtran.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngrutil.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngset.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngtrans.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngvcrd.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngwio.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngwrite.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngwtran.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/pngwutil.obj create mode 100644 wx28X/build/msw/vc_mswd/wxpng/wx_wxpng.log create mode 100644 wx28X/build/msw/vc_mswd/wxpng/wxpng.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswd/wxpng/wxpng.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxprec_advlib.pch create mode 100644 wx28X/build/msw/vc_mswd/wxprec_baselib.pch create mode 100644 wx28X/build/msw/vc_mswd/wxprec_corelib.pch create mode 100644 wx28X/build/msw/vc_mswd/wxprec_htmllib.pch create mode 100644 wx28X/build/msw/vc_mswd/wxprec_netlib.pch create mode 100644 wx28X/build/msw/vc_mswd/wxregex/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxregex/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxregex/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxregex/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxregex/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxregex/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxregex/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxregex/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxregex/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxregex/regcomp.obj create mode 100644 wx28X/build/msw/vc_mswd/wxregex/regerror.obj create mode 100644 wx28X/build/msw/vc_mswd/wxregex/regexec.obj create mode 100644 wx28X/build/msw/vc_mswd/wxregex/regfree.obj create mode 100644 wx28X/build/msw/vc_mswd/wxregex/wx_wxregex.log create mode 100644 wx28X/build/msw/vc_mswd/wxregex/wxregex.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_aux.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_close.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_codec.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_color.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_compress.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_dir.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_dirinfo.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_dirread.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_dirwrite.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_dumpmode.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_error.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_extension.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_fax3.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_fax3sm.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_flush.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_getimage.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_jpeg.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_luv.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_lzw.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_next.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_open.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_packbits.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_pixarlog.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_predict.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_print.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_read.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_strip.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_swab.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_thunder.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_tile.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_version.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_warning.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_win32.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_write.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/tif_zip.obj create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/wx_wxtiff.log create mode 100644 wx28X/build/msw/vc_mswd/wxtiff/wxtiff.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/adler32.obj create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/compress.obj create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/crc32.obj create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/deflate.obj create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/gzio.obj create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/infback.obj create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/inffast.obj create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/inflate.obj create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/inftrees.obj create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/trees.obj create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/uncompr.obj create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/wx_wxzlib.log create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/wxzlib.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswd/wxzlib/zutil.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/aboutdlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/aboutdlgg.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/adv.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/adv/adv.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/adv/adv.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/adv/adv.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/adv/adv.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/adv/adv.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/adv_manifest.rc create mode 100644 wx28X/build/msw/vc_mswddll/adv/animatecmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/animateg.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/bmpcboxg.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/calctrl.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/datavcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/datavgen.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/datectlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/datectrl.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/grid.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/gridctrl.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/gridsel.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/helpext.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/hyperlink.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/joystick.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/laywin.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/link.3868-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/link.3868-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/link.3868.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/link.3868.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/odcombo.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/propdlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/adv/sashwin.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/sound.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/splash.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/taskbar.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/taskbarcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/tipdlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/version.res create mode 100644 wx28X/build/msw/vc_mswddll/adv/wizard.obj create mode 100644 wx28X/build/msw/vc_mswddll/adv/wx_adv.log create mode 100644 wx28X/build/msw/vc_mswddll/aui/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/aui.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/aui/aui.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/aui/aui.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/aui/aui.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/aui/aui.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/aui/aui.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/aui_manifest.rc create mode 100644 wx28X/build/msw/vc_mswddll/aui/auibar.obj create mode 100644 wx28X/build/msw/vc_mswddll/aui/auibook.obj create mode 100644 wx28X/build/msw/vc_mswddll/aui/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/dockart.obj create mode 100644 wx28X/build/msw/vc_mswddll/aui/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/aui/floatpane.obj create mode 100644 wx28X/build/msw/vc_mswddll/aui/framemanager.obj create mode 100644 wx28X/build/msw/vc_mswddll/aui/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/link.1208-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/link.1208-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/link.1208.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/link.1208.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/aui/tabmdi.obj create mode 100644 wx28X/build/msw/vc_mswddll/aui/version.res create mode 100644 wx28X/build/msw/vc_mswddll/aui/wx_aui.log create mode 100644 wx28X/build/msw/vc_mswddll/base/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/appbase.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/arcall.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/arcfind.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/archive.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/base.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/base/base.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/basemsw.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/clntdata.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/cmdline.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/config.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/convauto.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/crashrpt.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/datetime.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/datstrm.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/dde.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/debughlp.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/dir.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/dircmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/dlmsw.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/dynarray.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/dynlib.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/dynload.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/encconv.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/event.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/extended.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/ffile.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/file.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/fileback.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/fileconf.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/filefn.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/filename.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/filesys.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/filtall.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/filtfind.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/fmapbase.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/fs_arc.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/fs_filter.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/fs_mem.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/hash.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/hashmap.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/init.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/intl.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/ipcbase.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/list.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/log.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/longlong.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/main.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/memory.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/mimecmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/mimetype.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/module.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/msgout.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/mslu.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/mstream.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/object.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/platinfo.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/power.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/powercmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/process.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/base/regconf.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/regex.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/registry.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/snglinst.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/sstream.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/stackwalk.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/stdpaths.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/stdpbase.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/stopwatch.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/strconv.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/stream.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/string.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/sysopt.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/tarstrm.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/textbuf.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/textfile.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/thread.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/tokenzr.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/txtstrm.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/uri.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/utils.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/utilscmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/utilsexc.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/variant.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/version.res create mode 100644 wx28X/build/msw/vc_mswddll/base/volume.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/wfstream.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/wx_base.log create mode 100644 wx28X/build/msw/vc_mswddll/base/wxbase28d_vc_custom.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/base/wxbase28d_vc_custom.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/base/wxbase28d_vc_custom.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/base/wxbase28d_vc_custom.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/base/wxbase28d_vc_custom_manifest.rc create mode 100644 wx28X/build/msw/vc_mswddll/base/wxchar.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/xti.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/xtistrm.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/zipstrm.obj create mode 100644 wx28X/build/msw/vc_mswddll/base/zstream.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/accel.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/access.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/accesscmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/anidecod.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/app.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/appcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/artprov.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/artstd.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/automtn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/bitmap.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/bmpbase.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/bmpbuttn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/bookctrl.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/brush.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/busyinfo.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/button.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/buttonbar.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/caret.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/checkbox.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/checklst.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/choicbkg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/choiccmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/choicdgg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/choice.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/clipbrd.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/clipcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/clrpickercmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/clrpickerg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/cmdproc.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/cmndata.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/collpaneg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/colordlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/colour.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/colourcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/combo.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/combobox.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/combocmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/combog.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/containr.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/control.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/core.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/core/core.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/core/core.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/core/core.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/core/core.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/core/core.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/core_manifest.rc create mode 100644 wx28X/build/msw/vc_mswddll/core/cshelp.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/ctrlcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/ctrlsub.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/cursor.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/data.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/datacmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dataobj.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dc.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dcbase.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dcbufcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dcclient.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dcgraph.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dcmemory.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dcprint.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dcpsg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dcscreen.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dialog.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dialup.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dib.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dirctrlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dirdlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/display.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dlgcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dndcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dobjcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/docmdi.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/docview.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dpycmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dragimag.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dragimgg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dropsrc.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/droptgt.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dseldlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/effects.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/enhmeta.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/event.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/evtloop.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/evtloopcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/fddlgcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/fdrepdlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/filedlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/filepickercmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/filepickerg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/fldlgcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/font.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/fontcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/fontdlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/fontenum.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/fontenumcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/fontmap.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/fontpickercmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/fontpickerg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/fontutil.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/frame.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/framecmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/fs_mem.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/gauge95.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/gaugecmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/gbsizer.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/gdicmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/gdiimage.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/gdiobj.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/geometry.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/gifdecod.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/graphcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/graphics.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/gsockmsw.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/helpbase.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/helpchm.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/helpwin.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/icon.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/iconbndl.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/imagall.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/imagbmp.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/image.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/imagfill.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/imaggif.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/imagiff.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/imagjpeg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/imaglist.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/imagpcx.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/imagpng.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/imagpnm.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/imagtga.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/imagtiff.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/imagxpm.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/iniconf.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/layout.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/lboxcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/link.1340-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/link.1340-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/link.1340.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/link.1340.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/listbkg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/listbox.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/listctrl.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/listctrlcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/logg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/main.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/matrix.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/mdi.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/menu.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/menucmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/menuitem.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/metafile.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/minifram.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/msgdlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/msgout.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/mslu.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/nativdlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/nbkbase.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/notebook.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/numdlgg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/oleutils.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/overlaycmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/ownerdrw.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/palette.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/panelg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/paper.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/pen.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/pickerbase.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/popupcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/popupwin.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/printdlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/printps.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/printwin.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/prntbase.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/prntdlgg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/progdlgg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/quantize.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/radiobox.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/radiobut.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/radiocmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/core/region.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/rendcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/renderer.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/renderg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/rgncmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/scrlwing.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/scrolbar.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/selstore.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/settcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/settings.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/sizer.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/slider95.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/spinbutt.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/spinctlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/spinctrl.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/splitter.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/srchcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/srchctlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/statbar.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/statbmp.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/statbox.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/statbr95.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/statline.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/stattext.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/statusbr.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/stockitem.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/tabctrl.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/tbar95.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/tbarbase.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/textcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/textctrl.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/textdlgg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/tglbtn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/timer.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/timercmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/tipwin.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/toolbkg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/tooltip.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/toplevel.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/toplvcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/treebase.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/treebkg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/treectlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/treectrl.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/utilscmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/utilsgui.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/uuid.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/uxtheme.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/valgen.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/validate.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/valtext.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/version.res create mode 100644 wx28X/build/msw/vc_mswddll/core/vlbox.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/volume.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/vscroll.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/wincmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/window.obj create mode 100644 wx28X/build/msw/vc_mswddll/core/wx_core.log create mode 100644 wx28X/build/msw/vc_mswddll/core/xpmdecod.obj create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/dbgrid.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/dbgrid.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/dbgrid.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/dbgrid.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/dbgrid.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/dbgrid.obj create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/dbgrid.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/dbgrid_manifest.rc create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/link.5000-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/link.5000-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/link.5000.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/link.5000.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/version.res create mode 100644 wx28X/build/msw/vc_mswddll/dbgrid/wx_dbgrid.log create mode 100644 wx28X/build/msw/vc_mswddll/gl/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/gl/gl.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/gl/gl.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/gl/gl.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/gl/gl.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/gl/gl.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/gl/gl.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/gl_manifest.rc create mode 100644 wx28X/build/msw/vc_mswddll/gl/glcanvas.obj create mode 100644 wx28X/build/msw/vc_mswddll/gl/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/link.5640-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/link.5640-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/link.5640.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/link.5640.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/gl/version.res create mode 100644 wx28X/build/msw/vc_mswddll/gl/wx_gl.log create mode 100644 wx28X/build/msw/vc_mswddll/html/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/helpbest.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/helpctrl.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/helpdata.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/helpdlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/helpfrm.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/helpwnd.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/html.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/html/html.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/html/html.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/html/html.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/html/html.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/html/html.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/html_manifest.rc create mode 100644 wx28X/build/msw/vc_mswddll/html/htmlcell.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/htmlfilt.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/htmllbox.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/htmlpars.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/htmltag.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/htmlwin.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/htmprint.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/link.3040-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/link.3040-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/link.3040.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/link.3040.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/m_dflist.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/m_fonts.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/m_hline.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/m_image.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/m_layout.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/m_links.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/m_list.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/m_pre.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/m_style.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/m_tables.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/html/version.res create mode 100644 wx28X/build/msw/vc_mswddll/html/winpars.obj create mode 100644 wx28X/build/msw/vc_mswddll/html/wx_html.log create mode 100644 wx28X/build/msw/vc_mswddll/media/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/activex.obj create mode 100644 wx28X/build/msw/vc_mswddll/media/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/media/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/link.1076-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/link.1076-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/link.1076.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/link.1076.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/media.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/media/media.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/media/media.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/media/media.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/media/media.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/media/media.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/media_manifest.rc create mode 100644 wx28X/build/msw/vc_mswddll/media/mediactrl_am.obj create mode 100644 wx28X/build/msw/vc_mswddll/media/mediactrl_qt.obj create mode 100644 wx28X/build/msw/vc_mswddll/media/mediactrl_wmp10.obj create mode 100644 wx28X/build/msw/vc_mswddll/media/mediactrlcmn.obj create mode 100644 wx28X/build/msw/vc_mswddll/media/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/media/version.res create mode 100644 wx28X/build/msw/vc_mswddll/media/wx_media.log create mode 100644 wx28X/build/msw/vc_mswddll/net/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/net/fs_inet.obj create mode 100644 wx28X/build/msw/vc_mswddll/net/ftp.obj create mode 100644 wx28X/build/msw/vc_mswddll/net/gsocket.obj create mode 100644 wx28X/build/msw/vc_mswddll/net/http.obj create mode 100644 wx28X/build/msw/vc_mswddll/net/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/link.4276-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/link.4276-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/link.4276.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/link.4276.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/net.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/net/net.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/net/net.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/net/net.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/net/net.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/net/net.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/net_manifest.rc create mode 100644 wx28X/build/msw/vc_mswddll/net/protocol.obj create mode 100644 wx28X/build/msw/vc_mswddll/net/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/net/sckaddr.obj create mode 100644 wx28X/build/msw/vc_mswddll/net/sckfile.obj create mode 100644 wx28X/build/msw/vc_mswddll/net/sckipc.obj create mode 100644 wx28X/build/msw/vc_mswddll/net/sckstrm.obj create mode 100644 wx28X/build/msw/vc_mswddll/net/socket.obj create mode 100644 wx28X/build/msw/vc_mswddll/net/url.obj create mode 100644 wx28X/build/msw/vc_mswddll/net/urlmsw.obj create mode 100644 wx28X/build/msw/vc_mswddll/net/version.res create mode 100644 wx28X/build/msw/vc_mswddll/net/wx_net.log create mode 100644 wx28X/build/msw/vc_mswddll/odbc/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/db.obj create mode 100644 wx28X/build/msw/vc_mswddll/odbc/dbtable.obj create mode 100644 wx28X/build/msw/vc_mswddll/odbc/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/odbc/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/link.4432-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/link.4432-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/link.4432.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/link.4432.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/odbc.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/odbc/odbc.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/odbc/odbc.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/odbc/odbc.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/odbc/odbc.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/odbc/odbc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/odbc_manifest.rc create mode 100644 wx28X/build/msw/vc_mswddll/odbc/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/odbc/version.res create mode 100644 wx28X/build/msw/vc_mswddll/odbc/wx_odbc.log create mode 100644 wx28X/build/msw/vc_mswddll/qa/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/dbgrptg.obj create mode 100644 wx28X/build/msw/vc_mswddll/qa/debugrpt.obj create mode 100644 wx28X/build/msw/vc_mswddll/qa/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/qa/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/link.1424-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/link.1424-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/link.1424.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/link.1424.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/qa.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/qa/qa.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/qa/qa.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/qa/qa.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/qa/qa.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/qa/qa.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/qa_manifest.rc create mode 100644 wx28X/build/msw/vc_mswddll/qa/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/qa/version.res create mode 100644 wx28X/build/msw/vc_mswddll/qa/wx_qa.log create mode 100644 wx28X/build/msw/vc_mswddll/richtext/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/richtext/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/link.1992-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/link.1992-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/link.1992.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/link.1992.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtext.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtext.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtext.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtext.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtext.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtext.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtext_manifest.rc create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtextbuffer.obj create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtextctrl.obj create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtextformatdlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtexthtml.obj create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtextprint.obj create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtextstyledlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtextstyles.obj create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtextsymboldlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/richtext/richtextxml.obj create mode 100644 wx28X/build/msw/vc_mswddll/richtext/version.res create mode 100644 wx28X/build/msw/vc_mswddll/richtext/wx_richtext.log create mode 100644 wx28X/build/msw/vc_mswddll/wxexpat/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxexpat/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxexpat/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxexpat/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxexpat/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxexpat/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxexpat/wx_wxexpat.log create mode 100644 wx28X/build/msw/vc_mswddll/wxexpat/wxexpat.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/wxexpat/wxexpatd.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/wxexpat/xmlparse.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxexpat/xmlrole.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxexpat/xmltok.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jcapimin.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jcapistd.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jccoefct.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jccolor.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jcdctmgr.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jchuff.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jcinit.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jcmainct.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jcmarker.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jcmaster.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jcomapi.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jcparam.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jcphuff.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jcprepct.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jcsample.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jctrans.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdapimin.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdapistd.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdatadst.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdatasrc.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdcoefct.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdcolor.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jddctmgr.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdhuff.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdinput.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdmainct.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdmarker.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdmaster.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdmerge.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdphuff.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdpostct.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdsample.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jdtrans.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jerror.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jfdctflt.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jfdctfst.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jfdctint.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jidctflt.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jidctfst.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jidctint.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jidctred.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jmemmgr.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jmemnobs.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jquant1.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jquant2.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/jutils.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/wx_wxjpeg.log create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/wxjpeg.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/wxjpeg/wxjpegd.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/png.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngerror.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pnggccrd.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngget.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngmem.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngpread.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngread.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngrio.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngrtran.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngrutil.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngset.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngtrans.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngvcrd.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngwio.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngwrite.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngwtran.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/pngwutil.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/wx_wxpng.log create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/wxpng.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/wxpng.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxpng/wxpngd.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_advdll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_auidll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_basedll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_coredll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_dbgriddll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_gldll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_htmldll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_mediadll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_netdll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_odbcdll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_qadll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_richtextdll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_xmldll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxprec_xrcdll.pch create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/regcomp.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/regerror.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/regexec.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/regfree.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/wx_wxregex.log create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/wxregex.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/wxregex/wxregexd.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_aux.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_close.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_codec.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_color.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_compress.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_dir.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_dirinfo.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_dirread.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_dirwrite.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_dumpmode.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_error.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_extension.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_fax3.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_fax3sm.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_flush.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_getimage.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_jpeg.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_luv.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_lzw.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_next.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_open.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_packbits.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_pixarlog.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_predict.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_print.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_read.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_strip.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_swab.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_thunder.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_tile.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_version.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_warning.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_win32.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_write.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/tif_zip.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/wx_wxtiff.log create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/wxtiff.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/wxtiff/wxtiffd.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/adler32.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/compress.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/crc32.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/deflate.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/gzio.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/infback.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/inffast.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/inflate.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/inftrees.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/trees.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/uncompr.obj create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/wx_wxzlib.log create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/wxzlib.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/wxzlibd.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/wxzlib/zutil.obj create mode 100644 wx28X/build/msw/vc_mswddll/xml/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/xml/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/link.3680-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/link.3680-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/link.3680.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/link.3680.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/version.res create mode 100644 wx28X/build/msw/vc_mswddll/xml/wx_xml.log create mode 100644 wx28X/build/msw/vc_mswddll/xml/xml.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/xml/xml.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/xml/xml.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/xml/xml.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/xml/xml.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/xml/xml.obj create mode 100644 wx28X/build/msw/vc_mswddll/xml/xml.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xml/xml_manifest.rc create mode 100644 wx28X/build/msw/vc_mswddll/xml/xtixml.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/dummy.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/link.4340-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/link.4340-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/link.4340.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/link.4340.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/version.res create mode 100644 wx28X/build/msw/vc_mswddll/xrc/wx_xrc.log create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_animatctrl.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_bmp.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_bmpbt.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_bmpcbox.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_bttn.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_cald.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_chckb.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_chckl.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_choic.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_choicbk.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_clrpicker.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_collpane.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_combo.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_datectrl.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_dirpicker.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_dlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_filepicker.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_fontpicker.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_frame.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_gauge.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_gdctl.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_grid.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_html.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_htmllbox.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_hyperlink.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_listb.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_listbk.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_listc.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_mdi.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_menu.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_notbk.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_odcombo.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_panel.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_propdlg.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_radbt.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_radbx.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_scrol.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_scwin.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_sizer.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_slidr.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_spin.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_split.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_statbar.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_stbmp.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_stbox.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_stlin.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_sttxt.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_text.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_tglbtn.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_toolb.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_tree.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_treebk.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_unkwn.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xh_wizrd.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xmlres.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xmlrsall.obj create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xrc.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xrc.dll.embed.manifest create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xrc.dll.embed.manifest.res create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xrc.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xrc.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xrc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswddll/xrc/xrc_manifest.rc create mode 100644 wx28X/build/msw/vc_mswdll/adv/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/ResolveAssemblyReference.cache create mode 100644 wx28X/build/msw/vc_mswdll/adv/aboutdlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/aboutdlgg.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/adv.Build.CppClean.log create mode 100644 wx28X/build/msw/vc_mswdll/adv/adv.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/adv/adv.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/adv/adv.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/animatecmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/animateg.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/bmpcboxg.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/calctrl.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/datavcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/datavgen.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/datectlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/datectrl.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/grid.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/gridctrl.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/gridsel.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/helpext.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/hyperlink.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/joystick.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/laywin.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/odcombo.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/propdlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/adv/sashwin.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/sound.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/splash.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/taskbar.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/taskbarcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/tipdlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/version.res create mode 100644 wx28X/build/msw/vc_mswdll/adv/wizard.obj create mode 100644 wx28X/build/msw/vc_mswdll/adv/wx_adv.log create mode 100644 wx28X/build/msw/vc_mswdll/aui/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/ResolveAssemblyReference.cache create mode 100644 wx28X/build/msw/vc_mswdll/aui/aui.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/aui/aui.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/aui/aui.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/auibar.obj create mode 100644 wx28X/build/msw/vc_mswdll/aui/auibook.obj create mode 100644 wx28X/build/msw/vc_mswdll/aui/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/dockart.obj create mode 100644 wx28X/build/msw/vc_mswdll/aui/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/aui/floatpane.obj create mode 100644 wx28X/build/msw/vc_mswdll/aui/framemanager.obj create mode 100644 wx28X/build/msw/vc_mswdll/aui/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/aui/tabmdi.obj create mode 100644 wx28X/build/msw/vc_mswdll/aui/version.res create mode 100644 wx28X/build/msw/vc_mswdll/aui/wx_aui.log create mode 100644 wx28X/build/msw/vc_mswdll/base/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/ResolveAssemblyReference.cache create mode 100644 wx28X/build/msw/vc_mswdll/base/appbase.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/arcall.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/arcfind.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/archive.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/base.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/base/base.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/base/base.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/basemsw.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/clntdata.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/cmdline.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/config.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/convauto.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/crashrpt.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/datetime.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/datstrm.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/dde.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/debughlp.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/dir.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/dircmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/dlmsw.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/dynarray.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/dynlib.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/dynload.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/encconv.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/event.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/extended.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/ffile.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/file.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/fileback.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/fileconf.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/filefn.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/filename.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/filesys.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/filtall.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/filtfind.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/fmapbase.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/fs_arc.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/fs_filter.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/fs_mem.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/hash.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/hashmap.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/init.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/intl.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/ipcbase.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/list.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/log.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/longlong.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/main.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/memory.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/mimecmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/mimetype.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/module.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/msgout.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/mslu.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/mstream.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/object.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/platinfo.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/power.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/powercmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/process.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/base/regconf.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/regex.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/registry.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/snglinst.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/sstream.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/stackwalk.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/stdpaths.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/stdpbase.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/stopwatch.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/strconv.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/stream.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/string.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/sysopt.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/tarstrm.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/textbuf.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/textfile.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/thread.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/tokenzr.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/txtstrm.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/uri.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/utils.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/utilscmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/utilsexc.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/variant.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/version.res create mode 100644 wx28X/build/msw/vc_mswdll/base/volume.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/wfstream.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/wx_base.log create mode 100644 wx28X/build/msw/vc_mswdll/base/wxchar.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/xti.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/xtistrm.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/zipstrm.obj create mode 100644 wx28X/build/msw/vc_mswdll/base/zstream.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/ResolveAssemblyReference.cache create mode 100644 wx28X/build/msw/vc_mswdll/core/accel.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/access.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/accesscmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/anidecod.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/app.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/appcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/artprov.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/artstd.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/automtn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/bitmap.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/bmpbase.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/bmpbuttn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/bookctrl.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/brush.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/busyinfo.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/button.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/buttonbar.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/caret.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/checkbox.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/checklst.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/choicbkg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/choiccmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/choicdgg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/choice.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/clipbrd.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/clipcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/clrpickercmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/clrpickerg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/cmdproc.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/cmndata.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/collpaneg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/colordlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/colour.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/colourcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/combo.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/combobox.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/combocmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/combog.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/containr.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/control.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/core.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/core/core.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/core/core.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/cshelp.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/ctrlcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/ctrlsub.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/cursor.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/data.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/datacmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dataobj.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dc.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dcbase.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dcbufcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dcclient.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dcgraph.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dcmemory.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dcprint.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dcpsg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dcscreen.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dialog.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dialup.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dib.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dirctrlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dirdlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/display.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dlgcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dndcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dobjcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/docmdi.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/docview.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dpycmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dragimag.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dragimgg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dropsrc.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/droptgt.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dseldlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/effects.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/enhmeta.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/event.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/evtloop.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/evtloopcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/fddlgcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/fdrepdlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/filedlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/filepickercmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/filepickerg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/fldlgcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/font.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/fontcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/fontdlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/fontenum.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/fontenumcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/fontmap.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/fontpickercmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/fontpickerg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/fontutil.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/frame.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/framecmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/fs_mem.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/gauge95.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/gaugecmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/gbsizer.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/gdicmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/gdiimage.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/gdiobj.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/geometry.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/gifdecod.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/graphcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/graphics.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/gsockmsw.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/helpbase.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/helpchm.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/helpwin.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/icon.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/iconbndl.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/imagall.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/imagbmp.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/image.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/imagfill.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/imaggif.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/imagiff.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/imagjpeg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/imaglist.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/imagpcx.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/imagpng.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/imagpnm.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/imagtga.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/imagtiff.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/imagxpm.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/iniconf.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/layout.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/lboxcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/listbkg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/listbox.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/listctrl.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/listctrlcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/logg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/main.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/matrix.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/mdi.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/menu.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/menucmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/menuitem.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/metafile.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/minifram.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/msgdlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/msgout.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/mslu.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/nativdlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/nbkbase.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/notebook.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/numdlgg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/oleutils.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/overlaycmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/ownerdrw.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/palette.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/panelg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/paper.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/pen.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/pickerbase.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/popupcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/popupwin.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/printdlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/printps.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/printwin.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/prntbase.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/prntdlgg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/progdlgg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/quantize.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/radiobox.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/radiobut.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/radiocmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/core/region.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/rendcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/renderer.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/renderg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/rgncmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/scrlwing.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/scrolbar.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/selstore.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/settcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/settings.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/sizer.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/slider95.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/spinbutt.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/spinctlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/spinctrl.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/splitter.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/srchcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/srchctlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/statbar.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/statbmp.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/statbox.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/statbr95.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/statline.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/stattext.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/statusbr.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/stockitem.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/tabctrl.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/tbar95.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/tbarbase.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/textcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/textctrl.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/textdlgg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/tglbtn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/timer.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/timercmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/tipwin.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/toolbkg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/tooltip.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/toplevel.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/toplvcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/treebase.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/treebkg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/treectlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/treectrl.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/utilscmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/utilsgui.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/uuid.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/uxtheme.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/valgen.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/validate.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/valtext.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/version.res create mode 100644 wx28X/build/msw/vc_mswdll/core/vlbox.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/volume.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/vscroll.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/wincmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/window.obj create mode 100644 wx28X/build/msw/vc_mswdll/core/wx_core.log create mode 100644 wx28X/build/msw/vc_mswdll/core/xpmdecod.obj create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/ResolveAssemblyReference.cache create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/dbgrid.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/dbgrid.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/dbgrid.obj create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/dbgrid.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/version.res create mode 100644 wx28X/build/msw/vc_mswdll/dbgrid/wx_dbgrid.log create mode 100644 wx28X/build/msw/vc_mswdll/gl/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/gl/gl.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/gl/gl.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/gl/gl.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/glcanvas.obj create mode 100644 wx28X/build/msw/vc_mswdll/gl/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/gl/version.res create mode 100644 wx28X/build/msw/vc_mswdll/gl/wx_gl.log create mode 100644 wx28X/build/msw/vc_mswdll/html/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/helpbest.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/helpctrl.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/helpdata.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/helpdlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/helpfrm.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/helpwnd.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/html.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/html/html.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/html/html.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/htmlcell.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/htmlfilt.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/htmllbox.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/htmlpars.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/htmltag.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/htmlwin.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/htmprint.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/m_dflist.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/m_fonts.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/m_hline.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/m_image.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/m_layout.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/m_links.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/m_list.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/m_pre.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/m_style.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/m_tables.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/html/version.res create mode 100644 wx28X/build/msw/vc_mswdll/html/winpars.obj create mode 100644 wx28X/build/msw/vc_mswdll/html/wx_html.log create mode 100644 wx28X/build/msw/vc_mswdll/media/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/activex.obj create mode 100644 wx28X/build/msw/vc_mswdll/media/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/media/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/media.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/media/media.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/media/media.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/mediactrl_am.obj create mode 100644 wx28X/build/msw/vc_mswdll/media/mediactrl_qt.obj create mode 100644 wx28X/build/msw/vc_mswdll/media/mediactrl_wmp10.obj create mode 100644 wx28X/build/msw/vc_mswdll/media/mediactrlcmn.obj create mode 100644 wx28X/build/msw/vc_mswdll/media/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/media/version.res create mode 100644 wx28X/build/msw/vc_mswdll/media/wx_media.log create mode 100644 wx28X/build/msw/vc_mswdll/net/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/net/fs_inet.obj create mode 100644 wx28X/build/msw/vc_mswdll/net/ftp.obj create mode 100644 wx28X/build/msw/vc_mswdll/net/gsocket.obj create mode 100644 wx28X/build/msw/vc_mswdll/net/http.obj create mode 100644 wx28X/build/msw/vc_mswdll/net/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/net.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/net/net.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/net/net.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/protocol.obj create mode 100644 wx28X/build/msw/vc_mswdll/net/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/net/sckaddr.obj create mode 100644 wx28X/build/msw/vc_mswdll/net/sckfile.obj create mode 100644 wx28X/build/msw/vc_mswdll/net/sckipc.obj create mode 100644 wx28X/build/msw/vc_mswdll/net/sckstrm.obj create mode 100644 wx28X/build/msw/vc_mswdll/net/socket.obj create mode 100644 wx28X/build/msw/vc_mswdll/net/url.obj create mode 100644 wx28X/build/msw/vc_mswdll/net/urlmsw.obj create mode 100644 wx28X/build/msw/vc_mswdll/net/version.res create mode 100644 wx28X/build/msw/vc_mswdll/net/wx_net.log create mode 100644 wx28X/build/msw/vc_mswdll/odbc/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/db.obj create mode 100644 wx28X/build/msw/vc_mswdll/odbc/dbtable.obj create mode 100644 wx28X/build/msw/vc_mswdll/odbc/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/odbc/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/odbc.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/odbc/odbc.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/odbc/odbc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/odbc/version.res create mode 100644 wx28X/build/msw/vc_mswdll/odbc/wx_odbc.log create mode 100644 wx28X/build/msw/vc_mswdll/qa/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/ResolveAssemblyReference.cache create mode 100644 wx28X/build/msw/vc_mswdll/qa/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/dbgrptg.obj create mode 100644 wx28X/build/msw/vc_mswdll/qa/debugrpt.obj create mode 100644 wx28X/build/msw/vc_mswdll/qa/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/qa/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/qa.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/qa/qa.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/qa/qa.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/qa/version.res create mode 100644 wx28X/build/msw/vc_mswdll/qa/wx_qa.log create mode 100644 wx28X/build/msw/vc_mswdll/richtext/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/ResolveAssemblyReference.cache create mode 100644 wx28X/build/msw/vc_mswdll/richtext/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/richtext/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/richtext.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/richtext/richtext.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/richtext/richtext.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/richtext/richtextbuffer.obj create mode 100644 wx28X/build/msw/vc_mswdll/richtext/richtextctrl.obj create mode 100644 wx28X/build/msw/vc_mswdll/richtext/richtextformatdlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/richtext/richtexthtml.obj create mode 100644 wx28X/build/msw/vc_mswdll/richtext/richtextprint.obj create mode 100644 wx28X/build/msw/vc_mswdll/richtext/richtextstyledlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/richtext/richtextstyles.obj create mode 100644 wx28X/build/msw/vc_mswdll/richtext/richtextsymboldlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/richtext/richtextxml.obj create mode 100644 wx28X/build/msw/vc_mswdll/richtext/version.res create mode 100644 wx28X/build/msw/vc_mswdll/richtext/wx_richtext.log create mode 100644 wx28X/build/msw/vc_mswdll/wxexpat/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxexpat/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxexpat/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxexpat/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxexpat/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxexpat/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxexpat/wx_wxexpat.log create mode 100644 wx28X/build/msw/vc_mswdll/wxexpat/wxexpat.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/wxexpat/xmlparse.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxexpat/xmlrole.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxexpat/xmltok.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jcapimin.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jcapistd.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jccoefct.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jccolor.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jcdctmgr.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jchuff.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jcinit.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jcmainct.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jcmarker.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jcmaster.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jcomapi.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jcparam.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jcphuff.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jcprepct.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jcsample.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jctrans.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdapimin.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdapistd.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdatadst.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdatasrc.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdcoefct.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdcolor.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jddctmgr.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdhuff.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdinput.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdmainct.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdmarker.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdmaster.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdmerge.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdphuff.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdpostct.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdsample.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jdtrans.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jerror.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jfdctflt.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jfdctfst.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jfdctint.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jidctflt.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jidctfst.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jidctint.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jidctred.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jmemmgr.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jmemnobs.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jquant1.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jquant2.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/jutils.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/wx_wxjpeg.log create mode 100644 wx28X/build/msw/vc_mswdll/wxjpeg/wxjpeg.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/png.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngerror.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pnggccrd.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngget.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngmem.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngpread.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngread.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngrio.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngrtran.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngrutil.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngset.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngtrans.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngvcrd.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngwio.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngwrite.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngwtran.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/pngwutil.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/wx_wxpng.log create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/wxpng.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/wxpng/wxpng.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_advdll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_auidll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_basedll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_coredll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_dbgriddll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_gldll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_htmldll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_mediadll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_netdll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_odbcdll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_qadll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_richtextdll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_xmldll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxprec_xrcdll.pch create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/regcomp.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/regerror.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/regexec.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/regfree.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/wx_wxregex.log create mode 100644 wx28X/build/msw/vc_mswdll/wxregex/wxregex.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_aux.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_close.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_codec.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_color.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_compress.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_dir.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_dirinfo.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_dirread.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_dirwrite.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_dumpmode.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_error.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_extension.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_fax3.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_fax3sm.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_flush.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_getimage.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_jpeg.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_luv.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_lzw.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_next.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_open.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_packbits.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_pixarlog.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_predict.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_print.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_read.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_strip.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_swab.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_thunder.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_tile.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_version.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_warning.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_win32.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_write.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/tif_zip.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/wx_wxtiff.log create mode 100644 wx28X/build/msw/vc_mswdll/wxtiff/wxtiff.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/Lib-link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/Lib-link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/adler32.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/compress.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/crc32.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/deflate.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/gzio.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/infback.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/inffast.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/inflate.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/inftrees.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/lib.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/trees.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/uncompr.obj create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/wx_wxzlib.log create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/wxzlib.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/wxzlib/zutil.obj create mode 100644 wx28X/build/msw/vc_mswdll/xml/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/xml/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/version.res create mode 100644 wx28X/build/msw/vc_mswdll/xml/wx_xml.log create mode 100644 wx28X/build/msw/vc_mswdll/xml/xml.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/xml/xml.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/xml/xml.obj create mode 100644 wx28X/build/msw/vc_mswdll/xml/xml.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xml/xtixml.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/CL.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/CL.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/cl.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/custombuild.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/custombuild.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/custombuild.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/dummy.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/link-cvtres.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/link-cvtres.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/link.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/link.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/link.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/mt.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/mt.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/mt.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/rc.command.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/rc.read.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/rc.write.1.tlog create mode 100644 wx28X/build/msw/vc_mswdll/xrc/version.res create mode 100644 wx28X/build/msw/vc_mswdll/xrc/wx_xrc.log create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_animatctrl.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_bmp.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_bmpbt.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_bmpcbox.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_bttn.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_cald.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_chckb.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_chckl.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_choic.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_choicbk.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_clrpicker.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_collpane.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_combo.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_datectrl.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_dirpicker.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_dlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_filepicker.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_fontpicker.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_frame.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_gauge.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_gdctl.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_grid.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_html.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_htmllbox.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_hyperlink.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_listb.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_listbk.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_listc.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_mdi.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_menu.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_notbk.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_odcombo.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_panel.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_propdlg.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_radbt.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_radbx.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_scrol.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_scwin.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_sizer.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_slidr.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_spin.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_split.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_statbar.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_stbmp.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_stbox.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_stlin.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_sttxt.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_text.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_tglbtn.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_toolb.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_tree.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_treebk.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_unkwn.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xh_wizrd.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xmlres.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xmlrsall.obj create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xrc.dll.intermediate.manifest create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xrc.lastbuildstate create mode 100644 wx28X/build/msw/vc_mswdll/xrc/xrc.write.1.tlog create mode 100644 wx28X/build/msw/wx.dsw create mode 100644 wx28X/build/msw/wx_adv.dsp create mode 100644 wx28X/build/msw/wx_adv.vcxproj create mode 100644 wx28X/build/msw/wx_adv.vcxproj.filters create mode 100644 wx28X/build/msw/wx_adv.vcxproj.user create mode 100644 wx28X/build/msw/wx_aui.dsp create mode 100644 wx28X/build/msw/wx_aui.vcxproj create mode 100644 wx28X/build/msw/wx_aui.vcxproj.filters create mode 100644 wx28X/build/msw/wx_aui.vcxproj.user create mode 100644 wx28X/build/msw/wx_base.dsp create mode 100644 wx28X/build/msw/wx_base.vcxproj create mode 100644 wx28X/build/msw/wx_base.vcxproj.filters create mode 100644 wx28X/build/msw/wx_base.vcxproj.user create mode 100644 wx28X/build/msw/wx_core.dsp create mode 100644 wx28X/build/msw/wx_core.vcxproj create mode 100644 wx28X/build/msw/wx_core.vcxproj.filters create mode 100644 wx28X/build/msw/wx_core.vcxproj.user create mode 100644 wx28X/build/msw/wx_dbgrid.dsp create mode 100644 wx28X/build/msw/wx_dbgrid.vcxproj create mode 100644 wx28X/build/msw/wx_dbgrid.vcxproj.filters create mode 100644 wx28X/build/msw/wx_dbgrid.vcxproj.user create mode 100644 wx28X/build/msw/wx_dll.dsw create mode 100644 wx28X/build/msw/wx_dll.sdf create mode 100644 wx28X/build/msw/wx_dll.sln create mode 100644 wx28X/build/msw/wx_dll.suo create mode 100644 wx28X/build/msw/wx_gl.dsp create mode 100644 wx28X/build/msw/wx_gl.vcxproj create mode 100644 wx28X/build/msw/wx_gl.vcxproj.filters create mode 100644 wx28X/build/msw/wx_gl.vcxproj.user create mode 100644 wx28X/build/msw/wx_html.dsp create mode 100644 wx28X/build/msw/wx_html.vcxproj create mode 100644 wx28X/build/msw/wx_html.vcxproj.filters create mode 100644 wx28X/build/msw/wx_html.vcxproj.user create mode 100644 wx28X/build/msw/wx_media.dsp create mode 100644 wx28X/build/msw/wx_media.vcxproj create mode 100644 wx28X/build/msw/wx_media.vcxproj.filters create mode 100644 wx28X/build/msw/wx_media.vcxproj.user create mode 100644 wx28X/build/msw/wx_net.dsp create mode 100644 wx28X/build/msw/wx_net.vcxproj create mode 100644 wx28X/build/msw/wx_net.vcxproj.filters create mode 100644 wx28X/build/msw/wx_net.vcxproj.user create mode 100644 wx28X/build/msw/wx_odbc.dsp create mode 100644 wx28X/build/msw/wx_odbc.vcxproj create mode 100644 wx28X/build/msw/wx_odbc.vcxproj.filters create mode 100644 wx28X/build/msw/wx_odbc.vcxproj.user create mode 100644 wx28X/build/msw/wx_qa.dsp create mode 100644 wx28X/build/msw/wx_qa.vcxproj create mode 100644 wx28X/build/msw/wx_qa.vcxproj.filters create mode 100644 wx28X/build/msw/wx_qa.vcxproj.user create mode 100644 wx28X/build/msw/wx_richtext.dsp create mode 100644 wx28X/build/msw/wx_richtext.vcxproj create mode 100644 wx28X/build/msw/wx_richtext.vcxproj.filters create mode 100644 wx28X/build/msw/wx_richtext.vcxproj.user create mode 100644 wx28X/build/msw/wx_wxexpat.dsp create mode 100644 wx28X/build/msw/wx_wxexpat.vcxproj create mode 100644 wx28X/build/msw/wx_wxexpat.vcxproj.filters create mode 100644 wx28X/build/msw/wx_wxexpat.vcxproj.user create mode 100644 wx28X/build/msw/wx_wxjpeg.dsp create mode 100644 wx28X/build/msw/wx_wxjpeg.vcxproj create mode 100644 wx28X/build/msw/wx_wxjpeg.vcxproj.filters create mode 100644 wx28X/build/msw/wx_wxjpeg.vcxproj.user create mode 100644 wx28X/build/msw/wx_wxpng.dsp create mode 100644 wx28X/build/msw/wx_wxpng.vcxproj create mode 100644 wx28X/build/msw/wx_wxpng.vcxproj.filters create mode 100644 wx28X/build/msw/wx_wxpng.vcxproj.user create mode 100644 wx28X/build/msw/wx_wxregex.dsp create mode 100644 wx28X/build/msw/wx_wxregex.vcxproj create mode 100644 wx28X/build/msw/wx_wxregex.vcxproj.filters create mode 100644 wx28X/build/msw/wx_wxregex.vcxproj.user create mode 100644 wx28X/build/msw/wx_wxtiff.dsp create mode 100644 wx28X/build/msw/wx_wxtiff.vcxproj create mode 100644 wx28X/build/msw/wx_wxtiff.vcxproj.filters create mode 100644 wx28X/build/msw/wx_wxtiff.vcxproj.user create mode 100644 wx28X/build/msw/wx_wxzlib.dsp create mode 100644 wx28X/build/msw/wx_wxzlib.vcxproj create mode 100644 wx28X/build/msw/wx_wxzlib.vcxproj.filters create mode 100644 wx28X/build/msw/wx_wxzlib.vcxproj.user create mode 100644 wx28X/build/msw/wx_xml.dsp create mode 100644 wx28X/build/msw/wx_xml.vcxproj create mode 100644 wx28X/build/msw/wx_xml.vcxproj.filters create mode 100644 wx28X/build/msw/wx_xml.vcxproj.user create mode 100644 wx28X/build/msw/wx_xrc.dsp create mode 100644 wx28X/build/msw/wx_xrc.vcxproj create mode 100644 wx28X/build/msw/wx_xrc.vcxproj.filters create mode 100644 wx28X/build/msw/wx_xrc.vcxproj.user create mode 100644 wx28X/build/script/makedocs.vc create mode 100644 wx28X/build/script/rebuild-makefiles.sh create mode 100644 wx28X/build/script/win_docs.bat create mode 100644 wx28X/build/script/word_macro.txt create mode 100644 wx28X/build/script/wxwidgets.iss create mode 100644 wx28X/build/tools/build-wxwidgets.py create mode 100644 wx28X/build/tools/builder.py create mode 100644 wx28X/build/tools/create-archive.py create mode 100644 wx28X/build/update-setup-h create mode 100644 wx28X/build/wince/missing/AGL/agl.h create mode 100644 wx28X/build/wince/missing/ATSUnicode.h create mode 100644 wx28X/build/wince/missing/Appearance.h create mode 100644 wx28X/build/wince/missing/AvailabilityMacros.h create mode 100644 wx28X/build/wince/missing/CFString.h create mode 100644 wx28X/build/wince/missing/Carbon/Carbon.h create mode 100644 wx28X/build/wince/missing/CodeFragments.h create mode 100644 wx28X/build/wince/missing/ControlDefinitions.h create mode 100644 wx28X/build/wince/missing/Controls.h create mode 100644 wx28X/build/wince/missing/CoreFoundation/CFBase.h create mode 100644 wx28X/build/wince/missing/CoreFoundation/CFString.h create mode 100644 wx28X/build/wince/missing/CoreFoundation/CFStringEncodingExt.h create mode 100644 wx28X/build/wince/missing/CoreFoundation/CoreFoundation.h create mode 100644 wx28X/build/wince/missing/CoreServices.h create mode 100644 wx28X/build/wince/missing/CoreServices/CoreServices.h create mode 100644 wx28X/build/wince/missing/DateTime.h create mode 100644 wx28X/build/wince/missing/Debugging.h create mode 100644 wx28X/build/wince/missing/DriverServices.h create mode 100644 wx28X/build/wince/missing/FixMath.h create mode 100644 wx28X/build/wince/missing/Folders.h create mode 100644 wx28X/build/wince/missing/GL/glx.h create mode 100644 wx28X/build/wince/missing/Gestalt.h create mode 100644 wx28X/build/wince/missing/InternetConfig.h create mode 100644 wx28X/build/wince/missing/LowMem.h create mode 100644 wx28X/build/wince/missing/MacHeaders.c create mode 100644 wx28X/build/wince/missing/MoreFilesX.h create mode 100644 wx28X/build/wince/missing/OpenGL/gl.h create mode 100644 wx28X/build/wince/missing/OpenGL/glx.h create mode 100644 wx28X/build/wince/missing/OpenTptInternet.h create mode 100644 wx28X/build/wince/missing/OpenTransport.h create mode 100644 wx28X/build/wince/missing/OpenTransportProviders.h create mode 100644 wx28X/build/wince/missing/PMApplication.h create mode 100644 wx28X/build/wince/missing/PalmOS.h create mode 100644 wx28X/build/wince/missing/Printing.h create mode 100644 wx28X/build/wince/missing/Quickdraw.h create mode 100644 wx28X/build/wince/missing/StringMgr.h create mode 100644 wx28X/build/wince/missing/SystemMgr.h create mode 100644 wx28X/build/wince/missing/TextCommon.h create mode 100644 wx28X/build/wince/missing/TextEncodingConverter.h create mode 100644 wx28X/build/wince/missing/TimeMgr.h create mode 100644 wx28X/build/wince/missing/Timer.h create mode 100644 wx28X/build/wince/missing/Xm/VendorSP.h create mode 100644 wx28X/build/wince/missing/Xm/Xm.h create mode 100644 wx28X/build/wince/missing/_mingw.h create mode 100644 wx28X/build/wince/missing/agl.h create mode 100644 wx28X/build/wince/missing/alloc.h create mode 100644 wx28X/build/wince/missing/ansi_prefix.mach.h create mode 100644 wx28X/build/wince/missing/clib.h create mode 100644 wx28X/build/wince/missing/dir.h create mode 100644 wx28X/build/wince/missing/dirent.h create mode 100644 wx28X/build/wince/missing/dl.h create mode 100644 wx28X/build/wince/missing/dlfcn.h create mode 100644 wx28X/build/wince/missing/expat_config.h create mode 100644 wx28X/build/wince/missing/ext/hash_map create mode 100644 wx28X/build/wince/missing/ext/hash_set create mode 100644 wx28X/build/wince/missing/fab.h create mode 100644 wx28X/build/wince/missing/fp.h create mode 100644 wx28X/build/wince/missing/gdk/gdk.h create mode 100644 wx28X/build/wince/missing/gdk/gdkx.h create mode 100644 wx28X/build/wince/missing/grp.h create mode 100644 wx28X/build/wince/missing/gsocket.h create mode 100644 wx28X/build/wince/missing/hash_map create mode 100644 wx28X/build/wince/missing/hash_set create mode 100644 wx28X/build/wince/missing/iconv.h create mode 100644 wx28X/build/wince/missing/langinfo.h create mode 100644 wx28X/build/wince/missing/m68881.h create mode 100644 wx28X/build/wince/missing/machine/ansi.h create mode 100644 wx28X/build/wince/missing/mem.h create mode 100644 wx28X/build/wince/missing/mgraph.hpp create mode 100644 wx28X/build/wince/missing/msl_c_version.h create mode 100644 wx28X/build/wince/missing/os2.h create mode 100644 wx28X/build/wince/missing/os2def.h create mode 100644 wx28X/build/wince/missing/pango/pango.h create mode 100644 wx28X/build/wince/missing/pmapi.h create mode 100644 wx28X/build/wince/missing/pmstddlg.h create mode 100644 wx28X/build/wince/missing/pngusr.h create mode 100644 wx28X/build/wince/missing/print.h create mode 100644 wx28X/build/wince/missing/pwd.h create mode 100644 wx28X/build/wince/missing/stdint.h create mode 100644 wx28X/build/wince/missing/strings.h create mode 100644 wx28X/build/wince/missing/sys/cygwin.h create mode 100644 wx28X/build/wince/missing/sys/hash_set create mode 100644 wx28X/build/wince/missing/sys/ioctl.h create mode 100644 wx28X/build/wince/missing/sys/minmax.h create mode 100644 wx28X/build/wince/missing/sys/select.h create mode 100644 wx28X/build/wince/missing/sys/socket.h create mode 100644 wx28X/build/wince/missing/sys/time.h create mode 100644 wx28X/build/wince/missing/sys/un.h create mode 100644 wx28X/build/wince/missing/sys/unistd.h create mode 100644 wx28X/build/wince/missing/tcpustd.h create mode 100644 wx28X/build/wince/missing/unistd.h create mode 100644 wx28X/build/wince/missing/unix.h create mode 100644 wx28X/build/wince/missing/unixio.h create mode 100644 wx28X/build/wince/missing/utils.h create mode 100644 wx28X/build/wince/missing/values.h create mode 100644 wx28X/build/wince/missing/w32api.h create mode 100644 wx28X/build/wince/missing/wcstr.h create mode 100644 wx28X/build/wince/missing/widec.h create mode 100644 wx28X/build/wince/missing/wtime.h create mode 100644 wx28X/build/wince/wx.vcw create mode 100644 wx28X/build/wince/wx_gl.vcp create mode 100644 wx28X/build/wince/wx_mono.vcp create mode 100644 wx28X/build/wince/wx_wxexpat.vcp create mode 100644 wx28X/build/wince/wx_wxjpeg.vcp create mode 100644 wx28X/build/wince/wx_wxpng.vcp create mode 100644 wx28X/build/wince/wx_wxzlib.vcp create mode 100644 wx28X/config.guess create mode 100644 wx28X/config.sub create mode 100644 wx28X/configure create mode 100644 wx28X/configure.in create mode 100644 wx28X/contrib/Makefile.in create mode 100644 wx28X/contrib/build/deprecated/deprecated.bkl create mode 100644 wx28X/contrib/build/deprecated/deprecated.dsp create mode 100644 wx28X/contrib/build/deprecated/deprecated.dsw create mode 100644 wx28X/contrib/build/deprecated/deprecated.vcp create mode 100644 wx28X/contrib/build/deprecated/deprecated.vcw create mode 100644 wx28X/contrib/build/deprecated/makefile.bcc create mode 100644 wx28X/contrib/build/deprecated/makefile.dmc create mode 100644 wx28X/contrib/build/deprecated/makefile.dms create mode 100644 wx28X/contrib/build/deprecated/makefile.gcc create mode 100644 wx28X/contrib/build/deprecated/makefile.vc create mode 100644 wx28X/contrib/build/deprecated/makefile.wat create mode 100644 wx28X/contrib/build/fl/fl.bkl create mode 100644 wx28X/contrib/build/fl/fl.dsp create mode 100644 wx28X/contrib/build/fl/fl.dsw create mode 100644 wx28X/contrib/build/fl/fl.vcp create mode 100644 wx28X/contrib/build/fl/fl.vcw create mode 100644 wx28X/contrib/build/fl/makefile.bcc create mode 100644 wx28X/contrib/build/fl/makefile.dmc create mode 100644 wx28X/contrib/build/fl/makefile.dms create mode 100644 wx28X/contrib/build/fl/makefile.gcc create mode 100644 wx28X/contrib/build/fl/makefile.vc create mode 100644 wx28X/contrib/build/fl/makefile.wat create mode 100644 wx28X/contrib/build/foldbar/foldbar.bkl create mode 100644 wx28X/contrib/build/foldbar/foldbar.dsp create mode 100644 wx28X/contrib/build/foldbar/foldbar.dsw create mode 100644 wx28X/contrib/build/foldbar/foldbar.vcp create mode 100644 wx28X/contrib/build/foldbar/foldbar.vcw create mode 100644 wx28X/contrib/build/foldbar/makefile.bcc create mode 100644 wx28X/contrib/build/foldbar/makefile.dmc create mode 100644 wx28X/contrib/build/foldbar/makefile.dms create mode 100644 wx28X/contrib/build/foldbar/makefile.gcc create mode 100644 wx28X/contrib/build/foldbar/makefile.vc create mode 100644 wx28X/contrib/build/foldbar/makefile.wat create mode 100644 wx28X/contrib/build/gizmos/gizmos.bkl create mode 100644 wx28X/contrib/build/gizmos/gizmos.dsp create mode 100644 wx28X/contrib/build/gizmos/gizmos.dsw create mode 100644 wx28X/contrib/build/gizmos/gizmos.vcw create mode 100644 wx28X/contrib/build/gizmos/gizmos_gizmos.dsp create mode 100644 wx28X/contrib/build/gizmos/gizmos_gizmos.vcp create mode 100644 wx28X/contrib/build/gizmos/gizmos_gizmos_xrc.dsp create mode 100644 wx28X/contrib/build/gizmos/gizmos_gizmos_xrc.vcp create mode 100644 wx28X/contrib/build/gizmos/makefile.bcc create mode 100644 wx28X/contrib/build/gizmos/makefile.dmc create mode 100644 wx28X/contrib/build/gizmos/makefile.dms create mode 100644 wx28X/contrib/build/gizmos/makefile.gcc create mode 100644 wx28X/contrib/build/gizmos/makefile.vc create mode 100644 wx28X/contrib/build/gizmos/makefile.wat create mode 100644 wx28X/contrib/build/mmedia/makefile.bcc create mode 100644 wx28X/contrib/build/mmedia/makefile.dmc create mode 100644 wx28X/contrib/build/mmedia/makefile.dms create mode 100644 wx28X/contrib/build/mmedia/makefile.gcc create mode 100644 wx28X/contrib/build/mmedia/makefile.vc create mode 100644 wx28X/contrib/build/mmedia/makefile.wat create mode 100644 wx28X/contrib/build/mmedia/mmedia.bkl create mode 100644 wx28X/contrib/build/mmedia/mmedia.dsp create mode 100644 wx28X/contrib/build/mmedia/mmedia.dsw create mode 100644 wx28X/contrib/build/mmedia/mmedia.vcp create mode 100644 wx28X/contrib/build/mmedia/mmedia.vcw create mode 100644 wx28X/contrib/build/net/makefile.bcc create mode 100644 wx28X/contrib/build/net/makefile.dmc create mode 100644 wx28X/contrib/build/net/makefile.dms create mode 100644 wx28X/contrib/build/net/makefile.gcc create mode 100644 wx28X/contrib/build/net/makefile.vc create mode 100644 wx28X/contrib/build/net/makefile.wat create mode 100644 wx28X/contrib/build/net/net.bkl create mode 100644 wx28X/contrib/build/net/net.dsp create mode 100644 wx28X/contrib/build/net/net.dsw create mode 100644 wx28X/contrib/build/net/net.vcp create mode 100644 wx28X/contrib/build/net/net.vcw create mode 100644 wx28X/contrib/build/ogl/makefile.bcc create mode 100644 wx28X/contrib/build/ogl/makefile.dmc create mode 100644 wx28X/contrib/build/ogl/makefile.dms create mode 100644 wx28X/contrib/build/ogl/makefile.gcc create mode 100644 wx28X/contrib/build/ogl/makefile.vc create mode 100644 wx28X/contrib/build/ogl/makefile.wat create mode 100644 wx28X/contrib/build/ogl/ogl.bkl create mode 100644 wx28X/contrib/build/ogl/ogl.dsp create mode 100644 wx28X/contrib/build/ogl/ogl.dsw create mode 100644 wx28X/contrib/build/ogl/ogl.vcp create mode 100644 wx28X/contrib/build/ogl/ogl.vcw create mode 100644 wx28X/contrib/build/plot/makefile.bcc create mode 100644 wx28X/contrib/build/plot/makefile.dmc create mode 100644 wx28X/contrib/build/plot/makefile.dms create mode 100644 wx28X/contrib/build/plot/makefile.gcc create mode 100644 wx28X/contrib/build/plot/makefile.vc create mode 100644 wx28X/contrib/build/plot/makefile.wat create mode 100644 wx28X/contrib/build/plot/plot.bkl create mode 100644 wx28X/contrib/build/plot/plot.dsp create mode 100644 wx28X/contrib/build/plot/plot.dsw create mode 100644 wx28X/contrib/build/plot/plot.vcp create mode 100644 wx28X/contrib/build/plot/plot.vcw create mode 100644 wx28X/contrib/build/stc/makefile.bcc create mode 100644 wx28X/contrib/build/stc/makefile.dmc create mode 100644 wx28X/contrib/build/stc/makefile.dms create mode 100644 wx28X/contrib/build/stc/makefile.gcc create mode 100644 wx28X/contrib/build/stc/makefile.vc create mode 100644 wx28X/contrib/build/stc/makefile.wat create mode 100644 wx28X/contrib/build/stc/stc.bkl create mode 100644 wx28X/contrib/build/stc/stc.dsp create mode 100644 wx28X/contrib/build/stc/stc.dsw create mode 100644 wx28X/contrib/build/stc/stc.vcp create mode 100644 wx28X/contrib/build/stc/stc.vcw create mode 100644 wx28X/contrib/build/svg/makefile.bcc create mode 100644 wx28X/contrib/build/svg/makefile.dmc create mode 100644 wx28X/contrib/build/svg/makefile.dms create mode 100644 wx28X/contrib/build/svg/makefile.gcc create mode 100644 wx28X/contrib/build/svg/makefile.vc create mode 100644 wx28X/contrib/build/svg/makefile.wat create mode 100644 wx28X/contrib/build/svg/svg.bkl create mode 100644 wx28X/contrib/build/svg/svg.dsp create mode 100644 wx28X/contrib/build/svg/svg.dsw create mode 100644 wx28X/contrib/build/svg/svg.vcp create mode 100644 wx28X/contrib/build/svg/svg.vcw create mode 100644 wx28X/contrib/include/wx/applet/applet.h create mode 100644 wx28X/contrib/include/wx/applet/echovar.h create mode 100644 wx28X/contrib/include/wx/applet/ifelsevar.h create mode 100644 wx28X/contrib/include/wx/applet/loadpage.h create mode 100644 wx28X/contrib/include/wx/applet/plugin.h create mode 100644 wx28X/contrib/include/wx/applet/prepecho.h create mode 100644 wx28X/contrib/include/wx/applet/prepifelse.h create mode 100644 wx28X/contrib/include/wx/applet/prepinclude.h create mode 100644 wx28X/contrib/include/wx/applet/window.h create mode 100644 wx28X/contrib/include/wx/deprecated/expr.h create mode 100644 wx28X/contrib/include/wx/deprecated/prop.h create mode 100644 wx28X/contrib/include/wx/deprecated/propform.h create mode 100644 wx28X/contrib/include/wx/deprecated/proplist.h create mode 100644 wx28X/contrib/include/wx/deprecated/resource.h create mode 100644 wx28X/contrib/include/wx/deprecated/setup.h create mode 100644 wx28X/contrib/include/wx/deprecated/tbarsmpl.h create mode 100644 wx28X/contrib/include/wx/deprecated/treelay.h create mode 100644 wx28X/contrib/include/wx/deprecated/wxexpr.h create mode 100644 wx28X/contrib/include/wx/fl/antiflickpl.h create mode 100644 wx28X/contrib/include/wx/fl/bardragpl.h create mode 100644 wx28X/contrib/include/wx/fl/barhintspl.h create mode 100644 wx28X/contrib/include/wx/fl/cbcustom.h create mode 100644 wx28X/contrib/include/wx/fl/controlbar.h create mode 100644 wx28X/contrib/include/wx/fl/dynbarhnd.h create mode 100644 wx28X/contrib/include/wx/fl/dyntbar.h create mode 100644 wx28X/contrib/include/wx/fl/dyntbarhnd.h create mode 100644 wx28X/contrib/include/wx/fl/fldefs.h create mode 100644 wx28X/contrib/include/wx/fl/frmview.h create mode 100644 wx28X/contrib/include/wx/fl/garbagec.h create mode 100644 wx28X/contrib/include/wx/fl/gcupdatesmgr.h create mode 100644 wx28X/contrib/include/wx/fl/hintanimpl.h create mode 100644 wx28X/contrib/include/wx/fl/newbmpbtn.h create mode 100644 wx28X/contrib/include/wx/fl/panedrawpl.h create mode 100644 wx28X/contrib/include/wx/fl/rowdragpl.h create mode 100644 wx28X/contrib/include/wx/fl/rowlayoutpl.h create mode 100644 wx28X/contrib/include/wx/fl/toolwnd.h create mode 100644 wx28X/contrib/include/wx/fl/updatesmgr.h create mode 100644 wx28X/contrib/include/wx/foldbar/captionbar.h create mode 100644 wx28X/contrib/include/wx/foldbar/doc_mainpage.h create mode 100644 wx28X/contrib/include/wx/foldbar/foldpanelbar.h create mode 100644 wx28X/contrib/include/wx/foldbar/foldpanelitem.h create mode 100644 wx28X/contrib/include/wx/gizmos/dynamicsash.h create mode 100644 wx28X/contrib/include/wx/gizmos/editlbox.h create mode 100644 wx28X/contrib/include/wx/gizmos/gizmos.h create mode 100644 wx28X/contrib/include/wx/gizmos/ledctrl.h create mode 100644 wx28X/contrib/include/wx/gizmos/multicell.h create mode 100644 wx28X/contrib/include/wx/gizmos/splittree.h create mode 100644 wx28X/contrib/include/wx/gizmos/statpict.h create mode 100644 wx28X/contrib/include/wx/gizmos/xh_statpict.h create mode 100644 wx28X/contrib/include/wx/mmedia/cdbase.h create mode 100644 wx28X/contrib/include/wx/mmedia/cdunix.h create mode 100644 wx28X/contrib/include/wx/mmedia/cdwin.h create mode 100644 wx28X/contrib/include/wx/mmedia/defs.h create mode 100644 wx28X/contrib/include/wx/mmedia/internal/g72x.h create mode 100644 wx28X/contrib/include/wx/mmedia/sndaiff.h create mode 100644 wx28X/contrib/include/wx/mmedia/sndbase.h create mode 100644 wx28X/contrib/include/wx/mmedia/sndcodec.h create mode 100644 wx28X/contrib/include/wx/mmedia/sndcpcm.h create mode 100644 wx28X/contrib/include/wx/mmedia/sndesd.h create mode 100644 wx28X/contrib/include/wx/mmedia/sndfile.h create mode 100644 wx28X/contrib/include/wx/mmedia/sndg72x.h create mode 100644 wx28X/contrib/include/wx/mmedia/sndmsad.h create mode 100644 wx28X/contrib/include/wx/mmedia/sndoss.h create mode 100644 wx28X/contrib/include/wx/mmedia/sndpcm.h create mode 100644 wx28X/contrib/include/wx/mmedia/sndulaw.h create mode 100644 wx28X/contrib/include/wx/mmedia/sndwav.h create mode 100644 wx28X/contrib/include/wx/mmedia/sndwin.h create mode 100644 wx28X/contrib/include/wx/mmedia/vidbase.h create mode 100644 wx28X/contrib/include/wx/mmedia/vidwin.h create mode 100644 wx28X/contrib/include/wx/mmedia/vidxanm.h create mode 100644 wx28X/contrib/include/wx/net/email.h create mode 100644 wx28X/contrib/include/wx/net/msg.h create mode 100644 wx28X/contrib/include/wx/net/smapi.h create mode 100644 wx28X/contrib/include/wx/net/web.h create mode 100644 wx28X/contrib/include/wx/ogl/basic.h create mode 100644 wx28X/contrib/include/wx/ogl/basicp.h create mode 100644 wx28X/contrib/include/wx/ogl/bmpshape.h create mode 100644 wx28X/contrib/include/wx/ogl/canvas.h create mode 100644 wx28X/contrib/include/wx/ogl/composit.h create mode 100644 wx28X/contrib/include/wx/ogl/constrnt.h create mode 100644 wx28X/contrib/include/wx/ogl/divided.h create mode 100644 wx28X/contrib/include/wx/ogl/drawn.h create mode 100644 wx28X/contrib/include/wx/ogl/drawnp.h create mode 100644 wx28X/contrib/include/wx/ogl/lines.h create mode 100644 wx28X/contrib/include/wx/ogl/linesp.h create mode 100644 wx28X/contrib/include/wx/ogl/mfutils.h create mode 100644 wx28X/contrib/include/wx/ogl/misc.h create mode 100644 wx28X/contrib/include/wx/ogl/ogl.h create mode 100644 wx28X/contrib/include/wx/ogl/ogldiag.h create mode 100644 wx28X/contrib/include/wx/plot/plot.h create mode 100644 wx28X/contrib/include/wx/plot/plot_dwn.bmp create mode 100644 wx28X/contrib/include/wx/plot/plot_dwn.xpm create mode 100644 wx28X/contrib/include/wx/plot/plot_enl.bmp create mode 100644 wx28X/contrib/include/wx/plot/plot_enl.xpm create mode 100644 wx28X/contrib/include/wx/plot/plot_shr.bmp create mode 100644 wx28X/contrib/include/wx/plot/plot_shr.xpm create mode 100644 wx28X/contrib/include/wx/plot/plot_up.bmp create mode 100644 wx28X/contrib/include/wx/plot/plot_up.xpm create mode 100644 wx28X/contrib/include/wx/plot/plot_zin.bmp create mode 100644 wx28X/contrib/include/wx/plot/plot_zin.xpm create mode 100644 wx28X/contrib/include/wx/plot/plot_zot.bmp create mode 100644 wx28X/contrib/include/wx/plot/plot_zot.xpm create mode 100644 wx28X/contrib/include/wx/plot/wxplot.rc create mode 100644 wx28X/contrib/include/wx/stc/stc.h create mode 100644 wx28X/contrib/include/wx/svg/dcsvg.h create mode 100644 wx28X/contrib/lib/dummy create mode 100644 wx28X/contrib/samples/Makefile.in create mode 100644 wx28X/contrib/samples/applet/about.html create mode 100644 wx28X/contrib/samples/applet/applet.cpp create mode 100644 wx28X/contrib/samples/applet/applet.h create mode 100644 wx28X/contrib/samples/applet/applet.rc create mode 100644 wx28X/contrib/samples/applet/combobox.cpp create mode 100644 wx28X/contrib/samples/applet/combobox.h create mode 100644 wx28X/contrib/samples/applet/dialogs.wdr create mode 100644 wx28X/contrib/samples/applet/dialogs_wdr.cpp create mode 100644 wx28X/contrib/samples/applet/dialogs_wdr.h create mode 100644 wx28X/contrib/samples/applet/index.html create mode 100644 wx28X/contrib/samples/applet/monitorapplet.cpp create mode 100644 wx28X/contrib/samples/applet/monitorapplet.h create mode 100644 wx28X/contrib/samples/applet/monitors.c create mode 100644 wx28X/contrib/samples/deprecated/Makefile.in create mode 100644 wx28X/contrib/samples/deprecated/proplist/Makefile.in create mode 100644 wx28X/contrib/samples/deprecated/proplist/cross.bmp create mode 100644 wx28X/contrib/samples/deprecated/proplist/makefile.bcc create mode 100644 wx28X/contrib/samples/deprecated/proplist/makefile.dmc create mode 100644 wx28X/contrib/samples/deprecated/proplist/makefile.dms create mode 100644 wx28X/contrib/samples/deprecated/proplist/makefile.gcc create mode 100644 wx28X/contrib/samples/deprecated/proplist/makefile.unx create mode 100644 wx28X/contrib/samples/deprecated/proplist/makefile.vc create mode 100644 wx28X/contrib/samples/deprecated/proplist/makefile.wat create mode 100644 wx28X/contrib/samples/deprecated/proplist/proplist.bkl create mode 100644 wx28X/contrib/samples/deprecated/proplist/proplist.cpp create mode 100644 wx28X/contrib/samples/deprecated/proplist/proplist.dsp create mode 100644 wx28X/contrib/samples/deprecated/proplist/proplist.h create mode 100644 wx28X/contrib/samples/deprecated/proplist/proplist.pro create mode 100644 wx28X/contrib/samples/deprecated/proplist/proplist.rc create mode 100644 wx28X/contrib/samples/deprecated/proplist/proplist.vcp create mode 100644 wx28X/contrib/samples/deprecated/proplist/proplist.vcw create mode 100644 wx28X/contrib/samples/deprecated/proplist/proplistM5.xml create mode 100644 wx28X/contrib/samples/deprecated/proplist/tick.bmp create mode 100644 wx28X/contrib/samples/deprecated/resource/Makefile.in create mode 100644 wx28X/contrib/samples/deprecated/resource/descrip.mms create mode 100644 wx28X/contrib/samples/deprecated/resource/dialog1.h create mode 100644 wx28X/contrib/samples/deprecated/resource/dialog1.wxr create mode 100644 wx28X/contrib/samples/deprecated/resource/makefile.bcc create mode 100644 wx28X/contrib/samples/deprecated/resource/makefile.dmc create mode 100644 wx28X/contrib/samples/deprecated/resource/makefile.dms create mode 100644 wx28X/contrib/samples/deprecated/resource/makefile.gcc create mode 100644 wx28X/contrib/samples/deprecated/resource/makefile.unx create mode 100644 wx28X/contrib/samples/deprecated/resource/makefile.vc create mode 100644 wx28X/contrib/samples/deprecated/resource/makefile.vms create mode 100644 wx28X/contrib/samples/deprecated/resource/makefile.wat create mode 100644 wx28X/contrib/samples/deprecated/resource/menu1.wxr create mode 100644 wx28X/contrib/samples/deprecated/resource/resource.bkl create mode 100644 wx28X/contrib/samples/deprecated/resource/resource.cpp create mode 100644 wx28X/contrib/samples/deprecated/resource/resource.dsp create mode 100644 wx28X/contrib/samples/deprecated/resource/resource.h create mode 100644 wx28X/contrib/samples/deprecated/resource/resource.pro create mode 100644 wx28X/contrib/samples/deprecated/resource/resource.rc create mode 100644 wx28X/contrib/samples/deprecated/resource/resource.vcp create mode 100644 wx28X/contrib/samples/deprecated/resource/resource.vcw create mode 100644 wx28X/contrib/samples/deprecated/resource/resourceM5.xml create mode 100644 wx28X/contrib/samples/deprecated/treelay/Makefile.in create mode 100644 wx28X/contrib/samples/deprecated/treelay/makefile.bcc create mode 100644 wx28X/contrib/samples/deprecated/treelay/makefile.dmc create mode 100644 wx28X/contrib/samples/deprecated/treelay/makefile.dms create mode 100644 wx28X/contrib/samples/deprecated/treelay/makefile.gcc create mode 100644 wx28X/contrib/samples/deprecated/treelay/makefile.unx create mode 100644 wx28X/contrib/samples/deprecated/treelay/makefile.vc create mode 100644 wx28X/contrib/samples/deprecated/treelay/makefile.wat create mode 100644 wx28X/contrib/samples/deprecated/treelay/mondrian.ico create mode 100644 wx28X/contrib/samples/deprecated/treelay/treelay.bkl create mode 100644 wx28X/contrib/samples/deprecated/treelay/treelay.cpp create mode 100644 wx28X/contrib/samples/deprecated/treelay/treelay.dsp create mode 100644 wx28X/contrib/samples/deprecated/treelay/treelay.h create mode 100644 wx28X/contrib/samples/deprecated/treelay/treelay.pro create mode 100644 wx28X/contrib/samples/deprecated/treelay/treelay.rc create mode 100644 wx28X/contrib/samples/deprecated/treelay/treelay.vcp create mode 100644 wx28X/contrib/samples/deprecated/treelay/treelay.vcw create mode 100644 wx28X/contrib/samples/deprecated/treelay/treelayM5.xml create mode 100644 wx28X/contrib/samples/fl/Makefile.in create mode 100644 wx28X/contrib/samples/fl/bitmaps/bookmarks.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/class_icon.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/class_icon1.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/copy.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/cut.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/file_icon.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/folder_icon.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/help_icon.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/new.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/nextmark.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/open.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/paste.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/prevmark.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/res_icon.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/save.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/saveall.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/search.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/start95_dp.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/start95_pr.bmp create mode 100644 wx28X/contrib/samples/fl/bitmaps/tile.bmp create mode 100644 wx28X/contrib/samples/fl/fl.bkl create mode 100644 wx28X/contrib/samples/fl/fl.vcw create mode 100644 wx28X/contrib/samples/fl/fl_demo1.cpp create mode 100644 wx28X/contrib/samples/fl/fl_demo1.h create mode 100644 wx28X/contrib/samples/fl/fl_demo1.rc create mode 100644 wx28X/contrib/samples/fl/fl_demo2.cpp create mode 100644 wx28X/contrib/samples/fl/fl_demo2.h create mode 100644 wx28X/contrib/samples/fl/fl_demo2.rc create mode 100644 wx28X/contrib/samples/fl/fl_fl_demo1.dsp create mode 100644 wx28X/contrib/samples/fl/fl_fl_demo1.vcp create mode 100644 wx28X/contrib/samples/fl/fl_fl_demo2.dsp create mode 100644 wx28X/contrib/samples/fl/fl_fl_demo2.vcp create mode 100644 wx28X/contrib/samples/fl/fl_fl_sample1.dsp create mode 100644 wx28X/contrib/samples/fl/fl_fl_sample1.vcp create mode 100644 wx28X/contrib/samples/fl/fl_fl_sample2.dsp create mode 100644 wx28X/contrib/samples/fl/fl_fl_sample2.vcp create mode 100644 wx28X/contrib/samples/fl/fl_fl_sample3.dsp create mode 100644 wx28X/contrib/samples/fl/fl_fl_sample3.vcp create mode 100644 wx28X/contrib/samples/fl/fl_sample1.cpp create mode 100644 wx28X/contrib/samples/fl/fl_sample1.rc create mode 100644 wx28X/contrib/samples/fl/fl_sample2.cpp create mode 100644 wx28X/contrib/samples/fl/fl_sample2.rc create mode 100644 wx28X/contrib/samples/fl/fl_sample3.cpp create mode 100644 wx28X/contrib/samples/fl/fl_sample3.rc create mode 100644 wx28X/contrib/samples/fl/makefile.bcc create mode 100644 wx28X/contrib/samples/fl/makefile.dmc create mode 100644 wx28X/contrib/samples/fl/makefile.dms create mode 100644 wx28X/contrib/samples/fl/makefile.gcc create mode 100644 wx28X/contrib/samples/fl/makefile.vc create mode 100644 wx28X/contrib/samples/fl/makefile.wat create mode 100644 wx28X/contrib/samples/foldbar/extended/Makefile.in create mode 100644 wx28X/contrib/samples/foldbar/extended/extended.bkl create mode 100644 wx28X/contrib/samples/foldbar/extended/extended.cpp create mode 100644 wx28X/contrib/samples/foldbar/extended/extended.dsp create mode 100644 wx28X/contrib/samples/foldbar/extended/extended.h create mode 100644 wx28X/contrib/samples/foldbar/extended/extended.rc create mode 100644 wx28X/contrib/samples/foldbar/extended/extended.vcp create mode 100644 wx28X/contrib/samples/foldbar/extended/extended.vcw create mode 100644 wx28X/contrib/samples/foldbar/extended/makefile.bcc create mode 100644 wx28X/contrib/samples/foldbar/extended/makefile.dmc create mode 100644 wx28X/contrib/samples/foldbar/extended/makefile.dms create mode 100644 wx28X/contrib/samples/foldbar/extended/makefile.gcc create mode 100644 wx28X/contrib/samples/foldbar/extended/makefile.vc create mode 100644 wx28X/contrib/samples/foldbar/extended/makefile.wat create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/Makefile.in create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/foldpanelbartest.cpp create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/foldpanelbartest.rc create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/foldtest.bkl create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/foldtest.dsp create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/foldtest.vcp create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/foldtest.vcw create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/foldtestpanel.cpp create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/foldtestpanel.h create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/layouttest.cpp create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/layouttest.h create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/makefile.bcc create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/makefile.dmc create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/makefile.dms create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/makefile.gcc create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/makefile.vc create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/makefile.wat create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/test.cpp create mode 100644 wx28X/contrib/samples/foldbar/foldpanelbar/test.h create mode 100644 wx28X/contrib/samples/gizmos/Makefile.in create mode 100644 wx28X/contrib/samples/gizmos/dynsash/Makefile.in create mode 100644 wx28X/contrib/samples/gizmos/dynsash/dynsash.bkl create mode 100644 wx28X/contrib/samples/gizmos/dynsash/dynsash.cpp create mode 100644 wx28X/contrib/samples/gizmos/dynsash/dynsash.dsp create mode 100644 wx28X/contrib/samples/gizmos/dynsash/dynsash.vcp create mode 100644 wx28X/contrib/samples/gizmos/dynsash/dynsash.vcw create mode 100644 wx28X/contrib/samples/gizmos/dynsash/makefile.bcc create mode 100644 wx28X/contrib/samples/gizmos/dynsash/makefile.dmc create mode 100644 wx28X/contrib/samples/gizmos/dynsash/makefile.dms create mode 100644 wx28X/contrib/samples/gizmos/dynsash/makefile.gcc create mode 100644 wx28X/contrib/samples/gizmos/dynsash/makefile.vc create mode 100644 wx28X/contrib/samples/gizmos/dynsash/makefile.wat create mode 100644 wx28X/contrib/samples/gizmos/dynsash_switch/Makefile.in create mode 100644 wx28X/contrib/samples/gizmos/dynsash_switch/dynsash_switch.bkl create mode 100644 wx28X/contrib/samples/gizmos/dynsash_switch/dynsash_switch.cpp create mode 100644 wx28X/contrib/samples/gizmos/dynsash_switch/dynsash_switch.dsp create mode 100644 wx28X/contrib/samples/gizmos/dynsash_switch/dynsash_switch.vcp create mode 100644 wx28X/contrib/samples/gizmos/dynsash_switch/dynsash_switch.vcw create mode 100644 wx28X/contrib/samples/gizmos/dynsash_switch/makefile.bcc create mode 100644 wx28X/contrib/samples/gizmos/dynsash_switch/makefile.dmc create mode 100644 wx28X/contrib/samples/gizmos/dynsash_switch/makefile.dms create mode 100644 wx28X/contrib/samples/gizmos/dynsash_switch/makefile.gcc create mode 100644 wx28X/contrib/samples/gizmos/dynsash_switch/makefile.vc create mode 100644 wx28X/contrib/samples/gizmos/dynsash_switch/makefile.wat create mode 100644 wx28X/contrib/samples/gizmos/editlbox/Makefile.in create mode 100644 wx28X/contrib/samples/gizmos/editlbox/editlbox.bkl create mode 100644 wx28X/contrib/samples/gizmos/editlbox/editlbox.dsp create mode 100644 wx28X/contrib/samples/gizmos/editlbox/editlbox.vcp create mode 100644 wx28X/contrib/samples/gizmos/editlbox/editlbox.vcw create mode 100644 wx28X/contrib/samples/gizmos/editlbox/makefile.bcc create mode 100644 wx28X/contrib/samples/gizmos/editlbox/makefile.dmc create mode 100644 wx28X/contrib/samples/gizmos/editlbox/makefile.dms create mode 100644 wx28X/contrib/samples/gizmos/editlbox/makefile.gcc create mode 100644 wx28X/contrib/samples/gizmos/editlbox/makefile.vc create mode 100644 wx28X/contrib/samples/gizmos/editlbox/makefile.wat create mode 100644 wx28X/contrib/samples/gizmos/editlbox/test.cpp create mode 100644 wx28X/contrib/samples/gizmos/led/Makefile.in create mode 100644 wx28X/contrib/samples/gizmos/led/led.bkl create mode 100644 wx28X/contrib/samples/gizmos/led/led.cpp create mode 100644 wx28X/contrib/samples/gizmos/led/led.dsp create mode 100644 wx28X/contrib/samples/gizmos/led/led.vcp create mode 100644 wx28X/contrib/samples/gizmos/led/led.vcw create mode 100644 wx28X/contrib/samples/gizmos/led/makefile.bcc create mode 100644 wx28X/contrib/samples/gizmos/led/makefile.dmc create mode 100644 wx28X/contrib/samples/gizmos/led/makefile.dms create mode 100644 wx28X/contrib/samples/gizmos/led/makefile.gcc create mode 100644 wx28X/contrib/samples/gizmos/led/makefile.vc create mode 100644 wx28X/contrib/samples/gizmos/led/makefile.wat create mode 100644 wx28X/contrib/samples/gizmos/multicell/Makefile.in create mode 100644 wx28X/contrib/samples/gizmos/multicell/makefile.bcc create mode 100644 wx28X/contrib/samples/gizmos/multicell/makefile.dmc create mode 100644 wx28X/contrib/samples/gizmos/multicell/makefile.dms create mode 100644 wx28X/contrib/samples/gizmos/multicell/makefile.gcc create mode 100644 wx28X/contrib/samples/gizmos/multicell/makefile.sl create mode 100644 wx28X/contrib/samples/gizmos/multicell/makefile.unx create mode 100644 wx28X/contrib/samples/gizmos/multicell/makefile.vc create mode 100644 wx28X/contrib/samples/gizmos/multicell/makefile.wat create mode 100644 wx28X/contrib/samples/gizmos/multicell/mtest.cpp create mode 100644 wx28X/contrib/samples/gizmos/multicell/multicell.bkl create mode 100644 wx28X/contrib/samples/gizmos/multicell/multicell.dsp create mode 100644 wx28X/contrib/samples/gizmos/multicell/multicell.vcp create mode 100644 wx28X/contrib/samples/gizmos/multicell/multicell.vcw create mode 100644 wx28X/contrib/samples/gizmos/multicell/multicell.vpj create mode 100644 wx28X/contrib/samples/gizmos/splittree/Makefile.in create mode 100644 wx28X/contrib/samples/gizmos/splittree/makefile.bcc create mode 100644 wx28X/contrib/samples/gizmos/splittree/makefile.dmc create mode 100644 wx28X/contrib/samples/gizmos/splittree/makefile.dms create mode 100644 wx28X/contrib/samples/gizmos/splittree/makefile.gcc create mode 100644 wx28X/contrib/samples/gizmos/splittree/makefile.sl create mode 100644 wx28X/contrib/samples/gizmos/splittree/makefile.unx create mode 100644 wx28X/contrib/samples/gizmos/splittree/makefile.va create mode 100644 wx28X/contrib/samples/gizmos/splittree/makefile.vc create mode 100644 wx28X/contrib/samples/gizmos/splittree/makefile.wat create mode 100644 wx28X/contrib/samples/gizmos/splittree/mondrian.ico create mode 100644 wx28X/contrib/samples/gizmos/splittree/mondrian.xpm create mode 100644 wx28X/contrib/samples/gizmos/splittree/splittree.bkl create mode 100644 wx28X/contrib/samples/gizmos/splittree/splittree.dsp create mode 100644 wx28X/contrib/samples/gizmos/splittree/splittree.vcp create mode 100644 wx28X/contrib/samples/gizmos/splittree/splittree.vcw create mode 100644 wx28X/contrib/samples/gizmos/splittree/tree.cpp create mode 100644 wx28X/contrib/samples/gizmos/splittree/tree.h create mode 100644 wx28X/contrib/samples/mmedia/Makefile.in create mode 100644 wx28X/contrib/samples/mmedia/descrip.mms create mode 100644 wx28X/contrib/samples/mmedia/eject.xpm create mode 100644 wx28X/contrib/samples/mmedia/makefile.bcc create mode 100644 wx28X/contrib/samples/mmedia/makefile.dmc create mode 100644 wx28X/contrib/samples/mmedia/makefile.dms create mode 100644 wx28X/contrib/samples/mmedia/makefile.gcc create mode 100644 wx28X/contrib/samples/mmedia/makefile.vc create mode 100644 wx28X/contrib/samples/mmedia/makefile.wat create mode 100644 wx28X/contrib/samples/mmedia/mmbman.cpp create mode 100644 wx28X/contrib/samples/mmedia/mmbman.h create mode 100644 wx28X/contrib/samples/mmedia/mmboard.bkl create mode 100644 wx28X/contrib/samples/mmedia/mmboard.cpp create mode 100644 wx28X/contrib/samples/mmedia/mmboard.dsp create mode 100644 wx28X/contrib/samples/mmedia/mmboard.h create mode 100644 wx28X/contrib/samples/mmedia/mmboard.rc create mode 100644 wx28X/contrib/samples/mmedia/mmboard.rc0 create mode 100644 wx28X/contrib/samples/mmedia/mmboard.vcp create mode 100644 wx28X/contrib/samples/mmedia/mmboard.vcw create mode 100644 wx28X/contrib/samples/mmedia/mondrian.ico create mode 100644 wx28X/contrib/samples/mmedia/mondrian.xpm create mode 100644 wx28X/contrib/samples/mmedia/mondros2.ico create mode 100644 wx28X/contrib/samples/mmedia/pause.xpm create mode 100644 wx28X/contrib/samples/mmedia/play.xpm create mode 100644 wx28X/contrib/samples/mmedia/stop.xpm create mode 100644 wx28X/contrib/samples/ogl/Makefile.in create mode 100644 wx28X/contrib/samples/ogl/ogledit/Makefile.in create mode 100644 wx28X/contrib/samples/ogl/ogledit/bitmaps/arrow.xpm create mode 100644 wx28X/contrib/samples/ogl/ogledit/bitmaps/tool1.xpm create mode 100644 wx28X/contrib/samples/ogl/ogledit/bitmaps/tool2.xpm create mode 100644 wx28X/contrib/samples/ogl/ogledit/bitmaps/tool3.xpm create mode 100644 wx28X/contrib/samples/ogl/ogledit/bitmaps/tool4.xpm create mode 100644 wx28X/contrib/samples/ogl/ogledit/doc.cpp create mode 100644 wx28X/contrib/samples/ogl/ogledit/doc.h create mode 100644 wx28X/contrib/samples/ogl/ogledit/makefile.bcc create mode 100644 wx28X/contrib/samples/ogl/ogledit/makefile.dmc create mode 100644 wx28X/contrib/samples/ogl/ogledit/makefile.dms create mode 100644 wx28X/contrib/samples/ogl/ogledit/makefile.gcc create mode 100644 wx28X/contrib/samples/ogl/ogledit/makefile.unx create mode 100644 wx28X/contrib/samples/ogl/ogledit/makefile.vc create mode 100644 wx28X/contrib/samples/ogl/ogledit/makefile.vms create mode 100644 wx28X/contrib/samples/ogl/ogledit/makefile.wat create mode 100644 wx28X/contrib/samples/ogl/ogledit/ogl.ico create mode 100644 wx28X/contrib/samples/ogl/ogledit/ogl.xpm create mode 100644 wx28X/contrib/samples/ogl/ogledit/ogledit.bkl create mode 100644 wx28X/contrib/samples/ogl/ogledit/ogledit.cpp create mode 100644 wx28X/contrib/samples/ogl/ogledit/ogledit.dsp create mode 100644 wx28X/contrib/samples/ogl/ogledit/ogledit.h create mode 100644 wx28X/contrib/samples/ogl/ogledit/ogledit.rc create mode 100644 wx28X/contrib/samples/ogl/ogledit/ogledit.vcp create mode 100644 wx28X/contrib/samples/ogl/ogledit/ogledit.vcw create mode 100644 wx28X/contrib/samples/ogl/ogledit/palette.cpp create mode 100644 wx28X/contrib/samples/ogl/ogledit/palette.h create mode 100644 wx28X/contrib/samples/ogl/ogledit/view.cpp create mode 100644 wx28X/contrib/samples/ogl/ogledit/view.h create mode 100644 wx28X/contrib/samples/ogl/studio/Makefile.in create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/alignb.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/alignl.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/alignr.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/alignt.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/arrow.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/arrow.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/copy.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/copysize.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/cut.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/cutpoint.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/file1.ico create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/folder1.ico create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/help.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/helpcs.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/horiz.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/linearrow.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/new.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/newpoint.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/open.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/paste.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/preview.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/print.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/redo.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/save.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/straight.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/texttool.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/texttool.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/tick.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/tick.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/undo.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/bitmaps/vert.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/cspalette.cpp create mode 100644 wx28X/contrib/samples/ogl/studio/cspalette.h create mode 100644 wx28X/contrib/samples/ogl/studio/csprint.cpp create mode 100644 wx28X/contrib/samples/ogl/studio/dialogs.cpp create mode 100644 wx28X/contrib/samples/ogl/studio/dialogs.h create mode 100644 wx28X/contrib/samples/ogl/studio/doc.cpp create mode 100644 wx28X/contrib/samples/ogl/studio/doc.h create mode 100644 wx28X/contrib/samples/ogl/studio/mainfrm.cpp create mode 100644 wx28X/contrib/samples/ogl/studio/mainfrm.h create mode 100644 wx28X/contrib/samples/ogl/studio/makefile.bcc create mode 100644 wx28X/contrib/samples/ogl/studio/makefile.dmc create mode 100644 wx28X/contrib/samples/ogl/studio/makefile.dms create mode 100644 wx28X/contrib/samples/ogl/studio/makefile.gcc create mode 100644 wx28X/contrib/samples/ogl/studio/makefile.unx create mode 100644 wx28X/contrib/samples/ogl/studio/makefile.vc create mode 100644 wx28X/contrib/samples/ogl/studio/makefile.wat create mode 100644 wx28X/contrib/samples/ogl/studio/manual/alignb.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/alignl.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/alignr.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/alignt.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/arrow.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/back.gif create mode 100644 wx28X/contrib/samples/ogl/studio/manual/bullet.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/contents.gif create mode 100644 wx28X/contrib/samples/ogl/studio/manual/copy.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/copysize.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/cut.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/cutpoint.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/forward.gif create mode 100644 wx28X/contrib/samples/ogl/studio/manual/help.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/helpcs.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/horiz.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/linearrow.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/new.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/newpoint.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/open.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/paste.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/pointsize.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/preview.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/print.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/redo.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/save.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/straight.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/studio.cnt create mode 100644 wx28X/contrib/samples/ogl/studio/manual/studio.hlp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/studio.hpj create mode 100644 wx28X/contrib/samples/ogl/studio/manual/studio.tex create mode 100644 wx28X/contrib/samples/ogl/studio/manual/tex2rtf.ini create mode 100644 wx28X/contrib/samples/ogl/studio/manual/texttool.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/tick.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/toback.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/tofront.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/tool1.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/tool2.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/tool3.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/tool4.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/undo.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/up.gif create mode 100644 wx28X/contrib/samples/ogl/studio/manual/vert.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/manual/zoom.bmp create mode 100644 wx28X/contrib/samples/ogl/studio/project.cpp create mode 100644 wx28X/contrib/samples/ogl/studio/project.h create mode 100644 wx28X/contrib/samples/ogl/studio/shapes.cpp create mode 100644 wx28X/contrib/samples/ogl/studio/shapes.h create mode 100644 wx28X/contrib/samples/ogl/studio/studio.bkl create mode 100644 wx28X/contrib/samples/ogl/studio/studio.cpp create mode 100644 wx28X/contrib/samples/ogl/studio/studio.dsp create mode 100644 wx28X/contrib/samples/ogl/studio/studio.h create mode 100644 wx28X/contrib/samples/ogl/studio/studio.ico create mode 100644 wx28X/contrib/samples/ogl/studio/studio.rc create mode 100644 wx28X/contrib/samples/ogl/studio/studio.vcp create mode 100644 wx28X/contrib/samples/ogl/studio/studio.vcw create mode 100644 wx28X/contrib/samples/ogl/studio/studio.xpm create mode 100644 wx28X/contrib/samples/ogl/studio/studio_resources.h create mode 100644 wx28X/contrib/samples/ogl/studio/studio_resources.wxr create mode 100644 wx28X/contrib/samples/ogl/studio/symbols.cpp create mode 100644 wx28X/contrib/samples/ogl/studio/symbols.h create mode 100644 wx28X/contrib/samples/ogl/studio/view.cpp create mode 100644 wx28X/contrib/samples/ogl/studio/view.h create mode 100644 wx28X/contrib/samples/plot/Makefile.in create mode 100644 wx28X/contrib/samples/plot/makefile.bcc create mode 100644 wx28X/contrib/samples/plot/makefile.dmc create mode 100644 wx28X/contrib/samples/plot/makefile.dms create mode 100644 wx28X/contrib/samples/plot/makefile.gcc create mode 100644 wx28X/contrib/samples/plot/makefile.vc create mode 100644 wx28X/contrib/samples/plot/makefile.wat create mode 100644 wx28X/contrib/samples/plot/plot.bkl create mode 100644 wx28X/contrib/samples/plot/plot.cpp create mode 100644 wx28X/contrib/samples/plot/plot.dsp create mode 100644 wx28X/contrib/samples/plot/plot.rc create mode 100644 wx28X/contrib/samples/plot/plot.vcp create mode 100644 wx28X/contrib/samples/plot/plot.vcw create mode 100644 wx28X/contrib/samples/stc/Makefile.in create mode 100644 wx28X/contrib/samples/stc/defsext.h create mode 100644 wx28X/contrib/samples/stc/edit.cpp create mode 100644 wx28X/contrib/samples/stc/edit.h create mode 100644 wx28X/contrib/samples/stc/makefile.bcc create mode 100644 wx28X/contrib/samples/stc/makefile.dmc create mode 100644 wx28X/contrib/samples/stc/makefile.dms create mode 100644 wx28X/contrib/samples/stc/makefile.gcc create mode 100644 wx28X/contrib/samples/stc/makefile.vc create mode 100644 wx28X/contrib/samples/stc/makefile.wat create mode 100644 wx28X/contrib/samples/stc/mondrian.ico create mode 100644 wx28X/contrib/samples/stc/mondrian.xpm create mode 100644 wx28X/contrib/samples/stc/prefs.cpp create mode 100644 wx28X/contrib/samples/stc/prefs.h create mode 100644 wx28X/contrib/samples/stc/stctest.bkl create mode 100644 wx28X/contrib/samples/stc/stctest.cpp create mode 100644 wx28X/contrib/samples/stc/stctest.dsp create mode 100644 wx28X/contrib/samples/stc/stctest.rc create mode 100644 wx28X/contrib/samples/stc/stctest.vcp create mode 100644 wx28X/contrib/samples/stc/stctest.vcw create mode 100644 wx28X/contrib/samples/svg/Makefile.in create mode 100644 wx28X/contrib/samples/svg/SVGlogo24.bmp create mode 100644 wx28X/contrib/samples/svg/SVGlogo24.xpm create mode 100644 wx28X/contrib/samples/svg/bitmaps/help.xpm create mode 100644 wx28X/contrib/samples/svg/bitmaps/new.xpm create mode 100644 wx28X/contrib/samples/svg/bitmaps/save.xpm create mode 100644 wx28X/contrib/samples/svg/makefile.bcc create mode 100644 wx28X/contrib/samples/svg/makefile.dmc create mode 100644 wx28X/contrib/samples/svg/makefile.dms create mode 100644 wx28X/contrib/samples/svg/makefile.gcc create mode 100644 wx28X/contrib/samples/svg/makefile.vc create mode 100644 wx28X/contrib/samples/svg/makefile.wat create mode 100644 wx28X/contrib/samples/svg/mondrian.ico create mode 100644 wx28X/contrib/samples/svg/mondrian.xpm create mode 100644 wx28X/contrib/samples/svg/svgtest.bkl create mode 100644 wx28X/contrib/samples/svg/svgtest.cpp create mode 100644 wx28X/contrib/samples/svg/svgtest.dsp create mode 100644 wx28X/contrib/samples/svg/svgtest.rc create mode 100644 wx28X/contrib/samples/svg/svgtest.vcp create mode 100644 wx28X/contrib/samples/svg/svgtest.vcw create mode 100644 wx28X/contrib/src/Makefile.in create mode 100644 wx28X/contrib/src/applet/applet.cpp create mode 100644 wx28X/contrib/src/applet/appletwindow.cpp create mode 100644 wx28X/contrib/src/applet/echovar.cpp create mode 100644 wx28X/contrib/src/applet/ifelsevar.cpp create mode 100644 wx28X/contrib/src/applet/loadpage.cpp create mode 100644 wx28X/contrib/src/applet/makefile create mode 100644 wx28X/contrib/src/applet/plugin.cpp create mode 100644 wx28X/contrib/src/applet/prepecho.cpp create mode 100644 wx28X/contrib/src/applet/prepifelse.cpp create mode 100644 wx28X/contrib/src/applet/prepinclude.cpp create mode 100644 wx28X/contrib/src/deprecated/Makefile.in create mode 100644 wx28X/contrib/src/deprecated/cwlex_yy.c create mode 100644 wx28X/contrib/src/deprecated/cwy_tab.c create mode 100644 wx28X/contrib/src/deprecated/descrip.mms create mode 100644 wx28X/contrib/src/deprecated/doslex.c create mode 100644 wx28X/contrib/src/deprecated/dosyacc.c create mode 100644 wx28X/contrib/src/deprecated/lexer.l create mode 100644 wx28X/contrib/src/deprecated/parser.y create mode 100644 wx28X/contrib/src/deprecated/prop.cpp create mode 100644 wx28X/contrib/src/deprecated/propform.cpp create mode 100644 wx28X/contrib/src/deprecated/proplist.cpp create mode 100644 wx28X/contrib/src/deprecated/resource.cpp create mode 100644 wx28X/contrib/src/deprecated/tbarsmpl.cpp create mode 100644 wx28X/contrib/src/deprecated/treelay.cpp create mode 100644 wx28X/contrib/src/deprecated/wxexpr.cpp create mode 100644 wx28X/contrib/src/fl/Makefile.in create mode 100644 wx28X/contrib/src/fl/antiflickpl.cpp create mode 100644 wx28X/contrib/src/fl/bardragpl.cpp create mode 100644 wx28X/contrib/src/fl/barhintspl.cpp create mode 100644 wx28X/contrib/src/fl/cbcustom.cpp create mode 100644 wx28X/contrib/src/fl/controlbar.cpp create mode 100644 wx28X/contrib/src/fl/dyntbar.cpp create mode 100644 wx28X/contrib/src/fl/dyntbarhnd.cpp create mode 100644 wx28X/contrib/src/fl/files.lst create mode 100644 wx28X/contrib/src/fl/frmview.cpp create mode 100644 wx28X/contrib/src/fl/garbagec.cpp create mode 100644 wx28X/contrib/src/fl/gcupdatesmgr.cpp create mode 100644 wx28X/contrib/src/fl/hintanimpl.cpp create mode 100644 wx28X/contrib/src/fl/makedocs.vc create mode 100644 wx28X/contrib/src/fl/newbmpbtn.cpp create mode 100644 wx28X/contrib/src/fl/panedrawpl.cpp create mode 100644 wx28X/contrib/src/fl/rowdragpl.cpp create mode 100644 wx28X/contrib/src/fl/rowlayoutpl.cpp create mode 100644 wx28X/contrib/src/fl/toolwnd.cpp create mode 100644 wx28X/contrib/src/fl/updatesmgr.cpp create mode 100644 wx28X/contrib/src/foldbar/Makefile.in create mode 100644 wx28X/contrib/src/foldbar/captionbar.cpp create mode 100644 wx28X/contrib/src/foldbar/foldpanelbar.cpp create mode 100644 wx28X/contrib/src/foldbar/foldpanelitem.cpp create mode 100644 wx28X/contrib/src/foldbar/icon_collapsed.old.xpm create mode 100644 wx28X/contrib/src/foldbar/icon_collapsed.xpm create mode 100644 wx28X/contrib/src/foldbar/icon_expanded.old.xpm create mode 100644 wx28X/contrib/src/foldbar/icon_expanded.xpm create mode 100644 wx28X/contrib/src/foldbar/icon_theresmore.xpm create mode 100644 wx28X/contrib/src/gizmos/Makefile.in create mode 100644 wx28X/contrib/src/gizmos/dynamicsash.cpp create mode 100644 wx28X/contrib/src/gizmos/editlbox.cpp create mode 100644 wx28X/contrib/src/gizmos/eldel.xpm create mode 100644 wx28X/contrib/src/gizmos/eldown.xpm create mode 100644 wx28X/contrib/src/gizmos/eledit.xpm create mode 100644 wx28X/contrib/src/gizmos/elnew.xpm create mode 100644 wx28X/contrib/src/gizmos/elup.xpm create mode 100644 wx28X/contrib/src/gizmos/ledctrl.cpp create mode 100644 wx28X/contrib/src/gizmos/makedocs.vc create mode 100644 wx28X/contrib/src/gizmos/multicell.cpp create mode 100644 wx28X/contrib/src/gizmos/multicell.txt create mode 100644 wx28X/contrib/src/gizmos/multicell_todo.txt create mode 100644 wx28X/contrib/src/gizmos/splittree.cpp create mode 100644 wx28X/contrib/src/gizmos/statpict.cpp create mode 100644 wx28X/contrib/src/gizmos/statpict.txt create mode 100644 wx28X/contrib/src/gizmos/xh_statpict.cpp create mode 100644 wx28X/contrib/src/mmedia/Makefile.in create mode 100644 wx28X/contrib/src/mmedia/cdbase.cpp create mode 100644 wx28X/contrib/src/mmedia/cdunix.cpp create mode 100644 wx28X/contrib/src/mmedia/cdwin.cpp create mode 100644 wx28X/contrib/src/mmedia/g711.cpp create mode 100644 wx28X/contrib/src/mmedia/g721.cpp create mode 100644 wx28X/contrib/src/mmedia/g723_24.cpp create mode 100644 wx28X/contrib/src/mmedia/g723_40.cpp create mode 100644 wx28X/contrib/src/mmedia/g72x.cpp create mode 100644 wx28X/contrib/src/mmedia/makedocs.vc create mode 100644 wx28X/contrib/src/mmedia/sndaiff.cpp create mode 100644 wx28X/contrib/src/mmedia/sndbase.cpp create mode 100644 wx28X/contrib/src/mmedia/sndcodec.cpp create mode 100644 wx28X/contrib/src/mmedia/sndcpcm.cpp create mode 100644 wx28X/contrib/src/mmedia/sndesd.cpp create mode 100644 wx28X/contrib/src/mmedia/sndfile.cpp create mode 100644 wx28X/contrib/src/mmedia/sndg72x.cpp create mode 100644 wx28X/contrib/src/mmedia/sndmsad.cpp create mode 100644 wx28X/contrib/src/mmedia/sndoss.cpp create mode 100644 wx28X/contrib/src/mmedia/sndpcm.cpp create mode 100644 wx28X/contrib/src/mmedia/sndulaw.cpp create mode 100644 wx28X/contrib/src/mmedia/sndwav.cpp create mode 100644 wx28X/contrib/src/mmedia/sndwin.cpp create mode 100644 wx28X/contrib/src/mmedia/vidbase.cpp create mode 100644 wx28X/contrib/src/mmedia/vidwin.cpp create mode 100644 wx28X/contrib/src/mmedia/vidxanm.cpp create mode 100644 wx28X/contrib/src/net/Makefile.in create mode 100644 wx28X/contrib/src/net/email.cpp create mode 100644 wx28X/contrib/src/net/readme.txt create mode 100644 wx28X/contrib/src/net/smapi.cpp create mode 100644 wx28X/contrib/src/net/web.cpp create mode 100644 wx28X/contrib/src/ogl/Makefile.in create mode 100644 wx28X/contrib/src/ogl/basic.cpp create mode 100644 wx28X/contrib/src/ogl/basic2.cpp create mode 100644 wx28X/contrib/src/ogl/bmpshape.cpp create mode 100644 wx28X/contrib/src/ogl/canvas.cpp create mode 100644 wx28X/contrib/src/ogl/composit.cpp create mode 100644 wx28X/contrib/src/ogl/constrnt.cpp create mode 100644 wx28X/contrib/src/ogl/divided.cpp create mode 100644 wx28X/contrib/src/ogl/drawn.cpp create mode 100644 wx28X/contrib/src/ogl/lines.cpp create mode 100644 wx28X/contrib/src/ogl/makedocs.vc create mode 100644 wx28X/contrib/src/ogl/mfutils.cpp create mode 100644 wx28X/contrib/src/ogl/ogldiag.cpp create mode 100644 wx28X/contrib/src/ogl/oglmisc.cpp create mode 100644 wx28X/contrib/src/plot/Makefile.in create mode 100644 wx28X/contrib/src/plot/plot.cpp create mode 100644 wx28X/contrib/src/stc/Makefile.in create mode 100644 wx28X/contrib/src/stc/PlatWX.cpp create mode 100644 wx28X/contrib/src/stc/PlatWX.h create mode 100644 wx28X/contrib/src/stc/README.txt create mode 100644 wx28X/contrib/src/stc/ScintillaWX.cpp create mode 100644 wx28X/contrib/src/stc/ScintillaWX.h create mode 100644 wx28X/contrib/src/stc/gen_iface.py create mode 100644 wx28X/contrib/src/stc/scintilla/License.txt create mode 100644 wx28X/contrib/src/stc/scintilla/README.txt create mode 100644 wx28X/contrib/src/stc/scintilla/include/Accessor.h create mode 100644 wx28X/contrib/src/stc/scintilla/include/KeyWords.h create mode 100644 wx28X/contrib/src/stc/scintilla/include/Platform.h create mode 100644 wx28X/contrib/src/stc/scintilla/include/PropSet.h create mode 100644 wx28X/contrib/src/stc/scintilla/include/SString.h create mode 100644 wx28X/contrib/src/stc/scintilla/include/SciLexer.h create mode 100644 wx28X/contrib/src/stc/scintilla/include/Scintilla.h create mode 100644 wx28X/contrib/src/stc/scintilla/include/Scintilla.iface create mode 100644 wx28X/contrib/src/stc/scintilla/include/ScintillaWidget.h create mode 100644 wx28X/contrib/src/stc/scintilla/include/WindowAccessor.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/AutoComplete.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/AutoComplete.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/CallTip.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/CallTip.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/CellBuffer.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/CellBuffer.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/CharClassify.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/CharClassify.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/ContractionState.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/ContractionState.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/Document.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/Document.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/DocumentAccessor.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/DocumentAccessor.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/Editor.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/Editor.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/ExternalLexer.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/ExternalLexer.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/Indicator.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/Indicator.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/KeyMap.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/KeyMap.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/KeyWords.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexAPDL.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexAU3.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexAVE.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexAda.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexAsm.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexAsn1.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexBaan.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexBash.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexBasic.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexBullant.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexCLW.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexCPP.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexCSS.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexCaml.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexConf.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexCrontab.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexCsound.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexEScript.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexEiffel.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexErlang.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexFlagship.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexForth.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexFortran.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexGui4Cli.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexHTML.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexHaskell.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexInno.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexKix.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexLisp.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexLout.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexLua.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexMMIXAL.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexMPT.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexMSSQL.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexMatlab.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexMetapost.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexNsis.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexOpal.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexOthers.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexPB.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexPOV.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexPS.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexPascal.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexPerl.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexPython.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexRebol.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexRuby.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexSQL.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexScriptol.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexSmalltalk.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexSpecman.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexSpice.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexTADS3.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexTCL.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexTeX.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexVB.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexVHDL.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexVerilog.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LexYAML.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LineMarker.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/LineMarker.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/PropSet.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/RESearch.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/RESearch.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/SVector.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/ScintillaBase.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/ScintillaBase.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/Style.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/Style.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/StyleContext.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/StyleContext.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/UniConversion.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/UniConversion.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/ViewStyle.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/ViewStyle.h create mode 100644 wx28X/contrib/src/stc/scintilla/src/WindowAccessor.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/XPM.cxx create mode 100644 wx28X/contrib/src/stc/scintilla/src/XPM.h create mode 100644 wx28X/contrib/src/stc/stc.cpp create mode 100644 wx28X/contrib/src/stc/stc.cpp.in create mode 100644 wx28X/contrib/src/stc/stc.h.in create mode 100644 wx28X/contrib/src/stc/stcM8.xml create mode 100644 wx28X/contrib/src/stc/stc_cw.h create mode 100644 wx28X/contrib/src/stc/stc_cw_d.h create mode 100644 wx28X/contrib/src/stc/stc_cwc.h create mode 100644 wx28X/contrib/src/stc/stc_cwc_d.h create mode 100644 wx28X/contrib/src/svg/Makefile.in create mode 100644 wx28X/contrib/src/svg/README.TXT create mode 100644 wx28X/contrib/src/svg/dcsvg.cpp create mode 100644 wx28X/contrib/src/svg/makedocs.vc create mode 100644 wx28X/contrib/utils/Makefile.in create mode 100644 wx28X/contrib/utils/convertrc/Makefile.in create mode 100644 wx28X/contrib/utils/convertrc/convert.cpp create mode 100644 wx28X/contrib/utils/convertrc/convert.h create mode 100644 wx28X/contrib/utils/convertrc/convertrc.bkl create mode 100644 wx28X/contrib/utils/convertrc/convertrc.dsp create mode 100644 wx28X/contrib/utils/convertrc/convertrc.vcp create mode 100644 wx28X/contrib/utils/convertrc/convertrc.vcw create mode 100644 wx28X/contrib/utils/convertrc/makefile.bcc create mode 100644 wx28X/contrib/utils/convertrc/makefile.dmc create mode 100644 wx28X/contrib/utils/convertrc/makefile.dms create mode 100644 wx28X/contrib/utils/convertrc/makefile.gcc create mode 100644 wx28X/contrib/utils/convertrc/makefile.vc create mode 100644 wx28X/contrib/utils/convertrc/makefile.wat create mode 100644 wx28X/contrib/utils/convertrc/rc2wxr.cpp create mode 100644 wx28X/contrib/utils/convertrc/rc2wxr.h create mode 100644 wx28X/contrib/utils/convertrc/rc2xml.cpp create mode 100644 wx28X/contrib/utils/convertrc/rc2xml.h create mode 100644 wx28X/contrib/utils/convertrc/wxconvert.rc create mode 100644 wx28X/contrib/utils/convertrc/wxr2xml.cpp create mode 100644 wx28X/contrib/utils/convertrc/wxr2xml.h create mode 100644 wx28X/demos/Makefile.in create mode 100644 wx28X/demos/bombs/Makefile.in create mode 100644 wx28X/demos/bombs/bombs.bkl create mode 100644 wx28X/demos/bombs/bombs.cpp create mode 100644 wx28X/demos/bombs/bombs.dsp create mode 100644 wx28X/demos/bombs/bombs.h create mode 100644 wx28X/demos/bombs/bombs.ico create mode 100644 wx28X/demos/bombs/bombs.pro create mode 100644 wx28X/demos/bombs/bombs.rc create mode 100644 wx28X/demos/bombs/bombs.vcp create mode 100644 wx28X/demos/bombs/bombs.vcw create mode 100644 wx28X/demos/bombs/bombs.xpm create mode 100644 wx28X/demos/bombs/bombs1.cpp create mode 100644 wx28X/demos/bombs/bombsM5.xml create mode 100644 wx28X/demos/bombs/descrip.mms create mode 100644 wx28X/demos/bombs/game.cpp create mode 100644 wx28X/demos/bombs/game.h create mode 100644 wx28X/demos/bombs/makefile.bcc create mode 100644 wx28X/demos/bombs/makefile.dmc create mode 100644 wx28X/demos/bombs/makefile.dms create mode 100644 wx28X/demos/bombs/makefile.gcc create mode 100644 wx28X/demos/bombs/makefile.unx create mode 100644 wx28X/demos/bombs/makefile.vc create mode 100644 wx28X/demos/bombs/makefile.wat create mode 100644 wx28X/demos/bombs/readme.txt create mode 100644 wx28X/demos/dbbrowse/Makefile.in create mode 100644 wx28X/demos/dbbrowse/bitmaps/col.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/col.xpm create mode 100644 wx28X/demos/dbbrowse/bitmaps/d_closed.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/d_closed.xpm create mode 100644 wx28X/demos/dbbrowse/bitmaps/d_open.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/d_open.xpm create mode 100644 wx28X/demos/dbbrowse/bitmaps/dsn.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/dsn.xpm create mode 100644 wx28X/demos/dbbrowse/bitmaps/dsnclose.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/dsnclose.xpm create mode 100644 wx28X/demos/dbbrowse/bitmaps/dsnopen.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/dsnopen.xpm create mode 100644 wx28X/demos/dbbrowse/bitmaps/f_closed.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/f_closed.xpm create mode 100644 wx28X/demos/dbbrowse/bitmaps/f_open.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/f_open.xpm create mode 100644 wx28X/demos/dbbrowse/bitmaps/key.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/key.xpm create mode 100644 wx28X/demos/dbbrowse/bitmaps/keyf.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/keyf.xpm create mode 100644 wx28X/demos/dbbrowse/bitmaps/logo.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/logo.xpm create mode 100644 wx28X/demos/dbbrowse/bitmaps/pgmctrl.bmp create mode 100644 wx28X/demos/dbbrowse/bitmaps/pgmctrl.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/pgmctrl.xpm create mode 100644 wx28X/demos/dbbrowse/bitmaps/tab.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/tab.xpm create mode 100644 wx28X/demos/dbbrowse/bitmaps/view.ico create mode 100644 wx28X/demos/dbbrowse/bitmaps/view.xpm create mode 100644 wx28X/demos/dbbrowse/browsedb.cpp create mode 100644 wx28X/demos/dbbrowse/browsedb.h create mode 100644 wx28X/demos/dbbrowse/dbbrowse.bkl create mode 100644 wx28X/demos/dbbrowse/dbbrowse.cpp create mode 100644 wx28X/demos/dbbrowse/dbbrowse.dsp create mode 100644 wx28X/demos/dbbrowse/dbbrowse.h create mode 100644 wx28X/demos/dbbrowse/dbbrowse.rc create mode 100644 wx28X/demos/dbbrowse/dbbrowse.vcp create mode 100644 wx28X/demos/dbbrowse/dbbrowse.vcw create mode 100644 wx28X/demos/dbbrowse/dbbrowseM5.xml create mode 100644 wx28X/demos/dbbrowse/dbgrid.cpp create mode 100644 wx28X/demos/dbbrowse/dbgrid.h create mode 100644 wx28X/demos/dbbrowse/dbtree.cpp create mode 100644 wx28X/demos/dbbrowse/dbtree.h create mode 100644 wx28X/demos/dbbrowse/de/dbbrowse.mo create mode 100644 wx28X/demos/dbbrowse/de/dbbrowse.po create mode 100644 wx28X/demos/dbbrowse/de/de.po create mode 100644 wx28X/demos/dbbrowse/de/help.mo create mode 100644 wx28X/demos/dbbrowse/de/help.po create mode 100644 wx28X/demos/dbbrowse/de/mo.cmd create mode 100644 wx28X/demos/dbbrowse/de/mo_de.cmd create mode 100644 wx28X/demos/dbbrowse/de/wxstd.mo create mode 100644 wx28X/demos/dbbrowse/de/xget.cfg create mode 100644 wx28X/demos/dbbrowse/de/xget.cmd create mode 100644 wx28X/demos/dbbrowse/dlguser.cpp create mode 100644 wx28X/demos/dbbrowse/dlguser.h create mode 100644 wx28X/demos/dbbrowse/doc.cpp create mode 100644 wx28X/demos/dbbrowse/doc.h create mode 100644 wx28X/demos/dbbrowse/dummy.cpp create mode 100644 wx28X/demos/dbbrowse/fr/wxstd.mo create mode 100644 wx28X/demos/dbbrowse/fr/xget.cfg create mode 100644 wx28X/demos/dbbrowse/help.cz/wxstd.mo create mode 100644 wx28X/demos/dbbrowse/help.de/compiler.htm create mode 100644 wx28X/demos/dbbrowse/help.de/dbbrowse.hhc create mode 100644 wx28X/demos/dbbrowse/help.de/dbbrowse.hhk create mode 100644 wx28X/demos/dbbrowse/help.de/dbbrowse.hhp create mode 100644 wx28X/demos/dbbrowse/help.de/dbbrowse.htm create mode 100644 wx28X/demos/dbbrowse/help.de/getcol.htm create mode 100644 wx28X/demos/dbbrowse/help.de/getcolsh.htm create mode 100644 wx28X/demos/dbbrowse/help.de/icons.htm create mode 100644 wx28X/demos/dbbrowse/help.de/picgrams.htm create mode 100644 wx28X/demos/dbbrowse/help.de/problems.htm create mode 100644 wx28X/demos/dbbrowse/help.de/remstar.htm create mode 100644 wx28X/demos/dbbrowse/help.de/sample.htm create mode 100644 wx28X/demos/dbbrowse/help.de/startprm.htm create mode 100644 wx28X/demos/dbbrowse/help.de/todo.htm create mode 100644 wx28X/demos/dbbrowse/help.de/wxdb.htm create mode 100644 wx28X/demos/dbbrowse/help.de/wxtable.htm create mode 100644 wx28X/demos/dbbrowse/help.png/col.png create mode 100644 wx28X/demos/dbbrowse/help.png/d_closed.png create mode 100644 wx28X/demos/dbbrowse/help.png/d_open.png create mode 100644 wx28X/demos/dbbrowse/help.png/dsn.png create mode 100644 wx28X/demos/dbbrowse/help.png/dsnclose.png create mode 100644 wx28X/demos/dbbrowse/help.png/dsnopen.png create mode 100644 wx28X/demos/dbbrowse/help.png/f_closed.png create mode 100644 wx28X/demos/dbbrowse/help.png/f_open.png create mode 100644 wx28X/demos/dbbrowse/help.png/gnu.png create mode 100644 wx28X/demos/dbbrowse/help.png/gtk.png create mode 100644 wx28X/demos/dbbrowse/help.png/imbau.png create mode 100644 wx28X/demos/dbbrowse/help.png/kde.png create mode 100644 wx28X/demos/dbbrowse/help.png/key.png create mode 100644 wx28X/demos/dbbrowse/help.png/keyf.png create mode 100644 wx28X/demos/dbbrowse/help.png/linux.png create mode 100644 wx28X/demos/dbbrowse/help.png/logo.png create mode 100644 wx28X/demos/dbbrowse/help.png/motif.png create mode 100644 wx28X/demos/dbbrowse/help.png/msvc.png create mode 100644 wx28X/demos/dbbrowse/help.png/odbc.png create mode 100644 wx28X/demos/dbbrowse/help.png/pgmctrl.png create mode 100644 wx28X/demos/dbbrowse/help.png/redh.png create mode 100644 wx28X/demos/dbbrowse/help.png/remstar.png create mode 100644 wx28X/demos/dbbrowse/help.png/server.png create mode 100644 wx28X/demos/dbbrowse/help.png/suse.png create mode 100644 wx28X/demos/dbbrowse/help.png/tab.png create mode 100644 wx28X/demos/dbbrowse/help.png/view.png create mode 100644 wx28X/demos/dbbrowse/help.png/winnt.png create mode 100644 wx28X/demos/dbbrowse/help.png/wins.png create mode 100644 wx28X/demos/dbbrowse/help.std/compiler.htm create mode 100644 wx28X/demos/dbbrowse/help.std/dbbrowse.hhc create mode 100644 wx28X/demos/dbbrowse/help.std/dbbrowse.hhk create mode 100644 wx28X/demos/dbbrowse/help.std/dbbrowse.hhp create mode 100644 wx28X/demos/dbbrowse/help.std/dbbrowse.htm create mode 100644 wx28X/demos/dbbrowse/help.std/getcol.htm create mode 100644 wx28X/demos/dbbrowse/help.std/getcolsh.htm create mode 100644 wx28X/demos/dbbrowse/help.std/icons.htm create mode 100644 wx28X/demos/dbbrowse/help.std/picgrams.htm create mode 100644 wx28X/demos/dbbrowse/help.std/problems.htm create mode 100644 wx28X/demos/dbbrowse/help.std/remstar.htm create mode 100644 wx28X/demos/dbbrowse/help.std/sample.htm create mode 100644 wx28X/demos/dbbrowse/help.std/startprm.htm create mode 100644 wx28X/demos/dbbrowse/help.std/todo.htm create mode 100644 wx28X/demos/dbbrowse/help.std/wxdb.htm create mode 100644 wx28X/demos/dbbrowse/help.std/wxtable.htm create mode 100644 wx28X/demos/dbbrowse/makefile.bcc create mode 100644 wx28X/demos/dbbrowse/makefile.dmc create mode 100644 wx28X/demos/dbbrowse/makefile.dms create mode 100644 wx28X/demos/dbbrowse/makefile.gcc create mode 100644 wx28X/demos/dbbrowse/makefile.vc create mode 100644 wx28X/demos/dbbrowse/makefile.wat create mode 100644 wx28X/demos/dbbrowse/pgmctrl.cpp create mode 100644 wx28X/demos/dbbrowse/pgmctrl.h create mode 100644 wx28X/demos/dbbrowse/std.h create mode 100644 wx28X/demos/dbbrowse/tabpgwin.cpp create mode 100644 wx28X/demos/dbbrowse/tabpgwin.h create mode 100644 wx28X/demos/demos.bkl create mode 100644 wx28X/demos/forty/Makefile.in create mode 100644 wx28X/demos/forty/about.htm create mode 100644 wx28X/demos/forty/canvas.cpp create mode 100644 wx28X/demos/forty/canvas.h create mode 100644 wx28X/demos/forty/card.cpp create mode 100644 wx28X/demos/forty/card.h create mode 100644 wx28X/demos/forty/cards.ico create mode 100644 wx28X/demos/forty/forty-icons.r create mode 100644 wx28X/demos/forty/forty.bkl create mode 100644 wx28X/demos/forty/forty.cpp create mode 100644 wx28X/demos/forty/forty.dsp create mode 100644 wx28X/demos/forty/forty.h create mode 100644 wx28X/demos/forty/forty.pro create mode 100644 wx28X/demos/forty/forty.r create mode 100644 wx28X/demos/forty/forty.rc create mode 100644 wx28X/demos/forty/forty.vcp create mode 100644 wx28X/demos/forty/forty.vcw create mode 100644 wx28X/demos/forty/forty.xpm create mode 100644 wx28X/demos/forty/fortyM5.xml create mode 100644 wx28X/demos/forty/game.cpp create mode 100644 wx28X/demos/forty/game.h create mode 100644 wx28X/demos/forty/makefile.bcc create mode 100644 wx28X/demos/forty/makefile.dmc create mode 100644 wx28X/demos/forty/makefile.dms create mode 100644 wx28X/demos/forty/makefile.gcc create mode 100644 wx28X/demos/forty/makefile.unx create mode 100644 wx28X/demos/forty/makefile.vc create mode 100644 wx28X/demos/forty/makefile.wat create mode 100644 wx28X/demos/forty/makemac6.mcp create mode 100644 wx28X/demos/forty/pictures.xpm create mode 100644 wx28X/demos/forty/pile.cpp create mode 100644 wx28X/demos/forty/pile.h create mode 100644 wx28X/demos/forty/playerdg.cpp create mode 100644 wx28X/demos/forty/playerdg.h create mode 100644 wx28X/demos/forty/readme.txt create mode 100644 wx28X/demos/forty/scoredg.cpp create mode 100644 wx28X/demos/forty/scoredg.h create mode 100644 wx28X/demos/forty/scorefil.cpp create mode 100644 wx28X/demos/forty/scorefil.h create mode 100644 wx28X/demos/forty/symbols.xpm create mode 100644 wx28X/demos/fractal/Makefile.in create mode 100644 wx28X/demos/fractal/fractal.bkl create mode 100644 wx28X/demos/fractal/fractal.cpp create mode 100644 wx28X/demos/fractal/fractal.dsp create mode 100644 wx28X/demos/fractal/fractal.pro create mode 100644 wx28X/demos/fractal/fractal.rc create mode 100644 wx28X/demos/fractal/fractal.vcp create mode 100644 wx28X/demos/fractal/fractal.vcw create mode 100644 wx28X/demos/fractal/fractalM5.xml create mode 100644 wx28X/demos/fractal/makefile.bcc create mode 100644 wx28X/demos/fractal/makefile.dmc create mode 100644 wx28X/demos/fractal/makefile.dms create mode 100644 wx28X/demos/fractal/makefile.gcc create mode 100644 wx28X/demos/fractal/makefile.unx create mode 100644 wx28X/demos/fractal/makefile.vc create mode 100644 wx28X/demos/fractal/makefile.wat create mode 100644 wx28X/demos/fractal/mondrian.ico create mode 100644 wx28X/demos/life/Makefile.in create mode 100644 wx28X/demos/life/bitmaps/center.bmp create mode 100644 wx28X/demos/life/bitmaps/center.xpm create mode 100644 wx28X/demos/life/bitmaps/east.bmp create mode 100644 wx28X/demos/life/bitmaps/east.xpm create mode 100644 wx28X/demos/life/bitmaps/info.bmp create mode 100644 wx28X/demos/life/bitmaps/info.xpm create mode 100644 wx28X/demos/life/bitmaps/life.bmp create mode 100644 wx28X/demos/life/bitmaps/life.xpm create mode 100644 wx28X/demos/life/bitmaps/north.bmp create mode 100644 wx28X/demos/life/bitmaps/north.xpm create mode 100644 wx28X/demos/life/bitmaps/open.bmp create mode 100644 wx28X/demos/life/bitmaps/open.xpm create mode 100644 wx28X/demos/life/bitmaps/play.bmp create mode 100644 wx28X/demos/life/bitmaps/play.xpm create mode 100644 wx28X/demos/life/bitmaps/reset.bmp create mode 100644 wx28X/demos/life/bitmaps/reset.xpm create mode 100644 wx28X/demos/life/bitmaps/south.bmp create mode 100644 wx28X/demos/life/bitmaps/south.xpm create mode 100644 wx28X/demos/life/bitmaps/stop.bmp create mode 100644 wx28X/demos/life/bitmaps/stop.xpm create mode 100644 wx28X/demos/life/bitmaps/west.bmp create mode 100644 wx28X/demos/life/bitmaps/west.xpm create mode 100644 wx28X/demos/life/bitmaps/zoomin.bmp create mode 100644 wx28X/demos/life/bitmaps/zoomin.xpm create mode 100644 wx28X/demos/life/bitmaps/zoomout.bmp create mode 100644 wx28X/demos/life/bitmaps/zoomout.xpm create mode 100644 wx28X/demos/life/breeder.lif create mode 100644 wx28X/demos/life/dialogs.cpp create mode 100644 wx28X/demos/life/dialogs.h create mode 100644 wx28X/demos/life/game.cpp create mode 100644 wx28X/demos/life/game.h create mode 100644 wx28X/demos/life/life.bkl create mode 100644 wx28X/demos/life/life.cpp create mode 100644 wx28X/demos/life/life.dsp create mode 100644 wx28X/demos/life/life.h create mode 100644 wx28X/demos/life/life.pro create mode 100644 wx28X/demos/life/life.rc create mode 100644 wx28X/demos/life/life.vcp create mode 100644 wx28X/demos/life/life.vcw create mode 100644 wx28X/demos/life/lifeM5.xml create mode 100644 wx28X/demos/life/makefile.bcc create mode 100644 wx28X/demos/life/makefile.dmc create mode 100644 wx28X/demos/life/makefile.dms create mode 100644 wx28X/demos/life/makefile.gcc create mode 100644 wx28X/demos/life/makefile.unx create mode 100644 wx28X/demos/life/makefile.vc create mode 100644 wx28X/demos/life/makefile.wat create mode 100644 wx28X/demos/life/mondrian.ico create mode 100644 wx28X/demos/life/mondrian.xpm create mode 100644 wx28X/demos/life/reader.cpp create mode 100644 wx28X/demos/life/reader.h create mode 100644 wx28X/demos/life/samples.inc create mode 100644 wx28X/demos/life/setup/wince/Common/breeder.lif create mode 100644 wx28X/demos/life/setup/wince/Common/life.htp create mode 100644 wx28X/demos/life/setup/wince/build.bat create mode 100644 wx28X/demos/life/setup/wince/install.ini create mode 100644 wx28X/demos/life/setup/wince/life.ico create mode 100644 wx28X/demos/life/setup/wince/life.inf create mode 100644 wx28X/demos/life/setup/wince/readme.txt create mode 100644 wx28X/demos/life/setup/wince/register.bat create mode 100644 wx28X/demos/makefile.bcc create mode 100644 wx28X/demos/makefile.dmc create mode 100644 wx28X/demos/makefile.dms create mode 100644 wx28X/demos/makefile.gcc create mode 100644 wx28X/demos/makefile.vc create mode 100644 wx28X/demos/makefile.wat create mode 100644 wx28X/demos/poem/Makefile.in create mode 100644 wx28X/demos/poem/corner1.ico create mode 100644 wx28X/demos/poem/corner1.xpm create mode 100644 wx28X/demos/poem/corner2.ico create mode 100644 wx28X/demos/poem/corner2.xpm create mode 100644 wx28X/demos/poem/corner3.ico create mode 100644 wx28X/demos/poem/corner3.xpm create mode 100644 wx28X/demos/poem/corner4.ico create mode 100644 wx28X/demos/poem/corner4.xpm create mode 100644 wx28X/demos/poem/makefile.bcc create mode 100644 wx28X/demos/poem/makefile.dmc create mode 100644 wx28X/demos/poem/makefile.dms create mode 100644 wx28X/demos/poem/makefile.gcc create mode 100644 wx28X/demos/poem/makefile.unx create mode 100644 wx28X/demos/poem/makefile.vc create mode 100644 wx28X/demos/poem/makefile.wat create mode 100644 wx28X/demos/poem/poem.bkl create mode 100644 wx28X/demos/poem/poem.dsp create mode 100644 wx28X/demos/poem/poem.pro create mode 100644 wx28X/demos/poem/poem.vcp create mode 100644 wx28X/demos/poem/poem.vcw create mode 100644 wx28X/demos/poem/poemM5.xml create mode 100644 wx28X/demos/poem/wxpoem.cpp create mode 100644 wx28X/demos/poem/wxpoem.dat create mode 100644 wx28X/demos/poem/wxpoem.h create mode 100644 wx28X/demos/poem/wxpoem.ico create mode 100644 wx28X/demos/poem/wxpoem.idx create mode 100644 wx28X/demos/poem/wxpoem.rc create mode 100644 wx28X/demos/poem/wxpoem.txt create mode 100644 wx28X/demos/poem/wxpoem.xpm create mode 100644 wx28X/descrip.mms create mode 100644 wx28X/difflast.pl create mode 100644 wx28X/docs/base/readme.txt create mode 100644 wx28X/docs/changes.txt create mode 100644 wx28X/docs/cocoa/readme.txt create mode 100644 wx28X/docs/gtk/changes.txt create mode 100644 wx28X/docs/gtk/licence.txt create mode 100644 wx28X/docs/gtk/readme.txt create mode 100644 wx28X/docs/htmlhelp/wx.chm create mode 100644 wx28X/docs/licence.txt create mode 100644 wx28X/docs/mac/readme.txt create mode 100644 wx28X/docs/mgl/readme.txt create mode 100644 wx28X/docs/microwin/readme.txt create mode 100644 wx28X/docs/motif/readme.txt create mode 100644 wx28X/docs/msw/install.txt create mode 100644 wx28X/docs/msw/readme.txt create mode 100644 wx28X/docs/msw/wince/readme.txt create mode 100644 wx28X/docs/os2/readme.txt create mode 100644 wx28X/docs/palmos/readme.txt create mode 100644 wx28X/docs/readme.txt create mode 100644 wx28X/docs/univ/readme.txt create mode 100644 wx28X/docs/wine/changes.txt create mode 100644 wx28X/docs/wine/licence.txt create mode 100644 wx28X/docs/wine/readme.txt create mode 100644 wx28X/docs/x11/readme.txt create mode 100644 wx28X/include/msvc/wx/setup.h create mode 100644 wx28X/include/wx/aboutdlg.h create mode 100644 wx28X/include/wx/accel.h create mode 100644 wx28X/include/wx/access.h create mode 100644 wx28X/include/wx/afterstd.h create mode 100644 wx28X/include/wx/anidecod.h create mode 100644 wx28X/include/wx/animate.h create mode 100644 wx28X/include/wx/animdecod.h create mode 100644 wx28X/include/wx/app.h create mode 100644 wx28X/include/wx/apptrait.h create mode 100644 wx28X/include/wx/archive.h create mode 100644 wx28X/include/wx/arrimpl.cpp create mode 100644 wx28X/include/wx/arrstr.h create mode 100644 wx28X/include/wx/artprov.h create mode 100644 wx28X/include/wx/aui/aui.h create mode 100644 wx28X/include/wx/aui/auibar.h create mode 100644 wx28X/include/wx/aui/auibook.h create mode 100644 wx28X/include/wx/aui/dockart.h create mode 100644 wx28X/include/wx/aui/floatpane.h create mode 100644 wx28X/include/wx/aui/framemanager.h create mode 100644 wx28X/include/wx/aui/tabmdi.h create mode 100644 wx28X/include/wx/beforestd.h create mode 100644 wx28X/include/wx/bitmap.h create mode 100644 wx28X/include/wx/bmpbuttn.h create mode 100644 wx28X/include/wx/bmpcbox.h create mode 100644 wx28X/include/wx/bookctrl.h create mode 100644 wx28X/include/wx/brush.h create mode 100644 wx28X/include/wx/buffer.h create mode 100644 wx28X/include/wx/build.h create mode 100644 wx28X/include/wx/busyinfo.h create mode 100644 wx28X/include/wx/button.h create mode 100644 wx28X/include/wx/calctrl.h create mode 100644 wx28X/include/wx/caret.h create mode 100644 wx28X/include/wx/checkbox.h create mode 100644 wx28X/include/wx/checklst.h create mode 100644 wx28X/include/wx/chkconf.h create mode 100644 wx28X/include/wx/choicdlg.h create mode 100644 wx28X/include/wx/choice.h create mode 100644 wx28X/include/wx/choicebk.h create mode 100644 wx28X/include/wx/clipbrd.h create mode 100644 wx28X/include/wx/clntdata.h create mode 100644 wx28X/include/wx/clrpicker.h create mode 100644 wx28X/include/wx/cmdline.h create mode 100644 wx28X/include/wx/cmdproc.h create mode 100644 wx28X/include/wx/cmndata.h create mode 100644 wx28X/include/wx/collpane.h create mode 100644 wx28X/include/wx/colordlg.h create mode 100644 wx28X/include/wx/colour.h create mode 100644 wx28X/include/wx/combo.h create mode 100644 wx28X/include/wx/combobox.h create mode 100644 wx28X/include/wx/confbase.h create mode 100644 wx28X/include/wx/config.h create mode 100644 wx28X/include/wx/containr.h create mode 100644 wx28X/include/wx/control.h create mode 100644 wx28X/include/wx/convauto.h create mode 100644 wx28X/include/wx/cpp.h create mode 100644 wx28X/include/wx/cppunit.h create mode 100644 wx28X/include/wx/cshelp.h create mode 100644 wx28X/include/wx/ctrlsub.h create mode 100644 wx28X/include/wx/cursor.h create mode 100644 wx28X/include/wx/dataobj.h create mode 100644 wx28X/include/wx/dataview.h create mode 100644 wx28X/include/wx/datectrl.h create mode 100644 wx28X/include/wx/dateevt.h create mode 100644 wx28X/include/wx/datetime.h create mode 100644 wx28X/include/wx/datstrm.h create mode 100644 wx28X/include/wx/db.h create mode 100644 wx28X/include/wx/dbgrid.h create mode 100644 wx28X/include/wx/dbkeyg.h create mode 100644 wx28X/include/wx/dbtable.h create mode 100644 wx28X/include/wx/dc.h create mode 100644 wx28X/include/wx/dcbuffer.h create mode 100644 wx28X/include/wx/dcclient.h create mode 100644 wx28X/include/wx/dcgraph.h create mode 100644 wx28X/include/wx/dcmemory.h create mode 100644 wx28X/include/wx/dcmirror.h create mode 100644 wx28X/include/wx/dcprint.h create mode 100644 wx28X/include/wx/dcps.h create mode 100644 wx28X/include/wx/dcscreen.h create mode 100644 wx28X/include/wx/dde.h create mode 100644 wx28X/include/wx/debug.h create mode 100644 wx28X/include/wx/debugrpt.h create mode 100644 wx28X/include/wx/defs.h create mode 100644 wx28X/include/wx/dialog.h create mode 100644 wx28X/include/wx/dialup.h create mode 100644 wx28X/include/wx/dir.h create mode 100644 wx28X/include/wx/dirctrl.h create mode 100644 wx28X/include/wx/dirdlg.h create mode 100644 wx28X/include/wx/display.h create mode 100644 wx28X/include/wx/display_impl.h create mode 100644 wx28X/include/wx/dlimpexp.h create mode 100644 wx28X/include/wx/dnd.h create mode 100644 wx28X/include/wx/docmdi.h create mode 100644 wx28X/include/wx/docview.h create mode 100644 wx28X/include/wx/dragimag.h create mode 100644 wx28X/include/wx/dynarray.h create mode 100644 wx28X/include/wx/dynlib.h create mode 100644 wx28X/include/wx/dynload.h create mode 100644 wx28X/include/wx/effects.h create mode 100644 wx28X/include/wx/encconv.h create mode 100644 wx28X/include/wx/encinfo.h create mode 100644 wx28X/include/wx/event.h create mode 100644 wx28X/include/wx/evtloop.h create mode 100644 wx28X/include/wx/except.h create mode 100644 wx28X/include/wx/fdrepdlg.h create mode 100644 wx28X/include/wx/features.h create mode 100644 wx28X/include/wx/ffile.h create mode 100644 wx28X/include/wx/file.h create mode 100644 wx28X/include/wx/fileconf.h create mode 100644 wx28X/include/wx/filedlg.h create mode 100644 wx28X/include/wx/filefn.h create mode 100644 wx28X/include/wx/filename.h create mode 100644 wx28X/include/wx/filepicker.h create mode 100644 wx28X/include/wx/filesys.h create mode 100644 wx28X/include/wx/flags.h create mode 100644 wx28X/include/wx/fmappriv.h create mode 100644 wx28X/include/wx/font.h create mode 100644 wx28X/include/wx/fontdlg.h create mode 100644 wx28X/include/wx/fontenc.h create mode 100644 wx28X/include/wx/fontenum.h create mode 100644 wx28X/include/wx/fontmap.h create mode 100644 wx28X/include/wx/fontpicker.h create mode 100644 wx28X/include/wx/fontutil.h create mode 100644 wx28X/include/wx/frame.h create mode 100644 wx28X/include/wx/fs_arc.h create mode 100644 wx28X/include/wx/fs_filter.h create mode 100644 wx28X/include/wx/fs_inet.h create mode 100644 wx28X/include/wx/fs_mem.h create mode 100644 wx28X/include/wx/fs_zip.h create mode 100644 wx28X/include/wx/gauge.h create mode 100644 wx28X/include/wx/gbsizer.h create mode 100644 wx28X/include/wx/gdicmn.h create mode 100644 wx28X/include/wx/gdiobj.h create mode 100644 wx28X/include/wx/generic/aboutdlgg.h create mode 100644 wx28X/include/wx/generic/accel.h create mode 100644 wx28X/include/wx/generic/animate.h create mode 100644 wx28X/include/wx/generic/bmpcbox.h create mode 100644 wx28X/include/wx/generic/busyinfo.h create mode 100644 wx28X/include/wx/generic/buttonbar.h create mode 100644 wx28X/include/wx/generic/calctrl.h create mode 100644 wx28X/include/wx/generic/caret.h create mode 100644 wx28X/include/wx/generic/choicdgg.h create mode 100644 wx28X/include/wx/generic/clrpickerg.h create mode 100644 wx28X/include/wx/generic/collpaneg.h create mode 100644 wx28X/include/wx/generic/colour.h create mode 100644 wx28X/include/wx/generic/colrdlgg.h create mode 100644 wx28X/include/wx/generic/combo.h create mode 100644 wx28X/include/wx/generic/dataview.h create mode 100644 wx28X/include/wx/generic/datectrl.h create mode 100644 wx28X/include/wx/generic/dcpsg.h create mode 100644 wx28X/include/wx/generic/dirctrlg.h create mode 100644 wx28X/include/wx/generic/dirdlgg.h create mode 100644 wx28X/include/wx/generic/dragimgg.h create mode 100644 wx28X/include/wx/generic/fdrepdlg.h create mode 100644 wx28X/include/wx/generic/filedlgg.h create mode 100644 wx28X/include/wx/generic/filepickerg.h create mode 100644 wx28X/include/wx/generic/fontdlgg.h create mode 100644 wx28X/include/wx/generic/fontpickerg.h create mode 100644 wx28X/include/wx/generic/grid.h create mode 100644 wx28X/include/wx/generic/gridctrl.h create mode 100644 wx28X/include/wx/generic/gridsel.h create mode 100644 wx28X/include/wx/generic/helpext.h create mode 100644 wx28X/include/wx/generic/icon.h create mode 100644 wx28X/include/wx/generic/imaglist.h create mode 100644 wx28X/include/wx/generic/laywin.h create mode 100644 wx28X/include/wx/generic/listctrl.h create mode 100644 wx28X/include/wx/generic/logg.h create mode 100644 wx28X/include/wx/generic/mask.h create mode 100644 wx28X/include/wx/generic/mdig.h create mode 100644 wx28X/include/wx/generic/msgdlgg.h create mode 100644 wx28X/include/wx/generic/notebook.h create mode 100644 wx28X/include/wx/generic/numdlgg.h create mode 100644 wx28X/include/wx/generic/paletteg.h create mode 100644 wx28X/include/wx/generic/panelg.h create mode 100644 wx28X/include/wx/generic/printps.h create mode 100644 wx28X/include/wx/generic/prntdlgg.h create mode 100644 wx28X/include/wx/generic/progdlgg.h create mode 100644 wx28X/include/wx/generic/propdlg.h create mode 100644 wx28X/include/wx/generic/region.h create mode 100644 wx28X/include/wx/generic/sashwin.h create mode 100644 wx28X/include/wx/generic/scrolwin.h create mode 100644 wx28X/include/wx/generic/spinctlg.h create mode 100644 wx28X/include/wx/generic/splash.h create mode 100644 wx28X/include/wx/generic/splitter.h create mode 100644 wx28X/include/wx/generic/srchctlg.h create mode 100644 wx28X/include/wx/generic/statline.h create mode 100644 wx28X/include/wx/generic/statusbr.h create mode 100644 wx28X/include/wx/generic/tabg.h create mode 100644 wx28X/include/wx/generic/textdlgg.h create mode 100644 wx28X/include/wx/generic/timer.h create mode 100644 wx28X/include/wx/generic/treectlg.h create mode 100644 wx28X/include/wx/generic/wizard.h create mode 100644 wx28X/include/wx/geometry.h create mode 100644 wx28X/include/wx/gifdecod.h create mode 100644 wx28X/include/wx/glcanvas.h create mode 100644 wx28X/include/wx/graphics.h create mode 100644 wx28X/include/wx/grid.h create mode 100644 wx28X/include/wx/gsocket.h create mode 100644 wx28X/include/wx/hash.h create mode 100644 wx28X/include/wx/hashmap.h create mode 100644 wx28X/include/wx/hashset.h create mode 100644 wx28X/include/wx/help.h create mode 100644 wx28X/include/wx/helpbase.h create mode 100644 wx28X/include/wx/helphtml.h create mode 100644 wx28X/include/wx/helpwin.h create mode 100644 wx28X/include/wx/html/forcelnk.h create mode 100644 wx28X/include/wx/html/helpctrl.h create mode 100644 wx28X/include/wx/html/helpdata.h create mode 100644 wx28X/include/wx/html/helpdlg.h create mode 100644 wx28X/include/wx/html/helpfrm.h create mode 100644 wx28X/include/wx/html/helpwnd.h create mode 100644 wx28X/include/wx/html/htmlcell.h create mode 100644 wx28X/include/wx/html/htmldefs.h create mode 100644 wx28X/include/wx/html/htmlfilt.h create mode 100644 wx28X/include/wx/html/htmlpars.h create mode 100644 wx28X/include/wx/html/htmlproc.h create mode 100644 wx28X/include/wx/html/htmltag.h create mode 100644 wx28X/include/wx/html/htmlwin.h create mode 100644 wx28X/include/wx/html/htmprint.h create mode 100644 wx28X/include/wx/html/m_templ.h create mode 100644 wx28X/include/wx/html/webkit.h create mode 100644 wx28X/include/wx/html/winpars.h create mode 100644 wx28X/include/wx/htmllbox.h create mode 100644 wx28X/include/wx/hyperlink.h create mode 100644 wx28X/include/wx/icon.h create mode 100644 wx28X/include/wx/iconbndl.h create mode 100644 wx28X/include/wx/iconloc.h create mode 100644 wx28X/include/wx/imagbmp.h create mode 100644 wx28X/include/wx/image.h create mode 100644 wx28X/include/wx/imaggif.h create mode 100644 wx28X/include/wx/imagiff.h create mode 100644 wx28X/include/wx/imagjpeg.h create mode 100644 wx28X/include/wx/imaglist.h create mode 100644 wx28X/include/wx/imagpcx.h create mode 100644 wx28X/include/wx/imagpng.h create mode 100644 wx28X/include/wx/imagpnm.h create mode 100644 wx28X/include/wx/imagtga.h create mode 100644 wx28X/include/wx/imagtiff.h create mode 100644 wx28X/include/wx/imagxpm.h create mode 100644 wx28X/include/wx/init.h create mode 100644 wx28X/include/wx/intl.h create mode 100644 wx28X/include/wx/iosfwrap.h create mode 100644 wx28X/include/wx/ioswrap.h create mode 100644 wx28X/include/wx/ipc.h create mode 100644 wx28X/include/wx/ipcbase.h create mode 100644 wx28X/include/wx/isql.h create mode 100644 wx28X/include/wx/isqlext.h create mode 100644 wx28X/include/wx/joystick.h create mode 100644 wx28X/include/wx/layout.h create mode 100644 wx28X/include/wx/laywin.h create mode 100644 wx28X/include/wx/link.h create mode 100644 wx28X/include/wx/list.h create mode 100644 wx28X/include/wx/listbase.h create mode 100644 wx28X/include/wx/listbook.h create mode 100644 wx28X/include/wx/listbox.h create mode 100644 wx28X/include/wx/listctrl.h create mode 100644 wx28X/include/wx/listimpl.cpp create mode 100644 wx28X/include/wx/log.h create mode 100644 wx28X/include/wx/longlong.h create mode 100644 wx28X/include/wx/math.h create mode 100644 wx28X/include/wx/matrix.h create mode 100644 wx28X/include/wx/mdi.h create mode 100644 wx28X/include/wx/mediactrl.h create mode 100644 wx28X/include/wx/memconf.h create mode 100644 wx28X/include/wx/memory.h create mode 100644 wx28X/include/wx/memtext.h create mode 100644 wx28X/include/wx/menu.h create mode 100644 wx28X/include/wx/menuitem.h create mode 100644 wx28X/include/wx/metafile.h create mode 100644 wx28X/include/wx/mimetype.h create mode 100644 wx28X/include/wx/minifram.h create mode 100644 wx28X/include/wx/module.h create mode 100644 wx28X/include/wx/msgdlg.h create mode 100644 wx28X/include/wx/msgout.h create mode 100644 wx28X/include/wx/mstream.h create mode 100644 wx28X/include/wx/msw/accel.h create mode 100644 wx28X/include/wx/msw/amd64.manifest create mode 100644 wx28X/include/wx/msw/app.h create mode 100644 wx28X/include/wx/msw/apptbase.h create mode 100644 wx28X/include/wx/msw/apptrait.h create mode 100644 wx28X/include/wx/msw/bitmap.h create mode 100644 wx28X/include/wx/msw/blank.cur create mode 100644 wx28X/include/wx/msw/bmpbuttn.h create mode 100644 wx28X/include/wx/msw/brush.h create mode 100644 wx28X/include/wx/msw/bullseye.cur create mode 100644 wx28X/include/wx/msw/button.h create mode 100644 wx28X/include/wx/msw/caret.h create mode 100644 wx28X/include/wx/msw/cdrom.ico create mode 100644 wx28X/include/wx/msw/checkbox.h create mode 100644 wx28X/include/wx/msw/checklst.h create mode 100644 wx28X/include/wx/msw/child.ico create mode 100644 wx28X/include/wx/msw/chkconf.h create mode 100644 wx28X/include/wx/msw/choice.h create mode 100644 wx28X/include/wx/msw/clipbrd.h create mode 100644 wx28X/include/wx/msw/colordlg.h create mode 100644 wx28X/include/wx/msw/colour.h create mode 100644 wx28X/include/wx/msw/colours.bmp create mode 100644 wx28X/include/wx/msw/combo.h create mode 100644 wx28X/include/wx/msw/combobox.h create mode 100644 wx28X/include/wx/msw/computer.ico create mode 100644 wx28X/include/wx/msw/control.h create mode 100644 wx28X/include/wx/msw/crashrpt.h create mode 100644 wx28X/include/wx/msw/cross.cur create mode 100644 wx28X/include/wx/msw/csquery.bmp create mode 100644 wx28X/include/wx/msw/cursor.h create mode 100644 wx28X/include/wx/msw/datectrl.h create mode 100644 wx28X/include/wx/msw/dc.h create mode 100644 wx28X/include/wx/msw/dcclient.h create mode 100644 wx28X/include/wx/msw/dcmemory.h create mode 100644 wx28X/include/wx/msw/dcprint.h create mode 100644 wx28X/include/wx/msw/dcscreen.h create mode 100644 wx28X/include/wx/msw/dde.h create mode 100644 wx28X/include/wx/msw/debughlp.h create mode 100644 wx28X/include/wx/msw/dialog.h create mode 100644 wx28X/include/wx/msw/dib.h create mode 100644 wx28X/include/wx/msw/dirdlg.h create mode 100644 wx28X/include/wx/msw/dragimag.h create mode 100644 wx28X/include/wx/msw/drive.ico create mode 100644 wx28X/include/wx/msw/enhmeta.h create mode 100644 wx28X/include/wx/msw/evtloop.h create mode 100644 wx28X/include/wx/msw/fdrepdlg.h create mode 100644 wx28X/include/wx/msw/file1.ico create mode 100644 wx28X/include/wx/msw/filedlg.h create mode 100644 wx28X/include/wx/msw/floppy.ico create mode 100644 wx28X/include/wx/msw/folder1.ico create mode 100644 wx28X/include/wx/msw/folder2.ico create mode 100644 wx28X/include/wx/msw/font.h create mode 100644 wx28X/include/wx/msw/fontdlg.h create mode 100644 wx28X/include/wx/msw/fontenum.h create mode 100644 wx28X/include/wx/msw/frame.h create mode 100644 wx28X/include/wx/msw/gauge95.h create mode 100644 wx28X/include/wx/msw/gccpriv.h create mode 100644 wx28X/include/wx/msw/gdiimage.h create mode 100644 wx28X/include/wx/msw/genrcdefs.h create mode 100644 wx28X/include/wx/msw/glcanvas.h create mode 100644 wx28X/include/wx/msw/gsockmsw.h create mode 100644 wx28X/include/wx/msw/hand.cur create mode 100644 wx28X/include/wx/msw/helpbest.h create mode 100644 wx28X/include/wx/msw/helpchm.h create mode 100644 wx28X/include/wx/msw/helpwin.h create mode 100644 wx28X/include/wx/msw/htmlhelp.h create mode 100644 wx28X/include/wx/msw/ia64.manifest create mode 100644 wx28X/include/wx/msw/icon.h create mode 100644 wx28X/include/wx/msw/imaglist.h create mode 100644 wx28X/include/wx/msw/iniconf.h create mode 100644 wx28X/include/wx/msw/joystick.h create mode 100644 wx28X/include/wx/msw/libraries.h create mode 100644 wx28X/include/wx/msw/listbox.h create mode 100644 wx28X/include/wx/msw/listctrl.h create mode 100644 wx28X/include/wx/msw/magnif1.cur create mode 100644 wx28X/include/wx/msw/mdi.h create mode 100644 wx28X/include/wx/msw/mdi.ico create mode 100644 wx28X/include/wx/msw/menu.h create mode 100644 wx28X/include/wx/msw/menuitem.h create mode 100644 wx28X/include/wx/msw/metafile.h create mode 100644 wx28X/include/wx/msw/microwin.h create mode 100644 wx28X/include/wx/msw/mimetype.h create mode 100644 wx28X/include/wx/msw/minifram.h create mode 100644 wx28X/include/wx/msw/missing.h create mode 100644 wx28X/include/wx/msw/msgdlg.h create mode 100644 wx28X/include/wx/msw/mslu.h create mode 100644 wx28X/include/wx/msw/msvcrt.h create mode 100644 wx28X/include/wx/msw/notebook.h create mode 100644 wx28X/include/wx/msw/ole/access.h create mode 100644 wx28X/include/wx/msw/ole/activex.h create mode 100644 wx28X/include/wx/msw/ole/automtn.h create mode 100644 wx28X/include/wx/msw/ole/dataform.h create mode 100644 wx28X/include/wx/msw/ole/dataobj.h create mode 100644 wx28X/include/wx/msw/ole/dataobj2.h create mode 100644 wx28X/include/wx/msw/ole/dropsrc.h create mode 100644 wx28X/include/wx/msw/ole/droptgt.h create mode 100644 wx28X/include/wx/msw/ole/oleutils.h create mode 100644 wx28X/include/wx/msw/ole/uuid.h create mode 100644 wx28X/include/wx/msw/palette.h create mode 100644 wx28X/include/wx/msw/pbrush.cur create mode 100644 wx28X/include/wx/msw/pen.h create mode 100644 wx28X/include/wx/msw/pencil.cur create mode 100644 wx28X/include/wx/msw/pntleft.cur create mode 100644 wx28X/include/wx/msw/pntright.cur create mode 100644 wx28X/include/wx/msw/popupwin.h create mode 100644 wx28X/include/wx/msw/printdlg.h create mode 100644 wx28X/include/wx/msw/printwin.h create mode 100644 wx28X/include/wx/msw/private.h create mode 100644 wx28X/include/wx/msw/question.ico create mode 100644 wx28X/include/wx/msw/radiobox.h create mode 100644 wx28X/include/wx/msw/radiobut.h create mode 100644 wx28X/include/wx/msw/rcdefs.h create mode 100644 wx28X/include/wx/msw/regconf.h create mode 100644 wx28X/include/wx/msw/region.h create mode 100644 wx28X/include/wx/msw/registry.h create mode 100644 wx28X/include/wx/msw/removble.ico create mode 100644 wx28X/include/wx/msw/rightarr.cur create mode 100644 wx28X/include/wx/msw/roller.cur create mode 100644 wx28X/include/wx/msw/scrolbar.h create mode 100644 wx28X/include/wx/msw/seh.h create mode 100644 wx28X/include/wx/msw/setup.h create mode 100644 wx28X/include/wx/msw/setup0.h create mode 100644 wx28X/include/wx/msw/setup_microwin.h create mode 100644 wx28X/include/wx/msw/slider95.h create mode 100644 wx28X/include/wx/msw/sound.h create mode 100644 wx28X/include/wx/msw/spinbutt.h create mode 100644 wx28X/include/wx/msw/spinctrl.h create mode 100644 wx28X/include/wx/msw/stackwalk.h create mode 100644 wx28X/include/wx/msw/statbmp.h create mode 100644 wx28X/include/wx/msw/statbox.h create mode 100644 wx28X/include/wx/msw/statbr95.h create mode 100644 wx28X/include/wx/msw/statline.h create mode 100644 wx28X/include/wx/msw/stattext.h create mode 100644 wx28X/include/wx/msw/std.ico create mode 100644 wx28X/include/wx/msw/stdpaths.h create mode 100644 wx28X/include/wx/msw/subwin.h create mode 100644 wx28X/include/wx/msw/tabctrl.h create mode 100644 wx28X/include/wx/msw/taskbar.h create mode 100644 wx28X/include/wx/msw/tbar95.h create mode 100644 wx28X/include/wx/msw/textctrl.h create mode 100644 wx28X/include/wx/msw/tglbtn.h create mode 100644 wx28X/include/wx/msw/timer.h create mode 100644 wx28X/include/wx/msw/tooltip.h create mode 100644 wx28X/include/wx/msw/toplevel.h create mode 100644 wx28X/include/wx/msw/treectrl.h create mode 100644 wx28X/include/wx/msw/uxtheme.h create mode 100644 wx28X/include/wx/msw/uxthemep.h create mode 100644 wx28X/include/wx/msw/wince/checklst.h create mode 100644 wx28X/include/wx/msw/wince/chkconf.h create mode 100644 wx28X/include/wx/msw/wince/choicece.h create mode 100644 wx28X/include/wx/msw/wince/helpwce.h create mode 100644 wx28X/include/wx/msw/wince/libraries.h create mode 100644 wx28X/include/wx/msw/wince/missing.h create mode 100644 wx28X/include/wx/msw/wince/net.h create mode 100644 wx28X/include/wx/msw/wince/resources.h create mode 100644 wx28X/include/wx/msw/wince/setup.h create mode 100644 wx28X/include/wx/msw/wince/smartphone.rc create mode 100644 wx28X/include/wx/msw/wince/tbarwce.h create mode 100644 wx28X/include/wx/msw/wince/textctrlce.h create mode 100644 wx28X/include/wx/msw/wince/time.h create mode 100644 wx28X/include/wx/msw/wince/wince.rc create mode 100644 wx28X/include/wx/msw/window.h create mode 100644 wx28X/include/wx/msw/winundef.h create mode 100644 wx28X/include/wx/msw/wrapcctl.h create mode 100644 wx28X/include/wx/msw/wrapcdlg.h create mode 100644 wx28X/include/wx/msw/wrapshl.h create mode 100644 wx28X/include/wx/msw/wrapwin.h create mode 100644 wx28X/include/wx/msw/wx.manifest create mode 100644 wx28X/include/wx/msw/wx.rc create mode 100644 wx28X/include/wx/notebook.h create mode 100644 wx28X/include/wx/numdlg.h create mode 100644 wx28X/include/wx/object.h create mode 100644 wx28X/include/wx/odcombo.h create mode 100644 wx28X/include/wx/overlay.h create mode 100644 wx28X/include/wx/ownerdrw.h create mode 100644 wx28X/include/wx/palette.h create mode 100644 wx28X/include/wx/panel.h create mode 100644 wx28X/include/wx/paper.h create mode 100644 wx28X/include/wx/pen.h create mode 100644 wx28X/include/wx/pickerbase.h create mode 100644 wx28X/include/wx/platform.h create mode 100644 wx28X/include/wx/platinfo.h create mode 100644 wx28X/include/wx/popupwin.h create mode 100644 wx28X/include/wx/power.h create mode 100644 wx28X/include/wx/print.h create mode 100644 wx28X/include/wx/printdlg.h create mode 100644 wx28X/include/wx/private/browserhack28.h create mode 100644 wx28X/include/wx/private/fileback.h create mode 100644 wx28X/include/wx/private/filename.h create mode 100644 wx28X/include/wx/private/fontmgr.h create mode 100644 wx28X/include/wx/private/overlay.h create mode 100644 wx28X/include/wx/private/socketevtdispatch.h create mode 100644 wx28X/include/wx/prntbase.h create mode 100644 wx28X/include/wx/process.h create mode 100644 wx28X/include/wx/progdlg.h create mode 100644 wx28X/include/wx/propdlg.h create mode 100644 wx28X/include/wx/protocol/file.h create mode 100644 wx28X/include/wx/protocol/ftp.h create mode 100644 wx28X/include/wx/protocol/http.h create mode 100644 wx28X/include/wx/protocol/protocol.h create mode 100644 wx28X/include/wx/ptr_scpd.h create mode 100644 wx28X/include/wx/quantize.h create mode 100644 wx28X/include/wx/radiobox.h create mode 100644 wx28X/include/wx/radiobut.h create mode 100644 wx28X/include/wx/rawbmp.h create mode 100644 wx28X/include/wx/recguard.h create mode 100644 wx28X/include/wx/regex.h create mode 100644 wx28X/include/wx/region.h create mode 100644 wx28X/include/wx/renderer.h create mode 100644 wx28X/include/wx/richtext/richtextbuffer.h create mode 100644 wx28X/include/wx/richtext/richtextbulletspage.h create mode 100644 wx28X/include/wx/richtext/richtextctrl.h create mode 100644 wx28X/include/wx/richtext/richtextfontpage.h create mode 100644 wx28X/include/wx/richtext/richtextformatdlg.h create mode 100644 wx28X/include/wx/richtext/richtexthtml.h create mode 100644 wx28X/include/wx/richtext/richtextindentspage.h create mode 100644 wx28X/include/wx/richtext/richtextliststylepage.h create mode 100644 wx28X/include/wx/richtext/richtextprint.h create mode 100644 wx28X/include/wx/richtext/richtextstyledlg.h create mode 100644 wx28X/include/wx/richtext/richtextstylepage.h create mode 100644 wx28X/include/wx/richtext/richtextstyles.h create mode 100644 wx28X/include/wx/richtext/richtextsymboldlg.h create mode 100644 wx28X/include/wx/richtext/richtexttabspage.h create mode 100644 wx28X/include/wx/richtext/richtextxml.h create mode 100644 wx28X/include/wx/sashwin.h create mode 100644 wx28X/include/wx/sckaddr.h create mode 100644 wx28X/include/wx/sckipc.h create mode 100644 wx28X/include/wx/sckstrm.h create mode 100644 wx28X/include/wx/scopeguard.h create mode 100644 wx28X/include/wx/scrolbar.h create mode 100644 wx28X/include/wx/scrolwin.h create mode 100644 wx28X/include/wx/selstore.h create mode 100644 wx28X/include/wx/settings.h create mode 100644 wx28X/include/wx/setup_inc.h create mode 100644 wx28X/include/wx/setup_redirect.h create mode 100644 wx28X/include/wx/sizer.h create mode 100644 wx28X/include/wx/slider.h create mode 100644 wx28X/include/wx/snglinst.h create mode 100644 wx28X/include/wx/socket.h create mode 100644 wx28X/include/wx/sound.h create mode 100644 wx28X/include/wx/spinbutt.h create mode 100644 wx28X/include/wx/spinctrl.h create mode 100644 wx28X/include/wx/splash.h create mode 100644 wx28X/include/wx/splitter.h create mode 100644 wx28X/include/wx/srchctrl.h create mode 100644 wx28X/include/wx/sstream.h create mode 100644 wx28X/include/wx/stack.h create mode 100644 wx28X/include/wx/stackwalk.h create mode 100644 wx28X/include/wx/statbmp.h create mode 100644 wx28X/include/wx/statbox.h create mode 100644 wx28X/include/wx/statline.h create mode 100644 wx28X/include/wx/stattext.h create mode 100644 wx28X/include/wx/statusbr.h create mode 100644 wx28X/include/wx/stdpaths.h create mode 100644 wx28X/include/wx/stockitem.h create mode 100644 wx28X/include/wx/stopwatch.h create mode 100644 wx28X/include/wx/strconv.h create mode 100644 wx28X/include/wx/stream.h create mode 100644 wx28X/include/wx/string.h create mode 100644 wx28X/include/wx/sysopt.h create mode 100644 wx28X/include/wx/tab.h create mode 100644 wx28X/include/wx/tabctrl.h create mode 100644 wx28X/include/wx/tarstrm.h create mode 100644 wx28X/include/wx/taskbar.h create mode 100644 wx28X/include/wx/tbarbase.h create mode 100644 wx28X/include/wx/textbuf.h create mode 100644 wx28X/include/wx/textctrl.h create mode 100644 wx28X/include/wx/textdlg.h create mode 100644 wx28X/include/wx/textfile.h create mode 100644 wx28X/include/wx/tglbtn.h create mode 100644 wx28X/include/wx/thread.h create mode 100644 wx28X/include/wx/thrimpl.cpp create mode 100644 wx28X/include/wx/timer.h create mode 100644 wx28X/include/wx/tipdlg.h create mode 100644 wx28X/include/wx/tipwin.h create mode 100644 wx28X/include/wx/tokenzr.h create mode 100644 wx28X/include/wx/toolbar.h create mode 100644 wx28X/include/wx/toolbook.h create mode 100644 wx28X/include/wx/tooltip.h create mode 100644 wx28X/include/wx/toplevel.h create mode 100644 wx28X/include/wx/treebase.h create mode 100644 wx28X/include/wx/treebook.h create mode 100644 wx28X/include/wx/treectrl.h create mode 100644 wx28X/include/wx/txtstrm.h create mode 100644 wx28X/include/wx/types.h create mode 100644 wx28X/include/wx/univ/app.h create mode 100644 wx28X/include/wx/univ/bmpbuttn.h create mode 100644 wx28X/include/wx/univ/button.h create mode 100644 wx28X/include/wx/univ/checkbox.h create mode 100644 wx28X/include/wx/univ/checklst.h create mode 100644 wx28X/include/wx/univ/chkconf.h create mode 100644 wx28X/include/wx/univ/choice.h create mode 100644 wx28X/include/wx/univ/colschem.h create mode 100644 wx28X/include/wx/univ/combobox.h create mode 100644 wx28X/include/wx/univ/control.h create mode 100644 wx28X/include/wx/univ/dialog.h create mode 100644 wx28X/include/wx/univ/frame.h create mode 100644 wx28X/include/wx/univ/gauge.h create mode 100644 wx28X/include/wx/univ/inpcons.h create mode 100644 wx28X/include/wx/univ/inphand.h create mode 100644 wx28X/include/wx/univ/listbox.h create mode 100644 wx28X/include/wx/univ/menu.h create mode 100644 wx28X/include/wx/univ/menuitem.h create mode 100644 wx28X/include/wx/univ/notebook.h create mode 100644 wx28X/include/wx/univ/radiobox.h create mode 100644 wx28X/include/wx/univ/radiobut.h create mode 100644 wx28X/include/wx/univ/renderer.h create mode 100644 wx28X/include/wx/univ/scrarrow.h create mode 100644 wx28X/include/wx/univ/scrolbar.h create mode 100644 wx28X/include/wx/univ/scrthumb.h create mode 100644 wx28X/include/wx/univ/scrtimer.h create mode 100644 wx28X/include/wx/univ/setup.h create mode 100644 wx28X/include/wx/univ/setup0.h create mode 100644 wx28X/include/wx/univ/slider.h create mode 100644 wx28X/include/wx/univ/spinbutt.h create mode 100644 wx28X/include/wx/univ/statbmp.h create mode 100644 wx28X/include/wx/univ/statbox.h create mode 100644 wx28X/include/wx/univ/statline.h create mode 100644 wx28X/include/wx/univ/stattext.h create mode 100644 wx28X/include/wx/univ/statusbr.h create mode 100644 wx28X/include/wx/univ/stdrend.h create mode 100644 wx28X/include/wx/univ/textctrl.h create mode 100644 wx28X/include/wx/univ/tglbtn.h create mode 100644 wx28X/include/wx/univ/theme.h create mode 100644 wx28X/include/wx/univ/toolbar.h create mode 100644 wx28X/include/wx/univ/toplevel.h create mode 100644 wx28X/include/wx/univ/window.h create mode 100644 wx28X/include/wx/unix/apptbase.h create mode 100644 wx28X/include/wx/unix/apptrait.h create mode 100644 wx28X/include/wx/unix/execute.h create mode 100644 wx28X/include/wx/unix/fontutil.h create mode 100644 wx28X/include/wx/unix/gsockunx.h create mode 100644 wx28X/include/wx/unix/joystick.h create mode 100644 wx28X/include/wx/unix/mimetype.h create mode 100644 wx28X/include/wx/unix/pipe.h create mode 100644 wx28X/include/wx/unix/private.h create mode 100644 wx28X/include/wx/unix/sound.h create mode 100644 wx28X/include/wx/unix/stackwalk.h create mode 100644 wx28X/include/wx/unix/stdpaths.h create mode 100644 wx28X/include/wx/unix/taskbarx11.h create mode 100644 wx28X/include/wx/unix/utilsx11.h create mode 100644 wx28X/include/wx/uri.h create mode 100644 wx28X/include/wx/url.h create mode 100644 wx28X/include/wx/utils.h create mode 100644 wx28X/include/wx/valgen.h create mode 100644 wx28X/include/wx/validate.h create mode 100644 wx28X/include/wx/valtext.h create mode 100644 wx28X/include/wx/variant.h create mode 100644 wx28X/include/wx/vector.h create mode 100644 wx28X/include/wx/version.h create mode 100644 wx28X/include/wx/vidmode.h create mode 100644 wx28X/include/wx/vlbox.h create mode 100644 wx28X/include/wx/vms_x_fix.h create mode 100644 wx28X/include/wx/volume.h create mode 100644 wx28X/include/wx/vscroll.h create mode 100644 wx28X/include/wx/wave.h create mode 100644 wx28X/include/wx/wfstream.h create mode 100644 wx28X/include/wx/window.h create mode 100644 wx28X/include/wx/wizard.h create mode 100644 wx28X/include/wx/wupdlock.h create mode 100644 wx28X/include/wx/wx.h create mode 100644 wx28X/include/wx/wx_cw.h create mode 100644 wx28X/include/wx/wx_cw_cm.h create mode 100644 wx28X/include/wx/wx_cw_d.h create mode 100644 wx28X/include/wx/wx_cwc.h create mode 100644 wx28X/include/wx/wx_cwc_d.h create mode 100644 wx28X/include/wx/wx_cwcocoa.h create mode 100644 wx28X/include/wx/wx_cwcocoa_cm.h create mode 100644 wx28X/include/wx/wx_cwcocoa_d.h create mode 100644 wx28X/include/wx/wx_cwu_d.h create mode 100644 wx28X/include/wx/wxchar.h create mode 100644 wx28X/include/wx/wxhtml.h create mode 100644 wx28X/include/wx/wxprec.h create mode 100644 wx28X/include/wx/wxshlb_cw.h create mode 100644 wx28X/include/wx/wxshlb_cw_d.h create mode 100644 wx28X/include/wx/wxshlb_cwc.h create mode 100644 wx28X/include/wx/wxshlb_cwc_d.h create mode 100644 wx28X/include/wx/wxshlba_cw.h create mode 100644 wx28X/include/wx/wxshlba_cw_d.h create mode 100644 wx28X/include/wx/wxshlba_cwc.h create mode 100644 wx28X/include/wx/wxshlba_cwc_d.h create mode 100644 wx28X/include/wx/xml/xml.h create mode 100644 wx28X/include/wx/xpmdecod.h create mode 100644 wx28X/include/wx/xpmhand.h create mode 100644 wx28X/include/wx/xrc/xh_all.h create mode 100644 wx28X/include/wx/xrc/xh_animatctrl.h create mode 100644 wx28X/include/wx/xrc/xh_bmp.h create mode 100644 wx28X/include/wx/xrc/xh_bmpbt.h create mode 100644 wx28X/include/wx/xrc/xh_bmpcbox.h create mode 100644 wx28X/include/wx/xrc/xh_bttn.h create mode 100644 wx28X/include/wx/xrc/xh_cald.h create mode 100644 wx28X/include/wx/xrc/xh_chckb.h create mode 100644 wx28X/include/wx/xrc/xh_chckl.h create mode 100644 wx28X/include/wx/xrc/xh_choic.h create mode 100644 wx28X/include/wx/xrc/xh_choicbk.h create mode 100644 wx28X/include/wx/xrc/xh_clrpicker.h create mode 100644 wx28X/include/wx/xrc/xh_collpane.h create mode 100644 wx28X/include/wx/xrc/xh_combo.h create mode 100644 wx28X/include/wx/xrc/xh_datectrl.h create mode 100644 wx28X/include/wx/xrc/xh_dirpicker.h create mode 100644 wx28X/include/wx/xrc/xh_dlg.h create mode 100644 wx28X/include/wx/xrc/xh_filepicker.h create mode 100644 wx28X/include/wx/xrc/xh_fontpicker.h create mode 100644 wx28X/include/wx/xrc/xh_frame.h create mode 100644 wx28X/include/wx/xrc/xh_gauge.h create mode 100644 wx28X/include/wx/xrc/xh_gdctl.h create mode 100644 wx28X/include/wx/xrc/xh_grid.h create mode 100644 wx28X/include/wx/xrc/xh_html.h create mode 100644 wx28X/include/wx/xrc/xh_htmllbox.h create mode 100644 wx28X/include/wx/xrc/xh_hyperlink.h create mode 100644 wx28X/include/wx/xrc/xh_listb.h create mode 100644 wx28X/include/wx/xrc/xh_listbk.h create mode 100644 wx28X/include/wx/xrc/xh_listc.h create mode 100644 wx28X/include/wx/xrc/xh_mdi.h create mode 100644 wx28X/include/wx/xrc/xh_menu.h create mode 100644 wx28X/include/wx/xrc/xh_notbk.h create mode 100644 wx28X/include/wx/xrc/xh_odcombo.h create mode 100644 wx28X/include/wx/xrc/xh_panel.h create mode 100644 wx28X/include/wx/xrc/xh_propdlg.h create mode 100644 wx28X/include/wx/xrc/xh_radbt.h create mode 100644 wx28X/include/wx/xrc/xh_radbx.h create mode 100644 wx28X/include/wx/xrc/xh_richtext.h create mode 100644 wx28X/include/wx/xrc/xh_scrol.h create mode 100644 wx28X/include/wx/xrc/xh_scwin.h create mode 100644 wx28X/include/wx/xrc/xh_sizer.h create mode 100644 wx28X/include/wx/xrc/xh_slidr.h create mode 100644 wx28X/include/wx/xrc/xh_spin.h create mode 100644 wx28X/include/wx/xrc/xh_split.h create mode 100644 wx28X/include/wx/xrc/xh_statbar.h create mode 100644 wx28X/include/wx/xrc/xh_stbmp.h create mode 100644 wx28X/include/wx/xrc/xh_stbox.h create mode 100644 wx28X/include/wx/xrc/xh_stlin.h create mode 100644 wx28X/include/wx/xrc/xh_sttxt.h create mode 100644 wx28X/include/wx/xrc/xh_text.h create mode 100644 wx28X/include/wx/xrc/xh_tglbtn.h create mode 100644 wx28X/include/wx/xrc/xh_toolb.h create mode 100644 wx28X/include/wx/xrc/xh_tree.h create mode 100644 wx28X/include/wx/xrc/xh_treebk.h create mode 100644 wx28X/include/wx/xrc/xh_unkwn.h create mode 100644 wx28X/include/wx/xrc/xh_wizrd.h create mode 100644 wx28X/include/wx/xrc/xmlres.h create mode 100644 wx28X/include/wx/xti.h create mode 100644 wx28X/include/wx/xtistrm.h create mode 100644 wx28X/include/wx/xtixml.h create mode 100644 wx28X/include/wx/zipstrm.h create mode 100644 wx28X/include/wx/zstream.h create mode 100644 wx28X/include/wx_pb.h create mode 100644 wx28X/install-sh create mode 100644 wx28X/lib/VMS_GTK2.OPT create mode 100644 wx28X/lib/VMS_X11_UNIV.OPT create mode 100644 wx28X/lib/_sc/Readme.txt create mode 100644 wx28X/lib/_sc/shell32_sc.def create mode 100644 wx28X/lib/_sc/winmm32_sc.def create mode 100644 wx28X/lib/_sc/wsock32_sc.def create mode 100644 wx28X/lib/abicheck.sh create mode 100644 wx28X/lib/dummy create mode 100644 wx28X/lib/expected_abi create mode 100644 wx28X/lib/vc_dll/msw/wx/msw/rcdefs.h create mode 100644 wx28X/lib/vc_dll/msw/wx/setup.h create mode 100644 wx28X/lib/vc_dll/mswd/wx/msw/rcdefs.h create mode 100644 wx28X/lib/vc_dll/mswd/wx/setup.h create mode 100644 wx28X/lib/vc_dll/wxbase28.exp create mode 100644 wx28X/lib/vc_dll/wxbase28.lib create mode 100644 wx28X/lib/vc_dll/wxbase28_net.exp create mode 100644 wx28X/lib/vc_dll/wxbase28_net.lib create mode 100644 wx28X/lib/vc_dll/wxbase28_net_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxbase28_net_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxbase28_odbc.exp create mode 100644 wx28X/lib/vc_dll/wxbase28_odbc.lib create mode 100644 wx28X/lib/vc_dll/wxbase28_odbc_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxbase28_odbc_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxbase28_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxbase28_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxbase28_xml.exp create mode 100644 wx28X/lib/vc_dll/wxbase28_xml.lib create mode 100644 wx28X/lib/vc_dll/wxbase28_xml_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxbase28_xml_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxbase28d.exp create mode 100644 wx28X/lib/vc_dll/wxbase28d.lib create mode 100644 wx28X/lib/vc_dll/wxbase28d_net.exp create mode 100644 wx28X/lib/vc_dll/wxbase28d_net.lib create mode 100644 wx28X/lib/vc_dll/wxbase28d_net_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxbase28d_net_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxbase28d_net_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxbase28d_net_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxbase28d_odbc.exp create mode 100644 wx28X/lib/vc_dll/wxbase28d_odbc.lib create mode 100644 wx28X/lib/vc_dll/wxbase28d_odbc_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxbase28d_odbc_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxbase28d_odbc_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxbase28d_odbc_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxbase28d_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxbase28d_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxbase28d_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxbase28d_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxbase28d_xml.exp create mode 100644 wx28X/lib/vc_dll/wxbase28d_xml.lib create mode 100644 wx28X/lib/vc_dll/wxbase28d_xml_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxbase28d_xml_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxbase28d_xml_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxbase28d_xml_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxexpat.lib create mode 100644 wx28X/lib/vc_dll/wxexpat.pdb create mode 100644 wx28X/lib/vc_dll/wxexpatd.idb create mode 100644 wx28X/lib/vc_dll/wxexpatd.lib create mode 100644 wx28X/lib/vc_dll/wxexpatd.pdb create mode 100644 wx28X/lib/vc_dll/wxjpeg.lib create mode 100644 wx28X/lib/vc_dll/wxjpeg.pdb create mode 100644 wx28X/lib/vc_dll/wxjpegd.idb create mode 100644 wx28X/lib/vc_dll/wxjpegd.lib create mode 100644 wx28X/lib/vc_dll/wxjpegd.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28_adv.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28_adv.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28_adv_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28_adv_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28_aui.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28_aui.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28_aui_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28_aui_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28_core.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28_core.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28_core_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28_core_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28_dbgrid.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28_dbgrid.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28_dbgrid_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28_dbgrid_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28_gl_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28_gl_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28_html.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28_html.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28_html_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28_html_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28_media.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28_media.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28_media_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28_media_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28_qa.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28_qa.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28_qa_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28_qa_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28_richtext.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28_richtext.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28_richtext_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28_richtext_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28_xrc.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28_xrc.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28_xrc_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28_xrc_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_adv.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28d_adv.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28d_adv_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28d_adv_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_adv_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxmsw28d_adv_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_aui.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28d_aui.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28d_aui_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28d_aui_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_aui_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxmsw28d_aui_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_core.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28d_core.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28d_core_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28d_core_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_core_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxmsw28d_core_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_dbgrid.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28d_dbgrid.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28d_dbgrid_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28d_dbgrid_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_dbgrid_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxmsw28d_dbgrid_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_gl_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28d_gl_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_gl_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxmsw28d_gl_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_html.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28d_html.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28d_html_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28d_html_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_html_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxmsw28d_html_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_media.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28d_media.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28d_media_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28d_media_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_media_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxmsw28d_media_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_qa.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28d_qa.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28d_qa_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28d_qa_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_qa_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxmsw28d_qa_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_richtext.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28d_richtext.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28d_richtext_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28d_richtext_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_richtext_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxmsw28d_richtext_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_xrc.exp create mode 100644 wx28X/lib/vc_dll/wxmsw28d_xrc.lib create mode 100644 wx28X/lib/vc_dll/wxmsw28d_xrc_vc_custom.dll create mode 100644 wx28X/lib/vc_dll/wxmsw28d_xrc_vc_custom.idb create mode 100644 wx28X/lib/vc_dll/wxmsw28d_xrc_vc_custom.ilk create mode 100644 wx28X/lib/vc_dll/wxmsw28d_xrc_vc_custom.pdb create mode 100644 wx28X/lib/vc_dll/wxpng.lib create mode 100644 wx28X/lib/vc_dll/wxpng.pdb create mode 100644 wx28X/lib/vc_dll/wxpngd.idb create mode 100644 wx28X/lib/vc_dll/wxpngd.lib create mode 100644 wx28X/lib/vc_dll/wxpngd.pdb create mode 100644 wx28X/lib/vc_dll/wxregex.lib create mode 100644 wx28X/lib/vc_dll/wxregex.pdb create mode 100644 wx28X/lib/vc_dll/wxregexd.idb create mode 100644 wx28X/lib/vc_dll/wxregexd.lib create mode 100644 wx28X/lib/vc_dll/wxregexd.pdb create mode 100644 wx28X/lib/vc_dll/wxtiff.lib create mode 100644 wx28X/lib/vc_dll/wxtiff.pdb create mode 100644 wx28X/lib/vc_dll/wxtiffd.idb create mode 100644 wx28X/lib/vc_dll/wxtiffd.lib create mode 100644 wx28X/lib/vc_dll/wxtiffd.pdb create mode 100644 wx28X/lib/vc_dll/wxzlib.lib create mode 100644 wx28X/lib/vc_dll/wxzlib.pdb create mode 100644 wx28X/lib/vc_dll/wxzlibd.idb create mode 100644 wx28X/lib/vc_dll/wxzlibd.lib create mode 100644 wx28X/lib/vc_dll/wxzlibd.pdb create mode 100644 wx28X/lib/vc_lib/msw/wx/msw/rcdefs.h create mode 100644 wx28X/lib/vc_lib/msw/wx/setup.h create mode 100644 wx28X/lib/vc_lib/mswd/wx/msw/rcdefs.h create mode 100644 wx28X/lib/vc_lib/mswd/wx/setup.h create mode 100644 wx28X/lib/vc_lib/wxbase28.lib create mode 100644 wx28X/lib/vc_lib/wxbase28.pdb create mode 100644 wx28X/lib/vc_lib/wxbase28_net.lib create mode 100644 wx28X/lib/vc_lib/wxbase28_net.pdb create mode 100644 wx28X/lib/vc_lib/wxbase28_odbc.lib create mode 100644 wx28X/lib/vc_lib/wxbase28_odbc.pdb create mode 100644 wx28X/lib/vc_lib/wxbase28_xml.lib create mode 100644 wx28X/lib/vc_lib/wxbase28_xml.pdb create mode 100644 wx28X/lib/vc_lib/wxbase28d.idb create mode 100644 wx28X/lib/vc_lib/wxbase28d.lib create mode 100644 wx28X/lib/vc_lib/wxbase28d.pdb create mode 100644 wx28X/lib/vc_lib/wxbase28d_net.idb create mode 100644 wx28X/lib/vc_lib/wxbase28d_net.lib create mode 100644 wx28X/lib/vc_lib/wxbase28d_net.pdb create mode 100644 wx28X/lib/vc_lib/wxexpat.lib create mode 100644 wx28X/lib/vc_lib/wxexpat.pdb create mode 100644 wx28X/lib/vc_lib/wxexpatd.idb create mode 100644 wx28X/lib/vc_lib/wxexpatd.lib create mode 100644 wx28X/lib/vc_lib/wxexpatd.pdb create mode 100644 wx28X/lib/vc_lib/wxjpeg.lib create mode 100644 wx28X/lib/vc_lib/wxjpeg.pdb create mode 100644 wx28X/lib/vc_lib/wxjpegd.idb create mode 100644 wx28X/lib/vc_lib/wxjpegd.lib create mode 100644 wx28X/lib/vc_lib/wxjpegd.pdb create mode 100644 wx28X/lib/vc_lib/wxmsw28_adv.lib create mode 100644 wx28X/lib/vc_lib/wxmsw28_adv.pdb create mode 100644 wx28X/lib/vc_lib/wxmsw28_aui.lib create mode 100644 wx28X/lib/vc_lib/wxmsw28_aui.pdb create mode 100644 wx28X/lib/vc_lib/wxmsw28_core.lib create mode 100644 wx28X/lib/vc_lib/wxmsw28_core.pdb create mode 100644 wx28X/lib/vc_lib/wxmsw28_dbgrid.lib create mode 100644 wx28X/lib/vc_lib/wxmsw28_dbgrid.pdb create mode 100644 wx28X/lib/vc_lib/wxmsw28_gl.lib create mode 100644 wx28X/lib/vc_lib/wxmsw28_gl.pdb create mode 100644 wx28X/lib/vc_lib/wxmsw28_html.lib create mode 100644 wx28X/lib/vc_lib/wxmsw28_html.pdb create mode 100644 wx28X/lib/vc_lib/wxmsw28_media.lib create mode 100644 wx28X/lib/vc_lib/wxmsw28_media.pdb create mode 100644 wx28X/lib/vc_lib/wxmsw28_qa.lib create mode 100644 wx28X/lib/vc_lib/wxmsw28_qa.pdb create mode 100644 wx28X/lib/vc_lib/wxmsw28_richtext.lib create mode 100644 wx28X/lib/vc_lib/wxmsw28_richtext.pdb create mode 100644 wx28X/lib/vc_lib/wxmsw28_xrc.lib create mode 100644 wx28X/lib/vc_lib/wxmsw28_xrc.pdb create mode 100644 wx28X/lib/vc_lib/wxmsw28d_adv.idb create mode 100644 wx28X/lib/vc_lib/wxmsw28d_adv.lib create mode 100644 wx28X/lib/vc_lib/wxmsw28d_adv.pdb create mode 100644 wx28X/lib/vc_lib/wxmsw28d_core.idb create mode 100644 wx28X/lib/vc_lib/wxmsw28d_core.lib create mode 100644 wx28X/lib/vc_lib/wxmsw28d_core.pdb create mode 100644 wx28X/lib/vc_lib/wxmsw28d_html.idb create mode 100644 wx28X/lib/vc_lib/wxmsw28d_html.lib create mode 100644 wx28X/lib/vc_lib/wxmsw28d_html.pdb create mode 100644 wx28X/lib/vc_lib/wxpng.lib create mode 100644 wx28X/lib/vc_lib/wxpng.pdb create mode 100644 wx28X/lib/vc_lib/wxpngd.idb create mode 100644 wx28X/lib/vc_lib/wxpngd.lib create mode 100644 wx28X/lib/vc_lib/wxpngd.pdb create mode 100644 wx28X/lib/vc_lib/wxregex.lib create mode 100644 wx28X/lib/vc_lib/wxregex.pdb create mode 100644 wx28X/lib/vc_lib/wxregexd.idb create mode 100644 wx28X/lib/vc_lib/wxregexd.lib create mode 100644 wx28X/lib/vc_lib/wxregexd.pdb create mode 100644 wx28X/lib/vc_lib/wxtiff.lib create mode 100644 wx28X/lib/vc_lib/wxtiff.pdb create mode 100644 wx28X/lib/vc_lib/wxtiffd.idb create mode 100644 wx28X/lib/vc_lib/wxtiffd.lib create mode 100644 wx28X/lib/vc_lib/wxtiffd.pdb create mode 100644 wx28X/lib/vc_lib/wxzlib.lib create mode 100644 wx28X/lib/vc_lib/wxzlib.pdb create mode 100644 wx28X/lib/vc_lib/wxzlibd.idb create mode 100644 wx28X/lib/vc_lib/wxzlibd.lib create mode 100644 wx28X/lib/vc_lib/wxzlibd.pdb create mode 100644 wx28X/lib/vms.opt create mode 100644 wx28X/lib/vms_gtk.opt create mode 100644 wx28X/lib/watcom/makeit.bat create mode 100644 wx28X/lib/watcom/odbc.txt create mode 100644 wx28X/lib/watcom/odbc32.lib create mode 100644 wx28X/lib/watcom/readme.txt create mode 100644 wx28X/locale/Makefile create mode 100644 wx28X/locale/af.po create mode 100644 wx28X/locale/ca.po create mode 100644 wx28X/locale/cs.po create mode 100644 wx28X/locale/da.po create mode 100644 wx28X/locale/de.po create mode 100644 wx28X/locale/el.po create mode 100644 wx28X/locale/es.po create mode 100644 wx28X/locale/eu.po create mode 100644 wx28X/locale/fi.po create mode 100644 wx28X/locale/fr.po create mode 100644 wx28X/locale/gl_ES.po create mode 100644 wx28X/locale/hi.po create mode 100644 wx28X/locale/hu.po create mode 100644 wx28X/locale/id.po create mode 100644 wx28X/locale/it.po create mode 100644 wx28X/locale/ja.po create mode 100644 wx28X/locale/lv.po create mode 100644 wx28X/locale/ms.po create mode 100644 wx28X/locale/msw/it.po create mode 100644 wx28X/locale/nb.po create mode 100644 wx28X/locale/nl.po create mode 100644 wx28X/locale/pl.po create mode 100644 wx28X/locale/pt.po create mode 100644 wx28X/locale/pt_BR.po create mode 100644 wx28X/locale/ru.po create mode 100644 wx28X/locale/sk.po create mode 100644 wx28X/locale/sl.po create mode 100644 wx28X/locale/sq.po create mode 100644 wx28X/locale/sv.po create mode 100644 wx28X/locale/tr.po create mode 100644 wx28X/locale/uk.po create mode 100644 wx28X/locale/vi.po create mode 100644 wx28X/locale/wxstd.po create mode 100644 wx28X/locale/zh_CN.po create mode 100644 wx28X/locale/zh_TW.po create mode 100644 wx28X/mkinstalldirs create mode 100644 wx28X/regen create mode 100644 wx28X/samples/Info.plist create mode 100644 wx28X/samples/Makefile.in create mode 100644 wx28X/samples/access/Makefile.in create mode 100644 wx28X/samples/access/access.bkl create mode 100644 wx28X/samples/access/access.dsp create mode 100644 wx28X/samples/access/access.vcp create mode 100644 wx28X/samples/access/access.vcw create mode 100644 wx28X/samples/access/accesstest.cpp create mode 100644 wx28X/samples/access/accesstest.rc create mode 100644 wx28X/samples/access/accesstestM5.xml create mode 100644 wx28X/samples/access/accesstestW7.xml create mode 100644 wx28X/samples/access/descrip.mms create mode 100644 wx28X/samples/access/makefile.bcc create mode 100644 wx28X/samples/access/makefile.dmc create mode 100644 wx28X/samples/access/makefile.dms create mode 100644 wx28X/samples/access/makefile.gcc create mode 100644 wx28X/samples/access/makefile.unx create mode 100644 wx28X/samples/access/makefile.vc create mode 100644 wx28X/samples/access/makefile.wat create mode 100644 wx28X/samples/access/mondrian.ico create mode 100644 wx28X/samples/access/mondrian.xpm create mode 100644 wx28X/samples/animate/Makefile.in create mode 100644 wx28X/samples/animate/anitest.bkl create mode 100644 wx28X/samples/animate/anitest.cpp create mode 100644 wx28X/samples/animate/anitest.dsp create mode 100644 wx28X/samples/animate/anitest.h create mode 100644 wx28X/samples/animate/anitest.vcp create mode 100644 wx28X/samples/animate/anitest.vcw create mode 100644 wx28X/samples/animate/hourglass.ani create mode 100644 wx28X/samples/animate/makefile.bcc create mode 100644 wx28X/samples/animate/makefile.dmc create mode 100644 wx28X/samples/animate/makefile.dms create mode 100644 wx28X/samples/animate/makefile.gcc create mode 100644 wx28X/samples/animate/makefile.unx create mode 100644 wx28X/samples/animate/makefile.vc create mode 100644 wx28X/samples/animate/makefile.wat create mode 100644 wx28X/samples/animate/throbber.gif create mode 100644 wx28X/samples/artprov/Makefile.in create mode 100644 wx28X/samples/artprov/artbrows.cpp create mode 100644 wx28X/samples/artprov/artbrows.h create mode 100644 wx28X/samples/artprov/artprov.bkl create mode 100644 wx28X/samples/artprov/artprov.dsp create mode 100644 wx28X/samples/artprov/artprov.pro create mode 100644 wx28X/samples/artprov/artprov.vcp create mode 100644 wx28X/samples/artprov/artprov.vcw create mode 100644 wx28X/samples/artprov/artprovM5.xml create mode 100644 wx28X/samples/artprov/arttest.cpp create mode 100644 wx28X/samples/artprov/arttest.rc create mode 100644 wx28X/samples/artprov/error.xpm create mode 100644 wx28X/samples/artprov/info.xpm create mode 100644 wx28X/samples/artprov/makefile.bcc create mode 100644 wx28X/samples/artprov/makefile.dmc create mode 100644 wx28X/samples/artprov/makefile.dms create mode 100644 wx28X/samples/artprov/makefile.gcc create mode 100644 wx28X/samples/artprov/makefile.unx create mode 100644 wx28X/samples/artprov/makefile.vc create mode 100644 wx28X/samples/artprov/makefile.wat create mode 100644 wx28X/samples/artprov/mondrian.ico create mode 100644 wx28X/samples/artprov/mondrian.xpm create mode 100644 wx28X/samples/artprov/null.xpm create mode 100644 wx28X/samples/artprov/question.xpm create mode 100644 wx28X/samples/artprov/warning.xpm create mode 100644 wx28X/samples/aui/Makefile.in create mode 100644 wx28X/samples/aui/auidemo.bkl create mode 100644 wx28X/samples/aui/auidemo.cpp create mode 100644 wx28X/samples/aui/auidemo.dsp create mode 100644 wx28X/samples/aui/auidemo.vcp create mode 100644 wx28X/samples/aui/auidemo.vcw create mode 100644 wx28X/samples/aui/descrip.mms create mode 100644 wx28X/samples/aui/makefile.bcc create mode 100644 wx28X/samples/aui/makefile.dmc create mode 100644 wx28X/samples/aui/makefile.dms create mode 100644 wx28X/samples/aui/makefile.gcc create mode 100644 wx28X/samples/aui/makefile.unx create mode 100644 wx28X/samples/aui/makefile.vc create mode 100644 wx28X/samples/aui/makefile.wat create mode 100644 wx28X/samples/calendar/Makefile.in create mode 100644 wx28X/samples/calendar/calendar.bkl create mode 100644 wx28X/samples/calendar/calendar.cpp create mode 100644 wx28X/samples/calendar/calendar.dsp create mode 100644 wx28X/samples/calendar/calendar.pro create mode 100644 wx28X/samples/calendar/calendar.rc create mode 100644 wx28X/samples/calendar/calendar.vcp create mode 100644 wx28X/samples/calendar/calendar.vcw create mode 100644 wx28X/samples/calendar/calendarM5.xml create mode 100644 wx28X/samples/calendar/descrip.mms create mode 100644 wx28X/samples/calendar/makefile.bcc create mode 100644 wx28X/samples/calendar/makefile.dmc create mode 100644 wx28X/samples/calendar/makefile.dms create mode 100644 wx28X/samples/calendar/makefile.gcc create mode 100644 wx28X/samples/calendar/makefile.sl create mode 100644 wx28X/samples/calendar/makefile.unx create mode 100644 wx28X/samples/calendar/makefile.vc create mode 100644 wx28X/samples/calendar/makefile.wat create mode 100644 wx28X/samples/caret/Makefile.in create mode 100644 wx28X/samples/caret/caret.bkl create mode 100644 wx28X/samples/caret/caret.cpp create mode 100644 wx28X/samples/caret/caret.dsp create mode 100644 wx28X/samples/caret/caret.pro create mode 100644 wx28X/samples/caret/caret.rc create mode 100644 wx28X/samples/caret/caret.vcp create mode 100644 wx28X/samples/caret/caret.vcw create mode 100644 wx28X/samples/caret/caretM5.xml create mode 100644 wx28X/samples/caret/descrip.mms create mode 100644 wx28X/samples/caret/makefile.bcc create mode 100644 wx28X/samples/caret/makefile.dmc create mode 100644 wx28X/samples/caret/makefile.dms create mode 100644 wx28X/samples/caret/makefile.gcc create mode 100644 wx28X/samples/caret/makefile.unx create mode 100644 wx28X/samples/caret/makefile.vc create mode 100644 wx28X/samples/caret/makefile.wat create mode 100644 wx28X/samples/caret/mondrian.xpm create mode 100644 wx28X/samples/checklst/Makefile.in create mode 100644 wx28X/samples/checklst/checklst.bkl create mode 100644 wx28X/samples/checklst/checklst.cpp create mode 100644 wx28X/samples/checklst/checklst.dsp create mode 100644 wx28X/samples/checklst/checklst.pro create mode 100644 wx28X/samples/checklst/checklst.rc create mode 100644 wx28X/samples/checklst/checklst.rcO create mode 100644 wx28X/samples/checklst/checklst.vcp create mode 100644 wx28X/samples/checklst/checklst.vcw create mode 100644 wx28X/samples/checklst/checklstM5.xml create mode 100644 wx28X/samples/checklst/descrip.mms create mode 100644 wx28X/samples/checklst/makefile.bcc create mode 100644 wx28X/samples/checklst/makefile.dmc create mode 100644 wx28X/samples/checklst/makefile.dms create mode 100644 wx28X/samples/checklst/makefile.gcc create mode 100644 wx28X/samples/checklst/makefile.unx create mode 100644 wx28X/samples/checklst/makefile.va create mode 100644 wx28X/samples/checklst/makefile.vc create mode 100644 wx28X/samples/checklst/makefile.wat create mode 100644 wx28X/samples/checklst/mondrian.xpm create mode 100644 wx28X/samples/checklst/mondros2.ico create mode 100644 wx28X/samples/collpane/Makefile.in create mode 100644 wx28X/samples/collpane/collpane.bkl create mode 100644 wx28X/samples/collpane/collpane.cpp create mode 100644 wx28X/samples/collpane/collpane.dsp create mode 100644 wx28X/samples/collpane/collpane.vcp create mode 100644 wx28X/samples/collpane/collpane.vcw create mode 100644 wx28X/samples/collpane/makefile.bcc create mode 100644 wx28X/samples/collpane/makefile.dmc create mode 100644 wx28X/samples/collpane/makefile.dms create mode 100644 wx28X/samples/collpane/makefile.gcc create mode 100644 wx28X/samples/collpane/makefile.unx create mode 100644 wx28X/samples/collpane/makefile.vc create mode 100644 wx28X/samples/collpane/makefile.wat create mode 100644 wx28X/samples/combo/Makefile.in create mode 100644 wx28X/samples/combo/combo.bkl create mode 100644 wx28X/samples/combo/combo.cpp create mode 100644 wx28X/samples/combo/combo.dsp create mode 100644 wx28X/samples/combo/combo.vcp create mode 100644 wx28X/samples/combo/combo.vcw create mode 100644 wx28X/samples/combo/dropbuth.png create mode 100644 wx28X/samples/combo/dropbutn.png create mode 100644 wx28X/samples/combo/dropbutp.png create mode 100644 wx28X/samples/combo/makefile.bcc create mode 100644 wx28X/samples/combo/makefile.dmc create mode 100644 wx28X/samples/combo/makefile.dms create mode 100644 wx28X/samples/combo/makefile.gcc create mode 100644 wx28X/samples/combo/makefile.unx create mode 100644 wx28X/samples/combo/makefile.vc create mode 100644 wx28X/samples/combo/makefile.wat create mode 100644 wx28X/samples/config/Makefile.in create mode 100644 wx28X/samples/config/config.bkl create mode 100644 wx28X/samples/config/config.dsp create mode 100644 wx28X/samples/config/config.pro create mode 100644 wx28X/samples/config/config.vcp create mode 100644 wx28X/samples/config/config.vcw create mode 100644 wx28X/samples/config/configM5.xml create mode 100644 wx28X/samples/config/conftest.cpp create mode 100644 wx28X/samples/config/conftest.rc create mode 100644 wx28X/samples/config/descrip.mms create mode 100644 wx28X/samples/config/makefile.bcc create mode 100644 wx28X/samples/config/makefile.dmc create mode 100644 wx28X/samples/config/makefile.dms create mode 100644 wx28X/samples/config/makefile.gcc create mode 100644 wx28X/samples/config/makefile.unx create mode 100644 wx28X/samples/config/makefile.vc create mode 100644 wx28X/samples/config/makefile.wat create mode 100644 wx28X/samples/console/Makefile.in create mode 100644 wx28X/samples/console/console.bkl create mode 100644 wx28X/samples/console/console.cpp create mode 100644 wx28X/samples/console/console.dsp create mode 100644 wx28X/samples/console/console.pro create mode 100644 wx28X/samples/console/makefile.bcc create mode 100644 wx28X/samples/console/makefile.dmc create mode 100644 wx28X/samples/console/makefile.dms create mode 100644 wx28X/samples/console/makefile.gcc create mode 100644 wx28X/samples/console/makefile.unx create mode 100644 wx28X/samples/console/makefile.vc create mode 100644 wx28X/samples/console/makefile.wat create mode 100644 wx28X/samples/console/testdata.fc create mode 100644 wx28X/samples/controls/Makefile.in create mode 100644 wx28X/samples/controls/controls.bkl create mode 100644 wx28X/samples/controls/controls.cpp create mode 100644 wx28X/samples/controls/controls.dsp create mode 100644 wx28X/samples/controls/controls.pro create mode 100644 wx28X/samples/controls/controls.rc create mode 100644 wx28X/samples/controls/controls.vcp create mode 100644 wx28X/samples/controls/controls.vcw create mode 100644 wx28X/samples/controls/controlsM5.xml create mode 100644 wx28X/samples/controls/controlsW7.xml create mode 100644 wx28X/samples/controls/descrip.mms create mode 100644 wx28X/samples/controls/icons/choice.bmp create mode 100644 wx28X/samples/controls/icons/choice.xpm create mode 100644 wx28X/samples/controls/icons/combo.bmp create mode 100644 wx28X/samples/controls/icons/combo.xpm create mode 100644 wx28X/samples/controls/icons/gauge.bmp create mode 100644 wx28X/samples/controls/icons/gauge.xpm create mode 100644 wx28X/samples/controls/icons/list.bmp create mode 100644 wx28X/samples/controls/icons/list.xpm create mode 100644 wx28X/samples/controls/icons/radio.bmp create mode 100644 wx28X/samples/controls/icons/radio.xpm create mode 100644 wx28X/samples/controls/icons/stattext.xpm create mode 100644 wx28X/samples/controls/icons/text.bmp create mode 100644 wx28X/samples/controls/icons/text.xpm create mode 100644 wx28X/samples/controls/makefile.bcc create mode 100644 wx28X/samples/controls/makefile.dmc create mode 100644 wx28X/samples/controls/makefile.dms create mode 100644 wx28X/samples/controls/makefile.gcc create mode 100644 wx28X/samples/controls/makefile.unx create mode 100644 wx28X/samples/controls/makefile.vc create mode 100644 wx28X/samples/controls/makefile.wat create mode 100644 wx28X/samples/controls/mondrian.ico create mode 100644 wx28X/samples/controls/mondrian.xpm create mode 100644 wx28X/samples/controls/test2.bmp create mode 100644 wx28X/samples/dataview/Makefile.in create mode 100644 wx28X/samples/dataview/dataview.bkl create mode 100644 wx28X/samples/dataview/dataview.cpp create mode 100644 wx28X/samples/dataview/dataview.dsp create mode 100644 wx28X/samples/dataview/dataview.vcp create mode 100644 wx28X/samples/dataview/dataview.vcw create mode 100644 wx28X/samples/dataview/makefile.bcc create mode 100644 wx28X/samples/dataview/makefile.dmc create mode 100644 wx28X/samples/dataview/makefile.dms create mode 100644 wx28X/samples/dataview/makefile.gcc create mode 100644 wx28X/samples/dataview/makefile.unx create mode 100644 wx28X/samples/dataview/makefile.vc create mode 100644 wx28X/samples/dataview/makefile.wat create mode 100644 wx28X/samples/dataview/null.xpm create mode 100644 wx28X/samples/db/Makefile.in create mode 100644 wx28X/samples/db/db.bkl create mode 100644 wx28X/samples/db/db.dsp create mode 100644 wx28X/samples/db/db.pro create mode 100644 wx28X/samples/db/db.vcp create mode 100644 wx28X/samples/db/db.vcw create mode 100644 wx28X/samples/db/db.xpm create mode 100644 wx28X/samples/db/dbM5.xml create mode 100644 wx28X/samples/db/dbtest.cpp create mode 100644 wx28X/samples/db/dbtest.h create mode 100644 wx28X/samples/db/dbtest.ico create mode 100644 wx28X/samples/db/dbtest.rc create mode 100644 wx28X/samples/db/descrip.mms create mode 100644 wx28X/samples/db/listdb.cpp create mode 100644 wx28X/samples/db/listdb.h create mode 100644 wx28X/samples/db/makefile.bcc create mode 100644 wx28X/samples/db/makefile.dmc create mode 100644 wx28X/samples/db/makefile.dms create mode 100644 wx28X/samples/db/makefile.gcc create mode 100644 wx28X/samples/db/makefile.unx create mode 100644 wx28X/samples/db/makefile.vc create mode 100644 wx28X/samples/db/makefile.wat create mode 100644 wx28X/samples/debugrpt/Makefile.in create mode 100644 wx28X/samples/debugrpt/debugrpt.bkl create mode 100644 wx28X/samples/debugrpt/debugrpt.cpp create mode 100644 wx28X/samples/debugrpt/debugrpt.dsp create mode 100644 wx28X/samples/debugrpt/debugrpt.vcp create mode 100644 wx28X/samples/debugrpt/debugrpt.vcw create mode 100644 wx28X/samples/debugrpt/makefile.bcc create mode 100644 wx28X/samples/debugrpt/makefile.dmc create mode 100644 wx28X/samples/debugrpt/makefile.dms create mode 100644 wx28X/samples/debugrpt/makefile.gcc create mode 100644 wx28X/samples/debugrpt/makefile.unx create mode 100644 wx28X/samples/debugrpt/makefile.vc create mode 100644 wx28X/samples/debugrpt/makefile.wat create mode 100644 wx28X/samples/dialogs/Makefile.in create mode 100644 wx28X/samples/dialogs/descrip.mms create mode 100644 wx28X/samples/dialogs/dialogs.bkl create mode 100644 wx28X/samples/dialogs/dialogs.cpp create mode 100644 wx28X/samples/dialogs/dialogs.dsp create mode 100644 wx28X/samples/dialogs/dialogs.h create mode 100644 wx28X/samples/dialogs/dialogs.ico create mode 100644 wx28X/samples/dialogs/dialogs.pro create mode 100644 wx28X/samples/dialogs/dialogs.rc create mode 100644 wx28X/samples/dialogs/dialogs.rcO create mode 100644 wx28X/samples/dialogs/dialogs.vcp create mode 100644 wx28X/samples/dialogs/dialogs.vcw create mode 100644 wx28X/samples/dialogs/dialogsM5.xml create mode 100644 wx28X/samples/dialogs/dialogsW7.xml create mode 100644 wx28X/samples/dialogs/makefile.bcc create mode 100644 wx28X/samples/dialogs/makefile.dmc create mode 100644 wx28X/samples/dialogs/makefile.dms create mode 100644 wx28X/samples/dialogs/makefile.gcc create mode 100644 wx28X/samples/dialogs/makefile.mgl create mode 100644 wx28X/samples/dialogs/makefile.unx create mode 100644 wx28X/samples/dialogs/makefile.va create mode 100644 wx28X/samples/dialogs/makefile.vc create mode 100644 wx28X/samples/dialogs/makefile.wat create mode 100644 wx28X/samples/dialogs/tips.txt create mode 100644 wx28X/samples/dialup/Makefile.in create mode 100644 wx28X/samples/dialup/descrip.mms create mode 100644 wx28X/samples/dialup/dialup.bkl create mode 100644 wx28X/samples/dialup/dialup.dsp create mode 100644 wx28X/samples/dialup/dialup.pro create mode 100644 wx28X/samples/dialup/dialup.vcp create mode 100644 wx28X/samples/dialup/dialup.vcw create mode 100644 wx28X/samples/dialup/makefile.bcc create mode 100644 wx28X/samples/dialup/makefile.dmc create mode 100644 wx28X/samples/dialup/makefile.dms create mode 100644 wx28X/samples/dialup/makefile.gcc create mode 100644 wx28X/samples/dialup/makefile.unx create mode 100644 wx28X/samples/dialup/makefile.vc create mode 100644 wx28X/samples/dialup/makefile.wat create mode 100644 wx28X/samples/dialup/nettest.cpp create mode 100644 wx28X/samples/dialup/nettest.rc create mode 100644 wx28X/samples/display/Makefile.in create mode 100644 wx28X/samples/display/display.bkl create mode 100644 wx28X/samples/display/display.cpp create mode 100644 wx28X/samples/display/display.dsp create mode 100644 wx28X/samples/display/display.pro create mode 100644 wx28X/samples/display/display.vcp create mode 100644 wx28X/samples/display/display.vcw create mode 100644 wx28X/samples/display/makefile.bcc create mode 100644 wx28X/samples/display/makefile.dmc create mode 100644 wx28X/samples/display/makefile.dms create mode 100644 wx28X/samples/display/makefile.gcc create mode 100644 wx28X/samples/display/makefile.unx create mode 100644 wx28X/samples/display/makefile.vc create mode 100644 wx28X/samples/display/makefile.wat create mode 100644 wx28X/samples/dnd/Makefile.in create mode 100644 wx28X/samples/dnd/d_and_d.txt create mode 100644 wx28X/samples/dnd/descrip.mms create mode 100644 wx28X/samples/dnd/dnd.bkl create mode 100644 wx28X/samples/dnd/dnd.cpp create mode 100644 wx28X/samples/dnd/dnd.dsp create mode 100644 wx28X/samples/dnd/dnd.pro create mode 100644 wx28X/samples/dnd/dnd.rc create mode 100644 wx28X/samples/dnd/dnd.vcp create mode 100644 wx28X/samples/dnd/dnd.vcw create mode 100644 wx28X/samples/dnd/dndM5.xml create mode 100644 wx28X/samples/dnd/dndM7.mcp create mode 100644 wx28X/samples/dnd/dndW7.xml create mode 100644 wx28X/samples/dnd/dnd_copy.cur create mode 100644 wx28X/samples/dnd/dnd_copy.xpm create mode 100644 wx28X/samples/dnd/dnd_move.cur create mode 100644 wx28X/samples/dnd/dnd_move.xpm create mode 100644 wx28X/samples/dnd/dnd_none.cur create mode 100644 wx28X/samples/dnd/dnd_none.xpm create mode 100644 wx28X/samples/dnd/makefile.bcc create mode 100644 wx28X/samples/dnd/makefile.dmc create mode 100644 wx28X/samples/dnd/makefile.dms create mode 100644 wx28X/samples/dnd/makefile.gcc create mode 100644 wx28X/samples/dnd/makefile.unx create mode 100644 wx28X/samples/dnd/makefile.vc create mode 100644 wx28X/samples/dnd/makefile.wat create mode 100644 wx28X/samples/dnd/wxwin.png create mode 100644 wx28X/samples/docview/Makefile.in create mode 100644 wx28X/samples/docview/chart.ico create mode 100644 wx28X/samples/docview/chart.r create mode 100644 wx28X/samples/docview/descrip.mms create mode 100644 wx28X/samples/docview/doc.cpp create mode 100644 wx28X/samples/docview/doc.h create mode 100644 wx28X/samples/docview/doc.ico create mode 100644 wx28X/samples/docview/doc.r create mode 100644 wx28X/samples/docview/docview.bkl create mode 100644 wx28X/samples/docview/docview.cpp create mode 100644 wx28X/samples/docview/docview.dsp create mode 100644 wx28X/samples/docview/docview.h create mode 100644 wx28X/samples/docview/docview.pro create mode 100644 wx28X/samples/docview/docview.r create mode 100644 wx28X/samples/docview/docview.rc create mode 100644 wx28X/samples/docview/docview.vcp create mode 100644 wx28X/samples/docview/docview.vcw create mode 100644 wx28X/samples/docview/docviewM5.xml create mode 100644 wx28X/samples/docview/docviewM7.mcp create mode 100644 wx28X/samples/docview/docviewW7.xml create mode 100644 wx28X/samples/docview/makefile.bcc create mode 100644 wx28X/samples/docview/makefile.dmc create mode 100644 wx28X/samples/docview/makefile.dms create mode 100644 wx28X/samples/docview/makefile.gcc create mode 100644 wx28X/samples/docview/makefile.unx create mode 100644 wx28X/samples/docview/makefile.vc create mode 100644 wx28X/samples/docview/makefile.vms create mode 100644 wx28X/samples/docview/makefile.wat create mode 100644 wx28X/samples/docview/mondrian.ico create mode 100644 wx28X/samples/docview/mondrian.r create mode 100644 wx28X/samples/docview/mondrian.xpm create mode 100644 wx28X/samples/docview/notepad.ico create mode 100644 wx28X/samples/docview/view.cpp create mode 100644 wx28X/samples/docview/view.h create mode 100644 wx28X/samples/docvwmdi/Makefile.in create mode 100644 wx28X/samples/docvwmdi/chart.ico create mode 100644 wx28X/samples/docvwmdi/doc.cpp create mode 100644 wx28X/samples/docvwmdi/doc.h create mode 100644 wx28X/samples/docvwmdi/doc.ico create mode 100644 wx28X/samples/docvwmdi/docview.cpp create mode 100644 wx28X/samples/docvwmdi/docview.h create mode 100644 wx28X/samples/docvwmdi/docview.rc create mode 100644 wx28X/samples/docvwmdi/docvwmdi.bkl create mode 100644 wx28X/samples/docvwmdi/docvwmdi.dsp create mode 100644 wx28X/samples/docvwmdi/docvwmdi.pro create mode 100644 wx28X/samples/docvwmdi/docvwmdi.vcp create mode 100644 wx28X/samples/docvwmdi/docvwmdi.vcw create mode 100644 wx28X/samples/docvwmdi/docvwmdiM5.xml create mode 100644 wx28X/samples/docvwmdi/makefile.bcc create mode 100644 wx28X/samples/docvwmdi/makefile.dmc create mode 100644 wx28X/samples/docvwmdi/makefile.dms create mode 100644 wx28X/samples/docvwmdi/makefile.gcc create mode 100644 wx28X/samples/docvwmdi/makefile.unx create mode 100644 wx28X/samples/docvwmdi/makefile.vc create mode 100644 wx28X/samples/docvwmdi/makefile.wat create mode 100644 wx28X/samples/docvwmdi/notepad.ico create mode 100644 wx28X/samples/docvwmdi/view.cpp create mode 100644 wx28X/samples/docvwmdi/view.h create mode 100644 wx28X/samples/dragimag/Makefile.in create mode 100644 wx28X/samples/dragimag/backgrnd.png create mode 100644 wx28X/samples/dragimag/dragicon.ico create mode 100644 wx28X/samples/dragimag/dragicon.xpm create mode 100644 wx28X/samples/dragimag/dragimag.bkl create mode 100644 wx28X/samples/dragimag/dragimag.cpp create mode 100644 wx28X/samples/dragimag/dragimag.dsp create mode 100644 wx28X/samples/dragimag/dragimag.h create mode 100644 wx28X/samples/dragimag/dragimag.pro create mode 100644 wx28X/samples/dragimag/dragimag.rc create mode 100644 wx28X/samples/dragimag/dragimag.vcp create mode 100644 wx28X/samples/dragimag/dragimag.vcw create mode 100644 wx28X/samples/dragimag/dragimagM5.xml create mode 100644 wx28X/samples/dragimag/makefile.bcc create mode 100644 wx28X/samples/dragimag/makefile.dmc create mode 100644 wx28X/samples/dragimag/makefile.dms create mode 100644 wx28X/samples/dragimag/makefile.gcc create mode 100644 wx28X/samples/dragimag/makefile.sl create mode 100644 wx28X/samples/dragimag/makefile.unx create mode 100644 wx28X/samples/dragimag/makefile.va create mode 100644 wx28X/samples/dragimag/makefile.vc create mode 100644 wx28X/samples/dragimag/makefile.wat create mode 100644 wx28X/samples/dragimag/mondrian.ico create mode 100644 wx28X/samples/dragimag/mondrian.xpm create mode 100644 wx28X/samples/dragimag/shape01.png create mode 100644 wx28X/samples/dragimag/shape02.png create mode 100644 wx28X/samples/dragimag/shape03.png create mode 100644 wx28X/samples/drawing/Makefile.in create mode 100644 wx28X/samples/drawing/descrip.mms create mode 100644 wx28X/samples/drawing/drawing.bkl create mode 100644 wx28X/samples/drawing/drawing.cpp create mode 100644 wx28X/samples/drawing/drawing.dsp create mode 100644 wx28X/samples/drawing/drawing.pro create mode 100644 wx28X/samples/drawing/drawing.rc create mode 100644 wx28X/samples/drawing/drawing.vcp create mode 100644 wx28X/samples/drawing/drawing.vcw create mode 100644 wx28X/samples/drawing/drawingM5.xml create mode 100644 wx28X/samples/drawing/image.bmp create mode 100644 wx28X/samples/drawing/makefile.bcc create mode 100644 wx28X/samples/drawing/makefile.dmc create mode 100644 wx28X/samples/drawing/makefile.dms create mode 100644 wx28X/samples/drawing/makefile.gcc create mode 100644 wx28X/samples/drawing/makefile.unx create mode 100644 wx28X/samples/drawing/makefile.vc create mode 100644 wx28X/samples/drawing/makefile.wat create mode 100644 wx28X/samples/drawing/mask.bmp create mode 100644 wx28X/samples/drawing/mondrian.ico create mode 100644 wx28X/samples/drawing/mondrian.xpm create mode 100644 wx28X/samples/drawing/pat35.bmp create mode 100644 wx28X/samples/drawing/pat36.bmp create mode 100644 wx28X/samples/drawing/pat4.bmp create mode 100644 wx28X/samples/drawing/smile.xpm create mode 100644 wx28X/samples/dynamic/Makefile.in create mode 100644 wx28X/samples/dynamic/dynamic.bkl create mode 100644 wx28X/samples/dynamic/dynamic.cpp create mode 100644 wx28X/samples/dynamic/dynamic.dsp create mode 100644 wx28X/samples/dynamic/dynamic.pro create mode 100644 wx28X/samples/dynamic/dynamic.rc create mode 100644 wx28X/samples/dynamic/dynamic.vcp create mode 100644 wx28X/samples/dynamic/dynamic.vcw create mode 100644 wx28X/samples/dynamic/dynamicM5.xml create mode 100644 wx28X/samples/dynamic/makefile.bcc create mode 100644 wx28X/samples/dynamic/makefile.dmc create mode 100644 wx28X/samples/dynamic/makefile.dms create mode 100644 wx28X/samples/dynamic/makefile.gcc create mode 100644 wx28X/samples/dynamic/makefile.unx create mode 100644 wx28X/samples/dynamic/makefile.vc create mode 100644 wx28X/samples/dynamic/makefile.wat create mode 100644 wx28X/samples/dynamic/mondrian.ico create mode 100644 wx28X/samples/dynamic/mondrian.xpm create mode 100644 wx28X/samples/erase/Erase.icc create mode 100644 wx28X/samples/erase/Makefile.in create mode 100644 wx28X/samples/erase/descrip.mms create mode 100644 wx28X/samples/erase/erase.bkl create mode 100644 wx28X/samples/erase/erase.cpp create mode 100644 wx28X/samples/erase/erase.dsp create mode 100644 wx28X/samples/erase/erase.pro create mode 100644 wx28X/samples/erase/erase.rc create mode 100644 wx28X/samples/erase/erase.rc0 create mode 100644 wx28X/samples/erase/erase.rc4 create mode 100644 wx28X/samples/erase/erase.vcp create mode 100644 wx28X/samples/erase/erase.vcw create mode 100644 wx28X/samples/erase/eraseM5.xml create mode 100644 wx28X/samples/erase/makefile.bcc create mode 100644 wx28X/samples/erase/makefile.dmc create mode 100644 wx28X/samples/erase/makefile.dms create mode 100644 wx28X/samples/erase/makefile.gcc create mode 100644 wx28X/samples/erase/makefile.sl create mode 100644 wx28X/samples/erase/makefile.unx create mode 100644 wx28X/samples/erase/makefile.va create mode 100644 wx28X/samples/erase/makefile.vc create mode 100644 wx28X/samples/erase/makefile.wat create mode 100644 wx28X/samples/erase/makemac6.mcp create mode 100644 wx28X/samples/erase/mondrian.ico create mode 100644 wx28X/samples/erase/mondrian.xpm create mode 100644 wx28X/samples/erase/mondros2.ico create mode 100644 wx28X/samples/event/Makefile.in create mode 100644 wx28X/samples/event/event.bkl create mode 100644 wx28X/samples/event/event.cpp create mode 100644 wx28X/samples/event/event.dsp create mode 100644 wx28X/samples/event/event.pro create mode 100644 wx28X/samples/event/event.rc create mode 100644 wx28X/samples/event/event.vcp create mode 100644 wx28X/samples/event/event.vcw create mode 100644 wx28X/samples/event/eventM5.xml create mode 100644 wx28X/samples/event/makefile.bcc create mode 100644 wx28X/samples/event/makefile.dmc create mode 100644 wx28X/samples/event/makefile.dms create mode 100644 wx28X/samples/event/makefile.gcc create mode 100644 wx28X/samples/event/makefile.sl create mode 100644 wx28X/samples/event/makefile.unx create mode 100644 wx28X/samples/event/makefile.vc create mode 100644 wx28X/samples/event/makefile.wat create mode 100644 wx28X/samples/except/Makefile.in create mode 100644 wx28X/samples/except/except.bkl create mode 100644 wx28X/samples/except/except.cpp create mode 100644 wx28X/samples/except/except.dsp create mode 100644 wx28X/samples/except/except.vcp create mode 100644 wx28X/samples/except/except.vcw create mode 100644 wx28X/samples/except/makefile.bcc create mode 100644 wx28X/samples/except/makefile.dmc create mode 100644 wx28X/samples/except/makefile.dms create mode 100644 wx28X/samples/except/makefile.gcc create mode 100644 wx28X/samples/except/makefile.unx create mode 100644 wx28X/samples/except/makefile.vc create mode 100644 wx28X/samples/except/makefile.wat create mode 100644 wx28X/samples/exec/Makefile.in create mode 100644 wx28X/samples/exec/exec.bkl create mode 100644 wx28X/samples/exec/exec.cpp create mode 100644 wx28X/samples/exec/exec.dsp create mode 100644 wx28X/samples/exec/exec.pro create mode 100644 wx28X/samples/exec/exec.rc create mode 100644 wx28X/samples/exec/exec.vcp create mode 100644 wx28X/samples/exec/exec.vcw create mode 100644 wx28X/samples/exec/execM5.xml create mode 100644 wx28X/samples/exec/makefile.bcc create mode 100644 wx28X/samples/exec/makefile.dmc create mode 100644 wx28X/samples/exec/makefile.dms create mode 100644 wx28X/samples/exec/makefile.gcc create mode 100644 wx28X/samples/exec/makefile.sl create mode 100644 wx28X/samples/exec/makefile.unx create mode 100644 wx28X/samples/exec/makefile.vc create mode 100644 wx28X/samples/exec/makefile.wat create mode 100644 wx28X/samples/font/Makefile.in create mode 100644 wx28X/samples/font/descrip.mms create mode 100644 wx28X/samples/font/font.bkl create mode 100644 wx28X/samples/font/font.cpp create mode 100644 wx28X/samples/font/font.dsp create mode 100644 wx28X/samples/font/font.pro create mode 100644 wx28X/samples/font/font.rc create mode 100644 wx28X/samples/font/font.vcp create mode 100644 wx28X/samples/font/font.vcw create mode 100644 wx28X/samples/font/fontM5.xml create mode 100644 wx28X/samples/font/makefile.bcc create mode 100644 wx28X/samples/font/makefile.dmc create mode 100644 wx28X/samples/font/makefile.dms create mode 100644 wx28X/samples/font/makefile.gcc create mode 100644 wx28X/samples/font/makefile.unx create mode 100644 wx28X/samples/font/makefile.vc create mode 100644 wx28X/samples/font/makefile.wat create mode 100644 wx28X/samples/font/mondrian.ico create mode 100644 wx28X/samples/grid/Makefile.in create mode 100644 wx28X/samples/grid/bitmap1.bmp create mode 100644 wx28X/samples/grid/bitmap2.bmp create mode 100644 wx28X/samples/grid/grid.bkl create mode 100644 wx28X/samples/grid/grid.dsp create mode 100644 wx28X/samples/grid/grid.vcp create mode 100644 wx28X/samples/grid/grid.vcw create mode 100644 wx28X/samples/grid/griddemo.cpp create mode 100644 wx28X/samples/grid/griddemo.h create mode 100644 wx28X/samples/grid/griddemo.pro create mode 100644 wx28X/samples/grid/griddemo.rc create mode 100644 wx28X/samples/grid/griddemoM5.xml create mode 100644 wx28X/samples/grid/griddemoM7.mcp create mode 100644 wx28X/samples/grid/makefile.bcc create mode 100644 wx28X/samples/grid/makefile.dmc create mode 100644 wx28X/samples/grid/makefile.dms create mode 100644 wx28X/samples/grid/makefile.gcc create mode 100644 wx28X/samples/grid/makefile.sl create mode 100644 wx28X/samples/grid/makefile.unx create mode 100644 wx28X/samples/grid/makefile.vc create mode 100644 wx28X/samples/grid/makefile.wat create mode 100644 wx28X/samples/help/Makefile.in create mode 100644 wx28X/samples/help/back.gif create mode 100644 wx28X/samples/help/bullet.bmp create mode 100644 wx28X/samples/help/contents.gif create mode 100644 wx28X/samples/help/cshelp.txt create mode 100644 wx28X/samples/help/demo.cpp create mode 100644 wx28X/samples/help/demo.rc create mode 100644 wx28X/samples/help/doc.chm create mode 100644 wx28X/samples/help/doc.cnt create mode 100644 wx28X/samples/help/doc.h create mode 100644 wx28X/samples/help/doc.hhc create mode 100644 wx28X/samples/help/doc.hhk create mode 100644 wx28X/samples/help/doc.hhp create mode 100644 wx28X/samples/help/doc.hlp create mode 100644 wx28X/samples/help/doc.hpj create mode 100644 wx28X/samples/help/doc.tex create mode 100644 wx28X/samples/help/doc.zip create mode 100644 wx28X/samples/help/doc/ClassGraph.class create mode 100644 wx28X/samples/help/doc/ClassGraphPanel.class create mode 100644 wx28X/samples/help/doc/ClassLayout.class create mode 100644 wx28X/samples/help/doc/HIER.html create mode 100644 wx28X/samples/help/doc/HIERjava.html create mode 100644 wx28X/samples/help/doc/NavigatorButton.class create mode 100644 wx28X/samples/help/doc/USE_HELP.html create mode 100644 wx28X/samples/help/doc/aindex.html create mode 100644 wx28X/samples/help/doc/down.gif create mode 100644 wx28X/samples/help/doc/dxxgifs.tex create mode 100644 wx28X/samples/help/doc/icon1.gif create mode 100644 wx28X/samples/help/doc/icon2.gif create mode 100644 wx28X/samples/help/doc/index.html create mode 100644 wx28X/samples/help/doc/logo.gif create mode 100644 wx28X/samples/help/doc/wx.htm create mode 100644 wx28X/samples/help/doc/wx204.htm create mode 100644 wx28X/samples/help/doc/wx34.htm create mode 100644 wx28X/samples/help/doc/wxExtHelpController.html create mode 100644 wx28X/samples/help/doc/wxhelp.map create mode 100644 wx28X/samples/help/forward.gif create mode 100644 wx28X/samples/help/help.bkl create mode 100644 wx28X/samples/help/help.dsp create mode 100644 wx28X/samples/help/help.pro create mode 100644 wx28X/samples/help/help.vcp create mode 100644 wx28X/samples/help/help.vcw create mode 100644 wx28X/samples/help/helpM5.xml create mode 100644 wx28X/samples/help/makefile.bcc create mode 100644 wx28X/samples/help/makefile.dmc create mode 100644 wx28X/samples/help/makefile.dms create mode 100644 wx28X/samples/help/makefile.gcc create mode 100644 wx28X/samples/help/makefile.unx create mode 100644 wx28X/samples/help/makefile.vc create mode 100644 wx28X/samples/help/makefile.wat create mode 100644 wx28X/samples/help/mondrian.ico create mode 100644 wx28X/samples/help/mondrian.xpm create mode 100644 wx28X/samples/help/tex2rtf.ini create mode 100644 wx28X/samples/help/up.gif create mode 100644 wx28X/samples/htlbox/Makefile.in create mode 100644 wx28X/samples/htlbox/htlbox.bkl create mode 100644 wx28X/samples/htlbox/htlbox.cpp create mode 100644 wx28X/samples/htlbox/htlbox.dsp create mode 100644 wx28X/samples/htlbox/htlbox.rc create mode 100644 wx28X/samples/htlbox/htlbox.vcp create mode 100644 wx28X/samples/htlbox/htlbox.vcw create mode 100644 wx28X/samples/htlbox/makefile.bcc create mode 100644 wx28X/samples/htlbox/makefile.dmc create mode 100644 wx28X/samples/htlbox/makefile.dms create mode 100644 wx28X/samples/htlbox/makefile.gcc create mode 100644 wx28X/samples/htlbox/makefile.unx create mode 100644 wx28X/samples/htlbox/makefile.vc create mode 100644 wx28X/samples/htlbox/makefile.wat create mode 100644 wx28X/samples/htlbox/mondrian.ico create mode 100644 wx28X/samples/htlbox/mondrian.xpm create mode 100644 wx28X/samples/htlbox/results create mode 100644 wx28X/samples/html/Makefile.in create mode 100644 wx28X/samples/html/about/Makefile.in create mode 100644 wx28X/samples/html/about/about.bkl create mode 100644 wx28X/samples/html/about/about.cpp create mode 100644 wx28X/samples/html/about/about.dsp create mode 100644 wx28X/samples/html/about/about.pro create mode 100644 wx28X/samples/html/about/about.rc create mode 100644 wx28X/samples/html/about/about.vcp create mode 100644 wx28X/samples/html/about/about.vcw create mode 100644 wx28X/samples/html/about/aboutM5.xml create mode 100644 wx28X/samples/html/about/aboutmac6.mcp create mode 100644 wx28X/samples/html/about/data/about.htm create mode 100644 wx28X/samples/html/about/data/logo.png create mode 100644 wx28X/samples/html/about/makefile.bcc create mode 100644 wx28X/samples/html/about/makefile.dmc create mode 100644 wx28X/samples/html/about/makefile.dms create mode 100644 wx28X/samples/html/about/makefile.gcc create mode 100644 wx28X/samples/html/about/makefile.unx create mode 100644 wx28X/samples/html/about/makefile.vc create mode 100644 wx28X/samples/html/about/makefile.wat create mode 100644 wx28X/samples/html/help/Makefile.in create mode 100644 wx28X/samples/html/help/help.bkl create mode 100644 wx28X/samples/html/help/help.cpp create mode 100644 wx28X/samples/html/help/help.dsp create mode 100644 wx28X/samples/html/help/help.pro create mode 100644 wx28X/samples/html/help/help.rc create mode 100644 wx28X/samples/html/help/help.vcp create mode 100644 wx28X/samples/html/help/help.vcw create mode 100644 wx28X/samples/html/help/helpM5.xml create mode 100644 wx28X/samples/html/help/helpfiles/Index.hhk create mode 100644 wx28X/samples/html/help/helpfiles/another.hhc create mode 100644 wx28X/samples/html/help/helpfiles/another.hhp create mode 100644 wx28X/samples/html/help/helpfiles/another.htm create mode 100644 wx28X/samples/html/help/helpfiles/book1.htm create mode 100644 wx28X/samples/html/help/helpfiles/book2.htm create mode 100644 wx28X/samples/html/help/helpfiles/contents.hhc create mode 100644 wx28X/samples/html/help/helpfiles/main.htm create mode 100644 wx28X/samples/html/help/helpfiles/page2-b.htm create mode 100644 wx28X/samples/html/help/helpfiles/testing.hhp create mode 100644 wx28X/samples/html/help/makefile.bcc create mode 100644 wx28X/samples/html/help/makefile.dmc create mode 100644 wx28X/samples/html/help/makefile.dms create mode 100644 wx28X/samples/html/help/makefile.gcc create mode 100644 wx28X/samples/html/help/makefile.unx create mode 100644 wx28X/samples/html/help/makefile.vc create mode 100644 wx28X/samples/html/help/makefile.wat create mode 100644 wx28X/samples/html/help/makemac6.mcp create mode 100644 wx28X/samples/html/helpview/Makefile.in create mode 100644 wx28X/samples/html/helpview/helpview.bkl create mode 100644 wx28X/samples/html/helpview/helpview.cpp create mode 100644 wx28X/samples/html/helpview/helpview.dsp create mode 100644 wx28X/samples/html/helpview/helpview.ico create mode 100644 wx28X/samples/html/helpview/helpview.pro create mode 100644 wx28X/samples/html/helpview/helpview.rc create mode 100644 wx28X/samples/html/helpview/helpview.vcp create mode 100644 wx28X/samples/html/helpview/helpview.vcw create mode 100644 wx28X/samples/html/helpview/helpviewM5.xml create mode 100644 wx28X/samples/html/helpview/makefile.bcc create mode 100644 wx28X/samples/html/helpview/makefile.dmc create mode 100644 wx28X/samples/html/helpview/makefile.dms create mode 100644 wx28X/samples/html/helpview/makefile.gcc create mode 100644 wx28X/samples/html/helpview/makefile.unx create mode 100644 wx28X/samples/html/helpview/makefile.vc create mode 100644 wx28X/samples/html/helpview/makefile.wat create mode 100644 wx28X/samples/html/helpview/mondrian.ico create mode 100644 wx28X/samples/html/helpview/test.zip create mode 100644 wx28X/samples/html/html_samples.bkl create mode 100644 wx28X/samples/html/htmlctrl/Makefile.in create mode 100644 wx28X/samples/html/htmlctrl/htmlctrl.bkl create mode 100644 wx28X/samples/html/htmlctrl/htmlctrl.cpp create mode 100644 wx28X/samples/html/htmlctrl/makefile.unx create mode 100644 wx28X/samples/html/makefile.bcc create mode 100644 wx28X/samples/html/makefile.dmc create mode 100644 wx28X/samples/html/makefile.dms create mode 100644 wx28X/samples/html/makefile.gcc create mode 100644 wx28X/samples/html/makefile.unx create mode 100644 wx28X/samples/html/makefile.vc create mode 100644 wx28X/samples/html/makefile.wat create mode 100644 wx28X/samples/html/printing/Makefile.in create mode 100644 wx28X/samples/html/printing/logo6.gif create mode 100644 wx28X/samples/html/printing/makefile.bcc create mode 100644 wx28X/samples/html/printing/makefile.dmc create mode 100644 wx28X/samples/html/printing/makefile.dms create mode 100644 wx28X/samples/html/printing/makefile.gcc create mode 100644 wx28X/samples/html/printing/makefile.unx create mode 100644 wx28X/samples/html/printing/makefile.vc create mode 100644 wx28X/samples/html/printing/makefile.wat create mode 100644 wx28X/samples/html/printing/mondrian.ico create mode 100644 wx28X/samples/html/printing/printing.bkl create mode 100644 wx28X/samples/html/printing/printing.cpp create mode 100644 wx28X/samples/html/printing/printing.dsp create mode 100644 wx28X/samples/html/printing/printing.pro create mode 100644 wx28X/samples/html/printing/printing.rc create mode 100644 wx28X/samples/html/printing/printing.vcp create mode 100644 wx28X/samples/html/printing/printing.vcw create mode 100644 wx28X/samples/html/printing/printingM5.xml create mode 100644 wx28X/samples/html/printing/test.htm create mode 100644 wx28X/samples/html/test/8859_2.htm create mode 100644 wx28X/samples/html/test/Makefile.in create mode 100644 wx28X/samples/html/test/cp1250.htm create mode 100644 wx28X/samples/html/test/f.html create mode 100644 wx28X/samples/html/test/fft.html create mode 100644 wx28X/samples/html/test/foo.png create mode 100644 wx28X/samples/html/test/i18n.gif create mode 100644 wx28X/samples/html/test/imagemap.htm create mode 100644 wx28X/samples/html/test/imagemap.png create mode 100644 wx28X/samples/html/test/listtest.htm create mode 100644 wx28X/samples/html/test/makefile.bcc create mode 100644 wx28X/samples/html/test/makefile.dmc create mode 100644 wx28X/samples/html/test/makefile.dms create mode 100644 wx28X/samples/html/test/makefile.gcc create mode 100644 wx28X/samples/html/test/makefile.unx create mode 100644 wx28X/samples/html/test/makefile.vc create mode 100644 wx28X/samples/html/test/makefile.wat create mode 100644 wx28X/samples/html/test/makemac6.mcp create mode 100644 wx28X/samples/html/test/pic.png create mode 100644 wx28X/samples/html/test/pic2.bmp create mode 100644 wx28X/samples/html/test/regres.htm create mode 100644 wx28X/samples/html/test/subsup.html create mode 100644 wx28X/samples/html/test/tables.htm create mode 100644 wx28X/samples/html/test/test.bkl create mode 100644 wx28X/samples/html/test/test.cpp create mode 100644 wx28X/samples/html/test/test.dsp create mode 100644 wx28X/samples/html/test/test.htm create mode 100644 wx28X/samples/html/test/test.pro create mode 100644 wx28X/samples/html/test/test.rc create mode 100644 wx28X/samples/html/test/test.vcp create mode 100644 wx28X/samples/html/test/test.vcw create mode 100644 wx28X/samples/html/test/testM5.xml create mode 100644 wx28X/samples/html/virtual/Makefile.in create mode 100644 wx28X/samples/html/virtual/makefile.bcc create mode 100644 wx28X/samples/html/virtual/makefile.dmc create mode 100644 wx28X/samples/html/virtual/makefile.dms create mode 100644 wx28X/samples/html/virtual/makefile.gcc create mode 100644 wx28X/samples/html/virtual/makefile.unx create mode 100644 wx28X/samples/html/virtual/makefile.vc create mode 100644 wx28X/samples/html/virtual/makefile.wat create mode 100644 wx28X/samples/html/virtual/start.htm create mode 100644 wx28X/samples/html/virtual/virtual.bkl create mode 100644 wx28X/samples/html/virtual/virtual.cpp create mode 100644 wx28X/samples/html/virtual/virtual.dsp create mode 100644 wx28X/samples/html/virtual/virtual.pro create mode 100644 wx28X/samples/html/virtual/virtual.rc create mode 100644 wx28X/samples/html/virtual/virtual.vcp create mode 100644 wx28X/samples/html/virtual/virtual.vcw create mode 100644 wx28X/samples/html/virtual/virtualM5.xml create mode 100644 wx28X/samples/html/virtual/virtualmac6.mcp create mode 100644 wx28X/samples/html/widget/Makefile.in create mode 100644 wx28X/samples/html/widget/makefile.bcc create mode 100644 wx28X/samples/html/widget/makefile.dmc create mode 100644 wx28X/samples/html/widget/makefile.dms create mode 100644 wx28X/samples/html/widget/makefile.gcc create mode 100644 wx28X/samples/html/widget/makefile.unx create mode 100644 wx28X/samples/html/widget/makefile.vc create mode 100644 wx28X/samples/html/widget/makefile.wat create mode 100644 wx28X/samples/html/widget/start.htm create mode 100644 wx28X/samples/html/widget/widget.bkl create mode 100644 wx28X/samples/html/widget/widget.cpp create mode 100644 wx28X/samples/html/widget/widget.dsp create mode 100644 wx28X/samples/html/widget/widget.pro create mode 100644 wx28X/samples/html/widget/widget.rc create mode 100644 wx28X/samples/html/widget/widget.vcp create mode 100644 wx28X/samples/html/widget/widget.vcw create mode 100644 wx28X/samples/html/widget/widgetM5.xml create mode 100644 wx28X/samples/html/zip/Makefile.in create mode 100644 wx28X/samples/html/zip/makefile.bcc create mode 100644 wx28X/samples/html/zip/makefile.dmc create mode 100644 wx28X/samples/html/zip/makefile.dms create mode 100644 wx28X/samples/html/zip/makefile.gcc create mode 100644 wx28X/samples/html/zip/makefile.unx create mode 100644 wx28X/samples/html/zip/makefile.vc create mode 100644 wx28X/samples/html/zip/makefile.wat create mode 100644 wx28X/samples/html/zip/pages.zip create mode 100644 wx28X/samples/html/zip/start.htm create mode 100644 wx28X/samples/html/zip/zip.bkl create mode 100644 wx28X/samples/html/zip/zip.cpp create mode 100644 wx28X/samples/html/zip/zip.dsp create mode 100644 wx28X/samples/html/zip/zip.pro create mode 100644 wx28X/samples/html/zip/zip.rc create mode 100644 wx28X/samples/html/zip/zip.vcp create mode 100644 wx28X/samples/html/zip/zip.vcw create mode 100644 wx28X/samples/html/zip/zipM5.xml create mode 100644 wx28X/samples/image/Makefile.in create mode 100644 wx28X/samples/image/cmyk.jpg create mode 100644 wx28X/samples/image/descrip.mms create mode 100644 wx28X/samples/image/horse.bmp create mode 100644 wx28X/samples/image/horse.cur create mode 100644 wx28X/samples/image/horse.gif create mode 100644 wx28X/samples/image/horse.ico create mode 100644 wx28X/samples/image/horse.jpg create mode 100644 wx28X/samples/image/horse.pcx create mode 100644 wx28X/samples/image/horse.png create mode 100644 wx28X/samples/image/horse.pnm create mode 100644 wx28X/samples/image/horse.tga create mode 100644 wx28X/samples/image/horse.tif create mode 100644 wx28X/samples/image/horse.xpm create mode 100644 wx28X/samples/image/horse3.ani create mode 100644 wx28X/samples/image/horse_ag.pnm create mode 100644 wx28X/samples/image/horse_rg.pnm create mode 100644 wx28X/samples/image/image.bkl create mode 100644 wx28X/samples/image/image.cpp create mode 100644 wx28X/samples/image/image.dsp create mode 100644 wx28X/samples/image/image.pro create mode 100644 wx28X/samples/image/image.rc create mode 100644 wx28X/samples/image/image.rco create mode 100644 wx28X/samples/image/image.vcp create mode 100644 wx28X/samples/image/image.vcw create mode 100644 wx28X/samples/image/imageM5.xml create mode 100644 wx28X/samples/image/makefile.bcc create mode 100644 wx28X/samples/image/makefile.dmc create mode 100644 wx28X/samples/image/makefile.dms create mode 100644 wx28X/samples/image/makefile.gcc create mode 100644 wx28X/samples/image/makefile.unx create mode 100644 wx28X/samples/image/makefile.va create mode 100644 wx28X/samples/image/makefile.vc create mode 100644 wx28X/samples/image/makefile.wat create mode 100644 wx28X/samples/image/makemac6.mcp create mode 100644 wx28X/samples/image/smile.xbm create mode 100644 wx28X/samples/image/smile.xpm create mode 100644 wx28X/samples/image/toucan.png create mode 100644 wx28X/samples/internat/Makefile.in create mode 100644 wx28X/samples/internat/ar/internat.mo create mode 100644 wx28X/samples/internat/ar/internat.po create mode 100644 wx28X/samples/internat/bg/internat.mo create mode 100644 wx28X/samples/internat/bg/internat.po create mode 100644 wx28X/samples/internat/cs/internat.mo create mode 100644 wx28X/samples/internat/cs/internat.po create mode 100644 wx28X/samples/internat/de/internat.mo create mode 100644 wx28X/samples/internat/de/internat.po create mode 100644 wx28X/samples/internat/fr/internat.mo create mode 100644 wx28X/samples/internat/fr/internat.po create mode 100644 wx28X/samples/internat/internat.bkl create mode 100644 wx28X/samples/internat/internat.cpp create mode 100644 wx28X/samples/internat/internat.dsp create mode 100644 wx28X/samples/internat/internat.pro create mode 100644 wx28X/samples/internat/internat.rc create mode 100644 wx28X/samples/internat/internat.vcp create mode 100644 wx28X/samples/internat/internat.vcw create mode 100644 wx28X/samples/internat/internatM5.xml create mode 100644 wx28X/samples/internat/ja/internat.mo create mode 100644 wx28X/samples/internat/ja/internat.po create mode 100644 wx28X/samples/internat/ja_JP.EUC-JP/internat.mo create mode 100644 wx28X/samples/internat/ja_JP.EUC-JP/internat.po create mode 100644 wx28X/samples/internat/ka/internat.mo create mode 100644 wx28X/samples/internat/ka/internat.po create mode 100644 wx28X/samples/internat/makefile.bcc create mode 100644 wx28X/samples/internat/makefile.dmc create mode 100644 wx28X/samples/internat/makefile.dms create mode 100644 wx28X/samples/internat/makefile.gcc create mode 100644 wx28X/samples/internat/makefile.unx create mode 100644 wx28X/samples/internat/makefile.vc create mode 100644 wx28X/samples/internat/makefile.vms create mode 100644 wx28X/samples/internat/makefile.wat create mode 100644 wx28X/samples/internat/makemac6.mcp create mode 100644 wx28X/samples/internat/mondrian.ico create mode 100644 wx28X/samples/internat/mondrian.xpm create mode 100644 wx28X/samples/internat/pl/internat.mo create mode 100644 wx28X/samples/internat/pl/internat.po create mode 100644 wx28X/samples/internat/readme.txt create mode 100644 wx28X/samples/internat/ru/internat.mo create mode 100644 wx28X/samples/internat/ru/internat.po create mode 100644 wx28X/samples/internat/sv/internat.mo create mode 100644 wx28X/samples/internat/sv/internat.po create mode 100644 wx28X/samples/ipc/Makefile.in create mode 100644 wx28X/samples/ipc/client.b32 create mode 100644 wx28X/samples/ipc/client.cpp create mode 100644 wx28X/samples/ipc/client.g95 create mode 100644 wx28X/samples/ipc/client.h create mode 100644 wx28X/samples/ipc/client.pro create mode 100644 wx28X/samples/ipc/client.rc create mode 100644 wx28X/samples/ipc/client.vc create mode 100644 wx28X/samples/ipc/client.wat create mode 100644 wx28X/samples/ipc/ipc.bkl create mode 100644 wx28X/samples/ipc/ipc.vcw create mode 100644 wx28X/samples/ipc/ipc_ipcclient.dsp create mode 100644 wx28X/samples/ipc/ipc_ipcclient.vcp create mode 100644 wx28X/samples/ipc/ipc_ipcserver.dsp create mode 100644 wx28X/samples/ipc/ipc_ipcserver.vcp create mode 100644 wx28X/samples/ipc/ipcsetup.h create mode 100644 wx28X/samples/ipc/makefile.bcc create mode 100644 wx28X/samples/ipc/makefile.dmc create mode 100644 wx28X/samples/ipc/makefile.dms create mode 100644 wx28X/samples/ipc/makefile.gcc create mode 100644 wx28X/samples/ipc/makefile.unx create mode 100644 wx28X/samples/ipc/makefile.vc create mode 100644 wx28X/samples/ipc/makefile.wat create mode 100644 wx28X/samples/ipc/mondrian.ico create mode 100644 wx28X/samples/ipc/mondrian.xpm create mode 100644 wx28X/samples/ipc/server.b32 create mode 100644 wx28X/samples/ipc/server.cpp create mode 100644 wx28X/samples/ipc/server.g95 create mode 100644 wx28X/samples/ipc/server.h create mode 100644 wx28X/samples/ipc/server.pro create mode 100644 wx28X/samples/ipc/server.rc create mode 100644 wx28X/samples/ipc/server.vc create mode 100644 wx28X/samples/ipc/server.wat create mode 100644 wx28X/samples/joytest/Makefile.in create mode 100644 wx28X/samples/joytest/buttonpress.wav create mode 100644 wx28X/samples/joytest/chart.ico create mode 100644 wx28X/samples/joytest/joytest.bkl create mode 100644 wx28X/samples/joytest/joytest.cpp create mode 100644 wx28X/samples/joytest/joytest.dsp create mode 100644 wx28X/samples/joytest/joytest.h create mode 100644 wx28X/samples/joytest/joytest.ico create mode 100644 wx28X/samples/joytest/joytest.pro create mode 100644 wx28X/samples/joytest/joytest.rc create mode 100644 wx28X/samples/joytest/joytest.vcp create mode 100644 wx28X/samples/joytest/joytest.vcw create mode 100644 wx28X/samples/joytest/joytestM5.xml create mode 100644 wx28X/samples/joytest/makefile.bcc create mode 100644 wx28X/samples/joytest/makefile.dmc create mode 100644 wx28X/samples/joytest/makefile.dms create mode 100644 wx28X/samples/joytest/makefile.gcc create mode 100644 wx28X/samples/joytest/makefile.sl create mode 100644 wx28X/samples/joytest/makefile.unx create mode 100644 wx28X/samples/joytest/makefile.vc create mode 100644 wx28X/samples/joytest/makefile.wat create mode 100644 wx28X/samples/joytest/mondrian.ico create mode 100644 wx28X/samples/keyboard/Makefile.in create mode 100644 wx28X/samples/keyboard/keyboard.bkl create mode 100644 wx28X/samples/keyboard/keyboard.cpp create mode 100644 wx28X/samples/keyboard/keyboard.dsp create mode 100644 wx28X/samples/keyboard/keyboard.pro create mode 100644 wx28X/samples/keyboard/keyboard.rc create mode 100644 wx28X/samples/keyboard/keyboard.vcp create mode 100644 wx28X/samples/keyboard/keyboard.vcw create mode 100644 wx28X/samples/keyboard/keyboardM5.xml create mode 100644 wx28X/samples/keyboard/makefile.bcc create mode 100644 wx28X/samples/keyboard/makefile.dmc create mode 100644 wx28X/samples/keyboard/makefile.dms create mode 100644 wx28X/samples/keyboard/makefile.gcc create mode 100644 wx28X/samples/keyboard/makefile.unx create mode 100644 wx28X/samples/keyboard/makefile.vc create mode 100644 wx28X/samples/keyboard/makefile.wat create mode 100644 wx28X/samples/layout/Makefile.in create mode 100644 wx28X/samples/layout/expt.cpp create mode 100644 wx28X/samples/layout/layout.bkl create mode 100644 wx28X/samples/layout/layout.cpp create mode 100644 wx28X/samples/layout/layout.dsp create mode 100644 wx28X/samples/layout/layout.h create mode 100644 wx28X/samples/layout/layout.pro create mode 100644 wx28X/samples/layout/layout.rc create mode 100644 wx28X/samples/layout/layout.vcp create mode 100644 wx28X/samples/layout/layout.vcw create mode 100644 wx28X/samples/layout/layoutM5.xml create mode 100644 wx28X/samples/layout/makefile.bcc create mode 100644 wx28X/samples/layout/makefile.dmc create mode 100644 wx28X/samples/layout/makefile.dms create mode 100644 wx28X/samples/layout/makefile.gcc create mode 100644 wx28X/samples/layout/makefile.unx create mode 100644 wx28X/samples/layout/makefile.vc create mode 100644 wx28X/samples/layout/makefile.vms create mode 100644 wx28X/samples/layout/makefile.wat create mode 100644 wx28X/samples/listbox/Makefile.in create mode 100644 wx28X/samples/listbox/lboxtest.cpp create mode 100644 wx28X/samples/listbox/lboxtestM5.xml create mode 100644 wx28X/samples/listbox/listbox.bkl create mode 100644 wx28X/samples/listbox/listbox.dsp create mode 100644 wx28X/samples/listbox/listbox.vcp create mode 100644 wx28X/samples/listbox/listbox.vcw create mode 100644 wx28X/samples/listbox/makefile.bcc create mode 100644 wx28X/samples/listbox/makefile.dmc create mode 100644 wx28X/samples/listbox/makefile.dms create mode 100644 wx28X/samples/listbox/makefile.gcc create mode 100644 wx28X/samples/listbox/makefile.unx create mode 100644 wx28X/samples/listbox/makefile.vc create mode 100644 wx28X/samples/listbox/makefile.wat create mode 100644 wx28X/samples/listctrl/Makefile.in create mode 100644 wx28X/samples/listctrl/bitmaps/small1.ico create mode 100644 wx28X/samples/listctrl/bitmaps/small1.xpm create mode 100644 wx28X/samples/listctrl/bitmaps/toolbrai.ico create mode 100644 wx28X/samples/listctrl/bitmaps/toolbrai.xpm create mode 100644 wx28X/samples/listctrl/bitmaps/toolchar.ico create mode 100644 wx28X/samples/listctrl/bitmaps/toolchar.xpm create mode 100644 wx28X/samples/listctrl/bitmaps/toolchec.ico create mode 100644 wx28X/samples/listctrl/bitmaps/toolchec.xpm create mode 100644 wx28X/samples/listctrl/bitmaps/tooldata.ico create mode 100644 wx28X/samples/listctrl/bitmaps/tooldata.xpm create mode 100644 wx28X/samples/listctrl/bitmaps/toolgame.ico create mode 100644 wx28X/samples/listctrl/bitmaps/toolgame.xpm create mode 100644 wx28X/samples/listctrl/bitmaps/toolnote.ico create mode 100644 wx28X/samples/listctrl/bitmaps/toolnote.xpm create mode 100644 wx28X/samples/listctrl/bitmaps/tooltime.ico create mode 100644 wx28X/samples/listctrl/bitmaps/tooltime.xpm create mode 100644 wx28X/samples/listctrl/bitmaps/tooltodo.ico create mode 100644 wx28X/samples/listctrl/bitmaps/tooltodo.xpm create mode 100644 wx28X/samples/listctrl/bitmaps/toolword.ico create mode 100644 wx28X/samples/listctrl/bitmaps/toolword.xpm create mode 100644 wx28X/samples/listctrl/listctrl.bkl create mode 100644 wx28X/samples/listctrl/listctrl.dsp create mode 100644 wx28X/samples/listctrl/listctrl.pro create mode 100644 wx28X/samples/listctrl/listctrl.vcp create mode 100644 wx28X/samples/listctrl/listctrl.vcw create mode 100644 wx28X/samples/listctrl/listctrlM5.xml create mode 100644 wx28X/samples/listctrl/listtest.cpp create mode 100644 wx28X/samples/listctrl/listtest.h create mode 100644 wx28X/samples/listctrl/listtest.rc create mode 100644 wx28X/samples/listctrl/makefile.bcc create mode 100644 wx28X/samples/listctrl/makefile.dmc create mode 100644 wx28X/samples/listctrl/makefile.dms create mode 100644 wx28X/samples/listctrl/makefile.gcc create mode 100644 wx28X/samples/listctrl/makefile.unx create mode 100644 wx28X/samples/listctrl/makefile.vc create mode 100644 wx28X/samples/listctrl/makefile.wat create mode 100644 wx28X/samples/listctrl/mondrian.ico create mode 100644 wx28X/samples/listctrl/mondrian.xpm create mode 100644 wx28X/samples/makefile.bcc create mode 100644 wx28X/samples/makefile.dmc create mode 100644 wx28X/samples/makefile.dms create mode 100644 wx28X/samples/makefile.gcc create mode 100644 wx28X/samples/makefile.vc create mode 100644 wx28X/samples/makefile.wat create mode 100644 wx28X/samples/mdi/Makefile.in create mode 100644 wx28X/samples/mdi/bitmaps/copy.xpm create mode 100644 wx28X/samples/mdi/bitmaps/cut.xpm create mode 100644 wx28X/samples/mdi/bitmaps/help.xpm create mode 100644 wx28X/samples/mdi/bitmaps/new.xpm create mode 100644 wx28X/samples/mdi/bitmaps/open.xpm create mode 100644 wx28X/samples/mdi/bitmaps/paste.xpm create mode 100644 wx28X/samples/mdi/bitmaps/preview.xpm create mode 100644 wx28X/samples/mdi/bitmaps/print.xpm create mode 100644 wx28X/samples/mdi/bitmaps/save.xpm create mode 100644 wx28X/samples/mdi/chart.ico create mode 100644 wx28X/samples/mdi/chart.xpm create mode 100644 wx28X/samples/mdi/descrip.mms create mode 100644 wx28X/samples/mdi/makefile.bcc create mode 100644 wx28X/samples/mdi/makefile.dmc create mode 100644 wx28X/samples/mdi/makefile.dms create mode 100644 wx28X/samples/mdi/makefile.gcc create mode 100644 wx28X/samples/mdi/makefile.sl create mode 100644 wx28X/samples/mdi/makefile.unx create mode 100644 wx28X/samples/mdi/makefile.vc create mode 100644 wx28X/samples/mdi/makefile.vms create mode 100644 wx28X/samples/mdi/makefile.wat create mode 100644 wx28X/samples/mdi/mdi.bkl create mode 100644 wx28X/samples/mdi/mdi.cpp create mode 100644 wx28X/samples/mdi/mdi.dsp create mode 100644 wx28X/samples/mdi/mdi.h create mode 100644 wx28X/samples/mdi/mdi.pro create mode 100644 wx28X/samples/mdi/mdi.rc create mode 100644 wx28X/samples/mdi/mdi.vcp create mode 100644 wx28X/samples/mdi/mdi.vcw create mode 100644 wx28X/samples/mdi/mdiM5.xml create mode 100644 wx28X/samples/mediaplayer/Makefile.in create mode 100644 wx28X/samples/mediaplayer/makefile.bcc create mode 100644 wx28X/samples/mediaplayer/makefile.dmc create mode 100644 wx28X/samples/mediaplayer/makefile.dms create mode 100644 wx28X/samples/mediaplayer/makefile.gcc create mode 100644 wx28X/samples/mediaplayer/makefile.unx create mode 100644 wx28X/samples/mediaplayer/makefile.vc create mode 100644 wx28X/samples/mediaplayer/makefile.wat create mode 100644 wx28X/samples/mediaplayer/mediaplayer.bkl create mode 100644 wx28X/samples/mediaplayer/mediaplayer.cpp create mode 100644 wx28X/samples/mediaplayer/mediaplayer.dsp create mode 100644 wx28X/samples/mediaplayer/mediaplayer.vcp create mode 100644 wx28X/samples/mediaplayer/mediaplayer.vcw create mode 100644 wx28X/samples/memcheck/Makefile.in create mode 100644 wx28X/samples/memcheck/makefile.bcc create mode 100644 wx28X/samples/memcheck/makefile.dmc create mode 100644 wx28X/samples/memcheck/makefile.dms create mode 100644 wx28X/samples/memcheck/makefile.gcc create mode 100644 wx28X/samples/memcheck/makefile.unx create mode 100644 wx28X/samples/memcheck/makefile.vc create mode 100644 wx28X/samples/memcheck/makefile.wat create mode 100644 wx28X/samples/memcheck/memcheck.bkl create mode 100644 wx28X/samples/memcheck/memcheck.cpp create mode 100644 wx28X/samples/memcheck/memcheck.dsp create mode 100644 wx28X/samples/memcheck/memcheck.pro create mode 100644 wx28X/samples/memcheck/memcheck.rc create mode 100644 wx28X/samples/memcheck/memcheck.vcp create mode 100644 wx28X/samples/memcheck/memcheck.vcw create mode 100644 wx28X/samples/memcheck/mondrian.ico create mode 100644 wx28X/samples/memcheck/mondrian.xpm create mode 100644 wx28X/samples/menu/MENU.RCO create mode 100644 wx28X/samples/menu/Makefile.in create mode 100644 wx28X/samples/menu/copy.xpm create mode 100644 wx28X/samples/menu/descrip.mms create mode 100644 wx28X/samples/menu/makefile.bcc create mode 100644 wx28X/samples/menu/makefile.dmc create mode 100644 wx28X/samples/menu/makefile.dms create mode 100644 wx28X/samples/menu/makefile.gcc create mode 100644 wx28X/samples/menu/makefile.unx create mode 100644 wx28X/samples/menu/makefile.va create mode 100644 wx28X/samples/menu/makefile.vc create mode 100644 wx28X/samples/menu/makefile.wat create mode 100644 wx28X/samples/menu/menu.bkl create mode 100644 wx28X/samples/menu/menu.cpp create mode 100644 wx28X/samples/menu/menu.dsp create mode 100644 wx28X/samples/menu/menu.pro create mode 100644 wx28X/samples/menu/menu.rc create mode 100644 wx28X/samples/menu/menu.vcp create mode 100644 wx28X/samples/menu/menu.vcw create mode 100644 wx28X/samples/menu/menuM5.xml create mode 100644 wx28X/samples/menu/mondros2.ico create mode 100644 wx28X/samples/mfc/Makefile.in create mode 100644 wx28X/samples/mfc/makefile.bcc create mode 100644 wx28X/samples/mfc/makefile.dmc create mode 100644 wx28X/samples/mfc/makefile.dms create mode 100644 wx28X/samples/mfc/makefile.gcc create mode 100644 wx28X/samples/mfc/makefile.unx create mode 100644 wx28X/samples/mfc/makefile.vc create mode 100644 wx28X/samples/mfc/makefile.wat create mode 100644 wx28X/samples/mfc/mfc.bkl create mode 100644 wx28X/samples/mfc/mfc.dsp create mode 100644 wx28X/samples/mfc/mfc.pro create mode 100644 wx28X/samples/mfc/mfc.vcp create mode 100644 wx28X/samples/mfc/mfc.vcw create mode 100644 wx28X/samples/mfc/mfctest.cpp create mode 100644 wx28X/samples/mfc/mfctest.h create mode 100644 wx28X/samples/mfc/mfctest.ico create mode 100644 wx28X/samples/mfc/mfctest.rc create mode 100644 wx28X/samples/mfc/resource.h create mode 100644 wx28X/samples/mfc/stdafx.h create mode 100644 wx28X/samples/minifram/Makefile.in create mode 100644 wx28X/samples/minifram/bitmaps/copy.xpm create mode 100644 wx28X/samples/minifram/bitmaps/cut.xpm create mode 100644 wx28X/samples/minifram/bitmaps/help.xpm create mode 100644 wx28X/samples/minifram/bitmaps/new.xpm create mode 100644 wx28X/samples/minifram/bitmaps/open.xpm create mode 100644 wx28X/samples/minifram/bitmaps/preview.xpm create mode 100644 wx28X/samples/minifram/bitmaps/print.xpm create mode 100644 wx28X/samples/minifram/bitmaps/save.xpm create mode 100644 wx28X/samples/minifram/makefile.bcc create mode 100644 wx28X/samples/minifram/makefile.dmc create mode 100644 wx28X/samples/minifram/makefile.dms create mode 100644 wx28X/samples/minifram/makefile.gcc create mode 100644 wx28X/samples/minifram/makefile.sl create mode 100644 wx28X/samples/minifram/makefile.unx create mode 100644 wx28X/samples/minifram/makefile.vc create mode 100644 wx28X/samples/minifram/makefile.wat create mode 100644 wx28X/samples/minifram/minifram.bkl create mode 100644 wx28X/samples/minifram/minifram.cpp create mode 100644 wx28X/samples/minifram/minifram.dsp create mode 100644 wx28X/samples/minifram/minifram.h create mode 100644 wx28X/samples/minifram/minifram.pro create mode 100644 wx28X/samples/minifram/minifram.rc create mode 100644 wx28X/samples/minifram/minifram.vcp create mode 100644 wx28X/samples/minifram/minifram.vcw create mode 100644 wx28X/samples/minifram/miniframM5.xml create mode 100644 wx28X/samples/minifram/mondrian.ico create mode 100644 wx28X/samples/minifram/mondrian.xpm create mode 100644 wx28X/samples/minimal/Info.plist create mode 100644 wx28X/samples/minimal/Makefile.in create mode 100644 wx28X/samples/minimal/Minimal.icc create mode 100644 wx28X/samples/minimal/MinimalClassicM8.xml create mode 100644 wx28X/samples/minimal/MinimalM8.xml create mode 100644 wx28X/samples/minimal/descrip.mms create mode 100644 wx28X/samples/minimal/makefile.bcc create mode 100644 wx28X/samples/minimal/makefile.dmc create mode 100644 wx28X/samples/minimal/makefile.dms create mode 100644 wx28X/samples/minimal/makefile.gcc create mode 100644 wx28X/samples/minimal/makefile.mic create mode 100644 wx28X/samples/minimal/makefile.sl create mode 100644 wx28X/samples/minimal/makefile.unx create mode 100644 wx28X/samples/minimal/makefile.va create mode 100644 wx28X/samples/minimal/makefile.vc create mode 100644 wx28X/samples/minimal/makefile.wat create mode 100644 wx28X/samples/minimal/minimal.bkl create mode 100644 wx28X/samples/minimal/minimal.cpp create mode 100644 wx28X/samples/minimal/minimal.dsp create mode 100644 wx28X/samples/minimal/minimal.plc create mode 100644 wx28X/samples/minimal/minimal.pro create mode 100644 wx28X/samples/minimal/minimal.rc create mode 100644 wx28X/samples/minimal/minimal.rc4 create mode 100644 wx28X/samples/minimal/minimal.rcO create mode 100644 wx28X/samples/minimal/minimal.vcp create mode 100644 wx28X/samples/minimal/minimal.vcw create mode 100644 wx28X/samples/minimal/minimal.xcode/project.pbxproj create mode 100644 wx28X/samples/minimal/minimal.xcodeproj/project.pbxproj create mode 100644 wx28X/samples/minimal/minimalW7.xml create mode 100644 wx28X/samples/minimal/mondrian.icns create mode 100644 wx28X/samples/minimal/mondrian.r create mode 100644 wx28X/samples/minimal/mondros2.ico create mode 100644 wx28X/samples/mobile/Makefile.in create mode 100644 wx28X/samples/mobile/makefile.bcc create mode 100644 wx28X/samples/mobile/makefile.dmc create mode 100644 wx28X/samples/mobile/makefile.dms create mode 100644 wx28X/samples/mobile/makefile.gcc create mode 100644 wx28X/samples/mobile/makefile.unx create mode 100644 wx28X/samples/mobile/makefile.vc create mode 100644 wx28X/samples/mobile/makefile.wat create mode 100644 wx28X/samples/mobile/mobile_samples.bkl create mode 100644 wx28X/samples/mobile/styles/Makefile.in create mode 100644 wx28X/samples/mobile/styles/makefile.bcc create mode 100644 wx28X/samples/mobile/styles/makefile.dmc create mode 100644 wx28X/samples/mobile/styles/makefile.dms create mode 100644 wx28X/samples/mobile/styles/makefile.gcc create mode 100644 wx28X/samples/mobile/styles/makefile.unx create mode 100644 wx28X/samples/mobile/styles/makefile.vc create mode 100644 wx28X/samples/mobile/styles/makefile.wat create mode 100644 wx28X/samples/mobile/styles/marble.jpg create mode 100644 wx28X/samples/mobile/styles/styles.bkl create mode 100644 wx28X/samples/mobile/styles/styles.cpp create mode 100644 wx28X/samples/mobile/styles/styles.dsp create mode 100644 wx28X/samples/mobile/styles/styles.h create mode 100644 wx28X/samples/mobile/styles/styles.vcp create mode 100644 wx28X/samples/mobile/styles/styles.vcw create mode 100644 wx28X/samples/mobile/wxedit/Makefile.in create mode 100644 wx28X/samples/mobile/wxedit/makefile.bcc create mode 100644 wx28X/samples/mobile/wxedit/makefile.dmc create mode 100644 wx28X/samples/mobile/wxedit/makefile.dms create mode 100644 wx28X/samples/mobile/wxedit/makefile.gcc create mode 100644 wx28X/samples/mobile/wxedit/makefile.unx create mode 100644 wx28X/samples/mobile/wxedit/makefile.vc create mode 100644 wx28X/samples/mobile/wxedit/makefile.wat create mode 100644 wx28X/samples/mobile/wxedit/wxedit.bkl create mode 100644 wx28X/samples/mobile/wxedit/wxedit.cpp create mode 100644 wx28X/samples/mobile/wxedit/wxedit.dsp create mode 100644 wx28X/samples/mobile/wxedit/wxedit.h create mode 100644 wx28X/samples/mobile/wxedit/wxedit.vcp create mode 100644 wx28X/samples/mobile/wxedit/wxedit.vcw create mode 100644 wx28X/samples/multimon/Makefile.in create mode 100644 wx28X/samples/multimon/makefile.bcc create mode 100644 wx28X/samples/multimon/makefile.dmc create mode 100644 wx28X/samples/multimon/makefile.dms create mode 100644 wx28X/samples/multimon/makefile.gcc create mode 100644 wx28X/samples/multimon/makefile.unx create mode 100644 wx28X/samples/multimon/makefile.vc create mode 100644 wx28X/samples/multimon/makefile.wat create mode 100644 wx28X/samples/multimon/multimon.bkl create mode 100644 wx28X/samples/multimon/multimon.dsp create mode 100644 wx28X/samples/multimon/multimon.vcp create mode 100644 wx28X/samples/multimon/multimon.vcw create mode 100644 wx28X/samples/multimon/multimon_test.cpp create mode 100644 wx28X/samples/nativdlg/Makefile.in create mode 100644 wx28X/samples/nativdlg/dialog1.rc create mode 100644 wx28X/samples/nativdlg/makefile.bcc create mode 100644 wx28X/samples/nativdlg/makefile.dmc create mode 100644 wx28X/samples/nativdlg/makefile.dms create mode 100644 wx28X/samples/nativdlg/makefile.gcc create mode 100644 wx28X/samples/nativdlg/makefile.unx create mode 100644 wx28X/samples/nativdlg/makefile.vc create mode 100644 wx28X/samples/nativdlg/makefile.vms create mode 100644 wx28X/samples/nativdlg/makefile.wat create mode 100644 wx28X/samples/nativdlg/nativdlg.bkl create mode 100644 wx28X/samples/nativdlg/nativdlg.cpp create mode 100644 wx28X/samples/nativdlg/nativdlg.dsp create mode 100644 wx28X/samples/nativdlg/nativdlg.h create mode 100644 wx28X/samples/nativdlg/nativdlg.pro create mode 100644 wx28X/samples/nativdlg/nativdlg.rc create mode 100644 wx28X/samples/nativdlg/nativdlg.vcp create mode 100644 wx28X/samples/nativdlg/nativdlg.vcw create mode 100644 wx28X/samples/nativdlg/resource.h create mode 100644 wx28X/samples/notebook/Makefile.in create mode 100644 wx28X/samples/notebook/makefile.bcc create mode 100644 wx28X/samples/notebook/makefile.dmc create mode 100644 wx28X/samples/notebook/makefile.dms create mode 100644 wx28X/samples/notebook/makefile.gcc create mode 100644 wx28X/samples/notebook/makefile.sl create mode 100644 wx28X/samples/notebook/makefile.unx create mode 100644 wx28X/samples/notebook/makefile.va create mode 100644 wx28X/samples/notebook/makefile.vc create mode 100644 wx28X/samples/notebook/makefile.wat create mode 100644 wx28X/samples/notebook/mondrian.ico create mode 100644 wx28X/samples/notebook/mondros2.ico create mode 100644 wx28X/samples/notebook/notebook.bkl create mode 100644 wx28X/samples/notebook/notebook.cpp create mode 100644 wx28X/samples/notebook/notebook.dsp create mode 100644 wx28X/samples/notebook/notebook.h create mode 100644 wx28X/samples/notebook/notebook.pro create mode 100644 wx28X/samples/notebook/notebook.rcO create mode 100644 wx28X/samples/notebook/notebook.vcp create mode 100644 wx28X/samples/notebook/notebook.vcw create mode 100644 wx28X/samples/notebook/notebookM5.xml create mode 100644 wx28X/samples/oleauto/Makefile.in create mode 100644 wx28X/samples/oleauto/makefile.bcc create mode 100644 wx28X/samples/oleauto/makefile.dmc create mode 100644 wx28X/samples/oleauto/makefile.dms create mode 100644 wx28X/samples/oleauto/makefile.gcc create mode 100644 wx28X/samples/oleauto/makefile.unx create mode 100644 wx28X/samples/oleauto/makefile.vc create mode 100644 wx28X/samples/oleauto/makefile.wat create mode 100644 wx28X/samples/oleauto/mondrian.ico create mode 100644 wx28X/samples/oleauto/mondrian.xpm create mode 100644 wx28X/samples/oleauto/oleauto.bkl create mode 100644 wx28X/samples/oleauto/oleauto.cpp create mode 100644 wx28X/samples/oleauto/oleauto.dsp create mode 100644 wx28X/samples/oleauto/oleauto.pro create mode 100644 wx28X/samples/oleauto/oleauto.rc create mode 100644 wx28X/samples/oleauto/oleauto.vcp create mode 100644 wx28X/samples/oleauto/oleauto.vcw create mode 100644 wx28X/samples/opengl/Makefile.in create mode 100644 wx28X/samples/opengl/cube/Makefile.in create mode 100644 wx28X/samples/opengl/cube/cube.bkl create mode 100644 wx28X/samples/opengl/cube/cube.cpp create mode 100644 wx28X/samples/opengl/cube/cube.dsp create mode 100644 wx28X/samples/opengl/cube/cube.h create mode 100644 wx28X/samples/opengl/cube/cube.pro create mode 100644 wx28X/samples/opengl/cube/cube.rc create mode 100644 wx28X/samples/opengl/cube/cube.vcp create mode 100644 wx28X/samples/opengl/cube/cube.vcw create mode 100644 wx28X/samples/opengl/cube/makefile.bcc create mode 100644 wx28X/samples/opengl/cube/makefile.dmc create mode 100644 wx28X/samples/opengl/cube/makefile.dms create mode 100644 wx28X/samples/opengl/cube/makefile.gcc create mode 100644 wx28X/samples/opengl/cube/makefile.unx create mode 100644 wx28X/samples/opengl/cube/makefile.vc create mode 100644 wx28X/samples/opengl/cube/makefile.wat create mode 100644 wx28X/samples/opengl/cube/mondrian.ico create mode 100644 wx28X/samples/opengl/isosurf/Makefile.in create mode 100644 wx28X/samples/opengl/isosurf/isosurf.bkl create mode 100644 wx28X/samples/opengl/isosurf/isosurf.cpp create mode 100644 wx28X/samples/opengl/isosurf/isosurf.dat.gz create mode 100644 wx28X/samples/opengl/isosurf/isosurf.dsp create mode 100644 wx28X/samples/opengl/isosurf/isosurf.h create mode 100644 wx28X/samples/opengl/isosurf/isosurf.pro create mode 100644 wx28X/samples/opengl/isosurf/isosurf.vcp create mode 100644 wx28X/samples/opengl/isosurf/isosurf.vcw create mode 100644 wx28X/samples/opengl/isosurf/makefile.bcc create mode 100644 wx28X/samples/opengl/isosurf/makefile.dmc create mode 100644 wx28X/samples/opengl/isosurf/makefile.dms create mode 100644 wx28X/samples/opengl/isosurf/makefile.gcc create mode 100644 wx28X/samples/opengl/isosurf/makefile.unx create mode 100644 wx28X/samples/opengl/isosurf/makefile.vc create mode 100644 wx28X/samples/opengl/isosurf/makefile.wat create mode 100644 wx28X/samples/opengl/isosurf/mondrian.ico create mode 100644 wx28X/samples/opengl/makefile.bcc create mode 100644 wx28X/samples/opengl/makefile.dmc create mode 100644 wx28X/samples/opengl/makefile.dms create mode 100644 wx28X/samples/opengl/makefile.gcc create mode 100644 wx28X/samples/opengl/makefile.unx create mode 100644 wx28X/samples/opengl/makefile.vc create mode 100644 wx28X/samples/opengl/makefile.wat create mode 100644 wx28X/samples/opengl/opengl_samples.bkl create mode 100644 wx28X/samples/opengl/penguin/Makefile.in create mode 100644 wx28X/samples/opengl/penguin/dxfrenderer.cpp create mode 100644 wx28X/samples/opengl/penguin/dxfrenderer.h create mode 100644 wx28X/samples/opengl/penguin/makefile.bcc create mode 100644 wx28X/samples/opengl/penguin/makefile.dmc create mode 100644 wx28X/samples/opengl/penguin/makefile.dms create mode 100644 wx28X/samples/opengl/penguin/makefile.gcc create mode 100644 wx28X/samples/opengl/penguin/makefile.unx create mode 100644 wx28X/samples/opengl/penguin/makefile.vc create mode 100644 wx28X/samples/opengl/penguin/makefile.wat create mode 100644 wx28X/samples/opengl/penguin/penguin.bkl create mode 100644 wx28X/samples/opengl/penguin/penguin.cpp create mode 100644 wx28X/samples/opengl/penguin/penguin.dsp create mode 100644 wx28X/samples/opengl/penguin/penguin.dxf.gz create mode 100644 wx28X/samples/opengl/penguin/penguin.h create mode 100644 wx28X/samples/opengl/penguin/penguin.pro create mode 100644 wx28X/samples/opengl/penguin/penguin.rc create mode 100644 wx28X/samples/opengl/penguin/penguin.vcp create mode 100644 wx28X/samples/opengl/penguin/penguin.vcw create mode 100644 wx28X/samples/opengl/penguin/trackball.c create mode 100644 wx28X/samples/opengl/penguin/trackball.h create mode 100644 wx28X/samples/ownerdrw/Makefile.in create mode 100644 wx28X/samples/ownerdrw/bell.bmp create mode 100644 wx28X/samples/ownerdrw/info.bmp create mode 100644 wx28X/samples/ownerdrw/info_mono.bmp create mode 100644 wx28X/samples/ownerdrw/makefile.bcc create mode 100644 wx28X/samples/ownerdrw/makefile.dmc create mode 100644 wx28X/samples/ownerdrw/makefile.dms create mode 100644 wx28X/samples/ownerdrw/makefile.gcc create mode 100644 wx28X/samples/ownerdrw/makefile.unx create mode 100644 wx28X/samples/ownerdrw/makefile.vc create mode 100644 wx28X/samples/ownerdrw/makefile.wat create mode 100644 wx28X/samples/ownerdrw/mondrian.ico create mode 100644 wx28X/samples/ownerdrw/nosound.bmp create mode 100644 wx28X/samples/ownerdrw/nosound.png create mode 100644 wx28X/samples/ownerdrw/ownerdrw.bkl create mode 100644 wx28X/samples/ownerdrw/ownerdrw.cpp create mode 100644 wx28X/samples/ownerdrw/ownerdrw.dsp create mode 100644 wx28X/samples/ownerdrw/ownerdrw.pro create mode 100644 wx28X/samples/ownerdrw/ownerdrw.rc create mode 100644 wx28X/samples/ownerdrw/ownerdrw.vcp create mode 100644 wx28X/samples/ownerdrw/ownerdrw.vcw create mode 100644 wx28X/samples/ownerdrw/sound.bmp create mode 100644 wx28X/samples/ownerdrw/sound.png create mode 100644 wx28X/samples/png/Makefile.in create mode 100644 wx28X/samples/png/julian.png create mode 100644 wx28X/samples/png/makefile.bcc create mode 100644 wx28X/samples/png/makefile.dmc create mode 100644 wx28X/samples/png/makefile.dms create mode 100644 wx28X/samples/png/makefile.gcc create mode 100644 wx28X/samples/png/makefile.unx create mode 100644 wx28X/samples/png/makefile.vc create mode 100644 wx28X/samples/png/makefile.wat create mode 100644 wx28X/samples/png/png.bkl create mode 100644 wx28X/samples/png/png.dsp create mode 100644 wx28X/samples/png/png.pro create mode 100644 wx28X/samples/png/png.vcp create mode 100644 wx28X/samples/png/png.vcw create mode 100644 wx28X/samples/png/pngM5.xml create mode 100644 wx28X/samples/png/pngdemo.cpp create mode 100644 wx28X/samples/png/pngdemo.h create mode 100644 wx28X/samples/png/pngdemo.rc create mode 100644 wx28X/samples/popup/Makefile.in create mode 100644 wx28X/samples/popup/makefile.bcc create mode 100644 wx28X/samples/popup/makefile.dmc create mode 100644 wx28X/samples/popup/makefile.dms create mode 100644 wx28X/samples/popup/makefile.gcc create mode 100644 wx28X/samples/popup/makefile.unx create mode 100644 wx28X/samples/popup/makefile.vc create mode 100644 wx28X/samples/popup/makefile.wat create mode 100644 wx28X/samples/popup/popup.bkl create mode 100644 wx28X/samples/popup/popup.cpp create mode 100644 wx28X/samples/popup/popup.dsp create mode 100644 wx28X/samples/popup/popup.vcp create mode 100644 wx28X/samples/popup/popup.vcw create mode 100644 wx28X/samples/power/Makefile.in create mode 100644 wx28X/samples/power/makefile.bcc create mode 100644 wx28X/samples/power/makefile.dmc create mode 100644 wx28X/samples/power/makefile.dms create mode 100644 wx28X/samples/power/makefile.gcc create mode 100644 wx28X/samples/power/makefile.unx create mode 100644 wx28X/samples/power/makefile.vc create mode 100644 wx28X/samples/power/makefile.wat create mode 100644 wx28X/samples/power/power.bkl create mode 100644 wx28X/samples/power/power.cpp create mode 100644 wx28X/samples/power/power.dsp create mode 100644 wx28X/samples/power/power.vcp create mode 100644 wx28X/samples/power/power.vcw create mode 100644 wx28X/samples/printing/Makefile.in create mode 100644 wx28X/samples/printing/folder.xpm create mode 100644 wx28X/samples/printing/makefile.bcc create mode 100644 wx28X/samples/printing/makefile.dmc create mode 100644 wx28X/samples/printing/makefile.dms create mode 100644 wx28X/samples/printing/makefile.gcc create mode 100644 wx28X/samples/printing/makefile.unx create mode 100644 wx28X/samples/printing/makefile.vc create mode 100644 wx28X/samples/printing/makefile.wat create mode 100644 wx28X/samples/printing/mondrian.ico create mode 100644 wx28X/samples/printing/mondrian.xpm create mode 100644 wx28X/samples/printing/printing.bkl create mode 100644 wx28X/samples/printing/printing.cpp create mode 100644 wx28X/samples/printing/printing.dsp create mode 100644 wx28X/samples/printing/printing.h create mode 100644 wx28X/samples/printing/printing.pro create mode 100644 wx28X/samples/printing/printing.rc create mode 100644 wx28X/samples/printing/printing.vcp create mode 100644 wx28X/samples/printing/printing.vcw create mode 100644 wx28X/samples/printing/printingM5.xml create mode 100644 wx28X/samples/propsize/Makefile.in create mode 100644 wx28X/samples/propsize/makefile.bcc create mode 100644 wx28X/samples/propsize/makefile.dmc create mode 100644 wx28X/samples/propsize/makefile.dms create mode 100644 wx28X/samples/propsize/makefile.gcc create mode 100644 wx28X/samples/propsize/makefile.sl create mode 100644 wx28X/samples/propsize/makefile.unx create mode 100644 wx28X/samples/propsize/makefile.vc create mode 100644 wx28X/samples/propsize/makefile.wat create mode 100644 wx28X/samples/propsize/mondrian.ico create mode 100644 wx28X/samples/propsize/mondrian.xpm create mode 100644 wx28X/samples/propsize/propsize.bkl create mode 100644 wx28X/samples/propsize/propsize.cpp create mode 100644 wx28X/samples/propsize/propsize.dsp create mode 100644 wx28X/samples/propsize/propsize.pro create mode 100644 wx28X/samples/propsize/propsize.rc create mode 100644 wx28X/samples/propsize/propsize.vcp create mode 100644 wx28X/samples/propsize/propsize.vcw create mode 100644 wx28X/samples/propsize/propsizeM5.xml create mode 100644 wx28X/samples/regtest/Makefile.in create mode 100644 wx28X/samples/regtest/key1.ico create mode 100644 wx28X/samples/regtest/key2.ico create mode 100644 wx28X/samples/regtest/key3.ico create mode 100644 wx28X/samples/regtest/makefile.bcc create mode 100644 wx28X/samples/regtest/makefile.dmc create mode 100644 wx28X/samples/regtest/makefile.dms create mode 100644 wx28X/samples/regtest/makefile.gcc create mode 100644 wx28X/samples/regtest/makefile.unx create mode 100644 wx28X/samples/regtest/makefile.vc create mode 100644 wx28X/samples/regtest/makefile.wat create mode 100644 wx28X/samples/regtest/registry.ico create mode 100644 wx28X/samples/regtest/regtest.bkl create mode 100644 wx28X/samples/regtest/regtest.cpp create mode 100644 wx28X/samples/regtest/regtest.dsp create mode 100644 wx28X/samples/regtest/regtest.pro create mode 100644 wx28X/samples/regtest/regtest.rc create mode 100644 wx28X/samples/regtest/regtest.vcp create mode 100644 wx28X/samples/regtest/regtest.vcw create mode 100644 wx28X/samples/regtest/regtestM5.xml create mode 100644 wx28X/samples/regtest/value1.ico create mode 100644 wx28X/samples/regtest/value2.ico create mode 100644 wx28X/samples/render/Makefile.in create mode 100644 wx28X/samples/render/makefile.bcc create mode 100644 wx28X/samples/render/makefile.dmc create mode 100644 wx28X/samples/render/makefile.dms create mode 100644 wx28X/samples/render/makefile.gcc create mode 100644 wx28X/samples/render/makefile.unx create mode 100644 wx28X/samples/render/makefile.vc create mode 100644 wx28X/samples/render/makefile.wat create mode 100644 wx28X/samples/render/renddll.cpp create mode 100644 wx28X/samples/render/render.bkl create mode 100644 wx28X/samples/render/render.cpp create mode 100644 wx28X/samples/render/render.vcw create mode 100644 wx28X/samples/render/render_renddll.dsp create mode 100644 wx28X/samples/render/render_renddll.vcp create mode 100644 wx28X/samples/render/render_render.dsp create mode 100644 wx28X/samples/render/render_render.vcp create mode 100644 wx28X/samples/richtext/Makefile.in create mode 100644 wx28X/samples/richtext/bitmaps/alignleft.xpm create mode 100644 wx28X/samples/richtext/bitmaps/alignright.xpm create mode 100644 wx28X/samples/richtext/bitmaps/bold.xpm create mode 100644 wx28X/samples/richtext/bitmaps/centre.xpm create mode 100644 wx28X/samples/richtext/bitmaps/copy.xpm create mode 100644 wx28X/samples/richtext/bitmaps/cut.xpm create mode 100644 wx28X/samples/richtext/bitmaps/font.xpm create mode 100644 wx28X/samples/richtext/bitmaps/idea.xpm create mode 100644 wx28X/samples/richtext/bitmaps/indentless.xpm create mode 100644 wx28X/samples/richtext/bitmaps/indentmore.xpm create mode 100644 wx28X/samples/richtext/bitmaps/italic.xpm create mode 100644 wx28X/samples/richtext/bitmaps/open.xpm create mode 100644 wx28X/samples/richtext/bitmaps/paste.xpm create mode 100644 wx28X/samples/richtext/bitmaps/redo.xpm create mode 100644 wx28X/samples/richtext/bitmaps/save.xpm create mode 100644 wx28X/samples/richtext/bitmaps/smiley.xpm create mode 100644 wx28X/samples/richtext/bitmaps/underline.xpm create mode 100644 wx28X/samples/richtext/bitmaps/undo.xpm create mode 100644 wx28X/samples/richtext/bitmaps/zebra.xpm create mode 100644 wx28X/samples/richtext/makefile.bcc create mode 100644 wx28X/samples/richtext/makefile.dmc create mode 100644 wx28X/samples/richtext/makefile.dms create mode 100644 wx28X/samples/richtext/makefile.gcc create mode 100644 wx28X/samples/richtext/makefile.unx create mode 100644 wx28X/samples/richtext/makefile.vc create mode 100644 wx28X/samples/richtext/makefile.wat create mode 100644 wx28X/samples/richtext/readme.txt create mode 100644 wx28X/samples/richtext/richtext.bkl create mode 100644 wx28X/samples/richtext/richtext.cpp create mode 100644 wx28X/samples/richtext/richtext.dsp create mode 100644 wx28X/samples/richtext/richtext.vcp create mode 100644 wx28X/samples/richtext/richtext.vcw create mode 100644 wx28X/samples/richtext/todo.txt create mode 100644 wx28X/samples/rotate/Makefile.in create mode 100644 wx28X/samples/rotate/duck.png create mode 100644 wx28X/samples/rotate/makefile.bcc create mode 100644 wx28X/samples/rotate/makefile.dmc create mode 100644 wx28X/samples/rotate/makefile.dms create mode 100644 wx28X/samples/rotate/makefile.gcc create mode 100644 wx28X/samples/rotate/makefile.unx create mode 100644 wx28X/samples/rotate/makefile.vc create mode 100644 wx28X/samples/rotate/makefile.wat create mode 100644 wx28X/samples/rotate/mondrian.ico create mode 100644 wx28X/samples/rotate/rotate.bkl create mode 100644 wx28X/samples/rotate/rotate.cpp create mode 100644 wx28X/samples/rotate/rotate.dsp create mode 100644 wx28X/samples/rotate/rotate.pro create mode 100644 wx28X/samples/rotate/rotate.rc create mode 100644 wx28X/samples/rotate/rotate.vcp create mode 100644 wx28X/samples/rotate/rotate.vcw create mode 100644 wx28X/samples/rotate/rotateM5.xml create mode 100644 wx28X/samples/sample.ico create mode 100644 wx28X/samples/sample.r create mode 100644 wx28X/samples/sample.rc create mode 100644 wx28X/samples/sample.xpm create mode 100644 wx28X/samples/samples.bkl create mode 100644 wx28X/samples/samples.dsw create mode 100644 wx28X/samples/sashtest/Makefile.in create mode 100644 wx28X/samples/sashtest/makefile.bcc create mode 100644 wx28X/samples/sashtest/makefile.dmc create mode 100644 wx28X/samples/sashtest/makefile.dms create mode 100644 wx28X/samples/sashtest/makefile.gcc create mode 100644 wx28X/samples/sashtest/makefile.sl create mode 100644 wx28X/samples/sashtest/makefile.unx create mode 100644 wx28X/samples/sashtest/makefile.vc create mode 100644 wx28X/samples/sashtest/makefile.wat create mode 100644 wx28X/samples/sashtest/sashtest.bkl create mode 100644 wx28X/samples/sashtest/sashtest.cpp create mode 100644 wx28X/samples/sashtest/sashtest.dsp create mode 100644 wx28X/samples/sashtest/sashtest.h create mode 100644 wx28X/samples/sashtest/sashtest.ico create mode 100644 wx28X/samples/sashtest/sashtest.pro create mode 100644 wx28X/samples/sashtest/sashtest.rc create mode 100644 wx28X/samples/sashtest/sashtest.vcp create mode 100644 wx28X/samples/sashtest/sashtest.vcw create mode 100644 wx28X/samples/sashtest/sashtestM5.xml create mode 100644 wx28X/samples/scroll/Makefile.in create mode 100644 wx28X/samples/scroll/makefile.bcc create mode 100644 wx28X/samples/scroll/makefile.dmc create mode 100644 wx28X/samples/scroll/makefile.dms create mode 100644 wx28X/samples/scroll/makefile.gcc create mode 100644 wx28X/samples/scroll/makefile.unx create mode 100644 wx28X/samples/scroll/makefile.va create mode 100644 wx28X/samples/scroll/makefile.vc create mode 100644 wx28X/samples/scroll/makefile.wat create mode 100644 wx28X/samples/scroll/mondros2.ico create mode 100644 wx28X/samples/scroll/scroll.bkl create mode 100644 wx28X/samples/scroll/scroll.cpp create mode 100644 wx28X/samples/scroll/scroll.dsp create mode 100644 wx28X/samples/scroll/scroll.pro create mode 100644 wx28X/samples/scroll/scroll.rc create mode 100644 wx28X/samples/scroll/scroll.vcp create mode 100644 wx28X/samples/scroll/scroll.vcw create mode 100644 wx28X/samples/scroll/scrollM5.xml create mode 100644 wx28X/samples/scrollsub/Makefile.in create mode 100644 wx28X/samples/scrollsub/makefile.bcc create mode 100644 wx28X/samples/scrollsub/makefile.dmc create mode 100644 wx28X/samples/scrollsub/makefile.dms create mode 100644 wx28X/samples/scrollsub/makefile.gcc create mode 100644 wx28X/samples/scrollsub/makefile.unx create mode 100644 wx28X/samples/scrollsub/makefile.vc create mode 100644 wx28X/samples/scrollsub/makefile.wat create mode 100644 wx28X/samples/scrollsub/scrollsub.bkl create mode 100644 wx28X/samples/scrollsub/scrollsub.cpp create mode 100644 wx28X/samples/scrollsub/scrollsub.dsp create mode 100644 wx28X/samples/scrollsub/scrollsub.pro create mode 100644 wx28X/samples/scrollsub/scrollsub.rc create mode 100644 wx28X/samples/scrollsub/scrollsub.vcp create mode 100644 wx28X/samples/scrollsub/scrollsub.vcw create mode 100644 wx28X/samples/scrollsub/scrollsubM5.xml create mode 100644 wx28X/samples/shaped/Makefile.in create mode 100644 wx28X/samples/shaped/descrip.mms create mode 100644 wx28X/samples/shaped/makefile.bcc create mode 100644 wx28X/samples/shaped/makefile.dmc create mode 100644 wx28X/samples/shaped/makefile.dms create mode 100644 wx28X/samples/shaped/makefile.gcc create mode 100644 wx28X/samples/shaped/makefile.sl create mode 100644 wx28X/samples/shaped/makefile.unx create mode 100644 wx28X/samples/shaped/makefile.vc create mode 100644 wx28X/samples/shaped/makefile.wat create mode 100644 wx28X/samples/shaped/shaped.bkl create mode 100644 wx28X/samples/shaped/shaped.cpp create mode 100644 wx28X/samples/shaped/shaped.dsp create mode 100644 wx28X/samples/shaped/shaped.rc create mode 100644 wx28X/samples/shaped/shaped.vcp create mode 100644 wx28X/samples/shaped/shaped.vcw create mode 100644 wx28X/samples/shaped/shapedM5.xml create mode 100644 wx28X/samples/shaped/star.png create mode 100644 wx28X/samples/sockets/Makefile.in create mode 100644 wx28X/samples/sockets/client.b32 create mode 100644 wx28X/samples/sockets/client.cpp create mode 100644 wx28X/samples/sockets/client.g95 create mode 100644 wx28X/samples/sockets/client.pro create mode 100644 wx28X/samples/sockets/client.rc create mode 100644 wx28X/samples/sockets/client.vc create mode 100644 wx28X/samples/sockets/client.wat create mode 100644 wx28X/samples/sockets/connect.ico create mode 100644 wx28X/samples/sockets/makefile.bcc create mode 100644 wx28X/samples/sockets/makefile.dmc create mode 100644 wx28X/samples/sockets/makefile.dms create mode 100644 wx28X/samples/sockets/makefile.gcc create mode 100644 wx28X/samples/sockets/makefile.unx create mode 100644 wx28X/samples/sockets/makefile.vc create mode 100644 wx28X/samples/sockets/makefile.wat create mode 100644 wx28X/samples/sockets/mondrian.ico create mode 100644 wx28X/samples/sockets/mondrian.xpm create mode 100644 wx28X/samples/sockets/server.b32 create mode 100644 wx28X/samples/sockets/server.cpp create mode 100644 wx28X/samples/sockets/server.g95 create mode 100644 wx28X/samples/sockets/server.pro create mode 100644 wx28X/samples/sockets/server.rc create mode 100644 wx28X/samples/sockets/server.vc create mode 100644 wx28X/samples/sockets/server.wat create mode 100644 wx28X/samples/sockets/sockets.bkl create mode 100644 wx28X/samples/sockets/sockets.vcw create mode 100644 wx28X/samples/sockets/sockets_client.dsp create mode 100644 wx28X/samples/sockets/sockets_client.vcp create mode 100644 wx28X/samples/sockets/sockets_server.dsp create mode 100644 wx28X/samples/sockets/sockets_server.vcp create mode 100644 wx28X/samples/sound/9000g.wav create mode 100644 wx28X/samples/sound/Makefile.in create mode 100644 wx28X/samples/sound/cuckoo.wav create mode 100644 wx28X/samples/sound/doggrowl.wav create mode 100644 wx28X/samples/sound/makefile.bcc create mode 100644 wx28X/samples/sound/makefile.dmc create mode 100644 wx28X/samples/sound/makefile.dms create mode 100644 wx28X/samples/sound/makefile.gcc create mode 100644 wx28X/samples/sound/makefile.unx create mode 100644 wx28X/samples/sound/makefile.vc create mode 100644 wx28X/samples/sound/makefile.wat create mode 100644 wx28X/samples/sound/sound.bkl create mode 100644 wx28X/samples/sound/sound.cpp create mode 100644 wx28X/samples/sound/sound.dsp create mode 100644 wx28X/samples/sound/sound.rc create mode 100644 wx28X/samples/sound/sound.vcp create mode 100644 wx28X/samples/sound/sound.vcw create mode 100644 wx28X/samples/sound/tinkalink2.wav create mode 100644 wx28X/samples/splash/Makefile.in create mode 100644 wx28X/samples/splash/makefile.bcc create mode 100644 wx28X/samples/splash/makefile.dmc create mode 100644 wx28X/samples/splash/makefile.dms create mode 100644 wx28X/samples/splash/makefile.gcc create mode 100644 wx28X/samples/splash/makefile.unx create mode 100644 wx28X/samples/splash/makefile.vc create mode 100644 wx28X/samples/splash/makefile.wat create mode 100644 wx28X/samples/splash/mobile.xpm create mode 100644 wx28X/samples/splash/press.mpg create mode 100644 wx28X/samples/splash/press.pov create mode 100644 wx28X/samples/splash/splash.bkl create mode 100644 wx28X/samples/splash/splash.cpp create mode 100644 wx28X/samples/splash/splash.dsp create mode 100644 wx28X/samples/splash/splash.png create mode 100644 wx28X/samples/splash/splash.pov create mode 100644 wx28X/samples/splash/splash.vcp create mode 100644 wx28X/samples/splash/splash.vcw create mode 100644 wx28X/samples/splitter/Makefile.in create mode 100644 wx28X/samples/splitter/makefile.bcc create mode 100644 wx28X/samples/splitter/makefile.dmc create mode 100644 wx28X/samples/splitter/makefile.dms create mode 100644 wx28X/samples/splitter/makefile.gcc create mode 100644 wx28X/samples/splitter/makefile.sl create mode 100644 wx28X/samples/splitter/makefile.unx create mode 100644 wx28X/samples/splitter/makefile.vc create mode 100644 wx28X/samples/splitter/makefile.wat create mode 100644 wx28X/samples/splitter/mondrian.ico create mode 100644 wx28X/samples/splitter/splitter.bkl create mode 100644 wx28X/samples/splitter/splitter.cpp create mode 100644 wx28X/samples/splitter/splitter.dsp create mode 100644 wx28X/samples/splitter/splitter.pro create mode 100644 wx28X/samples/splitter/splitter.rc create mode 100644 wx28X/samples/splitter/splitter.vcp create mode 100644 wx28X/samples/splitter/splitter.vcw create mode 100644 wx28X/samples/splitter/splitterM5.xml create mode 100644 wx28X/samples/statbar/Makefile.in create mode 100644 wx28X/samples/statbar/green.xpm create mode 100644 wx28X/samples/statbar/makefile.bcc create mode 100644 wx28X/samples/statbar/makefile.dmc create mode 100644 wx28X/samples/statbar/makefile.dms create mode 100644 wx28X/samples/statbar/makefile.gcc create mode 100644 wx28X/samples/statbar/makefile.sl create mode 100644 wx28X/samples/statbar/makefile.unx create mode 100644 wx28X/samples/statbar/makefile.vc create mode 100644 wx28X/samples/statbar/makefile.wat create mode 100644 wx28X/samples/statbar/red.xpm create mode 100644 wx28X/samples/statbar/statbar.bkl create mode 100644 wx28X/samples/statbar/statbar.cpp create mode 100644 wx28X/samples/statbar/statbar.dsp create mode 100644 wx28X/samples/statbar/statbar.pro create mode 100644 wx28X/samples/statbar/statbar.rc create mode 100644 wx28X/samples/statbar/statbar.vcp create mode 100644 wx28X/samples/statbar/statbar.vcw create mode 100644 wx28X/samples/statbar/statbarM5.xml create mode 100644 wx28X/samples/taskbar/Makefile.in create mode 100644 wx28X/samples/taskbar/makefile.bcc create mode 100644 wx28X/samples/taskbar/makefile.dmc create mode 100644 wx28X/samples/taskbar/makefile.dms create mode 100644 wx28X/samples/taskbar/makefile.gcc create mode 100644 wx28X/samples/taskbar/makefile.unx create mode 100644 wx28X/samples/taskbar/makefile.vc create mode 100644 wx28X/samples/taskbar/makefile.wat create mode 100644 wx28X/samples/taskbar/smile.xpm create mode 100644 wx28X/samples/taskbar/taskbar.bkl create mode 100644 wx28X/samples/taskbar/taskbar.dsp create mode 100644 wx28X/samples/taskbar/taskbar.pro create mode 100644 wx28X/samples/taskbar/taskbar.vcp create mode 100644 wx28X/samples/taskbar/taskbar.vcw create mode 100644 wx28X/samples/taskbar/taskbarM5.xml create mode 100644 wx28X/samples/taskbar/tbtest.cpp create mode 100644 wx28X/samples/taskbar/tbtest.h create mode 100644 wx28X/samples/text/Makefile.in create mode 100644 wx28X/samples/text/makefile.bcc create mode 100644 wx28X/samples/text/makefile.dmc create mode 100644 wx28X/samples/text/makefile.dms create mode 100644 wx28X/samples/text/makefile.gcc create mode 100644 wx28X/samples/text/makefile.unx create mode 100644 wx28X/samples/text/makefile.vc create mode 100644 wx28X/samples/text/makefile.wat create mode 100644 wx28X/samples/text/mondrian.ico create mode 100644 wx28X/samples/text/mondrian.xpm create mode 100644 wx28X/samples/text/text.bkl create mode 100644 wx28X/samples/text/text.cpp create mode 100644 wx28X/samples/text/text.dsp create mode 100644 wx28X/samples/text/text.pro create mode 100644 wx28X/samples/text/text.rc create mode 100644 wx28X/samples/text/text.vcp create mode 100644 wx28X/samples/text/text.vcw create mode 100644 wx28X/samples/text/textM5.xml create mode 100644 wx28X/samples/thread/Makefile.in create mode 100644 wx28X/samples/thread/makefile.bcc create mode 100644 wx28X/samples/thread/makefile.dmc create mode 100644 wx28X/samples/thread/makefile.dms create mode 100644 wx28X/samples/thread/makefile.gcc create mode 100644 wx28X/samples/thread/makefile.sl create mode 100644 wx28X/samples/thread/makefile.unx create mode 100644 wx28X/samples/thread/makefile.vc create mode 100644 wx28X/samples/thread/makefile.wat create mode 100644 wx28X/samples/thread/thread.bkl create mode 100644 wx28X/samples/thread/thread.cpp create mode 100644 wx28X/samples/thread/thread.dsp create mode 100644 wx28X/samples/thread/thread.pro create mode 100644 wx28X/samples/thread/thread.rc create mode 100644 wx28X/samples/thread/thread.vcp create mode 100644 wx28X/samples/thread/thread.vcw create mode 100644 wx28X/samples/thread/threadM5.xml create mode 100644 wx28X/samples/toolbar/Makefile.in create mode 100644 wx28X/samples/toolbar/bitmaps/copy.bmp create mode 100644 wx28X/samples/toolbar/bitmaps/copy.xpm create mode 100644 wx28X/samples/toolbar/bitmaps/cut.bmp create mode 100644 wx28X/samples/toolbar/bitmaps/cut.xpm create mode 100644 wx28X/samples/toolbar/bitmaps/help.bmp create mode 100644 wx28X/samples/toolbar/bitmaps/help.xpm create mode 100644 wx28X/samples/toolbar/bitmaps/new.bmp create mode 100644 wx28X/samples/toolbar/bitmaps/new.xpm create mode 100644 wx28X/samples/toolbar/bitmaps/open.bmp create mode 100644 wx28X/samples/toolbar/bitmaps/open.xpm create mode 100644 wx28X/samples/toolbar/bitmaps/page.bmp create mode 100644 wx28X/samples/toolbar/bitmaps/paste.bmp create mode 100644 wx28X/samples/toolbar/bitmaps/preview.bmp create mode 100644 wx28X/samples/toolbar/bitmaps/preview.xpm create mode 100644 wx28X/samples/toolbar/bitmaps/print.bmp create mode 100644 wx28X/samples/toolbar/bitmaps/print.xpm create mode 100644 wx28X/samples/toolbar/bitmaps/save.bmp create mode 100644 wx28X/samples/toolbar/bitmaps/save.xpm create mode 100644 wx28X/samples/toolbar/makefile.bcc create mode 100644 wx28X/samples/toolbar/makefile.dmc create mode 100644 wx28X/samples/toolbar/makefile.dms create mode 100644 wx28X/samples/toolbar/makefile.gcc create mode 100644 wx28X/samples/toolbar/makefile.sl create mode 100644 wx28X/samples/toolbar/makefile.unx create mode 100644 wx28X/samples/toolbar/makefile.va create mode 100644 wx28X/samples/toolbar/makefile.vc create mode 100644 wx28X/samples/toolbar/makefile.wat create mode 100644 wx28X/samples/toolbar/mondrian.ico create mode 100644 wx28X/samples/toolbar/mondrian.xpm create mode 100644 wx28X/samples/toolbar/mondros2.ico create mode 100644 wx28X/samples/toolbar/toolbar.bkl create mode 100644 wx28X/samples/toolbar/toolbar.cpp create mode 100644 wx28X/samples/toolbar/toolbar.dsp create mode 100644 wx28X/samples/toolbar/toolbar.pro create mode 100644 wx28X/samples/toolbar/toolbar.rc create mode 100644 wx28X/samples/toolbar/toolbar.rco create mode 100644 wx28X/samples/toolbar/toolbar.vcp create mode 100644 wx28X/samples/toolbar/toolbar.vcw create mode 100644 wx28X/samples/toolbar/toolbarM5.xml create mode 100644 wx28X/samples/treectrl/Makefile.in create mode 100644 wx28X/samples/treectrl/icon1.xpm create mode 100644 wx28X/samples/treectrl/icon2.xpm create mode 100644 wx28X/samples/treectrl/icon3.xpm create mode 100644 wx28X/samples/treectrl/icon4.xpm create mode 100644 wx28X/samples/treectrl/icon5.xpm create mode 100644 wx28X/samples/treectrl/makefile.bcc create mode 100644 wx28X/samples/treectrl/makefile.dmc create mode 100644 wx28X/samples/treectrl/makefile.dms create mode 100644 wx28X/samples/treectrl/makefile.gcc create mode 100644 wx28X/samples/treectrl/makefile.unx create mode 100644 wx28X/samples/treectrl/makefile.vc create mode 100644 wx28X/samples/treectrl/makefile.wat create mode 100644 wx28X/samples/treectrl/treectrl.bkl create mode 100644 wx28X/samples/treectrl/treectrl.dsp create mode 100644 wx28X/samples/treectrl/treectrl.vcp create mode 100644 wx28X/samples/treectrl/treectrl.vcw create mode 100644 wx28X/samples/treectrl/treetest.cpp create mode 100644 wx28X/samples/treectrl/treetest.h create mode 100644 wx28X/samples/treectrl/treetestM5.xml create mode 100644 wx28X/samples/typetest/Makefile.in create mode 100644 wx28X/samples/typetest/makefile.bcc create mode 100644 wx28X/samples/typetest/makefile.dmc create mode 100644 wx28X/samples/typetest/makefile.dms create mode 100644 wx28X/samples/typetest/makefile.gcc create mode 100644 wx28X/samples/typetest/makefile.sl create mode 100644 wx28X/samples/typetest/makefile.unx create mode 100644 wx28X/samples/typetest/makefile.vc create mode 100644 wx28X/samples/typetest/makefile.wat create mode 100644 wx28X/samples/typetest/mondrian.ico create mode 100644 wx28X/samples/typetest/mondrian.xpm create mode 100644 wx28X/samples/typetest/typetest.bkl create mode 100644 wx28X/samples/typetest/typetest.cpp create mode 100644 wx28X/samples/typetest/typetest.dsp create mode 100644 wx28X/samples/typetest/typetest.h create mode 100644 wx28X/samples/typetest/typetest.pro create mode 100644 wx28X/samples/typetest/typetest.rc create mode 100644 wx28X/samples/typetest/typetest.vcp create mode 100644 wx28X/samples/typetest/typetest.vcw create mode 100644 wx28X/samples/typetest/typetestM5.xml create mode 100644 wx28X/samples/validate/Makefile.in create mode 100644 wx28X/samples/validate/makefile.bcc create mode 100644 wx28X/samples/validate/makefile.dmc create mode 100644 wx28X/samples/validate/makefile.dms create mode 100644 wx28X/samples/validate/makefile.gcc create mode 100644 wx28X/samples/validate/makefile.unx create mode 100644 wx28X/samples/validate/makefile.vc create mode 100644 wx28X/samples/validate/makefile.wat create mode 100644 wx28X/samples/validate/validate.bkl create mode 100644 wx28X/samples/validate/validate.cpp create mode 100644 wx28X/samples/validate/validate.dsp create mode 100644 wx28X/samples/validate/validate.h create mode 100644 wx28X/samples/validate/validate.vcp create mode 100644 wx28X/samples/validate/validate.vcw create mode 100644 wx28X/samples/validate/validateM5.xml create mode 100644 wx28X/samples/vscroll/Makefile.in create mode 100644 wx28X/samples/vscroll/makefile.bcc create mode 100644 wx28X/samples/vscroll/makefile.dmc create mode 100644 wx28X/samples/vscroll/makefile.dms create mode 100644 wx28X/samples/vscroll/makefile.gcc create mode 100644 wx28X/samples/vscroll/makefile.unx create mode 100644 wx28X/samples/vscroll/makefile.vc create mode 100644 wx28X/samples/vscroll/makefile.wat create mode 100644 wx28X/samples/vscroll/vscroll.bkl create mode 100644 wx28X/samples/vscroll/vscroll.dsp create mode 100644 wx28X/samples/vscroll/vscroll.vcp create mode 100644 wx28X/samples/vscroll/vscroll.vcw create mode 100644 wx28X/samples/vscroll/vstest.cpp create mode 100644 wx28X/samples/widgets/Makefile.in create mode 100644 wx28X/samples/widgets/bmpcombobox.cpp create mode 100644 wx28X/samples/widgets/button.cpp create mode 100644 wx28X/samples/widgets/checkbox.cpp create mode 100644 wx28X/samples/widgets/clrpicker.cpp create mode 100644 wx28X/samples/widgets/combobox.cpp create mode 100644 wx28X/samples/widgets/datepick.cpp create mode 100644 wx28X/samples/widgets/dirctrl.cpp create mode 100644 wx28X/samples/widgets/dirpicker.cpp create mode 100644 wx28X/samples/widgets/filepicker.cpp create mode 100644 wx28X/samples/widgets/fontpicker.cpp create mode 100644 wx28X/samples/widgets/gauge.cpp create mode 100644 wx28X/samples/widgets/hyperlnk.cpp create mode 100644 wx28X/samples/widgets/icons/bmpbtn.xpm create mode 100644 wx28X/samples/widgets/icons/bmpcombobox.xpm create mode 100644 wx28X/samples/widgets/icons/button.xpm create mode 100644 wx28X/samples/widgets/icons/checkbox.xpm create mode 100644 wx28X/samples/widgets/icons/choicebk.xpm create mode 100644 wx28X/samples/widgets/icons/clrpicker.xpm create mode 100644 wx28X/samples/widgets/icons/combobox.xpm create mode 100644 wx28X/samples/widgets/icons/datepick.xpm create mode 100644 wx28X/samples/widgets/icons/dirctrl.xpm create mode 100644 wx28X/samples/widgets/icons/dirpicker.xpm create mode 100644 wx28X/samples/widgets/icons/filepicker.xpm create mode 100644 wx28X/samples/widgets/icons/fontpicker.xpm create mode 100644 wx28X/samples/widgets/icons/gauge.xpm create mode 100644 wx28X/samples/widgets/icons/hyperlnk.xpm create mode 100644 wx28X/samples/widgets/icons/listbook.xpm create mode 100644 wx28X/samples/widgets/icons/listbox.xpm create mode 100644 wx28X/samples/widgets/icons/notebook.xpm create mode 100644 wx28X/samples/widgets/icons/odcombobox.xpm create mode 100644 wx28X/samples/widgets/icons/radiobox.xpm create mode 100644 wx28X/samples/widgets/icons/scrolbar.xpm create mode 100644 wx28X/samples/widgets/icons/slider.xpm create mode 100644 wx28X/samples/widgets/icons/spinbtn.xpm create mode 100644 wx28X/samples/widgets/icons/statbox.xpm create mode 100644 wx28X/samples/widgets/icons/stattext.xpm create mode 100644 wx28X/samples/widgets/icons/text.xpm create mode 100644 wx28X/samples/widgets/icons/toggle.xpm create mode 100644 wx28X/samples/widgets/listbox.cpp create mode 100644 wx28X/samples/widgets/makefile.bcc create mode 100644 wx28X/samples/widgets/makefile.dmc create mode 100644 wx28X/samples/widgets/makefile.dms create mode 100644 wx28X/samples/widgets/makefile.gcc create mode 100644 wx28X/samples/widgets/makefile.mic create mode 100644 wx28X/samples/widgets/makefile.unx create mode 100644 wx28X/samples/widgets/makefile.vc create mode 100644 wx28X/samples/widgets/makefile.wat create mode 100644 wx28X/samples/widgets/notebook.cpp create mode 100644 wx28X/samples/widgets/odcombobox.cpp create mode 100644 wx28X/samples/widgets/radiobox.cpp create mode 100644 wx28X/samples/widgets/searchctrl.cpp create mode 100644 wx28X/samples/widgets/slider.cpp create mode 100644 wx28X/samples/widgets/spinbtn.cpp create mode 100644 wx28X/samples/widgets/static.cpp create mode 100644 wx28X/samples/widgets/textctrl.cpp create mode 100644 wx28X/samples/widgets/toggle.cpp create mode 100644 wx28X/samples/widgets/widgets.bkl create mode 100644 wx28X/samples/widgets/widgets.cpp create mode 100644 wx28X/samples/widgets/widgets.dsp create mode 100644 wx28X/samples/widgets/widgets.h create mode 100644 wx28X/samples/widgets/widgets.pro create mode 100644 wx28X/samples/widgets/widgets.vcp create mode 100644 wx28X/samples/widgets/widgets.vcw create mode 100644 wx28X/samples/widgets/widgetsM5.xml create mode 100644 wx28X/samples/wizard/Makefile.in create mode 100644 wx28X/samples/wizard/makefile.bcc create mode 100644 wx28X/samples/wizard/makefile.dmc create mode 100644 wx28X/samples/wizard/makefile.dms create mode 100644 wx28X/samples/wizard/makefile.gcc create mode 100644 wx28X/samples/wizard/makefile.sl create mode 100644 wx28X/samples/wizard/makefile.unx create mode 100644 wx28X/samples/wizard/makefile.vc create mode 100644 wx28X/samples/wizard/makefile.wat create mode 100644 wx28X/samples/wizard/wizard.bkl create mode 100644 wx28X/samples/wizard/wizard.cpp create mode 100644 wx28X/samples/wizard/wizard.dsp create mode 100644 wx28X/samples/wizard/wizard.pro create mode 100644 wx28X/samples/wizard/wizard.rc create mode 100644 wx28X/samples/wizard/wizard.vcp create mode 100644 wx28X/samples/wizard/wizard.vcw create mode 100644 wx28X/samples/wizard/wizardM5.xml create mode 100644 wx28X/samples/wizard/wiztest.xpm create mode 100644 wx28X/samples/wizard/wiztest2.xpm create mode 100644 wx28X/samples/xrc/Makefile.in create mode 100644 wx28X/samples/xrc/custclas.cpp create mode 100644 wx28X/samples/xrc/custclas.h create mode 100644 wx28X/samples/xrc/derivdlg.cpp create mode 100644 wx28X/samples/xrc/derivdlg.h create mode 100644 wx28X/samples/xrc/descrip.mms create mode 100644 wx28X/samples/xrc/makefile.bcc create mode 100644 wx28X/samples/xrc/makefile.dmc create mode 100644 wx28X/samples/xrc/makefile.dms create mode 100644 wx28X/samples/xrc/makefile.gcc create mode 100644 wx28X/samples/xrc/makefile.unx create mode 100644 wx28X/samples/xrc/makefile.vc create mode 100644 wx28X/samples/xrc/makefile.wat create mode 100644 wx28X/samples/xrc/myframe.cpp create mode 100644 wx28X/samples/xrc/myframe.h create mode 100644 wx28X/samples/xrc/rc/appicon.ico create mode 100644 wx28X/samples/xrc/rc/appicon.xpm create mode 100644 wx28X/samples/xrc/rc/artprov.xpm create mode 100644 wx28X/samples/xrc/rc/artprov.xrc create mode 100644 wx28X/samples/xrc/rc/basicdlg.xpm create mode 100644 wx28X/samples/xrc/rc/basicdlg.xrc create mode 100644 wx28X/samples/xrc/rc/controls.xpm create mode 100644 wx28X/samples/xrc/rc/controls.xrc create mode 100644 wx28X/samples/xrc/rc/custclas.xpm create mode 100644 wx28X/samples/xrc/rc/custclas.xrc create mode 100644 wx28X/samples/xrc/rc/derivdlg.xpm create mode 100644 wx28X/samples/xrc/rc/derivdlg.xrc create mode 100644 wx28X/samples/xrc/rc/fileopen.gif create mode 100644 wx28X/samples/xrc/rc/filesave.gif create mode 100644 wx28X/samples/xrc/rc/frame.xrc create mode 100644 wx28X/samples/xrc/rc/fuzzy.gif create mode 100644 wx28X/samples/xrc/rc/menu.xrc create mode 100644 wx28X/samples/xrc/rc/platform.xpm create mode 100644 wx28X/samples/xrc/rc/platform.xrc create mode 100644 wx28X/samples/xrc/rc/quotes.gif create mode 100644 wx28X/samples/xrc/rc/resource.xrc create mode 100644 wx28X/samples/xrc/rc/stop.xpm create mode 100644 wx28X/samples/xrc/rc/throbber.gif create mode 100644 wx28X/samples/xrc/rc/toolbar.xrc create mode 100644 wx28X/samples/xrc/rc/uncenter.xpm create mode 100644 wx28X/samples/xrc/rc/uncenter.xrc create mode 100644 wx28X/samples/xrc/rc/update.gif create mode 100644 wx28X/samples/xrc/rc/variable.xpm create mode 100644 wx28X/samples/xrc/rc/variable.xrc create mode 100644 wx28X/samples/xrc/xrcdemo.bkl create mode 100644 wx28X/samples/xrc/xrcdemo.cpp create mode 100644 wx28X/samples/xrc/xrcdemo.dsp create mode 100644 wx28X/samples/xrc/xrcdemo.h create mode 100644 wx28X/samples/xrc/xrcdemo.rc create mode 100644 wx28X/samples/xrc/xrcdemo.vcp create mode 100644 wx28X/samples/xrc/xrcdemo.vcw create mode 100644 wx28X/setup.h.in create mode 100644 wx28X/setup.h_vms create mode 100644 wx28X/src/Wxwindll.icc create mode 100644 wx28X/src/aui/auibar.cpp create mode 100644 wx28X/src/aui/auibook.cpp create mode 100644 wx28X/src/aui/descrip.mms create mode 100644 wx28X/src/aui/dockart.cpp create mode 100644 wx28X/src/aui/floatpane.cpp create mode 100644 wx28X/src/aui/framemanager.cpp create mode 100644 wx28X/src/aui/tabmdi.cpp create mode 100644 wx28X/src/common/accesscmn.cpp create mode 100644 wx28X/src/common/anidecod.cpp create mode 100644 wx28X/src/common/animatecmn.cpp create mode 100644 wx28X/src/common/appbase.cpp create mode 100644 wx28X/src/common/appcmn.cpp create mode 100644 wx28X/src/common/arcall.cpp create mode 100644 wx28X/src/common/arcfind.cpp create mode 100644 wx28X/src/common/archive.cpp create mode 100644 wx28X/src/common/artprov.cpp create mode 100644 wx28X/src/common/artstd.cpp create mode 100644 wx28X/src/common/base.rc create mode 100644 wx28X/src/common/bmpbase.cpp create mode 100644 wx28X/src/common/bookctrl.cpp create mode 100644 wx28X/src/common/choiccmn.cpp create mode 100644 wx28X/src/common/clipcmn.cpp create mode 100644 wx28X/src/common/clntdata.cpp create mode 100644 wx28X/src/common/clrpickercmn.cpp create mode 100644 wx28X/src/common/cmdline.cpp create mode 100644 wx28X/src/common/cmdproc.cpp create mode 100644 wx28X/src/common/cmndata.cpp create mode 100644 wx28X/src/common/colourcmn.cpp create mode 100644 wx28X/src/common/combocmn.cpp create mode 100644 wx28X/src/common/config.cpp create mode 100644 wx28X/src/common/containr.cpp create mode 100644 wx28X/src/common/convauto.cpp create mode 100644 wx28X/src/common/cshelp.cpp create mode 100644 wx28X/src/common/ctrlcmn.cpp create mode 100644 wx28X/src/common/ctrlsub.cpp create mode 100644 wx28X/src/common/datacmn.cpp create mode 100644 wx28X/src/common/datavcmn.cpp create mode 100644 wx28X/src/common/datetime.cpp create mode 100644 wx28X/src/common/datstrm.cpp create mode 100644 wx28X/src/common/db.cpp create mode 100644 wx28X/src/common/dbgrid.cpp create mode 100644 wx28X/src/common/dbtable.cpp create mode 100644 wx28X/src/common/dcbase.cpp create mode 100644 wx28X/src/common/dcbufcmn.cpp create mode 100644 wx28X/src/common/dcgraph.cpp create mode 100644 wx28X/src/common/debugrpt.cpp create mode 100644 wx28X/src/common/descrip.mms create mode 100644 wx28X/src/common/dircmn.cpp create mode 100644 wx28X/src/common/dlgcmn.cpp create mode 100644 wx28X/src/common/dndcmn.cpp create mode 100644 wx28X/src/common/dobjcmn.cpp create mode 100644 wx28X/src/common/docmdi.cpp create mode 100644 wx28X/src/common/docview.cpp create mode 100644 wx28X/src/common/dpycmn.cpp create mode 100644 wx28X/src/common/dseldlg.cpp create mode 100644 wx28X/src/common/dummy.cpp create mode 100644 wx28X/src/common/dynarray.cpp create mode 100644 wx28X/src/common/dynlib.cpp create mode 100644 wx28X/src/common/dynload.cpp create mode 100644 wx28X/src/common/effects.cpp create mode 100644 wx28X/src/common/emptydmy.cpp create mode 100644 wx28X/src/common/encconv.cpp create mode 100644 wx28X/src/common/event.cpp create mode 100644 wx28X/src/common/evtloopcmn.cpp create mode 100644 wx28X/src/common/execcmn.cpp create mode 100644 wx28X/src/common/extended.c create mode 100644 wx28X/src/common/fddlgcmn.cpp create mode 100644 wx28X/src/common/ffile.cpp create mode 100644 wx28X/src/common/file.cpp create mode 100644 wx28X/src/common/fileback.cpp create mode 100644 wx28X/src/common/fileconf.cpp create mode 100644 wx28X/src/common/filefn.cpp create mode 100644 wx28X/src/common/filename.cpp create mode 100644 wx28X/src/common/filepickercmn.cpp create mode 100644 wx28X/src/common/filesys.cpp create mode 100644 wx28X/src/common/filtall.cpp create mode 100644 wx28X/src/common/filtfind.cpp create mode 100644 wx28X/src/common/fldlgcmn.cpp create mode 100644 wx28X/src/common/fmapbase.cpp create mode 100644 wx28X/src/common/fontcmn.cpp create mode 100644 wx28X/src/common/fontenumcmn.cpp create mode 100644 wx28X/src/common/fontmap.cpp create mode 100644 wx28X/src/common/fontmgrcmn.cpp create mode 100644 wx28X/src/common/fontpickercmn.cpp create mode 100644 wx28X/src/common/framecmn.cpp create mode 100644 wx28X/src/common/fs_arc.cpp create mode 100644 wx28X/src/common/fs_filter.cpp create mode 100644 wx28X/src/common/fs_inet.cpp create mode 100644 wx28X/src/common/fs_mem.cpp create mode 100644 wx28X/src/common/ftp.cpp create mode 100644 wx28X/src/common/gaugecmn.cpp create mode 100644 wx28X/src/common/gbsizer.cpp create mode 100644 wx28X/src/common/gdicmn.cpp create mode 100644 wx28X/src/common/geometry.cpp create mode 100644 wx28X/src/common/gifdecod.cpp create mode 100644 wx28X/src/common/glob.inc create mode 100644 wx28X/src/common/graphcmn.cpp create mode 100644 wx28X/src/common/hash.cpp create mode 100644 wx28X/src/common/hashmap.cpp create mode 100644 wx28X/src/common/helpbase.cpp create mode 100644 wx28X/src/common/http.cpp create mode 100644 wx28X/src/common/iconbndl.cpp create mode 100644 wx28X/src/common/imagall.cpp create mode 100644 wx28X/src/common/imagbmp.cpp create mode 100644 wx28X/src/common/image.cpp create mode 100644 wx28X/src/common/imagfill.cpp create mode 100644 wx28X/src/common/imaggif.cpp create mode 100644 wx28X/src/common/imagiff.cpp create mode 100644 wx28X/src/common/imagjpeg.cpp create mode 100644 wx28X/src/common/imagpcx.cpp create mode 100644 wx28X/src/common/imagpng.cpp create mode 100644 wx28X/src/common/imagpnm.cpp create mode 100644 wx28X/src/common/imagtga.cpp create mode 100644 wx28X/src/common/imagtiff.cpp create mode 100644 wx28X/src/common/imagxpm.cpp create mode 100644 wx28X/src/common/init.cpp create mode 100644 wx28X/src/common/intl.cpp create mode 100644 wx28X/src/common/ipcbase.cpp create mode 100644 wx28X/src/common/layout.cpp create mode 100644 wx28X/src/common/lboxcmn.cpp create mode 100644 wx28X/src/common/list.cpp create mode 100644 wx28X/src/common/listctrlcmn.cpp create mode 100644 wx28X/src/common/log.cpp create mode 100644 wx28X/src/common/longlong.cpp create mode 100644 wx28X/src/common/matrix.cpp create mode 100644 wx28X/src/common/mediactrlcmn.cpp create mode 100644 wx28X/src/common/memory.cpp create mode 100644 wx28X/src/common/menucmn.cpp create mode 100644 wx28X/src/common/mimecmn.cpp create mode 100644 wx28X/src/common/module.cpp create mode 100644 wx28X/src/common/msgout.cpp create mode 100644 wx28X/src/common/mstream.cpp create mode 100644 wx28X/src/common/nbkbase.cpp create mode 100644 wx28X/src/common/object.cpp create mode 100644 wx28X/src/common/overlaycmn.cpp create mode 100644 wx28X/src/common/paper.cpp create mode 100644 wx28X/src/common/pickerbase.cpp create mode 100644 wx28X/src/common/platinfo.cpp create mode 100644 wx28X/src/common/popupcmn.cpp create mode 100644 wx28X/src/common/powercmn.cpp create mode 100644 wx28X/src/common/prntbase.cpp create mode 100644 wx28X/src/common/process.cpp create mode 100644 wx28X/src/common/protocol.cpp create mode 100644 wx28X/src/common/quantize.cpp create mode 100644 wx28X/src/common/radiocmn.cpp create mode 100644 wx28X/src/common/regex.cpp create mode 100644 wx28X/src/common/rendcmn.cpp create mode 100644 wx28X/src/common/rgncmn.cpp create mode 100644 wx28X/src/common/sckaddr.cpp create mode 100644 wx28X/src/common/sckfile.cpp create mode 100644 wx28X/src/common/sckipc.cpp create mode 100644 wx28X/src/common/sckstrm.cpp create mode 100644 wx28X/src/common/settcmn.cpp create mode 100644 wx28X/src/common/sizer.cpp create mode 100644 wx28X/src/common/socket.cpp create mode 100644 wx28X/src/common/socketevtdispatch.cpp create mode 100644 wx28X/src/common/srchcmn.cpp create mode 100644 wx28X/src/common/sstream.cpp create mode 100644 wx28X/src/common/statbar.cpp create mode 100644 wx28X/src/common/stdpbase.cpp create mode 100644 wx28X/src/common/stockitem.cpp create mode 100644 wx28X/src/common/stopwatch.cpp create mode 100644 wx28X/src/common/strconv.cpp create mode 100644 wx28X/src/common/stream.cpp create mode 100644 wx28X/src/common/string.cpp create mode 100644 wx28X/src/common/sysopt.cpp create mode 100644 wx28X/src/common/tarstrm.cpp create mode 100644 wx28X/src/common/taskbarcmn.cpp create mode 100644 wx28X/src/common/tbarbase.cpp create mode 100644 wx28X/src/common/textbuf.cpp create mode 100644 wx28X/src/common/textcmn.cpp create mode 100644 wx28X/src/common/textfile.cpp create mode 100644 wx28X/src/common/timercmn.cpp create mode 100644 wx28X/src/common/tokenzr.cpp create mode 100644 wx28X/src/common/toplvcmn.cpp create mode 100644 wx28X/src/common/treebase.cpp create mode 100644 wx28X/src/common/txtstrm.cpp create mode 100644 wx28X/src/common/unictabl.inc create mode 100644 wx28X/src/common/uri.cpp create mode 100644 wx28X/src/common/url.cpp create mode 100644 wx28X/src/common/utilscmn.cpp create mode 100644 wx28X/src/common/valgen.cpp create mode 100644 wx28X/src/common/validate.cpp create mode 100644 wx28X/src/common/valtext.cpp create mode 100644 wx28X/src/common/variant.cpp create mode 100644 wx28X/src/common/wfstream.cpp create mode 100644 wx28X/src/common/wincmn.cpp create mode 100644 wx28X/src/common/wxchar.cpp create mode 100644 wx28X/src/common/xpmdecod.cpp create mode 100644 wx28X/src/common/xti.cpp create mode 100644 wx28X/src/common/xtistrm.cpp create mode 100644 wx28X/src/common/xtixml.cpp create mode 100644 wx28X/src/common/zipstrm.cpp create mode 100644 wx28X/src/common/zstream.cpp create mode 100644 wx28X/src/cwcopysetup.bat create mode 100644 wx28X/src/cwdcopysetup.bat create mode 100644 wx28X/src/cygnus.bat create mode 100644 wx28X/src/expat/COPYING create mode 100644 wx28X/src/expat/Changes create mode 100644 wx28X/src/expat/MANIFEST create mode 100644 wx28X/src/expat/Makefile.in create mode 100644 wx28X/src/expat/README create mode 100644 wx28X/src/expat/aclocal.m4 create mode 100644 wx28X/src/expat/bcb5/README.txt create mode 100644 wx28X/src/expat/bcb5/elements.bpf create mode 100644 wx28X/src/expat/bcb5/elements.bpr create mode 100644 wx28X/src/expat/bcb5/elements.mak create mode 100644 wx28X/src/expat/bcb5/expat.bpf create mode 100644 wx28X/src/expat/bcb5/expat.bpr create mode 100644 wx28X/src/expat/bcb5/expat.mak create mode 100644 wx28X/src/expat/bcb5/expat_static.bpf create mode 100644 wx28X/src/expat/bcb5/expat_static.bpr create mode 100644 wx28X/src/expat/bcb5/expat_static.mak create mode 100644 wx28X/src/expat/bcb5/expatw.bpf create mode 100644 wx28X/src/expat/bcb5/expatw.bpr create mode 100644 wx28X/src/expat/bcb5/expatw.mak create mode 100644 wx28X/src/expat/bcb5/expatw_static.bpf create mode 100644 wx28X/src/expat/bcb5/expatw_static.bpr create mode 100644 wx28X/src/expat/bcb5/expatw_static.mak create mode 100644 wx28X/src/expat/bcb5/libexpat_mtd.def create mode 100644 wx28X/src/expat/bcb5/libexpatw_mtd.def create mode 100644 wx28X/src/expat/bcb5/makefile.mak create mode 100644 wx28X/src/expat/bcb5/outline.bpf create mode 100644 wx28X/src/expat/bcb5/outline.bpr create mode 100644 wx28X/src/expat/bcb5/outline.mak create mode 100644 wx28X/src/expat/bcb5/setup.bat create mode 100644 wx28X/src/expat/bcb5/xmlwf.bpf create mode 100644 wx28X/src/expat/bcb5/xmlwf.bpr create mode 100644 wx28X/src/expat/bcb5/xmlwf.mak create mode 100644 wx28X/src/expat/configure create mode 100644 wx28X/src/expat/configure.in create mode 100644 wx28X/src/expat/conftools/PrintPath create mode 100644 wx28X/src/expat/conftools/ac_c_bigendian_cross.m4 create mode 100644 wx28X/src/expat/conftools/config.guess create mode 100644 wx28X/src/expat/conftools/config.sub create mode 100644 wx28X/src/expat/conftools/expat.m4 create mode 100644 wx28X/src/expat/conftools/install-sh create mode 100644 wx28X/src/expat/conftools/libtool.m4 create mode 100644 wx28X/src/expat/conftools/ltmain.sh create mode 100644 wx28X/src/expat/conftools/mkinstalldirs create mode 100644 wx28X/src/expat/doc/reference.html create mode 100644 wx28X/src/expat/doc/style.css create mode 100644 wx28X/src/expat/doc/valid-xhtml10.png create mode 100644 wx28X/src/expat/doc/xmlwf.1 create mode 100644 wx28X/src/expat/doc/xmlwf.sgml create mode 100644 wx28X/src/expat/examples/elements.c create mode 100644 wx28X/src/expat/examples/outline.c create mode 100644 wx28X/src/expat/expat.dsp create mode 100644 wx28X/src/expat/expat_config.h.in create mode 100644 wx28X/src/expat/lib/ascii.h create mode 100644 wx28X/src/expat/lib/asciitab.h create mode 100644 wx28X/src/expat/lib/dosconfig.h create mode 100644 wx28X/src/expat/lib/expat.h create mode 100644 wx28X/src/expat/lib/iasciitab.h create mode 100644 wx28X/src/expat/lib/internal.h create mode 100644 wx28X/src/expat/lib/latin1tab.h create mode 100644 wx28X/src/expat/lib/macconfig.h create mode 100644 wx28X/src/expat/lib/nametab.h create mode 100644 wx28X/src/expat/lib/os2config.h create mode 100644 wx28X/src/expat/lib/utf8tab.h create mode 100644 wx28X/src/expat/lib/winconfig.h create mode 100644 wx28X/src/expat/lib/xmlparse.c create mode 100644 wx28X/src/expat/lib/xmlrole.c create mode 100644 wx28X/src/expat/lib/xmlrole.h create mode 100644 wx28X/src/expat/lib/xmltok.c create mode 100644 wx28X/src/expat/lib/xmltok.h create mode 100644 wx28X/src/expat/lib/xmltok_impl.c create mode 100644 wx28X/src/expat/lib/xmltok_impl.h create mode 100644 wx28X/src/expat/lib/xmltok_ns.c create mode 100644 wx28X/src/expat/vms/README.vms create mode 100644 wx28X/src/expat/vms/descrip.mms create mode 100644 wx28X/src/expat/vms/expat_config.h create mode 100644 wx28X/src/expat/win32/MANIFEST.txt create mode 100644 wx28X/src/expat/win32/expat.iss create mode 100644 wx28X/src/expat/xmlwf/codepage.c create mode 100644 wx28X/src/expat/xmlwf/codepage.h create mode 100644 wx28X/src/expat/xmlwf/ct.c create mode 100644 wx28X/src/expat/xmlwf/filemap.h create mode 100644 wx28X/src/expat/xmlwf/readfilemap.c create mode 100644 wx28X/src/expat/xmlwf/unixfilemap.c create mode 100644 wx28X/src/expat/xmlwf/win32filemap.c create mode 100644 wx28X/src/expat/xmlwf/xmlfile.c create mode 100644 wx28X/src/expat/xmlwf/xmlfile.h create mode 100644 wx28X/src/expat/xmlwf/xmlmime.c create mode 100644 wx28X/src/expat/xmlwf/xmlmime.h create mode 100644 wx28X/src/expat/xmlwf/xmltchar.h create mode 100644 wx28X/src/expat/xmlwf/xmlurl.h create mode 100644 wx28X/src/expat/xmlwf/xmlwf.c create mode 100644 wx28X/src/expat/xmlwf/xmlwin32url.cxx create mode 100644 wx28X/src/generic/aboutdlgg.cpp create mode 100644 wx28X/src/generic/accel.cpp create mode 100644 wx28X/src/generic/animateg.cpp create mode 100644 wx28X/src/generic/bmpcboxg.cpp create mode 100644 wx28X/src/generic/busyinfo.cpp create mode 100644 wx28X/src/generic/buttonbar.cpp create mode 100644 wx28X/src/generic/calctrl.cpp create mode 100644 wx28X/src/generic/caret.cpp create mode 100644 wx28X/src/generic/choicbkg.cpp create mode 100644 wx28X/src/generic/choicdgg.cpp create mode 100644 wx28X/src/generic/clrpickerg.cpp create mode 100644 wx28X/src/generic/collpaneg.cpp create mode 100644 wx28X/src/generic/colour.cpp create mode 100644 wx28X/src/generic/colrdlgg.cpp create mode 100644 wx28X/src/generic/combog.cpp create mode 100644 wx28X/src/generic/datavgen.cpp create mode 100644 wx28X/src/generic/datectlg.cpp create mode 100644 wx28X/src/generic/dbgrptg.cpp create mode 100644 wx28X/src/generic/dcpsg.cpp create mode 100644 wx28X/src/generic/descrip.mms create mode 100644 wx28X/src/generic/dirctrlg.cpp create mode 100644 wx28X/src/generic/dirdlgg.cpp create mode 100644 wx28X/src/generic/dragimgg.cpp create mode 100644 wx28X/src/generic/fdrepdlg.cpp create mode 100644 wx28X/src/generic/filedlgg.cpp create mode 100644 wx28X/src/generic/filepickerg.cpp create mode 100644 wx28X/src/generic/fontdlgg.cpp create mode 100644 wx28X/src/generic/fontpickerg.cpp create mode 100644 wx28X/src/generic/graphicc.cpp create mode 100644 wx28X/src/generic/grid.cpp create mode 100644 wx28X/src/generic/gridctrl.cpp create mode 100644 wx28X/src/generic/gridsel.cpp create mode 100644 wx28X/src/generic/helpext.cpp create mode 100644 wx28X/src/generic/htmllbox.cpp create mode 100644 wx28X/src/generic/hyperlink.cpp create mode 100644 wx28X/src/generic/icon.cpp create mode 100644 wx28X/src/generic/imaglist.cpp create mode 100644 wx28X/src/generic/laywin.cpp create mode 100644 wx28X/src/generic/listbkg.cpp create mode 100644 wx28X/src/generic/listctrl.cpp create mode 100644 wx28X/src/generic/logg.cpp create mode 100644 wx28X/src/generic/mask.cpp create mode 100644 wx28X/src/generic/mdig.cpp create mode 100644 wx28X/src/generic/msgdlgg.cpp create mode 100644 wx28X/src/generic/notebook.cpp create mode 100644 wx28X/src/generic/numdlgg.cpp create mode 100644 wx28X/src/generic/odcombo.cpp create mode 100644 wx28X/src/generic/paletteg.cpp create mode 100644 wx28X/src/generic/panelg.cpp create mode 100644 wx28X/src/generic/printps.cpp create mode 100644 wx28X/src/generic/prntdlgg.cpp create mode 100644 wx28X/src/generic/progdlgg.cpp create mode 100644 wx28X/src/generic/propdlg.cpp create mode 100644 wx28X/src/generic/regiong.cpp create mode 100644 wx28X/src/generic/renderg.cpp create mode 100644 wx28X/src/generic/sashwin.cpp create mode 100644 wx28X/src/generic/scrlwing.cpp create mode 100644 wx28X/src/generic/selstore.cpp create mode 100644 wx28X/src/generic/spinctlg.cpp create mode 100644 wx28X/src/generic/splash.cpp create mode 100644 wx28X/src/generic/splitter.cpp create mode 100644 wx28X/src/generic/srchctlg.cpp create mode 100644 wx28X/src/generic/statline.cpp create mode 100644 wx28X/src/generic/statusbr.cpp create mode 100644 wx28X/src/generic/tabg.cpp create mode 100644 wx28X/src/generic/textdlgg.cpp create mode 100644 wx28X/src/generic/timer.cpp create mode 100644 wx28X/src/generic/tipdlg.cpp create mode 100644 wx28X/src/generic/tipwin.cpp create mode 100644 wx28X/src/generic/toolbkg.cpp create mode 100644 wx28X/src/generic/treebkg.cpp create mode 100644 wx28X/src/generic/treectlg.cpp create mode 100644 wx28X/src/generic/vlbox.cpp create mode 100644 wx28X/src/generic/vscroll.cpp create mode 100644 wx28X/src/generic/wizard.cpp create mode 100644 wx28X/src/html/chm.cpp create mode 100644 wx28X/src/html/descrip.mms create mode 100644 wx28X/src/html/helpctrl.cpp create mode 100644 wx28X/src/html/helpdata.cpp create mode 100644 wx28X/src/html/helpdlg.cpp create mode 100644 wx28X/src/html/helpfrm.cpp create mode 100644 wx28X/src/html/helpwnd.cpp create mode 100644 wx28X/src/html/htmlcell.cpp create mode 100644 wx28X/src/html/htmlctrl/webkit/webkit.mm create mode 100644 wx28X/src/html/htmlfilt.cpp create mode 100644 wx28X/src/html/htmlpars.cpp create mode 100644 wx28X/src/html/htmltag.cpp create mode 100644 wx28X/src/html/htmlwin.cpp create mode 100644 wx28X/src/html/htmprint.cpp create mode 100644 wx28X/src/html/m_dflist.cpp create mode 100644 wx28X/src/html/m_fonts.cpp create mode 100644 wx28X/src/html/m_hline.cpp create mode 100644 wx28X/src/html/m_image.cpp create mode 100644 wx28X/src/html/m_layout.cpp create mode 100644 wx28X/src/html/m_links.cpp create mode 100644 wx28X/src/html/m_list.cpp create mode 100644 wx28X/src/html/m_pre.cpp create mode 100644 wx28X/src/html/m_style.cpp create mode 100644 wx28X/src/html/m_tables.cpp create mode 100644 wx28X/src/html/winpars.cpp create mode 100644 wx28X/src/iodbc/AUTHORS create mode 100644 wx28X/src/iodbc/COPYING create mode 100644 wx28X/src/iodbc/Changes.log create mode 100644 wx28X/src/iodbc/IAFA-PACKAGE create mode 100644 wx28X/src/iodbc/INSTALL create mode 100644 wx28X/src/iodbc/NEWS create mode 100644 wx28X/src/iodbc/README create mode 100644 wx28X/src/iodbc/autoconfig create mode 100644 wx28X/src/iodbc/catalog.c create mode 100644 wx28X/src/iodbc/config.h create mode 100644 wx28X/src/iodbc/connect.c create mode 100644 wx28X/src/iodbc/dlf.c create mode 100644 wx28X/src/iodbc/dlf.h create mode 100644 wx28X/src/iodbc/dlproc.c create mode 100644 wx28X/src/iodbc/dlproc.h create mode 100644 wx28X/src/iodbc/execute.c create mode 100644 wx28X/src/iodbc/fetch.c create mode 100644 wx28X/src/iodbc/hdbc.c create mode 100644 wx28X/src/iodbc/hdbc.h create mode 100644 wx28X/src/iodbc/henv.c create mode 100644 wx28X/src/iodbc/henv.ci create mode 100644 wx28X/src/iodbc/henv.h create mode 100644 wx28X/src/iodbc/herr.c create mode 100644 wx28X/src/iodbc/herr.ci create mode 100644 wx28X/src/iodbc/herr.h create mode 100644 wx28X/src/iodbc/hstmt.c create mode 100644 wx28X/src/iodbc/hstmt.h create mode 100644 wx28X/src/iodbc/info.c create mode 100644 wx28X/src/iodbc/iodbc.h create mode 100644 wx28X/src/iodbc/isql.h create mode 100644 wx28X/src/iodbc/isqlext.h create mode 100644 wx28X/src/iodbc/itrace.c create mode 100644 wx28X/src/iodbc/itrace.h create mode 100644 wx28X/src/iodbc/misc.c create mode 100644 wx28X/src/iodbc/prepare.c create mode 100644 wx28X/src/iodbc/result.c create mode 100644 wx28X/src/iodbc/shrsub.exp create mode 100644 wx28X/src/jpeg/MAKEFILE.VA create mode 100644 wx28X/src/jpeg/README create mode 100644 wx28X/src/jpeg/ansi2knr.1 create mode 100644 wx28X/src/jpeg/ansi2knr.c create mode 100644 wx28X/src/jpeg/change.log create mode 100644 wx28X/src/jpeg/jcapimin.c create mode 100644 wx28X/src/jpeg/jcapistd.c create mode 100644 wx28X/src/jpeg/jccoefct.c create mode 100644 wx28X/src/jpeg/jccolor.c create mode 100644 wx28X/src/jpeg/jcdctmgr.c create mode 100644 wx28X/src/jpeg/jchuff.c create mode 100644 wx28X/src/jpeg/jchuff.h create mode 100644 wx28X/src/jpeg/jcinit.c create mode 100644 wx28X/src/jpeg/jcmainct.c create mode 100644 wx28X/src/jpeg/jcmarker.c create mode 100644 wx28X/src/jpeg/jcmaster.c create mode 100644 wx28X/src/jpeg/jcomapi.c create mode 100644 wx28X/src/jpeg/jconfig.h create mode 100644 wx28X/src/jpeg/jconfig.vc create mode 100644 wx28X/src/jpeg/jcparam.c create mode 100644 wx28X/src/jpeg/jcphuff.c create mode 100644 wx28X/src/jpeg/jcprepct.c create mode 100644 wx28X/src/jpeg/jcsample.c create mode 100644 wx28X/src/jpeg/jctrans.c create mode 100644 wx28X/src/jpeg/jdapimin.c create mode 100644 wx28X/src/jpeg/jdapistd.c create mode 100644 wx28X/src/jpeg/jdatadst.c create mode 100644 wx28X/src/jpeg/jdatasrc.c create mode 100644 wx28X/src/jpeg/jdcoefct.c create mode 100644 wx28X/src/jpeg/jdcolor.c create mode 100644 wx28X/src/jpeg/jdct.h create mode 100644 wx28X/src/jpeg/jddctmgr.c create mode 100644 wx28X/src/jpeg/jdhuff.c create mode 100644 wx28X/src/jpeg/jdhuff.h create mode 100644 wx28X/src/jpeg/jdinput.c create mode 100644 wx28X/src/jpeg/jdmainct.c create mode 100644 wx28X/src/jpeg/jdmarker.c create mode 100644 wx28X/src/jpeg/jdmaster.c create mode 100644 wx28X/src/jpeg/jdmerge.c create mode 100644 wx28X/src/jpeg/jdphuff.c create mode 100644 wx28X/src/jpeg/jdpostct.c create mode 100644 wx28X/src/jpeg/jdsample.c create mode 100644 wx28X/src/jpeg/jdtrans.c create mode 100644 wx28X/src/jpeg/jerror.c create mode 100644 wx28X/src/jpeg/jerror.h create mode 100644 wx28X/src/jpeg/jfdctflt.c create mode 100644 wx28X/src/jpeg/jfdctfst.c create mode 100644 wx28X/src/jpeg/jfdctint.c create mode 100644 wx28X/src/jpeg/jidctflt.c create mode 100644 wx28X/src/jpeg/jidctfst.c create mode 100644 wx28X/src/jpeg/jidctint.c create mode 100644 wx28X/src/jpeg/jidctred.c create mode 100644 wx28X/src/jpeg/jinclude.h create mode 100644 wx28X/src/jpeg/jmemansi.c create mode 100644 wx28X/src/jpeg/jmemdos.c create mode 100644 wx28X/src/jpeg/jmemdosa.asm create mode 100644 wx28X/src/jpeg/jmemmac.c create mode 100644 wx28X/src/jpeg/jmemmgr.c create mode 100644 wx28X/src/jpeg/jmemname.c create mode 100644 wx28X/src/jpeg/jmemnobs.c create mode 100644 wx28X/src/jpeg/jmemsys.h create mode 100644 wx28X/src/jpeg/jmorecfg.h create mode 100644 wx28X/src/jpeg/jpeg.dsp create mode 100644 wx28X/src/jpeg/jpegM8.xml create mode 100644 wx28X/src/jpeg/jpeg_CW_Prefix.h create mode 100644 wx28X/src/jpeg/jpegint.h create mode 100644 wx28X/src/jpeg/jpeglib.h create mode 100644 wx28X/src/jpeg/jpegtran.1 create mode 100644 wx28X/src/jpeg/jpegtran.c create mode 100644 wx28X/src/jpeg/jquant1.c create mode 100644 wx28X/src/jpeg/jquant2.c create mode 100644 wx28X/src/jpeg/jutils.c create mode 100644 wx28X/src/jpeg/jversion.h create mode 100644 wx28X/src/jpeg/makefile.unx create mode 100644 wx28X/src/jpeg/makefile.vc create mode 100644 wx28X/src/makeb32.env create mode 100644 wx28X/src/makebcc.env create mode 100644 wx28X/src/makefile.va create mode 100644 wx28X/src/makefile.vc create mode 100644 wx28X/src/makeg95.env create mode 100644 wx28X/src/makelib.b32 create mode 100644 wx28X/src/makelib.bcc create mode 100644 wx28X/src/makelib.g95 create mode 100644 wx28X/src/makelib.vc create mode 100644 wx28X/src/makemsc.env create mode 100644 wx28X/src/makeprog.b32 create mode 100644 wx28X/src/makeprog.bcc create mode 100644 wx28X/src/makeprog.g95 create mode 100644 wx28X/src/makeprog.sl create mode 100644 wx28X/src/makeprog.va create mode 100644 wx28X/src/makeprog.vc create mode 100644 wx28X/src/makesl.env create mode 100644 wx28X/src/makeva.env create mode 100644 wx28X/src/makevc.env create mode 100644 wx28X/src/mingegcs.bat create mode 100644 wx28X/src/mingw32.bat create mode 100644 wx28X/src/msw/aboutdlg.cpp create mode 100644 wx28X/src/msw/accel.cpp create mode 100644 wx28X/src/msw/app.cpp create mode 100644 wx28X/src/msw/basemsw.cpp create mode 100644 wx28X/src/msw/bitmap.cpp create mode 100644 wx28X/src/msw/bmpbuttn.cpp create mode 100644 wx28X/src/msw/brush.cpp create mode 100644 wx28X/src/msw/button.cpp create mode 100644 wx28X/src/msw/caret.cpp create mode 100644 wx28X/src/msw/checkbox.cpp create mode 100644 wx28X/src/msw/checklst.cpp create mode 100644 wx28X/src/msw/choice.cpp create mode 100644 wx28X/src/msw/clipbrd.cpp create mode 100644 wx28X/src/msw/colordlg.cpp create mode 100644 wx28X/src/msw/colour.cpp create mode 100644 wx28X/src/msw/combo.cpp create mode 100644 wx28X/src/msw/combobox.cpp create mode 100644 wx28X/src/msw/control.cpp create mode 100644 wx28X/src/msw/crashrpt.cpp create mode 100644 wx28X/src/msw/cursor.cpp create mode 100644 wx28X/src/msw/data.cpp create mode 100644 wx28X/src/msw/datectrl.cpp create mode 100644 wx28X/src/msw/dc.cpp create mode 100644 wx28X/src/msw/dcclient.cpp create mode 100644 wx28X/src/msw/dcmemory.cpp create mode 100644 wx28X/src/msw/dcprint.cpp create mode 100644 wx28X/src/msw/dcscreen.cpp create mode 100644 wx28X/src/msw/dde.cpp create mode 100644 wx28X/src/msw/debughlp.cpp create mode 100644 wx28X/src/msw/dialog.cpp create mode 100644 wx28X/src/msw/dialup.cpp create mode 100644 wx28X/src/msw/dib.cpp create mode 100644 wx28X/src/msw/dir.cpp create mode 100644 wx28X/src/msw/dirdlg.cpp create mode 100644 wx28X/src/msw/display.cpp create mode 100644 wx28X/src/msw/dlmsw.cpp create mode 100644 wx28X/src/msw/dragimag.cpp create mode 100644 wx28X/src/msw/enhmeta.cpp create mode 100644 wx28X/src/msw/evtloop.cpp create mode 100644 wx28X/src/msw/fdrepdlg.cpp create mode 100644 wx28X/src/msw/filedlg.cpp create mode 100644 wx28X/src/msw/font.cpp create mode 100644 wx28X/src/msw/fontdlg.cpp create mode 100644 wx28X/src/msw/fontenum.cpp create mode 100644 wx28X/src/msw/fontutil.cpp create mode 100644 wx28X/src/msw/frame.cpp create mode 100644 wx28X/src/msw/gauge95.cpp create mode 100644 wx28X/src/msw/gdiimage.cpp create mode 100644 wx28X/src/msw/gdiobj.cpp create mode 100644 wx28X/src/msw/glcanvas.cpp create mode 100644 wx28X/src/msw/graphics.cpp create mode 100644 wx28X/src/msw/gsocket.cpp create mode 100644 wx28X/src/msw/gsockmsw.cpp create mode 100644 wx28X/src/msw/helpbest.cpp create mode 100644 wx28X/src/msw/helpchm.cpp create mode 100644 wx28X/src/msw/helpwin.cpp create mode 100644 wx28X/src/msw/icon.cpp create mode 100644 wx28X/src/msw/imaglist.cpp create mode 100644 wx28X/src/msw/iniconf.cpp create mode 100644 wx28X/src/msw/joystick.cpp create mode 100644 wx28X/src/msw/listbox.cpp create mode 100644 wx28X/src/msw/listctrl.cpp create mode 100644 wx28X/src/msw/main.cpp create mode 100644 wx28X/src/msw/makebase.b32 create mode 100644 wx28X/src/msw/makebase.vc create mode 100644 wx28X/src/msw/makefile.mic create mode 100644 wx28X/src/msw/makefile.sl create mode 100644 wx28X/src/msw/mdi.cpp create mode 100644 wx28X/src/msw/mediactrl.cpp create mode 100644 wx28X/src/msw/mediactrl_am.cpp create mode 100644 wx28X/src/msw/mediactrl_qt.cpp create mode 100644 wx28X/src/msw/mediactrl_wmp10.cpp create mode 100644 wx28X/src/msw/menu.cpp create mode 100644 wx28X/src/msw/menuitem.cpp create mode 100644 wx28X/src/msw/metafile.cpp create mode 100644 wx28X/src/msw/microwin.c create mode 100644 wx28X/src/msw/mimetype.cpp create mode 100644 wx28X/src/msw/minifram.cpp create mode 100644 wx28X/src/msw/msgdlg.cpp create mode 100644 wx28X/src/msw/mslu.cpp create mode 100644 wx28X/src/msw/nativdlg.cpp create mode 100644 wx28X/src/msw/notebook.cpp create mode 100644 wx28X/src/msw/ole/access.cpp create mode 100644 wx28X/src/msw/ole/activex.cpp create mode 100644 wx28X/src/msw/ole/automtn.cpp create mode 100644 wx28X/src/msw/ole/dataobj.cpp create mode 100644 wx28X/src/msw/ole/dropsrc.cpp create mode 100644 wx28X/src/msw/ole/droptgt.cpp create mode 100644 wx28X/src/msw/ole/oleutils.cpp create mode 100644 wx28X/src/msw/ole/uuid.cpp create mode 100644 wx28X/src/msw/ownerdrw.cpp create mode 100644 wx28X/src/msw/palette.cpp create mode 100644 wx28X/src/msw/pen.cpp create mode 100644 wx28X/src/msw/penwin.cpp create mode 100644 wx28X/src/msw/popupwin.cpp create mode 100644 wx28X/src/msw/power.cpp create mode 100644 wx28X/src/msw/printdlg.cpp create mode 100644 wx28X/src/msw/printwin.cpp create mode 100644 wx28X/src/msw/radiobox.cpp create mode 100644 wx28X/src/msw/radiobut.cpp create mode 100644 wx28X/src/msw/regconf.cpp create mode 100644 wx28X/src/msw/region.cpp create mode 100644 wx28X/src/msw/registry.cpp create mode 100644 wx28X/src/msw/renderer.cpp create mode 100644 wx28X/src/msw/salford.lnk create mode 100644 wx28X/src/msw/scrolbar.cpp create mode 100644 wx28X/src/msw/settings.cpp create mode 100644 wx28X/src/msw/slider95.cpp create mode 100644 wx28X/src/msw/snglinst.cpp create mode 100644 wx28X/src/msw/sound.cpp create mode 100644 wx28X/src/msw/spinbutt.cpp create mode 100644 wx28X/src/msw/spinctrl.cpp create mode 100644 wx28X/src/msw/stackwalk.cpp create mode 100644 wx28X/src/msw/statbmp.cpp create mode 100644 wx28X/src/msw/statbox.cpp create mode 100644 wx28X/src/msw/statbr95.cpp create mode 100644 wx28X/src/msw/statline.cpp create mode 100644 wx28X/src/msw/stattext.cpp create mode 100644 wx28X/src/msw/stdpaths.cpp create mode 100644 wx28X/src/msw/tabctrl.cpp create mode 100644 wx28X/src/msw/taskbar.cpp create mode 100644 wx28X/src/msw/tbar95.cpp create mode 100644 wx28X/src/msw/textctrl.cpp create mode 100644 wx28X/src/msw/tglbtn.cpp create mode 100644 wx28X/src/msw/thread.cpp create mode 100644 wx28X/src/msw/timer.cpp create mode 100644 wx28X/src/msw/tooltip.cpp create mode 100644 wx28X/src/msw/toplevel.cpp create mode 100644 wx28X/src/msw/treectrl.cpp create mode 100644 wx28X/src/msw/urlmsw.cpp create mode 100644 wx28X/src/msw/utils.cpp create mode 100644 wx28X/src/msw/utilsexc.cpp create mode 100644 wx28X/src/msw/utilsgui.cpp create mode 100644 wx28X/src/msw/uxtheme.cpp create mode 100644 wx28X/src/msw/version.rc create mode 100644 wx28X/src/msw/volume.cpp create mode 100644 wx28X/src/msw/wince/checklst.cpp create mode 100644 wx28X/src/msw/wince/choicece.cpp create mode 100644 wx28X/src/msw/wince/clean_vcp.py create mode 100644 wx28X/src/msw/wince/crt.cpp create mode 100644 wx28X/src/msw/wince/filedlgwce.cpp create mode 100644 wx28X/src/msw/wince/filefnwce.cpp create mode 100644 wx28X/src/msw/wince/helpwce.cpp create mode 100644 wx28X/src/msw/wince/menuce.cpp create mode 100644 wx28X/src/msw/wince/net.cpp create mode 100644 wx28X/src/msw/wince/tbarwce.cpp create mode 100644 wx28X/src/msw/wince/textctrlce.cpp create mode 100644 wx28X/src/msw/wince/time.cpp create mode 100644 wx28X/src/msw/window.cpp create mode 100644 wx28X/src/msw/winestub.c create mode 100644 wx28X/src/ntwxwin.mak create mode 100644 wx28X/src/png/ANNOUNCE create mode 100644 wx28X/src/png/CHANGES create mode 100644 wx28X/src/png/INSTALL create mode 100644 wx28X/src/png/KNOWNBUG create mode 100644 wx28X/src/png/LICENSE create mode 100644 wx28X/src/png/MAKEFILE.VA create mode 100644 wx28X/src/png/README create mode 100644 wx28X/src/png/TODO create mode 100644 wx28X/src/png/Y2KINFO create mode 100644 wx28X/src/png/ansi2knr.1 create mode 100644 wx28X/src/png/ansi2knr.c create mode 100644 wx28X/src/png/configure create mode 100644 wx28X/src/png/example.c create mode 100644 wx28X/src/png/libpng.3 create mode 100644 wx28X/src/png/libpng.txt create mode 100644 wx28X/src/png/libpngpf.3 create mode 100644 wx28X/src/png/makefile.unx create mode 100644 wx28X/src/png/makefile.vc create mode 100644 wx28X/src/png/png.5 create mode 100644 wx28X/src/png/png.c create mode 100644 wx28X/src/png/png.dsp create mode 100644 wx28X/src/png/png.h create mode 100644 wx28X/src/png/pngM8.xml create mode 100644 wx28X/src/png/pngasmrd.h create mode 100644 wx28X/src/png/pngbar.jpg create mode 100644 wx28X/src/png/pngbar.png create mode 100644 wx28X/src/png/pngconf.h create mode 100644 wx28X/src/png/pngerror.c create mode 100644 wx28X/src/png/pnggccrd.c create mode 100644 wx28X/src/png/pngget.c create mode 100644 wx28X/src/png/pngmem.c create mode 100644 wx28X/src/png/pngnow.png create mode 100644 wx28X/src/png/pngpread.c create mode 100644 wx28X/src/png/pngread.c create mode 100644 wx28X/src/png/pngrio.c create mode 100644 wx28X/src/png/pngrtran.c create mode 100644 wx28X/src/png/pngrutil.c create mode 100644 wx28X/src/png/pngset.c create mode 100644 wx28X/src/png/pngtest.c create mode 100644 wx28X/src/png/pngtest.png create mode 100644 wx28X/src/png/pngtrans.c create mode 100644 wx28X/src/png/pngvcrd.c create mode 100644 wx28X/src/png/pngwio.c create mode 100644 wx28X/src/png/pngwrite.c create mode 100644 wx28X/src/png/pngwtran.c create mode 100644 wx28X/src/png/pngwutil.c create mode 100644 wx28X/src/png/projects/beos/x86-shared.proj create mode 100644 wx28X/src/png/projects/beos/x86-shared.txt create mode 100644 wx28X/src/png/projects/beos/x86-static.proj create mode 100644 wx28X/src/png/projects/beos/x86-static.txt create mode 100644 wx28X/src/png/projects/cbuilder5/libpng.bpf create mode 100644 wx28X/src/png/projects/cbuilder5/libpng.bpg create mode 100644 wx28X/src/png/projects/cbuilder5/libpng.bpr create mode 100644 wx28X/src/png/projects/cbuilder5/libpng.cpp create mode 100644 wx28X/src/png/projects/cbuilder5/libpng.readme.txt create mode 100644 wx28X/src/png/projects/cbuilder5/libpngstat.bpf create mode 100644 wx28X/src/png/projects/cbuilder5/libpngstat.bpr create mode 100644 wx28X/src/png/projects/cbuilder5/zlib.readme.txt create mode 100644 wx28X/src/png/projects/netware.txt create mode 100644 wx28X/src/png/projects/visualc6/README.txt create mode 100644 wx28X/src/png/projects/visualc6/libpng.dsp create mode 100644 wx28X/src/png/projects/visualc6/pngtest.dsp create mode 100644 wx28X/src/png/projects/wince.txt create mode 100644 wx28X/src/png/scripts/SCOPTIONS.ppc create mode 100644 wx28X/src/png/scripts/descrip.mms create mode 100644 wx28X/src/png/scripts/libpng-config-body.in create mode 100644 wx28X/src/png/scripts/libpng-config-head.in create mode 100644 wx28X/src/png/scripts/libpng.icc create mode 100644 wx28X/src/png/scripts/libpng.pc.in create mode 100644 wx28X/src/png/scripts/makefile.32sunu create mode 100644 wx28X/src/png/scripts/makefile.64sunu create mode 100644 wx28X/src/png/scripts/makefile.acorn create mode 100644 wx28X/src/png/scripts/makefile.aix create mode 100644 wx28X/src/png/scripts/makefile.amiga create mode 100644 wx28X/src/png/scripts/makefile.atari create mode 100644 wx28X/src/png/scripts/makefile.bc32 create mode 100644 wx28X/src/png/scripts/makefile.beos create mode 100644 wx28X/src/png/scripts/makefile.bor create mode 100644 wx28X/src/png/scripts/makefile.cygwin create mode 100644 wx28X/src/png/scripts/makefile.darwin create mode 100644 wx28X/src/png/scripts/makefile.dec create mode 100644 wx28X/src/png/scripts/makefile.dj2 create mode 100644 wx28X/src/png/scripts/makefile.freebsd create mode 100644 wx28X/src/png/scripts/makefile.gcc create mode 100644 wx28X/src/png/scripts/makefile.gcmmx create mode 100644 wx28X/src/png/scripts/makefile.hp64 create mode 100644 wx28X/src/png/scripts/makefile.hpgcc create mode 100644 wx28X/src/png/scripts/makefile.hpux create mode 100644 wx28X/src/png/scripts/makefile.ibmc create mode 100644 wx28X/src/png/scripts/makefile.intel create mode 100644 wx28X/src/png/scripts/makefile.knr create mode 100644 wx28X/src/png/scripts/makefile.linux create mode 100644 wx28X/src/png/scripts/makefile.macosx create mode 100644 wx28X/src/png/scripts/makefile.mips create mode 100644 wx28X/src/png/scripts/makefile.msc create mode 100644 wx28X/src/png/scripts/makefile.ne12bsd create mode 100644 wx28X/src/png/scripts/makefile.netbsd create mode 100644 wx28X/src/png/scripts/makefile.openbsd create mode 100644 wx28X/src/png/scripts/makefile.os2 create mode 100644 wx28X/src/png/scripts/makefile.sco create mode 100644 wx28X/src/png/scripts/makefile.sggcc create mode 100644 wx28X/src/png/scripts/makefile.sgi create mode 100644 wx28X/src/png/scripts/makefile.so9 create mode 100644 wx28X/src/png/scripts/makefile.solaris create mode 100644 wx28X/src/png/scripts/makefile.std create mode 100644 wx28X/src/png/scripts/makefile.sunos create mode 100644 wx28X/src/png/scripts/makefile.tc3 create mode 100644 wx28X/src/png/scripts/makefile.vcawin32 create mode 100644 wx28X/src/png/scripts/makefile.vcwin32 create mode 100644 wx28X/src/png/scripts/makefile.watcom create mode 100644 wx28X/src/png/scripts/makevms.com create mode 100644 wx28X/src/png/scripts/pngos2.def create mode 100644 wx28X/src/png/scripts/pngw32.def create mode 100644 wx28X/src/png/scripts/pngw32.rc create mode 100644 wx28X/src/png/scripts/smakefile.ppc create mode 100644 wx28X/src/regex/COPYRIGHT create mode 100644 wx28X/src/regex/README create mode 100644 wx28X/src/regex/re_syntax.n create mode 100644 wx28X/src/regex/regc_color.c create mode 100644 wx28X/src/regex/regc_cvec.c create mode 100644 wx28X/src/regex/regc_lex.c create mode 100644 wx28X/src/regex/regc_locale.c create mode 100644 wx28X/src/regex/regc_nfa.c create mode 100644 wx28X/src/regex/regcomp.c create mode 100644 wx28X/src/regex/regcustom.h create mode 100644 wx28X/src/regex/rege_dfa.c create mode 100644 wx28X/src/regex/regerror.c create mode 100644 wx28X/src/regex/regerrs.h create mode 100644 wx28X/src/regex/regex.dsp create mode 100644 wx28X/src/regex/regex.h create mode 100644 wx28X/src/regex/regexM8.xml create mode 100644 wx28X/src/regex/regexec.c create mode 100644 wx28X/src/regex/regfree.c create mode 100644 wx28X/src/regex/regfronts.c create mode 100644 wx28X/src/regex/regguts.h create mode 100644 wx28X/src/regex/splice.sh create mode 100644 wx28X/src/regex/tclUniData.c create mode 100644 wx28X/src/richtext/richtextbuffer.cpp create mode 100644 wx28X/src/richtext/richtextbulletspage.cpp create mode 100644 wx28X/src/richtext/richtextctrl.cpp create mode 100644 wx28X/src/richtext/richtextdialogs.pjd create mode 100644 wx28X/src/richtext/richtextfontpage.cpp create mode 100644 wx28X/src/richtext/richtextformatdlg.cpp create mode 100644 wx28X/src/richtext/richtexthtml.cpp create mode 100644 wx28X/src/richtext/richtextindentspage.cpp create mode 100644 wx28X/src/richtext/richtextliststylepage.cpp create mode 100644 wx28X/src/richtext/richtextprint.cpp create mode 100644 wx28X/src/richtext/richtextstyledlg.cpp create mode 100644 wx28X/src/richtext/richtextstylepage.cpp create mode 100644 wx28X/src/richtext/richtextstyles.cpp create mode 100644 wx28X/src/richtext/richtextsymboldlg.cpp create mode 100644 wx28X/src/richtext/richtexttabspage.cpp create mode 100644 wx28X/src/richtext/richtextxml.cpp create mode 100644 wx28X/src/tiff/COPYRIGHT create mode 100644 wx28X/src/tiff/MAKEFILE.VA create mode 100644 wx28X/src/tiff/Makefile.lcc create mode 100644 wx28X/src/tiff/README create mode 100644 wx28X/src/tiff/TODO create mode 100644 wx28X/src/tiff/VERSION create mode 100644 wx28X/src/tiff/fax3sm_winnt.c create mode 100644 wx28X/src/tiff/libtiff.def create mode 100644 wx28X/src/tiff/makefile.vc create mode 100644 wx28X/src/tiff/mkg3states.c create mode 100644 wx28X/src/tiff/mkspans.c create mode 100644 wx28X/src/tiff/mkversion.c create mode 100644 wx28X/src/tiff/port.h create mode 100644 wx28X/src/tiff/t4.h create mode 100644 wx28X/src/tiff/tif_acorn.c create mode 100644 wx28X/src/tiff/tif_apple.c create mode 100644 wx28X/src/tiff/tif_atari.c create mode 100644 wx28X/src/tiff/tif_aux.c create mode 100644 wx28X/src/tiff/tif_close.c create mode 100644 wx28X/src/tiff/tif_codec.c create mode 100644 wx28X/src/tiff/tif_color.c create mode 100644 wx28X/src/tiff/tif_compress.c create mode 100644 wx28X/src/tiff/tif_dir.c create mode 100644 wx28X/src/tiff/tif_dir.h create mode 100644 wx28X/src/tiff/tif_dirinfo.c create mode 100644 wx28X/src/tiff/tif_dirread.c create mode 100644 wx28X/src/tiff/tif_dirwrite.c create mode 100644 wx28X/src/tiff/tif_dumpmode.c create mode 100644 wx28X/src/tiff/tif_error.c create mode 100644 wx28X/src/tiff/tif_extension.c create mode 100644 wx28X/src/tiff/tif_fax3.c create mode 100644 wx28X/src/tiff/tif_fax3.h create mode 100644 wx28X/src/tiff/tif_fax3sm.c create mode 100644 wx28X/src/tiff/tif_flush.c create mode 100644 wx28X/src/tiff/tif_getimage.c create mode 100644 wx28X/src/tiff/tif_jpeg.c create mode 100644 wx28X/src/tiff/tif_luv.c create mode 100644 wx28X/src/tiff/tif_lzw.c create mode 100644 wx28X/src/tiff/tif_msdos.c create mode 100644 wx28X/src/tiff/tif_next.c create mode 100644 wx28X/src/tiff/tif_ojpeg.c create mode 100644 wx28X/src/tiff/tif_open.c create mode 100644 wx28X/src/tiff/tif_os2.c create mode 100644 wx28X/src/tiff/tif_packbits.c create mode 100644 wx28X/src/tiff/tif_pixarlog.c create mode 100644 wx28X/src/tiff/tif_predict.c create mode 100644 wx28X/src/tiff/tif_predict.h create mode 100644 wx28X/src/tiff/tif_print.c create mode 100644 wx28X/src/tiff/tif_read.c create mode 100644 wx28X/src/tiff/tif_strip.c create mode 100644 wx28X/src/tiff/tif_swab.c create mode 100644 wx28X/src/tiff/tif_thunder.c create mode 100644 wx28X/src/tiff/tif_tile.c create mode 100644 wx28X/src/tiff/tif_unix.c create mode 100644 wx28X/src/tiff/tif_version.c create mode 100644 wx28X/src/tiff/tif_vms.c create mode 100644 wx28X/src/tiff/tif_warning.c create mode 100644 wx28X/src/tiff/tif_win3.c create mode 100644 wx28X/src/tiff/tif_win32.c create mode 100644 wx28X/src/tiff/tif_write.c create mode 100644 wx28X/src/tiff/tif_zip.c create mode 100644 wx28X/src/tiff/tiff.dsp create mode 100644 wx28X/src/tiff/tiff.h create mode 100644 wx28X/src/tiff/tiffM8.xml create mode 100644 wx28X/src/tiff/tiff_CW_Prefix.h create mode 100644 wx28X/src/tiff/tiffcomp.h create mode 100644 wx28X/src/tiff/tiffconf.h create mode 100644 wx28X/src/tiff/tiffio.h create mode 100644 wx28X/src/tiff/tiffiop.h create mode 100644 wx28X/src/tiff/tiffvers.h create mode 100644 wx28X/src/tiff/uvcode.h create mode 100644 wx28X/src/univ/bmpbuttn.cpp create mode 100644 wx28X/src/univ/button.cpp create mode 100644 wx28X/src/univ/checkbox.cpp create mode 100644 wx28X/src/univ/checklst.cpp create mode 100644 wx28X/src/univ/choice.cpp create mode 100644 wx28X/src/univ/colschem.cpp create mode 100644 wx28X/src/univ/combobox.cpp create mode 100644 wx28X/src/univ/control.cpp create mode 100644 wx28X/src/univ/ctrlrend.cpp create mode 100644 wx28X/src/univ/descrip.mms create mode 100644 wx28X/src/univ/dialog.cpp create mode 100644 wx28X/src/univ/framuniv.cpp create mode 100644 wx28X/src/univ/gauge.cpp create mode 100644 wx28X/src/univ/inpcons.cpp create mode 100644 wx28X/src/univ/inphand.cpp create mode 100644 wx28X/src/univ/listbox.cpp create mode 100644 wx28X/src/univ/menu.cpp create mode 100644 wx28X/src/univ/notebook.cpp create mode 100644 wx28X/src/univ/radiobox.cpp create mode 100644 wx28X/src/univ/radiobut.cpp create mode 100644 wx28X/src/univ/scrarrow.cpp create mode 100644 wx28X/src/univ/scrolbar.cpp create mode 100644 wx28X/src/univ/scrthumb.cpp create mode 100644 wx28X/src/univ/slider.cpp create mode 100644 wx28X/src/univ/spinbutt.cpp create mode 100644 wx28X/src/univ/statbmp.cpp create mode 100644 wx28X/src/univ/statbox.cpp create mode 100644 wx28X/src/univ/statline.cpp create mode 100644 wx28X/src/univ/stattext.cpp create mode 100644 wx28X/src/univ/statusbr.cpp create mode 100644 wx28X/src/univ/stdrend.cpp create mode 100644 wx28X/src/univ/textctrl.cpp create mode 100644 wx28X/src/univ/tglbtn.cpp create mode 100644 wx28X/src/univ/theme.cpp create mode 100644 wx28X/src/univ/themes/gtk.cpp create mode 100644 wx28X/src/univ/themes/metal.cpp create mode 100644 wx28X/src/univ/themes/mono.cpp create mode 100644 wx28X/src/univ/themes/win32.cpp create mode 100644 wx28X/src/univ/toolbar.cpp create mode 100644 wx28X/src/univ/topluniv.cpp create mode 100644 wx28X/src/univ/winuniv.cpp create mode 100644 wx28X/src/unix/baseunix.cpp create mode 100644 wx28X/src/unix/descrip.mms create mode 100644 wx28X/src/unix/dialup.cpp create mode 100644 wx28X/src/unix/dir.cpp create mode 100644 wx28X/src/unix/displayx11.cpp create mode 100644 wx28X/src/unix/dlunix.cpp create mode 100644 wx28X/src/unix/fontenum.cpp create mode 100644 wx28X/src/unix/fontutil.cpp create mode 100644 wx28X/src/unix/gsocket.cpp create mode 100644 wx28X/src/unix/joystick.cpp create mode 100644 wx28X/src/unix/mediactrl.cpp create mode 100644 wx28X/src/unix/mimetype.cpp create mode 100644 wx28X/src/unix/snglinst.cpp create mode 100644 wx28X/src/unix/sound.cpp create mode 100644 wx28X/src/unix/sound_sdl.cpp create mode 100644 wx28X/src/unix/stackwalk.cpp create mode 100644 wx28X/src/unix/stdpaths.cpp create mode 100644 wx28X/src/unix/taskbarx11.cpp create mode 100644 wx28X/src/unix/threadpsx.cpp create mode 100644 wx28X/src/unix/utilsunx.cpp create mode 100644 wx28X/src/unix/utilsx11.cpp create mode 100644 wx28X/src/version.mak create mode 100644 wx28X/src/wxJpeg.icc create mode 100644 wx28X/src/wxPng.icc create mode 100644 wx28X/src/wxTiff.icc create mode 100644 wx28X/src/wxWin.icc create mode 100644 wx28X/src/wxWindowsClassicM8.xml create mode 100644 wx28X/src/wxWindowsM8.xml create mode 100644 wx28X/src/wxWindowsW7.xml create mode 100644 wx28X/src/wxXpm.icc create mode 100644 wx28X/src/wxZlib.icc create mode 100644 wx28X/src/xml/descrip.mms create mode 100644 wx28X/src/xml/xml.cpp create mode 100644 wx28X/src/xrc/descrip.mms create mode 100644 wx28X/src/xrc/xh_animatctrl.cpp create mode 100644 wx28X/src/xrc/xh_bmp.cpp create mode 100644 wx28X/src/xrc/xh_bmpbt.cpp create mode 100644 wx28X/src/xrc/xh_bmpcbox.cpp create mode 100644 wx28X/src/xrc/xh_bttn.cpp create mode 100644 wx28X/src/xrc/xh_cald.cpp create mode 100644 wx28X/src/xrc/xh_chckb.cpp create mode 100644 wx28X/src/xrc/xh_chckl.cpp create mode 100644 wx28X/src/xrc/xh_choic.cpp create mode 100644 wx28X/src/xrc/xh_choicbk.cpp create mode 100644 wx28X/src/xrc/xh_clrpicker.cpp create mode 100644 wx28X/src/xrc/xh_collpane.cpp create mode 100644 wx28X/src/xrc/xh_combo.cpp create mode 100644 wx28X/src/xrc/xh_datectrl.cpp create mode 100644 wx28X/src/xrc/xh_dirpicker.cpp create mode 100644 wx28X/src/xrc/xh_dlg.cpp create mode 100644 wx28X/src/xrc/xh_filepicker.cpp create mode 100644 wx28X/src/xrc/xh_fontpicker.cpp create mode 100644 wx28X/src/xrc/xh_frame.cpp create mode 100644 wx28X/src/xrc/xh_gauge.cpp create mode 100644 wx28X/src/xrc/xh_gdctl.cpp create mode 100644 wx28X/src/xrc/xh_grid.cpp create mode 100644 wx28X/src/xrc/xh_html.cpp create mode 100644 wx28X/src/xrc/xh_htmllbox.cpp create mode 100644 wx28X/src/xrc/xh_hyperlink.cpp create mode 100644 wx28X/src/xrc/xh_listb.cpp create mode 100644 wx28X/src/xrc/xh_listbk.cpp create mode 100644 wx28X/src/xrc/xh_listc.cpp create mode 100644 wx28X/src/xrc/xh_mdi.cpp create mode 100644 wx28X/src/xrc/xh_menu.cpp create mode 100644 wx28X/src/xrc/xh_notbk.cpp create mode 100644 wx28X/src/xrc/xh_odcombo.cpp create mode 100644 wx28X/src/xrc/xh_panel.cpp create mode 100644 wx28X/src/xrc/xh_propdlg.cpp create mode 100644 wx28X/src/xrc/xh_radbt.cpp create mode 100644 wx28X/src/xrc/xh_radbx.cpp create mode 100644 wx28X/src/xrc/xh_richtext.cpp create mode 100644 wx28X/src/xrc/xh_scrol.cpp create mode 100644 wx28X/src/xrc/xh_scwin.cpp create mode 100644 wx28X/src/xrc/xh_sizer.cpp create mode 100644 wx28X/src/xrc/xh_slidr.cpp create mode 100644 wx28X/src/xrc/xh_spin.cpp create mode 100644 wx28X/src/xrc/xh_split.cpp create mode 100644 wx28X/src/xrc/xh_statbar.cpp create mode 100644 wx28X/src/xrc/xh_stbmp.cpp create mode 100644 wx28X/src/xrc/xh_stbox.cpp create mode 100644 wx28X/src/xrc/xh_stlin.cpp create mode 100644 wx28X/src/xrc/xh_sttxt.cpp create mode 100644 wx28X/src/xrc/xh_text.cpp create mode 100644 wx28X/src/xrc/xh_tglbtn.cpp create mode 100644 wx28X/src/xrc/xh_toolb.cpp create mode 100644 wx28X/src/xrc/xh_tree.cpp create mode 100644 wx28X/src/xrc/xh_treebk.cpp create mode 100644 wx28X/src/xrc/xh_unkwn.cpp create mode 100644 wx28X/src/xrc/xh_wizrd.cpp create mode 100644 wx28X/src/xrc/xmlres.cpp create mode 100644 wx28X/src/xrc/xmlrsall.cpp create mode 100644 wx28X/src/zlib/ChangeLog create mode 100644 wx28X/src/zlib/FAQ create mode 100644 wx28X/src/zlib/INDEX create mode 100644 wx28X/src/zlib/README create mode 100644 wx28X/src/zlib/adler32.c create mode 100644 wx28X/src/zlib/algorithm.txt create mode 100644 wx28X/src/zlib/compress.c create mode 100644 wx28X/src/zlib/crc32.c create mode 100644 wx28X/src/zlib/crc32.h create mode 100644 wx28X/src/zlib/deflate.c create mode 100644 wx28X/src/zlib/deflate.h create mode 100644 wx28X/src/zlib/example.c create mode 100644 wx28X/src/zlib/gzio.c create mode 100644 wx28X/src/zlib/infback.c create mode 100644 wx28X/src/zlib/inffast.c create mode 100644 wx28X/src/zlib/inffast.h create mode 100644 wx28X/src/zlib/inffixed.h create mode 100644 wx28X/src/zlib/inflate.c create mode 100644 wx28X/src/zlib/inflate.h create mode 100644 wx28X/src/zlib/inftrees.c create mode 100644 wx28X/src/zlib/inftrees.h create mode 100644 wx28X/src/zlib/minigzip.c create mode 100644 wx28X/src/zlib/trees.c create mode 100644 wx28X/src/zlib/trees.h create mode 100644 wx28X/src/zlib/uncompr.c create mode 100644 wx28X/src/zlib/zconf.h create mode 100644 wx28X/src/zlib/zlib.3 create mode 100644 wx28X/src/zlib/zlib.dsp create mode 100644 wx28X/src/zlib/zlib.h create mode 100644 wx28X/src/zlib/zlibM8.xml create mode 100644 wx28X/src/zlib/zutil.c create mode 100644 wx28X/src/zlib/zutil.h create mode 100644 wx28X/unins000.dat create mode 100644 wx28X/unins000.exe create mode 100644 wx28X/utils/HelpGen/Makefile.in create mode 100644 wx28X/utils/HelpGen/src/HelpGen.cpp create mode 100644 wx28X/utils/HelpGen/src/HelpGenM5.mcp create mode 100644 wx28X/utils/HelpGen/src/Makefile.in create mode 100644 wx28X/utils/HelpGen/src/cjparser.cpp create mode 100644 wx28X/utils/HelpGen/src/cjparser.h create mode 100644 wx28X/utils/HelpGen/src/docripper.cpp create mode 100644 wx28X/utils/HelpGen/src/docripper.h create mode 100644 wx28X/utils/HelpGen/src/helpgen.bkl create mode 100644 wx28X/utils/HelpGen/src/helpgen.dsp create mode 100644 wx28X/utils/HelpGen/src/ifcontext.cpp create mode 100644 wx28X/utils/HelpGen/src/ifcontext.h create mode 100644 wx28X/utils/HelpGen/src/makefile.bcc create mode 100644 wx28X/utils/HelpGen/src/makefile.dmc create mode 100644 wx28X/utils/HelpGen/src/makefile.dms create mode 100644 wx28X/utils/HelpGen/src/makefile.gcc create mode 100644 wx28X/utils/HelpGen/src/makefile.vc create mode 100644 wx28X/utils/HelpGen/src/makefile.wat create mode 100644 wx28X/utils/HelpGen/src/markup.cpp create mode 100644 wx28X/utils/HelpGen/src/markup.h create mode 100644 wx28X/utils/HelpGen/src/ripper_main.cpp create mode 100644 wx28X/utils/HelpGen/src/scriptbinder.cpp create mode 100644 wx28X/utils/HelpGen/src/scriptbinder.h create mode 100644 wx28X/utils/HelpGen/src/sourcepainter.cpp create mode 100644 wx28X/utils/HelpGen/src/sourcepainter.h create mode 100644 wx28X/utils/HelpGen/src/srcparser.cpp create mode 100644 wx28X/utils/HelpGen/src/srcparser.h create mode 100644 wx28X/utils/HelpGen/src/wx_extra_imps.cpp create mode 100644 wx28X/utils/HelpGen/src/wxstlac.h create mode 100644 wx28X/utils/HelpGen/src/wxstllst.h create mode 100644 wx28X/utils/HelpGen/src/wxstlvec.h create mode 100644 wx28X/utils/HelpHTML/README create mode 100644 wx28X/utils/HelpHTML/html2wxhelp create mode 100644 wx28X/utils/HelpHTML/striphelpids create mode 100644 wx28X/utils/Makefile.in create mode 100644 wx28X/utils/emulator/Makefile.in create mode 100644 wx28X/utils/emulator/artwork/ipaq01.png create mode 100644 wx28X/utils/emulator/artwork/ipaq02.png create mode 100644 wx28X/utils/emulator/src/Makefile.in create mode 100644 wx28X/utils/emulator/src/bluegradient.jpg create mode 100644 wx28X/utils/emulator/src/default.wxe create mode 100644 wx28X/utils/emulator/src/emulator.bkl create mode 100644 wx28X/utils/emulator/src/emulator.bmp create mode 100644 wx28X/utils/emulator/src/emulator.cpp create mode 100644 wx28X/utils/emulator/src/emulator.dsp create mode 100644 wx28X/utils/emulator/src/emulator.h create mode 100644 wx28X/utils/emulator/src/emulator.ico create mode 100644 wx28X/utils/emulator/src/emulator.rc create mode 100644 wx28X/utils/emulator/src/emulator.vcp create mode 100644 wx28X/utils/emulator/src/emulator.vcw create mode 100644 wx28X/utils/emulator/src/emulator.xpm create mode 100644 wx28X/utils/emulator/src/ipaq.wxe create mode 100644 wx28X/utils/emulator/src/ipaq01.jpg create mode 100644 wx28X/utils/emulator/src/makefile.bcc create mode 100644 wx28X/utils/emulator/src/makefile.dmc create mode 100644 wx28X/utils/emulator/src/makefile.dms create mode 100644 wx28X/utils/emulator/src/makefile.gcc create mode 100644 wx28X/utils/emulator/src/makefile.vc create mode 100644 wx28X/utils/emulator/src/makefile.wat create mode 100644 wx28X/utils/emulator/src/mondrian.ico create mode 100644 wx28X/utils/emulator/src/mondrian.xpm create mode 100644 wx28X/utils/helpview/Makefile.in create mode 100644 wx28X/utils/helpview/src/HelpviewM7.mcp create mode 100644 wx28X/utils/helpview/src/Makefile.in create mode 100644 wx28X/utils/helpview/src/bitmaps/helpback.xpm create mode 100644 wx28X/utils/helpview/src/bitmaps/helpbook.xpm create mode 100644 wx28X/utils/helpview/src/bitmaps/helpdown.xpm create mode 100644 wx28X/utils/helpview/src/bitmaps/helpforward.xpm create mode 100644 wx28X/utils/helpview/src/bitmaps/helpicon.xpm create mode 100644 wx28X/utils/helpview/src/bitmaps/helpopen.xpm create mode 100644 wx28X/utils/helpview/src/bitmaps/helpoptions.xpm create mode 100644 wx28X/utils/helpview/src/bitmaps/helppage.xpm create mode 100644 wx28X/utils/helpview/src/bitmaps/helpsidepanel.xpm create mode 100644 wx28X/utils/helpview/src/bitmaps/helpup.xpm create mode 100644 wx28X/utils/helpview/src/bitmaps/helpuplevel.xpm create mode 100644 wx28X/utils/helpview/src/client.cpp create mode 100644 wx28X/utils/helpview/src/client.dsp create mode 100644 wx28X/utils/helpview/src/client.h create mode 100644 wx28X/utils/helpview/src/client.rc create mode 100644 wx28X/utils/helpview/src/helpview-docicon.r create mode 100644 wx28X/utils/helpview/src/helpview-icon.r create mode 100644 wx28X/utils/helpview/src/helpview.bkl create mode 100644 wx28X/utils/helpview/src/helpview.cpp create mode 100644 wx28X/utils/helpview/src/helpview.dsp create mode 100644 wx28X/utils/helpview/src/helpview.h create mode 100644 wx28X/utils/helpview/src/helpview.ico create mode 100644 wx28X/utils/helpview/src/helpview.r create mode 100644 wx28X/utils/helpview/src/helpview.rc create mode 100644 wx28X/utils/helpview/src/helpview.vcp create mode 100644 wx28X/utils/helpview/src/helpview.vcw create mode 100644 wx28X/utils/helpview/src/helpviewM5.xml create mode 100644 wx28X/utils/helpview/src/makefile.bcc create mode 100644 wx28X/utils/helpview/src/makefile.dmc create mode 100644 wx28X/utils/helpview/src/makefile.dms create mode 100644 wx28X/utils/helpview/src/makefile.gcc create mode 100644 wx28X/utils/helpview/src/makefile.vc create mode 100644 wx28X/utils/helpview/src/makefile.wat create mode 100644 wx28X/utils/helpview/src/readme.txt create mode 100644 wx28X/utils/helpview/src/remhelp.cpp create mode 100644 wx28X/utils/helpview/src/remhelp.h create mode 100644 wx28X/utils/helpview/src/test.zip create mode 100644 wx28X/utils/hhp2cached/Makefile.in create mode 100644 wx28X/utils/hhp2cached/hhp2cached.bkl create mode 100644 wx28X/utils/hhp2cached/hhp2cached.cpp create mode 100644 wx28X/utils/hhp2cached/hhp2cached.dsp create mode 100644 wx28X/utils/hhp2cached/hhp2cached.rc create mode 100644 wx28X/utils/hhp2cached/hhp2cached.vcp create mode 100644 wx28X/utils/hhp2cached/hhp2cached.vcw create mode 100644 wx28X/utils/hhp2cached/makefile.bcc create mode 100644 wx28X/utils/hhp2cached/makefile.dmc create mode 100644 wx28X/utils/hhp2cached/makefile.dms create mode 100644 wx28X/utils/hhp2cached/makefile.gcc create mode 100644 wx28X/utils/hhp2cached/makefile.vc create mode 100644 wx28X/utils/hhp2cached/makefile.wat create mode 100644 wx28X/utils/makefile.bcc create mode 100644 wx28X/utils/makefile.dmc create mode 100644 wx28X/utils/makefile.dms create mode 100644 wx28X/utils/makefile.gcc create mode 100644 wx28X/utils/makefile.vc create mode 100644 wx28X/utils/makefile.wat create mode 100644 wx28X/utils/nplugin/lib/dummy create mode 100644 wx28X/utils/nplugin/makefile.vc create mode 100644 wx28X/utils/nplugin/samples/gui/gui.cpp create mode 100644 wx28X/utils/nplugin/samples/gui/gui.h create mode 100644 wx28X/utils/nplugin/samples/gui/index.html create mode 100644 wx28X/utils/nplugin/samples/gui/makefile.vc create mode 100644 wx28X/utils/nplugin/samples/gui/npgui32.rc create mode 100644 wx28X/utils/nplugin/samples/simple/index.html create mode 100644 wx28X/utils/nplugin/samples/simple/makefile.vc create mode 100644 wx28X/utils/nplugin/samples/simple/npsimple32.rc create mode 100644 wx28X/utils/nplugin/samples/simple/simple.cpp create mode 100644 wx28X/utils/nplugin/src/makefile.vc create mode 100644 wx28X/utils/nplugin/src/npapi.h create mode 100644 wx28X/utils/nplugin/src/npapp.cpp create mode 100644 wx28X/utils/nplugin/src/npapp.h create mode 100644 wx28X/utils/nplugin/src/npframe.cpp create mode 100644 wx28X/utils/nplugin/src/npframe.h create mode 100644 wx28X/utils/nplugin/src/npshell.cpp create mode 100644 wx28X/utils/nplugin/src/npupp.h create mode 100644 wx28X/utils/nplugin/src/npwin.cpp create mode 100644 wx28X/utils/tex2rtf/Makefile.in create mode 100644 wx28X/utils/tex2rtf/src/Makefile.in create mode 100644 wx28X/utils/tex2rtf/src/bmputils.h create mode 100644 wx28X/utils/tex2rtf/src/htmlutil.cpp create mode 100644 wx28X/utils/tex2rtf/src/makefile.bcc create mode 100644 wx28X/utils/tex2rtf/src/makefile.dmc create mode 100644 wx28X/utils/tex2rtf/src/makefile.dms create mode 100644 wx28X/utils/tex2rtf/src/makefile.gcc create mode 100644 wx28X/utils/tex2rtf/src/makefile.unx create mode 100644 wx28X/utils/tex2rtf/src/makefile.vc create mode 100644 wx28X/utils/tex2rtf/src/makefile.wat create mode 100644 wx28X/utils/tex2rtf/src/makengui.nt create mode 100644 wx28X/utils/tex2rtf/src/maths.cpp create mode 100644 wx28X/utils/tex2rtf/src/readshg.cpp create mode 100644 wx28X/utils/tex2rtf/src/readshg.h create mode 100644 wx28X/utils/tex2rtf/src/rtfutils.cpp create mode 100644 wx28X/utils/tex2rtf/src/rtfutils.h create mode 100644 wx28X/utils/tex2rtf/src/symbols.h create mode 100644 wx28X/utils/tex2rtf/src/table.cpp create mode 100644 wx28X/utils/tex2rtf/src/table.h create mode 100644 wx28X/utils/tex2rtf/src/tex2any.cpp create mode 100644 wx28X/utils/tex2rtf/src/tex2any.h create mode 100644 wx28X/utils/tex2rtf/src/tex2rtf.bkl create mode 100644 wx28X/utils/tex2rtf/src/tex2rtf.cpp create mode 100644 wx28X/utils/tex2rtf/src/tex2rtf.h create mode 100644 wx28X/utils/tex2rtf/src/tex2rtf.ico create mode 100644 wx28X/utils/tex2rtf/src/tex2rtf.ini create mode 100644 wx28X/utils/tex2rtf/src/tex2rtf.rc create mode 100644 wx28X/utils/tex2rtf/src/tex2rtf.vcp create mode 100644 wx28X/utils/tex2rtf/src/tex2rtf.vcw create mode 100644 wx28X/utils/tex2rtf/src/tex2rtf.xpm create mode 100644 wx28X/utils/tex2rtf/src/tex2rtf_tex2rtf.dsp create mode 100644 wx28X/utils/tex2rtf/src/tex2rtf_tex2rtf_gui.dsp create mode 100644 wx28X/utils/tex2rtf/src/texutils.cpp create mode 100644 wx28X/utils/tex2rtf/src/wxhlpblk.h create mode 100644 wx28X/utils/tex2rtf/src/xlputils.cpp create mode 100644 wx28X/utils/tex2rtf/tools/suppresswarnings.sh create mode 100644 wx28X/utils/utils.bkl create mode 100644 wx28X/utils/wxOLE/samples/servlet/mondrian.xpm create mode 100644 wx28X/utils/wxOLE/samples/servlet/servlet.cpp create mode 100644 wx28X/utils/wxOLE/samples/servlet/servlet.gnorba create mode 100644 wx28X/utils/wxrc/Makefile.in create mode 100644 wx28X/utils/wxrc/makefile.bcc create mode 100644 wx28X/utils/wxrc/makefile.dmc create mode 100644 wx28X/utils/wxrc/makefile.dms create mode 100644 wx28X/utils/wxrc/makefile.gcc create mode 100644 wx28X/utils/wxrc/makefile.vc create mode 100644 wx28X/utils/wxrc/makefile.wat create mode 100644 wx28X/utils/wxrc/mondrian.ico create mode 100644 wx28X/utils/wxrc/wxrc.bkl create mode 100644 wx28X/utils/wxrc/wxrc.cpp create mode 100644 wx28X/utils/wxrc/wxrc.dsp create mode 100644 wx28X/utils/wxrc/wxrc.rc create mode 100644 wx28X/version-script.in create mode 100644 wx28X/wx-config-inplace.in create mode 100644 wx28X/wx-config.in create mode 100644 wx28X/wx.url create mode 100644 wx28X/wxBase.spec create mode 100644 wx28X/wxGTK.spec create mode 100644 wx28X/wxMGL.spec create mode 100644 wx28X/wxMotif.spec create mode 100644 wx28X/wxX11.spec create mode 100644 wx28X/wxwin.m4 create mode 100644 wxPG/propgrid/CHANGES.txt create mode 100644 wxPG/propgrid/Makefile.in create mode 100644 wxPG/propgrid/README.txt create mode 100644 wxPG/propgrid/build/Bakefiles.bkgen create mode 100644 wxPG/propgrid/build/GNUMakefile create mode 100644 wxPG/propgrid/build/autoconf_inc.m4 create mode 100644 wxPG/propgrid/build/config.guess create mode 100644 wxPG/propgrid/build/config.sub create mode 100644 wxPG/propgrid/build/configure.ac create mode 100644 wxPG/propgrid/build/makefile.bcc create mode 100644 wxPG/propgrid/build/makefile.gcc create mode 100644 wxPG/propgrid/build/makefile.vc create mode 100644 wxPG/propgrid/build/makefile.wat create mode 100644 wxPG/propgrid/build/propgrid.bkl create mode 100644 wxPG/propgrid/build/propgrid.dsw create mode 100644 wxPG/propgrid/build/propgrid_propgrid.dsp create mode 100644 wxPG/propgrid/build/propgrid_propgrid_vc10.vcxproj create mode 100644 wxPG/propgrid/build/propgrid_propgrid_vc10.vcxproj.filters create mode 100644 wxPG/propgrid/build/propgrid_propgrid_vc10.vcxproj.user create mode 100644 wxPG/propgrid/build/propgrid_propgrid_vc7.vcproj create mode 100644 wxPG/propgrid/build/propgrid_propgrid_vc8.vcproj create mode 100644 wxPG/propgrid/build/propgrid_propgrid_vc9.vcproj create mode 100644 wxPG/propgrid/build/propgrid_propgridsample.dsp create mode 100644 wxPG/propgrid/build/propgrid_propgridsample.vcxproj.filters create mode 100644 wxPG/propgrid/build/propgrid_propgridsample.vcxproj.user create mode 100644 wxPG/propgrid/build/propgrid_propgridsample_vc10.vcxproj create mode 100644 wxPG/propgrid/build/propgrid_propgridsample_vc10.vcxproj.user create mode 100644 wxPG/propgrid/build/propgrid_propgridsample_vc7.vcproj create mode 100644 wxPG/propgrid/build/propgrid_propgridsample_vc8.vcproj create mode 100644 wxPG/propgrid/build/propgrid_propgridsample_vc9.vcproj create mode 100644 wxPG/propgrid/build/propgrid_vc10.sdf create mode 100644 wxPG/propgrid/build/propgrid_vc10.sln create mode 100644 wxPG/propgrid/build/propgrid_vc10.suo create mode 100644 wxPG/propgrid/build/propgrid_vc7.sln create mode 100644 wxPG/propgrid/build/propgrid_vc8.sln create mode 100644 wxPG/propgrid/build/propgrid_vc9.sln create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/CL.read.1.tlog create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/CL.write.1.tlog create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/advprops.obj create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/cl.command.1.tlog create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/editors.obj create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/extras.obj create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/link.command.1.tlog create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/link.read.1.tlog create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/link.write.1.tlog create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/manager.obj create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/mt.command.1.tlog create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/mt.read.1.tlog create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/mt.write.1.tlog create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/odcombo.obj create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/propgrid.dll.intermediate.manifest create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/propgrid.lastbuildstate create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/propgrid.obj create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/propgrid.write.1.tlog create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/propgrid_propgrid_vc10.log create mode 100644 wxPG/propgrid/build/vcmsw_dll/propgrid/props.obj create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/CL.read.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/CL.write.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/advprops.obj create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/cl.command.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/editors.obj create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/extras.obj create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/link-cvtres.read.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/link-cvtres.write.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/link.5356-cvtres.read.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/link.5356-cvtres.write.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/link.5356.read.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/link.5356.write.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/link.command.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/link.read.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/link.write.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/manager.obj create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/mt.command.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/mt.read.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/mt.write.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/odcombo.obj create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/propgrid.Build.CppClean.log create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/propgrid.dll.embed.manifest create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/propgrid.dll.embed.manifest.res create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/propgrid.dll.intermediate.manifest create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/propgrid.lastbuildstate create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/propgrid.obj create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/propgrid.write.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/propgrid_manifest.rc create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/propgrid_propgrid_vc10.log create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/props.obj create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/rc.command.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/rc.read.1.tlog create mode 100644 wxPG/propgrid/build/vcmswd_dll/propgrid/rc.write.1.tlog create mode 100644 wxPG/propgrid/build_wx26/makefile.bcc create mode 100644 wxPG/propgrid/build_wx26/makefile.gcc create mode 100644 wxPG/propgrid/build_wx26/makefile.vc create mode 100644 wxPG/propgrid/build_wx26/makefile.wat create mode 100644 wxPG/propgrid/build_wx26/propgrid.dsw create mode 100644 wxPG/propgrid/build_wx26/propgrid.sln create mode 100644 wxPG/propgrid/build_wx26/propgrid_propgrid.dsp create mode 100644 wxPG/propgrid/build_wx26/propgrid_propgrid.vcproj create mode 100644 wxPG/propgrid/build_wx26/propgrid_propgridsample.dsp create mode 100644 wxPG/propgrid/build_wx26/propgrid_propgridsample.vcproj create mode 100644 wxPG/propgrid/configure create mode 100644 wxPG/propgrid/docs/Doxyfile create mode 100644 wxPG/propgrid/docs/html/annotated.htm create mode 100644 wxPG/propgrid/docs/html/classes.htm create mode 100644 wxPG/propgrid/docs/html/classwxArrayEditorDialog-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxArrayEditorDialog.htm create mode 100644 wxPG/propgrid/docs/html/classwxArrayEditorDialog.png create mode 100644 wxPG/propgrid/docs/html/classwxArrayStringProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxArrayStringProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxArrayStringProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxBaseEnumProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxBaseEnumProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxBaseEnumProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxBoolProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxBoolProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxBoolProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxColourProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxColourProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxColourPropertyValue-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxColourPropertyValue.htm create mode 100644 wxPG/propgrid/docs/html/classwxCursorProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxCursorProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxCursorProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxCustomProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxCustomProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxCustomProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxDateProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxDateProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxDateProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxDirProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxDirProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxDirProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxEditEnumProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxEditEnumProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxEditEnumProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxEnumProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxEnumProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxEnumProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxFileProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxFileProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxFileProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxFlagsProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxFlagsProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxFlagsProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxFloatProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxFloatProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxFloatProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxFontProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxFontProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxFontProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxImageFileProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxImageFileProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxImageFileProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxIntProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxIntProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxIntProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxLongStringProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxLongStringProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxLongStringProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxMultiChoiceProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxMultiChoiceProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxMultiChoiceProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxPGArrayStringEditorDialog-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGArrayStringEditorDialog.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGArrayStringEditorDialog.png create mode 100644 wxPG/propgrid/docs/html/classwxPGAttributeStorage-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGAttributeStorage.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGCell-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGCell.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGCell.png create mode 100644 wxPG/propgrid/docs/html/classwxPGCellRenderer-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGCellRenderer.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGCellRenderer.png create mode 100644 wxPG/propgrid/docs/html/classwxPGCheckBoxEditor-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGCheckBoxEditor.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGCheckBoxEditor.png create mode 100644 wxPG/propgrid/docs/html/classwxPGChoiceAndButtonEditor-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGChoiceAndButtonEditor.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGChoiceAndButtonEditor.png create mode 100644 wxPG/propgrid/docs/html/classwxPGChoiceEditor-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGChoiceEditor.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGChoiceEditor.png create mode 100644 wxPG/propgrid/docs/html/classwxPGChoiceEntry-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGChoiceEntry.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGChoiceEntry.png create mode 100644 wxPG/propgrid/docs/html/classwxPGChoices-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGChoices.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGChoicesData-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGChoicesData.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGComboBoxEditor-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGComboBoxEditor.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGComboBoxEditor.png create mode 100644 wxPG/propgrid/docs/html/classwxPGCommonValue-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGCommonValue.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGDefaultRenderer-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGDefaultRenderer.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGDefaultRenderer.png create mode 100644 wxPG/propgrid/docs/html/classwxPGEditableState-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGEditableState.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGEditableState.png create mode 100644 wxPG/propgrid/docs/html/classwxPGEditor-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGEditor.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGEditor.png create mode 100644 wxPG/propgrid/docs/html/classwxPGEditorDialogAdapter-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGEditorDialogAdapter.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGEditorDialogAdapter.png create mode 100644 wxPG/propgrid/docs/html/classwxPGFileDialogAdapter-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGFileDialogAdapter.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGFileDialogAdapter.png create mode 100644 wxPG/propgrid/docs/html/classwxPGGlobalVarsClass-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGGlobalVarsClass.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGInDialogValidator-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGInDialogValidator.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGLongStringDialogAdapter-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGLongStringDialogAdapter.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGLongStringDialogAdapter.png create mode 100644 wxPG/propgrid/docs/html/classwxPGMEditableState-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGMEditableState.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGMEditableState.png create mode 100644 wxPG/propgrid/docs/html/classwxPGMultiButton-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGMultiButton.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGPaintData-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGPropArgCls-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGPropArgCls.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxPGPropertyDataExt-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGPropertyDataExt.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGPropertyWithChildren-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGPropertyWithChildren.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGPropertyWithChildren.png create mode 100644 wxPG/propgrid/docs/html/classwxPGRootProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGRootProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGRootProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxPGStringTokenizer-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGStringTokenizer.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGTextCtrlAndButtonEditor-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGTextCtrlAndButtonEditor.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGTextCtrlAndButtonEditor.png create mode 100644 wxPG/propgrid/docs/html/classwxPGTextCtrlEditor-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGTextCtrlEditor.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGTextCtrlEditor.png create mode 100644 wxPG/propgrid/docs/html/classwxPGVIterator-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGVIterator.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGVIteratorBase-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGVIteratorBase.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGValidationInfo-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGVariantData-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGVariantData.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGWindowList-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPGWindowList.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyCategory-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyCategory.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyCategory.png create mode 100644 wxPG/propgrid/docs/html/classwxPropertyContainerMethods-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyContainerMethods.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyContainerMethods.png create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGrid-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGrid.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGrid.png create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridConstIterator-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridConstIterator.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridConstIterator.png create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridEvent-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridEvent.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridHitTestResult-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridHitTestResult.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridInterface-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridInterface.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridInterface.png create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridIterator-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridIterator.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridIterator.png create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridIteratorBase-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridIteratorBase.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridIteratorBase.png create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridManager-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridManager.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridManager.png create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridPage-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridPage.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridPage.png create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridPopulator-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridPopulator.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridState-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridState.htm create mode 100644 wxPG/propgrid/docs/html/classwxPropertyGridState.png create mode 100644 wxPG/propgrid/docs/html/classwxStringProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxStringProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxStringProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxSystemColourProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxSystemColourProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxSystemColourProperty.png create mode 100644 wxPG/propgrid/docs/html/classwxUIntProperty-members.htm create mode 100644 wxPG/propgrid/docs/html/classwxUIntProperty.htm create mode 100644 wxPG/propgrid/docs/html/classwxUIntProperty.png create mode 100644 wxPG/propgrid/docs/html/deprecated.htm create mode 100644 wxPG/propgrid/docs/html/doxygen.css create mode 100644 wxPG/propgrid/docs/html/doxygen.png create mode 100644 wxPG/propgrid/docs/html/functions.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x62.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x63.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x64.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x65.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x66.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x67.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x68.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x69.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x6c.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x6d.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x6e.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x6f.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x70.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x72.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x73.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x74.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x75.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x76.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x77.htm create mode 100644 wxPG/propgrid/docs/html/functions_0x7e.htm create mode 100644 wxPG/propgrid/docs/html/functions_enum.htm create mode 100644 wxPG/propgrid/docs/html/functions_eval.htm create mode 100644 wxPG/propgrid/docs/html/functions_func.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x62.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x63.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x64.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x65.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x66.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x67.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x68.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x69.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x6c.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x6d.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x6e.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x6f.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x70.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x72.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x73.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x74.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x75.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x76.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x77.htm create mode 100644 wxPG/propgrid/docs/html/functions_func_0x7e.htm create mode 100644 wxPG/propgrid/docs/html/functions_vars.htm create mode 100644 wxPG/propgrid/docs/html/group__attrids.htm create mode 100644 wxPG/propgrid/docs/html/group__iteratorflags.htm create mode 100644 wxPG/propgrid/docs/html/group__miscellaneous.htm create mode 100644 wxPG/propgrid/docs/html/group__pgactions.htm create mode 100644 wxPG/propgrid/docs/html/group__propflags.htm create mode 100644 wxPG/propgrid/docs/html/group__vfbflags.htm create mode 100644 wxPG/propgrid/docs/html/group__wndflags.htm create mode 100644 wxPG/propgrid/docs/html/hierarchy.htm create mode 100644 wxPG/propgrid/docs/html/index.htm create mode 100644 wxPG/propgrid/docs/html/modules.htm create mode 100644 wxPG/propgrid/docs/html/pages.htm create mode 100644 wxPG/propgrid/docs/html/structwxPGChoiceInfo-members.htm create mode 100644 wxPG/propgrid/docs/html/structwxPGChoiceInfo.htm create mode 100644 wxPG/propgrid/docs/html/structwxPGPaintData-members.htm create mode 100644 wxPG/propgrid/docs/html/structwxPGPaintData.htm create mode 100644 wxPG/propgrid/docs/html/structwxPGValidationInfo.htm create mode 100644 wxPG/propgrid/docs/html/structwxPropertyGridHitTestResult-members.htm create mode 100644 wxPG/propgrid/docs/html/structwxPropertyGridHitTestResult.htm create mode 100644 wxPG/propgrid/docs/html/tab_b.gif create mode 100644 wxPG/propgrid/docs/html/tab_l.gif create mode 100644 wxPG/propgrid/docs/html/tab_r.gif create mode 100644 wxPG/propgrid/docs/html/tabs.css create mode 100644 wxPG/propgrid/include/wx/propgrid/advprops.h create mode 100644 wxPG/propgrid/include/wx/propgrid/editors.h create mode 100644 wxPG/propgrid/include/wx/propgrid/extras.h create mode 100644 wxPG/propgrid/include/wx/propgrid/manager.h create mode 100644 wxPG/propgrid/include/wx/propgrid/odcombo.h create mode 100644 wxPG/propgrid/include/wx/propgrid/pg_dox_mainpage.h create mode 100644 wxPG/propgrid/include/wx/propgrid/propdev.h create mode 100644 wxPG/propgrid/include/wx/propgrid/propgrid.h create mode 100644 wxPG/propgrid/include/wx/propgrid/props.h create mode 100644 wxPG/propgrid/include/wx/propgrid/xh_propgrid.h create mode 100644 wxPG/propgrid/lib/filler.txt create mode 100644 wxPG/propgrid/lib/vc_dll/wxcode_msw28_propgrid.dll create mode 100644 wxPG/propgrid/lib/vc_dll/wxcode_msw28_propgrid.exp create mode 100644 wxPG/propgrid/lib/vc_dll/wxcode_msw28_propgrid.lib create mode 100644 wxPG/propgrid/lib/vc_dll/wxcode_msw28d_propgrid.dll create mode 100644 wxPG/propgrid/lib/vc_dll/wxcode_msw28d_propgrid.exp create mode 100644 wxPG/propgrid/lib/vc_dll/wxcode_msw28d_propgrid.idb create mode 100644 wxPG/propgrid/lib/vc_dll/wxcode_msw28d_propgrid.ilk create mode 100644 wxPG/propgrid/lib/vc_dll/wxcode_msw28d_propgrid.lib create mode 100644 wxPG/propgrid/lib/vc_dll/wxcode_msw28d_propgrid.pdb create mode 100644 wxPG/propgrid/locale/fi.mo create mode 100644 wxPG/propgrid/locale/fi.po create mode 100644 wxPG/propgrid/locale/it.mo create mode 100644 wxPG/propgrid/locale/it.po create mode 100644 wxPG/propgrid/locale/pl.mo create mode 100644 wxPG/propgrid/locale/pl.po create mode 100644 wxPG/propgrid/locale/propgrid.pot create mode 100644 wxPG/propgrid/patch_wx26/include/wx/variant.h create mode 100644 wxPG/propgrid/patch_wx26/propgrid-patch-wxvariant-README.txt create mode 100644 wxPG/propgrid/patch_wx26/src/common/variant.cpp create mode 100644 wxPG/propgrid/samples/minimal.cpp create mode 100644 wxPG/propgrid/samples/propgridsample.cpp create mode 100644 wxPG/propgrid/samples/propgridsample.h create mode 100644 wxPG/propgrid/samples/propgridsample_temp.cpp create mode 100644 wxPG/propgrid/samples/sample.ico create mode 100644 wxPG/propgrid/samples/sample.rc create mode 100644 wxPG/propgrid/samples/sample.xrc create mode 100644 wxPG/propgrid/samples/sampleprops.cpp create mode 100644 wxPG/propgrid/samples/sampleprops.h create mode 100644 wxPG/propgrid/samples/tests.cpp create mode 100644 wxPG/propgrid/src/advprops.cpp create mode 100644 wxPG/propgrid/src/editors.cpp create mode 100644 wxPG/propgrid/src/extras.cpp create mode 100644 wxPG/propgrid/src/manager.cpp create mode 100644 wxPG/propgrid/src/odcombo.cpp create mode 100644 wxPG/propgrid/src/propgrid.cpp create mode 100644 wxPG/propgrid/src/props.cpp create mode 100644 wxPG/propgrid/src/xh_propgrid.cpp create mode 100644 wxPG/uninstall-propgrid.exe create mode 100644 wxPG/wxPG.zip diff --git a/SQLite3/LibX86/sqlite3.def b/SQLite3/LibX86/sqlite3.def new file mode 100644 index 000000000..e314cb85b --- /dev/null +++ b/SQLite3/LibX86/sqlite3.def @@ -0,0 +1,205 @@ +EXPORTS +sqlite3_aggregate_context +sqlite3_aggregate_count +sqlite3_auto_extension +sqlite3_backup_finish +sqlite3_backup_init +sqlite3_backup_pagecount +sqlite3_backup_remaining +sqlite3_backup_step +sqlite3_bind_blob +sqlite3_bind_double +sqlite3_bind_int +sqlite3_bind_int64 +sqlite3_bind_null +sqlite3_bind_parameter_count +sqlite3_bind_parameter_index +sqlite3_bind_parameter_name +sqlite3_bind_text +sqlite3_bind_text16 +sqlite3_bind_value +sqlite3_bind_zeroblob +sqlite3_blob_bytes +sqlite3_blob_close +sqlite3_blob_open +sqlite3_blob_read +sqlite3_blob_reopen +sqlite3_blob_write +sqlite3_busy_handler +sqlite3_busy_timeout +sqlite3_changes +sqlite3_clear_bindings +sqlite3_close +sqlite3_collation_needed +sqlite3_collation_needed16 +sqlite3_column_blob +sqlite3_column_bytes +sqlite3_column_bytes16 +sqlite3_column_count +sqlite3_column_database_name +sqlite3_column_database_name16 +sqlite3_column_decltype +sqlite3_column_decltype16 +sqlite3_column_double +sqlite3_column_int +sqlite3_column_int64 +sqlite3_column_name +sqlite3_column_name16 +sqlite3_column_origin_name +sqlite3_column_origin_name16 +sqlite3_column_table_name +sqlite3_column_table_name16 +sqlite3_column_text +sqlite3_column_text16 +sqlite3_column_type +sqlite3_column_value +sqlite3_commit_hook +sqlite3_compileoption_get +sqlite3_compileoption_used +sqlite3_complete +sqlite3_complete16 +sqlite3_config +sqlite3_context_db_handle +sqlite3_create_collation +sqlite3_create_collation16 +sqlite3_create_collation_v2 +sqlite3_create_function +sqlite3_create_function16 +sqlite3_create_function_v2 +sqlite3_create_module +sqlite3_create_module_v2 +sqlite3_data_count +sqlite3_db_config +sqlite3_db_filename +sqlite3_db_handle +sqlite3_db_mutex +sqlite3_db_readonly +sqlite3_db_release_memory +sqlite3_db_status +sqlite3_declare_vtab +sqlite3_enable_load_extension +sqlite3_enable_shared_cache +sqlite3_errcode +sqlite3_errmsg +sqlite3_errmsg16 +sqlite3_exec +sqlite3_expired +sqlite3_extended_errcode +sqlite3_extended_result_codes +sqlite3_file_control +sqlite3_finalize +sqlite3_free +sqlite3_free_table +sqlite3_get_autocommit +sqlite3_get_auxdata +sqlite3_get_table +sqlite3_global_recover +sqlite3_initialize +sqlite3_interrupt +sqlite3_last_insert_rowid +sqlite3_libversion +sqlite3_libversion_number +sqlite3_limit +sqlite3_load_extension +sqlite3_log +sqlite3_malloc +sqlite3_memory_alarm +sqlite3_memory_highwater +sqlite3_memory_used +sqlite3_mprintf +sqlite3_mutex_alloc +sqlite3_mutex_enter +sqlite3_mutex_free +sqlite3_mutex_leave +sqlite3_mutex_try +sqlite3_next_stmt +sqlite3_open +sqlite3_open16 +sqlite3_open_v2 +sqlite3_os_end +sqlite3_os_init +sqlite3_overload_function +sqlite3_prepare +sqlite3_prepare16 +sqlite3_prepare16_v2 +sqlite3_prepare_v2 +sqlite3_profile +sqlite3_progress_handler +sqlite3_randomness +sqlite3_realloc +sqlite3_release_memory +sqlite3_reset +sqlite3_reset_auto_extension +sqlite3_result_blob +sqlite3_result_double +sqlite3_result_error +sqlite3_result_error16 +sqlite3_result_error_code +sqlite3_result_error_nomem +sqlite3_result_error_toobig +sqlite3_result_int +sqlite3_result_int64 +sqlite3_result_null +sqlite3_result_text +sqlite3_result_text16 +sqlite3_result_text16be +sqlite3_result_text16le +sqlite3_result_value +sqlite3_result_zeroblob +sqlite3_rollback_hook +sqlite3_rtree_geometry_callback +sqlite3_set_authorizer +sqlite3_set_auxdata +sqlite3_shutdown +sqlite3_sleep +sqlite3_snprintf +sqlite3_soft_heap_limit +sqlite3_soft_heap_limit64 +sqlite3_sourceid +sqlite3_sql +sqlite3_status +sqlite3_step +sqlite3_stmt_busy +sqlite3_stmt_readonly +sqlite3_stmt_status +sqlite3_stricmp +sqlite3_strnicmp +sqlite3_table_column_metadata +sqlite3_test_control +sqlite3_thread_cleanup +sqlite3_threadsafe +sqlite3_total_changes +sqlite3_trace +sqlite3_transfer_bindings +sqlite3_update_hook +sqlite3_uri_boolean +sqlite3_uri_int64 +sqlite3_uri_parameter +sqlite3_user_data +sqlite3_value_blob +sqlite3_value_bytes +sqlite3_value_bytes16 +sqlite3_value_double +sqlite3_value_int +sqlite3_value_int64 +sqlite3_value_numeric_type +sqlite3_value_text +sqlite3_value_text16 +sqlite3_value_text16be +sqlite3_value_text16le +sqlite3_value_type +sqlite3_vfs_find +sqlite3_vfs_register +sqlite3_vfs_unregister +sqlite3_vmprintf +sqlite3_vsnprintf +sqlite3_vtab_config +sqlite3_vtab_on_conflict +sqlite3_wal_autocheckpoint +sqlite3_wal_checkpoint +sqlite3_wal_checkpoint_v2 +sqlite3_wal_hook +sqlite3_win32_mbcs_to_utf8 +sqlite3_win32_sleep +sqlite3_win32_utf8_to_mbcs +sqlite3_win32_write_debug diff --git a/SQLite3/LibX86/sqlite3.dll b/SQLite3/LibX86/sqlite3.dll new file mode 100644 index 0000000000000000000000000000000000000000..45b2e4eb377d3a3a8948867a7418ee9bb2f0b32c GIT binary patch literal 599419 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]=!;~Tiy&%)0Wb&Xrp6B&=sN6#p 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 P{j2GYT*1k>s*;LMp43Jq>d2M#P=P_; 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 Ap#T5? literal 0 HcmV?d00001 diff --git a/SQLite3/LibX86/sqlite3.exp b/SQLite3/LibX86/sqlite3.exp new file mode 100644 index 0000000000000000000000000000000000000000..967c8f53177f324e5818c7c739cd4329aa3f638d GIT binary patch literal 28975 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 b-EG3Z<{LG3bL3Ub%Z*oP<;1I)nG65Fw$b6b literal 0 HcmV?d00001 diff --git a/SQLite3/LibX86/sqlite3.lib b/SQLite3/LibX86/sqlite3.lib new file mode 100644 index 0000000000000000000000000000000000000000..a35ac11f45ccf2df9640fedc0dd0f0c341b806ac GIT binary patch literal 48640 zcmeHQYp@+fwO#~842m%-A|eKi0Td&Ilkkv>AtDNdfFU3vxUEX(3r{;({|;s<3}6s7m;o}QVt*7S5{&OTJ#A2(HB zX7=i}`kU_Q?&)5$dd|)VR6Dit180A6p8U7h-b0HPEg9NxXo-~X>3;6D*M3W)^VPG7 zwz!e##J7o7&nK!LPc-~sgc^QZ+<+r6vaQ1g91Y%zP+vo2@dl2-=t_rIa0JGN9B#)E z7@zB~0Y`&(A~dFmEZ)QsShL#UH#h<(EpvDZN1(aD;Tjx)iLD%_a5VT!gw}CH7O&w5 zv=4B&A4gzvCx?wV0wwxP~j}|ZC2;8vHVH1wPjkwPi8*nsuGs313A`8^vCg7&S9A3Z? zxOq>9+i?VLK{+fg!4bF>_u1l191W1K!EM71zr_)_{Sb%ea0Ko^z7}`m2;8~71M<8R zxNDXJ^1RF7tq6CI5?LV6yMcR_Iy{UcaPNEvl=)uZzS#~v91Y%xa6igvfor)RcwnK! ztvCV?ZtHLwjt0121`pxBTl^76;NcYxuiywgf_yAcrbmEBQ7(&(I2ybi;jtEx1@d?d zcpUjyyo@98#E=8>cmjA5^=^SS@Fehka+t)?;7<{rI+n=dH5`Gb_jkA#N8p(q94^7p z;GGE1Hi;~7Ezbhat#Ux0cn)}eslzik0xv9ZxEV*_#W@bRwihp`R1Q7js3TXdsvP{) zqrbB9(4$rzxw6tdx!LH|_ohl^#WBm5XBFrSrxB&E`uZ^|4zC=1(5i!A(U_R5#2Hko zV`H8AShZKL)Y`3HeO-@2N%^+@R*t1jPR7$j7DaMKEX8ZtsZUgqaceAdfh@&q+3nRQGe(h6={H&< zmEmT4m}#dXkM2mjKisSUwhS)N}J*+rc2JGIuhSd%wHBGG1+sH0vFvFQgueUSp!(?(?C?SR_(u zQA7S?yvh@S(rebMor-Br7-rZVswug)5;w?uZ))vkv)aRuTxr$oBXw5o*%Xz#vgA!! z+h$udH2M=QHKqw+hRy2B78)Bw(tHbbZAnhK*QG`v$K#}4o{?&=I$Z76D{|m)mMV4g zIe4yEydDD@R#w9HnKgo0t}f%bbiPeoa};6IR#PhFYTyHfP0J!2Z^G+7&`& zWY|3m`DJ91lr0|Gc9G#8G0ZfR61Eg2QnsFwDUHh1qI_zb=w%=6w`%5YXKd4ipq=NU zW6RuYjum{DEYiHp6YY^cpY_+GiipJl8y{a}=BXd^AkuSmE|WZHIdRj9*QZRB(H%uE zlLIQWQ(;CwnxUolh&9xV?nEC0lu&h&j3z2>q}^(+7s{#7qmP*w9{v;ciFQX@$)t>J zw^!};*`y97h($^l&*5sPUYWx1%q~nwr3GrzJRzFx>WFXgos;a%qdN}jkxH#v8)rk2 z%Rwe8`%b6U9^p2zAfq?YW#du3)3LvOTD)sTdf6UTUstcCwG{nQd99mlpiErJ3A7&E z7ML4XK&6Ue92z1e$FfuJ_M1I)gb_a5xBd`gE|X;*rtO;^)a$g_Qd&y2MXTCuoWiOc z4iqO*nw>h=vcIw#6+0bBt7#N^u}o^?xmc;fqZ2(yQwuHkS*soSh}d+@Dv>z!Vu(_Y(P ztEJ`fdDMY1v`6QpIpMkzQsr_{LJN#du?Ed@Uv=Y(?*^Sc=zDPTQQ3Z@xA$*}>f( zWtSBTRKDh6go~BM$G@}rh)Io6^UP)1-3mtVw1(o}Dz`5BEbkFeiv&s! z{nNJpc&^4W&L&CQ$xa;}N>=-cz^lirz-eZmfk}d>3MuvG?$h_w-ejk39zPeJB`LBjO-aX9pFd8xUU z`>fQQI5P3hiM!+d-bi~bb5^7hm2U`>)N)*e zmXoaVsAKJuS;^v+Baf~8U{lDc-FSJNFX^J>f2fKJ`_7LX*&H2`D!mRlW9KdXoet563Ozkvy~M+-t`C? zT|tz_rwm%2&%-AS+$uX?aH-;@5SJ;A(XI&`Vr#ppM3U7+KvV-GJ9|DG?Npkz=(p0; zq-J5m<;p7K8kkBXN;7@jCRwKgj&TtuLXSS)_ZyRDqsA8H)<~pC%e5FM zt#@y{UOQ>BEtx&e3#SW_o@16Vmq^a?OEh6q()?l^RScYvt| z(VM{PHAKGwmYsy?N?-w^Ca(dunt%@Q7vMNVcD@E2&_-k_uoI#)Hv%T)d>!yt;Dip* zuYqMBtut`Yx^k*yRjF_X2az#I*pk&cgKqe*;d~fP8@i&&D+XJD!6`Xke>z zp#%H{7&(vVkHGTt!3``xl;>r@zkuF_s2gB-BgzEqe-Su=oi2tBV8X6@z@LFth&X*6 zIN(x5u>$ihLliXdFJR5(M1KHQUP1IKu;@xe0t4G!g-CJWpTPLlM85-;U4v@{cDxqR z;lMwD)^)H4mS0cw60qn zCNO*((Qko6Zbt+xu;(3!I0m-A6S}~xyPyla1&rPeU0~@wxGrG+z2F9B--ogTZvcng zk9>fI40^_27!f-fD73EQQR-!ZJ_lSbbu9)6TJ)!JpmnH zyC+cxfC&kn1pWjZ`xM$Bu>aGDf(CYY2GuK&}V2qeU=u`uCyENPM@RC(;oB%T1a1{J!vmmM0?W^Ev6;35A93) z(f;%$I)MIz4x}&BQaXs1(O2kT`YIhlU!$+np>!A>PRr>CT0uwBQS=R3Nk`KvI);v= zZ_;t}EjpgQO()Qa^c||uYO2yO)o6t3G)iMMP7PW^CsC6os6}m>M2GB9mwMEvDOyYG zXg!@mr_yP3I(?VUpfl+#+CXR1Idm?aN9WT8bRlh|i|ArB=u7BQx{NNTE9gqPims+> z=vumtuBRL5M%qL-(am%V-AcF7?Q{p-Nq5oRbPwH2_tE|I06j<#(ZlozJxY(!~j#?1pm6lCVAE< zu{`U0u_-Qw0z55rcK0KEbczQqGKvz8`&)7Pd7hG41; zF{a2k%W%4fSmoeZOuJaZ^u@N9BTmkxh!ye~ibg9+e$!k151nGchAOu-+BK7~`H;bk zN%*yL!FWHJ>-0nSR6cP?TSgoVzEj#Z)K1F^#?oms7g6V4^|^>SsZ=cZP1$TFxJ_!8 z2w2M++7V7a42uVx$qX^l7mg&8mT8oizLqp49RH>AQvqK(H8++^Dwd1V^4bQ&u9QW= zfGVHWX5*xMM&bA;X%Px<%4&Ls%*{kAsXPitAW6Fb3t#pVNEyvE)srz@3jLFkfvb2*lj zohXRJ0>LKUi}g!c!pAzkrTSVmI$m+`Q}GXC`B77 zp=C*IgeSo)hog-ap2W=rH)xAanaBlcTqX!XS=vy90)Yj}tYFB1v?>|`psWhM+E-RZ zUf4^M=w+8wqW7tPA5&^u&hW8Nf}d?_q*knd^rpd?d0^Mx|+Y!$J6b6fZotk0OgOAUP_C4TFh zaVjSX>N_W~Tse}JSO%SEzel3f+4n|NO5`w3gvNmyIo*UP?twyRyPlTt*cIzQm4U2Q zlyL@&Owv^62F^*9djW06(Ud~y$Ng0ZZHG)>tt&@wqH3J4zAs<+zHbrD*oCQif-w^A z$`yL>o$!xvMxG=$N}0{^{@v@cAToT(1c{nW zLu@l|avjQ5$u2{s2m+O6pED}U*fp8SF;4Jg7$^DiiyfJYhHa~kQ@Haok)`olOk_M? zvN3w92%_vxXERKBb~Ixk@o!s>=iUjq*k&9{bKH*AO>v*HCTLY?%xYD5*8>PEu6N%VO$M?a;8rpFvc(Z2mJG4!cZManWas)|2Boi&} z(vw2(?nvJjNHqKGMn|!mk?l~7Ipo9N{NioX{1(GN?3_!?<2{3kAnTBelbri3t=h!b z<`D^2?s!Xc%Wl(CyY6CDzPB!s#SXSq;2$>7x%hLz{>)Z{eObx%DJbzDZsUL~SrkaGh7rUThNi=VB(=5-n8L{^zF;cr*q+IQ5k=s-f)yxJJ zz2PL*6fUJi$hVGgp=#@9(@3(AOGhTQ*CRHLoFlTcJDFTkFd^?0kywulkyLcbM8sQ3 zB$N&zd1bO^M*2|?OpC>(ykBxT@0Lz3_bVjMo`hfQGvHG0;7R0}$Kh1!)Jc?#&&InY zKsa(@b>m?P#r3B__Gw*s+%`Nr6?X3lp-;5AlST?<6ueC1j+ry!B>P=l_T5`2UpUfi z+Cccteer#0zrEeJ-&fCGzQvZ*Id+Sqwm}r{)(8&9zbzKpc>DQBM?VSiwfHu6{KFlW z(wt=r8)im7e^H$DQJnk|_#Y?O633;q=gUrSi4!9-nCRa?tY_p)Y2M4TaGZ$5<{r_gb=t<+KX12{yU$yG=!(N_s`}568AFo+AsE)2&B6cg zwP%clmYPKzuC+b2iT;i2i|CAn`DZR}7R5zgir8u+8IL8laK>WGSTbaEAV_rrW&21>NS#b-sltqix}GpJ^%YN((4*Uq6LQ$^GDT=~~-o-%S7dZxBQ`*IPGhK!5HI?sTdc4@x30#G=QDcvh!kf8(`ha!c?V5oTmhUZl`PkRMHUhwgKko9UfyVUB^pu>UejQ`9lF_>ka3`rE7a}4zuZ{pm%=Q%ZG*VV2nBKX&y>AH^XR`t%8t|7ivYJXXZyTe2IgK(M;o+87SjN1!wxc zmlLw{Vr2~QeJsNly-Q{sync)E1zPEL89wW(=5#aKD?Xm#GafTuq-os0K(E-|!#4vZ z4BWv_WEi8@_qJ^FFvejAgD?)|tVhf;a!1Y> zhcs}q@@+J*9{7}ClkpOql${r<)1jP|&nHpBog}A;#bDV_qfZ3p$DbBlDx5>mvP&pb zLia}x(OBgwYd4f|UWiparpodz4vYXhE8gU9hcJ?9)Ni0i?&4##u4+!n&I{G;;y{c2 zOdjK)^%^MUd=F<7wZlrrTT`J@hGvnU^)QN!m2W>l{C(J?*CkvYsorN`~VxvP&`!Vb4FNS$lk;^iN z{Iq*|nA3PaQQ*=&CbX*FE6A$~T$(xbG+*RnHbIQ6TBk7*23qpoIgIaSDTjQV=4J3; zr3{Qoi#?1pu$m8yNlPSS`ZtvZD`Vi9wvS>|e|l*k-q5(TZ$7V$SL4L&ywJFmyi8Ox zZsR@OPxIPnTE@VeQ!%!jQE(pE_V=-=PQthg@eSpyVs-@Imn5H!0%rM_FI%AH9H6+2 zCyzxKbK3HwT}~Oz`;-3=yebfxmyn+qs@YI`Jut*N;2jM;RlXeJHIa&g)pKBuz0|`T z$7c`78faAq1z1%zmu^*|`@1Z_tE-t+d7*X{^51^N!|Nj58O=1F-hm!;a4zS-B@K*) zU*)VUM4uOvofoUwfEV`=!IuPZF^Xx_YT()ZHN}_gEf|b3P{OY(M)$Yd2IC97c|26{ zMY|$69Xl^}{{r=Sm|{z!NEyjA?qFc-IXuHC;<5+h4cy1&iq{3k4#pRl*B&AG_(l{? z$<7Pi%OyGY^7D9Rui%XSO)iYC{9O$_L67usiybrrF^4?#M+s)PJ!desoKfA({l1~t z%-$bP#?A}f&(JJ-WtK}loXfHe<#=*;K*^34Z06%gEO&lhs9d2twn{QZ`=K~l={d*Z zoI7S_vd2g^wb_c(vhzY^4E4ohy{v9`L$r~L(UtFuivuIiH#xW1CB`Y)d7;vVTIz9< z(f!><#!$Zf1X}911e@92HVD(=z-;Px&E)=G<3M~lB{T7W-{yR3SKdIJIZq7}n|DH% zGujoy3Cs7$z?1ky&1fBm;wF~o3)Jd&1fSfi$P3BNi}i>=%c*cqwhxkV@B$a(3)Jaq z$rtaja&cS#C^*Stg)7_z*kewH+*FZUIe!h6;DWfVshKJtDk4Rp# zt#u%-&^z3^;F5c0IVn3YRIfuhzU@z7)ESkWauQX#rG~t9W1Put_GKmE)mo@jp(pRS z;NlyJ2VxA&ZWnIs4^GR@2d>laa#r^B5XLd1 zJ^u{B=e|tB$;!9UzF>30YIa_z zl%aXy*@`*&s4^odU)Io@%X2)8GqU$B;6FUq!x??Wh8L5a7pvDmi#;!oQ4Qs#Idh&< z=J|Mj9%uCR9Y$6Dj)vZWUy#ciecFc;v-3iA9C|}@VJ@%xY!D+WU*gacY@>(y-HdX* z$j|pKM!8<>VH|u%WoRV&o`-P;cKPLaY|Os#OL7=h7cKuJ3q;3Un#+k#*$mcR1FVsN$G>vC;U^aAPfK@#>XS8lNN#1^^R&U5nxva>A z>NfP&;U>X`Z|P#n9^KwhZ44#is@Q)VF6iXChK8l#KyijRFPx^ZVqx>Q!f=2_1+lw6pC2#ihPMIv8(Y+=5sQ(-?IEWqed{CV!7;usRL&|Hn9A^z~Nz z#ad3t&WnvVfp+@1hcEMqfzrJ{Gz)klhjC!fL*Uu*WR}z8b}e16fp+u#ETeXkm9N#n zeSFHxH)wARc|M=cGK#Mov)bg{vsjA_^pIz=yct&+<1WS*XgkmP`BZZ)&6u+SFma>L zMMeeebRg|#=sl& zA7vQ%_tH5nJ1^97LSy->oYnI!cE&ZME%wKnmwo4bAkKhq>?ir0IuN6LTMG1)pK4zF zf%-v88M>oC6KvU!-w(nY@>Ksk%NzamLrz$_UPC2)Ez2mr+RusEd7(ZNT3P-g%gg^F J0HdPW{|kCbf7t*4 literal 0 HcmV?d00001 diff --git a/SQLite3/include/shell.c b/SQLite3/include/shell.c new file mode 100644 index 000000000..d097e913a --- /dev/null +++ b/SQLite3/include/shell.c @@ -0,0 +1,4814 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code to implement the "sqlite" command line +** utility for accessing SQLite databases. +*/ +#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS) +/* This needs to come before any includes for MSVC compiler */ +#define _CRT_SECURE_NO_WARNINGS +#endif + +/* +** If requested, include the SQLite compiler options file for MSVC. +*/ +#if defined(INCLUDE_MSVC_H) +#include "msvc.h" +#endif + +/* +** No support for loadable extensions in VxWorks. +*/ +#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION +# define SQLITE_OMIT_LOAD_EXTENSION 1 +#endif + +/* +** Enable large-file support for fopen() and friends on unix. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + +#include +#include +#include +#include +#include "sqlite3.h" +#if SQLITE_USER_AUTHENTICATION +# include "sqlite3userauth.h" +#endif +#include +#include + +#if !defined(_WIN32) && !defined(WIN32) +# include +# if !defined(__RTP__) && !defined(_WRS_KERNEL) +# include +# endif +# include +# include +#endif + +#if HAVE_READLINE +# include +# include +#endif + +#if HAVE_EDITLINE +# include +#endif + +#if HAVE_EDITLINE || HAVE_READLINE + +# define shell_add_history(X) add_history(X) +# define shell_read_history(X) read_history(X) +# define shell_write_history(X) write_history(X) +# define shell_stifle_history(X) stifle_history(X) +# define shell_readline(X) readline(X) + +#elif HAVE_LINENOISE + +# include "linenoise.h" +# define shell_add_history(X) linenoiseHistoryAdd(X) +# define shell_read_history(X) linenoiseHistoryLoad(X) +# define shell_write_history(X) linenoiseHistorySave(X) +# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X) +# define shell_readline(X) linenoise(X) + +#else + +# define shell_read_history(X) +# define shell_write_history(X) +# define shell_stifle_history(X) + +# define SHELL_USE_LOCAL_GETLINE 1 +#endif + + +#if defined(_WIN32) || defined(WIN32) +# include +# include +# define isatty(h) _isatty(h) +# ifndef access +# define access(f,m) _access((f),(m)) +# endif +# undef popen +# define popen _popen +# undef pclose +# define pclose _pclose +#else + /* Make sure isatty() has a prototype. */ + extern int isatty(int); + +# if !defined(__RTP__) && !defined(_WRS_KERNEL) + /* popen and pclose are not C89 functions and so are + ** sometimes omitted from the header */ + extern FILE *popen(const char*,const char*); + extern int pclose(FILE*); +# else +# define SQLITE_OMIT_POPEN 1 +# endif +#endif + +#if defined(_WIN32_WCE) +/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty() + * thus we always assume that we have a console. That can be + * overridden with the -batch command line option. + */ +#define isatty(x) 1 +#endif + +/* ctype macros that work with signed characters */ +#define IsSpace(X) isspace((unsigned char)X) +#define IsDigit(X) isdigit((unsigned char)X) +#define ToLower(X) (char)tolower((unsigned char)X) + +/* On Windows, we normally run with output mode of TEXT so that \n characters +** are automatically translated into \r\n. However, this behavior needs +** to be disabled in some cases (ex: when generating CSV output and when +** rendering quoted strings that contain \n characters). The following +** routines take care of that. +*/ +#if defined(_WIN32) || defined(WIN32) +static void setBinaryMode(FILE *out){ + fflush(out); + _setmode(_fileno(out), _O_BINARY); +} +static void setTextMode(FILE *out){ + fflush(out); + _setmode(_fileno(out), _O_TEXT); +} +#else +# define setBinaryMode(X) +# define setTextMode(X) +#endif + + +/* True if the timer is enabled */ +static int enableTimer = 0; + +/* Return the current wall-clock time */ +static sqlite3_int64 timeOfDay(void){ + static sqlite3_vfs *clockVfs = 0; + sqlite3_int64 t; + if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); + if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){ + clockVfs->xCurrentTimeInt64(clockVfs, &t); + }else{ + double r; + clockVfs->xCurrentTime(clockVfs, &r); + t = (sqlite3_int64)(r*86400000.0); + } + return t; +} + +#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux) +#include +#include + +/* VxWorks does not support getrusage() as far as we can determine */ +#if defined(_WRS_KERNEL) || defined(__RTP__) +struct rusage { + struct timeval ru_utime; /* user CPU time used */ + struct timeval ru_stime; /* system CPU time used */ +}; +#define getrusage(A,B) memset(B,0,sizeof(*B)) +#endif + +/* Saved resource information for the beginning of an operation */ +static struct rusage sBegin; /* CPU time at start */ +static sqlite3_int64 iBegin; /* Wall-clock time at start */ + +/* +** Begin timing an operation +*/ +static void beginTimer(void){ + if( enableTimer ){ + getrusage(RUSAGE_SELF, &sBegin); + iBegin = timeOfDay(); + } +} + +/* Return the difference of two time_structs in seconds */ +static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ + return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + + (double)(pEnd->tv_sec - pStart->tv_sec); +} + +/* +** Print the timing results. +*/ +static void endTimer(void){ + if( enableTimer ){ + sqlite3_int64 iEnd = timeOfDay(); + struct rusage sEnd; + getrusage(RUSAGE_SELF, &sEnd); + printf("Run Time: real %.3f user %f sys %f\n", + (iEnd - iBegin)*0.001, + timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), + timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); + } +} + +#define BEGIN_TIMER beginTimer() +#define END_TIMER endTimer() +#define HAS_TIMER 1 + +#elif (defined(_WIN32) || defined(WIN32)) + +#include + +/* Saved resource information for the beginning of an operation */ +static HANDLE hProcess; +static FILETIME ftKernelBegin; +static FILETIME ftUserBegin; +static sqlite3_int64 ftWallBegin; +typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, + LPFILETIME, LPFILETIME); +static GETPROCTIMES getProcessTimesAddr = NULL; + +/* +** Check to see if we have timer support. Return 1 if necessary +** support found (or found previously). +*/ +static int hasTimer(void){ + if( getProcessTimesAddr ){ + return 1; + } else { + /* GetProcessTimes() isn't supported in WIN95 and some other Windows + ** versions. See if the version we are running on has it, and if it + ** does, save off a pointer to it and the current process handle. + */ + hProcess = GetCurrentProcess(); + if( hProcess ){ + HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); + if( NULL != hinstLib ){ + getProcessTimesAddr = + (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); + if( NULL != getProcessTimesAddr ){ + return 1; + } + FreeLibrary(hinstLib); + } + } + } + return 0; +} + +/* +** Begin timing an operation +*/ +static void beginTimer(void){ + if( enableTimer && getProcessTimesAddr ){ + FILETIME ftCreation, ftExit; + getProcessTimesAddr(hProcess,&ftCreation,&ftExit, + &ftKernelBegin,&ftUserBegin); + ftWallBegin = timeOfDay(); + } +} + +/* Return the difference of two FILETIME structs in seconds */ +static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ + sqlite_int64 i64Start = *((sqlite_int64 *) pStart); + sqlite_int64 i64End = *((sqlite_int64 *) pEnd); + return (double) ((i64End - i64Start) / 10000000.0); +} + +/* +** Print the timing results. +*/ +static void endTimer(void){ + if( enableTimer && getProcessTimesAddr){ + FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; + sqlite3_int64 ftWallEnd = timeOfDay(); + getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd); + printf("Run Time: real %.3f user %f sys %f\n", + (ftWallEnd - ftWallBegin)*0.001, + timeDiff(&ftUserBegin, &ftUserEnd), + timeDiff(&ftKernelBegin, &ftKernelEnd)); + } +} + +#define BEGIN_TIMER beginTimer() +#define END_TIMER endTimer() +#define HAS_TIMER hasTimer() + +#else +#define BEGIN_TIMER +#define END_TIMER +#define HAS_TIMER 0 +#endif + +/* +** Used to prevent warnings about unused parameters +*/ +#define UNUSED_PARAMETER(x) (void)(x) + +/* +** If the following flag is set, then command execution stops +** at an error if we are not interactive. +*/ +static int bail_on_error = 0; + +/* +** Threat stdin as an interactive input if the following variable +** is true. Otherwise, assume stdin is connected to a file or pipe. +*/ +static int stdin_is_interactive = 1; + +/* +** The following is the open SQLite database. We make a pointer +** to this database a static variable so that it can be accessed +** by the SIGINT handler to interrupt database processing. +*/ +static sqlite3 *globalDb = 0; + +/* +** True if an interrupt (Control-C) has been received. +*/ +static volatile int seenInterrupt = 0; + +/* +** This is the name of our program. It is set in main(), used +** in a number of other places, mostly for error messages. +*/ +static char *Argv0; + +/* +** Prompt strings. Initialized in main. Settable with +** .prompt main continue +*/ +static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ +static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ + +/* +** Write I/O traces to the following stream. +*/ +#ifdef SQLITE_ENABLE_IOTRACE +static FILE *iotrace = 0; +#endif + +/* +** This routine works like printf in that its first argument is a +** format string and subsequent arguments are values to be substituted +** in place of % fields. The result of formatting this string +** is written to iotrace. +*/ +#ifdef SQLITE_ENABLE_IOTRACE +static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){ + va_list ap; + char *z; + if( iotrace==0 ) return; + va_start(ap, zFormat); + z = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + fprintf(iotrace, "%s", z); + sqlite3_free(z); +} +#endif + + +/* +** Determines if a string is a number of not. +*/ +static int isNumber(const char *z, int *realnum){ + if( *z=='-' || *z=='+' ) z++; + if( !IsDigit(*z) ){ + return 0; + } + z++; + if( realnum ) *realnum = 0; + while( IsDigit(*z) ){ z++; } + if( *z=='.' ){ + z++; + if( !IsDigit(*z) ) return 0; + while( IsDigit(*z) ){ z++; } + if( realnum ) *realnum = 1; + } + if( *z=='e' || *z=='E' ){ + z++; + if( *z=='+' || *z=='-' ) z++; + if( !IsDigit(*z) ) return 0; + while( IsDigit(*z) ){ z++; } + if( realnum ) *realnum = 1; + } + return *z==0; +} + +/* +** A global char* and an SQL function to access its current value +** from within an SQL statement. This program used to use the +** sqlite_exec_printf() API to substitue a string into an SQL statement. +** The correct way to do this with sqlite3 is to use the bind API, but +** since the shell is built around the callback paradigm it would be a lot +** of work. Instead just use this hack, which is quite harmless. +*/ +static const char *zShellStatic = 0; +static void shellstaticFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + assert( 0==argc ); + assert( zShellStatic ); + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC); +} + + +/* +** This routine reads a line of text from FILE in, stores +** the text in memory obtained from malloc() and returns a pointer +** to the text. NULL is returned at end of file, or if malloc() +** fails. +** +** If zLine is not NULL then it is a malloced buffer returned from +** a previous call to this routine that may be reused. +*/ +static char *local_getline(char *zLine, FILE *in){ + int nLine = zLine==0 ? 0 : 100; + int n = 0; + + while( 1 ){ + if( n+100>nLine ){ + nLine = nLine*2 + 100; + zLine = realloc(zLine, nLine); + if( zLine==0 ) return 0; + } + if( fgets(&zLine[n], nLine - n, in)==0 ){ + if( n==0 ){ + free(zLine); + return 0; + } + zLine[n] = 0; + break; + } + while( zLine[n] ) n++; + if( n>0 && zLine[n-1]=='\n' ){ + n--; + if( n>0 && zLine[n-1]=='\r' ) n--; + zLine[n] = 0; + break; + } + } + return zLine; +} + +/* +** Retrieve a single line of input text. +** +** If in==0 then read from standard input and prompt before each line. +** If isContinuation is true, then a continuation prompt is appropriate. +** If isContinuation is zero, then the main prompt should be used. +** +** If zPrior is not NULL then it is a buffer from a prior call to this +** routine that can be reused. +** +** The result is stored in space obtained from malloc() and must either +** be freed by the caller or else passed back into this routine via the +** zPrior argument for reuse. +*/ +static char *one_input_line(FILE *in, char *zPrior, int isContinuation){ + char *zPrompt; + char *zResult; + if( in!=0 ){ + zResult = local_getline(zPrior, in); + }else{ + zPrompt = isContinuation ? continuePrompt : mainPrompt; +#if SHELL_USE_LOCAL_GETLINE + printf("%s", zPrompt); + fflush(stdout); + zResult = local_getline(zPrior, stdin); +#else + free(zPrior); + zResult = shell_readline(zPrompt); + if( zResult && *zResult ) shell_add_history(zResult); +#endif + } + return zResult; +} + +/* +** Shell output mode information from before ".explain on", +** saved so that it can be restored by ".explain off" +*/ +typedef struct SavedModeInfo SavedModeInfo; +struct SavedModeInfo { + int valid; /* Is there legit data in here? */ + int mode; /* Mode prior to ".explain on" */ + int showHeader; /* The ".header" setting prior to ".explain on" */ + int colWidth[100]; /* Column widths prior to ".explain on" */ +}; + +/* +** State information about the database connection is contained in an +** instance of the following structure. +*/ +typedef struct ShellState ShellState; +struct ShellState { + sqlite3 *db; /* The database */ + int echoOn; /* True to echo input commands */ + int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ + int statsOn; /* True to display memory stats before each finalize */ + int scanstatsOn; /* True to display scan stats before each finalize */ + int backslashOn; /* Resolve C-style \x escapes in SQL input text */ + int outCount; /* Revert to stdout when reaching zero */ + int cnt; /* Number of records displayed so far */ + FILE *out; /* Write results here */ + FILE *traceOut; /* Output for sqlite3_trace() */ + int nErr; /* Number of errors seen */ + int mode; /* An output mode setting */ + int writableSchema; /* True if PRAGMA writable_schema=ON */ + int showHeader; /* True to show column names in List or Column mode */ + unsigned shellFlgs; /* Various flags */ + char *zDestTable; /* Name of destination table when MODE_Insert */ + char colSeparator[20]; /* Column separator character for several modes */ + char rowSeparator[20]; /* Row separator character for MODE_Ascii */ + int colWidth[100]; /* Requested width of each column when in column mode*/ + int actualWidth[100]; /* Actual width of each column */ + char nullValue[20]; /* The text to print when a NULL comes back from + ** the database */ + SavedModeInfo normalMode;/* Holds the mode just before .explain ON */ + char outfile[FILENAME_MAX]; /* Filename for *out */ + const char *zDbFilename; /* name of the database file */ + char *zFreeOnClose; /* Filename to free when closing */ + const char *zVfs; /* Name of VFS to use */ + sqlite3_stmt *pStmt; /* Current statement if any. */ + FILE *pLog; /* Write log output here */ + int *aiIndent; /* Array of indents used in MODE_Explain */ + int nIndent; /* Size of array aiIndent[] */ + int iIndent; /* Index of current op in aiIndent[] */ +}; + +/* +** These are the allowed shellFlgs values +*/ +#define SHFLG_Scratch 0x00001 /* The --scratch option is used */ +#define SHFLG_Pagecache 0x00002 /* The --pagecache option is used */ +#define SHFLG_Lookaside 0x00004 /* Lookaside memory is used */ + +/* +** These are the allowed modes. +*/ +#define MODE_Line 0 /* One column per line. Blank line between records */ +#define MODE_Column 1 /* One record per line in neat columns */ +#define MODE_List 2 /* One record per line with a separator */ +#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ +#define MODE_Html 4 /* Generate an XHTML table */ +#define MODE_Insert 5 /* Generate SQL "insert" statements */ +#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */ +#define MODE_Csv 7 /* Quote strings, numbers are plain */ +#define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */ +#define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */ + +static const char *modeDescr[] = { + "line", + "column", + "list", + "semi", + "html", + "insert", + "tcl", + "csv", + "explain", + "ascii", +}; + +/* +** These are the column/row/line separators used by the various +** import/export modes. +*/ +#define SEP_Column "|" +#define SEP_Row "\n" +#define SEP_Tab "\t" +#define SEP_Space " " +#define SEP_Comma "," +#define SEP_CrLf "\r\n" +#define SEP_Unit "\x1F" +#define SEP_Record "\x1E" + +/* +** Number of elements in an array +*/ +#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0])) + +/* +** Compute a string length that is limited to what can be stored in +** lower 30 bits of a 32-bit signed integer. +*/ +static int strlen30(const char *z){ + const char *z2 = z; + while( *z2 ){ z2++; } + return 0x3fffffff & (int)(z2 - z); +} + +/* +** A callback for the sqlite3_log() interface. +*/ +static void shellLog(void *pArg, int iErrCode, const char *zMsg){ + ShellState *p = (ShellState*)pArg; + if( p->pLog==0 ) return; + fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg); + fflush(p->pLog); +} + +/* +** Output the given string as a hex-encoded blob (eg. X'1234' ) +*/ +static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ + int i; + char *zBlob = (char *)pBlob; + fprintf(out,"X'"); + for(i=0; i0 ){ + fprintf(out,"%.*s",i,z); + } + if( z[i]=='<' ){ + fprintf(out,"<"); + }else if( z[i]=='&' ){ + fprintf(out,"&"); + }else if( z[i]=='>' ){ + fprintf(out,">"); + }else if( z[i]=='\"' ){ + fprintf(out,"""); + }else if( z[i]=='\'' ){ + fprintf(out,"'"); + }else{ + break; + } + z += i + 1; + } +} + +/* +** If a field contains any character identified by a 1 in the following +** array, then the string must be quoted for CSV. +*/ +static const char needCsvQuote[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; + +/* +** Output a single term of CSV. Actually, p->colSeparator is used for +** the separator, which may or may not be a comma. p->nullValue is +** the null value. Strings are quoted if necessary. The separator +** is only issued if bSep is true. +*/ +static void output_csv(ShellState *p, const char *z, int bSep){ + FILE *out = p->out; + if( z==0 ){ + fprintf(out,"%s",p->nullValue); + }else{ + int i; + int nSep = strlen30(p->colSeparator); + for(i=0; z[i]; i++){ + if( needCsvQuote[((unsigned char*)z)[i]] + || (z[i]==p->colSeparator[0] && + (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){ + i = 0; + break; + } + } + if( i==0 ){ + putc('"', out); + for(i=0; z[i]; i++){ + if( z[i]=='"' ) putc('"', out); + putc(z[i], out); + } + putc('"', out); + }else{ + fprintf(out, "%s", z); + } + } + if( bSep ){ + fprintf(p->out, "%s", p->colSeparator); + } +} + +#ifdef SIGINT +/* +** This routine runs when the user presses Ctrl-C +*/ +static void interrupt_handler(int NotUsed){ + UNUSED_PARAMETER(NotUsed); + seenInterrupt++; + if( seenInterrupt>2 ) exit(1); + if( globalDb ) sqlite3_interrupt(globalDb); +} +#endif + +/* +** This is the callback routine that the shell +** invokes for each row of a query result. +*/ +static int shell_callback( + void *pArg, + int nArg, /* Number of result columns */ + char **azArg, /* Text of each result column */ + char **azCol, /* Column names */ + int *aiType /* Column types */ +){ + int i; + ShellState *p = (ShellState*)pArg; + + switch( p->mode ){ + case MODE_Line: { + int w = 5; + if( azArg==0 ) break; + for(i=0; iw ) w = len; + } + if( p->cnt++>0 ) fprintf(p->out, "%s", p->rowSeparator); + for(i=0; iout,"%*s = %s%s", w, azCol[i], + azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator); + } + break; + } + case MODE_Explain: + case MODE_Column: { + if( p->cnt++==0 ){ + for(i=0; icolWidth) ){ + w = p->colWidth[i]; + }else{ + w = 0; + } + if( w==0 ){ + w = strlen30(azCol[i] ? azCol[i] : ""); + if( w<10 ) w = 10; + n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullValue); + if( wactualWidth) ){ + p->actualWidth[i] = w; + } + if( p->showHeader ){ + if( w<0 ){ + fprintf(p->out,"%*.*s%s",-w,-w,azCol[i], + i==nArg-1 ? p->rowSeparator : " "); + }else{ + fprintf(p->out,"%-*.*s%s",w,w,azCol[i], + i==nArg-1 ? p->rowSeparator : " "); + } + } + } + if( p->showHeader ){ + for(i=0; iactualWidth) ){ + w = p->actualWidth[i]; + if( w<0 ) w = -w; + }else{ + w = 10; + } + fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------" + "----------------------------------------------------------", + i==nArg-1 ? p->rowSeparator : " "); + } + } + } + if( azArg==0 ) break; + for(i=0; iactualWidth) ){ + w = p->actualWidth[i]; + }else{ + w = 10; + } + if( p->mode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){ + w = strlen30(azArg[i]); + } + if( i==1 && p->aiIndent && p->pStmt ){ + if( p->iIndentnIndent ){ + fprintf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); + } + p->iIndent++; + } + if( w<0 ){ + fprintf(p->out,"%*.*s%s",-w,-w, + azArg[i] ? azArg[i] : p->nullValue, + i==nArg-1 ? p->rowSeparator : " "); + }else{ + fprintf(p->out,"%-*.*s%s",w,w, + azArg[i] ? azArg[i] : p->nullValue, + i==nArg-1 ? p->rowSeparator : " "); + } + } + break; + } + case MODE_Semi: + case MODE_List: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout,"%s%s",azCol[i], + i==nArg-1 ? p->rowSeparator : p->colSeparator); + } + } + if( azArg==0 ) break; + for(i=0; inullValue; + fprintf(p->out, "%s", z); + if( iout, "%s", p->colSeparator); + }else if( p->mode==MODE_Semi ){ + fprintf(p->out, ";%s", p->rowSeparator); + }else{ + fprintf(p->out, "%s", p->rowSeparator); + } + } + break; + } + case MODE_Html: { + if( p->cnt++==0 && p->showHeader ){ + fprintf(p->out,""); + for(i=0; iout,""); + output_html_string(p->out, azCol[i]); + fprintf(p->out,"\n"); + } + fprintf(p->out,"\n"); + } + if( azArg==0 ) break; + fprintf(p->out,""); + for(i=0; iout,""); + output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue); + fprintf(p->out,"\n"); + } + fprintf(p->out,"\n"); + break; + } + case MODE_Tcl: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout,azCol[i] ? azCol[i] : ""); + if(iout, "%s", p->colSeparator); + } + fprintf(p->out, "%s", p->rowSeparator); + } + if( azArg==0 ) break; + for(i=0; iout, azArg[i] ? azArg[i] : p->nullValue); + if(iout, "%s", p->colSeparator); + } + fprintf(p->out, "%s", p->rowSeparator); + break; + } + case MODE_Csv: { + setBinaryMode(p->out); + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout, "%s", p->rowSeparator); + } + if( nArg>0 ){ + for(i=0; iout, "%s", p->rowSeparator); + } + setTextMode(p->out); + break; + } + case MODE_Insert: { + p->cnt++; + if( azArg==0 ) break; + fprintf(p->out,"INSERT INTO %s",p->zDestTable); + if( p->showHeader ){ + fprintf(p->out,"("); + for(i=0; i0 ? ",": ""; + fprintf(p->out, "%s%s", zSep, azCol[i]); + } + fprintf(p->out,")"); + } + fprintf(p->out," VALUES("); + for(i=0; i0 ? ",": ""; + if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ + fprintf(p->out,"%sNULL",zSep); + }else if( aiType && aiType[i]==SQLITE_TEXT ){ + if( zSep[0] ) fprintf(p->out,"%s",zSep); + output_quoted_string(p->out, azArg[i]); + }else if( aiType && (aiType[i]==SQLITE_INTEGER + || aiType[i]==SQLITE_FLOAT) ){ + fprintf(p->out,"%s%s",zSep, azArg[i]); + }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ + const void *pBlob = sqlite3_column_blob(p->pStmt, i); + int nBlob = sqlite3_column_bytes(p->pStmt, i); + if( zSep[0] ) fprintf(p->out,"%s",zSep); + output_hex_blob(p->out, pBlob, nBlob); + }else if( isNumber(azArg[i], 0) ){ + fprintf(p->out,"%s%s",zSep, azArg[i]); + }else{ + if( zSep[0] ) fprintf(p->out,"%s",zSep); + output_quoted_string(p->out, azArg[i]); + } + } + fprintf(p->out,");\n"); + break; + } + case MODE_Ascii: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; i0 ) fprintf(p->out, "%s", p->colSeparator); + fprintf(p->out,"%s",azCol[i] ? azCol[i] : ""); + } + fprintf(p->out, "%s", p->rowSeparator); + } + if( azArg==0 ) break; + for(i=0; i0 ) fprintf(p->out, "%s", p->colSeparator); + fprintf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue); + } + fprintf(p->out, "%s", p->rowSeparator); + break; + } + } + return 0; +} + +/* +** This is the callback routine that the SQLite library +** invokes for each row of a query result. +*/ +static int callback(void *pArg, int nArg, char **azArg, char **azCol){ + /* since we don't have type info, call the shell_callback with a NULL value */ + return shell_callback(pArg, nArg, azArg, azCol, NULL); +} + +/* +** Set the destination table field of the ShellState structure to +** the name of the table given. Escape any quote characters in the +** table name. +*/ +static void set_table_name(ShellState *p, const char *zName){ + int i, n; + int needQuote; + char *z; + + if( p->zDestTable ){ + free(p->zDestTable); + p->zDestTable = 0; + } + if( zName==0 ) return; + needQuote = !isalpha((unsigned char)*zName) && *zName!='_'; + for(i=n=0; zName[i]; i++, n++){ + if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){ + needQuote = 1; + if( zName[i]=='\'' ) n++; + } + } + if( needQuote ) n += 2; + z = p->zDestTable = malloc( n+1 ); + if( z==0 ){ + fprintf(stderr,"Error: out of memory\n"); + exit(1); + } + n = 0; + if( needQuote ) z[n++] = '\''; + for(i=0; zName[i]; i++){ + z[n++] = zName[i]; + if( zName[i]=='\'' ) z[n++] = '\''; + } + if( needQuote ) z[n++] = '\''; + z[n] = 0; +} + +/* zIn is either a pointer to a NULL-terminated string in memory obtained +** from malloc(), or a NULL pointer. The string pointed to by zAppend is +** added to zIn, and the result returned in memory obtained from malloc(). +** zIn, if it was not NULL, is freed. +** +** If the third argument, quote, is not '\0', then it is used as a +** quote character for zAppend. +*/ +static char *appendText(char *zIn, char const *zAppend, char quote){ + int len; + int i; + int nAppend = strlen30(zAppend); + int nIn = (zIn?strlen30(zIn):0); + + len = nAppend+nIn+1; + if( quote ){ + len += 2; + for(i=0; idb, zSelect, -1, &pSelect, 0); + if( rc!=SQLITE_OK || !pSelect ){ + fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); + if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; + return rc; + } + rc = sqlite3_step(pSelect); + nResult = sqlite3_column_count(pSelect); + while( rc==SQLITE_ROW ){ + if( zFirstRow ){ + fprintf(p->out, "%s", zFirstRow); + zFirstRow = 0; + } + z = (const char*)sqlite3_column_text(pSelect, 0); + fprintf(p->out, "%s", z); + for(i=1; iout, ",%s", sqlite3_column_text(pSelect, i)); + } + if( z==0 ) z = ""; + while( z[0] && (z[0]!='-' || z[1]!='-') ) z++; + if( z[0] ){ + fprintf(p->out, "\n;\n"); + }else{ + fprintf(p->out, ";\n"); + } + rc = sqlite3_step(pSelect); + } + rc = sqlite3_finalize(pSelect); + if( rc!=SQLITE_OK ){ + fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); + if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; + } + return rc; +} + +/* +** Allocate space and save off current error string. +*/ +static char *save_err_msg( + sqlite3 *db /* Database to query */ +){ + int nErrMsg = 1+strlen30(sqlite3_errmsg(db)); + char *zErrMsg = sqlite3_malloc64(nErrMsg); + if( zErrMsg ){ + memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg); + } + return zErrMsg; +} + +/* +** Display memory stats. +*/ +static int display_stats( + sqlite3 *db, /* Database to query */ + ShellState *pArg, /* Pointer to ShellState */ + int bReset /* True to reset the stats */ +){ + int iCur; + int iHiwtr; + + if( pArg && pArg->out ){ + + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, + "Memory Used: %d (max %d) bytes\n", + iCur, iHiwtr); + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n", + iCur, iHiwtr); + if( pArg->shellFlgs & SHFLG_Pagecache ){ + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, + "Number of Pcache Pages Used: %d (max %d) pages\n", + iCur, iHiwtr); + } + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, + "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", + iCur, iHiwtr); + if( pArg->shellFlgs & SHFLG_Scratch ){ + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Number of Scratch Allocations Used: %d (max %d)\n", + iCur, iHiwtr); + } + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, + "Number of Scratch Overflow Bytes: %d (max %d) bytes\n", + iCur, iHiwtr); + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Largest Allocation: %d bytes\n", + iHiwtr); + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Largest Pcache Allocation: %d bytes\n", + iHiwtr); + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Largest Scratch Allocation: %d bytes\n", + iHiwtr); +#ifdef YYTRACKMAXSTACKDEPTH + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Deepest Parser Stack: %d (max %d)\n", + iCur, iHiwtr); +#endif + } + + if( pArg && pArg->out && db ){ + if( pArg->shellFlgs & SHFLG_Lookaside ){ + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, + &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n", + iCur, iHiwtr); + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, + &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Successful lookaside attempts: %d\n", iHiwtr); + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, + &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Lookaside failures due to size: %d\n", iHiwtr); + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, + &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Lookaside failures due to OOM: %d\n", iHiwtr); + } + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Pager Heap Usage: %d bytes\n",iCur); + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); + fprintf(pArg->out, "Page cache hits: %d\n", iCur); + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1); + fprintf(pArg->out, "Page cache misses: %d\n", iCur); + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1); + fprintf(pArg->out, "Page cache writes: %d\n", iCur); + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Schema Heap Usage: %d bytes\n",iCur); + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",iCur); + } + + if( pArg && pArg->out && db && pArg->pStmt ){ + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, + bReset); + fprintf(pArg->out, "Fullscan Steps: %d\n", iCur); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); + fprintf(pArg->out, "Sort Operations: %d\n", iCur); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset); + fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); + fprintf(pArg->out, "Virtual Machine Steps: %d\n", iCur); + } + + return 0; +} + +/* +** Display scan stats. +*/ +static void display_scanstats( + sqlite3 *db, /* Database to query */ + ShellState *pArg /* Pointer to ShellState */ +){ +#ifndef SQLITE_ENABLE_STMT_SCANSTATUS + UNUSED_PARAMETER(db); + UNUSED_PARAMETER(pArg); +#else + int i, k, n, mx; + fprintf(pArg->out, "-------- scanstats --------\n"); + mx = 0; + for(k=0; k<=mx; k++){ + double rEstLoop = 1.0; + for(i=n=0; 1; i++){ + sqlite3_stmt *p = pArg->pStmt; + sqlite3_int64 nLoop, nVisit; + double rEst; + int iSid; + const char *zExplain; + if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){ + break; + } + sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid); + if( iSid>mx ) mx = iSid; + if( iSid!=k ) continue; + if( n==0 ){ + rEstLoop = (double)nLoop; + if( k>0 ) fprintf(pArg->out, "-------- subquery %d -------\n", k); + } + n++; + sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit); + sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst); + sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain); + fprintf(pArg->out, "Loop %2d: %s\n", n, zExplain); + rEstLoop *= rEst; + fprintf(pArg->out, + " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n", + nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst + ); + } + } + fprintf(pArg->out, "---------------------------\n"); +#endif +} + +/* +** Parameter azArray points to a zero-terminated array of strings. zStr +** points to a single nul-terminated string. Return non-zero if zStr +** is equal, according to strcmp(), to any of the strings in the array. +** Otherwise, return zero. +*/ +static int str_in_array(const char *zStr, const char **azArray){ + int i; + for(i=0; azArray[i]; i++){ + if( 0==strcmp(zStr, azArray[i]) ) return 1; + } + return 0; +} + +/* +** If compiled statement pSql appears to be an EXPLAIN statement, allocate +** and populate the ShellState.aiIndent[] array with the number of +** spaces each opcode should be indented before it is output. +** +** The indenting rules are: +** +** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent +** all opcodes that occur between the p2 jump destination and the opcode +** itself by 2 spaces. +** +** * For each "Goto", if the jump destination is earlier in the program +** and ends on one of: +** Yield SeekGt SeekLt RowSetRead Rewind +** or if the P1 parameter is one instead of zero, +** then indent all opcodes between the earlier instruction +** and "Goto" by 2 spaces. +*/ +static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ + const char *zSql; /* The text of the SQL statement */ + const char *z; /* Used to check if this is an EXPLAIN */ + int *abYield = 0; /* True if op is an OP_Yield */ + int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ + int iOp; /* Index of operation in p->aiIndent[] */ + + const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", + "NextIfOpen", "PrevIfOpen", 0 }; + const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", + "Rewind", 0 }; + const char *azGoto[] = { "Goto", 0 }; + + /* Try to figure out if this is really an EXPLAIN statement. If this + ** cannot be verified, return early. */ + zSql = sqlite3_sql(pSql); + if( zSql==0 ) return; + for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++); + if( sqlite3_strnicmp(z, "explain", 7) ) return; + + for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){ + int i; + int iAddr = sqlite3_column_int(pSql, 0); + const char *zOp = (const char*)sqlite3_column_text(pSql, 1); + + /* Set p2 to the P2 field of the current opcode. Then, assuming that + ** p2 is an instruction address, set variable p2op to the index of that + ** instruction in the aiIndent[] array. p2 and p2op may be different if + ** the current instruction is part of a sub-program generated by an + ** SQL trigger or foreign key. */ + int p2 = sqlite3_column_int(pSql, 3); + int p2op = (p2 + (iOp-iAddr)); + + /* Grow the p->aiIndent array as required */ + if( iOp>=nAlloc ){ + nAlloc += 100; + p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); + abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); + } + abYield[iOp] = str_in_array(zOp, azYield); + p->aiIndent[iOp] = 0; + p->nIndent = iOp+1; + + if( str_in_array(zOp, azNext) ){ + for(i=p2op; iaiIndent[i] += 2; + } + if( str_in_array(zOp, azGoto) && p2opnIndent + && (abYield[p2op] || sqlite3_column_int(pSql, 2)) + ){ + for(i=p2op+1; iaiIndent[i] += 2; + } + } + + p->iIndent = 0; + sqlite3_free(abYield); + sqlite3_reset(pSql); +} + +/* +** Free the array allocated by explain_data_prepare(). +*/ +static void explain_data_delete(ShellState *p){ + sqlite3_free(p->aiIndent); + p->aiIndent = 0; + p->nIndent = 0; + p->iIndent = 0; +} + +/* +** Execute a statement or set of statements. Print +** any result rows/columns depending on the current mode +** set via the supplied callback. +** +** This is very similar to SQLite's built-in sqlite3_exec() +** function except it takes a slightly different callback +** and callback data argument. +*/ +static int shell_exec( + sqlite3 *db, /* An open database */ + const char *zSql, /* SQL to be evaluated */ + int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ + /* (not the same as sqlite3_exec) */ + ShellState *pArg, /* Pointer to ShellState */ + char **pzErrMsg /* Error msg written here */ +){ + sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ + int rc = SQLITE_OK; /* Return Code */ + int rc2; + const char *zLeftover; /* Tail of unprocessed SQL */ + + if( pzErrMsg ){ + *pzErrMsg = NULL; + } + + while( zSql[0] && (SQLITE_OK == rc) ){ + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); + if( SQLITE_OK != rc ){ + if( pzErrMsg ){ + *pzErrMsg = save_err_msg(db); + } + }else{ + if( !pStmt ){ + /* this happens for a comment or white-space */ + zSql = zLeftover; + while( IsSpace(zSql[0]) ) zSql++; + continue; + } + + /* save off the prepared statment handle and reset row count */ + if( pArg ){ + pArg->pStmt = pStmt; + pArg->cnt = 0; + } + + /* echo the sql statement if echo on */ + if( pArg && pArg->echoOn ){ + const char *zStmtSql = sqlite3_sql(pStmt); + fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); + } + + /* Show the EXPLAIN QUERY PLAN if .eqp is on */ + if( pArg && pArg->autoEQP ){ + sqlite3_stmt *pExplain; + char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", + sqlite3_sql(pStmt)); + rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); + if( rc==SQLITE_OK ){ + while( sqlite3_step(pExplain)==SQLITE_ROW ){ + fprintf(pArg->out,"--EQP-- %d,", sqlite3_column_int(pExplain, 0)); + fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1)); + fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2)); + fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3)); + } + } + sqlite3_finalize(pExplain); + sqlite3_free(zEQP); + } + + /* If the shell is currently in ".explain" mode, gather the extra + ** data required to add indents to the output.*/ + if( pArg && pArg->mode==MODE_Explain ){ + explain_data_prepare(pArg, pStmt); + } + + /* perform the first step. this will tell us if we + ** have a result set or not and how wide it is. + */ + rc = sqlite3_step(pStmt); + /* if we have a result set... */ + if( SQLITE_ROW == rc ){ + /* if we have a callback... */ + if( xCallback ){ + /* allocate space for col name ptr, value ptr, and type */ + int nCol = sqlite3_column_count(pStmt); + void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1); + if( !pData ){ + rc = SQLITE_NOMEM; + }else{ + char **azCols = (char **)pData; /* Names of result columns */ + char **azVals = &azCols[nCol]; /* Results */ + int *aiTypes = (int *)&azVals[nCol]; /* Result types */ + int i, x; + assert(sizeof(int) <= sizeof(char *)); + /* save off ptrs to column names */ + for(i=0; imode==MODE_Insert ){ + azVals[i] = ""; + }else{ + azVals[i] = (char*)sqlite3_column_text(pStmt, i); + } + if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ + rc = SQLITE_NOMEM; + break; /* from for */ + } + } /* end for */ + + /* if data and types extracted successfully... */ + if( SQLITE_ROW == rc ){ + /* call the supplied callback with the result row data */ + if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){ + rc = SQLITE_ABORT; + }else{ + rc = sqlite3_step(pStmt); + } + } + } while( SQLITE_ROW == rc ); + sqlite3_free(pData); + } + }else{ + do{ + rc = sqlite3_step(pStmt); + } while( rc == SQLITE_ROW ); + } + } + + explain_data_delete(pArg); + + /* print usage stats if stats on */ + if( pArg && pArg->statsOn ){ + display_stats(db, pArg, 0); + } + + /* print loop-counters if required */ + if( pArg && pArg->scanstatsOn ){ + display_scanstats(db, pArg); + } + + /* Finalize the statement just executed. If this fails, save a + ** copy of the error message. Otherwise, set zSql to point to the + ** next statement to execute. */ + rc2 = sqlite3_finalize(pStmt); + if( rc!=SQLITE_NOMEM ) rc = rc2; + if( rc==SQLITE_OK ){ + zSql = zLeftover; + while( IsSpace(zSql[0]) ) zSql++; + }else if( pzErrMsg ){ + *pzErrMsg = save_err_msg(db); + } + + /* clear saved stmt handle */ + if( pArg ){ + pArg->pStmt = NULL; + } + } + } /* end while */ + + return rc; +} + + +/* +** This is a different callback routine used for dumping the database. +** Each row received by this callback consists of a table name, +** the table type ("index" or "table") and SQL to create the table. +** This routine should print text sufficient to recreate the table. +*/ +static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ + int rc; + const char *zTable; + const char *zType; + const char *zSql; + const char *zPrepStmt = 0; + ShellState *p = (ShellState *)pArg; + + UNUSED_PARAMETER(azCol); + if( nArg!=3 ) return 1; + zTable = azArg[0]; + zType = azArg[1]; + zSql = azArg[2]; + + if( strcmp(zTable, "sqlite_sequence")==0 ){ + zPrepStmt = "DELETE FROM sqlite_sequence;\n"; + }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){ + fprintf(p->out, "ANALYZE sqlite_master;\n"); + }else if( strncmp(zTable, "sqlite_", 7)==0 ){ + return 0; + }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ + char *zIns; + if( !p->writableSchema ){ + fprintf(p->out, "PRAGMA writable_schema=ON;\n"); + p->writableSchema = 1; + } + zIns = sqlite3_mprintf( + "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)" + "VALUES('table','%q','%q',0,'%q');", + zTable, zTable, zSql); + fprintf(p->out, "%s\n", zIns); + sqlite3_free(zIns); + return 0; + }else{ + fprintf(p->out, "%s;\n", zSql); + } + + if( strcmp(zType, "table")==0 ){ + sqlite3_stmt *pTableInfo = 0; + char *zSelect = 0; + char *zTableInfo = 0; + char *zTmp = 0; + int nRow = 0; + + zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0); + zTableInfo = appendText(zTableInfo, zTable, '"'); + zTableInfo = appendText(zTableInfo, ");", 0); + + rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0); + free(zTableInfo); + if( rc!=SQLITE_OK || !pTableInfo ){ + return 1; + } + + zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0); + /* Always quote the table name, even if it appears to be pure ascii, + ** in case it is a keyword. Ex: INSERT INTO "table" ... */ + zTmp = appendText(zTmp, zTable, '"'); + if( zTmp ){ + zSelect = appendText(zSelect, zTmp, '\''); + free(zTmp); + } + zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); + rc = sqlite3_step(pTableInfo); + while( rc==SQLITE_ROW ){ + const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1); + zSelect = appendText(zSelect, "quote(", 0); + zSelect = appendText(zSelect, zText, '"'); + rc = sqlite3_step(pTableInfo); + if( rc==SQLITE_ROW ){ + zSelect = appendText(zSelect, "), ", 0); + }else{ + zSelect = appendText(zSelect, ") ", 0); + } + nRow++; + } + rc = sqlite3_finalize(pTableInfo); + if( rc!=SQLITE_OK || nRow==0 ){ + free(zSelect); + return 1; + } + zSelect = appendText(zSelect, "|| ')' FROM ", 0); + zSelect = appendText(zSelect, zTable, '"'); + + rc = run_table_dump_query(p, zSelect, zPrepStmt); + if( rc==SQLITE_CORRUPT ){ + zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0); + run_table_dump_query(p, zSelect, 0); + } + free(zSelect); + } + return 0; +} + +/* +** Run zQuery. Use dump_callback() as the callback routine so that +** the contents of the query are output as SQL statements. +** +** If we get a SQLITE_CORRUPT error, rerun the query after appending +** "ORDER BY rowid DESC" to the end. +*/ +static int run_schema_dump_query( + ShellState *p, + const char *zQuery +){ + int rc; + char *zErr = 0; + rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr); + if( rc==SQLITE_CORRUPT ){ + char *zQ2; + int len = strlen30(zQuery); + fprintf(p->out, "/****** CORRUPTION ERROR *******/\n"); + if( zErr ){ + fprintf(p->out, "/****** %s ******/\n", zErr); + sqlite3_free(zErr); + zErr = 0; + } + zQ2 = malloc( len+100 ); + if( zQ2==0 ) return rc; + sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery); + rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr); + if( rc ){ + fprintf(p->out, "/****** ERROR: %s ******/\n", zErr); + }else{ + rc = SQLITE_CORRUPT; + } + sqlite3_free(zErr); + free(zQ2); + } + return rc; +} + +/* +** Text of a help message +*/ +static char zHelp[] = + ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" + ".bail on|off Stop after hitting an error. Default OFF\n" + ".binary on|off Turn binary output on or off. Default OFF\n" + ".clone NEWDB Clone data into NEWDB from the existing database\n" + ".databases List names and files of attached databases\n" + ".dbinfo ?DB? Show status information about the database\n" + ".dump ?TABLE? ... Dump the database in an SQL text format\n" + " If TABLE specified, only dump tables matching\n" + " LIKE pattern TABLE.\n" + ".echo on|off Turn command echo on or off\n" + ".eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN\n" + ".exit Exit this program\n" + ".explain ?on|off? Turn output mode suitable for EXPLAIN on or off.\n" + " With no args, it turns EXPLAIN on.\n" + ".fullschema Show schema and the content of sqlite_stat tables\n" + ".headers on|off Turn display of headers on or off\n" + ".help Show this message\n" + ".import FILE TABLE Import data from FILE into TABLE\n" + ".indexes ?TABLE? Show names of all indexes\n" + " If TABLE specified, only show indexes for tables\n" + " matching LIKE pattern TABLE.\n" +#ifdef SQLITE_ENABLE_IOTRACE + ".iotrace FILE Enable I/O diagnostic logging to FILE\n" +#endif + ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n" +#ifndef SQLITE_OMIT_LOAD_EXTENSION + ".load FILE ?ENTRY? Load an extension library\n" +#endif + ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n" + ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" + " ascii Columns/rows delimited by 0x1F and 0x1E\n" + " csv Comma-separated values\n" + " column Left-aligned columns. (See .width)\n" + " html HTML code\n" + " insert SQL insert statements for TABLE\n" + " line One value per line\n" + " list Values delimited by .separator strings\n" + " tabs Tab-separated values\n" + " tcl TCL list elements\n" + ".nullvalue STRING Use STRING in place of NULL values\n" + ".once FILENAME Output for the next SQL command only to FILENAME\n" + ".open ?FILENAME? Close existing database and reopen FILENAME\n" + ".output ?FILENAME? Send output to FILENAME or stdout\n" + ".print STRING... Print literal STRING\n" + ".prompt MAIN CONTINUE Replace the standard prompts\n" + ".quit Exit this program\n" + ".read FILENAME Execute SQL in FILENAME\n" + ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" + ".save FILE Write in-memory database into FILE\n" + ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n" + ".schema ?TABLE? Show the CREATE statements\n" + " If TABLE specified, only show tables matching\n" + " LIKE pattern TABLE.\n" + ".separator COL ?ROW? Change the column separator and optionally the row\n" + " separator for both the output mode and .import\n" + ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" + ".show Show the current values for various settings\n" + ".stats on|off Turn stats on or off\n" + ".system CMD ARGS... Run CMD ARGS... in a system shell\n" + ".tables ?TABLE? List names of tables\n" + " If TABLE specified, only list tables matching\n" + " LIKE pattern TABLE.\n" + ".timeout MS Try opening locked tables for MS milliseconds\n" + ".timer on|off Turn SQL timer on or off\n" + ".trace FILE|off Output each SQL statement as it is run\n" + ".vfsname ?AUX? Print the name of the VFS stack\n" + ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" + " Negative values right-justify\n" +; + +/* Forward reference */ +static int process_input(ShellState *p, FILE *in); +/* +** Implementation of the "readfile(X)" SQL function. The entire content +** of the file named X is read and returned as a BLOB. NULL is returned +** if the file does not exist or is unreadable. +*/ +static void readfileFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *zName; + FILE *in; + long nIn; + void *pBuf; + + UNUSED_PARAMETER(argc); + zName = (const char*)sqlite3_value_text(argv[0]); + if( zName==0 ) return; + in = fopen(zName, "rb"); + if( in==0 ) return; + fseek(in, 0, SEEK_END); + nIn = ftell(in); + rewind(in); + pBuf = sqlite3_malloc64( nIn ); + if( pBuf && 1==fread(pBuf, nIn, 1, in) ){ + sqlite3_result_blob(context, pBuf, nIn, sqlite3_free); + }else{ + sqlite3_free(pBuf); + } + fclose(in); +} + +/* +** Implementation of the "writefile(X,Y)" SQL function. The argument Y +** is written into file X. The number of bytes written is returned. Or +** NULL is returned if something goes wrong, such as being unable to open +** file X for writing. +*/ +static void writefileFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + FILE *out; + const char *z; + sqlite3_int64 rc; + const char *zFile; + + UNUSED_PARAMETER(argc); + zFile = (const char*)sqlite3_value_text(argv[0]); + if( zFile==0 ) return; + out = fopen(zFile, "wb"); + if( out==0 ) return; + z = (const char*)sqlite3_value_blob(argv[1]); + if( z==0 ){ + rc = 0; + }else{ + rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out); + } + fclose(out); + sqlite3_result_int64(context, rc); +} + +/* +** Make sure the database is open. If it is not, then open it. If +** the database fails to open, print an error message and exit. +*/ +static void open_db(ShellState *p, int keepAlive){ + if( p->db==0 ){ + sqlite3_initialize(); + sqlite3_open(p->zDbFilename, &p->db); + globalDb = p->db; + if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){ + sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0, + shellstaticFunc, 0, 0); + } + if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ + fprintf(stderr,"Error: unable to open database \"%s\": %s\n", + p->zDbFilename, sqlite3_errmsg(p->db)); + if( keepAlive ) return; + exit(1); + } +#ifndef SQLITE_OMIT_LOAD_EXTENSION + sqlite3_enable_load_extension(p->db, 1); +#endif + sqlite3_create_function(p->db, "readfile", 1, SQLITE_UTF8, 0, + readfileFunc, 0, 0); + sqlite3_create_function(p->db, "writefile", 2, SQLITE_UTF8, 0, + writefileFunc, 0, 0); + } +} + +/* +** Do C-language style dequoting. +** +** \a -> alarm +** \b -> backspace +** \t -> tab +** \n -> newline +** \v -> vertical tab +** \f -> form feed +** \r -> carriage return +** \s -> space +** \" -> " +** \' -> ' +** \\ -> backslash +** \NNN -> ascii character NNN in octal +*/ +static void resolve_backslashes(char *z){ + int i, j; + char c; + while( *z && *z!='\\' ) z++; + for(i=j=0; (c = z[i])!=0; i++, j++){ + if( c=='\\' && z[i+1]!=0 ){ + c = z[++i]; + if( c=='a' ){ + c = '\a'; + }else if( c=='b' ){ + c = '\b'; + }else if( c=='t' ){ + c = '\t'; + }else if( c=='n' ){ + c = '\n'; + }else if( c=='v' ){ + c = '\v'; + }else if( c=='f' ){ + c = '\f'; + }else if( c=='r' ){ + c = '\r'; + }else if( c=='"' ){ + c = '"'; + }else if( c=='\'' ){ + c = '\''; + }else if( c=='\\' ){ + c = '\\'; + }else if( c>='0' && c<='7' ){ + c -= '0'; + if( z[i+1]>='0' && z[i+1]<='7' ){ + i++; + c = (c<<3) + z[i] - '0'; + if( z[i+1]>='0' && z[i+1]<='7' ){ + i++; + c = (c<<3) + z[i] - '0'; + } + } + } + } + z[j] = c; + } + if( j='0' && c<='9' ) return c - '0'; + if( c>='a' && c<='f' ) return c - 'a' + 10; + if( c>='A' && c<='F' ) return c - 'A' + 10; + return -1; +} + +/* +** Interpret zArg as an integer value, possibly with suffixes. +*/ +static sqlite3_int64 integerValue(const char *zArg){ + sqlite3_int64 v = 0; + static const struct { char *zSuffix; int iMult; } aMult[] = { + { "KiB", 1024 }, + { "MiB", 1024*1024 }, + { "GiB", 1024*1024*1024 }, + { "KB", 1000 }, + { "MB", 1000000 }, + { "GB", 1000000000 }, + { "K", 1000 }, + { "M", 1000000 }, + { "G", 1000000000 }, + }; + int i; + int isNeg = 0; + if( zArg[0]=='-' ){ + isNeg = 1; + zArg++; + }else if( zArg[0]=='+' ){ + zArg++; + } + if( zArg[0]=='0' && zArg[1]=='x' ){ + int x; + zArg += 2; + while( (x = hexDigitValue(zArg[0]))>=0 ){ + v = (v<<4) + x; + zArg++; + } + }else{ + while( IsDigit(zArg[0]) ){ + v = v*10 + zArg[0] - '0'; + zArg++; + } + } + for(i=0; i=0; i++){} + }else{ + for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){} + } + if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff); + if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){ + return 1; + } + if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){ + return 0; + } + fprintf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", + zArg); + return 0; +} + +/* +** Close an output file, assuming it is not stderr or stdout +*/ +static void output_file_close(FILE *f){ + if( f && f!=stdout && f!=stderr ) fclose(f); +} + +/* +** Try to open an output file. The names "stdout" and "stderr" are +** recognized and do the right thing. NULL is returned if the output +** filename is "off". +*/ +static FILE *output_file_open(const char *zFile){ + FILE *f; + if( strcmp(zFile,"stdout")==0 ){ + f = stdout; + }else if( strcmp(zFile, "stderr")==0 ){ + f = stderr; + }else if( strcmp(zFile, "off")==0 ){ + f = 0; + }else{ + f = fopen(zFile, "wb"); + if( f==0 ){ + fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); + } + } + return f; +} + +/* +** A routine for handling output from sqlite3_trace(). +*/ +static void sql_trace_callback(void *pArg, const char *z){ + FILE *f = (FILE*)pArg; + if( f ){ + int i = (int)strlen(z); + while( i>0 && z[i-1]==';' ){ i--; } + fprintf(f, "%.*s;\n", i, z); + } +} + +/* +** A no-op routine that runs with the ".breakpoint" doc-command. This is +** a useful spot to set a debugger breakpoint. +*/ +static void test_breakpoint(void){ + static int nCall = 0; + nCall++; +} + +/* +** An object used to read a CSV and other files for import. +*/ +typedef struct ImportCtx ImportCtx; +struct ImportCtx { + const char *zFile; /* Name of the input file */ + FILE *in; /* Read the CSV text from this input stream */ + char *z; /* Accumulated text for a field */ + int n; /* Number of bytes in z */ + int nAlloc; /* Space allocated for z[] */ + int nLine; /* Current line number */ + int cTerm; /* Character that terminated the most recent field */ + int cColSep; /* The column separator character. (Usually ",") */ + int cRowSep; /* The row separator character. (Usually "\n") */ +}; + +/* Append a single byte to z[] */ +static void import_append_char(ImportCtx *p, int c){ + if( p->n+1>=p->nAlloc ){ + p->nAlloc += p->nAlloc + 100; + p->z = sqlite3_realloc64(p->z, p->nAlloc); + if( p->z==0 ){ + fprintf(stderr, "out of memory\n"); + exit(1); + } + } + p->z[p->n++] = (char)c; +} + +/* Read a single field of CSV text. Compatible with rfc4180 and extended +** with the option of having a separator other than ",". +** +** + Input comes from p->in. +** + Store results in p->z of length p->n. Space to hold p->z comes +** from sqlite3_malloc64(). +** + Use p->cSep as the column separator. The default is ",". +** + Use p->rSep as the row separator. The default is "\n". +** + Keep track of the line number in p->nLine. +** + Store the character that terminates the field in p->cTerm. Store +** EOF on end-of-file. +** + Report syntax errors on stderr +*/ +static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){ + int c; + int cSep = p->cColSep; + int rSep = p->cRowSep; + p->n = 0; + c = fgetc(p->in); + if( c==EOF || seenInterrupt ){ + p->cTerm = EOF; + return 0; + } + if( c=='"' ){ + int pc, ppc; + int startLine = p->nLine; + int cQuote = c; + pc = ppc = 0; + while( 1 ){ + c = fgetc(p->in); + if( c==rSep ) p->nLine++; + if( c==cQuote ){ + if( pc==cQuote ){ + pc = 0; + continue; + } + } + if( (c==cSep && pc==cQuote) + || (c==rSep && pc==cQuote) + || (c==rSep && pc=='\r' && ppc==cQuote) + || (c==EOF && pc==cQuote) + ){ + do{ p->n--; }while( p->z[p->n]!=cQuote ); + p->cTerm = c; + break; + } + if( pc==cQuote && c!='\r' ){ + fprintf(stderr, "%s:%d: unescaped %c character\n", + p->zFile, p->nLine, cQuote); + } + if( c==EOF ){ + fprintf(stderr, "%s:%d: unterminated %c-quoted field\n", + p->zFile, startLine, cQuote); + p->cTerm = c; + break; + } + import_append_char(p, c); + ppc = pc; + pc = c; + } + }else{ + while( c!=EOF && c!=cSep && c!=rSep ){ + import_append_char(p, c); + c = fgetc(p->in); + } + if( c==rSep ){ + p->nLine++; + if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--; + } + p->cTerm = c; + } + if( p->z ) p->z[p->n] = 0; + return p->z; +} + +/* Read a single field of ASCII delimited text. +** +** + Input comes from p->in. +** + Store results in p->z of length p->n. Space to hold p->z comes +** from sqlite3_malloc64(). +** + Use p->cSep as the column separator. The default is "\x1F". +** + Use p->rSep as the row separator. The default is "\x1E". +** + Keep track of the row number in p->nLine. +** + Store the character that terminates the field in p->cTerm. Store +** EOF on end-of-file. +** + Report syntax errors on stderr +*/ +static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){ + int c; + int cSep = p->cColSep; + int rSep = p->cRowSep; + p->n = 0; + c = fgetc(p->in); + if( c==EOF || seenInterrupt ){ + p->cTerm = EOF; + return 0; + } + while( c!=EOF && c!=cSep && c!=rSep ){ + import_append_char(p, c); + c = fgetc(p->in); + } + if( c==rSep ){ + p->nLine++; + } + p->cTerm = c; + if( p->z ) p->z[p->n] = 0; + return p->z; +} + +/* +** Try to transfer data for table zTable. If an error is seen while +** moving forward, try to go backwards. The backwards movement won't +** work for WITHOUT ROWID tables. +*/ +static void tryToCloneData( + ShellState *p, + sqlite3 *newDb, + const char *zTable +){ + sqlite3_stmt *pQuery = 0; + sqlite3_stmt *pInsert = 0; + char *zQuery = 0; + char *zInsert = 0; + int rc; + int i, j, n; + int nTable = (int)strlen(zTable); + int k = 0; + int cnt = 0; + const int spinRate = 10000; + + zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable); + rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); + if( rc ){ + fprintf(stderr, "Error %d: %s on [%s]\n", + sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), + zQuery); + goto end_data_xfer; + } + n = sqlite3_column_count(pQuery); + zInsert = sqlite3_malloc64(200 + nTable + n*3); + if( zInsert==0 ){ + fprintf(stderr, "out of memory\n"); + goto end_data_xfer; + } + sqlite3_snprintf(200+nTable,zInsert, + "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable); + i = (int)strlen(zInsert); + for(j=1; jdb, zQuery, -1, &pQuery, 0); + if( rc ){ + fprintf(stderr, "Warning: cannot step \"%s\" backwards", zTable); + break; + } + } /* End for(k=0...) */ + +end_data_xfer: + sqlite3_finalize(pQuery); + sqlite3_finalize(pInsert); + sqlite3_free(zQuery); + sqlite3_free(zInsert); +} + + +/* +** Try to transfer all rows of the schema that match zWhere. For +** each row, invoke xForEach() on the object defined by that row. +** If an error is encountered while moving forward through the +** sqlite_master table, try again moving backwards. +*/ +static void tryToCloneSchema( + ShellState *p, + sqlite3 *newDb, + const char *zWhere, + void (*xForEach)(ShellState*,sqlite3*,const char*) +){ + sqlite3_stmt *pQuery = 0; + char *zQuery = 0; + int rc; + const unsigned char *zName; + const unsigned char *zSql; + char *zErrMsg = 0; + + zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master" + " WHERE %s", zWhere); + rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); + if( rc ){ + fprintf(stderr, "Error: (%d) %s on [%s]\n", + sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), + zQuery); + goto end_schema_xfer; + } + while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ + zName = sqlite3_column_text(pQuery, 0); + zSql = sqlite3_column_text(pQuery, 1); + printf("%s... ", zName); fflush(stdout); + sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); + if( zErrMsg ){ + fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); + sqlite3_free(zErrMsg); + zErrMsg = 0; + } + if( xForEach ){ + xForEach(p, newDb, (const char*)zName); + } + printf("done\n"); + } + if( rc!=SQLITE_DONE ){ + sqlite3_finalize(pQuery); + sqlite3_free(zQuery); + zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master" + " WHERE %s ORDER BY rowid DESC", zWhere); + rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); + if( rc ){ + fprintf(stderr, "Error: (%d) %s on [%s]\n", + sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), + zQuery); + goto end_schema_xfer; + } + while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ + zName = sqlite3_column_text(pQuery, 0); + zSql = sqlite3_column_text(pQuery, 1); + printf("%s... ", zName); fflush(stdout); + sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); + if( zErrMsg ){ + fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); + sqlite3_free(zErrMsg); + zErrMsg = 0; + } + if( xForEach ){ + xForEach(p, newDb, (const char*)zName); + } + printf("done\n"); + } + } +end_schema_xfer: + sqlite3_finalize(pQuery); + sqlite3_free(zQuery); +} + +/* +** Open a new database file named "zNewDb". Try to recover as much information +** as possible out of the main database (which might be corrupt) and write it +** into zNewDb. +*/ +static void tryToClone(ShellState *p, const char *zNewDb){ + int rc; + sqlite3 *newDb = 0; + if( access(zNewDb,0)==0 ){ + fprintf(stderr, "File \"%s\" already exists.\n", zNewDb); + return; + } + rc = sqlite3_open(zNewDb, &newDb); + if( rc ){ + fprintf(stderr, "Cannot create output database: %s\n", + sqlite3_errmsg(newDb)); + }else{ + sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0); + sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0); + tryToCloneSchema(p, newDb, "type='table'", tryToCloneData); + tryToCloneSchema(p, newDb, "type!='table'", 0); + sqlite3_exec(newDb, "COMMIT;", 0, 0, 0); + sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); + } + sqlite3_close(newDb); +} + +/* +** Change the output file back to stdout +*/ +static void output_reset(ShellState *p){ + if( p->outfile[0]=='|' ){ +#ifndef SQLITE_OMIT_POPEN + pclose(p->out); +#endif + }else{ + output_file_close(p->out); + } + p->outfile[0] = 0; + p->out = stdout; +} + +/* +** Run an SQL command and return the single integer result. +*/ +static int db_int(ShellState *p, const char *zSql){ + sqlite3_stmt *pStmt; + int res = 0; + sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ + res = sqlite3_column_int(pStmt,0); + } + sqlite3_finalize(pStmt); + return res; +} + +/* +** Convert a 2-byte or 4-byte big-endian integer into a native integer +*/ +unsigned int get2byteInt(unsigned char *a){ + return (a[0]<<8) + a[1]; +} +unsigned int get4byteInt(unsigned char *a){ + return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3]; +} + +/* +** Implementation of the ".info" command. +** +** Return 1 on error, 2 to exit, and 0 otherwise. +*/ +static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ + static const struct { const char *zName; int ofst; } aField[] = { + { "file change counter:", 24 }, + { "database page count:", 28 }, + { "freelist page count:", 36 }, + { "schema cookie:", 40 }, + { "schema format:", 44 }, + { "default cache size:", 48 }, + { "autovacuum top root:", 52 }, + { "incremental vacuum:", 64 }, + { "text encoding:", 56 }, + { "user version:", 60 }, + { "application id:", 68 }, + { "software version:", 96 }, + }; + static const struct { const char *zName; const char *zSql; } aQuery[] = { + { "number of tables:", + "SELECT count(*) FROM %s WHERE type='table'" }, + { "number of indexes:", + "SELECT count(*) FROM %s WHERE type='index'" }, + { "number of triggers:", + "SELECT count(*) FROM %s WHERE type='trigger'" }, + { "number of views:", + "SELECT count(*) FROM %s WHERE type='view'" }, + { "schema size:", + "SELECT total(length(sql)) FROM %s" }, + }; + sqlite3_file *pFile; + int i; + char *zSchemaTab; + char *zDb = nArg>=2 ? azArg[1] : "main"; + unsigned char aHdr[100]; + open_db(p, 0); + if( p->db==0 ) return 1; + sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFile); + if( pFile==0 || pFile->pMethods==0 || pFile->pMethods->xRead==0 ){ + return 1; + } + i = pFile->pMethods->xRead(pFile, aHdr, 100, 0); + if( i!=SQLITE_OK ){ + fprintf(stderr, "unable to read database header\n"); + return 1; + } + i = get2byteInt(aHdr+16); + if( i==1 ) i = 65536; + fprintf(p->out, "%-20s %d\n", "database page size:", i); + fprintf(p->out, "%-20s %d\n", "write format:", aHdr[18]); + fprintf(p->out, "%-20s %d\n", "read format:", aHdr[19]); + fprintf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]); + for(i=0; iout, "%-20s %u", aField[i].zName, val); + switch( ofst ){ + case 56: { + if( val==1 ) fprintf(p->out, " (utf8)"); + if( val==2 ) fprintf(p->out, " (utf16le)"); + if( val==3 ) fprintf(p->out, " (utf16be)"); + } + } + fprintf(p->out, "\n"); + } + if( zDb==0 ){ + zSchemaTab = sqlite3_mprintf("main.sqlite_master"); + }else if( strcmp(zDb,"temp")==0 ){ + zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master"); + }else{ + zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb); + } + for(i=0; iout, "%-20s %d\n", aQuery[i].zName, val); + } + sqlite3_free(zSchemaTab); + return 0; +} + + +/* +** If an input line begins with "." then invoke this routine to +** process that line. +** +** Return 1 on error, 2 to exit, and 0 otherwise. +*/ +static int do_meta_command(char *zLine, ShellState *p){ + int h = 1; + int nArg = 0; + int n, c; + int rc = 0; + char *azArg[50]; + + /* Parse the input line into tokens. + */ + while( zLine[h] && nArg=3 && strncmp(azArg[0], "backup", n)==0) + || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0) + ){ + const char *zDestFile = 0; + const char *zDb = 0; + sqlite3 *pDest; + sqlite3_backup *pBackup; + int j; + for(j=1; jdb, zDb); + if( pBackup==0 ){ + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); + sqlite3_close(pDest); + return 1; + } + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} + sqlite3_backup_finish(pBackup); + if( rc==SQLITE_DONE ){ + rc = 0; + }else{ + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); + rc = 1; + } + sqlite3_close(pDest); + }else + + if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){ + if( nArg==2 ){ + bail_on_error = booleanValue(azArg[1]); + }else{ + fprintf(stderr, "Usage: .bail on|off\n"); + rc = 1; + } + }else + + if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){ + if( nArg==2 ){ + if( booleanValue(azArg[1]) ){ + setBinaryMode(p->out); + }else{ + setTextMode(p->out); + } + }else{ + fprintf(stderr, "Usage: .binary on|off\n"); + rc = 1; + } + }else + + /* The undocumented ".breakpoint" command causes a call to the no-op + ** routine named test_breakpoint(). + */ + if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){ + test_breakpoint(); + }else + + if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){ + if( nArg==2 ){ + tryToClone(p, azArg[1]); + }else{ + fprintf(stderr, "Usage: .clone FILENAME\n"); + rc = 1; + } + }else + + if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ + ShellState data; + char *zErrMsg = 0; + open_db(p, 0); + memcpy(&data, p, sizeof(data)); + data.showHeader = 1; + data.mode = MODE_Column; + data.colWidth[0] = 3; + data.colWidth[1] = 15; + data.colWidth[2] = 58; + data.cnt = 0; + sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg); + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + rc = 1; + } + }else + + if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){ + rc = shell_dbinfo_command(p, nArg, azArg); + }else + + if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ + open_db(p, 0); + /* When playing back a "dump", the content might appear in an order + ** which causes immediate foreign key constraints to be violated. + ** So disable foreign-key constraint enforcement to prevent problems. */ + if( nArg!=1 && nArg!=2 ){ + fprintf(stderr, "Usage: .dump ?LIKE-PATTERN?\n"); + rc = 1; + goto meta_command_exit; + } + fprintf(p->out, "PRAGMA foreign_keys=OFF;\n"); + fprintf(p->out, "BEGIN TRANSACTION;\n"); + p->writableSchema = 0; + sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); + p->nErr = 0; + if( nArg==1 ){ + run_schema_dump_query(p, + "SELECT name, type, sql FROM sqlite_master " + "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'" + ); + run_schema_dump_query(p, + "SELECT name, type, sql FROM sqlite_master " + "WHERE name=='sqlite_sequence'" + ); + run_table_dump_query(p, + "SELECT sql FROM sqlite_master " + "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0 + ); + }else{ + int i; + for(i=1; iwritableSchema ){ + fprintf(p->out, "PRAGMA writable_schema=OFF;\n"); + p->writableSchema = 0; + } + sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); + sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); + fprintf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n"); + }else + + if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){ + if( nArg==2 ){ + p->echoOn = booleanValue(azArg[1]); + }else{ + fprintf(stderr, "Usage: .echo on|off\n"); + rc = 1; + } + }else + + if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){ + if( nArg==2 ){ + p->autoEQP = booleanValue(azArg[1]); + }else{ + fprintf(stderr, "Usage: .eqp on|off\n"); + rc = 1; + } + }else + + if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ + if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc); + rc = 2; + }else + + if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ + int val = nArg>=2 ? booleanValue(azArg[1]) : 1; + if(val == 1) { + if(!p->normalMode.valid) { + p->normalMode.valid = 1; + p->normalMode.mode = p->mode; + p->normalMode.showHeader = p->showHeader; + memcpy(p->normalMode.colWidth,p->colWidth,sizeof(p->colWidth)); + } + /* We could put this code under the !p->explainValid + ** condition so that it does not execute if we are already in + ** explain mode. However, always executing it allows us an easy + ** was to reset to explain mode in case the user previously + ** did an .explain followed by a .width, .mode or .header + ** command. + */ + p->mode = MODE_Explain; + p->showHeader = 1; + memset(p->colWidth,0,sizeof(p->colWidth)); + p->colWidth[0] = 4; /* addr */ + p->colWidth[1] = 13; /* opcode */ + p->colWidth[2] = 4; /* P1 */ + p->colWidth[3] = 4; /* P2 */ + p->colWidth[4] = 4; /* P3 */ + p->colWidth[5] = 13; /* P4 */ + p->colWidth[6] = 2; /* P5 */ + p->colWidth[7] = 13; /* Comment */ + }else if (p->normalMode.valid) { + p->normalMode.valid = 0; + p->mode = p->normalMode.mode; + p->showHeader = p->normalMode.showHeader; + memcpy(p->colWidth,p->normalMode.colWidth,sizeof(p->colWidth)); + } + }else + + if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ + ShellState data; + char *zErrMsg = 0; + int doStats = 0; + if( nArg!=1 ){ + fprintf(stderr, "Usage: .fullschema\n"); + rc = 1; + goto meta_command_exit; + } + open_db(p, 0); + memcpy(&data, p, sizeof(data)); + data.showHeader = 0; + data.mode = MODE_Semi; + rc = sqlite3_exec(p->db, + "SELECT sql FROM" + " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" + " FROM sqlite_master UNION ALL" + " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " + "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " + "ORDER BY rowid", + callback, &data, &zErrMsg + ); + if( rc==SQLITE_OK ){ + sqlite3_stmt *pStmt; + rc = sqlite3_prepare_v2(p->db, + "SELECT rowid FROM sqlite_master" + " WHERE name GLOB 'sqlite_stat[134]'", + -1, &pStmt, 0); + doStats = sqlite3_step(pStmt)==SQLITE_ROW; + sqlite3_finalize(pStmt); + } + if( doStats==0 ){ + fprintf(p->out, "/* No STAT tables available */\n"); + }else{ + fprintf(p->out, "ANALYZE sqlite_master;\n"); + sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'", + callback, &data, &zErrMsg); + data.mode = MODE_Insert; + data.zDestTable = "sqlite_stat1"; + shell_exec(p->db, "SELECT * FROM sqlite_stat1", + shell_callback, &data,&zErrMsg); + data.zDestTable = "sqlite_stat3"; + shell_exec(p->db, "SELECT * FROM sqlite_stat3", + shell_callback, &data,&zErrMsg); + data.zDestTable = "sqlite_stat4"; + shell_exec(p->db, "SELECT * FROM sqlite_stat4", + shell_callback, &data, &zErrMsg); + fprintf(p->out, "ANALYZE sqlite_master;\n"); + } + }else + + if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){ + if( nArg==2 ){ + p->showHeader = booleanValue(azArg[1]); + }else{ + fprintf(stderr, "Usage: .headers on|off\n"); + rc = 1; + } + }else + + if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ + fprintf(p->out, "%s", zHelp); + }else + + if( c=='i' && strncmp(azArg[0], "import", n)==0 ){ + char *zTable; /* Insert data into this table */ + char *zFile; /* Name of file to extra content from */ + sqlite3_stmt *pStmt = NULL; /* A statement */ + int nCol; /* Number of columns in the table */ + int nByte; /* Number of bytes in an SQL string */ + int i, j; /* Loop counters */ + int needCommit; /* True to COMMIT or ROLLBACK at end */ + int nSep; /* Number of bytes in p->colSeparator[] */ + char *zSql; /* An SQL statement */ + ImportCtx sCtx; /* Reader context */ + char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ + int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */ + + if( nArg!=3 ){ + fprintf(stderr, "Usage: .import FILE TABLE\n"); + goto meta_command_exit; + } + zFile = azArg[1]; + zTable = azArg[2]; + seenInterrupt = 0; + memset(&sCtx, 0, sizeof(sCtx)); + open_db(p, 0); + nSep = strlen30(p->colSeparator); + if( nSep==0 ){ + fprintf(stderr, "Error: non-null column separator required for import\n"); + return 1; + } + if( nSep>1 ){ + fprintf(stderr, "Error: multi-character column separators not allowed" + " for import\n"); + return 1; + } + nSep = strlen30(p->rowSeparator); + if( nSep==0 ){ + fprintf(stderr, "Error: non-null row separator required for import\n"); + return 1; + } + if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){ + /* When importing CSV (only), if the row separator is set to the + ** default output row separator, change it to the default input + ** row separator. This avoids having to maintain different input + ** and output row separators. */ + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + nSep = strlen30(p->rowSeparator); + } + if( nSep>1 ){ + fprintf(stderr, "Error: multi-character row separators not allowed" + " for import\n"); + return 1; + } + sCtx.zFile = zFile; + sCtx.nLine = 1; + if( sCtx.zFile[0]=='|' ){ +#ifdef SQLITE_OMIT_POPEN + fprintf(stderr, "Error: pipes are not supported in this OS\n"); + return 1; +#else + sCtx.in = popen(sCtx.zFile+1, "r"); + sCtx.zFile = ""; + xCloser = pclose; +#endif + }else{ + sCtx.in = fopen(sCtx.zFile, "rb"); + xCloser = fclose; + } + if( p->mode==MODE_Ascii ){ + xRead = ascii_read_one_field; + }else{ + xRead = csv_read_one_field; + } + if( sCtx.in==0 ){ + fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); + return 1; + } + sCtx.cColSep = p->colSeparator[0]; + sCtx.cRowSep = p->rowSeparator[0]; + zSql = sqlite3_mprintf("SELECT * FROM %s", zTable); + if( zSql==0 ){ + fprintf(stderr, "Error: out of memory\n"); + xCloser(sCtx.in); + return 1; + } + nByte = strlen30(zSql); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ + if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){ + char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable); + char cSep = '('; + while( xRead(&sCtx) ){ + zCreate = sqlite3_mprintf("%z%c\n \"%s\" TEXT", zCreate, cSep, sCtx.z); + cSep = ','; + if( sCtx.cTerm!=sCtx.cColSep ) break; + } + if( cSep=='(' ){ + sqlite3_free(zCreate); + sqlite3_free(sCtx.z); + xCloser(sCtx.in); + fprintf(stderr,"%s: empty file\n", sCtx.zFile); + return 1; + } + zCreate = sqlite3_mprintf("%z\n)", zCreate); + rc = sqlite3_exec(p->db, zCreate, 0, 0, 0); + sqlite3_free(zCreate); + if( rc ){ + fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable, + sqlite3_errmsg(p->db)); + sqlite3_free(sCtx.z); + xCloser(sCtx.in); + return 1; + } + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + } + sqlite3_free(zSql); + if( rc ){ + if (pStmt) sqlite3_finalize(pStmt); + fprintf(stderr,"Error: %s\n", sqlite3_errmsg(p->db)); + xCloser(sCtx.in); + return 1; + } + nCol = sqlite3_column_count(pStmt); + sqlite3_finalize(pStmt); + pStmt = 0; + if( nCol==0 ) return 0; /* no columns, no error */ + zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 ); + if( zSql==0 ){ + fprintf(stderr, "Error: out of memory\n"); + xCloser(sCtx.in); + return 1; + } + sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); + j = strlen30(zSql); + for(i=1; idb, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc ){ + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); + if (pStmt) sqlite3_finalize(pStmt); + xCloser(sCtx.in); + return 1; + } + needCommit = sqlite3_get_autocommit(p->db); + if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0); + do{ + int startLine = sCtx.nLine; + for(i=0; imode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break; + sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); + if( i=nCol ){ + sqlite3_step(pStmt); + rc = sqlite3_reset(pStmt); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile, startLine, + sqlite3_errmsg(p->db)); + } + } + }while( sCtx.cTerm!=EOF ); + + xCloser(sCtx.in); + sqlite3_free(sCtx.z); + sqlite3_finalize(pStmt); + if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); + }else + + if( c=='i' && (strncmp(azArg[0], "indices", n)==0 + || strncmp(azArg[0], "indexes", n)==0) ){ + ShellState data; + char *zErrMsg = 0; + open_db(p, 0); + memcpy(&data, p, sizeof(data)); + data.showHeader = 0; + data.mode = MODE_List; + if( nArg==1 ){ + rc = sqlite3_exec(p->db, + "SELECT name FROM sqlite_master " + "WHERE type='index' AND name NOT LIKE 'sqlite_%' " + "UNION ALL " + "SELECT name FROM sqlite_temp_master " + "WHERE type='index' " + "ORDER BY 1", + callback, &data, &zErrMsg + ); + }else if( nArg==2 ){ + zShellStatic = azArg[1]; + rc = sqlite3_exec(p->db, + "SELECT name FROM sqlite_master " + "WHERE type='index' AND tbl_name LIKE shellstatic() " + "UNION ALL " + "SELECT name FROM sqlite_temp_master " + "WHERE type='index' AND tbl_name LIKE shellstatic() " + "ORDER BY 1", + callback, &data, &zErrMsg + ); + zShellStatic = 0; + }else{ + fprintf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n"); + rc = 1; + goto meta_command_exit; + } + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + rc = 1; + }else if( rc != SQLITE_OK ){ + fprintf(stderr,"Error: querying sqlite_master and sqlite_temp_master\n"); + rc = 1; + } + }else + +#ifdef SQLITE_ENABLE_IOTRACE + if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){ + SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...); + if( iotrace && iotrace!=stdout ) fclose(iotrace); + iotrace = 0; + if( nArg<2 ){ + sqlite3IoTrace = 0; + }else if( strcmp(azArg[1], "-")==0 ){ + sqlite3IoTrace = iotracePrintf; + iotrace = stdout; + }else{ + iotrace = fopen(azArg[1], "w"); + if( iotrace==0 ){ + fprintf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); + sqlite3IoTrace = 0; + rc = 1; + }else{ + sqlite3IoTrace = iotracePrintf; + } + } + }else +#endif + if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){ + static const struct { + const char *zLimitName; /* Name of a limit */ + int limitCode; /* Integer code for that limit */ + } aLimit[] = { + { "length", SQLITE_LIMIT_LENGTH }, + { "sql_length", SQLITE_LIMIT_SQL_LENGTH }, + { "column", SQLITE_LIMIT_COLUMN }, + { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH }, + { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT }, + { "vdbe_op", SQLITE_LIMIT_VDBE_OP }, + { "function_arg", SQLITE_LIMIT_FUNCTION_ARG }, + { "attached", SQLITE_LIMIT_ATTACHED }, + { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, + { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER }, + { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH }, + { "worker_threads", SQLITE_LIMIT_WORKER_THREADS }, + }; + int i, n2; + open_db(p, 0); + if( nArg==1 ){ + for(i=0; idb, aLimit[i].limitCode, -1)); + } + }else if( nArg>3 ){ + fprintf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n"); + rc = 1; + goto meta_command_exit; + }else{ + int iLimit = -1; + n2 = strlen30(azArg[1]); + for(i=0; idb, aLimit[iLimit].limitCode, + (int)integerValue(azArg[2])); + } + printf("%20s %d\n", aLimit[iLimit].zLimitName, + sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); + } + }else + +#ifndef SQLITE_OMIT_LOAD_EXTENSION + if( c=='l' && strncmp(azArg[0], "load", n)==0 ){ + const char *zFile, *zProc; + char *zErrMsg = 0; + if( nArg<2 ){ + fprintf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n"); + rc = 1; + goto meta_command_exit; + } + zFile = azArg[1]; + zProc = nArg>=3 ? azArg[2] : 0; + open_db(p, 0); + rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + rc = 1; + } + }else +#endif + + if( c=='l' && strncmp(azArg[0], "log", n)==0 ){ + if( nArg!=2 ){ + fprintf(stderr, "Usage: .log FILENAME\n"); + rc = 1; + }else{ + const char *zFile = azArg[1]; + output_file_close(p->pLog); + p->pLog = output_file_open(zFile); + } + }else + + if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){ + const char *zMode = nArg>=2 ? azArg[1] : ""; + int n2 = (int)strlen(zMode); + int c2 = zMode[0]; + if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){ + p->mode = MODE_Line; + }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){ + p->mode = MODE_Column; + }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){ + p->mode = MODE_List; + }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){ + p->mode = MODE_Html; + }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){ + p->mode = MODE_Tcl; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space); + }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){ + p->mode = MODE_Csv; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); + }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){ + p->mode = MODE_List; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); + }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ + p->mode = MODE_Insert; + set_table_name(p, nArg>=3 ? azArg[2] : "table"); + }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ + p->mode = MODE_Ascii; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); + }else { + fprintf(stderr,"Error: mode should be one of: " + "ascii column csv html insert line list tabs tcl\n"); + rc = 1; + } + }else + + if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){ + if( nArg==2 ){ + sqlite3_snprintf(sizeof(p->nullValue), p->nullValue, + "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]); + }else{ + fprintf(stderr, "Usage: .nullvalue STRING\n"); + rc = 1; + } + }else + + if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){ + sqlite3 *savedDb = p->db; + const char *zSavedFilename = p->zDbFilename; + char *zNewFilename = 0; + p->db = 0; + if( nArg>=2 ) zNewFilename = sqlite3_mprintf("%s", azArg[1]); + p->zDbFilename = zNewFilename; + open_db(p, 1); + if( p->db!=0 ){ + sqlite3_close(savedDb); + sqlite3_free(p->zFreeOnClose); + p->zFreeOnClose = zNewFilename; + }else{ + sqlite3_free(zNewFilename); + p->db = savedDb; + p->zDbFilename = zSavedFilename; + } + }else + + if( c=='o' + && (strncmp(azArg[0], "output", n)==0 || strncmp(azArg[0], "once", n)==0) + ){ + const char *zFile = nArg>=2 ? azArg[1] : "stdout"; + if( nArg>2 ){ + fprintf(stderr, "Usage: .%s FILE\n", azArg[0]); + rc = 1; + goto meta_command_exit; + } + if( n>1 && strncmp(azArg[0], "once", n)==0 ){ + if( nArg<2 ){ + fprintf(stderr, "Usage: .once FILE\n"); + rc = 1; + goto meta_command_exit; + } + p->outCount = 2; + }else{ + p->outCount = 0; + } + output_reset(p); + if( zFile[0]=='|' ){ +#ifdef SQLITE_OMIT_POPEN + fprintf(stderr,"Error: pipes are not supported in this OS\n"); + rc = 1; + p->out = stdout; +#else + p->out = popen(zFile + 1, "w"); + if( p->out==0 ){ + fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1); + p->out = stdout; + rc = 1; + }else{ + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); + } +#endif + }else{ + p->out = output_file_open(zFile); + if( p->out==0 ){ + if( strcmp(zFile,"off")!=0 ){ + fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile); + } + p->out = stdout; + rc = 1; + } else { + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); + } + } + }else + + if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){ + int i; + for(i=1; i1 ) fprintf(p->out, " "); + fprintf(p->out, "%s", azArg[i]); + } + fprintf(p->out, "\n"); + }else + + if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){ + if( nArg >= 2) { + strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); + } + if( nArg >= 3) { + strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); + } + }else + + if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){ + rc = 2; + }else + + if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){ + FILE *alt; + if( nArg!=2 ){ + fprintf(stderr, "Usage: .read FILE\n"); + rc = 1; + goto meta_command_exit; + } + alt = fopen(azArg[1], "rb"); + if( alt==0 ){ + fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); + rc = 1; + }else{ + rc = process_input(p, alt); + fclose(alt); + } + }else + + if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){ + const char *zSrcFile; + const char *zDb; + sqlite3 *pSrc; + sqlite3_backup *pBackup; + int nTimeout = 0; + + if( nArg==2 ){ + zSrcFile = azArg[1]; + zDb = "main"; + }else if( nArg==3 ){ + zSrcFile = azArg[2]; + zDb = azArg[1]; + }else{ + fprintf(stderr, "Usage: .restore ?DB? FILE\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_open(zSrcFile, &pSrc); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "Error: cannot open \"%s\"\n", zSrcFile); + sqlite3_close(pSrc); + return 1; + } + open_db(p, 0); + pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); + if( pBackup==0 ){ + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); + sqlite3_close(pSrc); + return 1; + } + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK + || rc==SQLITE_BUSY ){ + if( rc==SQLITE_BUSY ){ + if( nTimeout++ >= 3 ) break; + sqlite3_sleep(100); + } + } + sqlite3_backup_finish(pBackup); + if( rc==SQLITE_DONE ){ + rc = 0; + }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ + fprintf(stderr, "Error: source database is busy\n"); + rc = 1; + }else{ + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); + rc = 1; + } + sqlite3_close(pSrc); + }else + + + if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){ + if( nArg==2 ){ + p->scanstatsOn = booleanValue(azArg[1]); +#ifndef SQLITE_ENABLE_STMT_SCANSTATUS + fprintf(stderr, "Warning: .scanstats not available in this build.\n"); +#endif + }else{ + fprintf(stderr, "Usage: .scanstats on|off\n"); + rc = 1; + } + }else + + if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ + ShellState data; + char *zErrMsg = 0; + open_db(p, 0); + memcpy(&data, p, sizeof(data)); + data.showHeader = 0; + data.mode = MODE_Semi; + if( nArg==2 ){ + int i; + for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]); + if( strcmp(azArg[1],"sqlite_master")==0 ){ + char *new_argv[2], *new_colv[2]; + new_argv[0] = "CREATE TABLE sqlite_master (\n" + " type text,\n" + " name text,\n" + " tbl_name text,\n" + " rootpage integer,\n" + " sql text\n" + ")"; + new_argv[1] = 0; + new_colv[0] = "sql"; + new_colv[1] = 0; + callback(&data, 1, new_argv, new_colv); + rc = SQLITE_OK; + }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){ + char *new_argv[2], *new_colv[2]; + new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n" + " type text,\n" + " name text,\n" + " tbl_name text,\n" + " rootpage integer,\n" + " sql text\n" + ")"; + new_argv[1] = 0; + new_colv[0] = "sql"; + new_colv[1] = 0; + callback(&data, 1, new_argv, new_colv); + rc = SQLITE_OK; + }else{ + zShellStatic = azArg[1]; + rc = sqlite3_exec(p->db, + "SELECT sql FROM " + " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" + " FROM sqlite_master UNION ALL" + " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " + "WHERE lower(tbl_name) LIKE shellstatic()" + " AND type!='meta' AND sql NOTNULL " + "ORDER BY rowid", + callback, &data, &zErrMsg); + zShellStatic = 0; + } + }else if( nArg==1 ){ + rc = sqlite3_exec(p->db, + "SELECT sql FROM " + " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" + " FROM sqlite_master UNION ALL" + " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " + "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " + "ORDER BY rowid", + callback, &data, &zErrMsg + ); + }else{ + fprintf(stderr, "Usage: .schema ?LIKE-PATTERN?\n"); + rc = 1; + goto meta_command_exit; + } + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + rc = 1; + }else if( rc != SQLITE_OK ){ + fprintf(stderr,"Error: querying schema information\n"); + rc = 1; + }else{ + rc = 0; + } + }else + + +#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) + if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ + extern int sqlite3SelectTrace; + sqlite3SelectTrace = integerValue(azArg[1]); + }else +#endif + + +#ifdef SQLITE_DEBUG + /* Undocumented commands for internal testing. Subject to change + ** without notice. */ + if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){ + if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){ + int i, v; + for(i=1; iout, "%s: %d 0x%x\n", azArg[i], v, v); + } + } + if( strncmp(azArg[0]+9, "integer", n-9)==0 ){ + int i; sqlite3_int64 v; + for(i=1; iout, "%s", zBuf); + } + } + }else +#endif + + if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){ + if( nArg<2 || nArg>3 ){ + fprintf(stderr, "Usage: .separator COL ?ROW?\n"); + rc = 1; + } + if( nArg>=2 ){ + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, + "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]); + } + if( nArg>=3 ){ + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, + "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]); + } + }else + + if( c=='s' + && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0) + ){ + char *zCmd; + int i, x; + if( nArg<2 ){ + fprintf(stderr, "Usage: .system COMMAND\n"); + rc = 1; + goto meta_command_exit; + } + zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]); + for(i=2; iout,"%12.12s: %s\n","echo", p->echoOn ? "on" : "off"); + fprintf(p->out,"%12.12s: %s\n","eqp", p->autoEQP ? "on" : "off"); + fprintf(p->out,"%9.9s: %s\n","explain", p->normalMode.valid ? "on" :"off"); + fprintf(p->out,"%12.12s: %s\n","headers", p->showHeader ? "on" : "off"); + fprintf(p->out,"%12.12s: %s\n","mode", modeDescr[p->mode]); + fprintf(p->out,"%12.12s: ", "nullvalue"); + output_c_string(p->out, p->nullValue); + fprintf(p->out, "\n"); + fprintf(p->out,"%12.12s: %s\n","output", + strlen30(p->outfile) ? p->outfile : "stdout"); + fprintf(p->out,"%12.12s: ", "colseparator"); + output_c_string(p->out, p->colSeparator); + fprintf(p->out, "\n"); + fprintf(p->out,"%12.12s: ", "rowseparator"); + output_c_string(p->out, p->rowSeparator); + fprintf(p->out, "\n"); + fprintf(p->out,"%12.12s: %s\n","stats", p->statsOn ? "on" : "off"); + fprintf(p->out,"%12.12s: ","width"); + for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { + fprintf(p->out,"%d ",p->colWidth[i]); + } + fprintf(p->out,"\n"); + }else + + if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){ + if( nArg==2 ){ + p->statsOn = booleanValue(azArg[1]); + }else{ + fprintf(stderr, "Usage: .stats on|off\n"); + rc = 1; + } + }else + + if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){ + sqlite3_stmt *pStmt; + char **azResult; + int nRow, nAlloc; + char *zSql = 0; + int ii; + open_db(p, 0); + rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); + if( rc ) return rc; + zSql = sqlite3_mprintf( + "SELECT name FROM sqlite_master" + " WHERE type IN ('table','view')" + " AND name NOT LIKE 'sqlite_%%'" + " AND name LIKE ?1"); + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); + if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue; + if( strcmp(zDbName,"temp")==0 ){ + zSql = sqlite3_mprintf( + "%z UNION ALL " + "SELECT 'temp.' || name FROM sqlite_temp_master" + " WHERE type IN ('table','view')" + " AND name NOT LIKE 'sqlite_%%'" + " AND name LIKE ?1", zSql); + }else{ + zSql = sqlite3_mprintf( + "%z UNION ALL " + "SELECT '%q.' || name FROM \"%w\".sqlite_master" + " WHERE type IN ('table','view')" + " AND name NOT LIKE 'sqlite_%%'" + " AND name LIKE ?1", zSql, zDbName, zDbName); + } + } + sqlite3_finalize(pStmt); + zSql = sqlite3_mprintf("%z ORDER BY 1", zSql); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc ) return rc; + nRow = nAlloc = 0; + azResult = 0; + if( nArg>1 ){ + sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT); + }else{ + sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC); + } + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + if( nRow>=nAlloc ){ + char **azNew; + int n2 = nAlloc*2 + 10; + azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); + if( azNew==0 ){ + fprintf(stderr, "Error: out of memory\n"); + break; + } + nAlloc = n2; + azResult = azNew; + } + azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); + if( azResult[nRow] ) nRow++; + } + sqlite3_finalize(pStmt); + if( nRow>0 ){ + int len, maxlen = 0; + int i, j; + int nPrintCol, nPrintRow; + for(i=0; imaxlen ) maxlen = len; + } + nPrintCol = 80/(maxlen+2); + if( nPrintCol<1 ) nPrintCol = 1; + nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; + for(i=0; iout, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:""); + } + fprintf(p->out, "\n"); + } + } + for(ii=0; ii=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){ + static const struct { + const char *zCtrlName; /* Name of a test-control option */ + int ctrlCode; /* Integer code for that option */ + } aCtrl[] = { + { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE }, + { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE }, + { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET }, + { "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST }, + { "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL }, + { "benign_malloc_hooks", SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS }, + { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE }, + { "assert", SQLITE_TESTCTRL_ASSERT }, + { "always", SQLITE_TESTCTRL_ALWAYS }, + { "reserve", SQLITE_TESTCTRL_RESERVE }, + { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS }, + { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD }, + { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC }, + { "byteorder", SQLITE_TESTCTRL_BYTEORDER }, + { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT }, + { "imposter", SQLITE_TESTCTRL_IMPOSTER }, + }; + int testctrl = -1; + int rc2 = 0; + int i, n2; + open_db(p, 0); + + /* convert testctrl text option to value. allow any unique prefix + ** of the option name, or a numerical value. */ + n2 = strlen30(azArg[1]); + for(i=0; iSQLITE_TESTCTRL_LAST) ){ + fprintf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]); + }else{ + switch(testctrl){ + + /* sqlite3_test_control(int, db, int) */ + case SQLITE_TESTCTRL_OPTIMIZATIONS: + case SQLITE_TESTCTRL_RESERVE: + if( nArg==3 ){ + int opt = (int)strtol(azArg[2], 0, 0); + rc2 = sqlite3_test_control(testctrl, p->db, opt); + fprintf(p->out, "%d (0x%08x)\n", rc2, rc2); + } else { + fprintf(stderr,"Error: testctrl %s takes a single int option\n", + azArg[1]); + } + break; + + /* sqlite3_test_control(int) */ + case SQLITE_TESTCTRL_PRNG_SAVE: + case SQLITE_TESTCTRL_PRNG_RESTORE: + case SQLITE_TESTCTRL_PRNG_RESET: + case SQLITE_TESTCTRL_BYTEORDER: + if( nArg==2 ){ + rc2 = sqlite3_test_control(testctrl); + fprintf(p->out, "%d (0x%08x)\n", rc2, rc2); + } else { + fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]); + } + break; + + /* sqlite3_test_control(int, uint) */ + case SQLITE_TESTCTRL_PENDING_BYTE: + if( nArg==3 ){ + unsigned int opt = (unsigned int)integerValue(azArg[2]); + rc2 = sqlite3_test_control(testctrl, opt); + fprintf(p->out, "%d (0x%08x)\n", rc2, rc2); + } else { + fprintf(stderr,"Error: testctrl %s takes a single unsigned" + " int option\n", azArg[1]); + } + break; + + /* sqlite3_test_control(int, int) */ + case SQLITE_TESTCTRL_ASSERT: + case SQLITE_TESTCTRL_ALWAYS: + case SQLITE_TESTCTRL_NEVER_CORRUPT: + if( nArg==3 ){ + int opt = booleanValue(azArg[2]); + rc2 = sqlite3_test_control(testctrl, opt); + fprintf(p->out, "%d (0x%08x)\n", rc2, rc2); + } else { + fprintf(stderr,"Error: testctrl %s takes a single int option\n", + azArg[1]); + } + break; + + /* sqlite3_test_control(int, char *) */ +#ifdef SQLITE_N_KEYWORD + case SQLITE_TESTCTRL_ISKEYWORD: + if( nArg==3 ){ + const char *opt = azArg[2]; + rc2 = sqlite3_test_control(testctrl, opt); + fprintf(p->out, "%d (0x%08x)\n", rc2, rc2); + } else { + fprintf(stderr,"Error: testctrl %s takes a single char * option\n", + azArg[1]); + } + break; +#endif + + case SQLITE_TESTCTRL_IMPOSTER: + if( nArg==5 ){ + rc2 = sqlite3_test_control(testctrl, p->db, + azArg[2], + integerValue(azArg[3]), + integerValue(azArg[4])); + fprintf(p->out, "%d (0x%08x)\n", rc2, rc2); + }else{ + fprintf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n"); + } + break; + + case SQLITE_TESTCTRL_BITVEC_TEST: + case SQLITE_TESTCTRL_FAULT_INSTALL: + case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: + case SQLITE_TESTCTRL_SCRATCHMALLOC: + default: + fprintf(stderr,"Error: CLI support for testctrl %s not implemented\n", + azArg[1]); + break; + } + } + }else + + if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){ + open_db(p, 0); + sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); + }else + + if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){ + if( nArg==2 ){ + enableTimer = booleanValue(azArg[1]); + if( enableTimer && !HAS_TIMER ){ + fprintf(stderr, "Error: timer not available on this system.\n"); + enableTimer = 0; + } + }else{ + fprintf(stderr, "Usage: .timer on|off\n"); + rc = 1; + } + }else + + if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){ + open_db(p, 0); + if( nArg!=2 ){ + fprintf(stderr, "Usage: .trace FILE|off\n"); + rc = 1; + goto meta_command_exit; + } + output_file_close(p->traceOut); + p->traceOut = output_file_open(azArg[1]); +#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) + if( p->traceOut==0 ){ + sqlite3_trace(p->db, 0, 0); + }else{ + sqlite3_trace(p->db, sql_trace_callback, p->traceOut); + } +#endif + }else + +#if SQLITE_USER_AUTHENTICATION + if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ + if( nArg<2 ){ + fprintf(stderr, "Usage: .user SUBCOMMAND ...\n"); + rc = 1; + goto meta_command_exit; + } + open_db(p, 0); + if( strcmp(azArg[1],"login")==0 ){ + if( nArg!=4 ){ + fprintf(stderr, "Usage: .user login USER PASSWORD\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], + (int)strlen(azArg[3])); + if( rc ){ + fprintf(stderr, "Authentication failed for user %s\n", azArg[2]); + rc = 1; + } + }else if( strcmp(azArg[1],"add")==0 ){ + if( nArg!=5 ){ + fprintf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_user_add(p->db, azArg[2], + azArg[3], (int)strlen(azArg[3]), + booleanValue(azArg[4])); + if( rc ){ + fprintf(stderr, "User-Add failed: %d\n", rc); + rc = 1; + } + }else if( strcmp(azArg[1],"edit")==0 ){ + if( nArg!=5 ){ + fprintf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_user_change(p->db, azArg[2], + azArg[3], (int)strlen(azArg[3]), + booleanValue(azArg[4])); + if( rc ){ + fprintf(stderr, "User-Edit failed: %d\n", rc); + rc = 1; + } + }else if( strcmp(azArg[1],"delete")==0 ){ + if( nArg!=3 ){ + fprintf(stderr, "Usage: .user delete USER\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_user_delete(p->db, azArg[2]); + if( rc ){ + fprintf(stderr, "User-Delete failed: %d\n", rc); + rc = 1; + } + }else{ + fprintf(stderr, "Usage: .user login|add|edit|delete ...\n"); + rc = 1; + goto meta_command_exit; + } + }else +#endif /* SQLITE_USER_AUTHENTICATION */ + + if( c=='v' && strncmp(azArg[0], "version", n)==0 ){ + fprintf(p->out, "SQLite %s %s\n" /*extra-version-info*/, + sqlite3_libversion(), sqlite3_sourceid()); + }else + + if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){ + const char *zDbName = nArg==2 ? azArg[1] : "main"; + char *zVfsName = 0; + if( p->db ){ + sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName); + if( zVfsName ){ + fprintf(p->out, "%s\n", zVfsName); + sqlite3_free(zVfsName); + } + } + }else + +#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) + if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){ + extern int sqlite3WhereTrace; + sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff; + }else +#endif + + if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ + int j; + assert( nArg<=ArraySize(azArg) ); + for(j=1; jcolWidth); j++){ + p->colWidth[j-1] = (int)integerValue(azArg[j]); + } + }else + + { + fprintf(stderr, "Error: unknown command or invalid arguments: " + " \"%s\". Enter \".help\" for help\n", azArg[0]); + rc = 1; + } + +meta_command_exit: + if( p->outCount ){ + p->outCount--; + if( p->outCount==0 ) output_reset(p); + } + return rc; +} + +/* +** Return TRUE if a semicolon occurs anywhere in the first N characters +** of string z[]. +*/ +static int line_contains_semicolon(const char *z, int N){ + int i; + for(i=0; iout); + zLine = one_input_line(in, zLine, nSql>0); + if( zLine==0 ){ + /* End of input */ + if( stdin_is_interactive ) printf("\n"); + break; + } + if( seenInterrupt ){ + if( in!=0 ) break; + seenInterrupt = 0; + } + lineno++; + if( nSql==0 && _all_whitespace(zLine) ){ + if( p->echoOn ) printf("%s\n", zLine); + continue; + } + if( zLine && zLine[0]=='.' && nSql==0 ){ + if( p->echoOn ) printf("%s\n", zLine); + rc = do_meta_command(zLine, p); + if( rc==2 ){ /* exit requested */ + break; + }else if( rc ){ + errCnt++; + } + continue; + } + if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){ + memcpy(zLine,";",2); + } + nLine = strlen30(zLine); + if( nSql+nLine+2>=nAlloc ){ + nAlloc = nSql+nLine+100; + zSql = realloc(zSql, nAlloc); + if( zSql==0 ){ + fprintf(stderr, "Error: out of memory\n"); + exit(1); + } + } + nSqlPrior = nSql; + if( nSql==0 ){ + int i; + for(i=0; zLine[i] && IsSpace(zLine[i]); i++){} + assert( nAlloc>0 && zSql!=0 ); + memcpy(zSql, zLine+i, nLine+1-i); + startline = lineno; + nSql = nLine-i; + }else{ + zSql[nSql++] = '\n'; + memcpy(zSql+nSql, zLine, nLine+1); + nSql += nLine; + } + if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) + && sqlite3_complete(zSql) ){ + p->cnt = 0; + open_db(p, 0); + if( p->backslashOn ) resolve_backslashes(zSql); + BEGIN_TIMER; + rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); + END_TIMER; + if( rc || zErrMsg ){ + char zPrefix[100]; + if( in!=0 || !stdin_is_interactive ){ + sqlite3_snprintf(sizeof(zPrefix), zPrefix, + "Error: near line %d:", startline); + }else{ + sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:"); + } + if( zErrMsg!=0 ){ + fprintf(stderr, "%s %s\n", zPrefix, zErrMsg); + sqlite3_free(zErrMsg); + zErrMsg = 0; + }else{ + fprintf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); + } + errCnt++; + } + nSql = 0; + if( p->outCount ){ + output_reset(p); + p->outCount = 0; + } + }else if( nSql && _all_whitespace(zSql) ){ + if( p->echoOn ) printf("%s\n", zSql); + nSql = 0; + } + } + if( nSql ){ + if( !_all_whitespace(zSql) ){ + fprintf(stderr, "Error: incomplete SQL: %s\n", zSql); + errCnt++; + } + free(zSql); + } + free(zLine); + return errCnt>0; +} + +/* +** Return a pathname which is the user's home directory. A +** 0 return indicates an error of some kind. +*/ +static char *find_home_dir(void){ + static char *home_dir = NULL; + if( home_dir ) return home_dir; + +#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \ + && !defined(__RTP__) && !defined(_WRS_KERNEL) + { + struct passwd *pwent; + uid_t uid = getuid(); + if( (pwent=getpwuid(uid)) != NULL) { + home_dir = pwent->pw_dir; + } + } +#endif + +#if defined(_WIN32_WCE) + /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv() + */ + home_dir = "/"; +#else + +#if defined(_WIN32) || defined(WIN32) + if (!home_dir) { + home_dir = getenv("USERPROFILE"); + } +#endif + + if (!home_dir) { + home_dir = getenv("HOME"); + } + +#if defined(_WIN32) || defined(WIN32) + if (!home_dir) { + char *zDrive, *zPath; + int n; + zDrive = getenv("HOMEDRIVE"); + zPath = getenv("HOMEPATH"); + if( zDrive && zPath ){ + n = strlen30(zDrive) + strlen30(zPath) + 1; + home_dir = malloc( n ); + if( home_dir==0 ) return 0; + sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath); + return home_dir; + } + home_dir = "c:\\"; + } +#endif + +#endif /* !_WIN32_WCE */ + + if( home_dir ){ + int n = strlen30(home_dir) + 1; + char *z = malloc( n ); + if( z ) memcpy(z, home_dir, n); + home_dir = z; + } + + return home_dir; +} + +/* +** Read input from the file given by sqliterc_override. Or if that +** parameter is NULL, take input from ~/.sqliterc +** +** Returns the number of errors. +*/ +static void process_sqliterc( + ShellState *p, /* Configuration data */ + const char *sqliterc_override /* Name of config file. NULL to use default */ +){ + char *home_dir = NULL; + const char *sqliterc = sqliterc_override; + char *zBuf = 0; + FILE *in = NULL; + + if (sqliterc == NULL) { + home_dir = find_home_dir(); + if( home_dir==0 ){ + fprintf(stderr, "-- warning: cannot find home directory;" + " cannot read ~/.sqliterc\n"); + return; + } + sqlite3_initialize(); + zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); + sqliterc = zBuf; + } + in = fopen(sqliterc,"rb"); + if( in ){ + if( stdin_is_interactive ){ + fprintf(stderr,"-- Loading resources from %s\n",sqliterc); + } + process_input(p,in); + fclose(in); + } + sqlite3_free(zBuf); +} + +/* +** Show available command line options +*/ +static const char zOptions[] = + " -ascii set output mode to 'ascii'\n" + " -bail stop after hitting an error\n" + " -batch force batch I/O\n" + " -column set output mode to 'column'\n" + " -cmd COMMAND run \"COMMAND\" before reading stdin\n" + " -csv set output mode to 'csv'\n" + " -echo print commands before execution\n" + " -init FILENAME read/process named file\n" + " -[no]header turn headers on or off\n" +#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) + " -heap SIZE Size of heap for memsys3 or memsys5\n" +#endif + " -help show this message\n" + " -html set output mode to HTML\n" + " -interactive force interactive I/O\n" + " -line set output mode to 'line'\n" + " -list set output mode to 'list'\n" + " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n" + " -mmap N default mmap size set to N\n" +#ifdef SQLITE_ENABLE_MULTIPLEX + " -multiplex enable the multiplexor VFS\n" +#endif + " -newline SEP set output row separator. Default: '\\n'\n" + " -nullvalue TEXT set text string for NULL values. Default ''\n" + " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n" + " -scratch SIZE N use N slots of SZ bytes each for scratch memory\n" + " -separator SEP set output column separator. Default: '|'\n" + " -stats print memory stats before each finalize\n" + " -version show SQLite version\n" + " -vfs NAME use NAME as the default VFS\n" +#ifdef SQLITE_ENABLE_VFSTRACE + " -vfstrace enable tracing of all VFS calls\n" +#endif +; +static void usage(int showDetail){ + fprintf(stderr, + "Usage: %s [OPTIONS] FILENAME [SQL]\n" + "FILENAME is the name of an SQLite database. A new database is created\n" + "if the file does not previously exist.\n", Argv0); + if( showDetail ){ + fprintf(stderr, "OPTIONS include:\n%s", zOptions); + }else{ + fprintf(stderr, "Use the -help option for additional information\n"); + } + exit(1); +} + +/* +** Initialize the state information in data +*/ +static void main_init(ShellState *data) { + memset(data, 0, sizeof(*data)); + data->mode = MODE_List; + memcpy(data->colSeparator,SEP_Column, 2); + memcpy(data->rowSeparator,SEP_Row, 2); + data->showHeader = 0; + data->shellFlgs = SHFLG_Lookaside; + sqlite3_config(SQLITE_CONFIG_URI, 1); + sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); + sqlite3_config(SQLITE_CONFIG_MULTITHREAD); + sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); + sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); +} + +/* +** Output text to the console in a font that attracts extra attention. +*/ +#ifdef _WIN32 +static void printBold(const char *zText){ + HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo; + GetConsoleScreenBufferInfo(out, &defaultScreenInfo); + SetConsoleTextAttribute(out, + FOREGROUND_RED|FOREGROUND_INTENSITY + ); + printf("%s", zText); + SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes); +} +#else +static void printBold(const char *zText){ + printf("\033[1m%s\033[0m", zText); +} +#endif + +/* +** Get the argument to an --option. Throw an error and die if no argument +** is available. +*/ +static char *cmdline_option_value(int argc, char **argv, int i){ + if( i==argc ){ + fprintf(stderr, "%s: Error: missing argument to %s\n", + argv[0], argv[argc-1]); + exit(1); + } + return argv[i]; +} + +int SQLITE_CDECL main(int argc, char **argv){ + char *zErrMsg = 0; + ShellState data; + const char *zInitFile = 0; + int i; + int rc = 0; + int warnInmemoryDb = 0; + int readStdin = 1; + int nCmd = 0; + char **azCmd = 0; + +#if USE_SYSTEM_SQLITE+0!=1 + if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){ + fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", + sqlite3_sourceid(), SQLITE_SOURCE_ID); + exit(1); + } +#endif + setBinaryMode(stdin); + setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ + Argv0 = argv[0]; + main_init(&data); + stdin_is_interactive = isatty(0); + + /* Make sure we have a valid signal handler early, before anything + ** else is done. + */ +#ifdef SIGINT + signal(SIGINT, interrupt_handler); +#endif + +#ifdef SQLITE_SHELL_DBNAME_PROC + { + /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name + ** of a C-function that will provide the name of the database file. Use + ** this compile-time option to embed this shell program in larger + ** applications. */ + extern void SQLITE_SHELL_DBNAME_PROC(const char**); + SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename); + warnInmemoryDb = 0; + } +#endif + + /* Do an initial pass through the command-line argument to locate + ** the name of the database file, the name of the initialization file, + ** the size of the alternative malloc heap, + ** and the first command to execute. + */ + for(i=1; i0x7fff0000 ) szHeap = 0x7fff0000; + sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64); +#endif + }else if( strcmp(z,"-scratch")==0 ){ + int n, sz; + sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( sz>400000 ) sz = 400000; + if( sz<2500 ) sz = 2500; + n = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( n>10 ) n = 10; + if( n<1 ) n = 1; + sqlite3_config(SQLITE_CONFIG_SCRATCH, malloc(n*sz+1), sz, n); + data.shellFlgs |= SHFLG_Scratch; + }else if( strcmp(z,"-pagecache")==0 ){ + int n, sz; + sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( sz>70000 ) sz = 70000; + if( sz<800 ) sz = 800; + n = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( n<10 ) n = 10; + sqlite3_config(SQLITE_CONFIG_PAGECACHE, malloc(n*sz+1), sz, n); + data.shellFlgs |= SHFLG_Pagecache; + }else if( strcmp(z,"-lookaside")==0 ){ + int n, sz; + sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( sz<0 ) sz = 0; + n = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( n<0 ) n = 0; + sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n); + if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside; +#ifdef SQLITE_ENABLE_VFSTRACE + }else if( strcmp(z,"-vfstrace")==0 ){ + extern int vfstrace_register( + const char *zTraceName, + const char *zOldVfsName, + int (*xOut)(const char*,void*), + void *pOutArg, + int makeDefault + ); + vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1); +#endif +#ifdef SQLITE_ENABLE_MULTIPLEX + }else if( strcmp(z,"-multiplex")==0 ){ + extern int sqlite3_multiple_initialize(const char*,int); + sqlite3_multiplex_initialize(0, 1); +#endif + }else if( strcmp(z,"-mmap")==0 ){ + sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i)); + sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz); + }else if( strcmp(z,"-vfs")==0 ){ + sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i)); + if( pVfs ){ + sqlite3_vfs_register(pVfs, 1); + }else{ + fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]); + exit(1); + } + } + } + if( data.zDbFilename==0 ){ +#ifndef SQLITE_OMIT_MEMORYDB + data.zDbFilename = ":memory:"; + warnInmemoryDb = argc==1; +#else + fprintf(stderr,"%s: Error: no database filename specified\n", Argv0); + return 1; +#endif + } + data.out = stdout; + + /* Go ahead and open the database file if it already exists. If the + ** file does not exist, delay opening it. This prevents empty database + ** files from being created if a user mistypes the database name argument + ** to the sqlite command-line tool. + */ + if( access(data.zDbFilename, 0)==0 ){ + open_db(&data, 0); + } + + /* Process the initialization file if there is one. If no -init option + ** is given on the command line, look for a file named ~/.sqliterc and + ** try to process it. + */ + process_sqliterc(&data,zInitFile); + + /* Make a second pass through the command-line argument and set + ** options. This second pass is delayed until after the initialization + ** file is processed so that the command-line arguments will override + ** settings in the initialization file. + */ + for(i=1; i +#include /* amalgamator: dontcache */ +#define OS_VXWORKS 1 +#define SQLITE_OS_OTHER 0 +#define SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1 +#define SQLITE_OMIT_LOAD_EXTENSION 1 +#define SQLITE_ENABLE_LOCKING_STYLE 0 +#define HAVE_UTIME 1 +#else +/* This is not VxWorks. */ +#define OS_VXWORKS 0 +#endif /* defined(_WRS_KERNEL) */ + +/************** End of vxworks.h *********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + +/* +** These #defines should enable >2GB file support on POSIX if the +** underlying operating system supports it. If the OS lacks +** large file support, or if the OS is windows, these should be no-ops. +** +** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any +** system #includes. Hence, this block of code must be the very first +** code in all source files. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: Red Hat 7.2) but you want your code to work +** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in Red Hat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +** +** The previous paragraph was written in 2005. (This paragraph is written +** on 2008-11-28.) These days, all Linux kernels support large files, so +** you should probably leave LFS enabled. But some embedded platforms might +** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful. +** +** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + +/* What version of GCC is being used. 0 means GCC is not being used */ +#ifdef __GNUC__ +# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) +#else +# define GCC_VERSION 0 +#endif + +/* Needed for various definitions... */ +#if defined(__GNUC__) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif + +#if defined(__OpenBSD__) && !defined(_BSD_SOURCE) +# define _BSD_SOURCE +#endif + +/* +** For MinGW, check to see if we can include the header file containing its +** version information, among other things. Normally, this internal MinGW +** header file would [only] be included automatically by other MinGW header +** files; however, the contained version information is now required by this +** header file to work around binary compatibility issues (see below) and +** this is the only known way to reliably obtain it. This entire #if block +** would be completely unnecessary if there was any other way of detecting +** MinGW via their preprocessor (e.g. if they customized their GCC to define +** some MinGW-specific macros). When compiling for MinGW, either the +** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be +** defined; otherwise, detection of conditions specific to MinGW will be +** disabled. +*/ +#if defined(_HAVE_MINGW_H) +# include "mingw.h" +#elif defined(_HAVE__MINGW_H) +# include "_mingw.h" +#endif + +/* +** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T +** define is required to maintain binary compatibility with the MSVC runtime +** library in use (e.g. for Windows XP). +*/ +#if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \ + defined(_WIN32) && !defined(_WIN64) && \ + defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \ + defined(__MSVCRT__) +# define _USE_32BIT_TIME_T +#endif + +/* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear +** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for +** MinGW. +*/ +/************** Include sqlite3.h in the middle of sqliteInt.h ***************/ +/************** Begin file sqlite3.h *****************************************/ +/* +** 2001 September 15 +** +** 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 library +** presents to client programs. If a C-function, structure, datatype, +** or constant definition does not appear in this file, then it is +** not a published API of SQLite, is subject to change without +** notice, and should not be referenced by programs that use SQLite. +** +** Some of the definitions that are in this file are marked as +** "experimental". Experimental interfaces are normally new +** features recently added to SQLite. We do not anticipate changes +** to experimental interfaces but reserve the right to make minor changes +** if experience from use "in the wild" suggest such changes are prudent. +** +** The official C-language API documentation for SQLite is derived +** from comments in this file. This file is the authoritative source +** on how SQLite interfaces are supposed to operate. +** +** The name of this file under configuration management is "sqlite.h.in". +** The makefile makes some minor changes to this file (such as inserting +** the version number) and changes its name to "sqlite3.h" as +** part of the build process. +*/ +#ifndef _SQLITE3_H_ +#define _SQLITE3_H_ +#include /* Needed for the definition of va_list */ + +/* +** Make sure we can call this stuff from C++. +*/ +#if 0 +extern "C" { +#endif + + +/* +** Provide the ability to override linkage features of the interface. +*/ +#ifndef SQLITE_EXTERN +# define SQLITE_EXTERN extern +#endif +#ifndef SQLITE_API +# define SQLITE_API +#endif +#ifndef SQLITE_CDECL +# define SQLITE_CDECL +#endif +#ifndef SQLITE_STDCALL +# define SQLITE_STDCALL +#endif + +/* +** These no-op macros are used in front of interfaces to mark those +** interfaces as either deprecated or experimental. New applications +** should not use deprecated interfaces - they are supported for backwards +** compatibility only. Application writers should be aware that +** experimental interfaces are subject to change in point releases. +** +** These macros used to resolve to various kinds of compiler magic that +** would generate warning messages when they were used. But that +** compiler magic ended up generating such a flurry of bug reports +** that we have taken it all out and gone back to using simple +** noop macros. +*/ +#define SQLITE_DEPRECATED +#define SQLITE_EXPERIMENTAL + +/* +** Ensure these symbols were not defined by some previous header file. +*/ +#ifdef SQLITE_VERSION +# undef SQLITE_VERSION +#endif +#ifdef SQLITE_VERSION_NUMBER +# undef SQLITE_VERSION_NUMBER +#endif + +/* +** CAPI3REF: Compile-Time Library Version Numbers +** +** ^(The [SQLITE_VERSION] C preprocessor macro in the sqlite3.h header +** evaluates to a string literal that is the SQLite version in the +** format "X.Y.Z" where X is the major version number (always 3 for +** SQLite3) and Y is the minor version number and Z is the release number.)^ +** ^(The [SQLITE_VERSION_NUMBER] C preprocessor macro resolves to an integer +** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same +** numbers used in [SQLITE_VERSION].)^ +** The SQLITE_VERSION_NUMBER for any given release of SQLite will also +** be larger than the release from which it is derived. Either Y will +** be held constant and Z will be incremented or else Y will be incremented +** and Z will be reset to zero. +** +** Since version 3.6.18, SQLite source code has been stored in the +** Fossil configuration management +** system. ^The SQLITE_SOURCE_ID macro evaluates to +** a string which identifies a particular check-in of SQLite +** within its configuration management system. ^The SQLITE_SOURCE_ID +** string contains the date and time of the check-in (UTC) and an SHA1 +** hash of the entire source tree. +** +** See also: [sqlite3_libversion()], +** [sqlite3_libversion_number()], [sqlite3_sourceid()], +** [sqlite_version()] and [sqlite_source_id()]. +*/ +#define SQLITE_VERSION "3.8.11.1" +#define SQLITE_VERSION_NUMBER 3008011 +#define SQLITE_SOURCE_ID "2015-07-29 20:00:57 cf538e2783e468bbc25e7cb2a9ee64d3e0e80b2f" + +/* +** CAPI3REF: Run-Time Library Version Numbers +** KEYWORDS: sqlite3_version, sqlite3_sourceid +** +** These interfaces provide the same information as the [SQLITE_VERSION], +** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros +** but are associated with the library instead of the header file. ^(Cautious +** programmers might include assert() statements in their application to +** verify that values returned by these interfaces match the macros in +** the header, and thus insure that the application is +** compiled with matching library and header files. +** +**
+** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
+** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
+** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
+** 
)^ +** +** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] +** macro. ^The sqlite3_libversion() function returns a pointer to the +** to the sqlite3_version[] string constant. The sqlite3_libversion() +** function is provided for use in DLLs since DLL users usually do not have +** direct access to string constants within the DLL. ^The +** sqlite3_libversion_number() function returns an integer equal to +** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns +** a pointer to a string constant whose value is the same as the +** [SQLITE_SOURCE_ID] C preprocessor macro. +** +** See also: [sqlite_version()] and [sqlite_source_id()]. +*/ +SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; +SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void); +SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void); +SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void); + +/* +** CAPI3REF: Run-Time Library Compilation Options Diagnostics +** +** ^The sqlite3_compileoption_used() function returns 0 or 1 +** indicating whether the specified option was defined at +** compile time. ^The SQLITE_ prefix may be omitted from the +** option name passed to sqlite3_compileoption_used(). +** +** ^The sqlite3_compileoption_get() function allows iterating +** over the list of options that were defined at compile time by +** returning the N-th compile time option string. ^If N is out of range, +** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ +** prefix is omitted from any strings returned by +** sqlite3_compileoption_get(). +** +** ^Support for the diagnostic functions sqlite3_compileoption_used() +** and sqlite3_compileoption_get() may be omitted by specifying the +** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. +** +** See also: SQL functions [sqlite_compileoption_used()] and +** [sqlite_compileoption_get()] and the [compile_options pragma]. +*/ +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS +SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName); +SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N); +#endif + +/* +** CAPI3REF: Test To See If The Library Is Threadsafe +** +** ^The sqlite3_threadsafe() function returns zero if and only if +** SQLite was compiled with mutexing code omitted due to the +** [SQLITE_THREADSAFE] compile-time option being set to 0. +** +** SQLite can be compiled with or without mutexes. When +** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes +** are enabled and SQLite is threadsafe. When the +** [SQLITE_THREADSAFE] macro is 0, +** the mutexes are omitted. Without the mutexes, it is not safe +** to use SQLite concurrently from more than one thread. +** +** Enabling mutexes incurs a measurable performance penalty. +** So if speed is of utmost importance, it makes sense to disable +** the mutexes. But for maximum safety, mutexes should be enabled. +** ^The default behavior is for mutexes to be enabled. +** +** This interface can be used by an application to make sure that the +** version of SQLite that it is linking against was compiled with +** the desired setting of the [SQLITE_THREADSAFE] macro. +** +** This interface only reports on the compile-time mutex setting +** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with +** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but +** can be fully or partially disabled using a call to [sqlite3_config()] +** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], +** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the +** sqlite3_threadsafe() function shows only the compile-time setting of +** thread safety, not any run-time changes to that setting made by +** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() +** is unchanged by calls to sqlite3_config().)^ +** +** See the [threading mode] documentation for additional information. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void); + +/* +** CAPI3REF: Database Connection Handle +** KEYWORDS: {database connection} {database connections} +** +** Each open SQLite database is represented by a pointer to an instance of +** the opaque structure named "sqlite3". It is useful to think of an sqlite3 +** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and +** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()] +** and [sqlite3_close_v2()] are its destructors. There are many other +** interfaces (such as +** [sqlite3_prepare_v2()], [sqlite3_create_function()], and +** [sqlite3_busy_timeout()] to name but three) that are methods on an +** sqlite3 object. +*/ +typedef struct sqlite3 sqlite3; + +/* +** CAPI3REF: 64-Bit Integer Types +** KEYWORDS: sqlite_int64 sqlite_uint64 +** +** Because there is no cross-platform way to specify 64-bit integer types +** SQLite includes typedefs for 64-bit signed and unsigned integers. +** +** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions. +** The sqlite_int64 and sqlite_uint64 types are supported for backwards +** compatibility only. +** +** ^The sqlite3_int64 and sqlite_int64 types can store integer values +** between -9223372036854775808 and +9223372036854775807 inclusive. ^The +** sqlite3_uint64 and sqlite_uint64 types can store integer values +** between 0 and +18446744073709551615 inclusive. +*/ +#ifdef SQLITE_INT64_TYPE + typedef SQLITE_INT64_TYPE sqlite_int64; + typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; +#elif defined(_MSC_VER) || defined(__BORLANDC__) + typedef __int64 sqlite_int64; + typedef unsigned __int64 sqlite_uint64; +#else + typedef long long int sqlite_int64; + typedef unsigned long long int sqlite_uint64; +#endif +typedef sqlite_int64 sqlite3_int64; +typedef sqlite_uint64 sqlite3_uint64; + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite3_int64 +#endif + +/* +** CAPI3REF: Closing A Database Connection +** DESTRUCTOR: sqlite3 +** +** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors +** for the [sqlite3] object. +** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if +** the [sqlite3] object is successfully destroyed and all associated +** resources are deallocated. +** +** ^If the database connection is associated with unfinalized prepared +** statements or unfinished sqlite3_backup objects then sqlite3_close() +** will leave the database connection open and return [SQLITE_BUSY]. +** ^If sqlite3_close_v2() is called with unfinalized prepared statements +** and/or unfinished sqlite3_backups, then the database connection becomes +** an unusable "zombie" which will automatically be deallocated when the +** last prepared statement is finalized or the last sqlite3_backup is +** finished. The sqlite3_close_v2() interface is intended for use with +** host languages that are garbage collected, and where the order in which +** destructors are called is arbitrary. +** +** Applications should [sqlite3_finalize | finalize] all [prepared statements], +** [sqlite3_blob_close | close] all [BLOB handles], and +** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated +** with the [sqlite3] object prior to attempting to close the object. ^If +** sqlite3_close_v2() is called on a [database connection] that still has +** outstanding [prepared statements], [BLOB handles], and/or +** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation +** of resources is deferred until all [prepared statements], [BLOB handles], +** and [sqlite3_backup] objects are also destroyed. +** +** ^If an [sqlite3] object is destroyed while a transaction is open, +** the transaction is automatically rolled back. +** +** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)] +** must be either a NULL +** pointer or an [sqlite3] object pointer obtained +** from [sqlite3_open()], [sqlite3_open16()], or +** [sqlite3_open_v2()], and not previously closed. +** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer +** argument is a harmless no-op. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3*); +SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3*); + +/* +** The type for a callback function. +** This is legacy and deprecated. It is included for historical +** compatibility and is not documented. +*/ +typedef int (*sqlite3_callback)(void*,int,char**, char**); + +/* +** CAPI3REF: One-Step Query Execution Interface +** METHOD: sqlite3 +** +** The sqlite3_exec() interface is a convenience wrapper around +** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], +** that allows an application to run multiple statements of SQL +** without having to use a lot of C code. +** +** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, +** semicolon-separate SQL statements passed into its 2nd argument, +** in the context of the [database connection] passed in as its 1st +** argument. ^If the callback function of the 3rd argument to +** sqlite3_exec() is not NULL, then it is invoked for each result row +** coming out of the evaluated SQL statements. ^The 4th argument to +** sqlite3_exec() is relayed through to the 1st argument of each +** callback invocation. ^If the callback pointer to sqlite3_exec() +** is NULL, then no callback is ever invoked and result rows are +** ignored. +** +** ^If an error occurs while evaluating the SQL statements passed into +** sqlite3_exec(), then execution of the current statement stops and +** subsequent statements are skipped. ^If the 5th parameter to sqlite3_exec() +** is not NULL then any error message is written into memory obtained +** from [sqlite3_malloc()] and passed back through the 5th parameter. +** To avoid memory leaks, the application should invoke [sqlite3_free()] +** on error message strings returned through the 5th parameter of +** of sqlite3_exec() after the error message string is no longer needed. +** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors +** occur, then sqlite3_exec() sets the pointer in its 5th parameter to +** NULL before returning. +** +** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec() +** routine returns SQLITE_ABORT without invoking the callback again and +** without running any subsequent SQL statements. +** +** ^The 2nd argument to the sqlite3_exec() callback function is the +** number of columns in the result. ^The 3rd argument to the sqlite3_exec() +** callback is an array of pointers to strings obtained as if from +** [sqlite3_column_text()], one for each column. ^If an element of a +** result row is NULL then the corresponding string pointer for the +** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the +** sqlite3_exec() callback is an array of pointers to strings where each +** entry represents the name of corresponding result column as obtained +** from [sqlite3_column_name()]. +** +** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer +** to an empty string, or a pointer that contains only whitespace and/or +** SQL comments, then no SQL statements are evaluated and the database +** is not changed. +** +** Restrictions: +** +**
    +**
  • The application must insure that the 1st parameter to sqlite3_exec() +** is a valid and open [database connection]. +**
  • The application must not close the [database connection] specified by +** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. +**
  • The application must not modify the SQL statement text passed into +** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. +**
+*/ +SQLITE_API int SQLITE_STDCALL sqlite3_exec( + sqlite3*, /* An open database */ + const char *sql, /* SQL to be evaluated */ + int (*callback)(void*,int,char**,char**), /* Callback function */ + void *, /* 1st argument to callback */ + char **errmsg /* Error msg written here */ +); + +/* +** CAPI3REF: Result Codes +** KEYWORDS: {result code definitions} +** +** Many SQLite functions return an integer result code from the set shown +** here in order to indicate success or failure. +** +** New error codes may be added in future versions of SQLite. +** +** See also: [extended result code definitions] +*/ +#define SQLITE_OK 0 /* Successful result */ +/* beginning-of-error-codes */ +#define SQLITE_ERROR 1 /* SQL error or missing database */ +#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ +#define SQLITE_PERM 3 /* Access permission denied */ +#define SQLITE_ABORT 4 /* Callback routine requested an abort */ +#define SQLITE_BUSY 5 /* The database file is locked */ +#define SQLITE_LOCKED 6 /* A table in the database is locked */ +#define SQLITE_NOMEM 7 /* A malloc() failed */ +#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ +#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ +#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ +#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ +#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */ +#define SQLITE_FULL 13 /* Insertion failed because database is full */ +#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ +#define SQLITE_PROTOCOL 15 /* Database lock protocol error */ +#define SQLITE_EMPTY 16 /* Database is empty */ +#define SQLITE_SCHEMA 17 /* The database schema changed */ +#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ +#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ +#define SQLITE_MISMATCH 20 /* Data type mismatch */ +#define SQLITE_MISUSE 21 /* Library used incorrectly */ +#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ +#define SQLITE_AUTH 23 /* Authorization denied */ +#define SQLITE_FORMAT 24 /* Auxiliary database format error */ +#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ +#define SQLITE_NOTADB 26 /* File opened that is not a database file */ +#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */ +#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */ +#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ +#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ +/* end-of-error-codes */ + +/* +** CAPI3REF: Extended Result Codes +** KEYWORDS: {extended result code definitions} +** +** In its default configuration, SQLite API routines return one of 30 integer +** [result codes]. However, experience has shown that many of +** these result codes are too coarse-grained. They do not provide as +** much information about problems as programmers might like. In an effort to +** address this, newer versions of SQLite (version 3.3.8 and later) include +** support for additional result codes that provide more detailed information +** about errors. These [extended result codes] are enabled or disabled +** on a per database connection basis using the +** [sqlite3_extended_result_codes()] API. Or, the extended code for +** the most recent error can be obtained using +** [sqlite3_extended_errcode()]. +*/ +#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) +#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) +#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) +#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) +#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) +#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) +#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) +#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) +#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) +#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) +#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) +#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) +#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8)) +#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8)) +#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8)) +#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) +#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) +#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) +#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) +#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) +#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) +#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) +#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8)) +#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) +#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8)) +#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) +#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) +#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) +#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) +#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) +#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) +#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) +#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) +#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) +#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) +#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) +#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) +#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) +#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) +#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) +#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) +#define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8)) +#define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) +#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8)) +#define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) +#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) +#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) +#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) +#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8)) +#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) +#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) +#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) +#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) + +/* +** CAPI3REF: Flags For File Open Operations +** +** These bit values are intended for use in the +** 3rd parameter to the [sqlite3_open_v2()] interface and +** in the 4th parameter to the [sqlite3_vfs.xOpen] method. +*/ +#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ +#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ +#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ +#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ +#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ +#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ +#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ +#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ +#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ +#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ + +/* Reserved: 0x00F00000 */ + +/* +** CAPI3REF: Device Characteristics +** +** The xDeviceCharacteristics method of the [sqlite3_io_methods] +** object returns an integer which is a vector of these +** bit values expressing I/O characteristics of the mass storage +** device that holds the file that the [sqlite3_io_methods] +** refers to. +** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that +** after reboot following a crash or power loss, the only bytes in a +** file that were written at the application level might have changed +** and that adjacent bytes, even bytes within the same sector are +** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN +** flag indicate that a file cannot be deleted when open. The +** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on +** read-only media and cannot be changed even by processes with +** elevated privileges. +*/ +#define SQLITE_IOCAP_ATOMIC 0x00000001 +#define SQLITE_IOCAP_ATOMIC512 0x00000002 +#define SQLITE_IOCAP_ATOMIC1K 0x00000004 +#define SQLITE_IOCAP_ATOMIC2K 0x00000008 +#define SQLITE_IOCAP_ATOMIC4K 0x00000010 +#define SQLITE_IOCAP_ATOMIC8K 0x00000020 +#define SQLITE_IOCAP_ATOMIC16K 0x00000040 +#define SQLITE_IOCAP_ATOMIC32K 0x00000080 +#define SQLITE_IOCAP_ATOMIC64K 0x00000100 +#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 +#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 +#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 +#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 +#define SQLITE_IOCAP_IMMUTABLE 0x00002000 + +/* +** CAPI3REF: File Locking Levels +** +** SQLite uses one of these integer values as the second +** argument to calls it makes to the xLock() and xUnlock() methods +** of an [sqlite3_io_methods] object. +*/ +#define SQLITE_LOCK_NONE 0 +#define SQLITE_LOCK_SHARED 1 +#define SQLITE_LOCK_RESERVED 2 +#define SQLITE_LOCK_PENDING 3 +#define SQLITE_LOCK_EXCLUSIVE 4 + +/* +** CAPI3REF: Synchronization Type Flags +** +** When SQLite invokes the xSync() method of an +** [sqlite3_io_methods] object it uses a combination of +** these integer values as the second argument. +** +** When the SQLITE_SYNC_DATAONLY flag is used, it means that the +** sync operation only needs to flush data to mass storage. Inode +** information need not be flushed. If the lower four bits of the flag +** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. +** If the lower four bits equal SQLITE_SYNC_FULL, that means +** to use Mac OS X style fullsync instead of fsync(). +** +** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags +** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL +** settings. The [synchronous pragma] determines when calls to the +** xSync VFS method occur and applies uniformly across all platforms. +** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how +** energetic or rigorous or forceful the sync operations are and +** only make a difference on Mac OSX for the default SQLite code. +** (Third-party VFS implementations might also make the distinction +** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the +** operating systems natively supported by SQLite, only Mac OSX +** cares about the difference.) +*/ +#define SQLITE_SYNC_NORMAL 0x00002 +#define SQLITE_SYNC_FULL 0x00003 +#define SQLITE_SYNC_DATAONLY 0x00010 + +/* +** CAPI3REF: OS Interface Open File Handle +** +** An [sqlite3_file] object represents an open file in the +** [sqlite3_vfs | OS interface layer]. Individual OS interface +** implementations will +** want to subclass this object by appending additional fields +** for their own use. The pMethods entry is a pointer to an +** [sqlite3_io_methods] object that defines methods for performing +** I/O operations on the open file. +*/ +typedef struct sqlite3_file sqlite3_file; +struct sqlite3_file { + const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ +}; + +/* +** CAPI3REF: OS Interface File Virtual Methods Object +** +** Every file opened by the [sqlite3_vfs.xOpen] method populates an +** [sqlite3_file] object (or, more commonly, a subclass of the +** [sqlite3_file] object) with a pointer to an instance of this object. +** This object defines the methods used to perform various operations +** against the open file represented by the [sqlite3_file] object. +** +** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element +** to a non-NULL pointer, then the sqlite3_io_methods.xClose method +** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The +** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen] +** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element +** to NULL. +** +** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or +** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). +** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY] +** flag may be ORed in to indicate that only the data of the file +** and not its inode needs to be synced. +** +** The integer values to xLock() and xUnlock() are one of +**
    +**
  • [SQLITE_LOCK_NONE], +**
  • [SQLITE_LOCK_SHARED], +**
  • [SQLITE_LOCK_RESERVED], +**
  • [SQLITE_LOCK_PENDING], or +**
  • [SQLITE_LOCK_EXCLUSIVE]. +**
+** xLock() increases the lock. xUnlock() decreases the lock. +** The xCheckReservedLock() method checks whether any database connection, +** either in this process or in some other process, is holding a RESERVED, +** PENDING, or EXCLUSIVE lock on the file. It returns true +** if such a lock exists and false otherwise. +** +** The xFileControl() method is a generic interface that allows custom +** VFS implementations to directly control an open file using the +** [sqlite3_file_control()] interface. The second "op" argument is an +** integer opcode. The third argument is a generic pointer intended to +** point to a structure that may contain arguments or space in which to +** write return values. Potential uses for xFileControl() might be +** functions to enable blocking locks with timeouts, to change the +** locking strategy (for example to use dot-file locks), to inquire +** about the status of a lock, or to break stale locks. The SQLite +** core reserves all opcodes less than 100 for its own use. +** A [file control opcodes | list of opcodes] less than 100 is available. +** Applications that define a custom xFileControl method should use opcodes +** greater than 100 to avoid conflicts. VFS implementations should +** return [SQLITE_NOTFOUND] for file control opcodes that they do not +** recognize. +** +** The xSectorSize() method returns the sector size of the +** device that underlies the file. The sector size is the +** minimum write that can be performed without disturbing +** other bytes in the file. The xDeviceCharacteristics() +** method returns a bit vector describing behaviors of the +** underlying device: +** +**
    +**
  • [SQLITE_IOCAP_ATOMIC] +**
  • [SQLITE_IOCAP_ATOMIC512] +**
  • [SQLITE_IOCAP_ATOMIC1K] +**
  • [SQLITE_IOCAP_ATOMIC2K] +**
  • [SQLITE_IOCAP_ATOMIC4K] +**
  • [SQLITE_IOCAP_ATOMIC8K] +**
  • [SQLITE_IOCAP_ATOMIC16K] +**
  • [SQLITE_IOCAP_ATOMIC32K] +**
  • [SQLITE_IOCAP_ATOMIC64K] +**
  • [SQLITE_IOCAP_SAFE_APPEND] +**
  • [SQLITE_IOCAP_SEQUENTIAL] +**
+** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). +** +** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill +** in the unread portions of the buffer with zeros. A VFS that +** fails to zero-fill short reads might seem to work. However, +** failure to zero-fill short reads will eventually lead to +** database corruption. +*/ +typedef struct sqlite3_io_methods sqlite3_io_methods; +struct sqlite3_io_methods { + int iVersion; + int (*xClose)(sqlite3_file*); + int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); + int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); + int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); + int (*xSync)(sqlite3_file*, int flags); + int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); + int (*xLock)(sqlite3_file*, int); + int (*xUnlock)(sqlite3_file*, int); + int (*xCheckReservedLock)(sqlite3_file*, int *pResOut); + int (*xFileControl)(sqlite3_file*, int op, void *pArg); + int (*xSectorSize)(sqlite3_file*); + int (*xDeviceCharacteristics)(sqlite3_file*); + /* Methods above are valid for version 1 */ + int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); + int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); + void (*xShmBarrier)(sqlite3_file*); + int (*xShmUnmap)(sqlite3_file*, int deleteFlag); + /* Methods above are valid for version 2 */ + int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); + int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p); + /* Methods above are valid for version 3 */ + /* Additional methods may be added in future releases */ +}; + +/* +** CAPI3REF: Standard File Control Opcodes +** KEYWORDS: {file control opcodes} {file control opcode} +** +** These integer constants are opcodes for the xFileControl method +** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] +** interface. +** +**
    +**
  • [[SQLITE_FCNTL_LOCKSTATE]] +** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This +** opcode causes the xFileControl method to write the current state of +** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], +** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) +** into an integer that the pArg argument points to. This capability +** is used during testing and is only available when the SQLITE_TEST +** compile-time option is used. +** +**
  • [[SQLITE_FCNTL_SIZE_HINT]] +** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS +** layer a hint of how large the database file will grow to be during the +** current transaction. This hint is not guaranteed to be accurate but it +** is often close. The underlying VFS might choose to preallocate database +** file space based on this hint in order to help writes to the database +** file run faster. +** +**
  • [[SQLITE_FCNTL_CHUNK_SIZE]] +** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS +** extends and truncates the database file in chunks of a size specified +** by the user. The fourth argument to [sqlite3_file_control()] should +** point to an integer (type int) containing the new chunk-size to use +** for the nominated database. Allocating database file space in large +** chunks (say 1MB at a time), may reduce file-system fragmentation and +** improve performance on some systems. +** +**
  • [[SQLITE_FCNTL_FILE_POINTER]] +** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer +** to the [sqlite3_file] object associated with a particular database +** connection. See the [sqlite3_file_control()] documentation for +** additional information. +** +**
  • [[SQLITE_FCNTL_SYNC_OMITTED]] +** No longer in use. +** +**
  • [[SQLITE_FCNTL_SYNC]] +** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and +** sent to the VFS immediately before the xSync method is invoked on a +** database file descriptor. Or, if the xSync method is not invoked +** because the user has configured SQLite with +** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place +** of the xSync method. In most cases, the pointer argument passed with +** this file-control is NULL. However, if the database file is being synced +** as part of a multi-database commit, the argument points to a nul-terminated +** string containing the transactions master-journal file name. VFSes that +** do not need this signal should silently ignore this opcode. Applications +** should not call [sqlite3_file_control()] with this opcode as doing so may +** disrupt the operation of the specialized VFSes that do require it. +** +**
  • [[SQLITE_FCNTL_COMMIT_PHASETWO]] +** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite +** and sent to the VFS after a transaction has been committed immediately +** but before the database is unlocked. VFSes that do not need this signal +** should silently ignore this opcode. Applications should not call +** [sqlite3_file_control()] with this opcode as doing so may disrupt the +** operation of the specialized VFSes that do require it. +** +**
  • [[SQLITE_FCNTL_WIN32_AV_RETRY]] +** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic +** retry counts and intervals for certain disk I/O operations for the +** windows [VFS] in order to provide robustness in the presence of +** anti-virus programs. By default, the windows VFS will retry file read, +** file write, and file delete operations up to 10 times, with a delay +** of 25 milliseconds before the first retry and with the delay increasing +** by an additional 25 milliseconds with each subsequent retry. This +** opcode allows these two values (10 retries and 25 milliseconds of delay) +** to be adjusted. The values are changed for all database connections +** within the same process. The argument is a pointer to an array of two +** integers where the first integer i the new retry count and the second +** integer is the delay. If either integer is negative, then the setting +** is not changed but instead the prior value of that setting is written +** into the array entry, allowing the current retry settings to be +** interrogated. The zDbName parameter is ignored. +** +**
  • [[SQLITE_FCNTL_PERSIST_WAL]] +** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the +** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary +** write ahead log and shared memory files used for transaction control +** are automatically deleted when the latest connection to the database +** closes. Setting persistent WAL mode causes those files to persist after +** close. Persisting the files is useful when other processes that do not +** have write permission on the directory containing the database file want +** to read the database file, as the WAL and shared memory files must exist +** in order for the database to be readable. The fourth parameter to +** [sqlite3_file_control()] for this opcode should be a pointer to an integer. +** That integer is 0 to disable persistent WAL mode or 1 to enable persistent +** WAL mode. If the integer is -1, then it is overwritten with the current +** WAL persistence setting. +** +**
  • [[SQLITE_FCNTL_POWERSAFE_OVERWRITE]] +** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the +** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting +** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the +** xDeviceCharacteristics methods. The fourth parameter to +** [sqlite3_file_control()] for this opcode should be a pointer to an integer. +** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage +** mode. If the integer is -1, then it is overwritten with the current +** zero-damage mode setting. +** +**
  • [[SQLITE_FCNTL_OVERWRITE]] +** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening +** a write transaction to indicate that, unless it is rolled back for some +** reason, the entire database file will be overwritten by the current +** transaction. This is used by VACUUM operations. +** +**
  • [[SQLITE_FCNTL_VFSNAME]] +** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of +** all [VFSes] in the VFS stack. The names are of all VFS shims and the +** final bottom-level VFS are written into memory obtained from +** [sqlite3_malloc()] and the result is stored in the char* variable +** that the fourth parameter of [sqlite3_file_control()] points to. +** The caller is responsible for freeing the memory when done. As with +** all file-control actions, there is no guarantee that this will actually +** do anything. Callers should initialize the char* variable to a NULL +** pointer in case this file-control is not implemented. This file-control +** is intended for diagnostic use only. +** +**
  • [[SQLITE_FCNTL_PRAGMA]] +** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] +** file control is sent to the open [sqlite3_file] object corresponding +** to the database file to which the pragma statement refers. ^The argument +** to the [SQLITE_FCNTL_PRAGMA] file control is an array of +** pointers to strings (char**) in which the second element of the array +** is the name of the pragma and the third element is the argument to the +** pragma or NULL if the pragma has no argument. ^The handler for an +** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element +** of the char** argument point to a string obtained from [sqlite3_mprintf()] +** or the equivalent and that string will become the result of the pragma or +** the error message if the pragma fails. ^If the +** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal +** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] +** file control returns [SQLITE_OK], then the parser assumes that the +** VFS has handled the PRAGMA itself and the parser generates a no-op +** prepared statement if result string is NULL, or that returns a copy +** of the result string if the string is non-NULL. +** ^If the [SQLITE_FCNTL_PRAGMA] file control returns +** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means +** that the VFS encountered an error while handling the [PRAGMA] and the +** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] +** file control occurs at the beginning of pragma statement analysis and so +** it is able to override built-in [PRAGMA] statements. +** +**
  • [[SQLITE_FCNTL_BUSYHANDLER]] +** ^The [SQLITE_FCNTL_BUSYHANDLER] +** file-control may be invoked by SQLite on the database file handle +** shortly after it is opened in order to provide a custom VFS with access +** to the connections busy-handler callback. The argument is of type (void **) +** - an array of two (void *) values. The first (void *) actually points +** to a function of type (int (*)(void *)). In order to invoke the connections +** busy-handler, this function should be invoked with the second (void *) in +** the array as the only argument. If it returns non-zero, then the operation +** should be retried. If it returns zero, the custom VFS should abandon the +** current operation. +** +**
  • [[SQLITE_FCNTL_TEMPFILENAME]] +** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control +** to have SQLite generate a +** temporary filename using the same algorithm that is followed to generate +** temporary filenames for TEMP tables and other internal uses. The +** argument should be a char** which will be filled with the filename +** written into memory obtained from [sqlite3_malloc()]. The caller should +** invoke [sqlite3_free()] on the result to avoid a memory leak. +** +**
  • [[SQLITE_FCNTL_MMAP_SIZE]] +** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the +** maximum number of bytes that will be used for memory-mapped I/O. +** The argument is a pointer to a value of type sqlite3_int64 that +** is an advisory maximum number of bytes in the file to memory map. The +** pointer is overwritten with the old value. The limit is not changed if +** the value originally pointed to is negative, and so the current limit +** can be queried by passing in a pointer to a negative number. This +** file-control is used internally to implement [PRAGMA mmap_size]. +** +**
  • [[SQLITE_FCNTL_TRACE]] +** The [SQLITE_FCNTL_TRACE] file control provides advisory information +** to the VFS about what the higher layers of the SQLite stack are doing. +** This file control is used by some VFS activity tracing [shims]. +** The argument is a zero-terminated string. Higher layers in the +** SQLite stack may generate instances of this file control if +** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled. +** +**
  • [[SQLITE_FCNTL_HAS_MOVED]] +** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a +** pointer to an integer and it writes a boolean into that integer depending +** on whether or not the file has been renamed, moved, or deleted since it +** was first opened. +** +**
  • [[SQLITE_FCNTL_WIN32_SET_HANDLE]] +** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This +** opcode causes the xFileControl method to swap the file handle with the one +** pointed to by the pArg argument. This capability is used during testing +** and only needs to be supported when SQLITE_TEST is defined. +** +**
  • [[SQLITE_FCNTL_WAL_BLOCK]] +** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might +** be advantageous to block on the next WAL lock if the lock is not immediately +** available. The WAL subsystem issues this signal during rare +** circumstances in order to fix a problem with priority inversion. +** Applications should not use this file-control. +** +**
  • [[SQLITE_FCNTL_ZIPVFS]] +** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other +** VFS should return SQLITE_NOTFOUND for this opcode. +** +**
  • [[SQLITE_FCNTL_RBU]] +** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by +** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for +** this opcode. +**
+*/ +#define SQLITE_FCNTL_LOCKSTATE 1 +#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 +#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 +#define SQLITE_FCNTL_LAST_ERRNO 4 +#define SQLITE_FCNTL_SIZE_HINT 5 +#define SQLITE_FCNTL_CHUNK_SIZE 6 +#define SQLITE_FCNTL_FILE_POINTER 7 +#define SQLITE_FCNTL_SYNC_OMITTED 8 +#define SQLITE_FCNTL_WIN32_AV_RETRY 9 +#define SQLITE_FCNTL_PERSIST_WAL 10 +#define SQLITE_FCNTL_OVERWRITE 11 +#define SQLITE_FCNTL_VFSNAME 12 +#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 +#define SQLITE_FCNTL_PRAGMA 14 +#define SQLITE_FCNTL_BUSYHANDLER 15 +#define SQLITE_FCNTL_TEMPFILENAME 16 +#define SQLITE_FCNTL_MMAP_SIZE 18 +#define SQLITE_FCNTL_TRACE 19 +#define SQLITE_FCNTL_HAS_MOVED 20 +#define SQLITE_FCNTL_SYNC 21 +#define SQLITE_FCNTL_COMMIT_PHASETWO 22 +#define SQLITE_FCNTL_WIN32_SET_HANDLE 23 +#define SQLITE_FCNTL_WAL_BLOCK 24 +#define SQLITE_FCNTL_ZIPVFS 25 +#define SQLITE_FCNTL_RBU 26 + +/* deprecated names */ +#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE +#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE +#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO + + +/* +** CAPI3REF: Mutex Handle +** +** The mutex module within SQLite defines [sqlite3_mutex] to be an +** abstract type for a mutex object. The SQLite core never looks +** at the internal representation of an [sqlite3_mutex]. It only +** deals with pointers to the [sqlite3_mutex] object. +** +** Mutexes are created using [sqlite3_mutex_alloc()]. +*/ +typedef struct sqlite3_mutex sqlite3_mutex; + +/* +** CAPI3REF: OS Interface Object +** +** An instance of the sqlite3_vfs object defines the interface between +** the SQLite core and the underlying operating system. The "vfs" +** in the name of the object stands for "virtual file system". See +** the [VFS | VFS documentation] for further information. +** +** The value of the iVersion field is initially 1 but may be larger in +** future versions of SQLite. Additional fields may be appended to this +** object when the iVersion value is increased. Note that the structure +** of the sqlite3_vfs object changes in the transaction between +** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not +** modified. +** +** The szOsFile field is the size of the subclassed [sqlite3_file] +** structure used by this VFS. mxPathname is the maximum length of +** a pathname in this VFS. +** +** Registered sqlite3_vfs objects are kept on a linked list formed by +** the pNext pointer. The [sqlite3_vfs_register()] +** and [sqlite3_vfs_unregister()] interfaces manage this list +** in a thread-safe way. The [sqlite3_vfs_find()] interface +** searches the list. Neither the application code nor the VFS +** implementation should use the pNext pointer. +** +** The pNext field is the only field in the sqlite3_vfs +** structure that SQLite will ever modify. SQLite will only access +** or modify this field while holding a particular static mutex. +** The application should never modify anything within the sqlite3_vfs +** object once the object has been registered. +** +** The zName field holds the name of the VFS module. The name must +** be unique across all VFS modules. +** +** [[sqlite3_vfs.xOpen]] +** ^SQLite guarantees that the zFilename parameter to xOpen +** is either a NULL pointer or string obtained +** from xFullPathname() with an optional suffix added. +** ^If a suffix is added to the zFilename parameter, it will +** consist of a single "-" character followed by no more than +** 11 alphanumeric and/or "-" characters. +** ^SQLite further guarantees that +** the string will be valid and unchanged until xClose() is +** called. Because of the previous sentence, +** the [sqlite3_file] can safely store a pointer to the +** filename if it needs to remember the filename for some reason. +** If the zFilename parameter to xOpen is a NULL pointer then xOpen +** must invent its own temporary name for the file. ^Whenever the +** xFilename parameter is NULL it will also be the case that the +** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. +** +** The flags argument to xOpen() includes all bits set in +** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] +** or [sqlite3_open16()] is used, then flags includes at least +** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. +** If xOpen() opens a file read-only then it sets *pOutFlags to +** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set. +** +** ^(SQLite will also add one of the following flags to the xOpen() +** call, depending on the object being opened: +** +**
    +**
  • [SQLITE_OPEN_MAIN_DB] +**
  • [SQLITE_OPEN_MAIN_JOURNAL] +**
  • [SQLITE_OPEN_TEMP_DB] +**
  • [SQLITE_OPEN_TEMP_JOURNAL] +**
  • [SQLITE_OPEN_TRANSIENT_DB] +**
  • [SQLITE_OPEN_SUBJOURNAL] +**
  • [SQLITE_OPEN_MASTER_JOURNAL] +**
  • [SQLITE_OPEN_WAL] +**
)^ +** +** The file I/O implementation can use the object type flags to +** change the way it deals with files. For example, an application +** that does not care about crash recovery or rollback might make +** the open of a journal file a no-op. Writes to this journal would +** also be no-ops, and any attempt to read the journal would return +** SQLITE_IOERR. Or the implementation might recognize that a database +** file will be doing page-aligned sector reads and writes in a random +** order and set up its I/O subsystem accordingly. +** +** SQLite might also add one of the following flags to the xOpen method: +** +**
    +**
  • [SQLITE_OPEN_DELETEONCLOSE] +**
  • [SQLITE_OPEN_EXCLUSIVE] +**
+** +** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be +** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE] +** will be set for TEMP databases and their journals, transient +** databases, and subjournals. +** +** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction +** with the [SQLITE_OPEN_CREATE] flag, which are both directly +** analogous to the O_EXCL and O_CREAT flags of the POSIX open() +** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the +** SQLITE_OPEN_CREATE, is used to indicate that file should always +** be created, and that it is an error if it already exists. +** It is not used to indicate the file should be opened +** for exclusive access. +** +** ^At least szOsFile bytes of memory are allocated by SQLite +** to hold the [sqlite3_file] structure passed as the third +** argument to xOpen. The xOpen method does not have to +** allocate the structure; it should just fill it in. Note that +** the xOpen method must set the sqlite3_file.pMethods to either +** a valid [sqlite3_io_methods] object or to NULL. xOpen must do +** this even if the open fails. SQLite expects that the sqlite3_file.pMethods +** element will be valid after xOpen returns regardless of the success +** or failure of the xOpen call. +** +** [[sqlite3_vfs.xAccess]] +** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] +** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to +** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] +** to test whether a file is at least readable. The file can be a +** directory. +** +** ^SQLite will always allocate at least mxPathname+1 bytes for the +** output buffer xFullPathname. The exact size of the output buffer +** is also passed as a parameter to both methods. If the output buffer +** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is +** handled as a fatal error by SQLite, vfs implementations should endeavor +** to prevent this by setting mxPathname to a sufficiently large value. +** +** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64() +** interfaces are not strictly a part of the filesystem, but they are +** included in the VFS structure for completeness. +** The xRandomness() function attempts to return nBytes bytes +** of good-quality randomness into zOut. The return value is +** the actual number of bytes of randomness obtained. +** The xSleep() method causes the calling thread to sleep for at +** least the number of microseconds given. ^The xCurrentTime() +** method returns a Julian Day Number for the current date and time as +** a floating point value. +** ^The xCurrentTimeInt64() method returns, as an integer, the Julian +** Day Number multiplied by 86400000 (the number of milliseconds in +** a 24-hour day). +** ^SQLite will use the xCurrentTimeInt64() method to get the current +** date and time if that method is available (if iVersion is 2 or +** greater and the function pointer is not NULL) and will fall back +** to xCurrentTime() if xCurrentTimeInt64() is unavailable. +** +** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces +** are not used by the SQLite core. These optional interfaces are provided +** by some VFSes to facilitate testing of the VFS code. By overriding +** system calls with functions under its control, a test program can +** simulate faults and error conditions that would otherwise be difficult +** or impossible to induce. The set of system calls that can be overridden +** varies from one VFS to another, and from one version of the same VFS to the +** next. Applications that use these interfaces must be prepared for any +** or all of these interfaces to be NULL or for their behavior to change +** from one release to the next. Applications must not attempt to access +** any of these methods if the iVersion of the VFS is less than 3. +*/ +typedef struct sqlite3_vfs sqlite3_vfs; +typedef void (*sqlite3_syscall_ptr)(void); +struct sqlite3_vfs { + int iVersion; /* Structure version number (currently 3) */ + int szOsFile; /* Size of subclassed sqlite3_file */ + int mxPathname; /* Maximum file pathname length */ + sqlite3_vfs *pNext; /* Next registered VFS */ + const char *zName; /* Name of this virtual file system */ + void *pAppData; /* Pointer to application-specific data */ + int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, + int flags, int *pOutFlags); + int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); + int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); + int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); + void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); + void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); + void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); + void (*xDlClose)(sqlite3_vfs*, void*); + int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); + int (*xSleep)(sqlite3_vfs*, int microseconds); + int (*xCurrentTime)(sqlite3_vfs*, double*); + int (*xGetLastError)(sqlite3_vfs*, int, char *); + /* + ** The methods above are in version 1 of the sqlite_vfs object + ** definition. Those that follow are added in version 2 or later + */ + int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); + /* + ** The methods above are in versions 1 and 2 of the sqlite_vfs object. + ** Those below are for version 3 and greater. + */ + int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); + sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); + const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); + /* + ** The methods above are in versions 1 through 3 of the sqlite_vfs object. + ** New fields may be appended in figure versions. The iVersion + ** value will increment whenever this happens. + */ +}; + +/* +** CAPI3REF: Flags for the xAccess VFS method +** +** These integer constants can be used as the third parameter to +** the xAccess method of an [sqlite3_vfs] object. They determine +** what kind of permissions the xAccess method is looking for. +** With SQLITE_ACCESS_EXISTS, the xAccess method +** simply checks whether the file exists. +** With SQLITE_ACCESS_READWRITE, the xAccess method +** checks whether the named directory is both readable and writable +** (in other words, if files can be added, removed, and renamed within +** the directory). +** The SQLITE_ACCESS_READWRITE constant is currently used only by the +** [temp_store_directory pragma], though this could change in a future +** release of SQLite. +** With SQLITE_ACCESS_READ, the xAccess method +** checks whether the file is readable. The SQLITE_ACCESS_READ constant is +** currently unused, though it might be used in a future release of +** SQLite. +*/ +#define SQLITE_ACCESS_EXISTS 0 +#define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */ +#define SQLITE_ACCESS_READ 2 /* Unused */ + +/* +** CAPI3REF: Flags for the xShmLock VFS method +** +** These integer constants define the various locking operations +** allowed by the xShmLock method of [sqlite3_io_methods]. The +** following are the only legal combinations of flags to the +** xShmLock method: +** +**
    +**
  • SQLITE_SHM_LOCK | SQLITE_SHM_SHARED +**
  • SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE +**
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED +**
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE +**
+** +** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as +** was given on the corresponding lock. +** +** The xShmLock method can transition between unlocked and SHARED or +** between unlocked and EXCLUSIVE. It cannot transition between SHARED +** and EXCLUSIVE. +*/ +#define SQLITE_SHM_UNLOCK 1 +#define SQLITE_SHM_LOCK 2 +#define SQLITE_SHM_SHARED 4 +#define SQLITE_SHM_EXCLUSIVE 8 + +/* +** CAPI3REF: Maximum xShmLock index +** +** The xShmLock method on [sqlite3_io_methods] may use values +** between 0 and this upper bound as its "offset" argument. +** The SQLite core will never attempt to acquire or release a +** lock outside of this range +*/ +#define SQLITE_SHM_NLOCK 8 + + +/* +** CAPI3REF: Initialize The SQLite Library +** +** ^The sqlite3_initialize() routine initializes the +** SQLite library. ^The sqlite3_shutdown() routine +** deallocates any resources that were allocated by sqlite3_initialize(). +** These routines are designed to aid in process initialization and +** shutdown on embedded systems. Workstation applications using +** SQLite normally do not need to invoke either of these routines. +** +** A call to sqlite3_initialize() is an "effective" call if it is +** the first time sqlite3_initialize() is invoked during the lifetime of +** the process, or if it is the first time sqlite3_initialize() is invoked +** following a call to sqlite3_shutdown(). ^(Only an effective call +** of sqlite3_initialize() does any initialization. All other calls +** are harmless no-ops.)^ +** +** A call to sqlite3_shutdown() is an "effective" call if it is the first +** call to sqlite3_shutdown() since the last sqlite3_initialize(). ^(Only +** an effective call to sqlite3_shutdown() does any deinitialization. +** All other valid calls to sqlite3_shutdown() are harmless no-ops.)^ +** +** The sqlite3_initialize() interface is threadsafe, but sqlite3_shutdown() +** is not. The sqlite3_shutdown() interface must only be called from a +** single thread. All open [database connections] must be closed and all +** other SQLite resources must be deallocated prior to invoking +** sqlite3_shutdown(). +** +** Among other things, ^sqlite3_initialize() will invoke +** sqlite3_os_init(). Similarly, ^sqlite3_shutdown() +** will invoke sqlite3_os_end(). +** +** ^The sqlite3_initialize() routine returns [SQLITE_OK] on success. +** ^If for some reason, sqlite3_initialize() is unable to initialize +** the library (perhaps it is unable to allocate a needed resource such +** as a mutex) it returns an [error code] other than [SQLITE_OK]. +** +** ^The sqlite3_initialize() routine is called internally by many other +** SQLite interfaces so that an application usually does not need to +** invoke sqlite3_initialize() directly. For example, [sqlite3_open()] +** calls sqlite3_initialize() so the SQLite library will be automatically +** initialized when [sqlite3_open()] is called if it has not be initialized +** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT] +** compile-time option, then the automatic calls to sqlite3_initialize() +** are omitted and the application must call sqlite3_initialize() directly +** prior to using any other SQLite interface. For maximum portability, +** it is recommended that applications always invoke sqlite3_initialize() +** directly prior to using any other SQLite interface. Future releases +** of SQLite may require this. In other words, the behavior exhibited +** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the +** default behavior in some future release of SQLite. +** +** The sqlite3_os_init() routine does operating-system specific +** initialization of the SQLite library. The sqlite3_os_end() +** routine undoes the effect of sqlite3_os_init(). Typical tasks +** performed by these routines include allocation or deallocation +** of static resources, initialization of global variables, +** setting up a default [sqlite3_vfs] module, or setting up +** a default configuration using [sqlite3_config()]. +** +** The application should never invoke either sqlite3_os_init() +** or sqlite3_os_end() directly. The application should only invoke +** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init() +** interface is called automatically by sqlite3_initialize() and +** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate +** implementations for sqlite3_os_init() and sqlite3_os_end() +** are built into SQLite when it is compiled for Unix, Windows, or OS/2. +** When [custom builds | built for other platforms] +** (using the [SQLITE_OS_OTHER=1] compile-time +** option) the application must supply a suitable implementation for +** sqlite3_os_init() and sqlite3_os_end(). An application-supplied +** implementation of sqlite3_os_init() or sqlite3_os_end() +** must return [SQLITE_OK] on success and some other [error code] upon +** failure. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void); +SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void); +SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void); +SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); + +/* +** CAPI3REF: Configuring The SQLite Library +** +** The sqlite3_config() interface is used to make global configuration +** changes to SQLite in order to tune SQLite to the specific needs of +** the application. The default configuration is recommended for most +** applications and so this routine is usually not necessary. It is +** provided to support rare applications with unusual needs. +** +** The sqlite3_config() interface is not threadsafe. The application +** must insure that no other SQLite interfaces are invoked by other +** threads while sqlite3_config() is running. Furthermore, sqlite3_config() +** may only be invoked prior to library initialization using +** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. +** ^If sqlite3_config() is called after [sqlite3_initialize()] and before +** [sqlite3_shutdown()] then it will return SQLITE_MISUSE. +** Note, however, that ^sqlite3_config() can be called as part of the +** implementation of an application-defined [sqlite3_os_init()]. +** +** The first argument to sqlite3_config() is an integer +** [configuration option] that determines +** what property of SQLite is to be configured. Subsequent arguments +** vary depending on the [configuration option] +** in the first argument. +** +** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK]. +** ^If the option is unknown or SQLite is unable to set the option +** then this routine returns a non-zero [error code]. +*/ +SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...); + +/* +** CAPI3REF: Configure database connections +** METHOD: sqlite3 +** +** The sqlite3_db_config() interface is used to make configuration +** changes to a [database connection]. The interface is similar to +** [sqlite3_config()] except that the changes apply to a single +** [database connection] (specified in the first argument). +** +** The second argument to sqlite3_db_config(D,V,...) is the +** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code +** that indicates what aspect of the [database connection] is being configured. +** Subsequent arguments vary depending on the configuration verb. +** +** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if +** the call is considered successful. +*/ +SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3*, int op, ...); + +/* +** CAPI3REF: Memory Allocation Routines +** +** An instance of this object defines the interface between SQLite +** and low-level memory allocation routines. +** +** This object is used in only one place in the SQLite interface. +** A pointer to an instance of this object is the argument to +** [sqlite3_config()] when the configuration option is +** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. +** By creating an instance of this object +** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC]) +** during configuration, an application can specify an alternative +** memory allocation subsystem for SQLite to use for all of its +** dynamic memory needs. +** +** Note that SQLite comes with several [built-in memory allocators] +** that are perfectly adequate for the overwhelming majority of applications +** and that this object is only useful to a tiny minority of applications +** with specialized memory allocation requirements. This object is +** also used during testing of SQLite in order to specify an alternative +** memory allocator that simulates memory out-of-memory conditions in +** order to verify that SQLite recovers gracefully from such +** conditions. +** +** The xMalloc, xRealloc, and xFree methods must work like the +** malloc(), realloc() and free() functions from the standard C library. +** ^SQLite guarantees that the second argument to +** xRealloc is always a value returned by a prior call to xRoundup. +** +** xSize should return the allocated size of a memory allocation +** previously obtained from xMalloc or xRealloc. The allocated size +** is always at least as big as the requested size but may be larger. +** +** The xRoundup method returns what would be the allocated size of +** a memory allocation given a particular requested size. Most memory +** allocators round up memory allocations at least to the next multiple +** of 8. Some allocators round up to a larger multiple or to a power of 2. +** Every memory allocation request coming in through [sqlite3_malloc()] +** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, +** that causes the corresponding memory allocation to fail. +** +** The xInit method initializes the memory allocator. For example, +** it might allocate any require mutexes or initialize internal data +** structures. The xShutdown method is invoked (indirectly) by +** [sqlite3_shutdown()] and should deallocate any resources acquired +** by xInit. The pAppData pointer is used as the only parameter to +** xInit and xShutdown. +** +** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes +** the xInit method, so the xInit method need not be threadsafe. The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. For all other methods, SQLite +** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the +** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which +** it is by default) and so the methods are automatically serialized. +** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other +** methods must be threadsafe or else make their own arrangements for +** serialization. +** +** SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). +*/ +typedef struct sqlite3_mem_methods sqlite3_mem_methods; +struct sqlite3_mem_methods { + void *(*xMalloc)(int); /* Memory allocation function */ + void (*xFree)(void*); /* Free a prior allocation */ + void *(*xRealloc)(void*,int); /* Resize an allocation */ + int (*xSize)(void*); /* Return the size of an allocation */ + int (*xRoundup)(int); /* Round up request size to allocation size */ + int (*xInit)(void*); /* Initialize the memory allocator */ + void (*xShutdown)(void*); /* Deinitialize the memory allocator */ + void *pAppData; /* Argument to xInit() and xShutdown() */ +}; + +/* +** CAPI3REF: Configuration Options +** KEYWORDS: {configuration option} +** +** These constants are the available integer configuration options that +** can be passed as the first argument to the [sqlite3_config()] interface. +** +** New configuration options may be added in future releases of SQLite. +** Existing configuration options might be discontinued. Applications +** should check the return code from [sqlite3_config()] to make sure that +** the call worked. The [sqlite3_config()] interface will return a +** non-zero [error code] if a discontinued or unsupported configuration option +** is invoked. +** +**
+** [[SQLITE_CONFIG_SINGLETHREAD]]
SQLITE_CONFIG_SINGLETHREAD
+**
There are no arguments to this option. ^This option sets the +** [threading mode] to Single-thread. In other words, it disables +** all mutexing and puts SQLite into a mode where it can only be used +** by a single thread. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to change the [threading mode] from its default +** value of Single-thread and so [sqlite3_config()] will return +** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD +** configuration option.
+** +** [[SQLITE_CONFIG_MULTITHREAD]]
SQLITE_CONFIG_MULTITHREAD
+**
There are no arguments to this option. ^This option sets the +** [threading mode] to Multi-thread. In other words, it disables +** mutexing on [database connection] and [prepared statement] objects. +** The application is responsible for serializing access to +** [database connections] and [prepared statements]. But other mutexes +** are enabled so that SQLite will be safe to use in a multi-threaded +** environment as long as no two threads attempt to use the same +** [database connection] at the same time. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to set the Multi-thread [threading mode] and +** [sqlite3_config()] will return [SQLITE_ERROR] if called with the +** SQLITE_CONFIG_MULTITHREAD configuration option.
+** +** [[SQLITE_CONFIG_SERIALIZED]]
SQLITE_CONFIG_SERIALIZED
+**
There are no arguments to this option. ^This option sets the +** [threading mode] to Serialized. In other words, this option enables +** all mutexes including the recursive +** mutexes on [database connection] and [prepared statement] objects. +** In this mode (which is the default when SQLite is compiled with +** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access +** to [database connections] and [prepared statements] so that the +** application is free to use the same [database connection] or the +** same [prepared statement] in different threads at the same time. +** ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to set the Serialized [threading mode] and +** [sqlite3_config()] will return [SQLITE_ERROR] if called with the +** SQLITE_CONFIG_SERIALIZED configuration option.
+** +** [[SQLITE_CONFIG_MALLOC]]
SQLITE_CONFIG_MALLOC
+**
^(The SQLITE_CONFIG_MALLOC option takes a single argument which is +** a pointer to an instance of the [sqlite3_mem_methods] structure. +** The argument specifies +** alternative low-level memory allocation routines to be used in place of +** the memory allocation routines built into SQLite.)^ ^SQLite makes +** its own private copy of the content of the [sqlite3_mem_methods] structure +** before the [sqlite3_config()] call returns.
+** +** [[SQLITE_CONFIG_GETMALLOC]]
SQLITE_CONFIG_GETMALLOC
+**
^(The SQLITE_CONFIG_GETMALLOC option takes a single argument which +** is a pointer to an instance of the [sqlite3_mem_methods] structure. +** The [sqlite3_mem_methods] +** structure is filled with the currently defined memory allocation routines.)^ +** This option can be used to overload the default memory allocation +** routines with a wrapper that simulations memory allocation failure or +** tracks memory usage, for example.
+** +** [[SQLITE_CONFIG_MEMSTATUS]]
SQLITE_CONFIG_MEMSTATUS
+**
^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, +** interpreted as a boolean, which enables or disables the collection of +** memory allocation statistics. ^(When memory allocation statistics are +** disabled, the following SQLite interfaces become non-operational: +**
    +**
  • [sqlite3_memory_used()] +**
  • [sqlite3_memory_highwater()] +**
  • [sqlite3_soft_heap_limit64()] +**
  • [sqlite3_status64()] +**
)^ +** ^Memory allocation statistics are enabled by default unless SQLite is +** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory +** allocation statistics are disabled by default. +**
+** +** [[SQLITE_CONFIG_SCRATCH]]
SQLITE_CONFIG_SCRATCH
+**
^The SQLITE_CONFIG_SCRATCH option specifies a static memory buffer +** that SQLite can use for scratch memory. ^(There are three arguments +** to SQLITE_CONFIG_SCRATCH: A pointer an 8-byte +** aligned memory buffer from which the scratch allocations will be +** drawn, the size of each scratch allocation (sz), +** and the maximum number of scratch allocations (N).)^ +** The first argument must be a pointer to an 8-byte aligned buffer +** of at least sz*N bytes of memory. +** ^SQLite will not use more than one scratch buffers per thread. +** ^SQLite will never request a scratch buffer that is more than 6 +** times the database page size. +** ^If SQLite needs needs additional +** scratch memory beyond what is provided by this configuration option, then +** [sqlite3_malloc()] will be used to obtain the memory needed.

+** ^When the application provides any amount of scratch memory using +** SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary large +** [sqlite3_malloc|heap allocations]. +** This can help [Robson proof|prevent memory allocation failures] due to heap +** fragmentation in low-memory embedded systems. +**

+** +** [[SQLITE_CONFIG_PAGECACHE]]
SQLITE_CONFIG_PAGECACHE
+**
^The SQLITE_CONFIG_PAGECACHE option specifies a static memory buffer +** that SQLite can use for the database page cache with the default page +** cache implementation. +** This configuration should not be used if an application-define page +** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] +** configuration option. +** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to +** 8-byte aligned +** memory, the size of each page buffer (sz), and the number of pages (N). +** The sz argument should be the size of the largest database page +** (a power of two between 512 and 65536) plus some extra bytes for each +** page header. ^The number of extra bytes needed by the page header +** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option +** to [sqlite3_config()]. +** ^It is harmless, apart from the wasted memory, +** for the sz parameter to be larger than necessary. The first +** argument should pointer to an 8-byte aligned block of memory that +** is at least sz*N bytes of memory, otherwise subsequent behavior is +** undefined. +** ^SQLite will use the memory provided by the first argument to satisfy its +** memory needs for the first N pages that it adds to cache. ^If additional +** page cache memory is needed beyond what is provided by this option, then +** SQLite goes to [sqlite3_malloc()] for the additional storage space.
+** +** [[SQLITE_CONFIG_HEAP]]
SQLITE_CONFIG_HEAP
+**
^The SQLITE_CONFIG_HEAP option specifies a static memory buffer +** that SQLite will use for all of its dynamic memory allocation needs +** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and +** [SQLITE_CONFIG_PAGECACHE]. +** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled +** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns +** [SQLITE_ERROR] if invoked otherwise. +** ^There are three arguments to SQLITE_CONFIG_HEAP: +** An 8-byte aligned pointer to the memory, +** the number of bytes in the memory buffer, and the minimum allocation size. +** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts +** to using its default memory allocator (the system malloc() implementation), +** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the +** memory pointer is not NULL then the alternative memory +** allocator is engaged to handle all of SQLites memory allocation needs. +** The first pointer (the memory pointer) must be aligned to an 8-byte +** boundary or subsequent behavior of SQLite will be undefined. +** The minimum allocation size is capped at 2**12. Reasonable values +** for the minimum allocation size are 2**5 through 2**8.
+** +** [[SQLITE_CONFIG_MUTEX]]
SQLITE_CONFIG_MUTEX
+**
^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a +** pointer to an instance of the [sqlite3_mutex_methods] structure. +** The argument specifies alternative low-level mutex routines to be used +** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of +** the content of the [sqlite3_mutex_methods] structure before the call to +** [sqlite3_config()] returns. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** the entire mutexing subsystem is omitted from the build and hence calls to +** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will +** return [SQLITE_ERROR].
+** +** [[SQLITE_CONFIG_GETMUTEX]]
SQLITE_CONFIG_GETMUTEX
+**
^(The SQLITE_CONFIG_GETMUTEX option takes a single argument which +** is a pointer to an instance of the [sqlite3_mutex_methods] structure. The +** [sqlite3_mutex_methods] +** structure is filled with the currently defined mutex routines.)^ +** This option can be used to overload the default mutex allocation +** routines with a wrapper used to track mutex usage for performance +** profiling or testing, for example. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** the entire mutexing subsystem is omitted from the build and hence calls to +** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will +** return [SQLITE_ERROR].
+** +** [[SQLITE_CONFIG_LOOKASIDE]]
SQLITE_CONFIG_LOOKASIDE
+**
^(The SQLITE_CONFIG_LOOKASIDE option takes two arguments that determine +** the default size of lookaside memory on each [database connection]. +** The first argument is the +** size of each lookaside buffer slot and the second is the number of +** slots allocated to each database connection.)^ ^(SQLITE_CONFIG_LOOKASIDE +** sets the default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] +** option to [sqlite3_db_config()] can be used to change the lookaside +** configuration on individual connections.)^
+** +** [[SQLITE_CONFIG_PCACHE2]]
SQLITE_CONFIG_PCACHE2
+**
^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is +** a pointer to an [sqlite3_pcache_methods2] object. This object specifies +** the interface to a custom page cache implementation.)^ +** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.
+** +** [[SQLITE_CONFIG_GETPCACHE2]]
SQLITE_CONFIG_GETPCACHE2
+**
^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which +** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of +** the current page cache implementation into that object.)^
+** +** [[SQLITE_CONFIG_LOG]]
SQLITE_CONFIG_LOG
+**
The SQLITE_CONFIG_LOG option is used to configure the SQLite +** global [error log]. +** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a +** function with a call signature of void(*)(void*,int,const char*), +** and a pointer to void. ^If the function pointer is not NULL, it is +** invoked by [sqlite3_log()] to process each logging event. ^If the +** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. +** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is +** passed through as the first parameter to the application-defined logger +** function whenever that function is invoked. ^The second parameter to +** the logger function is a copy of the first parameter to the corresponding +** [sqlite3_log()] call and is intended to be a [result code] or an +** [extended result code]. ^The third parameter passed to the logger is +** log message after formatting via [sqlite3_snprintf()]. +** The SQLite logging interface is not reentrant; the logger function +** supplied by the application must not invoke any SQLite interface. +** In a multi-threaded application, the application-defined logger +** function must be threadsafe.
+** +** [[SQLITE_CONFIG_URI]]
SQLITE_CONFIG_URI +**
^(The SQLITE_CONFIG_URI option takes a single argument of type int. +** If non-zero, then URI handling is globally enabled. If the parameter is zero, +** then URI handling is globally disabled.)^ ^If URI handling is globally +** enabled, all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], +** [sqlite3_open16()] or +** specified as part of [ATTACH] commands are interpreted as URIs, regardless +** of whether or not the [SQLITE_OPEN_URI] flag is set when the database +** connection is opened. ^If it is globally disabled, filenames are +** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the +** database connection is opened. ^(By default, URI handling is globally +** disabled. The default value may be changed by compiling with the +** [SQLITE_USE_URI] symbol defined.)^ +** +** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]]
SQLITE_CONFIG_COVERING_INDEX_SCAN +**
^The SQLITE_CONFIG_COVERING_INDEX_SCAN option takes a single integer +** argument which is interpreted as a boolean in order to enable or disable +** the use of covering indices for full table scans in the query optimizer. +** ^The default setting is determined +** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" +** if that compile-time option is omitted. +** The ability to disable the use of covering indices for full table scans +** is because some incorrectly coded legacy applications might malfunction +** when the optimization is enabled. Providing the ability to +** disable the optimization allows the older, buggy application code to work +** without change even with newer versions of SQLite. +** +** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] +**
SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE +**
These options are obsolete and should not be used by new code. +** They are retained for backwards compatibility but are now no-ops. +**
+** +** [[SQLITE_CONFIG_SQLLOG]] +**
SQLITE_CONFIG_SQLLOG +**
This option is only available if sqlite is compiled with the +** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should +** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int). +** The second should be of type (void*). The callback is invoked by the library +** in three separate circumstances, identified by the value passed as the +** fourth parameter. If the fourth parameter is 0, then the database connection +** passed as the second argument has just been opened. The third argument +** points to a buffer containing the name of the main database file. If the +** fourth parameter is 1, then the SQL statement that the third parameter +** points to has just been executed. Or, if the fourth parameter is 2, then +** the connection being passed as the second parameter is being closed. The +** third parameter is passed NULL In this case. An example of using this +** configuration option can be seen in the "test_sqllog.c" source file in +** the canonical SQLite source tree.
+** +** [[SQLITE_CONFIG_MMAP_SIZE]] +**
SQLITE_CONFIG_MMAP_SIZE +**
^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values +** that are the default mmap size limit (the default setting for +** [PRAGMA mmap_size]) and the maximum allowed mmap size limit. +** ^The default setting can be overridden by each database connection using +** either the [PRAGMA mmap_size] command, or by using the +** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size +** will be silently truncated if necessary so that it does not exceed the +** compile-time maximum mmap size set by the +** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ +** ^If either argument to this option is negative, then that argument is +** changed to its compile-time default. +** +** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] +**
SQLITE_CONFIG_WIN32_HEAPSIZE +**
^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is +** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro +** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value +** that specifies the maximum size of the created heap. +** +** [[SQLITE_CONFIG_PCACHE_HDRSZ]] +**
SQLITE_CONFIG_PCACHE_HDRSZ +**
^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which +** is a pointer to an integer and writes into that integer the number of extra +** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. +** The amount of extra space required can change depending on the compiler, +** target platform, and SQLite version. +** +** [[SQLITE_CONFIG_PMASZ]] +**
SQLITE_CONFIG_PMASZ +**
^The SQLITE_CONFIG_PMASZ option takes a single parameter which +** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded +** sorter to that integer. The default minimum PMA Size is set by the +** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched +** to help with sort operations when multithreaded sorting +** is enabled (using the [PRAGMA threads] command) and the amount of content +** to be sorted exceeds the page size times the minimum of the +** [PRAGMA cache_size] setting and this value. +**
+*/ +#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ +#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ +#define SQLITE_CONFIG_SERIALIZED 3 /* nil */ +#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ +#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ +#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ +#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ +#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ +#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ +#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ +#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ +/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ +#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ +#define SQLITE_CONFIG_PCACHE 14 /* no-op */ +#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ +#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ +#define SQLITE_CONFIG_URI 17 /* int */ +#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ +#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ +#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ +#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ +#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ +#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ + +/* +** CAPI3REF: Database Connection Configuration Options +** +** These constants are the available integer configuration options that +** can be passed as the second argument to the [sqlite3_db_config()] interface. +** +** New configuration options may be added in future releases of SQLite. +** Existing configuration options might be discontinued. Applications +** should check the return code from [sqlite3_db_config()] to make sure that +** the call worked. ^The [sqlite3_db_config()] interface will return a +** non-zero [error code] if a discontinued or unsupported configuration option +** is invoked. +** +**
+**
SQLITE_DBCONFIG_LOOKASIDE
+**
^This option takes three additional arguments that determine the +** [lookaside memory allocator] configuration for the [database connection]. +** ^The first argument (the third parameter to [sqlite3_db_config()] is a +** pointer to a memory buffer to use for lookaside memory. +** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb +** may be NULL in which case SQLite will allocate the +** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the +** size of each lookaside buffer slot. ^The third argument is the number of +** slots. The size of the buffer in the first argument must be greater than +** or equal to the product of the second and third arguments. The buffer +** must be aligned to an 8-byte boundary. ^If the second argument to +** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally +** rounded down to the next smaller multiple of 8. ^(The lookaside memory +** configuration for a database connection can only be changed when that +** connection is not currently using lookaside memory, or in other words +** when the "current value" returned by +** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero. +** Any attempt to change the lookaside memory configuration when lookaside +** memory is in use leaves the configuration unchanged and returns +** [SQLITE_BUSY].)^
+** +**
SQLITE_DBCONFIG_ENABLE_FKEY
+**
^This option is used to enable or disable the enforcement of +** [foreign key constraints]. There should be two additional arguments. +** The first argument is an integer which is 0 to disable FK enforcement, +** positive to enable FK enforcement or negative to leave FK enforcement +** unchanged. The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether FK enforcement is off or on +** following this call. The second parameter may be a NULL pointer, in +** which case the FK enforcement setting is not reported back.
+** +**
SQLITE_DBCONFIG_ENABLE_TRIGGER
+**
^This option is used to enable or disable [CREATE TRIGGER | triggers]. +** There should be two additional arguments. +** The first argument is an integer which is 0 to disable triggers, +** positive to enable triggers or negative to leave the setting unchanged. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether triggers are disabled or enabled +** following this call. The second parameter may be a NULL pointer, in +** which case the trigger setting is not reported back.
+** +**
+*/ +#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ +#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ + + +/* +** CAPI3REF: Enable Or Disable Extended Result Codes +** METHOD: sqlite3 +** +** ^The sqlite3_extended_result_codes() routine enables or disables the +** [extended result codes] feature of SQLite. ^The extended result +** codes are disabled by default for historical compatibility. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff); + +/* +** CAPI3REF: Last Insert Rowid +** METHOD: sqlite3 +** +** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables) +** has a unique 64-bit signed +** integer key called the [ROWID | "rowid"]. ^The rowid is always available +** as an undeclared column named ROWID, OID, or _ROWID_ as long as those +** names are not also used by explicitly declared columns. ^If +** the table has a column of type [INTEGER PRIMARY KEY] then that column +** is another alias for the rowid. +** +** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the +** most recent successful [INSERT] into a rowid table or [virtual table] +** on database connection D. +** ^Inserts into [WITHOUT ROWID] tables are not recorded. +** ^If no successful [INSERT]s into rowid tables +** have ever occurred on the database connection D, +** then sqlite3_last_insert_rowid(D) returns zero. +** +** ^(If an [INSERT] occurs within a trigger or within a [virtual table] +** method, then this routine will return the [rowid] of the inserted +** row as long as the trigger or virtual table method is running. +** But once the trigger or virtual table method ends, the value returned +** by this routine reverts to what it was before the trigger or virtual +** table method began.)^ +** +** ^An [INSERT] that fails due to a constraint violation is not a +** successful [INSERT] and does not change the value returned by this +** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, +** and INSERT OR ABORT make no changes to the return value of this +** routine when their insertion fails. ^(When INSERT OR REPLACE +** encounters a constraint violation, it does not fail. The +** INSERT continues to completion after deleting rows that caused +** the constraint problem so INSERT OR REPLACE will always change +** the return value of this interface.)^ +** +** ^For the purposes of this routine, an [INSERT] is considered to +** be successful even if it is subsequently rolled back. +** +** This function is accessible to SQL statements via the +** [last_insert_rowid() SQL function]. +** +** If a separate thread performs a new [INSERT] on the same +** database connection while the [sqlite3_last_insert_rowid()] +** function is running and thus changes the last insert [rowid], +** then the value returned by [sqlite3_last_insert_rowid()] is +** unpredictable and might not equal either the old or the new +** last insert [rowid]. +*/ +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*); + +/* +** CAPI3REF: Count The Number Of Rows Modified +** METHOD: sqlite3 +** +** ^This function returns the number of rows modified, inserted or +** deleted by the most recently completed INSERT, UPDATE or DELETE +** statement on the database connection specified by the only parameter. +** ^Executing any other type of SQL statement does not modify the value +** returned by this function. +** +** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are +** considered - auxiliary changes caused by [CREATE TRIGGER | triggers], +** [foreign key actions] or [REPLACE] constraint resolution are not counted. +** +** Changes to a view that are intercepted by +** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value +** returned by sqlite3_changes() immediately after an INSERT, UPDATE or +** DELETE statement run on a view is always zero. Only changes made to real +** tables are counted. +** +** Things are more complicated if the sqlite3_changes() function is +** executed while a trigger program is running. This may happen if the +** program uses the [changes() SQL function], or if some other callback +** function invokes sqlite3_changes() directly. Essentially: +** +**
    +**
  • ^(Before entering a trigger program the value returned by +** sqlite3_changes() function is saved. After the trigger program +** has finished, the original value is restored.)^ +** +**
  • ^(Within a trigger program each INSERT, UPDATE and DELETE +** statement sets the value returned by sqlite3_changes() +** upon completion as normal. Of course, this value will not include +** any changes performed by sub-triggers, as the sqlite3_changes() +** value will be saved and restored after each sub-trigger has run.)^ +**
+** +** ^This means that if the changes() SQL function (or similar) is used +** by the first INSERT, UPDATE or DELETE statement within a trigger, it +** returns the value as set when the calling statement began executing. +** ^If it is used by the second or subsequent such statement within a trigger +** program, the value returned reflects the number of rows modified by the +** previous INSERT, UPDATE or DELETE statement within the same trigger. +** +** See also the [sqlite3_total_changes()] interface, the +** [count_changes pragma], and the [changes() SQL function]. +** +** If a separate thread makes changes on the same database connection +** while [sqlite3_changes()] is running then the value returned +** is unpredictable and not meaningful. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*); + +/* +** CAPI3REF: Total Number Of Rows Modified +** METHOD: sqlite3 +** +** ^This function returns the total number of rows inserted, modified or +** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed +** since the database connection was opened, including those executed as +** part of trigger programs. ^Executing any other type of SQL statement +** does not affect the value returned by sqlite3_total_changes(). +** +** ^Changes made as part of [foreign key actions] are included in the +** count, but those made as part of REPLACE constraint resolution are +** not. ^Changes to a view that are intercepted by INSTEAD OF triggers +** are not counted. +** +** See also the [sqlite3_changes()] interface, the +** [count_changes pragma], and the [total_changes() SQL function]. +** +** If a separate thread makes changes on the same database connection +** while [sqlite3_total_changes()] is running then the value +** returned is unpredictable and not meaningful. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*); + +/* +** CAPI3REF: Interrupt A Long-Running Query +** METHOD: sqlite3 +** +** ^This function causes any pending database operation to abort and +** return at its earliest opportunity. This routine is typically +** called in response to a user action such as pressing "Cancel" +** or Ctrl-C where the user wants a long query operation to halt +** immediately. +** +** ^It is safe to call this routine from a thread different from the +** thread that is currently running the database operation. But it +** is not safe to call this routine with a [database connection] that +** is closed or might close before sqlite3_interrupt() returns. +** +** ^If an SQL operation is very nearly finished at the time when +** sqlite3_interrupt() is called, then it might not have an opportunity +** to be interrupted and might continue to completion. +** +** ^An SQL operation that is interrupted will return [SQLITE_INTERRUPT]. +** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE +** that is inside an explicit transaction, then the entire transaction +** will be rolled back automatically. +** +** ^The sqlite3_interrupt(D) call is in effect until all currently running +** SQL statements on [database connection] D complete. ^Any new SQL statements +** that are started after the sqlite3_interrupt() call and before the +** running statements reaches zero are interrupted as if they had been +** running prior to the sqlite3_interrupt() call. ^New SQL statements +** that are started after the running statement count reaches zero are +** not effected by the sqlite3_interrupt(). +** ^A call to sqlite3_interrupt(D) that occurs when there are no running +** SQL statements is a no-op and has no effect on SQL statements +** that are started after the sqlite3_interrupt() call returns. +** +** If the database connection closes while [sqlite3_interrupt()] +** is running then bad things will likely happen. +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*); + +/* +** CAPI3REF: Determine If An SQL Statement Is Complete +** +** These routines are useful during command-line input to determine if the +** currently entered text seems to form a complete SQL statement or +** if additional input is needed before sending the text into +** SQLite for parsing. ^These routines return 1 if the input string +** appears to be a complete SQL statement. ^A statement is judged to be +** complete if it ends with a semicolon token and is not a prefix of a +** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within +** string literals or quoted identifier names or comments are not +** independent tokens (they are part of the token in which they are +** embedded) and thus do not count as a statement terminator. ^Whitespace +** and comments that follow the final semicolon are ignored. +** +** ^These routines return 0 if the statement is incomplete. ^If a +** memory allocation fails, then SQLITE_NOMEM is returned. +** +** ^These routines do not parse the SQL statements thus +** will not detect syntactically incorrect SQL. +** +** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior +** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked +** automatically by sqlite3_complete16(). If that initialization fails, +** then the return value from sqlite3_complete16() will be non-zero +** regardless of whether or not the input SQL is complete.)^ +** +** The input to [sqlite3_complete()] must be a zero-terminated +** UTF-8 string. +** +** The input to [sqlite3_complete16()] must be a zero-terminated +** UTF-16 string in native byte order. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *sql); +SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql); + +/* +** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors +** KEYWORDS: {busy-handler callback} {busy handler} +** METHOD: sqlite3 +** +** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X +** that might be invoked with argument P whenever +** an attempt is made to access a database table associated with +** [database connection] D when another thread +** or process has the table locked. +** The sqlite3_busy_handler() interface is used to implement +** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout]. +** +** ^If the busy callback is NULL, then [SQLITE_BUSY] +** is returned immediately upon encountering the lock. ^If the busy callback +** is not NULL, then the callback might be invoked with two arguments. +** +** ^The first argument to the busy handler is a copy of the void* pointer which +** is the third argument to sqlite3_busy_handler(). ^The second argument to +** the busy handler callback is the number of times that the busy handler has +** been invoked previously for the same locking event. ^If the +** busy callback returns 0, then no additional attempts are made to +** access the database and [SQLITE_BUSY] is returned +** to the application. +** ^If the callback returns non-zero, then another attempt +** is made to access the database and the cycle repeats. +** +** The presence of a busy handler does not guarantee that it will be invoked +** when there is lock contention. ^If SQLite determines that invoking the busy +** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY] +** to the application instead of invoking the +** busy handler. +** Consider a scenario where one process is holding a read lock that +** it is trying to promote to a reserved lock and +** a second process is holding a reserved lock that it is trying +** to promote to an exclusive lock. The first process cannot proceed +** because it is blocked by the second and the second process cannot +** proceed because it is blocked by the first. If both processes +** invoke the busy handlers, neither will make any progress. Therefore, +** SQLite returns [SQLITE_BUSY] for the first process, hoping that this +** will induce the first process to release its read lock and allow +** the second process to proceed. +** +** ^The default busy callback is NULL. +** +** ^(There can only be a single busy handler defined for each +** [database connection]. Setting a new busy handler clears any +** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()] +** or evaluating [PRAGMA busy_timeout=N] will change the +** busy handler and thus clear any previously set busy handler. +** +** The busy callback should not take any actions which modify the +** database connection that invoked the busy handler. In other words, +** the busy handler is not reentrant. Any such actions +** result in undefined behavior. +** +** A busy handler must not close the database connection +** or [prepared statement] that invoked the busy handler. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); + +/* +** CAPI3REF: Set A Busy Timeout +** METHOD: sqlite3 +** +** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps +** for a specified amount of time when a table is locked. ^The handler +** will sleep multiple times until at least "ms" milliseconds of sleeping +** have accumulated. ^After at least "ms" milliseconds of sleeping, +** the handler returns 0 which causes [sqlite3_step()] to return +** [SQLITE_BUSY]. +** +** ^Calling this routine with an argument less than or equal to zero +** turns off all busy handlers. +** +** ^(There can only be a single busy handler for a particular +** [database connection] at any given moment. If another busy handler +** was defined (using [sqlite3_busy_handler()]) prior to calling +** this routine, that other busy handler is cleared.)^ +** +** See also: [PRAGMA busy_timeout] +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms); + +/* +** CAPI3REF: Convenience Routines For Running Queries +** METHOD: sqlite3 +** +** This is a legacy interface that is preserved for backwards compatibility. +** Use of this interface is not recommended. +** +** Definition: A result table is memory data structure created by the +** [sqlite3_get_table()] interface. A result table records the +** complete query results from one or more queries. +** +** The table conceptually has a number of rows and columns. But +** these numbers are not part of the result table itself. These +** numbers are obtained separately. Let N be the number of rows +** and M be the number of columns. +** +** A result table is an array of pointers to zero-terminated UTF-8 strings. +** There are (N+1)*M elements in the array. The first M pointers point +** to zero-terminated strings that contain the names of the columns. +** The remaining entries all point to query results. NULL values result +** in NULL pointers. All other values are in their UTF-8 zero-terminated +** string representation as returned by [sqlite3_column_text()]. +** +** A result table might consist of one or more memory allocations. +** It is not safe to pass a result table directly to [sqlite3_free()]. +** A result table should be deallocated using [sqlite3_free_table()]. +** +** ^(As an example of the result table format, suppose a query result +** is as follows: +** +**
+**        Name        | Age
+**        -----------------------
+**        Alice       | 43
+**        Bob         | 28
+**        Cindy       | 21
+** 
+** +** There are two column (M==2) and three rows (N==3). Thus the +** result table has 8 entries. Suppose the result table is stored +** in an array names azResult. Then azResult holds this content: +** +**
+**        azResult[0] = "Name";
+**        azResult[1] = "Age";
+**        azResult[2] = "Alice";
+**        azResult[3] = "43";
+**        azResult[4] = "Bob";
+**        azResult[5] = "28";
+**        azResult[6] = "Cindy";
+**        azResult[7] = "21";
+** 
)^ +** +** ^The sqlite3_get_table() function evaluates one or more +** semicolon-separated SQL statements in the zero-terminated UTF-8 +** string of its 2nd parameter and returns a result table to the +** pointer given in its 3rd parameter. +** +** After the application has finished with the result from sqlite3_get_table(), +** it must pass the result table pointer to sqlite3_free_table() in order to +** release the memory that was malloced. Because of the way the +** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling +** function must not try to call [sqlite3_free()] directly. Only +** [sqlite3_free_table()] is able to release the memory properly and safely. +** +** The sqlite3_get_table() interface is implemented as a wrapper around +** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access +** to any internal data structures of SQLite. It uses only the public +** interface defined here. As a consequence, errors that occur in the +** wrapper layer outside of the internal [sqlite3_exec()] call are not +** reflected in subsequent calls to [sqlite3_errcode()] or +** [sqlite3_errmsg()]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_get_table( + sqlite3 *db, /* An open database */ + const char *zSql, /* SQL to be evaluated */ + char ***pazResult, /* Results of the query */ + int *pnRow, /* Number of result rows written here */ + int *pnColumn, /* Number of result columns written here */ + char **pzErrmsg /* Error msg written here */ +); +SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); + +/* +** CAPI3REF: Formatted String Printing Functions +** +** These routines are work-alikes of the "printf()" family of functions +** from the standard C library. +** These routines understand most of the common K&R formatting options, +** plus some additional non-standard formats, detailed below. +** Note that some of the more obscure formatting options from recent +** C-library standards are omitted from this implementation. +** +** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their +** results into memory obtained from [sqlite3_malloc()]. +** The strings returned by these two routines should be +** released by [sqlite3_free()]. ^Both routines return a +** NULL pointer if [sqlite3_malloc()] is unable to allocate enough +** memory to hold the resulting string. +** +** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from +** the standard C library. The result is written into the +** buffer supplied as the second parameter whose size is given by +** the first parameter. Note that the order of the +** first two parameters is reversed from snprintf().)^ This is an +** historical accident that cannot be fixed without breaking +** backwards compatibility. ^(Note also that sqlite3_snprintf() +** returns a pointer to its buffer instead of the number of +** characters actually written into the buffer.)^ We admit that +** the number of characters written would be a more useful return +** value but we cannot change the implementation of sqlite3_snprintf() +** now without breaking compatibility. +** +** ^As long as the buffer size is greater than zero, sqlite3_snprintf() +** guarantees that the buffer is always zero-terminated. ^The first +** parameter "n" is the total size of the buffer, including space for +** the zero terminator. So the longest string that can be completely +** written will be n-1 characters. +** +** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). +** +** These routines all implement some additional formatting +** options that are useful for constructing SQL statements. +** All of the usual printf() formatting options apply. In addition, there +** is are "%q", "%Q", "%w" and "%z" options. +** +** ^(The %q option works like %s in that it substitutes a nul-terminated +** string from the argument list. But %q also doubles every '\'' character. +** %q is designed for use inside a string literal.)^ By doubling each '\'' +** character it escapes that character and allows it to be inserted into +** the string. +** +** For example, assume the string variable zText contains text as follows: +** +**
+**  char *zText = "It's a happy day!";
+** 
+** +** One can use this text in an SQL statement as follows: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** Because the %q format string is used, the '\'' character in zText +** is escaped and the SQL generated is as follows: +** +**
+**  INSERT INTO table1 VALUES('It''s a happy day!')
+** 
+** +** This is correct. Had we used %s instead of %q, the generated SQL +** would have looked like this: +** +**
+**  INSERT INTO table1 VALUES('It's a happy day!');
+** 
+** +** This second example is an SQL syntax error. As a general rule you should +** always use %q instead of %s when inserting text into a string literal. +** +** ^(The %Q option works like %q except it also adds single quotes around +** the outside of the total string. Additionally, if the parameter in the +** argument list is a NULL pointer, %Q substitutes the text "NULL" (without +** single quotes).)^ So, for example, one could say: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** The code above will render a correct SQL statement in the zSQL +** variable even if the zText variable is a NULL pointer. +** +** ^(The "%w" formatting option is like "%q" except that it expects to +** be contained within double-quotes instead of single quotes, and it +** escapes the double-quote character instead of the single-quote +** character.)^ The "%w" formatting option is intended for safely inserting +** table and column names into a constructed SQL statement. +** +** ^(The "%z" formatting option works like "%s" but with the +** addition that after the string has been read and copied into +** the result, [sqlite3_free()] is called on the input string.)^ +*/ +SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char*,...); +SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int,char*,const char*, ...); +SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list); + +/* +** CAPI3REF: Memory Allocation Subsystem +** +** The SQLite core uses these three routines for all of its own +** internal memory allocation needs. "Core" in the previous sentence +** does not include operating-system specific VFS implementation. The +** Windows VFS uses native malloc() and free() for some operations. +** +** ^The sqlite3_malloc() routine returns a pointer to a block +** of memory at least N bytes in length, where N is the parameter. +** ^If sqlite3_malloc() is unable to obtain sufficient free +** memory, it returns a NULL pointer. ^If the parameter N to +** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns +** a NULL pointer. +** +** ^The sqlite3_malloc64(N) routine works just like +** sqlite3_malloc(N) except that N is an unsigned 64-bit integer instead +** of a signed 32-bit integer. +** +** ^Calling sqlite3_free() with a pointer previously returned +** by sqlite3_malloc() or sqlite3_realloc() releases that memory so +** that it might be reused. ^The sqlite3_free() routine is +** a no-op if is called with a NULL pointer. Passing a NULL pointer +** to sqlite3_free() is harmless. After being freed, memory +** should neither be read nor written. Even reading previously freed +** memory might result in a segmentation fault or other severe error. +** Memory corruption, a segmentation fault, or other severe error +** might result if sqlite3_free() is called with a non-NULL pointer that +** was not obtained from sqlite3_malloc() or sqlite3_realloc(). +** +** ^The sqlite3_realloc(X,N) interface attempts to resize a +** prior memory allocation X to be at least N bytes. +** ^If the X parameter to sqlite3_realloc(X,N) +** is a NULL pointer then its behavior is identical to calling +** sqlite3_malloc(N). +** ^If the N parameter to sqlite3_realloc(X,N) is zero or +** negative then the behavior is exactly the same as calling +** sqlite3_free(X). +** ^sqlite3_realloc(X,N) returns a pointer to a memory allocation +** of at least N bytes in size or NULL if insufficient memory is available. +** ^If M is the size of the prior allocation, then min(N,M) bytes +** of the prior allocation are copied into the beginning of buffer returned +** by sqlite3_realloc(X,N) and the prior allocation is freed. +** ^If sqlite3_realloc(X,N) returns NULL and N is positive, then the +** prior allocation is not freed. +** +** ^The sqlite3_realloc64(X,N) interfaces works the same as +** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead +** of a 32-bit signed integer. +** +** ^If X is a memory allocation previously obtained from sqlite3_malloc(), +** sqlite3_malloc64(), sqlite3_realloc(), or sqlite3_realloc64(), then +** sqlite3_msize(X) returns the size of that memory allocation in bytes. +** ^The value returned by sqlite3_msize(X) might be larger than the number +** of bytes requested when X was allocated. ^If X is a NULL pointer then +** sqlite3_msize(X) returns zero. If X points to something that is not +** the beginning of memory allocation, or if it points to a formerly +** valid memory allocation that has now been freed, then the behavior +** of sqlite3_msize(X) is undefined and possibly harmful. +** +** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(), +** sqlite3_malloc64(), and sqlite3_realloc64() +** is always aligned to at least an 8 byte boundary, or to a +** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time +** option is used. +** +** In SQLite version 3.5.0 and 3.5.1, it was possible to define +** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in +** implementation of these routines to be omitted. That capability +** is no longer provided. Only built-in memory allocators can be used. +** +** Prior to SQLite version 3.7.10, the Windows OS interface layer called +** the system malloc() and free() directly when converting +** filenames between the UTF-8 encoding used by SQLite +** and whatever filename encoding is used by the particular Windows +** installation. Memory allocation errors were detected, but +** they were reported back as [SQLITE_CANTOPEN] or +** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. +** +** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] +** must be either NULL or else pointers obtained from a prior +** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have +** not yet been released. +** +** The application must not read or write any part of +** a block of memory after it has been released using +** [sqlite3_free()] or [sqlite3_realloc()]. +*/ +SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int); +SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64); +SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void*, int); +SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void*, sqlite3_uint64); +SQLITE_API void SQLITE_STDCALL sqlite3_free(void*); +SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*); + +/* +** CAPI3REF: Memory Allocator Statistics +** +** SQLite provides these two interfaces for reporting on the status +** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()] +** routines, which form the built-in memory allocation subsystem. +** +** ^The [sqlite3_memory_used()] routine returns the number of bytes +** of memory currently outstanding (malloced but not freed). +** ^The [sqlite3_memory_highwater()] routine returns the maximum +** value of [sqlite3_memory_used()] since the high-water mark +** was last reset. ^The values returned by [sqlite3_memory_used()] and +** [sqlite3_memory_highwater()] include any overhead +** added by SQLite in its implementation of [sqlite3_malloc()], +** but not overhead added by the any underlying system library +** routines that [sqlite3_malloc()] may call. +** +** ^The memory high-water mark is reset to the current value of +** [sqlite3_memory_used()] if and only if the parameter to +** [sqlite3_memory_highwater()] is true. ^The value returned +** by [sqlite3_memory_highwater(1)] is the high-water mark +** prior to the reset. +*/ +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag); + +/* +** CAPI3REF: Pseudo-Random Number Generator +** +** SQLite contains a high-quality pseudo-random number generator (PRNG) used to +** select random [ROWID | ROWIDs] when inserting new records into a table that +** already uses the largest possible [ROWID]. The PRNG is also used for +** the build-in random() and randomblob() SQL functions. This interface allows +** applications to access the same PRNG for other purposes. +** +** ^A call to this routine stores N bytes of randomness into buffer P. +** ^The P parameter can be a NULL pointer. +** +** ^If this routine has not been previously called or if the previous +** call had N less than one or a NULL pointer for P, then the PRNG is +** seeded using randomness obtained from the xRandomness method of +** the default [sqlite3_vfs] object. +** ^If the previous call to this routine had an N of 1 or more and a +** non-NULL P then the pseudo-randomness is generated +** internally and without recourse to the [sqlite3_vfs] xRandomness +** method. +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P); + +/* +** CAPI3REF: Compile-Time Authorization Callbacks +** METHOD: sqlite3 +** +** ^This routine registers an authorizer callback with a particular +** [database connection], supplied in the first argument. +** ^The authorizer callback is invoked as SQL statements are being compiled +** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], +** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. ^At various +** points during the compilation process, as logic is being created +** to perform various actions, the authorizer callback is invoked to +** see if those actions are allowed. ^The authorizer callback should +** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the +** specific action but allow the SQL statement to continue to be +** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be +** rejected with an error. ^If the authorizer callback returns +** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] +** then the [sqlite3_prepare_v2()] or equivalent call that triggered +** the authorizer will fail with an error message. +** +** When the callback returns [SQLITE_OK], that means the operation +** requested is ok. ^When the callback returns [SQLITE_DENY], the +** [sqlite3_prepare_v2()] or equivalent call that triggered the +** authorizer will fail with an error message explaining that +** access is denied. +** +** ^The first parameter to the authorizer callback is a copy of the third +** parameter to the sqlite3_set_authorizer() interface. ^The second parameter +** to the callback is an integer [SQLITE_COPY | action code] that specifies +** the particular action to be authorized. ^The third through sixth parameters +** to the callback are zero-terminated strings that contain additional +** details about the action to be authorized. +** +** ^If the action code is [SQLITE_READ] +** and the callback returns [SQLITE_IGNORE] then the +** [prepared statement] statement is constructed to substitute +** a NULL value in place of the table column that would have +** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] +** return can be used to deny an untrusted user access to individual +** columns of a table. +** ^If the action code is [SQLITE_DELETE] and the callback returns +** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the +** [truncate optimization] is disabled and all rows are deleted individually. +** +** An authorizer is used when [sqlite3_prepare | preparing] +** SQL statements from an untrusted source, to ensure that the SQL statements +** do not try to access data they are not allowed to see, or that they do not +** try to execute malicious statements that damage the database. For +** example, an application may allow a user to enter arbitrary +** SQL queries for evaluation by a database. But the application does +** not want the user to be able to make arbitrary changes to the +** database. An authorizer could then be put in place while the +** user-entered SQL is being [sqlite3_prepare | prepared] that +** disallows everything except [SELECT] statements. +** +** Applications that need to process SQL from untrusted sources +** might also consider lowering resource limits using [sqlite3_limit()] +** and limiting database size using the [max_page_count] [PRAGMA] +** in addition to using an authorizer. +** +** ^(Only a single authorizer can be in place on a database connection +** at a time. Each call to sqlite3_set_authorizer overrides the +** previous call.)^ ^Disable the authorizer by installing a NULL callback. +** The authorizer is disabled by default. +** +** The authorizer callback must not do anything that will modify +** the database connection that invoked the authorizer callback. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the +** statement might be re-prepared during [sqlite3_step()] due to a +** schema change. Hence, the application should ensure that the +** correct authorizer callback remains in place during the [sqlite3_step()]. +** +** ^Note that the authorizer callback is invoked only during +** [sqlite3_prepare()] or its variants. Authorization is not +** performed during statement evaluation in [sqlite3_step()], unless +** as stated in the previous paragraph, sqlite3_step() invokes +** sqlite3_prepare_v2() to reprepare a statement after a schema change. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( + sqlite3*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData +); + +/* +** CAPI3REF: Authorizer Return Codes +** +** The [sqlite3_set_authorizer | authorizer callback function] must +** return either [SQLITE_OK] or one of these two constants in order +** to signal SQLite whether or not the action is permitted. See the +** [sqlite3_set_authorizer | authorizer documentation] for additional +** information. +** +** Note that SQLITE_IGNORE is also used as a [conflict resolution mode] +** returned from the [sqlite3_vtab_on_conflict()] interface. +*/ +#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ +#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ + +/* +** CAPI3REF: Authorizer Action Codes +** +** The [sqlite3_set_authorizer()] interface registers a callback function +** that is invoked to authorize certain SQL statement actions. The +** second parameter to the callback is an integer code that specifies +** what action is being authorized. These are the integer action codes that +** the authorizer callback may be passed. +** +** These action code values signify what kind of operation is to be +** authorized. The 3rd and 4th parameters to the authorization +** callback function will be parameters or NULL depending on which of these +** codes is used as the second parameter. ^(The 5th parameter to the +** authorizer callback is the name of the database ("main", "temp", +** etc.) if applicable.)^ ^The 6th parameter to the authorizer callback +** is the name of the inner-most trigger or view that is responsible for +** the access attempt or NULL if this access attempt is directly from +** top-level SQL code. +*/ +/******************************************* 3rd ************ 4th ***********/ +#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ +#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ +#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ +#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ +#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ +#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ +#define SQLITE_DELETE 9 /* Table Name NULL */ +#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ +#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ +#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ +#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ +#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ +#define SQLITE_DROP_VIEW 17 /* View Name NULL */ +#define SQLITE_INSERT 18 /* Table Name NULL */ +#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ +#define SQLITE_READ 20 /* Table Name Column Name */ +#define SQLITE_SELECT 21 /* NULL NULL */ +#define SQLITE_TRANSACTION 22 /* Operation NULL */ +#define SQLITE_UPDATE 23 /* Table Name Column Name */ +#define SQLITE_ATTACH 24 /* Filename NULL */ +#define SQLITE_DETACH 25 /* Database Name NULL */ +#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ +#define SQLITE_REINDEX 27 /* Index Name NULL */ +#define SQLITE_ANALYZE 28 /* Table Name NULL */ +#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ +#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ +#define SQLITE_FUNCTION 31 /* NULL Function Name */ +#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ +#define SQLITE_COPY 0 /* No longer used */ +#define SQLITE_RECURSIVE 33 /* NULL NULL */ + +/* +** CAPI3REF: Tracing And Profiling Functions +** METHOD: sqlite3 +** +** These routines register callback functions that can be used for +** tracing and profiling the execution of SQL statements. +** +** ^The callback function registered by sqlite3_trace() is invoked at +** various times when an SQL statement is being run by [sqlite3_step()]. +** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the +** SQL statement text as the statement first begins executing. +** ^(Additional sqlite3_trace() callbacks might occur +** as each triggered subprogram is entered. The callbacks for triggers +** contain a UTF-8 SQL comment that identifies the trigger.)^ +** +** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit +** the length of [bound parameter] expansion in the output of sqlite3_trace(). +** +** ^The callback function registered by sqlite3_profile() is invoked +** as each SQL statement finishes. ^The profile callback contains +** the original statement text and an estimate of wall-clock time +** of how long that statement took to run. ^The profile callback +** time is in units of nanoseconds, however the current implementation +** is only capable of millisecond resolution so the six least significant +** digits in the time are meaningless. Future versions of SQLite +** might provide greater resolution on the profiler callback. The +** sqlite3_profile() function is considered experimental and is +** subject to change in future versions of SQLite. +*/ +SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); +SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_profile(sqlite3*, + void(*xProfile)(void*,const char*,sqlite3_uint64), void*); + +/* +** CAPI3REF: Query Progress Callbacks +** METHOD: sqlite3 +** +** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback +** function X to be invoked periodically during long running calls to +** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for +** database connection D. An example use for this +** interface is to keep a GUI updated during a large query. +** +** ^The parameter P is passed through as the only parameter to the +** callback function X. ^The parameter N is the approximate number of +** [virtual machine instructions] that are evaluated between successive +** invocations of the callback X. ^If N is less than one then the progress +** handler is disabled. +** +** ^Only a single progress handler may be defined at one time per +** [database connection]; setting a new progress handler cancels the +** old one. ^Setting parameter X to NULL disables the progress handler. +** ^The progress handler is also disabled by setting N to a value less +** than 1. +** +** ^If the progress callback returns non-zero, the operation is +** interrupted. This feature can be used to implement a +** "Cancel" button on a GUI progress dialog box. +** +** The progress handler callback must not do anything that will modify +** the database connection that invoked the progress handler. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); + +/* +** CAPI3REF: Opening A New Database Connection +** CONSTRUCTOR: sqlite3 +** +** ^These routines open an SQLite database file as specified by the +** filename argument. ^The filename argument is interpreted as UTF-8 for +** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte +** order for sqlite3_open16(). ^(A [database connection] handle is usually +** returned in *ppDb, even if an error occurs. The only exception is that +** if SQLite is unable to allocate memory to hold the [sqlite3] object, +** a NULL will be written into *ppDb instead of a pointer to the [sqlite3] +** object.)^ ^(If the database is opened (and/or created) successfully, then +** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The +** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain +** an English language description of the error following a failure of any +** of the sqlite3_open() routines. +** +** ^The default encoding will be UTF-8 for databases created using +** sqlite3_open() or sqlite3_open_v2(). ^The default encoding for databases +** created using sqlite3_open16() will be UTF-16 in the native byte order. +** +** Whether or not an error occurs when it is opened, resources +** associated with the [database connection] handle should be released by +** passing it to [sqlite3_close()] when it is no longer required. +** +** The sqlite3_open_v2() interface works like sqlite3_open() +** except that it accepts two additional parameters for additional control +** over the new database connection. ^(The flags parameter to +** sqlite3_open_v2() can take one of +** the following three values, optionally combined with the +** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE], +** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^ +** +**
+** ^(
[SQLITE_OPEN_READONLY]
+**
The database is opened in read-only mode. If the database does not +** already exist, an error is returned.
)^ +** +** ^(
[SQLITE_OPEN_READWRITE]
+**
The database is opened for reading and writing if possible, or reading +** only if the file is write protected by the operating system. In either +** case the database must already exist, otherwise an error is returned.
)^ +** +** ^(
[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]
+**
The database is opened for reading and writing, and is created if +** it does not already exist. This is the behavior that is always used for +** sqlite3_open() and sqlite3_open16().
)^ +**
+** +** If the 3rd parameter to sqlite3_open_v2() is not one of the +** combinations shown above optionally combined with other +** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] +** then the behavior is undefined. +** +** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection +** opens in the multi-thread [threading mode] as long as the single-thread +** mode has not been set at compile-time or start-time. ^If the +** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens +** in the serialized [threading mode] unless single-thread was +** previously selected at compile-time or start-time. +** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be +** eligible to use [shared cache mode], regardless of whether or not shared +** cache is enabled using [sqlite3_enable_shared_cache()]. ^The +** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not +** participate in [shared cache mode] even if it is enabled. +** +** ^The fourth parameter to sqlite3_open_v2() is the name of the +** [sqlite3_vfs] object that defines the operating system interface that +** the new database connection should use. ^If the fourth parameter is +** a NULL pointer then the default [sqlite3_vfs] object is used. +** +** ^If the filename is ":memory:", then a private, temporary in-memory database +** is created for the connection. ^This in-memory database will vanish when +** the database connection is closed. Future versions of SQLite might +** make use of additional special filenames that begin with the ":" character. +** It is recommended that when a database filename actually does begin with +** a ":" character you should prefix the filename with a pathname such as +** "./" to avoid ambiguity. +** +** ^If the filename is an empty string, then a private, temporary +** on-disk database will be created. ^This private database will be +** automatically deleted as soon as the database connection is closed. +** +** [[URI filenames in sqlite3_open()]]

URI Filenames

+** +** ^If [URI filename] interpretation is enabled, and the filename argument +** begins with "file:", then the filename is interpreted as a URI. ^URI +** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is +** set in the fourth argument to sqlite3_open_v2(), or if it has +** been enabled globally using the [SQLITE_CONFIG_URI] option with the +** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option. +** As of SQLite version 3.7.7, URI filename interpretation is turned off +** by default, but future releases of SQLite might enable URI filename +** interpretation by default. See "[URI filenames]" for additional +** information. +** +** URI filenames are parsed according to RFC 3986. ^If the URI contains an +** authority, then it must be either an empty string or the string +** "localhost". ^If the authority is not an empty string or "localhost", an +** error is returned to the caller. ^The fragment component of a URI, if +** present, is ignored. +** +** ^SQLite uses the path component of the URI as the name of the disk file +** which contains the database. ^If the path begins with a '/' character, +** then it is interpreted as an absolute path. ^If the path does not begin +** with a '/' (meaning that the authority section is omitted from the URI) +** then the path is interpreted as a relative path. +** ^(On windows, the first component of an absolute path +** is a drive specification (e.g. "C:").)^ +** +** [[core URI query parameters]] +** The query component of a URI may contain parameters that are interpreted +** either by SQLite itself, or by a [VFS | custom VFS implementation]. +** SQLite and its built-in [VFSes] interpret the +** following query parameters: +** +**
    +**
  • vfs: ^The "vfs" parameter may be used to specify the name of +** a VFS object that provides the operating system interface that should +** be used to access the database file on disk. ^If this option is set to +** an empty string the default VFS object is used. ^Specifying an unknown +** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is +** present, then the VFS specified by the option takes precedence over +** the value passed as the fourth parameter to sqlite3_open_v2(). +** +**
  • mode: ^(The mode parameter may be set to either "ro", "rw", +** "rwc", or "memory". Attempting to set it to any other value is +** an error)^. +** ^If "ro" is specified, then the database is opened for read-only +** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the +** third argument to sqlite3_open_v2(). ^If the mode option is set to +** "rw", then the database is opened for read-write (but not create) +** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had +** been set. ^Value "rwc" is equivalent to setting both +** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is +** set to "memory" then a pure [in-memory database] that never reads +** or writes from disk is used. ^It is an error to specify a value for +** the mode parameter that is less restrictive than that specified by +** the flags passed in the third parameter to sqlite3_open_v2(). +** +**
  • cache: ^The cache parameter may be set to either "shared" or +** "private". ^Setting it to "shared" is equivalent to setting the +** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to +** sqlite3_open_v2(). ^Setting the cache parameter to "private" is +** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. +** ^If sqlite3_open_v2() is used and the "cache" parameter is present in +** a URI filename, its value overrides any behavior requested by setting +** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. +** +**
  • psow: ^The psow parameter indicates whether or not the +** [powersafe overwrite] property does or does not apply to the +** storage media on which the database file resides. +** +**
  • nolock: ^The nolock parameter is a boolean query parameter +** which if set disables file locking in rollback journal modes. This +** is useful for accessing a database on a filesystem that does not +** support locking. Caution: Database corruption might result if two +** or more processes write to the same database and any one of those +** processes uses nolock=1. +** +**
  • immutable: ^The immutable parameter is a boolean query +** parameter that indicates that the database file is stored on +** read-only media. ^When immutable is set, SQLite assumes that the +** database file cannot be changed, even by a process with higher +** privilege, and so the database is opened read-only and all locking +** and change detection is disabled. Caution: Setting the immutable +** property on a database file that does in fact change can result +** in incorrect query results and/or [SQLITE_CORRUPT] errors. +** See also: [SQLITE_IOCAP_IMMUTABLE]. +** +**
+** +** ^Specifying an unknown parameter in the query component of a URI is not an +** error. Future versions of SQLite might understand additional query +** parameters. See "[query parameters with special meaning to SQLite]" for +** additional information. +** +** [[URI filename examples]]

URI filename examples

+** +**
+**
URI filenames Results +**
file:data.db +** Open the file "data.db" in the current directory. +**
file:/home/fred/data.db
+** file:///home/fred/data.db
+** file://localhost/home/fred/data.db
+** Open the database file "/home/fred/data.db". +**
file://darkstar/home/fred/data.db +** An error. "darkstar" is not a recognized authority. +**
+** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db +** Windows only: Open the file "data.db" on fred's desktop on drive +** C:. Note that the %20 escaping in this example is not strictly +** necessary - space characters can be used literally +** in URI filenames. +**
file:data.db?mode=ro&cache=private +** Open file "data.db" in the current directory for read-only access. +** Regardless of whether or not shared-cache mode is enabled by +** default, use a private cache. +**
file:/home/fred/data.db?vfs=unix-dotfile +** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile" +** that uses dot-files in place of posix advisory locking. +**
file:data.db?mode=readonly +** An error. "readonly" is not a valid option for the "mode" parameter. +**
+** +** ^URI hexadecimal escape sequences (%HH) are supported within the path and +** query components of a URI. A hexadecimal escape sequence consists of a +** percent sign - "%" - followed by exactly two hexadecimal digits +** specifying an octet value. ^Before the path or query components of a +** URI filename are interpreted, they are encoded using UTF-8 and all +** hexadecimal escape sequences replaced by a single byte containing the +** corresponding octet. If this process generates an invalid UTF-8 encoding, +** the results are undefined. +** +** Note to Windows users: The encoding used for the filename argument +** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever +** codepage is currently defined. Filenames containing international +** characters must be converted to UTF-8 prior to passing them into +** sqlite3_open() or sqlite3_open_v2(). +** +** Note to Windows Runtime users: The temporary directory must be set +** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various +** features that require the use of temporary files may fail. +** +** See also: [sqlite3_temp_directory] +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_open( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +SQLITE_API int SQLITE_STDCALL sqlite3_open16( + const void *filename, /* Database filename (UTF-16) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs /* Name of VFS module to use */ +); + +/* +** CAPI3REF: Obtain Values For URI Parameters +** +** These are utility routines, useful to VFS implementations, that check +** to see if a database file was a URI that contained a specific query +** parameter, and if so obtains the value of that query parameter. +** +** If F is the database filename pointer passed into the xOpen() method of +** a VFS implementation when the flags parameter to xOpen() has one or +** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and +** P is the name of the query parameter, then +** sqlite3_uri_parameter(F,P) returns the value of the P +** parameter if it exists or a NULL pointer if P does not appear as a +** query parameter on F. If P is a query parameter of F +** has no explicit value, then sqlite3_uri_parameter(F,P) returns +** a pointer to an empty string. +** +** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean +** parameter and returns true (1) or false (0) according to the value +** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the +** value of query parameter P is one of "yes", "true", or "on" in any +** case or if the value begins with a non-zero number. The +** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of +** query parameter P is one of "no", "false", or "off" in any case or +** if the value begins with a numeric zero. If P is not a query +** parameter on F or if the value of P is does not match any of the +** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0). +** +** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a +** 64-bit signed integer and returns that integer, or D if P does not +** exist. If the value of P is something other than an integer, then +** zero is returned. +** +** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and +** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and +** is not a database file pathname pointer that SQLite passed into the xOpen +** VFS method, then the behavior of this routine is undefined and probably +** undesirable. +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const char*, sqlite3_int64); + + +/* +** CAPI3REF: Error Codes And Messages +** METHOD: sqlite3 +** +** ^If the most recent sqlite3_* API call associated with +** [database connection] D failed, then the sqlite3_errcode(D) interface +** returns the numeric [result code] or [extended result code] for that +** API call. +** If the most recent API call was successful, +** then the return value from sqlite3_errcode() is undefined. +** ^The sqlite3_extended_errcode() +** interface is the same except that it always returns the +** [extended result code] even when extended result codes are +** disabled. +** +** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language +** text that describes the error, as either UTF-8 or UTF-16 respectively. +** ^(Memory to hold the error message string is managed internally. +** The application does not need to worry about freeing the result. +** However, the error string might be overwritten or deallocated by +** subsequent calls to other SQLite interface functions.)^ +** +** ^The sqlite3_errstr() interface returns the English-language text +** that describes the [result code], as UTF-8. +** ^(Memory to hold the error message string is managed internally +** and must not be freed by the application)^. +** +** When the serialized [threading mode] is in use, it might be the +** case that a second error occurs on a separate thread in between +** the time of the first error and the call to these interfaces. +** When that happens, the second error will be reported since these +** interfaces always report the most recent result. To avoid +** this, each thread can obtain exclusive use of the [database connection] D +** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning +** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after +** all calls to the interfaces listed here are completed. +** +** If an interface fails with SQLITE_MISUSE, that means the interface +** was invoked incorrectly by the application. In that case, the +** error code and message may or may not be set. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db); +SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3*); +SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int); + +/* +** CAPI3REF: Prepared Statement Object +** KEYWORDS: {prepared statement} {prepared statements} +** +** An instance of this object represents a single SQL statement that +** has been compiled into binary form and is ready to be evaluated. +** +** Think of each SQL statement as a separate computer program. The +** original SQL text is source code. A prepared statement object +** is the compiled object code. All SQL must be converted into a +** prepared statement before it can be run. +** +** The life-cycle of a prepared statement object usually goes like this: +** +**
    +**
  1. Create the prepared statement object using [sqlite3_prepare_v2()]. +**
  2. Bind values to [parameters] using the sqlite3_bind_*() +** interfaces. +**
  3. Run the SQL by calling [sqlite3_step()] one or more times. +**
  4. Reset the prepared statement using [sqlite3_reset()] then go back +** to step 2. Do this zero or more times. +**
  5. Destroy the object using [sqlite3_finalize()]. +**
+*/ +typedef struct sqlite3_stmt sqlite3_stmt; + +/* +** CAPI3REF: Run-time Limits +** METHOD: sqlite3 +** +** ^(This interface allows the size of various constructs to be limited +** on a connection by connection basis. The first parameter is the +** [database connection] whose limit is to be set or queried. The +** second parameter is one of the [limit categories] that define a +** class of constructs to be size limited. The third parameter is the +** new limit for that construct.)^ +** +** ^If the new limit is a negative number, the limit is unchanged. +** ^(For each limit category SQLITE_LIMIT_NAME there is a +** [limits | hard upper bound] +** set at compile-time by a C preprocessor macro called +** [limits | SQLITE_MAX_NAME]. +** (The "_LIMIT_" in the name is changed to "_MAX_".))^ +** ^Attempts to increase a limit above its hard upper bound are +** silently truncated to the hard upper bound. +** +** ^Regardless of whether or not the limit was changed, the +** [sqlite3_limit()] interface returns the prior value of the limit. +** ^Hence, to find the current value of a limit without changing it, +** simply invoke this interface with the third parameter set to -1. +** +** Run-time limits are intended for use in applications that manage +** both their own internal database and also databases that are controlled +** by untrusted external sources. An example application might be a +** web browser that has its own databases for storing history and +** separate databases controlled by JavaScript applications downloaded +** off the Internet. The internal databases can be given the +** large, default limits. Databases managed by external sources can +** be given much smaller limits designed to prevent a denial of service +** attack. Developers might also want to use the [sqlite3_set_authorizer()] +** interface to further control untrusted SQL. The size of the database +** created by an untrusted script can be contained using the +** [max_page_count] [PRAGMA]. +** +** New run-time limit categories may be added in future releases. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); + +/* +** CAPI3REF: Run-Time Limit Categories +** KEYWORDS: {limit category} {*limit categories} +** +** These constants define various performance limits +** that can be lowered at run-time using [sqlite3_limit()]. +** The synopsis of the meanings of the various limits is shown below. +** Additional information is available at [limits | Limits in SQLite]. +** +**
+** [[SQLITE_LIMIT_LENGTH]] ^(
SQLITE_LIMIT_LENGTH
+**
The maximum size of any string or BLOB or table row, in bytes.
)^ +** +** [[SQLITE_LIMIT_SQL_LENGTH]] ^(
SQLITE_LIMIT_SQL_LENGTH
+**
The maximum length of an SQL statement, in bytes.
)^ +** +** [[SQLITE_LIMIT_COLUMN]] ^(
SQLITE_LIMIT_COLUMN
+**
The maximum number of columns in a table definition or in the +** result set of a [SELECT] or the maximum number of columns in an index +** or in an ORDER BY or GROUP BY clause.
)^ +** +** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
SQLITE_LIMIT_EXPR_DEPTH
+**
The maximum depth of the parse tree on any expression.
)^ +** +** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
SQLITE_LIMIT_COMPOUND_SELECT
+**
The maximum number of terms in a compound SELECT statement.
)^ +** +** [[SQLITE_LIMIT_VDBE_OP]] ^(
SQLITE_LIMIT_VDBE_OP
+**
The maximum number of instructions in a virtual machine program +** used to implement an SQL statement. This limit is not currently +** enforced, though that might be added in some future release of +** SQLite.
)^ +** +** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(
SQLITE_LIMIT_FUNCTION_ARG
+**
The maximum number of arguments on a function.
)^ +** +** [[SQLITE_LIMIT_ATTACHED]] ^(
SQLITE_LIMIT_ATTACHED
+**
The maximum number of [ATTACH | attached databases].)^
+** +** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]] +** ^(
SQLITE_LIMIT_LIKE_PATTERN_LENGTH
+**
The maximum length of the pattern argument to the [LIKE] or +** [GLOB] operators.
)^ +** +** [[SQLITE_LIMIT_VARIABLE_NUMBER]] +** ^(
SQLITE_LIMIT_VARIABLE_NUMBER
+**
The maximum index number of any [parameter] in an SQL statement.)^ +** +** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(
SQLITE_LIMIT_TRIGGER_DEPTH
+**
The maximum depth of recursion for triggers.
)^ +** +** [[SQLITE_LIMIT_WORKER_THREADS]] ^(
SQLITE_LIMIT_WORKER_THREADS
+**
The maximum number of auxiliary worker threads that a single +** [prepared statement] may start.
)^ +**
+*/ +#define SQLITE_LIMIT_LENGTH 0 +#define SQLITE_LIMIT_SQL_LENGTH 1 +#define SQLITE_LIMIT_COLUMN 2 +#define SQLITE_LIMIT_EXPR_DEPTH 3 +#define SQLITE_LIMIT_COMPOUND_SELECT 4 +#define SQLITE_LIMIT_VDBE_OP 5 +#define SQLITE_LIMIT_FUNCTION_ARG 6 +#define SQLITE_LIMIT_ATTACHED 7 +#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 +#define SQLITE_LIMIT_VARIABLE_NUMBER 9 +#define SQLITE_LIMIT_TRIGGER_DEPTH 10 +#define SQLITE_LIMIT_WORKER_THREADS 11 + +/* +** CAPI3REF: Compiling An SQL Statement +** KEYWORDS: {SQL statement compiler} +** METHOD: sqlite3 +** CONSTRUCTOR: sqlite3_stmt +** +** To execute an SQL query, it must first be compiled into a byte-code +** program using one of these routines. +** +** The first argument, "db", is a [database connection] obtained from a +** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or +** [sqlite3_open16()]. The database connection must not have been closed. +** +** The second argument, "zSql", is the statement to be compiled, encoded +** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() +** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() +** use UTF-16. +** +** ^If the nByte argument is negative, then zSql is read up to the +** first zero terminator. ^If nByte is positive, then it is the +** number of bytes read from zSql. ^If nByte is zero, then no prepared +** statement is generated. +** If the caller knows that the supplied string is nul-terminated, then +** there is a small performance advantage to passing an nByte parameter that +** is the number of bytes in the input string including +** the nul-terminator. +** +** ^If pzTail is not NULL then *pzTail is made to point to the first byte +** past the end of the first SQL statement in zSql. These routines only +** compile the first statement in zSql, so *pzTail is left pointing to +** what remains uncompiled. +** +** ^*ppStmt is left pointing to a compiled [prepared statement] that can be +** executed using [sqlite3_step()]. ^If there is an error, *ppStmt is set +** to NULL. ^If the input text contains no SQL (if the input is an empty +** string or a comment) then *ppStmt is set to NULL. +** The calling procedure is responsible for deleting the compiled +** SQL statement using [sqlite3_finalize()] after it has finished with it. +** ppStmt may not be NULL. +** +** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK]; +** otherwise an [error code] is returned. +** +** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are +** recommended for all new programs. The two older interfaces are retained +** for backwards compatibility, but their use is discouraged. +** ^In the "v2" interfaces, the prepared statement +** that is returned (the [sqlite3_stmt] object) contains a copy of the +** original SQL text. This causes the [sqlite3_step()] interface to +** behave differently in three ways: +** +**
    +**
  1. +** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it +** always used to do, [sqlite3_step()] will automatically recompile the SQL +** statement and try to run it again. As many as [SQLITE_MAX_SCHEMA_RETRY] +** retries will occur before sqlite3_step() gives up and returns an error. +**
  2. +** +**
  3. +** ^When an error occurs, [sqlite3_step()] will return one of the detailed +** [error codes] or [extended error codes]. ^The legacy behavior was that +** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code +** and the application would have to make a second call to [sqlite3_reset()] +** in order to find the underlying cause of the problem. With the "v2" prepare +** interfaces, the underlying reason for the error is returned immediately. +**
  4. +** +**
  5. +** ^If the specific value bound to [parameter | host parameter] in the +** WHERE clause might influence the choice of query plan for a statement, +** then the statement will be automatically recompiled, as if there had been +** a schema change, on the first [sqlite3_step()] call following any change +** to the [sqlite3_bind_text | bindings] of that [parameter]. +** ^The specific value of WHERE-clause [parameter] might influence the +** choice of query plan if the parameter is the left-hand side of a [LIKE] +** or [GLOB] operator or if the parameter is compared to an indexed column +** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. +**
  6. +**
+*/ +SQLITE_API int SQLITE_STDCALL sqlite3_prepare( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); + +/* +** CAPI3REF: Retrieving Statement SQL +** METHOD: sqlite3_stmt +** +** ^This interface can be used to retrieve a saved copy of the original +** SQL text used to create a [prepared statement] if that statement was +** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Determine If An SQL Statement Writes The Database +** METHOD: sqlite3_stmt +** +** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if +** and only if the [prepared statement] X makes no direct changes to +** the content of the database file. +** +** Note that [application-defined SQL functions] or +** [virtual tables] might change the database indirectly as a side effect. +** ^(For example, if an application defines a function "eval()" that +** calls [sqlite3_exec()], then the following SQL statement would +** change the database file through side-effects: +** +**
+**    SELECT eval('DELETE FROM t1') FROM t2;
+** 
+** +** But because the [SELECT] statement does not change the database file +** directly, sqlite3_stmt_readonly() would still return true.)^ +** +** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK], +** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true, +** since the statements themselves do not actually modify the database but +** rather they control the timing of when other statements modify the +** database. ^The [ATTACH] and [DETACH] statements also cause +** sqlite3_stmt_readonly() to return true since, while those statements +** change the configuration of a database connection, they do not make +** changes to the content of the database files on disk. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Determine If A Prepared Statement Has Been Reset +** METHOD: sqlite3_stmt +** +** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the +** [prepared statement] S has been stepped at least once using +** [sqlite3_step(S)] but has not run to completion and/or has not +** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S) +** interface returns false if S is a NULL pointer. If S is not a +** NULL pointer and is not a pointer to a valid [prepared statement] +** object, then the behavior is undefined and probably undesirable. +** +** This interface can be used in combination [sqlite3_next_stmt()] +** to locate all prepared statements associated with a database +** connection that are in need of being reset. This can be used, +** for example, in diagnostic routines to search for prepared +** statements that are holding a transaction open. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt*); + +/* +** CAPI3REF: Dynamically Typed Value Object +** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value} +** +** SQLite uses the sqlite3_value object to represent all values +** that can be stored in a database table. SQLite uses dynamic typing +** for the values it stores. ^Values stored in sqlite3_value objects +** can be integers, floating point values, strings, BLOBs, or NULL. +** +** An sqlite3_value object may be either "protected" or "unprotected". +** Some interfaces require a protected sqlite3_value. Other interfaces +** will accept either a protected or an unprotected sqlite3_value. +** Every interface that accepts sqlite3_value arguments specifies +** whether or not it requires a protected sqlite3_value. The +** [sqlite3_value_dup()] interface can be used to construct a new +** protected sqlite3_value from an unprotected sqlite3_value. +** +** The terms "protected" and "unprotected" refer to whether or not +** a mutex is held. An internal mutex is held for a protected +** sqlite3_value object but no mutex is held for an unprotected +** sqlite3_value object. If SQLite is compiled to be single-threaded +** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0) +** or if SQLite is run in one of reduced mutex modes +** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD] +** then there is no distinction between protected and unprotected +** sqlite3_value objects and they can be used interchangeably. However, +** for maximum code portability it is recommended that applications +** still make the distinction between protected and unprotected +** sqlite3_value objects even when not strictly required. +** +** ^The sqlite3_value objects that are passed as parameters into the +** implementation of [application-defined SQL functions] are protected. +** ^The sqlite3_value object returned by +** [sqlite3_column_value()] is unprotected. +** Unprotected sqlite3_value objects may only be used with +** [sqlite3_result_value()] and [sqlite3_bind_value()]. +** The [sqlite3_value_blob | sqlite3_value_type()] family of +** interfaces require protected sqlite3_value objects. +*/ +typedef struct Mem sqlite3_value; + +/* +** CAPI3REF: SQL Function Context Object +** +** The context in which an SQL function executes is stored in an +** sqlite3_context object. ^A pointer to an sqlite3_context object +** is always first parameter to [application-defined SQL functions]. +** The application-defined SQL function implementation will pass this +** pointer through into calls to [sqlite3_result_int | sqlite3_result()], +** [sqlite3_aggregate_context()], [sqlite3_user_data()], +** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()], +** and/or [sqlite3_set_auxdata()]. +*/ +typedef struct sqlite3_context sqlite3_context; + +/* +** CAPI3REF: Binding Values To Prepared Statements +** KEYWORDS: {host parameter} {host parameters} {host parameter name} +** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} +** METHOD: sqlite3_stmt +** +** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants, +** literals may be replaced by a [parameter] that matches one of following +** templates: +** +**
    +**
  • ? +**
  • ?NNN +**
  • :VVV +**
  • @VVV +**
  • $VVV +**
+** +** In the templates above, NNN represents an integer literal, +** and VVV represents an alphanumeric identifier.)^ ^The values of these +** parameters (also called "host parameter names" or "SQL parameters") +** can be set using the sqlite3_bind_*() routines defined here. +** +** ^The first argument to the sqlite3_bind_*() routines is always +** a pointer to the [sqlite3_stmt] object returned from +** [sqlite3_prepare_v2()] or its variants. +** +** ^The second argument is the index of the SQL parameter to be set. +** ^The leftmost SQL parameter has an index of 1. ^When the same named +** SQL parameter is used more than once, second and subsequent +** occurrences have the same index as the first occurrence. +** ^The index for named parameters can be looked up using the +** [sqlite3_bind_parameter_index()] API if desired. ^The index +** for "?NNN" parameters is the value of NNN. +** ^The NNN value must be between 1 and the [sqlite3_limit()] +** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). +** +** ^The third argument is the value to bind to the parameter. +** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16() +** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter +** is ignored and the end result is the same as sqlite3_bind_null(). +** +** ^(In those routines that have a fourth argument, its value is the +** number of bytes in the parameter. To be clear: the value is the +** number of bytes in the value, not the number of characters.)^ +** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16() +** is negative, then the length of the string is +** the number of bytes up to the first zero terminator. +** If the fourth parameter to sqlite3_bind_blob() is negative, then +** the behavior is undefined. +** If a non-negative fourth parameter is provided to sqlite3_bind_text() +** or sqlite3_bind_text16() or sqlite3_bind_text64() then +** that parameter must be the byte offset +** where the NUL terminator would occur assuming the string were NUL +** terminated. If any NUL characters occur at byte offsets less than +** the value of the fourth parameter then the resulting string value will +** contain embedded NULs. The result of expressions involving strings +** with embedded NULs is undefined. +** +** ^The fifth argument to the BLOB and string binding interfaces +** is a destructor used to dispose of the BLOB or +** string after SQLite has finished with it. ^The destructor is called +** to dispose of the BLOB or string even if the call to bind API fails. +** ^If the fifth argument is +** the special value [SQLITE_STATIC], then SQLite assumes that the +** information is in static, unmanaged space and does not need to be freed. +** ^If the fifth argument has the value [SQLITE_TRANSIENT], then +** SQLite makes its own private copy of the data immediately, before +** the sqlite3_bind_*() routine returns. +** +** ^The sixth argument to sqlite3_bind_text64() must be one of +** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] +** to specify the encoding of the text in the third parameter. If +** the sixth argument to sqlite3_bind_text64() is not one of the +** allowed values shown above, or if the text encoding is different +** from the encoding specified by the sixth parameter, then the behavior +** is undefined. +** +** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that +** is filled with zeroes. ^A zeroblob uses a fixed amount of memory +** (just an integer to hold its size) while it is being processed. +** Zeroblobs are intended to serve as placeholders for BLOBs whose +** content is later written using +** [sqlite3_blob_open | incremental BLOB I/O] routines. +** ^A negative value for the zeroblob results in a zero-length BLOB. +** +** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer +** for the [prepared statement] or with a prepared statement for which +** [sqlite3_step()] has been called more recently than [sqlite3_reset()], +** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() +** routine is passed a [prepared statement] that has been finalized, the +** result is undefined and probably harmful. +** +** ^Bindings are not cleared by the [sqlite3_reset()] routine. +** ^Unbound parameters are interpreted as NULL. +** +** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an +** [error code] if anything goes wrong. +** ^[SQLITE_TOOBIG] might be returned if the size of a string or BLOB +** exceeds limits imposed by [sqlite3_limit]([SQLITE_LIMIT_LENGTH]) or +** [SQLITE_MAX_LENGTH]. +** ^[SQLITE_RANGE] is returned if the parameter +** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails. +** +** See also: [sqlite3_bind_parameter_count()], +** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, + void(*)(void*)); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, + void(*)(void*), unsigned char encoding); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); + +/* +** CAPI3REF: Number Of SQL Parameters +** METHOD: sqlite3_stmt +** +** ^This routine can be used to find the number of [SQL parameters] +** in a [prepared statement]. SQL parameters are tokens of the +** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as +** placeholders for values that are [sqlite3_bind_blob | bound] +** to the parameters at a later time. +** +** ^(This routine actually returns the index of the largest (rightmost) +** parameter. For all forms except ?NNN, this will correspond to the +** number of unique parameters. If parameters of the ?NNN form are used, +** there may be gaps in the list.)^ +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_name()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*); + +/* +** CAPI3REF: Name Of A Host Parameter +** METHOD: sqlite3_stmt +** +** ^The sqlite3_bind_parameter_name(P,N) interface returns +** the name of the N-th [SQL parameter] in the [prepared statement] P. +** ^(SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA" +** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA" +** respectively. +** In other words, the initial ":" or "$" or "@" or "?" +** is included as part of the name.)^ +** ^Parameters of the form "?" without a following integer have no name +** and are referred to as "nameless" or "anonymous parameters". +** +** ^The first host parameter has an index of 1, not 0. +** +** ^If the value N is out of range or if the N-th parameter is +** nameless, then NULL is returned. ^The returned string is +** always in UTF-8 encoding even if the named parameter was +** originally specified as UTF-16 in [sqlite3_prepare16()] or +** [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, int); + +/* +** CAPI3REF: Index Of A Parameter With A Given Name +** METHOD: sqlite3_stmt +** +** ^Return the index of an SQL parameter given its name. ^The +** index value returned is suitable for use as the second +** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero +** is returned if no matching parameter is found. ^The parameter +** name must be given in UTF-8 even if the original statement +** was prepared from UTF-16 text using [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); + +/* +** CAPI3REF: Reset All Bindings On A Prepared Statement +** METHOD: sqlite3_stmt +** +** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset +** the [sqlite3_bind_blob | bindings] on a [prepared statement]. +** ^Use this routine to reset all host parameters to NULL. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*); + +/* +** CAPI3REF: Number Of Columns In A Result Set +** METHOD: sqlite3_stmt +** +** ^Return the number of columns in the result set returned by the +** [prepared statement]. ^This routine returns 0 if pStmt is an SQL +** statement that does not return data (for example an [UPDATE]). +** +** See also: [sqlite3_data_count()] +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Column Names In A Result Set +** METHOD: sqlite3_stmt +** +** ^These routines return the name assigned to a particular column +** in the result set of a [SELECT] statement. ^The sqlite3_column_name() +** interface returns a pointer to a zero-terminated UTF-8 string +** and sqlite3_column_name16() returns a pointer to a zero-terminated +** UTF-16 string. ^The first parameter is the [prepared statement] +** that implements the [SELECT] statement. ^The second parameter is the +** column number. ^The leftmost column is number 0. +** +** ^The returned string pointer is valid until either the [prepared statement] +** is destroyed by [sqlite3_finalize()] or until the statement is automatically +** reprepared by the first call to [sqlite3_step()] for a particular run +** or until the next call to +** sqlite3_column_name() or sqlite3_column_name16() on the same column. +** +** ^If sqlite3_malloc() fails during the processing of either routine +** (for example during a conversion from UTF-8 to UTF-16) then a +** NULL pointer is returned. +** +** ^The name of a result column is the value of the "AS" clause for +** that column, if there is an AS clause. If there is no AS clause +** then the name of the column is unspecified and may change from +** one release of SQLite to the next. +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N); + +/* +** CAPI3REF: Source Of Data In A Query Result +** METHOD: sqlite3_stmt +** +** ^These routines provide a means to determine the database, table, and +** table column that is the origin of a particular result column in +** [SELECT] statement. +** ^The name of the database or table or column can be returned as +** either a UTF-8 or UTF-16 string. ^The _database_ routines return +** the database name, the _table_ routines return the table name, and +** the origin_ routines return the column name. +** ^The returned string is valid until the [prepared statement] is destroyed +** using [sqlite3_finalize()] or until the statement is automatically +** reprepared by the first call to [sqlite3_step()] for a particular run +** or until the same information is requested +** again in a different encoding. +** +** ^The names returned are the original un-aliased names of the +** database, table, and column. +** +** ^The first argument to these interfaces is a [prepared statement]. +** ^These functions return information about the Nth result column returned by +** the statement, where N is the second function argument. +** ^The left-most column is column 0 for these routines. +** +** ^If the Nth column returned by the statement is an expression or +** subquery and is not a column value, then all of these functions return +** NULL. ^These routine might also return NULL if a memory allocation error +** occurs. ^Otherwise, they return the name of the attached database, table, +** or column that query result column was extracted from. +** +** ^As with all other SQLite APIs, those whose names end with "16" return +** UTF-16 encoded strings and the other functions return UTF-8. +** +** ^These APIs are only available if the library was compiled with the +** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol. +** +** If two or more threads call one or more of these routines against the same +** prepared statement and column at the same time then the results are +** undefined. +** +** If two or more threads call one or more +** [sqlite3_column_database_name | column metadata interfaces] +** for the same [prepared statement] and result column +** at the same time then the results are undefined. +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Declared Datatype Of A Query Result +** METHOD: sqlite3_stmt +** +** ^(The first parameter is a [prepared statement]. +** If this statement is a [SELECT] statement and the Nth column of the +** returned result set of that [SELECT] is a table column (not an +** expression or subquery) then the declared type of the table +** column is returned.)^ ^If the Nth column of the result set is an +** expression or subquery, then a NULL pointer is returned. +** ^The returned string is always UTF-8 encoded. +** +** ^(For example, given the database schema: +** +** CREATE TABLE t1(c1 VARIANT); +** +** and the following statement to be compiled: +** +** SELECT c1 + 1, c1 FROM t1; +** +** this routine would return the string "VARIANT" for the second result +** column (i==1), and a NULL pointer for the first result column (i==0).)^ +** +** ^SQLite uses dynamic run-time typing. ^So just because a column +** is declared to contain a particular type does not mean that the +** data stored in that column is of the declared type. SQLite is +** strongly typed, but the typing is dynamic not static. ^Type +** is associated with individual values, not with the containers +** used to hold those values. +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Evaluate An SQL Statement +** METHOD: sqlite3_stmt +** +** After a [prepared statement] has been prepared using either +** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy +** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function +** must be called one or more times to evaluate the statement. +** +** The details of the behavior of the sqlite3_step() interface depend +** on whether the statement was prepared using the newer "v2" interface +** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy +** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the +** new "v2" interface is recommended for new applications but the legacy +** interface will continue to be supported. +** +** ^In the legacy interface, the return value will be either [SQLITE_BUSY], +** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. +** ^With the "v2" interface, any of the other [result codes] or +** [extended result codes] might be returned as well. +** +** ^[SQLITE_BUSY] means that the database engine was unable to acquire the +** database locks it needs to do its job. ^If the statement is a [COMMIT] +** or occurs outside of an explicit transaction, then you can retry the +** statement. If the statement is not a [COMMIT] and occurs within an +** explicit transaction then you should rollback the transaction before +** continuing. +** +** ^[SQLITE_DONE] means that the statement has finished executing +** successfully. sqlite3_step() should not be called again on this virtual +** machine without first calling [sqlite3_reset()] to reset the virtual +** machine back to its initial state. +** +** ^If the SQL statement being executed returns any data, then [SQLITE_ROW] +** is returned each time a new row of data is ready for processing by the +** caller. The values may be accessed using the [column access functions]. +** sqlite3_step() is called again to retrieve the next row of data. +** +** ^[SQLITE_ERROR] means that a run-time error (such as a constraint +** violation) has occurred. sqlite3_step() should not be called again on +** the VM. More information may be found by calling [sqlite3_errmsg()]. +** ^With the legacy interface, a more specific error code (for example, +** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) +** can be obtained by calling [sqlite3_reset()] on the +** [prepared statement]. ^In the "v2" interface, +** the more specific error code is returned directly by sqlite3_step(). +** +** [SQLITE_MISUSE] means that the this routine was called inappropriately. +** Perhaps it was called on a [prepared statement] that has +** already been [sqlite3_finalize | finalized] or on one that had +** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could +** be the case that the same database connection is being used by two or +** more threads at the same moment in time. +** +** For all versions of SQLite up to and including 3.6.23.1, a call to +** [sqlite3_reset()] was required after sqlite3_step() returned anything +** other than [SQLITE_ROW] before any subsequent invocation of +** sqlite3_step(). Failure to reset the prepared statement using +** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from +** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began +** calling [sqlite3_reset()] automatically in this circumstance rather +** than returning [SQLITE_MISUSE]. This is not considered a compatibility +** break because any application that ever receives an SQLITE_MISUSE error +** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option +** can be used to restore the legacy behavior. +** +** Goofy Interface Alert: In the legacy interface, the sqlite3_step() +** API always returns a generic error code, [SQLITE_ERROR], following any +** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call +** [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the +** specific [error codes] that better describes the error. +** We admit that this is a goofy design. The problem has been fixed +** with the "v2" interface. If you prepare all of your SQL statements +** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead +** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, +** then the more specific [error codes] are returned directly +** by sqlite3_step(). The use of the "v2" interface is recommended. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*); + +/* +** CAPI3REF: Number of columns in a result set +** METHOD: sqlite3_stmt +** +** ^The sqlite3_data_count(P) interface returns the number of columns in the +** current row of the result set of [prepared statement] P. +** ^If prepared statement P does not have results ready to return +** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of +** interfaces) then sqlite3_data_count(P) returns 0. +** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. +** ^The sqlite3_data_count(P) routine returns 0 if the previous call to +** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P) +** will return non-zero if previous call to [sqlite3_step](P) returned +** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum] +** where it always returns zero since each step of that multi-step +** pragma returns 0 columns of data. +** +** See also: [sqlite3_column_count()] +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Fundamental Datatypes +** KEYWORDS: SQLITE_TEXT +** +** ^(Every value in SQLite has one of five fundamental datatypes: +** +**
    +**
  • 64-bit signed integer +**
  • 64-bit IEEE floating point number +**
  • string +**
  • BLOB +**
  • NULL +**
)^ +** +** These constants are codes for each of those types. +** +** Note that the SQLITE_TEXT constant was also used in SQLite version 2 +** for a completely different meaning. Software that links against both +** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, not +** SQLITE_TEXT. +*/ +#define SQLITE_INTEGER 1 +#define SQLITE_FLOAT 2 +#define SQLITE_BLOB 4 +#define SQLITE_NULL 5 +#ifdef SQLITE_TEXT +# undef SQLITE_TEXT +#else +# define SQLITE_TEXT 3 +#endif +#define SQLITE3_TEXT 3 + +/* +** CAPI3REF: Result Values From A Query +** KEYWORDS: {column access functions} +** METHOD: sqlite3_stmt +** +** ^These routines return information about a single column of the current +** result row of a query. ^In every case the first argument is a pointer +** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*] +** that was returned from [sqlite3_prepare_v2()] or one of its variants) +** and the second argument is the index of the column for which information +** should be returned. ^The leftmost column of the result set has the index 0. +** ^The number of columns in the result can be determined using +** [sqlite3_column_count()]. +** +** If the SQL statement does not currently point to a valid row, or if the +** column index is out of range, the result is undefined. +** These routines may only be called when the most recent call to +** [sqlite3_step()] has returned [SQLITE_ROW] and neither +** [sqlite3_reset()] nor [sqlite3_finalize()] have been called subsequently. +** If any of these routines are called after [sqlite3_reset()] or +** [sqlite3_finalize()] or after [sqlite3_step()] has returned +** something other than [SQLITE_ROW], the results are undefined. +** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] +** are called from a different thread while any of these routines +** are pending, then the results are undefined. +** +** ^The sqlite3_column_type() routine returns the +** [SQLITE_INTEGER | datatype code] for the initial data type +** of the result column. ^The returned value is one of [SQLITE_INTEGER], +** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value +** returned by sqlite3_column_type() is only meaningful if no type +** conversions have occurred as described below. After a type conversion, +** the value returned by sqlite3_column_type() is undefined. Future +** versions of SQLite may change the behavior of sqlite3_column_type() +** following a type conversion. +** +** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() +** routine returns the number of bytes in that BLOB or string. +** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts +** the string to UTF-8 and then returns the number of bytes. +** ^If the result is a numeric value then sqlite3_column_bytes() uses +** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns +** the number of bytes in that string. +** ^If the result is NULL, then sqlite3_column_bytes() returns zero. +** +** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16() +** routine returns the number of bytes in that BLOB or string. +** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts +** the string to UTF-16 and then returns the number of bytes. +** ^If the result is a numeric value then sqlite3_column_bytes16() uses +** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns +** the number of bytes in that string. +** ^If the result is NULL, then sqlite3_column_bytes16() returns zero. +** +** ^The values returned by [sqlite3_column_bytes()] and +** [sqlite3_column_bytes16()] do not include the zero terminators at the end +** of the string. ^For clarity: the values returned by +** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of +** bytes in the string, not the number of characters. +** +** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(), +** even empty strings, are always zero-terminated. ^The return +** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. +** +** Warning: ^The object returned by [sqlite3_column_value()] is an +** [unprotected sqlite3_value] object. In a multithreaded environment, +** an unprotected sqlite3_value object may only be used safely with +** [sqlite3_bind_value()] and [sqlite3_result_value()]. +** If the [unprotected sqlite3_value] object returned by +** [sqlite3_column_value()] is used in any other way, including calls +** to routines like [sqlite3_value_int()], [sqlite3_value_text()], +** or [sqlite3_value_bytes()], the behavior is not threadsafe. +** +** These routines attempt to convert the value where appropriate. ^For +** example, if the internal representation is FLOAT and a text result +** is requested, [sqlite3_snprintf()] is used internally to perform the +** conversion automatically. ^(The following table details the conversions +** that are applied: +** +**
+** +**
Internal
Type
Requested
Type
Conversion +** +**
NULL INTEGER Result is 0 +**
NULL FLOAT Result is 0.0 +**
NULL TEXT Result is a NULL pointer +**
NULL BLOB Result is a NULL pointer +**
INTEGER FLOAT Convert from integer to float +**
INTEGER TEXT ASCII rendering of the integer +**
INTEGER BLOB Same as INTEGER->TEXT +**
FLOAT INTEGER [CAST] to INTEGER +**
FLOAT TEXT ASCII rendering of the float +**
FLOAT BLOB [CAST] to BLOB +**
TEXT INTEGER [CAST] to INTEGER +**
TEXT FLOAT [CAST] to REAL +**
TEXT BLOB No change +**
BLOB INTEGER [CAST] to INTEGER +**
BLOB FLOAT [CAST] to REAL +**
BLOB TEXT Add a zero terminator if needed +**
+**
)^ +** +** Note that when type conversions occur, pointers returned by prior +** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or +** sqlite3_column_text16() may be invalidated. +** Type conversions and pointer invalidations might occur +** in the following cases: +** +**
    +**
  • The initial content is a BLOB and sqlite3_column_text() or +** sqlite3_column_text16() is called. A zero-terminator might +** need to be added to the string.
  • +**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or +** sqlite3_column_text16() is called. The content must be converted +** to UTF-16.
  • +**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or +** sqlite3_column_text() is called. The content must be converted +** to UTF-8.
  • +**
+** +** ^Conversions between UTF-16be and UTF-16le are always done in place and do +** not invalidate a prior pointer, though of course the content of the buffer +** that the prior pointer references will have been modified. Other kinds +** of conversion are done in place when it is possible, but sometimes they +** are not possible and in those cases prior pointers are invalidated. +** +** The safest policy is to invoke these routines +** in one of the following ways: +** +**
    +**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • +**
+** +** In other words, you should call sqlite3_column_text(), +** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result +** into the desired format, then invoke sqlite3_column_bytes() or +** sqlite3_column_bytes16() to find the size of the result. Do not mix calls +** to sqlite3_column_text() or sqlite3_column_blob() with calls to +** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16() +** with calls to sqlite3_column_bytes(). +** +** ^The pointers returned are valid until a type conversion occurs as +** described above, or until [sqlite3_step()] or [sqlite3_reset()] or +** [sqlite3_finalize()] is called. ^The memory space used to hold strings +** and BLOBs is freed automatically. Do not pass the pointers returned +** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into +** [sqlite3_free()]. +** +** ^(If a memory allocation error occurs during the evaluation of any +** of these routines, a default value is returned. The default value +** is either the integer 0, the floating point number 0.0, or a NULL +** pointer. Subsequent calls to [sqlite3_errcode()] will return +** [SQLITE_NOMEM].)^ +*/ +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt*, int iCol); +SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt*, int iCol); +SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt*, int iCol); +SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*, int iCol); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt*, int iCol); +SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int iCol); + +/* +** CAPI3REF: Destroy A Prepared Statement Object +** DESTRUCTOR: sqlite3_stmt +** +** ^The sqlite3_finalize() function is called to delete a [prepared statement]. +** ^If the most recent evaluation of the statement encountered no errors +** or if the statement is never been evaluated, then sqlite3_finalize() returns +** SQLITE_OK. ^If the most recent evaluation of statement S failed, then +** sqlite3_finalize(S) returns the appropriate [error code] or +** [extended error code]. +** +** ^The sqlite3_finalize(S) routine can be called at any point during +** the life cycle of [prepared statement] S: +** before statement S is ever evaluated, after +** one or more calls to [sqlite3_reset()], or after any call +** to [sqlite3_step()] regardless of whether or not the statement has +** completed execution. +** +** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. +** +** The application must finalize every [prepared statement] in order to avoid +** resource leaks. It is a grievous error for the application to try to use +** a prepared statement after it has been finalized. Any use of a prepared +** statement after it has been finalized can result in undefined and +** undesirable behavior such as segfaults and heap corruption. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Reset A Prepared Statement Object +** METHOD: sqlite3_stmt +** +** The sqlite3_reset() function is called to reset a [prepared statement] +** object back to its initial state, ready to be re-executed. +** ^Any SQL statement variables that had values bound to them using +** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. +** Use [sqlite3_clear_bindings()] to reset the bindings. +** +** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S +** back to the beginning of its program. +** +** ^If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], +** or if [sqlite3_step(S)] has never before been called on S, +** then [sqlite3_reset(S)] returns [SQLITE_OK]. +** +** ^If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S indicated an error, then +** [sqlite3_reset(S)] returns an appropriate [error code]. +** +** ^The [sqlite3_reset(S)] interface does not change the values +** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Create Or Redefine SQL Functions +** KEYWORDS: {function creation routines} +** KEYWORDS: {application-defined SQL function} +** KEYWORDS: {application-defined SQL functions} +** METHOD: sqlite3 +** +** ^These functions (collectively known as "function creation routines") +** are used to add SQL functions or aggregates or to redefine the behavior +** of existing SQL functions or aggregates. The only differences between +** these routines are the text encoding expected for +** the second parameter (the name of the function being created) +** and the presence or absence of a destructor callback for +** the application data pointer. +** +** ^The first parameter is the [database connection] to which the SQL +** function is to be added. ^If an application uses more than one database +** connection then application-defined SQL functions must be added +** to each database connection separately. +** +** ^The second parameter is the name of the SQL function to be created or +** redefined. ^The length of the name is limited to 255 bytes in a UTF-8 +** representation, exclusive of the zero-terminator. ^Note that the name +** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. +** ^Any attempt to create a function with a longer name +** will result in [SQLITE_MISUSE] being returned. +** +** ^The third parameter (nArg) +** is the number of arguments that the SQL function or +** aggregate takes. ^If this parameter is -1, then the SQL function or +** aggregate may take any number of arguments between 0 and the limit +** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third +** parameter is less than -1 or greater than 127 then the behavior is +** undefined. +** +** ^The fourth parameter, eTextRep, specifies what +** [SQLITE_UTF8 | text encoding] this SQL function prefers for +** its parameters. The application should set this parameter to +** [SQLITE_UTF16LE] if the function implementation invokes +** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the +** implementation invokes [sqlite3_value_text16be()] on an input, or +** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8] +** otherwise. ^The same SQL function may be registered multiple times using +** different preferred text encodings, with different implementations for +** each encoding. +** ^When multiple implementations of the same function are available, SQLite +** will pick the one that involves the least amount of data conversion. +** +** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC] +** to signal that the function will always return the same result given +** the same inputs within a single SQL statement. Most SQL functions are +** deterministic. The built-in [random()] SQL function is an example of a +** function that is not deterministic. The SQLite query planner is able to +** perform additional optimizations on deterministic functions, so use +** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. +** +** ^(The fifth parameter is an arbitrary pointer. The implementation of the +** function can gain access to this pointer using [sqlite3_user_data()].)^ +** +** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are +** pointers to C-language functions that implement the SQL function or +** aggregate. ^A scalar SQL function requires an implementation of the xFunc +** callback only; NULL pointers must be passed as the xStep and xFinal +** parameters. ^An aggregate SQL function requires an implementation of xStep +** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing +** SQL function or aggregate, pass NULL pointers for all three function +** callbacks. +** +** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL, +** then it is destructor for the application data pointer. +** The destructor is invoked when the function is deleted, either by being +** overloaded or when the database connection closes.)^ +** ^The destructor is also invoked if the call to +** sqlite3_create_function_v2() fails. +** ^When the destructor callback of the tenth parameter is invoked, it +** is passed a single argument which is a copy of the application data +** pointer which was the fifth parameter to sqlite3_create_function_v2(). +** +** ^It is permitted to register multiple implementations of the same +** functions with the same name but with either differing numbers of +** arguments or differing preferred text encodings. ^SQLite will use +** the implementation that most closely matches the way in which the +** SQL function is used. ^A function implementation with a non-negative +** nArg parameter is a better match than a function implementation with +** a negative nArg. ^A function where the preferred text encoding +** matches the database encoding is a better +** match than a function where the encoding is different. +** ^A function where the encoding difference is between UTF16le and UTF16be +** is a closer match than a function where the encoding difference is +** between UTF8 and UTF16. +** +** ^Built-in functions may be overloaded by new application-defined functions. +** +** ^An application-defined function is permitted to call other +** SQLite interfaces. However, such calls must not +** close the database connection nor finalize or reset the prepared +** statement in which the function is running. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( + sqlite3 *db, + const void *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*), + void(*xDestroy)(void*) +); + +/* +** CAPI3REF: Text Encodings +** +** These constant define integer codes that represent the various +** text encodings supported by SQLite. +*/ +#define SQLITE_UTF8 1 /* IMP: R-37514-35566 */ +#define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */ +#define SQLITE_UTF16BE 3 /* IMP: R-51971-34154 */ +#define SQLITE_UTF16 4 /* Use native byte order */ +#define SQLITE_ANY 5 /* Deprecated */ +#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ + +/* +** CAPI3REF: Function Flags +** +** These constants may be ORed together with the +** [SQLITE_UTF8 | preferred text encoding] as the fourth argument +** to [sqlite3_create_function()], [sqlite3_create_function16()], or +** [sqlite3_create_function_v2()]. +*/ +#define SQLITE_DETERMINISTIC 0x800 + +/* +** CAPI3REF: Deprecated Functions +** DEPRECATED +** +** These functions are [deprecated]. In order to maintain +** backwards compatibility with older code, these functions continue +** to be supported. However, new applications should avoid +** the use of these functions. To encourage programmers to avoid +** these functions, we will not explain what they do. +*/ +#ifndef SQLITE_OMIT_DEPRECATED +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), + void*,sqlite3_int64); +#endif + +/* +** CAPI3REF: Obtaining SQL Values +** METHOD: sqlite3_value +** +** The C-language implementation of SQL functions and aggregates uses +** this set of interface routines to access the parameter values on +** the function or aggregate. +** +** The xFunc (for scalar functions) or xStep (for aggregates) parameters +** to [sqlite3_create_function()] and [sqlite3_create_function16()] +** define callbacks that implement the SQL functions and aggregates. +** The 3rd parameter to these callbacks is an array of pointers to +** [protected sqlite3_value] objects. There is one [sqlite3_value] object for +** each parameter to the SQL function. These routines are used to +** extract values from the [sqlite3_value] objects. +** +** These routines work only with [protected sqlite3_value] objects. +** Any attempt to use these routines on an [unprotected sqlite3_value] +** object results in undefined behavior. +** +** ^These routines work just like the corresponding [column access functions] +** except that these routines take a single [protected sqlite3_value] object +** pointer instead of a [sqlite3_stmt*] pointer and an integer column number. +** +** ^The sqlite3_value_text16() interface extracts a UTF-16 string +** in the native byte-order of the host machine. ^The +** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces +** extract UTF-16 strings as big-endian and little-endian respectively. +** +** ^(The sqlite3_value_numeric_type() interface attempts to apply +** numeric affinity to the value. This means that an attempt is +** made to convert the value to an integer or floating point. If +** such a conversion is possible without loss of information (in other +** words, if the value is a string that looks like a number) +** then the conversion is performed. Otherwise no conversion occurs. +** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ +** +** Please pay particular attention to the fact that the pointer returned +** from [sqlite3_value_blob()], [sqlite3_value_text()], or +** [sqlite3_value_text16()] can be invalidated by a subsequent call to +** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], +** or [sqlite3_value_text16()]. +** +** These routines must be called from the same thread as +** the SQL function that supplied the [sqlite3_value*] parameters. +*/ +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value*); +SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value*); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value*); +SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*); + +/* +** CAPI3REF: Copy And Free SQL Values +** METHOD: sqlite3_value +** +** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value] +** object D and returns a pointer to that copy. ^The [sqlite3_value] returned +** is a [protected sqlite3_value] object even if the input is not. +** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a +** memory allocation fails. +** +** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object +** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer +** then sqlite3_value_free(V) is a harmless no-op. +*/ +SQLITE_API SQLITE_EXPERIMENTAL sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value*); +SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*); + +/* +** CAPI3REF: Obtain Aggregate Function Context +** METHOD: sqlite3_context +** +** Implementations of aggregate SQL functions use this +** routine to allocate memory for storing their state. +** +** ^The first time the sqlite3_aggregate_context(C,N) routine is called +** for a particular aggregate function, SQLite +** allocates N of memory, zeroes out that memory, and returns a pointer +** to the new memory. ^On second and subsequent calls to +** sqlite3_aggregate_context() for the same aggregate function instance, +** the same buffer is returned. Sqlite3_aggregate_context() is normally +** called once for each invocation of the xStep callback and then one +** last time when the xFinal callback is invoked. ^(When no rows match +** an aggregate query, the xStep() callback of the aggregate function +** implementation is never called and xFinal() is called exactly once. +** In those cases, sqlite3_aggregate_context() might be called for the +** first time from within xFinal().)^ +** +** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer +** when first called if N is less than or equal to zero or if a memory +** allocate error occurs. +** +** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is +** determined by the N parameter on first successful call. Changing the +** value of N in subsequent call to sqlite3_aggregate_context() within +** the same aggregate function instance will not resize the memory +** allocation.)^ Within the xFinal callback, it is customary to set +** N=0 in calls to sqlite3_aggregate_context(C,N) so that no +** pointless memory allocations occur. +** +** ^SQLite automatically frees the memory allocated by +** sqlite3_aggregate_context() when the aggregate query concludes. +** +** The first parameter must be a copy of the +** [sqlite3_context | SQL function context] that is the first parameter +** to the xStep or xFinal callback routine that implements the aggregate +** function. +** +** This routine must be called from the same thread in which +** the aggregate SQL function is running. +*/ +SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int nBytes); + +/* +** CAPI3REF: User Data For Functions +** METHOD: sqlite3_context +** +** ^The sqlite3_user_data() interface returns a copy of +** the pointer that was the pUserData parameter (the 5th parameter) +** of the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. +** +** This routine must be called from the same thread in which +** the application-defined function is running. +*/ +SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*); + +/* +** CAPI3REF: Database Connection For Functions +** METHOD: sqlite3_context +** +** ^The sqlite3_context_db_handle() interface returns a copy of +** the pointer to the [database connection] (the 1st parameter) +** of the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. +*/ +SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); + +/* +** CAPI3REF: Function Auxiliary Data +** METHOD: sqlite3_context +** +** These functions may be used by (non-aggregate) SQL functions to +** associate metadata with argument values. If the same value is passed to +** multiple invocations of the same SQL function during query execution, under +** some circumstances the associated metadata may be preserved. An example +** of where this might be useful is in a regular-expression matching +** function. The compiled version of the regular expression can be stored as +** metadata associated with the pattern string. +** Then as long as the pattern string remains the same, +** the compiled regular expression can be reused on multiple +** invocations of the same function. +** +** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata +** associated by the sqlite3_set_auxdata() function with the Nth argument +** value to the application-defined function. ^If there is no metadata +** associated with the function argument, this sqlite3_get_auxdata() interface +** returns a NULL pointer. +** +** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th +** argument of the application-defined function. ^Subsequent +** calls to sqlite3_get_auxdata(C,N) return P from the most recent +** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or +** NULL if the metadata has been discarded. +** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL, +** SQLite will invoke the destructor function X with parameter P exactly +** once, when the metadata is discarded. +** SQLite is free to discard the metadata at any time, including:
    +**
  • when the corresponding function parameter changes, or +**
  • when [sqlite3_reset()] or [sqlite3_finalize()] is called for the +** SQL statement, or +**
  • when sqlite3_set_auxdata() is invoked again on the same parameter, or +**
  • during the original sqlite3_set_auxdata() call when a memory +** allocation error occurs.
)^ +** +** Note the last bullet in particular. The destructor X in +** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the +** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() +** should be called near the end of the function implementation and the +** function implementation should not make any use of P after +** sqlite3_set_auxdata() has been called. +** +** ^(In practice, metadata is preserved between function calls for +** function parameters that are compile-time constants, including literal +** values and [parameters] and expressions composed from the same.)^ +** +** These routines must be called from the same thread in which +** the SQL function is running. +*/ +SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); + + +/* +** CAPI3REF: Constants Defining Special Destructor Behavior +** +** These are special values for the destructor that is passed in as the +** final argument to routines like [sqlite3_result_blob()]. ^If the destructor +** argument is SQLITE_STATIC, it means that the content pointer is constant +** and will never change. It does not need to be destroyed. ^The +** SQLITE_TRANSIENT value means that the content will likely change in +** the near future and that SQLite should make its own private copy of +** the content before returning. +** +** The typedef is necessary to work around problems in certain +** C++ compilers. +*/ +typedef void (*sqlite3_destructor_type)(void*); +#define SQLITE_STATIC ((sqlite3_destructor_type)0) +#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) + +/* +** CAPI3REF: Setting The Result Of An SQL Function +** METHOD: sqlite3_context +** +** These routines are used by the xFunc or xFinal callbacks that +** implement SQL functions and aggregates. See +** [sqlite3_create_function()] and [sqlite3_create_function16()] +** for additional information. +** +** These functions work very much like the [parameter binding] family of +** functions used to bind values to host parameters in prepared statements. +** Refer to the [SQL parameter] documentation for additional information. +** +** ^The sqlite3_result_blob() interface sets the result from +** an application-defined function to be the BLOB whose content is pointed +** to by the second parameter and which is N bytes long where N is the +** third parameter. +** +** ^The sqlite3_result_zeroblob(C,N) and sqlite3_result_zeroblob64(C,N) +** interfaces set the result of the application-defined function to be +** a BLOB containing all zero bytes and N bytes in size. +** +** ^The sqlite3_result_double() interface sets the result from +** an application-defined function to be a floating point value specified +** by its 2nd argument. +** +** ^The sqlite3_result_error() and sqlite3_result_error16() functions +** cause the implemented SQL function to throw an exception. +** ^SQLite uses the string pointed to by the +** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() +** as the text of an error message. ^SQLite interprets the error +** message string from sqlite3_result_error() as UTF-8. ^SQLite +** interprets the string from sqlite3_result_error16() as UTF-16 in native +** byte order. ^If the third parameter to sqlite3_result_error() +** or sqlite3_result_error16() is negative then SQLite takes as the error +** message all text up through the first zero character. +** ^If the third parameter to sqlite3_result_error() or +** sqlite3_result_error16() is non-negative then SQLite takes that many +** bytes (not characters) from the 2nd parameter as the error message. +** ^The sqlite3_result_error() and sqlite3_result_error16() +** routines make a private copy of the error message text before +** they return. Hence, the calling function can deallocate or +** modify the text after they return without harm. +** ^The sqlite3_result_error_code() function changes the error code +** returned by SQLite as a result of an error in a function. ^By default, +** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error() +** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. +** +** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an +** error indicating that a string or BLOB is too long to represent. +** +** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an +** error indicating that a memory allocation failed. +** +** ^The sqlite3_result_int() interface sets the return value +** of the application-defined function to be the 32-bit signed integer +** value given in the 2nd argument. +** ^The sqlite3_result_int64() interface sets the return value +** of the application-defined function to be the 64-bit signed integer +** value given in the 2nd argument. +** +** ^The sqlite3_result_null() interface sets the return value +** of the application-defined function to be NULL. +** +** ^The sqlite3_result_text(), sqlite3_result_text16(), +** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces +** set the return value of the application-defined function to be +** a text string which is represented as UTF-8, UTF-16 native byte order, +** UTF-16 little endian, or UTF-16 big endian, respectively. +** ^The sqlite3_result_text64() interface sets the return value of an +** application-defined function to be a text string in an encoding +** specified by the fifth (and last) parameter, which must be one +** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. +** ^SQLite takes the text result from the application from +** the 2nd parameter of the sqlite3_result_text* interfaces. +** ^If the 3rd parameter to the sqlite3_result_text* interfaces +** is negative, then SQLite takes result text from the 2nd parameter +** through the first zero character. +** ^If the 3rd parameter to the sqlite3_result_text* interfaces +** is non-negative, then as many bytes (not characters) of the text +** pointed to by the 2nd parameter are taken as the application-defined +** function result. If the 3rd parameter is non-negative, then it +** must be the byte offset into the string where the NUL terminator would +** appear if the string where NUL terminated. If any NUL characters occur +** in the string at a byte offset that is less than the value of the 3rd +** parameter, then the resulting string will contain embedded NULs and the +** result of expressions operating on strings with embedded NULs is undefined. +** ^If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that +** function as the destructor on the text or BLOB result when it has +** finished using that result. +** ^If the 4th parameter to the sqlite3_result_text* interfaces or to +** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite +** assumes that the text or BLOB result is in constant space and does not +** copy the content of the parameter nor call a destructor on the content +** when it has finished using that result. +** ^If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT +** then SQLite makes a copy of the result into space obtained from +** from [sqlite3_malloc()] before it returns. +** +** ^The sqlite3_result_value() interface sets the result of +** the application-defined function to be a copy of the +** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The +** sqlite3_result_value() interface makes a copy of the [sqlite3_value] +** so that the [sqlite3_value] specified in the parameter may change or +** be deallocated after sqlite3_result_value() returns without harm. +** ^A [protected sqlite3_value] object may always be used where an +** [unprotected sqlite3_value] object is required, so either +** kind of [sqlite3_value] object can be used with this interface. +** +** If these routines are called from within the different thread +** than the one containing the application-defined function that received +** the [sqlite3_context] pointer, the results are undefined. +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64(sqlite3_context*,const void*, + sqlite3_uint64,void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context*); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, + void(*)(void*), unsigned char encoding); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n); +SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); + +/* +** CAPI3REF: Define New Collating Sequences +** METHOD: sqlite3 +** +** ^These functions add, remove, or modify a [collation] associated +** with the [database connection] specified as the first argument. +** +** ^The name of the collation is a UTF-8 string +** for sqlite3_create_collation() and sqlite3_create_collation_v2() +** and a UTF-16 string in native byte order for sqlite3_create_collation16(). +** ^Collation names that compare equal according to [sqlite3_strnicmp()] are +** considered to be the same name. +** +** ^(The third argument (eTextRep) must be one of the constants: +**
    +**
  • [SQLITE_UTF8], +**
  • [SQLITE_UTF16LE], +**
  • [SQLITE_UTF16BE], +**
  • [SQLITE_UTF16], or +**
  • [SQLITE_UTF16_ALIGNED]. +**
)^ +** ^The eTextRep argument determines the encoding of strings passed +** to the collating function callback, xCallback. +** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep +** force strings to be UTF16 with native byte order. +** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin +** on an even byte address. +** +** ^The fourth argument, pArg, is an application data pointer that is passed +** through as the first argument to the collating function callback. +** +** ^The fifth argument, xCallback, is a pointer to the collating function. +** ^Multiple collating functions can be registered using the same name but +** with different eTextRep parameters and SQLite will use whichever +** function requires the least amount of data transformation. +** ^If the xCallback argument is NULL then the collating function is +** deleted. ^When all collating functions having the same name are deleted, +** that collation is no longer usable. +** +** ^The collating function callback is invoked with a copy of the pArg +** application data pointer and with two strings in the encoding specified +** by the eTextRep argument. The collating function must return an +** integer that is negative, zero, or positive +** if the first string is less than, equal to, or greater than the second, +** respectively. A collating function must always return the same answer +** given the same inputs. If two or more collating functions are registered +** to the same collation name (using different eTextRep values) then all +** must give an equivalent answer when invoked with equivalent strings. +** The collating function must obey the following properties for all +** strings A, B, and C: +** +**
    +**
  1. If A==B then B==A. +**
  2. If A==B and B==C then A==C. +**
  3. If A<B THEN B>A. +**
  4. If A<B and B<C then A<C. +**
+** +** If a collating function fails any of the above constraints and that +** collating function is registered and used, then the behavior of SQLite +** is undefined. +** +** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() +** with the addition that the xDestroy callback is invoked on pArg when +** the collating function is deleted. +** ^Collating functions are deleted when they are overridden by later +** calls to the collation creation functions or when the +** [database connection] is closed using [sqlite3_close()]. +** +** ^The xDestroy callback is not called if the +** sqlite3_create_collation_v2() function fails. Applications that invoke +** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should +** check the return code and dispose of the application data pointer +** themselves rather than expecting SQLite to deal with it for them. +** This is different from every other SQLite interface. The inconsistency +** is unfortunate but cannot be changed without breaking backwards +** compatibility. +** +** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_create_collation( + sqlite3*, + const char *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*) +); +SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( + sqlite3*, + const char *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDestroy)(void*) +); +SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( + sqlite3*, + const void *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*) +); + +/* +** CAPI3REF: Collation Needed Callbacks +** METHOD: sqlite3 +** +** ^To avoid having to register all collation sequences before a database +** can be used, a single callback function may be registered with the +** [database connection] to be invoked whenever an undefined collation +** sequence is required. +** +** ^If the function is registered using the sqlite3_collation_needed() API, +** then it is passed the names of undefined collation sequences as strings +** encoded in UTF-8. ^If sqlite3_collation_needed16() is used, +** the names are passed as UTF-16 in machine native byte order. +** ^A call to either function replaces the existing collation-needed callback. +** +** ^(When the callback is invoked, the first argument passed is a copy +** of the second argument to sqlite3_collation_needed() or +** sqlite3_collation_needed16(). The second argument is the database +** connection. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE], +** or [SQLITE_UTF16LE], indicating the most desirable form of the collation +** sequence function required. The fourth parameter is the name of the +** required collation sequence.)^ +** +** The callback function should register the desired collation using +** [sqlite3_create_collation()], [sqlite3_create_collation16()], or +** [sqlite3_create_collation_v2()]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const char*) +); +SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const void*) +); + +#ifdef SQLITE_HAS_CODEC +/* +** Specify the key for an encrypted database. This routine should be +** called right after sqlite3_open(). +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_key( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The key */ +); +SQLITE_API int SQLITE_STDCALL sqlite3_key_v2( + sqlite3 *db, /* Database to be rekeyed */ + const char *zDbName, /* Name of the database */ + const void *pKey, int nKey /* The key */ +); + +/* +** Change the key on an open database. If the current database is not +** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the +** database is decrypted. +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_rekey( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The new key */ +); +SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2( + sqlite3 *db, /* Database to be rekeyed */ + const char *zDbName, /* Name of the database */ + const void *pKey, int nKey /* The new key */ +); + +/* +** Specify the activation key for a SEE database. Unless +** activated, none of the SEE routines will work. +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_activate_see( + const char *zPassPhrase /* Activation phrase */ +); +#endif + +#ifdef SQLITE_ENABLE_CEROD +/* +** Specify the activation key for a CEROD database. Unless +** activated, none of the CEROD routines will work. +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod( + const char *zPassPhrase /* Activation phrase */ +); +#endif + +/* +** CAPI3REF: Suspend Execution For A Short Time +** +** The sqlite3_sleep() function causes the current thread to suspend execution +** for at least a number of milliseconds specified in its parameter. +** +** If the operating system does not support sleep requests with +** millisecond time resolution, then the time will be rounded up to +** the nearest second. The number of milliseconds of sleep actually +** requested from the operating system is returned. +** +** ^SQLite implements this interface by calling the xSleep() +** method of the default [sqlite3_vfs] object. If the xSleep() method +** of the default VFS is not implemented correctly, or not implemented at +** all, then the behavior of sqlite3_sleep() may deviate from the description +** in the previous paragraphs. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int); + +/* +** CAPI3REF: Name Of The Folder Holding Temporary Files +** +** ^(If this global variable is made to point to a string which is +** the name of a folder (a.k.a. directory), then all temporary files +** created by SQLite when using a built-in [sqlite3_vfs | VFS] +** will be placed in that directory.)^ ^If this variable +** is a NULL pointer, then SQLite performs a search for an appropriate +** temporary file directory. +** +** Applications are strongly discouraged from using this global variable. +** It is required to set a temporary folder on Windows Runtime (WinRT). +** But for all other platforms, it is highly recommended that applications +** neither read nor write this variable. This global variable is a relic +** that exists for backwards compatibility of legacy applications and should +** be avoided in new projects. +** +** It is not safe to read or modify this variable in more than one +** thread at a time. It is not safe to read or modify this variable +** if a [database connection] is being used at the same time in a separate +** thread. +** It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been called and that this variable remain unchanged +** thereafter. +** +** ^The [temp_store_directory pragma] may modify this variable and cause +** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, +** the [temp_store_directory pragma] always assumes that any string +** that this variable points to is held in memory obtained from +** [sqlite3_malloc] and the pragma may attempt to free that memory +** using [sqlite3_free]. +** Hence, if this variable is modified directly, either it should be +** made NULL or made to point to memory obtained from [sqlite3_malloc] +** or else the use of the [temp_store_directory pragma] should be avoided. +** Except when requested by the [temp_store_directory pragma], SQLite +** does not free the memory that sqlite3_temp_directory points to. If +** the application wants that memory to be freed, it must do +** so itself, taking care to only do so after all [database connection] +** objects have been destroyed. +** +** Note to Windows Runtime users: The temporary directory must be set +** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various +** features that require the use of temporary files may fail. Here is an +** example of how to do this using C++ with the Windows Runtime: +** +**
+** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
+**       TemporaryFolder->Path->Data();
+** char zPathBuf[MAX_PATH + 1];
+** memset(zPathBuf, 0, sizeof(zPathBuf));
+** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
+**       NULL, NULL);
+** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
+** 
+*/ +SQLITE_API char *sqlite3_temp_directory; + +/* +** CAPI3REF: Name Of The Folder Holding Database Files +** +** ^(If this global variable is made to point to a string which is +** the name of a folder (a.k.a. directory), then all database files +** specified with a relative pathname and created or accessed by +** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed +** to be relative to that directory.)^ ^If this variable is a NULL +** pointer, then SQLite assumes that all database files specified +** with a relative pathname are relative to the current directory +** for the process. Only the windows VFS makes use of this global +** variable; it is ignored by the unix VFS. +** +** Changing the value of this variable while a database connection is +** open can result in a corrupt database. +** +** It is not safe to read or modify this variable in more than one +** thread at a time. It is not safe to read or modify this variable +** if a [database connection] is being used at the same time in a separate +** thread. +** It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been called and that this variable remain unchanged +** thereafter. +** +** ^The [data_store_directory pragma] may modify this variable and cause +** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, +** the [data_store_directory pragma] always assumes that any string +** that this variable points to is held in memory obtained from +** [sqlite3_malloc] and the pragma may attempt to free that memory +** using [sqlite3_free]. +** Hence, if this variable is modified directly, either it should be +** made NULL or made to point to memory obtained from [sqlite3_malloc] +** or else the use of the [data_store_directory pragma] should be avoided. +*/ +SQLITE_API char *sqlite3_data_directory; + +/* +** CAPI3REF: Test For Auto-Commit Mode +** KEYWORDS: {autocommit mode} +** METHOD: sqlite3 +** +** ^The sqlite3_get_autocommit() interface returns non-zero or +** zero if the given database connection is or is not in autocommit mode, +** respectively. ^Autocommit mode is on by default. +** ^Autocommit mode is disabled by a [BEGIN] statement. +** ^Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK]. +** +** If certain kinds of errors occur on a statement within a multi-statement +** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR], +** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the +** transaction might be rolled back automatically. The only way to +** find out whether SQLite automatically rolled back the transaction after +** an error is to use this function. +** +** If another thread changes the autocommit status of the database +** connection while this routine is running, then the return value +** is undefined. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*); + +/* +** CAPI3REF: Find The Database Handle Of A Prepared Statement +** METHOD: sqlite3_stmt +** +** ^The sqlite3_db_handle interface returns the [database connection] handle +** to which a [prepared statement] belongs. ^The [database connection] +** returned by sqlite3_db_handle is the same [database connection] +** that was the first argument +** to the [sqlite3_prepare_v2()] call (or its variants) that was used to +** create the statement in the first place. +*/ +SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*); + +/* +** CAPI3REF: Return The Filename For A Database Connection +** METHOD: sqlite3 +** +** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename +** associated with database N of connection D. ^The main database file +** has the name "main". If there is no attached database N on the database +** connection D, or if database N is a temporary or in-memory database, then +** a NULL pointer is returned. +** +** ^The filename returned by this function is the output of the +** xFullPathname method of the [VFS]. ^In other words, the filename +** will be an absolute pathname, even if the filename used +** to open the database originally was a URI or relative pathname. +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName); + +/* +** CAPI3REF: Determine if a database is read-only +** METHOD: sqlite3 +** +** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N +** of connection D is read-only, 0 if it is read/write, or -1 if N is not +** the name of a database on connection D. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName); + +/* +** CAPI3REF: Find the next prepared statement +** METHOD: sqlite3 +** +** ^This interface returns a pointer to the next [prepared statement] after +** pStmt associated with the [database connection] pDb. ^If pStmt is NULL +** then this interface returns a pointer to the first prepared statement +** associated with the database connection pDb. ^If no prepared statement +** satisfies the conditions of this routine, it returns NULL. +** +** The [database connection] pointer D in a call to +** [sqlite3_next_stmt(D,S)] must refer to an open database +** connection and in particular must not be a NULL pointer. +*/ +SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Commit And Rollback Notification Callbacks +** METHOD: sqlite3 +** +** ^The sqlite3_commit_hook() interface registers a callback +** function to be invoked whenever a transaction is [COMMIT | committed]. +** ^Any callback set by a previous call to sqlite3_commit_hook() +** for the same database connection is overridden. +** ^The sqlite3_rollback_hook() interface registers a callback +** function to be invoked whenever a transaction is [ROLLBACK | rolled back]. +** ^Any callback set by a previous call to sqlite3_rollback_hook() +** for the same database connection is overridden. +** ^The pArg argument is passed through to the callback. +** ^If the callback on a commit hook function returns non-zero, +** then the commit is converted into a rollback. +** +** ^The sqlite3_commit_hook(D,C,P) and sqlite3_rollback_hook(D,C,P) functions +** return the P argument from the previous call of the same function +** on the same [database connection] D, or NULL for +** the first call for each function on D. +** +** The commit and rollback hook callbacks are not reentrant. +** The callback implementation must not do anything that will modify +** the database connection that invoked the callback. Any actions +** to modify the database connection must be deferred until after the +** completion of the [sqlite3_step()] call that triggered the commit +** or rollback hook in the first place. +** Note that running any other SQL statements, including SELECT statements, +** or merely calling [sqlite3_prepare_v2()] and [sqlite3_step()] will modify +** the database connections for the meaning of "modify" in this paragraph. +** +** ^Registering a NULL function disables the callback. +** +** ^When the commit hook callback routine returns zero, the [COMMIT] +** operation is allowed to continue normally. ^If the commit hook +** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK]. +** ^The rollback hook is invoked on a rollback that results from a commit +** hook returning non-zero, just as it would be with any other rollback. +** +** ^For the purposes of this API, a transaction is said to have been +** rolled back if an explicit "ROLLBACK" statement is executed, or +** an error or constraint causes an implicit rollback to occur. +** ^The rollback callback is not invoked if a transaction is +** automatically rolled back because the database connection is closed. +** +** See also the [sqlite3_update_hook()] interface. +*/ +SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); + +/* +** CAPI3REF: Data Change Notification Callbacks +** METHOD: sqlite3 +** +** ^The sqlite3_update_hook() interface registers a callback function +** with the [database connection] identified by the first argument +** to be invoked whenever a row is updated, inserted or deleted in +** a rowid table. +** ^Any callback set by a previous call to this function +** for the same database connection is overridden. +** +** ^The second argument is a pointer to the function to invoke when a +** row is updated, inserted or deleted in a rowid table. +** ^The first argument to the callback is a copy of the third argument +** to sqlite3_update_hook(). +** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE], +** or [SQLITE_UPDATE], depending on the operation that caused the callback +** to be invoked. +** ^The third and fourth arguments to the callback contain pointers to the +** database and table name containing the affected row. +** ^The final callback parameter is the [rowid] of the row. +** ^In the case of an update, this is the [rowid] after the update takes place. +** +** ^(The update hook is not invoked when internal system tables are +** modified (i.e. sqlite_master and sqlite_sequence).)^ +** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified. +** +** ^In the current implementation, the update hook +** is not invoked when duplication rows are deleted because of an +** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook +** invoked when rows are deleted using the [truncate optimization]. +** The exceptions defined in this paragraph might change in a future +** release of SQLite. +** +** The update hook implementation must not do anything that will modify +** the database connection that invoked the update hook. Any actions +** to modify the database connection must be deferred until after the +** completion of the [sqlite3_step()] call that triggered the update hook. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** ^The sqlite3_update_hook(D,C,P) function +** returns the P argument from the previous call +** on the same [database connection] D, or NULL for +** the first call on D. +** +** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] +** interfaces. +*/ +SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( + sqlite3*, + void(*)(void *,int ,char const *,char const *,sqlite3_int64), + void* +); + +/* +** CAPI3REF: Enable Or Disable Shared Pager Cache +** +** ^(This routine enables or disables the sharing of the database cache +** and schema data structures between [database connection | connections] +** to the same database. Sharing is enabled if the argument is true +** and disabled if the argument is false.)^ +** +** ^Cache sharing is enabled and disabled for an entire process. +** This is a change as of SQLite version 3.5.0. In prior versions of SQLite, +** sharing was enabled or disabled for each thread separately. +** +** ^(The cache sharing mode set by this interface effects all subsequent +** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. +** Existing database connections continue use the sharing mode +** that was in effect at the time they were opened.)^ +** +** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled +** successfully. An [error code] is returned otherwise.)^ +** +** ^Shared cache is disabled by default. But this might change in +** future releases of SQLite. Applications that care about shared +** cache setting should set it explicitly. +** +** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0 +** and will always return SQLITE_MISUSE. On those systems, +** shared cache mode should be enabled per-database connection via +** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE]. +** +** This interface is threadsafe on processors where writing a +** 32-bit integer is atomic. +** +** See Also: [SQLite Shared-Cache Mode] +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int); + +/* +** CAPI3REF: Attempt To Free Heap Memory +** +** ^The sqlite3_release_memory() interface attempts to free N bytes +** of heap memory by deallocating non-essential memory allocations +** held by the database library. Memory used to cache database +** pages to improve performance is an example of non-essential memory. +** ^sqlite3_release_memory() returns the number of bytes actually freed, +** which might be more or less than the amount requested. +** ^The sqlite3_release_memory() routine is a no-op returning zero +** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT]. +** +** See also: [sqlite3_db_release_memory()] +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int); + +/* +** CAPI3REF: Free Memory Used By A Database Connection +** METHOD: sqlite3 +** +** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap +** memory as possible from database connection D. Unlike the +** [sqlite3_release_memory()] interface, this interface is in effect even +** when the [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is +** omitted. +** +** See also: [sqlite3_release_memory()] +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); + +/* +** CAPI3REF: Impose A Limit On Heap Size +** +** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the +** soft limit on the amount of heap memory that may be allocated by SQLite. +** ^SQLite strives to keep heap memory utilization below the soft heap +** limit by reducing the number of pages held in the page cache +** as heap memory usages approaches the limit. +** ^The soft heap limit is "soft" because even though SQLite strives to stay +** below the limit, it will exceed the limit rather than generate +** an [SQLITE_NOMEM] error. In other words, the soft heap limit +** is advisory only. +** +** ^The return value from sqlite3_soft_heap_limit64() is the size of +** the soft heap limit prior to the call, or negative in the case of an +** error. ^If the argument N is negative +** then no change is made to the soft heap limit. Hence, the current +** size of the soft heap limit can be determined by invoking +** sqlite3_soft_heap_limit64() with a negative argument. +** +** ^If the argument N is zero then the soft heap limit is disabled. +** +** ^(The soft heap limit is not enforced in the current implementation +** if one or more of following conditions are true: +** +**
    +**
  • The soft heap limit is set to zero. +**
  • Memory accounting is disabled using a combination of the +** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and +** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. +**
  • An alternative page cache implementation is specified using +** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...). +**
  • The page cache allocates from its own memory pool supplied +** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than +** from the heap. +**
)^ +** +** Beginning with SQLite version 3.7.3, the soft heap limit is enforced +** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] +** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], +** the soft heap limit is enforced on every memory allocation. Without +** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced +** when memory is allocated by the page cache. Testing suggests that because +** the page cache is the predominate memory user in SQLite, most +** applications will achieve adequate soft heap limit enforcement without +** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT]. +** +** The circumstances under which SQLite will enforce the soft heap limit may +** changes in future releases of SQLite. +*/ +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 N); + +/* +** CAPI3REF: Deprecated Soft Heap Limit Interface +** DEPRECATED +** +** This is a deprecated version of the [sqlite3_soft_heap_limit64()] +** interface. This routine is provided for historical compatibility +** only. All new applications should use the +** [sqlite3_soft_heap_limit64()] interface rather than this one. +*/ +SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); + + +/* +** CAPI3REF: Extract Metadata About A Column Of A Table +** METHOD: sqlite3 +** +** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns +** information about column C of table T in database D +** on [database connection] X.)^ ^The sqlite3_table_column_metadata() +** interface returns SQLITE_OK and fills in the non-NULL pointers in +** the final five arguments with appropriate values if the specified +** column exists. ^The sqlite3_table_column_metadata() interface returns +** SQLITE_ERROR and if the specified column does not exist. +** ^If the column-name parameter to sqlite3_table_column_metadata() is a +** NULL pointer, then this routine simply checks for the existance of the +** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it +** does not. +** +** ^The column is identified by the second, third and fourth parameters to +** this function. ^(The second parameter is either the name of the database +** (i.e. "main", "temp", or an attached database) containing the specified +** table or NULL.)^ ^If it is NULL, then all attached databases are searched +** for the table using the same algorithm used by the database engine to +** resolve unqualified table references. +** +** ^The third and fourth parameters to this function are the table and column +** name of the desired column, respectively. +** +** ^Metadata is returned by writing to the memory locations passed as the 5th +** and subsequent parameters to this function. ^Any of these arguments may be +** NULL, in which case the corresponding element of metadata is omitted. +** +** ^(
+** +**
Parameter Output
Type
Description +** +**
5th const char* Data type +**
6th const char* Name of default collation sequence +**
7th int True if column has a NOT NULL constraint +**
8th int True if column is part of the PRIMARY KEY +**
9th int True if column is [AUTOINCREMENT] +**
+**
)^ +** +** ^The memory pointed to by the character pointers returned for the +** declaration type and collation sequence is valid until the next +** call to any SQLite API function. +** +** ^If the specified table is actually a view, an [error code] is returned. +** +** ^If the specified column is "rowid", "oid" or "_rowid_" and the table +** is not a [WITHOUT ROWID] table and an +** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output +** parameters are set for the explicitly declared column. ^(If there is no +** [INTEGER PRIMARY KEY] column, then the outputs +** for the [rowid] are set as follows: +** +**
+**     data type: "INTEGER"
+**     collation sequence: "BINARY"
+**     not null: 0
+**     primary key: 1
+**     auto increment: 0
+** 
)^ +** +** ^This function causes all database schemas to be read from disk and +** parsed, if that has not already been done, and returns an error if +** any errors are encountered while loading the schema. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if column is auto-increment */ +); + +/* +** CAPI3REF: Load An Extension +** METHOD: sqlite3 +** +** ^This interface loads an SQLite extension library from the named file. +** +** ^The sqlite3_load_extension() interface attempts to load an +** [SQLite extension] library contained in the file zFile. If +** the file cannot be loaded directly, attempts are made to load +** with various operating-system specific extensions added. +** So for example, if "samplelib" cannot be loaded, then names like +** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might +** be tried also. +** +** ^The entry point is zProc. +** ^(zProc may be 0, in which case SQLite will try to come up with an +** entry point name on its own. It first tries "sqlite3_extension_init". +** If that does not work, it constructs a name "sqlite3_X_init" where the +** X is consists of the lower-case equivalent of all ASCII alphabetic +** characters in the filename from the last "/" to the first following +** "." and omitting any initial "lib".)^ +** ^The sqlite3_load_extension() interface returns +** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. +** ^If an error occurs and pzErrMsg is not 0, then the +** [sqlite3_load_extension()] interface shall attempt to +** fill *pzErrMsg with error message text stored in memory +** obtained from [sqlite3_malloc()]. The calling function +** should free this memory by calling [sqlite3_free()]. +** +** ^Extension loading must be enabled using +** [sqlite3_enable_load_extension()] prior to calling this API, +** otherwise an error will be returned. +** +** See also the [load_extension() SQL function]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Derived from zFile if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +); + +/* +** CAPI3REF: Enable Or Disable Extension Loading +** METHOD: sqlite3 +** +** ^So as not to open security holes in older applications that are +** unprepared to deal with [extension loading], and as a means of disabling +** [extension loading] while evaluating user-entered SQL, the following API +** is provided to turn the [sqlite3_load_extension()] mechanism on and off. +** +** ^Extension loading is off by default. +** ^Call the sqlite3_enable_load_extension() routine with onoff==1 +** to turn extension loading on and call it with onoff==0 to turn +** it back off again. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff); + +/* +** CAPI3REF: Automatically Load Statically Linked Extensions +** +** ^This interface causes the xEntryPoint() function to be invoked for +** each new [database connection] that is created. The idea here is that +** xEntryPoint() is the entry point for a statically linked [SQLite extension] +** that is to be automatically loaded into all new database connections. +** +** ^(Even though the function prototype shows that xEntryPoint() takes +** no arguments and returns void, SQLite invokes xEntryPoint() with three +** arguments and expects and integer result as if the signature of the +** entry point where as follows: +** +**
+**    int xEntryPoint(
+**      sqlite3 *db,
+**      const char **pzErrMsg,
+**      const struct sqlite3_api_routines *pThunk
+**    );
+** 
)^ +** +** If the xEntryPoint routine encounters an error, it should make *pzErrMsg +** point to an appropriate error message (obtained from [sqlite3_mprintf()]) +** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg +** is NULL before calling the xEntryPoint(). ^SQLite will invoke +** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any +** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], +** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. +** +** ^Calling sqlite3_auto_extension(X) with an entry point X that is already +** on the list of automatic extensions is a harmless no-op. ^No entry point +** will be called more than once for each database connection that is opened. +** +** See also: [sqlite3_reset_auto_extension()] +** and [sqlite3_cancel_auto_extension()] +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xEntryPoint)(void)); + +/* +** CAPI3REF: Cancel Automatic Extension Loading +** +** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the +** initialization routine X that was registered using a prior call to +** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] +** routine returns 1 if initialization routine X was successfully +** unregistered and it returns 0 if X was not on the list of initialization +** routines. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); + +/* +** CAPI3REF: Reset Automatic Extension Loading +** +** ^This interface disables all automatic extensions previously +** registered using [sqlite3_auto_extension()]. +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void); + +/* +** The interface to the virtual-table mechanism is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + +/* +** Structures used by the virtual table interface +*/ +typedef struct sqlite3_vtab sqlite3_vtab; +typedef struct sqlite3_index_info sqlite3_index_info; +typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; +typedef struct sqlite3_module sqlite3_module; + +/* +** CAPI3REF: Virtual Table Object +** KEYWORDS: sqlite3_module {virtual table module} +** +** This structure, sometimes called a "virtual table module", +** defines the implementation of a [virtual tables]. +** This structure consists mostly of methods for the module. +** +** ^A virtual table module is created by filling in a persistent +** instance of this structure and passing a pointer to that instance +** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. +** ^The registration remains valid until it is replaced by a different +** module or until the [database connection] closes. The content +** of this structure must not change while it is registered with +** any database connection. +*/ +struct sqlite3_module { + int iVersion; + int (*xCreate)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xConnect)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); + int (*xDisconnect)(sqlite3_vtab *pVTab); + int (*xDestroy)(sqlite3_vtab *pVTab); + int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); + int (*xClose)(sqlite3_vtab_cursor*); + int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, + int argc, sqlite3_value **argv); + int (*xNext)(sqlite3_vtab_cursor*); + int (*xEof)(sqlite3_vtab_cursor*); + int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); + int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); + int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); + int (*xBegin)(sqlite3_vtab *pVTab); + int (*xSync)(sqlite3_vtab *pVTab); + int (*xCommit)(sqlite3_vtab *pVTab); + int (*xRollback)(sqlite3_vtab *pVTab); + int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg); + int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); + /* The methods above are in version 1 of the sqlite_module object. Those + ** below are for version 2 and greater. */ + int (*xSavepoint)(sqlite3_vtab *pVTab, int); + int (*xRelease)(sqlite3_vtab *pVTab, int); + int (*xRollbackTo)(sqlite3_vtab *pVTab, int); +}; + +/* +** CAPI3REF: Virtual Table Indexing Information +** KEYWORDS: sqlite3_index_info +** +** The sqlite3_index_info structure and its substructures is used as part +** of the [virtual table] interface to +** pass information into and receive the reply from the [xBestIndex] +** method of a [virtual table module]. The fields under **Inputs** are the +** inputs to xBestIndex and are read-only. xBestIndex inserts its +** results into the **Outputs** fields. +** +** ^(The aConstraint[] array records WHERE clause constraints of the form: +** +**
column OP expr
+** +** where OP is =, <, <=, >, or >=.)^ ^(The particular operator is +** stored in aConstraint[].op using one of the +** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^ +** ^(The index of the column is stored in +** aConstraint[].iColumn.)^ ^(aConstraint[].usable is TRUE if the +** expr on the right-hand side can be evaluated (and thus the constraint +** is usable) and false if it cannot.)^ +** +** ^The optimizer automatically inverts terms of the form "expr OP column" +** and makes other simplifications to the WHERE clause in an attempt to +** get as many WHERE clause terms into the form shown above as possible. +** ^The aConstraint[] array only reports WHERE clause terms that are +** relevant to the particular virtual table being queried. +** +** ^Information about the ORDER BY clause is stored in aOrderBy[]. +** ^Each term of aOrderBy records a column of the ORDER BY clause. +** +** The [xBestIndex] method must fill aConstraintUsage[] with information +** about what parameters to pass to xFilter. ^If argvIndex>0 then +** the right-hand side of the corresponding aConstraint[] is evaluated +** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit +** is true, then the constraint is assumed to be fully handled by the +** virtual table and is not checked again by SQLite.)^ +** +** ^The idxNum and idxPtr values are recorded and passed into the +** [xFilter] method. +** ^[sqlite3_free()] is used to free idxPtr if and only if +** needToFreeIdxPtr is true. +** +** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in +** the correct order to satisfy the ORDER BY clause so that no separate +** sorting step is required. +** +** ^The estimatedCost value is an estimate of the cost of a particular +** strategy. A cost of N indicates that the cost of the strategy is similar +** to a linear scan of an SQLite table with N rows. A cost of log(N) +** indicates that the expense of the operation is similar to that of a +** binary search on a unique indexed field of an SQLite table with N rows. +** +** ^The estimatedRows value is an estimate of the number of rows that +** will be returned by the strategy. +** +** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info +** structure for SQLite version 3.8.2. If a virtual table extension is +** used with an SQLite version earlier than 3.8.2, the results of attempting +** to read or write the estimatedRows field are undefined (but are likely +** to included crashing the application). The estimatedRows field should +** therefore only be used if [sqlite3_libversion_number()] returns a +** value greater than or equal to 3008002. +*/ +struct sqlite3_index_info { + /* Inputs */ + int nConstraint; /* Number of entries in aConstraint */ + struct sqlite3_index_constraint { + int iColumn; /* Column on left-hand side of constraint */ + unsigned char op; /* Constraint operator */ + unsigned char usable; /* True if this constraint is usable */ + int iTermOffset; /* Used internally - xBestIndex should ignore */ + } *aConstraint; /* Table of WHERE clause constraints */ + int nOrderBy; /* Number of terms in the ORDER BY clause */ + struct sqlite3_index_orderby { + int iColumn; /* Column number */ + unsigned char desc; /* True for DESC. False for ASC. */ + } *aOrderBy; /* The ORDER BY clause */ + /* Outputs */ + struct sqlite3_index_constraint_usage { + int argvIndex; /* if >0, constraint is part of argv to xFilter */ + unsigned char omit; /* Do not code a test for this constraint */ + } *aConstraintUsage; + int idxNum; /* Number used to identify the index */ + char *idxStr; /* String, possibly obtained from sqlite3_malloc */ + int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ + int orderByConsumed; /* True if output is already ordered */ + double estimatedCost; /* Estimated cost of using this index */ + /* Fields below are only available in SQLite 3.8.2 and later */ + sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ +}; + +/* +** CAPI3REF: Virtual Table Constraint Operator Codes +** +** These macros defined the allowed values for the +** [sqlite3_index_info].aConstraint[].op field. Each value represents +** an operator that is part of a constraint term in the wHERE clause of +** a query that uses a [virtual table]. +*/ +#define SQLITE_INDEX_CONSTRAINT_EQ 2 +#define SQLITE_INDEX_CONSTRAINT_GT 4 +#define SQLITE_INDEX_CONSTRAINT_LE 8 +#define SQLITE_INDEX_CONSTRAINT_LT 16 +#define SQLITE_INDEX_CONSTRAINT_GE 32 +#define SQLITE_INDEX_CONSTRAINT_MATCH 64 + +/* +** CAPI3REF: Register A Virtual Table Implementation +** METHOD: sqlite3 +** +** ^These routines are used to register a new [virtual table module] name. +** ^Module names must be registered before +** creating a new [virtual table] using the module and before using a +** preexisting [virtual table] for the module. +** +** ^The module name is registered on the [database connection] specified +** by the first parameter. ^The name of the module is given by the +** second parameter. ^The third parameter is a pointer to +** the implementation of the [virtual table module]. ^The fourth +** parameter is an arbitrary client data pointer that is passed through +** into the [xCreate] and [xConnect] methods of the virtual table module +** when a new virtual table is be being created or reinitialized. +** +** ^The sqlite3_create_module_v2() interface has a fifth parameter which +** is a pointer to a destructor for the pClientData. ^SQLite will +** invoke the destructor function (if it is not NULL) when SQLite +** no longer needs the pClientData pointer. ^The destructor will also +** be invoked if the call to sqlite3_create_module_v2() fails. +** ^The sqlite3_create_module() +** interface is equivalent to sqlite3_create_module_v2() with a NULL +** destructor. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_create_module( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData /* Client data for xCreate/xConnect */ +); +SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData, /* Client data for xCreate/xConnect */ + void(*xDestroy)(void*) /* Module destructor function */ +); + +/* +** CAPI3REF: Virtual Table Instance Object +** KEYWORDS: sqlite3_vtab +** +** Every [virtual table module] implementation uses a subclass +** of this object to describe a particular instance +** of the [virtual table]. Each subclass will +** be tailored to the specific needs of the module implementation. +** The purpose of this superclass is to define certain fields that are +** common to all module implementations. +** +** ^Virtual tables methods can set an error message by assigning a +** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should +** take care that any prior string is freed by a call to [sqlite3_free()] +** prior to assigning a new string to zErrMsg. ^After the error message +** is delivered up to the client application, the string will be automatically +** freed by sqlite3_free() and the zErrMsg field will be zeroed. +*/ +struct sqlite3_vtab { + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* Number of open cursors */ + char *zErrMsg; /* Error message from sqlite3_mprintf() */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** CAPI3REF: Virtual Table Cursor Object +** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor} +** +** Every [virtual table module] implementation uses a subclass of the +** following structure to describe cursors that point into the +** [virtual table] and are used +** to loop through the virtual table. Cursors are created using the +** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed +** by the [sqlite3_module.xClose | xClose] method. Cursors are used +** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods +** of the module. Each module implementation will define +** the content of a cursor structure to suit its own needs. +** +** This superclass exists in order to define fields of the cursor that +** are common to all implementations. +*/ +struct sqlite3_vtab_cursor { + sqlite3_vtab *pVtab; /* Virtual table of this cursor */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** CAPI3REF: Declare The Schema Of A Virtual Table +** +** ^The [xCreate] and [xConnect] methods of a +** [virtual table module] call this interface +** to declare the format (the names and datatypes of the columns) of +** the virtual tables they implement. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL); + +/* +** CAPI3REF: Overload A Function For A Virtual Table +** METHOD: sqlite3 +** +** ^(Virtual tables can provide alternative implementations of functions +** using the [xFindFunction] method of the [virtual table module]. +** But global versions of those functions +** must exist in order to be overloaded.)^ +** +** ^(This API makes sure a global version of a function with a particular +** name and number of parameters exists. If no such function exists +** before this API is called, a new function is created.)^ ^The implementation +** of the new function always causes an exception to be thrown. So +** the new function is not good for anything by itself. Its only +** purpose is to be a placeholder function that can be overloaded +** by a [virtual table]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); + +/* +** The interface to the virtual-table mechanism defined above (back up +** to a comment remarkably similar to this one) is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + +/* +** CAPI3REF: A Handle To An Open BLOB +** KEYWORDS: {BLOB handle} {BLOB handles} +** +** An instance of this object represents an open BLOB on which +** [sqlite3_blob_open | incremental BLOB I/O] can be performed. +** ^Objects of this type are created by [sqlite3_blob_open()] +** and destroyed by [sqlite3_blob_close()]. +** ^The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces +** can be used to read or write small subsections of the BLOB. +** ^The [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes. +*/ +typedef struct sqlite3_blob sqlite3_blob; + +/* +** CAPI3REF: Open A BLOB For Incremental I/O +** METHOD: sqlite3 +** CONSTRUCTOR: sqlite3_blob +** +** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located +** in row iRow, column zColumn, table zTable in database zDb; +** in other words, the same BLOB that would be selected by: +** +**
+**     SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
+** 
)^ +** +** ^(Parameter zDb is not the filename that contains the database, but +** rather the symbolic name of the database. For attached databases, this is +** the name that appears after the AS keyword in the [ATTACH] statement. +** For the main database file, the database name is "main". For TEMP +** tables, the database name is "temp".)^ +** +** ^If the flags parameter is non-zero, then the BLOB is opened for read +** and write access. ^If the flags parameter is zero, the BLOB is opened for +** read-only access. +** +** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is stored +** in *ppBlob. Otherwise an [error code] is returned and, unless the error +** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided +** the API is not misused, it is always safe to call [sqlite3_blob_close()] +** on *ppBlob after this function it returns. +** +** This function fails with SQLITE_ERROR if any of the following are true: +**
    +**
  • ^(Database zDb does not exist)^, +**
  • ^(Table zTable does not exist within database zDb)^, +**
  • ^(Table zTable is a WITHOUT ROWID table)^, +**
  • ^(Column zColumn does not exist)^, +**
  • ^(Row iRow is not present in the table)^, +**
  • ^(The specified column of row iRow contains a value that is not +** a TEXT or BLOB value)^, +**
  • ^(Column zColumn is part of an index, PRIMARY KEY or UNIQUE +** constraint and the blob is being opened for read/write access)^, +**
  • ^([foreign key constraints | Foreign key constraints] are enabled, +** column zColumn is part of a [child key] definition and the blob is +** being opened for read/write access)^. +**
+** +** ^Unless it returns SQLITE_MISUSE, this function sets the +** [database connection] error code and message accessible via +** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. +** +** +** ^(If the row that a BLOB handle points to is modified by an +** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects +** then the BLOB handle is marked as "expired". +** This is true if any column of the row is changed, even a column +** other than the one the BLOB handle is open on.)^ +** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for +** an expired BLOB handle fail with a return code of [SQLITE_ABORT]. +** ^(Changes written into a BLOB prior to the BLOB expiring are not +** rolled back by the expiration of the BLOB. Such changes will eventually +** commit if the transaction continues to completion.)^ +** +** ^Use the [sqlite3_blob_bytes()] interface to determine the size of +** the opened blob. ^The size of a blob may not be changed by this +** interface. Use the [UPDATE] SQL command to change the size of a +** blob. +** +** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces +** and the built-in [zeroblob] SQL function may be used to create a +** zero-filled blob to read or write using the incremental-blob interface. +** +** To avoid a resource leak, every open [BLOB handle] should eventually +** be released by a call to [sqlite3_blob_close()]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( + sqlite3*, + const char *zDb, + const char *zTable, + const char *zColumn, + sqlite3_int64 iRow, + int flags, + sqlite3_blob **ppBlob +); + +/* +** CAPI3REF: Move a BLOB Handle to a New Row +** METHOD: sqlite3_blob +** +** ^This function is used to move an existing blob handle so that it points +** to a different row of the same database table. ^The new row is identified +** by the rowid value passed as the second argument. Only the row can be +** changed. ^The database, table and column on which the blob handle is open +** remain the same. Moving an existing blob handle to a new row can be +** faster than closing the existing handle and opening a new one. +** +** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] - +** it must exist and there must be either a blob or text value stored in +** the nominated column.)^ ^If the new row is not present in the table, or if +** it does not contain a blob or text value, or if another error occurs, an +** SQLite error code is returned and the blob handle is considered aborted. +** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or +** [sqlite3_blob_reopen()] on an aborted blob handle immediately return +** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle +** always returns zero. +** +** ^This function sets the database handle error code and message. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); + +/* +** CAPI3REF: Close A BLOB Handle +** DESTRUCTOR: sqlite3_blob +** +** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed +** unconditionally. Even if this routine returns an error code, the +** handle is still closed.)^ +** +** ^If the blob handle being closed was opened for read-write access, and if +** the database is in auto-commit mode and there are no other open read-write +** blob handles or active write statements, the current transaction is +** committed. ^If an error occurs while committing the transaction, an error +** code is returned and the transaction rolled back. +** +** Calling this function with an argument that is not a NULL pointer or an +** open blob handle results in undefined behaviour. ^Calling this routine +** with a null pointer (such as would be returned by a failed call to +** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function +** is passed a valid open blob handle, the values returned by the +** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *); + +/* +** CAPI3REF: Return The Size Of An Open BLOB +** METHOD: sqlite3_blob +** +** ^Returns the size in bytes of the BLOB accessible via the +** successfully opened [BLOB handle] in its only argument. ^The +** incremental blob I/O routines can only read or overwriting existing +** blob content; they cannot change the size of a blob. +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *); + +/* +** CAPI3REF: Read Data From A BLOB Incrementally +** METHOD: sqlite3_blob +** +** ^(This function is used to read data from an open [BLOB handle] into a +** caller-supplied buffer. N bytes of data are copied into buffer Z +** from the open BLOB, starting at offset iOffset.)^ +** +** ^If offset iOffset is less than N bytes from the end of the BLOB, +** [SQLITE_ERROR] is returned and no data is read. ^If N or iOffset is +** less than zero, [SQLITE_ERROR] is returned and no data is read. +** ^The size of the blob (and hence the maximum value of N+iOffset) +** can be determined using the [sqlite3_blob_bytes()] interface. +** +** ^An attempt to read from an expired [BLOB handle] fails with an +** error code of [SQLITE_ABORT]. +** +** ^(On success, sqlite3_blob_read() returns SQLITE_OK. +** Otherwise, an [error code] or an [extended error code] is returned.)^ +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_write()]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); + +/* +** CAPI3REF: Write Data Into A BLOB Incrementally +** METHOD: sqlite3_blob +** +** ^(This function is used to write data into an open [BLOB handle] from a +** caller-supplied buffer. N bytes of data are copied from the buffer Z +** into the open BLOB, starting at offset iOffset.)^ +** +** ^(On success, sqlite3_blob_write() returns SQLITE_OK. +** Otherwise, an [error code] or an [extended error code] is returned.)^ +** ^Unless SQLITE_MISUSE is returned, this function sets the +** [database connection] error code and message accessible via +** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. +** +** ^If the [BLOB handle] passed as the first argument was not opened for +** writing (the flags parameter to [sqlite3_blob_open()] was zero), +** this function returns [SQLITE_READONLY]. +** +** This function may only modify the contents of the BLOB; it is +** not possible to increase the size of a BLOB using this API. +** ^If offset iOffset is less than N bytes from the end of the BLOB, +** [SQLITE_ERROR] is returned and no data is written. The size of the +** BLOB (and hence the maximum value of N+iOffset) can be determined +** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less +** than zero [SQLITE_ERROR] is returned and no data is written. +** +** ^An attempt to write to an expired [BLOB handle] fails with an +** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred +** before the [BLOB handle] expired are not rolled back by the +** expiration of the handle, though of course those changes might +** have been overwritten by the statement that expired the BLOB handle +** or by other independent statements. +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_read()]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); + +/* +** CAPI3REF: Virtual File System Objects +** +** A virtual filesystem (VFS) is an [sqlite3_vfs] object +** that SQLite uses to interact +** with the underlying operating system. Most SQLite builds come with a +** single default VFS that is appropriate for the host computer. +** New VFSes can be registered and existing VFSes can be unregistered. +** The following interfaces are provided. +** +** ^The sqlite3_vfs_find() interface returns a pointer to a VFS given its name. +** ^Names are case sensitive. +** ^Names are zero-terminated UTF-8 strings. +** ^If there is no match, a NULL pointer is returned. +** ^If zVfsName is NULL then the default VFS is returned. +** +** ^New VFSes are registered with sqlite3_vfs_register(). +** ^Each new VFS becomes the default VFS if the makeDflt flag is set. +** ^The same VFS can be registered multiple times without injury. +** ^To make an existing VFS into the default VFS, register it again +** with the makeDflt flag set. If two different VFSes with the +** same name are registered, the behavior is undefined. If a +** VFS is registered with a name that is NULL or an empty string, +** then the behavior is undefined. +** +** ^Unregister a VFS with the sqlite3_vfs_unregister() interface. +** ^(If the default VFS is unregistered, another VFS is chosen as +** the default. The choice for the new VFS is arbitrary.)^ +*/ +SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfsName); +SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*); + +/* +** CAPI3REF: Mutexes +** +** The SQLite core uses these routines for thread +** synchronization. Though they are intended for internal +** use by SQLite, code that links against SQLite is +** permitted to use any of these routines. +** +** The SQLite source code contains multiple implementations +** of these mutex routines. An appropriate implementation +** is selected automatically at compile-time. The following +** implementations are available in the SQLite core: +** +**
    +**
  • SQLITE_MUTEX_PTHREADS +**
  • SQLITE_MUTEX_W32 +**
  • SQLITE_MUTEX_NOOP +**
+** +** The SQLITE_MUTEX_NOOP implementation is a set of routines +** that does no real locking and is appropriate for use in +** a single-threaded application. The SQLITE_MUTEX_PTHREADS and +** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix +** and Windows. +** +** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor +** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex +** implementation is included with the library. In this case the +** application must supply a custom mutex implementation using the +** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function +** before calling sqlite3_initialize() or any other public sqlite3_ +** function that calls sqlite3_initialize(). +** +** ^The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. ^The sqlite3_mutex_alloc() +** routine returns NULL if it is unable to allocate the requested +** mutex. The argument to sqlite3_mutex_alloc() must one of these +** integer constants: +** +**
    +**
  • SQLITE_MUTEX_FAST +**
  • SQLITE_MUTEX_RECURSIVE +**
  • SQLITE_MUTEX_STATIC_MASTER +**
  • SQLITE_MUTEX_STATIC_MEM +**
  • SQLITE_MUTEX_STATIC_OPEN +**
  • SQLITE_MUTEX_STATIC_PRNG +**
  • SQLITE_MUTEX_STATIC_LRU +**
  • SQLITE_MUTEX_STATIC_PMEM +**
  • SQLITE_MUTEX_STATIC_APP1 +**
  • SQLITE_MUTEX_STATIC_APP2 +**
  • SQLITE_MUTEX_STATIC_APP3 +**
+** +** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) +** cause sqlite3_mutex_alloc() to create +** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. SQLite will only request a recursive mutex in +** cases where it really needs one. If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** ^The other allowed parameters to sqlite3_mutex_alloc() (anything other +** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return +** a pointer to a static preexisting mutex. ^Nine static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** ^Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. ^For the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +** +** ^The sqlite3_mutex_free() routine deallocates a previously +** allocated dynamic mutex. Attempting to deallocate a static +** mutex results in undefined behavior. +** +** ^The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. ^If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. ^The sqlite3_mutex_try() interface returns [SQLITE_OK] +** upon successful entry. ^(Mutexes created using +** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. +** In such cases, the +** mutex must be exited an equal number of times before another thread +** can enter.)^ If the same thread tries to enter any mutex other +** than an SQLITE_MUTEX_RECURSIVE more than once, the behavior is undefined. +** +** ^(Some systems (for example, Windows 95) do not support the operation +** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() +** will always return SQLITE_BUSY. The SQLite core only ever uses +** sqlite3_mutex_try() as an optimization so this is acceptable +** behavior.)^ +** +** ^The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. The behavior +** is undefined if the mutex is not currently entered by the +** calling thread or is not currently allocated. +** +** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or +** sqlite3_mutex_leave() is a NULL pointer, then all three routines +** behave as no-ops. +** +** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. +*/ +SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int); +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex*); +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex*); +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex*); +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex*); + +/* +** CAPI3REF: Mutex Methods Object +** +** An instance of this structure defines the low-level routines +** used to allocate and use mutexes. +** +** Usually, the default mutex implementations provided by SQLite are +** sufficient, however the application has the option of substituting a custom +** implementation for specialized deployments or systems for which SQLite +** does not provide a suitable implementation. In this case, the application +** creates and populates an instance of this structure to pass +** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option. +** Additionally, an instance of this structure can be used as an +** output variable when querying the system for the current mutex +** implementation, using the [SQLITE_CONFIG_GETMUTEX] option. +** +** ^The xMutexInit method defined by this structure is invoked as +** part of system initialization by the sqlite3_initialize() function. +** ^The xMutexInit routine is called by SQLite exactly once for each +** effective call to [sqlite3_initialize()]. +** +** ^The xMutexEnd method defined by this structure is invoked as +** part of system shutdown by the sqlite3_shutdown() function. The +** implementation of this method is expected to release all outstanding +** resources obtained by the mutex methods implementation, especially +** those obtained by the xMutexInit method. ^The xMutexEnd() +** interface is invoked exactly once for each call to [sqlite3_shutdown()]. +** +** ^(The remaining seven methods defined by this structure (xMutexAlloc, +** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and +** xMutexNotheld) implement the following interfaces (respectively): +** +**
    +**
  • [sqlite3_mutex_alloc()]
  • +**
  • [sqlite3_mutex_free()]
  • +**
  • [sqlite3_mutex_enter()]
  • +**
  • [sqlite3_mutex_try()]
  • +**
  • [sqlite3_mutex_leave()]
  • +**
  • [sqlite3_mutex_held()]
  • +**
  • [sqlite3_mutex_notheld()]
  • +**
)^ +** +** The only difference is that the public sqlite3_XXX functions enumerated +** above silently ignore any invocations that pass a NULL pointer instead +** of a valid mutex handle. The implementations of the methods defined +** by this structure are not required to handle this case, the results +** of passing a NULL pointer instead of a valid mutex handle are undefined +** (i.e. it is acceptable to provide an implementation that segfaults if +** it is passed a NULL pointer). +** +** The xMutexInit() method must be threadsafe. It must be harmless to +** invoke xMutexInit() multiple times within the same process and without +** intervening calls to xMutexEnd(). Second and subsequent calls to +** xMutexInit() must be no-ops. +** +** xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] +** and its associates). Similarly, xMutexAlloc() must not use SQLite memory +** allocation for a static mutex. ^However xMutexAlloc() may use SQLite +** memory allocation for a fast or recursive mutex. +** +** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is +** called, but only if the prior call to xMutexInit returned SQLITE_OK. +** If xMutexInit fails in any way, it is expected to clean up after itself +** prior to returning. +*/ +typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; +struct sqlite3_mutex_methods { + int (*xMutexInit)(void); + int (*xMutexEnd)(void); + sqlite3_mutex *(*xMutexAlloc)(int); + void (*xMutexFree)(sqlite3_mutex *); + void (*xMutexEnter)(sqlite3_mutex *); + int (*xMutexTry)(sqlite3_mutex *); + void (*xMutexLeave)(sqlite3_mutex *); + int (*xMutexHeld)(sqlite3_mutex *); + int (*xMutexNotheld)(sqlite3_mutex *); +}; + +/* +** CAPI3REF: Mutex Verification Routines +** +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines +** are intended for use inside assert() statements. The SQLite core +** never uses these routines except inside an assert() and applications +** are advised to follow the lead of the core. The SQLite core only +** provides implementations for these routines when it is compiled +** with the SQLITE_DEBUG flag. External mutex implementations +** are only required to provide these routines if SQLITE_DEBUG is +** defined and if NDEBUG is not defined. +** +** These routines should return true if the mutex in their argument +** is held or not held, respectively, by the calling thread. +** +** The implementation is not required to provide versions of these +** routines that actually work. If the implementation does not provide working +** versions of these routines, it should at least provide stubs that always +** return true so that one does not get spurious assertion failures. +** +** If the argument to sqlite3_mutex_held() is a NULL pointer then +** the routine should return 1. This seems counter-intuitive since +** clearly the mutex cannot be held if it does not exist. But +** the reason the mutex does not exist is because the build is not +** using mutexes. And we do not want the assert() containing the +** call to sqlite3_mutex_held() to fail, so a non-zero return is +** the appropriate thing to do. The sqlite3_mutex_notheld() +** interface should also return 1 when given a NULL pointer. +*/ +#ifndef NDEBUG +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex*); +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*); +#endif + +/* +** CAPI3REF: Mutex Types +** +** The [sqlite3_mutex_alloc()] interface takes a single argument +** which is one of these integer constants. +** +** The set of static mutexes may change from one SQLite release to the +** next. Applications that override the built-in mutex logic must be +** prepared to accommodate additional static mutexes. +*/ +#define SQLITE_MUTEX_FAST 0 +#define SQLITE_MUTEX_RECURSIVE 1 +#define SQLITE_MUTEX_STATIC_MASTER 2 +#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ +#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */ +#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */ +#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ +#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ +#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */ +#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */ +#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */ +#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */ +#define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */ +#define SQLITE_MUTEX_STATIC_VFS1 11 /* For use by built-in VFS */ +#define SQLITE_MUTEX_STATIC_VFS2 12 /* For use by extension VFS */ +#define SQLITE_MUTEX_STATIC_VFS3 13 /* For use by application VFS */ + +/* +** CAPI3REF: Retrieve the mutex for a database connection +** METHOD: sqlite3 +** +** ^This interface returns a pointer the [sqlite3_mutex] object that +** serializes access to the [database connection] given in the argument +** when the [threading mode] is Serialized. +** ^If the [threading mode] is Single-thread or Multi-thread then this +** routine returns a NULL pointer. +*/ +SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*); + +/* +** CAPI3REF: Low-Level Control Of Database Files +** METHOD: sqlite3 +** +** ^The [sqlite3_file_control()] interface makes a direct call to the +** xFileControl method for the [sqlite3_io_methods] object associated +** with a particular database identified by the second argument. ^The +** name of the database is "main" for the main database or "temp" for the +** TEMP database, or the name that appears after the AS keyword for +** databases that are added using the [ATTACH] SQL command. +** ^A NULL pointer can be used in place of "main" to refer to the +** main database file. +** ^The third and fourth parameters to this routine +** are passed directly through to the second and third parameters of +** the xFileControl method. ^The return value of the xFileControl +** method becomes the return value of this routine. +** +** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes +** a pointer to the underlying [sqlite3_file] object to be written into +** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER +** case is a short-circuit path which does not actually invoke the +** underlying sqlite3_io_methods.xFileControl method. +** +** ^If the second parameter (zDbName) does not match the name of any +** open database file, then SQLITE_ERROR is returned. ^This error +** code is not remembered and will not be recalled by [sqlite3_errcode()] +** or [sqlite3_errmsg()]. The underlying xFileControl method might +** also return SQLITE_ERROR. There is no way to distinguish between +** an incorrect zDbName and an SQLITE_ERROR return from the underlying +** xFileControl method. +** +** See also: [SQLITE_FCNTL_LOCKSTATE] +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); + +/* +** CAPI3REF: Testing Interface +** +** ^The sqlite3_test_control() interface is used to read out internal +** state of SQLite and to inject faults into SQLite for testing +** purposes. ^The first parameter is an operation code that determines +** the number, meaning, and operation of all subsequent parameters. +** +** This interface is not for use by applications. It exists solely +** for verifying the correct operation of the SQLite library. Depending +** on how the SQLite library is compiled, this interface might not exist. +** +** The details of the operation codes, their meanings, the parameters +** they take, and what they do are all subject to change without notice. +** Unlike most of the SQLite API, this function is not guaranteed to +** operate consistently from one release to the next. +*/ +SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...); + +/* +** CAPI3REF: Testing Interface Operation Codes +** +** These constants are the valid operation code parameters used +** as the first argument to [sqlite3_test_control()]. +** +** These parameters and their meanings are subject to change +** without notice. These values are for testing purposes only. +** Applications should not use any of these parameters or the +** [sqlite3_test_control()] interface. +*/ +#define SQLITE_TESTCTRL_FIRST 5 +#define SQLITE_TESTCTRL_PRNG_SAVE 5 +#define SQLITE_TESTCTRL_PRNG_RESTORE 6 +#define SQLITE_TESTCTRL_PRNG_RESET 7 +#define SQLITE_TESTCTRL_BITVEC_TEST 8 +#define SQLITE_TESTCTRL_FAULT_INSTALL 9 +#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 +#define SQLITE_TESTCTRL_PENDING_BYTE 11 +#define SQLITE_TESTCTRL_ASSERT 12 +#define SQLITE_TESTCTRL_ALWAYS 13 +#define SQLITE_TESTCTRL_RESERVE 14 +#define SQLITE_TESTCTRL_OPTIMIZATIONS 15 +#define SQLITE_TESTCTRL_ISKEYWORD 16 +#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 +#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 +#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ +#define SQLITE_TESTCTRL_NEVER_CORRUPT 20 +#define SQLITE_TESTCTRL_VDBE_COVERAGE 21 +#define SQLITE_TESTCTRL_BYTEORDER 22 +#define SQLITE_TESTCTRL_ISINIT 23 +#define SQLITE_TESTCTRL_SORTER_MMAP 24 +#define SQLITE_TESTCTRL_IMPOSTER 25 +#define SQLITE_TESTCTRL_LAST 25 + +/* +** CAPI3REF: SQLite Runtime Status +** +** ^These interfaces are used to retrieve runtime status information +** about the performance of SQLite, and optionally to reset various +** highwater marks. ^The first argument is an integer code for +** the specific parameter to measure. ^(Recognized integer codes +** are of the form [status parameters | SQLITE_STATUS_...].)^ +** ^The current value of the parameter is returned into *pCurrent. +** ^The highest recorded value is returned in *pHighwater. ^If the +** resetFlag is true, then the highest record value is reset after +** *pHighwater is written. ^(Some parameters do not record the highest +** value. For those parameters +** nothing is written into *pHighwater and the resetFlag is ignored.)^ +** ^(Other parameters record only the highwater mark and not the current +** value. For these latter parameters nothing is written into *pCurrent.)^ +** +** ^The sqlite3_status() and sqlite3_status64() routines return +** SQLITE_OK on success and a non-zero [error code] on failure. +** +** If either the current value or the highwater mark is too large to +** be represented by a 32-bit integer, then the values returned by +** sqlite3_status() are undefined. +** +** See also: [sqlite3_db_status()] +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); +SQLITE_API int SQLITE_STDCALL sqlite3_status64( + int op, + sqlite3_int64 *pCurrent, + sqlite3_int64 *pHighwater, + int resetFlag +); + + +/* +** CAPI3REF: Status Parameters +** KEYWORDS: {status parameters} +** +** These integer constants designate various run-time status parameters +** that can be returned by [sqlite3_status()]. +** +**
+** [[SQLITE_STATUS_MEMORY_USED]] ^(
SQLITE_STATUS_MEMORY_USED
+**
This parameter is the current amount of memory checked out +** using [sqlite3_malloc()], either directly or indirectly. The +** figure includes calls made to [sqlite3_malloc()] by the application +** and internal memory usage by the SQLite library. Scratch memory +** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache +** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in +** this parameter. The amount returned is the sum of the allocation +** sizes as reported by the xSize method in [sqlite3_mem_methods].
)^ +** +** [[SQLITE_STATUS_MALLOC_SIZE]] ^(
SQLITE_STATUS_MALLOC_SIZE
+**
This parameter records the largest memory allocation request +** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their +** internal equivalents). Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
)^ +** +** [[SQLITE_STATUS_MALLOC_COUNT]] ^(
SQLITE_STATUS_MALLOC_COUNT
+**
This parameter records the number of separate memory allocations +** currently checked out.
)^ +** +** [[SQLITE_STATUS_PAGECACHE_USED]] ^(
SQLITE_STATUS_PAGECACHE_USED
+**
This parameter returns the number of pages used out of the +** [pagecache memory allocator] that was configured using +** [SQLITE_CONFIG_PAGECACHE]. The +** value returned is in pages, not in bytes.
)^ +** +** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] +** ^(
SQLITE_STATUS_PAGECACHE_OVERFLOW
+**
This parameter returns the number of bytes of page cache +** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] +** buffer and where forced to overflow to [sqlite3_malloc()]. The +** returned value includes allocations that overflowed because they +** where too large (they were larger than the "sz" parameter to +** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because +** no space was left in the page cache.
)^ +** +** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(
SQLITE_STATUS_PAGECACHE_SIZE
+**
This parameter records the largest memory allocation request +** handed to [pagecache memory allocator]. Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
)^ +** +** [[SQLITE_STATUS_SCRATCH_USED]] ^(
SQLITE_STATUS_SCRATCH_USED
+**
This parameter returns the number of allocations used out of the +** [scratch memory allocator] configured using +** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not +** in bytes. Since a single thread may only have one scratch allocation +** outstanding at time, this parameter also reports the number of threads +** using scratch memory at the same time.
)^ +** +** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(
SQLITE_STATUS_SCRATCH_OVERFLOW
+**
This parameter returns the number of bytes of scratch memory +** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH] +** buffer and where forced to overflow to [sqlite3_malloc()]. The values +** returned include overflows because the requested allocation was too +** larger (that is, because the requested allocation was larger than the +** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer +** slots were available. +**
)^ +** +** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(
SQLITE_STATUS_SCRATCH_SIZE
+**
This parameter records the largest memory allocation request +** handed to [scratch memory allocator]. Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
)^ +** +** [[SQLITE_STATUS_PARSER_STACK]] ^(
SQLITE_STATUS_PARSER_STACK
+**
This parameter records the deepest parser stack. It is only +** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
)^ +**
+** +** New status parameters may be added from time to time. +*/ +#define SQLITE_STATUS_MEMORY_USED 0 +#define SQLITE_STATUS_PAGECACHE_USED 1 +#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 +#define SQLITE_STATUS_SCRATCH_USED 3 +#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 +#define SQLITE_STATUS_MALLOC_SIZE 5 +#define SQLITE_STATUS_PARSER_STACK 6 +#define SQLITE_STATUS_PAGECACHE_SIZE 7 +#define SQLITE_STATUS_SCRATCH_SIZE 8 +#define SQLITE_STATUS_MALLOC_COUNT 9 + +/* +** CAPI3REF: Database Connection Status +** METHOD: sqlite3 +** +** ^This interface is used to retrieve runtime status information +** about a single [database connection]. ^The first argument is the +** database connection object to be interrogated. ^The second argument +** is an integer constant, taken from the set of +** [SQLITE_DBSTATUS options], that +** determines the parameter to interrogate. The set of +** [SQLITE_DBSTATUS options] is likely +** to grow in future releases of SQLite. +** +** ^The current value of the requested parameter is written into *pCur +** and the highest instantaneous value is written into *pHiwtr. ^If +** the resetFlg is true, then the highest instantaneous value is +** reset back down to the current value. +** +** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a +** non-zero [error code] on failure. +** +** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); + +/* +** CAPI3REF: Status Parameters for database connections +** KEYWORDS: {SQLITE_DBSTATUS options} +** +** These constants are the available integer "verbs" that can be passed as +** the second argument to the [sqlite3_db_status()] interface. +** +** New verbs may be added in future releases of SQLite. Existing verbs +** might be discontinued. Applications should check the return code from +** [sqlite3_db_status()] to make sure that the call worked. +** The [sqlite3_db_status()] interface will return a non-zero error code +** if a discontinued or unsupported verb is invoked. +** +**
+** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(
SQLITE_DBSTATUS_LOOKASIDE_USED
+**
This parameter returns the number of lookaside memory slots currently +** checked out.
)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(
SQLITE_DBSTATUS_LOOKASIDE_HIT
+**
This parameter returns the number malloc attempts that were +** satisfied using lookaside memory. Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]] +** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
+**
This parameter returns the number malloc attempts that might have +** been satisfied using lookaside memory but failed due to the amount of +** memory requested being larger than the lookaside slot size. +** Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]] +** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
+**
This parameter returns the number malloc attempts that might have +** been satisfied using lookaside memory but failed due to all lookaside +** memory already being in use. +** Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_CACHE_USED]] ^(
SQLITE_DBSTATUS_CACHE_USED
+**
This parameter returns the approximate number of bytes of heap +** memory used by all pager caches associated with the database connection.)^ +** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. +** +** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(
SQLITE_DBSTATUS_SCHEMA_USED
+**
This parameter returns the approximate number of bytes of heap +** memory used to store the schema for all databases associated +** with the connection - main, temp, and any [ATTACH]-ed databases.)^ +** ^The full amount of memory used by the schemas is reported, even if the +** schema memory is shared with other database connections due to +** [shared cache mode] being enabled. +** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0. +** +** [[SQLITE_DBSTATUS_STMT_USED]] ^(
SQLITE_DBSTATUS_STMT_USED
+**
This parameter returns the approximate number of bytes of heap +** and lookaside memory used by all prepared statements associated with +** the database connection.)^ +** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. +**
+** +** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(
SQLITE_DBSTATUS_CACHE_HIT
+**
This parameter returns the number of pager cache hits that have +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT +** is always 0. +**
+** +** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(
SQLITE_DBSTATUS_CACHE_MISS
+**
This parameter returns the number of pager cache misses that have +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS +** is always 0. +**
+** +** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(
SQLITE_DBSTATUS_CACHE_WRITE
+**
This parameter returns the number of dirty cache entries that have +** been written to disk. Specifically, the number of pages written to the +** wal file in wal mode databases, or the number of pages written to the +** database file in rollback mode databases. Any pages written as part of +** transaction rollback or database recovery operations are not included. +** If an IO or other error occurs while writing a page to disk, the effect +** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The +** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. +**
+** +** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(
SQLITE_DBSTATUS_DEFERRED_FKS
+**
This parameter returns zero for the current value if and only if +** all foreign key constraints (deferred or immediate) have been +** resolved.)^ ^The highwater mark is always 0. +**
+**
+*/ +#define SQLITE_DBSTATUS_LOOKASIDE_USED 0 +#define SQLITE_DBSTATUS_CACHE_USED 1 +#define SQLITE_DBSTATUS_SCHEMA_USED 2 +#define SQLITE_DBSTATUS_STMT_USED 3 +#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 +#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 +#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 +#define SQLITE_DBSTATUS_CACHE_HIT 7 +#define SQLITE_DBSTATUS_CACHE_MISS 8 +#define SQLITE_DBSTATUS_CACHE_WRITE 9 +#define SQLITE_DBSTATUS_DEFERRED_FKS 10 +#define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */ + + +/* +** CAPI3REF: Prepared Statement Status +** METHOD: sqlite3_stmt +** +** ^(Each prepared statement maintains various +** [SQLITE_STMTSTATUS counters] that measure the number +** of times it has performed specific operations.)^ These counters can +** be used to monitor the performance characteristics of the prepared +** statements. For example, if the number of table steps greatly exceeds +** the number of table searches or result rows, that would tend to indicate +** that the prepared statement is using a full table scan rather than +** an index. +** +** ^(This interface is used to retrieve and reset counter values from +** a [prepared statement]. The first argument is the prepared statement +** object to be interrogated. The second argument +** is an integer code for a specific [SQLITE_STMTSTATUS counter] +** to be interrogated.)^ +** ^The current value of the requested counter is returned. +** ^If the resetFlg is true, then the counter is reset to zero after this +** interface call returns. +** +** See also: [sqlite3_status()] and [sqlite3_db_status()]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); + +/* +** CAPI3REF: Status Parameters for prepared statements +** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters} +** +** These preprocessor macros define integer codes that name counter +** values associated with the [sqlite3_stmt_status()] interface. +** The meanings of the various counters are as follows: +** +**
+** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]]
SQLITE_STMTSTATUS_FULLSCAN_STEP
+**
^This is the number of times that SQLite has stepped forward in +** a table as part of a full table scan. Large numbers for this counter +** may indicate opportunities for performance improvement through +** careful use of indices.
+** +** [[SQLITE_STMTSTATUS_SORT]]
SQLITE_STMTSTATUS_SORT
+**
^This is the number of sort operations that have occurred. +** A non-zero value in this counter may indicate an opportunity to +** improvement performance through careful use of indices.
+** +** [[SQLITE_STMTSTATUS_AUTOINDEX]]
SQLITE_STMTSTATUS_AUTOINDEX
+**
^This is the number of rows inserted into transient indices that +** were created automatically in order to help joins run faster. +** A non-zero value in this counter may indicate an opportunity to +** improvement performance by adding permanent indices that do not +** need to be reinitialized each time the statement is run.
+** +** [[SQLITE_STMTSTATUS_VM_STEP]]
SQLITE_STMTSTATUS_VM_STEP
+**
^This is the number of virtual machine operations executed +** by the prepared statement if that number is less than or equal +** to 2147483647. The number of virtual machine operations can be +** used as a proxy for the total work done by the prepared statement. +** If the number of virtual machine operations exceeds 2147483647 +** then the value returned by this statement status code is undefined. +**
+**
+*/ +#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 +#define SQLITE_STMTSTATUS_SORT 2 +#define SQLITE_STMTSTATUS_AUTOINDEX 3 +#define SQLITE_STMTSTATUS_VM_STEP 4 + +/* +** CAPI3REF: Custom Page Cache Object +** +** The sqlite3_pcache type is opaque. It is implemented by +** the pluggable module. The SQLite core has no knowledge of +** its size or internal structure and never deals with the +** sqlite3_pcache object except by holding and passing pointers +** to the object. +** +** See [sqlite3_pcache_methods2] for additional information. +*/ +typedef struct sqlite3_pcache sqlite3_pcache; + +/* +** CAPI3REF: Custom Page Cache Object +** +** The sqlite3_pcache_page object represents a single page in the +** page cache. The page cache will allocate instances of this +** object. Various methods of the page cache use pointers to instances +** of this object as parameters or as their return value. +** +** See [sqlite3_pcache_methods2] for additional information. +*/ +typedef struct sqlite3_pcache_page sqlite3_pcache_page; +struct sqlite3_pcache_page { + void *pBuf; /* The content of the page */ + void *pExtra; /* Extra information associated with the page */ +}; + +/* +** CAPI3REF: Application Defined Page Cache. +** KEYWORDS: {page cache} +** +** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can +** register an alternative page cache implementation by passing in an +** instance of the sqlite3_pcache_methods2 structure.)^ +** In many applications, most of the heap memory allocated by +** SQLite is used for the page cache. +** By implementing a +** custom page cache using this API, an application can better control +** the amount of memory consumed by SQLite, the way in which +** that memory is allocated and released, and the policies used to +** determine exactly which parts of a database file are cached and for +** how long. +** +** The alternative page cache mechanism is an +** extreme measure that is only needed by the most demanding applications. +** The built-in page cache is recommended for most uses. +** +** ^(The contents of the sqlite3_pcache_methods2 structure are copied to an +** internal buffer by SQLite within the call to [sqlite3_config]. Hence +** the application may discard the parameter after the call to +** [sqlite3_config()] returns.)^ +** +** [[the xInit() page cache method]] +** ^(The xInit() method is called once for each effective +** call to [sqlite3_initialize()])^ +** (usually only once during the lifetime of the process). ^(The xInit() +** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^ +** The intent of the xInit() method is to set up global data structures +** required by the custom page cache implementation. +** ^(If the xInit() method is NULL, then the +** built-in default page cache is used instead of the application defined +** page cache.)^ +** +** [[the xShutdown() page cache method]] +** ^The xShutdown() method is called by [sqlite3_shutdown()]. +** It can be used to clean up +** any outstanding resources before process shutdown, if required. +** ^The xShutdown() method may be NULL. +** +** ^SQLite automatically serializes calls to the xInit method, +** so the xInit method need not be threadsafe. ^The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. All other methods must be threadsafe +** in multithreaded applications. +** +** ^SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). +** +** [[the xCreate() page cache methods]] +** ^SQLite invokes the xCreate() method to construct a new cache instance. +** SQLite will typically create one cache instance for each open database file, +** though this is not guaranteed. ^The +** first parameter, szPage, is the size in bytes of the pages that must +** be allocated by the cache. ^szPage will always a power of two. ^The +** second parameter szExtra is a number of bytes of extra storage +** associated with each page cache entry. ^The szExtra parameter will +** a number less than 250. SQLite will use the +** extra szExtra bytes on each page to store metadata about the underlying +** database page on disk. The value passed into szExtra depends +** on the SQLite version, the target platform, and how SQLite was compiled. +** ^The third argument to xCreate(), bPurgeable, is true if the cache being +** created will be used to cache database pages of a file stored on disk, or +** false if it is used for an in-memory database. The cache implementation +** does not have to do anything special based with the value of bPurgeable; +** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will +** never invoke xUnpin() except to deliberately delete a page. +** ^In other words, calls to xUnpin() on a cache with bPurgeable set to +** false will always have the "discard" flag set to true. +** ^Hence, a cache created with bPurgeable false will +** never contain any unpinned pages. +** +** [[the xCachesize() page cache method]] +** ^(The xCachesize() method may be called at any time by SQLite to set the +** suggested maximum cache-size (number of pages stored by) the cache +** instance passed as the first argument. This is the value configured using +** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable +** parameter, the implementation is not required to do anything with this +** value; it is advisory only. +** +** [[the xPagecount() page cache methods]] +** The xPagecount() method must return the number of pages currently +** stored in the cache, both pinned and unpinned. +** +** [[the xFetch() page cache methods]] +** The xFetch() method locates a page in the cache and returns a pointer to +** an sqlite3_pcache_page object associated with that page, or a NULL pointer. +** The pBuf element of the returned sqlite3_pcache_page object will be a +** pointer to a buffer of szPage bytes used to store the content of a +** single database page. The pExtra element of sqlite3_pcache_page will be +** a pointer to the szExtra bytes of extra storage that SQLite has requested +** for each entry in the page cache. +** +** The page to be fetched is determined by the key. ^The minimum key value +** is 1. After it has been retrieved using xFetch, the page is considered +** to be "pinned". +** +** If the requested page is already in the page cache, then the page cache +** implementation must return a pointer to the page buffer with its content +** intact. If the requested page is not already in the cache, then the +** cache implementation should use the value of the createFlag +** parameter to help it determined what action to take: +** +** +**
createFlag Behavior when page is not already in cache +**
0 Do not allocate a new page. Return NULL. +**
1 Allocate a new page if it easy and convenient to do so. +** Otherwise return NULL. +**
2 Make every effort to allocate a new page. Only return +** NULL if allocating a new page is effectively impossible. +**
+** +** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite +** will only use a createFlag of 2 after a prior call with a createFlag of 1 +** failed.)^ In between the to xFetch() calls, SQLite may +** attempt to unpin one or more cache pages by spilling the content of +** pinned pages to disk and synching the operating system disk cache. +** +** [[the xUnpin() page cache method]] +** ^xUnpin() is called by SQLite with a pointer to a currently pinned page +** as its second argument. If the third parameter, discard, is non-zero, +** then the page must be evicted from the cache. +** ^If the discard parameter is +** zero, then the page may be discarded or retained at the discretion of +** page cache implementation. ^The page cache implementation +** may choose to evict unpinned pages at any time. +** +** The cache must not perform any reference counting. A single +** call to xUnpin() unpins the page regardless of the number of prior calls +** to xFetch(). +** +** [[the xRekey() page cache methods]] +** The xRekey() method is used to change the key value associated with the +** page passed as the second argument. If the cache +** previously contains an entry associated with newKey, it must be +** discarded. ^Any prior cache entry associated with newKey is guaranteed not +** to be pinned. +** +** When SQLite calls the xTruncate() method, the cache must discard all +** existing cache entries with page numbers (keys) greater than or equal +** to the value of the iLimit parameter passed to xTruncate(). If any +** of these pages are pinned, they are implicitly unpinned, meaning that +** they can be safely discarded. +** +** [[the xDestroy() page cache method]] +** ^The xDestroy() method is used to delete a cache allocated by xCreate(). +** All resources associated with the specified cache should be freed. ^After +** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*] +** handle invalid, and will not use it with any other sqlite3_pcache_methods2 +** functions. +** +** [[the xShrink() page cache method]] +** ^SQLite invokes the xShrink() method when it wants the page cache to +** free up as much of heap memory as possible. The page cache implementation +** is not obligated to free any memory, but well-behaved implementations should +** do their best. +*/ +typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2; +struct sqlite3_pcache_methods2 { + int iVersion; + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard); + void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, + unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); + void (*xShrink)(sqlite3_pcache*); +}; + +/* +** This is the obsolete pcache_methods object that has now been replaced +** by sqlite3_pcache_methods2. This object is not used by SQLite. It is +** retained in the header file for backwards compatibility only. +*/ +typedef struct sqlite3_pcache_methods sqlite3_pcache_methods; +struct sqlite3_pcache_methods { + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, void*, int discard); + void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); +}; + + +/* +** CAPI3REF: Online Backup Object +** +** The sqlite3_backup object records state information about an ongoing +** online backup operation. ^The sqlite3_backup object is created by +** a call to [sqlite3_backup_init()] and is destroyed by a call to +** [sqlite3_backup_finish()]. +** +** See Also: [Using the SQLite Online Backup API] +*/ +typedef struct sqlite3_backup sqlite3_backup; + +/* +** CAPI3REF: Online Backup API. +** +** The backup API copies the content of one database into another. +** It is useful either for creating backups of databases or +** for copying in-memory databases to or from persistent files. +** +** See Also: [Using the SQLite Online Backup API] +** +** ^SQLite holds a write transaction open on the destination database file +** for the duration of the backup operation. +** ^The source database is read-locked only while it is being read; +** it is not locked continuously for the entire backup operation. +** ^Thus, the backup may be performed on a live source database without +** preventing other database connections from +** reading or writing to the source database while the backup is underway. +** +** ^(To perform a backup operation: +**
    +**
  1. sqlite3_backup_init() is called once to initialize the +** backup, +**
  2. sqlite3_backup_step() is called one or more times to transfer +** the data between the two databases, and finally +**
  3. sqlite3_backup_finish() is called to release all resources +** associated with the backup operation. +**
)^ +** There should be exactly one call to sqlite3_backup_finish() for each +** successful call to sqlite3_backup_init(). +** +** [[sqlite3_backup_init()]] sqlite3_backup_init() +** +** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the +** [database connection] associated with the destination database +** and the database name, respectively. +** ^The database name is "main" for the main database, "temp" for the +** temporary database, or the name specified after the AS keyword in +** an [ATTACH] statement for an attached database. +** ^The S and M arguments passed to +** sqlite3_backup_init(D,N,S,M) identify the [database connection] +** and database name of the source database, respectively. +** ^The source and destination [database connections] (parameters S and D) +** must be different or else sqlite3_backup_init(D,N,S,M) will fail with +** an error. +** +** ^A call to sqlite3_backup_init() will fail, returning SQLITE_ERROR, if +** there is already a read or read-write transaction open on the +** destination database. +** +** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is +** returned and an error code and error message are stored in the +** destination [database connection] D. +** ^The error code and message for the failed call to sqlite3_backup_init() +** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or +** [sqlite3_errmsg16()] functions. +** ^A successful call to sqlite3_backup_init() returns a pointer to an +** [sqlite3_backup] object. +** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and +** sqlite3_backup_finish() functions to perform the specified backup +** operation. +** +** [[sqlite3_backup_step()]] sqlite3_backup_step() +** +** ^Function sqlite3_backup_step(B,N) will copy up to N pages between +** the source and destination databases specified by [sqlite3_backup] object B. +** ^If N is negative, all remaining source pages are copied. +** ^If sqlite3_backup_step(B,N) successfully copies N pages and there +** are still more pages to be copied, then the function returns [SQLITE_OK]. +** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages +** from source to destination, then it returns [SQLITE_DONE]. +** ^If an error occurs while running sqlite3_backup_step(B,N), +** then an [error code] is returned. ^As well as [SQLITE_OK] and +** [SQLITE_DONE], a call to sqlite3_backup_step() may return [SQLITE_READONLY], +** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an +** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code. +** +** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if +**
    +**
  1. the destination database was opened read-only, or +**
  2. the destination database is using write-ahead-log journaling +** and the destination and source page sizes differ, or +**
  3. the destination database is an in-memory database and the +** destination and source page sizes differ. +**
)^ +** +** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then +** the [sqlite3_busy_handler | busy-handler function] +** is invoked (if one is specified). ^If the +** busy-handler returns non-zero before the lock is available, then +** [SQLITE_BUSY] is returned to the caller. ^In this case the call to +** sqlite3_backup_step() can be retried later. ^If the source +** [database connection] +** is being used to write to the source database when sqlite3_backup_step() +** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this +** case the call to sqlite3_backup_step() can be retried later on. ^(If +** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or +** [SQLITE_READONLY] is returned, then +** there is no point in retrying the call to sqlite3_backup_step(). These +** errors are considered fatal.)^ The application must accept +** that the backup operation has failed and pass the backup operation handle +** to the sqlite3_backup_finish() to release associated resources. +** +** ^The first call to sqlite3_backup_step() obtains an exclusive lock +** on the destination file. ^The exclusive lock is not released until either +** sqlite3_backup_finish() is called or the backup operation is complete +** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to +** sqlite3_backup_step() obtains a [shared lock] on the source database that +** lasts for the duration of the sqlite3_backup_step() call. +** ^Because the source database is not locked between calls to +** sqlite3_backup_step(), the source database may be modified mid-way +** through the backup process. ^If the source database is modified by an +** external process or via a database connection other than the one being +** used by the backup operation, then the backup will be automatically +** restarted by the next call to sqlite3_backup_step(). ^If the source +** database is modified by the using the same database connection as is used +** by the backup operation, then the backup database is automatically +** updated at the same time. +** +** [[sqlite3_backup_finish()]] sqlite3_backup_finish() +** +** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the +** application wishes to abandon the backup operation, the application +** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish(). +** ^The sqlite3_backup_finish() interfaces releases all +** resources associated with the [sqlite3_backup] object. +** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any +** active write-transaction on the destination database is rolled back. +** The [sqlite3_backup] object is invalid +** and may not be used following a call to sqlite3_backup_finish(). +** +** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no +** sqlite3_backup_step() errors occurred, regardless or whether or not +** sqlite3_backup_step() completed. +** ^If an out-of-memory condition or IO error occurred during any prior +** sqlite3_backup_step() call on the same [sqlite3_backup] object, then +** sqlite3_backup_finish() returns the corresponding [error code]. +** +** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step() +** is not a permanent error and does not affect the return value of +** sqlite3_backup_finish(). +** +** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]] +** sqlite3_backup_remaining() and sqlite3_backup_pagecount() +** +** ^The sqlite3_backup_remaining() routine returns the number of pages still +** to be backed up at the conclusion of the most recent sqlite3_backup_step(). +** ^The sqlite3_backup_pagecount() routine returns the total number of pages +** in the source database at the conclusion of the most recent +** sqlite3_backup_step(). +** ^(The values returned by these functions are only updated by +** sqlite3_backup_step(). If the source database is modified in a way that +** changes the size of the source database or the number of pages remaining, +** those changes are not reflected in the output of sqlite3_backup_pagecount() +** and sqlite3_backup_remaining() until after the next +** sqlite3_backup_step().)^ +** +** Concurrent Usage of Database Handles +** +** ^The source [database connection] may be used by the application for other +** purposes while a backup operation is underway or being initialized. +** ^If SQLite is compiled and configured to support threadsafe database +** connections, then the source database connection may be used concurrently +** from within other threads. +** +** However, the application must guarantee that the destination +** [database connection] is not passed to any other API (by any thread) after +** sqlite3_backup_init() is called and before the corresponding call to +** sqlite3_backup_finish(). SQLite does not currently check to see +** if the application incorrectly accesses the destination [database connection] +** and so no error code is reported, but the operations may malfunction +** nevertheless. Use of the destination database connection while a +** backup is in progress might also also cause a mutex deadlock. +** +** If running in [shared cache mode], the application must +** guarantee that the shared cache used by the destination database +** is not accessed while the backup is running. In practice this means +** that the application must guarantee that the disk file being +** backed up to is not accessed by any connection within the process, +** not just the specific connection that was passed to sqlite3_backup_init(). +** +** The [sqlite3_backup] object itself is partially threadsafe. Multiple +** threads may safely make multiple concurrent calls to sqlite3_backup_step(). +** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() +** APIs are not strictly speaking threadsafe. If they are invoked at the +** same time as another thread is invoking sqlite3_backup_step() it is +** possible that they return invalid values. +*/ +SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( + sqlite3 *pDest, /* Destination database handle */ + const char *zDestName, /* Destination database name */ + sqlite3 *pSource, /* Source database handle */ + const char *zSourceName /* Source database name */ +); +SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p); + +/* +** CAPI3REF: Unlock Notification +** METHOD: sqlite3 +** +** ^When running in shared-cache mode, a database operation may fail with +** an [SQLITE_LOCKED] error if the required locks on the shared-cache or +** individual tables within the shared-cache cannot be obtained. See +** [SQLite Shared-Cache Mode] for a description of shared-cache locking. +** ^This API may be used to register a callback that SQLite will invoke +** when the connection currently holding the required lock relinquishes it. +** ^This API is only available if the library was compiled with the +** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined. +** +** See Also: [Using the SQLite Unlock Notification Feature]. +** +** ^Shared-cache locks are released when a database connection concludes +** its current transaction, either by committing it or rolling it back. +** +** ^When a connection (known as the blocked connection) fails to obtain a +** shared-cache lock and SQLITE_LOCKED is returned to the caller, the +** identity of the database connection (the blocking connection) that +** has locked the required resource is stored internally. ^After an +** application receives an SQLITE_LOCKED error, it may call the +** sqlite3_unlock_notify() method with the blocked connection handle as +** the first argument to register for a callback that will be invoked +** when the blocking connections current transaction is concluded. ^The +** callback is invoked from within the [sqlite3_step] or [sqlite3_close] +** call that concludes the blocking connections transaction. +** +** ^(If sqlite3_unlock_notify() is called in a multi-threaded application, +** there is a chance that the blocking connection will have already +** concluded its transaction by the time sqlite3_unlock_notify() is invoked. +** If this happens, then the specified callback is invoked immediately, +** from within the call to sqlite3_unlock_notify().)^ +** +** ^If the blocked connection is attempting to obtain a write-lock on a +** shared-cache table, and more than one other connection currently holds +** a read-lock on the same table, then SQLite arbitrarily selects one of +** the other connections to use as the blocking connection. +** +** ^(There may be at most one unlock-notify callback registered by a +** blocked connection. If sqlite3_unlock_notify() is called when the +** blocked connection already has a registered unlock-notify callback, +** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is +** called with a NULL pointer as its second argument, then any existing +** unlock-notify callback is canceled. ^The blocked connections +** unlock-notify callback may also be canceled by closing the blocked +** connection using [sqlite3_close()]. +** +** The unlock-notify callback is not reentrant. If an application invokes +** any sqlite3_xxx API functions from within an unlock-notify callback, a +** crash or deadlock may be the result. +** +** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always +** returns SQLITE_OK. +** +** Callback Invocation Details +** +** When an unlock-notify callback is registered, the application provides a +** single void* pointer that is passed to the callback when it is invoked. +** However, the signature of the callback function allows SQLite to pass +** it an array of void* context pointers. The first argument passed to +** an unlock-notify callback is a pointer to an array of void* pointers, +** and the second is the number of entries in the array. +** +** When a blocking connections transaction is concluded, there may be +** more than one blocked connection that has registered for an unlock-notify +** callback. ^If two or more such blocked connections have specified the +** same callback function, then instead of invoking the callback function +** multiple times, it is invoked once with the set of void* context pointers +** specified by the blocked connections bundled together into an array. +** This gives the application an opportunity to prioritize any actions +** related to the set of unblocked database connections. +** +** Deadlock Detection +** +** Assuming that after registering for an unlock-notify callback a +** database waits for the callback to be issued before taking any further +** action (a reasonable assumption), then using this API may cause the +** application to deadlock. For example, if connection X is waiting for +** connection Y's transaction to be concluded, and similarly connection +** Y is waiting on connection X's transaction, then neither connection +** will proceed and the system may remain deadlocked indefinitely. +** +** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock +** detection. ^If a given call to sqlite3_unlock_notify() would put the +** system in a deadlocked state, then SQLITE_LOCKED is returned and no +** unlock-notify callback is registered. The system is said to be in +** a deadlocked state if connection A has registered for an unlock-notify +** callback on the conclusion of connection B's transaction, and connection +** B has itself registered for an unlock-notify callback when connection +** A's transaction is concluded. ^Indirect deadlock is also detected, so +** the system is also considered to be deadlocked if connection B has +** registered for an unlock-notify callback on the conclusion of connection +** C's transaction, where connection C is waiting on connection A. ^Any +** number of levels of indirection are allowed. +** +** The "DROP TABLE" Exception +** +** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost +** always appropriate to call sqlite3_unlock_notify(). There is however, +** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement, +** SQLite checks if there are any currently executing SELECT statements +** that belong to the same connection. If there are, SQLITE_LOCKED is +** returned. In this case there is no "blocking connection", so invoking +** sqlite3_unlock_notify() results in the unlock-notify callback being +** invoked immediately. If the application then re-attempts the "DROP TABLE" +** or "DROP INDEX" query, an infinite loop might be the result. +** +** One way around this problem is to check the extended error code returned +** by an sqlite3_step() call. ^(If there is a blocking connection, then the +** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in +** the special "DROP TABLE/INDEX" case, the extended error code is just +** SQLITE_LOCKED.)^ +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( + sqlite3 *pBlocked, /* Waiting connection */ + void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ + void *pNotifyArg /* Argument to pass to xNotify */ +); + + +/* +** CAPI3REF: String Comparison +** +** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications +** and extensions to compare the contents of two buffers containing UTF-8 +** strings in a case-independent fashion, using the same definition of "case +** independence" that SQLite uses internally when comparing identifiers. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *, const char *); +SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int); + +/* +** CAPI3REF: String Globbing +* +** ^The [sqlite3_strglob(P,X)] interface returns zero if string X matches +** the glob pattern P, and it returns non-zero if string X does not match +** the glob pattern P. ^The definition of glob pattern matching used in +** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the +** SQL dialect used by SQLite. ^The sqlite3_strglob(P,X) function is case +** sensitive. +** +** Note that this routine returns zero on a match and non-zero if the strings +** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zStr); + +/* +** CAPI3REF: Error Logging Interface +** +** ^The [sqlite3_log()] interface writes a message into the [error log] +** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. +** ^If logging is enabled, the zFormat string and subsequent arguments are +** used with [sqlite3_snprintf()] to generate the final output string. +** +** The sqlite3_log() interface is intended for use by extensions such as +** virtual tables, collating functions, and SQL functions. While there is +** nothing to prevent an application from calling sqlite3_log(), doing so +** is considered bad form. +** +** The zFormat string must not be NULL. +** +** To avoid deadlocks and other threading problems, the sqlite3_log() routine +** will not use dynamically allocated memory. The log message is stored in +** a fixed-length buffer on the stack. If the log message is longer than +** a few hundred characters, it will be truncated to the length of the +** buffer. +*/ +SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...); + +/* +** CAPI3REF: Write-Ahead Log Commit Hook +** METHOD: sqlite3 +** +** ^The [sqlite3_wal_hook()] function is used to register a callback that +** is invoked each time data is committed to a database in wal mode. +** +** ^(The callback is invoked by SQLite after the commit has taken place and +** the associated write-lock on the database released)^, so the implementation +** may read, write or [checkpoint] the database as required. +** +** ^The first parameter passed to the callback function when it is invoked +** is a copy of the third parameter passed to sqlite3_wal_hook() when +** registering the callback. ^The second is a copy of the database handle. +** ^The third parameter is the name of the database that was written to - +** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter +** is the number of pages currently in the write-ahead log file, +** including those that were just committed. +** +** The callback function should normally return [SQLITE_OK]. ^If an error +** code is returned, that error will propagate back up through the +** SQLite code base to cause the statement that provoked the callback +** to report an error, though the commit will have still occurred. If the +** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value +** that does not correspond to any valid SQLite error code, the results +** are undefined. +** +** A single database handle may have at most a single write-ahead log callback +** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any +** previously registered write-ahead log callback. ^Note that the +** [sqlite3_wal_autocheckpoint()] interface and the +** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will +** those overwrite any prior [sqlite3_wal_hook()] settings. +*/ +SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( + sqlite3*, + int(*)(void *,sqlite3*,const char*,int), + void* +); + +/* +** CAPI3REF: Configure an auto-checkpoint +** METHOD: sqlite3 +** +** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around +** [sqlite3_wal_hook()] that causes any database on [database connection] D +** to automatically [checkpoint] +** after committing a transaction if there are N or +** more frames in the [write-ahead log] file. ^Passing zero or +** a negative value as the nFrame parameter disables automatic +** checkpoints entirely. +** +** ^The callback registered by this function replaces any existing callback +** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback +** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism +** configured by this function. +** +** ^The [wal_autocheckpoint pragma] can be used to invoke this interface +** from SQL. +** +** ^Checkpoints initiated by this mechanism are +** [sqlite3_wal_checkpoint_v2|PASSIVE]. +** +** ^Every new [database connection] defaults to having the auto-checkpoint +** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] +** pages. The use of this interface +** is only necessary if the default setting is found to be suboptimal +** for a particular application. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N); + +/* +** CAPI3REF: Checkpoint a database +** METHOD: sqlite3 +** +** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to +** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ +** +** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the +** [write-ahead log] for database X on [database connection] D to be +** transferred into the database file and for the write-ahead log to +** be reset. See the [checkpointing] documentation for addition +** information. +** +** This interface used to be the only way to cause a checkpoint to +** occur. But then the newer and more powerful [sqlite3_wal_checkpoint_v2()] +** interface was added. This interface is retained for backwards +** compatibility and as a convenience for applications that need to manually +** start a callback but which do not need the full power (and corresponding +** complication) of [sqlite3_wal_checkpoint_v2()]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); + +/* +** CAPI3REF: Checkpoint a database +** METHOD: sqlite3 +** +** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint +** operation on database X of [database connection] D in mode M. Status +** information is written back into integers pointed to by L and C.)^ +** ^(The M parameter must be a valid [checkpoint mode]:)^ +** +**
+**
SQLITE_CHECKPOINT_PASSIVE
+** ^Checkpoint as many frames as possible without waiting for any database +** readers or writers to finish, then sync the database file if all frames +** in the log were checkpointed. ^The [busy-handler callback] +** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. +** ^On the other hand, passive mode might leave the checkpoint unfinished +** if there are concurrent readers or writers. +** +**
SQLITE_CHECKPOINT_FULL
+** ^This mode blocks (it invokes the +** [sqlite3_busy_handler|busy-handler callback]) until there is no +** database writer and all readers are reading from the most recent database +** snapshot. ^It then checkpoints all frames in the log file and syncs the +** database file. ^This mode blocks new database writers while it is pending, +** but new database readers are allowed to continue unimpeded. +** +**
SQLITE_CHECKPOINT_RESTART
+** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition +** that after checkpointing the log file it blocks (calls the +** [busy-handler callback]) +** until all readers are reading from the database file only. ^This ensures +** that the next writer will restart the log file from the beginning. +** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new +** database writer attempts while it is pending, but does not impede readers. +** +**
SQLITE_CHECKPOINT_TRUNCATE
+** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the +** addition that it also truncates the log file to zero bytes just prior +** to a successful return. +**
+** +** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in +** the log file or to -1 if the checkpoint could not run because +** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not +** NULL,then *pnCkpt is set to the total number of checkpointed frames in the +** log file (including any that were already checkpointed before the function +** was called) or to -1 if the checkpoint could not run due to an error or +** because the database is not in WAL mode. ^Note that upon successful +** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been +** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero. +** +** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If +** any other process is running a checkpoint operation at the same time, the +** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a +** busy-handler configured, it will not be invoked in this case. +** +** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the +** exclusive "writer" lock on the database file. ^If the writer lock cannot be +** obtained immediately, and a busy-handler is configured, it is invoked and +** the writer lock retried until either the busy-handler returns 0 or the lock +** is successfully obtained. ^The busy-handler is also invoked while waiting for +** database readers as described above. ^If the busy-handler returns 0 before +** the writer lock is obtained or while waiting for database readers, the +** checkpoint operation proceeds from that point in the same way as +** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible +** without blocking any further. ^SQLITE_BUSY is returned in this case. +** +** ^If parameter zDb is NULL or points to a zero length string, then the +** specified operation is attempted on all WAL databases [attached] to +** [database connection] db. In this case the +** values written to output parameters *pnLog and *pnCkpt are undefined. ^If +** an SQLITE_BUSY error is encountered when processing one or more of the +** attached WAL databases, the operation is still attempted on any remaining +** attached databases and SQLITE_BUSY is returned at the end. ^If any other +** error occurs while processing an attached database, processing is abandoned +** and the error code is returned to the caller immediately. ^If no error +** (SQLITE_BUSY or otherwise) is encountered while processing the attached +** databases, SQLITE_OK is returned. +** +** ^If database zDb is the name of an attached database that is not in WAL +** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If +** zDb is not NULL (or a zero length string) and is not the name of any +** attached database, SQLITE_ERROR is returned to the caller. +** +** ^Unless it returns SQLITE_MISUSE, +** the sqlite3_wal_checkpoint_v2() interface +** sets the error information that is queried by +** [sqlite3_errcode()] and [sqlite3_errmsg()]. +** +** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface +** from SQL. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( + sqlite3 *db, /* Database handle */ + const char *zDb, /* Name of attached database (or NULL) */ + int eMode, /* SQLITE_CHECKPOINT_* value */ + int *pnLog, /* OUT: Size of WAL log in frames */ + int *pnCkpt /* OUT: Total number of frames checkpointed */ +); + +/* +** CAPI3REF: Checkpoint Mode Values +** KEYWORDS: {checkpoint mode} +** +** These constants define all valid values for the "checkpoint mode" passed +** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface. +** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the +** meaning of each of these checkpoint modes. +*/ +#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ +#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ +#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */ +#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */ + +/* +** CAPI3REF: Virtual Table Interface Configuration +** +** This function may be called by either the [xConnect] or [xCreate] method +** of a [virtual table] implementation to configure +** various facets of the virtual table interface. +** +** If this interface is invoked outside the context of an xConnect or +** xCreate virtual table method then the behavior is undefined. +** +** At present, there is only one option that may be configured using +** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options +** may be added in the future. +*/ +SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...); + +/* +** CAPI3REF: Virtual Table Configuration Options +** +** These macros define the various options to the +** [sqlite3_vtab_config()] interface that [virtual table] implementations +** can use to customize and optimize their behavior. +** +**
+**
SQLITE_VTAB_CONSTRAINT_SUPPORT +**
Calls of the form +** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, +** where X is an integer. If X is zero, then the [virtual table] whose +** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not +** support constraints. In this configuration (which is the default) if +** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire +** statement is rolled back as if [ON CONFLICT | OR ABORT] had been +** specified as part of the users SQL statement, regardless of the actual +** ON CONFLICT mode specified. +** +** If X is non-zero, then the virtual table implementation guarantees +** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before +** any modifications to internal or persistent data structures have been made. +** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite +** is able to roll back a statement or database transaction, and abandon +** or continue processing the current SQL statement as appropriate. +** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns +** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode +** had been ABORT. +** +** Virtual table implementations that are required to handle OR REPLACE +** must do so within the [xUpdate] method. If a call to the +** [sqlite3_vtab_on_conflict()] function indicates that the current ON +** CONFLICT policy is REPLACE, the virtual table implementation should +** silently replace the appropriate rows within the xUpdate callback and +** return SQLITE_OK. Or, if this is not possible, it may return +** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT +** constraint handling. +**
+*/ +#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 + +/* +** CAPI3REF: Determine The Virtual Table Conflict Policy +** +** This function may only be called from within a call to the [xUpdate] method +** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The +** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL], +** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode +** of the SQL statement that triggered the call to the [xUpdate] method of the +** [virtual table]. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *); + +/* +** CAPI3REF: Conflict resolution modes +** KEYWORDS: {conflict resolution mode} +** +** These constants are returned by [sqlite3_vtab_on_conflict()] to +** inform a [virtual table] implementation what the [ON CONFLICT] mode +** is for the SQL statement being evaluated. +** +** Note that the [SQLITE_IGNORE] constant is also used as a potential +** return value from the [sqlite3_set_authorizer()] callback and that +** [SQLITE_ABORT] is also a [result code]. +*/ +#define SQLITE_ROLLBACK 1 +/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */ +#define SQLITE_FAIL 3 +/* #define SQLITE_ABORT 4 // Also an error code */ +#define SQLITE_REPLACE 5 + +/* +** CAPI3REF: Prepared Statement Scan Status Opcodes +** KEYWORDS: {scanstatus options} +** +** The following constants can be used for the T parameter to the +** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a +** different metric for sqlite3_stmt_scanstatus() to return. +** +** When the value returned to V is a string, space to hold that string is +** managed by the prepared statement S and will be automatically freed when +** S is finalized. +** +**
+** [[SQLITE_SCANSTAT_NLOOP]]
SQLITE_SCANSTAT_NLOOP
+**
^The [sqlite3_int64] variable pointed to by the T parameter will be +** set to the total number of times that the X-th loop has run.
+** +** [[SQLITE_SCANSTAT_NVISIT]]
SQLITE_SCANSTAT_NVISIT
+**
^The [sqlite3_int64] variable pointed to by the T parameter will be set +** to the total number of rows examined by all iterations of the X-th loop.
+** +** [[SQLITE_SCANSTAT_EST]]
SQLITE_SCANSTAT_EST
+**
^The "double" variable pointed to by the T parameter will be set to the +** query planner's estimate for the average number of rows output from each +** iteration of the X-th loop. If the query planner's estimates was accurate, +** then this value will approximate the quotient NVISIT/NLOOP and the +** product of this value for all prior loops with the same SELECTID will +** be the NLOOP value for the current loop. +** +** [[SQLITE_SCANSTAT_NAME]]
SQLITE_SCANSTAT_NAME
+**
^The "const char *" variable pointed to by the T parameter will be set +** to a zero-terminated UTF-8 string containing the name of the index or table +** used for the X-th loop. +** +** [[SQLITE_SCANSTAT_EXPLAIN]]
SQLITE_SCANSTAT_EXPLAIN
+**
^The "const char *" variable pointed to by the T parameter will be set +** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] +** description for the X-th loop. +** +** [[SQLITE_SCANSTAT_SELECTID]]
SQLITE_SCANSTAT_SELECT
+**
^The "int" variable pointed to by the T parameter will be set to the +** "select-id" for the X-th loop. The select-id identifies which query or +** subquery the loop is part of. The main query has a select-id of zero. +** The select-id is the same value as is output in the first column +** of an [EXPLAIN QUERY PLAN] query. +**
+*/ +#define SQLITE_SCANSTAT_NLOOP 0 +#define SQLITE_SCANSTAT_NVISIT 1 +#define SQLITE_SCANSTAT_EST 2 +#define SQLITE_SCANSTAT_NAME 3 +#define SQLITE_SCANSTAT_EXPLAIN 4 +#define SQLITE_SCANSTAT_SELECTID 5 + +/* +** CAPI3REF: Prepared Statement Scan Status +** METHOD: sqlite3_stmt +** +** This interface returns information about the predicted and measured +** performance for pStmt. Advanced applications can use this +** interface to compare the predicted and the measured performance and +** issue warnings and/or rerun [ANALYZE] if discrepancies are found. +** +** Since this interface is expected to be rarely used, it is only +** available if SQLite is compiled using the [SQLITE_ENABLE_STMT_SCANSTATUS] +** compile-time option. +** +** The "iScanStatusOp" parameter determines which status information to return. +** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior +** of this interface is undefined. +** ^The requested measurement is written into a variable pointed to by +** the "pOut" parameter. +** Parameter "idx" identifies the specific loop to retrieve statistics for. +** Loops are numbered starting from zero. ^If idx is out of range - less than +** zero or greater than or equal to the total number of loops used to implement +** the statement - a non-zero value is returned and the variable that pOut +** points to is unchanged. +** +** ^Statistics might not be available for all loops in all statements. ^In cases +** where there exist loops with no available statistics, this function behaves +** as if the loop did not exist - it returns non-zero and leave the variable +** that pOut points to unchanged. +** +** See also: [sqlite3_stmt_scanstatus_reset()] +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( + sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ + int idx, /* Index of loop to report on */ + int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ + void *pOut /* Result written here */ +); + +/* +** CAPI3REF: Zero Scan-Status Counters +** METHOD: sqlite3_stmt +** +** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. +** +** This API is only available if the library is built with pre-processor +** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); + + +/* +** Undo the hack that converts floating point types to integer for +** builds on processors without floating point support. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# undef double +#endif + +#if 0 +} /* End of the 'extern "C"' block */ +#endif +#endif /* _SQLITE3_H_ */ + +/* +** 2010 August 30 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +*/ + +#ifndef _SQLITE3RTREE_H_ +#define _SQLITE3RTREE_H_ + + +#if 0 +extern "C" { +#endif + +typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; +typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info; + +/* The double-precision datatype used by RTree depends on the +** SQLITE_RTREE_INT_ONLY compile-time option. +*/ +#ifdef SQLITE_RTREE_INT_ONLY + typedef sqlite3_int64 sqlite3_rtree_dbl; +#else + typedef double sqlite3_rtree_dbl; +#endif + +/* +** Register a geometry callback named zGeom that can be used as part of an +** R-Tree geometry query as follows: +** +** SELECT ... FROM WHERE MATCH $zGeom(... params ...) +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( + sqlite3 *db, + const char *zGeom, + int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), + void *pContext +); + + +/* +** A pointer to a structure of the following type is passed as the first +** argument to callbacks registered using rtree_geometry_callback(). +*/ +struct sqlite3_rtree_geometry { + void *pContext; /* Copy of pContext passed to s_r_g_c() */ + int nParam; /* Size of array aParam[] */ + sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */ + void *pUser; /* Callback implementation user data */ + void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ +}; + +/* +** Register a 2nd-generation geometry callback named zScore that can be +** used as part of an R-Tree geometry query as follows: +** +** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( + sqlite3 *db, + const char *zQueryFunc, + int (*xQueryFunc)(sqlite3_rtree_query_info*), + void *pContext, + void (*xDestructor)(void*) +); + + +/* +** A pointer to a structure of the following type is passed as the +** argument to scored geometry callback registered using +** sqlite3_rtree_query_callback(). +** +** Note that the first 5 fields of this structure are identical to +** sqlite3_rtree_geometry. This structure is a subclass of +** sqlite3_rtree_geometry. +*/ +struct sqlite3_rtree_query_info { + void *pContext; /* pContext from when function registered */ + int nParam; /* Number of function parameters */ + sqlite3_rtree_dbl *aParam; /* value of function parameters */ + void *pUser; /* callback can use this, if desired */ + void (*xDelUser)(void*); /* function to free pUser */ + sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */ + unsigned int *anQueue; /* Number of pending entries in the queue */ + int nCoord; /* Number of coordinates */ + int iLevel; /* Level of current node or entry */ + int mxLevel; /* The largest iLevel value in the tree */ + sqlite3_int64 iRowid; /* Rowid for current entry */ + sqlite3_rtree_dbl rParentScore; /* Score of parent node */ + int eParentWithin; /* Visibility of parent node */ + int eWithin; /* OUT: Visiblity */ + sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ + /* The following fields are only available in 3.8.11 and later */ + sqlite3_value **apSqlParam; /* Original SQL values of parameters */ +}; + +/* +** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin. +*/ +#define NOT_WITHIN 0 /* Object completely outside of query region */ +#define PARTLY_WITHIN 1 /* Object partially overlaps query region */ +#define FULLY_WITHIN 2 /* Object fully contained within query region */ + + +#if 0 +} /* end of the 'extern "C"' block */ +#endif + +#endif /* ifndef _SQLITE3RTREE_H_ */ + + +/************** End of sqlite3.h *********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + +/* +** Include the configuration header output by 'configure' if we're using the +** autoconf-based build +*/ +#ifdef _HAVE_SQLITE_CONFIG_H +#include "config.h" +#endif + +/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/ +/************** Begin file sqliteLimit.h *************************************/ +/* +** 2007 May 7 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file defines various limits of what SQLite can process. +*/ + +/* +** The maximum length of a TEXT or BLOB in bytes. This also +** limits the size of a row in a table or index. +** +** The hard limit is the ability of a 32-bit signed integer +** to count the size: 2^31-1 or 2147483647. +*/ +#ifndef SQLITE_MAX_LENGTH +# define SQLITE_MAX_LENGTH 1000000000 +#endif + +/* +** This is the maximum number of +** +** * Columns in a table +** * Columns in an index +** * Columns in a view +** * Terms in the SET clause of an UPDATE statement +** * Terms in the result set of a SELECT statement +** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement. +** * Terms in the VALUES clause of an INSERT statement +** +** The hard upper limit here is 32676. Most database people will +** tell you that in a well-normalized database, you usually should +** not have more than a dozen or so columns in any table. And if +** that is the case, there is no point in having more than a few +** dozen values in any of the other situations described above. +*/ +#ifndef SQLITE_MAX_COLUMN +# define SQLITE_MAX_COLUMN 2000 +#endif + +/* +** The maximum length of a single SQL statement in bytes. +** +** It used to be the case that setting this value to zero would +** turn the limit off. That is no longer true. It is not possible +** to turn this limit off. +*/ +#ifndef SQLITE_MAX_SQL_LENGTH +# define SQLITE_MAX_SQL_LENGTH 1000000000 +#endif + +/* +** The maximum depth of an expression tree. This is limited to +** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might +** want to place more severe limits on the complexity of an +** expression. +** +** A value of 0 used to mean that the limit was not enforced. +** But that is no longer true. The limit is now strictly enforced +** at all times. +*/ +#ifndef SQLITE_MAX_EXPR_DEPTH +# define SQLITE_MAX_EXPR_DEPTH 1000 +#endif + +/* +** The maximum number of terms in a compound SELECT statement. +** The code generator for compound SELECT statements does one +** level of recursion for each term. A stack overflow can result +** if the number of terms is too large. In practice, most SQL +** never has more than 3 or 4 terms. Use a value of 0 to disable +** any limit on the number of terms in a compount SELECT. +*/ +#ifndef SQLITE_MAX_COMPOUND_SELECT +# define SQLITE_MAX_COMPOUND_SELECT 500 +#endif + +/* +** The maximum number of opcodes in a VDBE program. +** Not currently enforced. +*/ +#ifndef SQLITE_MAX_VDBE_OP +# define SQLITE_MAX_VDBE_OP 25000 +#endif + +/* +** The maximum number of arguments to an SQL function. +*/ +#ifndef SQLITE_MAX_FUNCTION_ARG +# define SQLITE_MAX_FUNCTION_ARG 127 +#endif + +/* +** The suggested maximum number of in-memory pages to use for +** the main database table and for temporary tables. +** +** IMPLEMENTATION-OF: R-31093-59126 The default suggested cache size +** is 2000 pages. +** IMPLEMENTATION-OF: R-48205-43578 The default suggested cache size can be +** altered using the SQLITE_DEFAULT_CACHE_SIZE compile-time options. +*/ +#ifndef SQLITE_DEFAULT_CACHE_SIZE +# define SQLITE_DEFAULT_CACHE_SIZE 2000 +#endif + +/* +** The default number of frames to accumulate in the log file before +** checkpointing the database in WAL mode. +*/ +#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT +# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000 +#endif + +/* +** The maximum number of attached databases. This must be between 0 +** and 62. The upper bound on 62 is because a 64-bit integer bitmap +** is used internally to track attached databases. +*/ +#ifndef SQLITE_MAX_ATTACHED +# define SQLITE_MAX_ATTACHED 10 +#endif + + +/* +** The maximum value of a ?nnn wildcard that the parser will accept. +*/ +#ifndef SQLITE_MAX_VARIABLE_NUMBER +# define SQLITE_MAX_VARIABLE_NUMBER 999 +#endif + +/* Maximum page size. The upper bound on this value is 65536. This a limit +** imposed by the use of 16-bit offsets within each page. +** +** Earlier versions of SQLite allowed the user to change this value at +** compile time. This is no longer permitted, on the grounds that it creates +** a library that is technically incompatible with an SQLite library +** compiled with a different limit. If a process operating on a database +** with a page-size of 65536 bytes crashes, then an instance of SQLite +** compiled with the default page-size limit will not be able to rollback +** the aborted transaction. This could lead to database corruption. +*/ +#ifdef SQLITE_MAX_PAGE_SIZE +# undef SQLITE_MAX_PAGE_SIZE +#endif +#define SQLITE_MAX_PAGE_SIZE 65536 + + +/* +** The default size of a database page. +*/ +#ifndef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE 1024 +#endif +#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE +# undef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE +#endif + +/* +** Ordinarily, if no value is explicitly provided, SQLite creates databases +** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain +** device characteristics (sector-size and atomic write() support), +** SQLite may choose a larger value. This constant is the maximum value +** SQLite will choose on its own. +*/ +#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE +# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192 +#endif +#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE +# undef SQLITE_MAX_DEFAULT_PAGE_SIZE +# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE +#endif + + +/* +** Maximum number of pages in one database file. +** +** This is really just the default value for the max_page_count pragma. +** This value can be lowered (or raised) at run-time using that the +** max_page_count macro. +*/ +#ifndef SQLITE_MAX_PAGE_COUNT +# define SQLITE_MAX_PAGE_COUNT 1073741823 +#endif + +/* +** Maximum length (in bytes) of the pattern in a LIKE or GLOB +** operator. +*/ +#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH +# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 +#endif + +/* +** Maximum depth of recursion for triggers. +** +** A value of 1 means that a trigger program will not be able to itself +** fire any triggers. A value of 0 means that no trigger programs at all +** may be executed. +*/ +#ifndef SQLITE_MAX_TRIGGER_DEPTH +# define SQLITE_MAX_TRIGGER_DEPTH 1000 +#endif + +/************** End of sqliteLimit.h *****************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + +/* Disable nuisance warnings on Borland compilers */ +#if defined(__BORLANDC__) +#pragma warn -rch /* unreachable code */ +#pragma warn -ccc /* Condition is always true or false */ +#pragma warn -aus /* Assigned value is never used */ +#pragma warn -csu /* Comparing signed and unsigned */ +#pragma warn -spa /* Suspicious pointer arithmetic */ +#endif + +/* +** Include standard header files as necessary +*/ +#ifdef HAVE_STDINT_H +#include +#endif +#ifdef HAVE_INTTYPES_H +#include +#endif + +/* +** The following macros are used to cast pointers to integers and +** integers to pointers. The way you do this varies from one compiler +** to the next, so we have developed the following set of #if statements +** to generate appropriate macros for a wide range of compilers. +** +** The correct "ANSI" way to do this is to use the intptr_t type. +** Unfortunately, that typedef is not available on all compilers, or +** if it is available, it requires an #include of specific headers +** that vary from one machine to the next. +** +** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on +** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)). +** So we have to define the macros in different ways depending on the +** compiler. +*/ +#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ +# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X)) +#elif !defined(__GNUC__) /* Works for compilers other than LLVM */ +# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) +# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) +#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ +# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) +#else /* Generates a warning - but it always works */ +# define SQLITE_INT_TO_PTR(X) ((void*)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(X)) +#endif + +/* +** A macro to hint to the compiler that a function should not be +** inlined. +*/ +#if defined(__GNUC__) +# define SQLITE_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) && _MSC_VER>=1310 +# define SQLITE_NOINLINE __declspec(noinline) +#else +# define SQLITE_NOINLINE +#endif + +/* +** Make sure that the compiler intrinsics we desire are enabled when +** compiling with an appropriate version of MSVC. +*/ +#if defined(_MSC_VER) && _MSC_VER>=1300 +# if !defined(_WIN32_WCE) +# include +# pragma intrinsic(_byteswap_ushort) +# pragma intrinsic(_byteswap_ulong) +# else +# include +# endif +#endif + +/* +** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. +** 0 means mutexes are permanently disable and the library is never +** threadsafe. 1 means the library is serialized which is the highest +** level of threadsafety. 2 means the library is multithreaded - multiple +** threads can use SQLite as long as no two threads try to use the same +** database connection at the same time. +** +** Older versions of SQLite used an optional THREADSAFE macro. +** We support that for legacy. +*/ +#if !defined(SQLITE_THREADSAFE) +# if defined(THREADSAFE) +# define SQLITE_THREADSAFE THREADSAFE +# else +# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */ +# endif +#endif + +/* +** Powersafe overwrite is on by default. But can be turned off using +** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option. +*/ +#ifndef SQLITE_POWERSAFE_OVERWRITE +# define SQLITE_POWERSAFE_OVERWRITE 1 +#endif + +/* +** EVIDENCE-OF: R-25715-37072 Memory allocation statistics are enabled by +** default unless SQLite is compiled with SQLITE_DEFAULT_MEMSTATUS=0 in +** which case memory allocation statistics are disabled by default. +*/ +#if !defined(SQLITE_DEFAULT_MEMSTATUS) +# define SQLITE_DEFAULT_MEMSTATUS 1 +#endif + +/* +** Exactly one of the following macros must be defined in order to +** specify which memory allocation subsystem to use. +** +** SQLITE_SYSTEM_MALLOC // Use normal system malloc() +** SQLITE_WIN32_MALLOC // Use Win32 native heap API +** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails +** SQLITE_MEMDEBUG // Debugging version of system malloc() +** +** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the +** assert() macro is enabled, each call into the Win32 native heap subsystem +** will cause HeapValidate to be called. If heap validation should fail, an +** assertion will be triggered. +** +** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as +** the default. +*/ +#if defined(SQLITE_SYSTEM_MALLOC) \ + + defined(SQLITE_WIN32_MALLOC) \ + + defined(SQLITE_ZERO_MALLOC) \ + + defined(SQLITE_MEMDEBUG)>1 +# error "Two or more of the following compile-time configuration options\ + are defined but at most one is allowed:\ + SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\ + SQLITE_ZERO_MALLOC" +#endif +#if defined(SQLITE_SYSTEM_MALLOC) \ + + defined(SQLITE_WIN32_MALLOC) \ + + defined(SQLITE_ZERO_MALLOC) \ + + defined(SQLITE_MEMDEBUG)==0 +# define SQLITE_SYSTEM_MALLOC 1 +#endif + +/* +** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the +** sizes of memory allocations below this value where possible. +*/ +#if !defined(SQLITE_MALLOC_SOFT_LIMIT) +# define SQLITE_MALLOC_SOFT_LIMIT 1024 +#endif + +/* +** We need to define _XOPEN_SOURCE as follows in order to enable +** recursive mutexes on most Unix systems and fchmod() on OpenBSD. +** But _XOPEN_SOURCE define causes problems for Mac OS X, so omit +** it. +*/ +#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) +# define _XOPEN_SOURCE 600 +#endif + +/* +** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that +** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true, +** make it true by defining or undefining NDEBUG. +** +** Setting NDEBUG makes the code smaller and faster by disabling the +** assert() statements in the code. So we want the default action +** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG +** is set. Thus NDEBUG becomes an opt-in rather than an opt-out +** feature. +*/ +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 +#endif +#if defined(NDEBUG) && defined(SQLITE_DEBUG) +# undef NDEBUG +#endif + +/* +** Enable SQLITE_ENABLE_EXPLAIN_COMMENTS if SQLITE_DEBUG is turned on. +*/ +#if !defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) && defined(SQLITE_DEBUG) +# define SQLITE_ENABLE_EXPLAIN_COMMENTS 1 +#endif + +/* +** The testcase() macro is used to aid in coverage testing. When +** doing coverage testing, the condition inside the argument to +** testcase() must be evaluated both true and false in order to +** get full branch coverage. The testcase() macro is inserted +** to help ensure adequate test coverage in places where simple +** condition/decision coverage is inadequate. For example, testcase() +** can be used to make sure boundary values are tested. For +** bitmask tests, testcase() can be used to make sure each bit +** is significant and used at least once. On switch statements +** where multiple cases go to the same block of code, testcase() +** can insure that all cases are evaluated. +** +*/ +#ifdef SQLITE_COVERAGE_TEST +SQLITE_PRIVATE void sqlite3Coverage(int); +# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); } +#else +# define testcase(X) +#endif + +/* +** The TESTONLY macro is used to enclose variable declarations or +** other bits of code that are needed to support the arguments +** within testcase() and assert() macros. +*/ +#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST) +# define TESTONLY(X) X +#else +# define TESTONLY(X) +#endif + +/* +** Sometimes we need a small amount of code such as a variable initialization +** to setup for a later assert() statement. We do not want this code to +** appear when assert() is disabled. The following macro is therefore +** used to contain that setup code. The "VVA" acronym stands for +** "Verification, Validation, and Accreditation". In other words, the +** code within VVA_ONLY() will only run during verification processes. +*/ +#ifndef NDEBUG +# define VVA_ONLY(X) X +#else +# define VVA_ONLY(X) +#endif + +/* +** The ALWAYS and NEVER macros surround boolean expressions which +** are intended to always be true or false, respectively. Such +** expressions could be omitted from the code completely. But they +** are included in a few cases in order to enhance the resilience +** of SQLite to unexpected behavior - to make the code "self-healing" +** or "ductile" rather than being "brittle" and crashing at the first +** hint of unplanned behavior. +** +** In other words, ALWAYS and NEVER are added for defensive code. +** +** When doing coverage testing ALWAYS and NEVER are hard-coded to +** be true and false so that the unreachable code they specify will +** not be counted as untested code. +*/ +#if defined(SQLITE_COVERAGE_TEST) +# define ALWAYS(X) (1) +# define NEVER(X) (0) +#elif !defined(NDEBUG) +# define ALWAYS(X) ((X)?1:(assert(0),0)) +# define NEVER(X) ((X)?(assert(0),1):0) +#else +# define ALWAYS(X) (X) +# define NEVER(X) (X) +#endif + +/* +** Declarations used for tracing the operating system interfaces. +*/ +#if defined(SQLITE_FORCE_OS_TRACE) || defined(SQLITE_TEST) || \ + (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) + extern int sqlite3OSTrace; +# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X +# define SQLITE_HAVE_OS_TRACE +#else +# define OSTRACE(X) +# undef SQLITE_HAVE_OS_TRACE +#endif + +/* +** Is the sqlite3ErrName() function needed in the build? Currently, +** it is needed by "mutex_w32.c" (when debugging), "os_win.c" (when +** OSTRACE is enabled), and by several "test*.c" files (which are +** compiled using SQLITE_TEST). +*/ +#if defined(SQLITE_HAVE_OS_TRACE) || defined(SQLITE_TEST) || \ + (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) +# define SQLITE_NEED_ERR_NAME +#else +# undef SQLITE_NEED_ERR_NAME +#endif + +/* +** Return true (non-zero) if the input is an integer that is too large +** to fit in 32-bits. This macro is used inside of various testcase() +** macros to verify that we have tested SQLite for large-file support. +*/ +#define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0) + +/* +** The macro unlikely() is a hint that surrounds a boolean +** expression that is usually false. Macro likely() surrounds +** a boolean expression that is usually true. These hints could, +** in theory, be used by the compiler to generate better code, but +** currently they are just comments for human readers. +*/ +#define likely(X) (X) +#define unlikely(X) (X) + +/************** Include hash.h in the middle of sqliteInt.h ******************/ +/************** Begin file hash.h ********************************************/ +/* +** 2001 September 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This is the header file for the generic hash-table implementation +** used in SQLite. +*/ +#ifndef _SQLITE_HASH_H_ +#define _SQLITE_HASH_H_ + +/* Forward declarations of structures. */ +typedef struct Hash Hash; +typedef struct HashElem HashElem; + +/* A complete hash table is an instance of the following structure. +** The internals of this structure are intended to be opaque -- client +** code should not attempt to access or modify the fields of this structure +** directly. Change this structure only by using the routines below. +** However, some of the "procedures" and "functions" for modifying and +** accessing this structure are really macros, so we can't really make +** this structure opaque. +** +** All elements of the hash table are on a single doubly-linked list. +** Hash.first points to the head of this list. +** +** There are Hash.htsize buckets. Each bucket points to a spot in +** the global doubly-linked list. The contents of the bucket are the +** element pointed to plus the next _ht.count-1 elements in the list. +** +** Hash.htsize and Hash.ht may be zero. In that case lookup is done +** by a linear search of the global list. For small tables, the +** Hash.ht table is never allocated because if there are few elements +** in the table, it is faster to do a linear search than to manage +** the hash table. +*/ +struct Hash { + unsigned int htsize; /* Number of buckets in the hash table */ + unsigned int count; /* Number of entries in this table */ + HashElem *first; /* The first element of the array */ + struct _ht { /* the hash table */ + int count; /* Number of entries with this hash */ + HashElem *chain; /* Pointer to first entry with this hash */ + } *ht; +}; + +/* Each element in the hash table is an instance of the following +** structure. All elements are stored on a single doubly-linked list. +** +** Again, this structure is intended to be opaque, but it can't really +** be opaque because it is used by macros. +*/ +struct HashElem { + HashElem *next, *prev; /* Next and previous elements in the table */ + void *data; /* Data associated with this element */ + const char *pKey; /* Key associated with this element */ +}; + +/* +** Access routines. To delete, insert a NULL pointer. +*/ +SQLITE_PRIVATE void sqlite3HashInit(Hash*); +SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const char *pKey, void *pData); +SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const char *pKey); +SQLITE_PRIVATE void sqlite3HashClear(Hash*); + +/* +** Macros for looping over all elements of a hash table. The idiom is +** like this: +** +** Hash h; +** HashElem *p; +** ... +** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){ +** SomeStructure *pData = sqliteHashData(p); +** // do something with pData +** } +*/ +#define sqliteHashFirst(H) ((H)->first) +#define sqliteHashNext(E) ((E)->next) +#define sqliteHashData(E) ((E)->data) +/* #define sqliteHashKey(E) ((E)->pKey) // NOT USED */ +/* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */ + +/* +** Number of entries in a hash table +*/ +/* #define sqliteHashCount(H) ((H)->count) // NOT USED */ + +#endif /* _SQLITE_HASH_H_ */ + +/************** End of hash.h ************************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include parse.h in the middle of sqliteInt.h *****************/ +/************** Begin file parse.h *******************************************/ +#define TK_SEMI 1 +#define TK_EXPLAIN 2 +#define TK_QUERY 3 +#define TK_PLAN 4 +#define TK_BEGIN 5 +#define TK_TRANSACTION 6 +#define TK_DEFERRED 7 +#define TK_IMMEDIATE 8 +#define TK_EXCLUSIVE 9 +#define TK_COMMIT 10 +#define TK_END 11 +#define TK_ROLLBACK 12 +#define TK_SAVEPOINT 13 +#define TK_RELEASE 14 +#define TK_TO 15 +#define TK_TABLE 16 +#define TK_CREATE 17 +#define TK_IF 18 +#define TK_NOT 19 +#define TK_EXISTS 20 +#define TK_TEMP 21 +#define TK_LP 22 +#define TK_RP 23 +#define TK_AS 24 +#define TK_WITHOUT 25 +#define TK_COMMA 26 +#define TK_ID 27 +#define TK_INDEXED 28 +#define TK_ABORT 29 +#define TK_ACTION 30 +#define TK_AFTER 31 +#define TK_ANALYZE 32 +#define TK_ASC 33 +#define TK_ATTACH 34 +#define TK_BEFORE 35 +#define TK_BY 36 +#define TK_CASCADE 37 +#define TK_CAST 38 +#define TK_COLUMNKW 39 +#define TK_CONFLICT 40 +#define TK_DATABASE 41 +#define TK_DESC 42 +#define TK_DETACH 43 +#define TK_EACH 44 +#define TK_FAIL 45 +#define TK_FOR 46 +#define TK_IGNORE 47 +#define TK_INITIALLY 48 +#define TK_INSTEAD 49 +#define TK_LIKE_KW 50 +#define TK_MATCH 51 +#define TK_NO 52 +#define TK_KEY 53 +#define TK_OF 54 +#define TK_OFFSET 55 +#define TK_PRAGMA 56 +#define TK_RAISE 57 +#define TK_RECURSIVE 58 +#define TK_REPLACE 59 +#define TK_RESTRICT 60 +#define TK_ROW 61 +#define TK_TRIGGER 62 +#define TK_VACUUM 63 +#define TK_VIEW 64 +#define TK_VIRTUAL 65 +#define TK_WITH 66 +#define TK_REINDEX 67 +#define TK_RENAME 68 +#define TK_CTIME_KW 69 +#define TK_ANY 70 +#define TK_OR 71 +#define TK_AND 72 +#define TK_IS 73 +#define TK_BETWEEN 74 +#define TK_IN 75 +#define TK_ISNULL 76 +#define TK_NOTNULL 77 +#define TK_NE 78 +#define TK_EQ 79 +#define TK_GT 80 +#define TK_LE 81 +#define TK_LT 82 +#define TK_GE 83 +#define TK_ESCAPE 84 +#define TK_BITAND 85 +#define TK_BITOR 86 +#define TK_LSHIFT 87 +#define TK_RSHIFT 88 +#define TK_PLUS 89 +#define TK_MINUS 90 +#define TK_STAR 91 +#define TK_SLASH 92 +#define TK_REM 93 +#define TK_CONCAT 94 +#define TK_COLLATE 95 +#define TK_BITNOT 96 +#define TK_STRING 97 +#define TK_JOIN_KW 98 +#define TK_CONSTRAINT 99 +#define TK_DEFAULT 100 +#define TK_NULL 101 +#define TK_PRIMARY 102 +#define TK_UNIQUE 103 +#define TK_CHECK 104 +#define TK_REFERENCES 105 +#define TK_AUTOINCR 106 +#define TK_ON 107 +#define TK_INSERT 108 +#define TK_DELETE 109 +#define TK_UPDATE 110 +#define TK_SET 111 +#define TK_DEFERRABLE 112 +#define TK_FOREIGN 113 +#define TK_DROP 114 +#define TK_UNION 115 +#define TK_ALL 116 +#define TK_EXCEPT 117 +#define TK_INTERSECT 118 +#define TK_SELECT 119 +#define TK_VALUES 120 +#define TK_DISTINCT 121 +#define TK_DOT 122 +#define TK_FROM 123 +#define TK_JOIN 124 +#define TK_USING 125 +#define TK_ORDER 126 +#define TK_GROUP 127 +#define TK_HAVING 128 +#define TK_LIMIT 129 +#define TK_WHERE 130 +#define TK_INTO 131 +#define TK_INTEGER 132 +#define TK_FLOAT 133 +#define TK_BLOB 134 +#define TK_VARIABLE 135 +#define TK_CASE 136 +#define TK_WHEN 137 +#define TK_THEN 138 +#define TK_ELSE 139 +#define TK_INDEX 140 +#define TK_ALTER 141 +#define TK_ADD 142 +#define TK_TO_TEXT 143 +#define TK_TO_BLOB 144 +#define TK_TO_NUMERIC 145 +#define TK_TO_INT 146 +#define TK_TO_REAL 147 +#define TK_ISNOT 148 +#define TK_END_OF_FILE 149 +#define TK_ILLEGAL 150 +#define TK_SPACE 151 +#define TK_UNCLOSED_STRING 152 +#define TK_FUNCTION 153 +#define TK_COLUMN 154 +#define TK_AGG_FUNCTION 155 +#define TK_AGG_COLUMN 156 +#define TK_UMINUS 157 +#define TK_UPLUS 158 +#define TK_REGISTER 159 + +/************** End of parse.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +#include +#include +#include +#include +#include + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite_int64 +# define float sqlite_int64 +# define LONGDOUBLE_TYPE sqlite_int64 +# ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) +# endif +# define SQLITE_OMIT_DATETIME_FUNCS 1 +# define SQLITE_OMIT_TRACE 1 +# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT +# undef SQLITE_HAVE_ISNAN +#endif +#ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (1e99) +#endif + +/* +** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0 +** afterward. Having this macro allows us to cause the C compiler +** to omit code used by TEMP tables without messy #ifndef statements. +*/ +#ifdef SQLITE_OMIT_TEMPDB +#define OMIT_TEMPDB 1 +#else +#define OMIT_TEMPDB 0 +#endif + +/* +** The "file format" number is an integer that is incremented whenever +** the VDBE-level file format changes. The following macros define the +** the default file format for new databases and the maximum file format +** that the library can read. +*/ +#define SQLITE_MAX_FILE_FORMAT 4 +#ifndef SQLITE_DEFAULT_FILE_FORMAT +# define SQLITE_DEFAULT_FILE_FORMAT 4 +#endif + +/* +** Determine whether triggers are recursive by default. This can be +** changed at run-time using a pragma. +*/ +#ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS +# define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0 +#endif + +/* +** Provide a default value for SQLITE_TEMP_STORE in case it is not specified +** on the command-line +*/ +#ifndef SQLITE_TEMP_STORE +# define SQLITE_TEMP_STORE 1 +# define SQLITE_TEMP_STORE_xc 1 /* Exclude from ctime.c */ +#endif + +/* +** If no value has been provided for SQLITE_MAX_WORKER_THREADS, or if +** SQLITE_TEMP_STORE is set to 3 (never use temporary files), set it +** to zero. +*/ +#if SQLITE_TEMP_STORE==3 || SQLITE_THREADSAFE==0 +# undef SQLITE_MAX_WORKER_THREADS +# define SQLITE_MAX_WORKER_THREADS 0 +#endif +#ifndef SQLITE_MAX_WORKER_THREADS +# define SQLITE_MAX_WORKER_THREADS 8 +#endif +#ifndef SQLITE_DEFAULT_WORKER_THREADS +# define SQLITE_DEFAULT_WORKER_THREADS 0 +#endif +#if SQLITE_DEFAULT_WORKER_THREADS>SQLITE_MAX_WORKER_THREADS +# undef SQLITE_MAX_WORKER_THREADS +# define SQLITE_MAX_WORKER_THREADS SQLITE_DEFAULT_WORKER_THREADS +#endif + +/* +** The default initial allocation for the pagecache when using separate +** pagecaches for each database connection. A positive number is the +** number of pages. A negative number N translations means that a buffer +** of -1024*N bytes is allocated and used for as many pages as it will hold. +*/ +#ifndef SQLITE_DEFAULT_PCACHE_INITSZ +# define SQLITE_DEFAULT_PCACHE_INITSZ 100 +#endif + + +/* +** GCC does not define the offsetof() macro so we'll have to do it +** ourselves. +*/ +#ifndef offsetof +#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) +#endif + +/* +** Macros to compute minimum and maximum of two numbers. +*/ +#define MIN(A,B) ((A)<(B)?(A):(B)) +#define MAX(A,B) ((A)>(B)?(A):(B)) + +/* +** Swap two objects of type TYPE. +*/ +#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} + +/* +** Check to see if this machine uses EBCDIC. (Yes, believe it or +** not, there are still machines out there that use EBCDIC.) +*/ +#if 'A' == '\301' +# define SQLITE_EBCDIC 1 +#else +# define SQLITE_ASCII 1 +#endif + +/* +** Integers of known sizes. These typedefs might change for architectures +** where the sizes very. Preprocessor macros are available so that the +** types can be conveniently redefined at compile-type. Like this: +** +** cc '-DUINTPTR_TYPE=long long int' ... +*/ +#ifndef UINT32_TYPE +# ifdef HAVE_UINT32_T +# define UINT32_TYPE uint32_t +# else +# define UINT32_TYPE unsigned int +# endif +#endif +#ifndef UINT16_TYPE +# ifdef HAVE_UINT16_T +# define UINT16_TYPE uint16_t +# else +# define UINT16_TYPE unsigned short int +# endif +#endif +#ifndef INT16_TYPE +# ifdef HAVE_INT16_T +# define INT16_TYPE int16_t +# else +# define INT16_TYPE short int +# endif +#endif +#ifndef UINT8_TYPE +# ifdef HAVE_UINT8_T +# define UINT8_TYPE uint8_t +# else +# define UINT8_TYPE unsigned char +# endif +#endif +#ifndef INT8_TYPE +# ifdef HAVE_INT8_T +# define INT8_TYPE int8_t +# else +# define INT8_TYPE signed char +# endif +#endif +#ifndef LONGDOUBLE_TYPE +# define LONGDOUBLE_TYPE long double +#endif +typedef sqlite_int64 i64; /* 8-byte signed integer */ +typedef sqlite_uint64 u64; /* 8-byte unsigned integer */ +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 INT8_TYPE i8; /* 1-byte signed integer */ + +/* +** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value +** that can be stored in a u32 without loss of data. The value +** is 0x00000000ffffffff. But because of quirks of some compilers, we +** have to specify the value in the less intuitive manner shown: +*/ +#define SQLITE_MAX_U32 ((((u64)1)<<32)-1) + +/* +** The datatype used to store estimates of the number of rows in a +** table or index. This is an unsigned integer type. For 99.9% of +** the world, a 32-bit integer is sufficient. But a 64-bit integer +** can be used at compile-time if desired. +*/ +#ifdef SQLITE_64BIT_STATS + typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */ +#else + typedef u32 tRowcnt; /* 32-bit is the default */ +#endif + +/* +** Estimated quantities used for query planning are stored as 16-bit +** logarithms. For quantity X, the value stored is 10*log2(X). This +** gives a possible range of values of approximately 1.0e986 to 1e-986. +** But the allowed values are "grainy". Not every value is representable. +** For example, quantities 16 and 17 are both represented by a LogEst +** of 40. However, since LogEst quantities are suppose to be estimates, +** not exact values, this imprecision is not a problem. +** +** "LogEst" is short for "Logarithmic Estimate". +** +** Examples: +** 1 -> 0 20 -> 43 10000 -> 132 +** 2 -> 10 25 -> 46 25000 -> 146 +** 3 -> 16 100 -> 66 1000000 -> 199 +** 4 -> 20 1000 -> 99 1048576 -> 200 +** 10 -> 33 1024 -> 100 4294967296 -> 320 +** +** The LogEst can be negative to indicate fractional values. +** Examples: +** +** 0.5 -> -10 0.1 -> -33 0.0625 -> -40 +*/ +typedef INT16_TYPE LogEst; + +/* +** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer +*/ +#ifndef SQLITE_PTRSIZE +# if defined(__SIZEOF_POINTER__) +# define SQLITE_PTRSIZE __SIZEOF_POINTER__ +# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(_M_ARM) || defined(__arm__) || defined(__x86) +# define SQLITE_PTRSIZE 4 +# else +# define SQLITE_PTRSIZE 8 +# endif +#endif + +/* +** Macros to determine whether the machine is big or little endian, +** and whether or not that determination is run-time or compile-time. +** +** For best performance, an attempt is made to guess at the byte-order +** using C-preprocessor macros. If that is unsuccessful, or if +** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined +** at run-time. +*/ +#ifdef SQLITE_AMALGAMATION +SQLITE_PRIVATE const int sqlite3one = 1; +#else +SQLITE_PRIVATE const int sqlite3one; +#endif +#if (defined(i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ + defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ + defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER) +# define SQLITE_BYTEORDER 1234 +# define SQLITE_BIGENDIAN 0 +# define SQLITE_LITTLEENDIAN 1 +# define SQLITE_UTF16NATIVE SQLITE_UTF16LE +#endif +#if (defined(sparc) || defined(__ppc__)) \ + && !defined(SQLITE_RUNTIME_BYTEORDER) +# define SQLITE_BYTEORDER 4321 +# define SQLITE_BIGENDIAN 1 +# define SQLITE_LITTLEENDIAN 0 +# define SQLITE_UTF16NATIVE SQLITE_UTF16BE +#endif +#if !defined(SQLITE_BYTEORDER) +# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */ +# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) +# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) +# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) +#endif + +/* +** Constants for the largest and smallest possible 64-bit signed integers. +** These macros are designed to work correctly on both 32-bit and 64-bit +** compilers. +*/ +#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) +#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) + +/* +** Round up a number to the next larger multiple of 8. This is used +** to force 8-byte alignment on 64-bit architectures. +*/ +#define ROUND8(x) (((x)+7)&~7) + +/* +** Round down to the nearest multiple of 8 +*/ +#define ROUNDDOWN8(x) ((x)&~7) + +/* +** Assert that the pointer X is aligned to an 8-byte boundary. This +** macro is used only within assert() to verify that the code gets +** all alignment restrictions correct. +** +** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the +** underlying malloc() implementation might return us 4-byte aligned +** pointers. In that case, only verify 4-byte alignment. +*/ +#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC +# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0) +#else +# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) +#endif + +/* +** Disable MMAP on platforms where it is known to not work +*/ +#if defined(__OpenBSD__) || defined(__QNXNTO__) +# undef SQLITE_MAX_MMAP_SIZE +# define SQLITE_MAX_MMAP_SIZE 0 +#endif + +/* +** Default maximum size of memory used by memory-mapped I/O in the VFS +*/ +#ifdef __APPLE__ +# include +# if TARGET_OS_IPHONE +# undef SQLITE_MAX_MMAP_SIZE +# define SQLITE_MAX_MMAP_SIZE 0 +# endif +#endif +#ifndef SQLITE_MAX_MMAP_SIZE +# if defined(__linux__) \ + || defined(_WIN32) \ + || (defined(__APPLE__) && defined(__MACH__)) \ + || defined(__sun) \ + || defined(__FreeBSD__) \ + || defined(__DragonFly__) +# define SQLITE_MAX_MMAP_SIZE 0x7fff0000 /* 2147418112 */ +# else +# define SQLITE_MAX_MMAP_SIZE 0 +# endif +# define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */ +#endif + +/* +** The default MMAP_SIZE is zero on all platforms. Or, even if a larger +** default MMAP_SIZE is specified at compile-time, make sure that it does +** not exceed the maximum mmap size. +*/ +#ifndef SQLITE_DEFAULT_MMAP_SIZE +# define SQLITE_DEFAULT_MMAP_SIZE 0 +# define SQLITE_DEFAULT_MMAP_SIZE_xc 1 /* Exclude from ctime.c */ +#endif +#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE +# undef SQLITE_DEFAULT_MMAP_SIZE +# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE +#endif + +/* +** Only one of SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4 can be defined. +** Priority is given to SQLITE_ENABLE_STAT4. If either are defined, also +** define SQLITE_ENABLE_STAT3_OR_STAT4 +*/ +#ifdef SQLITE_ENABLE_STAT4 +# undef SQLITE_ENABLE_STAT3 +# define SQLITE_ENABLE_STAT3_OR_STAT4 1 +#elif SQLITE_ENABLE_STAT3 +# define SQLITE_ENABLE_STAT3_OR_STAT4 1 +#elif SQLITE_ENABLE_STAT3_OR_STAT4 +# undef SQLITE_ENABLE_STAT3_OR_STAT4 +#endif + +/* +** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not +** the Select query generator tracing logic is turned on. +*/ +#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_SELECTTRACE) +# define SELECTTRACE_ENABLED 1 +#else +# define SELECTTRACE_ENABLED 0 +#endif + +/* +** An instance of the following structure is used to store the busy-handler +** callback for a given sqlite handle. +** +** The sqlite.busyHandler member of the sqlite struct contains the busy +** callback for the database handle. Each pager opened via the sqlite +** handle is passed a pointer to sqlite.busyHandler. The busy-handler +** callback is currently invoked only from within pager.c. +*/ +typedef struct BusyHandler BusyHandler; +struct BusyHandler { + int (*xFunc)(void *,int); /* The busy callback */ + void *pArg; /* First arg to busy callback */ + int nBusy; /* Incremented with each busy call */ +}; + +/* +** Name of the master database table. The master database table +** is a special table that holds the names and attributes of all +** user tables and indices. +*/ +#define MASTER_NAME "sqlite_master" +#define TEMP_MASTER_NAME "sqlite_temp_master" + +/* +** The root-page of the master database table. +*/ +#define MASTER_ROOT 1 + +/* +** The name of the schema table. +*/ +#define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME) + +/* +** A convenience macro that returns the number of elements in +** an array. +*/ +#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) + +/* +** Determine if the argument is a power of two +*/ +#define IsPowerOfTwo(X) (((X)&((X)-1))==0) + +/* +** The following value as a destructor means to use sqlite3DbFree(). +** The sqlite3DbFree() routine requires two parameters instead of the +** one parameter that destructors normally want. So we have to introduce +** this magic value that the code knows to handle differently. Any +** pointer will work here as long as it is distinct from SQLITE_STATIC +** and SQLITE_TRANSIENT. +*/ +#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3MallocSize) + +/* +** When SQLITE_OMIT_WSD is defined, it means that the target platform does +** not support Writable Static Data (WSD) such as global and static variables. +** All variables must either be on the stack or dynamically allocated from +** the heap. When WSD is unsupported, the variable declarations scattered +** throughout the SQLite code must become constants instead. The SQLITE_WSD +** macro is used for this purpose. And instead of referencing the variable +** directly, we use its constant as a key to lookup the run-time allocated +** buffer that holds real variable. The constant is also the initializer +** for the run-time allocated buffer. +** +** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL +** macros become no-ops and have zero performance impact. +*/ +#ifdef SQLITE_OMIT_WSD + #define SQLITE_WSD const + #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v))) + #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config) +SQLITE_API int SQLITE_STDCALL sqlite3_wsd_init(int N, int J); +SQLITE_API void *SQLITE_STDCALL sqlite3_wsd_find(void *K, int L); +#else + #define SQLITE_WSD + #define GLOBAL(t,v) v + #define sqlite3GlobalConfig sqlite3Config +#endif + +/* +** The following macros are used to suppress compiler warnings and to +** make it clear to human readers when a function parameter is deliberately +** left unused within the body of a function. This usually happens when +** a function is called via a function pointer. For example the +** implementation of an SQL aggregate step callback may not use the +** parameter indicating the number of arguments passed to the aggregate, +** if it knows that this is enforced elsewhere. +** +** When a function parameter is not used at all within the body of a function, +** it is generally named "NotUsed" or "NotUsed2" to make things even clearer. +** However, these macros may also be used to suppress warnings related to +** parameters that may or may not be used depending on compilation options. +** For example those parameters only used in assert() statements. In these +** cases the parameters are named as per the usual conventions. +*/ +#define UNUSED_PARAMETER(x) (void)(x) +#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y) + +/* +** Forward references to structures +*/ +typedef struct AggInfo AggInfo; +typedef struct AuthContext AuthContext; +typedef struct AutoincInfo AutoincInfo; +typedef struct Bitvec Bitvec; +typedef struct CollSeq CollSeq; +typedef struct Column Column; +typedef struct Db Db; +typedef struct Schema Schema; +typedef struct Expr Expr; +typedef struct ExprList ExprList; +typedef struct ExprSpan ExprSpan; +typedef struct FKey FKey; +typedef struct FuncDestructor FuncDestructor; +typedef struct FuncDef FuncDef; +typedef struct FuncDefHash FuncDefHash; +typedef struct IdList IdList; +typedef struct Index Index; +typedef struct IndexSample IndexSample; +typedef struct KeyClass KeyClass; +typedef struct KeyInfo KeyInfo; +typedef struct Lookaside Lookaside; +typedef struct LookasideSlot LookasideSlot; +typedef struct Module Module; +typedef struct NameContext NameContext; +typedef struct Parse Parse; +typedef struct PrintfArguments PrintfArguments; +typedef struct RowSet RowSet; +typedef struct Savepoint Savepoint; +typedef struct Select Select; +typedef struct SQLiteThread SQLiteThread; +typedef struct SelectDest SelectDest; +typedef struct SrcList SrcList; +typedef struct StrAccum StrAccum; +typedef struct Table Table; +typedef struct TableLock TableLock; +typedef struct Token Token; +typedef struct TreeView TreeView; +typedef struct Trigger Trigger; +typedef struct TriggerPrg TriggerPrg; +typedef struct TriggerStep TriggerStep; +typedef struct UnpackedRecord UnpackedRecord; +typedef struct VTable VTable; +typedef struct VtabCtx VtabCtx; +typedef struct Walker Walker; +typedef struct WhereInfo WhereInfo; +typedef struct With With; + +/* +** Defer sourcing vdbe.h and btree.h until after the "u8" and +** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque +** pointer types (i.e. FuncDef) defined above. +*/ +/************** Include btree.h in the middle of sqliteInt.h *****************/ +/************** Begin file btree.h *******************************************/ +/* +** 2001 September 15 +** +** 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 B-Tree file +** subsystem. See comments in the source code for a detailed description +** of what each interface routine does. +*/ +#ifndef _BTREE_H_ +#define _BTREE_H_ + +/* TODO: This definition is just included so other modules compile. It +** needs to be revisited. +*/ +#define SQLITE_N_BTREE_META 16 + +/* +** If defined as non-zero, auto-vacuum is enabled by default. Otherwise +** it must be turned on for each database using "PRAGMA auto_vacuum = 1". +*/ +#ifndef SQLITE_DEFAULT_AUTOVACUUM + #define SQLITE_DEFAULT_AUTOVACUUM 0 +#endif + +#define BTREE_AUTOVACUUM_NONE 0 /* Do not do auto-vacuum */ +#define BTREE_AUTOVACUUM_FULL 1 /* Do full auto-vacuum */ +#define BTREE_AUTOVACUUM_INCR 2 /* Incremental vacuum */ + +/* +** Forward declarations of structure +*/ +typedef struct Btree Btree; +typedef struct BtCursor BtCursor; +typedef struct BtShared BtShared; + + +SQLITE_PRIVATE int sqlite3BtreeOpen( + sqlite3_vfs *pVfs, /* VFS to use with this b-tree */ + const char *zFilename, /* Name of database file to open */ + sqlite3 *db, /* Associated database connection */ + Btree **ppBtree, /* Return open Btree* here */ + int flags, /* Flags */ + int vfsFlags /* Flags passed through to VFS open */ +); + +/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the +** following values. +** +** NOTE: These values must match the corresponding PAGER_ values in +** pager.h. +*/ +#define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */ +#define BTREE_MEMORY 2 /* This is an in-memory DB */ +#define BTREE_SINGLE 4 /* The file contains at most 1 b-tree */ +#define BTREE_UNORDERED 8 /* Use of a hash implementation is OK */ + +SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); +SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); +#if SQLITE_MAX_MMAP_SIZE>0 +SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64); +#endif +SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(Btree*,unsigned); +SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); +SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); +SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); +SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); +SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*); +SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree*); +SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p); +SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); +SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); +SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); +SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); +SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); +SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int,int); +SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags); +SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*); +SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*); +SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); +SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); +SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree); +SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock); +SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int); + +SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); +SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *); +SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *); + +SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *); + +/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR +** of the flags shown below. +** +** Every SQLite table must have either BTREE_INTKEY or BTREE_BLOBKEY set. +** With BTREE_INTKEY, the table key is a 64-bit integer and arbitrary data +** is stored in the leaves. (BTREE_INTKEY is used for SQL tables.) With +** BTREE_BLOBKEY, the key is an arbitrary BLOB and no content is stored +** anywhere - the key is the content. (BTREE_BLOBKEY is used for SQL +** indices.) +*/ +#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ +#define BTREE_BLOBKEY 2 /* Table has keys only - no data */ + +SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); +SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); +SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree*, int, int); + +SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); +SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); + +SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p); + +/* +** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta +** should be one of the following values. The integer values are assigned +** to constants so that the offset of the corresponding field in an +** SQLite database header may be found using the following formula: +** +** offset = 36 + (idx * 4) +** +** For example, the free-page-count field is located at byte offset 36 of +** the database file header. The incr-vacuum-flag field is located at +** byte offset 64 (== 36+4*7). +** +** The BTREE_DATA_VERSION value is not really a value stored in the header. +** It is a read-only number computed by the pager. But we merge it with +** the header value access routines since its access pattern is the same. +** Call it a "virtual meta value". +*/ +#define BTREE_FREE_PAGE_COUNT 0 +#define BTREE_SCHEMA_VERSION 1 +#define BTREE_FILE_FORMAT 2 +#define BTREE_DEFAULT_CACHE_SIZE 3 +#define BTREE_LARGEST_ROOT_PAGE 4 +#define BTREE_TEXT_ENCODING 5 +#define BTREE_USER_VERSION 6 +#define BTREE_INCR_VACUUM 7 +#define BTREE_APPLICATION_ID 8 +#define BTREE_DATA_VERSION 15 /* A virtual meta-value */ + +/* +** Values that may be OR'd together to form the second argument of an +** sqlite3BtreeCursorHints() call. +** +** The BTREE_BULKLOAD flag is set on index cursors when the index is going +** to be filled with content that is already in sorted order. +** +** The BTREE_SEEK_EQ flag is set on cursors that will get OP_SeekGE or +** OP_SeekLE opcodes for a range search, but where the range of entries +** selected will all have the same key. In other words, the cursor will +** be used only for equality key searches. +** +*/ +#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */ +#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */ + +SQLITE_PRIVATE int sqlite3BtreeCursor( + Btree*, /* BTree containing table to open */ + int iTable, /* Index of root page */ + int wrFlag, /* 1 for writing. 0 for read-only */ + struct KeyInfo*, /* First argument to compare function */ + BtCursor *pCursor /* Space to write cursor structure */ +); +SQLITE_PRIVATE int sqlite3BtreeCursorSize(void); +SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*); + +SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( + BtCursor*, + UnpackedRecord *pUnKey, + i64 intKey, + int bias, + int *pRes +); +SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*); +SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, + const void *pData, int nData, + int nZero, int bias, int seekResult); +SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor*, i64 *pSize); +SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); +SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, u32 *pAmt); +SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, u32 *pAmt); +SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); +SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); + +SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); +SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*); + +SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); +SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *); +SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *); +SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); +SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask); +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask); +#endif +SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *pBt); +SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void); + +#ifndef NDEBUG +SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*); +#endif + +#ifndef SQLITE_OMIT_BTREECOUNT +SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *); +#endif + +#ifdef SQLITE_TEST +SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int); +SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*); +#endif + +#ifndef SQLITE_OMIT_WAL +SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); +#endif + +/* +** If we are not using shared cache, then there is no need to +** use mutexes to access the BtShared structures. So make the +** Enter and Leave procedures no-ops. +*/ +#ifndef SQLITE_OMIT_SHARED_CACHE +SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*); +SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*); +#else +# define sqlite3BtreeEnter(X) +# define sqlite3BtreeEnterAll(X) +#endif + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE +SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*); +SQLITE_PRIVATE void sqlite3BtreeLeave(Btree*); +SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*); +SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor*); +SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3*); +#ifndef NDEBUG + /* These routines are used inside assert() statements only. */ +SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree*); +SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3*); +SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*); +#endif +#else + +# define sqlite3BtreeSharable(X) 0 +# define sqlite3BtreeLeave(X) +# define sqlite3BtreeEnterCursor(X) +# define sqlite3BtreeLeaveCursor(X) +# define sqlite3BtreeLeaveAll(X) + +# define sqlite3BtreeHoldsMutex(X) 1 +# define sqlite3BtreeHoldsAllMutexes(X) 1 +# define sqlite3SchemaMutexHeld(X,Y,Z) 1 +#endif + + +#endif /* _BTREE_H_ */ + +/************** End of btree.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include vdbe.h in the middle of sqliteInt.h ******************/ +/************** Begin file vdbe.h ********************************************/ +/* +** 2001 September 15 +** +** 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. +** +************************************************************************* +** Header file for the Virtual DataBase Engine (VDBE) +** +** This header defines the interface to the virtual database engine +** or VDBE. The VDBE implements an abstract machine that runs a +** simple program to access and modify the underlying database. +*/ +#ifndef _SQLITE_VDBE_H_ +#define _SQLITE_VDBE_H_ +/* #include */ + +/* +** A single VDBE is an opaque structure named "Vdbe". Only routines +** in the source file sqliteVdbe.c are allowed to see the insides +** of this structure. +*/ +typedef struct Vdbe Vdbe; + +/* +** The names of the following types declared in vdbeInt.h are required +** for the VdbeOp definition. +*/ +typedef struct Mem Mem; +typedef struct SubProgram SubProgram; + +/* +** A single instruction of the virtual machine has an opcode +** and as many as three operands. The instruction is recorded +** as an instance of the following structure: +*/ +struct VdbeOp { + u8 opcode; /* What operation to perform */ + signed char p4type; /* One of the P4_xxx constants for p4 */ + u8 opflags; /* Mask of the OPFLG_* flags in opcodes.h */ + u8 p5; /* Fifth parameter is an unsigned character */ + int p1; /* First operand */ + int p2; /* Second parameter (often the jump destination) */ + int p3; /* The third parameter */ + union p4union { /* fourth parameter */ + int i; /* Integer value if p4type==P4_INT32 */ + void *p; /* Generic pointer */ + char *z; /* Pointer to data for string (char array) types */ + i64 *pI64; /* Used when p4type is P4_INT64 */ + double *pReal; /* Used when p4type is P4_REAL */ + FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */ + sqlite3_context *pCtx; /* Used when p4type is P4_FUNCCTX */ + CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ + Mem *pMem; /* Used when p4type is P4_MEM */ + VTable *pVtab; /* Used when p4type is P4_VTAB */ + KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ + int *ai; /* Used when p4type is P4_INTARRAY */ + SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ + int (*xAdvance)(BtCursor *, int *); + } p4; +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS + char *zComment; /* Comment to improve readability */ +#endif +#ifdef VDBE_PROFILE + u32 cnt; /* Number of times this instruction was executed */ + u64 cycles; /* Total time spent executing this instruction */ +#endif +#ifdef SQLITE_VDBE_COVERAGE + int iSrcLine; /* Source-code line that generated this opcode */ +#endif +}; +typedef struct VdbeOp VdbeOp; + + +/* +** A sub-routine used to implement a trigger program. +*/ +struct SubProgram { + VdbeOp *aOp; /* Array of opcodes for sub-program */ + int nOp; /* Elements in aOp[] */ + int nMem; /* Number of memory cells required */ + int nCsr; /* Number of cursors required */ + int nOnce; /* Number of OP_Once instructions */ + void *token; /* id that may be used to recursive triggers */ + SubProgram *pNext; /* Next sub-program already visited */ +}; + +/* +** A smaller version of VdbeOp used for the VdbeAddOpList() function because +** it takes up less space. +*/ +struct VdbeOpList { + u8 opcode; /* What operation to perform */ + signed char p1; /* First operand */ + signed char p2; /* Second parameter (often the jump destination) */ + signed char p3; /* Third parameter */ +}; +typedef struct VdbeOpList VdbeOpList; + +/* +** Allowed values of VdbeOp.p4type +*/ +#define P4_NOTUSED 0 /* The P4 parameter is not used */ +#define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ +#define P4_STATIC (-2) /* Pointer to a static string */ +#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ +#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ +#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ +#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ +#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ +#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */ +#define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */ +#define P4_REAL (-12) /* P4 is a 64-bit floating point value */ +#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ +#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ +#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ +#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */ +#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */ +#define P4_FUNCCTX (-20) /* P4 is a pointer to an sqlite3_context object */ + +/* Error message codes for OP_Halt */ +#define P5_ConstraintNotNull 1 +#define P5_ConstraintUnique 2 +#define P5_ConstraintCheck 3 +#define P5_ConstraintFK 4 + +/* +** The Vdbe.aColName array contains 5n Mem structures, where n is the +** number of columns of data returned by the statement. +*/ +#define COLNAME_NAME 0 +#define COLNAME_DECLTYPE 1 +#define COLNAME_DATABASE 2 +#define COLNAME_TABLE 3 +#define COLNAME_COLUMN 4 +#ifdef SQLITE_ENABLE_COLUMN_METADATA +# define COLNAME_N 5 /* Number of COLNAME_xxx symbols */ +#else +# ifdef SQLITE_OMIT_DECLTYPE +# define COLNAME_N 1 /* Store only the name */ +# else +# define COLNAME_N 2 /* Store the name and decltype */ +# endif +#endif + +/* +** The following macro converts a relative address in the p2 field +** of a VdbeOp structure into a negative number so that +** sqlite3VdbeAddOpList() knows that the address is relative. Calling +** the macro again restores the address. +*/ +#define ADDR(X) (-1-(X)) + +/* +** The makefile scans the vdbe.c source file and creates the "opcodes.h" +** header file that defines a number for each opcode used by the VDBE. +*/ +/************** Include opcodes.h in the middle of vdbe.h ********************/ +/************** Begin file opcodes.h *****************************************/ +/* Automatically generated. Do not edit */ +/* See the mkopcodeh.awk script for details */ +#define OP_Savepoint 1 +#define OP_AutoCommit 2 +#define OP_Transaction 3 +#define OP_SorterNext 4 +#define OP_PrevIfOpen 5 +#define OP_NextIfOpen 6 +#define OP_Prev 7 +#define OP_Next 8 +#define OP_Checkpoint 9 +#define OP_JournalMode 10 +#define OP_Vacuum 11 +#define OP_VFilter 12 /* synopsis: iplan=r[P3] zplan='P4' */ +#define OP_VUpdate 13 /* synopsis: data=r[P3@P2] */ +#define OP_Goto 14 +#define OP_Gosub 15 +#define OP_Return 16 +#define OP_InitCoroutine 17 +#define OP_EndCoroutine 18 +#define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ +#define OP_Yield 20 +#define OP_HaltIfNull 21 /* synopsis: if r[P3]=null halt */ +#define OP_Halt 22 +#define OP_Integer 23 /* synopsis: r[P2]=P1 */ +#define OP_Int64 24 /* synopsis: r[P2]=P4 */ +#define OP_String 25 /* synopsis: r[P2]='P4' (len=P1) */ +#define OP_Null 26 /* synopsis: r[P2..P3]=NULL */ +#define OP_SoftNull 27 /* synopsis: r[P1]=NULL */ +#define OP_Blob 28 /* synopsis: r[P2]=P4 (len=P1) */ +#define OP_Variable 29 /* synopsis: r[P2]=parameter(P1,P4) */ +#define OP_Move 30 /* synopsis: r[P2@P3]=r[P1@P3] */ +#define OP_Copy 31 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ +#define OP_SCopy 32 /* synopsis: r[P2]=r[P1] */ +#define OP_ResultRow 33 /* synopsis: output=r[P1@P2] */ +#define OP_CollSeq 34 +#define OP_Function0 35 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_Function 36 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_AddImm 37 /* synopsis: r[P1]=r[P1]+P2 */ +#define OP_MustBeInt 38 +#define OP_RealAffinity 39 +#define OP_Cast 40 /* synopsis: affinity(r[P1]) */ +#define OP_Permutation 41 +#define OP_Compare 42 /* synopsis: r[P1@P3] <-> r[P2@P3] */ +#define OP_Jump 43 +#define OP_Once 44 +#define OP_If 45 +#define OP_IfNot 46 +#define OP_Column 47 /* synopsis: r[P3]=PX */ +#define OP_Affinity 48 /* synopsis: affinity(r[P1@P2]) */ +#define OP_MakeRecord 49 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +#define OP_Count 50 /* synopsis: r[P2]=count() */ +#define OP_ReadCookie 51 +#define OP_SetCookie 52 +#define OP_ReopenIdx 53 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenRead 54 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenWrite 55 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenAutoindex 56 /* synopsis: nColumn=P2 */ +#define OP_OpenEphemeral 57 /* synopsis: nColumn=P2 */ +#define OP_SorterOpen 58 +#define OP_SequenceTest 59 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ +#define OP_OpenPseudo 60 /* synopsis: P3 columns in r[P2] */ +#define OP_Close 61 +#define OP_ColumnsUsed 62 +#define OP_SeekLT 63 /* synopsis: key=r[P3@P4] */ +#define OP_SeekLE 64 /* synopsis: key=r[P3@P4] */ +#define OP_SeekGE 65 /* synopsis: key=r[P3@P4] */ +#define OP_SeekGT 66 /* synopsis: key=r[P3@P4] */ +#define OP_Seek 67 /* synopsis: intkey=r[P2] */ +#define OP_NoConflict 68 /* synopsis: key=r[P3@P4] */ +#define OP_NotFound 69 /* synopsis: key=r[P3@P4] */ +#define OP_Found 70 /* synopsis: key=r[P3@P4] */ +#define OP_Or 71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ +#define OP_And 72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ +#define OP_NotExists 73 /* synopsis: intkey=r[P3] */ +#define OP_Sequence 74 /* synopsis: r[P2]=cursor[P1].ctr++ */ +#define OP_NewRowid 75 /* synopsis: r[P2]=rowid */ +#define OP_IsNull 76 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ +#define OP_NotNull 77 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ +#define OP_Ne 78 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */ +#define OP_Eq 79 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */ +#define OP_Gt 80 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */ +#define OP_Le 81 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */ +#define OP_Lt 82 /* same as TK_LT, synopsis: if r[P1]=r[P3] goto P2 */ +#define OP_Insert 84 /* synopsis: intkey=r[P3] data=r[P2] */ +#define OP_BitAnd 85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ +#define OP_BitOr 86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ +#define OP_ShiftLeft 87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */ +#define OP_Add 89 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ +#define OP_Subtract 90 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ +#define OP_Multiply 91 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ +#define OP_Divide 92 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ +#define OP_Remainder 93 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ +#define OP_Concat 94 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ +#define OP_InsertInt 95 /* synopsis: intkey=P3 data=r[P2] */ +#define OP_BitNot 96 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ +#define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ +#define OP_Delete 98 +#define OP_ResetCount 99 +#define OP_SorterCompare 100 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ +#define OP_SorterData 101 /* synopsis: r[P2]=data */ +#define OP_RowKey 102 /* synopsis: r[P2]=key */ +#define OP_RowData 103 /* synopsis: r[P2]=data */ +#define OP_Rowid 104 /* synopsis: r[P2]=rowid */ +#define OP_NullRow 105 +#define OP_Last 106 +#define OP_SorterSort 107 +#define OP_Sort 108 +#define OP_Rewind 109 +#define OP_SorterInsert 110 +#define OP_IdxInsert 111 /* synopsis: key=r[P2] */ +#define OP_IdxDelete 112 /* synopsis: key=r[P2@P3] */ +#define OP_IdxRowid 113 /* synopsis: r[P2]=rowid */ +#define OP_IdxLE 114 /* synopsis: key=r[P3@P4] */ +#define OP_IdxGT 115 /* synopsis: key=r[P3@P4] */ +#define OP_IdxLT 116 /* synopsis: key=r[P3@P4] */ +#define OP_IdxGE 117 /* synopsis: key=r[P3@P4] */ +#define OP_Destroy 118 +#define OP_Clear 119 +#define OP_ResetSorter 120 +#define OP_CreateIndex 121 /* synopsis: r[P2]=root iDb=P1 */ +#define OP_CreateTable 122 /* synopsis: r[P2]=root iDb=P1 */ +#define OP_ParseSchema 123 +#define OP_LoadAnalysis 124 +#define OP_DropTable 125 +#define OP_DropIndex 126 +#define OP_DropTrigger 127 +#define OP_IntegrityCk 128 +#define OP_RowSetAdd 129 /* synopsis: rowset(P1)=r[P2] */ +#define OP_RowSetRead 130 /* synopsis: r[P3]=rowset(P1) */ +#define OP_RowSetTest 131 /* synopsis: if r[P3] in rowset(P1) goto P2 */ +#define OP_Program 132 +#define OP_Real 133 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ +#define OP_Param 134 +#define OP_FkCounter 135 /* synopsis: fkctr[P1]+=P2 */ +#define OP_FkIfZero 136 /* synopsis: if fkctr[P1]==0 goto P2 */ +#define OP_MemMax 137 /* synopsis: r[P1]=max(r[P1],r[P2]) */ +#define OP_IfPos 138 /* synopsis: if r[P1]>0 goto P2 */ +#define OP_IfNeg 139 /* synopsis: r[P1]+=P3, if r[P1]<0 goto P2 */ +#define OP_IfNotZero 140 /* synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2 */ +#define OP_DecrJumpZero 141 /* synopsis: if (--r[P1])==0 goto P2 */ +#define OP_JumpZeroIncr 142 /* synopsis: if (r[P1]++)==0 ) goto P2 */ +#define OP_AggStep0 143 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggStep 144 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggFinal 145 /* synopsis: accum=r[P1] N=P2 */ +#define OP_IncrVacuum 146 +#define OP_Expire 147 +#define OP_TableLock 148 /* synopsis: iDb=P1 root=P2 write=P3 */ +#define OP_VBegin 149 +#define OP_VCreate 150 +#define OP_VDestroy 151 +#define OP_VOpen 152 +#define OP_VColumn 153 /* synopsis: r[P3]=vcolumn(P2) */ +#define OP_VNext 154 +#define OP_VRename 155 +#define OP_Pagecount 156 +#define OP_MaxPgcnt 157 +#define OP_Init 158 /* synopsis: Start at P2 */ +#define OP_Noop 159 +#define OP_Explain 160 + + +/* Properties such as "out2" or "jump" that are specified in +** comments following the "case" for each opcode in the vdbe.c +** are encoded into bitvectors as follows: +*/ +#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */ +#define OPFLG_IN1 0x0002 /* in1: P1 is an input */ +#define OPFLG_IN2 0x0004 /* in2: P2 is an input */ +#define OPFLG_IN3 0x0008 /* in3: P3 is an input */ +#define OPFLG_OUT2 0x0010 /* out2: P2 is an output */ +#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */ +#define OPFLG_INITIALIZER {\ +/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,\ +/* 8 */ 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01,\ +/* 16 */ 0x02, 0x01, 0x02, 0x12, 0x03, 0x08, 0x00, 0x10,\ +/* 24 */ 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00,\ +/* 32 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x02,\ +/* 40 */ 0x02, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x00,\ +/* 48 */ 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00,\ +/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,\ +/* 64 */ 0x09, 0x09, 0x09, 0x04, 0x09, 0x09, 0x09, 0x26,\ +/* 72 */ 0x26, 0x09, 0x10, 0x10, 0x03, 0x03, 0x0b, 0x0b,\ +/* 80 */ 0x0b, 0x0b, 0x0b, 0x0b, 0x00, 0x26, 0x26, 0x26,\ +/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00,\ +/* 96 */ 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 104 */ 0x10, 0x00, 0x01, 0x01, 0x01, 0x01, 0x04, 0x04,\ +/* 112 */ 0x00, 0x10, 0x01, 0x01, 0x01, 0x01, 0x10, 0x00,\ +/* 120 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 128 */ 0x00, 0x06, 0x23, 0x0b, 0x01, 0x10, 0x10, 0x00,\ +/* 136 */ 0x01, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00,\ +/* 144 */ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 152 */ 0x00, 0x00, 0x01, 0x00, 0x10, 0x10, 0x01, 0x00,\ +/* 160 */ 0x00,} + +/************** End of opcodes.h *********************************************/ +/************** Continuing where we left off in vdbe.h ***********************/ + +/* +** Prototypes for the VDBE interface. See comments on the implementation +** for a description of what each of these routines does. +*/ +SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse*); +SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); +SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); +SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); +SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); +SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); +SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5); +SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr); +SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr); +SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op); +SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); +SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*); +SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); +SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); +SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*); +SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); +SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int); +#endif +SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe*); +SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int); +SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); +SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*); +SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int); +SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*); +SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); +SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8); +SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int); +#ifndef SQLITE_OMIT_TRACE +SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*); +#endif +SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); + +SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); +SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); +SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int); +SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); + +typedef int (*RecordCompare)(int,const void*,UnpackedRecord*); +SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); + +#ifndef SQLITE_OMIT_TRIGGER +SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); +#endif + +/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on +** each VDBE opcode. +** +** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op +** comments in VDBE programs that show key decision points in the code +** generator. +*/ +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS +SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe*, const char*, ...); +# define VdbeComment(X) sqlite3VdbeComment X +SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); +# define VdbeNoopComment(X) sqlite3VdbeNoopComment X +# ifdef SQLITE_ENABLE_MODULE_COMMENTS +# define VdbeModuleComment(X) sqlite3VdbeNoopComment X +# else +# define VdbeModuleComment(X) +# endif +#else +# define VdbeComment(X) +# define VdbeNoopComment(X) +# define VdbeModuleComment(X) +#endif + +/* +** The VdbeCoverage macros are used to set a coverage testing point +** for VDBE branch instructions. The coverage testing points are line +** numbers in the sqlite3.c source file. VDBE branch coverage testing +** only works with an amalagmation build. That's ok since a VDBE branch +** coverage build designed for testing the test suite only. No application +** should ever ship with VDBE branch coverage measuring turned on. +** +** VdbeCoverage(v) // Mark the previously coded instruction +** // as a branch +** +** VdbeCoverageIf(v, conditional) // Mark previous if conditional true +** +** VdbeCoverageAlwaysTaken(v) // Previous branch is always taken +** +** VdbeCoverageNeverTaken(v) // Previous branch is never taken +** +** Every VDBE branch operation must be tagged with one of the macros above. +** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and +** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch() +** routine in vdbe.c, alerting the developer to the missed tag. +*/ +#ifdef SQLITE_VDBE_COVERAGE +SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe*,int); +# define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__) +# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__) +# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2); +# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1); +# define VDBE_OFFSET_LINENO(x) (__LINE__+x) +#else +# define VdbeCoverage(v) +# define VdbeCoverageIf(v,x) +# define VdbeCoverageAlwaysTaken(v) +# define VdbeCoverageNeverTaken(v) +# define VDBE_OFFSET_LINENO(x) 0 +#endif + +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS +SQLITE_PRIVATE void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*); +#else +# define sqlite3VdbeScanStatus(a,b,c,d,e) +#endif + +#endif + +/************** End of vdbe.h ************************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include pager.h in the middle of sqliteInt.h *****************/ +/************** Begin file pager.h *******************************************/ +/* +** 2001 September 15 +** +** 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. The page cache subsystem reads and writes a file a page +** at a time and provides a journal for rollback. +*/ + +#ifndef _PAGER_H_ +#define _PAGER_H_ + +/* +** Default maximum size for persistent journal files. A negative +** value means no limit. This value may be overridden using the +** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit". +*/ +#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT + #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1 +#endif + +/* +** The type used to represent a page number. The first page in a file +** is called page 1. 0 is used to represent "not a page". +*/ +typedef u32 Pgno; + +/* +** Each open file is managed by a separate instance of the "Pager" structure. +*/ +typedef struct Pager Pager; + +/* +** Handle type for pages. +*/ +typedef struct PgHdr DbPage; + +/* +** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is +** reserved for working around a windows/posix incompatibility). It is +** used in the journal to signify that the remainder of the journal file +** is devoted to storing a master journal name - there are no more pages to +** roll back. See comments for function writeMasterJournal() in pager.c +** for details. +*/ +#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1)) + +/* +** Allowed values for the flags parameter to sqlite3PagerOpen(). +** +** NOTE: These values must match the corresponding BTREE_ values in btree.h. +*/ +#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ +#define PAGER_MEMORY 0x0002 /* In-memory database */ + +/* +** Valid values for the second argument to sqlite3PagerLockingMode(). +*/ +#define PAGER_LOCKINGMODE_QUERY -1 +#define PAGER_LOCKINGMODE_NORMAL 0 +#define PAGER_LOCKINGMODE_EXCLUSIVE 1 + +/* +** Numeric constants that encode the journalmode. +*/ +#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */ +#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */ +#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */ +#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */ +#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */ +#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */ +#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */ + +/* +** Flags that make up the mask passed to sqlite3PagerAcquire(). +*/ +#define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */ +#define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */ + +/* +** Flags for sqlite3PagerSetFlags() +*/ +#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */ +#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */ +#define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */ +#define PAGER_SYNCHRONOUS_MASK 0x03 /* Mask for three values above */ +#define PAGER_FULLFSYNC 0x04 /* PRAGMA fullfsync=ON */ +#define PAGER_CKPT_FULLFSYNC 0x08 /* PRAGMA checkpoint_fullfsync=ON */ +#define PAGER_CACHESPILL 0x10 /* PRAGMA cache_spill=ON */ +#define PAGER_FLAGS_MASK 0x1c /* All above except SYNCHRONOUS */ + +/* +** The remainder of this file contains the declarations of the functions +** that make up the Pager sub-system API. See source code comments for +** a detailed description of each routine. +*/ + +/* Open and close a Pager connection. */ +SQLITE_PRIVATE int sqlite3PagerOpen( + sqlite3_vfs*, + Pager **ppPager, + const char*, + int, + int, + int, + void(*)(DbPage*) +); +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); + +/* Functions used to configure a Pager object. */ +SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); +SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); +SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); +SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); +SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64); +SQLITE_PRIVATE void sqlite3PagerShrink(Pager*); +SQLITE_PRIVATE void sqlite3PagerSetFlags(Pager*,unsigned); +SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); +SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int); +SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); +SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*); +SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64); +SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*); + +/* Functions used to obtain and release page references. */ +SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); +#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) +SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); +SQLITE_PRIVATE void sqlite3PagerRef(DbPage*); +SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*); +SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*); + +/* Operations on page references. */ +SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*); +SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*); +SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int); +SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*); +SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *); +SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *); + +/* Functions used to manage pager transactions and savepoints. */ +SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*); +SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int); +SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int); +SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*); +SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster); +SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); +SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); +SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); +SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); +SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); + +#ifndef SQLITE_OMIT_WAL +SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); +SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); +#endif + +#ifdef SQLITE_ENABLE_ZIPVFS +SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); +#endif + +/* Functions used to query pager state and configuration. */ +SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); +SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*); +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); +#endif +SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); +SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int); +SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*); +SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); +SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*); +SQLITE_PRIVATE int sqlite3PagerNosync(Pager*); +SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); +SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); +SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *); +SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *); +SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); + +/* Functions used to truncate the database file. */ +SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); + +SQLITE_PRIVATE void sqlite3PagerRekey(DbPage*, Pgno, u16); + +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL) +SQLITE_PRIVATE void *sqlite3PagerCodec(DbPage *); +#endif + +/* Functions to support testing and debugging. */ +#if !defined(NDEBUG) || defined(SQLITE_TEST) +SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*); +SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage*); +#endif +#ifdef SQLITE_TEST +SQLITE_PRIVATE int *sqlite3PagerStats(Pager*); +SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*); + void disable_simulated_io_errors(void); + void enable_simulated_io_errors(void); +#else +# define disable_simulated_io_errors() +# define enable_simulated_io_errors() +#endif + +#endif /* _PAGER_H_ */ + +/************** End of pager.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include pcache.h in the middle of sqliteInt.h ****************/ +/************** Begin file pcache.h ******************************************/ +/* +** 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. +*/ + +#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 { + sqlite3_pcache_page *pPage; /* Pcache object page handle */ + void *pData; /* Page data */ + void *pExtra; /* Extra content */ + PgHdr *pDirty; /* Transient list of dirty pages */ + Pager *pPager; /* The pager this page is part of */ + Pgno pgno; /* Page number for this page */ +#ifdef SQLITE_CHECK_PAGES + u32 pageHash; /* Hash of page content */ +#endif + u16 flags; /* PGHDR flags defined below */ + + /********************************************************************** + ** Elements above are public. All that follows is private to pcache.c + ** and should not be accessed by other modules. + */ + i16 nRef; /* Number of users of this page */ + PCache *pCache; /* Cache that owns this page */ + + PgHdr *pDirtyNext; /* Next element in list of dirty pages */ + PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */ +}; + +/* Bit values for PgHdr.flags */ +#define PGHDR_CLEAN 0x001 /* Page not on the PCache.pDirty list */ +#define PGHDR_DIRTY 0x002 /* Page is on the PCache.pDirty list */ +#define PGHDR_WRITEABLE 0x004 /* Journaled and ready to modify */ +#define PGHDR_NEED_SYNC 0x008 /* Fsync the rollback journal before + ** writing this page to the database */ +#define PGHDR_NEED_READ 0x010 /* Content is unread */ +#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ +#define PGHDR_MMAP 0x040 /* This is an mmap page object */ + +/* Initialize and shutdown the page cache subsystem */ +SQLITE_PRIVATE int sqlite3PcacheInitialize(void); +SQLITE_PRIVATE void sqlite3PcacheShutdown(void); + +/* Page cache buffer management: +** These routines implement SQLITE_CONFIG_PAGECACHE. +*/ +SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *, int sz, int n); + +/* Create a new pager cache. +** Under memory stress, invoke xStress to try to make pages clean. +** Only clean and unpinned pages can be reclaimed. +*/ +SQLITE_PRIVATE int sqlite3PcacheOpen( + int szPage, /* Size of every page */ + int szExtra, /* Extra space associated with each page */ + int bPurgeable, /* True if pages are on backing store */ + int (*xStress)(void*, PgHdr*), /* 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. */ +SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *, int); + +/* Return the size in bytes of a PCache object. Used to preallocate +** storage space. +*/ +SQLITE_PRIVATE int sqlite3PcacheSize(void); + +/* One release per successful fetch. Page is pinned until released. +** Reference counted. +*/ +SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch(PCache*, Pgno, int createFlag); +SQLITE_PRIVATE int sqlite3PcacheFetchStress(PCache*, Pgno, sqlite3_pcache_page**); +SQLITE_PRIVATE PgHdr *sqlite3PcacheFetchFinish(PCache*, Pgno, sqlite3_pcache_page *pPage); +SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*); + +SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */ +SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */ +SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */ +SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */ + +/* Change a page number. Used by incr-vacuum. */ +SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr*, Pgno); + +/* Remove all pages with pgno>x. Reset the cache if x==0 */ +SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache*, Pgno x); + +/* Get a list of all dirty pages in the cache, sorted by page number */ +SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*); + +/* Reset and close the cache object */ +SQLITE_PRIVATE void sqlite3PcacheClose(PCache*); + +/* Clear flags from pages of the page cache */ +SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *); + +/* Discard the contents of the cache */ +SQLITE_PRIVATE void sqlite3PcacheClear(PCache*); + +/* Return the total number of outstanding page references */ +SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache*); + +/* Increment the reference count of an existing page */ +SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*); + +SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*); + +/* Return the total number of pages stored in the cache */ +SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*); + +#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) +/* Iterate through all dirty pages currently stored in the cache. This +** interface is only available if SQLITE_CHECK_PAGES is defined when the +** library is built. +*/ +SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)); +#endif + +/* Set and get the suggested cache-size for the specified pager-cache. +** +** 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. +*/ +SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *, int); +#ifdef SQLITE_TEST +SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *); +#endif + +/* Free up as much memory as possible from the page cache */ +SQLITE_PRIVATE void sqlite3PcacheShrink(PCache*); + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +/* Try to return memory used by the pcache module to the main memory heap */ +SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int); +#endif + +#ifdef SQLITE_TEST +SQLITE_PRIVATE void sqlite3PcacheStats(int*,int*,int*,int*); +#endif + +SQLITE_PRIVATE void sqlite3PCacheSetDefault(void); + +/* Return the header size */ +SQLITE_PRIVATE int sqlite3HeaderSizePcache(void); +SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void); + +#endif /* _PCACHE_H_ */ + +/************** End of pcache.h **********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + +/************** Include os.h in the middle of sqliteInt.h ********************/ +/************** Begin file os.h **********************************************/ +/* +** 2001 September 16 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This header file (together with is companion C source-code file +** "os.c") attempt to abstract the underlying operating system so that +** the SQLite library will work on both POSIX and windows systems. +** +** This header file is #include-ed by sqliteInt.h and thus ends up +** being included by every source file. +*/ +#ifndef _SQLITE_OS_H_ +#define _SQLITE_OS_H_ + +/* +** Attempt to automatically detect the operating system and setup the +** necessary pre-processor macros for it. +*/ +/************** Include os_setup.h in the middle of os.h *********************/ +/************** Begin file os_setup.h ****************************************/ +/* +** 2013 November 25 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains pre-processor directives related to operating system +** detection and/or setup. +*/ +#ifndef _OS_SETUP_H_ +#define _OS_SETUP_H_ + +/* +** Figure out if we are dealing with Unix, Windows, or some other operating +** system. +** +** After the following block of preprocess macros, all of SQLITE_OS_UNIX, +** SQLITE_OS_WIN, and SQLITE_OS_OTHER will defined to either 1 or 0. One of +** the three will be 1. The other two will be 0. +*/ +#if defined(SQLITE_OS_OTHER) +# if SQLITE_OS_OTHER==1 +# undef SQLITE_OS_UNIX +# define SQLITE_OS_UNIX 0 +# undef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +# else +# undef SQLITE_OS_OTHER +# endif +#endif +#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER) +# define SQLITE_OS_OTHER 0 +# ifndef SQLITE_OS_WIN +# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \ + defined(__MINGW32__) || defined(__BORLANDC__) +# define SQLITE_OS_WIN 1 +# define SQLITE_OS_UNIX 0 +# else +# define SQLITE_OS_WIN 0 +# define SQLITE_OS_UNIX 1 +# endif +# else +# define SQLITE_OS_UNIX 0 +# endif +#else +# ifndef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +# endif +#endif + +#endif /* _OS_SETUP_H_ */ + +/************** End of os_setup.h ********************************************/ +/************** Continuing where we left off in os.h *************************/ + +/* If the SET_FULLSYNC macro is not defined above, then make it +** a no-op +*/ +#ifndef SET_FULLSYNC +# define SET_FULLSYNC(x,y) +#endif + +/* +** The default size of a disk sector +*/ +#ifndef SQLITE_DEFAULT_SECTOR_SIZE +# define SQLITE_DEFAULT_SECTOR_SIZE 4096 +#endif + +/* +** Temporary files are named starting with this prefix followed by 16 random +** alphanumeric characters, and no file extension. They are stored in the +** OS's standard temporary file directory, and are deleted prior to exit. +** If sqlite is being embedded in another program, you may wish to change the +** prefix to reflect your program's name, so that if your program exits +** prematurely, old temporary files can be easily identified. This can be done +** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line. +** +** 2006-10-31: The default prefix used to be "sqlite_". But then +** Mcafee started using SQLite in their anti-virus product and it +** started putting files with the "sqlite" name in the c:/temp folder. +** This annoyed many windows users. Those users would then do a +** Google search for "sqlite", find the telephone numbers of the +** developers and call to wake them up at night and complain. +** For this reason, the default name prefix is changed to be "sqlite" +** spelled backwards. So the temp files are still identified, but +** anybody smart enough to figure out the code is also likely smart +** enough to know that calling the developer will not help get rid +** of the file. +*/ +#ifndef SQLITE_TEMP_FILE_PREFIX +# define SQLITE_TEMP_FILE_PREFIX "etilqs_" +#endif + +/* +** The following values may be passed as the second argument to +** sqlite3OsLock(). The various locks exhibit the following semantics: +** +** SHARED: Any number of processes may hold a SHARED lock simultaneously. +** RESERVED: A single process may hold a RESERVED lock on a file at +** any time. Other processes may hold and obtain new SHARED locks. +** PENDING: A single process may hold a PENDING lock on a file at +** any one time. Existing SHARED locks may persist, but no new +** SHARED locks may be obtained by other processes. +** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks. +** +** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a +** process that requests an EXCLUSIVE lock may actually obtain a PENDING +** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to +** sqlite3OsLock(). +*/ +#define NO_LOCK 0 +#define SHARED_LOCK 1 +#define RESERVED_LOCK 2 +#define PENDING_LOCK 3 +#define EXCLUSIVE_LOCK 4 + +/* +** File Locking Notes: (Mostly about windows but also some info for Unix) +** +** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because +** those functions are not available. So we use only LockFile() and +** UnlockFile(). +** +** LockFile() prevents not just writing but also reading by other processes. +** A SHARED_LOCK is obtained by locking a single randomly-chosen +** byte out of a specific range of bytes. The lock byte is obtained at +** random so two separate readers can probably access the file at the +** same time, unless they are unlucky and choose the same lock byte. +** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range. +** There can only be one writer. A RESERVED_LOCK is obtained by locking +** a single byte of the file that is designated as the reserved lock byte. +** A PENDING_LOCK is obtained by locking a designated byte different from +** the RESERVED_LOCK byte. +** +** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available, +** which means we can use reader/writer locks. When reader/writer locks +** are used, the lock is placed on the same range of bytes that is used +** for probabilistic locking in Win95/98/ME. Hence, the locking scheme +** will support two or more Win95 readers or two or more WinNT readers. +** But a single Win95 reader will lock out all WinNT readers and a single +** WinNT reader will lock out all other Win95 readers. +** +** The following #defines specify the range of bytes used for locking. +** SHARED_SIZE is the number of bytes available in the pool from which +** a random byte is selected for a shared lock. The pool of bytes for +** shared locks begins at SHARED_FIRST. +** +** The same locking strategy and +** byte ranges are used for Unix. This leaves open the possibility of having +** clients on win95, winNT, and unix all talking to the same shared file +** and all locking correctly. To do so would require that samba (or whatever +** tool is being used for file sharing) implements locks correctly between +** windows and unix. I'm guessing that isn't likely to happen, but by +** using the same locking range we are at least open to the possibility. +** +** Locking in windows is manditory. For this reason, we cannot store +** actual data in the bytes used for locking. The pager never allocates +** the pages involved in locking therefore. SHARED_SIZE is selected so +** that all locks will fit on a single page even at the minimum page size. +** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE +** is set high so that we don't have to allocate an unused page except +** for very large databases. But one should test the page skipping logic +** by setting PENDING_BYTE low and running the entire regression suite. +** +** Changing the value of PENDING_BYTE results in a subtly incompatible +** file format. Depending on how it is changed, you might not notice +** the incompatibility right away, even running a full regression test. +** The default location of PENDING_BYTE is the first byte past the +** 1GB boundary. +** +*/ +#ifdef SQLITE_OMIT_WSD +# define PENDING_BYTE (0x40000000) +#else +# define PENDING_BYTE sqlite3PendingByte +#endif +#define RESERVED_BYTE (PENDING_BYTE+1) +#define SHARED_FIRST (PENDING_BYTE+2) +#define SHARED_SIZE 510 + +/* +** Wrapper around OS specific sqlite3_os_init() function. +*/ +SQLITE_PRIVATE int sqlite3OsInit(void); + +/* +** Functions for accessing sqlite3_file methods +*/ +SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file*); +SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset); +SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset); +SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size); +SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize); +SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut); +SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*); +SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file*,int,void*); +#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0 +SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id); +SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id); +SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **); +SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int); +SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id); +SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int); +SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **); +SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *); + + +/* +** Functions for accessing sqlite3_vfs methods +*/ +SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *); +SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int); +SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut); +SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *); +#ifndef SQLITE_OMIT_LOAD_EXTENSION +SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *); +SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *); +SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void); +SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *); +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ +SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *); +SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int); +SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*); + +/* +** Convenience functions for opening and closing files using +** sqlite3_malloc() to obtain space for the file-handle structure. +*/ +SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*); +SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *); + +#endif /* _SQLITE_OS_H_ */ + +/************** End of os.h **************************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include mutex.h in the middle of sqliteInt.h *****************/ +/************** Begin file mutex.h *******************************************/ +/* +** 2007 August 28 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains the common header for all mutex implementations. +** The sqliteInt.h header #includes this file so that it is available +** to all source files. We break it out in an effort to keep the code +** better organized. +** +** NOTE: source files should *not* #include this header file directly. +** Source files should #include the sqliteInt.h file and let that file +** include this one indirectly. +*/ + + +/* +** Figure out what version of the code to use. The choices are +** +** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The +** mutexes implementation cannot be overridden +** at start-time. +** +** SQLITE_MUTEX_NOOP For single-threaded applications. No +** mutual exclusion is provided. But this +** implementation can be overridden at +** start-time. +** +** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix. +** +** SQLITE_MUTEX_W32 For multi-threaded applications on Win32. +*/ +#if !SQLITE_THREADSAFE +# define SQLITE_MUTEX_OMIT +#endif +#if SQLITE_THREADSAFE && !defined(SQLITE_MUTEX_NOOP) +# if SQLITE_OS_UNIX +# define SQLITE_MUTEX_PTHREADS +# elif SQLITE_OS_WIN +# define SQLITE_MUTEX_W32 +# else +# define SQLITE_MUTEX_NOOP +# endif +#endif + +#ifdef SQLITE_MUTEX_OMIT +/* +** If this is a no-op implementation, implement everything as macros. +*/ +#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8) +#define sqlite3_mutex_free(X) +#define sqlite3_mutex_enter(X) +#define sqlite3_mutex_try(X) SQLITE_OK +#define sqlite3_mutex_leave(X) +#define sqlite3_mutex_held(X) ((void)(X),1) +#define sqlite3_mutex_notheld(X) ((void)(X),1) +#define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8) +#define sqlite3MutexInit() SQLITE_OK +#define sqlite3MutexEnd() +#define MUTEX_LOGIC(X) +#else +#define MUTEX_LOGIC(X) X +#endif /* defined(SQLITE_MUTEX_OMIT) */ + +/************** End of mutex.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + + +/* +** Each database file to be accessed by the system is an instance +** of the following structure. There are normally two of these structures +** in the sqlite.aDb[] array. aDb[0] is the main database file and +** aDb[1] is the database file used to hold temporary tables. Additional +** databases may be attached. +*/ +struct Db { + char *zName; /* Name of this database */ + Btree *pBt; /* The B*Tree structure for this database file */ + u8 safety_level; /* How aggressive at syncing data to disk */ + Schema *pSchema; /* Pointer to database schema (possibly shared) */ +}; + +/* +** An instance of the following structure stores a database schema. +** +** Most Schema objects are associated with a Btree. The exception is +** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing. +** In shared cache mode, a single Schema object can be shared by multiple +** Btrees that refer to the same underlying BtShared object. +** +** Schema objects are automatically deallocated when the last Btree that +** references them is destroyed. The TEMP Schema is manually freed by +** sqlite3_close(). +* +** A thread must be holding a mutex on the corresponding Btree in order +** to access Schema content. This implies that the thread must also be +** holding a mutex on the sqlite3 connection pointer that owns the Btree. +** For a TEMP Schema, only the connection mutex is required. +*/ +struct Schema { + int schema_cookie; /* Database schema version number for this file */ + int iGeneration; /* Generation counter. Incremented with each change */ + Hash tblHash; /* All tables indexed by name */ + Hash idxHash; /* All (named) indices indexed by name */ + Hash trigHash; /* All triggers indexed by name */ + Hash fkeyHash; /* All foreign keys by referenced table name */ + Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ + u8 file_format; /* Schema format version for this file */ + u8 enc; /* Text encoding used by this database */ + u16 schemaFlags; /* Flags associated with this schema */ + int cache_size; /* Number of pages to use in the cache */ +}; + +/* +** These macros can be used to test, set, or clear bits in the +** Db.pSchema->flags field. +*/ +#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))==(P)) +#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))!=0) +#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags|=(P) +#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags&=~(P) + +/* +** Allowed values for the DB.pSchema->flags field. +** +** The DB_SchemaLoaded flag is set after the database schema has been +** read into internal hash tables. +** +** DB_UnresetViews means that one or more views have column names that +** have been filled out. If the schema changes, these column names might +** changes and so the view will need to be reset. +*/ +#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ +#define DB_UnresetViews 0x0002 /* Some views have defined column names */ +#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */ + +/* +** The number of different kinds of things that can be limited +** using the sqlite3_limit() interface. +*/ +#define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1) + +/* +** Lookaside malloc is a set of fixed-size buffers that can be used +** to satisfy small transient memory allocation requests for objects +** associated with a particular database connection. The use of +** lookaside malloc provides a significant performance enhancement +** (approx 10%) by avoiding numerous malloc/free requests while parsing +** SQL statements. +** +** The Lookaside structure holds configuration information about the +** lookaside malloc subsystem. Each available memory allocation in +** the lookaside subsystem is stored on a linked list of LookasideSlot +** objects. +** +** Lookaside allocations are only allowed for objects that are associated +** with a particular database connection. Hence, schema information cannot +** be stored in lookaside because in shared cache mode the schema information +** is shared by multiple database connections. Therefore, while parsing +** schema information, the Lookaside.bEnabled flag is cleared so that +** lookaside allocations are not used to construct the schema objects. +*/ +struct Lookaside { + u16 sz; /* Size of each buffer in bytes */ + u8 bEnabled; /* False to disable new lookaside allocations */ + u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ + int nOut; /* Number of buffers currently checked out */ + int mxOut; /* Highwater mark for nOut */ + int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ + LookasideSlot *pFree; /* List of available buffers */ + void *pStart; /* First byte of available memory space */ + void *pEnd; /* First byte past end of available space */ +}; +struct LookasideSlot { + LookasideSlot *pNext; /* Next buffer in the list of free buffers */ +}; + +/* +** A hash table for function definitions. +** +** Hash each FuncDef structure into one of the FuncDefHash.a[] slots. +** Collisions are on the FuncDef.pHash chain. +*/ +struct FuncDefHash { + FuncDef *a[23]; /* Hash table for functions */ +}; + +#ifdef SQLITE_USER_AUTHENTICATION +/* +** Information held in the "sqlite3" database connection object and used +** to manage user authentication. +*/ +typedef struct sqlite3_userauth sqlite3_userauth; +struct sqlite3_userauth { + u8 authLevel; /* Current authentication level */ + int nAuthPW; /* Size of the zAuthPW in bytes */ + char *zAuthPW; /* Password used to authenticate */ + char *zAuthUser; /* User name used to authenticate */ +}; + +/* Allowed values for sqlite3_userauth.authLevel */ +#define UAUTH_Unknown 0 /* Authentication not yet checked */ +#define UAUTH_Fail 1 /* User authentication failed */ +#define UAUTH_User 2 /* Authenticated as a normal user */ +#define UAUTH_Admin 3 /* Authenticated as an administrator */ + +/* Functions used only by user authorization logic */ +SQLITE_PRIVATE int sqlite3UserAuthTable(const char*); +SQLITE_PRIVATE int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*); +SQLITE_PRIVATE void sqlite3UserAuthInit(sqlite3*); +SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**); + +#endif /* SQLITE_USER_AUTHENTICATION */ + +/* +** typedef for the authorization callback function. +*/ +#ifdef SQLITE_USER_AUTHENTICATION + typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*, + const char*, const char*); +#else + typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*, + const char*); +#endif + + +/* +** Each database connection is an instance of the following structure. +*/ +struct sqlite3 { + sqlite3_vfs *pVfs; /* OS Interface */ + struct Vdbe *pVdbe; /* List of active virtual machines */ + CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ + sqlite3_mutex *mutex; /* Connection mutex */ + Db *aDb; /* All backends */ + int nDb; /* Number of backends currently in use */ + int flags; /* Miscellaneous flags. See below */ + i64 lastRowid; /* ROWID of most recent insert (see above) */ + i64 szMmap; /* Default mmap_size setting */ + unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ + int errCode; /* Most recent error code (SQLITE_*) */ + int errMask; /* & result codes with this before returning */ + u16 dbOptFlags; /* Flags to enable/disable optimizations */ + u8 enc; /* Text encoding */ + u8 autoCommit; /* The auto-commit flag. */ + u8 temp_store; /* 1: file 2: memory 0: default */ + u8 mallocFailed; /* True if we have seen a malloc failure */ + u8 dfltLockMode; /* Default locking-mode for attached dbs */ + signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ + u8 suppressErr; /* Do not issue error messages if true */ + u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ + u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ + int nextPagesize; /* Pagesize after VACUUM if >0 */ + u32 magic; /* Magic number for detect library misuse */ + int nChange; /* Value returned by sqlite3_changes() */ + int nTotalChange; /* Value returned by sqlite3_total_changes() */ + int aLimit[SQLITE_N_LIMIT]; /* Limits */ + int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */ + struct sqlite3InitInfo { /* Information used during initialization */ + int newTnum; /* Rootpage of table being initialized */ + u8 iDb; /* Which db file is being initialized */ + u8 busy; /* TRUE if currently initializing */ + u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ + u8 imposterTable; /* Building an imposter table */ + } init; + int nVdbeActive; /* Number of VDBEs currently running */ + int nVdbeRead; /* Number of active VDBEs that read or write */ + int nVdbeWrite; /* Number of active VDBEs that read and write */ + int nVdbeExec; /* Number of nested calls to VdbeExec() */ + int nVDestroy; /* Number of active OP_VDestroy operations */ + int nExtension; /* Number of loaded extensions */ + void **aExtension; /* Array of shared library handles */ + void (*xTrace)(void*,const char*); /* Trace function */ + void *pTraceArg; /* Argument to the trace function */ + void (*xProfile)(void*,const char*,u64); /* Profiling function */ + void *pProfileArg; /* Argument to profile function */ + void *pCommitArg; /* Argument to xCommitCallback() */ + int (*xCommitCallback)(void*); /* Invoked at every commit. */ + void *pRollbackArg; /* Argument to xRollbackCallback() */ + void (*xRollbackCallback)(void*); /* Invoked at every commit. */ + void *pUpdateArg; + void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); +#ifndef SQLITE_OMIT_WAL + int (*xWalCallback)(void *, sqlite3 *, const char *, int); + void *pWalArg; +#endif + void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); + void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); + void *pCollNeededArg; + sqlite3_value *pErr; /* Most recent error message */ + union { + volatile int isInterrupted; /* True if sqlite3_interrupt has been called */ + double notUsed1; /* Spacer */ + } u1; + Lookaside lookaside; /* Lookaside malloc configuration */ +#ifndef SQLITE_OMIT_AUTHORIZATION + sqlite3_xauth xAuth; /* Access authorization function */ + void *pAuthArg; /* 1st argument to the access auth function */ +#endif +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + int (*xProgress)(void *); /* The progress callback */ + void *pProgressArg; /* Argument to the progress callback */ + unsigned nProgressOps; /* Number of opcodes for progress callback */ +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + int nVTrans; /* Allocated size of aVTrans */ + Hash aModule; /* populated by sqlite3_create_module() */ + VtabCtx *pVtabCtx; /* Context for active vtab connect/create */ + VTable **aVTrans; /* Virtual tables with open transactions */ + VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */ +#endif + FuncDefHash aFunc; /* Hash table of connection functions */ + Hash aCollSeq; /* All collating sequences */ + BusyHandler busyHandler; /* Busy callback */ + Db aDbStatic[2]; /* Static space for the 2 default backends */ + Savepoint *pSavepoint; /* List of active savepoints */ + int busyTimeout; /* Busy handler timeout, in msec */ + int nSavepoint; /* Number of non-transaction savepoints */ + int nStatement; /* Number of nested statement-transactions */ + i64 nDeferredCons; /* Net deferred constraints this transaction. */ + i64 nDeferredImmCons; /* Net deferred immediate constraints */ + int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ +#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY + /* The following variables are all protected by the STATIC_MASTER + ** mutex, not by sqlite3.mutex. They are used by code in notify.c. + ** + ** When X.pUnlockConnection==Y, that means that X is waiting for Y to + ** unlock so that it can proceed. + ** + ** When X.pBlockingConnection==Y, that means that something that X tried + ** tried to do recently failed with an SQLITE_LOCKED error due to locks + ** held by Y. + */ + sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */ + sqlite3 *pUnlockConnection; /* Connection to watch for unlock */ + void *pUnlockArg; /* Argument to xUnlockNotify */ + void (*xUnlockNotify)(void **, int); /* Unlock notify callback */ + sqlite3 *pNextBlocked; /* Next in list of all blocked connections */ +#endif +#ifdef SQLITE_USER_AUTHENTICATION + sqlite3_userauth auth; /* User authentication information */ +#endif +}; + +/* +** A macro to discover the encoding of a database. +*/ +#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc) +#define ENC(db) ((db)->enc) + +/* +** Possible values for the sqlite3.flags. +*/ +#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ +#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */ +#define SQLITE_FullFSync 0x00000004 /* Use full fsync on the backend */ +#define SQLITE_CkptFullFSync 0x00000008 /* Use full fsync for checkpoint */ +#define SQLITE_CacheSpill 0x00000010 /* OK to spill pager cache */ +#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ +#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ +#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */ + /* DELETE, or UPDATE and return */ + /* the count using a callback. */ +#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ + /* result set is empty */ +#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */ +#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */ +#define SQLITE_VdbeAddopTrace 0x00001000 /* Trace sqlite3VdbeAddOp() calls */ +#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */ +#define SQLITE_ReadUncommitted 0x0004000 /* For shared-cache mode */ +#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */ +#define SQLITE_RecoveryMode 0x00010000 /* Ignore schema errors */ +#define SQLITE_ReverseOrder 0x00020000 /* Reverse unordered SELECTs */ +#define SQLITE_RecTriggers 0x00040000 /* Enable recursive triggers */ +#define SQLITE_ForeignKeys 0x00080000 /* Enforce foreign key constraints */ +#define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */ +#define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */ +#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */ +#define SQLITE_EnableTrigger 0x00800000 /* True to enable triggers */ +#define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */ +#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */ +#define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */ +#define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */ +#define SQLITE_CellSizeCk 0x10000000 /* Check btree cell sizes on load */ + + +/* +** Bits of the sqlite3.dbOptFlags field that are used by the +** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to +** selectively disable various optimizations. +*/ +#define SQLITE_QueryFlattener 0x0001 /* Query flattening */ +#define SQLITE_ColumnCache 0x0002 /* Column cache */ +#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ +#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ +/* not used 0x0010 // Was: SQLITE_IdxRealAsInt */ +#define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ +#define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ +#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ +#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */ +#define SQLITE_Transitive 0x0200 /* Transitive constraints */ +#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */ +#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */ +#define SQLITE_AllOpts 0xffff /* All optimizations */ + +/* +** Macros for testing whether or not optimizations are enabled or disabled. +*/ +#ifndef SQLITE_OMIT_BUILTIN_TEST +#define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) +#define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) +#else +#define OptimizationDisabled(db, mask) 0 +#define OptimizationEnabled(db, mask) 1 +#endif + +/* +** Return true if it OK to factor constant expressions into the initialization +** code. The argument is a Parse object for the code generator. +*/ +#define ConstFactorOk(P) ((P)->okConstFactor) + +/* +** Possible values for the sqlite.magic field. +** The numbers are obtained at random and have no special meaning, other +** than being distinct from one another. +*/ +#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ +#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ +#define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */ +#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ +#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ +#define SQLITE_MAGIC_ZOMBIE 0x64cffc7f /* Close with last statement close */ + +/* +** Each SQL function is defined by an instance of the following +** structure. A pointer to this structure is stored in the sqlite.aFunc +** hash table. When multiple functions have the same name, the hash table +** points to a linked list of these structures. +*/ +struct FuncDef { + i16 nArg; /* Number of arguments. -1 means unlimited */ + u16 funcFlags; /* Some combination of SQLITE_FUNC_* */ + void *pUserData; /* User data parameter */ + FuncDef *pNext; /* Next function with same name */ + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ + void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */ + void (*xFinalize)(sqlite3_context*); /* Aggregate finalizer */ + char *zName; /* SQL name of the function. */ + FuncDef *pHash; /* Next with a different name but the same hash */ + FuncDestructor *pDestructor; /* Reference counted destructor function */ +}; + +/* +** This structure encapsulates a user-function destructor callback (as +** configured using create_function_v2()) and a reference counter. When +** create_function_v2() is called to create a function with a destructor, +** a single object of this type is allocated. FuncDestructor.nRef is set to +** the number of FuncDef objects created (either 1 or 3, depending on whether +** or not the specified encoding is SQLITE_ANY). The FuncDef.pDestructor +** member of each of the new FuncDef objects is set to point to the allocated +** FuncDestructor. +** +** Thereafter, when one of the FuncDef objects is deleted, the reference +** count on this object is decremented. When it reaches 0, the destructor +** is invoked and the FuncDestructor structure freed. +*/ +struct FuncDestructor { + int nRef; + void (*xDestroy)(void *); + void *pUserData; +}; + +/* +** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF +** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There +** are assert() statements in the code to verify this. +*/ +#define SQLITE_FUNC_ENCMASK 0x003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ +#define SQLITE_FUNC_LIKE 0x004 /* Candidate for the LIKE optimization */ +#define SQLITE_FUNC_CASE 0x008 /* Case-sensitive LIKE-type function */ +#define SQLITE_FUNC_EPHEM 0x010 /* Ephemeral. Delete with VDBE */ +#define SQLITE_FUNC_NEEDCOLL 0x020 /* sqlite3GetFuncCollSeq() might be called */ +#define SQLITE_FUNC_LENGTH 0x040 /* Built-in length() function */ +#define SQLITE_FUNC_TYPEOF 0x080 /* Built-in typeof() function */ +#define SQLITE_FUNC_COUNT 0x100 /* Built-in count(*) aggregate */ +#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */ +#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */ +#define SQLITE_FUNC_CONSTANT 0x800 /* Constant inputs give a constant output */ +#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */ + +/* +** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are +** used to create the initializers for the FuncDef structures. +** +** FUNCTION(zName, nArg, iArg, bNC, xFunc) +** Used to create a scalar function definition of a function zName +** 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 SQLITE_FUNC_NEEDCOLL flag is set. +** +** VFUNCTION(zName, nArg, iArg, bNC, xFunc) +** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag. +** +** 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. +*/ +#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} +#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} +#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ + {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\ + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} +#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ + {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ + pArg, 0, xFunc, 0, 0, #zName, 0, 0} +#define LIKEFUNC(zName, nArg, arg, flags) \ + {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \ + (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0} +#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ + {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \ + SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0} +#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \ + {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ + SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0} + +/* +** All current savepoints are stored in a linked list starting at +** sqlite3.pSavepoint. The first element in the list is the most recently +** opened savepoint. Savepoints are added to the list by the vdbe +** OP_Savepoint instruction. +*/ +struct Savepoint { + char *zName; /* Savepoint name (nul-terminated) */ + i64 nDeferredCons; /* Number of deferred fk violations */ + i64 nDeferredImmCons; /* Number of deferred imm fk. */ + Savepoint *pNext; /* Parent savepoint (if any) */ +}; + +/* +** The following are used as the second parameter to sqlite3Savepoint(), +** and as the P1 argument to the OP_Savepoint instruction. +*/ +#define SAVEPOINT_BEGIN 0 +#define SAVEPOINT_RELEASE 1 +#define SAVEPOINT_ROLLBACK 2 + + +/* +** Each SQLite module (virtual table definition) is defined by an +** instance of the following structure, stored in the sqlite3.aModule +** hash table. +*/ +struct Module { + const sqlite3_module *pModule; /* Callback pointers */ + const char *zName; /* Name passed to create_module() */ + void *pAux; /* pAux passed to create_module() */ + void (*xDestroy)(void *); /* Module destructor function */ +}; + +/* +** information about each column of an SQL table is held in an instance +** of this structure. +*/ +struct Column { + char *zName; /* Name of this column */ + Expr *pDflt; /* Default value of this column */ + char *zDflt; /* Original text of the default value */ + char *zType; /* Data type for this column */ + char *zColl; /* Collating sequence. If NULL, use the default */ + u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ + char affinity; /* One of the SQLITE_AFF_... values */ + u8 szEst; /* Estimated size of this column. INT==1 */ + u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */ +}; + +/* Allowed values for Column.colFlags: +*/ +#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */ +#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ + +/* +** A "Collating Sequence" is defined by an instance of the following +** structure. Conceptually, a collating sequence consists of a name and +** a comparison routine that defines the order of that sequence. +** +** If CollSeq.xCmp is NULL, it means that the +** collating sequence is undefined. Indices built on an undefined +** collating sequence may not be read or written. +*/ +struct CollSeq { + char *zName; /* Name of the collating sequence, UTF-8 encoded */ + u8 enc; /* Text encoding handled by xCmp() */ + void *pUser; /* First argument to xCmp() */ + int (*xCmp)(void*,int, const void*, int, const void*); + void (*xDel)(void*); /* Destructor for pUser */ +}; + +/* +** A sort order can be either ASC or DESC. +*/ +#define SQLITE_SO_ASC 0 /* Sort in ascending order */ +#define SQLITE_SO_DESC 1 /* Sort in ascending order */ + +/* +** Column affinity types. +** +** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and +** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve +** the speed a little by numbering the values consecutively. +** +** But rather than start with 0 or 1, we begin with 'A'. That way, +** when multiple affinity types are concatenated into a string and +** used as the P4 operand, they will be more readable. +** +** Note also that the numeric types are grouped together so that testing +** for a numeric type is a single comparison. And the BLOB type is first. +*/ +#define SQLITE_AFF_BLOB 'A' +#define SQLITE_AFF_TEXT 'B' +#define SQLITE_AFF_NUMERIC 'C' +#define SQLITE_AFF_INTEGER 'D' +#define SQLITE_AFF_REAL 'E' + +#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) + +/* +** The SQLITE_AFF_MASK values masks off the significant bits of an +** affinity value. +*/ +#define SQLITE_AFF_MASK 0x47 + +/* +** Additional bit values that can be ORed with an affinity without +** changing the affinity. +** +** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL. +** It causes an assert() to fire if either operand to a comparison +** operator is NULL. It is added to certain comparison operators to +** prove that the operands are always NOT NULL. +*/ +#define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */ +#define SQLITE_STOREP2 0x20 /* Store result in reg[P2] rather than jump */ +#define SQLITE_NULLEQ 0x80 /* NULL=NULL */ +#define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */ + +/* +** An object of this type is created for each virtual table present in +** the database schema. +** +** If the database schema is shared, then there is one instance of this +** structure for each database connection (sqlite3*) that uses the shared +** schema. This is because each database connection requires its own unique +** instance of the sqlite3_vtab* handle used to access the virtual table +** implementation. sqlite3_vtab* handles can not be shared between +** database connections, even when the rest of the in-memory database +** schema is shared, as the implementation often stores the database +** connection handle passed to it via the xConnect() or xCreate() method +** during initialization internally. This database connection handle may +** then be used by the virtual table implementation to access real tables +** within the database. So that they appear as part of the callers +** transaction, these accesses need to be made via the same database +** connection as that used to execute SQL operations on the virtual table. +** +** All VTable objects that correspond to a single table in a shared +** database schema are initially stored in a linked-list pointed to by +** the Table.pVTable member variable of the corresponding Table object. +** When an sqlite3_prepare() operation is required to access the virtual +** table, it searches the list for the VTable that corresponds to the +** database connection doing the preparing so as to use the correct +** sqlite3_vtab* handle in the compiled query. +** +** When an in-memory Table object is deleted (for example when the +** schema is being reloaded for some reason), the VTable objects are not +** deleted and the sqlite3_vtab* handles are not xDisconnect()ed +** immediately. Instead, they are moved from the Table.pVTable list to +** another linked list headed by the sqlite3.pDisconnect member of the +** corresponding sqlite3 structure. They are then deleted/xDisconnected +** next time a statement is prepared using said sqlite3*. This is done +** to avoid deadlock issues involving multiple sqlite3.mutex mutexes. +** Refer to comments above function sqlite3VtabUnlockList() for an +** explanation as to why it is safe to add an entry to an sqlite3.pDisconnect +** list without holding the corresponding sqlite3.mutex mutex. +** +** The memory for objects of this type is always allocated by +** sqlite3DbMalloc(), using the connection handle stored in VTable.db as +** the first argument. +*/ +struct VTable { + sqlite3 *db; /* Database connection associated with this table */ + Module *pMod; /* Pointer to module implementation */ + sqlite3_vtab *pVtab; /* Pointer to vtab instance */ + int nRef; /* Number of pointers to this structure */ + u8 bConstraint; /* True if constraints are supported */ + int iSavepoint; /* Depth of the SAVEPOINT stack */ + VTable *pNext; /* Next in linked list (see above) */ +}; + +/* +** The schema for each SQL table and view is represented in memory +** by an instance of the following structure. +*/ +struct Table { + char *zName; /* Name of the table or view */ + Column *aCol; /* Information about each column */ + Index *pIndex; /* List of SQL indexes on this table. */ + Select *pSelect; /* NULL for tables. Points to definition if a view. */ + FKey *pFKey; /* Linked list of all foreign keys in this table */ + char *zColAff; /* String defining the affinity of each column */ +#ifndef SQLITE_OMIT_CHECK + ExprList *pCheck; /* All CHECK constraints */ +#endif + int tnum; /* Root BTree page for this table */ + i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */ + i16 nCol; /* Number of columns in this table */ + u16 nRef; /* Number of pointers to this Table */ + LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ + LogEst szTabRow; /* Estimated size of each table row in bytes */ +#ifdef SQLITE_ENABLE_COSTMULT + LogEst costMult; /* Cost multiplier for using this table */ +#endif + u8 tabFlags; /* Mask of TF_* values */ + u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ +#ifndef SQLITE_OMIT_ALTERTABLE + int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + int nModuleArg; /* Number of arguments to the module */ + char **azModuleArg; /* Text of all module args. [0] is module name */ + VTable *pVTable; /* List of VTable objects. */ +#endif + Trigger *pTrigger; /* List of triggers stored in pSchema */ + Schema *pSchema; /* Schema that contains this table */ + Table *pNextZombie; /* Next on the Parse.pZombieTab list */ +}; + +/* +** Allowed values for Table.tabFlags. +** +** TF_OOOHidden applies to virtual tables that have hidden columns that are +** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING +** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, +** the TF_OOOHidden attribute would apply in this case. Such tables require +** special handling during INSERT processing. +*/ +#define TF_Readonly 0x01 /* Read-only system table */ +#define TF_Ephemeral 0x02 /* An ephemeral table */ +#define TF_HasPrimaryKey 0x04 /* Table has a primary key */ +#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */ +#define TF_Virtual 0x10 /* Is a virtual table */ +#define TF_WithoutRowid 0x20 /* No rowid. PRIMARY KEY is the key */ +#define TF_NoVisibleRowid 0x40 /* No user-visible "rowid" column */ +#define TF_OOOHidden 0x80 /* Out-of-Order hidden columns */ + + +/* +** Test to see whether or not a table is a virtual table. This is +** done as a macro so that it will be optimized out when virtual +** table support is omitted from the build. +*/ +#ifndef SQLITE_OMIT_VIRTUALTABLE +# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) +# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) +#else +# define IsVirtual(X) 0 +# define IsHiddenColumn(X) 0 +#endif + +/* Does the table have a rowid */ +#define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0) +#define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0) + +/* +** Each foreign key constraint is an instance of the following structure. +** +** A foreign key is associated with two tables. The "from" table is +** the table that contains the REFERENCES clause that creates the foreign +** key. The "to" table is the table that is named in the REFERENCES clause. +** Consider this example: +** +** CREATE TABLE ex1( +** a INTEGER PRIMARY KEY, +** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x) +** ); +** +** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2". +** Equivalent names: +** +** from-table == child-table +** to-table == parent-table +** +** Each REFERENCES clause generates an instance of the following structure +** which is attached to the from-table. The to-table need not exist when +** the from-table is created. The existence of the to-table is not checked. +** +** The list of all parents for child Table X is held at X.pFKey. +** +** A list of all children for a table named Z (which might not even exist) +** is held in Schema.fkeyHash with a hash key of Z. +*/ +struct FKey { + Table *pFrom; /* Table containing the REFERENCES clause (aka: Child) */ + FKey *pNextFrom; /* Next FKey with the same in pFrom. Next parent of pFrom */ + char *zTo; /* Name of table that the key points to (aka: Parent) */ + FKey *pNextTo; /* Next with the same zTo. Next child of zTo. */ + FKey *pPrevTo; /* Previous with the same zTo */ + int nCol; /* Number of columns in this key */ + /* EV: R-30323-21917 */ + u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ + u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */ + Trigger *apTrigger[2];/* Triggers for aAction[] actions */ + struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ + int iFrom; /* Index of column in pFrom */ + char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */ + } aCol[1]; /* One entry for each of nCol columns */ +}; + +/* +** SQLite supports many different ways to resolve a constraint +** error. ROLLBACK processing means that a constraint violation +** causes the operation in process to fail and for the current transaction +** to be rolled back. ABORT processing means the operation in process +** fails and any prior changes from that one operation are backed out, +** but the transaction is not rolled back. FAIL processing means that +** the operation in progress stops and returns an error code. But prior +** changes due to the same operation are not backed out and no rollback +** occurs. IGNORE means that the particular row that caused the constraint +** error is not inserted or updated. Processing continues and no error +** is returned. REPLACE means that preexisting database rows that caused +** a UNIQUE constraint violation are removed so that the new insert or +** update can proceed. Processing continues and no error is reported. +** +** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys. +** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the +** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign +** key is set to NULL. CASCADE means that a DELETE or UPDATE of the +** referenced table row is propagated into the row that holds the +** foreign key. +** +** The following symbolic values are used to record which type +** of action to take. +*/ +#define OE_None 0 /* There is no constraint to check */ +#define OE_Rollback 1 /* Fail the operation and rollback the transaction */ +#define OE_Abort 2 /* Back out changes but do no rollback transaction */ +#define OE_Fail 3 /* Stop the operation but leave all prior changes */ +#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ +#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ + +#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ +#define OE_SetNull 7 /* Set the foreign key value to NULL */ +#define OE_SetDflt 8 /* Set the foreign key value to its default */ +#define OE_Cascade 9 /* Cascade the changes */ + +#define OE_Default 10 /* Do whatever the default action is */ + + +/* +** An instance of the following structure is passed as the first +** argument to sqlite3VdbeKeyCompare and is used to control the +** comparison of the two index keys. +** +** Note that aSortOrder[] and aColl[] have nField+1 slots. There +** are nField slots for the columns of an index then one extra slot +** for the rowid at the end. +*/ +struct KeyInfo { + u32 nRef; /* Number of references to this KeyInfo object */ + u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ + u16 nField; /* Number of key columns in the index */ + u16 nXField; /* Number of columns beyond the key columns */ + sqlite3 *db; /* The database connection */ + u8 *aSortOrder; /* Sort order for each column. */ + CollSeq *aColl[1]; /* Collating sequence for each term of the key */ +}; + +/* +** An instance of the following structure holds information about a +** single index record that has already been parsed out into individual +** values. +** +** A record is an object that contains one or more fields of data. +** Records are used to store the content of a table row and to store +** the key of an index. A blob encoding of a record is created by +** the OP_MakeRecord opcode of the VDBE and is disassembled by the +** OP_Column opcode. +** +** This structure holds a record that has already been disassembled +** into its constituent fields. +** +** The r1 and r2 member variables are only used by the optimized comparison +** functions vdbeRecordCompareInt() and vdbeRecordCompareString(). +*/ +struct UnpackedRecord { + KeyInfo *pKeyInfo; /* Collation and sort-order information */ + u16 nField; /* Number of entries in apMem[] */ + i8 default_rc; /* Comparison result if keys are equal */ + u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */ + Mem *aMem; /* Values */ + int r1; /* Value to return if (lhs > rhs) */ + int r2; /* Value to return if (rhs < lhs) */ +}; + + +/* +** Each SQL index is represented in memory by an +** instance of the following structure. +** +** The columns of the table that are to be indexed are described +** by the aiColumn[] field of this structure. For example, suppose +** we have the following table and index: +** +** CREATE TABLE Ex1(c1 int, c2 int, c3 text); +** CREATE INDEX Ex2 ON Ex1(c3,c1); +** +** In the Table structure describing Ex1, nCol==3 because there are +** three columns in the table. In the Index structure describing +** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed. +** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the +** first column to be indexed (c3) has an index of 2 in Ex1.aCol[]. +** The second column to be indexed (c1) has an index of 0 in +** Ex1.aCol[], hence Ex2.aiColumn[1]==0. +** +** The Index.onError field determines whether or not the indexed columns +** must be unique and what to do if they are not. When Index.onError=OE_None, +** it means this is not a unique index. Otherwise it is a unique index +** and the value of Index.onError indicate the which conflict resolution +** algorithm to employ whenever an attempt is made to insert a non-unique +** element. +** +** While parsing a CREATE TABLE or CREATE INDEX statement in order to +** generate VDBE code (as opposed to parsing one read from an sqlite_master +** table as part of parsing an existing database schema), transient instances +** of this structure may be created. In this case the Index.tnum variable is +** used to store the address of a VDBE instruction, not a database page +** number (it cannot - the database page is not allocated until the VDBE +** program is executed). See convertToWithoutRowidTable() for details. +*/ +struct Index { + char *zName; /* Name of this index */ + i16 *aiColumn; /* Which columns are used by this index. 1st is 0 */ + LogEst *aiRowLogEst; /* From ANALYZE: Est. rows selected by each column */ + Table *pTable; /* The SQL table being indexed */ + char *zColAff; /* String defining the affinity of each column */ + Index *pNext; /* The next index associated with the same table */ + Schema *pSchema; /* Schema containing this index */ + u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ + char **azColl; /* Array of collation sequence names for index */ + Expr *pPartIdxWhere; /* WHERE clause for partial indices */ + int tnum; /* DB Page containing root of this index */ + LogEst szIdxRow; /* Estimated average row size in bytes */ + u16 nKeyCol; /* Number of columns forming the key */ + u16 nColumn; /* Number of columns stored in the index */ + u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ + unsigned idxType:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ + unsigned bUnordered:1; /* Use this index for == or IN queries only */ + unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ + unsigned isResized:1; /* True if resizeIndexObject() has been called */ + unsigned isCovering:1; /* True if this is a covering index */ + unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + int nSample; /* Number of elements in aSample[] */ + int nSampleCol; /* Size of IndexSample.anEq[] and so on */ + tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ + IndexSample *aSample; /* Samples of the left-most key */ + tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this index */ + tRowcnt nRowEst0; /* Non-logarithmic number of rows in the index */ +#endif +}; + +/* +** Allowed values for Index.idxType +*/ +#define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */ +#define SQLITE_IDXTYPE_UNIQUE 1 /* Implements a UNIQUE constraint */ +#define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */ + +/* Return true if index X is a PRIMARY KEY index */ +#define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY) + +/* Return true if index X is a UNIQUE index */ +#define IsUniqueIndex(X) ((X)->onError!=OE_None) + +/* +** Each sample stored in the sqlite_stat3 table is represented in memory +** using a structure of this type. See documentation at the top of the +** analyze.c source file for additional information. +*/ +struct IndexSample { + void *p; /* Pointer to sampled record */ + int n; /* Size of record in bytes */ + tRowcnt *anEq; /* Est. number of rows where the key equals this sample */ + tRowcnt *anLt; /* Est. number of rows where key is less than this sample */ + tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */ +}; + +/* +** Each token coming out of the lexer is an instance of +** this structure. Tokens are also used as part of an expression. +** +** Note if Token.z==0 then Token.dyn and Token.n are undefined and +** may contain random values. Do not make any assumptions about Token.dyn +** and Token.n when Token.z==0. +*/ +struct Token { + const char *z; /* Text of the token. Not NULL-terminated! */ + unsigned int n; /* Number of characters in this token */ +}; + +/* +** An instance of this structure contains information needed to generate +** code for a SELECT that contains aggregate functions. +** +** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a +** pointer to this structure. The Expr.iColumn field is the index in +** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate +** code for that node. +** +** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the +** original Select structure that describes the SELECT statement. These +** fields do not need to be freed when deallocating the AggInfo structure. +*/ +struct AggInfo { + u8 directMode; /* Direct rendering mode means take data directly + ** from source tables rather than from accumulators */ + u8 useSortingIdx; /* In direct mode, reference the sorting index rather + ** than the source table */ + int sortingIdx; /* Cursor number of the sorting index */ + int sortingIdxPTab; /* Cursor number of pseudo-table */ + int nSortingColumn; /* Number of columns in the sorting index */ + int mnReg, mxReg; /* Range of registers allocated for aCol and aFunc */ + ExprList *pGroupBy; /* The group by clause */ + struct AggInfo_col { /* For each column used in source tables */ + Table *pTab; /* Source table */ + int iTable; /* Cursor number of the source table */ + int iColumn; /* Column number within the source table */ + int iSorterColumn; /* Column number in the sorting index */ + int iMem; /* Memory location that acts as accumulator */ + Expr *pExpr; /* The original expression */ + } *aCol; + int nColumn; /* Number of used entries in aCol[] */ + int nAccumulator; /* Number of columns that show through to the output. + ** Additional columns are used only as parameters to + ** aggregate functions */ + struct AggInfo_func { /* For each aggregate function */ + Expr *pExpr; /* Expression encoding the function */ + FuncDef *pFunc; /* The aggregate function implementation */ + int iMem; /* Memory location that acts as accumulator */ + int iDistinct; /* Ephemeral table used to enforce DISTINCT */ + } *aFunc; + int nFunc; /* Number of entries in aFunc[] */ +}; + +/* +** The datatype ynVar is a signed integer, either 16-bit or 32-bit. +** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater +** than 32767 we have to make it 32-bit. 16-bit is preferred because +** it uses less memory in the Expr object, which is a big memory user +** in systems with lots of prepared statements. And few applications +** need more than about 10 or 20 variables. But some extreme users want +** to have prepared statements with over 32767 variables, and for them +** the option is available (at compile-time). +*/ +#if SQLITE_MAX_VARIABLE_NUMBER<=32767 +typedef i16 ynVar; +#else +typedef int ynVar; +#endif + +/* +** Each node of an expression in the parse tree is an instance +** of this structure. +** +** Expr.op is the opcode. The integer parser token codes are reused +** as opcodes here. For example, the parser defines TK_GE to be an integer +** code representing the ">=" operator. This same integer code is reused +** to represent the greater-than-or-equal-to operator in the expression +** tree. +** +** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB, +** or TK_STRING), then Expr.token contains the text of the SQL literal. If +** the expression is a variable (TK_VARIABLE), then Expr.token contains the +** variable name. Finally, if the expression is an SQL function (TK_FUNCTION), +** then Expr.token contains the name of the function. +** +** Expr.pRight and Expr.pLeft are the left and right subexpressions of a +** binary operator. Either or both may be NULL. +** +** Expr.x.pList is a list of arguments if the expression is an SQL function, +** a CASE expression or an IN expression of the form " IN (, ...)". +** Expr.x.pSelect is used if the expression is a sub-select or an expression of +** the form " IN (SELECT ...)". If the EP_xIsSelect bit is set in the +** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is +** valid. +** +** An expression of the form ID or ID.ID refers to a column in a table. +** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is +** the integer cursor number of a VDBE cursor pointing to that table and +** Expr.iColumn is the column number for the specific column. If the +** expression is used as a result in an aggregate SELECT, then the +** value is also stored in the Expr.iAgg column in the aggregate so that +** it can be accessed after all aggregates are computed. +** +** If the expression is an unbound variable marker (a question mark +** character '?' in the original SQL) then the Expr.iTable holds the index +** number for that variable. +** +** If the expression is a subquery then Expr.iColumn holds an integer +** register number containing the result of the subquery. If the +** subquery gives a constant result, then iTable is -1. If the subquery +** gives a different answer at different times during statement processing +** then iTable is the address of a subroutine that computes the subquery. +** +** If the Expr is of type OP_Column, and the table it is selecting from +** is a disk table or the "old.*" pseudo-table, then pTab points to the +** corresponding table definition. +** +** ALLOCATION NOTES: +** +** Expr objects can use a lot of memory space in database schema. To +** help reduce memory requirements, sometimes an Expr object will be +** truncated. And to reduce the number of memory allocations, sometimes +** two or more Expr objects will be stored in a single memory allocation, +** together with Expr.zToken strings. +** +** If the EP_Reduced and EP_TokenOnly flags are set when +** an Expr object is truncated. When EP_Reduced is set, then all +** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees +** are contained within the same memory allocation. Note, however, that +** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately +** allocated, regardless of whether or not EP_Reduced is set. +*/ +struct Expr { + u8 op; /* Operation performed by this node */ + char affinity; /* The affinity of the column or 0 if not a column */ + u32 flags; /* Various flags. EP_* See below */ + union { + char *zToken; /* Token value. Zero terminated and dequoted */ + int iValue; /* Non-negative integer value if EP_IntValue */ + } u; + + /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no + ** space is allocated for the fields below this point. An attempt to + ** access them will result in a segfault or malfunction. + *********************************************************************/ + + Expr *pLeft; /* Left subnode */ + Expr *pRight; /* Right subnode */ + union { + ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */ + Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */ + } x; + + /* If the EP_Reduced flag is set in the Expr.flags mask, then no + ** space is allocated for the fields below this point. An attempt to + ** access them will result in a segfault or malfunction. + *********************************************************************/ + +#if SQLITE_MAX_EXPR_DEPTH>0 + int nHeight; /* Height of the tree headed by this node */ +#endif + int iTable; /* TK_COLUMN: cursor number of table holding column + ** TK_REGISTER: register number + ** TK_TRIGGER: 1 -> new, 0 -> old + ** EP_Unlikely: 134217728 times likelihood */ + ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. + ** TK_VARIABLE: variable number (always >= 1). */ + i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ + i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ + u8 op2; /* TK_REGISTER: original value of Expr.op + ** TK_COLUMN: the value of p5 for OP_Column + ** TK_AGG_FUNCTION: nesting depth */ + AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ + Table *pTab; /* Table for TK_COLUMN expressions. */ +}; + +/* +** The following are the meanings of bits in the Expr.flags field. +*/ +#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ +#define EP_Agg 0x000002 /* Contains one or more aggregate functions */ +#define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */ +#define EP_Error 0x000008 /* Expression contains one or more errors */ +#define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */ +#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ +#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */ +#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */ +#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */ +#define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */ +#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */ +#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */ +#define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */ +#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ +#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ +#define EP_Static 0x008000 /* Held in memory not obtained from malloc() */ +#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ +#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ +#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ +#define EP_ConstFunc 0x080000 /* Node is a SQLITE_FUNC_CONSTANT function */ +#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ +#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ + +/* +** Combinations of two or more EP_* flags +*/ +#define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */ + +/* +** These macros can be used to test, set, or clear bits in the +** Expr.flags field. +*/ +#define ExprHasProperty(E,P) (((E)->flags&(P))!=0) +#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P)) +#define ExprSetProperty(E,P) (E)->flags|=(P) +#define ExprClearProperty(E,P) (E)->flags&=~(P) + +/* The ExprSetVVAProperty() macro is used for Verification, Validation, +** and Accreditation only. It works like ExprSetProperty() during VVA +** processes but is a no-op for delivery. +*/ +#ifdef SQLITE_DEBUG +# define ExprSetVVAProperty(E,P) (E)->flags|=(P) +#else +# define ExprSetVVAProperty(E,P) +#endif + +/* +** Macros to determine the number of bytes required by a normal Expr +** struct, an Expr struct with the EP_Reduced flag set in Expr.flags +** and an Expr struct with the EP_TokenOnly flag set. +*/ +#define EXPR_FULLSIZE sizeof(Expr) /* Full size */ +#define EXPR_REDUCEDSIZE offsetof(Expr,iTable) /* Common features */ +#define EXPR_TOKENONLYSIZE offsetof(Expr,pLeft) /* Fewer features */ + +/* +** Flags passed to the sqlite3ExprDup() function. See the header comment +** above sqlite3ExprDup() for details. +*/ +#define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */ + +/* +** A list of expressions. Each expression may optionally have a +** name. An expr/name combination can be used in several ways, such +** as the list of "expr AS ID" fields following a "SELECT" or in the +** list of "ID = expr" items in an UPDATE. A list of expressions can +** also be used as the argument to a function, in which case the a.zName +** field is not used. +** +** By default the Expr.zSpan field holds a human-readable description of +** the expression that is used in the generation of error messages and +** column labels. In this case, Expr.zSpan is typically the text of a +** column expression as it exists in a SELECT statement. However, if +** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name +** of the result column in the form: DATABASE.TABLE.COLUMN. This later +** form is used for name resolution with nested FROM clauses. +*/ +struct ExprList { + int nExpr; /* Number of expressions on the list */ + struct ExprList_item { /* For each expression in the list */ + Expr *pExpr; /* The list of expressions */ + char *zName; /* Token associated with this expression */ + char *zSpan; /* Original text of the expression */ + u8 sortOrder; /* 1 for DESC or 0 for ASC */ + unsigned done :1; /* A flag to indicate when processing is finished */ + unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ + unsigned reusable :1; /* Constant expression is reusable */ + union { + struct { + u16 iOrderByCol; /* For ORDER BY, column number in result set */ + u16 iAlias; /* Index into Parse.aAlias[] for zName */ + } x; + int iConstExprReg; /* Register in which Expr value is cached */ + } u; + } *a; /* Alloc a power of two greater or equal to nExpr */ +}; + +/* +** An instance of this structure is used by the parser to record both +** the parse tree for an expression and the span of input text for an +** expression. +*/ +struct ExprSpan { + Expr *pExpr; /* The expression parse tree */ + const char *zStart; /* First character of input text */ + const char *zEnd; /* One character past the end of input text */ +}; + +/* +** An instance of this structure can hold a simple list of identifiers, +** such as the list "a,b,c" in the following statements: +** +** INSERT INTO t(a,b,c) VALUES ...; +** CREATE INDEX idx ON t(a,b,c); +** CREATE TRIGGER trig BEFORE UPDATE ON t(a,b,c) ...; +** +** The IdList.a.idx field is used when the IdList represents the list of +** column names after a table name in an INSERT statement. In the statement +** +** INSERT INTO t(a,b,c) ... +** +** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. +*/ +struct IdList { + struct IdList_item { + char *zName; /* Name of the identifier */ + int idx; /* Index in some Table.aCol[] of a column named zName */ + } *a; + int nId; /* Number of identifiers on the list */ +}; + +/* +** The bitmask datatype defined below is used for various optimizations. +** +** Changing this from a 64-bit to a 32-bit type limits the number of +** tables in a join to 32 instead of 64. But it also reduces the size +** of the library by 738 bytes on ix86. +*/ +typedef u64 Bitmask; + +/* +** The number of bits in a Bitmask. "BMS" means "BitMask Size". +*/ +#define BMS ((int)(sizeof(Bitmask)*8)) + +/* +** A bit in a Bitmask +*/ +#define MASKBIT(n) (((Bitmask)1)<<(n)) +#define MASKBIT32(n) (((unsigned int)1)<<(n)) + +/* +** The following structure describes the FROM clause of a SELECT statement. +** Each table or subquery in the FROM clause is a separate element of +** the SrcList.a[] array. +** +** With the addition of multiple database support, the following structure +** can also be used to describe a particular table such as the table that +** is modified by an INSERT, DELETE, or UPDATE statement. In standard SQL, +** such a table must be a simple name: ID. But in SQLite, the table can +** now be identified by a database name, a dot, then the table name: ID.ID. +** +** The jointype starts out showing the join type between the current table +** and the next table on the list. The parser builds the list this way. +** But sqlite3SrcListShiftJoinType() later shifts the jointypes so that each +** jointype expresses the join between the table and the previous table. +** +** In the colUsed field, the high-order bit (bit 63) is set if the table +** contains more than 63 columns and the 64-th or later column is used. +*/ +struct SrcList { + int nSrc; /* Number of tables or subqueries in the FROM clause */ + u32 nAlloc; /* Number of entries allocated in a[] below */ + struct SrcList_item { + Schema *pSchema; /* Schema to which this item is fixed */ + char *zDatabase; /* Name of database holding this table */ + char *zName; /* Name of the table */ + char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ + Table *pTab; /* An SQL table corresponding to zName */ + Select *pSelect; /* A SELECT statement used in place of a table name */ + int addrFillSub; /* Address of subroutine to manifest a subquery */ + int regReturn; /* Register holding return address of addrFillSub */ + int regResult; /* Registers holding results of a co-routine */ + u8 jointype; /* Type of join between this able and the previous */ + unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */ + unsigned isCorrelated :1; /* True if sub-query is correlated */ + unsigned viaCoroutine :1; /* Implemented as a co-routine */ + unsigned isRecursive :1; /* True for recursive reference in WITH */ +#ifndef SQLITE_OMIT_EXPLAIN + u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */ +#endif + int iCursor; /* The VDBE cursor number used to access this table */ + Expr *pOn; /* The ON clause of a join */ + IdList *pUsing; /* The USING clause of a join */ + Bitmask colUsed; /* Bit N (1<" clause */ + Index *pIndex; /* Index structure corresponding to zIndex, if any */ + } a[1]; /* One entry for each identifier on the list */ +}; + +/* +** Permitted values of the SrcList.a.jointype field +*/ +#define JT_INNER 0x0001 /* Any kind of inner or cross join */ +#define JT_CROSS 0x0002 /* Explicit use of the CROSS keyword */ +#define JT_NATURAL 0x0004 /* True for a "natural" join */ +#define JT_LEFT 0x0008 /* Left outer join */ +#define JT_RIGHT 0x0010 /* Right outer join */ +#define JT_OUTER 0x0020 /* The "OUTER" keyword is present */ +#define JT_ERROR 0x0040 /* unknown or unsupported join type */ + + +/* +** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin() +** and the WhereInfo.wctrlFlags member. +*/ +#define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */ +#define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */ +#define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */ +#define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */ +#define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */ +#define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */ +#define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */ +#define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */ +#define WHERE_NO_AUTOINDEX 0x0080 /* Disallow automatic indexes */ +#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */ +#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */ +#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */ +#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */ +#define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */ + +/* Allowed return values from sqlite3WhereIsDistinct() +*/ +#define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */ +#define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */ +#define WHERE_DISTINCT_ORDERED 2 /* All duplicates are adjacent */ +#define WHERE_DISTINCT_UNORDERED 3 /* Duplicates are scattered */ + +/* +** A NameContext defines a context in which to resolve table and column +** names. The context consists of a list of tables (the pSrcList) field and +** a list of named expression (pEList). The named expression list may +** be NULL. The pSrc corresponds to the FROM clause of a SELECT or +** to the table being operated on by INSERT, UPDATE, or DELETE. The +** pEList corresponds to the result set of a SELECT and is NULL for +** other statements. +** +** NameContexts can be nested. When resolving names, the inner-most +** context is searched first. If no match is found, the next outer +** context is checked. If there is still no match, the next context +** is checked. This process continues until either a match is found +** or all contexts are check. When a match is found, the nRef member of +** the context containing the match is incremented. +** +** Each subquery gets a new NameContext. The pNext field points to the +** NameContext in the parent query. Thus the process of scanning the +** NameContext list corresponds to searching through successively outer +** subqueries looking for a match. +*/ +struct NameContext { + Parse *pParse; /* The parser */ + SrcList *pSrcList; /* One or more tables used to resolve names */ + ExprList *pEList; /* Optional list of result-set columns */ + AggInfo *pAggInfo; /* Information about aggregates at this level */ + NameContext *pNext; /* Next outer name context. NULL for outermost */ + int nRef; /* Number of names resolved by this context */ + int nErr; /* Number of errors encountered while resolving names */ + u16 ncFlags; /* Zero or more NC_* flags defined below */ +}; + +/* +** Allowed values for the NameContext, ncFlags field. +** +** Note: NC_MinMaxAgg must have the same value as SF_MinMaxAgg and +** SQLITE_FUNC_MINMAX. +** +*/ +#define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */ +#define NC_HasAgg 0x0002 /* One or more aggregate functions seen */ +#define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */ +#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */ +#define NC_PartIdx 0x0010 /* True if resolving a partial index WHERE */ +#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */ + +/* +** An instance of the following structure contains all information +** needed to generate code for a single SELECT statement. +** +** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0. +** If there is a LIMIT clause, the parser sets nLimit to the value of the +** limit and nOffset to the value of the offset (or 0 if there is not +** offset). But later on, nLimit and nOffset become the memory locations +** in the VDBE that record the limit and offset counters. +** +** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes. +** These addresses must be stored so that we can go back and fill in +** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor +** the number of columns in P2 can be computed at the same time +** as the OP_OpenEphm instruction is coded because not +** enough information about the compound query is known at that point. +** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences +** for the result set. The KeyInfo for addrOpenEphm[2] contains collating +** sequences for the ORDER BY clause. +*/ +struct Select { + ExprList *pEList; /* The fields of the result */ + u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ + u16 selFlags; /* Various SF_* values */ + int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ +#if SELECTTRACE_ENABLED + char zSelName[12]; /* Symbolic name of this SELECT use for debugging */ +#endif + int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ + u64 nSelectRow; /* Estimated number of result rows */ + SrcList *pSrc; /* The FROM clause */ + Expr *pWhere; /* The WHERE clause */ + ExprList *pGroupBy; /* The GROUP BY clause */ + Expr *pHaving; /* The HAVING clause */ + ExprList *pOrderBy; /* The ORDER BY clause */ + Select *pPrior; /* Prior select in a compound select statement */ + Select *pNext; /* Next select to the left in a compound */ + Expr *pLimit; /* LIMIT expression. NULL means not used. */ + Expr *pOffset; /* OFFSET expression. NULL means not used. */ + With *pWith; /* WITH clause attached to this select. Or NULL. */ +}; + +/* +** Allowed values for Select.selFlags. The "SF" prefix stands for +** "Select Flag". +*/ +#define SF_Distinct 0x0001 /* Output should be DISTINCT */ +#define SF_All 0x0002 /* Includes the ALL keyword */ +#define SF_Resolved 0x0004 /* Identifiers have been resolved */ +#define SF_Aggregate 0x0008 /* Contains aggregate functions */ +#define SF_UsesEphemeral 0x0010 /* Uses the OpenEphemeral opcode */ +#define SF_Expanded 0x0020 /* sqlite3SelectExpand() called on this */ +#define SF_HasTypeInfo 0x0040 /* FROM subqueries have Table metadata */ +#define SF_Compound 0x0080 /* Part of a compound query */ +#define SF_Values 0x0100 /* Synthesized from VALUES clause */ +#define SF_MultiValue 0x0200 /* Single VALUES term with multiple rows */ +#define SF_NestedFrom 0x0400 /* Part of a parenthesized FROM clause */ +#define SF_MaybeConvert 0x0800 /* Need convertCompoundSelectToSubquery() */ +#define SF_MinMaxAgg 0x1000 /* Aggregate containing min() or max() */ +#define SF_Recursive 0x2000 /* The recursive part of a recursive CTE */ +#define SF_Converted 0x4000 /* By convertCompoundSelectToSubquery() */ + + +/* +** The results of a SELECT can be distributed in several ways, as defined +** by one of the following macros. The "SRT" prefix means "SELECT Result +** Type". +** +** SRT_Union Store results as a key in a temporary index +** identified by pDest->iSDParm. +** +** SRT_Except Remove results from the temporary index pDest->iSDParm. +** +** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result +** set is not empty. +** +** SRT_Discard Throw the results away. This is used by SELECT +** statements within triggers whose only purpose is +** the side-effects of functions. +** +** All of the above are free to ignore their ORDER BY clause. Those that +** follow must honor the ORDER BY clause. +** +** SRT_Output Generate a row of output (using the OP_ResultRow +** opcode) for each row in the result set. +** +** SRT_Mem Only valid if the result is a single column. +** Store the first column of the first result row +** in register pDest->iSDParm then abandon the rest +** of the query. This destination implies "LIMIT 1". +** +** SRT_Set The result must be a single column. Store each +** row of result as the key in table pDest->iSDParm. +** Apply the affinity pDest->affSdst before storing +** results. Used to implement "IN (SELECT ...)". +** +** SRT_EphemTab Create an temporary table pDest->iSDParm and store +** the result there. The cursor is left open after +** returning. This is like SRT_Table except that +** this destination uses OP_OpenEphemeral to create +** the table first. +** +** SRT_Coroutine Generate a co-routine that returns a new row of +** results each time it is invoked. The entry point +** of the co-routine is stored in register pDest->iSDParm +** and the result row is stored in pDest->nDest registers +** starting with pDest->iSdst. +** +** SRT_Table Store results in temporary table pDest->iSDParm. +** SRT_Fifo This is like SRT_EphemTab except that the table +** is assumed to already be open. SRT_Fifo has +** the additional property of being able to ignore +** the ORDER BY clause. +** +** SRT_DistFifo Store results in a temporary table pDest->iSDParm. +** But also use temporary table pDest->iSDParm+1 as +** a record of all prior results and ignore any duplicate +** rows. Name means: "Distinct Fifo". +** +** SRT_Queue Store results in priority queue pDest->iSDParm (really +** an index). Append a sequence number so that all entries +** are distinct. +** +** SRT_DistQueue Store results in priority queue pDest->iSDParm only if +** the same record has never been stored before. The +** index at pDest->iSDParm+1 hold all prior stores. +*/ +#define SRT_Union 1 /* Store result as keys in an index */ +#define SRT_Except 2 /* Remove result from a UNION index */ +#define SRT_Exists 3 /* Store 1 if the result is not empty */ +#define SRT_Discard 4 /* Do not save the results anywhere */ +#define SRT_Fifo 5 /* Store result as data with an automatic rowid */ +#define SRT_DistFifo 6 /* Like SRT_Fifo, but unique results only */ +#define SRT_Queue 7 /* Store result in an queue */ +#define SRT_DistQueue 8 /* Like SRT_Queue, but unique results only */ + +/* The ORDER BY clause is ignored for all of the above */ +#define IgnorableOrderby(X) ((X->eDest)<=SRT_DistQueue) + +#define SRT_Output 9 /* Output each row of result */ +#define SRT_Mem 10 /* Store result in a memory cell */ +#define SRT_Set 11 /* Store results as keys in an index */ +#define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */ +#define SRT_Coroutine 13 /* Generate a single row of result */ +#define SRT_Table 14 /* Store result as data with an automatic rowid */ + +/* +** An instance of this object describes where to put of the results of +** a SELECT statement. +*/ +struct SelectDest { + u8 eDest; /* How to dispose of the results. On of SRT_* above. */ + char affSdst; /* Affinity used when eDest==SRT_Set */ + int iSDParm; /* A parameter used by the eDest disposal method */ + int iSdst; /* Base register where results are written */ + int nSdst; /* Number of registers allocated */ + ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */ +}; + +/* +** During code generation of statements that do inserts into AUTOINCREMENT +** tables, the following information is attached to the Table.u.autoInc.p +** pointer of each autoincrement table to record some side information that +** the code generator needs. We have to keep per-table autoincrement +** information in case inserts are down within triggers. Triggers do not +** normally coordinate their activities, but we do need to coordinate the +** loading and saving of autoincrement information. +*/ +struct AutoincInfo { + AutoincInfo *pNext; /* Next info block in a list of them all */ + Table *pTab; /* Table this info block refers to */ + int iDb; /* Index in sqlite3.aDb[] of database holding pTab */ + int regCtr; /* Memory register holding the rowid counter */ +}; + +/* +** Size of the column cache +*/ +#ifndef SQLITE_N_COLCACHE +# define SQLITE_N_COLCACHE 10 +#endif + +/* +** At least one instance of the following structure is created for each +** trigger that may be fired while parsing an INSERT, UPDATE or DELETE +** statement. All such objects are stored in the linked list headed at +** Parse.pTriggerPrg and deleted once statement compilation has been +** completed. +** +** A Vdbe sub-program that implements the body and WHEN clause of trigger +** TriggerPrg.pTrigger, assuming a default ON CONFLICT clause of +** TriggerPrg.orconf, is stored in the TriggerPrg.pProgram variable. +** The Parse.pTriggerPrg list never contains two entries with the same +** values for both pTrigger and orconf. +** +** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns +** accessed (or set to 0 for triggers fired as a result of INSERT +** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to +** a mask of new.* columns used by the program. +*/ +struct TriggerPrg { + Trigger *pTrigger; /* Trigger this program was coded from */ + TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */ + SubProgram *pProgram; /* Program implementing pTrigger/orconf */ + int orconf; /* Default ON CONFLICT policy */ + u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */ +}; + +/* +** The yDbMask datatype for the bitmask of all attached databases. +*/ +#if SQLITE_MAX_ATTACHED>30 + typedef unsigned char yDbMask[(SQLITE_MAX_ATTACHED+9)/8]; +# define DbMaskTest(M,I) (((M)[(I)/8]&(1<<((I)&7)))!=0) +# define DbMaskZero(M) memset((M),0,sizeof(M)) +# define DbMaskSet(M,I) (M)[(I)/8]|=(1<<((I)&7)) +# define DbMaskAllZero(M) sqlite3DbMaskAllZero(M) +# define DbMaskNonZero(M) (sqlite3DbMaskAllZero(M)==0) +#else + typedef unsigned int yDbMask; +# define DbMaskTest(M,I) (((M)&(((yDbMask)1)<<(I)))!=0) +# define DbMaskZero(M) (M)=0 +# define DbMaskSet(M,I) (M)|=(((yDbMask)1)<<(I)) +# define DbMaskAllZero(M) (M)==0 +# define DbMaskNonZero(M) (M)!=0 +#endif + +/* +** An SQL parser context. A copy of this structure is passed through +** the parser and down into all the parser action routine in order to +** carry around information that is global to the entire parse. +** +** The structure is divided into two parts. When the parser and code +** generate call themselves recursively, the first part of the structure +** is constant but the second part is reset at the beginning and end of +** each recursion. +** +** The nTableLock and aTableLock variables are only used if the shared-cache +** feature is enabled (if sqlite3Tsd()->useSharedData is true). They are +** used to store the set of table-locks required by the statement being +** compiled. Function sqlite3TableLock() is used to add entries to the +** list. +*/ +struct Parse { + sqlite3 *db; /* The main database structure */ + char *zErrMsg; /* An error message */ + Vdbe *pVdbe; /* An engine for executing database bytecode */ + int rc; /* Return code from execution */ + u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ + u8 checkSchema; /* Causes schema cookie check after an error */ + u8 nested; /* Number of nested calls to the parser/code generator */ + u8 nTempReg; /* Number of temporary registers in aTempReg[] */ + u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ + u8 mayAbort; /* True if statement may throw an ABORT exception */ + u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ + u8 okConstFactor; /* OK to factor out constants */ + int aTempReg[8]; /* Holding area for temporary registers */ + int nRangeReg; /* Size of the temporary register block */ + int iRangeReg; /* First register in temporary register block */ + int nErr; /* Number of errors seen */ + int nTab; /* Number of previously allocated VDBE cursors */ + int nMem; /* Number of memory cells used so far */ + int nSet; /* Number of sets used so far */ + int nOnce; /* Number of OP_Once instructions so far */ + int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ + int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */ + int ckBase; /* Base register of data during check constraints */ + int iPartIdxTab; /* Table corresponding to a partial index */ + int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ + int iCacheCnt; /* Counter used to generate aColCache[].lru values */ + int nLabel; /* Number of labels used */ + int *aLabel; /* Space to hold the labels */ + struct yColCache { + int iTable; /* Table cursor number */ + i16 iColumn; /* Table column number */ + u8 tempReg; /* iReg is a temp register that needs to be freed */ + int iLevel; /* Nesting level */ + int iReg; /* Reg with value of this column. 0 means none. */ + int lru; /* Least recently used entry has the smallest value */ + } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ + ExprList *pConstExpr;/* Constant expressions */ + Token constraintName;/* Name of the constraint currently being parsed */ + yDbMask writeMask; /* Start a write transaction on these databases */ + yDbMask cookieMask; /* Bitmask of schema verified databases */ + int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ + int regRowid; /* Register holding rowid of CREATE TABLE entry */ + int regRoot; /* Register holding root page number for new objects */ + int nMaxArg; /* Max args passed to user function by sub-program */ +#if SELECTTRACE_ENABLED + int nSelect; /* Number of SELECT statements seen */ + int nSelectIndent; /* How far to indent SELECTTRACE() output */ +#endif +#ifndef SQLITE_OMIT_SHARED_CACHE + int nTableLock; /* Number of locks in aTableLock */ + TableLock *aTableLock; /* Required table locks for shared-cache mode */ +#endif + AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ + + /* Information used while coding trigger programs. */ + Parse *pToplevel; /* Parse structure for main program (or NULL) */ + Table *pTriggerTab; /* Table triggers are being coded for */ + int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */ + u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ + u32 oldmask; /* Mask of old.* columns referenced */ + u32 newmask; /* Mask of new.* columns referenced */ + u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ + u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ + u8 disableTriggers; /* True to disable triggers */ + + /************************************************************************ + ** Above is constant between recursions. Below is reset before and after + ** each recursion. The boundary between these two regions is determined + ** using offsetof(Parse,nVar) so the nVar field must be the first field + ** in the recursive region. + ************************************************************************/ + + int nVar; /* Number of '?' variables seen in the SQL so far */ + int nzVar; /* Number of available slots in azVar[] */ + u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */ + u8 bFreeWith; /* True if pWith should be freed with parser */ + u8 explain; /* True if the EXPLAIN flag is found on the query */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ + int nVtabLock; /* Number of virtual tables to lock */ +#endif + int nAlias; /* Number of aliased result set columns */ + int nHeight; /* Expression tree height of current sub-select */ +#ifndef SQLITE_OMIT_EXPLAIN + int iSelectId; /* ID of current select for EXPLAIN output */ + int iNextSelectId; /* Next available select ID for EXPLAIN output */ +#endif + char **azVar; /* Pointers to names of parameters */ + Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */ + const char *zTail; /* All SQL text past the last semicolon parsed */ + Table *pNewTable; /* A table being constructed by CREATE TABLE */ + Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ + const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ + Token sNameToken; /* Token with unqualified schema object name */ + Token sLastToken; /* The last token parsed */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + Token sArg; /* Complete text of a module argument */ + Table **apVtabLock; /* Pointer to virtual tables needing locking */ +#endif + Table *pZombieTab; /* List of Table objects to delete after code gen */ + TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ + With *pWith; /* Current WITH clause, or NULL */ +}; + +/* +** Return true if currently inside an sqlite3_declare_vtab() call. +*/ +#ifdef SQLITE_OMIT_VIRTUALTABLE + #define IN_DECLARE_VTAB 0 +#else + #define IN_DECLARE_VTAB (pParse->declareVtab) +#endif + +/* +** An instance of the following structure can be declared on a stack and used +** to save the Parse.zAuthContext value so that it can be restored later. +*/ +struct AuthContext { + const char *zAuthContext; /* Put saved Parse.zAuthContext here */ + Parse *pParse; /* The Parse structure */ +}; + +/* +** Bitfield flags for P5 value in various opcodes. +*/ +#define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */ +#define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ +#define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */ +#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ +#define OPFLAG_APPEND 0x08 /* This is likely to be an append */ +#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ +#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ +#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ +#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ +#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ +#define OPFLAG_P2ISREG 0x04 /* P2 to OP_Open** is a register number */ +#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ + +/* + * Each trigger present in the database schema is stored as an instance of + * struct Trigger. + * + * Pointers to instances of struct Trigger are stored in two ways. + * 1. In the "trigHash" hash table (part of the sqlite3* that represents the + * database). This allows Trigger structures to be retrieved by name. + * 2. All triggers associated with a single table form a linked list, using the + * pNext member of struct Trigger. A pointer to the first element of the + * linked list is stored as the "pTrigger" member of the associated + * struct Table. + * + * The "step_list" member points to the first element of a linked list + * containing the SQL statements specified as the trigger program. + */ +struct Trigger { + char *zName; /* The name of the trigger */ + char *table; /* The table or view to which the trigger applies */ + u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */ + u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ + Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */ + IdList *pColumns; /* If this is an UPDATE OF trigger, + the is stored here */ + Schema *pSchema; /* Schema containing the trigger */ + Schema *pTabSchema; /* Schema containing the table */ + TriggerStep *step_list; /* Link list of trigger program steps */ + Trigger *pNext; /* Next trigger associated with the table */ +}; + +/* +** A trigger is either a BEFORE or an AFTER trigger. The following constants +** determine which. +** +** If there are multiple triggers, you might of some BEFORE and some AFTER. +** In that cases, the constants below can be ORed together. +*/ +#define TRIGGER_BEFORE 1 +#define TRIGGER_AFTER 2 + +/* + * An instance of struct TriggerStep is used to store a single SQL statement + * that is a part of a trigger-program. + * + * Instances of struct TriggerStep are stored in a singly linked list (linked + * using the "pNext" member) referenced by the "step_list" member of the + * associated struct Trigger instance. The first element of the linked list is + * the first step of the trigger-program. + * + * The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or + * "SELECT" statement. The meanings of the other members is determined by the + * value of "op" as follows: + * + * (op == TK_INSERT) + * orconf -> stores the ON CONFLICT algorithm + * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then + * this stores a pointer to the SELECT statement. Otherwise NULL. + * zTarget -> Dequoted name of the table to insert into. + * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then + * this stores values to be inserted. Otherwise NULL. + * pIdList -> If this is an INSERT INTO ... () VALUES ... + * statement, then this stores the column-names to be + * inserted into. + * + * (op == TK_DELETE) + * zTarget -> Dequoted name of the table to delete from. + * pWhere -> The WHERE clause of the DELETE statement if one is specified. + * Otherwise NULL. + * + * (op == TK_UPDATE) + * zTarget -> Dequoted name of the table to update. + * pWhere -> The WHERE clause of the UPDATE statement if one is specified. + * Otherwise NULL. + * pExprList -> A list of the columns to update and the expressions to update + * them to. See sqlite3Update() documentation of "pChanges" + * argument. + * + */ +struct TriggerStep { + u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ + u8 orconf; /* OE_Rollback etc. */ + Trigger *pTrig; /* The trigger that this step is a part of */ + Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */ + char *zTarget; /* Target table for DELETE, UPDATE, INSERT */ + Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ + ExprList *pExprList; /* SET clause for UPDATE. */ + IdList *pIdList; /* Column names for INSERT */ + TriggerStep *pNext; /* Next in the link-list */ + TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */ +}; + +/* +** The following structure contains information used by the sqliteFix... +** routines as they walk the parse tree to make database references +** explicit. +*/ +typedef struct DbFixer DbFixer; +struct DbFixer { + Parse *pParse; /* The parsing context. Error messages written here */ + Schema *pSchema; /* Fix items to this schema */ + int bVarOnly; /* Check for variable references only */ + const char *zDb; /* Make sure all objects are contained in this database */ + const char *zType; /* Type of the container - used for error messages */ + const Token *pName; /* Name of the container - used for error messages */ +}; + +/* +** An objected used to accumulate the text of a string where we +** do not necessarily know how big the string will be in the end. +*/ +struct StrAccum { + sqlite3 *db; /* Optional database for lookaside. Can be NULL */ + char *zBase; /* A base allocation. Not from malloc. */ + char *zText; /* The string collected so far */ + int nChar; /* Length of the string so far */ + int nAlloc; /* Amount of space allocated in zText */ + int mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */ + u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */ +}; +#define STRACCUM_NOMEM 1 +#define STRACCUM_TOOBIG 2 + +/* +** A pointer to this structure is used to communicate information +** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. +*/ +typedef struct { + sqlite3 *db; /* The database being initialized */ + char **pzErrMsg; /* Error message stored here */ + int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */ + int rc; /* Result code stored here */ +} InitData; + +/* +** Structure containing global configuration data for the SQLite library. +** +** This structure also contains some state information. +*/ +struct Sqlite3Config { + int bMemstat; /* True to enable memory status */ + int bCoreMutex; /* True to enable core mutexing */ + int bFullMutex; /* True to enable full mutexing */ + int bOpenUri; /* True to interpret filenames as URIs */ + int bUseCis; /* Use covering indices for full-scans */ + int mxStrlen; /* Maximum string length */ + int neverCorrupt; /* Database is always well-formed */ + int szLookaside; /* Default lookaside buffer size */ + int nLookaside; /* Default lookaside buffer count */ + sqlite3_mem_methods m; /* Low-level memory allocation interface */ + sqlite3_mutex_methods mutex; /* Low-level mutex interface */ + sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */ + void *pHeap; /* Heap storage space */ + int nHeap; /* Size of pHeap[] */ + int mnReq, mxReq; /* Min and max heap requests sizes */ + sqlite3_int64 szMmap; /* mmap() space per open file */ + sqlite3_int64 mxMmap; /* Maximum value for szMmap */ + void *pScratch; /* Scratch memory */ + int szScratch; /* Size of each scratch buffer */ + int nScratch; /* Number of scratch buffers */ + void *pPage; /* Page cache memory */ + int szPage; /* Size of each page in pPage[] */ + int nPage; /* Number of pages in pPage[] */ + int mxParserStack; /* maximum depth of the parser stack */ + int sharedCacheEnabled; /* true if shared-cache mode enabled */ + u32 szPma; /* Maximum Sorter PMA size */ + /* The above might be initialized to non-zero. The following need to always + ** initially be zero, however. */ + int isInit; /* True after initialization has finished */ + int inProgress; /* True while initialization in progress */ + int isMutexInit; /* True after mutexes are initialized */ + int isMallocInit; /* True after malloc is initialized */ + int isPCacheInit; /* True after malloc is initialized */ + int nRefInitMutex; /* Number of users of pInitMutex */ + sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ + void (*xLog)(void*,int,const char*); /* Function for logging */ + void *pLogArg; /* First argument to xLog() */ +#ifdef SQLITE_ENABLE_SQLLOG + void(*xSqllog)(void*,sqlite3*,const char*, int); + void *pSqllogArg; +#endif +#ifdef SQLITE_VDBE_COVERAGE + /* The following callback (if not NULL) is invoked on every VDBE branch + ** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE. + */ + void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */ + void *pVdbeBranchArg; /* 1st argument */ +#endif +#ifndef SQLITE_OMIT_BUILTIN_TEST + int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ +#endif + int bLocaltimeFault; /* True to fail localtime() calls */ +}; + +/* +** This macro is used inside of assert() statements to indicate that +** the assert is only valid on a well-formed database. Instead of: +** +** assert( X ); +** +** One writes: +** +** assert( X || CORRUPT_DB ); +** +** CORRUPT_DB is true during normal operation. CORRUPT_DB does not indicate +** that the database is definitely corrupt, only that it might be corrupt. +** For most test cases, CORRUPT_DB is set to false using a special +** sqlite3_test_control(). This enables assert() statements to prove +** things that are always true for well-formed databases. +*/ +#define CORRUPT_DB (sqlite3Config.neverCorrupt==0) + +/* +** Context pointer passed down through the tree-walk. +*/ +struct Walker { + int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */ + int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */ + void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */ + Parse *pParse; /* Parser context. */ + int walkerDepth; /* Number of subqueries */ + u8 eCode; /* A small processing code */ + union { /* Extra data for callback */ + NameContext *pNC; /* Naming context */ + int n; /* A counter */ + int iCur; /* A cursor number */ + SrcList *pSrcList; /* FROM clause */ + struct SrcCount *pSrcCount; /* Counting column references */ + } u; +}; + +/* Forward declarations */ +SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*); +SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*); +SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*); +SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*); +SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*); + +/* +** Return code from the parse-tree walking primitives and their +** callbacks. +*/ +#define WRC_Continue 0 /* Continue down into children */ +#define WRC_Prune 1 /* Omit children but continue walking siblings */ +#define WRC_Abort 2 /* Abandon the tree walk */ + +/* +** An instance of this structure represents a set of one or more CTEs +** (common table expressions) created by a single WITH clause. +*/ +struct With { + int nCte; /* Number of CTEs in the WITH clause */ + With *pOuter; /* Containing WITH clause, or NULL */ + struct Cte { /* For each CTE in the WITH clause.... */ + char *zName; /* Name of this CTE */ + ExprList *pCols; /* List of explicit column names, or NULL */ + Select *pSelect; /* The definition of this CTE */ + const char *zErr; /* Error message for circular references */ + } a[1]; +}; + +#ifdef SQLITE_DEBUG +/* +** An instance of the TreeView object is used for printing the content of +** data structures on sqlite3DebugPrintf() using a tree-like view. +*/ +struct TreeView { + int iLevel; /* Which level of the tree we are on */ + u8 bLine[100]; /* Draw vertical in column i if bLine[i] is true */ +}; +#endif /* SQLITE_DEBUG */ + +/* +** Assuming zIn points to the first byte of a UTF-8 character, +** advance zIn to point to the first byte of the next UTF-8 character. +*/ +#define SQLITE_SKIP_UTF8(zIn) { \ + if( (*(zIn++))>=0xc0 ){ \ + while( (*zIn & 0xc0)==0x80 ){ zIn++; } \ + } \ +} + +/* +** The SQLITE_*_BKPT macros are substitutes for the error codes with +** the same name but without the _BKPT suffix. These macros invoke +** routines that report the line-number on which the error originated +** using sqlite3_log(). The routines also provide a convenient place +** to set a debugger breakpoint. +*/ +SQLITE_PRIVATE int sqlite3CorruptError(int); +SQLITE_PRIVATE int sqlite3MisuseError(int); +SQLITE_PRIVATE int sqlite3CantopenError(int); +#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__) +#define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__) +#define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__) + + +/* +** FTS4 is really an extension for FTS3. It is enabled using the +** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also call +** the SQLITE_ENABLE_FTS4 macro to serve as an alias for SQLITE_ENABLE_FTS3. +*/ +#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3) +# define SQLITE_ENABLE_FTS3 1 +#endif + +/* +** The ctype.h header is needed for non-ASCII systems. It is also +** needed by FTS3 when FTS3 is included in the amalgamation. +*/ +#if !defined(SQLITE_ASCII) || \ + (defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_AMALGAMATION)) +# include +#endif + +/* +** The following macros mimic the standard library functions toupper(), +** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The +** sqlite versions only work for ASCII characters, regardless of locale. +*/ +#ifdef SQLITE_ASCII +# define sqlite3Toupper(x) ((x)&~(sqlite3CtypeMap[(unsigned char)(x)]&0x20)) +# define sqlite3Isspace(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x01) +# define sqlite3Isalnum(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x06) +# define sqlite3Isalpha(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x02) +# define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04) +# define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08) +# define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)]) +#else +# define sqlite3Toupper(x) toupper((unsigned char)(x)) +# define sqlite3Isspace(x) isspace((unsigned char)(x)) +# define sqlite3Isalnum(x) isalnum((unsigned char)(x)) +# define sqlite3Isalpha(x) isalpha((unsigned char)(x)) +# define sqlite3Isdigit(x) isdigit((unsigned char)(x)) +# define sqlite3Isxdigit(x) isxdigit((unsigned char)(x)) +# define sqlite3Tolower(x) tolower((unsigned char)(x)) +#endif +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS +SQLITE_PRIVATE int sqlite3IsIdChar(u8); +#endif + +/* +** Internal function prototypes +*/ +#define sqlite3StrICmp sqlite3_stricmp +SQLITE_PRIVATE int sqlite3Strlen30(const char*); +#define sqlite3StrNICmp sqlite3_strnicmp + +SQLITE_PRIVATE int sqlite3MallocInit(void); +SQLITE_PRIVATE void sqlite3MallocEnd(void); +SQLITE_PRIVATE void *sqlite3Malloc(u64); +SQLITE_PRIVATE void *sqlite3MallocZero(u64); +SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3*, u64); +SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, u64); +SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*); +SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, u64); +SQLITE_PRIVATE void *sqlite3Realloc(void*, u64); +SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64); +SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64); +SQLITE_PRIVATE void sqlite3DbFree(sqlite3*, void*); +SQLITE_PRIVATE int sqlite3MallocSize(void*); +SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, void*); +SQLITE_PRIVATE void *sqlite3ScratchMalloc(int); +SQLITE_PRIVATE void sqlite3ScratchFree(void*); +SQLITE_PRIVATE void *sqlite3PageMalloc(int); +SQLITE_PRIVATE void sqlite3PageFree(void*); +SQLITE_PRIVATE void sqlite3MemSetDefault(void); +#ifndef SQLITE_OMIT_BUILTIN_TEST +SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); +#endif +SQLITE_PRIVATE int sqlite3HeapNearlyFull(void); + +/* +** On systems with ample stack space and that support alloca(), make +** use of alloca() to obtain space for large automatic objects. By default, +** obtain space from malloc(). +** +** The alloca() routine never returns NULL. This will cause code paths +** that deal with sqlite3StackAlloc() failures to be unreachable. +*/ +#ifdef SQLITE_USE_ALLOCA +# define sqlite3StackAllocRaw(D,N) alloca(N) +# define sqlite3StackAllocZero(D,N) memset(alloca(N), 0, N) +# define sqlite3StackFree(D,P) +#else +# define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N) +# define sqlite3StackAllocZero(D,N) sqlite3DbMallocZero(D,N) +# define sqlite3StackFree(D,P) sqlite3DbFree(D,P) +#endif + +#ifdef SQLITE_ENABLE_MEMSYS3 +SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void); +#endif +#ifdef SQLITE_ENABLE_MEMSYS5 +SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void); +#endif + + +#ifndef SQLITE_MUTEX_OMIT +SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void); +SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void); +SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int); +SQLITE_PRIVATE int sqlite3MutexInit(void); +SQLITE_PRIVATE int sqlite3MutexEnd(void); +#endif + +SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int); +SQLITE_PRIVATE void sqlite3StatusUp(int, int); +SQLITE_PRIVATE void sqlite3StatusDown(int, int); +SQLITE_PRIVATE void sqlite3StatusSet(int, int); + +/* Access to mutexes used by sqlite3_status() */ +SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void); +SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void); + +#ifndef SQLITE_OMIT_FLOATING_POINT +SQLITE_PRIVATE int sqlite3IsNaN(double); +#else +# define sqlite3IsNaN(X) 0 +#endif + +/* +** An instance of the following structure holds information about SQL +** functions arguments that are the parameters to the printf() function. +*/ +struct PrintfArguments { + int nArg; /* Total number of arguments */ + int nUsed; /* Number of arguments used so far */ + sqlite3_value **apArg; /* The argument values */ +}; + +#define SQLITE_PRINTF_INTERNAL 0x01 +#define SQLITE_PRINTF_SQLFUNC 0x02 +SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, u32, const char*, va_list); +SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, u32, const char*, ...); +SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); +SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) +SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); +#endif +#if defined(SQLITE_TEST) +SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); +#endif + +#if defined(SQLITE_DEBUG) +SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); +SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); +SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8); +#endif + + +SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); +SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); +SQLITE_PRIVATE int sqlite3Dequote(char*); +SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); +SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); +SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); +SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); +SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int); +SQLITE_PRIVATE int sqlite3GetTempRange(Parse*,int); +SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse*,int,int); +SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse*); +SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int); +SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*); +SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); +SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*); +SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); +SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); +SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*); +SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); +SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); +SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); +SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); +SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); +SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); +SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); +SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); +SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); +SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*); +SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int); +SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*); +SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int); +SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*); +SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*); +SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int); +SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*); +SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index*, i16); +SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); +SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*); +SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int); +SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); +SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*); +SQLITE_PRIVATE void sqlite3AddColumnType(Parse*,Token*); +SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*); +SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*); +SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); +SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*, + sqlite3_vfs**,char**,char **); +SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*); +SQLITE_PRIVATE int sqlite3CodeOnce(Parse *); + +#ifdef SQLITE_OMIT_BUILTIN_TEST +# define sqlite3FaultSim(X) SQLITE_OK +#else +SQLITE_PRIVATE int sqlite3FaultSim(int); +#endif + +SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32); +SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32); +SQLITE_PRIVATE int sqlite3BitvecTestNotNull(Bitvec*, u32); +SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32); +SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*); +SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*); +SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*); +#ifndef SQLITE_OMIT_BUILTIN_TEST +SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*); +#endif + +SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int); +SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*); +SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64); +SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, int iBatch, i64); +SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*); + +SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int); + +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) +SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse*,Table*); +#else +# define sqlite3ViewGetColumnNames(A,B) 0 +#endif + +#if SQLITE_MAX_ATTACHED>30 +SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask); +#endif +SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int); +SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int); +SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*); +#ifndef SQLITE_OMIT_AUTOINCREMENT +SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse); +SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse); +#else +# define sqlite3AutoincrementBegin(X) +# define sqlite3AutoincrementEnd(X) +#endif +SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int); +SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*); +SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); +SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*); +SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int); +SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*); +SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, + Token*, Select*, Expr*, IdList*); +SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *); +SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, struct SrcList_item *); +SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList*); +SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*); +SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*); +SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*); +SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**); +SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, + Expr*, int, int); +SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); +SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); +SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, + Expr*,ExprList*,u16,Expr*,Expr*); +SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); +SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); +SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int); +SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); +#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) +SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*); +#endif +SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); +SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); +SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); +SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); +SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo*); +SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*); +SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*); +SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*); +SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*); +SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*); +SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*, int*); +SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); +SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); +SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int); +SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int); +SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*); +SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*); +SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int); +SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*); +SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int); +SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int); +SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int); +SQLITE_PRIVATE void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8); +SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*); +SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int); +SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse*, Expr*, int); +SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, u8); +#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */ +#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */ +SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int); +SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int); +SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int); +SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*); +SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*); +SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *); +SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*); +SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); +SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); +SQLITE_PRIVATE void sqlite3Vacuum(Parse*); +SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*); +SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*); +SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*, int); +SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int); +SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr*, Expr*, int); +SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); +SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); +SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*); +SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*); +#ifndef SQLITE_OMIT_BUILTIN_TEST +SQLITE_PRIVATE void sqlite3PrngSaveState(void); +SQLITE_PRIVATE void sqlite3PrngRestoreState(void); +#endif +SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int); +SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int); +SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb); +SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int); +SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*); +SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*); +SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*); +SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *); +SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*); +SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*); +SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); +SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); +SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int); +SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*); +SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); +SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); +SQLITE_PRIVATE int sqlite3IsRowid(const char*); +SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8); +SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*); +SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); +SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int); +SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, + u8,u8,int,int*); +SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int); +SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, u8*, int*, int*); +SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int); +SQLITE_PRIVATE void sqlite3MultiWrite(Parse*); +SQLITE_PRIVATE void sqlite3MayAbort(Parse*); +SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, i8, u8); +SQLITE_PRIVATE void sqlite3UniqueConstraint(Parse*, int, Index*); +SQLITE_PRIVATE void sqlite3RowidConstraint(Parse*, int, Table*); +SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int); +SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int); +SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); +SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); +SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); +#if SELECTTRACE_ENABLED +SQLITE_PRIVATE void sqlite3SelectSetName(Select*,const char*); +#else +# define sqlite3SelectSetName(A,B) +#endif +SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); +SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8); +SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*); +SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); +SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void); +SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); +SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); +SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); + +#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) +SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, int); +#endif + +#ifndef SQLITE_OMIT_TRIGGER +SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, + Expr*,int, int); +SQLITE_PRIVATE void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); +SQLITE_PRIVATE void sqlite3DropTrigger(Parse*, SrcList*, int); +SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse*, Trigger*); +SQLITE_PRIVATE Trigger *sqlite3TriggersExist(Parse *, Table*, int, ExprList*, int *pMask); +SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *, Table *); +SQLITE_PRIVATE void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *, + int, int, int); +SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int); + void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); +SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); +SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*); +SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*, + Select*,u8); +SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8); +SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); +SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); +SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); +SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); +# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) +#else +# define sqlite3TriggersExist(B,C,D,E,F) 0 +# define sqlite3DeleteTrigger(A,B) +# define sqlite3DropTriggerPtr(A,B) +# define sqlite3UnlinkAndDeleteTrigger(A,B,C) +# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I) +# define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F) +# define sqlite3TriggerList(X, Y) 0 +# define sqlite3ParseToplevel(p) p +# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 +#endif + +SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); +SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); +SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int); +#ifndef SQLITE_OMIT_AUTHORIZATION +SQLITE_PRIVATE void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*); +SQLITE_PRIVATE int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*); +SQLITE_PRIVATE void sqlite3AuthContextPush(Parse*, AuthContext*, const char*); +SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext*); +SQLITE_PRIVATE int sqlite3AuthReadCol(Parse*, const char *, const char *, int); +#else +# define sqlite3AuthRead(a,b,c,d) +# define sqlite3AuthCheck(a,b,c,d,e) SQLITE_OK +# define sqlite3AuthContextPush(a,b,c) +# define sqlite3AuthContextPop(a) ((void)(a)) +#endif +SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*); +SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*); +SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*); +SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*); +SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*); +SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*); +SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*); +SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); +SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8); +SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*); +SQLITE_PRIVATE int sqlite3Atoi(const char*); +SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar); +SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); +SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**); +SQLITE_PRIVATE LogEst sqlite3LogEst(u64); +SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst); +#ifndef SQLITE_OMIT_VIRTUALTABLE +SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double); +#endif +SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst); + +/* +** Routines to read and write variable-length integers. These used to +** be defined locally, but now we use the varint routines in the util.c +** file. +*/ +SQLITE_PRIVATE int sqlite3PutVarint(unsigned char*, u64); +SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *, u64 *); +SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *, u32 *); +SQLITE_PRIVATE int sqlite3VarintLen(u64 v); + +/* +** The common case is for a varint to be a single byte. They following +** macros handle the common case without a procedure call, but then call +** the procedure for larger varints. +*/ +#define getVarint32(A,B) \ + (u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B))) +#define putVarint32(A,B) \ + (u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\ + sqlite3PutVarint((A),(B))) +#define getVarint sqlite3GetVarint +#define putVarint sqlite3PutVarint + + +SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *, Index *); +SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int); +SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2); +SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); +SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr); +SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8); +SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*); +SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...); +SQLITE_PRIVATE void sqlite3Error(sqlite3*,int); +SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n); +SQLITE_PRIVATE u8 sqlite3HexToInt(int h); +SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); + +#if defined(SQLITE_NEED_ERR_NAME) +SQLITE_PRIVATE const char *sqlite3ErrName(int); +#endif + +SQLITE_PRIVATE const char *sqlite3ErrStr(int); +SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); +SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); +SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); +SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int); +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); +SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); +SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); +SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *); +SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int); +SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); +SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64); +SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64); +SQLITE_PRIVATE int sqlite3AbsInt32(int); +#ifdef SQLITE_ENABLE_8_3_NAMES +SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*); +#else +# define sqlite3FileSuffix3(X,Y) +#endif +SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,u8); + +SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8); +SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8); +SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, + void(*)(void*)); +SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value*); +SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*); +SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *); +SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8); +SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); +SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); +#ifndef SQLITE_AMALGAMATION +SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[]; +SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[]; +SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[]; +SQLITE_PRIVATE const Token sqlite3IntTokens[]; +SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config; +SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions; +#ifndef SQLITE_OMIT_WSD +SQLITE_PRIVATE int sqlite3PendingByte; +#endif +#endif +SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, int, int); +SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*); +SQLITE_PRIVATE void sqlite3AlterFunctions(void); +SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); +SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); +SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); +SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); +SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); +SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); +SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p); +SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*); +SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); +SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); +SQLITE_PRIVATE void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*); +SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); +SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); +SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); +SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); +SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); +SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*); +SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*); +SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*); +SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*); +SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *); +SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB); +SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3*,Index*); +SQLITE_PRIVATE void sqlite3DefaultRowEst(Index*); +SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3*, int); +SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); +SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse*, int, int); +SQLITE_PRIVATE void sqlite3SchemaClear(void *); +SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *, Btree *); +SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *); +SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int); +SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo*); +SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo*); +SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*); +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo*); +#endif +SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, + void (*)(sqlite3_context*,int,sqlite3_value **), + void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), + FuncDestructor *pDestructor +); +SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); +SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); + +SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); +SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); +SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum*,const char*); +SQLITE_PRIVATE void sqlite3AppendChar(StrAccum*,int,char); +SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); +SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*); +SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int); +SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int); + +SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *); +SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *); + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void); +SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(Parse*,Index*,UnpackedRecord**,Expr*,u8,int,int*); +SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**); +SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord*); +SQLITE_PRIVATE int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**); +#endif + +/* +** The interface to the LEMON-generated parser +*/ +SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64)); +SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*)); +SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*); +#ifdef YYTRACKMAXSTACKDEPTH +SQLITE_PRIVATE int sqlite3ParserStackPeak(void*); +#endif + +SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3*); +#ifndef SQLITE_OMIT_LOAD_EXTENSION +SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3*); +#else +# define sqlite3CloseExtensions(X) +#endif + +#ifndef SQLITE_OMIT_SHARED_CACHE +SQLITE_PRIVATE void sqlite3TableLock(Parse *, int, int, u8, const char *); +#else + #define sqlite3TableLock(v,w,x,y,z) +#endif + +#ifdef SQLITE_TEST +SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*); +#endif + +#ifdef SQLITE_OMIT_VIRTUALTABLE +# define sqlite3VtabClear(Y) +# define sqlite3VtabSync(X,Y) SQLITE_OK +# define sqlite3VtabRollback(X) +# define sqlite3VtabCommit(X) +# define sqlite3VtabInSync(db) 0 +# define sqlite3VtabLock(X) +# define sqlite3VtabUnlock(X) +# define sqlite3VtabUnlockList(X) +# define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK +# define sqlite3GetVTable(X,Y) ((VTable*)0) +#else +SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table*); +SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p); +SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, Vdbe*); +SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db); +SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db); +SQLITE_PRIVATE void sqlite3VtabLock(VTable *); +SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *); +SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*); +SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int); +SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*); +SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*); +# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) +#endif +SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*); +SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int); +SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*); +SQLITE_PRIVATE void sqlite3VtabArgInit(Parse*); +SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse*, Token*); +SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **); +SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*); +SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); +SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); +SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); +SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); +SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); +SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); +SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); +SQLITE_PRIVATE void sqlite3ParserReset(Parse*); +SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); +SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); +SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); +SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*); +SQLITE_PRIVATE const char *sqlite3JournalModename(int); +#ifndef SQLITE_OMIT_WAL +SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*); +SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); +#endif +#ifndef SQLITE_OMIT_CTE +SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*); +SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*); +SQLITE_PRIVATE void sqlite3WithPush(Parse*, With*, u8); +#else +#define sqlite3WithPush(x,y,z) +#define sqlite3WithDelete(x,y) +#endif + +/* Declarations for functions in fkey.c. All of these are replaced by +** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign +** key functionality is available. If OMIT_TRIGGER is defined but +** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In +** this case foreign keys are parsed, but no other functionality is +** provided (enforcement of FK constraints requires the triggers sub-system). +*/ +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) +SQLITE_PRIVATE void sqlite3FkCheck(Parse*, Table*, int, int, int*, int); +SQLITE_PRIVATE void sqlite3FkDropTable(Parse*, SrcList *, Table*); +SQLITE_PRIVATE void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int); +SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int); +SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*); +SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *); +#else + #define sqlite3FkActions(a,b,c,d,e,f) + #define sqlite3FkCheck(a,b,c,d,e,f) + #define sqlite3FkDropTable(a,b,c) + #define sqlite3FkOldmask(a,b) 0 + #define sqlite3FkRequired(a,b,c,d) 0 +#endif +#ifndef SQLITE_OMIT_FOREIGN_KEY +SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); +SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**); +#else + #define sqlite3FkDelete(a,b) + #define sqlite3FkLocateIndex(a,b,c,d,e) +#endif + + +/* +** Available fault injectors. Should be numbered beginning with 0. +*/ +#define SQLITE_FAULTINJECTOR_MALLOC 0 +#define SQLITE_FAULTINJECTOR_COUNT 1 + +/* +** The interface to the code in fault.c used for identifying "benign" +** malloc failures. This is only present if SQLITE_OMIT_BUILTIN_TEST +** is not defined. +*/ +#ifndef SQLITE_OMIT_BUILTIN_TEST +SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void); +SQLITE_PRIVATE void sqlite3EndBenignMalloc(void); +#else + #define sqlite3BeginBenignMalloc() + #define sqlite3EndBenignMalloc() +#endif + +/* +** Allowed return values from sqlite3FindInIndex() +*/ +#define IN_INDEX_ROWID 1 /* Search the rowid of the table */ +#define IN_INDEX_EPH 2 /* Search an ephemeral b-tree */ +#define IN_INDEX_INDEX_ASC 3 /* Existing index ASCENDING */ +#define IN_INDEX_INDEX_DESC 4 /* Existing index DESCENDING */ +#define IN_INDEX_NOOP 5 /* No table available. Use comparisons */ +/* +** Allowed flags for the 3rd parameter to sqlite3FindInIndex(). +*/ +#define IN_INDEX_NOOP_OK 0x0001 /* OK to return IN_INDEX_NOOP */ +#define IN_INDEX_MEMBERSHIP 0x0002 /* IN operator used for membership test */ +#define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */ +SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*); + +#ifdef SQLITE_ENABLE_ATOMIC_WRITE +SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); +SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *); +SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *); +SQLITE_PRIVATE int sqlite3JournalExists(sqlite3_file *p); +#else + #define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile) + #define sqlite3JournalExists(p) 1 +#endif + +SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *); +SQLITE_PRIVATE int sqlite3MemJournalSize(void); +SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *); + +SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p); +#if SQLITE_MAX_EXPR_DEPTH>0 +SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *); +SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int); +#else + #define sqlite3SelectExprHeight(x) 0 + #define sqlite3ExprCheckHeight(x,y) +#endif + +SQLITE_PRIVATE u32 sqlite3Get4byte(const u8*); +SQLITE_PRIVATE void sqlite3Put4byte(u8*, u32); + +#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY +SQLITE_PRIVATE void sqlite3ConnectionBlocked(sqlite3 *, sqlite3 *); +SQLITE_PRIVATE void sqlite3ConnectionUnlocked(sqlite3 *db); +SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db); +#else + #define sqlite3ConnectionBlocked(x,y) + #define sqlite3ConnectionUnlocked(x) + #define sqlite3ConnectionClosed(x) +#endif + +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *); +#endif + +/* +** If the SQLITE_ENABLE IOTRACE exists then the global variable +** sqlite3IoTrace is a pointer to a printf-like routine used to +** print I/O tracing messages. +*/ +#ifdef SQLITE_ENABLE_IOTRACE +# define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } +SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*); +SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...); +#else +# define IOTRACE(A) +# define sqlite3VdbeIOTraceSql(X) +#endif + +/* +** These routines are available for the mem2.c debugging memory allocator +** only. They are used to verify that different "types" of memory +** allocations are properly tracked by the system. +** +** sqlite3MemdebugSetType() sets the "type" of an allocation to one of +** the MEMTYPE_* macros defined below. The type must be a bitmask with +** a single bit set. +** +** sqlite3MemdebugHasType() returns true if any of the bits in its second +** argument match the type set by the previous sqlite3MemdebugSetType(). +** sqlite3MemdebugHasType() is intended for use inside assert() statements. +** +** sqlite3MemdebugNoType() returns true if none of the bits in its second +** argument match the type set by the previous sqlite3MemdebugSetType(). +** +** Perhaps the most important point is the difference between MEMTYPE_HEAP +** and MEMTYPE_LOOKASIDE. If an allocation is MEMTYPE_LOOKASIDE, that means +** it might have been allocated by lookaside, except the allocation was +** too large or lookaside was already full. It is important to verify +** that allocations that might have been satisfied by lookaside are not +** passed back to non-lookaside free() routines. Asserts such as the +** example above are placed on the non-lookaside free() routines to verify +** this constraint. +** +** All of this is no-op for a production build. It only comes into +** play when the SQLITE_MEMDEBUG compile-time option is used. +*/ +#ifdef SQLITE_MEMDEBUG +SQLITE_PRIVATE void sqlite3MemdebugSetType(void*,u8); +SQLITE_PRIVATE int sqlite3MemdebugHasType(void*,u8); +SQLITE_PRIVATE int sqlite3MemdebugNoType(void*,u8); +#else +# define sqlite3MemdebugSetType(X,Y) /* no-op */ +# define sqlite3MemdebugHasType(X,Y) 1 +# define sqlite3MemdebugNoType(X,Y) 1 +#endif +#define MEMTYPE_HEAP 0x01 /* General heap allocations */ +#define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */ +#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */ +#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */ + +/* +** Threading interface +*/ +#if SQLITE_MAX_WORKER_THREADS>0 +SQLITE_PRIVATE int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*); +SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread*, void**); +#endif + +#if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST) +SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3*); +#endif + +#endif /* _SQLITEINT_H_ */ + +/************** End of sqliteInt.h *******************************************/ +/************** Begin file global.c ******************************************/ +/* +** 2008 June 13 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains definitions of global variables and constants. +*/ +/* #include "sqliteInt.h" */ + +/* An array to map all upper-case characters into their corresponding +** lower-case character. +** +** SQLite only considers US-ASCII (or EBCDIC) characters. We do not +** handle case conversions for the UTF character set since the tables +** involved are nearly as big or bigger than SQLite itself. +*/ +SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = { +#ifdef SQLITE_ASCII + 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 +#endif +#ifdef SQLITE_EBCDIC + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */ + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 2x */ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */ + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */ + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */ + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 6x */ + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 7x */ + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */ + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 9x */ + 160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */ + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */ + 192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */ + 208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */ + 224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */ + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */ +#endif +}; + +/* +** The following 256 byte lookup table is used to support SQLites built-in +** equivalents to the following standard library functions: +** +** isspace() 0x01 +** isalpha() 0x02 +** isdigit() 0x04 +** isalnum() 0x06 +** isxdigit() 0x08 +** toupper() 0x20 +** SQLite identifier character 0x40 +** +** Bit 0x20 is set if the mapped character requires translation to upper +** case. i.e. if the character is a lower-case ASCII character. +** If x is a lower-case ASCII character, then its upper-case equivalent +** is (x - 0x20). Therefore toupper() can be implemented as: +** +** (x & ~(map[x]&0x20)) +** +** Standard function tolower() is implemented using the sqlite3UpperToLower[] +** array. tolower() is used more often than toupper() by SQLite. +** +** Bit 0x40 is set if the character non-alphanumeric and can be used in an +** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any +** non-ASCII UTF character. Hence the test for whether or not a character is +** part of an identifier is 0x46. +** +** SQLite's versions are identical to the standard versions assuming a +** locale of "C". They are implemented as macros in sqliteInt.h. +*/ +#ifdef SQLITE_ASCII +SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */ + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17 ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f ........ */ + 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, /* 20..27 !"#$%&' */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f ()*+,-./ */ + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37 01234567 */ + 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f 89:;<=>? */ + + 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47 @ABCDEFG */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f HIJKLMNO */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57 PQRSTUVW */ + 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, /* 58..5f XYZ[\]^_ */ + 0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67 `abcdefg */ + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f hijklmno */ + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77 pqrstuvw */ + 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f xyz{|}~. */ + + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 80..87 ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 88..8f ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 90..97 ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 98..9f ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a0..a7 ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a8..af ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b0..b7 ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b8..bf ........ */ + + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c0..c7 ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c8..cf ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d0..d7 ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d8..df ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7 ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */ +}; +#endif + +/* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards +** compatibility for legacy applications, the URI filename capability is +** disabled by default. +** +** EVIDENCE-OF: R-38799-08373 URI filenames can be enabled or disabled +** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options. +** +** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally +** disabled. The default value may be changed by compiling with the +** SQLITE_USE_URI symbol defined. +*/ +#ifndef SQLITE_USE_URI +# define SQLITE_USE_URI 0 +#endif + +/* EVIDENCE-OF: R-38720-18127 The default setting is determined by the +** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if +** that compile-time option is omitted. +*/ +#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN +# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 +#endif + +/* The minimum PMA size is set to this value multiplied by the database +** page size in bytes. +*/ +#ifndef SQLITE_SORTER_PMASZ +# define SQLITE_SORTER_PMASZ 250 +#endif + +/* +** The following singleton contains the global configuration for +** the SQLite library. +*/ +SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { + SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */ + 1, /* bCoreMutex */ + SQLITE_THREADSAFE==1, /* bFullMutex */ + SQLITE_USE_URI, /* bOpenUri */ + SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ + 0x7ffffffe, /* mxStrlen */ + 0, /* neverCorrupt */ + 128, /* szLookaside */ + 500, /* nLookaside */ + {0,0,0,0,0,0,0,0}, /* m */ + {0,0,0,0,0,0,0,0,0}, /* mutex */ + {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */ + (void*)0, /* pHeap */ + 0, /* nHeap */ + 0, 0, /* mnHeap, mxHeap */ + SQLITE_DEFAULT_MMAP_SIZE, /* szMmap */ + SQLITE_MAX_MMAP_SIZE, /* mxMmap */ + (void*)0, /* pScratch */ + 0, /* szScratch */ + 0, /* nScratch */ + (void*)0, /* pPage */ + 0, /* szPage */ + SQLITE_DEFAULT_PCACHE_INITSZ, /* nPage */ + 0, /* mxParserStack */ + 0, /* sharedCacheEnabled */ + SQLITE_SORTER_PMASZ, /* szPma */ + /* All the rest should always be initialized to zero */ + 0, /* isInit */ + 0, /* inProgress */ + 0, /* isMutexInit */ + 0, /* isMallocInit */ + 0, /* isPCacheInit */ + 0, /* nRefInitMutex */ + 0, /* pInitMutex */ + 0, /* xLog */ + 0, /* pLogArg */ +#ifdef SQLITE_ENABLE_SQLLOG + 0, /* xSqllog */ + 0, /* pSqllogArg */ +#endif +#ifdef SQLITE_VDBE_COVERAGE + 0, /* xVdbeBranch */ + 0, /* pVbeBranchArg */ +#endif +#ifndef SQLITE_OMIT_BUILTIN_TEST + 0, /* xTestCallback */ +#endif + 0 /* bLocaltimeFault */ +}; + +/* +** Hash table for global functions - functions common to all +** database connections. After initialization, this table is +** read-only. +*/ +SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions; + +/* +** Constant tokens for values 0 and 1. +*/ +SQLITE_PRIVATE const Token sqlite3IntTokens[] = { + { "0", 1 }, + { "1", 1 } +}; + + +/* +** The value of the "pending" byte must be 0x40000000 (1 byte past the +** 1-gibabyte boundary) in a compatible database. SQLite never uses +** the database page that contains the pending byte. It never attempts +** to read or write that page. The pending byte page is set assign +** for use by the VFS layers as space for managing file locks. +** +** During testing, it is often desirable to move the pending byte to +** a different position in the file. This allows code that has to +** deal with the pending byte to run on files that are much smaller +** than 1 GiB. The sqlite3_test_control() interface can be used to +** move the pending byte. +** +** IMPORTANT: Changing the pending byte to any value other than +** 0x40000000 results in an incompatible database file format! +** Changing the pending byte during operation will result in undefined +** and incorrect behavior. +*/ +#ifndef SQLITE_OMIT_WSD +SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000; +#endif + +/* #include "opcodes.h" */ +/* +** Properties of opcodes. The OPFLG_INITIALIZER macro is +** created by mkopcodeh.awk during compilation. Data is obtained +** from the comments following the "case OP_xxxx:" statements in +** the vdbe.c file. +*/ +SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER; + +/************** End of global.c **********************************************/ +/************** Begin file ctime.c *******************************************/ +/* +** 2010 February 23 +** +** 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 routines used to report what compile-time options +** SQLite was built with. +*/ + +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS + +/* #include "sqliteInt.h" */ + +/* +** An array of names of all compile-time options. This array should +** be sorted A-Z. +** +** This array looks large, but in a typical installation actually uses +** only a handful of compile-time options, so most times this array is usually +** rather short and uses little memory space. +*/ +static const char * const azCompileOpt[] = { + +/* These macros are provided to "stringify" the value of the define +** for those options in which the value is meaningful. */ +#define CTIMEOPT_VAL_(opt) #opt +#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) + +#if SQLITE_32BIT_ROWID + "32BIT_ROWID", +#endif +#if SQLITE_4_BYTE_ALIGNED_MALLOC + "4_BYTE_ALIGNED_MALLOC", +#endif +#if SQLITE_CASE_SENSITIVE_LIKE + "CASE_SENSITIVE_LIKE", +#endif +#if SQLITE_CHECK_PAGES + "CHECK_PAGES", +#endif +#if SQLITE_COVERAGE_TEST + "COVERAGE_TEST", +#endif +#if SQLITE_DEBUG + "DEBUG", +#endif +#if SQLITE_DEFAULT_LOCKING_MODE + "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), +#endif +#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) + "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), +#endif +#if SQLITE_DISABLE_DIRSYNC + "DISABLE_DIRSYNC", +#endif +#if SQLITE_DISABLE_LFS + "DISABLE_LFS", +#endif +#if SQLITE_ENABLE_API_ARMOR + "ENABLE_API_ARMOR", +#endif +#if SQLITE_ENABLE_ATOMIC_WRITE + "ENABLE_ATOMIC_WRITE", +#endif +#if SQLITE_ENABLE_CEROD + "ENABLE_CEROD", +#endif +#if SQLITE_ENABLE_COLUMN_METADATA + "ENABLE_COLUMN_METADATA", +#endif +#if SQLITE_ENABLE_DBSTAT_VTAB + "ENABLE_DBSTAT_VTAB", +#endif +#if SQLITE_ENABLE_EXPENSIVE_ASSERT + "ENABLE_EXPENSIVE_ASSERT", +#endif +#if SQLITE_ENABLE_FTS1 + "ENABLE_FTS1", +#endif +#if SQLITE_ENABLE_FTS2 + "ENABLE_FTS2", +#endif +#if SQLITE_ENABLE_FTS3 + "ENABLE_FTS3", +#endif +#if SQLITE_ENABLE_FTS3_PARENTHESIS + "ENABLE_FTS3_PARENTHESIS", +#endif +#if SQLITE_ENABLE_FTS4 + "ENABLE_FTS4", +#endif +#if SQLITE_ENABLE_ICU + "ENABLE_ICU", +#endif +#if SQLITE_ENABLE_IOTRACE + "ENABLE_IOTRACE", +#endif +#if SQLITE_ENABLE_LOAD_EXTENSION + "ENABLE_LOAD_EXTENSION", +#endif +#if SQLITE_ENABLE_LOCKING_STYLE + "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), +#endif +#if SQLITE_ENABLE_MEMORY_MANAGEMENT + "ENABLE_MEMORY_MANAGEMENT", +#endif +#if SQLITE_ENABLE_MEMSYS3 + "ENABLE_MEMSYS3", +#endif +#if SQLITE_ENABLE_MEMSYS5 + "ENABLE_MEMSYS5", +#endif +#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK + "ENABLE_OVERSIZE_CELL_CHECK", +#endif +#if SQLITE_ENABLE_RTREE + "ENABLE_RTREE", +#endif +#if defined(SQLITE_ENABLE_STAT4) + "ENABLE_STAT4", +#elif defined(SQLITE_ENABLE_STAT3) + "ENABLE_STAT3", +#endif +#if SQLITE_ENABLE_UNLOCK_NOTIFY + "ENABLE_UNLOCK_NOTIFY", +#endif +#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT + "ENABLE_UPDATE_DELETE_LIMIT", +#endif +#if SQLITE_HAS_CODEC + "HAS_CODEC", +#endif +#if HAVE_ISNAN || SQLITE_HAVE_ISNAN + "HAVE_ISNAN", +#endif +#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX + "HOMEGROWN_RECURSIVE_MUTEX", +#endif +#if SQLITE_IGNORE_AFP_LOCK_ERRORS + "IGNORE_AFP_LOCK_ERRORS", +#endif +#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS + "IGNORE_FLOCK_LOCK_ERRORS", +#endif +#ifdef SQLITE_INT64_TYPE + "INT64_TYPE", +#endif +#if SQLITE_LOCK_TRACE + "LOCK_TRACE", +#endif +#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc) + "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE), +#endif +#ifdef SQLITE_MAX_SCHEMA_RETRY + "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY), +#endif +#if SQLITE_MEMDEBUG + "MEMDEBUG", +#endif +#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT + "MIXED_ENDIAN_64BIT_FLOAT", +#endif +#if SQLITE_NO_SYNC + "NO_SYNC", +#endif +#if SQLITE_OMIT_ALTERTABLE + "OMIT_ALTERTABLE", +#endif +#if SQLITE_OMIT_ANALYZE + "OMIT_ANALYZE", +#endif +#if SQLITE_OMIT_ATTACH + "OMIT_ATTACH", +#endif +#if SQLITE_OMIT_AUTHORIZATION + "OMIT_AUTHORIZATION", +#endif +#if SQLITE_OMIT_AUTOINCREMENT + "OMIT_AUTOINCREMENT", +#endif +#if SQLITE_OMIT_AUTOINIT + "OMIT_AUTOINIT", +#endif +#if SQLITE_OMIT_AUTOMATIC_INDEX + "OMIT_AUTOMATIC_INDEX", +#endif +#if SQLITE_OMIT_AUTORESET + "OMIT_AUTORESET", +#endif +#if SQLITE_OMIT_AUTOVACUUM + "OMIT_AUTOVACUUM", +#endif +#if SQLITE_OMIT_BETWEEN_OPTIMIZATION + "OMIT_BETWEEN_OPTIMIZATION", +#endif +#if SQLITE_OMIT_BLOB_LITERAL + "OMIT_BLOB_LITERAL", +#endif +#if SQLITE_OMIT_BTREECOUNT + "OMIT_BTREECOUNT", +#endif +#if SQLITE_OMIT_BUILTIN_TEST + "OMIT_BUILTIN_TEST", +#endif +#if SQLITE_OMIT_CAST + "OMIT_CAST", +#endif +#if SQLITE_OMIT_CHECK + "OMIT_CHECK", +#endif +#if SQLITE_OMIT_COMPLETE + "OMIT_COMPLETE", +#endif +#if SQLITE_OMIT_COMPOUND_SELECT + "OMIT_COMPOUND_SELECT", +#endif +#if SQLITE_OMIT_CTE + "OMIT_CTE", +#endif +#if SQLITE_OMIT_DATETIME_FUNCS + "OMIT_DATETIME_FUNCS", +#endif +#if SQLITE_OMIT_DECLTYPE + "OMIT_DECLTYPE", +#endif +#if SQLITE_OMIT_DEPRECATED + "OMIT_DEPRECATED", +#endif +#if SQLITE_OMIT_DISKIO + "OMIT_DISKIO", +#endif +#if SQLITE_OMIT_EXPLAIN + "OMIT_EXPLAIN", +#endif +#if SQLITE_OMIT_FLAG_PRAGMAS + "OMIT_FLAG_PRAGMAS", +#endif +#if SQLITE_OMIT_FLOATING_POINT + "OMIT_FLOATING_POINT", +#endif +#if SQLITE_OMIT_FOREIGN_KEY + "OMIT_FOREIGN_KEY", +#endif +#if SQLITE_OMIT_GET_TABLE + "OMIT_GET_TABLE", +#endif +#if SQLITE_OMIT_INCRBLOB + "OMIT_INCRBLOB", +#endif +#if SQLITE_OMIT_INTEGRITY_CHECK + "OMIT_INTEGRITY_CHECK", +#endif +#if SQLITE_OMIT_LIKE_OPTIMIZATION + "OMIT_LIKE_OPTIMIZATION", +#endif +#if SQLITE_OMIT_LOAD_EXTENSION + "OMIT_LOAD_EXTENSION", +#endif +#if SQLITE_OMIT_LOCALTIME + "OMIT_LOCALTIME", +#endif +#if SQLITE_OMIT_LOOKASIDE + "OMIT_LOOKASIDE", +#endif +#if SQLITE_OMIT_MEMORYDB + "OMIT_MEMORYDB", +#endif +#if SQLITE_OMIT_OR_OPTIMIZATION + "OMIT_OR_OPTIMIZATION", +#endif +#if SQLITE_OMIT_PAGER_PRAGMAS + "OMIT_PAGER_PRAGMAS", +#endif +#if SQLITE_OMIT_PRAGMA + "OMIT_PRAGMA", +#endif +#if SQLITE_OMIT_PROGRESS_CALLBACK + "OMIT_PROGRESS_CALLBACK", +#endif +#if SQLITE_OMIT_QUICKBALANCE + "OMIT_QUICKBALANCE", +#endif +#if SQLITE_OMIT_REINDEX + "OMIT_REINDEX", +#endif +#if SQLITE_OMIT_SCHEMA_PRAGMAS + "OMIT_SCHEMA_PRAGMAS", +#endif +#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS + "OMIT_SCHEMA_VERSION_PRAGMAS", +#endif +#if SQLITE_OMIT_SHARED_CACHE + "OMIT_SHARED_CACHE", +#endif +#if SQLITE_OMIT_SUBQUERY + "OMIT_SUBQUERY", +#endif +#if SQLITE_OMIT_TCL_VARIABLE + "OMIT_TCL_VARIABLE", +#endif +#if SQLITE_OMIT_TEMPDB + "OMIT_TEMPDB", +#endif +#if SQLITE_OMIT_TRACE + "OMIT_TRACE", +#endif +#if SQLITE_OMIT_TRIGGER + "OMIT_TRIGGER", +#endif +#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION + "OMIT_TRUNCATE_OPTIMIZATION", +#endif +#if SQLITE_OMIT_UTF16 + "OMIT_UTF16", +#endif +#if SQLITE_OMIT_VACUUM + "OMIT_VACUUM", +#endif +#if SQLITE_OMIT_VIEW + "OMIT_VIEW", +#endif +#if SQLITE_OMIT_VIRTUALTABLE + "OMIT_VIRTUALTABLE", +#endif +#if SQLITE_OMIT_WAL + "OMIT_WAL", +#endif +#if SQLITE_OMIT_WSD + "OMIT_WSD", +#endif +#if SQLITE_OMIT_XFER_OPT + "OMIT_XFER_OPT", +#endif +#if SQLITE_PERFORMANCE_TRACE + "PERFORMANCE_TRACE", +#endif +#if SQLITE_PROXY_DEBUG + "PROXY_DEBUG", +#endif +#if SQLITE_RTREE_INT_ONLY + "RTREE_INT_ONLY", +#endif +#if SQLITE_SECURE_DELETE + "SECURE_DELETE", +#endif +#if SQLITE_SMALL_STACK + "SMALL_STACK", +#endif +#if SQLITE_SOUNDEX + "SOUNDEX", +#endif +#if SQLITE_SYSTEM_MALLOC + "SYSTEM_MALLOC", +#endif +#if SQLITE_TCL + "TCL", +#endif +#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc) + "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), +#endif +#if SQLITE_TEST + "TEST", +#endif +#if defined(SQLITE_THREADSAFE) + "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), +#endif +#if SQLITE_USE_ALLOCA + "USE_ALLOCA", +#endif +#if SQLITE_USER_AUTHENTICATION + "USER_AUTHENTICATION", +#endif +#if SQLITE_WIN32_MALLOC + "WIN32_MALLOC", +#endif +#if SQLITE_ZERO_MALLOC + "ZERO_MALLOC" +#endif +}; + +/* +** Given the name of a compile-time option, return true if that option +** was used and false if not. +** +** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix +** is not required for a match. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName){ + int i, n; + +#if SQLITE_ENABLE_API_ARMOR + if( zOptName==0 ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; + n = sqlite3Strlen30(zOptName); + + /* Since ArraySize(azCompileOpt) is normally in single digits, a + ** linear search is adequate. No need for a binary search. */ + for(i=0; i=0 && NaDb[] (or -1) */ + u8 nullRow; /* True if pointing to a row with no data */ + u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ + Bool isEphemeral:1; /* True for an ephemeral table */ + Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ + Bool isTable:1; /* True if a table requiring integer keys */ + Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */ + Pgno pgnoRoot; /* Root page of the open btree cursor */ + sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */ + i64 seqCount; /* Sequence counter */ + i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ + VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */ +#ifdef SQLITE_ENABLE_COLUMN_USED_MASK + u64 maskUsed; /* Mask of columns used by this cursor */ +#endif + + /* Cached information about the header for the data record that the + ** cursor is currently pointing to. Only valid if cacheStatus matches + ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of + ** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that + ** the cache is out of date. + ** + ** aRow might point to (ephemeral) data for the current row, or it might + ** be NULL. + */ + u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */ + u32 payloadSize; /* Total number of bytes in the record */ + u32 szRow; /* Byte available in aRow */ + u32 iHdrOffset; /* Offset to next unparsed byte of the header */ + const u8 *aRow; /* Data for the current row, if all on one page */ + u32 *aOffset; /* Pointer to aType[nField] */ + u32 aType[1]; /* Type values for all entries in the record */ + /* 2*nField extra array elements allocated for aType[], beyond the one + ** static element declared in the structure. nField total array slots for + ** aType[] and nField+1 array slots for aOffset[] */ +}; +typedef struct VdbeCursor VdbeCursor; + +/* +** When a sub-program is executed (OP_Program), a structure of this type +** is allocated to store the current value of the program counter, as +** well as the current memory cell array and various other frame specific +** values stored in the Vdbe struct. When the sub-program is finished, +** these values are copied back to the Vdbe from the VdbeFrame structure, +** restoring the state of the VM to as it was before the sub-program +** began executing. +** +** The memory for a VdbeFrame object is allocated and managed by a memory +** cell in the parent (calling) frame. When the memory cell is deleted or +** overwritten, the VdbeFrame object is not freed immediately. Instead, it +** is linked into the Vdbe.pDelFrame list. The contents of the Vdbe.pDelFrame +** list is deleted when the VM is reset in VdbeHalt(). The reason for doing +** this instead of deleting the VdbeFrame immediately is to avoid recursive +** calls to sqlite3VdbeMemRelease() when the memory cells belonging to the +** child frame are released. +** +** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is +** set to NULL if the currently executing frame is the main program. +*/ +typedef struct VdbeFrame VdbeFrame; +struct VdbeFrame { + Vdbe *v; /* VM this frame belongs to */ + VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */ + Op *aOp; /* Program instructions for parent frame */ + i64 *anExec; /* Event counters from parent frame */ + Mem *aMem; /* Array of memory cells for parent frame */ + u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */ + VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ + void *token; /* Copy of SubProgram.token */ + i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ + int nCursor; /* Number of entries in apCsr */ + int pc; /* Program Counter in parent (calling) frame */ + int nOp; /* Size of aOp array */ + int nMem; /* Number of entries in aMem */ + int nOnceFlag; /* Number of entries in aOnceFlag */ + int nChildMem; /* Number of memory cells for child frame */ + int nChildCsr; /* Number of cursors for child frame */ + int nChange; /* Statement changes (Vdbe.nChange) */ + int nDbChange; /* Value of db->nChange */ +}; + +#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) + +/* +** A value for VdbeCursor.cacheValid that means the cache is always invalid. +*/ +#define CACHE_STALE 0 + +/* +** Internally, the vdbe manipulates nearly all SQL values as Mem +** structures. Each Mem struct may cache multiple representations (string, +** integer etc.) of the same value. +*/ +struct Mem { + union MemValue { + double r; /* Real value used when MEM_Real is set in flags */ + i64 i; /* Integer value used when MEM_Int is set in flags */ + int nZero; /* Used when bit MEM_Zero is set in flags */ + FuncDef *pDef; /* Used only when flags==MEM_Agg */ + RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ + VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ + } u; + u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ + u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ + int n; /* Number of characters in string value, excluding '\0' */ + char *z; /* String or BLOB value */ + /* ShallowCopy only needs to copy the information above */ + char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */ + int szMalloc; /* Size of the zMalloc allocation */ + u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */ + sqlite3 *db; /* The associated database connection */ + void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */ +#ifdef SQLITE_DEBUG + Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ + void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */ +#endif +}; + +/* +** Size of struct Mem not including the Mem.zMalloc member or anything that +** follows. +*/ +#define MEMCELLSIZE offsetof(Mem,zMalloc) + +/* One or more of the following flags are set to indicate the validOK +** representations of the value stored in the Mem struct. +** +** If the MEM_Null flag is set, then the value is an SQL NULL value. +** No other flags may be set in this case. +** +** If the MEM_Str flag is set then Mem.z points at a string representation. +** Usually this is encoded in the same unicode encoding as the main +** database (see below for exceptions). If the MEM_Term flag is also +** set, then the string is nul terminated. The MEM_Int and MEM_Real +** flags may coexist with the MEM_Str flag. +*/ +#define MEM_Null 0x0001 /* Value is NULL */ +#define MEM_Str 0x0002 /* Value is a string */ +#define MEM_Int 0x0004 /* Value is an integer */ +#define MEM_Real 0x0008 /* Value is a real number */ +#define MEM_Blob 0x0010 /* Value is a BLOB */ +#define MEM_AffMask 0x001f /* Mask of affinity bits */ +#define MEM_RowSet 0x0020 /* Value is a RowSet object */ +#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ +#define MEM_Undefined 0x0080 /* Value is undefined */ +#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ +#define MEM_TypeMask 0x01ff /* Mask of type bits */ + + +/* Whenever Mem contains a valid string or blob representation, one of +** the following flags must be set to determine the memory management +** policy for Mem.z. The MEM_Term flag tells us whether or not the +** string is \000 or \u0000 terminated +*/ +#define MEM_Term 0x0200 /* String rep is nul terminated */ +#define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */ +#define MEM_Static 0x0800 /* Mem.z points to a static string */ +#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */ +#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */ +#define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */ +#ifdef SQLITE_OMIT_INCRBLOB + #undef MEM_Zero + #define MEM_Zero 0x0000 +#endif + +/* +** Clear any existing type flags from a Mem and replace them with f +*/ +#define MemSetTypeFlag(p, f) \ + ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f) + +/* +** Return true if a memory cell is not marked as invalid. This macro +** is for use inside assert() statements only. +*/ +#ifdef SQLITE_DEBUG +#define memIsValid(M) ((M)->flags & MEM_Undefined)==0 +#endif + +/* +** Each auxiliary data pointer stored by a user defined function +** implementation calling sqlite3_set_auxdata() is stored in an instance +** of this structure. All such structures associated with a single VM +** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed +** when the VM is halted (if not before). +*/ +struct AuxData { + int iOp; /* Instruction number of OP_Function opcode */ + int iArg; /* Index of function argument. */ + void *pAux; /* Aux data pointer */ + void (*xDelete)(void *); /* Destructor for the aux data */ + AuxData *pNext; /* Next element in list */ +}; + +/* +** The "context" argument for an installable function. A pointer to an +** instance of this structure is the first argument to the routines used +** implement the SQL functions. +** +** There is a typedef for this structure in sqlite.h. So all routines, +** even the public interface to SQLite, can use a pointer to this structure. +** But this file is the only place where the internal details of this +** structure are known. +** +** This structure is defined inside of vdbeInt.h because it uses substructures +** (Mem) which are only defined there. +*/ +struct sqlite3_context { + Mem *pOut; /* The return value is stored here */ + FuncDef *pFunc; /* Pointer to function information */ + Mem *pMem; /* Memory cell used to store aggregate context */ + Vdbe *pVdbe; /* The VM that owns this context */ + int iOp; /* Instruction number of OP_Function */ + int isError; /* Error code returned by the function. */ + u8 skipFlag; /* Skip accumulator loading if true */ + u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */ + u8 argc; /* Number of arguments */ + sqlite3_value *argv[1]; /* Argument set */ +}; + +/* +** An Explain object accumulates indented output which is helpful +** in describing recursive data structures. +*/ +struct Explain { + Vdbe *pVdbe; /* Attach the explanation to this Vdbe */ + StrAccum str; /* The string being accumulated */ + int nIndent; /* Number of elements in aIndent */ + u16 aIndent[100]; /* Levels of indentation */ + char zBase[100]; /* Initial space */ +}; + +/* A bitfield type for use inside of structures. Always follow with :N where +** N is the number of bits. +*/ +typedef unsigned bft; /* Bit Field Type */ + +typedef struct ScanStatus ScanStatus; +struct ScanStatus { + int addrExplain; /* OP_Explain for loop */ + int addrLoop; /* Address of "loops" counter */ + int addrVisit; /* Address of "rows visited" counter */ + int iSelectID; /* The "Select-ID" for this loop */ + LogEst nEst; /* Estimated output rows per loop */ + char *zName; /* Name of table or index */ +}; + +/* +** An instance of the virtual machine. This structure contains the complete +** state of the virtual machine. +** +** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare() +** is really a pointer to an instance of this structure. +*/ +struct Vdbe { + sqlite3 *db; /* The database connection that owns this statement */ + Op *aOp; /* Space to hold the virtual machine's program */ + Mem *aMem; /* The memory locations */ + Mem **apArg; /* Arguments to currently executing user function */ + Mem *aColName; /* Column names to return */ + Mem *pResultSet; /* Pointer to an array of results */ + Parse *pParse; /* Parsing context used to create this Vdbe */ + int nMem; /* Number of memory locations currently allocated */ + int nOp; /* Number of instructions in the program */ + int nCursor; /* Number of slots in apCsr[] */ + u32 magic; /* Magic number for sanity checking */ + char *zErrMsg; /* Error message written here */ + Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ + VdbeCursor **apCsr; /* One element of this array for each open cursor */ + Mem *aVar; /* Values for the OP_Variable opcode. */ + char **azVar; /* Name of variables */ + ynVar nVar; /* Number of entries in aVar[] */ + ynVar nzVar; /* Number of entries in azVar[] */ + u32 cacheCtr; /* VdbeCursor row cache generation counter */ + int pc; /* The program counter */ + int rc; /* Value to return */ +#ifdef SQLITE_DEBUG + int rcApp; /* errcode set by sqlite3_result_error_code() */ +#endif + u16 nResColumn; /* Number of columns in one row of the result set */ + u8 errorAction; /* Recovery action to do in case of an error */ + u8 minWriteFileFormat; /* Minimum file format for writable database files */ + bft explain:2; /* True if EXPLAIN present on SQL command */ + bft changeCntOn:1; /* True to update the change-counter */ + bft expired:1; /* True if the VM needs to be recompiled */ + bft runOnlyOnce:1; /* Automatically expire on reset */ + bft usesStmtJournal:1; /* True if uses a statement journal */ + bft readOnly:1; /* True for statements that do not write */ + bft bIsReader:1; /* True for statements that read */ + bft isPrepareV2:1; /* True if prepared with prepare_v2() */ + bft doingRerun:1; /* True if rerunning after an auto-reprepare */ + int nChange; /* Number of db changes made since last reset */ + yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ + yDbMask lockMask; /* Subset of btreeMask that requires a lock */ + int iStatement; /* Statement number (or 0 if has not opened stmt) */ + u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */ +#ifndef SQLITE_OMIT_TRACE + i64 startTime; /* Time when query started - used for profiling */ +#endif + i64 iCurrentTime; /* Value of julianday('now') for this statement */ + i64 nFkConstraint; /* Number of imm. FK constraints this VM */ + i64 nStmtDefCons; /* Number of def. constraints when stmt started */ + i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ + char *zSql; /* Text of the SQL statement that generated this */ + void *pFree; /* Free this when deleting the vdbe */ + VdbeFrame *pFrame; /* Parent frame */ + VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ + int nFrame; /* Number of frames in pFrame list */ + u32 expmask; /* Binding to these vars invalidates VM */ + SubProgram *pProgram; /* Linked list of all sub-programs used by VM */ + int nOnceFlag; /* Size of array aOnceFlag[] */ + u8 *aOnceFlag; /* Flags for OP_Once */ + AuxData *pAuxData; /* Linked list of auxdata allocations */ +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + i64 *anExec; /* Number of times each op has been executed */ + int nScan; /* Entries in aScan[] */ + ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */ +#endif +}; + +/* +** The following are allowed values for Vdbe.magic +*/ +#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ +#define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ +#define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */ +#define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ + +/* +** Function prototypes +*/ +SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...); +SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); +void sqliteVdbePopStack(Vdbe*,int); +SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*); +SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*); +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) +SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); +#endif +SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); +SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int); +SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32); +SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); +SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe*, int, int); + +int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); +SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*); +SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*); +SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*); +SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*); +SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*); +SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int); +SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*); +SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*); +SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); +SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); +SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); +SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); +SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); +#ifdef SQLITE_OMIT_FLOATING_POINT +# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 +#else +SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); +#endif +SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16); +SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); +SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); +SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*); +SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); +SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); +SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*); +SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); +SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); +SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); +SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); +SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); +SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8); +SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*); +SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); +#define VdbeMemDynamic(X) \ + (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) +SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); +SQLITE_PRIVATE const char *sqlite3OpcodeName(int); +SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); +SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); +SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); +SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); +SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *); +SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p); + +SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *); +SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *); +SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *); +SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *); +SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *); +SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *, int *); +SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *); +SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *); + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0 +SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*); +#else +# define sqlite3VdbeEnter(X) +# define sqlite3VdbeLeave(X) +#endif + +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*); +SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem*); +#endif + +#ifndef SQLITE_OMIT_FOREIGN_KEY +SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int); +#else +# define sqlite3VdbeCheckFk(p,i) 0 +#endif + +SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8); +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf); +#endif +SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem); + +#ifndef SQLITE_OMIT_INCRBLOB +SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *); + #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0) +#else + #define sqlite3VdbeMemExpandBlob(x) SQLITE_OK + #define ExpandBlob(P) SQLITE_OK +#endif + +#endif /* !defined(_VDBEINT_H_) */ + +/************** End of vdbeInt.h *********************************************/ +/************** Continuing where we left off in status.c *********************/ + +/* +** Variables in which to record status information. +*/ +typedef struct sqlite3StatType sqlite3StatType; +static SQLITE_WSD struct sqlite3StatType { +#if SQLITE_PTRSIZE>4 + sqlite3_int64 nowValue[10]; /* Current value */ + sqlite3_int64 mxValue[10]; /* Maximum value */ +#else + u32 nowValue[10]; /* Current value */ + u32 mxValue[10]; /* Maximum value */ +#endif +} sqlite3Stat = { {0,}, {0,} }; + +/* +** Elements of sqlite3Stat[] are protected by either the memory allocator +** mutex, or by the pcache1 mutex. The following array determines which. +*/ +static const char statMutex[] = { + 0, /* SQLITE_STATUS_MEMORY_USED */ + 1, /* SQLITE_STATUS_PAGECACHE_USED */ + 1, /* SQLITE_STATUS_PAGECACHE_OVERFLOW */ + 0, /* SQLITE_STATUS_SCRATCH_USED */ + 0, /* SQLITE_STATUS_SCRATCH_OVERFLOW */ + 0, /* SQLITE_STATUS_MALLOC_SIZE */ + 0, /* SQLITE_STATUS_PARSER_STACK */ + 1, /* SQLITE_STATUS_PAGECACHE_SIZE */ + 0, /* SQLITE_STATUS_SCRATCH_SIZE */ + 0, /* SQLITE_STATUS_MALLOC_COUNT */ +}; + + +/* The "wsdStat" macro will resolve to the status information +** state vector. If writable static data is unsupported on the target, +** we have to locate the state vector at run-time. In the more common +** case where writable static data is supported, wsdStat can refer directly +** to the "sqlite3Stat" state vector declared above. +*/ +#ifdef SQLITE_OMIT_WSD +# define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat) +# define wsdStat x[0] +#else +# define wsdStatInit +# define wsdStat sqlite3Stat +#endif + +/* +** Return the current value of a status parameter. The caller must +** be holding the appropriate mutex. +*/ +SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int op){ + wsdStatInit; + assert( op>=0 && op=0 && op=0 && op=0 && opwsdStat.mxValue[op] ){ + wsdStat.mxValue[op] = wsdStat.nowValue[op]; + } +} +SQLITE_PRIVATE void sqlite3StatusDown(int op, int N){ + wsdStatInit; + assert( N>=0 ); + assert( op>=0 && op=0 && op=0 && op=0 && opwsdStat.mxValue[op] ){ + wsdStat.mxValue[op] = wsdStat.nowValue[op]; + } +} + +/* +** Query status information. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_status64( + int op, + sqlite3_int64 *pCurrent, + sqlite3_int64 *pHighwater, + int resetFlag +){ + sqlite3_mutex *pMutex; + wsdStatInit; + if( op<0 || op>=ArraySize(wsdStat.nowValue) ){ + return SQLITE_MISUSE_BKPT; + } +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; +#endif + pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex(); + sqlite3_mutex_enter(pMutex); + *pCurrent = wsdStat.nowValue[op]; + *pHighwater = wsdStat.mxValue[op]; + if( resetFlag ){ + wsdStat.mxValue[op] = wsdStat.nowValue[op]; + } + sqlite3_mutex_leave(pMutex); + (void)pMutex; /* Prevent warning when SQLITE_THREADSAFE=0 */ + return SQLITE_OK; +} +SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ + sqlite3_int64 iCur, iHwtr; + int rc; +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; +#endif + rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag); + if( rc==0 ){ + *pCurrent = (int)iCur; + *pHighwater = (int)iHwtr; + } + return rc; +} + +/* +** Query status information for a single database connection +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_db_status( + sqlite3 *db, /* The database connection whose status is desired */ + int op, /* Status verb */ + int *pCurrent, /* Write current value here */ + int *pHighwater, /* Write high-water mark here */ + int resetFlag /* Reset high-water mark if true */ +){ + int rc = SQLITE_OK; /* Return code */ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwater==0 ){ + return SQLITE_MISUSE_BKPT; + } +#endif + sqlite3_mutex_enter(db->mutex); + switch( op ){ + case SQLITE_DBSTATUS_LOOKASIDE_USED: { + *pCurrent = db->lookaside.nOut; + *pHighwater = db->lookaside.mxOut; + if( resetFlag ){ + db->lookaside.mxOut = db->lookaside.nOut; + } + break; + } + + case SQLITE_DBSTATUS_LOOKASIDE_HIT: + case SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE: + case SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: { + testcase( op==SQLITE_DBSTATUS_LOOKASIDE_HIT ); + testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE ); + testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL ); + assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 ); + assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 ); + *pCurrent = 0; + *pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT]; + if( resetFlag ){ + db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0; + } + break; + } + + /* + ** Return an approximation for the amount of memory currently used + ** by all pagers associated with the given database connection. The + ** highwater mark is meaningless and is returned as zero. + */ + case SQLITE_DBSTATUS_CACHE_USED: { + int totalUsed = 0; + int i; + sqlite3BtreeEnterAll(db); + for(i=0; inDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + Pager *pPager = sqlite3BtreePager(pBt); + totalUsed += sqlite3PagerMemUsed(pPager); + } + } + sqlite3BtreeLeaveAll(db); + *pCurrent = totalUsed; + *pHighwater = 0; + break; + } + + /* + ** *pCurrent gets an accurate estimate of the amount of memory used + ** to store the schema for all databases (main, temp, and any ATTACHed + ** databases. *pHighwater is set to zero. + */ + case SQLITE_DBSTATUS_SCHEMA_USED: { + int i; /* Used to iterate through schemas */ + int nByte = 0; /* Used to accumulate return value */ + + sqlite3BtreeEnterAll(db); + db->pnBytesFreed = &nByte; + for(i=0; inDb; i++){ + Schema *pSchema = db->aDb[i].pSchema; + if( ALWAYS(pSchema!=0) ){ + HashElem *p; + + nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * ( + pSchema->tblHash.count + + pSchema->trigHash.count + + pSchema->idxHash.count + + pSchema->fkeyHash.count + ); + nByte += sqlite3MallocSize(pSchema->tblHash.ht); + nByte += sqlite3MallocSize(pSchema->trigHash.ht); + nByte += sqlite3MallocSize(pSchema->idxHash.ht); + nByte += sqlite3MallocSize(pSchema->fkeyHash.ht); + + for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){ + sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p)); + } + for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ + sqlite3DeleteTable(db, (Table *)sqliteHashData(p)); + } + } + } + db->pnBytesFreed = 0; + sqlite3BtreeLeaveAll(db); + + *pHighwater = 0; + *pCurrent = nByte; + break; + } + + /* + ** *pCurrent gets an accurate estimate of the amount of memory used + ** to store all prepared statements. + ** *pHighwater is set to zero. + */ + case SQLITE_DBSTATUS_STMT_USED: { + struct Vdbe *pVdbe; /* Used to iterate through VMs */ + int nByte = 0; /* Used to accumulate return value */ + + db->pnBytesFreed = &nByte; + for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){ + sqlite3VdbeClearObject(db, pVdbe); + sqlite3DbFree(db, pVdbe); + } + db->pnBytesFreed = 0; + + *pHighwater = 0; /* IMP: R-64479-57858 */ + *pCurrent = nByte; + + break; + } + + /* + ** Set *pCurrent to the total cache hits or misses encountered by all + ** pagers the database handle is connected to. *pHighwater is always set + ** to zero. + */ + case SQLITE_DBSTATUS_CACHE_HIT: + case SQLITE_DBSTATUS_CACHE_MISS: + case SQLITE_DBSTATUS_CACHE_WRITE:{ + int i; + int nRet = 0; + assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 ); + assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 ); + + for(i=0; inDb; i++){ + if( db->aDb[i].pBt ){ + Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt); + sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet); + } + } + *pHighwater = 0; /* IMP: R-42420-56072 */ + /* IMP: R-54100-20147 */ + /* IMP: R-29431-39229 */ + *pCurrent = nRet; + break; + } + + /* Set *pCurrent to non-zero if there are unresolved deferred foreign + ** key constraints. Set *pCurrent to zero if all foreign key constraints + ** have been satisfied. The *pHighwater is always set to zero. + */ + case SQLITE_DBSTATUS_DEFERRED_FKS: { + *pHighwater = 0; /* IMP: R-11967-56545 */ + *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0; + break; + } + + default: { + rc = SQLITE_ERROR; + } + } + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/************** End of status.c **********************************************/ +/************** Begin file date.c ********************************************/ +/* +** 2003 October 31 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains the C functions that implement date and time +** functions for SQLite. +** +** There is only one exported symbol in this file - the function +** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. +** All other code has file scope. +** +** SQLite processes all times and dates as julian day numbers. The +** dates and times are stored as the number of days since noon +** in Greenwich on November 24, 4714 B.C. according to the Gregorian +** calendar system. +** +** 1970-01-01 00:00:00 is JD 2440587.5 +** 2000-01-01 00:00:00 is JD 2451544.5 +** +** This implementation requires years to be expressed as a 4-digit number +** which means that only dates between 0000-01-01 and 9999-12-31 can +** be represented, even though julian day numbers allow a much wider +** range of dates. +** +** The Gregorian calendar system is used for all dates and times, +** even those that predate the Gregorian calendar. Historians usually +** use the julian calendar for dates prior to 1582-10-15 and for some +** dates afterwards, depending on locale. Beware of this difference. +** +** The conversion algorithms are implemented based on descriptions +** in the following text: +** +** Jean Meeus +** Astronomical Algorithms, 2nd Edition, 1998 +** ISBM 0-943396-61-1 +** Willmann-Bell, Inc +** Richmond, Virginia (USA) +*/ +/* #include "sqliteInt.h" */ +/* #include */ +/* #include */ +#include + +#ifndef SQLITE_OMIT_DATETIME_FUNCS + + +/* +** A structure for holding a single date and time. +*/ +typedef struct DateTime DateTime; +struct DateTime { + sqlite3_int64 iJD; /* The julian day number times 86400000 */ + int Y, M, D; /* Year, month, and day */ + int h, m; /* Hour and minutes */ + int tz; /* Timezone offset in minutes */ + double s; /* Seconds */ + char validYMD; /* True (1) if Y,M,D are valid */ + char validHMS; /* True (1) if h,m,s are valid */ + char validJD; /* True (1) if iJD is valid */ + char validTZ; /* True (1) if tz is valid */ +}; + + +/* +** Convert zDate into one or more integers. Additional arguments +** come in groups of 5 as follows: +** +** N number of digits in the integer +** min minimum allowed value of the integer +** max maximum allowed value of the integer +** nextC first character after the integer +** pVal where to write the integers value. +** +** Conversions continue until one with nextC==0 is encountered. +** The function returns the number of successful conversions. +*/ +static int getDigits(const char *zDate, ...){ + va_list ap; + int val; + int N; + int min; + int max; + int nextC; + int *pVal; + int cnt = 0; + va_start(ap, zDate); + do{ + N = va_arg(ap, int); + min = va_arg(ap, int); + max = va_arg(ap, int); + nextC = va_arg(ap, int); + pVal = va_arg(ap, int*); + val = 0; + while( N-- ){ + if( !sqlite3Isdigit(*zDate) ){ + goto end_getDigits; + } + val = val*10 + *zDate - '0'; + zDate++; + } + if( valmax || (nextC!=0 && nextC!=*zDate) ){ + goto end_getDigits; + } + *pVal = val; + zDate++; + cnt++; + }while( nextC ); +end_getDigits: + va_end(ap); + return cnt; +} + +/* +** Parse a timezone extension on the end of a date-time. +** The extension is of the form: +** +** (+/-)HH:MM +** +** Or the "zulu" notation: +** +** Z +** +** If the parse is successful, write the number of minutes +** of change in p->tz and return 0. If a parser error occurs, +** return non-zero. +** +** A missing specifier is not considered an error. +*/ +static int parseTimezone(const char *zDate, DateTime *p){ + int sgn = 0; + int nHr, nMn; + int c; + while( sqlite3Isspace(*zDate) ){ zDate++; } + p->tz = 0; + c = *zDate; + if( c=='-' ){ + sgn = -1; + }else if( c=='+' ){ + sgn = +1; + }else if( c=='Z' || c=='z' ){ + zDate++; + goto zulu_time; + }else{ + return c!=0; + } + zDate++; + if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){ + return 1; + } + zDate += 5; + p->tz = sgn*(nMn + nHr*60); +zulu_time: + while( sqlite3Isspace(*zDate) ){ zDate++; } + return *zDate!=0; +} + +/* +** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF. +** The HH, MM, and SS must each be exactly 2 digits. The +** fractional seconds FFFF can be one or more digits. +** +** Return 1 if there is a parsing error and 0 on success. +*/ +static int parseHhMmSs(const char *zDate, DateTime *p){ + int h, m, s; + double ms = 0.0; + if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){ + return 1; + } + zDate += 5; + if( *zDate==':' ){ + zDate++; + if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){ + return 1; + } + zDate += 2; + if( *zDate=='.' && sqlite3Isdigit(zDate[1]) ){ + double rScale = 1.0; + zDate++; + while( sqlite3Isdigit(*zDate) ){ + ms = ms*10.0 + *zDate - '0'; + rScale *= 10.0; + zDate++; + } + ms /= rScale; + } + }else{ + s = 0; + } + p->validJD = 0; + p->validHMS = 1; + p->h = h; + p->m = m; + p->s = s + ms; + if( parseTimezone(zDate, p) ) return 1; + p->validTZ = (p->tz!=0)?1:0; + return 0; +} + +/* +** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume +** that the YYYY-MM-DD is according to the Gregorian calendar. +** +** Reference: Meeus page 61 +*/ +static void computeJD(DateTime *p){ + int Y, M, D, A, B, X1, X2; + + if( p->validJD ) return; + if( p->validYMD ){ + Y = p->Y; + M = p->M; + D = p->D; + }else{ + Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */ + M = 1; + D = 1; + } + if( M<=2 ){ + Y--; + M += 12; + } + A = Y/100; + B = 2 - A + (A/4); + X1 = 36525*(Y+4716)/100; + X2 = 306001*(M+1)/10000; + p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000); + p->validJD = 1; + if( p->validHMS ){ + p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000); + if( p->validTZ ){ + p->iJD -= p->tz*60000; + p->validYMD = 0; + p->validHMS = 0; + p->validTZ = 0; + } + } +} + +/* +** Parse dates of the form +** +** YYYY-MM-DD HH:MM:SS.FFF +** YYYY-MM-DD HH:MM:SS +** YYYY-MM-DD HH:MM +** YYYY-MM-DD +** +** Write the result into the DateTime structure and return 0 +** on success and 1 if the input string is not a well-formed +** date. +*/ +static int parseYyyyMmDd(const char *zDate, DateTime *p){ + int Y, M, D, neg; + + if( zDate[0]=='-' ){ + zDate++; + neg = 1; + }else{ + neg = 0; + } + if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){ + return 1; + } + zDate += 10; + while( sqlite3Isspace(*zDate) || 'T'==*(u8*)zDate ){ zDate++; } + if( parseHhMmSs(zDate, p)==0 ){ + /* We got the time */ + }else if( *zDate==0 ){ + p->validHMS = 0; + }else{ + return 1; + } + p->validJD = 0; + p->validYMD = 1; + p->Y = neg ? -Y : Y; + p->M = M; + p->D = D; + if( p->validTZ ){ + computeJD(p); + } + return 0; +} + +/* +** Set the time to the current time reported by the VFS. +** +** Return the number of errors. +*/ +static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){ + p->iJD = sqlite3StmtCurrentTime(context); + if( p->iJD>0 ){ + p->validJD = 1; + return 0; + }else{ + return 1; + } +} + +/* +** Attempt to parse the given string into a julian day number. Return +** the number of errors. +** +** The following are acceptable forms for the input string: +** +** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM +** DDDD.DD +** now +** +** In the first form, the +/-HH:MM is always optional. The fractional +** seconds extension (the ".FFF") is optional. The seconds portion +** (":SS.FFF") is option. The year and date can be omitted as long +** as there is a time string. The time string can be omitted as long +** as there is a year and date. +*/ +static int parseDateOrTime( + sqlite3_context *context, + const char *zDate, + DateTime *p +){ + double r; + if( parseYyyyMmDd(zDate,p)==0 ){ + return 0; + }else if( parseHhMmSs(zDate, p)==0 ){ + return 0; + }else if( sqlite3StrICmp(zDate,"now")==0){ + return setDateTimeToCurrent(context, p); + }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){ + p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5); + p->validJD = 1; + return 0; + } + return 1; +} + +/* +** Compute the Year, Month, and Day from the julian day number. +*/ +static void computeYMD(DateTime *p){ + int Z, A, B, C, D, E, X1; + if( p->validYMD ) return; + if( !p->validJD ){ + p->Y = 2000; + p->M = 1; + p->D = 1; + }else{ + Z = (int)((p->iJD + 43200000)/86400000); + A = (int)((Z - 1867216.25)/36524.25); + A = Z + 1 + A - (A/4); + B = A + 1524; + C = (int)((B - 122.1)/365.25); + D = (36525*(C&32767))/100; + E = (int)((B-D)/30.6001); + X1 = (int)(30.6001*E); + p->D = B - D - X1; + p->M = E<14 ? E-1 : E-13; + p->Y = p->M>2 ? C - 4716 : C - 4715; + } + p->validYMD = 1; +} + +/* +** Compute the Hour, Minute, and Seconds from the julian day number. +*/ +static void computeHMS(DateTime *p){ + int s; + if( p->validHMS ) return; + computeJD(p); + s = (int)((p->iJD + 43200000) % 86400000); + p->s = s/1000.0; + s = (int)p->s; + p->s -= s; + p->h = s/3600; + s -= p->h*3600; + p->m = s/60; + p->s += s - p->m*60; + p->validHMS = 1; +} + +/* +** Compute both YMD and HMS +*/ +static void computeYMD_HMS(DateTime *p){ + computeYMD(p); + computeHMS(p); +} + +/* +** Clear the YMD and HMS and the TZ +*/ +static void clearYMD_HMS_TZ(DateTime *p){ + p->validYMD = 0; + p->validHMS = 0; + p->validTZ = 0; +} + +/* +** On recent Windows platforms, the localtime_s() function is available +** as part of the "Secure CRT". It is essentially equivalent to +** localtime_r() available under most POSIX platforms, except that the +** order of the parameters is reversed. +** +** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx. +** +** If the user has not indicated to use localtime_r() or localtime_s() +** already, check for an MSVC build environment that provides +** localtime_s(). +*/ +#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S \ + && defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE) +#undef HAVE_LOCALTIME_S +#define HAVE_LOCALTIME_S 1 +#endif + +#ifndef SQLITE_OMIT_LOCALTIME +/* +** The following routine implements the rough equivalent of localtime_r() +** using whatever operating-system specific localtime facility that +** is available. This routine returns 0 on success and +** non-zero on any kind of error. +** +** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this +** routine will always fail. +** +** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C +** library function localtime_r() is used to assist in the calculation of +** local time. +*/ +static int osLocaltime(time_t *t, struct tm *pTm){ + int rc; +#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S + struct tm *pX; +#if SQLITE_THREADSAFE>0 + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); +#endif + sqlite3_mutex_enter(mutex); + pX = localtime(t); +#ifndef SQLITE_OMIT_BUILTIN_TEST + if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0; +#endif + if( pX ) *pTm = *pX; + sqlite3_mutex_leave(mutex); + rc = pX==0; +#else +#ifndef SQLITE_OMIT_BUILTIN_TEST + if( sqlite3GlobalConfig.bLocaltimeFault ) return 1; +#endif +#if HAVE_LOCALTIME_R + rc = localtime_r(t, pTm)==0; +#else + rc = localtime_s(pTm, t); +#endif /* HAVE_LOCALTIME_R */ +#endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */ + return rc; +} +#endif /* SQLITE_OMIT_LOCALTIME */ + + +#ifndef SQLITE_OMIT_LOCALTIME +/* +** Compute the difference (in milliseconds) between localtime and UTC +** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs, +** return this value and set *pRc to SQLITE_OK. +** +** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value +** is undefined in this case. +*/ +static sqlite3_int64 localtimeOffset( + DateTime *p, /* Date at which to calculate offset */ + sqlite3_context *pCtx, /* Write error here if one occurs */ + int *pRc /* OUT: Error code. SQLITE_OK or ERROR */ +){ + DateTime x, y; + time_t t; + struct tm sLocal; + + /* Initialize the contents of sLocal to avoid a compiler warning. */ + memset(&sLocal, 0, sizeof(sLocal)); + + x = *p; + computeYMD_HMS(&x); + if( x.Y<1971 || x.Y>=2038 ){ + /* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only + ** works for years between 1970 and 2037. For dates outside this range, + ** SQLite attempts to map the year into an equivalent year within this + ** range, do the calculation, then map the year back. + */ + x.Y = 2000; + x.M = 1; + x.D = 1; + x.h = 0; + x.m = 0; + x.s = 0.0; + } else { + int s = (int)(x.s + 0.5); + x.s = s; + } + x.tz = 0; + x.validJD = 0; + computeJD(&x); + t = (time_t)(x.iJD/1000 - 21086676*(i64)10000); + if( osLocaltime(&t, &sLocal) ){ + sqlite3_result_error(pCtx, "local time unavailable", -1); + *pRc = SQLITE_ERROR; + return 0; + } + y.Y = sLocal.tm_year + 1900; + y.M = sLocal.tm_mon + 1; + y.D = sLocal.tm_mday; + y.h = sLocal.tm_hour; + y.m = sLocal.tm_min; + y.s = sLocal.tm_sec; + y.validYMD = 1; + y.validHMS = 1; + y.validJD = 0; + y.validTZ = 0; + computeJD(&y); + *pRc = SQLITE_OK; + return y.iJD - x.iJD; +} +#endif /* SQLITE_OMIT_LOCALTIME */ + +/* +** Process a modifier to a date-time stamp. The modifiers are +** as follows: +** +** NNN days +** NNN hours +** NNN minutes +** NNN.NNNN seconds +** NNN months +** NNN years +** start of month +** start of year +** start of week +** start of day +** weekday N +** unixepoch +** localtime +** utc +** +** Return 0 on success and 1 if there is any kind of error. If the error +** is in a system call (i.e. localtime()), then an error message is written +** to context pCtx. If the error is an unrecognized modifier, no error is +** written to pCtx. +*/ +static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){ + int rc = 1; + int n; + double r; + char *z, zBuf[30]; + z = zBuf; + for(n=0; niJD += localtimeOffset(p, pCtx, &rc); + clearYMD_HMS_TZ(p); + } + break; + } +#endif + case 'u': { + /* + ** unixepoch + ** + ** Treat the current value of p->iJD as the number of + ** seconds since 1970. Convert to a real julian day number. + */ + if( strcmp(z, "unixepoch")==0 && p->validJD ){ + p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000; + clearYMD_HMS_TZ(p); + rc = 0; + } +#ifndef SQLITE_OMIT_LOCALTIME + else if( strcmp(z, "utc")==0 ){ + sqlite3_int64 c1; + computeJD(p); + c1 = localtimeOffset(p, pCtx, &rc); + if( rc==SQLITE_OK ){ + p->iJD -= c1; + clearYMD_HMS_TZ(p); + p->iJD += c1 - localtimeOffset(p, pCtx, &rc); + } + } +#endif + break; + } + case 'w': { + /* + ** weekday N + ** + ** Move the date to the same time on the next occurrence of + ** weekday N where 0==Sunday, 1==Monday, and so forth. If the + ** date is already on the appropriate weekday, this is a no-op. + */ + if( strncmp(z, "weekday ", 8)==0 + && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8) + && (n=(int)r)==r && n>=0 && r<7 ){ + sqlite3_int64 Z; + computeYMD_HMS(p); + p->validTZ = 0; + p->validJD = 0; + computeJD(p); + Z = ((p->iJD + 129600000)/86400000) % 7; + if( Z>n ) Z -= 7; + p->iJD += (n - Z)*86400000; + clearYMD_HMS_TZ(p); + rc = 0; + } + break; + } + case 's': { + /* + ** start of TTTTT + ** + ** Move the date backwards to the beginning of the current day, + ** or month or year. + */ + if( strncmp(z, "start of ", 9)!=0 ) break; + z += 9; + computeYMD(p); + p->validHMS = 1; + p->h = p->m = 0; + p->s = 0.0; + p->validTZ = 0; + p->validJD = 0; + if( strcmp(z,"month")==0 ){ + p->D = 1; + rc = 0; + }else if( strcmp(z,"year")==0 ){ + computeYMD(p); + p->M = 1; + p->D = 1; + rc = 0; + }else if( strcmp(z,"day")==0 ){ + rc = 0; + } + break; + } + case '+': + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + double rRounder; + for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){} + if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){ + rc = 1; + break; + } + if( z[n]==':' ){ + /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the + ** specified number of hours, minutes, seconds, and fractional seconds + ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be + ** omitted. + */ + const char *z2 = z; + DateTime tx; + sqlite3_int64 day; + if( !sqlite3Isdigit(*z2) ) z2++; + memset(&tx, 0, sizeof(tx)); + if( parseHhMmSs(z2, &tx) ) break; + computeJD(&tx); + tx.iJD -= 43200000; + day = tx.iJD/86400000; + tx.iJD -= day*86400000; + if( z[0]=='-' ) tx.iJD = -tx.iJD; + computeJD(p); + clearYMD_HMS_TZ(p); + p->iJD += tx.iJD; + rc = 0; + break; + } + z += n; + while( sqlite3Isspace(*z) ) z++; + n = sqlite3Strlen30(z); + if( n>10 || n<3 ) break; + if( z[n-1]=='s' ){ z[n-1] = 0; n--; } + computeJD(p); + rc = 0; + rRounder = r<0 ? -0.5 : +0.5; + if( n==3 && strcmp(z,"day")==0 ){ + p->iJD += (sqlite3_int64)(r*86400000.0 + rRounder); + }else if( n==4 && strcmp(z,"hour")==0 ){ + p->iJD += (sqlite3_int64)(r*(86400000.0/24.0) + rRounder); + }else if( n==6 && strcmp(z,"minute")==0 ){ + p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0)) + rRounder); + }else if( n==6 && strcmp(z,"second")==0 ){ + p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0*60.0)) + rRounder); + }else if( n==5 && strcmp(z,"month")==0 ){ + int x, y; + computeYMD_HMS(p); + p->M += (int)r; + x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; + p->Y += x; + p->M -= x*12; + p->validJD = 0; + computeJD(p); + y = (int)r; + if( y!=r ){ + p->iJD += (sqlite3_int64)((r - y)*30.0*86400000.0 + rRounder); + } + }else if( n==4 && strcmp(z,"year")==0 ){ + int y = (int)r; + computeYMD_HMS(p); + p->Y += y; + p->validJD = 0; + computeJD(p); + if( y!=r ){ + p->iJD += (sqlite3_int64)((r - y)*365.0*86400000.0 + rRounder); + } + }else{ + rc = 1; + } + clearYMD_HMS_TZ(p); + break; + } + default: { + break; + } + } + return rc; +} + +/* +** Process time function arguments. argv[0] is a date-time stamp. +** argv[1] and following are modifiers. Parse them all and write +** the resulting time into the DateTime structure p. Return 0 +** on success and 1 if there are any errors. +** +** If there are zero parameters (if even argv[0] is undefined) +** then assume a default value of "now" for argv[0]. +*/ +static int isDate( + sqlite3_context *context, + int argc, + sqlite3_value **argv, + DateTime *p +){ + int i; + const unsigned char *z; + int eType; + memset(p, 0, sizeof(*p)); + if( argc==0 ){ + return setDateTimeToCurrent(context, p); + } + if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT + || eType==SQLITE_INTEGER ){ + p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*86400000.0 + 0.5); + p->validJD = 1; + }else{ + z = sqlite3_value_text(argv[0]); + if( !z || parseDateOrTime(context, (char*)z, p) ){ + return 1; + } + } + for(i=1; iaLimit[SQLITE_LIMIT_LENGTH]+1 ); + testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ); + if( n(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){ + sqlite3_result_error_toobig(context); + return; + }else{ + z = sqlite3DbMallocRaw(db, (int)n); + if( z==0 ){ + sqlite3_result_error_nomem(context); + return; + } + } + computeJD(&x); + computeYMD_HMS(&x); + for(i=j=0; zFmt[i]; i++){ + if( zFmt[i]!='%' ){ + z[j++] = zFmt[i]; + }else{ + i++; + switch( zFmt[i] ){ + case 'd': sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break; + case 'f': { + double s = x.s; + if( s>59.999 ) s = 59.999; + sqlite3_snprintf(7, &z[j],"%06.3f", s); + j += sqlite3Strlen30(&z[j]); + break; + } + case 'H': sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break; + case 'W': /* Fall thru */ + case 'j': { + int nDay; /* Number of days since 1st day of year */ + DateTime y = x; + y.validJD = 0; + y.M = 1; + y.D = 1; + computeJD(&y); + nDay = (int)((x.iJD-y.iJD+43200000)/86400000); + if( zFmt[i]=='W' ){ + int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */ + wd = (int)(((x.iJD+43200000)/86400000)%7); + sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7); + j += 2; + }else{ + sqlite3_snprintf(4, &z[j],"%03d",nDay+1); + j += 3; + } + break; + } + case 'J': { + sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0); + j+=sqlite3Strlen30(&z[j]); + break; + } + case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break; + case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break; + case 's': { + sqlite3_snprintf(30,&z[j],"%lld", + (i64)(x.iJD/1000 - 21086676*(i64)10000)); + j += sqlite3Strlen30(&z[j]); + break; + } + case 'S': sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break; + case 'w': { + z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0'; + break; + } + case 'Y': { + sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlite3Strlen30(&z[j]); + break; + } + default: z[j++] = '%'; break; + } + } + } + z[j] = 0; + sqlite3_result_text(context, z, -1, + z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC); +} + +/* +** current_time() +** +** This function returns the same value as time('now'). +*/ +static void ctimeFunc( + sqlite3_context *context, + int NotUsed, + sqlite3_value **NotUsed2 +){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); + timeFunc(context, 0, 0); +} + +/* +** current_date() +** +** This function returns the same value as date('now'). +*/ +static void cdateFunc( + sqlite3_context *context, + int NotUsed, + sqlite3_value **NotUsed2 +){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); + dateFunc(context, 0, 0); +} + +/* +** current_timestamp() +** +** This function returns the same value as datetime('now'). +*/ +static void ctimestampFunc( + sqlite3_context *context, + int NotUsed, + sqlite3_value **NotUsed2 +){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); + datetimeFunc(context, 0, 0); +} +#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */ + +#ifdef SQLITE_OMIT_DATETIME_FUNCS +/* +** If the library is compiled to omit the full-scale date and time +** handling (to get a smaller binary), the following minimal version +** of the functions current_time(), current_date() and current_timestamp() +** are included instead. This is to support column declarations that +** include "DEFAULT CURRENT_TIME" etc. +** +** This function uses the C-library functions time(), gmtime() +** and strftime(). The format string to pass to strftime() is supplied +** as the user-data for the function. +*/ +static void currentTimeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + time_t t; + char *zFormat = (char *)sqlite3_user_data(context); + sqlite3 *db; + sqlite3_int64 iT; + struct tm *pTm; + struct tm sNow; + char zBuf[20]; + + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + iT = sqlite3StmtCurrentTime(context); + if( iT<=0 ) return; + t = iT/1000 - 10000*(sqlite3_int64)21086676; +#if HAVE_GMTIME_R + pTm = gmtime_r(&t, &sNow); +#else + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); + pTm = gmtime(&t); + if( pTm ) memcpy(&sNow, pTm, sizeof(sNow)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); +#endif + if( pTm ){ + strftime(zBuf, 20, zFormat, &sNow); + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); + } +} +#endif + +/* +** This function registered all of the above C functions as SQL +** functions. This should be the only routine in this file with +** external linkage. +*/ +SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ + static SQLITE_WSD FuncDef aDateTimeFuncs[] = { +#ifndef SQLITE_OMIT_DATETIME_FUNCS + FUNCTION(julianday, -1, 0, 0, juliandayFunc ), + FUNCTION(date, -1, 0, 0, dateFunc ), + FUNCTION(time, -1, 0, 0, timeFunc ), + FUNCTION(datetime, -1, 0, 0, datetimeFunc ), + FUNCTION(strftime, -1, 0, 0, strftimeFunc ), + FUNCTION(current_time, 0, 0, 0, ctimeFunc ), + FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), + FUNCTION(current_date, 0, 0, 0, cdateFunc ), +#else + STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc), + STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc), + STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc), +#endif + }; + int i; + FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); + FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs); + + for(i=0; ipMethods ){ + rc = pId->pMethods->xClose(pId); + pId->pMethods = 0; + } + return rc; +} +SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){ + DO_OS_MALLOC_TEST(id); + return id->pMethods->xRead(id, pBuf, amt, offset); +} +SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){ + DO_OS_MALLOC_TEST(id); + return id->pMethods->xWrite(id, pBuf, amt, offset); +} +SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file *id, i64 size){ + return id->pMethods->xTruncate(id, size); +} +SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){ + DO_OS_MALLOC_TEST(id); + return id->pMethods->xSync(id, flags); +} +SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){ + DO_OS_MALLOC_TEST(id); + return id->pMethods->xFileSize(id, pSize); +} +SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file *id, int lockType){ + DO_OS_MALLOC_TEST(id); + return id->pMethods->xLock(id, lockType); +} +SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file *id, int lockType){ + return id->pMethods->xUnlock(id, lockType); +} +SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){ + DO_OS_MALLOC_TEST(id); + return id->pMethods->xCheckReservedLock(id, pResOut); +} + +/* +** Use sqlite3OsFileControl() when we are doing something that might fail +** and we need to know about the failures. Use sqlite3OsFileControlHint() +** when simply tossing information over the wall to the VFS and we do not +** really care if the VFS receives and understands the information since it +** is only a hint and can be safely ignored. The sqlite3OsFileControlHint() +** routine has no return value since the return value would be meaningless. +*/ +SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ +#ifdef SQLITE_TEST + if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){ + /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite + ** is using a regular VFS, it is called after the corresponding + ** transaction has been committed. Injecting a fault at this point + ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM + ** but the transaction is committed anyway. + ** + ** The core must call OsFileControl() though, not OsFileControlHint(), + ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably + ** means the commit really has failed and an error should be returned + ** to the user. */ + DO_OS_MALLOC_TEST(id); + } +#endif + return id->pMethods->xFileControl(id, op, pArg); +} +SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){ + (void)id->pMethods->xFileControl(id, op, pArg); +} + +SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){ + int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize; + return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE); +} +SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ + return id->pMethods->xDeviceCharacteristics(id); +} +SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){ + return id->pMethods->xShmLock(id, offset, n, flags); +} +SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id){ + id->pMethods->xShmBarrier(id); +} +SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){ + return id->pMethods->xShmUnmap(id, deleteFlag); +} +SQLITE_PRIVATE int sqlite3OsShmMap( + sqlite3_file *id, /* Database file handle */ + int iPage, + int pgsz, + int bExtend, /* True to extend file if necessary */ + void volatile **pp /* OUT: Pointer to mapping */ +){ + DO_OS_MALLOC_TEST(id); + return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp); +} + +#if SQLITE_MAX_MMAP_SIZE>0 +/* The real implementation of xFetch and xUnfetch */ +SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){ + DO_OS_MALLOC_TEST(id); + return id->pMethods->xFetch(id, iOff, iAmt, pp); +} +SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){ + return id->pMethods->xUnfetch(id, iOff, p); +} +#else +/* No-op stubs to use when memory-mapped I/O is disabled */ +SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){ + *pp = 0; + return SQLITE_OK; +} +SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){ + return SQLITE_OK; +} +#endif + +/* +** The next group of routines are convenience wrappers around the +** VFS methods. +*/ +SQLITE_PRIVATE int sqlite3OsOpen( + sqlite3_vfs *pVfs, + const char *zPath, + sqlite3_file *pFile, + int flags, + int *pFlagsOut +){ + int rc; + DO_OS_MALLOC_TEST(0); + /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed + ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, + ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before + ** reaching the VFS. */ + rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut); + assert( rc==SQLITE_OK || pFile->pMethods==0 ); + return rc; +} +SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ + DO_OS_MALLOC_TEST(0); + assert( dirSync==0 || dirSync==1 ); + return pVfs->xDelete(pVfs, zPath, dirSync); +} +SQLITE_PRIVATE int sqlite3OsAccess( + sqlite3_vfs *pVfs, + const char *zPath, + int flags, + int *pResOut +){ + DO_OS_MALLOC_TEST(0); + return pVfs->xAccess(pVfs, zPath, flags, pResOut); +} +SQLITE_PRIVATE int sqlite3OsFullPathname( + sqlite3_vfs *pVfs, + const char *zPath, + int nPathOut, + char *zPathOut +){ + DO_OS_MALLOC_TEST(0); + zPathOut[0] = 0; + return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); +} +#ifndef SQLITE_OMIT_LOAD_EXTENSION +SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ + return pVfs->xDlOpen(pVfs, zPath); +} +SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + pVfs->xDlError(pVfs, nByte, zBufOut); +} +SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){ + return pVfs->xDlSym(pVfs, pHdle, zSym); +} +SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){ + pVfs->xDlClose(pVfs, pHandle); +} +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ +SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + return pVfs->xRandomness(pVfs, nByte, zBufOut); +} +SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ + return pVfs->xSleep(pVfs, nMicro); +} +SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ + int rc; + /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64() + ** method to get the current date and time if that method is available + ** (if iVersion is 2 or greater and the function pointer is not NULL) and + ** will fall back to xCurrentTime() if xCurrentTimeInt64() is + ** unavailable. + */ + if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){ + rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut); + }else{ + double r; + rc = pVfs->xCurrentTime(pVfs, &r); + *pTimeOut = (sqlite3_int64)(r*86400000.0); + } + return rc; +} + +SQLITE_PRIVATE int sqlite3OsOpenMalloc( + sqlite3_vfs *pVfs, + const char *zFile, + sqlite3_file **ppFile, + int flags, + int *pOutFlags +){ + int rc = SQLITE_NOMEM; + sqlite3_file *pFile; + pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile); + if( pFile ){ + rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags); + if( rc!=SQLITE_OK ){ + sqlite3_free(pFile); + }else{ + *ppFile = pFile; + } + } + return rc; +} +SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *pFile){ + int rc = SQLITE_OK; + assert( pFile ); + rc = sqlite3OsClose(pFile); + sqlite3_free(pFile); + return rc; +} + +/* +** This function is a wrapper around the OS specific implementation of +** sqlite3_os_init(). The purpose of the wrapper is to provide the +** ability to simulate a malloc failure, so that the handling of an +** error in sqlite3_os_init() by the upper layers can be tested. +*/ +SQLITE_PRIVATE int sqlite3OsInit(void){ + void *p = sqlite3_malloc(10); + if( p==0 ) return SQLITE_NOMEM; + sqlite3_free(p); + return sqlite3_os_init(); +} + +/* +** The list of all registered VFS implementations. +*/ +static sqlite3_vfs * SQLITE_WSD vfsList = 0; +#define vfsList GLOBAL(sqlite3_vfs *, vfsList) + +/* +** Locate a VFS by name. If no name is given, simply return the +** first VFS on the list. +*/ +SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfs){ + sqlite3_vfs *pVfs = 0; +#if SQLITE_THREADSAFE + sqlite3_mutex *mutex; +#endif +#ifndef SQLITE_OMIT_AUTOINIT + int rc = sqlite3_initialize(); + if( rc ) return 0; +#endif +#if SQLITE_THREADSAFE + mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); +#endif + sqlite3_mutex_enter(mutex); + for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){ + if( zVfs==0 ) break; + if( strcmp(zVfs, pVfs->zName)==0 ) break; + } + sqlite3_mutex_leave(mutex); + return pVfs; +} + +/* +** Unlink a VFS from the linked list +*/ +static void vfsUnlink(sqlite3_vfs *pVfs){ + assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) ); + if( pVfs==0 ){ + /* No-op */ + }else if( vfsList==pVfs ){ + vfsList = pVfs->pNext; + }else if( vfsList ){ + sqlite3_vfs *p = vfsList; + while( p->pNext && p->pNext!=pVfs ){ + p = p->pNext; + } + if( p->pNext==pVfs ){ + p->pNext = pVfs->pNext; + } + } +} + +/* +** Register a VFS with the system. It is harmless to register the same +** VFS multiple times. The new VFS becomes the default if makeDflt is +** true. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ + MUTEX_LOGIC(sqlite3_mutex *mutex;) +#ifndef SQLITE_OMIT_AUTOINIT + int rc = sqlite3_initialize(); + if( rc ) return rc; +#endif +#ifdef SQLITE_ENABLE_API_ARMOR + if( pVfs==0 ) return SQLITE_MISUSE_BKPT; +#endif + + MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) + sqlite3_mutex_enter(mutex); + vfsUnlink(pVfs); + if( makeDflt || vfsList==0 ){ + pVfs->pNext = vfsList; + vfsList = pVfs; + }else{ + pVfs->pNext = vfsList->pNext; + vfsList->pNext = pVfs; + } + assert(vfsList); + sqlite3_mutex_leave(mutex); + return SQLITE_OK; +} + +/* +** Unregister a VFS so that it is no longer accessible. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ +#if SQLITE_THREADSAFE + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); +#endif + sqlite3_mutex_enter(mutex); + vfsUnlink(pVfs); + sqlite3_mutex_leave(mutex); + return SQLITE_OK; +} + +/************** End of os.c **************************************************/ +/************** Begin file fault.c *******************************************/ +/* +** 2008 Jan 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains code to support the concept of "benign" +** malloc failures (when the xMalloc() or xRealloc() method of the +** sqlite3_mem_methods structure fails to allocate a block of memory +** and returns 0). +** +** Most malloc failures are non-benign. After they occur, SQLite +** abandons the current operation and returns an error code (usually +** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily +** fatal. For example, if a malloc fails while resizing a hash table, this +** is completely recoverable simply by not carrying out the resize. The +** hash table will continue to function normally. So a malloc failure +** during a hash table resize is a benign fault. +*/ + +/* #include "sqliteInt.h" */ + +#ifndef SQLITE_OMIT_BUILTIN_TEST + +/* +** Global variables. +*/ +typedef struct BenignMallocHooks BenignMallocHooks; +static SQLITE_WSD struct BenignMallocHooks { + void (*xBenignBegin)(void); + void (*xBenignEnd)(void); +} sqlite3Hooks = { 0, 0 }; + +/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks +** structure. If writable static data is unsupported on the target, +** we have to locate the state vector at run-time. In the more common +** case where writable static data is supported, wsdHooks can refer directly +** to the "sqlite3Hooks" state vector declared above. +*/ +#ifdef SQLITE_OMIT_WSD +# define wsdHooksInit \ + BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks) +# define wsdHooks x[0] +#else +# define wsdHooksInit +# define wsdHooks sqlite3Hooks +#endif + + +/* +** Register hooks to call when sqlite3BeginBenignMalloc() and +** sqlite3EndBenignMalloc() are called, respectively. +*/ +SQLITE_PRIVATE void sqlite3BenignMallocHooks( + void (*xBenignBegin)(void), + void (*xBenignEnd)(void) +){ + wsdHooksInit; + wsdHooks.xBenignBegin = xBenignBegin; + wsdHooks.xBenignEnd = xBenignEnd; +} + +/* +** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that +** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc() +** indicates that subsequent malloc failures are non-benign. +*/ +SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void){ + wsdHooksInit; + if( wsdHooks.xBenignBegin ){ + wsdHooks.xBenignBegin(); + } +} +SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){ + wsdHooksInit; + if( wsdHooks.xBenignEnd ){ + wsdHooks.xBenignEnd(); + } +} + +#endif /* #ifndef SQLITE_OMIT_BUILTIN_TEST */ + +/************** End of fault.c ***********************************************/ +/************** Begin file mem0.c ********************************************/ +/* +** 2008 October 28 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains a no-op memory allocation drivers for use when +** SQLITE_ZERO_MALLOC is defined. The allocation drivers implemented +** here always fail. SQLite will not operate with these drivers. These +** are merely placeholders. Real drivers must be substituted using +** sqlite3_config() before SQLite will operate. +*/ +/* #include "sqliteInt.h" */ + +/* +** This version of the memory allocator is the default. It is +** used when no other memory allocator is specified using compile-time +** macros. +*/ +#ifdef SQLITE_ZERO_MALLOC + +/* +** No-op versions of all memory allocation routines +*/ +static void *sqlite3MemMalloc(int nByte){ return 0; } +static void sqlite3MemFree(void *pPrior){ return; } +static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; } +static int sqlite3MemSize(void *pPrior){ return 0; } +static int sqlite3MemRoundup(int n){ return n; } +static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; } +static void sqlite3MemShutdown(void *NotUsed){ return; } + +/* +** This routine is the only routine in this file with external linkage. +** +** Populate the low-level memory allocation function pointers in +** sqlite3GlobalConfig.m with pointers to the routines in this file. +*/ +SQLITE_PRIVATE void sqlite3MemSetDefault(void){ + static const sqlite3_mem_methods defaultMethods = { + sqlite3MemMalloc, + sqlite3MemFree, + sqlite3MemRealloc, + sqlite3MemSize, + sqlite3MemRoundup, + sqlite3MemInit, + sqlite3MemShutdown, + 0 + }; + sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); +} + +#endif /* SQLITE_ZERO_MALLOC */ + +/************** End of mem0.c ************************************************/ +/************** Begin file mem1.c ********************************************/ +/* +** 2007 August 14 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains low-level memory allocation drivers for when +** SQLite will use the standard C-library malloc/realloc/free interface +** to obtain the memory it needs. +** +** This file contains implementations of the low-level memory allocation +** routines specified in the sqlite3_mem_methods object. The content of +** this file is only used if SQLITE_SYSTEM_MALLOC is defined. The +** SQLITE_SYSTEM_MALLOC macro is defined automatically if neither the +** SQLITE_MEMDEBUG nor the SQLITE_WIN32_MALLOC macros are defined. The +** default configuration is to use memory allocation routines in this +** file. +** +** C-preprocessor macro summary: +** +** HAVE_MALLOC_USABLE_SIZE The configure script sets this symbol if +** the malloc_usable_size() interface exists +** on the target platform. Or, this symbol +** can be set manually, if desired. +** If an equivalent interface exists by +** a different name, using a separate -D +** option to rename it. +** +** SQLITE_WITHOUT_ZONEMALLOC Some older macs lack support for the zone +** memory allocator. Set this symbol to enable +** building on older macs. +** +** SQLITE_WITHOUT_MSIZE Set this symbol to disable the use of +** _msize() on windows systems. This might +** be necessary when compiling for Delphi, +** for example. +*/ +/* #include "sqliteInt.h" */ + +/* +** This version of the memory allocator is the default. It is +** used when no other memory allocator is specified using compile-time +** macros. +*/ +#ifdef SQLITE_SYSTEM_MALLOC +#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) + +/* +** Use the zone allocator available on apple products unless the +** SQLITE_WITHOUT_ZONEMALLOC symbol is defined. +*/ +#include +#include +#include +static malloc_zone_t* _sqliteZone_; +#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x)) +#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x)); +#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y)) +#define SQLITE_MALLOCSIZE(x) \ + (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x)) + +#else /* if not __APPLE__ */ + +/* +** Use standard C library malloc and free on non-Apple systems. +** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined. +*/ +#define SQLITE_MALLOC(x) malloc(x) +#define SQLITE_FREE(x) free(x) +#define SQLITE_REALLOC(x,y) realloc((x),(y)) + +/* +** The malloc.h header file is needed for malloc_usable_size() function +** on some systems (e.g. Linux). +*/ +#if HAVE_MALLOC_H && HAVE_MALLOC_USABLE_SIZE +# define SQLITE_USE_MALLOC_H 1 +# define SQLITE_USE_MALLOC_USABLE_SIZE 1 +/* +** The MSVCRT has malloc_usable_size(), but it is called _msize(). The +** use of _msize() is automatic, but can be disabled by compiling with +** -DSQLITE_WITHOUT_MSIZE. Using the _msize() function also requires +** the malloc.h header file. +*/ +#elif defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE) +# define SQLITE_USE_MALLOC_H +# define SQLITE_USE_MSIZE +#endif + +/* +** Include the malloc.h header file, if necessary. Also set define macro +** SQLITE_MALLOCSIZE to the appropriate function name, which is _msize() +** for MSVC and malloc_usable_size() for most other systems (e.g. Linux). +** The memory size function can always be overridden manually by defining +** the macro SQLITE_MALLOCSIZE to the desired function name. +*/ +#if defined(SQLITE_USE_MALLOC_H) +# include +# if defined(SQLITE_USE_MALLOC_USABLE_SIZE) +# if !defined(SQLITE_MALLOCSIZE) +# define SQLITE_MALLOCSIZE(x) malloc_usable_size(x) +# endif +# elif defined(SQLITE_USE_MSIZE) +# if !defined(SQLITE_MALLOCSIZE) +# define SQLITE_MALLOCSIZE _msize +# endif +# endif +#endif /* defined(SQLITE_USE_MALLOC_H) */ + +#endif /* __APPLE__ or not __APPLE__ */ + +/* +** Like malloc(), but remember the size of the allocation +** so that we can find it later using sqlite3MemSize(). +** +** For this low-level routine, we are guaranteed that nByte>0 because +** cases of nByte<=0 will be intercepted and dealt with by higher level +** routines. +*/ +static void *sqlite3MemMalloc(int nByte){ +#ifdef SQLITE_MALLOCSIZE + void *p = SQLITE_MALLOC( nByte ); + if( p==0 ){ + testcase( sqlite3GlobalConfig.xLog!=0 ); + sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); + } + return p; +#else + sqlite3_int64 *p; + assert( nByte>0 ); + nByte = ROUND8(nByte); + p = SQLITE_MALLOC( nByte+8 ); + if( p ){ + p[0] = nByte; + p++; + }else{ + testcase( sqlite3GlobalConfig.xLog!=0 ); + sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); + } + return (void *)p; +#endif +} + +/* +** Like free() but works for allocations obtained from sqlite3MemMalloc() +** or sqlite3MemRealloc(). +** +** For this low-level routine, we already know that pPrior!=0 since +** cases where pPrior==0 will have been intecepted and dealt with +** by higher-level routines. +*/ +static void sqlite3MemFree(void *pPrior){ +#ifdef SQLITE_MALLOCSIZE + SQLITE_FREE(pPrior); +#else + sqlite3_int64 *p = (sqlite3_int64*)pPrior; + assert( pPrior!=0 ); + p--; + SQLITE_FREE(p); +#endif +} + +/* +** Report the allocated size of a prior return from xMalloc() +** or xRealloc(). +*/ +static int sqlite3MemSize(void *pPrior){ +#ifdef SQLITE_MALLOCSIZE + return pPrior ? (int)SQLITE_MALLOCSIZE(pPrior) : 0; +#else + sqlite3_int64 *p; + if( pPrior==0 ) return 0; + p = (sqlite3_int64*)pPrior; + p--; + return (int)p[0]; +#endif +} + +/* +** Like realloc(). Resize an allocation previously obtained from +** sqlite3MemMalloc(). +** +** For this low-level interface, we know that pPrior!=0. Cases where +** pPrior==0 while have been intercepted by higher-level routine and +** redirected to xMalloc. Similarly, we know that nByte>0 because +** cases where nByte<=0 will have been intercepted by higher-level +** routines and redirected to xFree. +*/ +static void *sqlite3MemRealloc(void *pPrior, int nByte){ +#ifdef SQLITE_MALLOCSIZE + void *p = SQLITE_REALLOC(pPrior, nByte); + if( p==0 ){ + testcase( sqlite3GlobalConfig.xLog!=0 ); + sqlite3_log(SQLITE_NOMEM, + "failed memory resize %u to %u bytes", + SQLITE_MALLOCSIZE(pPrior), nByte); + } + return p; +#else + sqlite3_int64 *p = (sqlite3_int64*)pPrior; + assert( pPrior!=0 && nByte>0 ); + assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */ + p--; + p = SQLITE_REALLOC(p, nByte+8 ); + if( p ){ + p[0] = nByte; + p++; + }else{ + testcase( sqlite3GlobalConfig.xLog!=0 ); + sqlite3_log(SQLITE_NOMEM, + "failed memory resize %u to %u bytes", + sqlite3MemSize(pPrior), nByte); + } + return (void*)p; +#endif +} + +/* +** Round up a request size to the next valid allocation size. +*/ +static int sqlite3MemRoundup(int n){ + return ROUND8(n); +} + +/* +** Initialize this module. +*/ +static int sqlite3MemInit(void *NotUsed){ +#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) + int cpuCount; + size_t len; + if( _sqliteZone_ ){ + return SQLITE_OK; + } + len = sizeof(cpuCount); + /* One usually wants to use hw.acctivecpu for MT decisions, but not here */ + sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0); + if( cpuCount>1 ){ + /* defer MT decisions to system malloc */ + _sqliteZone_ = malloc_default_zone(); + }else{ + /* only 1 core, use our own zone to contention over global locks, + ** e.g. we have our own dedicated locks */ + bool success; + malloc_zone_t* newzone = malloc_create_zone(4096, 0); + malloc_set_zone_name(newzone, "Sqlite_Heap"); + do{ + success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone, + (void * volatile *)&_sqliteZone_); + }while(!_sqliteZone_); + if( !success ){ + /* somebody registered a zone first */ + malloc_destroy_zone(newzone); + } + } +#endif + UNUSED_PARAMETER(NotUsed); + return SQLITE_OK; +} + +/* +** Deinitialize this module. +*/ +static void sqlite3MemShutdown(void *NotUsed){ + UNUSED_PARAMETER(NotUsed); + return; +} + +/* +** This routine is the only routine in this file with external linkage. +** +** Populate the low-level memory allocation function pointers in +** sqlite3GlobalConfig.m with pointers to the routines in this file. +*/ +SQLITE_PRIVATE void sqlite3MemSetDefault(void){ + static const sqlite3_mem_methods defaultMethods = { + sqlite3MemMalloc, + sqlite3MemFree, + sqlite3MemRealloc, + sqlite3MemSize, + sqlite3MemRoundup, + sqlite3MemInit, + sqlite3MemShutdown, + 0 + }; + sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); +} + +#endif /* SQLITE_SYSTEM_MALLOC */ + +/************** End of mem1.c ************************************************/ +/************** Begin file mem2.c ********************************************/ +/* +** 2007 August 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains low-level memory allocation drivers for when +** SQLite will use the standard C-library malloc/realloc/free interface +** to obtain the memory it needs while adding lots of additional debugging +** information to each allocation in order to help detect and fix memory +** leaks and memory usage errors. +** +** This file contains implementations of the low-level memory allocation +** routines specified in the sqlite3_mem_methods object. +*/ +/* #include "sqliteInt.h" */ + +/* +** This version of the memory allocator is used only if the +** SQLITE_MEMDEBUG macro is defined +*/ +#ifdef SQLITE_MEMDEBUG + +/* +** The backtrace functionality is only available with GLIBC +*/ +#ifdef __GLIBC__ + extern int backtrace(void**,int); + extern void backtrace_symbols_fd(void*const*,int,int); +#else +# define backtrace(A,B) 1 +# define backtrace_symbols_fd(A,B,C) +#endif +/* #include */ + +/* +** Each memory allocation looks like this: +** +** ------------------------------------------------------------------------ +** | Title | backtrace pointers | MemBlockHdr | allocation | EndGuard | +** ------------------------------------------------------------------------ +** +** The application code sees only a pointer to the allocation. We have +** to back up from the allocation pointer to find the MemBlockHdr. The +** MemBlockHdr tells us the size of the allocation and the number of +** backtrace pointers. There is also a guard word at the end of the +** MemBlockHdr. +*/ +struct MemBlockHdr { + i64 iSize; /* Size of this allocation */ + struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */ + char nBacktrace; /* Number of backtraces on this alloc */ + char nBacktraceSlots; /* Available backtrace slots */ + u8 nTitle; /* Bytes of title; includes '\0' */ + u8 eType; /* Allocation type code */ + int iForeGuard; /* Guard word for sanity */ +}; + +/* +** Guard words +*/ +#define FOREGUARD 0x80F5E153 +#define REARGUARD 0xE4676B53 + +/* +** Number of malloc size increments to track. +*/ +#define NCSIZE 1000 + +/* +** All of the static variables used by this module are collected +** into a single structure named "mem". This is to keep the +** static variables organized and to reduce namespace pollution +** when this module is combined with other in the amalgamation. +*/ +static struct { + + /* + ** Mutex to control access to the memory allocation subsystem. + */ + sqlite3_mutex *mutex; + + /* + ** Head and tail of a linked list of all outstanding allocations + */ + struct MemBlockHdr *pFirst; + struct MemBlockHdr *pLast; + + /* + ** The number of levels of backtrace to save in new allocations. + */ + int nBacktrace; + void (*xBacktrace)(int, int, void **); + + /* + ** Title text to insert in front of each block + */ + int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */ + char zTitle[100]; /* The title text */ + + /* + ** sqlite3MallocDisallow() increments the following counter. + ** sqlite3MallocAllow() decrements it. + */ + int disallow; /* Do not allow memory allocation */ + + /* + ** Gather statistics on the sizes of memory allocations. + ** nAlloc[i] is the number of allocation attempts of i*8 + ** bytes. i==NCSIZE is the number of allocation attempts for + ** sizes more than NCSIZE*8 bytes. + */ + int nAlloc[NCSIZE]; /* Total number of allocations */ + int nCurrent[NCSIZE]; /* Current number of allocations */ + int mxCurrent[NCSIZE]; /* Highwater mark for nCurrent */ + +} mem; + + +/* +** Adjust memory usage statistics +*/ +static void adjustStats(int iSize, int increment){ + int i = ROUND8(iSize)/8; + if( i>NCSIZE-1 ){ + i = NCSIZE - 1; + } + if( increment>0 ){ + mem.nAlloc[i]++; + mem.nCurrent[i]++; + if( mem.nCurrent[i]>mem.mxCurrent[i] ){ + mem.mxCurrent[i] = mem.nCurrent[i]; + } + }else{ + mem.nCurrent[i]--; + assert( mem.nCurrent[i]>=0 ); + } +} + +/* +** Given an allocation, find the MemBlockHdr for that allocation. +** +** This routine checks the guards at either end of the allocation and +** if they are incorrect it asserts. +*/ +static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){ + struct MemBlockHdr *p; + int *pInt; + u8 *pU8; + int nReserve; + + p = (struct MemBlockHdr*)pAllocation; + p--; + assert( p->iForeGuard==(int)FOREGUARD ); + nReserve = ROUND8(p->iSize); + pInt = (int*)pAllocation; + pU8 = (u8*)pAllocation; + assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD ); + /* This checks any of the "extra" bytes allocated due + ** to rounding up to an 8 byte boundary to ensure + ** they haven't been overwritten. + */ + while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 ); + return p; +} + +/* +** Return the number of bytes currently allocated at address p. +*/ +static int sqlite3MemSize(void *p){ + struct MemBlockHdr *pHdr; + if( !p ){ + return 0; + } + pHdr = sqlite3MemsysGetHeader(p); + return (int)pHdr->iSize; +} + +/* +** Initialize the memory allocation subsystem. +*/ +static int sqlite3MemInit(void *NotUsed){ + UNUSED_PARAMETER(NotUsed); + assert( (sizeof(struct MemBlockHdr)&7) == 0 ); + if( !sqlite3GlobalConfig.bMemstat ){ + /* If memory status is enabled, then the malloc.c wrapper will already + ** hold the STATIC_MEM mutex when the routines here are invoked. */ + mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + } + return SQLITE_OK; +} + +/* +** Deinitialize the memory allocation subsystem. +*/ +static void sqlite3MemShutdown(void *NotUsed){ + UNUSED_PARAMETER(NotUsed); + mem.mutex = 0; +} + +/* +** Round up a request size to the next valid allocation size. +*/ +static int sqlite3MemRoundup(int n){ + return ROUND8(n); +} + +/* +** Fill a buffer with pseudo-random bytes. This is used to preset +** the content of a new memory allocation to unpredictable values and +** to clear the content of a freed allocation to unpredictable values. +*/ +static void randomFill(char *pBuf, int nByte){ + unsigned int x, y, r; + x = SQLITE_PTR_TO_INT(pBuf); + y = nByte | 1; + while( nByte >= 4 ){ + x = (x>>1) ^ (-(int)(x&1) & 0xd0000001); + y = y*1103515245 + 12345; + r = x ^ y; + *(int*)pBuf = r; + pBuf += 4; + nByte -= 4; + } + while( nByte-- > 0 ){ + x = (x>>1) ^ (-(int)(x&1) & 0xd0000001); + y = y*1103515245 + 12345; + r = x ^ y; + *(pBuf++) = r & 0xff; + } +} + +/* +** Allocate nByte bytes of memory. +*/ +static void *sqlite3MemMalloc(int nByte){ + struct MemBlockHdr *pHdr; + void **pBt; + char *z; + int *pInt; + void *p = 0; + int totalSize; + int nReserve; + sqlite3_mutex_enter(mem.mutex); + assert( mem.disallow==0 ); + nReserve = ROUND8(nByte); + totalSize = nReserve + sizeof(*pHdr) + sizeof(int) + + mem.nBacktrace*sizeof(void*) + mem.nTitle; + p = malloc(totalSize); + if( p ){ + z = p; + pBt = (void**)&z[mem.nTitle]; + pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace]; + pHdr->pNext = 0; + pHdr->pPrev = mem.pLast; + if( mem.pLast ){ + mem.pLast->pNext = pHdr; + }else{ + mem.pFirst = pHdr; + } + mem.pLast = pHdr; + pHdr->iForeGuard = FOREGUARD; + pHdr->eType = MEMTYPE_HEAP; + pHdr->nBacktraceSlots = mem.nBacktrace; + pHdr->nTitle = mem.nTitle; + if( mem.nBacktrace ){ + void *aAddr[40]; + pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1; + memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*)); + assert(pBt[0]); + if( mem.xBacktrace ){ + mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]); + } + }else{ + pHdr->nBacktrace = 0; + } + if( mem.nTitle ){ + memcpy(z, mem.zTitle, mem.nTitle); + } + pHdr->iSize = nByte; + adjustStats(nByte, +1); + pInt = (int*)&pHdr[1]; + pInt[nReserve/sizeof(int)] = REARGUARD; + randomFill((char*)pInt, nByte); + memset(((char*)pInt)+nByte, 0x65, nReserve-nByte); + p = (void*)pInt; + } + sqlite3_mutex_leave(mem.mutex); + return p; +} + +/* +** Free memory. +*/ +static void sqlite3MemFree(void *pPrior){ + struct MemBlockHdr *pHdr; + void **pBt; + char *z; + assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0 + || mem.mutex!=0 ); + pHdr = sqlite3MemsysGetHeader(pPrior); + pBt = (void**)pHdr; + pBt -= pHdr->nBacktraceSlots; + sqlite3_mutex_enter(mem.mutex); + if( pHdr->pPrev ){ + assert( pHdr->pPrev->pNext==pHdr ); + pHdr->pPrev->pNext = pHdr->pNext; + }else{ + assert( mem.pFirst==pHdr ); + mem.pFirst = pHdr->pNext; + } + if( pHdr->pNext ){ + assert( pHdr->pNext->pPrev==pHdr ); + pHdr->pNext->pPrev = pHdr->pPrev; + }else{ + assert( mem.pLast==pHdr ); + mem.pLast = pHdr->pPrev; + } + z = (char*)pBt; + z -= pHdr->nTitle; + adjustStats((int)pHdr->iSize, -1); + randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + + (int)pHdr->iSize + sizeof(int) + pHdr->nTitle); + free(z); + sqlite3_mutex_leave(mem.mutex); +} + +/* +** Change the size of an existing memory allocation. +** +** For this debugging implementation, we *always* make a copy of the +** allocation into a new place in memory. In this way, if the +** higher level code is using pointer to the old allocation, it is +** much more likely to break and we are much more liking to find +** the error. +*/ +static void *sqlite3MemRealloc(void *pPrior, int nByte){ + struct MemBlockHdr *pOldHdr; + void *pNew; + assert( mem.disallow==0 ); + assert( (nByte & 7)==0 ); /* EV: R-46199-30249 */ + pOldHdr = sqlite3MemsysGetHeader(pPrior); + pNew = sqlite3MemMalloc(nByte); + if( pNew ){ + memcpy(pNew, pPrior, (int)(nByteiSize ? nByte : pOldHdr->iSize)); + if( nByte>pOldHdr->iSize ){ + randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - (int)pOldHdr->iSize); + } + sqlite3MemFree(pPrior); + } + return pNew; +} + +/* +** Populate the low-level memory allocation function pointers in +** sqlite3GlobalConfig.m with pointers to the routines in this file. +*/ +SQLITE_PRIVATE void sqlite3MemSetDefault(void){ + static const sqlite3_mem_methods defaultMethods = { + sqlite3MemMalloc, + sqlite3MemFree, + sqlite3MemRealloc, + sqlite3MemSize, + sqlite3MemRoundup, + sqlite3MemInit, + sqlite3MemShutdown, + 0 + }; + sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); +} + +/* +** Set the "type" of an allocation. +*/ +SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){ + if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){ + struct MemBlockHdr *pHdr; + pHdr = sqlite3MemsysGetHeader(p); + assert( pHdr->iForeGuard==FOREGUARD ); + pHdr->eType = eType; + } +} + +/* +** Return TRUE if the mask of type in eType matches the type of the +** allocation p. Also return true if p==NULL. +** +** This routine is designed for use within an assert() statement, to +** verify the type of an allocation. For example: +** +** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); +*/ +SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){ + int rc = 1; + if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){ + struct MemBlockHdr *pHdr; + pHdr = sqlite3MemsysGetHeader(p); + assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ + if( (pHdr->eType&eType)==0 ){ + rc = 0; + } + } + return rc; +} + +/* +** Return TRUE if the mask of type in eType matches no bits of the type of the +** allocation p. Also return true if p==NULL. +** +** This routine is designed for use within an assert() statement, to +** verify the type of an allocation. For example: +** +** assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); +*/ +SQLITE_PRIVATE int sqlite3MemdebugNoType(void *p, u8 eType){ + int rc = 1; + if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){ + struct MemBlockHdr *pHdr; + pHdr = sqlite3MemsysGetHeader(p); + assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ + if( (pHdr->eType&eType)!=0 ){ + rc = 0; + } + } + return rc; +} + +/* +** Set the number of backtrace levels kept for each allocation. +** A value of zero turns off backtracing. The number is always rounded +** up to a multiple of 2. +*/ +SQLITE_PRIVATE void sqlite3MemdebugBacktrace(int depth){ + if( depth<0 ){ depth = 0; } + if( depth>20 ){ depth = 20; } + depth = (depth+1)&0xfe; + mem.nBacktrace = depth; +} + +SQLITE_PRIVATE void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){ + mem.xBacktrace = xBacktrace; +} + +/* +** Set the title string for subsequent allocations. +*/ +SQLITE_PRIVATE void sqlite3MemdebugSettitle(const char *zTitle){ + unsigned int n = sqlite3Strlen30(zTitle) + 1; + sqlite3_mutex_enter(mem.mutex); + if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1; + memcpy(mem.zTitle, zTitle, n); + mem.zTitle[n] = 0; + mem.nTitle = ROUND8(n); + sqlite3_mutex_leave(mem.mutex); +} + +SQLITE_PRIVATE void sqlite3MemdebugSync(){ + struct MemBlockHdr *pHdr; + for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){ + void **pBt = (void**)pHdr; + pBt -= pHdr->nBacktraceSlots; + mem.xBacktrace((int)pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]); + } +} + +/* +** Open the file indicated and write a log of all unfreed memory +** allocations into that log. +*/ +SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){ + FILE *out; + struct MemBlockHdr *pHdr; + void **pBt; + int i; + out = fopen(zFilename, "w"); + if( out==0 ){ + fprintf(stderr, "** Unable to output memory debug output log: %s **\n", + zFilename); + return; + } + for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){ + char *z = (char*)pHdr; + z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle; + fprintf(out, "**** %lld bytes at %p from %s ****\n", + pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???"); + if( pHdr->nBacktrace ){ + fflush(out); + pBt = (void**)pHdr; + pBt -= pHdr->nBacktraceSlots; + backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out)); + fprintf(out, "\n"); + } + } + fprintf(out, "COUNTS:\n"); + for(i=0; i=1 ); + size = mem3.aPool[i-1].u.hdr.size4x/4; + assert( size==mem3.aPool[i+size-1].u.hdr.prevSize ); + assert( size>=2 ); + if( size <= MX_SMALL ){ + memsys3UnlinkFromList(i, &mem3.aiSmall[size-2]); + }else{ + hash = size % N_HASH; + memsys3UnlinkFromList(i, &mem3.aiHash[hash]); + } +} + +/* +** Link the chunk at mem3.aPool[i] so that is on the list rooted +** at *pRoot. +*/ +static void memsys3LinkIntoList(u32 i, u32 *pRoot){ + assert( sqlite3_mutex_held(mem3.mutex) ); + mem3.aPool[i].u.list.next = *pRoot; + mem3.aPool[i].u.list.prev = 0; + if( *pRoot ){ + mem3.aPool[*pRoot].u.list.prev = i; + } + *pRoot = i; +} + +/* +** Link the chunk at index i into either the appropriate +** small chunk list, or into the large chunk hash table. +*/ +static void memsys3Link(u32 i){ + u32 size, hash; + assert( sqlite3_mutex_held(mem3.mutex) ); + assert( i>=1 ); + assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 ); + size = mem3.aPool[i-1].u.hdr.size4x/4; + assert( size==mem3.aPool[i+size-1].u.hdr.prevSize ); + assert( size>=2 ); + if( size <= MX_SMALL ){ + memsys3LinkIntoList(i, &mem3.aiSmall[size-2]); + }else{ + hash = size % N_HASH; + memsys3LinkIntoList(i, &mem3.aiHash[hash]); + } +} + +/* +** If the STATIC_MEM mutex is not already held, obtain it now. The mutex +** will already be held (obtained by code in malloc.c) if +** sqlite3GlobalConfig.bMemStat is true. +*/ +static void memsys3Enter(void){ + if( sqlite3GlobalConfig.bMemstat==0 && mem3.mutex==0 ){ + mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + } + sqlite3_mutex_enter(mem3.mutex); +} +static void memsys3Leave(void){ + sqlite3_mutex_leave(mem3.mutex); +} + +/* +** Called when we are unable to satisfy an allocation of nBytes. +*/ +static void memsys3OutOfMemory(int nByte){ + if( !mem3.alarmBusy ){ + mem3.alarmBusy = 1; + assert( sqlite3_mutex_held(mem3.mutex) ); + sqlite3_mutex_leave(mem3.mutex); + sqlite3_release_memory(nByte); + sqlite3_mutex_enter(mem3.mutex); + mem3.alarmBusy = 0; + } +} + + +/* +** Chunk i is a free chunk that has been unlinked. Adjust its +** size parameters for check-out and return a pointer to the +** user portion of the chunk. +*/ +static void *memsys3Checkout(u32 i, u32 nBlock){ + u32 x; + assert( sqlite3_mutex_held(mem3.mutex) ); + assert( i>=1 ); + assert( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ); + assert( mem3.aPool[i+nBlock-1].u.hdr.prevSize==nBlock ); + x = mem3.aPool[i-1].u.hdr.size4x; + mem3.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2); + mem3.aPool[i+nBlock-1].u.hdr.prevSize = nBlock; + mem3.aPool[i+nBlock-1].u.hdr.size4x |= 2; + return &mem3.aPool[i]; +} + +/* +** Carve a piece off of the end of the mem3.iMaster free chunk. +** Return a pointer to the new allocation. Or, if the master chunk +** is not large enough, return 0. +*/ +static void *memsys3FromMaster(u32 nBlock){ + assert( sqlite3_mutex_held(mem3.mutex) ); + assert( mem3.szMaster>=nBlock ); + if( nBlock>=mem3.szMaster-1 ){ + /* Use the entire master */ + void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster); + mem3.iMaster = 0; + mem3.szMaster = 0; + mem3.mnMaster = 0; + return p; + }else{ + /* Split the master block. Return the tail. */ + u32 newi, x; + newi = mem3.iMaster + mem3.szMaster - nBlock; + assert( newi > mem3.iMaster+1 ); + mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock; + mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2; + mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1; + mem3.szMaster -= nBlock; + mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster; + x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2; + mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x; + if( mem3.szMaster < mem3.mnMaster ){ + mem3.mnMaster = mem3.szMaster; + } + return (void*)&mem3.aPool[newi]; + } +} + +/* +** *pRoot is the head of a list of free chunks of the same size +** or same size hash. In other words, *pRoot is an entry in either +** mem3.aiSmall[] or mem3.aiHash[]. +** +** This routine examines all entries on the given list and tries +** to coalesce each entries with adjacent free chunks. +** +** If it sees a chunk that is larger than mem3.iMaster, it replaces +** the current mem3.iMaster with the new larger chunk. In order for +** this mem3.iMaster replacement to work, the master chunk must be +** linked into the hash tables. That is not the normal state of +** affairs, of course. The calling routine must link the master +** chunk before invoking this routine, then must unlink the (possibly +** changed) master chunk once this routine has finished. +*/ +static void memsys3Merge(u32 *pRoot){ + u32 iNext, prev, size, i, x; + + assert( sqlite3_mutex_held(mem3.mutex) ); + for(i=*pRoot; i>0; i=iNext){ + iNext = mem3.aPool[i].u.list.next; + size = mem3.aPool[i-1].u.hdr.size4x; + assert( (size&1)==0 ); + if( (size&2)==0 ){ + memsys3UnlinkFromList(i, pRoot); + assert( i > mem3.aPool[i-1].u.hdr.prevSize ); + prev = i - mem3.aPool[i-1].u.hdr.prevSize; + if( prev==iNext ){ + iNext = mem3.aPool[prev].u.list.next; + } + memsys3Unlink(prev); + size = i + size/4 - prev; + x = mem3.aPool[prev-1].u.hdr.size4x & 2; + mem3.aPool[prev-1].u.hdr.size4x = size*4 | x; + mem3.aPool[prev+size-1].u.hdr.prevSize = size; + memsys3Link(prev); + i = prev; + }else{ + size /= 4; + } + if( size>mem3.szMaster ){ + mem3.iMaster = i; + mem3.szMaster = size; + } + } +} + +/* +** Return a block of memory of at least nBytes in size. +** Return NULL if unable. +** +** This function assumes that the necessary mutexes, if any, are +** already held by the caller. Hence "Unsafe". +*/ +static void *memsys3MallocUnsafe(int nByte){ + u32 i; + u32 nBlock; + u32 toFree; + + assert( sqlite3_mutex_held(mem3.mutex) ); + assert( sizeof(Mem3Block)==8 ); + if( nByte<=12 ){ + nBlock = 2; + }else{ + nBlock = (nByte + 11)/8; + } + assert( nBlock>=2 ); + + /* STEP 1: + ** Look for an entry of the correct size in either the small + ** chunk table or in the large chunk hash table. This is + ** successful most of the time (about 9 times out of 10). + */ + if( nBlock <= MX_SMALL ){ + i = mem3.aiSmall[nBlock-2]; + if( i>0 ){ + memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]); + return memsys3Checkout(i, nBlock); + } + }else{ + int hash = nBlock % N_HASH; + for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next){ + if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ){ + memsys3UnlinkFromList(i, &mem3.aiHash[hash]); + return memsys3Checkout(i, nBlock); + } + } + } + + /* STEP 2: + ** Try to satisfy the allocation by carving a piece off of the end + ** of the master chunk. This step usually works if step 1 fails. + */ + if( mem3.szMaster>=nBlock ){ + return memsys3FromMaster(nBlock); + } + + + /* STEP 3: + ** Loop through the entire memory pool. Coalesce adjacent free + ** chunks. Recompute the master chunk as the largest free chunk. + ** Then try again to satisfy the allocation by carving a piece off + ** of the end of the master chunk. This step happens very + ** rarely (we hope!) + */ + for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){ + memsys3OutOfMemory(toFree); + if( mem3.iMaster ){ + memsys3Link(mem3.iMaster); + mem3.iMaster = 0; + mem3.szMaster = 0; + } + for(i=0; i=nBlock ){ + return memsys3FromMaster(nBlock); + } + } + } + + /* If none of the above worked, then we fail. */ + return 0; +} + +/* +** Free an outstanding memory allocation. +** +** This function assumes that the necessary mutexes, if any, are +** already held by the caller. Hence "Unsafe". +*/ +static void memsys3FreeUnsafe(void *pOld){ + Mem3Block *p = (Mem3Block*)pOld; + int i; + u32 size, x; + assert( sqlite3_mutex_held(mem3.mutex) ); + assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] ); + i = p - mem3.aPool; + assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 ); + size = mem3.aPool[i-1].u.hdr.size4x/4; + assert( i+size<=mem3.nPool+1 ); + mem3.aPool[i-1].u.hdr.size4x &= ~1; + mem3.aPool[i+size-1].u.hdr.prevSize = size; + mem3.aPool[i+size-1].u.hdr.size4x &= ~2; + memsys3Link(i); + + /* Try to expand the master using the newly freed chunk */ + if( mem3.iMaster ){ + while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){ + size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize; + mem3.iMaster -= size; + mem3.szMaster += size; + memsys3Unlink(mem3.iMaster); + x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2; + mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x; + mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster; + } + x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2; + while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){ + memsys3Unlink(mem3.iMaster+mem3.szMaster); + mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4; + mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x; + mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster; + } + } +} + +/* +** Return the size of an outstanding allocation, in bytes. The +** size returned omits the 8-byte header overhead. This only +** works for chunks that are currently checked out. +*/ +static int memsys3Size(void *p){ + Mem3Block *pBlock; + if( p==0 ) return 0; + pBlock = (Mem3Block*)p; + assert( (pBlock[-1].u.hdr.size4x&1)!=0 ); + return (pBlock[-1].u.hdr.size4x&~3)*2 - 4; +} + +/* +** Round up a request size to the next valid allocation size. +*/ +static int memsys3Roundup(int n){ + if( n<=12 ){ + return 12; + }else{ + return ((n+11)&~7) - 4; + } +} + +/* +** Allocate nBytes of memory. +*/ +static void *memsys3Malloc(int nBytes){ + sqlite3_int64 *p; + assert( nBytes>0 ); /* malloc.c filters out 0 byte requests */ + memsys3Enter(); + p = memsys3MallocUnsafe(nBytes); + memsys3Leave(); + return (void*)p; +} + +/* +** Free memory. +*/ +static void memsys3Free(void *pPrior){ + assert( pPrior ); + memsys3Enter(); + memsys3FreeUnsafe(pPrior); + memsys3Leave(); +} + +/* +** Change the size of an existing memory allocation +*/ +static void *memsys3Realloc(void *pPrior, int nBytes){ + int nOld; + void *p; + if( pPrior==0 ){ + return sqlite3_malloc(nBytes); + } + if( nBytes<=0 ){ + sqlite3_free(pPrior); + return 0; + } + nOld = memsys3Size(pPrior); + if( nBytes<=nOld && nBytes>=nOld-128 ){ + return pPrior; + } + memsys3Enter(); + p = memsys3MallocUnsafe(nBytes); + if( p ){ + if( nOld>1)!=(size&1) ){ + fprintf(out, "%p tail checkout bit is incorrect\n", &mem3.aPool[i]); + assert( 0 ); + break; + } + if( size&1 ){ + fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8); + }else{ + fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8, + i==mem3.iMaster ? " **master**" : ""); + } + } + for(i=0; i0; j=mem3.aPool[j].u.list.next){ + fprintf(out, " %p(%d)", &mem3.aPool[j], + (mem3.aPool[j-1].u.hdr.size4x/4)*8-8); + } + fprintf(out, "\n"); + } + for(i=0; i0; j=mem3.aPool[j].u.list.next){ + fprintf(out, " %p(%d)", &mem3.aPool[j], + (mem3.aPool[j-1].u.hdr.size4x/4)*8-8); + } + fprintf(out, "\n"); + } + fprintf(out, "master=%d\n", mem3.iMaster); + fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8); + fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnMaster*8); + sqlite3_mutex_leave(mem3.mutex); + if( out==stdout ){ + fflush(stdout); + }else{ + fclose(out); + } +#else + UNUSED_PARAMETER(zFilename); +#endif +} + +/* +** This routine is the only routine in this file with external +** linkage. +** +** Populate the low-level memory allocation function pointers in +** sqlite3GlobalConfig.m with pointers to the routines in this file. The +** arguments specify the block of memory to manage. +** +** This routine is only called by sqlite3_config(), and therefore +** is not required to be threadsafe (it is not). +*/ +SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){ + static const sqlite3_mem_methods mempoolMethods = { + memsys3Malloc, + memsys3Free, + memsys3Realloc, + memsys3Size, + memsys3Roundup, + memsys3Init, + memsys3Shutdown, + 0 + }; + return &mempoolMethods; +} + +#endif /* SQLITE_ENABLE_MEMSYS3 */ + +/************** End of mem3.c ************************************************/ +/************** Begin file mem5.c ********************************************/ +/* +** 2007 October 14 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains the C functions that implement a memory +** allocation subsystem for use by SQLite. +** +** This version of the memory allocation subsystem omits all +** use of malloc(). The application gives SQLite a block of memory +** before calling sqlite3_initialize() from which allocations +** are made and returned by the xMalloc() and xRealloc() +** implementations. Once sqlite3_initialize() has been called, +** the amount of memory available to SQLite is fixed and cannot +** be changed. +** +** This version of the memory allocation subsystem is included +** in the build only if SQLITE_ENABLE_MEMSYS5 is defined. +** +** This memory allocator uses the following algorithm: +** +** 1. All memory allocations sizes are rounded up to a power of 2. +** +** 2. If two adjacent free blocks are the halves of a larger block, +** then the two blocks are coalesced into the single larger block. +** +** 3. New memory is allocated from the first available free block. +** +** This algorithm is described in: J. M. Robson. "Bounds for Some Functions +** Concerning Dynamic Storage Allocation". Journal of the Association for +** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499. +** +** Let n be the size of the largest allocation divided by the minimum +** allocation size (after rounding all sizes up to a power of 2.) Let M +** be the maximum amount of memory ever outstanding at one time. Let +** N be the total amount of memory available for allocation. Robson +** proved that this memory allocator will never breakdown due to +** fragmentation as long as the following constraint holds: +** +** N >= M*(1 + log2(n)/2) - n + 1 +** +** The sqlite3_status() logic tracks the maximum values of n and M so +** that an application can, at any time, verify this constraint. +*/ +/* #include "sqliteInt.h" */ + +/* +** This version of the memory allocator is used only when +** SQLITE_ENABLE_MEMSYS5 is defined. +*/ +#ifdef SQLITE_ENABLE_MEMSYS5 + +/* +** A minimum allocation is an instance of the following structure. +** Larger allocations are an array of these structures where the +** size of the array is a power of 2. +** +** The size of this object must be a power of two. That fact is +** verified in memsys5Init(). +*/ +typedef struct Mem5Link Mem5Link; +struct Mem5Link { + int next; /* Index of next free chunk */ + int prev; /* Index of previous free chunk */ +}; + +/* +** Maximum size of any allocation is ((1<=0 && i=0 && iLogsize<=LOGMAX ); + assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize ); + + next = MEM5LINK(i)->next; + prev = MEM5LINK(i)->prev; + if( prev<0 ){ + mem5.aiFreelist[iLogsize] = next; + }else{ + MEM5LINK(prev)->next = next; + } + if( next>=0 ){ + MEM5LINK(next)->prev = prev; + } +} + +/* +** Link the chunk at mem5.aPool[i] so that is on the iLogsize +** free list. +*/ +static void memsys5Link(int i, int iLogsize){ + int x; + assert( sqlite3_mutex_held(mem5.mutex) ); + assert( i>=0 && i=0 && iLogsize<=LOGMAX ); + assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize ); + + x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize]; + MEM5LINK(i)->prev = -1; + if( x>=0 ){ + assert( xprev = i; + } + mem5.aiFreelist[iLogsize] = i; +} + +/* +** If the STATIC_MEM mutex is not already held, obtain it now. The mutex +** will already be held (obtained by code in malloc.c) if +** sqlite3GlobalConfig.bMemStat is true. +*/ +static void memsys5Enter(void){ + sqlite3_mutex_enter(mem5.mutex); +} +static void memsys5Leave(void){ + sqlite3_mutex_leave(mem5.mutex); +} + +/* +** Return the size of an outstanding allocation, in bytes. The +** size returned omits the 8-byte header overhead. This only +** works for chunks that are currently checked out. +*/ +static int memsys5Size(void *p){ + int iSize = 0; + if( p ){ + int i = (int)(((u8 *)p-mem5.zPool)/mem5.szAtom); + assert( i>=0 && i0 ); + + /* Keep track of the maximum allocation request. Even unfulfilled + ** requests are counted */ + if( (u32)nByte>mem5.maxRequest ){ + mem5.maxRequest = nByte; + } + + /* Abort if the requested allocation size is larger than the largest + ** power of two that we can represent using 32-bit signed integers. + */ + if( nByte > 0x40000000 ){ + return 0; + } + + /* Round nByte up to the next valid power of two */ + for(iFullSz=mem5.szAtom, iLogsize=0; iFullSzLOGMAX ){ + testcase( sqlite3GlobalConfig.xLog!=0 ); + sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte); + return 0; + } + i = mem5.aiFreelist[iBin]; + memsys5Unlink(i, iBin); + while( iBin>iLogsize ){ + int newSize; + + iBin--; + newSize = 1 << iBin; + mem5.aCtrl[i+newSize] = CTRL_FREE | iBin; + memsys5Link(i+newSize, iBin); + } + mem5.aCtrl[i] = iLogsize; + + /* Update allocator performance statistics. */ + mem5.nAlloc++; + mem5.totalAlloc += iFullSz; + mem5.totalExcess += iFullSz - nByte; + mem5.currentCount++; + mem5.currentOut += iFullSz; + if( mem5.maxCount=0 && iBlock0 ); + assert( mem5.currentOut>=(size*mem5.szAtom) ); + mem5.currentCount--; + mem5.currentOut -= size*mem5.szAtom; + assert( mem5.currentOut>0 || mem5.currentCount==0 ); + assert( mem5.currentCount>0 || mem5.currentOut==0 ); + + mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize; + while( ALWAYS(iLogsize>iLogsize) & 1 ){ + iBuddy = iBlock - size; + }else{ + iBuddy = iBlock + size; + } + assert( iBuddy>=0 ); + if( (iBuddy+(1<mem5.nBlock ) break; + if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break; + memsys5Unlink(iBuddy, iLogsize); + iLogsize++; + if( iBuddy0 ){ + memsys5Enter(); + p = memsys5MallocUnsafe(nBytes); + memsys5Leave(); + } + return (void*)p; +} + +/* +** Free memory. +** +** The outer layer memory allocator prevents this routine from +** being called with pPrior==0. +*/ +static void memsys5Free(void *pPrior){ + assert( pPrior!=0 ); + memsys5Enter(); + memsys5FreeUnsafe(pPrior); + memsys5Leave(); +} + +/* +** Change the size of an existing memory allocation. +** +** The outer layer memory allocator prevents this routine from +** being called with pPrior==0. +** +** nBytes is always a value obtained from a prior call to +** memsys5Round(). Hence nBytes is always a non-negative power +** of two. If nBytes==0 that means that an oversize allocation +** (an allocation larger than 0x40000000) was requested and this +** routine should return 0 without freeing pPrior. +*/ +static void *memsys5Realloc(void *pPrior, int nBytes){ + int nOld; + void *p; + assert( pPrior!=0 ); + assert( (nBytes&(nBytes-1))==0 ); /* EV: R-46199-30249 */ + assert( nBytes>=0 ); + if( nBytes==0 ){ + return 0; + } + nOld = memsys5Size(pPrior); + if( nBytes<=nOld ){ + return pPrior; + } + memsys5Enter(); + p = memsys5MallocUnsafe(nBytes); + if( p ){ + memcpy(p, pPrior, nOld); + memsys5FreeUnsafe(pPrior); + } + memsys5Leave(); + return p; +} + +/* +** Round up a request size to the next valid allocation size. If +** the allocation is too large to be handled by this allocation system, +** return 0. +** +** All allocations must be a power of two and must be expressed by a +** 32-bit signed integer. Hence the largest allocation is 0x40000000 +** or 1073741824 bytes. +*/ +static int memsys5Roundup(int n){ + int iFullSz; + if( n > 0x40000000 ) return 0; + for(iFullSz=mem5.szAtom; iFullSz 0 +** memsys5Log(2) -> 1 +** memsys5Log(4) -> 2 +** memsys5Log(5) -> 3 +** memsys5Log(8) -> 3 +** memsys5Log(9) -> 4 +*/ +static int memsys5Log(int iValue){ + int iLog; + for(iLog=0; (iLog<(int)((sizeof(int)*8)-1)) && (1<mem5.szAtom ){ + mem5.szAtom = mem5.szAtom << 1; + } + + mem5.nBlock = (nByte / (mem5.szAtom+sizeof(u8))); + mem5.zPool = zByte; + mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.szAtom]; + + for(ii=0; ii<=LOGMAX; ii++){ + mem5.aiFreelist[ii] = -1; + } + + iOffset = 0; + for(ii=LOGMAX; ii>=0; ii--){ + int nAlloc = (1<mem5.nBlock); + } + + /* If a mutex is required for normal operation, allocate one */ + if( sqlite3GlobalConfig.bMemstat==0 ){ + mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + } + + return SQLITE_OK; +} + +/* +** Deinitialize this module. +*/ +static void memsys5Shutdown(void *NotUsed){ + UNUSED_PARAMETER(NotUsed); + mem5.mutex = 0; + return; +} + +#ifdef SQLITE_TEST +/* +** Open the file indicated and write a log of all unfreed memory +** allocations into that log. +*/ +SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){ + FILE *out; + int i, j, n; + int nMinLog; + + if( zFilename==0 || zFilename[0]==0 ){ + out = stdout; + }else{ + out = fopen(zFilename, "w"); + if( out==0 ){ + fprintf(stderr, "** Unable to output memory debug output log: %s **\n", + zFilename); + return; + } + } + memsys5Enter(); + nMinLog = memsys5Log(mem5.szAtom); + for(i=0; i<=LOGMAX && i+nMinLog<32; i++){ + for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){} + fprintf(out, "freelist items of size %d: %d\n", mem5.szAtom << i, n); + } + fprintf(out, "mem5.nAlloc = %llu\n", mem5.nAlloc); + fprintf(out, "mem5.totalAlloc = %llu\n", mem5.totalAlloc); + fprintf(out, "mem5.totalExcess = %llu\n", mem5.totalExcess); + fprintf(out, "mem5.currentOut = %u\n", mem5.currentOut); + fprintf(out, "mem5.currentCount = %u\n", mem5.currentCount); + fprintf(out, "mem5.maxOut = %u\n", mem5.maxOut); + fprintf(out, "mem5.maxCount = %u\n", mem5.maxCount); + fprintf(out, "mem5.maxRequest = %u\n", mem5.maxRequest); + memsys5Leave(); + if( out==stdout ){ + fflush(stdout); + }else{ + fclose(out); + } +} +#endif + +/* +** This routine is the only routine in this file with external +** linkage. It returns a pointer to a static sqlite3_mem_methods +** struct populated with the memsys5 methods. +*/ +SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void){ + static const sqlite3_mem_methods memsys5Methods = { + memsys5Malloc, + memsys5Free, + memsys5Realloc, + memsys5Size, + memsys5Roundup, + memsys5Init, + memsys5Shutdown, + 0 + }; + return &memsys5Methods; +} + +#endif /* SQLITE_ENABLE_MEMSYS5 */ + +/************** End of mem5.c ************************************************/ +/************** Begin file mutex.c *******************************************/ +/* +** 2007 August 14 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains the C functions that implement mutexes. +** +** This file contains code that is common across all mutex implementations. +*/ +/* #include "sqliteInt.h" */ + +#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT) +/* +** For debugging purposes, record when the mutex subsystem is initialized +** and uninitialized so that we can assert() if there is an attempt to +** allocate a mutex while the system is uninitialized. +*/ +static SQLITE_WSD int mutexIsInit = 0; +#endif /* SQLITE_DEBUG */ + + +#ifndef SQLITE_MUTEX_OMIT +/* +** Initialize the mutex system. +*/ +SQLITE_PRIVATE int sqlite3MutexInit(void){ + int rc = SQLITE_OK; + if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){ + /* If the xMutexAlloc method has not been set, then the user did not + ** install a mutex implementation via sqlite3_config() prior to + ** sqlite3_initialize() being called. This block copies pointers to + ** the default implementation into the sqlite3GlobalConfig structure. + */ + sqlite3_mutex_methods const *pFrom; + sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex; + + if( sqlite3GlobalConfig.bCoreMutex ){ + pFrom = sqlite3DefaultMutex(); + }else{ + pFrom = sqlite3NoopMutex(); + } + pTo->xMutexInit = pFrom->xMutexInit; + pTo->xMutexEnd = pFrom->xMutexEnd; + pTo->xMutexFree = pFrom->xMutexFree; + pTo->xMutexEnter = pFrom->xMutexEnter; + pTo->xMutexTry = pFrom->xMutexTry; + pTo->xMutexLeave = pFrom->xMutexLeave; + pTo->xMutexHeld = pFrom->xMutexHeld; + pTo->xMutexNotheld = pFrom->xMutexNotheld; + pTo->xMutexAlloc = pFrom->xMutexAlloc; + } + rc = sqlite3GlobalConfig.mutex.xMutexInit(); + +#ifdef SQLITE_DEBUG + GLOBAL(int, mutexIsInit) = 1; +#endif + + return rc; +} + +/* +** Shutdown the mutex system. This call frees resources allocated by +** sqlite3MutexInit(). +*/ +SQLITE_PRIVATE int sqlite3MutexEnd(void){ + int rc = SQLITE_OK; + if( sqlite3GlobalConfig.mutex.xMutexEnd ){ + rc = sqlite3GlobalConfig.mutex.xMutexEnd(); + } + +#ifdef SQLITE_DEBUG + GLOBAL(int, mutexIsInit) = 0; +#endif + + return rc; +} + +/* +** Retrieve a pointer to a static mutex or allocate a new dynamic one. +*/ +SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int id){ +#ifndef SQLITE_OMIT_AUTOINIT + if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0; + if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0; +#endif + return sqlite3GlobalConfig.mutex.xMutexAlloc(id); +} + +SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){ + if( !sqlite3GlobalConfig.bCoreMutex ){ + return 0; + } + assert( GLOBAL(int, mutexIsInit) ); + return sqlite3GlobalConfig.mutex.xMutexAlloc(id); +} + +/* +** Free a dynamic mutex. +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex *p){ + if( p ){ + sqlite3GlobalConfig.mutex.xMutexFree(p); + } +} + +/* +** Obtain the mutex p. If some other thread already has the mutex, block +** until it can be obtained. +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex *p){ + if( p ){ + sqlite3GlobalConfig.mutex.xMutexEnter(p); + } +} + +/* +** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another +** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex *p){ + int rc = SQLITE_OK; + if( p ){ + return sqlite3GlobalConfig.mutex.xMutexTry(p); + } + return rc; +} + +/* +** The sqlite3_mutex_leave() routine exits a mutex that was previously +** entered by the same thread. The behavior is undefined if the mutex +** is not currently entered. If a NULL pointer is passed as an argument +** this function is a no-op. +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex *p){ + if( p ){ + sqlite3GlobalConfig.mutex.xMutexLeave(p); + } +} + +#ifndef NDEBUG +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use inside assert() statements. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex *p){ + return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p); +} +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex *p){ + return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p); +} +#endif + +#endif /* !defined(SQLITE_MUTEX_OMIT) */ + +/************** End of mutex.c ***********************************************/ +/************** Begin file mutex_noop.c **************************************/ +/* +** 2008 October 07 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains the C functions that implement mutexes. +** +** This implementation in this file does not provide any mutual +** exclusion and is thus suitable for use only in applications +** that use SQLite in a single thread. The routines defined +** here are place-holders. Applications can substitute working +** mutex routines at start-time using the +** +** sqlite3_config(SQLITE_CONFIG_MUTEX,...) +** +** interface. +** +** If compiled with SQLITE_DEBUG, then additional logic is inserted +** that does error checking on mutexes to make sure they are being +** called correctly. +*/ +/* #include "sqliteInt.h" */ + +#ifndef SQLITE_MUTEX_OMIT + +#ifndef SQLITE_DEBUG +/* +** Stub routines for all mutex methods. +** +** This routines provide no mutual exclusion or error checking. +*/ +static int noopMutexInit(void){ return SQLITE_OK; } +static int noopMutexEnd(void){ return SQLITE_OK; } +static sqlite3_mutex *noopMutexAlloc(int id){ + UNUSED_PARAMETER(id); + return (sqlite3_mutex*)8; +} +static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } +static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } +static int noopMutexTry(sqlite3_mutex *p){ + UNUSED_PARAMETER(p); + return SQLITE_OK; +} +static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } + +SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){ + static const sqlite3_mutex_methods sMutex = { + noopMutexInit, + noopMutexEnd, + noopMutexAlloc, + noopMutexFree, + noopMutexEnter, + noopMutexTry, + noopMutexLeave, + + 0, + 0, + }; + + return &sMutex; +} +#endif /* !SQLITE_DEBUG */ + +#ifdef SQLITE_DEBUG +/* +** In this implementation, error checking is provided for testing +** and debugging purposes. The mutexes still do not provide any +** mutual exclusion. +*/ + +/* +** The mutex object +*/ +typedef struct sqlite3_debug_mutex { + int id; /* The mutex type */ + int cnt; /* Number of entries without a matching leave */ +} sqlite3_debug_mutex; + +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use inside assert() statements. +*/ +static int debugMutexHeld(sqlite3_mutex *pX){ + sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; + return p==0 || p->cnt>0; +} +static int debugMutexNotheld(sqlite3_mutex *pX){ + sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; + return p==0 || p->cnt==0; +} + +/* +** Initialize and deinitialize the mutex subsystem. +*/ +static int debugMutexInit(void){ return SQLITE_OK; } +static int debugMutexEnd(void){ return SQLITE_OK; } + +/* +** The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. If it returns NULL +** that means that a mutex could not be allocated. +*/ +static sqlite3_mutex *debugMutexAlloc(int id){ + static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_VFS3 - 1]; + sqlite3_debug_mutex *pNew = 0; + switch( id ){ + case SQLITE_MUTEX_FAST: + case SQLITE_MUTEX_RECURSIVE: { + pNew = sqlite3Malloc(sizeof(*pNew)); + if( pNew ){ + pNew->id = id; + pNew->cnt = 0; + } + break; + } + default: { +#ifdef SQLITE_ENABLE_API_ARMOR + if( id-2<0 || id-2>=ArraySize(aStatic) ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + pNew = &aStatic[id-2]; + pNew->id = id; + break; + } + } + return (sqlite3_mutex*)pNew; +} + +/* +** This routine deallocates a previously allocated mutex. +*/ +static void debugMutexFree(sqlite3_mutex *pX){ + sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; + assert( p->cnt==0 ); + if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){ + sqlite3_free(p); + }else{ +#ifdef SQLITE_ENABLE_API_ARMOR + (void)SQLITE_MISUSE_BKPT; +#endif + } +} + +/* +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK +** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can +** be entered multiple times by the same thread. In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. If the same thread tries to enter any other kind of mutex +** more than once, the behavior is undefined. +*/ +static void debugMutexEnter(sqlite3_mutex *pX){ + sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; + assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); + p->cnt++; +} +static int debugMutexTry(sqlite3_mutex *pX){ + sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; + assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); + p->cnt++; + return SQLITE_OK; +} + +/* +** The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. The behavior +** is undefined if the mutex is not currently entered or +** is not currently allocated. SQLite will never do either. +*/ +static void debugMutexLeave(sqlite3_mutex *pX){ + sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; + assert( debugMutexHeld(pX) ); + p->cnt--; + assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); +} + +SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){ + static const sqlite3_mutex_methods sMutex = { + debugMutexInit, + debugMutexEnd, + debugMutexAlloc, + debugMutexFree, + debugMutexEnter, + debugMutexTry, + debugMutexLeave, + + debugMutexHeld, + debugMutexNotheld + }; + + return &sMutex; +} +#endif /* SQLITE_DEBUG */ + +/* +** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation +** is used regardless of the run-time threadsafety setting. +*/ +#ifdef SQLITE_MUTEX_NOOP +SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ + return sqlite3NoopMutex(); +} +#endif /* defined(SQLITE_MUTEX_NOOP) */ +#endif /* !defined(SQLITE_MUTEX_OMIT) */ + +/************** End of mutex_noop.c ******************************************/ +/************** Begin file mutex_unix.c **************************************/ +/* +** 2007 August 28 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains the C functions that implement mutexes for pthreads +*/ +/* #include "sqliteInt.h" */ + +/* +** The code in this file is only used if we are compiling threadsafe +** under unix with pthreads. +** +** Note that this implementation requires a version of pthreads that +** supports recursive mutexes. +*/ +#ifdef SQLITE_MUTEX_PTHREADS + +#include + +/* +** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields +** are necessary under two condidtions: (1) Debug builds and (2) using +** home-grown mutexes. Encapsulate these conditions into a single #define. +*/ +#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX) +# define SQLITE_MUTEX_NREF 1 +#else +# define SQLITE_MUTEX_NREF 0 +#endif + +/* +** Each recursive mutex is an instance of the following structure. +*/ +struct sqlite3_mutex { + pthread_mutex_t mutex; /* Mutex controlling the lock */ +#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) + int id; /* Mutex type */ +#endif +#if SQLITE_MUTEX_NREF + volatile int nRef; /* Number of entrances */ + volatile pthread_t owner; /* Thread that is within this mutex */ + int trace; /* True to trace changes */ +#endif +}; +#if SQLITE_MUTEX_NREF +#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 } +#else +#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } +#endif + +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use only inside assert() statements. On some platforms, +** there might be race conditions that can cause these routines to +** deliver incorrect results. In particular, if pthread_equal() is +** not an atomic operation, then these routines might delivery +** incorrect results. On most platforms, pthread_equal() is a +** comparison of two integers and is therefore atomic. But we are +** told that HPUX is not such a platform. If so, then these routines +** will not always work correctly on HPUX. +** +** On those platforms where pthread_equal() is not atomic, SQLite +** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to +** make sure no assert() statements are evaluated and hence these +** routines are never called. +*/ +#if !defined(NDEBUG) || defined(SQLITE_DEBUG) +static int pthreadMutexHeld(sqlite3_mutex *p){ + return (p->nRef!=0 && pthread_equal(p->owner, pthread_self())); +} +static int pthreadMutexNotheld(sqlite3_mutex *p){ + return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0; +} +#endif + +/* +** Initialize and deinitialize the mutex subsystem. +*/ +static int pthreadMutexInit(void){ return SQLITE_OK; } +static int pthreadMutexEnd(void){ return SQLITE_OK; } + +/* +** The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. If it returns NULL +** that means that a mutex could not be allocated. SQLite +** will unwind its stack and return an error. The argument +** to sqlite3_mutex_alloc() is one of these integer constants: +** +**
    +**
  • SQLITE_MUTEX_FAST +**
  • SQLITE_MUTEX_RECURSIVE +**
  • SQLITE_MUTEX_STATIC_MASTER +**
  • SQLITE_MUTEX_STATIC_MEM +**
  • SQLITE_MUTEX_STATIC_OPEN +**
  • SQLITE_MUTEX_STATIC_PRNG +**
  • SQLITE_MUTEX_STATIC_LRU +**
  • SQLITE_MUTEX_STATIC_PMEM +**
  • SQLITE_MUTEX_STATIC_APP1 +**
  • SQLITE_MUTEX_STATIC_APP2 +**
  • SQLITE_MUTEX_STATIC_APP3 +**
  • SQLITE_MUTEX_STATIC_VFS1 +**
  • SQLITE_MUTEX_STATIC_VFS2 +**
  • SQLITE_MUTEX_STATIC_VFS3 +**
+** +** The first two constants cause sqlite3_mutex_alloc() to create +** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. But SQLite will only request a recursive mutex in +** cases where it really needs one. If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** The other allowed parameters to sqlite3_mutex_alloc() each return +** a pointer to a static preexisting mutex. Six static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +*/ +static sqlite3_mutex *pthreadMutexAlloc(int iType){ + static sqlite3_mutex staticMutexes[] = { + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER + }; + sqlite3_mutex *p; + switch( iType ){ + case SQLITE_MUTEX_RECURSIVE: { + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + /* If recursive mutexes are not available, we will have to + ** build our own. See below. */ + pthread_mutex_init(&p->mutex, 0); +#else + /* Use a recursive mutex if it is available */ + pthread_mutexattr_t recursiveAttr; + pthread_mutexattr_init(&recursiveAttr); + pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&p->mutex, &recursiveAttr); + pthread_mutexattr_destroy(&recursiveAttr); +#endif + } + break; + } + case SQLITE_MUTEX_FAST: { + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ + pthread_mutex_init(&p->mutex, 0); + } + break; + } + default: { +#ifdef SQLITE_ENABLE_API_ARMOR + if( iType-2<0 || iType-2>=ArraySize(staticMutexes) ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + p = &staticMutexes[iType-2]; + break; + } + } +#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) + if( p ) p->id = iType; +#endif + return p; +} + + +/* +** This routine deallocates a previously +** allocated mutex. SQLite is careful to deallocate every +** mutex that it allocates. +*/ +static void pthreadMutexFree(sqlite3_mutex *p){ + assert( p->nRef==0 ); +#if SQLITE_ENABLE_API_ARMOR + if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ) +#endif + { + pthread_mutex_destroy(&p->mutex); + sqlite3_free(p); + } +#ifdef SQLITE_ENABLE_API_ARMOR + else{ + (void)SQLITE_MISUSE_BKPT; + } +#endif +} + +/* +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK +** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can +** be entered multiple times by the same thread. In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. If the same thread tries to enter any other kind of mutex +** more than once, the behavior is undefined. +*/ +static void pthreadMutexEnter(sqlite3_mutex *p){ + assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) ); + +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + /* If recursive mutexes are not available, then we have to grow + ** our own. This implementation assumes that pthread_equal() + ** is atomic - that it cannot be deceived into thinking self + ** and p->owner are equal if p->owner changes between two values + ** that are not equal to self while the comparison is taking place. + ** This implementation also assumes a coherent cache - that + ** separate processes cannot read different values from the same + ** address at the same time. If either of these two conditions + ** are not met, then the mutexes will fail and problems will result. + */ + { + pthread_t self = pthread_self(); + if( p->nRef>0 && pthread_equal(p->owner, self) ){ + p->nRef++; + }else{ + pthread_mutex_lock(&p->mutex); + assert( p->nRef==0 ); + p->owner = self; + p->nRef = 1; + } + } +#else + /* Use the built-in recursive mutexes if they are available. + */ + pthread_mutex_lock(&p->mutex); +#if SQLITE_MUTEX_NREF + assert( p->nRef>0 || p->owner==0 ); + p->owner = pthread_self(); + p->nRef++; +#endif +#endif + +#ifdef SQLITE_DEBUG + if( p->trace ){ + printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); + } +#endif +} +static int pthreadMutexTry(sqlite3_mutex *p){ + int rc; + assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) ); + +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + /* If recursive mutexes are not available, then we have to grow + ** our own. This implementation assumes that pthread_equal() + ** is atomic - that it cannot be deceived into thinking self + ** and p->owner are equal if p->owner changes between two values + ** that are not equal to self while the comparison is taking place. + ** This implementation also assumes a coherent cache - that + ** separate processes cannot read different values from the same + ** address at the same time. If either of these two conditions + ** are not met, then the mutexes will fail and problems will result. + */ + { + pthread_t self = pthread_self(); + if( p->nRef>0 && pthread_equal(p->owner, self) ){ + p->nRef++; + rc = SQLITE_OK; + }else if( pthread_mutex_trylock(&p->mutex)==0 ){ + assert( p->nRef==0 ); + p->owner = self; + p->nRef = 1; + rc = SQLITE_OK; + }else{ + rc = SQLITE_BUSY; + } + } +#else + /* Use the built-in recursive mutexes if they are available. + */ + if( pthread_mutex_trylock(&p->mutex)==0 ){ +#if SQLITE_MUTEX_NREF + p->owner = pthread_self(); + p->nRef++; +#endif + rc = SQLITE_OK; + }else{ + rc = SQLITE_BUSY; + } +#endif + +#ifdef SQLITE_DEBUG + if( rc==SQLITE_OK && p->trace ){ + printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); + } +#endif + return rc; +} + +/* +** The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. The behavior +** is undefined if the mutex is not currently entered or +** is not currently allocated. SQLite will never do either. +*/ +static void pthreadMutexLeave(sqlite3_mutex *p){ + assert( pthreadMutexHeld(p) ); +#if SQLITE_MUTEX_NREF + p->nRef--; + if( p->nRef==0 ) p->owner = 0; +#endif + assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); + +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + if( p->nRef==0 ){ + pthread_mutex_unlock(&p->mutex); + } +#else + pthread_mutex_unlock(&p->mutex); +#endif + +#ifdef SQLITE_DEBUG + if( p->trace ){ + printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); + } +#endif +} + +SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ + static const sqlite3_mutex_methods sMutex = { + pthreadMutexInit, + pthreadMutexEnd, + pthreadMutexAlloc, + pthreadMutexFree, + pthreadMutexEnter, + pthreadMutexTry, + pthreadMutexLeave, +#ifdef SQLITE_DEBUG + pthreadMutexHeld, + pthreadMutexNotheld +#else + 0, + 0 +#endif + }; + + return &sMutex; +} + +#endif /* SQLITE_MUTEX_PTHREADS */ + +/************** End of mutex_unix.c ******************************************/ +/************** Begin file mutex_w32.c ***************************************/ +/* +** 2007 August 14 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains the C functions that implement mutexes for Win32. +*/ +/* #include "sqliteInt.h" */ + +#if SQLITE_OS_WIN +/* +** Include code that is common to all os_*.c files +*/ +/************** Include os_common.h in the middle of mutex_w32.c *************/ +/************** Begin file os_common.h ***************************************/ +/* +** 2004 May 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains macros and a little bit of code that is common to +** all of the platform-specific files (os_*.c) and is #included into those +** files. +** +** This file should be #included by the os_*.c files only. It is not a +** general purpose header file. +*/ +#ifndef _OS_COMMON_H_ +#define _OS_COMMON_H_ + +/* +** At least two bugs have slipped in because we changed the MEMORY_DEBUG +** macro to SQLITE_DEBUG and some older makefiles have not yet made the +** switch. The following code should catch this problem at compile-time. +*/ +#ifdef MEMORY_DEBUG +# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." +#endif + +/* +** Macros for performance tracing. Normally turned off. Only works +** on i486 hardware. +*/ +#ifdef SQLITE_PERFORMANCE_TRACE + +/* +** hwtime.h contains inline assembler code for implementing +** high-performance timing routines. +*/ +/************** Include hwtime.h in the middle of os_common.h ****************/ +/************** Begin file hwtime.h ******************************************/ +/* +** 2008 May 27 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains inline asm code for retrieving "high-performance" +** counters for x86 class CPUs. +*/ +#ifndef _HWTIME_H_ +#define _HWTIME_H_ + +/* +** The following routine only works on pentium-class (or newer) processors. +** It uses the RDTSC opcode to read the cycle count value out of the +** processor and returns that value. This can be used for high-res +** profiling. +*/ +#if (defined(__GNUC__) || defined(_MSC_VER)) && \ + (defined(i386) || defined(__i386__) || defined(_M_IX86)) + + #if defined(__GNUC__) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned int lo, hi; + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + return (sqlite_uint64)hi << 32 | lo; + } + + #elif defined(_MSC_VER) + + __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ + __asm { + rdtsc + ret ; return value at EDX:EAX + } + } + + #endif + +#elif (defined(__GNUC__) && defined(__x86_64__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long val; + __asm__ __volatile__ ("rdtsc" : "=A" (val)); + return val; + } + +#elif (defined(__GNUC__) && defined(__ppc__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long long retval; + unsigned long junk; + __asm__ __volatile__ ("\n\ + 1: mftbu %1\n\ + mftb %L0\n\ + mftbu %0\n\ + cmpw %0,%1\n\ + bne 1b" + : "=r" (retval), "=r" (junk)); + return retval; + } + +#else + + #error Need implementation of sqlite3Hwtime() for your platform. + + /* + ** To compile without implementing sqlite3Hwtime() for your platform, + ** you can remove the above #error and use the following + ** stub function. You will lose timing support for many + ** of the debugging and testing utilities, but it should at + ** least compile and run. + */ +SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } + +#endif + +#endif /* !defined(_HWTIME_H_) */ + +/************** End of hwtime.h **********************************************/ +/************** Continuing where we left off in os_common.h ******************/ + +static sqlite_uint64 g_start; +static sqlite_uint64 g_elapsed; +#define TIMER_START g_start=sqlite3Hwtime() +#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start +#define TIMER_ELAPSED g_elapsed +#else +#define TIMER_START +#define TIMER_END +#define TIMER_ELAPSED ((sqlite_uint64)0) +#endif + +/* +** If we compile with the SQLITE_TEST macro set, then the following block +** of code will give us the ability to simulate a disk I/O error. This +** is used for testing the I/O recovery logic. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */ +SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */ +SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */ +SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */ +SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */ +SQLITE_API int sqlite3_diskfull_pending = 0; +SQLITE_API int sqlite3_diskfull = 0; +#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) +#define SimulateIOError(CODE) \ + if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ + || sqlite3_io_error_pending-- == 1 ) \ + { local_ioerr(); CODE; } +static void local_ioerr(){ + IOTRACE(("IOERR\n")); + sqlite3_io_error_hit++; + if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++; +} +#define SimulateDiskfullError(CODE) \ + if( sqlite3_diskfull_pending ){ \ + if( sqlite3_diskfull_pending == 1 ){ \ + local_ioerr(); \ + sqlite3_diskfull = 1; \ + sqlite3_io_error_hit = 1; \ + CODE; \ + }else{ \ + sqlite3_diskfull_pending--; \ + } \ + } +#else +#define SimulateIOErrorBenign(X) +#define SimulateIOError(A) +#define SimulateDiskfullError(A) +#endif + +/* +** When testing, keep a count of the number of open files. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_open_file_count = 0; +#define OpenCounter(X) sqlite3_open_file_count+=(X) +#else +#define OpenCounter(X) +#endif + +#endif /* !defined(_OS_COMMON_H_) */ + +/************** End of os_common.h *******************************************/ +/************** Continuing where we left off in mutex_w32.c ******************/ + +/* +** Include the header file for the Windows VFS. +*/ +/************** Include os_win.h in the middle of mutex_w32.c ****************/ +/************** Begin file os_win.h ******************************************/ +/* +** 2013 November 25 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains code that is specific to Windows. +*/ +#ifndef _OS_WIN_H_ +#define _OS_WIN_H_ + +/* +** Include the primary Windows SDK header file. +*/ +#include "windows.h" + +#ifdef __CYGWIN__ +# include +# include /* amalgamator: dontcache */ +#endif + +/* +** Determine if we are dealing with Windows NT. +** +** We ought to be able to determine if we are compiling for Windows 9x or +** Windows NT using the _WIN32_WINNT macro as follows: +** +** #if defined(_WIN32_WINNT) +** # define SQLITE_OS_WINNT 1 +** #else +** # define SQLITE_OS_WINNT 0 +** #endif +** +** However, Visual Studio 2005 does not set _WIN32_WINNT by default, as +** it ought to, so the above test does not work. We'll just assume that +** everything is Windows NT unless the programmer explicitly says otherwise +** by setting SQLITE_OS_WINNT to 0. +*/ +#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT) +# define SQLITE_OS_WINNT 1 +#endif + +/* +** Determine if we are dealing with Windows CE - which has a much reduced +** API. +*/ +#if defined(_WIN32_WCE) +# define SQLITE_OS_WINCE 1 +#else +# define SQLITE_OS_WINCE 0 +#endif + +/* +** Determine if we are dealing with WinRT, which provides only a subset of +** the full Win32 API. +*/ +#if !defined(SQLITE_OS_WINRT) +# define SQLITE_OS_WINRT 0 +#endif + +/* +** For WinCE, some API function parameters do not appear to be declared as +** volatile. +*/ +#if SQLITE_OS_WINCE +# define SQLITE_WIN32_VOLATILE +#else +# define SQLITE_WIN32_VOLATILE volatile +#endif + +/* +** For some Windows sub-platforms, the _beginthreadex() / _endthreadex() +** functions are not available (e.g. those not using MSVC, Cygwin, etc). +*/ +#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ + SQLITE_THREADSAFE>0 && !defined(__CYGWIN__) +# define SQLITE_OS_WIN_THREADS 1 +#else +# define SQLITE_OS_WIN_THREADS 0 +#endif + +#endif /* _OS_WIN_H_ */ + +/************** End of os_win.h **********************************************/ +/************** Continuing where we left off in mutex_w32.c ******************/ +#endif + +/* +** The code in this file is only used if we are compiling multithreaded +** on a Win32 system. +*/ +#ifdef SQLITE_MUTEX_W32 + +/* +** Each recursive mutex is an instance of the following structure. +*/ +struct sqlite3_mutex { + CRITICAL_SECTION mutex; /* Mutex controlling the lock */ + int id; /* Mutex type */ +#ifdef SQLITE_DEBUG + volatile int nRef; /* Number of enterances */ + volatile DWORD owner; /* Thread holding this mutex */ + volatile int trace; /* True to trace changes */ +#endif +}; + +/* +** These are the initializer values used when declaring a "static" mutex +** on Win32. It should be noted that all mutexes require initialization +** on the Win32 platform. +*/ +#define SQLITE_W32_MUTEX_INITIALIZER { 0 } + +#ifdef SQLITE_DEBUG +#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, \ + 0L, (DWORD)0, 0 } +#else +#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 } +#endif + +#ifdef SQLITE_DEBUG +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use only inside assert() statements. +*/ +static int winMutexHeld(sqlite3_mutex *p){ + return p->nRef!=0 && p->owner==GetCurrentThreadId(); +} + +static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){ + return p->nRef==0 || p->owner!=tid; +} + +static int winMutexNotheld(sqlite3_mutex *p){ + DWORD tid = GetCurrentThreadId(); + return winMutexNotheld2(p, tid); +} +#endif + +/* +** Initialize and deinitialize the mutex subsystem. +*/ +static sqlite3_mutex winMutex_staticMutexes[] = { + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER +}; + +static int winMutex_isInit = 0; +static int winMutex_isNt = -1; /* <0 means "need to query" */ + +/* As the winMutexInit() and winMutexEnd() functions are called as part +** of the sqlite3_initialize() and sqlite3_shutdown() processing, the +** "interlocked" magic used here is probably not strictly necessary. +*/ +static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0; + +SQLITE_API int SQLITE_STDCALL sqlite3_win32_is_nt(void); /* os_win.c */ +SQLITE_API void SQLITE_STDCALL sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ + +static int winMutexInit(void){ + /* The first to increment to 1 does actual initialization */ + if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){ + int i; + for(i=0; i +**
  • SQLITE_MUTEX_FAST +**
  • SQLITE_MUTEX_RECURSIVE +**
  • SQLITE_MUTEX_STATIC_MASTER +**
  • SQLITE_MUTEX_STATIC_MEM +**
  • SQLITE_MUTEX_STATIC_OPEN +**
  • SQLITE_MUTEX_STATIC_PRNG +**
  • SQLITE_MUTEX_STATIC_LRU +**
  • SQLITE_MUTEX_STATIC_PMEM +**
  • SQLITE_MUTEX_STATIC_APP1 +**
  • SQLITE_MUTEX_STATIC_APP2 +**
  • SQLITE_MUTEX_STATIC_APP3 +**
  • SQLITE_MUTEX_STATIC_VFS1 +**
  • SQLITE_MUTEX_STATIC_VFS2 +**
  • SQLITE_MUTEX_STATIC_VFS3 +** +** +** The first two constants cause sqlite3_mutex_alloc() to create +** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. But SQLite will only request a recursive mutex in +** cases where it really needs one. If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** The other allowed parameters to sqlite3_mutex_alloc() each return +** a pointer to a static preexisting mutex. Six static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +*/ +static sqlite3_mutex *winMutexAlloc(int iType){ + sqlite3_mutex *p; + + switch( iType ){ + case SQLITE_MUTEX_FAST: + case SQLITE_MUTEX_RECURSIVE: { + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ + p->id = iType; +#ifdef SQLITE_DEBUG +#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC + p->trace = 1; +#endif +#endif +#if SQLITE_OS_WINRT + InitializeCriticalSectionEx(&p->mutex, 0, 0); +#else + InitializeCriticalSection(&p->mutex); +#endif + } + break; + } + default: { +#ifdef SQLITE_ENABLE_API_ARMOR + if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + p = &winMutex_staticMutexes[iType-2]; + p->id = iType; +#ifdef SQLITE_DEBUG +#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC + p->trace = 1; +#endif +#endif + break; + } + } + return p; +} + + +/* +** This routine deallocates a previously +** allocated mutex. SQLite is careful to deallocate every +** mutex that it allocates. +*/ +static void winMutexFree(sqlite3_mutex *p){ + assert( p ); + assert( p->nRef==0 && p->owner==0 ); + if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){ + DeleteCriticalSection(&p->mutex); + sqlite3_free(p); + }else{ +#ifdef SQLITE_ENABLE_API_ARMOR + (void)SQLITE_MISUSE_BKPT; +#endif + } +} + +/* +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK +** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can +** be entered multiple times by the same thread. In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. If the same thread tries to enter any other kind of mutex +** more than once, the behavior is undefined. +*/ +static void winMutexEnter(sqlite3_mutex *p){ +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) + DWORD tid = GetCurrentThreadId(); +#endif +#ifdef SQLITE_DEBUG + assert( p ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); +#else + assert( p ); +#endif + assert( winMutex_isInit==1 ); + EnterCriticalSection(&p->mutex); +#ifdef SQLITE_DEBUG + assert( p->nRef>0 || p->owner==0 ); + p->owner = tid; + p->nRef++; + if( p->trace ){ + OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n", + tid, p, p->trace, p->nRef)); + } +#endif +} + +static int winMutexTry(sqlite3_mutex *p){ +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) + DWORD tid = GetCurrentThreadId(); +#endif + int rc = SQLITE_BUSY; + assert( p ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); + /* + ** The sqlite3_mutex_try() routine is very rarely used, and when it + ** is used it is merely an optimization. So it is OK for it to always + ** fail. + ** + ** The TryEnterCriticalSection() interface is only available on WinNT. + ** And some windows compilers complain if you try to use it without + ** first doing some #defines that prevent SQLite from building on Win98. + ** For that reason, we will omit this optimization for now. See + ** ticket #2685. + */ +#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 + assert( winMutex_isInit==1 ); + assert( winMutex_isNt>=-1 && winMutex_isNt<=1 ); + if( winMutex_isNt<0 ){ + winMutex_isNt = sqlite3_win32_is_nt(); + } + assert( winMutex_isNt==0 || winMutex_isNt==1 ); + if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){ +#ifdef SQLITE_DEBUG + p->owner = tid; + p->nRef++; +#endif + rc = SQLITE_OK; + } +#else + UNUSED_PARAMETER(p); +#endif +#ifdef SQLITE_DEBUG + if( p->trace ){ + OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n", + tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc))); + } +#endif + return rc; +} + +/* +** The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. The behavior +** is undefined if the mutex is not currently entered or +** is not currently allocated. SQLite will never do either. +*/ +static void winMutexLeave(sqlite3_mutex *p){ +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) + DWORD tid = GetCurrentThreadId(); +#endif + assert( p ); +#ifdef SQLITE_DEBUG + assert( p->nRef>0 ); + assert( p->owner==tid ); + p->nRef--; + if( p->nRef==0 ) p->owner = 0; + assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); +#endif + assert( winMutex_isInit==1 ); + LeaveCriticalSection(&p->mutex); +#ifdef SQLITE_DEBUG + if( p->trace ){ + OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n", + tid, p, p->trace, p->nRef)); + } +#endif +} + +SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ + static const sqlite3_mutex_methods sMutex = { + winMutexInit, + winMutexEnd, + winMutexAlloc, + winMutexFree, + winMutexEnter, + winMutexTry, + winMutexLeave, +#ifdef SQLITE_DEBUG + winMutexHeld, + winMutexNotheld +#else + 0, + 0 +#endif + }; + return &sMutex; +} + +#endif /* SQLITE_MUTEX_W32 */ + +/************** End of mutex_w32.c *******************************************/ +/************** Begin file malloc.c ******************************************/ +/* +** 2001 September 15 +** +** 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. +** +************************************************************************* +** +** Memory allocation functions used throughout sqlite. +*/ +/* #include "sqliteInt.h" */ +/* #include */ + +/* +** Attempt to release up to n bytes of non-essential memory currently +** held by SQLite. An example of non-essential memory is memory used to +** cache database pages that are not currently in use. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int n){ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + return sqlite3PcacheReleaseMemory(n); +#else + /* IMPLEMENTATION-OF: R-34391-24921 The sqlite3_release_memory() routine + ** is a no-op returning zero if SQLite is not compiled with + ** SQLITE_ENABLE_MEMORY_MANAGEMENT. */ + UNUSED_PARAMETER(n); + return 0; +#endif +} + +/* +** An instance of the following object records the location of +** each unused scratch buffer. +*/ +typedef struct ScratchFreeslot { + struct ScratchFreeslot *pNext; /* Next unused scratch buffer */ +} ScratchFreeslot; + +/* +** State information local to the memory allocation subsystem. +*/ +static SQLITE_WSD struct Mem0Global { + sqlite3_mutex *mutex; /* Mutex to serialize access */ + + /* + ** The alarm callback and its arguments. The mem0.mutex lock will + ** be held while the callback is running. Recursive calls into + ** the memory subsystem are allowed, but no new callbacks will be + ** issued. + */ + sqlite3_int64 alarmThreshold; + void (*alarmCallback)(void*, sqlite3_int64,int); + void *alarmArg; + + /* + ** Pointers to the end of sqlite3GlobalConfig.pScratch memory + ** (so that a range test can be used to determine if an allocation + ** being freed came from pScratch) and a pointer to the list of + ** unused scratch allocations. + */ + void *pScratchEnd; + ScratchFreeslot *pScratchFree; + u32 nScratchFree; + + /* + ** True if heap is nearly "full" where "full" is defined by the + ** sqlite3_soft_heap_limit() setting. + */ + int nearlyFull; +} mem0 = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +#define mem0 GLOBAL(struct Mem0Global, mem0) + +/* +** Return the memory allocator mutex. sqlite3_status() needs it. +*/ +SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void){ + return mem0.mutex; +} + +/* +** This routine runs when the memory allocator sees that the +** total memory allocation is about to exceed the soft heap +** limit. +*/ +static void softHeapLimitEnforcer( + void *NotUsed, + sqlite3_int64 NotUsed2, + int allocSize +){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); + sqlite3_release_memory(allocSize); +} + +/* +** Change the alarm callback +*/ +static int sqlite3MemoryAlarm( + void(*xCallback)(void *pArg, sqlite3_int64 used,int N), + void *pArg, + sqlite3_int64 iThreshold +){ + sqlite3_int64 nUsed; + sqlite3_mutex_enter(mem0.mutex); + mem0.alarmCallback = xCallback; + mem0.alarmArg = pArg; + mem0.alarmThreshold = iThreshold; + nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); + mem0.nearlyFull = (iThreshold>0 && iThreshold<=nUsed); + sqlite3_mutex_leave(mem0.mutex); + return SQLITE_OK; +} + +#ifndef SQLITE_OMIT_DEPRECATED +/* +** Deprecated external interface. Internal/core SQLite code +** should call sqlite3MemoryAlarm. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_memory_alarm( + void(*xCallback)(void *pArg, sqlite3_int64 used,int N), + void *pArg, + sqlite3_int64 iThreshold +){ + return sqlite3MemoryAlarm(xCallback, pArg, iThreshold); +} +#endif + +/* +** Set the soft heap-size limit for the library. Passing a zero or +** negative value indicates no limit. +*/ +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 n){ + sqlite3_int64 priorLimit; + sqlite3_int64 excess; +#ifndef SQLITE_OMIT_AUTOINIT + int rc = sqlite3_initialize(); + if( rc ) return -1; +#endif + sqlite3_mutex_enter(mem0.mutex); + priorLimit = mem0.alarmThreshold; + sqlite3_mutex_leave(mem0.mutex); + if( n<0 ) return priorLimit; + if( n>0 ){ + sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, n); + }else{ + sqlite3MemoryAlarm(0, 0, 0); + } + excess = sqlite3_memory_used() - n; + if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff)); + return priorLimit; +} +SQLITE_API void SQLITE_STDCALL sqlite3_soft_heap_limit(int n){ + if( n<0 ) n = 0; + sqlite3_soft_heap_limit64(n); +} + +/* +** Initialize the memory allocation subsystem. +*/ +SQLITE_PRIVATE int sqlite3MallocInit(void){ + int rc; + if( sqlite3GlobalConfig.m.xMalloc==0 ){ + sqlite3MemSetDefault(); + } + memset(&mem0, 0, sizeof(mem0)); + if( sqlite3GlobalConfig.bCoreMutex ){ + mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + } + if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100 + && sqlite3GlobalConfig.nScratch>0 ){ + int i, n, sz; + ScratchFreeslot *pSlot; + sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch); + sqlite3GlobalConfig.szScratch = sz; + pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch; + n = sqlite3GlobalConfig.nScratch; + mem0.pScratchFree = pSlot; + mem0.nScratchFree = n; + for(i=0; ipNext = (ScratchFreeslot*)(sz+(char*)pSlot); + pSlot = pSlot->pNext; + } + pSlot->pNext = 0; + mem0.pScratchEnd = (void*)&pSlot[1]; + }else{ + mem0.pScratchEnd = 0; + sqlite3GlobalConfig.pScratch = 0; + sqlite3GlobalConfig.szScratch = 0; + sqlite3GlobalConfig.nScratch = 0; + } + if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512 + || sqlite3GlobalConfig.nPage<=0 ){ + sqlite3GlobalConfig.pPage = 0; + sqlite3GlobalConfig.szPage = 0; + } + rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData); + if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0)); + return rc; +} + +/* +** Return true if the heap is currently under memory pressure - in other +** words if the amount of heap used is close to the limit set by +** sqlite3_soft_heap_limit(). +*/ +SQLITE_PRIVATE int sqlite3HeapNearlyFull(void){ + return mem0.nearlyFull; +} + +/* +** Deinitialize the memory allocation subsystem. +*/ +SQLITE_PRIVATE void sqlite3MallocEnd(void){ + if( sqlite3GlobalConfig.m.xShutdown ){ + sqlite3GlobalConfig.m.xShutdown(sqlite3GlobalConfig.m.pAppData); + } + memset(&mem0, 0, sizeof(mem0)); +} + +/* +** Return the amount of memory currently checked out. +*/ +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void){ + sqlite3_int64 res, mx; + sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, 0); + return res; +} + +/* +** Return the maximum amount of memory that has ever been +** checked out since either the beginning of this process +** or since the most recent reset. +*/ +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag){ + sqlite3_int64 res, mx; + sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, resetFlag); + return mx; +} + +/* +** Trigger the alarm +*/ +static void sqlite3MallocAlarm(int nByte){ + void (*xCallback)(void*,sqlite3_int64,int); + sqlite3_int64 nowUsed; + void *pArg; + if( mem0.alarmCallback==0 ) return; + xCallback = mem0.alarmCallback; + nowUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); + pArg = mem0.alarmArg; + mem0.alarmCallback = 0; + sqlite3_mutex_leave(mem0.mutex); + xCallback(pArg, nowUsed, nByte); + sqlite3_mutex_enter(mem0.mutex); + mem0.alarmCallback = xCallback; + mem0.alarmArg = pArg; +} + +/* +** Do a memory allocation with statistics and alarms. Assume the +** lock is already held. +*/ +static int mallocWithAlarm(int n, void **pp){ + int nFull; + void *p; + assert( sqlite3_mutex_held(mem0.mutex) ); + nFull = sqlite3GlobalConfig.m.xRoundup(n); + sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n); + if( mem0.alarmCallback!=0 ){ + sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); + if( nUsed >= mem0.alarmThreshold - nFull ){ + mem0.nearlyFull = 1; + sqlite3MallocAlarm(nFull); + }else{ + mem0.nearlyFull = 0; + } + } + p = sqlite3GlobalConfig.m.xMalloc(nFull); +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + if( p==0 && mem0.alarmCallback ){ + sqlite3MallocAlarm(nFull); + p = sqlite3GlobalConfig.m.xMalloc(nFull); + } +#endif + if( p ){ + nFull = sqlite3MallocSize(p); + sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull); + sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1); + } + *pp = p; + return nFull; +} + +/* +** Allocate memory. This routine is like sqlite3_malloc() except that it +** assumes the memory subsystem has already been initialized. +*/ +SQLITE_PRIVATE void *sqlite3Malloc(u64 n){ + void *p; + if( n==0 || n>=0x7fffff00 ){ + /* A memory allocation of a number of bytes which is near the maximum + ** signed integer value might cause an integer overflow inside of the + ** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving + ** 255 bytes of overhead. SQLite itself will never use anything near + ** this amount. The only way to reach the limit is with sqlite3_malloc() */ + p = 0; + }else if( sqlite3GlobalConfig.bMemstat ){ + sqlite3_mutex_enter(mem0.mutex); + mallocWithAlarm((int)n, &p); + sqlite3_mutex_leave(mem0.mutex); + }else{ + p = sqlite3GlobalConfig.m.xMalloc((int)n); + } + assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-11148-40995 */ + return p; +} + +/* +** This version of the memory allocation is for use by the application. +** First make sure the memory subsystem is initialized, then do the +** allocation. +*/ +SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int n){ +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return n<=0 ? 0 : sqlite3Malloc(n); +} +SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64 n){ +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return sqlite3Malloc(n); +} + +/* +** Each thread may only have a single outstanding allocation from +** xScratchMalloc(). We verify this constraint in the single-threaded +** case by setting scratchAllocOut to 1 when an allocation +** is outstanding clearing it when the allocation is freed. +*/ +#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) +static int scratchAllocOut = 0; +#endif + + +/* +** Allocate memory that is to be used and released right away. +** This routine is similar to alloca() in that it is not intended +** for situations where the memory might be held long-term. This +** routine is intended to get memory to old large transient data +** structures that would not normally fit on the stack of an +** embedded processor. +*/ +SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){ + void *p; + assert( n>0 ); + + sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); + if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){ + p = mem0.pScratchFree; + mem0.pScratchFree = mem0.pScratchFree->pNext; + mem0.nScratchFree--; + sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1); + sqlite3_mutex_leave(mem0.mutex); + }else{ + sqlite3_mutex_leave(mem0.mutex); + p = sqlite3Malloc(n); + if( sqlite3GlobalConfig.bMemstat && p ){ + sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p)); + sqlite3_mutex_leave(mem0.mutex); + } + sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH); + } + assert( sqlite3_mutex_notheld(mem0.mutex) ); + + +#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) + /* EVIDENCE-OF: R-12970-05880 SQLite will not use more than one scratch + ** buffers per thread. + ** + ** This can only be checked in single-threaded mode. + */ + assert( scratchAllocOut==0 ); + if( p ) scratchAllocOut++; +#endif + + return p; +} +SQLITE_PRIVATE void sqlite3ScratchFree(void *p){ + if( p ){ + +#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) + /* Verify that no more than two scratch allocation per thread + ** is outstanding at one time. (This is only checked in the + ** single-threaded case since checking in the multi-threaded case + ** would be much more complicated.) */ + assert( scratchAllocOut>=1 && scratchAllocOut<=2 ); + scratchAllocOut--; +#endif + + if( p>=sqlite3GlobalConfig.pScratch && ppNext = mem0.pScratchFree; + mem0.pScratchFree = pSlot; + mem0.nScratchFree++; + assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch ); + sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1); + sqlite3_mutex_leave(mem0.mutex); + }else{ + /* Release memory back to the heap */ + assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) ); + assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_SCRATCH) ); + sqlite3MemdebugSetType(p, MEMTYPE_HEAP); + if( sqlite3GlobalConfig.bMemstat ){ + int iSize = sqlite3MallocSize(p); + sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize); + sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize); + sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1); + sqlite3GlobalConfig.m.xFree(p); + sqlite3_mutex_leave(mem0.mutex); + }else{ + sqlite3GlobalConfig.m.xFree(p); + } + } + } +} + +/* +** TRUE if p is a lookaside memory allocation from db +*/ +#ifndef SQLITE_OMIT_LOOKASIDE +static int isLookaside(sqlite3 *db, void *p){ + return p>=db->lookaside.pStart && plookaside.pEnd; +} +#else +#define isLookaside(A,B) 0 +#endif + +/* +** Return the size of a memory allocation previously obtained from +** sqlite3Malloc() or sqlite3_malloc(). +*/ +SQLITE_PRIVATE int sqlite3MallocSize(void *p){ + assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); + return sqlite3GlobalConfig.m.xSize(p); +} +SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){ + if( db==0 ){ + assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); + assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); + return sqlite3MallocSize(p); + }else{ + assert( sqlite3_mutex_held(db->mutex) ); + if( isLookaside(db, p) ){ + return db->lookaside.sz; + }else{ + assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + return sqlite3GlobalConfig.m.xSize(p); + } + } +} +SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void *p){ + assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); + assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); + return (sqlite3_uint64)sqlite3GlobalConfig.m.xSize(p); +} + +/* +** Free memory previously obtained from sqlite3Malloc(). +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_free(void *p){ + if( p==0 ) return; /* IMP: R-49053-54554 */ + assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); + assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); + if( sqlite3GlobalConfig.bMemstat ){ + sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p)); + sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1); + sqlite3GlobalConfig.m.xFree(p); + sqlite3_mutex_leave(mem0.mutex); + }else{ + sqlite3GlobalConfig.m.xFree(p); + } +} + +/* +** Add the size of memory allocation "p" to the count in +** *db->pnBytesFreed. +*/ +static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){ + *db->pnBytesFreed += sqlite3DbMallocSize(db,p); +} + +/* +** Free memory that might be associated with a particular database +** connection. +*/ +SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){ + assert( db==0 || sqlite3_mutex_held(db->mutex) ); + if( p==0 ) return; + if( db ){ + if( db->pnBytesFreed ){ + measureAllocationSize(db, p); + return; + } + if( isLookaside(db, p) ){ + LookasideSlot *pBuf = (LookasideSlot*)p; +#if SQLITE_DEBUG + /* Trash all content in the buffer being freed */ + memset(p, 0xaa, db->lookaside.sz); +#endif + pBuf->pNext = db->lookaside.pFree; + db->lookaside.pFree = pBuf; + db->lookaside.nOut--; + return; + } + } + assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); + sqlite3MemdebugSetType(p, MEMTYPE_HEAP); + sqlite3_free(p); +} + +/* +** Change the size of an existing memory allocation +*/ +SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){ + int nOld, nNew, nDiff; + void *pNew; + assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) ); + assert( sqlite3MemdebugNoType(pOld, (u8)~MEMTYPE_HEAP) ); + if( pOld==0 ){ + return sqlite3Malloc(nBytes); /* IMP: R-04300-56712 */ + } + if( nBytes==0 ){ + sqlite3_free(pOld); /* IMP: R-26507-47431 */ + return 0; + } + if( nBytes>=0x7fffff00 ){ + /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */ + return 0; + } + nOld = sqlite3MallocSize(pOld); + /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second + ** argument to xRealloc is always a value returned by a prior call to + ** xRoundup. */ + nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes); + if( nOld==nNew ){ + pNew = pOld; + }else if( sqlite3GlobalConfig.bMemstat ){ + sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes); + nDiff = nNew - nOld; + if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= + mem0.alarmThreshold-nDiff ){ + sqlite3MallocAlarm(nDiff); + } + pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); + if( pNew==0 && mem0.alarmCallback ){ + sqlite3MallocAlarm((int)nBytes); + pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); + } + if( pNew ){ + nNew = sqlite3MallocSize(pNew); + sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld); + } + sqlite3_mutex_leave(mem0.mutex); + }else{ + pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); + } + assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-11148-40995 */ + return pNew; +} + +/* +** The public interface to sqlite3Realloc. Make sure that the memory +** subsystem is initialized prior to invoking sqliteRealloc. +*/ +SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void *pOld, int n){ +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + if( n<0 ) n = 0; /* IMP: R-26507-47431 */ + return sqlite3Realloc(pOld, n); +} +SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void *pOld, sqlite3_uint64 n){ +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return sqlite3Realloc(pOld, n); +} + + +/* +** Allocate and zero memory. +*/ +SQLITE_PRIVATE void *sqlite3MallocZero(u64 n){ + void *p = sqlite3Malloc(n); + if( p ){ + memset(p, 0, (size_t)n); + } + return p; +} + +/* +** Allocate and zero memory. If the allocation fails, make +** the mallocFailed flag in the connection pointer. +*/ +SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, u64 n){ + void *p = sqlite3DbMallocRaw(db, n); + if( p ){ + memset(p, 0, (size_t)n); + } + return p; +} + +/* +** Allocate and zero memory. If the allocation fails, make +** the mallocFailed flag in the connection pointer. +** +** If db!=0 and db->mallocFailed is true (indicating a prior malloc +** failure on the same database connection) then always return 0. +** Hence for a particular database connection, once malloc starts +** failing, it fails consistently until mallocFailed is reset. +** This is an important assumption. There are many places in the +** code that do things like this: +** +** int *a = (int*)sqlite3DbMallocRaw(db, 100); +** int *b = (int*)sqlite3DbMallocRaw(db, 200); +** if( b ) a[10] = 9; +** +** In other words, if a subsequent malloc (ex: "b") worked, it is assumed +** that all prior mallocs (ex: "a") worked too. +*/ +SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ + void *p; + assert( db==0 || sqlite3_mutex_held(db->mutex) ); + assert( db==0 || db->pnBytesFreed==0 ); +#ifndef SQLITE_OMIT_LOOKASIDE + if( db ){ + LookasideSlot *pBuf; + if( db->mallocFailed ){ + return 0; + } + if( db->lookaside.bEnabled ){ + if( n>db->lookaside.sz ){ + db->lookaside.anStat[1]++; + }else if( (pBuf = db->lookaside.pFree)==0 ){ + db->lookaside.anStat[2]++; + }else{ + db->lookaside.pFree = pBuf->pNext; + db->lookaside.nOut++; + db->lookaside.anStat[0]++; + if( db->lookaside.nOut>db->lookaside.mxOut ){ + db->lookaside.mxOut = db->lookaside.nOut; + } + return (void*)pBuf; + } + } + } +#else + if( db && db->mallocFailed ){ + return 0; + } +#endif + p = sqlite3Malloc(n); + if( !p && db ){ + db->mallocFailed = 1; + } + sqlite3MemdebugSetType(p, + (db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); + return p; +} + +/* +** Resize the block of memory pointed to by p to n bytes. If the +** resize fails, set the mallocFailed flag in the connection object. +*/ +SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ + void *pNew = 0; + assert( db!=0 ); + assert( sqlite3_mutex_held(db->mutex) ); + if( db->mallocFailed==0 ){ + if( p==0 ){ + return sqlite3DbMallocRaw(db, n); + } + if( isLookaside(db, p) ){ + if( n<=db->lookaside.sz ){ + return p; + } + pNew = sqlite3DbMallocRaw(db, n); + if( pNew ){ + memcpy(pNew, p, db->lookaside.sz); + sqlite3DbFree(db, p); + } + }else{ + assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + sqlite3MemdebugSetType(p, MEMTYPE_HEAP); + pNew = sqlite3_realloc64(p, n); + if( !pNew ){ + db->mallocFailed = 1; + } + sqlite3MemdebugSetType(pNew, + (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); + } + } + return pNew; +} + +/* +** Attempt to reallocate p. If the reallocation fails, then free p +** and set the mallocFailed flag in the database connection. +*/ +SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, u64 n){ + void *pNew; + pNew = sqlite3DbRealloc(db, p, n); + if( !pNew ){ + sqlite3DbFree(db, p); + } + return pNew; +} + +/* +** Make a copy of a string in memory obtained from sqliteMalloc(). These +** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This +** is because when memory debugging is turned on, these two functions are +** called via macros that record the current file and line number in the +** ThreadData structure. +*/ +SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){ + char *zNew; + size_t n; + if( z==0 ){ + return 0; + } + n = sqlite3Strlen30(z) + 1; + assert( (n&0x7fffffff)==n ); + zNew = sqlite3DbMallocRaw(db, (int)n); + if( zNew ){ + memcpy(zNew, z, n); + } + return zNew; +} +SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ + char *zNew; + if( z==0 ){ + return 0; + } + assert( (n&0x7fffffff)==n ); + zNew = sqlite3DbMallocRaw(db, n+1); + if( zNew ){ + memcpy(zNew, z, (size_t)n); + zNew[n] = 0; + } + return zNew; +} + +/* +** Free any prior content in *pz and replace it with a copy of zNew. +*/ +SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ + sqlite3DbFree(db, *pz); + *pz = sqlite3DbStrDup(db, zNew); +} + +/* +** Take actions at the end of an API call to indicate an OOM error +*/ +static SQLITE_NOINLINE int apiOomError(sqlite3 *db){ + db->mallocFailed = 0; + sqlite3Error(db, SQLITE_NOMEM); + return SQLITE_NOMEM; +} + +/* +** This function must be called before exiting any API function (i.e. +** returning control to the user) that has called sqlite3_malloc or +** sqlite3_realloc. +** +** The returned value is normally a copy of the second argument to this +** function. However, if a malloc() failure has occurred since the previous +** invocation SQLITE_NOMEM is returned instead. +** +** If an OOM as occurred, then the connection error-code (the value +** returned by sqlite3_errcode()) is set to SQLITE_NOMEM. +*/ +SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){ + /* If the db handle must hold the connection handle mutex here. + ** Otherwise the read (and possible write) of db->mallocFailed + ** is unsafe, as is the call to sqlite3Error(). + */ + assert( db!=0 ); + assert( sqlite3_mutex_held(db->mutex) ); + if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){ + return apiOomError(db); + } + return rc & db->errMask; +} + +/************** End of malloc.c **********************************************/ +/************** Begin file printf.c ******************************************/ +/* +** The "printf" code that follows dates from the 1980's. It is in +** the public domain. +** +************************************************************************** +** +** This file contains code for a set of "printf"-like routines. These +** routines format strings much like the printf() from the standard C +** library, though the implementation here has enhancements to support +** SQLite. +*/ +/* #include "sqliteInt.h" */ + +/* +** Conversion types fall into various categories as defined by the +** following enumeration. +*/ +#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */ +#define etFLOAT 2 /* Floating point. %f */ +#define etEXP 3 /* Exponentional notation. %e and %E */ +#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */ +#define etSIZE 5 /* Return number of characters processed so far. %n */ +#define etSTRING 6 /* Strings. %s */ +#define etDYNSTRING 7 /* Dynamically allocated strings. %z */ +#define etPERCENT 8 /* Percent symbol. %% */ +#define etCHARX 9 /* Characters. %c */ +/* The rest are extensions, not normally found in printf() */ +#define etSQLESCAPE 10 /* Strings with '\'' doubled. %q */ +#define etSQLESCAPE2 11 /* Strings with '\'' doubled and enclosed in '', + NULL pointers replaced by SQL NULL. %Q */ +#define etTOKEN 12 /* a pointer to a Token structure */ +#define etSRCLIST 13 /* a pointer to a SrcList */ +#define etPOINTER 14 /* The %p conversion */ +#define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */ +#define etORDINAL 16 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ + +#define etINVALID 0 /* Any unrecognized conversion type */ + + +/* +** An "etByte" is an 8-bit unsigned value. +*/ +typedef unsigned char etByte; + +/* +** Each builtin conversion character (ex: the 'd' in "%d") is described +** by an instance of the following structure +*/ +typedef struct et_info { /* Information about each format field */ + char fmttype; /* The format field code letter */ + etByte base; /* The base for radix conversion */ + etByte flags; /* One or more of FLAG_ constants below */ + etByte type; /* Conversion paradigm */ + etByte charset; /* Offset into aDigits[] of the digits string */ + etByte prefix; /* Offset into aPrefix[] of the prefix string */ +} et_info; + +/* +** Allowed values for et_info.flags +*/ +#define FLAG_SIGNED 1 /* True if the value to convert is signed */ +#define FLAG_INTERN 2 /* True if for internal use only */ +#define FLAG_STRING 4 /* Allow infinity precision */ + + +/* +** The following table is searched linearly, so it is good to put the +** most frequently used conversion types first. +*/ +static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; +static const char aPrefix[] = "-x0\000X0"; +static const et_info fmtinfo[] = { + { 'd', 10, 1, etRADIX, 0, 0 }, + { 's', 0, 4, etSTRING, 0, 0 }, + { 'g', 0, 1, etGENERIC, 30, 0 }, + { 'z', 0, 4, etDYNSTRING, 0, 0 }, + { 'q', 0, 4, etSQLESCAPE, 0, 0 }, + { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, + { 'w', 0, 4, etSQLESCAPE3, 0, 0 }, + { 'c', 0, 0, etCHARX, 0, 0 }, + { 'o', 8, 0, etRADIX, 0, 2 }, + { 'u', 10, 0, etRADIX, 0, 0 }, + { 'x', 16, 0, etRADIX, 16, 1 }, + { 'X', 16, 0, etRADIX, 0, 4 }, +#ifndef SQLITE_OMIT_FLOATING_POINT + { 'f', 0, 1, etFLOAT, 0, 0 }, + { 'e', 0, 1, etEXP, 30, 0 }, + { 'E', 0, 1, etEXP, 14, 0 }, + { 'G', 0, 1, etGENERIC, 14, 0 }, +#endif + { 'i', 10, 1, etRADIX, 0, 0 }, + { 'n', 0, 0, etSIZE, 0, 0 }, + { '%', 0, 0, etPERCENT, 0, 0 }, + { 'p', 16, 0, etPOINTER, 0, 1 }, + +/* All the rest have the FLAG_INTERN bit set and are thus for internal +** use only */ + { 'T', 0, 2, etTOKEN, 0, 0 }, + { 'S', 0, 2, etSRCLIST, 0, 0 }, + { 'r', 10, 3, etORDINAL, 0, 0 }, +}; + +/* +** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point +** conversions will work. +*/ +#ifndef SQLITE_OMIT_FLOATING_POINT +/* +** "*val" is a double such that 0.1 <= *val < 10.0 +** Return the ascii code for the leading digit of *val, then +** multiply "*val" by 10.0 to renormalize. +** +** Example: +** input: *val = 3.14159 +** output: *val = 1.4159 function return = '3' +** +** The counter *cnt is incremented each time. After counter exceeds +** 16 (the number of significant digits in a 64-bit float) '0' is +** always returned. +*/ +static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ + int digit; + LONGDOUBLE_TYPE d; + if( (*cnt)<=0 ) return '0'; + (*cnt)--; + digit = (int)*val; + d = digit; + digit += '0'; + *val = (*val - d)*10.0; + return (char)digit; +} +#endif /* SQLITE_OMIT_FLOATING_POINT */ + +/* +** Set the StrAccum object to an error mode. +*/ +static void setStrAccumError(StrAccum *p, u8 eError){ + assert( eError==STRACCUM_NOMEM || eError==STRACCUM_TOOBIG ); + p->accError = eError; + p->nAlloc = 0; +} + +/* +** Extra argument values from a PrintfArguments object +*/ +static sqlite3_int64 getIntArg(PrintfArguments *p){ + if( p->nArg<=p->nUsed ) return 0; + return sqlite3_value_int64(p->apArg[p->nUsed++]); +} +static double getDoubleArg(PrintfArguments *p){ + if( p->nArg<=p->nUsed ) return 0.0; + return sqlite3_value_double(p->apArg[p->nUsed++]); +} +static char *getTextArg(PrintfArguments *p){ + if( p->nArg<=p->nUsed ) return 0; + return (char*)sqlite3_value_text(p->apArg[p->nUsed++]); +} + + +/* +** On machines with a small stack size, you can redefine the +** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired. +*/ +#ifndef SQLITE_PRINT_BUF_SIZE +# define SQLITE_PRINT_BUF_SIZE 70 +#endif +#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */ + +/* +** Render a string given by "fmt" into the StrAccum object. +*/ +SQLITE_PRIVATE void sqlite3VXPrintf( + StrAccum *pAccum, /* Accumulate results here */ + u32 bFlags, /* SQLITE_PRINTF_* flags */ + const char *fmt, /* Format string */ + va_list ap /* arguments */ +){ + int c; /* Next character in the format string */ + char *bufpt; /* Pointer to the conversion buffer */ + int precision; /* Precision of the current field */ + int length; /* Length of the field */ + int idx; /* A general purpose loop counter */ + int width; /* Width of the current field */ + etByte flag_leftjustify; /* True if "-" flag is present */ + etByte flag_plussign; /* True if "+" flag is present */ + etByte flag_blanksign; /* True if " " flag is present */ + etByte flag_alternateform; /* True if "#" flag is present */ + etByte flag_altform2; /* True if "!" flag is present */ + etByte flag_zeropad; /* True if field width constant starts with zero */ + etByte flag_long; /* True if "l" flag is present */ + etByte flag_longlong; /* True if the "ll" flag is present */ + etByte done; /* Loop termination flag */ + etByte xtype = 0; /* Conversion paradigm */ + u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ + u8 useIntern; /* Ok to use internal conversions (ex: %T) */ + char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ + sqlite_uint64 longvalue; /* Value for integer types */ + LONGDOUBLE_TYPE realvalue; /* Value for real types */ + const et_info *infop; /* Pointer to the appropriate info structure */ + char *zOut; /* Rendering buffer */ + int nOut; /* Size of the rendering buffer */ + char *zExtra = 0; /* Malloced memory used by some conversion */ +#ifndef SQLITE_OMIT_FLOATING_POINT + int exp, e2; /* exponent of real numbers */ + int nsd; /* Number of significant digits returned */ + double rounder; /* Used for rounding floating point values */ + etByte flag_dp; /* True if decimal point should be shown */ + etByte flag_rtz; /* True if trailing zeros should be removed */ +#endif + PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ + char buf[etBUFSIZE]; /* Conversion buffer */ + + bufpt = 0; + if( bFlags ){ + if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ + pArgList = va_arg(ap, PrintfArguments*); + } + useIntern = bFlags & SQLITE_PRINTF_INTERNAL; + }else{ + bArgList = useIntern = 0; + } + for(; (c=(*fmt))!=0; ++fmt){ + if( c!='%' ){ + bufpt = (char *)fmt; +#if HAVE_STRCHRNUL + fmt = strchrnul(fmt, '%'); +#else + do{ fmt++; }while( *fmt && *fmt != '%' ); +#endif + sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt)); + if( *fmt==0 ) break; + } + if( (c=(*++fmt))==0 ){ + sqlite3StrAccumAppend(pAccum, "%", 1); + break; + } + /* Find out what flags are present */ + flag_leftjustify = flag_plussign = flag_blanksign = + flag_alternateform = flag_altform2 = flag_zeropad = 0; + done = 0; + do{ + switch( c ){ + case '-': flag_leftjustify = 1; break; + case '+': flag_plussign = 1; break; + case ' ': flag_blanksign = 1; break; + case '#': flag_alternateform = 1; break; + case '!': flag_altform2 = 1; break; + case '0': flag_zeropad = 1; break; + default: done = 1; break; + } + }while( !done && (c=(*++fmt))!=0 ); + /* Get the field width */ + if( c=='*' ){ + if( bArgList ){ + width = (int)getIntArg(pArgList); + }else{ + width = va_arg(ap,int); + } + if( width<0 ){ + flag_leftjustify = 1; + width = width >= -2147483647 ? -width : 0; + } + c = *++fmt; + }else{ + unsigned wx = 0; + while( c>='0' && c<='9' ){ + wx = wx*10 + c - '0'; + c = *++fmt; + } + testcase( wx>0x7fffffff ); + width = wx & 0x7fffffff; + } + + /* Get the precision */ + if( c=='.' ){ + c = *++fmt; + if( c=='*' ){ + if( bArgList ){ + precision = (int)getIntArg(pArgList); + }else{ + precision = va_arg(ap,int); + } + c = *++fmt; + if( precision<0 ){ + precision = precision >= -2147483647 ? -precision : -1; + } + }else{ + unsigned px = 0; + while( c>='0' && c<='9' ){ + px = px*10 + c - '0'; + c = *++fmt; + } + testcase( px>0x7fffffff ); + precision = px & 0x7fffffff; + } + }else{ + precision = -1; + } + /* Get the conversion type modifier */ + if( c=='l' ){ + flag_long = 1; + c = *++fmt; + if( c=='l' ){ + flag_longlong = 1; + c = *++fmt; + }else{ + flag_longlong = 0; + } + }else{ + flag_long = flag_longlong = 0; + } + /* Fetch the info entry for the field */ + infop = &fmtinfo[0]; + xtype = etINVALID; + for(idx=0; idxflags & FLAG_INTERN)==0 ){ + xtype = infop->type; + }else{ + return; + } + break; + } + } + + /* + ** At this point, variables are initialized as follows: + ** + ** flag_alternateform TRUE if a '#' is present. + ** flag_altform2 TRUE if a '!' is present. + ** flag_plussign TRUE if a '+' is present. + ** flag_leftjustify TRUE if a '-' is present or if the + ** field width was negative. + ** flag_zeropad TRUE if the width began with 0. + ** flag_long TRUE if the letter 'l' (ell) prefixed + ** the conversion character. + ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed + ** the conversion character. + ** flag_blanksign TRUE if a ' ' is present. + ** width The specified field width. This is + ** always non-negative. Zero is the default. + ** precision The specified precision. The default + ** is -1. + ** xtype The class of the conversion. + ** infop Pointer to the appropriate info struct. + */ + switch( xtype ){ + case etPOINTER: + flag_longlong = sizeof(char*)==sizeof(i64); + flag_long = sizeof(char*)==sizeof(long int); + /* Fall through into the next case */ + case etORDINAL: + case etRADIX: + if( infop->flags & FLAG_SIGNED ){ + i64 v; + if( bArgList ){ + v = getIntArg(pArgList); + }else if( flag_longlong ){ + v = va_arg(ap,i64); + }else if( flag_long ){ + v = va_arg(ap,long int); + }else{ + v = va_arg(ap,int); + } + if( v<0 ){ + if( v==SMALLEST_INT64 ){ + longvalue = ((u64)1)<<63; + }else{ + longvalue = -v; + } + prefix = '-'; + }else{ + longvalue = v; + if( flag_plussign ) prefix = '+'; + else if( flag_blanksign ) prefix = ' '; + else prefix = 0; + } + }else{ + if( bArgList ){ + longvalue = (u64)getIntArg(pArgList); + }else if( flag_longlong ){ + longvalue = va_arg(ap,u64); + }else if( flag_long ){ + longvalue = va_arg(ap,unsigned long int); + }else{ + longvalue = va_arg(ap,unsigned int); + } + prefix = 0; + } + if( longvalue==0 ) flag_alternateform = 0; + if( flag_zeropad && precision=4 || (longvalue/10)%10==1 ){ + x = 0; + } + *(--bufpt) = zOrd[x*2+1]; + *(--bufpt) = zOrd[x*2]; + } + { + const char *cset = &aDigits[infop->charset]; + u8 base = infop->base; + do{ /* Convert to ascii */ + *(--bufpt) = cset[longvalue%base]; + longvalue = longvalue/base; + }while( longvalue>0 ); + } + length = (int)(&zOut[nOut-1]-bufpt); + for(idx=precision-length; idx>0; idx--){ + *(--bufpt) = '0'; /* Zero pad */ + } + if( prefix ) *(--bufpt) = prefix; /* Add sign */ + if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ + const char *pre; + char x; + pre = &aPrefix[infop->prefix]; + for(; (x=(*pre))!=0; pre++) *(--bufpt) = x; + } + length = (int)(&zOut[nOut-1]-bufpt); + break; + case etFLOAT: + case etEXP: + case etGENERIC: + if( bArgList ){ + realvalue = getDoubleArg(pArgList); + }else{ + realvalue = va_arg(ap,double); + } +#ifdef SQLITE_OMIT_FLOATING_POINT + length = 0; +#else + if( precision<0 ) precision = 6; /* Set default precision */ + if( realvalue<0.0 ){ + realvalue = -realvalue; + prefix = '-'; + }else{ + if( flag_plussign ) prefix = '+'; + else if( flag_blanksign ) prefix = ' '; + else prefix = 0; + } + if( xtype==etGENERIC && precision>0 ) precision--; + testcase( precision>0xfff ); + for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){} + if( xtype==etFLOAT ) realvalue += rounder; + /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ + exp = 0; + if( sqlite3IsNaN((double)realvalue) ){ + bufpt = "NaN"; + length = 3; + break; + } + if( realvalue>0.0 ){ + LONGDOUBLE_TYPE scale = 1.0; + while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;} + while( realvalue>=1e64*scale && exp<=350 ){ scale *= 1e64; exp+=64; } + while( realvalue>=1e8*scale && exp<=350 ){ scale *= 1e8; exp+=8; } + while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; } + realvalue /= scale; + while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; } + while( realvalue<1.0 ){ realvalue *= 10.0; exp--; } + if( exp>350 ){ + if( prefix=='-' ){ + bufpt = "-Inf"; + }else if( prefix=='+' ){ + bufpt = "+Inf"; + }else{ + bufpt = "Inf"; + } + length = sqlite3Strlen30(bufpt); + break; + } + } + bufpt = buf; + /* + ** If the field type is etGENERIC, then convert to either etEXP + ** or etFLOAT, as appropriate. + */ + if( xtype!=etFLOAT ){ + realvalue += rounder; + if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } + } + if( xtype==etGENERIC ){ + flag_rtz = !flag_alternateform; + if( exp<-4 || exp>precision ){ + xtype = etEXP; + }else{ + precision = precision - exp; + xtype = etFLOAT; + } + }else{ + flag_rtz = flag_altform2; + } + if( xtype==etEXP ){ + e2 = 0; + }else{ + e2 = exp; + } + if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){ + bufpt = zExtra + = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 ); + if( bufpt==0 ){ + setStrAccumError(pAccum, STRACCUM_NOMEM); + return; + } + } + zOut = bufpt; + nsd = 16 + flag_altform2*10; + flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2; + /* The sign in front of the number */ + if( prefix ){ + *(bufpt++) = prefix; + } + /* Digits prior to the decimal point */ + if( e2<0 ){ + *(bufpt++) = '0'; + }else{ + for(; e2>=0; e2--){ + *(bufpt++) = et_getdigit(&realvalue,&nsd); + } + } + /* The decimal point */ + if( flag_dp ){ + *(bufpt++) = '.'; + } + /* "0" digits after the decimal point but before the first + ** significant digit of the number */ + for(e2++; e2<0; precision--, e2++){ + assert( precision>0 ); + *(bufpt++) = '0'; + } + /* Significant digits after the decimal point */ + while( (precision--)>0 ){ + *(bufpt++) = et_getdigit(&realvalue,&nsd); + } + /* Remove trailing zeros and the "." if no digits follow the "." */ + if( flag_rtz && flag_dp ){ + while( bufpt[-1]=='0' ) *(--bufpt) = 0; + assert( bufpt>zOut ); + if( bufpt[-1]=='.' ){ + if( flag_altform2 ){ + *(bufpt++) = '0'; + }else{ + *(--bufpt) = 0; + } + } + } + /* Add the "eNNN" suffix */ + if( xtype==etEXP ){ + *(bufpt++) = aDigits[infop->charset]; + if( exp<0 ){ + *(bufpt++) = '-'; exp = -exp; + }else{ + *(bufpt++) = '+'; + } + if( exp>=100 ){ + *(bufpt++) = (char)((exp/100)+'0'); /* 100's digit */ + exp %= 100; + } + *(bufpt++) = (char)(exp/10+'0'); /* 10's digit */ + *(bufpt++) = (char)(exp%10+'0'); /* 1's digit */ + } + *bufpt = 0; + + /* The converted number is in buf[] and zero terminated. Output it. + ** Note that the number is in the usual order, not reversed as with + ** integer conversions. */ + length = (int)(bufpt-zOut); + bufpt = zOut; + + /* Special case: Add leading zeros if the flag_zeropad flag is + ** set and we are not left justified */ + if( flag_zeropad && !flag_leftjustify && length < width){ + int i; + int nPad = width - length; + for(i=width; i>=nPad; i--){ + bufpt[i] = bufpt[i-nPad]; + } + i = prefix!=0; + while( nPad-- ) bufpt[i++] = '0'; + length = width; + } +#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */ + break; + case etSIZE: + if( !bArgList ){ + *(va_arg(ap,int*)) = pAccum->nChar; + } + length = width = 0; + break; + case etPERCENT: + buf[0] = '%'; + bufpt = buf; + length = 1; + break; + case etCHARX: + if( bArgList ){ + bufpt = getTextArg(pArgList); + c = bufpt ? bufpt[0] : 0; + }else{ + c = va_arg(ap,int); + } + if( precision>1 ){ + width -= precision-1; + if( width>1 && !flag_leftjustify ){ + sqlite3AppendChar(pAccum, width-1, ' '); + width = 0; + } + sqlite3AppendChar(pAccum, precision-1, c); + } + length = 1; + buf[0] = c; + bufpt = buf; + break; + case etSTRING: + case etDYNSTRING: + if( bArgList ){ + bufpt = getTextArg(pArgList); + }else{ + bufpt = va_arg(ap,char*); + } + if( bufpt==0 ){ + bufpt = ""; + }else if( xtype==etDYNSTRING && !bArgList ){ + zExtra = bufpt; + } + if( precision>=0 ){ + for(length=0; lengthetBUFSIZE ){ + bufpt = zExtra = sqlite3Malloc( n ); + if( bufpt==0 ){ + setStrAccumError(pAccum, STRACCUM_NOMEM); + return; + } + }else{ + bufpt = buf; + } + j = 0; + if( needQuote ) bufpt[j++] = q; + k = i; + for(i=0; i=0 && precisionn ){ + sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n); + } + length = width = 0; + break; + } + case etSRCLIST: { + SrcList *pSrc = va_arg(ap, SrcList*); + int k = va_arg(ap, int); + struct SrcList_item *pItem = &pSrc->a[k]; + assert( bArgList==0 ); + assert( k>=0 && knSrc ); + if( pItem->zDatabase ){ + sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase); + sqlite3StrAccumAppend(pAccum, ".", 1); + } + sqlite3StrAccumAppendAll(pAccum, pItem->zName); + length = width = 0; + break; + } + default: { + assert( xtype==etINVALID ); + return; + } + }/* End switch over the format type */ + /* + ** The text of the conversion is pointed to by "bufpt" and is + ** "length" characters long. The field width is "width". Do + ** the output. + */ + width -= length; + if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); + sqlite3StrAccumAppend(pAccum, bufpt, length); + if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); + + if( zExtra ){ + sqlite3_free(zExtra); + zExtra = 0; + } + }/* End for loop over the format string */ +} /* End of function */ + +/* +** Enlarge the memory allocation on a StrAccum object so that it is +** able to accept at least N more bytes of text. +** +** Return the number of bytes of text that StrAccum is able to accept +** after the attempted enlargement. The value returned might be zero. +*/ +static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ + char *zNew; + assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ + if( p->accError ){ + testcase(p->accError==STRACCUM_TOOBIG); + testcase(p->accError==STRACCUM_NOMEM); + return 0; + } + if( p->mxAlloc==0 ){ + N = p->nAlloc - p->nChar - 1; + setStrAccumError(p, STRACCUM_TOOBIG); + return N; + }else{ + char *zOld = (p->zText==p->zBase ? 0 : p->zText); + i64 szNew = p->nChar; + szNew += N + 1; + if( szNew+p->nChar<=p->mxAlloc ){ + /* Force exponential buffer size growth as long as it does not overflow, + ** to avoid having to call this routine too often */ + szNew += p->nChar; + } + if( szNew > p->mxAlloc ){ + sqlite3StrAccumReset(p); + setStrAccumError(p, STRACCUM_TOOBIG); + return 0; + }else{ + p->nAlloc = (int)szNew; + } + if( p->db ){ + zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc); + }else{ + zNew = sqlite3_realloc64(zOld, p->nAlloc); + } + if( zNew ){ + assert( p->zText!=0 || p->nChar==0 ); + if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); + p->zText = zNew; + p->nAlloc = sqlite3DbMallocSize(p->db, zNew); + }else{ + sqlite3StrAccumReset(p); + setStrAccumError(p, STRACCUM_NOMEM); + return 0; + } + } + return N; +} + +/* +** Append N copies of character c to the given string buffer. +*/ +SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ + testcase( p->nChar + (i64)N > 0x7fffffff ); + if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ + return; + } + while( (N--)>0 ) p->zText[p->nChar++] = c; +} + +/* +** The StrAccum "p" is not large enough to accept N new bytes of z[]. +** So enlarge if first, then do the append. +** +** This is a helper routine to sqlite3StrAccumAppend() that does special-case +** work (enlarging the buffer) using tail recursion, so that the +** sqlite3StrAccumAppend() routine can use fast calling semantics. +*/ +static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ + N = sqlite3StrAccumEnlarge(p, N); + if( N>0 ){ + memcpy(&p->zText[p->nChar], z, N); + p->nChar += N; + } +} + +/* +** Append N bytes of text from z to the StrAccum object. Increase the +** size of the memory allocation for StrAccum if necessary. +*/ +SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ + assert( z!=0 || N==0 ); + assert( p->zText!=0 || p->nChar==0 || p->accError ); + assert( N>=0 ); + assert( p->accError==0 || p->nAlloc==0 ); + if( p->nChar+N >= p->nAlloc ){ + enlargeAndAppend(p,z,N); + }else{ + assert( p->zText ); + p->nChar += N; + memcpy(&p->zText[p->nChar-N], z, N); + } +} + +/* +** Append the complete text of zero-terminated string z[] to the p string. +*/ +SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ + sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z)); +} + + +/* +** Finish off a string by making sure it is zero-terminated. +** Return a pointer to the resulting string. Return a NULL +** pointer if any kind of error was encountered. +*/ +SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ + if( p->zText ){ + p->zText[p->nChar] = 0; + if( p->mxAlloc>0 && p->zText==p->zBase ){ + p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); + if( p->zText ){ + memcpy(p->zText, p->zBase, p->nChar+1); + }else{ + setStrAccumError(p, STRACCUM_NOMEM); + } + } + } + return p->zText; +} + +/* +** Reset an StrAccum string. Reclaim all malloced memory. +*/ +SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){ + if( p->zText!=p->zBase ){ + sqlite3DbFree(p->db, p->zText); + } + p->zText = 0; +} + +/* +** Initialize a string accumulator. +** +** p: The accumulator to be initialized. +** db: Pointer to a database connection. May be NULL. Lookaside +** memory is used if not NULL. db->mallocFailed is set appropriately +** when not NULL. +** zBase: An initial buffer. May be NULL in which case the initial buffer +** is malloced. +** n: Size of zBase in bytes. If total space requirements never exceed +** n then no memory allocations ever occur. +** mx: Maximum number of bytes to accumulate. If mx==0 then no memory +** allocations will ever occur. +*/ +SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){ + p->zText = p->zBase = zBase; + p->db = db; + p->nChar = 0; + p->nAlloc = n; + p->mxAlloc = mx; + p->accError = 0; +} + +/* +** Print into memory obtained from sqliteMalloc(). Use the internal +** %-conversion extensions. +*/ +SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){ + char *z; + char zBase[SQLITE_PRINT_BUF_SIZE]; + StrAccum acc; + assert( db!=0 ); + sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), + db->aLimit[SQLITE_LIMIT_LENGTH]); + sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap); + z = sqlite3StrAccumFinish(&acc); + if( acc.accError==STRACCUM_NOMEM ){ + db->mallocFailed = 1; + } + return z; +} + +/* +** Print into memory obtained from sqliteMalloc(). Use the internal +** %-conversion extensions. +*/ +SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){ + va_list ap; + char *z; + va_start(ap, zFormat); + z = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + return z; +} + +/* +** Print into memory obtained from sqlite3_malloc(). Omit the internal +** %-conversion extensions. +*/ +SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char *zFormat, va_list ap){ + char *z; + char zBase[SQLITE_PRINT_BUF_SIZE]; + StrAccum acc; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( zFormat==0 ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); + sqlite3VXPrintf(&acc, 0, zFormat, ap); + z = sqlite3StrAccumFinish(&acc); + return z; +} + +/* +** Print into memory obtained from sqlite3_malloc()(). Omit the internal +** %-conversion extensions. +*/ +SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char *zFormat, ...){ + va_list ap; + char *z; +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + va_start(ap, zFormat); + z = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + return z; +} + +/* +** sqlite3_snprintf() works like snprintf() except that it ignores the +** current locale settings. This is important for SQLite because we +** are not able to use a "," as the decimal point in place of "." as +** specified by some locales. +** +** Oops: The first two arguments of sqlite3_snprintf() are backwards +** from the snprintf() standard. Unfortunately, it is too late to change +** this without breaking compatibility, so we just have to live with the +** mistake. +** +** sqlite3_vsnprintf() is the varargs version. +*/ +SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ + StrAccum acc; + if( n<=0 ) return zBuf; +#ifdef SQLITE_ENABLE_API_ARMOR + if( zBuf==0 || zFormat==0 ) { + (void)SQLITE_MISUSE_BKPT; + if( zBuf ) zBuf[0] = 0; + return zBuf; + } +#endif + sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); + sqlite3VXPrintf(&acc, 0, zFormat, ap); + return sqlite3StrAccumFinish(&acc); +} +SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ + char *z; + va_list ap; + va_start(ap,zFormat); + z = sqlite3_vsnprintf(n, zBuf, zFormat, ap); + va_end(ap); + return z; +} + +/* +** This is the routine that actually formats the sqlite3_log() message. +** We house it in a separate routine from sqlite3_log() to avoid using +** stack space on small-stack systems when logging is disabled. +** +** sqlite3_log() must render into a static buffer. It cannot dynamically +** allocate memory because it might be called while the memory allocator +** mutex is held. +** +** sqlite3VXPrintf() might ask for *temporary* memory allocations for +** certain format characters (%q) or for very large precisions or widths. +** Care must be taken that any sqlite3_log() calls that occur while the +** memory mutex is held do not use these mechanisms. +*/ +static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ + StrAccum acc; /* String accumulator */ + char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ + + sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); + sqlite3VXPrintf(&acc, 0, zFormat, ap); + sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, + sqlite3StrAccumFinish(&acc)); +} + +/* +** Format and write a message to the log if logging is enabled. +*/ +SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...){ + va_list ap; /* Vararg list */ + if( sqlite3GlobalConfig.xLog ){ + va_start(ap, zFormat); + renderLogMsg(iErrCode, zFormat, ap); + va_end(ap); + } +} + +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) +/* +** A version of printf() that understands %lld. Used for debugging. +** The printf() built into some versions of windows does not understand %lld +** and segfaults if you give it a long long int. +*/ +SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){ + va_list ap; + StrAccum acc; + char zBuf[500]; + sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); + va_start(ap,zFormat); + sqlite3VXPrintf(&acc, 0, zFormat, ap); + va_end(ap); + sqlite3StrAccumFinish(&acc); + fprintf(stdout,"%s", zBuf); + fflush(stdout); +} +#endif + + +/* +** variable-argument wrapper around sqlite3VXPrintf(). +*/ +SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){ + va_list ap; + va_start(ap,zFormat); + sqlite3VXPrintf(p, bFlags, zFormat, ap); + va_end(ap); +} + +/************** End of printf.c **********************************************/ +/************** Begin file treeview.c ****************************************/ +/* +** 2015-06-08 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains C code to implement the TreeView debugging routines. +** These routines print a parse tree to standard output for debugging and +** analysis. +** +** The interfaces in this file is only available when compiling +** with SQLITE_DEBUG. +*/ +/* #include "sqliteInt.h" */ +#ifdef SQLITE_DEBUG + +/* +** Add a new subitem to the tree. The moreToFollow flag indicates that this +** is not the last item in the tree. +*/ +static TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){ + if( p==0 ){ + p = sqlite3_malloc64( sizeof(*p) ); + if( p==0 ) return 0; + memset(p, 0, sizeof(*p)); + }else{ + p->iLevel++; + } + assert( moreToFollow==0 || moreToFollow==1 ); + if( p->iLevelbLine) ) p->bLine[p->iLevel] = moreToFollow; + return p; +} + +/* +** Finished with one layer of the tree +*/ +static void sqlite3TreeViewPop(TreeView *p){ + if( p==0 ) return; + p->iLevel--; + if( p->iLevel<0 ) sqlite3_free(p); +} + +/* +** Generate a single line of output for the tree, with a prefix that contains +** all the appropriate tree lines +*/ +static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ + va_list ap; + int i; + StrAccum acc; + char zBuf[500]; + sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); + if( p ){ + for(i=0; iiLevel && ibLine)-1; i++){ + sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4); + } + sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); + } + va_start(ap, zFormat); + sqlite3VXPrintf(&acc, 0, zFormat, ap); + va_end(ap); + if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1); + sqlite3StrAccumFinish(&acc); + fprintf(stdout,"%s", zBuf); + fflush(stdout); +} + +/* +** Shorthand for starting a new tree item that consists of a single label +*/ +static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){ + p = sqlite3TreeViewPush(p, moreFollows); + sqlite3TreeViewLine(p, "%s", zLabel); +} + + +/* +** Generate a human-readable description of a the Select object. +*/ +SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ + int n = 0; + pView = sqlite3TreeViewPush(pView, moreToFollow); + sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x", + ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), + ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags + ); + if( p->pSrc && p->pSrc->nSrc ) n++; + if( p->pWhere ) n++; + if( p->pGroupBy ) n++; + if( p->pHaving ) n++; + if( p->pOrderBy ) n++; + if( p->pLimit ) n++; + if( p->pOffset ) n++; + if( p->pPrior ) n++; + sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set"); + if( p->pSrc && p->pSrc->nSrc ){ + int i; + pView = sqlite3TreeViewPush(pView, (n--)>0); + sqlite3TreeViewLine(pView, "FROM"); + for(i=0; ipSrc->nSrc; i++){ + struct SrcList_item *pItem = &p->pSrc->a[i]; + StrAccum x; + char zLine[100]; + sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); + sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor); + if( pItem->zDatabase ){ + sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName); + }else if( pItem->zName ){ + sqlite3XPrintf(&x, 0, " %s", pItem->zName); + } + if( pItem->pTab ){ + sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName); + } + if( pItem->zAlias ){ + sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias); + } + if( pItem->jointype & JT_LEFT ){ + sqlite3XPrintf(&x, 0, " LEFT-JOIN"); + } + sqlite3StrAccumFinish(&x); + sqlite3TreeViewItem(pView, zLine, ipSrc->nSrc-1); + if( pItem->pSelect ){ + sqlite3TreeViewSelect(pView, pItem->pSelect, 0); + } + sqlite3TreeViewPop(pView); + } + sqlite3TreeViewPop(pView); + } + if( p->pWhere ){ + sqlite3TreeViewItem(pView, "WHERE", (n--)>0); + sqlite3TreeViewExpr(pView, p->pWhere, 0); + sqlite3TreeViewPop(pView); + } + if( p->pGroupBy ){ + sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY"); + } + if( p->pHaving ){ + sqlite3TreeViewItem(pView, "HAVING", (n--)>0); + sqlite3TreeViewExpr(pView, p->pHaving, 0); + sqlite3TreeViewPop(pView); + } + if( p->pOrderBy ){ + sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY"); + } + if( p->pLimit ){ + sqlite3TreeViewItem(pView, "LIMIT", (n--)>0); + sqlite3TreeViewExpr(pView, p->pLimit, 0); + sqlite3TreeViewPop(pView); + } + if( p->pOffset ){ + sqlite3TreeViewItem(pView, "OFFSET", (n--)>0); + sqlite3TreeViewExpr(pView, p->pOffset, 0); + sqlite3TreeViewPop(pView); + } + if( p->pPrior ){ + const char *zOp = "UNION"; + switch( p->op ){ + case TK_ALL: zOp = "UNION ALL"; break; + case TK_INTERSECT: zOp = "INTERSECT"; break; + case TK_EXCEPT: zOp = "EXCEPT"; break; + } + sqlite3TreeViewItem(pView, zOp, (n--)>0); + sqlite3TreeViewSelect(pView, p->pPrior, 0); + sqlite3TreeViewPop(pView); + } + sqlite3TreeViewPop(pView); +} + +/* +** Generate a human-readable explanation of an expression tree. +*/ +SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ + const char *zBinOp = 0; /* Binary operator */ + const char *zUniOp = 0; /* Unary operator */ + char zFlgs[30]; + pView = sqlite3TreeViewPush(pView, moreToFollow); + if( pExpr==0 ){ + sqlite3TreeViewLine(pView, "nil"); + sqlite3TreeViewPop(pView); + return; + } + if( pExpr->flags ){ + sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x",pExpr->flags); + }else{ + zFlgs[0] = 0; + } + switch( pExpr->op ){ + case TK_AGG_COLUMN: { + sqlite3TreeViewLine(pView, "AGG{%d:%d}%s", + pExpr->iTable, pExpr->iColumn, zFlgs); + break; + } + case TK_COLUMN: { + if( pExpr->iTable<0 ){ + /* This only happens when coding check constraints */ + sqlite3TreeViewLine(pView, "COLUMN(%d)%s", pExpr->iColumn, zFlgs); + }else{ + sqlite3TreeViewLine(pView, "{%d:%d}%s", + pExpr->iTable, pExpr->iColumn, zFlgs); + } + break; + } + case TK_INTEGER: { + if( pExpr->flags & EP_IntValue ){ + sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue); + }else{ + sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken); + } + break; + } +#ifndef SQLITE_OMIT_FLOATING_POINT + case TK_FLOAT: { + sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); + break; + } +#endif + case TK_STRING: { + sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken); + break; + } + case TK_NULL: { + sqlite3TreeViewLine(pView,"NULL"); + break; + } +#ifndef SQLITE_OMIT_BLOB_LITERAL + case TK_BLOB: { + sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); + break; + } +#endif + case TK_VARIABLE: { + sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)", + pExpr->u.zToken, pExpr->iColumn); + break; + } + case TK_REGISTER: { + sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable); + break; + } + case TK_AS: { + sqlite3TreeViewLine(pView,"AS %Q", pExpr->u.zToken); + sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); + break; + } + case TK_ID: { + sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken); + break; + } +#ifndef SQLITE_OMIT_CAST + case TK_CAST: { + /* Expressions of the form: CAST(pLeft AS token) */ + sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken); + sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); + break; + } +#endif /* SQLITE_OMIT_CAST */ + case TK_LT: zBinOp = "LT"; break; + case TK_LE: zBinOp = "LE"; break; + case TK_GT: zBinOp = "GT"; break; + case TK_GE: zBinOp = "GE"; break; + case TK_NE: zBinOp = "NE"; break; + case TK_EQ: zBinOp = "EQ"; break; + case TK_IS: zBinOp = "IS"; break; + case TK_ISNOT: zBinOp = "ISNOT"; break; + case TK_AND: zBinOp = "AND"; break; + case TK_OR: zBinOp = "OR"; break; + case TK_PLUS: zBinOp = "ADD"; break; + case TK_STAR: zBinOp = "MUL"; break; + case TK_MINUS: zBinOp = "SUB"; break; + case TK_REM: zBinOp = "REM"; break; + case TK_BITAND: zBinOp = "BITAND"; break; + case TK_BITOR: zBinOp = "BITOR"; break; + case TK_SLASH: zBinOp = "DIV"; break; + case TK_LSHIFT: zBinOp = "LSHIFT"; break; + case TK_RSHIFT: zBinOp = "RSHIFT"; break; + case TK_CONCAT: zBinOp = "CONCAT"; break; + case TK_DOT: zBinOp = "DOT"; break; + + case TK_UMINUS: zUniOp = "UMINUS"; break; + case TK_UPLUS: zUniOp = "UPLUS"; break; + case TK_BITNOT: zUniOp = "BITNOT"; break; + case TK_NOT: zUniOp = "NOT"; break; + case TK_ISNULL: zUniOp = "ISNULL"; break; + case TK_NOTNULL: zUniOp = "NOTNULL"; break; + + case TK_COLLATE: { + sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken); + sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); + break; + } + + case TK_AGG_FUNCTION: + case TK_FUNCTION: { + ExprList *pFarg; /* List of function arguments */ + if( ExprHasProperty(pExpr, EP_TokenOnly) ){ + pFarg = 0; + }else{ + pFarg = pExpr->x.pList; + } + if( pExpr->op==TK_AGG_FUNCTION ){ + sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q", + pExpr->op2, pExpr->u.zToken); + }else{ + sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken); + } + if( pFarg ){ + sqlite3TreeViewExprList(pView, pFarg, 0, 0); + } + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_EXISTS: { + sqlite3TreeViewLine(pView, "EXISTS-expr"); + sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); + break; + } + case TK_SELECT: { + sqlite3TreeViewLine(pView, "SELECT-expr"); + sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); + break; + } + case TK_IN: { + sqlite3TreeViewLine(pView, "IN"); + sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); + }else{ + sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); + } + break; + } +#endif /* SQLITE_OMIT_SUBQUERY */ + + /* + ** x BETWEEN y AND z + ** + ** This is equivalent to + ** + ** x>=y AND x<=z + ** + ** X is stored in pExpr->pLeft. + ** Y is stored in pExpr->pList->a[0].pExpr. + ** Z is stored in pExpr->pList->a[1].pExpr. + */ + case TK_BETWEEN: { + Expr *pX = pExpr->pLeft; + Expr *pY = pExpr->x.pList->a[0].pExpr; + Expr *pZ = pExpr->x.pList->a[1].pExpr; + sqlite3TreeViewLine(pView, "BETWEEN"); + sqlite3TreeViewExpr(pView, pX, 1); + sqlite3TreeViewExpr(pView, pY, 1); + sqlite3TreeViewExpr(pView, pZ, 0); + break; + } + case TK_TRIGGER: { + /* If the opcode is TK_TRIGGER, then the expression is a reference + ** to a column in the new.* or old.* pseudo-tables available to + ** trigger programs. In this case Expr.iTable is set to 1 for the + ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn + ** is set to the column of the pseudo-table to read, or to -1 to + ** read the rowid field. + */ + sqlite3TreeViewLine(pView, "%s(%d)", + pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn); + break; + } + case TK_CASE: { + sqlite3TreeViewLine(pView, "CASE"); + sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); + sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); + break; + } +#ifndef SQLITE_OMIT_TRIGGER + case TK_RAISE: { + const char *zType = "unk"; + switch( pExpr->affinity ){ + case OE_Rollback: zType = "rollback"; break; + case OE_Abort: zType = "abort"; break; + case OE_Fail: zType = "fail"; break; + case OE_Ignore: zType = "ignore"; break; + } + sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken); + break; + } +#endif + default: { + sqlite3TreeViewLine(pView, "op=%d", pExpr->op); + break; + } + } + if( zBinOp ){ + sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs); + sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); + sqlite3TreeViewExpr(pView, pExpr->pRight, 0); + }else if( zUniOp ){ + sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs); + sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); + } + sqlite3TreeViewPop(pView); +} + +/* +** Generate a human-readable explanation of an expression list. +*/ +SQLITE_PRIVATE void sqlite3TreeViewExprList( + TreeView *pView, + const ExprList *pList, + u8 moreToFollow, + const char *zLabel +){ + int i; + pView = sqlite3TreeViewPush(pView, moreToFollow); + if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST"; + if( pList==0 ){ + sqlite3TreeViewLine(pView, "%s (empty)", zLabel); + }else{ + sqlite3TreeViewLine(pView, "%s", zLabel); + for(i=0; inExpr; i++){ + sqlite3TreeViewExpr(pView, pList->a[i].pExpr, inExpr-1); + } + } + sqlite3TreeViewPop(pView); +} + +#endif /* SQLITE_DEBUG */ + +/************** End of treeview.c ********************************************/ +/************** Begin file random.c ******************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code to implement a pseudo-random number +** generator (PRNG) for SQLite. +** +** Random numbers are used by some of the database backends in order +** to generate random integer keys for tables or random filenames. +*/ +/* #include "sqliteInt.h" */ + + +/* All threads share a single random number generator. +** This structure is the current state of the generator. +*/ +static SQLITE_WSD struct sqlite3PrngType { + unsigned char isInit; /* True if initialized */ + unsigned char i, j; /* State variables */ + unsigned char s[256]; /* State variables */ +} sqlite3Prng; + +/* +** Return N random bytes. +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *pBuf){ + unsigned char t; + unsigned char *zBuf = pBuf; + + /* The "wsdPrng" macro will resolve to the pseudo-random number generator + ** state vector. If writable static data is unsupported on the target, + ** we have to locate the state vector at run-time. In the more common + ** case where writable static data is supported, wsdPrng can refer directly + ** to the "sqlite3Prng" state vector declared above. + */ +#ifdef SQLITE_OMIT_WSD + struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng); +# define wsdPrng p[0] +#else +# define wsdPrng sqlite3Prng +#endif + +#if SQLITE_THREADSAFE + sqlite3_mutex *mutex; +#endif + +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return; +#endif + +#if SQLITE_THREADSAFE + mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG); +#endif + + sqlite3_mutex_enter(mutex); + if( N<=0 || pBuf==0 ){ + wsdPrng.isInit = 0; + sqlite3_mutex_leave(mutex); + return; + } + + /* Initialize the state of the random number generator once, + ** the first time this routine is called. The seed value does + ** not need to contain a lot of randomness since we are not + ** trying to do secure encryption or anything like that... + ** + ** Nothing in this file or anywhere else in SQLite does any kind of + ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random + ** number generator) not as an encryption device. + */ + if( !wsdPrng.isInit ){ + int i; + char k[256]; + wsdPrng.j = 0; + wsdPrng.i = 0; + sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k); + for(i=0; i<256; i++){ + wsdPrng.s[i] = (u8)i; + } + for(i=0; i<256; i++){ + wsdPrng.j += wsdPrng.s[i] + k[i]; + t = wsdPrng.s[wsdPrng.j]; + wsdPrng.s[wsdPrng.j] = wsdPrng.s[i]; + wsdPrng.s[i] = t; + } + wsdPrng.isInit = 1; + } + + assert( N>0 ); + do{ + wsdPrng.i++; + t = wsdPrng.s[wsdPrng.i]; + wsdPrng.j += t; + wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j]; + wsdPrng.s[wsdPrng.j] = t; + t += wsdPrng.s[wsdPrng.i]; + *(zBuf++) = wsdPrng.s[t]; + }while( --N ); + sqlite3_mutex_leave(mutex); +} + +#ifndef SQLITE_OMIT_BUILTIN_TEST +/* +** For testing purposes, we sometimes want to preserve the state of +** PRNG and restore the PRNG to its saved state at a later time, or +** to reset the PRNG to its initial state. These routines accomplish +** those tasks. +** +** The sqlite3_test_control() interface calls these routines to +** control the PRNG. +*/ +static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng; +SQLITE_PRIVATE void sqlite3PrngSaveState(void){ + memcpy( + &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng), + &GLOBAL(struct sqlite3PrngType, sqlite3Prng), + sizeof(sqlite3Prng) + ); +} +SQLITE_PRIVATE void sqlite3PrngRestoreState(void){ + memcpy( + &GLOBAL(struct sqlite3PrngType, sqlite3Prng), + &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng), + sizeof(sqlite3Prng) + ); +} +#endif /* SQLITE_OMIT_BUILTIN_TEST */ + +/************** End of random.c **********************************************/ +/************** Begin file threads.c *****************************************/ +/* +** 2012 July 21 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file presents a simple cross-platform threading interface for +** use internally by SQLite. +** +** A "thread" can be created using sqlite3ThreadCreate(). This thread +** runs independently of its creator until it is joined using +** sqlite3ThreadJoin(), at which point it terminates. +** +** Threads do not have to be real. It could be that the work of the +** "thread" is done by the main thread at either the sqlite3ThreadCreate() +** or sqlite3ThreadJoin() call. This is, in fact, what happens in +** single threaded systems. Nothing in SQLite requires multiple threads. +** This interface exists so that applications that want to take advantage +** of multiple cores can do so, while also allowing applications to stay +** single-threaded if desired. +*/ +/* #include "sqliteInt.h" */ +#if SQLITE_OS_WIN +/* # include "os_win.h" */ +#endif + +#if SQLITE_MAX_WORKER_THREADS>0 + +/********************************* Unix Pthreads ****************************/ +#if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0 + +#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ +/* #include */ + +/* A running thread */ +struct SQLiteThread { + pthread_t tid; /* Thread ID */ + int done; /* Set to true when thread finishes */ + void *pOut; /* Result returned by the thread */ + void *(*xTask)(void*); /* The thread routine */ + void *pIn; /* Argument to the thread */ +}; + +/* Create a new thread */ +SQLITE_PRIVATE int sqlite3ThreadCreate( + SQLiteThread **ppThread, /* OUT: Write the thread object here */ + void *(*xTask)(void*), /* Routine to run in a separate thread */ + void *pIn /* Argument passed into xTask() */ +){ + SQLiteThread *p; + int rc; + + assert( ppThread!=0 ); + assert( xTask!=0 ); + /* This routine is never used in single-threaded mode */ + assert( sqlite3GlobalConfig.bCoreMutex!=0 ); + + *ppThread = 0; + p = sqlite3Malloc(sizeof(*p)); + if( p==0 ) return SQLITE_NOMEM; + memset(p, 0, sizeof(*p)); + p->xTask = xTask; + p->pIn = pIn; + if( sqlite3FaultSim(200) ){ + rc = 1; + }else{ + rc = pthread_create(&p->tid, 0, xTask, pIn); + } + if( rc ){ + p->done = 1; + p->pOut = xTask(pIn); + } + *ppThread = p; + return SQLITE_OK; +} + +/* Get the results of the thread */ +SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ + int rc; + + assert( ppOut!=0 ); + if( NEVER(p==0) ) return SQLITE_NOMEM; + if( p->done ){ + *ppOut = p->pOut; + rc = SQLITE_OK; + }else{ + rc = pthread_join(p->tid, ppOut) ? SQLITE_ERROR : SQLITE_OK; + } + sqlite3_free(p); + return rc; +} + +#endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */ +/******************************** End Unix Pthreads *************************/ + + +/********************************* Win32 Threads ****************************/ +#if SQLITE_OS_WIN_THREADS + +#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ +#include + +/* A running thread */ +struct SQLiteThread { + void *tid; /* The thread handle */ + unsigned id; /* The thread identifier */ + void *(*xTask)(void*); /* The routine to run as a thread */ + void *pIn; /* Argument to xTask */ + void *pResult; /* Result of xTask */ +}; + +/* Thread procedure Win32 compatibility shim */ +static unsigned __stdcall sqlite3ThreadProc( + void *pArg /* IN: Pointer to the SQLiteThread structure */ +){ + SQLiteThread *p = (SQLiteThread *)pArg; + + assert( p!=0 ); +#if 0 + /* + ** This assert appears to trigger spuriously on certain + ** versions of Windows, possibly due to _beginthreadex() + ** and/or CreateThread() not fully setting their thread + ** ID parameter before starting the thread. + */ + assert( p->id==GetCurrentThreadId() ); +#endif + assert( p->xTask!=0 ); + p->pResult = p->xTask(p->pIn); + + _endthreadex(0); + return 0; /* NOT REACHED */ +} + +/* Create a new thread */ +SQLITE_PRIVATE int sqlite3ThreadCreate( + SQLiteThread **ppThread, /* OUT: Write the thread object here */ + void *(*xTask)(void*), /* Routine to run in a separate thread */ + void *pIn /* Argument passed into xTask() */ +){ + SQLiteThread *p; + + assert( ppThread!=0 ); + assert( xTask!=0 ); + *ppThread = 0; + p = sqlite3Malloc(sizeof(*p)); + if( p==0 ) return SQLITE_NOMEM; + if( sqlite3GlobalConfig.bCoreMutex==0 ){ + memset(p, 0, sizeof(*p)); + }else{ + p->xTask = xTask; + p->pIn = pIn; + p->tid = (void*)_beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id); + if( p->tid==0 ){ + memset(p, 0, sizeof(*p)); + } + } + if( p->xTask==0 ){ + p->id = GetCurrentThreadId(); + p->pResult = xTask(pIn); + } + *ppThread = p; + return SQLITE_OK; +} + +SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject); /* os_win.c */ + +/* Get the results of the thread */ +SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ + DWORD rc; + BOOL bRc; + + assert( ppOut!=0 ); + if( NEVER(p==0) ) return SQLITE_NOMEM; + if( p->xTask==0 ){ + assert( p->id==GetCurrentThreadId() ); + rc = WAIT_OBJECT_0; + assert( p->tid==0 ); + }else{ + assert( p->id!=0 && p->id!=GetCurrentThreadId() ); + rc = sqlite3Win32Wait((HANDLE)p->tid); + assert( rc!=WAIT_IO_COMPLETION ); + bRc = CloseHandle((HANDLE)p->tid); + assert( bRc ); + } + if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult; + sqlite3_free(p); + return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR; +} + +#endif /* SQLITE_OS_WIN_THREADS */ +/******************************** End Win32 Threads *************************/ + + +/********************************* Single-Threaded **************************/ +#ifndef SQLITE_THREADS_IMPLEMENTED +/* +** This implementation does not actually create a new thread. It does the +** work of the thread in the main thread, when either the thread is created +** or when it is joined +*/ + +/* A running thread */ +struct SQLiteThread { + void *(*xTask)(void*); /* The routine to run as a thread */ + void *pIn; /* Argument to xTask */ + void *pResult; /* Result of xTask */ +}; + +/* Create a new thread */ +SQLITE_PRIVATE int sqlite3ThreadCreate( + SQLiteThread **ppThread, /* OUT: Write the thread object here */ + void *(*xTask)(void*), /* Routine to run in a separate thread */ + void *pIn /* Argument passed into xTask() */ +){ + SQLiteThread *p; + + assert( ppThread!=0 ); + assert( xTask!=0 ); + *ppThread = 0; + p = sqlite3Malloc(sizeof(*p)); + if( p==0 ) return SQLITE_NOMEM; + if( (SQLITE_PTR_TO_INT(p)/17)&1 ){ + p->xTask = xTask; + p->pIn = pIn; + }else{ + p->xTask = 0; + p->pResult = xTask(pIn); + } + *ppThread = p; + return SQLITE_OK; +} + +/* Get the results of the thread */ +SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ + + assert( ppOut!=0 ); + if( NEVER(p==0) ) return SQLITE_NOMEM; + if( p->xTask ){ + *ppOut = p->xTask(p->pIn); + }else{ + *ppOut = p->pResult; + } + sqlite3_free(p); + +#if defined(SQLITE_TEST) + { + void *pTstAlloc = sqlite3Malloc(10); + if (!pTstAlloc) return SQLITE_NOMEM; + sqlite3_free(pTstAlloc); + } +#endif + + return SQLITE_OK; +} + +#endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */ +/****************************** End Single-Threaded *************************/ +#endif /* SQLITE_MAX_WORKER_THREADS>0 */ + +/************** End of threads.c *********************************************/ +/************** Begin file utf.c *********************************************/ +/* +** 2004 April 13 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains routines used to translate between UTF-8, +** UTF-16, UTF-16BE, and UTF-16LE. +** +** Notes on UTF-8: +** +** Byte-0 Byte-1 Byte-2 Byte-3 Value +** 0xxxxxxx 00000000 00000000 0xxxxxxx +** 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx +** 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx +** 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx 000uuuuu zzzzyyyy yyxxxxxx +** +** +** Notes on UTF-16: (with wwww+1==uuuuu) +** +** Word-0 Word-1 Value +** 110110ww wwzzzzyy 110111yy yyxxxxxx 000uuuuu zzzzyyyy yyxxxxxx +** zzzzyyyy yyxxxxxx 00000000 zzzzyyyy yyxxxxxx +** +** +** BOM or Byte Order Mark: +** 0xff 0xfe little-endian utf-16 follows +** 0xfe 0xff big-endian utf-16 follows +** +*/ +/* #include "sqliteInt.h" */ +/* #include */ +/* #include "vdbeInt.h" */ + +#ifndef SQLITE_AMALGAMATION +/* +** The following constant value is used by the SQLITE_BIGENDIAN and +** SQLITE_LITTLEENDIAN macros. +*/ +SQLITE_PRIVATE const int sqlite3one = 1; +#endif /* SQLITE_AMALGAMATION */ + +/* +** This lookup table is used to help decode the first byte of +** a multi-byte UTF8 character. +*/ +static const unsigned char sqlite3Utf8Trans1[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, +}; + + +#define WRITE_UTF8(zOut, c) { \ + if( c<0x00080 ){ \ + *zOut++ = (u8)(c&0xFF); \ + } \ + else if( c<0x00800 ){ \ + *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \ + *zOut++ = 0x80 + (u8)(c & 0x3F); \ + } \ + else if( c<0x10000 ){ \ + *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \ + *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ + *zOut++ = 0x80 + (u8)(c & 0x3F); \ + }else{ \ + *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \ + *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \ + *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ + *zOut++ = 0x80 + (u8)(c & 0x3F); \ + } \ +} + +#define WRITE_UTF16LE(zOut, c) { \ + if( c<=0xFFFF ){ \ + *zOut++ = (u8)(c&0x00FF); \ + *zOut++ = (u8)((c>>8)&0x00FF); \ + }else{ \ + *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \ + *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \ + *zOut++ = (u8)(c&0x00FF); \ + *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \ + } \ +} + +#define WRITE_UTF16BE(zOut, c) { \ + if( c<=0xFFFF ){ \ + *zOut++ = (u8)((c>>8)&0x00FF); \ + *zOut++ = (u8)(c&0x00FF); \ + }else{ \ + *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \ + *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \ + *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \ + *zOut++ = (u8)(c&0x00FF); \ + } \ +} + +#define READ_UTF16LE(zIn, TERM, c){ \ + c = (*zIn++); \ + c += ((*zIn++)<<8); \ + if( c>=0xD800 && c<0xE000 && TERM ){ \ + int c2 = (*zIn++); \ + c2 += ((*zIn++)<<8); \ + c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \ + } \ +} + +#define READ_UTF16BE(zIn, TERM, c){ \ + c = ((*zIn++)<<8); \ + c += (*zIn++); \ + if( c>=0xD800 && c<0xE000 && TERM ){ \ + int c2 = ((*zIn++)<<8); \ + c2 += (*zIn++); \ + c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \ + } \ +} + +/* +** Translate a single UTF-8 character. Return the unicode value. +** +** During translation, assume that the byte that zTerm points +** is a 0x00. +** +** Write a pointer to the next unread byte back into *pzNext. +** +** Notes On Invalid UTF-8: +** +** * This routine never allows a 7-bit character (0x00 through 0x7f) to +** be encoded as a multi-byte character. Any multi-byte character that +** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd. +** +** * This routine never allows a UTF16 surrogate value to be encoded. +** If a multi-byte character attempts to encode a value between +** 0xd800 and 0xe000 then it is rendered as 0xfffd. +** +** * Bytes in the range of 0x80 through 0xbf which occur as the first +** byte of a character are interpreted as single-byte characters +** and rendered as themselves even though they are technically +** invalid characters. +** +** * This routine accepts over-length UTF8 encodings +** for unicode values 0x80 and greater. It does not change over-length +** encodings to 0xfffd as some systems recommend. +*/ +#define READ_UTF8(zIn, zTerm, c) \ + c = *(zIn++); \ + if( c>=0xc0 ){ \ + c = sqlite3Utf8Trans1[c-0xc0]; \ + while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \ + c = (c<<6) + (0x3f & *(zIn++)); \ + } \ + if( c<0x80 \ + || (c&0xFFFFF800)==0xD800 \ + || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ + } +SQLITE_PRIVATE u32 sqlite3Utf8Read( + const unsigned char **pz /* Pointer to string from which to read char */ +){ + unsigned int c; + + /* Same as READ_UTF8() above but without the zTerm parameter. + ** For this routine, we assume the UTF8 string is always zero-terminated. + */ + c = *((*pz)++); + if( c>=0xc0 ){ + c = sqlite3Utf8Trans1[c-0xc0]; + while( (*(*pz) & 0xc0)==0x80 ){ + c = (c<<6) + (0x3f & *((*pz)++)); + } + if( c<0x80 + || (c&0xFFFFF800)==0xD800 + || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } + } + return c; +} + + + + +/* +** If the TRANSLATE_TRACE macro is defined, the value of each Mem is +** printed on stderr on the way into and out of sqlite3VdbeMemTranslate(). +*/ +/* #define TRANSLATE_TRACE 1 */ + +#ifndef SQLITE_OMIT_UTF16 +/* +** This routine transforms the internal text encoding used by pMem to +** desiredEnc. It is an error if the string is already of the desired +** encoding, or if *pMem does not contain a string value. +*/ +SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ + int len; /* Maximum length of output string in bytes */ + unsigned char *zOut; /* Output buffer */ + unsigned char *zIn; /* Input iterator */ + unsigned char *zTerm; /* End of input */ + unsigned char *z; /* Output iterator */ + unsigned int c; + + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( pMem->flags&MEM_Str ); + assert( pMem->enc!=desiredEnc ); + assert( pMem->enc!=0 ); + assert( pMem->n>=0 ); + +#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) + { + char zBuf[100]; + sqlite3VdbeMemPrettyPrint(pMem, zBuf); + fprintf(stderr, "INPUT: %s\n", zBuf); + } +#endif + + /* If the translation is between UTF-16 little and big endian, then + ** all that is required is to swap the byte order. This case is handled + ** differently from the others. + */ + if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){ + u8 temp; + int rc; + rc = sqlite3VdbeMemMakeWriteable(pMem); + if( rc!=SQLITE_OK ){ + assert( rc==SQLITE_NOMEM ); + return SQLITE_NOMEM; + } + zIn = (u8*)pMem->z; + zTerm = &zIn[pMem->n&~1]; + while( zInenc = desiredEnc; + goto translate_out; + } + + /* Set len to the maximum number of bytes required in the output buffer. */ + if( desiredEnc==SQLITE_UTF8 ){ + /* When converting from UTF-16, the maximum growth results from + ** translating a 2-byte character to a 4-byte UTF-8 character. + ** A single byte is required for the output string + ** nul-terminator. + */ + pMem->n &= ~1; + len = pMem->n * 2 + 1; + }else{ + /* When converting from UTF-8 to UTF-16 the maximum growth is caused + ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16 + ** character. Two bytes are required in the output buffer for the + ** nul-terminator. + */ + len = pMem->n * 2 + 2; + } + + /* Set zIn to point at the start of the input buffer and zTerm to point 1 + ** byte past the end. + ** + ** Variable zOut is set to point at the output buffer, space obtained + ** from sqlite3_malloc(). + */ + zIn = (u8*)pMem->z; + zTerm = &zIn[pMem->n]; + zOut = sqlite3DbMallocRaw(pMem->db, len); + if( !zOut ){ + return SQLITE_NOMEM; + } + z = zOut; + + if( pMem->enc==SQLITE_UTF8 ){ + if( desiredEnc==SQLITE_UTF16LE ){ + /* UTF-8 -> UTF-16 Little-endian */ + while( zIn UTF-16 Big-endian */ + while( zInn = (int)(z - zOut); + *z++ = 0; + }else{ + assert( desiredEnc==SQLITE_UTF8 ); + if( pMem->enc==SQLITE_UTF16LE ){ + /* UTF-16 Little-endian -> UTF-8 */ + while( zIn UTF-8 */ + while( zInn = (int)(z - zOut); + } + *z = 0; + assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); + + c = pMem->flags; + sqlite3VdbeMemRelease(pMem); + pMem->flags = MEM_Str|MEM_Term|(c&MEM_AffMask); + pMem->enc = desiredEnc; + pMem->z = (char*)zOut; + pMem->zMalloc = pMem->z; + pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->z); + +translate_out: +#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) + { + char zBuf[100]; + sqlite3VdbeMemPrettyPrint(pMem, zBuf); + fprintf(stderr, "OUTPUT: %s\n", zBuf); + } +#endif + return SQLITE_OK; +} + +/* +** This routine checks for a byte-order mark at the beginning of the +** UTF-16 string stored in *pMem. If one is present, it is removed and +** the encoding of the Mem adjusted. This routine does not do any +** byte-swapping, it just sets Mem.enc appropriately. +** +** The allocation (static, dynamic etc.) and encoding of the Mem may be +** changed by this function. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem){ + int rc = SQLITE_OK; + u8 bom = 0; + + assert( pMem->n>=0 ); + if( pMem->n>1 ){ + u8 b1 = *(u8 *)pMem->z; + u8 b2 = *(((u8 *)pMem->z) + 1); + if( b1==0xFE && b2==0xFF ){ + bom = SQLITE_UTF16BE; + } + if( b1==0xFF && b2==0xFE ){ + bom = SQLITE_UTF16LE; + } + } + + if( bom ){ + rc = sqlite3VdbeMemMakeWriteable(pMem); + if( rc==SQLITE_OK ){ + pMem->n -= 2; + memmove(pMem->z, &pMem->z[2], pMem->n); + pMem->z[pMem->n] = '\0'; + pMem->z[pMem->n+1] = '\0'; + pMem->flags |= MEM_Term; + pMem->enc = bom; + } + } + return rc; +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** pZ is a UTF-8 encoded unicode string. If nByte is less than zero, +** return the number of unicode characters in pZ up to (but not including) +** the first 0x00 byte. If nByte is not less than zero, return the +** number of unicode characters in the first nByte of pZ (or up to +** the first 0x00, whichever comes first). +*/ +SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){ + int r = 0; + const u8 *z = (const u8*)zIn; + const u8 *zTerm; + if( nByte>=0 ){ + zTerm = &z[nByte]; + }else{ + zTerm = (const u8*)(-1); + } + assert( z<=zTerm ); + while( *z!=0 && zmallocFailed ){ + sqlite3VdbeMemRelease(&m); + m.z = 0; + } + assert( (m.flags & MEM_Term)!=0 || db->mallocFailed ); + assert( (m.flags & MEM_Str)!=0 || db->mallocFailed ); + assert( m.z || db->mallocFailed ); + return m.z; +} + +/* +** zIn is a UTF-16 encoded unicode string at least nChar characters long. +** Return the number of bytes in the first nChar unicode characters +** in pZ. nChar must be non-negative. +*/ +SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){ + int c; + unsigned char const *z = zIn; + int n = 0; + + if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){ + while( n0 && n<=4 ); + z[0] = 0; + z = zBuf; + c = sqlite3Utf8Read((const u8**)&z); + t = i; + if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD; + if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD; + assert( c==t ); + assert( (z-zBuf)==n ); + } + for(i=0; i<0x00110000; i++){ + if( i>=0xD800 && i<0xE000 ) continue; + z = zBuf; + WRITE_UTF16LE(z, i); + n = (int)(z-zBuf); + assert( n>0 && n<=4 ); + z[0] = 0; + z = zBuf; + READ_UTF16LE(z, 1, c); + assert( c==i ); + assert( (z-zBuf)==n ); + } + for(i=0; i<0x00110000; i++){ + if( i>=0xD800 && i<0xE000 ) continue; + z = zBuf; + WRITE_UTF16BE(z, i); + n = (int)(z-zBuf); + assert( n>0 && n<=4 ); + z[0] = 0; + z = zBuf; + READ_UTF16BE(z, 1, c); + assert( c==i ); + assert( (z-zBuf)==n ); + } +} +#endif /* SQLITE_TEST */ +#endif /* SQLITE_OMIT_UTF16 */ + +/************** End of utf.c *************************************************/ +/************** Begin file util.c ********************************************/ +/* +** 2001 September 15 +** +** 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. +** +************************************************************************* +** Utility functions used throughout sqlite. +** +** This file contains functions for allocating memory, comparing +** strings, and stuff like that. +** +*/ +/* #include "sqliteInt.h" */ +/* #include */ +#if HAVE_ISNAN || SQLITE_HAVE_ISNAN +# include +#endif + +/* +** Routine needed to support the testcase() macro. +*/ +#ifdef SQLITE_COVERAGE_TEST +SQLITE_PRIVATE void sqlite3Coverage(int x){ + static unsigned dummy = 0; + dummy += (unsigned)x; +} +#endif + +/* +** Give a callback to the test harness that can be used to simulate faults +** in places where it is difficult or expensive to do so purely by means +** of inputs. +** +** The intent of the integer argument is to let the fault simulator know +** which of multiple sqlite3FaultSim() calls has been hit. +** +** Return whatever integer value the test callback returns, or return +** SQLITE_OK if no test callback is installed. +*/ +#ifndef SQLITE_OMIT_BUILTIN_TEST +SQLITE_PRIVATE int sqlite3FaultSim(int iTest){ + int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback; + return xCallback ? xCallback(iTest) : SQLITE_OK; +} +#endif + +#ifndef SQLITE_OMIT_FLOATING_POINT +/* +** Return true if the floating point value is Not a Number (NaN). +** +** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN. +** Otherwise, we have our own implementation that works on most systems. +*/ +SQLITE_PRIVATE int sqlite3IsNaN(double x){ + int rc; /* The value return */ +#if !SQLITE_HAVE_ISNAN && !HAVE_ISNAN + /* + ** Systems that support the isnan() library function should probably + ** make use of it by compiling with -DSQLITE_HAVE_ISNAN. But we have + ** found that many systems do not have a working isnan() function so + ** this implementation is provided as an alternative. + ** + ** This NaN test sometimes fails if compiled on GCC with -ffast-math. + ** On the other hand, the use of -ffast-math comes with the following + ** warning: + ** + ** This option [-ffast-math] should never be turned on by any + ** -O option since it can result in incorrect output for programs + ** which depend on an exact implementation of IEEE or ISO + ** rules/specifications for math functions. + ** + ** Under MSVC, this NaN test may fail if compiled with a floating- + ** point precision mode other than /fp:precise. From the MSDN + ** documentation: + ** + ** The compiler [with /fp:precise] will properly handle comparisons + ** involving NaN. For example, x != x evaluates to true if x is NaN + ** ... + */ +#ifdef __FAST_MATH__ +# error SQLite will not work correctly with the -ffast-math option of GCC. +#endif + volatile double y = x; + volatile double z = y; + rc = (y!=z); +#else /* if HAVE_ISNAN */ + rc = isnan(x); +#endif /* HAVE_ISNAN */ + testcase( rc ); + return rc; +} +#endif /* SQLITE_OMIT_FLOATING_POINT */ + +/* +** Compute a string length that is limited to what can be stored in +** lower 30 bits of a 32-bit signed integer. +** +** The value returned will never be negative. Nor will it ever be greater +** than the actual length of the string. For very long strings (greater +** than 1GiB) the value returned might be less than the true string length. +*/ +SQLITE_PRIVATE int sqlite3Strlen30(const char *z){ + if( z==0 ) return 0; + return 0x3fffffff & (int)strlen(z); +} + +/* +** Set the current error code to err_code and clear any prior error message. +*/ +SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code){ + assert( db!=0 ); + db->errCode = err_code; + if( db->pErr ) sqlite3ValueSetNull(db->pErr); +} + +/* +** Set the most recent error code and error string for the sqlite +** handle "db". The error code is set to "err_code". +** +** If it is not NULL, string zFormat specifies the format of the +** error string in the style of the printf functions: The following +** format characters are allowed: +** +** %s Insert a string +** %z A string that should be freed after use +** %d Insert an integer +** %T Insert a token +** %S Insert the first element of a SrcList +** +** zFormat and any string tokens that follow it are assumed to be +** encoded in UTF-8. +** +** To clear the most recent error for sqlite handle "db", sqlite3Error +** should be called with err_code set to SQLITE_OK and zFormat set +** to NULL. +*/ +SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *zFormat, ...){ + assert( db!=0 ); + db->errCode = err_code; + if( zFormat==0 ){ + sqlite3Error(db, err_code); + }else if( db->pErr || (db->pErr = sqlite3ValueNew(db))!=0 ){ + char *z; + va_list ap; + va_start(ap, zFormat); + z = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC); + } +} + +/* +** Add an error message to pParse->zErrMsg and increment pParse->nErr. +** The following formatting characters are allowed: +** +** %s Insert a string +** %z A string that should be freed after use +** %d Insert an integer +** %T Insert a token +** %S Insert the first element of a SrcList +** +** This function should be used to report any error that occurs while +** compiling an SQL statement (i.e. within sqlite3_prepare()). The +** last thing the sqlite3_prepare() function does is copy the error +** stored by this function into the database handle using sqlite3Error(). +** Functions sqlite3Error() or sqlite3ErrorWithMsg() should be used +** during statement execution (sqlite3_step() etc.). +*/ +SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ + char *zMsg; + va_list ap; + sqlite3 *db = pParse->db; + va_start(ap, zFormat); + zMsg = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + if( db->suppressErr ){ + sqlite3DbFree(db, zMsg); + }else{ + pParse->nErr++; + sqlite3DbFree(db, pParse->zErrMsg); + pParse->zErrMsg = zMsg; + pParse->rc = SQLITE_ERROR; + } +} + +/* +** Convert an SQL-style quoted string into a normal string by removing +** the quote characters. The conversion is done in-place. If the +** input does not begin with a quote character, then this routine +** is a no-op. +** +** The input string must be zero-terminated. A new zero-terminator +** is added to the dequoted string. +** +** The return value is -1 if no dequoting occurs or the length of the +** dequoted string, exclusive of the zero terminator, if dequoting does +** occur. +** +** 2002-Feb-14: This routine is extended to remove MS-Access style +** brackets from around identifiers. For example: "[a-b-c]" becomes +** "a-b-c". +*/ +SQLITE_PRIVATE int sqlite3Dequote(char *z){ + char quote; + int i, j; + if( z==0 ) return -1; + quote = z[0]; + switch( quote ){ + case '\'': break; + case '"': break; + case '`': break; /* For MySQL compatibility */ + case '[': quote = ']'; break; /* For MS SqlServer compatibility */ + default: return -1; + } + for(i=1, j=0;; i++){ + assert( z[i] ); + if( z[i]==quote ){ + if( z[i+1]==quote ){ + z[j++] = quote; + i++; + }else{ + break; + } + }else{ + z[j++] = z[i]; + } + } + z[j] = 0; + return j; +} + +/* Convenient short-hand */ +#define UpperToLower sqlite3UpperToLower + +/* +** Some systems have stricmp(). Others have strcasecmp(). Because +** there is no consistency, we will define our own. +** +** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and +** sqlite3_strnicmp() APIs allow applications and extensions to compare +** the contents of two buffers containing UTF-8 strings in a +** case-independent fashion, using the same definition of "case +** independence" that SQLite uses internally when comparing identifiers. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *zLeft, const char *zRight){ + register unsigned char *a, *b; + if( zLeft==0 ){ + return zRight ? -1 : 0; + }else if( zRight==0 ){ + return 1; + } + a = (unsigned char *)zLeft; + b = (unsigned char *)zRight; + while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } + return UpperToLower[*a] - UpperToLower[*b]; +} +SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ + register unsigned char *a, *b; + if( zLeft==0 ){ + return zRight ? -1 : 0; + }else if( zRight==0 ){ + return 1; + } + a = (unsigned char *)zLeft; + b = (unsigned char *)zRight; + while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } + return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b]; +} + +/* +** The string z[] is an text representation of a real number. +** Convert this string to a double and write it into *pResult. +** +** The string z[] is length bytes in length (bytes, not characters) and +** uses the encoding enc. The string is not necessarily zero-terminated. +** +** Return TRUE if the result is a valid real number (or integer) and FALSE +** if the string is empty or contains extraneous text. Valid numbers +** are in one of these formats: +** +** [+-]digits[E[+-]digits] +** [+-]digits.[digits][E[+-]digits] +** [+-].digits[E[+-]digits] +** +** Leading and trailing whitespace is ignored for the purpose of determining +** validity. +** +** If some prefix of the input string is a valid number, this routine +** returns FALSE but it still converts the prefix and writes the result +** into *pResult. +*/ +SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ +#ifndef SQLITE_OMIT_FLOATING_POINT + int incr; + const char *zEnd = z + length; + /* sign * significand * (10 ^ (esign * exponent)) */ + int sign = 1; /* sign of significand */ + i64 s = 0; /* significand */ + int d = 0; /* adjust exponent for shifting decimal point */ + int esign = 1; /* sign of exponent */ + int e = 0; /* exponent */ + int eValid = 1; /* True exponent is either not used or is well-formed */ + double result; + int nDigits = 0; + int nonNum = 0; + + assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); + *pResult = 0.0; /* Default return value, in case of an error */ + + if( enc==SQLITE_UTF8 ){ + incr = 1; + }else{ + int i; + incr = 2; + assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); + for(i=3-enc; i=zEnd ) return 0; + + /* get sign of significand */ + if( *z=='-' ){ + sign = -1; + z+=incr; + }else if( *z=='+' ){ + z+=incr; + } + + /* skip leading zeroes */ + while( z=zEnd ) goto do_atof_calc; + + /* if decimal point is present */ + if( *z=='.' ){ + z+=incr; + /* copy digits from after decimal to significand + ** (decrease exponent by d to shift decimal right) */ + while( z=zEnd ) goto do_atof_calc; + + /* if exponent is present */ + if( *z=='e' || *z=='E' ){ + z+=incr; + eValid = 0; + if( z>=zEnd ) goto do_atof_calc; + /* get sign of exponent */ + if( *z=='-' ){ + esign = -1; + z+=incr; + }else if( *z=='+' ){ + z+=incr; + } + /* copy digits to exponent */ + while( z0 ){ + while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10; + }else{ + while( !(s%10) && e>0 ) e--,s/=10; + } + + /* adjust the sign of significand */ + s = sign<0 ? -s : s; + + /* if exponent, scale significand as appropriate + ** and store in result. */ + if( e ){ + LONGDOUBLE_TYPE scale = 1.0; + /* attempt to handle extremely small/large numbers better */ + if( e>307 && e<342 ){ + while( e%308 ) { scale *= 1.0e+1; e -= 1; } + if( esign<0 ){ + result = s / scale; + result /= 1.0e+308; + }else{ + result = s * scale; + result *= 1.0e+308; + } + }else if( e>=342 ){ + if( esign<0 ){ + result = 0.0*s; + }else{ + result = 1e308*1e308*s; /* Infinity */ + } + }else{ + /* 1.0e+22 is the largest power of 10 than can be + ** represented exactly. */ + while( e%22 ) { scale *= 1.0e+1; e -= 1; } + while( e>0 ) { scale *= 1.0e+22; e -= 22; } + if( esign<0 ){ + result = s / scale; + }else{ + result = s * scale; + } + } + } else { + result = (double)s; + } + } + + /* store the result */ + *pResult = result; + + /* return true if number and no extra non-whitespace chracters after */ + return z>=zEnd && nDigits>0 && eValid && nonNum==0; +#else + return !sqlite3Atoi64(z, pResult, length, enc); +#endif /* SQLITE_OMIT_FLOATING_POINT */ +} + +/* +** Compare the 19-character string zNum against the text representation +** value 2^63: 9223372036854775808. Return negative, zero, or positive +** if zNum is less than, equal to, or greater than the string. +** Note that zNum must contain exactly 19 characters. +** +** Unlike memcmp() this routine is guaranteed to return the difference +** in the values of the last digit if the only difference is in the +** last digit. So, for example, +** +** compare2pow63("9223372036854775800", 1) +** +** will return -8. +*/ +static int compare2pow63(const char *zNum, int incr){ + int c = 0; + int i; + /* 012345678901234567 */ + const char *pow63 = "922337203685477580"; + for(i=0; c==0 && i<18; i++){ + c = (zNum[i*incr]-pow63[i])*10; + } + if( c==0 ){ + c = zNum[18*incr] - '8'; + testcase( c==(-1) ); + testcase( c==0 ); + testcase( c==(+1) ); + } + return c; +} + +/* +** Convert zNum to a 64-bit signed integer. zNum must be decimal. This +** routine does *not* accept hexadecimal notation. +** +** If the zNum value is representable as a 64-bit twos-complement +** integer, then write that value into *pNum and return 0. +** +** If zNum is exactly 9223372036854775808, return 2. This special +** case is broken out because while 9223372036854775808 cannot be a +** signed 64-bit integer, its negative -9223372036854775808 can be. +** +** If zNum is too big for a 64-bit integer and is not +** 9223372036854775808 or if zNum contains any non-numeric text, +** then return 1. +** +** length is the number of bytes in the string (bytes, not characters). +** The string is not necessarily zero-terminated. The encoding is +** given by enc. +*/ +SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){ + int incr; + u64 u = 0; + int neg = 0; /* assume positive */ + int i; + int c = 0; + int nonNum = 0; + const char *zStart; + const char *zEnd = zNum + length; + assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); + if( enc==SQLITE_UTF8 ){ + incr = 1; + }else{ + incr = 2; + assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); + for(i=3-enc; i='0' && c<='9'; i+=incr){ + u = u*10 + c - '0'; + } + if( u>LARGEST_INT64 ){ + *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; + }else if( neg ){ + *pNum = -(i64)u; + }else{ + *pNum = (i64)u; + } + testcase( i==18 ); + testcase( i==19 ); + testcase( i==20 ); + if( (c!=0 && &zNum[i]19*incr || nonNum ){ + /* zNum is empty or contains non-numeric text or is longer + ** than 19 digits (thus guaranteeing that it is too large) */ + return 1; + }else if( i<19*incr ){ + /* Less than 19 digits, so we know that it fits in 64 bits */ + assert( u<=LARGEST_INT64 ); + return 0; + }else{ + /* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */ + c = compare2pow63(zNum, incr); + if( c<0 ){ + /* zNum is less than 9223372036854775808 so it fits */ + assert( u<=LARGEST_INT64 ); + return 0; + }else if( c>0 ){ + /* zNum is greater than 9223372036854775808 so it overflows */ + return 1; + }else{ + /* zNum is exactly 9223372036854775808. Fits if negative. The + ** special case 2 overflow if positive */ + assert( u-1==LARGEST_INT64 ); + return neg ? 0 : 2; + } + } +} + +/* +** Transform a UTF-8 integer literal, in either decimal or hexadecimal, +** into a 64-bit signed integer. This routine accepts hexadecimal literals, +** whereas sqlite3Atoi64() does not. +** +** Returns: +** +** 0 Successful transformation. Fits in a 64-bit signed integer. +** 1 Integer too large for a 64-bit signed integer or is malformed +** 2 Special case of 9223372036854775808 +*/ +SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){ +#ifndef SQLITE_OMIT_HEX_INTEGER + if( z[0]=='0' + && (z[1]=='x' || z[1]=='X') + && sqlite3Isxdigit(z[2]) + ){ + u64 u = 0; + int i, k; + for(i=2; z[i]=='0'; i++){} + for(k=i; sqlite3Isxdigit(z[k]); k++){ + u = u*16 + sqlite3HexToInt(z[k]); + } + memcpy(pOut, &u, 8); + return (z[k]==0 && k-i<=16) ? 0 : 1; + }else +#endif /* SQLITE_OMIT_HEX_INTEGER */ + { + return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8); + } +} + +/* +** If zNum represents an integer that will fit in 32-bits, then set +** *pValue to that integer and return true. Otherwise return false. +** +** This routine accepts both decimal and hexadecimal notation for integers. +** +** Any non-numeric characters that following zNum are ignored. +** This is different from sqlite3Atoi64() which requires the +** input number to be zero-terminated. +*/ +SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){ + sqlite_int64 v = 0; + int i, c; + int neg = 0; + if( zNum[0]=='-' ){ + neg = 1; + zNum++; + }else if( zNum[0]=='+' ){ + zNum++; + } +#ifndef SQLITE_OMIT_HEX_INTEGER + else if( zNum[0]=='0' + && (zNum[1]=='x' || zNum[1]=='X') + && sqlite3Isxdigit(zNum[2]) + ){ + u32 u = 0; + zNum += 2; + while( zNum[0]=='0' ) zNum++; + for(i=0; sqlite3Isxdigit(zNum[i]) && i<8; i++){ + u = u*16 + sqlite3HexToInt(zNum[i]); + } + if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){ + memcpy(pValue, &u, 4); + return 1; + }else{ + return 0; + } + } +#endif + while( zNum[0]=='0' ) zNum++; + for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){ + v = v*10 + c; + } + + /* The longest decimal representation of a 32 bit integer is 10 digits: + ** + ** 1234567890 + ** 2^31 -> 2147483648 + */ + testcase( i==10 ); + if( i>10 ){ + return 0; + } + testcase( v-neg==2147483647 ); + if( v-neg>2147483647 ){ + return 0; + } + if( neg ){ + v = -v; + } + *pValue = (int)v; + return 1; +} + +/* +** Return a 32-bit integer value extracted from a string. If the +** string is not an integer, just return 0. +*/ +SQLITE_PRIVATE int sqlite3Atoi(const char *z){ + int x = 0; + if( z ) sqlite3GetInt32(z, &x); + return x; +} + +/* +** The variable-length integer encoding is as follows: +** +** KEY: +** A = 0xxxxxxx 7 bits of data and one flag bit +** B = 1xxxxxxx 7 bits of data and one flag bit +** C = xxxxxxxx 8 bits of data +** +** 7 bits - A +** 14 bits - BA +** 21 bits - BBA +** 28 bits - BBBA +** 35 bits - BBBBA +** 42 bits - BBBBBA +** 49 bits - BBBBBBA +** 56 bits - BBBBBBBA +** 64 bits - BBBBBBBBC +*/ + +/* +** Write a 64-bit variable-length integer to memory starting at p[0]. +** The length of data write will be between 1 and 9 bytes. The number +** of bytes written is returned. +** +** A variable-length integer consists of the lower 7 bits of each byte +** for all bytes that have the 8th bit set and one byte with the 8th +** bit clear. Except, if we get to the 9th byte, it stores the full +** 8 bits and is the last byte. +*/ +static int SQLITE_NOINLINE putVarint64(unsigned char *p, u64 v){ + int i, j, n; + u8 buf[10]; + if( v & (((u64)0xff000000)<<32) ){ + p[8] = (u8)v; + v >>= 8; + for(i=7; i>=0; i--){ + p[i] = (u8)((v & 0x7f) | 0x80); + v >>= 7; + } + return 9; + } + n = 0; + do{ + buf[n++] = (u8)((v & 0x7f) | 0x80); + v >>= 7; + }while( v!=0 ); + buf[0] &= 0x7f; + assert( n<=9 ); + for(i=0, j=n-1; j>=0; j--, i++){ + p[i] = buf[j]; + } + return n; +} +SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){ + if( v<=0x7f ){ + p[0] = v&0x7f; + return 1; + } + if( v<=0x3fff ){ + p[0] = ((v>>7)&0x7f)|0x80; + p[1] = v&0x7f; + return 2; + } + return putVarint64(p,v); +} + +/* +** Bitmasks used by sqlite3GetVarint(). These precomputed constants +** are defined here rather than simply putting the constant expressions +** inline in order to work around bugs in the RVT compiler. +** +** SLOT_2_0 A mask for (0x7f<<14) | 0x7f +** +** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0 +*/ +#define SLOT_2_0 0x001fc07f +#define SLOT_4_2_0 0xf01fc07f + + +/* +** Read a 64-bit variable-length integer from memory starting at p[0]. +** Return the number of bytes read. The value is stored in *v. +*/ +SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){ + u32 a,b,s; + + a = *p; + /* a: p0 (unmasked) */ + if (!(a&0x80)) + { + *v = a; + return 1; + } + + p++; + b = *p; + /* b: p1 (unmasked) */ + if (!(b&0x80)) + { + a &= 0x7f; + a = a<<7; + a |= b; + *v = a; + return 2; + } + + /* Verify that constants are precomputed correctly */ + assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) ); + assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) ); + + p++; + a = a<<14; + a |= *p; + /* a: p0<<14 | p2 (unmasked) */ + if (!(a&0x80)) + { + a &= SLOT_2_0; + b &= 0x7f; + b = b<<7; + a |= b; + *v = a; + return 3; + } + + /* CSE1 from below */ + a &= SLOT_2_0; + p++; + b = b<<14; + b |= *p; + /* b: p1<<14 | p3 (unmasked) */ + if (!(b&0x80)) + { + b &= SLOT_2_0; + /* moved CSE1 up */ + /* a &= (0x7f<<14)|(0x7f); */ + a = a<<7; + a |= b; + *v = a; + return 4; + } + + /* a: p0<<14 | p2 (masked) */ + /* b: p1<<14 | p3 (unmasked) */ + /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ + /* moved CSE1 up */ + /* a &= (0x7f<<14)|(0x7f); */ + b &= SLOT_2_0; + s = a; + /* s: p0<<14 | p2 (masked) */ + + p++; + a = a<<14; + a |= *p; + /* a: p0<<28 | p2<<14 | p4 (unmasked) */ + if (!(a&0x80)) + { + /* we can skip these cause they were (effectively) done above in calc'ing s */ + /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ + /* b &= (0x7f<<14)|(0x7f); */ + b = b<<7; + a |= b; + s = s>>18; + *v = ((u64)s)<<32 | a; + return 5; + } + + /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ + s = s<<7; + s |= b; + /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ + + p++; + b = b<<14; + b |= *p; + /* b: p1<<28 | p3<<14 | p5 (unmasked) */ + if (!(b&0x80)) + { + /* we can skip this cause it was (effectively) done above in calc'ing s */ + /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ + a &= SLOT_2_0; + a = a<<7; + a |= b; + s = s>>18; + *v = ((u64)s)<<32 | a; + return 6; + } + + p++; + a = a<<14; + a |= *p; + /* a: p2<<28 | p4<<14 | p6 (unmasked) */ + if (!(a&0x80)) + { + a &= SLOT_4_2_0; + b &= SLOT_2_0; + b = b<<7; + a |= b; + s = s>>11; + *v = ((u64)s)<<32 | a; + return 7; + } + + /* CSE2 from below */ + a &= SLOT_2_0; + p++; + b = b<<14; + b |= *p; + /* b: p3<<28 | p5<<14 | p7 (unmasked) */ + if (!(b&0x80)) + { + b &= SLOT_4_2_0; + /* moved CSE2 up */ + /* a &= (0x7f<<14)|(0x7f); */ + a = a<<7; + a |= b; + s = s>>4; + *v = ((u64)s)<<32 | a; + return 8; + } + + p++; + a = a<<15; + a |= *p; + /* a: p4<<29 | p6<<15 | p8 (unmasked) */ + + /* moved CSE2 up */ + /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */ + b &= SLOT_2_0; + b = b<<8; + a |= b; + + s = s<<4; + b = p[-4]; + b &= 0x7f; + b = b>>3; + s |= b; + + *v = ((u64)s)<<32 | a; + + return 9; +} + +/* +** Read a 32-bit variable-length integer from memory starting at p[0]. +** Return the number of bytes read. The value is stored in *v. +** +** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned +** integer, then set *v to 0xffffffff. +** +** A MACRO version, getVarint32, is provided which inlines the +** single-byte case. All code should use the MACRO version as +** this function assumes the single-byte case has already been handled. +*/ +SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){ + u32 a,b; + + /* The 1-byte case. Overwhelmingly the most common. Handled inline + ** by the getVarin32() macro */ + a = *p; + /* a: p0 (unmasked) */ +#ifndef getVarint32 + if (!(a&0x80)) + { + /* Values between 0 and 127 */ + *v = a; + return 1; + } +#endif + + /* The 2-byte case */ + p++; + b = *p; + /* b: p1 (unmasked) */ + if (!(b&0x80)) + { + /* Values between 128 and 16383 */ + a &= 0x7f; + a = a<<7; + *v = a | b; + return 2; + } + + /* The 3-byte case */ + p++; + a = a<<14; + a |= *p; + /* a: p0<<14 | p2 (unmasked) */ + if (!(a&0x80)) + { + /* Values between 16384 and 2097151 */ + a &= (0x7f<<14)|(0x7f); + b &= 0x7f; + b = b<<7; + *v = a | b; + return 3; + } + + /* A 32-bit varint is used to store size information in btrees. + ** Objects are rarely larger than 2MiB limit of a 3-byte varint. + ** A 3-byte varint is sufficient, for example, to record the size + ** of a 1048569-byte BLOB or string. + ** + ** We only unroll the first 1-, 2-, and 3- byte cases. The very + ** rare larger cases can be handled by the slower 64-bit varint + ** routine. + */ +#if 1 + { + u64 v64; + u8 n; + + p -= 2; + n = sqlite3GetVarint(p, &v64); + assert( n>3 && n<=9 ); + if( (v64 & SQLITE_MAX_U32)!=v64 ){ + *v = 0xffffffff; + }else{ + *v = (u32)v64; + } + return n; + } + +#else + /* For following code (kept for historical record only) shows an + ** unrolling for the 3- and 4-byte varint cases. This code is + ** slightly faster, but it is also larger and much harder to test. + */ + p++; + b = b<<14; + b |= *p; + /* b: p1<<14 | p3 (unmasked) */ + if (!(b&0x80)) + { + /* Values between 2097152 and 268435455 */ + b &= (0x7f<<14)|(0x7f); + a &= (0x7f<<14)|(0x7f); + a = a<<7; + *v = a | b; + return 4; + } + + p++; + a = a<<14; + a |= *p; + /* a: p0<<28 | p2<<14 | p4 (unmasked) */ + if (!(a&0x80)) + { + /* Values between 268435456 and 34359738367 */ + a &= SLOT_4_2_0; + b &= SLOT_4_2_0; + b = b<<7; + *v = a | b; + return 5; + } + + /* We can only reach this point when reading a corrupt database + ** file. In that case we are not in any hurry. Use the (relatively + ** slow) general-purpose sqlite3GetVarint() routine to extract the + ** value. */ + { + u64 v64; + u8 n; + + p -= 4; + n = sqlite3GetVarint(p, &v64); + assert( n>5 && n<=9 ); + *v = (u32)v64; + return n; + } +#endif +} + +/* +** Return the number of bytes that will be needed to store the given +** 64-bit integer. +*/ +SQLITE_PRIVATE int sqlite3VarintLen(u64 v){ + int i = 0; + do{ + i++; + v >>= 7; + }while( v!=0 && ALWAYS(i<9) ); + return i; +} + + +/* +** Read or write a four-byte big-endian integer value. +*/ +SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){ +#if SQLITE_BYTEORDER==4321 + u32 x; + memcpy(&x,p,4); + return x; +#elif SQLITE_BYTEORDER==1234 && defined(__GNUC__) && GCC_VERSION>=4003000 + u32 x; + memcpy(&x,p,4); + return __builtin_bswap32(x); +#elif SQLITE_BYTEORDER==1234 && defined(_MSC_VER) && _MSC_VER>=1300 + u32 x; + memcpy(&x,p,4); + return _byteswap_ulong(x); +#else + testcase( p[0]&0x80 ); + return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; +#endif +} +SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){ +#if SQLITE_BYTEORDER==4321 + memcpy(p,&v,4); +#elif SQLITE_BYTEORDER==1234 && defined(__GNUC__) && GCC_VERSION>=4003000 + u32 x = __builtin_bswap32(v); + memcpy(p,&x,4); +#elif SQLITE_BYTEORDER==1234 && defined(_MSC_VER) && _MSC_VER>=1300 + u32 x = _byteswap_ulong(v); + memcpy(p,&x,4); +#else + p[0] = (u8)(v>>24); + p[1] = (u8)(v>>16); + p[2] = (u8)(v>>8); + p[3] = (u8)v; +#endif +} + + + +/* +** Translate a single byte of Hex into an integer. +** This routine only works if h really is a valid hexadecimal +** character: 0..9a..fA..F +*/ +SQLITE_PRIVATE u8 sqlite3HexToInt(int h){ + assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') ); +#ifdef SQLITE_ASCII + h += 9*(1&(h>>6)); +#endif +#ifdef SQLITE_EBCDIC + h += 9*(1&~(h>>4)); +#endif + return (u8)(h & 0xf); +} + +#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) +/* +** Convert a BLOB literal of the form "x'hhhhhh'" into its binary +** value. Return a pointer to its binary value. Space to hold the +** binary value has been obtained from malloc and must be freed by +** the calling routine. +*/ +SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){ + char *zBlob; + int i; + + zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1); + n--; + if( zBlob ){ + for(i=0; imagic; + if( magic!=SQLITE_MAGIC_OPEN ){ + if( sqlite3SafetyCheckSickOrOk(db) ){ + testcase( sqlite3GlobalConfig.xLog!=0 ); + logBadConnection("unopened"); + } + return 0; + }else{ + return 1; + } +} +SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ + u32 magic; + magic = db->magic; + if( magic!=SQLITE_MAGIC_SICK && + magic!=SQLITE_MAGIC_OPEN && + magic!=SQLITE_MAGIC_BUSY ){ + testcase( sqlite3GlobalConfig.xLog!=0 ); + logBadConnection("invalid"); + return 0; + }else{ + return 1; + } +} + +/* +** Attempt to add, substract, or multiply the 64-bit signed value iB against +** the other 64-bit signed integer at *pA and store the result in *pA. +** Return 0 on success. Or if the operation would have resulted in an +** overflow, leave *pA unchanged and return 1. +*/ +SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){ + i64 iA = *pA; + testcase( iA==0 ); testcase( iA==1 ); + testcase( iB==-1 ); testcase( iB==0 ); + if( iB>=0 ){ + testcase( iA>0 && LARGEST_INT64 - iA == iB ); + testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 ); + if( iA>0 && LARGEST_INT64 - iA < iB ) return 1; + }else{ + testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 ); + testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 ); + if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1; + } + *pA += iB; + return 0; +} +SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){ + testcase( iB==SMALLEST_INT64+1 ); + if( iB==SMALLEST_INT64 ){ + testcase( (*pA)==(-1) ); testcase( (*pA)==0 ); + if( (*pA)>=0 ) return 1; + *pA -= iB; + return 0; + }else{ + return sqlite3AddInt64(pA, -iB); + } +} +#define TWOPOWER32 (((i64)1)<<32) +#define TWOPOWER31 (((i64)1)<<31) +SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){ + i64 iA = *pA; + i64 iA1, iA0, iB1, iB0, r; + + iA1 = iA/TWOPOWER32; + iA0 = iA % TWOPOWER32; + iB1 = iB/TWOPOWER32; + iB0 = iB % TWOPOWER32; + if( iA1==0 ){ + if( iB1==0 ){ + *pA *= iB; + return 0; + } + r = iA0*iB1; + }else if( iB1==0 ){ + r = iA1*iB0; + }else{ + /* If both iA1 and iB1 are non-zero, overflow will result */ + return 1; + } + testcase( r==(-TWOPOWER31)-1 ); + testcase( r==(-TWOPOWER31) ); + testcase( r==TWOPOWER31 ); + testcase( r==TWOPOWER31-1 ); + if( r<(-TWOPOWER31) || r>=TWOPOWER31 ) return 1; + r *= TWOPOWER32; + if( sqlite3AddInt64(&r, iA0*iB0) ) return 1; + *pA = r; + return 0; +} + +/* +** Compute the absolute value of a 32-bit signed integer, of possible. Or +** if the integer has a value of -2147483648, return +2147483647 +*/ +SQLITE_PRIVATE int sqlite3AbsInt32(int x){ + if( x>=0 ) return x; + if( x==(int)0x80000000 ) return 0x7fffffff; + return -x; +} + +#ifdef SQLITE_ENABLE_8_3_NAMES +/* +** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database +** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and +** if filename in z[] has a suffix (a.k.a. "extension") that is longer than +** three characters, then shorten the suffix on z[] to be the last three +** characters of the original suffix. +** +** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always +** do the suffix shortening regardless of URI parameter. +** +** Examples: +** +** test.db-journal => test.nal +** test.db-wal => test.wal +** test.db-shm => test.shm +** test.db-mj7f3319fa => test.9fa +*/ +SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){ +#if SQLITE_ENABLE_8_3_NAMES<2 + if( sqlite3_uri_boolean(zBaseFilename, "8_3_names", 0) ) +#endif + { + int i, sz; + sz = sqlite3Strlen30(z); + for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} + if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4); + } +} +#endif + +/* +** Find (an approximate) sum of two LogEst values. This computation is +** not a simple "+" operator because LogEst is stored as a logarithmic +** value. +** +*/ +SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst a, LogEst b){ + static const unsigned char x[] = { + 10, 10, /* 0,1 */ + 9, 9, /* 2,3 */ + 8, 8, /* 4,5 */ + 7, 7, 7, /* 6,7,8 */ + 6, 6, 6, /* 9,10,11 */ + 5, 5, 5, /* 12-14 */ + 4, 4, 4, 4, /* 15-18 */ + 3, 3, 3, 3, 3, 3, /* 19-24 */ + 2, 2, 2, 2, 2, 2, 2, /* 25-31 */ + }; + if( a>=b ){ + if( a>b+49 ) return a; + if( a>b+31 ) return a+1; + return a+x[a-b]; + }else{ + if( b>a+49 ) return b; + if( b>a+31 ) return b+1; + return b+x[b-a]; + } +} + +/* +** Convert an integer into a LogEst. In other words, compute an +** approximation for 10*log2(x). +*/ +SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){ + static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 }; + LogEst y = 40; + if( x<8 ){ + if( x<2 ) return 0; + while( x<8 ){ y -= 10; x <<= 1; } + }else{ + while( x>255 ){ y += 40; x >>= 4; } + while( x>15 ){ y += 10; x >>= 1; } + } + return a[x&7] + y - 10; +} + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* +** Convert a double into a LogEst +** In other words, compute an approximation for 10*log2(x). +*/ +SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){ + u64 a; + LogEst e; + assert( sizeof(x)==8 && sizeof(a)==8 ); + if( x<=1 ) return 0; + if( x<=2000000000 ) return sqlite3LogEst((u64)x); + memcpy(&a, &x, 8); + e = (a>>52) - 1022; + return e*10; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +/* +** Convert a LogEst into an integer. +*/ +SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){ + u64 n; + if( x<10 ) return 1; + n = x%10; + x /= 10; + if( n>=5 ) n -= 2; + else if( n>=1 ) n -= 1; + if( x>=3 ){ + return x>60 ? (u64)LARGEST_INT64 : (n+8)<<(x-3); + } + return (n+8)>>(3-x); +} + +/************** End of util.c ************************************************/ +/************** Begin file hash.c ********************************************/ +/* +** 2001 September 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This is the implementation of generic hash-tables +** used in SQLite. +*/ +/* #include "sqliteInt.h" */ +/* #include */ + +/* Turn bulk memory into a hash table object by initializing the +** fields of the Hash structure. +** +** "pNew" is a pointer to the hash table that is to be initialized. +*/ +SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew){ + assert( pNew!=0 ); + pNew->first = 0; + pNew->count = 0; + pNew->htsize = 0; + pNew->ht = 0; +} + +/* Remove all entries from a hash table. Reclaim all memory. +** Call this routine to delete a hash table or to reset a hash table +** to the empty state. +*/ +SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){ + HashElem *elem; /* For looping over all elements of the table */ + + assert( pH!=0 ); + elem = pH->first; + pH->first = 0; + sqlite3_free(pH->ht); + pH->ht = 0; + pH->htsize = 0; + while( elem ){ + HashElem *next_elem = elem->next; + sqlite3_free(elem); + elem = next_elem; + } + pH->count = 0; +} + +/* +** The hashing function. +*/ +static unsigned int strHash(const char *z){ + unsigned int h = 0; + unsigned char c; + while( (c = (unsigned char)*z++)!=0 ){ + h = (h<<3) ^ h ^ sqlite3UpperToLower[c]; + } + return h; +} + + +/* Link pNew element into the hash table pH. If pEntry!=0 then also +** insert pNew into the pEntry hash bucket. +*/ +static void insertElement( + Hash *pH, /* The complete hash table */ + struct _ht *pEntry, /* The entry into which pNew is inserted */ + HashElem *pNew /* The element to be inserted */ +){ + HashElem *pHead; /* First element already in pEntry */ + if( pEntry ){ + pHead = pEntry->count ? pEntry->chain : 0; + pEntry->count++; + pEntry->chain = pNew; + }else{ + pHead = 0; + } + if( pHead ){ + pNew->next = pHead; + pNew->prev = pHead->prev; + if( pHead->prev ){ pHead->prev->next = pNew; } + else { pH->first = pNew; } + pHead->prev = pNew; + }else{ + pNew->next = pH->first; + if( pH->first ){ pH->first->prev = pNew; } + pNew->prev = 0; + pH->first = pNew; + } +} + + +/* Resize the hash table so that it cantains "new_size" buckets. +** +** The hash table might fail to resize if sqlite3_malloc() fails or +** if the new size is the same as the prior size. +** Return TRUE if the resize occurs and false if not. +*/ +static int rehash(Hash *pH, unsigned int new_size){ + struct _ht *new_ht; /* The new hash table */ + HashElem *elem, *next_elem; /* For looping over existing elements */ + +#if SQLITE_MALLOC_SOFT_LIMIT>0 + if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){ + new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht); + } + if( new_size==pH->htsize ) return 0; +#endif + + /* The inability to allocates space for a larger hash table is + ** a performance hit but it is not a fatal error. So mark the + ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of + ** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero() + ** only zeroes the requested number of bytes whereas this module will + ** use the actual amount of space allocated for the hash table (which + ** may be larger than the requested amount). + */ + sqlite3BeginBenignMalloc(); + new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) ); + sqlite3EndBenignMalloc(); + + if( new_ht==0 ) return 0; + sqlite3_free(pH->ht); + pH->ht = new_ht; + pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht); + memset(new_ht, 0, new_size*sizeof(struct _ht)); + for(elem=pH->first, pH->first=0; elem; elem = next_elem){ + unsigned int h = strHash(elem->pKey) % new_size; + next_elem = elem->next; + insertElement(pH, &new_ht[h], elem); + } + return 1; +} + +/* This function (for internal use only) locates an element in an +** hash table that matches the given key. The hash for this key is +** also computed and returned in the *pH parameter. +*/ +static HashElem *findElementWithHash( + const Hash *pH, /* The pH to be searched */ + const char *pKey, /* The key we are searching for */ + unsigned int *pHash /* Write the hash value here */ +){ + HashElem *elem; /* Used to loop thru the element list */ + int count; /* Number of elements left to test */ + unsigned int h; /* The computed hash */ + + if( pH->ht ){ + struct _ht *pEntry; + h = strHash(pKey) % pH->htsize; + pEntry = &pH->ht[h]; + elem = pEntry->chain; + count = pEntry->count; + }else{ + h = 0; + elem = pH->first; + count = pH->count; + } + *pHash = h; + while( count-- ){ + assert( elem!=0 ); + if( sqlite3StrICmp(elem->pKey,pKey)==0 ){ + return elem; + } + elem = elem->next; + } + return 0; +} + +/* Remove a single entry from the hash table given a pointer to that +** element and a hash on the element's key. +*/ +static void removeElementGivenHash( + Hash *pH, /* The pH containing "elem" */ + HashElem* elem, /* The element to be removed from the pH */ + unsigned int h /* Hash value for the element */ +){ + struct _ht *pEntry; + if( elem->prev ){ + elem->prev->next = elem->next; + }else{ + pH->first = elem->next; + } + if( elem->next ){ + elem->next->prev = elem->prev; + } + if( pH->ht ){ + pEntry = &pH->ht[h]; + if( pEntry->chain==elem ){ + pEntry->chain = elem->next; + } + pEntry->count--; + assert( pEntry->count>=0 ); + } + sqlite3_free( elem ); + pH->count--; + if( pH->count==0 ){ + assert( pH->first==0 ); + assert( pH->count==0 ); + sqlite3HashClear(pH); + } +} + +/* Attempt to locate an element of the hash table pH with a key +** that matches pKey. Return the data for this element if it is +** found, or NULL if there is no match. +*/ +SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey){ + HashElem *elem; /* The element that matches key */ + unsigned int h; /* A hash on key */ + + assert( pH!=0 ); + assert( pKey!=0 ); + elem = findElementWithHash(pH, pKey, &h); + return elem ? elem->data : 0; +} + +/* Insert an element into the hash table pH. The key is pKey +** and the data is "data". +** +** If no element exists with a matching key, then a new +** element is created and NULL is returned. +** +** If another element already exists with the same key, then the +** new data replaces the old data and the old data is returned. +** The key is not copied in this instance. If a malloc fails, then +** the new data is returned and the hash table is unchanged. +** +** If the "data" parameter to this function is NULL, then the +** element corresponding to "key" is removed from the hash table. +*/ +SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){ + unsigned int h; /* the hash of the key modulo hash table size */ + HashElem *elem; /* Used to loop thru the element list */ + HashElem *new_elem; /* New element added to the pH */ + + assert( pH!=0 ); + assert( pKey!=0 ); + elem = findElementWithHash(pH,pKey,&h); + if( elem ){ + void *old_data = elem->data; + if( data==0 ){ + removeElementGivenHash(pH,elem,h); + }else{ + elem->data = data; + elem->pKey = pKey; + } + return old_data; + } + if( data==0 ) return 0; + new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) ); + if( new_elem==0 ) return data; + new_elem->pKey = pKey; + new_elem->data = data; + pH->count++; + if( pH->count>=10 && pH->count > 2*pH->htsize ){ + if( rehash(pH, pH->count*2) ){ + assert( pH->htsize>0 ); + h = strHash(pKey) % pH->htsize; + } + } + insertElement(pH, pH->ht ? &pH->ht[h] : 0, new_elem); + return 0; +} + +/************** End of hash.c ************************************************/ +/************** Begin file opcodes.c *****************************************/ +/* Automatically generated. Do not edit */ +/* See the mkopcodec.awk script for details. */ +#if !defined(SQLITE_OMIT_EXPLAIN) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) +#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) || defined(SQLITE_DEBUG) +# define OpHelp(X) "\0" X +#else +# define OpHelp(X) +#endif +SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ + static const char *const azName[] = { "?", + /* 1 */ "Savepoint" OpHelp(""), + /* 2 */ "AutoCommit" OpHelp(""), + /* 3 */ "Transaction" OpHelp(""), + /* 4 */ "SorterNext" OpHelp(""), + /* 5 */ "PrevIfOpen" OpHelp(""), + /* 6 */ "NextIfOpen" OpHelp(""), + /* 7 */ "Prev" OpHelp(""), + /* 8 */ "Next" OpHelp(""), + /* 9 */ "Checkpoint" OpHelp(""), + /* 10 */ "JournalMode" OpHelp(""), + /* 11 */ "Vacuum" OpHelp(""), + /* 12 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), + /* 13 */ "VUpdate" OpHelp("data=r[P3@P2]"), + /* 14 */ "Goto" OpHelp(""), + /* 15 */ "Gosub" OpHelp(""), + /* 16 */ "Return" OpHelp(""), + /* 17 */ "InitCoroutine" OpHelp(""), + /* 18 */ "EndCoroutine" OpHelp(""), + /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), + /* 20 */ "Yield" OpHelp(""), + /* 21 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), + /* 22 */ "Halt" OpHelp(""), + /* 23 */ "Integer" OpHelp("r[P2]=P1"), + /* 24 */ "Int64" OpHelp("r[P2]=P4"), + /* 25 */ "String" OpHelp("r[P2]='P4' (len=P1)"), + /* 26 */ "Null" OpHelp("r[P2..P3]=NULL"), + /* 27 */ "SoftNull" OpHelp("r[P1]=NULL"), + /* 28 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), + /* 29 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), + /* 30 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), + /* 31 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), + /* 32 */ "SCopy" OpHelp("r[P2]=r[P1]"), + /* 33 */ "ResultRow" OpHelp("output=r[P1@P2]"), + /* 34 */ "CollSeq" OpHelp(""), + /* 35 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), + /* 36 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), + /* 37 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), + /* 38 */ "MustBeInt" OpHelp(""), + /* 39 */ "RealAffinity" OpHelp(""), + /* 40 */ "Cast" OpHelp("affinity(r[P1])"), + /* 41 */ "Permutation" OpHelp(""), + /* 42 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), + /* 43 */ "Jump" OpHelp(""), + /* 44 */ "Once" OpHelp(""), + /* 45 */ "If" OpHelp(""), + /* 46 */ "IfNot" OpHelp(""), + /* 47 */ "Column" OpHelp("r[P3]=PX"), + /* 48 */ "Affinity" OpHelp("affinity(r[P1@P2])"), + /* 49 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), + /* 50 */ "Count" OpHelp("r[P2]=count()"), + /* 51 */ "ReadCookie" OpHelp(""), + /* 52 */ "SetCookie" OpHelp(""), + /* 53 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), + /* 54 */ "OpenRead" OpHelp("root=P2 iDb=P3"), + /* 55 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 56 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 57 */ "OpenEphemeral" OpHelp("nColumn=P2"), + /* 58 */ "SorterOpen" OpHelp(""), + /* 59 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), + /* 60 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), + /* 61 */ "Close" OpHelp(""), + /* 62 */ "ColumnsUsed" OpHelp(""), + /* 63 */ "SeekLT" OpHelp("key=r[P3@P4]"), + /* 64 */ "SeekLE" OpHelp("key=r[P3@P4]"), + /* 65 */ "SeekGE" OpHelp("key=r[P3@P4]"), + /* 66 */ "SeekGT" OpHelp("key=r[P3@P4]"), + /* 67 */ "Seek" OpHelp("intkey=r[P2]"), + /* 68 */ "NoConflict" OpHelp("key=r[P3@P4]"), + /* 69 */ "NotFound" OpHelp("key=r[P3@P4]"), + /* 70 */ "Found" OpHelp("key=r[P3@P4]"), + /* 71 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), + /* 72 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), + /* 73 */ "NotExists" OpHelp("intkey=r[P3]"), + /* 74 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), + /* 75 */ "NewRowid" OpHelp("r[P2]=rowid"), + /* 76 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), + /* 77 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), + /* 78 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"), + /* 79 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"), + /* 80 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"), + /* 81 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"), + /* 82 */ "Lt" OpHelp("if r[P1]=r[P3] goto P2"), + /* 84 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), + /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), + /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), + /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), + /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), + /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), + /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), + /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), + /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), + /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), + /* 95 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), + /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), + /* 97 */ "String8" OpHelp("r[P2]='P4'"), + /* 98 */ "Delete" OpHelp(""), + /* 99 */ "ResetCount" OpHelp(""), + /* 100 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), + /* 101 */ "SorterData" OpHelp("r[P2]=data"), + /* 102 */ "RowKey" OpHelp("r[P2]=key"), + /* 103 */ "RowData" OpHelp("r[P2]=data"), + /* 104 */ "Rowid" OpHelp("r[P2]=rowid"), + /* 105 */ "NullRow" OpHelp(""), + /* 106 */ "Last" OpHelp(""), + /* 107 */ "SorterSort" OpHelp(""), + /* 108 */ "Sort" OpHelp(""), + /* 109 */ "Rewind" OpHelp(""), + /* 110 */ "SorterInsert" OpHelp(""), + /* 111 */ "IdxInsert" OpHelp("key=r[P2]"), + /* 112 */ "IdxDelete" OpHelp("key=r[P2@P3]"), + /* 113 */ "IdxRowid" OpHelp("r[P2]=rowid"), + /* 114 */ "IdxLE" OpHelp("key=r[P3@P4]"), + /* 115 */ "IdxGT" OpHelp("key=r[P3@P4]"), + /* 116 */ "IdxLT" OpHelp("key=r[P3@P4]"), + /* 117 */ "IdxGE" OpHelp("key=r[P3@P4]"), + /* 118 */ "Destroy" OpHelp(""), + /* 119 */ "Clear" OpHelp(""), + /* 120 */ "ResetSorter" OpHelp(""), + /* 121 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), + /* 122 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), + /* 123 */ "ParseSchema" OpHelp(""), + /* 124 */ "LoadAnalysis" OpHelp(""), + /* 125 */ "DropTable" OpHelp(""), + /* 126 */ "DropIndex" OpHelp(""), + /* 127 */ "DropTrigger" OpHelp(""), + /* 128 */ "IntegrityCk" OpHelp(""), + /* 129 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), + /* 130 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), + /* 131 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), + /* 132 */ "Program" OpHelp(""), + /* 133 */ "Real" OpHelp("r[P2]=P4"), + /* 134 */ "Param" OpHelp(""), + /* 135 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), + /* 136 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), + /* 137 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), + /* 138 */ "IfPos" OpHelp("if r[P1]>0 goto P2"), + /* 139 */ "IfNeg" OpHelp("r[P1]+=P3, if r[P1]<0 goto P2"), + /* 140 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]+=P3, goto P2"), + /* 141 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), + /* 142 */ "JumpZeroIncr" OpHelp("if (r[P1]++)==0 ) goto P2"), + /* 143 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 144 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 145 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), + /* 146 */ "IncrVacuum" OpHelp(""), + /* 147 */ "Expire" OpHelp(""), + /* 148 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), + /* 149 */ "VBegin" OpHelp(""), + /* 150 */ "VCreate" OpHelp(""), + /* 151 */ "VDestroy" OpHelp(""), + /* 152 */ "VOpen" OpHelp(""), + /* 153 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), + /* 154 */ "VNext" OpHelp(""), + /* 155 */ "VRename" OpHelp(""), + /* 156 */ "Pagecount" OpHelp(""), + /* 157 */ "MaxPgcnt" OpHelp(""), + /* 158 */ "Init" OpHelp("Start at P2"), + /* 159 */ "Noop" OpHelp(""), + /* 160 */ "Explain" OpHelp(""), + }; + return azName[i]; +} +#endif + +/************** End of opcodes.c *********************************************/ +/************** Begin file os_unix.c *****************************************/ +/* +** 2004 May 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains the VFS implementation for unix-like operating systems +** include Linux, MacOSX, *BSD, QNX, VxWorks, AIX, HPUX, and others. +** +** There are actually several different VFS implementations in this file. +** The differences are in the way that file locking is done. The default +** implementation uses Posix Advisory Locks. Alternative implementations +** use flock(), dot-files, various proprietary locking schemas, or simply +** skip locking all together. +** +** This source file is organized into divisions where the logic for various +** subfunctions is contained within the appropriate division. PLEASE +** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed +** in the correct division and should be clearly labeled. +** +** The layout of divisions is as follows: +** +** * General-purpose declarations and utility functions. +** * Unique file ID logic used by VxWorks. +** * Various locking primitive implementations (all except proxy locking): +** + for Posix Advisory Locks +** + for no-op locks +** + for dot-file locks +** + for flock() locking +** + for named semaphore locks (VxWorks only) +** + for AFP filesystem locks (MacOSX only) +** * sqlite3_file methods not associated with locking. +** * Definitions of sqlite3_io_methods objects for all locking +** methods plus "finder" functions for each locking method. +** * sqlite3_vfs method implementations. +** * Locking primitives for the proxy uber-locking-method. (MacOSX only) +** * Definitions of sqlite3_vfs objects for all locking methods +** plus implementations of sqlite3_os_init() and sqlite3_os_end(). +*/ +/* #include "sqliteInt.h" */ +#if SQLITE_OS_UNIX /* This file is used on unix only */ + +/* +** There are various methods for file locking used for concurrency +** control: +** +** 1. POSIX locking (the default), +** 2. No locking, +** 3. Dot-file locking, +** 4. flock() locking, +** 5. AFP locking (OSX only), +** 6. Named POSIX semaphores (VXWorks only), +** 7. proxy locking. (OSX only) +** +** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE +** is defined to 1. The SQLITE_ENABLE_LOCKING_STYLE also enables automatic +** selection of the appropriate locking style based on the filesystem +** where the database is located. +*/ +#if !defined(SQLITE_ENABLE_LOCKING_STYLE) +# if defined(__APPLE__) +# define SQLITE_ENABLE_LOCKING_STYLE 1 +# else +# define SQLITE_ENABLE_LOCKING_STYLE 0 +# endif +#endif + +/* +** standard include files. +*/ +#include +#include +#include +#include +/* #include */ +#include +#include +#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 +# include +#endif + +#if SQLITE_ENABLE_LOCKING_STYLE +# include +# include +# include +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +#if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \ + (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000)) +# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \ + && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0)) +# define HAVE_GETHOSTUUID 1 +# else +# warning "gethostuuid() is disabled." +# endif +#endif + + +#if OS_VXWORKS +/* # include */ +# include +# include +#endif /* OS_VXWORKS */ + +#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE +# include +#endif + +#ifdef HAVE_UTIME +# include +#endif + +/* +** Allowed values of unixFile.fsFlags +*/ +#define SQLITE_FSFLAGS_IS_MSDOS 0x1 + +/* +** If we are to be thread-safe, include the pthreads header and define +** the SQLITE_UNIX_THREADS macro. +*/ +#if SQLITE_THREADSAFE +/* # include */ +# define SQLITE_UNIX_THREADS 1 +#endif + +/* +** Default permissions when creating a new file +*/ +#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS +# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644 +#endif + +/* +** Default permissions when creating auto proxy dir +*/ +#ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS +# define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755 +#endif + +/* +** Maximum supported path-length. +*/ +#define MAX_PATHNAME 512 + +/* Always cast the getpid() return type for compatibility with +** kernel modules in VxWorks. */ +#define osGetpid(X) (pid_t)getpid() + +/* +** Only set the lastErrno if the error code is a real error and not +** a normal expected return code of SQLITE_BUSY or SQLITE_OK +*/ +#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY)) + +/* Forward references */ +typedef struct unixShm unixShm; /* Connection shared memory */ +typedef struct unixShmNode unixShmNode; /* Shared memory instance */ +typedef struct unixInodeInfo unixInodeInfo; /* An i-node */ +typedef struct UnixUnusedFd UnixUnusedFd; /* An unused file descriptor */ + +/* +** Sometimes, after a file handle is closed by SQLite, the file descriptor +** cannot be closed immediately. In these cases, instances of the following +** structure are used to store the file descriptor while waiting for an +** opportunity to either close or reuse it. +*/ +struct UnixUnusedFd { + int fd; /* File descriptor to close */ + int flags; /* Flags this file descriptor was opened with */ + UnixUnusedFd *pNext; /* Next unused file descriptor on same file */ +}; + +/* +** The unixFile structure is subclass of sqlite3_file specific to the unix +** VFS implementations. +*/ +typedef struct unixFile unixFile; +struct unixFile { + sqlite3_io_methods const *pMethod; /* Always the first entry */ + sqlite3_vfs *pVfs; /* The VFS that created this unixFile */ + unixInodeInfo *pInode; /* Info about locks on this inode */ + int h; /* The file descriptor */ + unsigned char eFileLock; /* The type of lock held on this fd */ + unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ + int lastErrno; /* The unix errno from last I/O error */ + void *lockingContext; /* Locking style specific state */ + UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ + const char *zPath; /* Name of the file */ + unixShm *pShm; /* Shared memory segment information */ + int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ +#if SQLITE_MAX_MMAP_SIZE>0 + int nFetchOut; /* Number of outstanding xFetch refs */ + sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */ + sqlite3_int64 mmapSizeActual; /* Actual size of mapping at pMapRegion */ + sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ + void *pMapRegion; /* Memory mapped region */ +#endif +#ifdef __QNXNTO__ + int sectorSize; /* Device sector size */ + int deviceCharacteristics; /* Precomputed device characteristics */ +#endif +#if SQLITE_ENABLE_LOCKING_STYLE + int openFlags; /* The flags specified at open() */ +#endif +#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) + unsigned fsFlags; /* cached details from statfs() */ +#endif +#if OS_VXWORKS + struct vxworksFileId *pId; /* Unique file ID */ +#endif +#ifdef SQLITE_DEBUG + /* The next group of variables are used to track whether or not the + ** transaction counter in bytes 24-27 of database files are updated + ** whenever any part of the database changes. An assertion fault will + ** occur if a file is updated without also updating the transaction + ** counter. This test is made to avoid new problems similar to the + ** one described by ticket #3584. + */ + unsigned char transCntrChng; /* True if the transaction counter changed */ + unsigned char dbUpdate; /* True if any part of database file changed */ + unsigned char inNormalWrite; /* True if in a normal write operation */ + +#endif + +#ifdef SQLITE_TEST + /* In test mode, increase the size of this structure a bit so that + ** it is larger than the struct CrashFile defined in test6.c. + */ + char aPadding[32]; +#endif +}; + +/* This variable holds the process id (pid) from when the xRandomness() +** method was called. If xOpen() is called from a different process id, +** indicating that a fork() has occurred, the PRNG will be reset. +*/ +static pid_t randomnessPid = 0; + +/* +** Allowed values for the unixFile.ctrlFlags bitmask: +*/ +#define UNIXFILE_EXCL 0x01 /* Connections from one process only */ +#define UNIXFILE_RDONLY 0x02 /* Connection is read only */ +#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */ +#ifndef SQLITE_DISABLE_DIRSYNC +# define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */ +#else +# define UNIXFILE_DIRSYNC 0x00 +#endif +#define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ +#define UNIXFILE_DELETE 0x20 /* Delete on close */ +#define UNIXFILE_URI 0x40 /* Filename might have query parameters */ +#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */ +#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings issued */ +#define UNIXFILE_BLOCK 0x0200 /* Next SHM lock might block */ + +/* +** Include code that is common to all os_*.c files +*/ +/************** Include os_common.h in the middle of os_unix.c ***************/ +/************** Begin file os_common.h ***************************************/ +/* +** 2004 May 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains macros and a little bit of code that is common to +** all of the platform-specific files (os_*.c) and is #included into those +** files. +** +** This file should be #included by the os_*.c files only. It is not a +** general purpose header file. +*/ +#ifndef _OS_COMMON_H_ +#define _OS_COMMON_H_ + +/* +** At least two bugs have slipped in because we changed the MEMORY_DEBUG +** macro to SQLITE_DEBUG and some older makefiles have not yet made the +** switch. The following code should catch this problem at compile-time. +*/ +#ifdef MEMORY_DEBUG +# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." +#endif + +/* +** Macros for performance tracing. Normally turned off. Only works +** on i486 hardware. +*/ +#ifdef SQLITE_PERFORMANCE_TRACE + +/* +** hwtime.h contains inline assembler code for implementing +** high-performance timing routines. +*/ +/************** Include hwtime.h in the middle of os_common.h ****************/ +/************** Begin file hwtime.h ******************************************/ +/* +** 2008 May 27 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains inline asm code for retrieving "high-performance" +** counters for x86 class CPUs. +*/ +#ifndef _HWTIME_H_ +#define _HWTIME_H_ + +/* +** The following routine only works on pentium-class (or newer) processors. +** It uses the RDTSC opcode to read the cycle count value out of the +** processor and returns that value. This can be used for high-res +** profiling. +*/ +#if (defined(__GNUC__) || defined(_MSC_VER)) && \ + (defined(i386) || defined(__i386__) || defined(_M_IX86)) + + #if defined(__GNUC__) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned int lo, hi; + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + return (sqlite_uint64)hi << 32 | lo; + } + + #elif defined(_MSC_VER) + + __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ + __asm { + rdtsc + ret ; return value at EDX:EAX + } + } + + #endif + +#elif (defined(__GNUC__) && defined(__x86_64__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long val; + __asm__ __volatile__ ("rdtsc" : "=A" (val)); + return val; + } + +#elif (defined(__GNUC__) && defined(__ppc__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long long retval; + unsigned long junk; + __asm__ __volatile__ ("\n\ + 1: mftbu %1\n\ + mftb %L0\n\ + mftbu %0\n\ + cmpw %0,%1\n\ + bne 1b" + : "=r" (retval), "=r" (junk)); + return retval; + } + +#else + + #error Need implementation of sqlite3Hwtime() for your platform. + + /* + ** To compile without implementing sqlite3Hwtime() for your platform, + ** you can remove the above #error and use the following + ** stub function. You will lose timing support for many + ** of the debugging and testing utilities, but it should at + ** least compile and run. + */ +SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } + +#endif + +#endif /* !defined(_HWTIME_H_) */ + +/************** End of hwtime.h **********************************************/ +/************** Continuing where we left off in os_common.h ******************/ + +static sqlite_uint64 g_start; +static sqlite_uint64 g_elapsed; +#define TIMER_START g_start=sqlite3Hwtime() +#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start +#define TIMER_ELAPSED g_elapsed +#else +#define TIMER_START +#define TIMER_END +#define TIMER_ELAPSED ((sqlite_uint64)0) +#endif + +/* +** If we compile with the SQLITE_TEST macro set, then the following block +** of code will give us the ability to simulate a disk I/O error. This +** is used for testing the I/O recovery logic. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */ +SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */ +SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */ +SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */ +SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */ +SQLITE_API int sqlite3_diskfull_pending = 0; +SQLITE_API int sqlite3_diskfull = 0; +#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) +#define SimulateIOError(CODE) \ + if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ + || sqlite3_io_error_pending-- == 1 ) \ + { local_ioerr(); CODE; } +static void local_ioerr(){ + IOTRACE(("IOERR\n")); + sqlite3_io_error_hit++; + if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++; +} +#define SimulateDiskfullError(CODE) \ + if( sqlite3_diskfull_pending ){ \ + if( sqlite3_diskfull_pending == 1 ){ \ + local_ioerr(); \ + sqlite3_diskfull = 1; \ + sqlite3_io_error_hit = 1; \ + CODE; \ + }else{ \ + sqlite3_diskfull_pending--; \ + } \ + } +#else +#define SimulateIOErrorBenign(X) +#define SimulateIOError(A) +#define SimulateDiskfullError(A) +#endif + +/* +** When testing, keep a count of the number of open files. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_open_file_count = 0; +#define OpenCounter(X) sqlite3_open_file_count+=(X) +#else +#define OpenCounter(X) +#endif + +#endif /* !defined(_OS_COMMON_H_) */ + +/************** End of os_common.h *******************************************/ +/************** Continuing where we left off in os_unix.c ********************/ + +/* +** Define various macros that are missing from some systems. +*/ +#ifndef O_LARGEFILE +# define O_LARGEFILE 0 +#endif +#ifdef SQLITE_DISABLE_LFS +# undef O_LARGEFILE +# define O_LARGEFILE 0 +#endif +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0 +#endif +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +/* +** The threadid macro resolves to the thread-id or to 0. Used for +** testing and debugging only. +*/ +#if SQLITE_THREADSAFE +#define threadid pthread_self() +#else +#define threadid 0 +#endif + +/* +** HAVE_MREMAP defaults to true on Linux and false everywhere else. +*/ +#if !defined(HAVE_MREMAP) +# if defined(__linux__) && defined(_GNU_SOURCE) +# define HAVE_MREMAP 1 +# else +# define HAVE_MREMAP 0 +# endif +#endif + +/* +** Explicitly call the 64-bit version of lseek() on Android. Otherwise, lseek() +** is the 32-bit version, even if _FILE_OFFSET_BITS=64 is defined. +*/ +#ifdef __ANDROID__ +# define lseek lseek64 +#endif + +/* +** Different Unix systems declare open() in different ways. Same use +** open(const char*,int,mode_t). Others use open(const char*,int,...). +** The difference is important when using a pointer to the function. +** +** The safest way to deal with the problem is to always use this wrapper +** which always has the same well-defined interface. +*/ +static int posixOpen(const char *zFile, int flags, int mode){ + return open(zFile, flags, mode); +} + +/* +** On some systems, calls to fchown() will trigger a message in a security +** log if they come from non-root processes. So avoid calling fchown() if +** we are not running as root. +*/ +static int posixFchown(int fd, uid_t uid, gid_t gid){ +#if OS_VXWORKS + return 0; +#else + return geteuid() ? 0 : fchown(fd,uid,gid); +#endif +} + +/* Forward reference */ +static int openDirectory(const char*, int*); +static int unixGetpagesize(void); + +/* +** Many system calls are accessed through pointer-to-functions so that +** they may be overridden at runtime to facilitate fault injection during +** testing and sandboxing. The following array holds the names and pointers +** to all overrideable system calls. +*/ +static struct unix_syscall { + const char *zName; /* Name of the system call */ + sqlite3_syscall_ptr pCurrent; /* Current value of the system call */ + sqlite3_syscall_ptr pDefault; /* Default value */ +} aSyscall[] = { + { "open", (sqlite3_syscall_ptr)posixOpen, 0 }, +#define osOpen ((int(*)(const char*,int,int))aSyscall[0].pCurrent) + + { "close", (sqlite3_syscall_ptr)close, 0 }, +#define osClose ((int(*)(int))aSyscall[1].pCurrent) + + { "access", (sqlite3_syscall_ptr)access, 0 }, +#define osAccess ((int(*)(const char*,int))aSyscall[2].pCurrent) + + { "getcwd", (sqlite3_syscall_ptr)getcwd, 0 }, +#define osGetcwd ((char*(*)(char*,size_t))aSyscall[3].pCurrent) + + { "stat", (sqlite3_syscall_ptr)stat, 0 }, +#define osStat ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent) + +/* +** The DJGPP compiler environment looks mostly like Unix, but it +** lacks the fcntl() system call. So redefine fcntl() to be something +** that always succeeds. This means that locking does not occur under +** DJGPP. But it is DOS - what did you expect? +*/ +#ifdef __DJGPP__ + { "fstat", 0, 0 }, +#define osFstat(a,b,c) 0 +#else + { "fstat", (sqlite3_syscall_ptr)fstat, 0 }, +#define osFstat ((int(*)(int,struct stat*))aSyscall[5].pCurrent) +#endif + + { "ftruncate", (sqlite3_syscall_ptr)ftruncate, 0 }, +#define osFtruncate ((int(*)(int,off_t))aSyscall[6].pCurrent) + + { "fcntl", (sqlite3_syscall_ptr)fcntl, 0 }, +#define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent) + + { "read", (sqlite3_syscall_ptr)read, 0 }, +#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent) + +#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE + { "pread", (sqlite3_syscall_ptr)pread, 0 }, +#else + { "pread", (sqlite3_syscall_ptr)0, 0 }, +#endif +#define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent) + +#if defined(USE_PREAD64) + { "pread64", (sqlite3_syscall_ptr)pread64, 0 }, +#else + { "pread64", (sqlite3_syscall_ptr)0, 0 }, +#endif +#define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent) + + { "write", (sqlite3_syscall_ptr)write, 0 }, +#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent) + +#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE + { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 }, +#else + { "pwrite", (sqlite3_syscall_ptr)0, 0 }, +#endif +#define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\ + aSyscall[12].pCurrent) + +#if defined(USE_PREAD64) + { "pwrite64", (sqlite3_syscall_ptr)pwrite64, 0 }, +#else + { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, +#endif +#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\ + aSyscall[13].pCurrent) + + { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, +#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) + +#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE + { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, +#else + { "fallocate", (sqlite3_syscall_ptr)0, 0 }, +#endif +#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent) + + { "unlink", (sqlite3_syscall_ptr)unlink, 0 }, +#define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent) + + { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 }, +#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent) + + { "mkdir", (sqlite3_syscall_ptr)mkdir, 0 }, +#define osMkdir ((int(*)(const char*,mode_t))aSyscall[18].pCurrent) + + { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 }, +#define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent) + + { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 }, +#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) + +#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 + { "mmap", (sqlite3_syscall_ptr)mmap, 0 }, +#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent) + + { "munmap", (sqlite3_syscall_ptr)munmap, 0 }, +#define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent) + +#if HAVE_MREMAP + { "mremap", (sqlite3_syscall_ptr)mremap, 0 }, +#else + { "mremap", (sqlite3_syscall_ptr)0, 0 }, +#endif +#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent) + { "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 }, +#define osGetpagesize ((int(*)(void))aSyscall[24].pCurrent) + +#endif + +}; /* End of the overrideable system calls */ + +/* +** This is the xSetSystemCall() method of sqlite3_vfs for all of the +** "unix" VFSes. Return SQLITE_OK opon successfully updating the +** system call pointer, or SQLITE_NOTFOUND if there is no configurable +** system call named zName. +*/ +static int unixSetSystemCall( + sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */ + const char *zName, /* Name of system call to override */ + sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */ +){ + unsigned int i; + int rc = SQLITE_NOTFOUND; + + UNUSED_PARAMETER(pNotUsed); + if( zName==0 ){ + /* If no zName is given, restore all system calls to their default + ** settings and return NULL + */ + rc = SQLITE_OK; + for(i=0; i=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break; + osClose(fd); + sqlite3_log(SQLITE_WARNING, + "attempt to open \"%s\" as file descriptor %d", z, fd); + fd = -1; + if( osOpen("/dev/null", f, m)<0 ) break; + } + if( fd>=0 ){ + if( m!=0 ){ + struct stat statbuf; + if( osFstat(fd, &statbuf)==0 + && statbuf.st_size==0 + && (statbuf.st_mode&0777)!=m + ){ + osFchmod(fd, m); + } + } +#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) + osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); +#endif + } + return fd; +} + +/* +** Helper functions to obtain and relinquish the global mutex. The +** global mutex is used to protect the unixInodeInfo and +** vxworksFileId objects used by this file, all of which may be +** shared by multiple threads. +** +** Function unixMutexHeld() is used to assert() that the global mutex +** is held when required. This function is only used as part of assert() +** statements. e.g. +** +** unixEnterMutex() +** assert( unixMutexHeld() ); +** unixEnterLeave() +*/ +static void unixEnterMutex(void){ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); +} +static void unixLeaveMutex(void){ + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); +} +#ifdef SQLITE_DEBUG +static int unixMutexHeld(void) { + return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); +} +#endif + + +#ifdef SQLITE_HAVE_OS_TRACE +/* +** Helper function for printing out trace information from debugging +** binaries. This returns the string representation of the supplied +** integer lock-type. +*/ +static const char *azFileLock(int eFileLock){ + switch( eFileLock ){ + case NO_LOCK: return "NONE"; + case SHARED_LOCK: return "SHARED"; + case RESERVED_LOCK: return "RESERVED"; + case PENDING_LOCK: return "PENDING"; + case EXCLUSIVE_LOCK: return "EXCLUSIVE"; + } + return "ERROR"; +} +#endif + +#ifdef SQLITE_LOCK_TRACE +/* +** Print out information about all locking operations. +** +** This routine is used for troubleshooting locks on multithreaded +** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE +** command-line option on the compiler. This code is normally +** turned off. +*/ +static int lockTrace(int fd, int op, struct flock *p){ + char *zOpName, *zType; + int s; + int savedErrno; + if( op==F_GETLK ){ + zOpName = "GETLK"; + }else if( op==F_SETLK ){ + zOpName = "SETLK"; + }else{ + s = osFcntl(fd, op, p); + sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s); + return s; + } + if( p->l_type==F_RDLCK ){ + zType = "RDLCK"; + }else if( p->l_type==F_WRLCK ){ + zType = "WRLCK"; + }else if( p->l_type==F_UNLCK ){ + zType = "UNLCK"; + }else{ + assert( 0 ); + } + assert( p->l_whence==SEEK_SET ); + s = osFcntl(fd, op, p); + savedErrno = errno; + sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n", + threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len, + (int)p->l_pid, s); + if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){ + struct flock l2; + l2 = *p; + osFcntl(fd, F_GETLK, &l2); + if( l2.l_type==F_RDLCK ){ + zType = "RDLCK"; + }else if( l2.l_type==F_WRLCK ){ + zType = "WRLCK"; + }else if( l2.l_type==F_UNLCK ){ + zType = "UNLCK"; + }else{ + assert( 0 ); + } + sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n", + zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid); + } + errno = savedErrno; + return s; +} +#undef osFcntl +#define osFcntl lockTrace +#endif /* SQLITE_LOCK_TRACE */ + +/* +** Retry ftruncate() calls that fail due to EINTR +** +** All calls to ftruncate() within this file should be made through +** this wrapper. On the Android platform, bypassing the logic below +** could lead to a corrupt database. +*/ +static int robust_ftruncate(int h, sqlite3_int64 sz){ + int rc; +#ifdef __ANDROID__ + /* On Android, ftruncate() always uses 32-bit offsets, even if + ** _FILE_OFFSET_BITS=64 is defined. This means it is unsafe to attempt to + ** truncate a file to any size larger than 2GiB. Silently ignore any + ** such attempts. */ + if( sz>(sqlite3_int64)0x7FFFFFFF ){ + rc = SQLITE_OK; + }else +#endif + do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR ); + return rc; +} + +/* +** This routine translates a standard POSIX errno code into something +** useful to the clients of the sqlite3 functions. Specifically, it is +** intended to translate a variety of "try again" errors into SQLITE_BUSY +** and a variety of "please close the file descriptor NOW" errors into +** SQLITE_IOERR +** +** Errors during initialization of locks, or file system support for locks, +** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately. +*/ +static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) { + switch (posixError) { +#if 0 + /* At one point this code was not commented out. In theory, this branch + ** should never be hit, as this function should only be called after + ** a locking-related function (i.e. fcntl()) has returned non-zero with + ** the value of errno as the first argument. Since a system call has failed, + ** errno should be non-zero. + ** + ** Despite this, if errno really is zero, we still don't want to return + ** SQLITE_OK. The system call failed, and *some* SQLite error should be + ** propagated back to the caller. Commenting this branch out means errno==0 + ** will be handled by the "default:" case below. + */ + case 0: + return SQLITE_OK; +#endif + + case EAGAIN: + case ETIMEDOUT: + case EBUSY: + case EINTR: + case ENOLCK: + /* random NFS retry error, unless during file system support + * introspection, in which it actually means what it says */ + return SQLITE_BUSY; + + case EACCES: + /* EACCES is like EAGAIN during locking operations, but not any other time*/ + if( (sqliteIOErr == SQLITE_IOERR_LOCK) || + (sqliteIOErr == SQLITE_IOERR_UNLOCK) || + (sqliteIOErr == SQLITE_IOERR_RDLOCK) || + (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){ + return SQLITE_BUSY; + } + /* else fall through */ + case EPERM: + return SQLITE_PERM; + +#if EOPNOTSUPP!=ENOTSUP + case EOPNOTSUPP: + /* something went terribly awry, unless during file system support + * introspection, in which it actually means what it says */ +#endif +#ifdef ENOTSUP + case ENOTSUP: + /* invalid fd, unless during file system support introspection, in which + * it actually means what it says */ +#endif + case EIO: + case EBADF: + case EINVAL: + case ENOTCONN: + case ENODEV: + case ENXIO: + case ENOENT: +#ifdef ESTALE /* ESTALE is not defined on Interix systems */ + case ESTALE: +#endif + case ENOSYS: + /* these should force the client to close the file and reconnect */ + + default: + return sqliteIOErr; + } +} + + +/****************************************************************************** +****************** Begin Unique File ID Utility Used By VxWorks *************** +** +** On most versions of unix, we can get a unique ID for a file by concatenating +** the device number and the inode number. But this does not work on VxWorks. +** On VxWorks, a unique file id must be based on the canonical filename. +** +** A pointer to an instance of the following structure can be used as a +** unique file ID in VxWorks. Each instance of this structure contains +** a copy of the canonical filename. There is also a reference count. +** The structure is reclaimed when the number of pointers to it drops to +** zero. +** +** There are never very many files open at one time and lookups are not +** a performance-critical path, so it is sufficient to put these +** structures on a linked list. +*/ +struct vxworksFileId { + struct vxworksFileId *pNext; /* Next in a list of them all */ + int nRef; /* Number of references to this one */ + int nName; /* Length of the zCanonicalName[] string */ + char *zCanonicalName; /* Canonical filename */ +}; + +#if OS_VXWORKS +/* +** All unique filenames are held on a linked list headed by this +** variable: +*/ +static struct vxworksFileId *vxworksFileList = 0; + +/* +** Simplify a filename into its canonical form +** by making the following changes: +** +** * removing any trailing and duplicate / +** * convert /./ into just / +** * convert /A/../ where A is any simple name into just / +** +** Changes are made in-place. Return the new name length. +** +** The original filename is in z[0..n-1]. Return the number of +** characters in the simplified name. +*/ +static int vxworksSimplifyName(char *z, int n){ + int i, j; + while( n>1 && z[n-1]=='/' ){ n--; } + for(i=j=0; i0 && z[j-1]!='/' ){ j--; } + if( j>0 ){ j--; } + i += 2; + continue; + } + } + z[j++] = z[i]; + } + z[j] = 0; + return j; +} + +/* +** Find a unique file ID for the given absolute pathname. Return +** a pointer to the vxworksFileId object. This pointer is the unique +** file ID. +** +** The nRef field of the vxworksFileId object is incremented before +** the object is returned. A new vxworksFileId object is created +** and added to the global list if necessary. +** +** If a memory allocation error occurs, return NULL. +*/ +static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){ + struct vxworksFileId *pNew; /* search key and new file ID */ + struct vxworksFileId *pCandidate; /* For looping over existing file IDs */ + int n; /* Length of zAbsoluteName string */ + + assert( zAbsoluteName[0]=='/' ); + n = (int)strlen(zAbsoluteName); + pNew = sqlite3_malloc64( sizeof(*pNew) + (n+1) ); + if( pNew==0 ) return 0; + pNew->zCanonicalName = (char*)&pNew[1]; + memcpy(pNew->zCanonicalName, zAbsoluteName, n+1); + n = vxworksSimplifyName(pNew->zCanonicalName, n); + + /* Search for an existing entry that matching the canonical name. + ** If found, increment the reference count and return a pointer to + ** the existing file ID. + */ + unixEnterMutex(); + for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){ + if( pCandidate->nName==n + && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0 + ){ + sqlite3_free(pNew); + pCandidate->nRef++; + unixLeaveMutex(); + return pCandidate; + } + } + + /* No match was found. We will make a new file ID */ + pNew->nRef = 1; + pNew->nName = n; + pNew->pNext = vxworksFileList; + vxworksFileList = pNew; + unixLeaveMutex(); + return pNew; +} + +/* +** Decrement the reference count on a vxworksFileId object. Free +** the object when the reference count reaches zero. +*/ +static void vxworksReleaseFileId(struct vxworksFileId *pId){ + unixEnterMutex(); + assert( pId->nRef>0 ); + pId->nRef--; + if( pId->nRef==0 ){ + struct vxworksFileId **pp; + for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){} + assert( *pp==pId ); + *pp = pId->pNext; + sqlite3_free(pId); + } + unixLeaveMutex(); +} +#endif /* OS_VXWORKS */ +/*************** End of Unique File ID Utility Used By VxWorks **************** +******************************************************************************/ + + +/****************************************************************************** +*************************** Posix Advisory Locking **************************** +** +** POSIX advisory locks are broken by design. ANSI STD 1003.1 (1996) +** section 6.5.2.2 lines 483 through 490 specify that when a process +** sets or clears a lock, that operation overrides any prior locks set +** by the same process. It does not explicitly say so, but this implies +** that it overrides locks set by the same process using a different +** file descriptor. Consider this test case: +** +** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644); +** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644); +** +** Suppose ./file1 and ./file2 are really the same file (because +** one is a hard or symbolic link to the other) then if you set +** an exclusive lock on fd1, then try to get an exclusive lock +** on fd2, it works. I would have expected the second lock to +** fail since there was already a lock on the file due to fd1. +** But not so. Since both locks came from the same process, the +** second overrides the first, even though they were on different +** file descriptors opened on different file names. +** +** This means that we cannot use POSIX locks to synchronize file access +** among competing threads of the same process. POSIX locks will work fine +** to synchronize access for threads in separate processes, but not +** threads within the same process. +** +** To work around the problem, SQLite has to manage file locks internally +** on its own. Whenever a new database is opened, we have to find the +** specific inode of the database file (the inode is determined by the +** st_dev and st_ino fields of the stat structure that fstat() fills in) +** and check for locks already existing on that inode. When locks are +** created or removed, we have to look at our own internal record of the +** locks to see if another thread has previously set a lock on that same +** inode. +** +** (Aside: The use of inode numbers as unique IDs does not work on VxWorks. +** For VxWorks, we have to use the alternative unique ID system based on +** canonical filename and implemented in the previous division.) +** +** The sqlite3_file structure for POSIX is no longer just an integer file +** descriptor. It is now a structure that holds the integer file +** descriptor and a pointer to a structure that describes the internal +** locks on the corresponding inode. There is one locking structure +** per inode, so if the same inode is opened twice, both unixFile structures +** point to the same locking structure. The locking structure keeps +** a reference count (so we will know when to delete it) and a "cnt" +** field that tells us its internal lock status. cnt==0 means the +** file is unlocked. cnt==-1 means the file has an exclusive lock. +** cnt>0 means there are cnt shared locks on the file. +** +** Any attempt to lock or unlock a file first checks the locking +** structure. The fcntl() system call is only invoked to set a +** POSIX lock if the internal lock structure transitions between +** a locked and an unlocked state. +** +** But wait: there are yet more problems with POSIX advisory locks. +** +** If you close a file descriptor that points to a file that has locks, +** all locks on that file that are owned by the current process are +** released. To work around this problem, each unixInodeInfo object +** maintains a count of the number of pending locks on tha inode. +** When an attempt is made to close an unixFile, if there are +** other unixFile open on the same inode that are holding locks, the call +** to close() the file descriptor is deferred until all of the locks clear. +** The unixInodeInfo structure keeps a list of file descriptors that need to +** be closed and that list is walked (and cleared) when the last lock +** clears. +** +** Yet another problem: LinuxThreads do not play well with posix locks. +** +** Many older versions of linux use the LinuxThreads library which is +** not posix compliant. Under LinuxThreads, a lock created by thread +** A cannot be modified or overridden by a different thread B. +** Only thread A can modify the lock. Locking behavior is correct +** if the appliation uses the newer Native Posix Thread Library (NPTL) +** on linux - with NPTL a lock created by thread A can override locks +** in thread B. But there is no way to know at compile-time which +** threading library is being used. So there is no way to know at +** compile-time whether or not thread A can override locks on thread B. +** One has to do a run-time check to discover the behavior of the +** current process. +** +** SQLite used to support LinuxThreads. But support for LinuxThreads +** was dropped beginning with version 3.7.0. SQLite will still work with +** LinuxThreads provided that (1) there is no more than one connection +** per database file in the same process and (2) database connections +** do not move across threads. +*/ + +/* +** An instance of the following structure serves as the key used +** to locate a particular unixInodeInfo object. +*/ +struct unixFileId { + dev_t dev; /* Device number */ +#if OS_VXWORKS + struct vxworksFileId *pId; /* Unique file ID for vxworks. */ +#else + ino_t ino; /* Inode number */ +#endif +}; + +/* +** An instance of the following structure is allocated for each open +** inode. Or, on LinuxThreads, there is one of these structures for +** each inode opened by each thread. +** +** A single inode can have multiple file descriptors, so each unixFile +** structure contains a pointer to an instance of this object and this +** object keeps a count of the number of unixFile pointing to it. +*/ +struct unixInodeInfo { + struct unixFileId fileId; /* The lookup key */ + int nShared; /* Number of SHARED locks held */ + unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ + unsigned char bProcessLock; /* An exclusive process lock is held */ + int nRef; /* Number of pointers to this structure */ + unixShmNode *pShmNode; /* Shared memory associated with this inode */ + int nLock; /* Number of outstanding file locks */ + UnixUnusedFd *pUnused; /* Unused file descriptors to close */ + unixInodeInfo *pNext; /* List of all unixInodeInfo objects */ + unixInodeInfo *pPrev; /* .... doubly linked */ +#if SQLITE_ENABLE_LOCKING_STYLE + unsigned long long sharedByte; /* for AFP simulated shared lock */ +#endif +#if OS_VXWORKS + sem_t *pSem; /* Named POSIX semaphore */ + char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */ +#endif +}; + +/* +** A lists of all unixInodeInfo objects. +*/ +static unixInodeInfo *inodeList = 0; + +/* +** +** This function - unixLogError_x(), is only ever called via the macro +** unixLogError(). +** +** It is invoked after an error occurs in an OS function and errno has been +** set. It logs a message using sqlite3_log() containing the current value of +** errno and, if possible, the human-readable equivalent from strerror() or +** strerror_r(). +** +** The first argument passed to the macro should be the error code that +** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). +** The two subsequent arguments should be the name of the OS function that +** failed (e.g. "unlink", "open") and the associated file-system path, +** if any. +*/ +#define unixLogError(a,b,c) unixLogErrorAtLine(a,b,c,__LINE__) +static int unixLogErrorAtLine( + int errcode, /* SQLite error code */ + const char *zFunc, /* Name of OS function that failed */ + const char *zPath, /* File path associated with error */ + int iLine /* Source line number where error occurred */ +){ + char *zErr; /* Message from strerror() or equivalent */ + int iErrno = errno; /* Saved syscall error number */ + + /* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use + ** the strerror() function to obtain the human-readable error message + ** equivalent to errno. Otherwise, use strerror_r(). + */ +#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R) + char aErr[80]; + memset(aErr, 0, sizeof(aErr)); + zErr = aErr; + + /* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined, + ** assume that the system provides the GNU version of strerror_r() that + ** returns a pointer to a buffer containing the error message. That pointer + ** may point to aErr[], or it may point to some static storage somewhere. + ** Otherwise, assume that the system provides the POSIX version of + ** strerror_r(), which always writes an error message into aErr[]. + ** + ** If the code incorrectly assumes that it is the POSIX version that is + ** available, the error message will often be an empty string. Not a + ** huge problem. Incorrectly concluding that the GNU version is available + ** could lead to a segfault though. + */ +#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU) + zErr = +# endif + strerror_r(iErrno, aErr, sizeof(aErr)-1); + +#elif SQLITE_THREADSAFE + /* This is a threadsafe build, but strerror_r() is not available. */ + zErr = ""; +#else + /* Non-threadsafe build, use strerror(). */ + zErr = strerror(iErrno); +#endif + + if( zPath==0 ) zPath = ""; + sqlite3_log(errcode, + "os_unix.c:%d: (%d) %s(%s) - %s", + iLine, iErrno, zFunc, zPath, zErr + ); + + return errcode; +} + +/* +** Close a file descriptor. +** +** We assume that close() almost always works, since it is only in a +** very sick application or on a very sick platform that it might fail. +** If it does fail, simply leak the file descriptor, but do log the +** error. +** +** Note that it is not safe to retry close() after EINTR since the +** file descriptor might have already been reused by another thread. +** So we don't even try to recover from an EINTR. Just log the error +** and move on. +*/ +static void robust_close(unixFile *pFile, int h, int lineno){ + if( osClose(h) ){ + unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close", + pFile ? pFile->zPath : 0, lineno); + } +} + +/* +** Set the pFile->lastErrno. Do this in a subroutine as that provides +** a convenient place to set a breakpoint. +*/ +static void storeLastErrno(unixFile *pFile, int error){ + pFile->lastErrno = error; +} + +/* +** Close all file descriptors accumuated in the unixInodeInfo->pUnused list. +*/ +static void closePendingFds(unixFile *pFile){ + unixInodeInfo *pInode = pFile->pInode; + UnixUnusedFd *p; + UnixUnusedFd *pNext; + for(p=pInode->pUnused; p; p=pNext){ + pNext = p->pNext; + robust_close(pFile, p->fd, __LINE__); + sqlite3_free(p); + } + pInode->pUnused = 0; +} + +/* +** Release a unixInodeInfo structure previously allocated by findInodeInfo(). +** +** The mutex entered using the unixEnterMutex() function must be held +** when this function is called. +*/ +static void releaseInodeInfo(unixFile *pFile){ + unixInodeInfo *pInode = pFile->pInode; + assert( unixMutexHeld() ); + if( ALWAYS(pInode) ){ + pInode->nRef--; + if( pInode->nRef==0 ){ + assert( pInode->pShmNode==0 ); + closePendingFds(pFile); + if( pInode->pPrev ){ + assert( pInode->pPrev->pNext==pInode ); + pInode->pPrev->pNext = pInode->pNext; + }else{ + assert( inodeList==pInode ); + inodeList = pInode->pNext; + } + if( pInode->pNext ){ + assert( pInode->pNext->pPrev==pInode ); + pInode->pNext->pPrev = pInode->pPrev; + } + sqlite3_free(pInode); + } + } +} + +/* +** Given a file descriptor, locate the unixInodeInfo object that +** describes that file descriptor. Create a new one if necessary. The +** return value might be uninitialized if an error occurs. +** +** The mutex entered using the unixEnterMutex() function must be held +** when this function is called. +** +** Return an appropriate error code. +*/ +static int findInodeInfo( + unixFile *pFile, /* Unix file with file desc used in the key */ + unixInodeInfo **ppInode /* Return the unixInodeInfo object here */ +){ + int rc; /* System call return code */ + int fd; /* The file descriptor for pFile */ + struct unixFileId fileId; /* Lookup key for the unixInodeInfo */ + struct stat statbuf; /* Low-level file information */ + unixInodeInfo *pInode = 0; /* Candidate unixInodeInfo object */ + + assert( unixMutexHeld() ); + + /* Get low-level information about the file that we can used to + ** create a unique name for the file. + */ + fd = pFile->h; + rc = osFstat(fd, &statbuf); + if( rc!=0 ){ + storeLastErrno(pFile, errno); +#ifdef EOVERFLOW + if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS; +#endif + return SQLITE_IOERR; + } + +#ifdef __APPLE__ + /* On OS X on an msdos filesystem, the inode number is reported + ** incorrectly for zero-size files. See ticket #3260. To work + ** around this problem (we consider it a bug in OS X, not SQLite) + ** we always increase the file size to 1 by writing a single byte + ** prior to accessing the inode number. The one byte written is + ** an ASCII 'S' character which also happens to be the first byte + ** in the header of every SQLite database. In this way, if there + ** is a race condition such that another thread has already populated + ** the first page of the database, no damage is done. + */ + if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){ + do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR ); + if( rc!=1 ){ + storeLastErrno(pFile, errno); + return SQLITE_IOERR; + } + rc = osFstat(fd, &statbuf); + if( rc!=0 ){ + storeLastErrno(pFile, errno); + return SQLITE_IOERR; + } + } +#endif + + memset(&fileId, 0, sizeof(fileId)); + fileId.dev = statbuf.st_dev; +#if OS_VXWORKS + fileId.pId = pFile->pId; +#else + fileId.ino = statbuf.st_ino; +#endif + pInode = inodeList; + while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){ + pInode = pInode->pNext; + } + if( pInode==0 ){ + pInode = sqlite3_malloc64( sizeof(*pInode) ); + if( pInode==0 ){ + return SQLITE_NOMEM; + } + memset(pInode, 0, sizeof(*pInode)); + memcpy(&pInode->fileId, &fileId, sizeof(fileId)); + pInode->nRef = 1; + pInode->pNext = inodeList; + pInode->pPrev = 0; + if( inodeList ) inodeList->pPrev = pInode; + inodeList = pInode; + }else{ + pInode->nRef++; + } + *ppInode = pInode; + return SQLITE_OK; +} + +/* +** Return TRUE if pFile has been renamed or unlinked since it was first opened. +*/ +static int fileHasMoved(unixFile *pFile){ +#if OS_VXWORKS + return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId; +#else + struct stat buf; + return pFile->pInode!=0 && + (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino); +#endif +} + + +/* +** Check a unixFile that is a database. Verify the following: +** +** (1) There is exactly one hard link on the file +** (2) The file is not a symbolic link +** (3) The file has not been renamed or unlinked +** +** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right. +*/ +static void verifyDbFile(unixFile *pFile){ + struct stat buf; + int rc; + if( pFile->ctrlFlags & UNIXFILE_WARNED ){ + /* One or more of the following warnings have already been issued. Do not + ** repeat them so as not to clutter the error log */ + return; + } + rc = osFstat(pFile->h, &buf); + if( rc!=0 ){ + sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath); + pFile->ctrlFlags |= UNIXFILE_WARNED; + return; + } + if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){ + sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath); + pFile->ctrlFlags |= UNIXFILE_WARNED; + return; + } + if( buf.st_nlink>1 ){ + sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath); + pFile->ctrlFlags |= UNIXFILE_WARNED; + return; + } + if( fileHasMoved(pFile) ){ + sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath); + pFile->ctrlFlags |= UNIXFILE_WARNED; + return; + } +} + + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, set *pResOut +** to a non-zero value otherwise *pResOut is set to zero. The return value +** is set to SQLITE_OK unless an I/O error occurs during lock checking. +*/ +static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ + int rc = SQLITE_OK; + int reserved = 0; + unixFile *pFile = (unixFile*)id; + + SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); + + assert( pFile ); + unixEnterMutex(); /* Because pFile->pInode is shared across threads */ + + /* Check if a thread in this process holds such a lock */ + if( pFile->pInode->eFileLock>SHARED_LOCK ){ + reserved = 1; + } + + /* Otherwise see if some other process holds it. + */ +#ifndef __DJGPP__ + if( !reserved && !pFile->pInode->bProcessLock ){ + struct flock lock; + lock.l_whence = SEEK_SET; + lock.l_start = RESERVED_BYTE; + lock.l_len = 1; + lock.l_type = F_WRLCK; + if( osFcntl(pFile->h, F_GETLK, &lock) ){ + rc = SQLITE_IOERR_CHECKRESERVEDLOCK; + storeLastErrno(pFile, errno); + } else if( lock.l_type!=F_UNLCK ){ + reserved = 1; + } + } +#endif + + unixLeaveMutex(); + OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved)); + + *pResOut = reserved; + return rc; +} + +/* +** Attempt to set a system-lock on the file pFile. The lock is +** described by pLock. +** +** If the pFile was opened read/write from unix-excl, then the only lock +** ever obtained is an exclusive lock, and it is obtained exactly once +** the first time any lock is attempted. All subsequent system locking +** operations become no-ops. Locking operations still happen internally, +** in order to coordinate access between separate database connections +** within this process, but all of that is handled in memory and the +** operating system does not participate. +** +** This function is a pass-through to fcntl(F_SETLK) if pFile is using +** any VFS other than "unix-excl" or if pFile is opened on "unix-excl" +** and is read-only. +** +** Zero is returned if the call completes successfully, or -1 if a call +** to fcntl() fails. In this case, errno is set appropriately (by fcntl()). +*/ +static int unixFileLock(unixFile *pFile, struct flock *pLock){ + int rc; + unixInodeInfo *pInode = pFile->pInode; + assert( unixMutexHeld() ); + assert( pInode!=0 ); + if( ((pFile->ctrlFlags & UNIXFILE_EXCL)!=0 || pInode->bProcessLock) + && ((pFile->ctrlFlags & UNIXFILE_RDONLY)==0) + ){ + if( pInode->bProcessLock==0 ){ + struct flock lock; + assert( pInode->nLock==0 ); + lock.l_whence = SEEK_SET; + lock.l_start = SHARED_FIRST; + lock.l_len = SHARED_SIZE; + lock.l_type = F_WRLCK; + rc = osFcntl(pFile->h, F_SETLK, &lock); + if( rc<0 ) return rc; + pInode->bProcessLock = 1; + pInode->nLock++; + }else{ + rc = 0; + } + }else{ + rc = osFcntl(pFile->h, F_SETLK, pLock); + } + return rc; +} + +/* +** Lock the file with the lock specified by parameter eFileLock - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** This routine will only increase a lock. Use the sqlite3OsUnlock() +** routine to lower a locking level. +*/ +static int unixLock(sqlite3_file *id, int eFileLock){ + /* The following describes the implementation of the various locks and + ** lock transitions in terms of the POSIX advisory shared and exclusive + ** lock primitives (called read-locks and write-locks below, to avoid + ** confusion with SQLite lock names). The algorithms are complicated + ** slightly in order to be compatible with windows systems simultaneously + ** accessing the same database file, in case that is ever required. + ** + ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved + ** byte', each single bytes at well known offsets, and the 'shared byte + ** range', a range of 510 bytes at a well known offset. + ** + ** To obtain a SHARED lock, a read-lock is obtained on the 'pending + ** byte'. If this is successful, a random byte from the 'shared byte + ** range' is read-locked and the lock on the 'pending byte' released. + ** + ** A process may only obtain a RESERVED lock after it has a SHARED lock. + ** A RESERVED lock is implemented by grabbing a write-lock on the + ** 'reserved byte'. + ** + ** A process may only obtain a PENDING lock after it has obtained a + ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock + ** on the 'pending byte'. This ensures that no new SHARED locks can be + ** obtained, but existing SHARED locks are allowed to persist. A process + ** does not have to obtain a RESERVED lock on the way to a PENDING lock. + ** This property is used by the algorithm for rolling back a journal file + ** after a crash. + ** + ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is + ** implemented by obtaining a write-lock on the entire 'shared byte + ** range'. Since all other locks require a read-lock on one of the bytes + ** within this range, this ensures that no other locks are held on the + ** database. + ** + ** The reason a single byte cannot be used instead of the 'shared byte + ** range' is that some versions of windows do not support read-locks. By + ** locking a random byte from a range, concurrent SHARED locks may exist + ** even if the locking primitive used is always a write-lock. + */ + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + unixInodeInfo *pInode; + struct flock lock; + int tErrno = 0; + + assert( pFile ); + OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h, + azFileLock(eFileLock), azFileLock(pFile->eFileLock), + azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared, + osGetpid(0))); + + /* If there is already a lock of this type or more restrictive on the + ** unixFile, do nothing. Don't use the end_lock: exit path, as + ** unixEnterMutex() hasn't been called yet. + */ + if( pFile->eFileLock>=eFileLock ){ + OSTRACE(("LOCK %d %s ok (already held) (unix)\n", pFile->h, + azFileLock(eFileLock))); + return SQLITE_OK; + } + + /* Make sure the locking sequence is correct. + ** (1) We never move from unlocked to anything higher than shared lock. + ** (2) SQLite never explicitly requests a pendig lock. + ** (3) A shared lock is always held when a reserve lock is requested. + */ + assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK ); + assert( eFileLock!=PENDING_LOCK ); + assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK ); + + /* This mutex is needed because pFile->pInode is shared across threads + */ + unixEnterMutex(); + pInode = pFile->pInode; + + /* If some thread using this PID has a lock via a different unixFile* + ** handle that precludes the requested lock, return BUSY. + */ + if( (pFile->eFileLock!=pInode->eFileLock && + (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK)) + ){ + rc = SQLITE_BUSY; + goto end_lock; + } + + /* If a SHARED lock is requested, and some thread using this PID already + ** has a SHARED or RESERVED lock, then increment reference counts and + ** return SQLITE_OK. + */ + if( eFileLock==SHARED_LOCK && + (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){ + assert( eFileLock==SHARED_LOCK ); + assert( pFile->eFileLock==0 ); + assert( pInode->nShared>0 ); + pFile->eFileLock = SHARED_LOCK; + pInode->nShared++; + pInode->nLock++; + goto end_lock; + } + + + /* A PENDING lock is needed before acquiring a SHARED lock and before + ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will + ** be released. + */ + lock.l_len = 1L; + lock.l_whence = SEEK_SET; + if( eFileLock==SHARED_LOCK + || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLocknShared==0 ); + assert( pInode->eFileLock==0 ); + assert( rc==SQLITE_OK ); + + /* Now get the read-lock */ + lock.l_start = SHARED_FIRST; + lock.l_len = SHARED_SIZE; + if( unixFileLock(pFile, &lock) ){ + tErrno = errno; + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); + } + + /* Drop the temporary PENDING lock */ + lock.l_start = PENDING_BYTE; + lock.l_len = 1L; + lock.l_type = F_UNLCK; + if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){ + /* This could happen with a network mount */ + tErrno = errno; + rc = SQLITE_IOERR_UNLOCK; + } + + if( rc ){ + if( rc!=SQLITE_BUSY ){ + storeLastErrno(pFile, tErrno); + } + goto end_lock; + }else{ + pFile->eFileLock = SHARED_LOCK; + pInode->nLock++; + pInode->nShared = 1; + } + }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){ + /* We are trying for an exclusive lock but another thread in this + ** same process is still holding a shared lock. */ + rc = SQLITE_BUSY; + }else{ + /* The request was for a RESERVED or EXCLUSIVE lock. It is + ** assumed that there is a SHARED or greater lock on the file + ** already. + */ + assert( 0!=pFile->eFileLock ); + lock.l_type = F_WRLCK; + + assert( eFileLock==RESERVED_LOCK || eFileLock==EXCLUSIVE_LOCK ); + if( eFileLock==RESERVED_LOCK ){ + lock.l_start = RESERVED_BYTE; + lock.l_len = 1L; + }else{ + lock.l_start = SHARED_FIRST; + lock.l_len = SHARED_SIZE; + } + + if( unixFileLock(pFile, &lock) ){ + tErrno = errno; + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); + if( rc!=SQLITE_BUSY ){ + storeLastErrno(pFile, tErrno); + } + } + } + + +#ifdef SQLITE_DEBUG + /* Set up the transaction-counter change checking flags when + ** transitioning from a SHARED to a RESERVED lock. The change + ** from SHARED to RESERVED marks the beginning of a normal + ** write operation (not a hot journal rollback). + */ + if( rc==SQLITE_OK + && pFile->eFileLock<=SHARED_LOCK + && eFileLock==RESERVED_LOCK + ){ + pFile->transCntrChng = 0; + pFile->dbUpdate = 0; + pFile->inNormalWrite = 1; + } +#endif + + + if( rc==SQLITE_OK ){ + pFile->eFileLock = eFileLock; + pInode->eFileLock = eFileLock; + }else if( eFileLock==EXCLUSIVE_LOCK ){ + pFile->eFileLock = PENDING_LOCK; + pInode->eFileLock = PENDING_LOCK; + } + +end_lock: + unixLeaveMutex(); + OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock), + rc==SQLITE_OK ? "ok" : "failed")); + return rc; +} + +/* +** Add the file descriptor used by file handle pFile to the corresponding +** pUnused list. +*/ +static void setPendingFd(unixFile *pFile){ + unixInodeInfo *pInode = pFile->pInode; + UnixUnusedFd *p = pFile->pUnused; + p->pNext = pInode->pUnused; + pInode->pUnused = p; + pFile->h = -1; + pFile->pUnused = 0; +} + +/* +** Lower the locking level on file descriptor pFile to eFileLock. eFileLock +** must be either NO_LOCK or SHARED_LOCK. +** +** If the locking level of the file descriptor is already at or below +** the requested locking level, this routine is a no-op. +** +** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED +** the byte range is divided into 2 parts and the first part is unlocked then +** set to a read lock, then the other part is simply unlocked. This works +** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to +** remove the write lock on a region when a read lock is set. +*/ +static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ + unixFile *pFile = (unixFile*)id; + unixInodeInfo *pInode; + struct flock lock; + int rc = SQLITE_OK; + + assert( pFile ); + OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock, + pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared, + osGetpid(0))); + + assert( eFileLock<=SHARED_LOCK ); + if( pFile->eFileLock<=eFileLock ){ + return SQLITE_OK; + } + unixEnterMutex(); + pInode = pFile->pInode; + assert( pInode->nShared!=0 ); + if( pFile->eFileLock>SHARED_LOCK ){ + assert( pInode->eFileLock==pFile->eFileLock ); + +#ifdef SQLITE_DEBUG + /* When reducing a lock such that other processes can start + ** reading the database file again, make sure that the + ** transaction counter was updated if any part of the database + ** file changed. If the transaction counter is not updated, + ** other connections to the same file might not realize that + ** the file has changed and hence might not know to flush their + ** cache. The use of a stale cache can lead to database corruption. + */ + pFile->inNormalWrite = 0; +#endif + + /* downgrading to a shared lock on NFS involves clearing the write lock + ** before establishing the readlock - to avoid a race condition we downgrade + ** the lock in 2 blocks, so that part of the range will be covered by a + ** write lock until the rest is covered by a read lock: + ** 1: [WWWWW] + ** 2: [....W] + ** 3: [RRRRW] + ** 4: [RRRR.] + */ + if( eFileLock==SHARED_LOCK ){ +#if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE + (void)handleNFSUnlock; + assert( handleNFSUnlock==0 ); +#endif +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE + if( handleNFSUnlock ){ + int tErrno; /* Error code from system call errors */ + off_t divSize = SHARED_SIZE - 1; + + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = SHARED_FIRST; + lock.l_len = divSize; + if( unixFileLock(pFile, &lock)==(-1) ){ + tErrno = errno; + rc = SQLITE_IOERR_UNLOCK; + if( IS_LOCK_ERROR(rc) ){ + storeLastErrno(pFile, tErrno); + } + goto end_unlock; + } + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = SHARED_FIRST; + lock.l_len = divSize; + if( unixFileLock(pFile, &lock)==(-1) ){ + tErrno = errno; + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); + if( IS_LOCK_ERROR(rc) ){ + storeLastErrno(pFile, tErrno); + } + goto end_unlock; + } + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = SHARED_FIRST+divSize; + lock.l_len = SHARED_SIZE-divSize; + if( unixFileLock(pFile, &lock)==(-1) ){ + tErrno = errno; + rc = SQLITE_IOERR_UNLOCK; + if( IS_LOCK_ERROR(rc) ){ + storeLastErrno(pFile, tErrno); + } + goto end_unlock; + } + }else +#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ + { + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = SHARED_FIRST; + lock.l_len = SHARED_SIZE; + if( unixFileLock(pFile, &lock) ){ + /* In theory, the call to unixFileLock() cannot fail because another + ** process is holding an incompatible lock. If it does, this + ** indicates that the other process is not following the locking + ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning + ** SQLITE_BUSY would confuse the upper layer (in practice it causes + ** an assert to fail). */ + rc = SQLITE_IOERR_RDLOCK; + storeLastErrno(pFile, errno); + goto end_unlock; + } + } + } + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = PENDING_BYTE; + lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); + if( unixFileLock(pFile, &lock)==0 ){ + pInode->eFileLock = SHARED_LOCK; + }else{ + rc = SQLITE_IOERR_UNLOCK; + storeLastErrno(pFile, errno); + goto end_unlock; + } + } + if( eFileLock==NO_LOCK ){ + /* Decrement the shared lock counter. Release the lock using an + ** OS call only when all threads in this same process have released + ** the lock. + */ + pInode->nShared--; + if( pInode->nShared==0 ){ + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = lock.l_len = 0L; + if( unixFileLock(pFile, &lock)==0 ){ + pInode->eFileLock = NO_LOCK; + }else{ + rc = SQLITE_IOERR_UNLOCK; + storeLastErrno(pFile, errno); + pInode->eFileLock = NO_LOCK; + pFile->eFileLock = NO_LOCK; + } + } + + /* Decrement the count of locks against this same file. When the + ** count reaches zero, close any other file descriptors whose close + ** was deferred because of outstanding locks. + */ + pInode->nLock--; + assert( pInode->nLock>=0 ); + if( pInode->nLock==0 ){ + closePendingFds(pFile); + } + } + +end_unlock: + unixLeaveMutex(); + if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock; + return rc; +} + +/* +** Lower the locking level on file descriptor pFile to eFileLock. eFileLock +** must be either NO_LOCK or SHARED_LOCK. +** +** If the locking level of the file descriptor is already at or below +** the requested locking level, this routine is a no-op. +*/ +static int unixUnlock(sqlite3_file *id, int eFileLock){ +#if SQLITE_MAX_MMAP_SIZE>0 + assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 ); +#endif + return posixUnlock(id, eFileLock, 0); +} + +#if SQLITE_MAX_MMAP_SIZE>0 +static int unixMapfile(unixFile *pFd, i64 nByte); +static void unixUnmapfile(unixFile *pFd); +#endif + +/* +** This function performs the parts of the "close file" operation +** common to all locking schemes. It closes the directory and file +** handles, if they are valid, and sets all fields of the unixFile +** structure to 0. +** +** It is *not* necessary to hold the mutex when this routine is called, +** even on VxWorks. A mutex will be acquired on VxWorks by the +** vxworksReleaseFileId() routine. +*/ +static int closeUnixFile(sqlite3_file *id){ + unixFile *pFile = (unixFile*)id; +#if SQLITE_MAX_MMAP_SIZE>0 + unixUnmapfile(pFile); +#endif + if( pFile->h>=0 ){ + robust_close(pFile, pFile->h, __LINE__); + pFile->h = -1; + } +#if OS_VXWORKS + if( pFile->pId ){ + if( pFile->ctrlFlags & UNIXFILE_DELETE ){ + osUnlink(pFile->pId->zCanonicalName); + } + vxworksReleaseFileId(pFile->pId); + pFile->pId = 0; + } +#endif +#ifdef SQLITE_UNLINK_AFTER_CLOSE + if( pFile->ctrlFlags & UNIXFILE_DELETE ){ + osUnlink(pFile->zPath); + sqlite3_free(*(char**)&pFile->zPath); + pFile->zPath = 0; + } +#endif + OSTRACE(("CLOSE %-3d\n", pFile->h)); + OpenCounter(-1); + sqlite3_free(pFile->pUnused); + memset(pFile, 0, sizeof(unixFile)); + return SQLITE_OK; +} + +/* +** Close a file. +*/ +static int unixClose(sqlite3_file *id){ + int rc = SQLITE_OK; + unixFile *pFile = (unixFile *)id; + verifyDbFile(pFile); + unixUnlock(id, NO_LOCK); + unixEnterMutex(); + + /* unixFile.pInode is always valid here. Otherwise, a different close + ** routine (e.g. nolockClose()) would be called instead. + */ + assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 ); + if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){ + /* If there are outstanding locks, do not actually close the file just + ** yet because that would clear those locks. Instead, add the file + ** descriptor to pInode->pUnused list. It will be automatically closed + ** when the last lock is cleared. + */ + setPendingFd(pFile); + } + releaseInodeInfo(pFile); + rc = closeUnixFile(id); + unixLeaveMutex(); + return rc; +} + +/************** End of the posix advisory lock implementation ***************** +******************************************************************************/ + +/****************************************************************************** +****************************** No-op Locking ********************************** +** +** Of the various locking implementations available, this is by far the +** simplest: locking is ignored. No attempt is made to lock the database +** file for reading or writing. +** +** This locking mode is appropriate for use on read-only databases +** (ex: databases that are burned into CD-ROM, for example.) It can +** also be used if the application employs some external mechanism to +** prevent simultaneous access of the same database by two or more +** database connections. But there is a serious risk of database +** corruption if this locking mode is used in situations where multiple +** database connections are accessing the same database file at the same +** time and one or more of those connections are writing. +*/ + +static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){ + UNUSED_PARAMETER(NotUsed); + *pResOut = 0; + return SQLITE_OK; +} +static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); + return SQLITE_OK; +} +static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); + return SQLITE_OK; +} + +/* +** Close the file. +*/ +static int nolockClose(sqlite3_file *id) { + return closeUnixFile(id); +} + +/******************* End of the no-op lock implementation ********************* +******************************************************************************/ + +/****************************************************************************** +************************* Begin dot-file Locking ****************************** +** +** The dotfile locking implementation uses the existence of separate lock +** files (really a directory) to control access to the database. This works +** on just about every filesystem imaginable. But there are serious downsides: +** +** (1) There is zero concurrency. A single reader blocks all other +** connections from reading or writing the database. +** +** (2) An application crash or power loss can leave stale lock files +** sitting around that need to be cleared manually. +** +** Nevertheless, a dotlock is an appropriate locking mode for use if no +** other locking strategy is available. +** +** Dotfile locking works by creating a subdirectory in the same directory as +** the database and with the same name but with a ".lock" extension added. +** The existence of a lock directory implies an EXCLUSIVE lock. All other +** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE. +*/ + +/* +** The file suffix added to the data base filename in order to create the +** lock directory. +*/ +#define DOTLOCK_SUFFIX ".lock" + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, set *pResOut +** to a non-zero value otherwise *pResOut is set to zero. The return value +** is set to SQLITE_OK unless an I/O error occurs during lock checking. +** +** In dotfile locking, either a lock exists or it does not. So in this +** variation of CheckReservedLock(), *pResOut is set to true if any lock +** is held on the file and false if the file is unlocked. +*/ +static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) { + int rc = SQLITE_OK; + int reserved = 0; + unixFile *pFile = (unixFile*)id; + + SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); + + assert( pFile ); + + /* Check if a thread in this process holds such a lock */ + if( pFile->eFileLock>SHARED_LOCK ){ + /* Either this connection or some other connection in the same process + ** holds a lock on the file. No need to check further. */ + reserved = 1; + }else{ + /* The lock is held if and only if the lockfile exists */ + const char *zLockFile = (const char*)pFile->lockingContext; + reserved = osAccess(zLockFile, 0)==0; + } + OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved)); + *pResOut = reserved; + return rc; +} + +/* +** Lock the file with the lock specified by parameter eFileLock - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** This routine will only increase a lock. Use the sqlite3OsUnlock() +** routine to lower a locking level. +** +** With dotfile locking, we really only support state (4): EXCLUSIVE. +** But we track the other locking levels internally. +*/ +static int dotlockLock(sqlite3_file *id, int eFileLock) { + unixFile *pFile = (unixFile*)id; + char *zLockFile = (char *)pFile->lockingContext; + int rc = SQLITE_OK; + + + /* If we have any lock, then the lock file already exists. All we have + ** to do is adjust our internal record of the lock level. + */ + if( pFile->eFileLock > NO_LOCK ){ + pFile->eFileLock = eFileLock; + /* Always update the timestamp on the old file */ +#ifdef HAVE_UTIME + utime(zLockFile, NULL); +#else + utimes(zLockFile, NULL); +#endif + return SQLITE_OK; + } + + /* grab an exclusive lock */ + rc = osMkdir(zLockFile, 0777); + if( rc<0 ){ + /* failed to open/create the lock directory */ + int tErrno = errno; + if( EEXIST == tErrno ){ + rc = SQLITE_BUSY; + } else { + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); + if( IS_LOCK_ERROR(rc) ){ + storeLastErrno(pFile, tErrno); + } + } + return rc; + } + + /* got it, set the type and return ok */ + pFile->eFileLock = eFileLock; + return rc; +} + +/* +** Lower the locking level on file descriptor pFile to eFileLock. eFileLock +** must be either NO_LOCK or SHARED_LOCK. +** +** If the locking level of the file descriptor is already at or below +** the requested locking level, this routine is a no-op. +** +** When the locking level reaches NO_LOCK, delete the lock file. +*/ +static int dotlockUnlock(sqlite3_file *id, int eFileLock) { + unixFile *pFile = (unixFile*)id; + char *zLockFile = (char *)pFile->lockingContext; + int rc; + + assert( pFile ); + OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock, + pFile->eFileLock, osGetpid(0))); + assert( eFileLock<=SHARED_LOCK ); + + /* no-op if possible */ + if( pFile->eFileLock==eFileLock ){ + return SQLITE_OK; + } + + /* To downgrade to shared, simply update our internal notion of the + ** lock state. No need to mess with the file on disk. + */ + if( eFileLock==SHARED_LOCK ){ + pFile->eFileLock = SHARED_LOCK; + return SQLITE_OK; + } + + /* To fully unlock the database, delete the lock file */ + assert( eFileLock==NO_LOCK ); + rc = osRmdir(zLockFile); + if( rc<0 && errno==ENOTDIR ) rc = osUnlink(zLockFile); + if( rc<0 ){ + int tErrno = errno; + rc = 0; + if( ENOENT != tErrno ){ + rc = SQLITE_IOERR_UNLOCK; + } + if( IS_LOCK_ERROR(rc) ){ + storeLastErrno(pFile, tErrno); + } + return rc; + } + pFile->eFileLock = NO_LOCK; + return SQLITE_OK; +} + +/* +** Close a file. Make sure the lock has been released before closing. +*/ +static int dotlockClose(sqlite3_file *id) { + int rc = SQLITE_OK; + if( id ){ + unixFile *pFile = (unixFile*)id; + dotlockUnlock(id, NO_LOCK); + sqlite3_free(pFile->lockingContext); + rc = closeUnixFile(id); + } + return rc; +} +/****************** End of the dot-file lock implementation ******************* +******************************************************************************/ + +/****************************************************************************** +************************** Begin flock Locking ******************************** +** +** Use the flock() system call to do file locking. +** +** flock() locking is like dot-file locking in that the various +** fine-grain locking levels supported by SQLite are collapsed into +** a single exclusive lock. In other words, SHARED, RESERVED, and +** PENDING locks are the same thing as an EXCLUSIVE lock. SQLite +** still works when you do this, but concurrency is reduced since +** only a single process can be reading the database at a time. +** +** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off +*/ +#if SQLITE_ENABLE_LOCKING_STYLE + +/* +** Retry flock() calls that fail with EINTR +*/ +#ifdef EINTR +static int robust_flock(int fd, int op){ + int rc; + do{ rc = flock(fd,op); }while( rc<0 && errno==EINTR ); + return rc; +} +#else +# define robust_flock(a,b) flock(a,b) +#endif + + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, set *pResOut +** to a non-zero value otherwise *pResOut is set to zero. The return value +** is set to SQLITE_OK unless an I/O error occurs during lock checking. +*/ +static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){ + int rc = SQLITE_OK; + int reserved = 0; + unixFile *pFile = (unixFile*)id; + + SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); + + assert( pFile ); + + /* Check if a thread in this process holds such a lock */ + if( pFile->eFileLock>SHARED_LOCK ){ + reserved = 1; + } + + /* Otherwise see if some other process holds it. */ + if( !reserved ){ + /* attempt to get the lock */ + int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB); + if( !lrc ){ + /* got the lock, unlock it */ + lrc = robust_flock(pFile->h, LOCK_UN); + if ( lrc ) { + int tErrno = errno; + /* unlock failed with an error */ + lrc = SQLITE_IOERR_UNLOCK; + if( IS_LOCK_ERROR(lrc) ){ + storeLastErrno(pFile, tErrno); + rc = lrc; + } + } + } else { + int tErrno = errno; + reserved = 1; + /* someone else might have it reserved */ + lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); + if( IS_LOCK_ERROR(lrc) ){ + storeLastErrno(pFile, tErrno); + rc = lrc; + } + } + } + OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved)); + +#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS + if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ + rc = SQLITE_OK; + reserved=1; + } +#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ + *pResOut = reserved; + return rc; +} + +/* +** Lock the file with the lock specified by parameter eFileLock - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** flock() only really support EXCLUSIVE locks. We track intermediate +** lock states in the sqlite3_file structure, but all locks SHARED or +** above are really EXCLUSIVE locks and exclude all other processes from +** access the file. +** +** This routine will only increase a lock. Use the sqlite3OsUnlock() +** routine to lower a locking level. +*/ +static int flockLock(sqlite3_file *id, int eFileLock) { + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + + assert( pFile ); + + /* if we already have a lock, it is exclusive. + ** Just adjust level and punt on outta here. */ + if (pFile->eFileLock > NO_LOCK) { + pFile->eFileLock = eFileLock; + return SQLITE_OK; + } + + /* grab an exclusive lock */ + + if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) { + int tErrno = errno; + /* didn't get, must be busy */ + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); + if( IS_LOCK_ERROR(rc) ){ + storeLastErrno(pFile, tErrno); + } + } else { + /* got it, set the type and return ok */ + pFile->eFileLock = eFileLock; + } + OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock), + rc==SQLITE_OK ? "ok" : "failed")); +#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS + if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ + rc = SQLITE_BUSY; + } +#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ + return rc; +} + + +/* +** Lower the locking level on file descriptor pFile to eFileLock. eFileLock +** must be either NO_LOCK or SHARED_LOCK. +** +** If the locking level of the file descriptor is already at or below +** the requested locking level, this routine is a no-op. +*/ +static int flockUnlock(sqlite3_file *id, int eFileLock) { + unixFile *pFile = (unixFile*)id; + + assert( pFile ); + OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock, + pFile->eFileLock, osGetpid(0))); + assert( eFileLock<=SHARED_LOCK ); + + /* no-op if possible */ + if( pFile->eFileLock==eFileLock ){ + return SQLITE_OK; + } + + /* shared can just be set because we always have an exclusive */ + if (eFileLock==SHARED_LOCK) { + pFile->eFileLock = eFileLock; + return SQLITE_OK; + } + + /* no, really, unlock. */ + if( robust_flock(pFile->h, LOCK_UN) ){ +#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS + return SQLITE_OK; +#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ + return SQLITE_IOERR_UNLOCK; + }else{ + pFile->eFileLock = NO_LOCK; + return SQLITE_OK; + } +} + +/* +** Close a file. +*/ +static int flockClose(sqlite3_file *id) { + int rc = SQLITE_OK; + if( id ){ + flockUnlock(id, NO_LOCK); + rc = closeUnixFile(id); + } + return rc; +} + +#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */ + +/******************* End of the flock lock implementation ********************* +******************************************************************************/ + +/****************************************************************************** +************************ Begin Named Semaphore Locking ************************ +** +** Named semaphore locking is only supported on VxWorks. +** +** Semaphore locking is like dot-lock and flock in that it really only +** supports EXCLUSIVE locking. Only a single process can read or write +** the database file at a time. This reduces potential concurrency, but +** makes the lock implementation much easier. +*/ +#if OS_VXWORKS + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, set *pResOut +** to a non-zero value otherwise *pResOut is set to zero. The return value +** is set to SQLITE_OK unless an I/O error occurs during lock checking. +*/ +static int semXCheckReservedLock(sqlite3_file *id, int *pResOut) { + int rc = SQLITE_OK; + int reserved = 0; + unixFile *pFile = (unixFile*)id; + + SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); + + assert( pFile ); + + /* Check if a thread in this process holds such a lock */ + if( pFile->eFileLock>SHARED_LOCK ){ + reserved = 1; + } + + /* Otherwise see if some other process holds it. */ + if( !reserved ){ + sem_t *pSem = pFile->pInode->pSem; + + if( sem_trywait(pSem)==-1 ){ + int tErrno = errno; + if( EAGAIN != tErrno ){ + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK); + storeLastErrno(pFile, tErrno); + } else { + /* someone else has the lock when we are in NO_LOCK */ + reserved = (pFile->eFileLock < SHARED_LOCK); + } + }else{ + /* we could have it if we want it */ + sem_post(pSem); + } + } + OSTRACE(("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved)); + + *pResOut = reserved; + return rc; +} + +/* +** Lock the file with the lock specified by parameter eFileLock - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** Semaphore locks only really support EXCLUSIVE locks. We track intermediate +** lock states in the sqlite3_file structure, but all locks SHARED or +** above are really EXCLUSIVE locks and exclude all other processes from +** access the file. +** +** This routine will only increase a lock. Use the sqlite3OsUnlock() +** routine to lower a locking level. +*/ +static int semXLock(sqlite3_file *id, int eFileLock) { + unixFile *pFile = (unixFile*)id; + sem_t *pSem = pFile->pInode->pSem; + int rc = SQLITE_OK; + + /* if we already have a lock, it is exclusive. + ** Just adjust level and punt on outta here. */ + if (pFile->eFileLock > NO_LOCK) { + pFile->eFileLock = eFileLock; + rc = SQLITE_OK; + goto sem_end_lock; + } + + /* lock semaphore now but bail out when already locked. */ + if( sem_trywait(pSem)==-1 ){ + rc = SQLITE_BUSY; + goto sem_end_lock; + } + + /* got it, set the type and return ok */ + pFile->eFileLock = eFileLock; + + sem_end_lock: + return rc; +} + +/* +** Lower the locking level on file descriptor pFile to eFileLock. eFileLock +** must be either NO_LOCK or SHARED_LOCK. +** +** If the locking level of the file descriptor is already at or below +** the requested locking level, this routine is a no-op. +*/ +static int semXUnlock(sqlite3_file *id, int eFileLock) { + unixFile *pFile = (unixFile*)id; + sem_t *pSem = pFile->pInode->pSem; + + assert( pFile ); + assert( pSem ); + OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock, + pFile->eFileLock, osGetpid(0))); + assert( eFileLock<=SHARED_LOCK ); + + /* no-op if possible */ + if( pFile->eFileLock==eFileLock ){ + return SQLITE_OK; + } + + /* shared can just be set because we always have an exclusive */ + if (eFileLock==SHARED_LOCK) { + pFile->eFileLock = eFileLock; + return SQLITE_OK; + } + + /* no, really unlock. */ + if ( sem_post(pSem)==-1 ) { + int rc, tErrno = errno; + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); + if( IS_LOCK_ERROR(rc) ){ + storeLastErrno(pFile, tErrno); + } + return rc; + } + pFile->eFileLock = NO_LOCK; + return SQLITE_OK; +} + +/* + ** Close a file. + */ +static int semXClose(sqlite3_file *id) { + if( id ){ + unixFile *pFile = (unixFile*)id; + semXUnlock(id, NO_LOCK); + assert( pFile ); + unixEnterMutex(); + releaseInodeInfo(pFile); + unixLeaveMutex(); + closeUnixFile(id); + } + return SQLITE_OK; +} + +#endif /* OS_VXWORKS */ +/* +** Named semaphore locking is only available on VxWorks. +** +*************** End of the named semaphore lock implementation **************** +******************************************************************************/ + + +/****************************************************************************** +*************************** Begin AFP Locking ********************************* +** +** AFP is the Apple Filing Protocol. AFP is a network filesystem found +** on Apple Macintosh computers - both OS9 and OSX. +** +** Third-party implementations of AFP are available. But this code here +** only works on OSX. +*/ + +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE +/* +** The afpLockingContext structure contains all afp lock specific state +*/ +typedef struct afpLockingContext afpLockingContext; +struct afpLockingContext { + int reserved; + const char *dbPath; /* Name of the open file */ +}; + +struct ByteRangeLockPB2 +{ + unsigned long long offset; /* offset to first byte to lock */ + unsigned long long length; /* nbr of bytes to lock */ + unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */ + unsigned char unLockFlag; /* 1 = unlock, 0 = lock */ + unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */ + int fd; /* file desc to assoc this lock with */ +}; + +#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2) + +/* +** This is a utility for setting or clearing a bit-range lock on an +** AFP filesystem. +** +** Return SQLITE_OK on success, SQLITE_BUSY on failure. +*/ +static int afpSetLock( + const char *path, /* Name of the file to be locked or unlocked */ + unixFile *pFile, /* Open file descriptor on path */ + unsigned long long offset, /* First byte to be locked */ + unsigned long long length, /* Number of bytes to lock */ + int setLockFlag /* True to set lock. False to clear lock */ +){ + struct ByteRangeLockPB2 pb; + int err; + + pb.unLockFlag = setLockFlag ? 0 : 1; + pb.startEndFlag = 0; + pb.offset = offset; + pb.length = length; + pb.fd = pFile->h; + + OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n", + (setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""), + offset, length)); + err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0); + if ( err==-1 ) { + int rc; + int tErrno = errno; + OSTRACE(("AFPSETLOCK failed to fsctl() '%s' %d %s\n", + path, tErrno, strerror(tErrno))); +#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS + rc = SQLITE_BUSY; +#else + rc = sqliteErrorFromPosixError(tErrno, + setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK); +#endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */ + if( IS_LOCK_ERROR(rc) ){ + storeLastErrno(pFile, tErrno); + } + return rc; + } else { + return SQLITE_OK; + } +} + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, set *pResOut +** to a non-zero value otherwise *pResOut is set to zero. The return value +** is set to SQLITE_OK unless an I/O error occurs during lock checking. +*/ +static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){ + int rc = SQLITE_OK; + int reserved = 0; + unixFile *pFile = (unixFile*)id; + afpLockingContext *context; + + SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); + + assert( pFile ); + context = (afpLockingContext *) pFile->lockingContext; + if( context->reserved ){ + *pResOut = 1; + return SQLITE_OK; + } + unixEnterMutex(); /* Because pFile->pInode is shared across threads */ + + /* Check if a thread in this process holds such a lock */ + if( pFile->pInode->eFileLock>SHARED_LOCK ){ + reserved = 1; + } + + /* Otherwise see if some other process holds it. + */ + if( !reserved ){ + /* lock the RESERVED byte */ + int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1); + if( SQLITE_OK==lrc ){ + /* if we succeeded in taking the reserved lock, unlock it to restore + ** the original state */ + lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0); + } else { + /* if we failed to get the lock then someone else must have it */ + reserved = 1; + } + if( IS_LOCK_ERROR(lrc) ){ + rc=lrc; + } + } + + unixLeaveMutex(); + OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved)); + + *pResOut = reserved; + return rc; +} + +/* +** Lock the file with the lock specified by parameter eFileLock - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** This routine will only increase a lock. Use the sqlite3OsUnlock() +** routine to lower a locking level. +*/ +static int afpLock(sqlite3_file *id, int eFileLock){ + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + unixInodeInfo *pInode = pFile->pInode; + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; + + assert( pFile ); + OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h, + azFileLock(eFileLock), azFileLock(pFile->eFileLock), + azFileLock(pInode->eFileLock), pInode->nShared , osGetpid(0))); + + /* If there is already a lock of this type or more restrictive on the + ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as + ** unixEnterMutex() hasn't been called yet. + */ + if( pFile->eFileLock>=eFileLock ){ + OSTRACE(("LOCK %d %s ok (already held) (afp)\n", pFile->h, + azFileLock(eFileLock))); + return SQLITE_OK; + } + + /* Make sure the locking sequence is correct + ** (1) We never move from unlocked to anything higher than shared lock. + ** (2) SQLite never explicitly requests a pendig lock. + ** (3) A shared lock is always held when a reserve lock is requested. + */ + assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK ); + assert( eFileLock!=PENDING_LOCK ); + assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK ); + + /* This mutex is needed because pFile->pInode is shared across threads + */ + unixEnterMutex(); + pInode = pFile->pInode; + + /* If some thread using this PID has a lock via a different unixFile* + ** handle that precludes the requested lock, return BUSY. + */ + if( (pFile->eFileLock!=pInode->eFileLock && + (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK)) + ){ + rc = SQLITE_BUSY; + goto afp_end_lock; + } + + /* If a SHARED lock is requested, and some thread using this PID already + ** has a SHARED or RESERVED lock, then increment reference counts and + ** return SQLITE_OK. + */ + if( eFileLock==SHARED_LOCK && + (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){ + assert( eFileLock==SHARED_LOCK ); + assert( pFile->eFileLock==0 ); + assert( pInode->nShared>0 ); + pFile->eFileLock = SHARED_LOCK; + pInode->nShared++; + pInode->nLock++; + goto afp_end_lock; + } + + /* A PENDING lock is needed before acquiring a SHARED lock and before + ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will + ** be released. + */ + if( eFileLock==SHARED_LOCK + || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLockdbPath, pFile, PENDING_BYTE, 1, 1); + if (failed) { + rc = failed; + goto afp_end_lock; + } + } + + /* If control gets to this point, then actually go ahead and make + ** operating system calls for the specified lock. + */ + if( eFileLock==SHARED_LOCK ){ + int lrc1, lrc2, lrc1Errno = 0; + long lk, mask; + + assert( pInode->nShared==0 ); + assert( pInode->eFileLock==0 ); + + mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff; + /* Now get the read-lock SHARED_LOCK */ + /* note that the quality of the randomness doesn't matter that much */ + lk = random(); + pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1); + lrc1 = afpSetLock(context->dbPath, pFile, + SHARED_FIRST+pInode->sharedByte, 1, 1); + if( IS_LOCK_ERROR(lrc1) ){ + lrc1Errno = pFile->lastErrno; + } + /* Drop the temporary PENDING lock */ + lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); + + if( IS_LOCK_ERROR(lrc1) ) { + storeLastErrno(pFile, lrc1Errno); + rc = lrc1; + goto afp_end_lock; + } else if( IS_LOCK_ERROR(lrc2) ){ + rc = lrc2; + goto afp_end_lock; + } else if( lrc1 != SQLITE_OK ) { + rc = lrc1; + } else { + pFile->eFileLock = SHARED_LOCK; + pInode->nLock++; + pInode->nShared = 1; + } + }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){ + /* We are trying for an exclusive lock but another thread in this + ** same process is still holding a shared lock. */ + rc = SQLITE_BUSY; + }else{ + /* The request was for a RESERVED or EXCLUSIVE lock. It is + ** assumed that there is a SHARED or greater lock on the file + ** already. + */ + int failed = 0; + assert( 0!=pFile->eFileLock ); + if (eFileLock >= RESERVED_LOCK && pFile->eFileLock < RESERVED_LOCK) { + /* Acquire a RESERVED lock */ + failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1); + if( !failed ){ + context->reserved = 1; + } + } + if (!failed && eFileLock == EXCLUSIVE_LOCK) { + /* Acquire an EXCLUSIVE lock */ + + /* Remove the shared lock before trying the range. we'll need to + ** reestablish the shared lock if we can't get the afpUnlock + */ + if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST + + pInode->sharedByte, 1, 0)) ){ + int failed2 = SQLITE_OK; + /* now attemmpt to get the exclusive lock range */ + failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, + SHARED_SIZE, 1); + if( failed && (failed2 = afpSetLock(context->dbPath, pFile, + SHARED_FIRST + pInode->sharedByte, 1, 1)) ){ + /* Can't reestablish the shared lock. Sqlite can't deal, this is + ** a critical I/O error + */ + rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : + SQLITE_IOERR_LOCK; + goto afp_end_lock; + } + }else{ + rc = failed; + } + } + if( failed ){ + rc = failed; + } + } + + if( rc==SQLITE_OK ){ + pFile->eFileLock = eFileLock; + pInode->eFileLock = eFileLock; + }else if( eFileLock==EXCLUSIVE_LOCK ){ + pFile->eFileLock = PENDING_LOCK; + pInode->eFileLock = PENDING_LOCK; + } + +afp_end_lock: + unixLeaveMutex(); + OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock), + rc==SQLITE_OK ? "ok" : "failed")); + return rc; +} + +/* +** Lower the locking level on file descriptor pFile to eFileLock. eFileLock +** must be either NO_LOCK or SHARED_LOCK. +** +** If the locking level of the file descriptor is already at or below +** the requested locking level, this routine is a no-op. +*/ +static int afpUnlock(sqlite3_file *id, int eFileLock) { + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + unixInodeInfo *pInode; + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; + int skipShared = 0; +#ifdef SQLITE_TEST + int h = pFile->h; +#endif + + assert( pFile ); + OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock, + pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared, + osGetpid(0))); + + assert( eFileLock<=SHARED_LOCK ); + if( pFile->eFileLock<=eFileLock ){ + return SQLITE_OK; + } + unixEnterMutex(); + pInode = pFile->pInode; + assert( pInode->nShared!=0 ); + if( pFile->eFileLock>SHARED_LOCK ){ + assert( pInode->eFileLock==pFile->eFileLock ); + SimulateIOErrorBenign(1); + SimulateIOError( h=(-1) ) + SimulateIOErrorBenign(0); + +#ifdef SQLITE_DEBUG + /* When reducing a lock such that other processes can start + ** reading the database file again, make sure that the + ** transaction counter was updated if any part of the database + ** file changed. If the transaction counter is not updated, + ** other connections to the same file might not realize that + ** the file has changed and hence might not know to flush their + ** cache. The use of a stale cache can lead to database corruption. + */ + assert( pFile->inNormalWrite==0 + || pFile->dbUpdate==0 + || pFile->transCntrChng==1 ); + pFile->inNormalWrite = 0; +#endif + + if( pFile->eFileLock==EXCLUSIVE_LOCK ){ + rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0); + if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1) ){ + /* only re-establish the shared lock if necessary */ + int sharedLockByte = SHARED_FIRST+pInode->sharedByte; + rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1); + } else { + skipShared = 1; + } + } + if( rc==SQLITE_OK && pFile->eFileLock>=PENDING_LOCK ){ + rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); + } + if( rc==SQLITE_OK && pFile->eFileLock>=RESERVED_LOCK && context->reserved ){ + rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0); + if( !rc ){ + context->reserved = 0; + } + } + if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){ + pInode->eFileLock = SHARED_LOCK; + } + } + if( rc==SQLITE_OK && eFileLock==NO_LOCK ){ + + /* Decrement the shared lock counter. Release the lock using an + ** OS call only when all threads in this same process have released + ** the lock. + */ + unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte; + pInode->nShared--; + if( pInode->nShared==0 ){ + SimulateIOErrorBenign(1); + SimulateIOError( h=(-1) ) + SimulateIOErrorBenign(0); + if( !skipShared ){ + rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0); + } + if( !rc ){ + pInode->eFileLock = NO_LOCK; + pFile->eFileLock = NO_LOCK; + } + } + if( rc==SQLITE_OK ){ + pInode->nLock--; + assert( pInode->nLock>=0 ); + if( pInode->nLock==0 ){ + closePendingFds(pFile); + } + } + } + + unixLeaveMutex(); + if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock; + return rc; +} + +/* +** Close a file & cleanup AFP specific locking context +*/ +static int afpClose(sqlite3_file *id) { + int rc = SQLITE_OK; + if( id ){ + unixFile *pFile = (unixFile*)id; + afpUnlock(id, NO_LOCK); + unixEnterMutex(); + if( pFile->pInode && pFile->pInode->nLock ){ + /* If there are outstanding locks, do not actually close the file just + ** yet because that would clear those locks. Instead, add the file + ** descriptor to pInode->aPending. It will be automatically closed when + ** the last lock is cleared. + */ + setPendingFd(pFile); + } + releaseInodeInfo(pFile); + sqlite3_free(pFile->lockingContext); + rc = closeUnixFile(id); + unixLeaveMutex(); + } + return rc; +} + +#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ +/* +** The code above is the AFP lock implementation. The code is specific +** to MacOSX and does not work on other unix platforms. No alternative +** is available. If you don't compile for a mac, then the "unix-afp" +** VFS is not available. +** +********************* End of the AFP lock implementation ********************** +******************************************************************************/ + +/****************************************************************************** +*************************** Begin NFS Locking ********************************/ + +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE +/* + ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock + ** must be either NO_LOCK or SHARED_LOCK. + ** + ** If the locking level of the file descriptor is already at or below + ** the requested locking level, this routine is a no-op. + */ +static int nfsUnlock(sqlite3_file *id, int eFileLock){ + return posixUnlock(id, eFileLock, 1); +} + +#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ +/* +** The code above is the NFS lock implementation. The code is specific +** to MacOSX and does not work on other unix platforms. No alternative +** is available. +** +********************* End of the NFS lock implementation ********************** +******************************************************************************/ + +/****************************************************************************** +**************** Non-locking sqlite3_file methods ***************************** +** +** The next division contains implementations for all methods of the +** sqlite3_file object other than the locking methods. The locking +** methods were defined in divisions above (one locking method per +** division). Those methods that are common to all locking modes +** are gather together into this division. +*/ + +/* +** Seek to the offset passed as the second argument, then read cnt +** bytes into pBuf. Return the number of bytes actually read. +** +** NB: If you define USE_PREAD or USE_PREAD64, then it might also +** be necessary to define _XOPEN_SOURCE to be 500. This varies from +** one system to another. Since SQLite does not define USE_PREAD +** in any form by default, we will not attempt to define _XOPEN_SOURCE. +** See tickets #2741 and #2681. +** +** To avoid stomping the errno value on a failed read the lastErrno value +** is set before returning. +*/ +static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ + int got; + int prior = 0; +#if (!defined(USE_PREAD) && !defined(USE_PREAD64)) + i64 newOffset; +#endif + TIMER_START; + assert( cnt==(cnt&0x1ffff) ); + assert( id->h>2 ); + cnt &= 0x1ffff; + do{ +#if defined(USE_PREAD) + got = osPread(id->h, pBuf, cnt, offset); + SimulateIOError( got = -1 ); +#elif defined(USE_PREAD64) + got = osPread64(id->h, pBuf, cnt, offset); + SimulateIOError( got = -1 ); +#else + newOffset = lseek(id->h, offset, SEEK_SET); + SimulateIOError( newOffset-- ); + if( newOffset!=offset ){ + if( newOffset == -1 ){ + storeLastErrno((unixFile*)id, errno); + }else{ + storeLastErrno((unixFile*)id, 0); + } + return -1; + } + got = osRead(id->h, pBuf, cnt); +#endif + if( got==cnt ) break; + if( got<0 ){ + if( errno==EINTR ){ got = 1; continue; } + prior = 0; + storeLastErrno((unixFile*)id, errno); + break; + }else if( got>0 ){ + cnt -= got; + offset += got; + prior += got; + pBuf = (void*)(got + (char*)pBuf); + } + }while( got>0 ); + TIMER_END; + OSTRACE(("READ %-3d %5d %7lld %llu\n", + id->h, got+prior, offset-prior, TIMER_ELAPSED)); + return got+prior; +} + +/* +** Read data from a file into a buffer. Return SQLITE_OK if all +** bytes were read successfully and SQLITE_IOERR if anything goes +** wrong. +*/ +static int unixRead( + sqlite3_file *id, + void *pBuf, + int amt, + sqlite3_int64 offset +){ + unixFile *pFile = (unixFile *)id; + int got; + assert( id ); + assert( offset>=0 ); + assert( amt>0 ); + + /* If this is a database file (not a journal, master-journal or temp + ** file), the bytes in the locking range should never be read or written. */ +#if 0 + assert( pFile->pUnused==0 + || offset>=PENDING_BYTE+512 + || offset+amt<=PENDING_BYTE + ); +#endif + +#if SQLITE_MAX_MMAP_SIZE>0 + /* Deal with as much of this read request as possible by transfering + ** data from the memory mapping using memcpy(). */ + if( offsetmmapSize ){ + if( offset+amt <= pFile->mmapSize ){ + memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); + return SQLITE_OK; + }else{ + int nCopy = pFile->mmapSize - offset; + memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy); + pBuf = &((u8 *)pBuf)[nCopy]; + amt -= nCopy; + offset += nCopy; + } + } +#endif + + got = seekAndRead(pFile, offset, pBuf, amt); + if( got==amt ){ + return SQLITE_OK; + }else if( got<0 ){ + /* lastErrno set by seekAndRead */ + return SQLITE_IOERR_READ; + }else{ + storeLastErrno(pFile, 0); /* not a system error */ + /* Unread parts of the buffer must be zero-filled */ + memset(&((char*)pBuf)[got], 0, amt-got); + return SQLITE_IOERR_SHORT_READ; + } +} + +/* +** Attempt to seek the file-descriptor passed as the first argument to +** absolute offset iOff, then attempt to write nBuf bytes of data from +** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise, +** return the actual number of bytes written (which may be less than +** nBuf). +*/ +static int seekAndWriteFd( + int fd, /* File descriptor to write to */ + i64 iOff, /* File offset to begin writing at */ + const void *pBuf, /* Copy data from this buffer to the file */ + int nBuf, /* Size of buffer pBuf in bytes */ + int *piErrno /* OUT: Error number if error occurs */ +){ + int rc = 0; /* Value returned by system call */ + + assert( nBuf==(nBuf&0x1ffff) ); + assert( fd>2 ); + nBuf &= 0x1ffff; + TIMER_START; + +#if defined(USE_PREAD) + do{ rc = (int)osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR ); +#elif defined(USE_PREAD64) + do{ rc = (int)osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR); +#else + do{ + i64 iSeek = lseek(fd, iOff, SEEK_SET); + SimulateIOError( iSeek-- ); + + if( iSeek!=iOff ){ + if( piErrno ) *piErrno = (iSeek==-1 ? errno : 0); + return -1; + } + rc = osWrite(fd, pBuf, nBuf); + }while( rc<0 && errno==EINTR ); +#endif + + TIMER_END; + OSTRACE(("WRITE %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED)); + + if( rc<0 && piErrno ) *piErrno = errno; + return rc; +} + + +/* +** Seek to the offset in id->offset then read cnt bytes into pBuf. +** Return the number of bytes actually read. Update the offset. +** +** To avoid stomping the errno value on a failed write the lastErrno value +** is set before returning. +*/ +static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ + return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno); +} + + +/* +** Write data from a buffer into a file. Return SQLITE_OK on success +** or some other error code on failure. +*/ +static int unixWrite( + sqlite3_file *id, + const void *pBuf, + int amt, + sqlite3_int64 offset +){ + unixFile *pFile = (unixFile*)id; + int wrote = 0; + assert( id ); + assert( amt>0 ); + + /* If this is a database file (not a journal, master-journal or temp + ** file), the bytes in the locking range should never be read or written. */ +#if 0 + assert( pFile->pUnused==0 + || offset>=PENDING_BYTE+512 + || offset+amt<=PENDING_BYTE + ); +#endif + +#ifdef SQLITE_DEBUG + /* If we are doing a normal write to a database file (as opposed to + ** doing a hot-journal rollback or a write to some file other than a + ** normal database file) then record the fact that the database + ** has changed. If the transaction counter is modified, record that + ** fact too. + */ + if( pFile->inNormalWrite ){ + pFile->dbUpdate = 1; /* The database has been modified */ + if( offset<=24 && offset+amt>=27 ){ + int rc; + char oldCntr[4]; + SimulateIOErrorBenign(1); + rc = seekAndRead(pFile, 24, oldCntr, 4); + SimulateIOErrorBenign(0); + if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){ + pFile->transCntrChng = 1; /* The transaction counter has changed */ + } + } + } +#endif + +#if SQLITE_MAX_MMAP_SIZE>0 + /* Deal with as much of this write request as possible by transfering + ** data from the memory mapping using memcpy(). */ + if( offsetmmapSize ){ + if( offset+amt <= pFile->mmapSize ){ + memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt); + return SQLITE_OK; + }else{ + int nCopy = pFile->mmapSize - offset; + memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy); + pBuf = &((u8 *)pBuf)[nCopy]; + amt -= nCopy; + offset += nCopy; + } + } +#endif + + while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){ + amt -= wrote; + offset += wrote; + pBuf = &((char*)pBuf)[wrote]; + } + SimulateIOError(( wrote=(-1), amt=1 )); + SimulateDiskfullError(( wrote=0, amt=1 )); + + if( amt>0 ){ + if( wrote<0 && pFile->lastErrno!=ENOSPC ){ + /* lastErrno set by seekAndWrite */ + return SQLITE_IOERR_WRITE; + }else{ + storeLastErrno(pFile, 0); /* not a system error */ + return SQLITE_FULL; + } + } + + return SQLITE_OK; +} + +#ifdef SQLITE_TEST +/* +** Count the number of fullsyncs and normal syncs. This is used to test +** that syncs and fullsyncs are occurring at the right times. +*/ +SQLITE_API int sqlite3_sync_count = 0; +SQLITE_API int sqlite3_fullsync_count = 0; +#endif + +/* +** We do not trust systems to provide a working fdatasync(). Some do. +** Others do no. To be safe, we will stick with the (slightly slower) +** fsync(). If you know that your system does support fdatasync() correctly, +** then simply compile with -Dfdatasync=fdatasync or -DHAVE_FDATASYNC +*/ +#if !defined(fdatasync) && !HAVE_FDATASYNC +# define fdatasync fsync +#endif + +/* +** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not +** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently +** only available on Mac OS X. But that could change. +*/ +#ifdef F_FULLFSYNC +# define HAVE_FULLFSYNC 1 +#else +# define HAVE_FULLFSYNC 0 +#endif + + +/* +** The fsync() system call does not work as advertised on many +** unix systems. The following procedure is an attempt to make +** it work better. +** +** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful +** for testing when we want to run through the test suite quickly. +** You are strongly advised *not* to deploy with SQLITE_NO_SYNC +** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash +** or power failure will likely corrupt the database file. +** +** SQLite sets the dataOnly flag if the size of the file is unchanged. +** The idea behind dataOnly is that it should only write the file content +** to disk, not the inode. We only set dataOnly if the file size is +** unchanged since the file size is part of the inode. However, +** Ted Ts'o tells us that fdatasync() will also write the inode if the +** file size has changed. The only real difference between fdatasync() +** and fsync(), Ted tells us, is that fdatasync() will not flush the +** inode if the mtime or owner or other inode attributes have changed. +** We only care about the file size, not the other file attributes, so +** as far as SQLite is concerned, an fdatasync() is always adequate. +** So, we always use fdatasync() if it is available, regardless of +** the value of the dataOnly flag. +*/ +static int full_fsync(int fd, int fullSync, int dataOnly){ + int rc; + + /* The following "ifdef/elif/else/" block has the same structure as + ** the one below. It is replicated here solely to avoid cluttering + ** up the real code with the UNUSED_PARAMETER() macros. + */ +#ifdef SQLITE_NO_SYNC + UNUSED_PARAMETER(fd); + UNUSED_PARAMETER(fullSync); + UNUSED_PARAMETER(dataOnly); +#elif HAVE_FULLFSYNC + UNUSED_PARAMETER(dataOnly); +#else + UNUSED_PARAMETER(fullSync); + UNUSED_PARAMETER(dataOnly); +#endif + + /* Record the number of times that we do a normal fsync() and + ** FULLSYNC. This is used during testing to verify that this procedure + ** gets called with the correct arguments. + */ +#ifdef SQLITE_TEST + if( fullSync ) sqlite3_fullsync_count++; + sqlite3_sync_count++; +#endif + + /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a + ** no-op + */ +#ifdef SQLITE_NO_SYNC + rc = SQLITE_OK; +#elif HAVE_FULLFSYNC + if( fullSync ){ + rc = osFcntl(fd, F_FULLFSYNC, 0); + }else{ + rc = 1; + } + /* If the FULLFSYNC failed, fall back to attempting an fsync(). + ** It shouldn't be possible for fullfsync to fail on the local + ** file system (on OSX), so failure indicates that FULLFSYNC + ** isn't supported for this file system. So, attempt an fsync + ** and (for now) ignore the overhead of a superfluous fcntl call. + ** It'd be better to detect fullfsync support once and avoid + ** the fcntl call every time sync is called. + */ + if( rc ) rc = fsync(fd); + +#elif defined(__APPLE__) + /* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly + ** so currently we default to the macro that redefines fdatasync to fsync + */ + rc = fsync(fd); +#else + rc = fdatasync(fd); +#if OS_VXWORKS + if( rc==-1 && errno==ENOTSUP ){ + rc = fsync(fd); + } +#endif /* OS_VXWORKS */ +#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */ + + if( OS_VXWORKS && rc!= -1 ){ + rc = 0; + } + return rc; +} + +/* +** Open a file descriptor to the directory containing file zFilename. +** If successful, *pFd is set to the opened file descriptor and +** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM +** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined +** value. +** +** The directory file descriptor is used for only one thing - to +** fsync() a directory to make sure file creation and deletion events +** are flushed to disk. Such fsyncs are not needed on newer +** journaling filesystems, but are required on older filesystems. +** +** This routine can be overridden using the xSetSysCall interface. +** The ability to override this routine was added in support of the +** chromium sandbox. Opening a directory is a security risk (we are +** told) so making it overrideable allows the chromium sandbox to +** replace this routine with a harmless no-op. To make this routine +** a no-op, replace it with a stub that returns SQLITE_OK but leaves +** *pFd set to a negative number. +** +** If SQLITE_OK is returned, the caller is responsible for closing +** the file descriptor *pFd using close(). +*/ +static int openDirectory(const char *zFilename, int *pFd){ + int ii; + int fd = -1; + char zDirname[MAX_PATHNAME+1]; + + sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename); + for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--); + if( ii>0 ){ + zDirname[ii] = '\0'; + fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0); + if( fd>=0 ){ + OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); + } + } + *pFd = fd; + return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); +} + +/* +** Make sure all writes to a particular file are committed to disk. +** +** If dataOnly==0 then both the file itself and its metadata (file +** size, access time, etc) are synced. If dataOnly!=0 then only the +** file data is synced. +** +** Under Unix, also make sure that the directory entry for the file +** has been created by fsync-ing the directory that contains the file. +** If we do not do this and we encounter a power failure, the directory +** entry for the journal might not exist after we reboot. The next +** SQLite to access the file will not know that the journal exists (because +** the directory entry for the journal was never created) and the transaction +** will not roll back - possibly leading to database corruption. +*/ +static int unixSync(sqlite3_file *id, int flags){ + int rc; + unixFile *pFile = (unixFile*)id; + + int isDataOnly = (flags&SQLITE_SYNC_DATAONLY); + int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL; + + /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */ + assert((flags&0x0F)==SQLITE_SYNC_NORMAL + || (flags&0x0F)==SQLITE_SYNC_FULL + ); + + /* Unix cannot, but some systems may return SQLITE_FULL from here. This + ** line is to test that doing so does not cause any problems. + */ + SimulateDiskfullError( return SQLITE_FULL ); + + assert( pFile ); + OSTRACE(("SYNC %-3d\n", pFile->h)); + rc = full_fsync(pFile->h, isFullsync, isDataOnly); + SimulateIOError( rc=1 ); + if( rc ){ + storeLastErrno(pFile, errno); + return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath); + } + + /* Also fsync the directory containing the file if the DIRSYNC flag + ** is set. This is a one-time occurrence. Many systems (examples: AIX) + ** are unable to fsync a directory, so ignore errors on the fsync. + */ + if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){ + int dirfd; + OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath, + HAVE_FULLFSYNC, isFullsync)); + rc = osOpenDirectory(pFile->zPath, &dirfd); + if( rc==SQLITE_OK && dirfd>=0 ){ + full_fsync(dirfd, 0, 0); + robust_close(pFile, dirfd, __LINE__); + }else if( rc==SQLITE_CANTOPEN ){ + rc = SQLITE_OK; + } + pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC; + } + return rc; +} + +/* +** Truncate an open file to a specified size +*/ +static int unixTruncate(sqlite3_file *id, i64 nByte){ + unixFile *pFile = (unixFile *)id; + int rc; + assert( pFile ); + SimulateIOError( return SQLITE_IOERR_TRUNCATE ); + + /* If the user has configured a chunk-size for this file, truncate the + ** file so that it consists of an integer number of chunks (i.e. the + ** actual file size after the operation may be larger than the requested + ** size). + */ + if( pFile->szChunk>0 ){ + nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; + } + + rc = robust_ftruncate(pFile->h, nByte); + if( rc ){ + storeLastErrno(pFile, errno); + return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); + }else{ +#ifdef SQLITE_DEBUG + /* If we are doing a normal write to a database file (as opposed to + ** doing a hot-journal rollback or a write to some file other than a + ** normal database file) and we truncate the file to zero length, + ** that effectively updates the change counter. This might happen + ** when restoring a database using the backup API from a zero-length + ** source. + */ + if( pFile->inNormalWrite && nByte==0 ){ + pFile->transCntrChng = 1; + } +#endif + +#if SQLITE_MAX_MMAP_SIZE>0 + /* If the file was just truncated to a size smaller than the currently + ** mapped region, reduce the effective mapping size as well. SQLite will + ** use read() and write() to access data beyond this point from now on. + */ + if( nBytemmapSize ){ + pFile->mmapSize = nByte; + } +#endif + + return SQLITE_OK; + } +} + +/* +** Determine the current size of a file in bytes +*/ +static int unixFileSize(sqlite3_file *id, i64 *pSize){ + int rc; + struct stat buf; + assert( id ); + rc = osFstat(((unixFile*)id)->h, &buf); + SimulateIOError( rc=1 ); + if( rc!=0 ){ + storeLastErrno((unixFile*)id, errno); + return SQLITE_IOERR_FSTAT; + } + *pSize = buf.st_size; + + /* When opening a zero-size database, the findInodeInfo() procedure + ** writes a single byte into that file in order to work around a bug + ** in the OS-X msdos filesystem. In order to avoid problems with upper + ** layers, we need to report this file size as zero even though it is + ** really 1. Ticket #3260. + */ + if( *pSize==1 ) *pSize = 0; + + + return SQLITE_OK; +} + +#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) +/* +** Handler for proxy-locking file-control verbs. Defined below in the +** proxying locking division. +*/ +static int proxyFileControl(sqlite3_file*,int,void*); +#endif + +/* +** This function is called to handle the SQLITE_FCNTL_SIZE_HINT +** file-control operation. Enlarge the database to nBytes in size +** (rounded up to the next chunk-size). If the database is already +** nBytes or larger, this routine is a no-op. +*/ +static int fcntlSizeHint(unixFile *pFile, i64 nByte){ + if( pFile->szChunk>0 ){ + i64 nSize; /* Required file size */ + struct stat buf; /* Used to hold return values of fstat() */ + + if( osFstat(pFile->h, &buf) ){ + return SQLITE_IOERR_FSTAT; + } + + nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk; + if( nSize>(i64)buf.st_size ){ + +#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE + /* The code below is handling the return value of osFallocate() + ** correctly. posix_fallocate() is defined to "returns zero on success, + ** or an error number on failure". See the manpage for details. */ + int err; + do{ + err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); + }while( err==EINTR ); + if( err ) return SQLITE_IOERR_WRITE; +#else + /* If the OS does not have posix_fallocate(), fake it. Write a + ** single byte to the last byte in each block that falls entirely + ** within the extended region. Then, if required, a single byte + ** at offset (nSize-1), to set the size of the file correctly. + ** This is a similar technique to that used by glibc on systems + ** that do not have a real fallocate() call. + */ + int nBlk = buf.st_blksize; /* File-system block size */ + int nWrite = 0; /* Number of bytes written by seekAndWrite */ + i64 iWrite; /* Next offset to write to */ + + iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1; + assert( iWrite>=buf.st_size ); + assert( (iWrite/nBlk)==((buf.st_size+nBlk-1)/nBlk) ); + assert( ((iWrite+1)%nBlk)==0 ); + for(/*no-op*/; iWrite0 + if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){ + int rc; + if( pFile->szChunk<=0 ){ + if( robust_ftruncate(pFile->h, nByte) ){ + storeLastErrno(pFile, errno); + return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); + } + } + + rc = unixMapfile(pFile, nByte); + return rc; + } +#endif + + return SQLITE_OK; +} + +/* +** If *pArg is initially negative then this is a query. Set *pArg to +** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set. +** +** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags. +*/ +static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){ + if( *pArg<0 ){ + *pArg = (pFile->ctrlFlags & mask)!=0; + }else if( (*pArg)==0 ){ + pFile->ctrlFlags &= ~mask; + }else{ + pFile->ctrlFlags |= mask; + } +} + +/* Forward declaration */ +static int unixGetTempname(int nBuf, char *zBuf); + +/* +** Information and control of an open file handle. +*/ +static int unixFileControl(sqlite3_file *id, int op, void *pArg){ + unixFile *pFile = (unixFile*)id; + switch( op ){ + case SQLITE_FCNTL_WAL_BLOCK: { + /* pFile->ctrlFlags |= UNIXFILE_BLOCK; // Deferred feature */ + return SQLITE_OK; + } + case SQLITE_FCNTL_LOCKSTATE: { + *(int*)pArg = pFile->eFileLock; + return SQLITE_OK; + } + case SQLITE_FCNTL_LAST_ERRNO: { + *(int*)pArg = pFile->lastErrno; + return SQLITE_OK; + } + case SQLITE_FCNTL_CHUNK_SIZE: { + pFile->szChunk = *(int *)pArg; + return SQLITE_OK; + } + case SQLITE_FCNTL_SIZE_HINT: { + int rc; + SimulateIOErrorBenign(1); + rc = fcntlSizeHint(pFile, *(i64 *)pArg); + SimulateIOErrorBenign(0); + return rc; + } + case SQLITE_FCNTL_PERSIST_WAL: { + unixModeBit(pFile, UNIXFILE_PERSIST_WAL, (int*)pArg); + return SQLITE_OK; + } + case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { + unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg); + return SQLITE_OK; + } + case SQLITE_FCNTL_VFSNAME: { + *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); + return SQLITE_OK; + } + case SQLITE_FCNTL_TEMPFILENAME: { + char *zTFile = sqlite3_malloc64( pFile->pVfs->mxPathname ); + if( zTFile ){ + unixGetTempname(pFile->pVfs->mxPathname, zTFile); + *(char**)pArg = zTFile; + } + return SQLITE_OK; + } + case SQLITE_FCNTL_HAS_MOVED: { + *(int*)pArg = fileHasMoved(pFile); + return SQLITE_OK; + } +#if SQLITE_MAX_MMAP_SIZE>0 + case SQLITE_FCNTL_MMAP_SIZE: { + i64 newLimit = *(i64*)pArg; + int rc = SQLITE_OK; + if( newLimit>sqlite3GlobalConfig.mxMmap ){ + newLimit = sqlite3GlobalConfig.mxMmap; + } + *(i64*)pArg = pFile->mmapSizeMax; + if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){ + pFile->mmapSizeMax = newLimit; + if( pFile->mmapSize>0 ){ + unixUnmapfile(pFile); + rc = unixMapfile(pFile, -1); + } + } + return rc; + } +#endif +#ifdef SQLITE_DEBUG + /* The pager calls this method to signal that it has done + ** a rollback and that the database is therefore unchanged and + ** it hence it is OK for the transaction change counter to be + ** unchanged. + */ + case SQLITE_FCNTL_DB_UNCHANGED: { + ((unixFile*)id)->dbUpdate = 0; + return SQLITE_OK; + } +#endif +#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) + case SQLITE_FCNTL_SET_LOCKPROXYFILE: + case SQLITE_FCNTL_GET_LOCKPROXYFILE: { + return proxyFileControl(id,op,pArg); + } +#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */ + } + return SQLITE_NOTFOUND; +} + +/* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and its journal file) that the sector size will be the +** same for both. +*/ +#ifndef __QNXNTO__ +static int unixSectorSize(sqlite3_file *NotUsed){ + UNUSED_PARAMETER(NotUsed); + return SQLITE_DEFAULT_SECTOR_SIZE; +} +#endif + +/* +** The following version of unixSectorSize() is optimized for QNX. +*/ +#ifdef __QNXNTO__ +#include +#include +static int unixSectorSize(sqlite3_file *id){ + unixFile *pFile = (unixFile*)id; + if( pFile->sectorSize == 0 ){ + struct statvfs fsInfo; + + /* Set defaults for non-supported filesystems */ + pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; + pFile->deviceCharacteristics = 0; + if( fstatvfs(pFile->h, &fsInfo) == -1 ) { + return pFile->sectorSize; + } + + if( !strcmp(fsInfo.f_basetype, "tmp") ) { + pFile->sectorSize = fsInfo.f_bsize; + pFile->deviceCharacteristics = + SQLITE_IOCAP_ATOMIC4K | /* All ram filesystem writes are atomic */ + SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until + ** the write succeeds */ + SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind + ** so it is ordered */ + 0; + }else if( strstr(fsInfo.f_basetype, "etfs") ){ + pFile->sectorSize = fsInfo.f_bsize; + pFile->deviceCharacteristics = + /* etfs cluster size writes are atomic */ + (pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) | + SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until + ** the write succeeds */ + SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind + ** so it is ordered */ + 0; + }else if( !strcmp(fsInfo.f_basetype, "qnx6") ){ + pFile->sectorSize = fsInfo.f_bsize; + pFile->deviceCharacteristics = + SQLITE_IOCAP_ATOMIC | /* All filesystem writes are atomic */ + SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until + ** the write succeeds */ + SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind + ** so it is ordered */ + 0; + }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){ + pFile->sectorSize = fsInfo.f_bsize; + pFile->deviceCharacteristics = + /* full bitset of atomics from max sector size and smaller */ + ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 | + SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind + ** so it is ordered */ + 0; + }else if( strstr(fsInfo.f_basetype, "dos") ){ + pFile->sectorSize = fsInfo.f_bsize; + pFile->deviceCharacteristics = + /* full bitset of atomics from max sector size and smaller */ + ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 | + SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind + ** so it is ordered */ + 0; + }else{ + pFile->deviceCharacteristics = + SQLITE_IOCAP_ATOMIC512 | /* blocks are atomic */ + SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until + ** the write succeeds */ + 0; + } + } + /* Last chance verification. If the sector size isn't a multiple of 512 + ** then it isn't valid.*/ + if( pFile->sectorSize % 512 != 0 ){ + pFile->deviceCharacteristics = 0; + pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; + } + return pFile->sectorSize; +} +#endif /* __QNXNTO__ */ + +/* +** Return the device characteristics for the file. +** +** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default. +** However, that choice is controversial since technically the underlying +** file system does not always provide powersafe overwrites. (In other +** words, after a power-loss event, parts of the file that were never +** written might end up being altered.) However, non-PSOW behavior is very, +** very rare. And asserting PSOW makes a large reduction in the amount +** of required I/O for journaling, since a lot of padding is eliminated. +** Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control +** available to turn it off and URI query parameter available to turn it off. +*/ +static int unixDeviceCharacteristics(sqlite3_file *id){ + unixFile *p = (unixFile*)id; + int rc = 0; +#ifdef __QNXNTO__ + if( p->sectorSize==0 ) unixSectorSize(id); + rc = p->deviceCharacteristics; +#endif + if( p->ctrlFlags & UNIXFILE_PSOW ){ + rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE; + } + return rc; +} + +#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 + +/* +** Return the system page size. +** +** This function should not be called directly by other code in this file. +** Instead, it should be called via macro osGetpagesize(). +*/ +static int unixGetpagesize(void){ +#if OS_VXWORKS + return 1024; +#elif defined(_BSD_SOURCE) + return getpagesize(); +#else + return (int)sysconf(_SC_PAGESIZE); +#endif +} + +#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */ + +#ifndef SQLITE_OMIT_WAL + +/* +** Object used to represent an shared memory buffer. +** +** When multiple threads all reference the same wal-index, each thread +** has its own unixShm object, but they all point to a single instance +** of this unixShmNode object. In other words, each wal-index is opened +** only once per process. +** +** Each unixShmNode object is connected to a single unixInodeInfo object. +** We could coalesce this object into unixInodeInfo, but that would mean +** every open file that does not use shared memory (in other words, most +** open files) would have to carry around this extra information. So +** the unixInodeInfo object contains a pointer to this unixShmNode object +** and the unixShmNode object is created only when needed. +** +** unixMutexHeld() must be true when creating or destroying +** this object or while reading or writing the following fields: +** +** nRef +** +** The following fields are read-only after the object is created: +** +** fid +** zFilename +** +** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and +** unixMutexHeld() is true when reading or writing any other field +** in this structure. +*/ +struct unixShmNode { + unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */ + sqlite3_mutex *mutex; /* Mutex to access this object */ + char *zFilename; /* Name of the mmapped file */ + int h; /* Open file descriptor */ + int szRegion; /* Size of shared-memory regions */ + u16 nRegion; /* Size of array apRegion */ + u8 isReadonly; /* True if read-only */ + char **apRegion; /* Array of mapped shared-memory regions */ + int nRef; /* Number of unixShm objects pointing to this */ + unixShm *pFirst; /* All unixShm objects pointing to this */ +#ifdef SQLITE_DEBUG + u8 exclMask; /* Mask of exclusive locks held */ + u8 sharedMask; /* Mask of shared locks held */ + u8 nextShmId; /* Next available unixShm.id value */ +#endif +}; + +/* +** Structure used internally by this VFS to record the state of an +** open shared memory connection. +** +** The following fields are initialized when this object is created and +** are read-only thereafter: +** +** unixShm.pFile +** unixShm.id +** +** All other fields are read/write. The unixShm.pFile->mutex must be held +** while accessing any read/write fields. +*/ +struct unixShm { + unixShmNode *pShmNode; /* The underlying unixShmNode object */ + unixShm *pNext; /* Next unixShm with the same unixShmNode */ + u8 hasMutex; /* True if holding the unixShmNode mutex */ + u8 id; /* Id of this connection within its unixShmNode */ + u16 sharedMask; /* Mask of shared locks held */ + u16 exclMask; /* Mask of exclusive locks held */ +}; + +/* +** Constants used for locking +*/ +#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ +#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ + +/* +** Apply posix advisory locks for all bytes from ofst through ofst+n-1. +** +** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking +** otherwise. +*/ +static int unixShmSystemLock( + unixFile *pFile, /* Open connection to the WAL file */ + int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */ + int ofst, /* First byte of the locking range */ + int n /* Number of bytes to lock */ +){ + unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */ + struct flock f; /* The posix advisory locking structure */ + int rc = SQLITE_OK; /* Result code form fcntl() */ + + /* Access to the unixShmNode object is serialized by the caller */ + pShmNode = pFile->pInode->pShmNode; + assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 ); + + /* Shared locks never span more than one byte */ + assert( n==1 || lockType!=F_RDLCK ); + + /* Locks are within range */ + assert( n>=1 && nh>=0 ){ + int lkType; + /* Initialize the locking parameters */ + memset(&f, 0, sizeof(f)); + f.l_type = lockType; + f.l_whence = SEEK_SET; + f.l_start = ofst; + f.l_len = n; + + lkType = (pFile->ctrlFlags & UNIXFILE_BLOCK)!=0 ? F_SETLKW : F_SETLK; + rc = osFcntl(pShmNode->h, lkType, &f); + rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; + pFile->ctrlFlags &= ~UNIXFILE_BLOCK; + } + + /* Update the global lock state and do debug tracing */ +#ifdef SQLITE_DEBUG + { u16 mask; + OSTRACE(("SHM-LOCK ")); + mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<exclMask &= ~mask; + pShmNode->sharedMask &= ~mask; + }else if( lockType==F_RDLCK ){ + OSTRACE(("read-lock %d ok", ofst)); + pShmNode->exclMask &= ~mask; + pShmNode->sharedMask |= mask; + }else{ + assert( lockType==F_WRLCK ); + OSTRACE(("write-lock %d ok", ofst)); + pShmNode->exclMask |= mask; + pShmNode->sharedMask &= ~mask; + } + }else{ + if( lockType==F_UNLCK ){ + OSTRACE(("unlock %d failed", ofst)); + }else if( lockType==F_RDLCK ){ + OSTRACE(("read-lock failed")); + }else{ + assert( lockType==F_WRLCK ); + OSTRACE(("write-lock %d failed", ofst)); + } + } + OSTRACE((" - afterwards %03x,%03x\n", + pShmNode->sharedMask, pShmNode->exclMask)); + } +#endif + + return rc; +} + +/* +** Return the minimum number of 32KB shm regions that should be mapped at +** a time, assuming that each mapping must be an integer multiple of the +** current system page-size. +** +** Usually, this is 1. The exception seems to be systems that are configured +** to use 64KB pages - in this case each mapping must cover at least two +** shm regions. +*/ +static int unixShmRegionPerMap(void){ + int shmsz = 32*1024; /* SHM region size */ + int pgsz = osGetpagesize(); /* System page size */ + assert( ((pgsz-1)&pgsz)==0 ); /* Page size must be a power of 2 */ + if( pgszpInode->pShmNode; + assert( unixMutexHeld() ); + if( p && p->nRef==0 ){ + int nShmPerMap = unixShmRegionPerMap(); + int i; + assert( p->pInode==pFd->pInode ); + sqlite3_mutex_free(p->mutex); + for(i=0; inRegion; i+=nShmPerMap){ + if( p->h>=0 ){ + osMunmap(p->apRegion[i], p->szRegion); + }else{ + sqlite3_free(p->apRegion[i]); + } + } + sqlite3_free(p->apRegion); + if( p->h>=0 ){ + robust_close(pFd, p->h, __LINE__); + p->h = -1; + } + p->pInode->pShmNode = 0; + sqlite3_free(p); + } +} + +/* +** Open a shared-memory area associated with open database file pDbFd. +** This particular implementation uses mmapped files. +** +** The file used to implement shared-memory is in the same directory +** as the open database file and has the same name as the open database +** file with the "-shm" suffix added. For example, if the database file +** is "/home/user1/config.db" then the file that is created and mmapped +** for shared memory will be called "/home/user1/config.db-shm". +** +** Another approach to is to use files in /dev/shm or /dev/tmp or an +** some other tmpfs mount. But if a file in a different directory +** from the database file is used, then differing access permissions +** or a chroot() might cause two different processes on the same +** database to end up using different files for shared memory - +** meaning that their memory would not really be shared - resulting +** in database corruption. Nevertheless, this tmpfs file usage +** can be enabled at compile-time using -DSQLITE_SHM_DIRECTORY="/dev/shm" +** or the equivalent. The use of the SQLITE_SHM_DIRECTORY compile-time +** option results in an incompatible build of SQLite; builds of SQLite +** that with differing SQLITE_SHM_DIRECTORY settings attempt to use the +** same database file at the same time, database corruption will likely +** result. The SQLITE_SHM_DIRECTORY compile-time option is considered +** "unsupported" and may go away in a future SQLite release. +** +** When opening a new shared-memory file, if no other instances of that +** file are currently open, in this process or in other processes, then +** the file must be truncated to zero length or have its header cleared. +** +** If the original database file (pDbFd) is using the "unix-excl" VFS +** that means that an exclusive lock is held on the database file and +** that no other processes are able to read or write the database. In +** that case, we do not really need shared memory. No shared memory +** file is created. The shared memory will be simulated with heap memory. +*/ +static int unixOpenSharedMemory(unixFile *pDbFd){ + struct unixShm *p = 0; /* The connection to be opened */ + struct unixShmNode *pShmNode; /* The underlying mmapped file */ + int rc; /* Result code */ + unixInodeInfo *pInode; /* The inode of fd */ + char *zShmFilename; /* Name of the file used for SHM */ + int nShmFilename; /* Size of the SHM filename in bytes */ + + /* Allocate space for the new unixShm object. */ + p = sqlite3_malloc64( sizeof(*p) ); + if( p==0 ) return SQLITE_NOMEM; + memset(p, 0, sizeof(*p)); + assert( pDbFd->pShm==0 ); + + /* Check to see if a unixShmNode object already exists. Reuse an existing + ** one if present. Create a new one if necessary. + */ + unixEnterMutex(); + pInode = pDbFd->pInode; + pShmNode = pInode->pShmNode; + if( pShmNode==0 ){ + struct stat sStat; /* fstat() info for database file */ +#ifndef SQLITE_SHM_DIRECTORY + const char *zBasePath = pDbFd->zPath; +#endif + + /* Call fstat() to figure out the permissions on the database file. If + ** a new *-shm file is created, an attempt will be made to create it + ** with the same permissions. + */ + if( osFstat(pDbFd->h, &sStat) && pInode->bProcessLock==0 ){ + rc = SQLITE_IOERR_FSTAT; + goto shm_open_err; + } + +#ifdef SQLITE_SHM_DIRECTORY + nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31; +#else + nShmFilename = 6 + (int)strlen(zBasePath); +#endif + pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename ); + if( pShmNode==0 ){ + rc = SQLITE_NOMEM; + goto shm_open_err; + } + memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename); + zShmFilename = pShmNode->zFilename = (char*)&pShmNode[1]; +#ifdef SQLITE_SHM_DIRECTORY + sqlite3_snprintf(nShmFilename, zShmFilename, + SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x", + (u32)sStat.st_ino, (u32)sStat.st_dev); +#else + sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", zBasePath); + sqlite3FileSuffix3(pDbFd->zPath, zShmFilename); +#endif + pShmNode->h = -1; + pDbFd->pInode->pShmNode = pShmNode; + pShmNode->pInode = pDbFd->pInode; + pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + if( pShmNode->mutex==0 ){ + rc = SQLITE_NOMEM; + goto shm_open_err; + } + + if( pInode->bProcessLock==0 ){ + int openFlags = O_RDWR | O_CREAT; + if( sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ + openFlags = O_RDONLY; + pShmNode->isReadonly = 1; + } + pShmNode->h = robust_open(zShmFilename, openFlags, (sStat.st_mode&0777)); + if( pShmNode->h<0 ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename); + goto shm_open_err; + } + + /* If this process is running as root, make sure that the SHM file + ** is owned by the same user that owns the original database. Otherwise, + ** the original owner will not be able to connect. + */ + osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid); + + /* Check to see if another process is holding the dead-man switch. + ** If not, truncate the file to zero length. + */ + rc = SQLITE_OK; + if( unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){ + if( robust_ftruncate(pShmNode->h, 0) ){ + rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename); + } + } + if( rc==SQLITE_OK ){ + rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1); + } + if( rc ) goto shm_open_err; + } + } + + /* Make the new connection a child of the unixShmNode */ + p->pShmNode = pShmNode; +#ifdef SQLITE_DEBUG + p->id = pShmNode->nextShmId++; +#endif + pShmNode->nRef++; + pDbFd->pShm = p; + unixLeaveMutex(); + + /* The reference count on pShmNode has already been incremented under + ** the cover of the unixEnterMutex() mutex and the pointer from the + ** new (struct unixShm) object to the pShmNode has been set. All that is + ** left to do is to link the new object into the linked list starting + ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex + ** mutex. + */ + sqlite3_mutex_enter(pShmNode->mutex); + p->pNext = pShmNode->pFirst; + pShmNode->pFirst = p; + sqlite3_mutex_leave(pShmNode->mutex); + return SQLITE_OK; + + /* Jump here on any error */ +shm_open_err: + unixShmPurge(pDbFd); /* This call frees pShmNode if required */ + sqlite3_free(p); + unixLeaveMutex(); + return rc; +} + +/* +** This function is called to obtain a pointer to region iRegion of the +** shared-memory associated with the database file fd. Shared-memory regions +** are numbered starting from zero. Each shared-memory region is szRegion +** bytes in size. +** +** If an error occurs, an error code is returned and *pp is set to NULL. +** +** Otherwise, if the bExtend parameter is 0 and the requested shared-memory +** region has not been allocated (by any client, including one running in a +** separate process), then *pp is set to NULL and SQLITE_OK returned. If +** bExtend is non-zero and the requested shared-memory region has not yet +** been allocated, it is allocated by this function. +** +** If the shared-memory region has already been allocated or is allocated by +** this call as described above, then it is mapped into this processes +** address space (if it is not already), *pp is set to point to the mapped +** memory and SQLITE_OK returned. +*/ +static int unixShmMap( + sqlite3_file *fd, /* Handle open on database file */ + int iRegion, /* Region to retrieve */ + int szRegion, /* Size of regions */ + int bExtend, /* True to extend file if necessary */ + void volatile **pp /* OUT: Mapped memory */ +){ + unixFile *pDbFd = (unixFile*)fd; + unixShm *p; + unixShmNode *pShmNode; + int rc = SQLITE_OK; + int nShmPerMap = unixShmRegionPerMap(); + int nReqRegion; + + /* If the shared-memory file has not yet been opened, open it now. */ + if( pDbFd->pShm==0 ){ + rc = unixOpenSharedMemory(pDbFd); + if( rc!=SQLITE_OK ) return rc; + } + + p = pDbFd->pShm; + pShmNode = p->pShmNode; + sqlite3_mutex_enter(pShmNode->mutex); + assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); + assert( pShmNode->pInode==pDbFd->pInode ); + assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); + assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 ); + + /* Minimum number of regions required to be mapped. */ + nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap; + + if( pShmNode->nRegionszRegion = szRegion; + + if( pShmNode->h>=0 ){ + /* The requested region is not mapped into this processes address space. + ** Check to see if it has been allocated (i.e. if the wal-index file is + ** large enough to contain the requested region). + */ + if( osFstat(pShmNode->h, &sStat) ){ + rc = SQLITE_IOERR_SHMSIZE; + goto shmpage_out; + } + + if( sStat.st_sizeh, iPg*pgsz + pgsz-1, "", 1, 0)!=1 ){ + const char *zFile = pShmNode->zFilename; + rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile); + goto shmpage_out; + } + } + } + } + } + + /* Map the requested memory region into this processes address space. */ + apNew = (char **)sqlite3_realloc( + pShmNode->apRegion, nReqRegion*sizeof(char *) + ); + if( !apNew ){ + rc = SQLITE_IOERR_NOMEM; + goto shmpage_out; + } + pShmNode->apRegion = apNew; + while( pShmNode->nRegionh>=0 ){ + pMem = osMmap(0, nMap, + pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, + MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion + ); + if( pMem==MAP_FAILED ){ + rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename); + goto shmpage_out; + } + }else{ + pMem = sqlite3_malloc64(szRegion); + if( pMem==0 ){ + rc = SQLITE_NOMEM; + goto shmpage_out; + } + memset(pMem, 0, szRegion); + } + + for(i=0; iapRegion[pShmNode->nRegion+i] = &((char*)pMem)[szRegion*i]; + } + pShmNode->nRegion += nShmPerMap; + } + } + +shmpage_out: + if( pShmNode->nRegion>iRegion ){ + *pp = pShmNode->apRegion[iRegion]; + }else{ + *pp = 0; + } + if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY; + sqlite3_mutex_leave(pShmNode->mutex); + return rc; +} + +/* +** Change the lock state for a shared-memory segment. +** +** Note that the relationship between SHAREd and EXCLUSIVE locks is a little +** different here than in posix. In xShmLock(), one can go from unlocked +** to shared and back or from unlocked to exclusive and back. But one may +** not go from shared to exclusive or from exclusive to shared. +*/ +static int unixShmLock( + sqlite3_file *fd, /* Database file holding the shared memory */ + int ofst, /* First lock to acquire or release */ + int n, /* Number of locks to acquire or release */ + int flags /* What to do with the lock */ +){ + unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */ + unixShm *p = pDbFd->pShm; /* The shared memory being locked */ + unixShm *pX; /* For looping over all siblings */ + unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */ + int rc = SQLITE_OK; /* Result code */ + u16 mask; /* Mask of locks to take or release */ + + assert( pShmNode==pDbFd->pInode->pShmNode ); + assert( pShmNode->pInode==pDbFd->pInode ); + assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK ); + assert( n>=1 ); + assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED) + || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE) + || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) + || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); + assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); + assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); + assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 ); + + mask = (1<<(ofst+n)) - (1<1 || mask==(1<mutex); + if( flags & SQLITE_SHM_UNLOCK ){ + u16 allMask = 0; /* Mask of locks held by siblings */ + + /* See if any siblings hold this same lock */ + for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ + if( pX==p ) continue; + assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 ); + allMask |= pX->sharedMask; + } + + /* Unlock the system-level locks */ + if( (mask & allMask)==0 ){ + rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n); + }else{ + rc = SQLITE_OK; + } + + /* Undo the local locks */ + if( rc==SQLITE_OK ){ + p->exclMask &= ~mask; + p->sharedMask &= ~mask; + } + }else if( flags & SQLITE_SHM_SHARED ){ + u16 allShared = 0; /* Union of locks held by connections other than "p" */ + + /* Find out which shared locks are already held by sibling connections. + ** If any sibling already holds an exclusive lock, go ahead and return + ** SQLITE_BUSY. + */ + for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ + if( (pX->exclMask & mask)!=0 ){ + rc = SQLITE_BUSY; + break; + } + allShared |= pX->sharedMask; + } + + /* Get shared locks at the system level, if necessary */ + if( rc==SQLITE_OK ){ + if( (allShared & mask)==0 ){ + rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n); + }else{ + rc = SQLITE_OK; + } + } + + /* Get the local shared locks */ + if( rc==SQLITE_OK ){ + p->sharedMask |= mask; + } + }else{ + /* Make sure no sibling connections hold locks that will block this + ** lock. If any do, return SQLITE_BUSY right away. + */ + for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ + if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){ + rc = SQLITE_BUSY; + break; + } + } + + /* Get the exclusive locks at the system level. Then if successful + ** also mark the local connection as being locked. + */ + if( rc==SQLITE_OK ){ + rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n); + if( rc==SQLITE_OK ){ + assert( (p->sharedMask & mask)==0 ); + p->exclMask |= mask; + } + } + } + sqlite3_mutex_leave(pShmNode->mutex); + OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n", + p->id, osGetpid(0), p->sharedMask, p->exclMask)); + return rc; +} + +/* +** Implement a memory barrier or memory fence on shared memory. +** +** All loads and stores begun before the barrier must complete before +** any load or store begun after the barrier. +*/ +static void unixShmBarrier( + sqlite3_file *fd /* Database file holding the shared memory */ +){ + UNUSED_PARAMETER(fd); + unixEnterMutex(); + unixLeaveMutex(); +} + +/* +** Close a connection to shared-memory. Delete the underlying +** storage if deleteFlag is true. +** +** If there is no shared memory associated with the connection then this +** routine is a harmless no-op. +*/ +static int unixShmUnmap( + sqlite3_file *fd, /* The underlying database file */ + int deleteFlag /* Delete shared-memory if true */ +){ + unixShm *p; /* The connection to be closed */ + unixShmNode *pShmNode; /* The underlying shared-memory file */ + unixShm **pp; /* For looping over sibling connections */ + unixFile *pDbFd; /* The underlying database file */ + + pDbFd = (unixFile*)fd; + p = pDbFd->pShm; + if( p==0 ) return SQLITE_OK; + pShmNode = p->pShmNode; + + assert( pShmNode==pDbFd->pInode->pShmNode ); + assert( pShmNode->pInode==pDbFd->pInode ); + + /* Remove connection p from the set of connections associated + ** with pShmNode */ + sqlite3_mutex_enter(pShmNode->mutex); + for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} + *pp = p->pNext; + + /* Free the connection p */ + sqlite3_free(p); + pDbFd->pShm = 0; + sqlite3_mutex_leave(pShmNode->mutex); + + /* If pShmNode->nRef has reached 0, then close the underlying + ** shared-memory file, too */ + unixEnterMutex(); + assert( pShmNode->nRef>0 ); + pShmNode->nRef--; + if( pShmNode->nRef==0 ){ + if( deleteFlag && pShmNode->h>=0 ){ + osUnlink(pShmNode->zFilename); + } + unixShmPurge(pDbFd); + } + unixLeaveMutex(); + + return SQLITE_OK; +} + + +#else +# define unixShmMap 0 +# define unixShmLock 0 +# define unixShmBarrier 0 +# define unixShmUnmap 0 +#endif /* #ifndef SQLITE_OMIT_WAL */ + +#if SQLITE_MAX_MMAP_SIZE>0 +/* +** If it is currently memory mapped, unmap file pFd. +*/ +static void unixUnmapfile(unixFile *pFd){ + assert( pFd->nFetchOut==0 ); + if( pFd->pMapRegion ){ + osMunmap(pFd->pMapRegion, pFd->mmapSizeActual); + pFd->pMapRegion = 0; + pFd->mmapSize = 0; + pFd->mmapSizeActual = 0; + } +} + +/* +** Attempt to set the size of the memory mapping maintained by file +** descriptor pFd to nNew bytes. Any existing mapping is discarded. +** +** If successful, this function sets the following variables: +** +** unixFile.pMapRegion +** unixFile.mmapSize +** unixFile.mmapSizeActual +** +** If unsuccessful, an error message is logged via sqlite3_log() and +** the three variables above are zeroed. In this case SQLite should +** continue accessing the database using the xRead() and xWrite() +** methods. +*/ +static void unixRemapfile( + unixFile *pFd, /* File descriptor object */ + i64 nNew /* Required mapping size */ +){ + const char *zErr = "mmap"; + int h = pFd->h; /* File descriptor open on db file */ + u8 *pOrig = (u8 *)pFd->pMapRegion; /* Pointer to current file mapping */ + i64 nOrig = pFd->mmapSizeActual; /* Size of pOrig region in bytes */ + u8 *pNew = 0; /* Location of new mapping */ + int flags = PROT_READ; /* Flags to pass to mmap() */ + + assert( pFd->nFetchOut==0 ); + assert( nNew>pFd->mmapSize ); + assert( nNew<=pFd->mmapSizeMax ); + assert( nNew>0 ); + assert( pFd->mmapSizeActual>=pFd->mmapSize ); + assert( MAP_FAILED!=0 ); + + if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE; + + if( pOrig ){ +#if HAVE_MREMAP + i64 nReuse = pFd->mmapSize; +#else + const int szSyspage = osGetpagesize(); + i64 nReuse = (pFd->mmapSize & ~(szSyspage-1)); +#endif + u8 *pReq = &pOrig[nReuse]; + + /* Unmap any pages of the existing mapping that cannot be reused. */ + if( nReuse!=nOrig ){ + osMunmap(pReq, nOrig-nReuse); + } + +#if HAVE_MREMAP + pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE); + zErr = "mremap"; +#else + pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse); + if( pNew!=MAP_FAILED ){ + if( pNew!=pReq ){ + osMunmap(pNew, nNew - nReuse); + pNew = 0; + }else{ + pNew = pOrig; + } + } +#endif + + /* The attempt to extend the existing mapping failed. Free it. */ + if( pNew==MAP_FAILED || pNew==0 ){ + osMunmap(pOrig, nReuse); + } + } + + /* If pNew is still NULL, try to create an entirely new mapping. */ + if( pNew==0 ){ + pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0); + } + + if( pNew==MAP_FAILED ){ + pNew = 0; + nNew = 0; + unixLogError(SQLITE_OK, zErr, pFd->zPath); + + /* If the mmap() above failed, assume that all subsequent mmap() calls + ** will probably fail too. Fall back to using xRead/xWrite exclusively + ** in this case. */ + pFd->mmapSizeMax = 0; + } + pFd->pMapRegion = (void *)pNew; + pFd->mmapSize = pFd->mmapSizeActual = nNew; +} + +/* +** Memory map or remap the file opened by file-descriptor pFd (if the file +** is already mapped, the existing mapping is replaced by the new). Or, if +** there already exists a mapping for this file, and there are still +** outstanding xFetch() references to it, this function is a no-op. +** +** If parameter nByte is non-negative, then it is the requested size of +** the mapping to create. Otherwise, if nByte is less than zero, then the +** requested size is the size of the file on disk. The actual size of the +** created mapping is either the requested size or the value configured +** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller. +** +** SQLITE_OK is returned if no error occurs (even if the mapping is not +** recreated as a result of outstanding references) or an SQLite error +** code otherwise. +*/ +static int unixMapfile(unixFile *pFd, i64 nByte){ + i64 nMap = nByte; + int rc; + + assert( nMap>=0 || pFd->nFetchOut==0 ); + if( pFd->nFetchOut>0 ) return SQLITE_OK; + + if( nMap<0 ){ + struct stat statbuf; /* Low-level file information */ + rc = osFstat(pFd->h, &statbuf); + if( rc!=SQLITE_OK ){ + return SQLITE_IOERR_FSTAT; + } + nMap = statbuf.st_size; + } + if( nMap>pFd->mmapSizeMax ){ + nMap = pFd->mmapSizeMax; + } + + if( nMap!=pFd->mmapSize ){ + if( nMap>0 ){ + unixRemapfile(pFd, nMap); + }else{ + unixUnmapfile(pFd); + } + } + + return SQLITE_OK; +} +#endif /* SQLITE_MAX_MMAP_SIZE>0 */ + +/* +** If possible, return a pointer to a mapping of file fd starting at offset +** iOff. The mapping must be valid for at least nAmt bytes. +** +** If such a pointer can be obtained, store it in *pp and return SQLITE_OK. +** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK. +** Finally, if an error does occur, return an SQLite error code. The final +** value of *pp is undefined in this case. +** +** If this function does return a pointer, the caller must eventually +** release the reference by calling unixUnfetch(). +*/ +static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ +#if SQLITE_MAX_MMAP_SIZE>0 + unixFile *pFd = (unixFile *)fd; /* The underlying database file */ +#endif + *pp = 0; + +#if SQLITE_MAX_MMAP_SIZE>0 + if( pFd->mmapSizeMax>0 ){ + if( pFd->pMapRegion==0 ){ + int rc = unixMapfile(pFd, -1); + if( rc!=SQLITE_OK ) return rc; + } + if( pFd->mmapSize >= iOff+nAmt ){ + *pp = &((u8 *)pFd->pMapRegion)[iOff]; + pFd->nFetchOut++; + } + } +#endif + return SQLITE_OK; +} + +/* +** If the third argument is non-NULL, then this function releases a +** reference obtained by an earlier call to unixFetch(). The second +** argument passed to this function must be the same as the corresponding +** argument that was passed to the unixFetch() invocation. +** +** Or, if the third argument is NULL, then this function is being called +** to inform the VFS layer that, according to POSIX, any existing mapping +** may now be invalid and should be unmapped. +*/ +static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){ +#if SQLITE_MAX_MMAP_SIZE>0 + unixFile *pFd = (unixFile *)fd; /* The underlying database file */ + UNUSED_PARAMETER(iOff); + + /* If p==0 (unmap the entire file) then there must be no outstanding + ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference), + ** then there must be at least one outstanding. */ + assert( (p==0)==(pFd->nFetchOut==0) ); + + /* If p!=0, it must match the iOff value. */ + assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] ); + + if( p ){ + pFd->nFetchOut--; + }else{ + unixUnmapfile(pFd); + } + + assert( pFd->nFetchOut>=0 ); +#else + UNUSED_PARAMETER(fd); + UNUSED_PARAMETER(p); + UNUSED_PARAMETER(iOff); +#endif + return SQLITE_OK; +} + +/* +** Here ends the implementation of all sqlite3_file methods. +** +********************** End sqlite3_file Methods ******************************* +******************************************************************************/ + +/* +** This division contains definitions of sqlite3_io_methods objects that +** implement various file locking strategies. It also contains definitions +** of "finder" functions. A finder-function is used to locate the appropriate +** sqlite3_io_methods object for a particular database file. The pAppData +** field of the sqlite3_vfs VFS objects are initialized to be pointers to +** the correct finder-function for that VFS. +** +** Most finder functions return a pointer to a fixed sqlite3_io_methods +** object. The only interesting finder-function is autolockIoFinder, which +** looks at the filesystem type and tries to guess the best locking +** strategy from that. +** +** For finder-function F, two objects are created: +** +** (1) The real finder-function named "FImpt()". +** +** (2) A constant pointer to this function named just "F". +** +** +** A pointer to the F pointer is used as the pAppData value for VFS +** objects. We have to do this instead of letting pAppData point +** directly at the finder-function since C90 rules prevent a void* +** from be cast into a function pointer. +** +** +** Each instance of this macro generates two objects: +** +** * A constant sqlite3_io_methods object call METHOD that has locking +** methods CLOSE, LOCK, UNLOCK, CKRESLOCK. +** +** * An I/O method finder function called FINDER that returns a pointer +** to the METHOD object in the previous bullet. +*/ +#define IOMETHODS(FINDER,METHOD,VERSION,CLOSE,LOCK,UNLOCK,CKLOCK,SHMMAP) \ +static const sqlite3_io_methods METHOD = { \ + VERSION, /* iVersion */ \ + CLOSE, /* xClose */ \ + unixRead, /* xRead */ \ + unixWrite, /* xWrite */ \ + unixTruncate, /* xTruncate */ \ + unixSync, /* xSync */ \ + unixFileSize, /* xFileSize */ \ + LOCK, /* xLock */ \ + UNLOCK, /* xUnlock */ \ + CKLOCK, /* xCheckReservedLock */ \ + unixFileControl, /* xFileControl */ \ + unixSectorSize, /* xSectorSize */ \ + unixDeviceCharacteristics, /* xDeviceCapabilities */ \ + SHMMAP, /* xShmMap */ \ + unixShmLock, /* xShmLock */ \ + unixShmBarrier, /* xShmBarrier */ \ + unixShmUnmap, /* xShmUnmap */ \ + unixFetch, /* xFetch */ \ + unixUnfetch, /* xUnfetch */ \ +}; \ +static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \ + UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \ + return &METHOD; \ +} \ +static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p) \ + = FINDER##Impl; + +/* +** Here are all of the sqlite3_io_methods objects for each of the +** locking strategies. Functions that return pointers to these methods +** are also created. +*/ +IOMETHODS( + posixIoFinder, /* Finder function name */ + posixIoMethods, /* sqlite3_io_methods object name */ + 3, /* shared memory and mmap are enabled */ + unixClose, /* xClose method */ + unixLock, /* xLock method */ + unixUnlock, /* xUnlock method */ + unixCheckReservedLock, /* xCheckReservedLock method */ + unixShmMap /* xShmMap method */ +) +IOMETHODS( + nolockIoFinder, /* Finder function name */ + nolockIoMethods, /* sqlite3_io_methods object name */ + 3, /* shared memory is disabled */ + nolockClose, /* xClose method */ + nolockLock, /* xLock method */ + nolockUnlock, /* xUnlock method */ + nolockCheckReservedLock, /* xCheckReservedLock method */ + 0 /* xShmMap method */ +) +IOMETHODS( + dotlockIoFinder, /* Finder function name */ + dotlockIoMethods, /* sqlite3_io_methods object name */ + 1, /* shared memory is disabled */ + dotlockClose, /* xClose method */ + dotlockLock, /* xLock method */ + dotlockUnlock, /* xUnlock method */ + dotlockCheckReservedLock, /* xCheckReservedLock method */ + 0 /* xShmMap method */ +) + +#if SQLITE_ENABLE_LOCKING_STYLE +IOMETHODS( + flockIoFinder, /* Finder function name */ + flockIoMethods, /* sqlite3_io_methods object name */ + 1, /* shared memory is disabled */ + flockClose, /* xClose method */ + flockLock, /* xLock method */ + flockUnlock, /* xUnlock method */ + flockCheckReservedLock, /* xCheckReservedLock method */ + 0 /* xShmMap method */ +) +#endif + +#if OS_VXWORKS +IOMETHODS( + semIoFinder, /* Finder function name */ + semIoMethods, /* sqlite3_io_methods object name */ + 1, /* shared memory is disabled */ + semXClose, /* xClose method */ + semXLock, /* xLock method */ + semXUnlock, /* xUnlock method */ + semXCheckReservedLock, /* xCheckReservedLock method */ + 0 /* xShmMap method */ +) +#endif + +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE +IOMETHODS( + afpIoFinder, /* Finder function name */ + afpIoMethods, /* sqlite3_io_methods object name */ + 1, /* shared memory is disabled */ + afpClose, /* xClose method */ + afpLock, /* xLock method */ + afpUnlock, /* xUnlock method */ + afpCheckReservedLock, /* xCheckReservedLock method */ + 0 /* xShmMap method */ +) +#endif + +/* +** The proxy locking method is a "super-method" in the sense that it +** opens secondary file descriptors for the conch and lock files and +** it uses proxy, dot-file, AFP, and flock() locking methods on those +** secondary files. For this reason, the division that implements +** proxy locking is located much further down in the file. But we need +** to go ahead and define the sqlite3_io_methods and finder function +** for proxy locking here. So we forward declare the I/O methods. +*/ +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE +static int proxyClose(sqlite3_file*); +static int proxyLock(sqlite3_file*, int); +static int proxyUnlock(sqlite3_file*, int); +static int proxyCheckReservedLock(sqlite3_file*, int*); +IOMETHODS( + proxyIoFinder, /* Finder function name */ + proxyIoMethods, /* sqlite3_io_methods object name */ + 1, /* shared memory is disabled */ + proxyClose, /* xClose method */ + proxyLock, /* xLock method */ + proxyUnlock, /* xUnlock method */ + proxyCheckReservedLock, /* xCheckReservedLock method */ + 0 /* xShmMap method */ +) +#endif + +/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */ +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE +IOMETHODS( + nfsIoFinder, /* Finder function name */ + nfsIoMethods, /* sqlite3_io_methods object name */ + 1, /* shared memory is disabled */ + unixClose, /* xClose method */ + unixLock, /* xLock method */ + nfsUnlock, /* xUnlock method */ + unixCheckReservedLock, /* xCheckReservedLock method */ + 0 /* xShmMap method */ +) +#endif + +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE +/* +** This "finder" function attempts to determine the best locking strategy +** for the database file "filePath". It then returns the sqlite3_io_methods +** object that implements that strategy. +** +** This is for MacOSX only. +*/ +static const sqlite3_io_methods *autolockIoFinderImpl( + const char *filePath, /* name of the database file */ + unixFile *pNew /* open file object for the database file */ +){ + static const struct Mapping { + const char *zFilesystem; /* Filesystem type name */ + const sqlite3_io_methods *pMethods; /* Appropriate locking method */ + } aMap[] = { + { "hfs", &posixIoMethods }, + { "ufs", &posixIoMethods }, + { "afpfs", &afpIoMethods }, + { "smbfs", &afpIoMethods }, + { "webdav", &nolockIoMethods }, + { 0, 0 } + }; + int i; + struct statfs fsInfo; + struct flock lockInfo; + + if( !filePath ){ + /* If filePath==NULL that means we are dealing with a transient file + ** that does not need to be locked. */ + return &nolockIoMethods; + } + if( statfs(filePath, &fsInfo) != -1 ){ + if( fsInfo.f_flags & MNT_RDONLY ){ + return &nolockIoMethods; + } + for(i=0; aMap[i].zFilesystem; i++){ + if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){ + return aMap[i].pMethods; + } + } + } + + /* Default case. Handles, amongst others, "nfs". + ** Test byte-range lock using fcntl(). If the call succeeds, + ** assume that the file-system supports POSIX style locks. + */ + lockInfo.l_len = 1; + lockInfo.l_start = 0; + lockInfo.l_whence = SEEK_SET; + lockInfo.l_type = F_RDLCK; + if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) { + if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){ + return &nfsIoMethods; + } else { + return &posixIoMethods; + } + }else{ + return &dotlockIoMethods; + } +} +static const sqlite3_io_methods + *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl; + +#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ + +#if OS_VXWORKS +/* +** This "finder" function for VxWorks checks to see if posix advisory +** locking works. If it does, then that is what is used. If it does not +** work, then fallback to named semaphore locking. +*/ +static const sqlite3_io_methods *vxworksIoFinderImpl( + const char *filePath, /* name of the database file */ + unixFile *pNew /* the open file object */ +){ + struct flock lockInfo; + + if( !filePath ){ + /* If filePath==NULL that means we are dealing with a transient file + ** that does not need to be locked. */ + return &nolockIoMethods; + } + + /* Test if fcntl() is supported and use POSIX style locks. + ** Otherwise fall back to the named semaphore method. + */ + lockInfo.l_len = 1; + lockInfo.l_start = 0; + lockInfo.l_whence = SEEK_SET; + lockInfo.l_type = F_RDLCK; + if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) { + return &posixIoMethods; + }else{ + return &semIoMethods; + } +} +static const sqlite3_io_methods + *(*const vxworksIoFinder)(const char*,unixFile*) = vxworksIoFinderImpl; + +#endif /* OS_VXWORKS */ + +/* +** An abstract type for a pointer to an IO method finder function: +*/ +typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*); + + +/**************************************************************************** +**************************** sqlite3_vfs methods **************************** +** +** This division contains the implementation of methods on the +** sqlite3_vfs object. +*/ + +/* +** Initialize the contents of the unixFile structure pointed to by pId. +*/ +static int fillInUnixFile( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + int h, /* Open file descriptor of file being opened */ + sqlite3_file *pId, /* Write to the unixFile structure here */ + const char *zFilename, /* Name of the file being opened */ + int ctrlFlags /* Zero or more UNIXFILE_* values */ +){ + const sqlite3_io_methods *pLockingStyle; + unixFile *pNew = (unixFile *)pId; + int rc = SQLITE_OK; + + assert( pNew->pInode==NULL ); + + /* Usually the path zFilename should not be a relative pathname. The + ** exception is when opening the proxy "conch" file in builds that + ** include the special Apple locking styles. + */ +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE + assert( zFilename==0 || zFilename[0]=='/' + || pVfs->pAppData==(void*)&autolockIoFinder ); +#else + assert( zFilename==0 || zFilename[0]=='/' ); +#endif + + /* No locking occurs in temporary files */ + assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 ); + + OSTRACE(("OPEN %-3d %s\n", h, zFilename)); + pNew->h = h; + pNew->pVfs = pVfs; + pNew->zPath = zFilename; + pNew->ctrlFlags = (u8)ctrlFlags; +#if SQLITE_MAX_MMAP_SIZE>0 + pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap; +#endif + if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0), + "psow", SQLITE_POWERSAFE_OVERWRITE) ){ + pNew->ctrlFlags |= UNIXFILE_PSOW; + } + if( strcmp(pVfs->zName,"unix-excl")==0 ){ + pNew->ctrlFlags |= UNIXFILE_EXCL; + } + +#if OS_VXWORKS + pNew->pId = vxworksFindFileId(zFilename); + if( pNew->pId==0 ){ + ctrlFlags |= UNIXFILE_NOLOCK; + rc = SQLITE_NOMEM; + } +#endif + + if( ctrlFlags & UNIXFILE_NOLOCK ){ + pLockingStyle = &nolockIoMethods; + }else{ + pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew); +#if SQLITE_ENABLE_LOCKING_STYLE + /* Cache zFilename in the locking context (AFP and dotlock override) for + ** proxyLock activation is possible (remote proxy is based on db name) + ** zFilename remains valid until file is closed, to support */ + pNew->lockingContext = (void*)zFilename; +#endif + } + + if( pLockingStyle == &posixIoMethods +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE + || pLockingStyle == &nfsIoMethods +#endif + ){ + unixEnterMutex(); + rc = findInodeInfo(pNew, &pNew->pInode); + if( rc!=SQLITE_OK ){ + /* If an error occurred in findInodeInfo(), close the file descriptor + ** immediately, before releasing the mutex. findInodeInfo() may fail + ** in two scenarios: + ** + ** (a) A call to fstat() failed. + ** (b) A malloc failed. + ** + ** Scenario (b) may only occur if the process is holding no other + ** file descriptors open on the same file. If there were other file + ** descriptors on this file, then no malloc would be required by + ** findInodeInfo(). If this is the case, it is quite safe to close + ** handle h - as it is guaranteed that no posix locks will be released + ** by doing so. + ** + ** If scenario (a) caused the error then things are not so safe. The + ** implicit assumption here is that if fstat() fails, things are in + ** such bad shape that dropping a lock or two doesn't matter much. + */ + robust_close(pNew, h, __LINE__); + h = -1; + } + unixLeaveMutex(); + } + +#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) + else if( pLockingStyle == &afpIoMethods ){ + /* AFP locking uses the file path so it needs to be included in + ** the afpLockingContext. + */ + afpLockingContext *pCtx; + pNew->lockingContext = pCtx = sqlite3_malloc64( sizeof(*pCtx) ); + if( pCtx==0 ){ + rc = SQLITE_NOMEM; + }else{ + /* NB: zFilename exists and remains valid until the file is closed + ** according to requirement F11141. So we do not need to make a + ** copy of the filename. */ + pCtx->dbPath = zFilename; + pCtx->reserved = 0; + srandomdev(); + unixEnterMutex(); + rc = findInodeInfo(pNew, &pNew->pInode); + if( rc!=SQLITE_OK ){ + sqlite3_free(pNew->lockingContext); + robust_close(pNew, h, __LINE__); + h = -1; + } + unixLeaveMutex(); + } + } +#endif + + else if( pLockingStyle == &dotlockIoMethods ){ + /* Dotfile locking uses the file path so it needs to be included in + ** the dotlockLockingContext + */ + char *zLockFile; + int nFilename; + assert( zFilename!=0 ); + nFilename = (int)strlen(zFilename) + 6; + zLockFile = (char *)sqlite3_malloc64(nFilename); + if( zLockFile==0 ){ + rc = SQLITE_NOMEM; + }else{ + sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename); + } + pNew->lockingContext = zLockFile; + } + +#if OS_VXWORKS + else if( pLockingStyle == &semIoMethods ){ + /* Named semaphore locking uses the file path so it needs to be + ** included in the semLockingContext + */ + unixEnterMutex(); + rc = findInodeInfo(pNew, &pNew->pInode); + if( (rc==SQLITE_OK) && (pNew->pInode->pSem==NULL) ){ + char *zSemName = pNew->pInode->aSemName; + int n; + sqlite3_snprintf(MAX_PATHNAME, zSemName, "/%s.sem", + pNew->pId->zCanonicalName); + for( n=1; zSemName[n]; n++ ) + if( zSemName[n]=='/' ) zSemName[n] = '_'; + pNew->pInode->pSem = sem_open(zSemName, O_CREAT, 0666, 1); + if( pNew->pInode->pSem == SEM_FAILED ){ + rc = SQLITE_NOMEM; + pNew->pInode->aSemName[0] = '\0'; + } + } + unixLeaveMutex(); + } +#endif + + storeLastErrno(pNew, 0); +#if OS_VXWORKS + if( rc!=SQLITE_OK ){ + if( h>=0 ) robust_close(pNew, h, __LINE__); + h = -1; + osUnlink(zFilename); + pNew->ctrlFlags |= UNIXFILE_DELETE; + } +#endif + if( rc!=SQLITE_OK ){ + if( h>=0 ) robust_close(pNew, h, __LINE__); + }else{ + pNew->pMethod = pLockingStyle; + OpenCounter(+1); + verifyDbFile(pNew); + } + return rc; +} + +/* +** Return the name of a directory in which to put temporary files. +** If no suitable temporary file directory can be found, return NULL. +*/ +static const char *unixTempFileDir(void){ + static const char *azDirs[] = { + 0, + 0, + 0, + "/var/tmp", + "/usr/tmp", + "/tmp", + 0 /* List terminator */ + }; + unsigned int i; + struct stat buf; + const char *zDir = 0; + + azDirs[0] = sqlite3_temp_directory; + if( !azDirs[1] ) azDirs[1] = getenv("SQLITE_TMPDIR"); + if( !azDirs[2] ) azDirs[2] = getenv("TMPDIR"); + for(i=0; imxPathname bytes. +*/ +static int unixGetTempname(int nBuf, char *zBuf){ + static const unsigned char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + unsigned int i, j; + const char *zDir; + + /* It's odd to simulate an io-error here, but really this is just + ** using the io-error infrastructure to test that SQLite handles this + ** function failing. + */ + SimulateIOError( return SQLITE_IOERR ); + + zDir = unixTempFileDir(); + if( zDir==0 ) zDir = "."; + + /* Check that the output buffer is large enough for the temporary file + ** name. If it is not, return SQLITE_ERROR. + */ + if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf ){ + return SQLITE_ERROR; + } + + do{ + sqlite3_snprintf(nBuf-18, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir); + j = (int)strlen(zBuf); + sqlite3_randomness(15, &zBuf[j]); + for(i=0; i<15; i++, j++){ + zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; + } + zBuf[j] = 0; + zBuf[j+1] = 0; + }while( osAccess(zBuf,0)==0 ); + return SQLITE_OK; +} + +#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) +/* +** Routine to transform a unixFile into a proxy-locking unixFile. +** Implementation in the proxy-lock division, but used by unixOpen() +** if SQLITE_PREFER_PROXY_LOCKING is defined. +*/ +static int proxyTransformUnixFile(unixFile*, const char*); +#endif + +/* +** Search for an unused file descriptor that was opened on the database +** file (not a journal or master-journal file) identified by pathname +** zPath with SQLITE_OPEN_XXX flags matching those passed as the second +** argument to this function. +** +** Such a file descriptor may exist if a database connection was closed +** but the associated file descriptor could not be closed because some +** other file descriptor open on the same file is holding a file-lock. +** Refer to comments in the unixClose() function and the lengthy comment +** describing "Posix Advisory Locking" at the start of this file for +** further details. Also, ticket #4018. +** +** If a suitable file descriptor is found, then it is returned. If no +** such file descriptor is located, -1 is returned. +*/ +static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ + UnixUnusedFd *pUnused = 0; + + /* Do not search for an unused file descriptor on vxworks. Not because + ** vxworks would not benefit from the change (it might, we're not sure), + ** but because no way to test it is currently available. It is better + ** not to risk breaking vxworks support for the sake of such an obscure + ** feature. */ +#if !OS_VXWORKS + struct stat sStat; /* Results of stat() call */ + + /* A stat() call may fail for various reasons. If this happens, it is + ** almost certain that an open() call on the same path will also fail. + ** For this reason, if an error occurs in the stat() call here, it is + ** ignored and -1 is returned. The caller will try to open a new file + ** descriptor on the same path, fail, and return an error to SQLite. + ** + ** Even if a subsequent open() call does succeed, the consequences of + ** not searching for a reusable file descriptor are not dire. */ + if( 0==osStat(zPath, &sStat) ){ + unixInodeInfo *pInode; + + unixEnterMutex(); + pInode = inodeList; + while( pInode && (pInode->fileId.dev!=sStat.st_dev + || pInode->fileId.ino!=sStat.st_ino) ){ + pInode = pInode->pNext; + } + if( pInode ){ + UnixUnusedFd **pp; + for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); + pUnused = *pp; + if( pUnused ){ + *pp = pUnused->pNext; + } + } + unixLeaveMutex(); + } +#endif /* if !OS_VXWORKS */ + return pUnused; +} + +/* +** This function is called by unixOpen() to determine the unix permissions +** to create new files with. If no error occurs, then SQLITE_OK is returned +** and a value suitable for passing as the third argument to open(2) is +** written to *pMode. If an IO error occurs, an SQLite error code is +** returned and the value of *pMode is not modified. +** +** In most cases, this routine sets *pMode to 0, which will become +** an indication to robust_open() to create the file using +** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask. +** But if the file being opened is a WAL or regular journal file, then +** this function queries the file-system for the permissions on the +** corresponding database file and sets *pMode to this value. Whenever +** possible, WAL and journal files are created using the same permissions +** as the associated database file. +** +** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the +** original filename is unavailable. But 8_3_NAMES is only used for +** FAT filesystems and permissions do not matter there, so just use +** the default permissions. +*/ +static int findCreateFileMode( + const char *zPath, /* Path of file (possibly) being created */ + int flags, /* Flags passed as 4th argument to xOpen() */ + mode_t *pMode, /* OUT: Permissions to open file with */ + uid_t *pUid, /* OUT: uid to set on the file */ + gid_t *pGid /* OUT: gid to set on the file */ +){ + int rc = SQLITE_OK; /* Return Code */ + *pMode = 0; + *pUid = 0; + *pGid = 0; + if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ + char zDb[MAX_PATHNAME+1]; /* Database file path */ + int nDb; /* Number of valid bytes in zDb */ + struct stat sStat; /* Output of stat() on database file */ + + /* zPath is a path to a WAL or journal file. The following block derives + ** the path to the associated database file from zPath. This block handles + ** the following naming conventions: + ** + ** "-journal" + ** "-wal" + ** "-journalNN" + ** "-walNN" + ** + ** where NN is a decimal number. The NN naming schemes are + ** used by the test_multiplex.c module. + */ + nDb = sqlite3Strlen30(zPath) - 1; +#ifdef SQLITE_ENABLE_8_3_NAMES + while( nDb>0 && sqlite3Isalnum(zPath[nDb]) ) nDb--; + if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK; +#else + while( zPath[nDb]!='-' ){ + assert( nDb>0 ); + assert( zPath[nDb]!='\n' ); + nDb--; + } +#endif + memcpy(zDb, zPath, nDb); + zDb[nDb] = '\0'; + + if( 0==osStat(zDb, &sStat) ){ + *pMode = sStat.st_mode & 0777; + *pUid = sStat.st_uid; + *pGid = sStat.st_gid; + }else{ + rc = SQLITE_IOERR_FSTAT; + } + }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){ + *pMode = 0600; + } + return rc; +} + +/* +** Open the file zPath. +** +** Previously, the SQLite OS layer used three functions in place of this +** one: +** +** sqlite3OsOpenReadWrite(); +** sqlite3OsOpenReadOnly(); +** sqlite3OsOpenExclusive(); +** +** These calls correspond to the following combinations of flags: +** +** ReadWrite() -> (READWRITE | CREATE) +** ReadOnly() -> (READONLY) +** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE) +** +** The old OpenExclusive() accepted a boolean argument - "delFlag". If +** true, the file was configured to be automatically deleted when the +** file handle closed. To achieve the same effect using this new +** interface, add the DELETEONCLOSE flag to those specified above for +** OpenExclusive(). +*/ +static int unixOpen( + sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */ + const char *zPath, /* Pathname of file to be opened */ + sqlite3_file *pFile, /* The file descriptor to be filled in */ + int flags, /* Input flags to control the opening */ + int *pOutFlags /* Output flags returned to SQLite core */ +){ + unixFile *p = (unixFile *)pFile; + int fd = -1; /* File descriptor returned by open() */ + int openFlags = 0; /* Flags to pass to open() */ + int eType = flags&0xFFFFFF00; /* Type of file to open */ + int noLock; /* True to omit locking primitives */ + int rc = SQLITE_OK; /* Function Return Code */ + int ctrlFlags = 0; /* UNIXFILE_* flags */ + + int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); + int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); + int isCreate = (flags & SQLITE_OPEN_CREATE); + int isReadonly = (flags & SQLITE_OPEN_READONLY); + int isReadWrite = (flags & SQLITE_OPEN_READWRITE); +#if SQLITE_ENABLE_LOCKING_STYLE + int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY); +#endif +#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE + struct statfs fsInfo; +#endif + + /* If creating a master or main-file journal, this function will open + ** a file-descriptor on the directory too. The first time unixSync() + ** is called the directory file descriptor will be fsync()ed and close()d. + */ + int syncDir = (isCreate && ( + eType==SQLITE_OPEN_MASTER_JOURNAL + || eType==SQLITE_OPEN_MAIN_JOURNAL + || eType==SQLITE_OPEN_WAL + )); + + /* If argument zPath is a NULL pointer, this function is required to open + ** a temporary file. Use this buffer to store the file name in. + */ + char zTmpname[MAX_PATHNAME+2]; + const char *zName = zPath; + + /* Check the following statements are true: + ** + ** (a) Exactly one of the READWRITE and READONLY flags must be set, and + ** (b) if CREATE is set, then READWRITE must also be set, and + ** (c) if EXCLUSIVE is set, then CREATE must also be set. + ** (d) if DELETEONCLOSE is set, then CREATE must also be set. + */ + assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); + assert(isCreate==0 || isReadWrite); + assert(isExclusive==0 || isCreate); + assert(isDelete==0 || isCreate); + + /* The main DB, main journal, WAL file and master journal are never + ** automatically deleted. Nor are they ever temporary files. */ + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB ); + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL ); + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL ); + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); + + /* Assert that the upper layer has set one of the "file-type" flags. */ + assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB + || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL + || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL + || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL + ); + + /* Detect a pid change and reset the PRNG. There is a race condition + ** here such that two or more threads all trying to open databases at + ** the same instant might all reset the PRNG. But multiple resets + ** are harmless. + */ + if( randomnessPid!=osGetpid(0) ){ + randomnessPid = osGetpid(0); + sqlite3_randomness(0,0); + } + + memset(p, 0, sizeof(unixFile)); + + if( eType==SQLITE_OPEN_MAIN_DB ){ + UnixUnusedFd *pUnused; + pUnused = findReusableFd(zName, flags); + if( pUnused ){ + fd = pUnused->fd; + }else{ + pUnused = sqlite3_malloc64(sizeof(*pUnused)); + if( !pUnused ){ + return SQLITE_NOMEM; + } + } + p->pUnused = pUnused; + + /* Database filenames are double-zero terminated if they are not + ** URIs with parameters. Hence, they can always be passed into + ** sqlite3_uri_parameter(). */ + assert( (flags & SQLITE_OPEN_URI) || zName[strlen(zName)+1]==0 ); + + }else if( !zName ){ + /* If zName is NULL, the upper layer is requesting a temp file. */ + assert(isDelete && !syncDir); + rc = unixGetTempname(MAX_PATHNAME+2, zTmpname); + if( rc!=SQLITE_OK ){ + return rc; + } + zName = zTmpname; + + /* Generated temporary filenames are always double-zero terminated + ** for use by sqlite3_uri_parameter(). */ + assert( zName[strlen(zName)+1]==0 ); + } + + /* Determine the value of the flags parameter passed to POSIX function + ** open(). These must be calculated even if open() is not called, as + ** they may be stored as part of the file handle and used by the + ** 'conch file' locking functions later on. */ + if( isReadonly ) openFlags |= O_RDONLY; + if( isReadWrite ) openFlags |= O_RDWR; + if( isCreate ) openFlags |= O_CREAT; + if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW); + openFlags |= (O_LARGEFILE|O_BINARY); + + if( fd<0 ){ + mode_t openMode; /* Permissions to create file with */ + uid_t uid; /* Userid for the file */ + gid_t gid; /* Groupid for the file */ + rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid); + if( rc!=SQLITE_OK ){ + assert( !p->pUnused ); + assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL ); + return rc; + } + fd = robust_open(zName, openFlags, openMode); + OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags)); + if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){ + /* Failed to open the file for read/write access. Try read-only. */ + flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); + openFlags &= ~(O_RDWR|O_CREAT); + flags |= SQLITE_OPEN_READONLY; + openFlags |= O_RDONLY; + isReadonly = 1; + fd = robust_open(zName, openFlags, openMode); + } + if( fd<0 ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); + goto open_finished; + } + + /* If this process is running as root and if creating a new rollback + ** journal or WAL file, set the ownership of the journal or WAL to be + ** the same as the original database. + */ + if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ + osFchown(fd, uid, gid); + } + } + assert( fd>=0 ); + if( pOutFlags ){ + *pOutFlags = flags; + } + + if( p->pUnused ){ + p->pUnused->fd = fd; + p->pUnused->flags = flags; + } + + if( isDelete ){ +#if OS_VXWORKS + zPath = zName; +#elif defined(SQLITE_UNLINK_AFTER_CLOSE) + zPath = sqlite3_mprintf("%s", zName); + if( zPath==0 ){ + robust_close(p, fd, __LINE__); + return SQLITE_NOMEM; + } +#else + osUnlink(zName); +#endif + } +#if SQLITE_ENABLE_LOCKING_STYLE + else{ + p->openFlags = openFlags; + } +#endif + + noLock = eType!=SQLITE_OPEN_MAIN_DB; + + +#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE + if( fstatfs(fd, &fsInfo) == -1 ){ + storeLastErrno(p, errno); + robust_close(p, fd, __LINE__); + return SQLITE_IOERR_ACCESS; + } + if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { + ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; + } + if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) { + ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; + } +#endif + + /* Set up appropriate ctrlFlags */ + if( isDelete ) ctrlFlags |= UNIXFILE_DELETE; + if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY; + if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK; + if( syncDir ) ctrlFlags |= UNIXFILE_DIRSYNC; + if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI; + +#if SQLITE_ENABLE_LOCKING_STYLE +#if SQLITE_PREFER_PROXY_LOCKING + isAutoProxy = 1; +#endif + if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){ + char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING"); + int useProxy = 0; + + /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means + ** never use proxy, NULL means use proxy for non-local files only. */ + if( envforce!=NULL ){ + useProxy = atoi(envforce)>0; + }else{ + useProxy = !(fsInfo.f_flags&MNT_LOCAL); + } + if( useProxy ){ + rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); + if( rc==SQLITE_OK ){ + rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); + if( rc!=SQLITE_OK ){ + /* Use unixClose to clean up the resources added in fillInUnixFile + ** and clear all the structure's references. Specifically, + ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op + */ + unixClose(pFile); + return rc; + } + } + goto open_finished; + } + } +#endif + + rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); + +open_finished: + if( rc!=SQLITE_OK ){ + sqlite3_free(p->pUnused); + } + return rc; +} + + +/* +** Delete the file at zPath. If the dirSync argument is true, fsync() +** the directory after deleting the file. +*/ +static int unixDelete( + sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */ + const char *zPath, /* Name of file to be deleted */ + int dirSync /* If true, fsync() directory after deleting file */ +){ + int rc = SQLITE_OK; + UNUSED_PARAMETER(NotUsed); + SimulateIOError(return SQLITE_IOERR_DELETE); + if( osUnlink(zPath)==(-1) ){ + if( errno==ENOENT +#if OS_VXWORKS + || osAccess(zPath,0)!=0 +#endif + ){ + rc = SQLITE_IOERR_DELETE_NOENT; + }else{ + rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath); + } + return rc; + } +#ifndef SQLITE_DISABLE_DIRSYNC + if( (dirSync & 1)!=0 ){ + int fd; + rc = osOpenDirectory(zPath, &fd); + if( rc==SQLITE_OK ){ +#if OS_VXWORKS + if( fsync(fd)==-1 ) +#else + if( fsync(fd) ) +#endif + { + rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); + } + robust_close(0, fd, __LINE__); + }else if( rc==SQLITE_CANTOPEN ){ + rc = SQLITE_OK; + } + } +#endif + return rc; +} + +/* +** Test the existence of or access permissions of file zPath. The +** test performed depends on the value of flags: +** +** SQLITE_ACCESS_EXISTS: Return 1 if the file exists +** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable. +** SQLITE_ACCESS_READONLY: Return 1 if the file is readable. +** +** Otherwise return 0. +*/ +static int unixAccess( + sqlite3_vfs *NotUsed, /* The VFS containing this xAccess method */ + const char *zPath, /* Path of the file to examine */ + int flags, /* What do we want to learn about the zPath file? */ + int *pResOut /* Write result boolean here */ +){ + int amode = 0; + UNUSED_PARAMETER(NotUsed); + SimulateIOError( return SQLITE_IOERR_ACCESS; ); + switch( flags ){ + case SQLITE_ACCESS_EXISTS: + amode = F_OK; + break; + case SQLITE_ACCESS_READWRITE: + amode = W_OK|R_OK; + break; + case SQLITE_ACCESS_READ: + amode = R_OK; + break; + + default: + assert(!"Invalid flags argument"); + } + *pResOut = (osAccess(zPath, amode)==0); + if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){ + struct stat buf; + if( 0==osStat(zPath, &buf) && buf.st_size==0 ){ + *pResOut = 0; + } + } + return SQLITE_OK; +} + + +/* +** Turn a relative pathname into a full pathname. The relative path +** is stored as a nul-terminated string in the buffer pointed to by +** zPath. +** +** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes +** (in this case, MAX_PATHNAME bytes). The full-path is written to +** this buffer before returning. +*/ +static int unixFullPathname( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + const char *zPath, /* Possibly relative input path */ + int nOut, /* Size of output buffer in bytes */ + char *zOut /* Output buffer */ +){ + + /* It's odd to simulate an io-error here, but really this is just + ** using the io-error infrastructure to test that SQLite handles this + ** function failing. This function could fail if, for example, the + ** current working directory has been unlinked. + */ + SimulateIOError( return SQLITE_ERROR ); + + assert( pVfs->mxPathname==MAX_PATHNAME ); + UNUSED_PARAMETER(pVfs); + + zOut[nOut-1] = '\0'; + if( zPath[0]=='/' ){ + sqlite3_snprintf(nOut, zOut, "%s", zPath); + }else{ + int nCwd; + if( osGetcwd(zOut, nOut-1)==0 ){ + return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath); + } + nCwd = (int)strlen(zOut); + sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath); + } + return SQLITE_OK; +} + + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +#include +static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){ + UNUSED_PARAMETER(NotUsed); + return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL); +} + +/* +** SQLite calls this function immediately after a call to unixDlSym() or +** unixDlOpen() fails (returns a null pointer). If a more detailed error +** message is available, it is written to zBufOut. If no error message +** is available, zBufOut is left unmodified and SQLite uses a default +** error message. +*/ +static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){ + const char *zErr; + UNUSED_PARAMETER(NotUsed); + unixEnterMutex(); + zErr = dlerror(); + if( zErr ){ + sqlite3_snprintf(nBuf, zBufOut, "%s", zErr); + } + unixLeaveMutex(); +} +static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){ + /* + ** GCC with -pedantic-errors says that C90 does not allow a void* to be + ** cast into a pointer to a function. And yet the library dlsym() routine + ** returns a void* which is really a pointer to a function. So how do we + ** use dlsym() with -pedantic-errors? + ** + ** Variable x below is defined to be a pointer to a function taking + ** parameters void* and const char* and returning a pointer to a function. + ** We initialize x by assigning it a pointer to the dlsym() function. + ** (That assignment requires a cast.) Then we call the function that + ** x points to. + ** + ** This work-around is unlikely to work correctly on any system where + ** you really cannot cast a function pointer into void*. But then, on the + ** other hand, dlsym() will not work on such a system either, so we have + ** not really lost anything. + */ + void (*(*x)(void*,const char*))(void); + UNUSED_PARAMETER(NotUsed); + x = (void(*(*)(void*,const char*))(void))dlsym; + return (*x)(p, zSym); +} +static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){ + UNUSED_PARAMETER(NotUsed); + dlclose(pHandle); +} +#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ + #define unixDlOpen 0 + #define unixDlError 0 + #define unixDlSym 0 + #define unixDlClose 0 +#endif + +/* +** Write nBuf bytes of random data to the supplied buffer zBuf. +*/ +static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ + UNUSED_PARAMETER(NotUsed); + assert((size_t)nBuf>=(sizeof(time_t)+sizeof(int))); + + /* We have to initialize zBuf to prevent valgrind from reporting + ** errors. The reports issued by valgrind are incorrect - we would + ** prefer that the randomness be increased by making use of the + ** uninitialized space in zBuf - but valgrind errors tend to worry + ** some users. Rather than argue, it seems easier just to initialize + ** the whole array and silence valgrind, even if that means less randomness + ** in the random seed. + ** + ** When testing, initializing zBuf[] to zero is all we do. That means + ** that we always use the same random number sequence. This makes the + ** tests repeatable. + */ + memset(zBuf, 0, nBuf); + randomnessPid = osGetpid(0); +#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS) + { + int fd, got; + fd = robust_open("/dev/urandom", O_RDONLY, 0); + if( fd<0 ){ + time_t t; + time(&t); + memcpy(zBuf, &t, sizeof(t)); + memcpy(&zBuf[sizeof(t)], &randomnessPid, sizeof(randomnessPid)); + assert( sizeof(t)+sizeof(randomnessPid)<=(size_t)nBuf ); + nBuf = sizeof(t) + sizeof(randomnessPid); + }else{ + do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR ); + robust_close(0, fd, __LINE__); + } + } +#endif + return nBuf; +} + + +/* +** Sleep for a little while. Return the amount of time slept. +** The argument is the number of microseconds we want to sleep. +** The return value is the number of microseconds of sleep actually +** requested from the underlying operating system, a number which +** might be greater than or equal to the argument, but not less +** than the argument. +*/ +static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){ +#if OS_VXWORKS + struct timespec sp; + + sp.tv_sec = microseconds / 1000000; + sp.tv_nsec = (microseconds % 1000000) * 1000; + nanosleep(&sp, NULL); + UNUSED_PARAMETER(NotUsed); + return microseconds; +#elif defined(HAVE_USLEEP) && HAVE_USLEEP + usleep(microseconds); + UNUSED_PARAMETER(NotUsed); + return microseconds; +#else + int seconds = (microseconds+999999)/1000000; + sleep(seconds); + UNUSED_PARAMETER(NotUsed); + return seconds*1000000; +#endif +} + +/* +** The following variable, if set to a non-zero value, is interpreted as +** the number of seconds since 1970 and is used to set the result of +** sqlite3OsCurrentTime() during testing. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */ +#endif + +/* +** Find the current time (in Universal Coordinated Time). Write into *piNow +** the current time and date as a Julian Day number times 86_400_000. In +** other words, write into *piNow the number of milliseconds since the Julian +** epoch of noon in Greenwich on November 24, 4714 B.C according to the +** proleptic Gregorian calendar. +** +** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date +** cannot be found. +*/ +static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){ + static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; + int rc = SQLITE_OK; +#if defined(NO_GETTOD) + time_t t; + time(&t); + *piNow = ((sqlite3_int64)t)*1000 + unixEpoch; +#elif OS_VXWORKS + struct timespec sNow; + clock_gettime(CLOCK_REALTIME, &sNow); + *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000; +#else + struct timeval sNow; + if( gettimeofday(&sNow, 0)==0 ){ + *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000; + }else{ + rc = SQLITE_ERROR; + } +#endif + +#ifdef SQLITE_TEST + if( sqlite3_current_time ){ + *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch; + } +#endif + UNUSED_PARAMETER(NotUsed); + return rc; +} + +/* +** Find the current time (in Universal Coordinated Time). Write the +** current time and date as a Julian Day number into *prNow and +** return 0. Return 1 if the time and date cannot be found. +*/ +static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){ + sqlite3_int64 i = 0; + int rc; + UNUSED_PARAMETER(NotUsed); + rc = unixCurrentTimeInt64(0, &i); + *prNow = i/86400000.0; + return rc; +} + +/* +** We added the xGetLastError() method with the intention of providing +** better low-level error messages when operating-system problems come up +** during SQLite operation. But so far, none of that has been implemented +** in the core. So this routine is never called. For now, it is merely +** a place-holder. +*/ +static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ + UNUSED_PARAMETER(NotUsed); + UNUSED_PARAMETER(NotUsed2); + UNUSED_PARAMETER(NotUsed3); + return 0; +} + + +/* +************************ End of sqlite3_vfs methods *************************** +******************************************************************************/ + +/****************************************************************************** +************************** Begin Proxy Locking ******************************** +** +** Proxy locking is a "uber-locking-method" in this sense: It uses the +** other locking methods on secondary lock files. Proxy locking is a +** meta-layer over top of the primitive locking implemented above. For +** this reason, the division that implements of proxy locking is deferred +** until late in the file (here) after all of the other I/O methods have +** been defined - so that the primitive locking methods are available +** as services to help with the implementation of proxy locking. +** +**** +** +** The default locking schemes in SQLite use byte-range locks on the +** database file to coordinate safe, concurrent access by multiple readers +** and writers [http://sqlite.org/lockingv3.html]. The five file locking +** states (UNLOCKED, PENDING, SHARED, RESERVED, EXCLUSIVE) are implemented +** as POSIX read & write locks over fixed set of locations (via fsctl), +** on AFP and SMB only exclusive byte-range locks are available via fsctl +** with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states. +** To simulate a F_RDLCK on the shared range, on AFP a randomly selected +** address in the shared range is taken for a SHARED lock, the entire +** shared range is taken for an EXCLUSIVE lock): +** +** PENDING_BYTE 0x40000000 +** RESERVED_BYTE 0x40000001 +** SHARED_RANGE 0x40000002 -> 0x40000200 +** +** This works well on the local file system, but shows a nearly 100x +** slowdown in read performance on AFP because the AFP client disables +** the read cache when byte-range locks are present. Enabling the read +** cache exposes a cache coherency problem that is present on all OS X +** supported network file systems. NFS and AFP both observe the +** close-to-open semantics for ensuring cache coherency +** [http://nfs.sourceforge.net/#faq_a8], which does not effectively +** address the requirements for concurrent database access by multiple +** readers and writers +** [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html]. +** +** To address the performance and cache coherency issues, proxy file locking +** changes the way database access is controlled by limiting access to a +** single host at a time and moving file locks off of the database file +** and onto a proxy file on the local file system. +** +** +** Using proxy locks +** ----------------- +** +** C APIs +** +** sqlite3_file_control(db, dbname, SQLITE_FCNTL_SET_LOCKPROXYFILE, +** | ":auto:"); +** sqlite3_file_control(db, dbname, SQLITE_FCNTL_GET_LOCKPROXYFILE, +** &); +** +** +** SQL pragmas +** +** PRAGMA [database.]lock_proxy_file= | :auto: +** PRAGMA [database.]lock_proxy_file +** +** Specifying ":auto:" means that if there is a conch file with a matching +** host ID in it, the proxy path in the conch file will be used, otherwise +** a proxy path based on the user's temp dir +** (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the +** actual proxy file name is generated from the name and path of the +** database file. For example: +** +** For database path "/Users/me/foo.db" +** The lock path will be "/sqliteplocks/_Users_me_foo.db:auto:") +** +** Once a lock proxy is configured for a database connection, it can not +** be removed, however it may be switched to a different proxy path via +** the above APIs (assuming the conch file is not being held by another +** connection or process). +** +** +** How proxy locking works +** ----------------------- +** +** Proxy file locking relies primarily on two new supporting files: +** +** * conch file to limit access to the database file to a single host +** at a time +** +** * proxy file to act as a proxy for the advisory locks normally +** taken on the database +** +** The conch file - to use a proxy file, sqlite must first "hold the conch" +** by taking an sqlite-style shared lock on the conch file, reading the +** contents and comparing the host's unique host ID (see below) and lock +** proxy path against the values stored in the conch. The conch file is +** stored in the same directory as the database file and the file name +** is patterned after the database file name as ".-conch". +** If the conch file does not exist, or its contents do not match the +** host ID and/or proxy path, then the lock is escalated to an exclusive +** lock and the conch file contents is updated with the host ID and proxy +** path and the lock is downgraded to a shared lock again. If the conch +** is held by another process (with a shared lock), the exclusive lock +** will fail and SQLITE_BUSY is returned. +** +** The proxy file - a single-byte file used for all advisory file locks +** normally taken on the database file. This allows for safe sharing +** of the database file for multiple readers and writers on the same +** host (the conch ensures that they all use the same local lock file). +** +** Requesting the lock proxy does not immediately take the conch, it is +** only taken when the first request to lock database file is made. +** This matches the semantics of the traditional locking behavior, where +** opening a connection to a database file does not take a lock on it. +** The shared lock and an open file descriptor are maintained until +** the connection to the database is closed. +** +** The proxy file and the lock file are never deleted so they only need +** to be created the first time they are used. +** +** Configuration options +** --------------------- +** +** SQLITE_PREFER_PROXY_LOCKING +** +** Database files accessed on non-local file systems are +** automatically configured for proxy locking, lock files are +** named automatically using the same logic as +** PRAGMA lock_proxy_file=":auto:" +** +** SQLITE_PROXY_DEBUG +** +** Enables the logging of error messages during host id file +** retrieval and creation +** +** LOCKPROXYDIR +** +** Overrides the default directory used for lock proxy files that +** are named automatically via the ":auto:" setting +** +** SQLITE_DEFAULT_PROXYDIR_PERMISSIONS +** +** Permissions to use when creating a directory for storing the +** lock proxy files, only used when LOCKPROXYDIR is not set. +** +** +** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING, +** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will +** force proxy locking to be used for every database file opened, and 0 +** will force automatic proxy locking to be disabled for all database +** files (explicitly calling the SQLITE_FCNTL_SET_LOCKPROXYFILE pragma or +** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING). +*/ + +/* +** Proxy locking is only available on MacOSX +*/ +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE + +/* +** The proxyLockingContext has the path and file structures for the remote +** and local proxy files in it +*/ +typedef struct proxyLockingContext proxyLockingContext; +struct proxyLockingContext { + unixFile *conchFile; /* Open conch file */ + char *conchFilePath; /* Name of the conch file */ + unixFile *lockProxy; /* Open proxy lock file */ + char *lockProxyPath; /* Name of the proxy lock file */ + char *dbPath; /* Name of the open file */ + int conchHeld; /* 1 if the conch is held, -1 if lockless */ + int nFails; /* Number of conch taking failures */ + void *oldLockingContext; /* Original lockingcontext to restore on close */ + sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */ +}; + +/* +** The proxy lock file path for the database at dbPath is written into lPath, +** which must point to valid, writable memory large enough for a maxLen length +** file path. +*/ +static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ + int len; + int dbLen; + int i; + +#ifdef LOCKPROXYDIR + len = strlcpy(lPath, LOCKPROXYDIR, maxLen); +#else +# ifdef _CS_DARWIN_USER_TEMP_DIR + { + if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){ + OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n", + lPath, errno, osGetpid(0))); + return SQLITE_IOERR_LOCK; + } + len = strlcat(lPath, "sqliteplocks", maxLen); + } +# else + len = strlcpy(lPath, "/tmp/", maxLen); +# endif +#endif + + if( lPath[len-1]!='/' ){ + len = strlcat(lPath, "/", maxLen); + } + + /* transform the db path to a unique cache name */ + dbLen = (int)strlen(dbPath); + for( i=0; i 0) ){ + /* only mkdir if leaf dir != "." or "/" or ".." */ + if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/') + || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){ + buf[i]='\0'; + if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){ + int err=errno; + if( err!=EEXIST ) { + OSTRACE(("CREATELOCKPATH FAILED creating %s, " + "'%s' proxy lock path=%s pid=%d\n", + buf, strerror(err), lockPath, osGetpid(0))); + return err; + } + } + } + start=i+1; + } + buf[i] = lockPath[i]; + } + OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, osGetpid(0))); + return 0; +} + +/* +** Create a new VFS file descriptor (stored in memory obtained from +** sqlite3_malloc) and open the file named "path" in the file descriptor. +** +** The caller is responsible not only for closing the file descriptor +** but also for freeing the memory associated with the file descriptor. +*/ +static int proxyCreateUnixFile( + const char *path, /* path for the new unixFile */ + unixFile **ppFile, /* unixFile created and returned by ref */ + int islockfile /* if non zero missing dirs will be created */ +) { + int fd = -1; + unixFile *pNew; + int rc = SQLITE_OK; + int openFlags = O_RDWR | O_CREAT; + sqlite3_vfs dummyVfs; + int terrno = 0; + UnixUnusedFd *pUnused = NULL; + + /* 1. first try to open/create the file + ** 2. if that fails, and this is a lock file (not-conch), try creating + ** the parent directories and then try again. + ** 3. if that fails, try to open the file read-only + ** otherwise return BUSY (if lock file) or CANTOPEN for the conch file + */ + pUnused = findReusableFd(path, openFlags); + if( pUnused ){ + fd = pUnused->fd; + }else{ + pUnused = sqlite3_malloc64(sizeof(*pUnused)); + if( !pUnused ){ + return SQLITE_NOMEM; + } + } + if( fd<0 ){ + fd = robust_open(path, openFlags, 0); + terrno = errno; + if( fd<0 && errno==ENOENT && islockfile ){ + if( proxyCreateLockPath(path) == SQLITE_OK ){ + fd = robust_open(path, openFlags, 0); + } + } + } + if( fd<0 ){ + openFlags = O_RDONLY; + fd = robust_open(path, openFlags, 0); + terrno = errno; + } + if( fd<0 ){ + if( islockfile ){ + return SQLITE_BUSY; + } + switch (terrno) { + case EACCES: + return SQLITE_PERM; + case EIO: + return SQLITE_IOERR_LOCK; /* even though it is the conch */ + default: + return SQLITE_CANTOPEN_BKPT; + } + } + + pNew = (unixFile *)sqlite3_malloc64(sizeof(*pNew)); + if( pNew==NULL ){ + rc = SQLITE_NOMEM; + goto end_create_proxy; + } + memset(pNew, 0, sizeof(unixFile)); + pNew->openFlags = openFlags; + memset(&dummyVfs, 0, sizeof(dummyVfs)); + dummyVfs.pAppData = (void*)&autolockIoFinder; + dummyVfs.zName = "dummy"; + pUnused->fd = fd; + pUnused->flags = openFlags; + pNew->pUnused = pUnused; + + rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0); + if( rc==SQLITE_OK ){ + *ppFile = pNew; + return SQLITE_OK; + } +end_create_proxy: + robust_close(pNew, fd, __LINE__); + sqlite3_free(pNew); + sqlite3_free(pUnused); + return rc; +} + +#ifdef SQLITE_TEST +/* simulate multiple hosts by creating unique hostid file paths */ +SQLITE_API int sqlite3_hostid_num = 0; +#endif + +#define PROXY_HOSTIDLEN 16 /* conch file host id length */ + +#ifdef HAVE_GETHOSTUUID +/* Not always defined in the headers as it ought to be */ +extern int gethostuuid(uuid_t id, const struct timespec *wait); +#endif + +/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN +** bytes of writable memory. +*/ +static int proxyGetHostID(unsigned char *pHostID, int *pError){ + assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); + memset(pHostID, 0, PROXY_HOSTIDLEN); +#ifdef HAVE_GETHOSTUUID + { + struct timespec timeout = {1, 0}; /* 1 sec timeout */ + if( gethostuuid(pHostID, &timeout) ){ + int err = errno; + if( pError ){ + *pError = err; + } + return SQLITE_IOERR; + } + } +#else + UNUSED_PARAMETER(pError); +#endif +#ifdef SQLITE_TEST + /* simulate multiple hosts by creating unique hostid file paths */ + if( sqlite3_hostid_num != 0){ + pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF)); + } +#endif + + return SQLITE_OK; +} + +/* The conch file contains the header, host id and lock file path + */ +#define PROXY_CONCHVERSION 2 /* 1-byte header, 16-byte host id, path */ +#define PROXY_HEADERLEN 1 /* conch file header length */ +#define PROXY_PATHINDEX (PROXY_HEADERLEN+PROXY_HOSTIDLEN) +#define PROXY_MAXCONCHLEN (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN) + +/* +** Takes an open conch file, copies the contents to a new path and then moves +** it back. The newly created file's file descriptor is assigned to the +** conch file structure and finally the original conch file descriptor is +** closed. Returns zero if successful. +*/ +static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){ + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; + unixFile *conchFile = pCtx->conchFile; + char tPath[MAXPATHLEN]; + char buf[PROXY_MAXCONCHLEN]; + char *cPath = pCtx->conchFilePath; + size_t readLen = 0; + size_t pathLen = 0; + char errmsg[64] = ""; + int fd = -1; + int rc = -1; + UNUSED_PARAMETER(myHostID); + + /* create a new path by replace the trailing '-conch' with '-break' */ + pathLen = strlcpy(tPath, cPath, MAXPATHLEN); + if( pathLen>MAXPATHLEN || pathLen<6 || + (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){ + sqlite3_snprintf(sizeof(errmsg),errmsg,"path error (len %d)",(int)pathLen); + goto end_breaklock; + } + /* read the conch content */ + readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0); + if( readLenh, __LINE__); + conchFile->h = fd; + conchFile->openFlags = O_RDWR | O_CREAT; + +end_breaklock: + if( rc ){ + if( fd>=0 ){ + osUnlink(tPath); + robust_close(pFile, fd, __LINE__); + } + fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg); + } + return rc; +} + +/* Take the requested lock on the conch file and break a stale lock if the +** host id matches. +*/ +static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; + unixFile *conchFile = pCtx->conchFile; + int rc = SQLITE_OK; + int nTries = 0; + struct timespec conchModTime; + + memset(&conchModTime, 0, sizeof(conchModTime)); + do { + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); + nTries ++; + if( rc==SQLITE_BUSY ){ + /* If the lock failed (busy): + * 1st try: get the mod time of the conch, wait 0.5s and try again. + * 2nd try: fail if the mod time changed or host id is different, wait + * 10 sec and try again + * 3rd try: break the lock unless the mod time has changed. + */ + struct stat buf; + if( osFstat(conchFile->h, &buf) ){ + storeLastErrno(pFile, errno); + return SQLITE_IOERR_LOCK; + } + + if( nTries==1 ){ + conchModTime = buf.st_mtimespec; + usleep(500000); /* wait 0.5 sec and try the lock again*/ + continue; + } + + assert( nTries>1 ); + if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec || + conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){ + return SQLITE_BUSY; + } + + if( nTries==2 ){ + char tBuf[PROXY_MAXCONCHLEN]; + int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0); + if( len<0 ){ + storeLastErrno(pFile, errno); + return SQLITE_IOERR_LOCK; + } + if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){ + /* don't break the lock if the host id doesn't match */ + if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){ + return SQLITE_BUSY; + } + }else{ + /* don't break the lock on short read or a version mismatch */ + return SQLITE_BUSY; + } + usleep(10000000); /* wait 10 sec and try the lock again */ + continue; + } + + assert( nTries==3 ); + if( 0==proxyBreakConchLock(pFile, myHostID) ){ + rc = SQLITE_OK; + if( lockType==EXCLUSIVE_LOCK ){ + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); + } + if( !rc ){ + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); + } + } + } + } while( rc==SQLITE_BUSY && nTries<3 ); + + return rc; +} + +/* Takes the conch by taking a shared lock and read the contents conch, if +** lockPath is non-NULL, the host ID and lock file path must match. A NULL +** lockPath means that the lockPath in the conch file will be used if the +** host IDs match, or a new lock path will be generated automatically +** and written to the conch file. +*/ +static int proxyTakeConch(unixFile *pFile){ + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; + + if( pCtx->conchHeld!=0 ){ + return SQLITE_OK; + }else{ + unixFile *conchFile = pCtx->conchFile; + uuid_t myHostID; + int pError = 0; + char readBuf[PROXY_MAXCONCHLEN]; + char lockPath[MAXPATHLEN]; + char *tempLockPath = NULL; + int rc = SQLITE_OK; + int createConch = 0; + int hostIdMatch = 0; + int readLen = 0; + int tryOldLockPath = 0; + int forceNewLockPath = 0; + + OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h, + (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), + osGetpid(0))); + + rc = proxyGetHostID(myHostID, &pError); + if( (rc&0xff)==SQLITE_IOERR ){ + storeLastErrno(pFile, pError); + goto end_takeconch; + } + rc = proxyConchLock(pFile, myHostID, SHARED_LOCK); + if( rc!=SQLITE_OK ){ + goto end_takeconch; + } + /* read the existing conch file */ + readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN); + if( readLen<0 ){ + /* I/O error: lastErrno set by seekAndRead */ + storeLastErrno(pFile, conchFile->lastErrno); + rc = SQLITE_IOERR_READ; + goto end_takeconch; + }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || + readBuf[0]!=(char)PROXY_CONCHVERSION ){ + /* a short read or version format mismatch means we need to create a new + ** conch file. + */ + createConch = 1; + } + /* if the host id matches and the lock path already exists in the conch + ** we'll try to use the path there, if we can't open that path, we'll + ** retry with a new auto-generated path + */ + do { /* in case we need to try again for an :auto: named lock file */ + + if( !createConch && !forceNewLockPath ){ + hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID, + PROXY_HOSTIDLEN); + /* if the conch has data compare the contents */ + if( !pCtx->lockProxyPath ){ + /* for auto-named local lock file, just check the host ID and we'll + ** use the local lock file path that's already in there + */ + if( hostIdMatch ){ + size_t pathLen = (readLen - PROXY_PATHINDEX); + + if( pathLen>=MAXPATHLEN ){ + pathLen=MAXPATHLEN-1; + } + memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen); + lockPath[pathLen] = 0; + tempLockPath = lockPath; + tryOldLockPath = 1; + /* create a copy of the lock path if the conch is taken */ + goto end_takeconch; + } + }else if( hostIdMatch + && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX], + readLen-PROXY_PATHINDEX) + ){ + /* conch host and lock path match */ + goto end_takeconch; + } + } + + /* if the conch isn't writable and doesn't match, we can't take it */ + if( (conchFile->openFlags&O_RDWR) == 0 ){ + rc = SQLITE_BUSY; + goto end_takeconch; + } + + /* either the conch didn't match or we need to create a new one */ + if( !pCtx->lockProxyPath ){ + proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN); + tempLockPath = lockPath; + /* create a copy of the lock path _only_ if the conch is taken */ + } + + /* update conch with host and path (this will fail if other process + ** has a shared lock already), if the host id matches, use the big + ** stick. + */ + futimes(conchFile->h, NULL); + if( hostIdMatch && !createConch ){ + if( conchFile->pInode && conchFile->pInode->nShared>1 ){ + /* We are trying for an exclusive lock but another thread in this + ** same process is still holding a shared lock. */ + rc = SQLITE_BUSY; + } else { + rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); + } + }else{ + rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); + } + if( rc==SQLITE_OK ){ + char writeBuffer[PROXY_MAXCONCHLEN]; + int writeSize = 0; + + writeBuffer[0] = (char)PROXY_CONCHVERSION; + memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN); + if( pCtx->lockProxyPath!=NULL ){ + strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, + MAXPATHLEN); + }else{ + strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN); + } + writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]); + robust_ftruncate(conchFile->h, writeSize); + rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0); + fsync(conchFile->h); + /* If we created a new conch file (not just updated the contents of a + ** valid conch file), try to match the permissions of the database + */ + if( rc==SQLITE_OK && createConch ){ + struct stat buf; + int err = osFstat(pFile->h, &buf); + if( err==0 ){ + mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP | + S_IROTH|S_IWOTH); + /* try to match the database file R/W permissions, ignore failure */ +#ifndef SQLITE_PROXY_DEBUG + osFchmod(conchFile->h, cmode); +#else + do{ + rc = osFchmod(conchFile->h, cmode); + }while( rc==(-1) && errno==EINTR ); + if( rc!=0 ){ + int code = errno; + fprintf(stderr, "fchmod %o FAILED with %d %s\n", + cmode, code, strerror(code)); + } else { + fprintf(stderr, "fchmod %o SUCCEDED\n",cmode); + } + }else{ + int code = errno; + fprintf(stderr, "STAT FAILED[%d] with %d %s\n", + err, code, strerror(code)); +#endif + } + } + } + conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK); + + end_takeconch: + OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h)); + if( rc==SQLITE_OK && pFile->openFlags ){ + int fd; + if( pFile->h>=0 ){ + robust_close(pFile, pFile->h, __LINE__); + } + pFile->h = -1; + fd = robust_open(pCtx->dbPath, pFile->openFlags, 0); + OSTRACE(("TRANSPROXY: OPEN %d\n", fd)); + if( fd>=0 ){ + pFile->h = fd; + }else{ + rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called + during locking */ + } + } + if( rc==SQLITE_OK && !pCtx->lockProxy ){ + char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath; + rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1); + if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){ + /* we couldn't create the proxy lock file with the old lock file path + ** so try again via auto-naming + */ + forceNewLockPath = 1; + tryOldLockPath = 0; + continue; /* go back to the do {} while start point, try again */ + } + } + if( rc==SQLITE_OK ){ + /* Need to make a copy of path if we extracted the value + ** from the conch file or the path was allocated on the stack + */ + if( tempLockPath ){ + pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath); + if( !pCtx->lockProxyPath ){ + rc = SQLITE_NOMEM; + } + } + } + if( rc==SQLITE_OK ){ + pCtx->conchHeld = 1; + + if( pCtx->lockProxy->pMethod == &afpIoMethods ){ + afpLockingContext *afpCtx; + afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext; + afpCtx->dbPath = pCtx->lockProxyPath; + } + } else { + conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); + } + OSTRACE(("TAKECONCH %d %s\n", conchFile->h, + rc==SQLITE_OK?"ok":"failed")); + return rc; + } while (1); /* in case we need to retry the :auto: lock file - + ** we should never get here except via the 'continue' call. */ + } +} + +/* +** If pFile holds a lock on a conch file, then release that lock. +*/ +static int proxyReleaseConch(unixFile *pFile){ + int rc = SQLITE_OK; /* Subroutine return code */ + proxyLockingContext *pCtx; /* The locking context for the proxy lock */ + unixFile *conchFile; /* Name of the conch file */ + + pCtx = (proxyLockingContext *)pFile->lockingContext; + conchFile = pCtx->conchFile; + OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h, + (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), + osGetpid(0))); + if( pCtx->conchHeld>0 ){ + rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); + } + pCtx->conchHeld = 0; + OSTRACE(("RELEASECONCH %d %s\n", conchFile->h, + (rc==SQLITE_OK ? "ok" : "failed"))); + return rc; +} + +/* +** Given the name of a database file, compute the name of its conch file. +** Store the conch filename in memory obtained from sqlite3_malloc64(). +** Make *pConchPath point to the new name. Return SQLITE_OK on success +** or SQLITE_NOMEM if unable to obtain memory. +** +** The caller is responsible for ensuring that the allocated memory +** space is eventually freed. +** +** *pConchPath is set to NULL if a memory allocation error occurs. +*/ +static int proxyCreateConchPathname(char *dbPath, char **pConchPath){ + int i; /* Loop counter */ + int len = (int)strlen(dbPath); /* Length of database filename - dbPath */ + char *conchPath; /* buffer in which to construct conch name */ + + /* Allocate space for the conch filename and initialize the name to + ** the name of the original database file. */ + *pConchPath = conchPath = (char *)sqlite3_malloc64(len + 8); + if( conchPath==0 ){ + return SQLITE_NOMEM; + } + memcpy(conchPath, dbPath, len+1); + + /* now insert a "." before the last / character */ + for( i=(len-1); i>=0; i-- ){ + if( conchPath[i]=='/' ){ + i++; + break; + } + } + conchPath[i]='.'; + while ( ilockingContext; + char *oldPath = pCtx->lockProxyPath; + int rc = SQLITE_OK; + + if( pFile->eFileLock!=NO_LOCK ){ + return SQLITE_BUSY; + } + + /* nothing to do if the path is NULL, :auto: or matches the existing path */ + if( !path || path[0]=='\0' || !strcmp(path, ":auto:") || + (oldPath && !strncmp(oldPath, path, MAXPATHLEN)) ){ + return SQLITE_OK; + }else{ + unixFile *lockProxy = pCtx->lockProxy; + pCtx->lockProxy=NULL; + pCtx->conchHeld = 0; + if( lockProxy!=NULL ){ + rc=lockProxy->pMethod->xClose((sqlite3_file *)lockProxy); + if( rc ) return rc; + sqlite3_free(lockProxy); + } + sqlite3_free(oldPath); + pCtx->lockProxyPath = sqlite3DbStrDup(0, path); + } + + return rc; +} + +/* +** pFile is a file that has been opened by a prior xOpen call. dbPath +** is a string buffer at least MAXPATHLEN+1 characters in size. +** +** This routine find the filename associated with pFile and writes it +** int dbPath. +*/ +static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){ +#if defined(__APPLE__) + if( pFile->pMethod == &afpIoMethods ){ + /* afp style keeps a reference to the db path in the filePath field + ** of the struct */ + assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); + strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, + MAXPATHLEN); + } else +#endif + if( pFile->pMethod == &dotlockIoMethods ){ + /* dot lock style uses the locking context to store the dot lock + ** file path */ + int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX); + memcpy(dbPath, (char *)pFile->lockingContext, len + 1); + }else{ + /* all other styles use the locking context to store the db file path */ + assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); + strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN); + } + return SQLITE_OK; +} + +/* +** Takes an already filled in unix file and alters it so all file locking +** will be performed on the local proxy lock file. The following fields +** are preserved in the locking context so that they can be restored and +** the unix structure properly cleaned up at close time: +** ->lockingContext +** ->pMethod +*/ +static int proxyTransformUnixFile(unixFile *pFile, const char *path) { + proxyLockingContext *pCtx; + char dbPath[MAXPATHLEN+1]; /* Name of the database file */ + char *lockPath=NULL; + int rc = SQLITE_OK; + + if( pFile->eFileLock!=NO_LOCK ){ + return SQLITE_BUSY; + } + proxyGetDbPathForUnixFile(pFile, dbPath); + if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){ + lockPath=NULL; + }else{ + lockPath=(char *)path; + } + + OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h, + (lockPath ? lockPath : ":auto:"), osGetpid(0))); + + pCtx = sqlite3_malloc64( sizeof(*pCtx) ); + if( pCtx==0 ){ + return SQLITE_NOMEM; + } + memset(pCtx, 0, sizeof(*pCtx)); + + rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath); + if( rc==SQLITE_OK ){ + rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0); + if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){ + /* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and + ** (c) the file system is read-only, then enable no-locking access. + ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts + ** that openFlags will have only one of O_RDONLY or O_RDWR. + */ + struct statfs fsInfo; + struct stat conchInfo; + int goLockless = 0; + + if( osStat(pCtx->conchFilePath, &conchInfo) == -1 ) { + int err = errno; + if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){ + goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY; + } + } + if( goLockless ){ + pCtx->conchHeld = -1; /* read only FS/ lockless */ + rc = SQLITE_OK; + } + } + } + if( rc==SQLITE_OK && lockPath ){ + pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath); + } + + if( rc==SQLITE_OK ){ + pCtx->dbPath = sqlite3DbStrDup(0, dbPath); + if( pCtx->dbPath==NULL ){ + rc = SQLITE_NOMEM; + } + } + if( rc==SQLITE_OK ){ + /* all memory is allocated, proxys are created and assigned, + ** switch the locking context and pMethod then return. + */ + pCtx->oldLockingContext = pFile->lockingContext; + pFile->lockingContext = pCtx; + pCtx->pOldMethod = pFile->pMethod; + pFile->pMethod = &proxyIoMethods; + }else{ + if( pCtx->conchFile ){ + pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile); + sqlite3_free(pCtx->conchFile); + } + sqlite3DbFree(0, pCtx->lockProxyPath); + sqlite3_free(pCtx->conchFilePath); + sqlite3_free(pCtx); + } + OSTRACE(("TRANSPROXY %d %s\n", pFile->h, + (rc==SQLITE_OK ? "ok" : "failed"))); + return rc; +} + + +/* +** This routine handles sqlite3_file_control() calls that are specific +** to proxy locking. +*/ +static int proxyFileControl(sqlite3_file *id, int op, void *pArg){ + switch( op ){ + case SQLITE_FCNTL_GET_LOCKPROXYFILE: { + unixFile *pFile = (unixFile*)id; + if( pFile->pMethod == &proxyIoMethods ){ + proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext; + proxyTakeConch(pFile); + if( pCtx->lockProxyPath ){ + *(const char **)pArg = pCtx->lockProxyPath; + }else{ + *(const char **)pArg = ":auto: (not held)"; + } + } else { + *(const char **)pArg = NULL; + } + return SQLITE_OK; + } + case SQLITE_FCNTL_SET_LOCKPROXYFILE: { + unixFile *pFile = (unixFile*)id; + int rc = SQLITE_OK; + int isProxyStyle = (pFile->pMethod == &proxyIoMethods); + if( pArg==NULL || (const char *)pArg==0 ){ + if( isProxyStyle ){ + /* turn off proxy locking - not supported. If support is added for + ** switching proxy locking mode off then it will need to fail if + ** the journal mode is WAL mode. + */ + rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/; + }else{ + /* turn off proxy locking - already off - NOOP */ + rc = SQLITE_OK; + } + }else{ + const char *proxyPath = (const char *)pArg; + if( isProxyStyle ){ + proxyLockingContext *pCtx = + (proxyLockingContext*)pFile->lockingContext; + if( !strcmp(pArg, ":auto:") + || (pCtx->lockProxyPath && + !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN)) + ){ + rc = SQLITE_OK; + }else{ + rc = switchLockProxyPath(pFile, proxyPath); + } + }else{ + /* turn on proxy file locking */ + rc = proxyTransformUnixFile(pFile, proxyPath); + } + } + return rc; + } + default: { + assert( 0 ); /* The call assures that only valid opcodes are sent */ + } + } + /*NOTREACHED*/ + return SQLITE_ERROR; +} + +/* +** Within this division (the proxying locking implementation) the procedures +** above this point are all utilities. The lock-related methods of the +** proxy-locking sqlite3_io_method object follow. +*/ + + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, set *pResOut +** to a non-zero value otherwise *pResOut is set to zero. The return value +** is set to SQLITE_OK unless an I/O error occurs during lock checking. +*/ +static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) { + unixFile *pFile = (unixFile*)id; + int rc = proxyTakeConch(pFile); + if( rc==SQLITE_OK ){ + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; + if( pCtx->conchHeld>0 ){ + unixFile *proxy = pCtx->lockProxy; + return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut); + }else{ /* conchHeld < 0 is lockless */ + pResOut=0; + } + } + return rc; +} + +/* +** Lock the file with the lock specified by parameter eFileLock - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** This routine will only increase a lock. Use the sqlite3OsUnlock() +** routine to lower a locking level. +*/ +static int proxyLock(sqlite3_file *id, int eFileLock) { + unixFile *pFile = (unixFile*)id; + int rc = proxyTakeConch(pFile); + if( rc==SQLITE_OK ){ + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; + if( pCtx->conchHeld>0 ){ + unixFile *proxy = pCtx->lockProxy; + rc = proxy->pMethod->xLock((sqlite3_file*)proxy, eFileLock); + pFile->eFileLock = proxy->eFileLock; + }else{ + /* conchHeld < 0 is lockless */ + } + } + return rc; +} + + +/* +** Lower the locking level on file descriptor pFile to eFileLock. eFileLock +** must be either NO_LOCK or SHARED_LOCK. +** +** If the locking level of the file descriptor is already at or below +** the requested locking level, this routine is a no-op. +*/ +static int proxyUnlock(sqlite3_file *id, int eFileLock) { + unixFile *pFile = (unixFile*)id; + int rc = proxyTakeConch(pFile); + if( rc==SQLITE_OK ){ + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; + if( pCtx->conchHeld>0 ){ + unixFile *proxy = pCtx->lockProxy; + rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, eFileLock); + pFile->eFileLock = proxy->eFileLock; + }else{ + /* conchHeld < 0 is lockless */ + } + } + return rc; +} + +/* +** Close a file that uses proxy locks. +*/ +static int proxyClose(sqlite3_file *id) { + if( id ){ + unixFile *pFile = (unixFile*)id; + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; + unixFile *lockProxy = pCtx->lockProxy; + unixFile *conchFile = pCtx->conchFile; + int rc = SQLITE_OK; + + if( lockProxy ){ + rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK); + if( rc ) return rc; + rc = lockProxy->pMethod->xClose((sqlite3_file*)lockProxy); + if( rc ) return rc; + sqlite3_free(lockProxy); + pCtx->lockProxy = 0; + } + if( conchFile ){ + if( pCtx->conchHeld ){ + rc = proxyReleaseConch(pFile); + if( rc ) return rc; + } + rc = conchFile->pMethod->xClose((sqlite3_file*)conchFile); + if( rc ) return rc; + sqlite3_free(conchFile); + } + sqlite3DbFree(0, pCtx->lockProxyPath); + sqlite3_free(pCtx->conchFilePath); + sqlite3DbFree(0, pCtx->dbPath); + /* restore the original locking context and pMethod then close it */ + pFile->lockingContext = pCtx->oldLockingContext; + pFile->pMethod = pCtx->pOldMethod; + sqlite3_free(pCtx); + return pFile->pMethod->xClose(id); + } + return SQLITE_OK; +} + + + +#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ +/* +** The proxy locking style is intended for use with AFP filesystems. +** And since AFP is only supported on MacOSX, the proxy locking is also +** restricted to MacOSX. +** +** +******************* End of the proxy lock implementation ********************** +******************************************************************************/ + +/* +** Initialize the operating system interface. +** +** This routine registers all VFS implementations for unix-like operating +** systems. This routine, and the sqlite3_os_end() routine that follows, +** should be the only routines in this file that are visible from other +** files. +** +** This routine is called once during SQLite initialization and by a +** single thread. The memory allocation and mutex subsystems have not +** necessarily been initialized when this routine is called, and so they +** should not be used. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ + /* + ** The following macro defines an initializer for an sqlite3_vfs object. + ** The name of the VFS is NAME. The pAppData is a pointer to a pointer + ** to the "finder" function. (pAppData is a pointer to a pointer because + ** silly C90 rules prohibit a void* from being cast to a function pointer + ** and so we have to go through the intermediate pointer to avoid problems + ** when compiling with -pedantic-errors on GCC.) + ** + ** The FINDER parameter to this macro is the name of the pointer to the + ** finder-function. The finder-function returns a pointer to the + ** sqlite_io_methods object that implements the desired locking + ** behaviors. See the division above that contains the IOMETHODS + ** macro for addition information on finder-functions. + ** + ** Most finders simply return a pointer to a fixed sqlite3_io_methods + ** object. But the "autolockIoFinder" available on MacOSX does a little + ** more than that; it looks at the filesystem type that hosts the + ** database file and tries to choose an locking method appropriate for + ** that filesystem time. + */ + #define UNIXVFS(VFSNAME, FINDER) { \ + 3, /* iVersion */ \ + sizeof(unixFile), /* szOsFile */ \ + MAX_PATHNAME, /* mxPathname */ \ + 0, /* pNext */ \ + VFSNAME, /* zName */ \ + (void*)&FINDER, /* pAppData */ \ + unixOpen, /* xOpen */ \ + unixDelete, /* xDelete */ \ + unixAccess, /* xAccess */ \ + unixFullPathname, /* xFullPathname */ \ + unixDlOpen, /* xDlOpen */ \ + unixDlError, /* xDlError */ \ + unixDlSym, /* xDlSym */ \ + unixDlClose, /* xDlClose */ \ + unixRandomness, /* xRandomness */ \ + unixSleep, /* xSleep */ \ + unixCurrentTime, /* xCurrentTime */ \ + unixGetLastError, /* xGetLastError */ \ + unixCurrentTimeInt64, /* xCurrentTimeInt64 */ \ + unixSetSystemCall, /* xSetSystemCall */ \ + unixGetSystemCall, /* xGetSystemCall */ \ + unixNextSystemCall, /* xNextSystemCall */ \ + } + + /* + ** All default VFSes for unix are contained in the following array. + ** + ** Note that the sqlite3_vfs.pNext field of the VFS object is modified + ** by the SQLite core when the VFS is registered. So the following + ** array cannot be const. + */ + static sqlite3_vfs aVfs[] = { +#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) + UNIXVFS("unix", autolockIoFinder ), +#elif OS_VXWORKS + UNIXVFS("unix", vxworksIoFinder ), +#else + UNIXVFS("unix", posixIoFinder ), +#endif + UNIXVFS("unix-none", nolockIoFinder ), + UNIXVFS("unix-dotfile", dotlockIoFinder ), + UNIXVFS("unix-excl", posixIoFinder ), +#if OS_VXWORKS + UNIXVFS("unix-namedsem", semIoFinder ), +#endif +#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS + UNIXVFS("unix-posix", posixIoFinder ), +#endif +#if SQLITE_ENABLE_LOCKING_STYLE + UNIXVFS("unix-flock", flockIoFinder ), +#endif +#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) + UNIXVFS("unix-afp", afpIoFinder ), + UNIXVFS("unix-nfs", nfsIoFinder ), + UNIXVFS("unix-proxy", proxyIoFinder ), +#endif + }; + unsigned int i; /* Loop counter */ + + /* Double-check that the aSyscall[] array has been constructed + ** correctly. See ticket [bb3a86e890c8e96ab] */ + assert( ArraySize(aSyscall)==25 ); + + /* Register all VFSes defined in the aVfs[] array */ + for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ + sqlite3_vfs_register(&aVfs[i], i==0); + } + return SQLITE_OK; +} + +/* +** Shutdown the operating system interface. +** +** Some operating systems might need to do some cleanup in this routine, +** to release dynamically allocated objects. But not on unix. +** This routine is a no-op for unix. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ + return SQLITE_OK; +} + +#endif /* SQLITE_OS_UNIX */ + +/************** End of os_unix.c *********************************************/ +/************** Begin file os_win.c ******************************************/ +/* +** 2004 May 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains code that is specific to Windows. +*/ +/* #include "sqliteInt.h" */ +#if SQLITE_OS_WIN /* This file is used for Windows only */ + +/* +** Include code that is common to all os_*.c files +*/ +/************** Include os_common.h in the middle of os_win.c ****************/ +/************** Begin file os_common.h ***************************************/ +/* +** 2004 May 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains macros and a little bit of code that is common to +** all of the platform-specific files (os_*.c) and is #included into those +** files. +** +** This file should be #included by the os_*.c files only. It is not a +** general purpose header file. +*/ +#ifndef _OS_COMMON_H_ +#define _OS_COMMON_H_ + +/* +** At least two bugs have slipped in because we changed the MEMORY_DEBUG +** macro to SQLITE_DEBUG and some older makefiles have not yet made the +** switch. The following code should catch this problem at compile-time. +*/ +#ifdef MEMORY_DEBUG +# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." +#endif + +/* +** Macros for performance tracing. Normally turned off. Only works +** on i486 hardware. +*/ +#ifdef SQLITE_PERFORMANCE_TRACE + +/* +** hwtime.h contains inline assembler code for implementing +** high-performance timing routines. +*/ +/************** Include hwtime.h in the middle of os_common.h ****************/ +/************** Begin file hwtime.h ******************************************/ +/* +** 2008 May 27 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains inline asm code for retrieving "high-performance" +** counters for x86 class CPUs. +*/ +#ifndef _HWTIME_H_ +#define _HWTIME_H_ + +/* +** The following routine only works on pentium-class (or newer) processors. +** It uses the RDTSC opcode to read the cycle count value out of the +** processor and returns that value. This can be used for high-res +** profiling. +*/ +#if (defined(__GNUC__) || defined(_MSC_VER)) && \ + (defined(i386) || defined(__i386__) || defined(_M_IX86)) + + #if defined(__GNUC__) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned int lo, hi; + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + return (sqlite_uint64)hi << 32 | lo; + } + + #elif defined(_MSC_VER) + + __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ + __asm { + rdtsc + ret ; return value at EDX:EAX + } + } + + #endif + +#elif (defined(__GNUC__) && defined(__x86_64__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long val; + __asm__ __volatile__ ("rdtsc" : "=A" (val)); + return val; + } + +#elif (defined(__GNUC__) && defined(__ppc__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long long retval; + unsigned long junk; + __asm__ __volatile__ ("\n\ + 1: mftbu %1\n\ + mftb %L0\n\ + mftbu %0\n\ + cmpw %0,%1\n\ + bne 1b" + : "=r" (retval), "=r" (junk)); + return retval; + } + +#else + + #error Need implementation of sqlite3Hwtime() for your platform. + + /* + ** To compile without implementing sqlite3Hwtime() for your platform, + ** you can remove the above #error and use the following + ** stub function. You will lose timing support for many + ** of the debugging and testing utilities, but it should at + ** least compile and run. + */ +SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } + +#endif + +#endif /* !defined(_HWTIME_H_) */ + +/************** End of hwtime.h **********************************************/ +/************** Continuing where we left off in os_common.h ******************/ + +static sqlite_uint64 g_start; +static sqlite_uint64 g_elapsed; +#define TIMER_START g_start=sqlite3Hwtime() +#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start +#define TIMER_ELAPSED g_elapsed +#else +#define TIMER_START +#define TIMER_END +#define TIMER_ELAPSED ((sqlite_uint64)0) +#endif + +/* +** If we compile with the SQLITE_TEST macro set, then the following block +** of code will give us the ability to simulate a disk I/O error. This +** is used for testing the I/O recovery logic. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */ +SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */ +SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */ +SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */ +SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */ +SQLITE_API int sqlite3_diskfull_pending = 0; +SQLITE_API int sqlite3_diskfull = 0; +#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) +#define SimulateIOError(CODE) \ + if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ + || sqlite3_io_error_pending-- == 1 ) \ + { local_ioerr(); CODE; } +static void local_ioerr(){ + IOTRACE(("IOERR\n")); + sqlite3_io_error_hit++; + if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++; +} +#define SimulateDiskfullError(CODE) \ + if( sqlite3_diskfull_pending ){ \ + if( sqlite3_diskfull_pending == 1 ){ \ + local_ioerr(); \ + sqlite3_diskfull = 1; \ + sqlite3_io_error_hit = 1; \ + CODE; \ + }else{ \ + sqlite3_diskfull_pending--; \ + } \ + } +#else +#define SimulateIOErrorBenign(X) +#define SimulateIOError(A) +#define SimulateDiskfullError(A) +#endif + +/* +** When testing, keep a count of the number of open files. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_open_file_count = 0; +#define OpenCounter(X) sqlite3_open_file_count+=(X) +#else +#define OpenCounter(X) +#endif + +#endif /* !defined(_OS_COMMON_H_) */ + +/************** End of os_common.h *******************************************/ +/************** Continuing where we left off in os_win.c *********************/ + +/* +** Include the header file for the Windows VFS. +*/ +/* #include "os_win.h" */ + +/* +** Compiling and using WAL mode requires several APIs that are only +** available in Windows platforms based on the NT kernel. +*/ +#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL) +# error "WAL mode requires support from the Windows NT kernel, compile\ + with SQLITE_OMIT_WAL." +#endif + +#if !SQLITE_OS_WINNT && SQLITE_MAX_MMAP_SIZE>0 +# error "Memory mapped files require support from the Windows NT kernel,\ + compile with SQLITE_MAX_MMAP_SIZE=0." +#endif + +/* +** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions +** based on the sub-platform)? +*/ +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(SQLITE_WIN32_NO_ANSI) +# define SQLITE_WIN32_HAS_ANSI +#endif + +/* +** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions +** based on the sub-platform)? +*/ +#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT) && \ + !defined(SQLITE_WIN32_NO_WIDE) +# define SQLITE_WIN32_HAS_WIDE +#endif + +/* +** Make sure at least one set of Win32 APIs is available. +*/ +#if !defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_WIN32_HAS_WIDE) +# error "At least one of SQLITE_WIN32_HAS_ANSI and SQLITE_WIN32_HAS_WIDE\ + must be defined." +#endif + +/* +** Define the required Windows SDK version constants if they are not +** already available. +*/ +#ifndef NTDDI_WIN8 +# define NTDDI_WIN8 0x06020000 +#endif + +#ifndef NTDDI_WINBLUE +# define NTDDI_WINBLUE 0x06030000 +#endif + +/* +** Check to see if the GetVersionEx[AW] functions are deprecated on the +** target system. GetVersionEx was first deprecated in Win8.1. +*/ +#ifndef SQLITE_WIN32_GETVERSIONEX +# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE +# define SQLITE_WIN32_GETVERSIONEX 0 /* GetVersionEx() is deprecated */ +# else +# define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */ +# endif +#endif + +/* +** This constant should already be defined (in the "WinDef.h" SDK file). +*/ +#ifndef MAX_PATH +# define MAX_PATH (260) +#endif + +/* +** Maximum pathname length (in chars) for Win32. This should normally be +** MAX_PATH. +*/ +#ifndef SQLITE_WIN32_MAX_PATH_CHARS +# define SQLITE_WIN32_MAX_PATH_CHARS (MAX_PATH) +#endif + +/* +** This constant should already be defined (in the "WinNT.h" SDK file). +*/ +#ifndef UNICODE_STRING_MAX_CHARS +# define UNICODE_STRING_MAX_CHARS (32767) +#endif + +/* +** Maximum pathname length (in chars) for WinNT. This should normally be +** UNICODE_STRING_MAX_CHARS. +*/ +#ifndef SQLITE_WINNT_MAX_PATH_CHARS +# define SQLITE_WINNT_MAX_PATH_CHARS (UNICODE_STRING_MAX_CHARS) +#endif + +/* +** Maximum pathname length (in bytes) for Win32. The MAX_PATH macro is in +** characters, so we allocate 4 bytes per character assuming worst-case of +** 4-bytes-per-character for UTF8. +*/ +#ifndef SQLITE_WIN32_MAX_PATH_BYTES +# define SQLITE_WIN32_MAX_PATH_BYTES (SQLITE_WIN32_MAX_PATH_CHARS*4) +#endif + +/* +** Maximum pathname length (in bytes) for WinNT. This should normally be +** UNICODE_STRING_MAX_CHARS * sizeof(WCHAR). +*/ +#ifndef SQLITE_WINNT_MAX_PATH_BYTES +# define SQLITE_WINNT_MAX_PATH_BYTES \ + (sizeof(WCHAR) * SQLITE_WINNT_MAX_PATH_CHARS) +#endif + +/* +** Maximum error message length (in chars) for WinRT. +*/ +#ifndef SQLITE_WIN32_MAX_ERRMSG_CHARS +# define SQLITE_WIN32_MAX_ERRMSG_CHARS (1024) +#endif + +/* +** Returns non-zero if the character should be treated as a directory +** separator. +*/ +#ifndef winIsDirSep +# define winIsDirSep(a) (((a) == '/') || ((a) == '\\')) +#endif + +/* +** This macro is used when a local variable is set to a value that is +** [sometimes] not used by the code (e.g. via conditional compilation). +*/ +#ifndef UNUSED_VARIABLE_VALUE +# define UNUSED_VARIABLE_VALUE(x) (void)(x) +#endif + +/* +** Returns the character that should be used as the directory separator. +*/ +#ifndef winGetDirSep +# define winGetDirSep() '\\' +#endif + +/* +** Do we need to manually define the Win32 file mapping APIs for use with WAL +** mode or memory mapped files (e.g. these APIs are available in the Windows +** CE SDK; however, they are not present in the header file)? +*/ +#if SQLITE_WIN32_FILEMAPPING_API && \ + (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) +/* +** Two of the file mapping APIs are different under WinRT. Figure out which +** set we need. +*/ +#if SQLITE_OS_WINRT +WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \ + LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR); + +WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T); +#else +#if defined(SQLITE_WIN32_HAS_ANSI) +WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \ + DWORD, DWORD, DWORD, LPCSTR); +#endif /* defined(SQLITE_WIN32_HAS_ANSI) */ + +#if defined(SQLITE_WIN32_HAS_WIDE) +WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \ + DWORD, DWORD, DWORD, LPCWSTR); +#endif /* defined(SQLITE_WIN32_HAS_WIDE) */ + +WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T); +#endif /* SQLITE_OS_WINRT */ + +/* +** These file mapping APIs are common to both Win32 and WinRT. +*/ + +WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T); +WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID); +#endif /* SQLITE_WIN32_FILEMAPPING_API */ + +/* +** Some Microsoft compilers lack this definition. +*/ +#ifndef INVALID_FILE_ATTRIBUTES +# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) +#endif + +#ifndef FILE_FLAG_MASK +# define FILE_FLAG_MASK (0xFF3C0000) +#endif + +#ifndef FILE_ATTRIBUTE_MASK +# define FILE_ATTRIBUTE_MASK (0x0003FFF7) +#endif + +#ifndef SQLITE_OMIT_WAL +/* Forward references to structures used for WAL */ +typedef struct winShm winShm; /* A connection to shared-memory */ +typedef struct winShmNode winShmNode; /* A region of shared-memory */ +#endif + +/* +** WinCE lacks native support for file locking so we have to fake it +** with some code of our own. +*/ +#if SQLITE_OS_WINCE +typedef struct winceLock { + int nReaders; /* Number of reader locks obtained */ + BOOL bPending; /* Indicates a pending lock has been obtained */ + BOOL bReserved; /* Indicates a reserved lock has been obtained */ + BOOL bExclusive; /* Indicates an exclusive lock has been obtained */ +} winceLock; +#endif + +/* +** The winFile structure is a subclass of sqlite3_file* specific to the win32 +** portability layer. +*/ +typedef struct winFile winFile; +struct winFile { + const sqlite3_io_methods *pMethod; /*** Must be first ***/ + sqlite3_vfs *pVfs; /* The VFS used to open this file */ + HANDLE h; /* Handle for accessing the file */ + u8 locktype; /* Type of lock currently held on this file */ + short sharedLockByte; /* Randomly chosen byte used as a shared lock */ + u8 ctrlFlags; /* Flags. See WINFILE_* below */ + DWORD lastErrno; /* The Windows errno from the last I/O error */ +#ifndef SQLITE_OMIT_WAL + winShm *pShm; /* Instance of shared memory on this file */ +#endif + const char *zPath; /* Full pathname of this file */ + int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */ +#if SQLITE_OS_WINCE + LPWSTR zDeleteOnClose; /* Name of file to delete when closing */ + HANDLE hMutex; /* Mutex used to control access to shared lock */ + HANDLE hShared; /* Shared memory segment used for locking */ + winceLock local; /* Locks obtained by this instance of winFile */ + winceLock *shared; /* Global shared lock memory for the file */ +#endif +#if SQLITE_MAX_MMAP_SIZE>0 + int nFetchOut; /* Number of outstanding xFetch references */ + HANDLE hMap; /* Handle for accessing memory mapping */ + void *pMapRegion; /* Area memory mapped */ + sqlite3_int64 mmapSize; /* Usable size of mapped region */ + sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */ + sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ +#endif +}; + +/* +** Allowed values for winFile.ctrlFlags +*/ +#define WINFILE_RDONLY 0x02 /* Connection is read only */ +#define WINFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */ +#define WINFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ + +/* + * The size of the buffer used by sqlite3_win32_write_debug(). + */ +#ifndef SQLITE_WIN32_DBG_BUF_SIZE +# define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD))) +#endif + +/* + * The value used with sqlite3_win32_set_directory() to specify that + * the data directory should be changed. + */ +#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE +# define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1) +#endif + +/* + * The value used with sqlite3_win32_set_directory() to specify that + * the temporary directory should be changed. + */ +#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE +# define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2) +#endif + +/* + * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the + * various Win32 API heap functions instead of our own. + */ +#ifdef SQLITE_WIN32_MALLOC + +/* + * If this is non-zero, an isolated heap will be created by the native Win32 + * allocator subsystem; otherwise, the default process heap will be used. This + * setting has no effect when compiling for WinRT. By default, this is enabled + * and an isolated heap will be created to store all allocated data. + * + ****************************************************************************** + * WARNING: It is important to note that when this setting is non-zero and the + * winMemShutdown function is called (e.g. by the sqlite3_shutdown + * function), all data that was allocated using the isolated heap will + * be freed immediately and any attempt to access any of that freed + * data will almost certainly result in an immediate access violation. + ****************************************************************************** + */ +#ifndef SQLITE_WIN32_HEAP_CREATE +# define SQLITE_WIN32_HEAP_CREATE (TRUE) +#endif + +/* + * The initial size of the Win32-specific heap. This value may be zero. + */ +#ifndef SQLITE_WIN32_HEAP_INIT_SIZE +# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \ + (SQLITE_DEFAULT_PAGE_SIZE) + 4194304) +#endif + +/* + * The maximum size of the Win32-specific heap. This value may be zero. + */ +#ifndef SQLITE_WIN32_HEAP_MAX_SIZE +# define SQLITE_WIN32_HEAP_MAX_SIZE (0) +#endif + +/* + * The extra flags to use in calls to the Win32 heap APIs. This value may be + * zero for the default behavior. + */ +#ifndef SQLITE_WIN32_HEAP_FLAGS +# define SQLITE_WIN32_HEAP_FLAGS (0) +#endif + + +/* +** The winMemData structure stores information required by the Win32-specific +** sqlite3_mem_methods implementation. +*/ +typedef struct winMemData winMemData; +struct winMemData { +#ifndef NDEBUG + u32 magic1; /* Magic number to detect structure corruption. */ +#endif + HANDLE hHeap; /* The handle to our heap. */ + BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */ +#ifndef NDEBUG + u32 magic2; /* Magic number to detect structure corruption. */ +#endif +}; + +#ifndef NDEBUG +#define WINMEM_MAGIC1 0x42b2830b +#define WINMEM_MAGIC2 0xbd4d7cf4 +#endif + +static struct winMemData win_mem_data = { +#ifndef NDEBUG + WINMEM_MAGIC1, +#endif + NULL, FALSE +#ifndef NDEBUG + ,WINMEM_MAGIC2 +#endif +}; + +#ifndef NDEBUG +#define winMemAssertMagic1() assert( win_mem_data.magic1==WINMEM_MAGIC1 ) +#define winMemAssertMagic2() assert( win_mem_data.magic2==WINMEM_MAGIC2 ) +#define winMemAssertMagic() winMemAssertMagic1(); winMemAssertMagic2(); +#else +#define winMemAssertMagic() +#endif + +#define winMemGetDataPtr() &win_mem_data +#define winMemGetHeap() win_mem_data.hHeap +#define winMemGetOwned() win_mem_data.bOwned + +static void *winMemMalloc(int nBytes); +static void winMemFree(void *pPrior); +static void *winMemRealloc(void *pPrior, int nBytes); +static int winMemSize(void *p); +static int winMemRoundup(int n); +static int winMemInit(void *pAppData); +static void winMemShutdown(void *pAppData); + +SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void); +#endif /* SQLITE_WIN32_MALLOC */ + +/* +** The following variable is (normally) set once and never changes +** thereafter. It records whether the operating system is Win9x +** or WinNT. +** +** 0: Operating system unknown. +** 1: Operating system is Win9x. +** 2: Operating system is WinNT. +** +** In order to facilitate testing on a WinNT system, the test fixture +** can manually set this value to 1 to emulate Win98 behavior. +*/ +#ifdef SQLITE_TEST +SQLITE_API LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0; +#else +static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0; +#endif + +#ifndef SYSCALL +# define SYSCALL sqlite3_syscall_ptr +#endif + +/* +** This function is not available on Windows CE or WinRT. + */ + +#if SQLITE_OS_WINCE || SQLITE_OS_WINRT +# define osAreFileApisANSI() 1 +#endif + +/* +** Many system calls are accessed through pointer-to-functions so that +** they may be overridden at runtime to facilitate fault injection during +** testing and sandboxing. The following array holds the names and pointers +** to all overrideable system calls. +*/ +static struct win_syscall { + const char *zName; /* Name of the system call */ + sqlite3_syscall_ptr pCurrent; /* Current value of the system call */ + sqlite3_syscall_ptr pDefault; /* Default value */ +} aSyscall[] = { +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT + { "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 }, +#else + { "AreFileApisANSI", (SYSCALL)0, 0 }, +#endif + +#ifndef osAreFileApisANSI +#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent) +#endif + +#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE) + { "CharLowerW", (SYSCALL)CharLowerW, 0 }, +#else + { "CharLowerW", (SYSCALL)0, 0 }, +#endif + +#define osCharLowerW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[1].pCurrent) + +#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE) + { "CharUpperW", (SYSCALL)CharUpperW, 0 }, +#else + { "CharUpperW", (SYSCALL)0, 0 }, +#endif + +#define osCharUpperW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[2].pCurrent) + + { "CloseHandle", (SYSCALL)CloseHandle, 0 }, + +#define osCloseHandle ((BOOL(WINAPI*)(HANDLE))aSyscall[3].pCurrent) + +#if defined(SQLITE_WIN32_HAS_ANSI) + { "CreateFileA", (SYSCALL)CreateFileA, 0 }, +#else + { "CreateFileA", (SYSCALL)0, 0 }, +#endif + +#define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \ + LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent) + +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) + { "CreateFileW", (SYSCALL)CreateFileW, 0 }, +#else + { "CreateFileW", (SYSCALL)0, 0 }, +#endif + +#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ + LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) + +#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ + (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) + { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, +#else + { "CreateFileMappingA", (SYSCALL)0, 0 }, +#endif + +#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ + DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent) + +#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ + (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) + { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 }, +#else + { "CreateFileMappingW", (SYSCALL)0, 0 }, +#endif + +#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ + DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent) + +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) + { "CreateMutexW", (SYSCALL)CreateMutexW, 0 }, +#else + { "CreateMutexW", (SYSCALL)0, 0 }, +#endif + +#define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \ + LPCWSTR))aSyscall[8].pCurrent) + +#if defined(SQLITE_WIN32_HAS_ANSI) + { "DeleteFileA", (SYSCALL)DeleteFileA, 0 }, +#else + { "DeleteFileA", (SYSCALL)0, 0 }, +#endif + +#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent) + +#if defined(SQLITE_WIN32_HAS_WIDE) + { "DeleteFileW", (SYSCALL)DeleteFileW, 0 }, +#else + { "DeleteFileW", (SYSCALL)0, 0 }, +#endif + +#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent) + +#if SQLITE_OS_WINCE + { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 }, +#else + { "FileTimeToLocalFileTime", (SYSCALL)0, 0 }, +#endif + +#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \ + LPFILETIME))aSyscall[11].pCurrent) + +#if SQLITE_OS_WINCE + { "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 }, +#else + { "FileTimeToSystemTime", (SYSCALL)0, 0 }, +#endif + +#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \ + LPSYSTEMTIME))aSyscall[12].pCurrent) + + { "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 }, + +#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent) + +#if defined(SQLITE_WIN32_HAS_ANSI) + { "FormatMessageA", (SYSCALL)FormatMessageA, 0 }, +#else + { "FormatMessageA", (SYSCALL)0, 0 }, +#endif + +#define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \ + DWORD,va_list*))aSyscall[14].pCurrent) + +#if defined(SQLITE_WIN32_HAS_WIDE) + { "FormatMessageW", (SYSCALL)FormatMessageW, 0 }, +#else + { "FormatMessageW", (SYSCALL)0, 0 }, +#endif + +#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \ + DWORD,va_list*))aSyscall[15].pCurrent) + +#if !defined(SQLITE_OMIT_LOAD_EXTENSION) + { "FreeLibrary", (SYSCALL)FreeLibrary, 0 }, +#else + { "FreeLibrary", (SYSCALL)0, 0 }, +#endif + +#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent) + + { "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 }, + +#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent) + +#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI) + { "GetDiskFreeSpaceA", (SYSCALL)GetDiskFreeSpaceA, 0 }, +#else + { "GetDiskFreeSpaceA", (SYSCALL)0, 0 }, +#endif + +#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \ + LPDWORD))aSyscall[18].pCurrent) + +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) + { "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 }, +#else + { "GetDiskFreeSpaceW", (SYSCALL)0, 0 }, +#endif + +#define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \ + LPDWORD))aSyscall[19].pCurrent) + +#if defined(SQLITE_WIN32_HAS_ANSI) + { "GetFileAttributesA", (SYSCALL)GetFileAttributesA, 0 }, +#else + { "GetFileAttributesA", (SYSCALL)0, 0 }, +#endif + +#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent) + +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) + { "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 }, +#else + { "GetFileAttributesW", (SYSCALL)0, 0 }, +#endif + +#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent) + +#if defined(SQLITE_WIN32_HAS_WIDE) + { "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 }, +#else + { "GetFileAttributesExW", (SYSCALL)0, 0 }, +#endif + +#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \ + LPVOID))aSyscall[22].pCurrent) + +#if !SQLITE_OS_WINRT + { "GetFileSize", (SYSCALL)GetFileSize, 0 }, +#else + { "GetFileSize", (SYSCALL)0, 0 }, +#endif + +#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent) + +#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI) + { "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 }, +#else + { "GetFullPathNameA", (SYSCALL)0, 0 }, +#endif + +#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \ + LPSTR*))aSyscall[24].pCurrent) + +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) + { "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 }, +#else + { "GetFullPathNameW", (SYSCALL)0, 0 }, +#endif + +#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \ + LPWSTR*))aSyscall[25].pCurrent) + + { "GetLastError", (SYSCALL)GetLastError, 0 }, + +#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent) + +#if !defined(SQLITE_OMIT_LOAD_EXTENSION) +#if SQLITE_OS_WINCE + /* The GetProcAddressA() routine is only available on Windows CE. */ + { "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 }, +#else + /* All other Windows platforms expect GetProcAddress() to take + ** an ANSI string regardless of the _UNICODE setting */ + { "GetProcAddressA", (SYSCALL)GetProcAddress, 0 }, +#endif +#else + { "GetProcAddressA", (SYSCALL)0, 0 }, +#endif + +#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \ + LPCSTR))aSyscall[27].pCurrent) + +#if !SQLITE_OS_WINRT + { "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 }, +#else + { "GetSystemInfo", (SYSCALL)0, 0 }, +#endif + +#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent) + + { "GetSystemTime", (SYSCALL)GetSystemTime, 0 }, + +#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent) + +#if !SQLITE_OS_WINCE + { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 }, +#else + { "GetSystemTimeAsFileTime", (SYSCALL)0, 0 }, +#endif + +#define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \ + LPFILETIME))aSyscall[30].pCurrent) + +#if defined(SQLITE_WIN32_HAS_ANSI) + { "GetTempPathA", (SYSCALL)GetTempPathA, 0 }, +#else + { "GetTempPathA", (SYSCALL)0, 0 }, +#endif + +#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent) + +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) + { "GetTempPathW", (SYSCALL)GetTempPathW, 0 }, +#else + { "GetTempPathW", (SYSCALL)0, 0 }, +#endif + +#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent) + +#if !SQLITE_OS_WINRT + { "GetTickCount", (SYSCALL)GetTickCount, 0 }, +#else + { "GetTickCount", (SYSCALL)0, 0 }, +#endif + +#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent) + +#if defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_GETVERSIONEX) && \ + SQLITE_WIN32_GETVERSIONEX + { "GetVersionExA", (SYSCALL)GetVersionExA, 0 }, +#else + { "GetVersionExA", (SYSCALL)0, 0 }, +#endif + +#define osGetVersionExA ((BOOL(WINAPI*)( \ + LPOSVERSIONINFOA))aSyscall[34].pCurrent) + +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ + defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX + { "GetVersionExW", (SYSCALL)GetVersionExW, 0 }, +#else + { "GetVersionExW", (SYSCALL)0, 0 }, +#endif + +#define osGetVersionExW ((BOOL(WINAPI*)( \ + LPOSVERSIONINFOW))aSyscall[35].pCurrent) + + { "HeapAlloc", (SYSCALL)HeapAlloc, 0 }, + +#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \ + SIZE_T))aSyscall[36].pCurrent) + +#if !SQLITE_OS_WINRT + { "HeapCreate", (SYSCALL)HeapCreate, 0 }, +#else + { "HeapCreate", (SYSCALL)0, 0 }, +#endif + +#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \ + SIZE_T))aSyscall[37].pCurrent) + +#if !SQLITE_OS_WINRT + { "HeapDestroy", (SYSCALL)HeapDestroy, 0 }, +#else + { "HeapDestroy", (SYSCALL)0, 0 }, +#endif + +#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[38].pCurrent) + + { "HeapFree", (SYSCALL)HeapFree, 0 }, + +#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[39].pCurrent) + + { "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 }, + +#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \ + SIZE_T))aSyscall[40].pCurrent) + + { "HeapSize", (SYSCALL)HeapSize, 0 }, + +#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \ + LPCVOID))aSyscall[41].pCurrent) + +#if !SQLITE_OS_WINRT + { "HeapValidate", (SYSCALL)HeapValidate, 0 }, +#else + { "HeapValidate", (SYSCALL)0, 0 }, +#endif + +#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \ + LPCVOID))aSyscall[42].pCurrent) + +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT + { "HeapCompact", (SYSCALL)HeapCompact, 0 }, +#else + { "HeapCompact", (SYSCALL)0, 0 }, +#endif + +#define osHeapCompact ((UINT(WINAPI*)(HANDLE,DWORD))aSyscall[43].pCurrent) + +#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION) + { "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 }, +#else + { "LoadLibraryA", (SYSCALL)0, 0 }, +#endif + +#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[44].pCurrent) + +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ + !defined(SQLITE_OMIT_LOAD_EXTENSION) + { "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 }, +#else + { "LoadLibraryW", (SYSCALL)0, 0 }, +#endif + +#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[45].pCurrent) + +#if !SQLITE_OS_WINRT + { "LocalFree", (SYSCALL)LocalFree, 0 }, +#else + { "LocalFree", (SYSCALL)0, 0 }, +#endif + +#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[46].pCurrent) + +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT + { "LockFile", (SYSCALL)LockFile, 0 }, +#else + { "LockFile", (SYSCALL)0, 0 }, +#endif + +#ifndef osLockFile +#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ + DWORD))aSyscall[47].pCurrent) +#endif + +#if !SQLITE_OS_WINCE + { "LockFileEx", (SYSCALL)LockFileEx, 0 }, +#else + { "LockFileEx", (SYSCALL)0, 0 }, +#endif + +#ifndef osLockFileEx +#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \ + LPOVERLAPPED))aSyscall[48].pCurrent) +#endif + +#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \ + (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) + { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 }, +#else + { "MapViewOfFile", (SYSCALL)0, 0 }, +#endif + +#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ + SIZE_T))aSyscall[49].pCurrent) + + { "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 }, + +#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \ + int))aSyscall[50].pCurrent) + + { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 }, + +#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \ + LARGE_INTEGER*))aSyscall[51].pCurrent) + + { "ReadFile", (SYSCALL)ReadFile, 0 }, + +#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \ + LPOVERLAPPED))aSyscall[52].pCurrent) + + { "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 }, + +#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[53].pCurrent) + +#if !SQLITE_OS_WINRT + { "SetFilePointer", (SYSCALL)SetFilePointer, 0 }, +#else + { "SetFilePointer", (SYSCALL)0, 0 }, +#endif + +#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \ + DWORD))aSyscall[54].pCurrent) + +#if !SQLITE_OS_WINRT + { "Sleep", (SYSCALL)Sleep, 0 }, +#else + { "Sleep", (SYSCALL)0, 0 }, +#endif + +#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[55].pCurrent) + + { "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 }, + +#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \ + LPFILETIME))aSyscall[56].pCurrent) + +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT + { "UnlockFile", (SYSCALL)UnlockFile, 0 }, +#else + { "UnlockFile", (SYSCALL)0, 0 }, +#endif + +#ifndef osUnlockFile +#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ + DWORD))aSyscall[57].pCurrent) +#endif + +#if !SQLITE_OS_WINCE + { "UnlockFileEx", (SYSCALL)UnlockFileEx, 0 }, +#else + { "UnlockFileEx", (SYSCALL)0, 0 }, +#endif + +#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ + LPOVERLAPPED))aSyscall[58].pCurrent) + +#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 + { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 }, +#else + { "UnmapViewOfFile", (SYSCALL)0, 0 }, +#endif + +#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[59].pCurrent) + + { "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 }, + +#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \ + LPCSTR,LPBOOL))aSyscall[60].pCurrent) + + { "WriteFile", (SYSCALL)WriteFile, 0 }, + +#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \ + LPOVERLAPPED))aSyscall[61].pCurrent) + +#if SQLITE_OS_WINRT + { "CreateEventExW", (SYSCALL)CreateEventExW, 0 }, +#else + { "CreateEventExW", (SYSCALL)0, 0 }, +#endif + +#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \ + DWORD,DWORD))aSyscall[62].pCurrent) + +#if !SQLITE_OS_WINRT + { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 }, +#else + { "WaitForSingleObject", (SYSCALL)0, 0 }, +#endif + +#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \ + DWORD))aSyscall[63].pCurrent) + +#if !SQLITE_OS_WINCE + { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 }, +#else + { "WaitForSingleObjectEx", (SYSCALL)0, 0 }, +#endif + +#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \ + BOOL))aSyscall[64].pCurrent) + +#if SQLITE_OS_WINRT + { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 }, +#else + { "SetFilePointerEx", (SYSCALL)0, 0 }, +#endif + +#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \ + PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent) + +#if SQLITE_OS_WINRT + { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 }, +#else + { "GetFileInformationByHandleEx", (SYSCALL)0, 0 }, +#endif + +#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \ + FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent) + +#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) + { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 }, +#else + { "MapViewOfFileFromApp", (SYSCALL)0, 0 }, +#endif + +#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \ + SIZE_T))aSyscall[67].pCurrent) + +#if SQLITE_OS_WINRT + { "CreateFile2", (SYSCALL)CreateFile2, 0 }, +#else + { "CreateFile2", (SYSCALL)0, 0 }, +#endif + +#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \ + LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent) + +#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION) + { "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 }, +#else + { "LoadPackagedLibrary", (SYSCALL)0, 0 }, +#endif + +#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \ + DWORD))aSyscall[69].pCurrent) + +#if SQLITE_OS_WINRT + { "GetTickCount64", (SYSCALL)GetTickCount64, 0 }, +#else + { "GetTickCount64", (SYSCALL)0, 0 }, +#endif + +#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent) + +#if SQLITE_OS_WINRT + { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 }, +#else + { "GetNativeSystemInfo", (SYSCALL)0, 0 }, +#endif + +#define osGetNativeSystemInfo ((VOID(WINAPI*)( \ + LPSYSTEM_INFO))aSyscall[71].pCurrent) + +#if defined(SQLITE_WIN32_HAS_ANSI) + { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 }, +#else + { "OutputDebugStringA", (SYSCALL)0, 0 }, +#endif + +#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent) + +#if defined(SQLITE_WIN32_HAS_WIDE) + { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 }, +#else + { "OutputDebugStringW", (SYSCALL)0, 0 }, +#endif + +#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent) + + { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 }, + +#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent) + +#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) + { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 }, +#else + { "CreateFileMappingFromApp", (SYSCALL)0, 0 }, +#endif + +#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \ + LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent) + +/* +** NOTE: On some sub-platforms, the InterlockedCompareExchange "function" +** is really just a macro that uses a compiler intrinsic (e.g. x64). +** So do not try to make this is into a redefinable interface. +*/ +#if defined(InterlockedCompareExchange) + { "InterlockedCompareExchange", (SYSCALL)0, 0 }, + +#define osInterlockedCompareExchange InterlockedCompareExchange +#else + { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 }, + +#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \ + SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent) +#endif /* defined(InterlockedCompareExchange) */ + +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID + { "UuidCreate", (SYSCALL)UuidCreate, 0 }, +#else + { "UuidCreate", (SYSCALL)0, 0 }, +#endif + +#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent) + +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID + { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 }, +#else + { "UuidCreateSequential", (SYSCALL)0, 0 }, +#endif + +#define osUuidCreateSequential \ + ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent) + +#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0 + { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 }, +#else + { "FlushViewOfFile", (SYSCALL)0, 0 }, +#endif + +#define osFlushViewOfFile \ + ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent) + +}; /* End of the overrideable system calls */ + +/* +** This is the xSetSystemCall() method of sqlite3_vfs for all of the +** "win32" VFSes. Return SQLITE_OK opon successfully updating the +** system call pointer, or SQLITE_NOTFOUND if there is no configurable +** system call named zName. +*/ +static int winSetSystemCall( + sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */ + const char *zName, /* Name of system call to override */ + sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */ +){ + unsigned int i; + int rc = SQLITE_NOTFOUND; + + UNUSED_PARAMETER(pNotUsed); + if( zName==0 ){ + /* If no zName is given, restore all system calls to their default + ** settings and return NULL + */ + rc = SQLITE_OK; + for(i=0; i0 ){ + memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); + memcpy(zDbgBuf, zBuf, nMin); + osOutputDebugStringA(zDbgBuf); + }else{ + osOutputDebugStringA(zBuf); + } +#elif defined(SQLITE_WIN32_HAS_WIDE) + memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); + if ( osMultiByteToWideChar( + osAreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, zBuf, + nMin, (LPWSTR)zDbgBuf, SQLITE_WIN32_DBG_BUF_SIZE/sizeof(WCHAR))<=0 ){ + return; + } + osOutputDebugStringW((LPCWSTR)zDbgBuf); +#else + if( nMin>0 ){ + memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); + memcpy(zDbgBuf, zBuf, nMin); + fprintf(stderr, "%s", zDbgBuf); + }else{ + fprintf(stderr, "%s", zBuf); + } +#endif +} + +/* +** The following routine suspends the current thread for at least ms +** milliseconds. This is equivalent to the Win32 Sleep() interface. +*/ +#if SQLITE_OS_WINRT +static HANDLE sleepObj = NULL; +#endif + +SQLITE_API void SQLITE_STDCALL sqlite3_win32_sleep(DWORD milliseconds){ +#if SQLITE_OS_WINRT + if ( sleepObj==NULL ){ + sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET, + SYNCHRONIZE); + } + assert( sleepObj!=NULL ); + osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE); +#else + osSleep(milliseconds); +#endif +} + +#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ + SQLITE_THREADSAFE>0 +SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){ + DWORD rc; + while( (rc = osWaitForSingleObjectEx(hObject, INFINITE, + TRUE))==WAIT_IO_COMPLETION ){} + return rc; +} +#endif + +/* +** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, +** or WinCE. Return false (zero) for Win95, Win98, or WinME. +** +** Here is an interesting observation: Win95, Win98, and WinME lack +** the LockFileEx() API. But we can still statically link against that +** API as long as we don't call it when running Win95/98/ME. A call to +** this routine is used to determine if the host is Win95/98/ME or +** WinNT/2K/XP so that we will know whether or not we can safely call +** the LockFileEx() API. +*/ + +#if !defined(SQLITE_WIN32_GETVERSIONEX) || !SQLITE_WIN32_GETVERSIONEX +# define osIsNT() (1) +#elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI) +# define osIsNT() (1) +#elif !defined(SQLITE_WIN32_HAS_WIDE) +# define osIsNT() (0) +#else +# define osIsNT() ((sqlite3_os_type==2) || sqlite3_win32_is_nt()) +#endif + +/* +** This function determines if the machine is running a version of Windows +** based on the NT kernel. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_win32_is_nt(void){ +#if SQLITE_OS_WINRT + /* + ** NOTE: The WinRT sub-platform is always assumed to be based on the NT + ** kernel. + */ + return 1; +#elif defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX + if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){ +#if defined(SQLITE_WIN32_HAS_ANSI) + OSVERSIONINFOA sInfo; + sInfo.dwOSVersionInfoSize = sizeof(sInfo); + osGetVersionExA(&sInfo); + osInterlockedCompareExchange(&sqlite3_os_type, + (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0); +#elif defined(SQLITE_WIN32_HAS_WIDE) + OSVERSIONINFOW sInfo; + sInfo.dwOSVersionInfoSize = sizeof(sInfo); + osGetVersionExW(&sInfo); + osInterlockedCompareExchange(&sqlite3_os_type, + (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0); +#endif + } + return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2; +#elif SQLITE_TEST + return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2; +#else + /* + ** NOTE: All sub-platforms where the GetVersionEx[AW] functions are + ** deprecated are always assumed to be based on the NT kernel. + */ + return 1; +#endif +} + +#ifdef SQLITE_WIN32_MALLOC +/* +** Allocate nBytes of memory. +*/ +static void *winMemMalloc(int nBytes){ + HANDLE hHeap; + void *p; + + winMemAssertMagic(); + hHeap = winMemGetHeap(); + assert( hHeap!=0 ); + assert( hHeap!=INVALID_HANDLE_VALUE ); +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) + assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); +#endif + assert( nBytes>=0 ); + p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes); + if( !p ){ + sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%lu), heap=%p", + nBytes, osGetLastError(), (void*)hHeap); + } + return p; +} + +/* +** Free memory. +*/ +static void winMemFree(void *pPrior){ + HANDLE hHeap; + + winMemAssertMagic(); + hHeap = winMemGetHeap(); + assert( hHeap!=0 ); + assert( hHeap!=INVALID_HANDLE_VALUE ); +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) + assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); +#endif + if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */ + if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){ + sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%lu), heap=%p", + pPrior, osGetLastError(), (void*)hHeap); + } +} + +/* +** Change the size of an existing memory allocation +*/ +static void *winMemRealloc(void *pPrior, int nBytes){ + HANDLE hHeap; + void *p; + + winMemAssertMagic(); + hHeap = winMemGetHeap(); + assert( hHeap!=0 ); + assert( hHeap!=INVALID_HANDLE_VALUE ); +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) + assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); +#endif + assert( nBytes>=0 ); + if( !pPrior ){ + p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes); + }else{ + p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes); + } + if( !p ){ + sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%lu), heap=%p", + pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(), + (void*)hHeap); + } + return p; +} + +/* +** Return the size of an outstanding allocation, in bytes. +*/ +static int winMemSize(void *p){ + HANDLE hHeap; + SIZE_T n; + + winMemAssertMagic(); + hHeap = winMemGetHeap(); + assert( hHeap!=0 ); + assert( hHeap!=INVALID_HANDLE_VALUE ); +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) + assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, p) ); +#endif + if( !p ) return 0; + n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p); + if( n==(SIZE_T)-1 ){ + sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%lu), heap=%p", + p, osGetLastError(), (void*)hHeap); + return 0; + } + return (int)n; +} + +/* +** Round up a request size to the next valid allocation size. +*/ +static int winMemRoundup(int n){ + return n; +} + +/* +** Initialize this module. +*/ +static int winMemInit(void *pAppData){ + winMemData *pWinMemData = (winMemData *)pAppData; + + if( !pWinMemData ) return SQLITE_ERROR; + assert( pWinMemData->magic1==WINMEM_MAGIC1 ); + assert( pWinMemData->magic2==WINMEM_MAGIC2 ); + +#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE + if( !pWinMemData->hHeap ){ + DWORD dwInitialSize = SQLITE_WIN32_HEAP_INIT_SIZE; + DWORD dwMaximumSize = (DWORD)sqlite3GlobalConfig.nHeap; + if( dwMaximumSize==0 ){ + dwMaximumSize = SQLITE_WIN32_HEAP_MAX_SIZE; + }else if( dwInitialSize>dwMaximumSize ){ + dwInitialSize = dwMaximumSize; + } + pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS, + dwInitialSize, dwMaximumSize); + if( !pWinMemData->hHeap ){ + sqlite3_log(SQLITE_NOMEM, + "failed to HeapCreate (%lu), flags=%u, initSize=%lu, maxSize=%lu", + osGetLastError(), SQLITE_WIN32_HEAP_FLAGS, dwInitialSize, + dwMaximumSize); + return SQLITE_NOMEM; + } + pWinMemData->bOwned = TRUE; + assert( pWinMemData->bOwned ); + } +#else + pWinMemData->hHeap = osGetProcessHeap(); + if( !pWinMemData->hHeap ){ + sqlite3_log(SQLITE_NOMEM, + "failed to GetProcessHeap (%lu)", osGetLastError()); + return SQLITE_NOMEM; + } + pWinMemData->bOwned = FALSE; + assert( !pWinMemData->bOwned ); +#endif + assert( pWinMemData->hHeap!=0 ); + assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) + assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); +#endif + return SQLITE_OK; +} + +/* +** Deinitialize this module. +*/ +static void winMemShutdown(void *pAppData){ + winMemData *pWinMemData = (winMemData *)pAppData; + + if( !pWinMemData ) return; + assert( pWinMemData->magic1==WINMEM_MAGIC1 ); + assert( pWinMemData->magic2==WINMEM_MAGIC2 ); + + if( pWinMemData->hHeap ){ + assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) + assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); +#endif + if( pWinMemData->bOwned ){ + if( !osHeapDestroy(pWinMemData->hHeap) ){ + sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%lu), heap=%p", + osGetLastError(), (void*)pWinMemData->hHeap); + } + pWinMemData->bOwned = FALSE; + } + pWinMemData->hHeap = NULL; + } +} + +/* +** Populate the low-level memory allocation function pointers in +** sqlite3GlobalConfig.m with pointers to the routines in this file. The +** arguments specify the block of memory to manage. +** +** This routine is only called by sqlite3_config(), and therefore +** is not required to be threadsafe (it is not). +*/ +SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void){ + static const sqlite3_mem_methods winMemMethods = { + winMemMalloc, + winMemFree, + winMemRealloc, + winMemSize, + winMemRoundup, + winMemInit, + winMemShutdown, + &win_mem_data + }; + return &winMemMethods; +} + +SQLITE_PRIVATE void sqlite3MemSetDefault(void){ + sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32()); +} +#endif /* SQLITE_WIN32_MALLOC */ + +/* +** Convert a UTF-8 string to Microsoft Unicode (UTF-16?). +** +** Space to hold the returned string is obtained from malloc. +*/ +static LPWSTR winUtf8ToUnicode(const char *zFilename){ + int nChar; + LPWSTR zWideFilename; + + nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); + if( nChar==0 ){ + return 0; + } + zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) ); + if( zWideFilename==0 ){ + return 0; + } + nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, + nChar); + if( nChar==0 ){ + sqlite3_free(zWideFilename); + zWideFilename = 0; + } + return zWideFilename; +} + +/* +** Convert Microsoft Unicode to UTF-8. Space to hold the returned string is +** obtained from sqlite3_malloc(). +*/ +static char *winUnicodeToUtf8(LPCWSTR zWideFilename){ + int nByte; + char *zFilename; + + nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); + if( nByte == 0 ){ + return 0; + } + zFilename = sqlite3MallocZero( nByte ); + if( zFilename==0 ){ + return 0; + } + nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, + 0, 0); + if( nByte == 0 ){ + sqlite3_free(zFilename); + zFilename = 0; + } + return zFilename; +} + +/* +** Convert an ANSI string to Microsoft Unicode, based on the +** current codepage settings for file apis. +** +** Space to hold the returned string is obtained +** from sqlite3_malloc. +*/ +static LPWSTR winMbcsToUnicode(const char *zFilename){ + int nByte; + LPWSTR zMbcsFilename; + int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; + + nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL, + 0)*sizeof(WCHAR); + if( nByte==0 ){ + return 0; + } + zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) ); + if( zMbcsFilename==0 ){ + return 0; + } + nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, + nByte); + if( nByte==0 ){ + sqlite3_free(zMbcsFilename); + zMbcsFilename = 0; + } + return zMbcsFilename; +} + +/* +** Convert Microsoft Unicode to multi-byte character string, based on the +** user's ANSI codepage. +** +** Space to hold the returned string is obtained from +** sqlite3_malloc(). +*/ +static char *winUnicodeToMbcs(LPCWSTR zWideFilename){ + int nByte; + char *zFilename; + int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; + + nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); + if( nByte == 0 ){ + return 0; + } + zFilename = sqlite3MallocZero( nByte ); + if( zFilename==0 ){ + return 0; + } + nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, + nByte, 0, 0); + if( nByte == 0 ){ + sqlite3_free(zFilename); + zFilename = 0; + } + return zFilename; +} + +/* +** Convert multibyte character string to UTF-8. Space to hold the +** returned string is obtained from sqlite3_malloc(). +*/ +SQLITE_API char *SQLITE_STDCALL sqlite3_win32_mbcs_to_utf8(const char *zFilename){ + char *zFilenameUtf8; + LPWSTR zTmpWide; + + zTmpWide = winMbcsToUnicode(zFilename); + if( zTmpWide==0 ){ + return 0; + } + zFilenameUtf8 = winUnicodeToUtf8(zTmpWide); + sqlite3_free(zTmpWide); + return zFilenameUtf8; +} + +/* +** Convert UTF-8 to multibyte character string. Space to hold the +** returned string is obtained from sqlite3_malloc(). +*/ +SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs(const char *zFilename){ + char *zFilenameMbcs; + LPWSTR zTmpWide; + + zTmpWide = winUtf8ToUnicode(zFilename); + if( zTmpWide==0 ){ + return 0; + } + zFilenameMbcs = winUnicodeToMbcs(zTmpWide); + sqlite3_free(zTmpWide); + return zFilenameMbcs; +} + +/* +** This function sets the data directory or the temporary directory based on +** the provided arguments. The type argument must be 1 in order to set the +** data directory or 2 in order to set the temporary directory. The zValue +** argument is the name of the directory to use. The return value will be +** SQLITE_OK if successful. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ + char **ppDirectory = 0; +#ifndef SQLITE_OMIT_AUTOINIT + int rc = sqlite3_initialize(); + if( rc ) return rc; +#endif + if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){ + ppDirectory = &sqlite3_data_directory; + }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){ + ppDirectory = &sqlite3_temp_directory; + } + assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE + || type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE + ); + assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) ); + if( ppDirectory ){ + char *zValueUtf8 = 0; + if( zValue && zValue[0] ){ + zValueUtf8 = winUnicodeToUtf8(zValue); + if ( zValueUtf8==0 ){ + return SQLITE_NOMEM; + } + } + sqlite3_free(*ppDirectory); + *ppDirectory = zValueUtf8; + return SQLITE_OK; + } + return SQLITE_ERROR; +} + +/* +** The return value of winGetLastErrorMsg +** is zero if the error message fits in the buffer, or non-zero +** otherwise (if the message was truncated). +*/ +static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){ + /* FormatMessage returns 0 on failure. Otherwise it + ** returns the number of TCHARs written to the output + ** buffer, excluding the terminating null char. + */ + DWORD dwLen = 0; + char *zOut = 0; + + if( osIsNT() ){ +#if SQLITE_OS_WINRT + WCHAR zTempWide[SQLITE_WIN32_MAX_ERRMSG_CHARS+1]; + dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + lastErrno, + 0, + zTempWide, + SQLITE_WIN32_MAX_ERRMSG_CHARS, + 0); +#else + LPWSTR zTempWide = NULL; + dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + lastErrno, + 0, + (LPWSTR) &zTempWide, + 0, + 0); +#endif + if( dwLen > 0 ){ + /* allocate a buffer and convert to UTF8 */ + sqlite3BeginBenignMalloc(); + zOut = winUnicodeToUtf8(zTempWide); + sqlite3EndBenignMalloc(); +#if !SQLITE_OS_WINRT + /* free the system buffer allocated by FormatMessage */ + osLocalFree(zTempWide); +#endif + } + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + char *zTemp = NULL; + dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + lastErrno, + 0, + (LPSTR) &zTemp, + 0, + 0); + if( dwLen > 0 ){ + /* allocate a buffer and convert to UTF8 */ + sqlite3BeginBenignMalloc(); + zOut = sqlite3_win32_mbcs_to_utf8(zTemp); + sqlite3EndBenignMalloc(); + /* free the system buffer allocated by FormatMessage */ + osLocalFree(zTemp); + } + } +#endif + if( 0 == dwLen ){ + sqlite3_snprintf(nBuf, zBuf, "OsError 0x%lx (%lu)", lastErrno, lastErrno); + }else{ + /* copy a maximum of nBuf chars to output buffer */ + sqlite3_snprintf(nBuf, zBuf, "%s", zOut); + /* free the UTF8 buffer */ + sqlite3_free(zOut); + } + return 0; +} + +/* +** +** This function - winLogErrorAtLine() - is only ever called via the macro +** winLogError(). +** +** This routine is invoked after an error occurs in an OS function. +** It logs a message using sqlite3_log() containing the current value of +** error code and, if possible, the human-readable equivalent from +** FormatMessage. +** +** The first argument passed to the macro should be the error code that +** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). +** The two subsequent arguments should be the name of the OS function that +** failed and the associated file-system path, if any. +*/ +#define winLogError(a,b,c,d) winLogErrorAtLine(a,b,c,d,__LINE__) +static int winLogErrorAtLine( + int errcode, /* SQLite error code */ + DWORD lastErrno, /* Win32 last error */ + const char *zFunc, /* Name of OS function that failed */ + const char *zPath, /* File path associated with error */ + int iLine /* Source line number where error occurred */ +){ + char zMsg[500]; /* Human readable error text */ + int i; /* Loop counter */ + + zMsg[0] = 0; + winGetLastErrorMsg(lastErrno, sizeof(zMsg), zMsg); + assert( errcode!=SQLITE_OK ); + if( zPath==0 ) zPath = ""; + for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){} + zMsg[i] = 0; + sqlite3_log(errcode, + "os_win.c:%d: (%lu) %s(%s) - %s", + iLine, lastErrno, zFunc, zPath, zMsg + ); + + return errcode; +} + +/* +** The number of times that a ReadFile(), WriteFile(), and DeleteFile() +** will be retried following a locking error - probably caused by +** antivirus software. Also the initial delay before the first retry. +** The delay increases linearly with each retry. +*/ +#ifndef SQLITE_WIN32_IOERR_RETRY +# define SQLITE_WIN32_IOERR_RETRY 10 +#endif +#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY +# define SQLITE_WIN32_IOERR_RETRY_DELAY 25 +#endif +static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY; +static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY; + +/* +** The "winIoerrCanRetry1" macro is used to determine if a particular I/O +** error code obtained via GetLastError() is eligible to be retried. It +** must accept the error code DWORD as its only argument and should return +** non-zero if the error code is transient in nature and the operation +** responsible for generating the original error might succeed upon being +** retried. The argument to this macro should be a variable. +** +** Additionally, a macro named "winIoerrCanRetry2" may be defined. If it +** is defined, it will be consulted only when the macro "winIoerrCanRetry1" +** returns zero. The "winIoerrCanRetry2" macro is completely optional and +** may be used to include additional error codes in the set that should +** result in the failing I/O operation being retried by the caller. If +** defined, the "winIoerrCanRetry2" macro must exhibit external semantics +** identical to those of the "winIoerrCanRetry1" macro. +*/ +#if !defined(winIoerrCanRetry1) +#define winIoerrCanRetry1(a) (((a)==ERROR_ACCESS_DENIED) || \ + ((a)==ERROR_SHARING_VIOLATION) || \ + ((a)==ERROR_LOCK_VIOLATION) || \ + ((a)==ERROR_DEV_NOT_EXIST) || \ + ((a)==ERROR_NETNAME_DELETED) || \ + ((a)==ERROR_SEM_TIMEOUT) || \ + ((a)==ERROR_NETWORK_UNREACHABLE)) +#endif + +/* +** If a ReadFile() or WriteFile() error occurs, invoke this routine +** to see if it should be retried. Return TRUE to retry. Return FALSE +** to give up with an error. +*/ +static int winRetryIoerr(int *pnRetry, DWORD *pError){ + DWORD e = osGetLastError(); + if( *pnRetry>=winIoerrRetry ){ + if( pError ){ + *pError = e; + } + return 0; + } + if( winIoerrCanRetry1(e) ){ + sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry)); + ++*pnRetry; + return 1; + } +#if defined(winIoerrCanRetry2) + else if( winIoerrCanRetry2(e) ){ + sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry)); + ++*pnRetry; + return 1; + } +#endif + if( pError ){ + *pError = e; + } + return 0; +} + +/* +** Log a I/O error retry episode. +*/ +static void winLogIoerr(int nRetry, int lineno){ + if( nRetry ){ + sqlite3_log(SQLITE_NOTICE, + "delayed %dms for lock/sharing conflict at line %d", + winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno + ); + } +} + +#if SQLITE_OS_WINCE +/************************************************************************* +** This section contains code for WinCE only. +*/ +#if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API +/* +** The MSVC CRT on Windows CE may not have a localtime() function. So +** create a substitute. +*/ +/* #include */ +struct tm *__cdecl localtime(const time_t *t) +{ + static struct tm y; + FILETIME uTm, lTm; + SYSTEMTIME pTm; + sqlite3_int64 t64; + t64 = *t; + t64 = (t64 + 11644473600)*10000000; + uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF); + uTm.dwHighDateTime= (DWORD)(t64 >> 32); + osFileTimeToLocalFileTime(&uTm,&lTm); + osFileTimeToSystemTime(&lTm,&pTm); + y.tm_year = pTm.wYear - 1900; + y.tm_mon = pTm.wMonth - 1; + y.tm_wday = pTm.wDayOfWeek; + y.tm_mday = pTm.wDay; + y.tm_hour = pTm.wHour; + y.tm_min = pTm.wMinute; + y.tm_sec = pTm.wSecond; + return &y; +} +#endif + +#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)] + +/* +** Acquire a lock on the handle h +*/ +static void winceMutexAcquire(HANDLE h){ + DWORD dwErr; + do { + dwErr = osWaitForSingleObject(h, INFINITE); + } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED); +} +/* +** Release a lock acquired by winceMutexAcquire() +*/ +#define winceMutexRelease(h) ReleaseMutex(h) + +/* +** Create the mutex and shared memory used for locking in the file +** descriptor pFile +*/ +static int winceCreateLock(const char *zFilename, winFile *pFile){ + LPWSTR zTok; + LPWSTR zName; + DWORD lastErrno; + BOOL bLogged = FALSE; + BOOL bInit = TRUE; + + zName = winUtf8ToUnicode(zFilename); + if( zName==0 ){ + /* out of memory */ + return SQLITE_IOERR_NOMEM; + } + + /* Initialize the local lockdata */ + memset(&pFile->local, 0, sizeof(pFile->local)); + + /* Replace the backslashes from the filename and lowercase it + ** to derive a mutex name. */ + zTok = osCharLowerW(zName); + for (;*zTok;zTok++){ + if (*zTok == '\\') *zTok = '_'; + } + + /* Create/open the named mutex */ + pFile->hMutex = osCreateMutexW(NULL, FALSE, zName); + if (!pFile->hMutex){ + pFile->lastErrno = osGetLastError(); + sqlite3_free(zName); + return winLogError(SQLITE_IOERR, pFile->lastErrno, + "winceCreateLock1", zFilename); + } + + /* Acquire the mutex before continuing */ + winceMutexAcquire(pFile->hMutex); + + /* Since the names of named mutexes, semaphores, file mappings etc are + ** case-sensitive, take advantage of that by uppercasing the mutex name + ** and using that as the shared filemapping name. + */ + osCharUpperW(zName); + pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL, + PAGE_READWRITE, 0, sizeof(winceLock), + zName); + + /* Set a flag that indicates we're the first to create the memory so it + ** must be zero-initialized */ + lastErrno = osGetLastError(); + if (lastErrno == ERROR_ALREADY_EXISTS){ + bInit = FALSE; + } + + sqlite3_free(zName); + + /* If we succeeded in making the shared memory handle, map it. */ + if( pFile->hShared ){ + pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, + FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); + /* If mapping failed, close the shared memory handle and erase it */ + if( !pFile->shared ){ + pFile->lastErrno = osGetLastError(); + winLogError(SQLITE_IOERR, pFile->lastErrno, + "winceCreateLock2", zFilename); + bLogged = TRUE; + osCloseHandle(pFile->hShared); + pFile->hShared = NULL; + } + } + + /* If shared memory could not be created, then close the mutex and fail */ + if( pFile->hShared==NULL ){ + if( !bLogged ){ + pFile->lastErrno = lastErrno; + winLogError(SQLITE_IOERR, pFile->lastErrno, + "winceCreateLock3", zFilename); + bLogged = TRUE; + } + winceMutexRelease(pFile->hMutex); + osCloseHandle(pFile->hMutex); + pFile->hMutex = NULL; + return SQLITE_IOERR; + } + + /* Initialize the shared memory if we're supposed to */ + if( bInit ){ + memset(pFile->shared, 0, sizeof(winceLock)); + } + + winceMutexRelease(pFile->hMutex); + return SQLITE_OK; +} + +/* +** Destroy the part of winFile that deals with wince locks +*/ +static void winceDestroyLock(winFile *pFile){ + if (pFile->hMutex){ + /* Acquire the mutex */ + winceMutexAcquire(pFile->hMutex); + + /* The following blocks should probably assert in debug mode, but they + are to cleanup in case any locks remained open */ + if (pFile->local.nReaders){ + pFile->shared->nReaders --; + } + if (pFile->local.bReserved){ + pFile->shared->bReserved = FALSE; + } + if (pFile->local.bPending){ + pFile->shared->bPending = FALSE; + } + if (pFile->local.bExclusive){ + pFile->shared->bExclusive = FALSE; + } + + /* De-reference and close our copy of the shared memory handle */ + osUnmapViewOfFile(pFile->shared); + osCloseHandle(pFile->hShared); + + /* Done with the mutex */ + winceMutexRelease(pFile->hMutex); + osCloseHandle(pFile->hMutex); + pFile->hMutex = NULL; + } +} + +/* +** An implementation of the LockFile() API of Windows for CE +*/ +static BOOL winceLockFile( + LPHANDLE phFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh +){ + winFile *pFile = HANDLE_TO_WINFILE(phFile); + BOOL bReturn = FALSE; + + UNUSED_PARAMETER(dwFileOffsetHigh); + UNUSED_PARAMETER(nNumberOfBytesToLockHigh); + + if (!pFile->hMutex) return TRUE; + winceMutexAcquire(pFile->hMutex); + + /* Wanting an exclusive lock? */ + if (dwFileOffsetLow == (DWORD)SHARED_FIRST + && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ + if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){ + pFile->shared->bExclusive = TRUE; + pFile->local.bExclusive = TRUE; + bReturn = TRUE; + } + } + + /* Want a read-only lock? */ + else if (dwFileOffsetLow == (DWORD)SHARED_FIRST && + nNumberOfBytesToLockLow == 1){ + if (pFile->shared->bExclusive == 0){ + pFile->local.nReaders ++; + if (pFile->local.nReaders == 1){ + pFile->shared->nReaders ++; + } + bReturn = TRUE; + } + } + + /* Want a pending lock? */ + else if (dwFileOffsetLow == (DWORD)PENDING_BYTE + && nNumberOfBytesToLockLow == 1){ + /* If no pending lock has been acquired, then acquire it */ + if (pFile->shared->bPending == 0) { + pFile->shared->bPending = TRUE; + pFile->local.bPending = TRUE; + bReturn = TRUE; + } + } + + /* Want a reserved lock? */ + else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE + && nNumberOfBytesToLockLow == 1){ + if (pFile->shared->bReserved == 0) { + pFile->shared->bReserved = TRUE; + pFile->local.bReserved = TRUE; + bReturn = TRUE; + } + } + + winceMutexRelease(pFile->hMutex); + return bReturn; +} + +/* +** An implementation of the UnlockFile API of Windows for CE +*/ +static BOOL winceUnlockFile( + LPHANDLE phFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh +){ + winFile *pFile = HANDLE_TO_WINFILE(phFile); + BOOL bReturn = FALSE; + + UNUSED_PARAMETER(dwFileOffsetHigh); + UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh); + + if (!pFile->hMutex) return TRUE; + winceMutexAcquire(pFile->hMutex); + + /* Releasing a reader lock or an exclusive lock */ + if (dwFileOffsetLow == (DWORD)SHARED_FIRST){ + /* Did we have an exclusive lock? */ + if (pFile->local.bExclusive){ + assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE); + pFile->local.bExclusive = FALSE; + pFile->shared->bExclusive = FALSE; + bReturn = TRUE; + } + + /* Did we just have a reader lock? */ + else if (pFile->local.nReaders){ + assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE + || nNumberOfBytesToUnlockLow == 1); + pFile->local.nReaders --; + if (pFile->local.nReaders == 0) + { + pFile->shared->nReaders --; + } + bReturn = TRUE; + } + } + + /* Releasing a pending lock */ + else if (dwFileOffsetLow == (DWORD)PENDING_BYTE + && nNumberOfBytesToUnlockLow == 1){ + if (pFile->local.bPending){ + pFile->local.bPending = FALSE; + pFile->shared->bPending = FALSE; + bReturn = TRUE; + } + } + /* Releasing a reserved lock */ + else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE + && nNumberOfBytesToUnlockLow == 1){ + if (pFile->local.bReserved) { + pFile->local.bReserved = FALSE; + pFile->shared->bReserved = FALSE; + bReturn = TRUE; + } + } + + winceMutexRelease(pFile->hMutex); + return bReturn; +} +/* +** End of the special code for wince +*****************************************************************************/ +#endif /* SQLITE_OS_WINCE */ + +/* +** Lock a file region. +*/ +static BOOL winLockFile( + LPHANDLE phFile, + DWORD flags, + DWORD offsetLow, + DWORD offsetHigh, + DWORD numBytesLow, + DWORD numBytesHigh +){ +#if SQLITE_OS_WINCE + /* + ** NOTE: Windows CE is handled differently here due its lack of the Win32 + ** API LockFile. + */ + return winceLockFile(phFile, offsetLow, offsetHigh, + numBytesLow, numBytesHigh); +#else + if( osIsNT() ){ + OVERLAPPED ovlp; + memset(&ovlp, 0, sizeof(OVERLAPPED)); + ovlp.Offset = offsetLow; + ovlp.OffsetHigh = offsetHigh; + return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp); + }else{ + return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow, + numBytesHigh); + } +#endif +} + +/* +** Unlock a file region. + */ +static BOOL winUnlockFile( + LPHANDLE phFile, + DWORD offsetLow, + DWORD offsetHigh, + DWORD numBytesLow, + DWORD numBytesHigh +){ +#if SQLITE_OS_WINCE + /* + ** NOTE: Windows CE is handled differently here due its lack of the Win32 + ** API UnlockFile. + */ + return winceUnlockFile(phFile, offsetLow, offsetHigh, + numBytesLow, numBytesHigh); +#else + if( osIsNT() ){ + OVERLAPPED ovlp; + memset(&ovlp, 0, sizeof(OVERLAPPED)); + ovlp.Offset = offsetLow; + ovlp.OffsetHigh = offsetHigh; + return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp); + }else{ + return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow, + numBytesHigh); + } +#endif +} + +/***************************************************************************** +** The next group of routines implement the I/O methods specified +** by the sqlite3_io_methods object. +******************************************************************************/ + +/* +** Some Microsoft compilers lack this definition. +*/ +#ifndef INVALID_SET_FILE_POINTER +# define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + +/* +** Move the current position of the file handle passed as the first +** argument to offset iOffset within the file. If successful, return 0. +** Otherwise, set pFile->lastErrno and return non-zero. +*/ +static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){ +#if !SQLITE_OS_WINRT + LONG upperBits; /* Most sig. 32 bits of new offset */ + LONG lowerBits; /* Least sig. 32 bits of new offset */ + DWORD dwRet; /* Value returned by SetFilePointer() */ + DWORD lastErrno; /* Value returned by GetLastError() */ + + OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset)); + + upperBits = (LONG)((iOffset>>32) & 0x7fffffff); + lowerBits = (LONG)(iOffset & 0xffffffff); + + /* API oddity: If successful, SetFilePointer() returns a dword + ** containing the lower 32-bits of the new file-offset. Or, if it fails, + ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, + ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine + ** whether an error has actually occurred, it is also necessary to call + ** GetLastError(). + */ + dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); + + if( (dwRet==INVALID_SET_FILE_POINTER + && ((lastErrno = osGetLastError())!=NO_ERROR)) ){ + pFile->lastErrno = lastErrno; + winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, + "winSeekFile", pFile->zPath); + OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h)); + return 1; + } + + OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h)); + return 0; +#else + /* + ** Same as above, except that this implementation works for WinRT. + */ + + LARGE_INTEGER x; /* The new offset */ + BOOL bRet; /* Value returned by SetFilePointerEx() */ + + x.QuadPart = iOffset; + bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN); + + if(!bRet){ + pFile->lastErrno = osGetLastError(); + winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, + "winSeekFile", pFile->zPath); + OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h)); + return 1; + } + + OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h)); + return 0; +#endif +} + +#if SQLITE_MAX_MMAP_SIZE>0 +/* Forward references to VFS helper methods used for memory mapped files */ +static int winMapfile(winFile*, sqlite3_int64); +static int winUnmapfile(winFile*); +#endif + +/* +** Close a file. +** +** It is reported that an attempt to close a handle might sometimes +** fail. This is a very unreasonable result, but Windows is notorious +** for being unreasonable so I do not doubt that it might happen. If +** the close fails, we pause for 100 milliseconds and try again. As +** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before +** giving up and returning an error. +*/ +#define MX_CLOSE_ATTEMPT 3 +static int winClose(sqlite3_file *id){ + int rc, cnt = 0; + winFile *pFile = (winFile*)id; + + assert( id!=0 ); +#ifndef SQLITE_OMIT_WAL + assert( pFile->pShm==0 ); +#endif + assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE ); + OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p\n", + osGetCurrentProcessId(), pFile, pFile->h)); + +#if SQLITE_MAX_MMAP_SIZE>0 + winUnmapfile(pFile); +#endif + + do{ + rc = osCloseHandle(pFile->h); + /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */ + }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) ); +#if SQLITE_OS_WINCE +#define WINCE_DELETION_ATTEMPTS 3 + winceDestroyLock(pFile); + if( pFile->zDeleteOnClose ){ + int cnt = 0; + while( + osDeleteFileW(pFile->zDeleteOnClose)==0 + && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff + && cnt++ < WINCE_DELETION_ATTEMPTS + ){ + sqlite3_win32_sleep(100); /* Wait a little before trying again */ + } + sqlite3_free(pFile->zDeleteOnClose); + } +#endif + if( rc ){ + pFile->h = NULL; + } + OpenCounter(-1); + OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p, rc=%s\n", + osGetCurrentProcessId(), pFile, pFile->h, rc ? "ok" : "failed")); + return rc ? SQLITE_OK + : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(), + "winClose", pFile->zPath); +} + +/* +** Read data from a file into a buffer. Return SQLITE_OK if all +** bytes were read successfully and SQLITE_IOERR if anything goes +** wrong. +*/ +static int winRead( + sqlite3_file *id, /* File to read from */ + void *pBuf, /* Write content into this buffer */ + int amt, /* Number of bytes to read */ + sqlite3_int64 offset /* Begin reading at this offset */ +){ +#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) + OVERLAPPED overlapped; /* The offset for ReadFile. */ +#endif + winFile *pFile = (winFile*)id; /* file handle */ + DWORD nRead; /* Number of bytes actually read from file */ + int nRetry = 0; /* Number of retrys */ + + assert( id!=0 ); + assert( amt>0 ); + assert( offset>=0 ); + SimulateIOError(return SQLITE_IOERR_READ); + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " + "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, + pFile->h, pBuf, amt, offset, pFile->locktype)); + +#if SQLITE_MAX_MMAP_SIZE>0 + /* Deal with as much of this read request as possible by transfering + ** data from the memory mapping using memcpy(). */ + if( offsetmmapSize ){ + if( offset+amt <= pFile->mmapSize ){ + memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); + OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); + return SQLITE_OK; + }else{ + int nCopy = (int)(pFile->mmapSize - offset); + memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy); + pBuf = &((u8 *)pBuf)[nCopy]; + amt -= nCopy; + offset += nCopy; + } + } +#endif + +#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) + if( winSeekFile(pFile, offset) ){ + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n", + osGetCurrentProcessId(), pFile, pFile->h)); + return SQLITE_FULL; + } + while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ +#else + memset(&overlapped, 0, sizeof(OVERLAPPED)); + overlapped.Offset = (LONG)(offset & 0xffffffff); + overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); + while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) && + osGetLastError()!=ERROR_HANDLE_EOF ){ +#endif + DWORD lastErrno; + if( winRetryIoerr(&nRetry, &lastErrno) ) continue; + pFile->lastErrno = lastErrno; + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_READ\n", + osGetCurrentProcessId(), pFile, pFile->h)); + return winLogError(SQLITE_IOERR_READ, pFile->lastErrno, + "winRead", pFile->zPath); + } + winLogIoerr(nRetry, __LINE__); + if( nRead<(DWORD)amt ){ + /* Unread parts of the buffer must be zero-filled */ + memset(&((char*)pBuf)[nRead], 0, amt-nRead); + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_SHORT_READ\n", + osGetCurrentProcessId(), pFile, pFile->h)); + return SQLITE_IOERR_SHORT_READ; + } + + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); + return SQLITE_OK; +} + +/* +** Write data from a buffer into a file. Return SQLITE_OK on success +** or some other error code on failure. +*/ +static int winWrite( + sqlite3_file *id, /* File to write into */ + const void *pBuf, /* The bytes to be written */ + int amt, /* Number of bytes to write */ + sqlite3_int64 offset /* Offset into the file to begin writing at */ +){ + int rc = 0; /* True if error has occurred, else false */ + winFile *pFile = (winFile*)id; /* File handle */ + int nRetry = 0; /* Number of retries */ + + assert( amt>0 ); + assert( pFile ); + SimulateIOError(return SQLITE_IOERR_WRITE); + SimulateDiskfullError(return SQLITE_FULL); + + OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " + "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, + pFile->h, pBuf, amt, offset, pFile->locktype)); + +#if SQLITE_MAX_MMAP_SIZE>0 + /* Deal with as much of this write request as possible by transfering + ** data from the memory mapping using memcpy(). */ + if( offsetmmapSize ){ + if( offset+amt <= pFile->mmapSize ){ + memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt); + OSTRACE(("WRITE-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); + return SQLITE_OK; + }else{ + int nCopy = (int)(pFile->mmapSize - offset); + memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy); + pBuf = &((u8 *)pBuf)[nCopy]; + amt -= nCopy; + offset += nCopy; + } + } +#endif + +#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) + rc = winSeekFile(pFile, offset); + if( rc==0 ){ +#else + { +#endif +#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) + OVERLAPPED overlapped; /* The offset for WriteFile. */ +#endif + u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ + int nRem = amt; /* Number of bytes yet to be written */ + DWORD nWrite; /* Bytes written by each WriteFile() call */ + DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */ + +#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) + memset(&overlapped, 0, sizeof(OVERLAPPED)); + overlapped.Offset = (LONG)(offset & 0xffffffff); + overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); +#endif + + while( nRem>0 ){ +#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) + if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ +#else + if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ +#endif + if( winRetryIoerr(&nRetry, &lastErrno) ) continue; + break; + } + assert( nWrite==0 || nWrite<=(DWORD)nRem ); + if( nWrite==0 || nWrite>(DWORD)nRem ){ + lastErrno = osGetLastError(); + break; + } +#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) + offset += nWrite; + overlapped.Offset = (LONG)(offset & 0xffffffff); + overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); +#endif + aRem += nWrite; + nRem -= nWrite; + } + if( nRem>0 ){ + pFile->lastErrno = lastErrno; + rc = 1; + } + } + + if( rc ){ + if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ) + || ( pFile->lastErrno==ERROR_DISK_FULL )){ + OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n", + osGetCurrentProcessId(), pFile, pFile->h)); + return winLogError(SQLITE_FULL, pFile->lastErrno, + "winWrite1", pFile->zPath); + } + OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_WRITE\n", + osGetCurrentProcessId(), pFile, pFile->h)); + return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno, + "winWrite2", pFile->zPath); + }else{ + winLogIoerr(nRetry, __LINE__); + } + OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); + return SQLITE_OK; +} + +/* +** Truncate an open file to a specified size +*/ +static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ + winFile *pFile = (winFile*)id; /* File handle object */ + int rc = SQLITE_OK; /* Return code for this function */ + DWORD lastErrno; + + assert( pFile ); + SimulateIOError(return SQLITE_IOERR_TRUNCATE); + OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n", + osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype)); + + /* If the user has configured a chunk-size for this file, truncate the + ** file so that it consists of an integer number of chunks (i.e. the + ** actual file size after the operation may be larger than the requested + ** size). + */ + if( pFile->szChunk>0 ){ + nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; + } + + /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */ + if( winSeekFile(pFile, nByte) ){ + rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, + "winTruncate1", pFile->zPath); + }else if( 0==osSetEndOfFile(pFile->h) && + ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){ + pFile->lastErrno = lastErrno; + rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, + "winTruncate2", pFile->zPath); + } + +#if SQLITE_MAX_MMAP_SIZE>0 + /* If the file was truncated to a size smaller than the currently + ** mapped region, reduce the effective mapping size as well. SQLite will + ** use read() and write() to access data beyond this point from now on. + */ + if( pFile->pMapRegion && nBytemmapSize ){ + pFile->mmapSize = nByte; + } +#endif + + OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n", + osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc))); + return rc; +} + +#ifdef SQLITE_TEST +/* +** Count the number of fullsyncs and normal syncs. This is used to test +** that syncs and fullsyncs are occuring at the right times. +*/ +SQLITE_API int sqlite3_sync_count = 0; +SQLITE_API int sqlite3_fullsync_count = 0; +#endif + +/* +** Make sure all writes to a particular file are committed to disk. +*/ +static int winSync(sqlite3_file *id, int flags){ +#ifndef SQLITE_NO_SYNC + /* + ** Used only when SQLITE_NO_SYNC is not defined. + */ + BOOL rc; +#endif +#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \ + defined(SQLITE_HAVE_OS_TRACE) + /* + ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or + ** OSTRACE() macros. + */ + winFile *pFile = (winFile*)id; +#else + UNUSED_PARAMETER(id); +#endif + + assert( pFile ); + /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */ + assert((flags&0x0F)==SQLITE_SYNC_NORMAL + || (flags&0x0F)==SQLITE_SYNC_FULL + ); + + /* Unix cannot, but some systems may return SQLITE_FULL from here. This + ** line is to test that doing so does not cause any problems. + */ + SimulateDiskfullError( return SQLITE_FULL ); + + OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, flags=%x, lock=%d\n", + osGetCurrentProcessId(), pFile, pFile->h, flags, + pFile->locktype)); + +#ifndef SQLITE_TEST + UNUSED_PARAMETER(flags); +#else + if( (flags&0x0F)==SQLITE_SYNC_FULL ){ + sqlite3_fullsync_count++; + } + sqlite3_sync_count++; +#endif + + /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a + ** no-op + */ +#ifdef SQLITE_NO_SYNC + OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); + return SQLITE_OK; +#else +#if SQLITE_MAX_MMAP_SIZE>0 + if( pFile->pMapRegion ){ + if( osFlushViewOfFile(pFile->pMapRegion, 0) ){ + OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, " + "rc=SQLITE_OK\n", osGetCurrentProcessId(), + pFile, pFile->pMapRegion)); + }else{ + pFile->lastErrno = osGetLastError(); + OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, " + "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), + pFile, pFile->pMapRegion)); + return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, + "winSync1", pFile->zPath); + } + } +#endif + rc = osFlushFileBuffers(pFile->h); + SimulateIOError( rc=FALSE ); + if( rc ){ + OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); + return SQLITE_OK; + }else{ + pFile->lastErrno = osGetLastError(); + OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n", + osGetCurrentProcessId(), pFile, pFile->h)); + return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno, + "winSync2", pFile->zPath); + } +#endif +} + +/* +** Determine the current size of a file in bytes +*/ +static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ + winFile *pFile = (winFile*)id; + int rc = SQLITE_OK; + + assert( id!=0 ); + assert( pSize!=0 ); + SimulateIOError(return SQLITE_IOERR_FSTAT); + OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize)); + +#if SQLITE_OS_WINRT + { + FILE_STANDARD_INFO info; + if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo, + &info, sizeof(info)) ){ + *pSize = info.EndOfFile.QuadPart; + }else{ + pFile->lastErrno = osGetLastError(); + rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, + "winFileSize", pFile->zPath); + } + } +#else + { + DWORD upperBits; + DWORD lowerBits; + DWORD lastErrno; + + lowerBits = osGetFileSize(pFile->h, &upperBits); + *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits; + if( (lowerBits == INVALID_FILE_SIZE) + && ((lastErrno = osGetLastError())!=NO_ERROR) ){ + pFile->lastErrno = lastErrno; + rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, + "winFileSize", pFile->zPath); + } + } +#endif + OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n", + pFile->h, pSize, *pSize, sqlite3ErrName(rc))); + return rc; +} + +/* +** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. +*/ +#ifndef LOCKFILE_FAIL_IMMEDIATELY +# define LOCKFILE_FAIL_IMMEDIATELY 1 +#endif + +#ifndef LOCKFILE_EXCLUSIVE_LOCK +# define LOCKFILE_EXCLUSIVE_LOCK 2 +#endif + +/* +** Historically, SQLite has used both the LockFile and LockFileEx functions. +** When the LockFile function was used, it was always expected to fail +** immediately if the lock could not be obtained. Also, it always expected to +** obtain an exclusive lock. These flags are used with the LockFileEx function +** and reflect those expectations; therefore, they should not be changed. +*/ +#ifndef SQLITE_LOCKFILE_FLAGS +# define SQLITE_LOCKFILE_FLAGS (LOCKFILE_FAIL_IMMEDIATELY | \ + LOCKFILE_EXCLUSIVE_LOCK) +#endif + +/* +** Currently, SQLite never calls the LockFileEx function without wanting the +** call to fail immediately if the lock cannot be obtained. +*/ +#ifndef SQLITE_LOCKFILEEX_FLAGS +# define SQLITE_LOCKFILEEX_FLAGS (LOCKFILE_FAIL_IMMEDIATELY) +#endif + +/* +** Acquire a reader lock. +** Different API routines are called depending on whether or not this +** is Win9x or WinNT. +*/ +static int winGetReadLock(winFile *pFile){ + int res; + OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype)); + if( osIsNT() ){ +#if SQLITE_OS_WINCE + /* + ** NOTE: Windows CE is handled differently here due its lack of the Win32 + ** API LockFileEx. + */ + res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0); +#else + res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0, + SHARED_SIZE, 0); +#endif + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + int lk; + sqlite3_randomness(sizeof(lk), &lk); + pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1)); + res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, + SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); + } +#endif + if( res == 0 ){ + pFile->lastErrno = osGetLastError(); + /* No need to log a failure to lock */ + } + OSTRACE(("READ-LOCK file=%p, result=%d\n", pFile->h, res)); + return res; +} + +/* +** Undo a readlock +*/ +static int winUnlockReadLock(winFile *pFile){ + int res; + DWORD lastErrno; + OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype)); + if( osIsNT() ){ + res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); + } +#endif + if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){ + pFile->lastErrno = lastErrno; + winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno, + "winUnlockReadLock", pFile->zPath); + } + OSTRACE(("READ-UNLOCK file=%p, result=%d\n", pFile->h, res)); + return res; +} + +/* +** Lock the file with the lock specified by parameter locktype - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** This routine will only increase a lock. The winUnlock() routine +** erases all locks at once and returns us immediately to locking level 0. +** It is not possible to lower the locking level one step at a time. You +** must go straight to locking level 0. +*/ +static int winLock(sqlite3_file *id, int locktype){ + int rc = SQLITE_OK; /* Return code from subroutines */ + int res = 1; /* Result of a Windows lock call */ + int newLocktype; /* Set pFile->locktype to this value before exiting */ + int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ + winFile *pFile = (winFile*)id; + DWORD lastErrno = NO_ERROR; + + assert( id!=0 ); + OSTRACE(("LOCK file=%p, oldLock=%d(%d), newLock=%d\n", + pFile->h, pFile->locktype, pFile->sharedLockByte, locktype)); + + /* If there is already a lock of this type or more restrictive on the + ** OsFile, do nothing. Don't use the end_lock: exit path, as + ** sqlite3OsEnterMutex() hasn't been called yet. + */ + if( pFile->locktype>=locktype ){ + OSTRACE(("LOCK-HELD file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; + } + + /* Do not allow any kind of write-lock on a read-only database + */ + if( (pFile->ctrlFlags & WINFILE_RDONLY)!=0 && locktype>=RESERVED_LOCK ){ + return SQLITE_IOERR_LOCK; + } + + /* Make sure the locking sequence is correct + */ + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); + + /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or + ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of + ** the PENDING_LOCK byte is temporary. + */ + newLocktype = pFile->locktype; + if( (pFile->locktype==NO_LOCK) + || ( (locktype==EXCLUSIVE_LOCK) + && (pFile->locktype==RESERVED_LOCK)) + ){ + int cnt = 3; + while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, + PENDING_BYTE, 0, 1, 0))==0 ){ + /* Try 3 times to get the pending lock. This is needed to work + ** around problems caused by indexing and/or anti-virus software on + ** Windows systems. + ** If you are using this code as a model for alternative VFSes, do not + ** copy this retry logic. It is a hack intended for Windows only. + */ + lastErrno = osGetLastError(); + OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n", + pFile->h, cnt, res)); + if( lastErrno==ERROR_INVALID_HANDLE ){ + pFile->lastErrno = lastErrno; + rc = SQLITE_IOERR_LOCK; + OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n", + pFile->h, cnt, sqlite3ErrName(rc))); + return rc; + } + if( cnt ) sqlite3_win32_sleep(1); + } + gotPendingLock = res; + if( !res ){ + lastErrno = osGetLastError(); + } + } + + /* Acquire a shared lock + */ + if( locktype==SHARED_LOCK && res ){ + assert( pFile->locktype==NO_LOCK ); + res = winGetReadLock(pFile); + if( res ){ + newLocktype = SHARED_LOCK; + }else{ + lastErrno = osGetLastError(); + } + } + + /* Acquire a RESERVED lock + */ + if( locktype==RESERVED_LOCK && res ){ + assert( pFile->locktype==SHARED_LOCK ); + res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0); + if( res ){ + newLocktype = RESERVED_LOCK; + }else{ + lastErrno = osGetLastError(); + } + } + + /* Acquire a PENDING lock + */ + if( locktype==EXCLUSIVE_LOCK && res ){ + newLocktype = PENDING_LOCK; + gotPendingLock = 0; + } + + /* Acquire an EXCLUSIVE lock + */ + if( locktype==EXCLUSIVE_LOCK && res ){ + assert( pFile->locktype>=SHARED_LOCK ); + res = winUnlockReadLock(pFile); + res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0, + SHARED_SIZE, 0); + if( res ){ + newLocktype = EXCLUSIVE_LOCK; + }else{ + lastErrno = osGetLastError(); + winGetReadLock(pFile); + } + } + + /* If we are holding a PENDING lock that ought to be released, then + ** release it now. + */ + if( gotPendingLock && locktype==SHARED_LOCK ){ + winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0); + } + + /* Update the state of the lock has held in the file descriptor then + ** return the appropriate result code. + */ + if( res ){ + rc = SQLITE_OK; + }else{ + pFile->lastErrno = lastErrno; + rc = SQLITE_BUSY; + OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n", + pFile->h, locktype, newLocktype)); + } + pFile->locktype = (u8)newLocktype; + OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n", + pFile->h, pFile->locktype, sqlite3ErrName(rc))); + return rc; +} + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, return +** non-zero, otherwise zero. +*/ +static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ + int res; + winFile *pFile = (winFile*)id; + + SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); + OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p\n", pFile->h, pResOut)); + + assert( id!=0 ); + if( pFile->locktype>=RESERVED_LOCK ){ + res = 1; + OSTRACE(("TEST-WR-LOCK file=%p, result=%d (local)\n", pFile->h, res)); + }else{ + res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0); + if( res ){ + winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); + } + res = !res; + OSTRACE(("TEST-WR-LOCK file=%p, result=%d (remote)\n", pFile->h, res)); + } + *pResOut = res; + OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n", + pFile->h, pResOut, *pResOut)); + return SQLITE_OK; +} + +/* +** Lower the locking level on file descriptor id to locktype. locktype +** must be either NO_LOCK or SHARED_LOCK. +** +** If the locking level of the file descriptor is already at or below +** the requested locking level, this routine is a no-op. +** +** It is not possible for this routine to fail if the second argument +** is NO_LOCK. If the second argument is SHARED_LOCK then this routine +** might return SQLITE_IOERR; +*/ +static int winUnlock(sqlite3_file *id, int locktype){ + int type; + winFile *pFile = (winFile*)id; + int rc = SQLITE_OK; + assert( pFile!=0 ); + assert( locktype<=SHARED_LOCK ); + OSTRACE(("UNLOCK file=%p, oldLock=%d(%d), newLock=%d\n", + pFile->h, pFile->locktype, pFile->sharedLockByte, locktype)); + type = pFile->locktype; + if( type>=EXCLUSIVE_LOCK ){ + winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + if( locktype==SHARED_LOCK && !winGetReadLock(pFile) ){ + /* This should never happen. We should always be able to + ** reacquire the read lock */ + rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(), + "winUnlock", pFile->zPath); + } + } + if( type>=RESERVED_LOCK ){ + winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); + } + if( locktype==NO_LOCK && type>=SHARED_LOCK ){ + winUnlockReadLock(pFile); + } + if( type>=PENDING_LOCK ){ + winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0); + } + pFile->locktype = (u8)locktype; + OSTRACE(("UNLOCK file=%p, lock=%d, rc=%s\n", + pFile->h, pFile->locktype, sqlite3ErrName(rc))); + return rc; +} + +/* +** If *pArg is initially negative then this is a query. Set *pArg to +** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set. +** +** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags. +*/ +static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){ + if( *pArg<0 ){ + *pArg = (pFile->ctrlFlags & mask)!=0; + }else if( (*pArg)==0 ){ + pFile->ctrlFlags &= ~mask; + }else{ + pFile->ctrlFlags |= mask; + } +} + +/* Forward references to VFS helper methods used for temporary files */ +static int winGetTempname(sqlite3_vfs *, char **); +static int winIsDir(const void *); +static BOOL winIsDriveLetterAndColon(const char *); + +/* +** Control and query of the open file handle. +*/ +static int winFileControl(sqlite3_file *id, int op, void *pArg){ + winFile *pFile = (winFile*)id; + OSTRACE(("FCNTL file=%p, op=%d, pArg=%p\n", pFile->h, op, pArg)); + switch( op ){ + case SQLITE_FCNTL_LOCKSTATE: { + *(int*)pArg = pFile->locktype; + OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; + } + case SQLITE_LAST_ERRNO: { + *(int*)pArg = (int)pFile->lastErrno; + OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; + } + case SQLITE_FCNTL_CHUNK_SIZE: { + pFile->szChunk = *(int *)pArg; + OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; + } + case SQLITE_FCNTL_SIZE_HINT: { + if( pFile->szChunk>0 ){ + sqlite3_int64 oldSz; + int rc = winFileSize(id, &oldSz); + if( rc==SQLITE_OK ){ + sqlite3_int64 newSz = *(sqlite3_int64*)pArg; + if( newSz>oldSz ){ + SimulateIOErrorBenign(1); + rc = winTruncate(id, newSz); + SimulateIOErrorBenign(0); + } + } + OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); + return rc; + } + OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; + } + case SQLITE_FCNTL_PERSIST_WAL: { + winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg); + OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; + } + case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { + winModeBit(pFile, WINFILE_PSOW, (int*)pArg); + OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; + } + case SQLITE_FCNTL_VFSNAME: { + *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); + OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; + } + case SQLITE_FCNTL_WIN32_AV_RETRY: { + int *a = (int*)pArg; + if( a[0]>0 ){ + winIoerrRetry = a[0]; + }else{ + a[0] = winIoerrRetry; + } + if( a[1]>0 ){ + winIoerrRetryDelay = a[1]; + }else{ + a[1] = winIoerrRetryDelay; + } + OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; + } +#ifdef SQLITE_TEST + case SQLITE_FCNTL_WIN32_SET_HANDLE: { + LPHANDLE phFile = (LPHANDLE)pArg; + HANDLE hOldFile = pFile->h; + pFile->h = *phFile; + *phFile = hOldFile; + OSTRACE(("FCNTL oldFile=%p, newFile=%p, rc=SQLITE_OK\n", + hOldFile, pFile->h)); + return SQLITE_OK; + } +#endif + case SQLITE_FCNTL_TEMPFILENAME: { + char *zTFile = 0; + int rc = winGetTempname(pFile->pVfs, &zTFile); + if( rc==SQLITE_OK ){ + *(char**)pArg = zTFile; + } + OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); + return rc; + } +#if SQLITE_MAX_MMAP_SIZE>0 + case SQLITE_FCNTL_MMAP_SIZE: { + i64 newLimit = *(i64*)pArg; + int rc = SQLITE_OK; + if( newLimit>sqlite3GlobalConfig.mxMmap ){ + newLimit = sqlite3GlobalConfig.mxMmap; + } + *(i64*)pArg = pFile->mmapSizeMax; + if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){ + pFile->mmapSizeMax = newLimit; + if( pFile->mmapSize>0 ){ + winUnmapfile(pFile); + rc = winMapfile(pFile, -1); + } + } + OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); + return rc; + } +#endif + } + OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h)); + return SQLITE_NOTFOUND; +} + +/* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and its journal file) that the sector size will be the +** same for both. +*/ +static int winSectorSize(sqlite3_file *id){ + (void)id; + return SQLITE_DEFAULT_SECTOR_SIZE; +} + +/* +** Return a vector of device characteristics. +*/ +static int winDeviceCharacteristics(sqlite3_file *id){ + winFile *p = (winFile*)id; + return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | + ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0); +} + +/* +** Windows will only let you create file view mappings +** on allocation size granularity boundaries. +** During sqlite3_os_init() we do a GetSystemInfo() +** to get the granularity size. +*/ +static SYSTEM_INFO winSysInfo; + +#ifndef SQLITE_OMIT_WAL + +/* +** Helper functions to obtain and relinquish the global mutex. The +** global mutex is used to protect the winLockInfo objects used by +** this file, all of which may be shared by multiple threads. +** +** Function winShmMutexHeld() is used to assert() that the global mutex +** is held when required. This function is only used as part of assert() +** statements. e.g. +** +** winShmEnterMutex() +** assert( winShmMutexHeld() ); +** winShmLeaveMutex() +*/ +static void winShmEnterMutex(void){ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); +} +static void winShmLeaveMutex(void){ + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); +} +#ifndef NDEBUG +static int winShmMutexHeld(void) { + return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); +} +#endif + +/* +** Object used to represent a single file opened and mmapped to provide +** shared memory. When multiple threads all reference the same +** log-summary, each thread has its own winFile object, but they all +** point to a single instance of this object. In other words, each +** log-summary is opened only once per process. +** +** winShmMutexHeld() must be true when creating or destroying +** this object or while reading or writing the following fields: +** +** nRef +** pNext +** +** The following fields are read-only after the object is created: +** +** fid +** zFilename +** +** Either winShmNode.mutex must be held or winShmNode.nRef==0 and +** winShmMutexHeld() is true when reading or writing any other field +** in this structure. +** +*/ +struct winShmNode { + sqlite3_mutex *mutex; /* Mutex to access this object */ + char *zFilename; /* Name of the file */ + winFile hFile; /* File handle from winOpen */ + + int szRegion; /* Size of shared-memory regions */ + int nRegion; /* Size of array apRegion */ + struct ShmRegion { + HANDLE hMap; /* File handle from CreateFileMapping */ + void *pMap; + } *aRegion; + DWORD lastErrno; /* The Windows errno from the last I/O error */ + + int nRef; /* Number of winShm objects pointing to this */ + winShm *pFirst; /* All winShm objects pointing to this */ + winShmNode *pNext; /* Next in list of all winShmNode objects */ +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) + u8 nextShmId; /* Next available winShm.id value */ +#endif +}; + +/* +** A global array of all winShmNode objects. +** +** The winShmMutexHeld() must be true while reading or writing this list. +*/ +static winShmNode *winShmNodeList = 0; + +/* +** Structure used internally by this VFS to record the state of an +** open shared memory connection. +** +** The following fields are initialized when this object is created and +** are read-only thereafter: +** +** winShm.pShmNode +** winShm.id +** +** All other fields are read/write. The winShm.pShmNode->mutex must be held +** while accessing any read/write fields. +*/ +struct winShm { + winShmNode *pShmNode; /* The underlying winShmNode object */ + winShm *pNext; /* Next winShm with the same winShmNode */ + u8 hasMutex; /* True if holding the winShmNode mutex */ + u16 sharedMask; /* Mask of shared locks held */ + u16 exclMask; /* Mask of exclusive locks held */ +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) + u8 id; /* Id of this connection with its winShmNode */ +#endif +}; + +/* +** Constants used for locking +*/ +#define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ +#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ + +/* +** Apply advisory locks for all n bytes beginning at ofst. +*/ +#define _SHM_UNLCK 1 +#define _SHM_RDLCK 2 +#define _SHM_WRLCK 3 +static int winShmSystemLock( + winShmNode *pFile, /* Apply locks to this open shared-memory segment */ + int lockType, /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */ + int ofst, /* Offset to first byte to be locked/unlocked */ + int nByte /* Number of bytes to lock or unlock */ +){ + int rc = 0; /* Result code form Lock/UnlockFileEx() */ + + /* Access to the winShmNode object is serialized by the caller */ + assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); + + OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n", + pFile->hFile.h, lockType, ofst, nByte)); + + /* Release/Acquire the system-level lock */ + if( lockType==_SHM_UNLCK ){ + rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0); + }else{ + /* Initialize the locking parameters */ + DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY; + if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; + rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0); + } + + if( rc!= 0 ){ + rc = SQLITE_OK; + }else{ + pFile->lastErrno = osGetLastError(); + rc = SQLITE_BUSY; + } + + OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n", + pFile->hFile.h, (lockType == _SHM_UNLCK) ? "winUnlockFile" : + "winLockFile", pFile->lastErrno, sqlite3ErrName(rc))); + + return rc; +} + +/* Forward references to VFS methods */ +static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*); +static int winDelete(sqlite3_vfs *,const char*,int); + +/* +** Purge the winShmNodeList list of all entries with winShmNode.nRef==0. +** +** This is not a VFS shared-memory method; it is a utility function called +** by VFS shared-memory methods. +*/ +static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ + winShmNode **pp; + winShmNode *p; + assert( winShmMutexHeld() ); + OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n", + osGetCurrentProcessId(), deleteFlag)); + pp = &winShmNodeList; + while( (p = *pp)!=0 ){ + if( p->nRef==0 ){ + int i; + if( p->mutex ){ sqlite3_mutex_free(p->mutex); } + for(i=0; inRegion; i++){ + BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap); + OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n", + osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); + UNUSED_VARIABLE_VALUE(bRc); + bRc = osCloseHandle(p->aRegion[i].hMap); + OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n", + osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); + UNUSED_VARIABLE_VALUE(bRc); + } + if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){ + SimulateIOErrorBenign(1); + winClose((sqlite3_file *)&p->hFile); + SimulateIOErrorBenign(0); + } + if( deleteFlag ){ + SimulateIOErrorBenign(1); + sqlite3BeginBenignMalloc(); + winDelete(pVfs, p->zFilename, 0); + sqlite3EndBenignMalloc(); + SimulateIOErrorBenign(0); + } + *pp = p->pNext; + sqlite3_free(p->aRegion); + sqlite3_free(p); + }else{ + pp = &p->pNext; + } + } +} + +/* +** Open the shared-memory area associated with database file pDbFd. +** +** When opening a new shared-memory file, if no other instances of that +** file are currently open, in this process or in other processes, then +** the file must be truncated to zero length or have its header cleared. +*/ +static int winOpenSharedMemory(winFile *pDbFd){ + struct winShm *p; /* The connection to be opened */ + struct winShmNode *pShmNode = 0; /* The underlying mmapped file */ + int rc; /* Result code */ + struct winShmNode *pNew; /* Newly allocated winShmNode */ + int nName; /* Size of zName in bytes */ + + assert( pDbFd->pShm==0 ); /* Not previously opened */ + + /* Allocate space for the new sqlite3_shm object. Also speculatively + ** allocate space for a new winShmNode and filename. + */ + p = sqlite3MallocZero( sizeof(*p) ); + if( p==0 ) return SQLITE_IOERR_NOMEM; + nName = sqlite3Strlen30(pDbFd->zPath); + pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 ); + if( pNew==0 ){ + sqlite3_free(p); + return SQLITE_IOERR_NOMEM; + } + pNew->zFilename = (char*)&pNew[1]; + sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); + sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); + + /* Look to see if there is an existing winShmNode that can be used. + ** If no matching winShmNode currently exists, create a new one. + */ + winShmEnterMutex(); + for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){ + /* TBD need to come up with better match here. Perhaps + ** use FILE_ID_BOTH_DIR_INFO Structure. + */ + if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break; + } + if( pShmNode ){ + sqlite3_free(pNew); + }else{ + pShmNode = pNew; + pNew = 0; + ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE; + pShmNode->pNext = winShmNodeList; + winShmNodeList = pShmNode; + + pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + if( pShmNode->mutex==0 ){ + rc = SQLITE_IOERR_NOMEM; + goto shm_open_err; + } + + rc = winOpen(pDbFd->pVfs, + pShmNode->zFilename, /* Name of the file (UTF-8) */ + (sqlite3_file*)&pShmNode->hFile, /* File handle here */ + SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, + 0); + if( SQLITE_OK!=rc ){ + goto shm_open_err; + } + + /* Check to see if another process is holding the dead-man switch. + ** If not, truncate the file to zero length. + */ + if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){ + rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0); + if( rc!=SQLITE_OK ){ + rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(), + "winOpenShm", pDbFd->zPath); + } + } + if( rc==SQLITE_OK ){ + winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); + rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1); + } + if( rc ) goto shm_open_err; + } + + /* Make the new connection a child of the winShmNode */ + p->pShmNode = pShmNode; +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) + p->id = pShmNode->nextShmId++; +#endif + pShmNode->nRef++; + pDbFd->pShm = p; + winShmLeaveMutex(); + + /* The reference count on pShmNode has already been incremented under + ** the cover of the winShmEnterMutex() mutex and the pointer from the + ** new (struct winShm) object to the pShmNode has been set. All that is + ** left to do is to link the new object into the linked list starting + ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex + ** mutex. + */ + sqlite3_mutex_enter(pShmNode->mutex); + p->pNext = pShmNode->pFirst; + pShmNode->pFirst = p; + sqlite3_mutex_leave(pShmNode->mutex); + return SQLITE_OK; + + /* Jump here on any error */ +shm_open_err: + winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); + winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */ + sqlite3_free(p); + sqlite3_free(pNew); + winShmLeaveMutex(); + return rc; +} + +/* +** Close a connection to shared-memory. Delete the underlying +** storage if deleteFlag is true. +*/ +static int winShmUnmap( + sqlite3_file *fd, /* Database holding shared memory */ + int deleteFlag /* Delete after closing if true */ +){ + winFile *pDbFd; /* Database holding shared-memory */ + winShm *p; /* The connection to be closed */ + winShmNode *pShmNode; /* The underlying shared-memory file */ + winShm **pp; /* For looping over sibling connections */ + + pDbFd = (winFile*)fd; + p = pDbFd->pShm; + if( p==0 ) return SQLITE_OK; + pShmNode = p->pShmNode; + + /* Remove connection p from the set of connections associated + ** with pShmNode */ + sqlite3_mutex_enter(pShmNode->mutex); + for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} + *pp = p->pNext; + + /* Free the connection p */ + sqlite3_free(p); + pDbFd->pShm = 0; + sqlite3_mutex_leave(pShmNode->mutex); + + /* If pShmNode->nRef has reached 0, then close the underlying + ** shared-memory file, too */ + winShmEnterMutex(); + assert( pShmNode->nRef>0 ); + pShmNode->nRef--; + if( pShmNode->nRef==0 ){ + winShmPurge(pDbFd->pVfs, deleteFlag); + } + winShmLeaveMutex(); + + return SQLITE_OK; +} + +/* +** Change the lock state for a shared-memory segment. +*/ +static int winShmLock( + sqlite3_file *fd, /* Database file holding the shared memory */ + int ofst, /* First lock to acquire or release */ + int n, /* Number of locks to acquire or release */ + int flags /* What to do with the lock */ +){ + winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */ + winShm *p = pDbFd->pShm; /* The shared memory being locked */ + winShm *pX; /* For looping over all siblings */ + winShmNode *pShmNode = p->pShmNode; + int rc = SQLITE_OK; /* Result code */ + u16 mask; /* Mask of locks to take or release */ + + assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK ); + assert( n>=1 ); + assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED) + || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE) + || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) + || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); + assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); + + mask = (u16)((1U<<(ofst+n)) - (1U<1 || mask==(1<mutex); + if( flags & SQLITE_SHM_UNLOCK ){ + u16 allMask = 0; /* Mask of locks held by siblings */ + + /* See if any siblings hold this same lock */ + for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ + if( pX==p ) continue; + assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 ); + allMask |= pX->sharedMask; + } + + /* Unlock the system-level locks */ + if( (mask & allMask)==0 ){ + rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n); + }else{ + rc = SQLITE_OK; + } + + /* Undo the local locks */ + if( rc==SQLITE_OK ){ + p->exclMask &= ~mask; + p->sharedMask &= ~mask; + } + }else if( flags & SQLITE_SHM_SHARED ){ + u16 allShared = 0; /* Union of locks held by connections other than "p" */ + + /* Find out which shared locks are already held by sibling connections. + ** If any sibling already holds an exclusive lock, go ahead and return + ** SQLITE_BUSY. + */ + for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ + if( (pX->exclMask & mask)!=0 ){ + rc = SQLITE_BUSY; + break; + } + allShared |= pX->sharedMask; + } + + /* Get shared locks at the system level, if necessary */ + if( rc==SQLITE_OK ){ + if( (allShared & mask)==0 ){ + rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n); + }else{ + rc = SQLITE_OK; + } + } + + /* Get the local shared locks */ + if( rc==SQLITE_OK ){ + p->sharedMask |= mask; + } + }else{ + /* Make sure no sibling connections hold locks that will block this + ** lock. If any do, return SQLITE_BUSY right away. + */ + for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ + if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){ + rc = SQLITE_BUSY; + break; + } + } + + /* Get the exclusive locks at the system level. Then if successful + ** also mark the local connection as being locked. + */ + if( rc==SQLITE_OK ){ + rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n); + if( rc==SQLITE_OK ){ + assert( (p->sharedMask & mask)==0 ); + p->exclMask |= mask; + } + } + } + sqlite3_mutex_leave(pShmNode->mutex); + OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n", + osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask, + sqlite3ErrName(rc))); + return rc; +} + +/* +** Implement a memory barrier or memory fence on shared memory. +** +** All loads and stores begun before the barrier must complete before +** any load or store begun after the barrier. +*/ +static void winShmBarrier( + sqlite3_file *fd /* Database holding the shared memory */ +){ + UNUSED_PARAMETER(fd); + /* MemoryBarrier(); // does not work -- do not know why not */ + winShmEnterMutex(); + winShmLeaveMutex(); +} + +/* +** This function is called to obtain a pointer to region iRegion of the +** shared-memory associated with the database file fd. Shared-memory regions +** are numbered starting from zero. Each shared-memory region is szRegion +** bytes in size. +** +** If an error occurs, an error code is returned and *pp is set to NULL. +** +** Otherwise, if the isWrite parameter is 0 and the requested shared-memory +** region has not been allocated (by any client, including one running in a +** separate process), then *pp is set to NULL and SQLITE_OK returned. If +** isWrite is non-zero and the requested shared-memory region has not yet +** been allocated, it is allocated by this function. +** +** If the shared-memory region has already been allocated or is allocated by +** this call as described above, then it is mapped into this processes +** address space (if it is not already), *pp is set to point to the mapped +** memory and SQLITE_OK returned. +*/ +static int winShmMap( + sqlite3_file *fd, /* Handle open on database file */ + int iRegion, /* Region to retrieve */ + int szRegion, /* Size of regions */ + int isWrite, /* True to extend file if necessary */ + void volatile **pp /* OUT: Mapped memory */ +){ + winFile *pDbFd = (winFile*)fd; + winShm *pShm = pDbFd->pShm; + winShmNode *pShmNode; + int rc = SQLITE_OK; + + if( !pShm ){ + rc = winOpenSharedMemory(pDbFd); + if( rc!=SQLITE_OK ) return rc; + pShm = pDbFd->pShm; + } + pShmNode = pShm->pShmNode; + + sqlite3_mutex_enter(pShmNode->mutex); + assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); + + if( pShmNode->nRegion<=iRegion ){ + struct ShmRegion *apNew; /* New aRegion[] array */ + int nByte = (iRegion+1)*szRegion; /* Minimum required file size */ + sqlite3_int64 sz; /* Current size of wal-index file */ + + pShmNode->szRegion = szRegion; + + /* The requested region is not mapped into this processes address space. + ** Check to see if it has been allocated (i.e. if the wal-index file is + ** large enough to contain the requested region). + */ + rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz); + if( rc!=SQLITE_OK ){ + rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(), + "winShmMap1", pDbFd->zPath); + goto shmpage_out; + } + + if( szhFile, nByte); + if( rc!=SQLITE_OK ){ + rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(), + "winShmMap2", pDbFd->zPath); + goto shmpage_out; + } + } + + /* Map the requested memory region into this processes address space. */ + apNew = (struct ShmRegion *)sqlite3_realloc64( + pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0]) + ); + if( !apNew ){ + rc = SQLITE_IOERR_NOMEM; + goto shmpage_out; + } + pShmNode->aRegion = apNew; + + while( pShmNode->nRegion<=iRegion ){ + HANDLE hMap = NULL; /* file-mapping handle */ + void *pMap = 0; /* Mapped memory region */ + +#if SQLITE_OS_WINRT + hMap = osCreateFileMappingFromApp(pShmNode->hFile.h, + NULL, PAGE_READWRITE, nByte, NULL + ); +#elif defined(SQLITE_WIN32_HAS_WIDE) + hMap = osCreateFileMappingW(pShmNode->hFile.h, + NULL, PAGE_READWRITE, 0, nByte, NULL + ); +#elif defined(SQLITE_WIN32_HAS_ANSI) + hMap = osCreateFileMappingA(pShmNode->hFile.h, + NULL, PAGE_READWRITE, 0, nByte, NULL + ); +#endif + OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", + osGetCurrentProcessId(), pShmNode->nRegion, nByte, + hMap ? "ok" : "failed")); + if( hMap ){ + int iOffset = pShmNode->nRegion*szRegion; + int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; +#if SQLITE_OS_WINRT + pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ, + iOffset - iOffsetShift, szRegion + iOffsetShift + ); +#else + pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ, + 0, iOffset - iOffsetShift, szRegion + iOffsetShift + ); +#endif + OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n", + osGetCurrentProcessId(), pShmNode->nRegion, iOffset, + szRegion, pMap ? "ok" : "failed")); + } + if( !pMap ){ + pShmNode->lastErrno = osGetLastError(); + rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno, + "winShmMap3", pDbFd->zPath); + if( hMap ) osCloseHandle(hMap); + goto shmpage_out; + } + + pShmNode->aRegion[pShmNode->nRegion].pMap = pMap; + pShmNode->aRegion[pShmNode->nRegion].hMap = hMap; + pShmNode->nRegion++; + } + } + +shmpage_out: + if( pShmNode->nRegion>iRegion ){ + int iOffset = iRegion*szRegion; + int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; + char *p = (char *)pShmNode->aRegion[iRegion].pMap; + *pp = (void *)&p[iOffsetShift]; + }else{ + *pp = 0; + } + sqlite3_mutex_leave(pShmNode->mutex); + return rc; +} + +#else +# define winShmMap 0 +# define winShmLock 0 +# define winShmBarrier 0 +# define winShmUnmap 0 +#endif /* #ifndef SQLITE_OMIT_WAL */ + +/* +** Cleans up the mapped region of the specified file, if any. +*/ +#if SQLITE_MAX_MMAP_SIZE>0 +static int winUnmapfile(winFile *pFile){ + assert( pFile!=0 ); + OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, " + "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n", + osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion, + pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax)); + if( pFile->pMapRegion ){ + if( !osUnmapViewOfFile(pFile->pMapRegion) ){ + pFile->lastErrno = osGetLastError(); + OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, pMapRegion=%p, " + "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile, + pFile->pMapRegion)); + return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, + "winUnmapfile1", pFile->zPath); + } + pFile->pMapRegion = 0; + pFile->mmapSize = 0; + pFile->mmapSizeActual = 0; + } + if( pFile->hMap!=NULL ){ + if( !osCloseHandle(pFile->hMap) ){ + pFile->lastErrno = osGetLastError(); + OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n", + osGetCurrentProcessId(), pFile, pFile->hMap)); + return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, + "winUnmapfile2", pFile->zPath); + } + pFile->hMap = NULL; + } + OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile)); + return SQLITE_OK; +} + +/* +** Memory map or remap the file opened by file-descriptor pFd (if the file +** is already mapped, the existing mapping is replaced by the new). Or, if +** there already exists a mapping for this file, and there are still +** outstanding xFetch() references to it, this function is a no-op. +** +** If parameter nByte is non-negative, then it is the requested size of +** the mapping to create. Otherwise, if nByte is less than zero, then the +** requested size is the size of the file on disk. The actual size of the +** created mapping is either the requested size or the value configured +** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller. +** +** SQLITE_OK is returned if no error occurs (even if the mapping is not +** recreated as a result of outstanding references) or an SQLite error +** code otherwise. +*/ +static int winMapfile(winFile *pFd, sqlite3_int64 nByte){ + sqlite3_int64 nMap = nByte; + int rc; + + assert( nMap>=0 || pFd->nFetchOut==0 ); + OSTRACE(("MAP-FILE pid=%lu, pFile=%p, size=%lld\n", + osGetCurrentProcessId(), pFd, nByte)); + + if( pFd->nFetchOut>0 ) return SQLITE_OK; + + if( nMap<0 ){ + rc = winFileSize((sqlite3_file*)pFd, &nMap); + if( rc ){ + OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_IOERR_FSTAT\n", + osGetCurrentProcessId(), pFd)); + return SQLITE_IOERR_FSTAT; + } + } + if( nMap>pFd->mmapSizeMax ){ + nMap = pFd->mmapSizeMax; + } + nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1); + + if( nMap==0 && pFd->mmapSize>0 ){ + winUnmapfile(pFd); + } + if( nMap!=pFd->mmapSize ){ + void *pNew = 0; + DWORD protect = PAGE_READONLY; + DWORD flags = FILE_MAP_READ; + + winUnmapfile(pFd); + if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){ + protect = PAGE_READWRITE; + flags |= FILE_MAP_WRITE; + } +#if SQLITE_OS_WINRT + pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL); +#elif defined(SQLITE_WIN32_HAS_WIDE) + pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect, + (DWORD)((nMap>>32) & 0xffffffff), + (DWORD)(nMap & 0xffffffff), NULL); +#elif defined(SQLITE_WIN32_HAS_ANSI) + pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect, + (DWORD)((nMap>>32) & 0xffffffff), + (DWORD)(nMap & 0xffffffff), NULL); +#endif + if( pFd->hMap==NULL ){ + pFd->lastErrno = osGetLastError(); + rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno, + "winMapfile1", pFd->zPath); + /* Log the error, but continue normal operation using xRead/xWrite */ + OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=%s\n", + osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); + return SQLITE_OK; + } + assert( (nMap % winSysInfo.dwPageSize)==0 ); + assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff ); +#if SQLITE_OS_WINRT + pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, (SIZE_T)nMap); +#else + pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap); +#endif + if( pNew==NULL ){ + osCloseHandle(pFd->hMap); + pFd->hMap = NULL; + pFd->lastErrno = osGetLastError(); + rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno, + "winMapfile2", pFd->zPath); + /* Log the error, but continue normal operation using xRead/xWrite */ + OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=%s\n", + osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); + return SQLITE_OK; + } + pFd->pMapRegion = pNew; + pFd->mmapSize = nMap; + pFd->mmapSizeActual = nMap; + } + + OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFd)); + return SQLITE_OK; +} +#endif /* SQLITE_MAX_MMAP_SIZE>0 */ + +/* +** If possible, return a pointer to a mapping of file fd starting at offset +** iOff. The mapping must be valid for at least nAmt bytes. +** +** If such a pointer can be obtained, store it in *pp and return SQLITE_OK. +** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK. +** Finally, if an error does occur, return an SQLite error code. The final +** value of *pp is undefined in this case. +** +** If this function does return a pointer, the caller must eventually +** release the reference by calling winUnfetch(). +*/ +static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ +#if SQLITE_MAX_MMAP_SIZE>0 + winFile *pFd = (winFile*)fd; /* The underlying database file */ +#endif + *pp = 0; + + OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n", + osGetCurrentProcessId(), fd, iOff, nAmt, pp)); + +#if SQLITE_MAX_MMAP_SIZE>0 + if( pFd->mmapSizeMax>0 ){ + if( pFd->pMapRegion==0 ){ + int rc = winMapfile(pFd, -1); + if( rc!=SQLITE_OK ){ + OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n", + osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); + return rc; + } + } + if( pFd->mmapSize >= iOff+nAmt ){ + *pp = &((u8 *)pFd->pMapRegion)[iOff]; + pFd->nFetchOut++; + } + } +#endif + + OSTRACE(("FETCH pid=%lu, pFile=%p, pp=%p, *pp=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), fd, pp, *pp)); + return SQLITE_OK; +} + +/* +** If the third argument is non-NULL, then this function releases a +** reference obtained by an earlier call to winFetch(). The second +** argument passed to this function must be the same as the corresponding +** argument that was passed to the winFetch() invocation. +** +** Or, if the third argument is NULL, then this function is being called +** to inform the VFS layer that, according to POSIX, any existing mapping +** may now be invalid and should be unmapped. +*/ +static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){ +#if SQLITE_MAX_MMAP_SIZE>0 + winFile *pFd = (winFile*)fd; /* The underlying database file */ + + /* If p==0 (unmap the entire file) then there must be no outstanding + ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference), + ** then there must be at least one outstanding. */ + assert( (p==0)==(pFd->nFetchOut==0) ); + + /* If p!=0, it must match the iOff value. */ + assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] ); + + OSTRACE(("UNFETCH pid=%lu, pFile=%p, offset=%lld, p=%p\n", + osGetCurrentProcessId(), pFd, iOff, p)); + + if( p ){ + pFd->nFetchOut--; + }else{ + /* FIXME: If Windows truly always prevents truncating or deleting a + ** file while a mapping is held, then the following winUnmapfile() call + ** is unnecessary can be omitted - potentially improving + ** performance. */ + winUnmapfile(pFd); + } + + assert( pFd->nFetchOut>=0 ); +#endif + + OSTRACE(("UNFETCH pid=%lu, pFile=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), fd)); + return SQLITE_OK; +} + +/* +** Here ends the implementation of all sqlite3_file methods. +** +********************** End sqlite3_file Methods ******************************* +******************************************************************************/ + +/* +** This vector defines all the methods that can operate on an +** sqlite3_file for win32. +*/ +static const sqlite3_io_methods winIoMethod = { + 3, /* iVersion */ + winClose, /* xClose */ + winRead, /* xRead */ + winWrite, /* xWrite */ + winTruncate, /* xTruncate */ + winSync, /* xSync */ + winFileSize, /* xFileSize */ + winLock, /* xLock */ + winUnlock, /* xUnlock */ + winCheckReservedLock, /* xCheckReservedLock */ + winFileControl, /* xFileControl */ + winSectorSize, /* xSectorSize */ + winDeviceCharacteristics, /* xDeviceCharacteristics */ + winShmMap, /* xShmMap */ + winShmLock, /* xShmLock */ + winShmBarrier, /* xShmBarrier */ + winShmUnmap, /* xShmUnmap */ + winFetch, /* xFetch */ + winUnfetch /* xUnfetch */ +}; + +/**************************************************************************** +**************************** sqlite3_vfs methods **************************** +** +** This division contains the implementation of methods on the +** sqlite3_vfs object. +*/ + +#if defined(__CYGWIN__) +/* +** Convert a filename from whatever the underlying operating system +** supports for filenames into UTF-8. Space to hold the result is +** obtained from malloc and must be freed by the calling function. +*/ +static char *winConvertToUtf8Filename(const void *zFilename){ + char *zConverted = 0; + if( osIsNT() ){ + zConverted = winUnicodeToUtf8(zFilename); + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + zConverted = sqlite3_win32_mbcs_to_utf8(zFilename); + } +#endif + /* caller will handle out of memory */ + return zConverted; +} +#endif + +/* +** Convert a UTF-8 filename into whatever form the underlying +** operating system wants filenames in. Space to hold the result +** is obtained from malloc and must be freed by the calling +** function. +*/ +static void *winConvertFromUtf8Filename(const char *zFilename){ + void *zConverted = 0; + if( osIsNT() ){ + zConverted = winUtf8ToUnicode(zFilename); + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + zConverted = sqlite3_win32_utf8_to_mbcs(zFilename); + } +#endif + /* caller will handle out of memory */ + return zConverted; +} + +/* +** This function returns non-zero if the specified UTF-8 string buffer +** ends with a directory separator character or one was successfully +** added to it. +*/ +static int winMakeEndInDirSep(int nBuf, char *zBuf){ + if( zBuf ){ + int nLen = sqlite3Strlen30(zBuf); + if( nLen>0 ){ + if( winIsDirSep(zBuf[nLen-1]) ){ + return 1; + }else if( nLen+1mxPathname; nBuf = nMax + 2; + zBuf = sqlite3MallocZero( nBuf ); + if( !zBuf ){ + OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); + return SQLITE_IOERR_NOMEM; + } + + /* Figure out the effective temporary directory. First, check if one + ** has been explicitly set by the application; otherwise, use the one + ** configured by the operating system. + */ + nDir = nMax - (nPre + 15); + assert( nDir>0 ); + if( sqlite3_temp_directory ){ + int nDirLen = sqlite3Strlen30(sqlite3_temp_directory); + if( nDirLen>0 ){ + if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){ + nDirLen++; + } + if( nDirLen>nDir ){ + sqlite3_free(zBuf); + OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); + return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0); + } + sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory); + } + } +#if defined(__CYGWIN__) + else{ + static const char *azDirs[] = { + 0, /* getenv("SQLITE_TMPDIR") */ + 0, /* getenv("TMPDIR") */ + 0, /* getenv("TMP") */ + 0, /* getenv("TEMP") */ + 0, /* getenv("USERPROFILE") */ + "/var/tmp", + "/usr/tmp", + "/tmp", + ".", + 0 /* List terminator */ + }; + unsigned int i; + const char *zDir = 0; + + if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR"); + if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR"); + if( !azDirs[2] ) azDirs[2] = getenv("TMP"); + if( !azDirs[3] ) azDirs[3] = getenv("TEMP"); + if( !azDirs[4] ) azDirs[4] = getenv("USERPROFILE"); + for(i=0; i/etilqs_XXXXXXXXXXXXXXX\0\0" + ** + ** If not, return SQLITE_ERROR. The number 17 is used here in order to + ** account for the space used by the 15 character random suffix and the + ** two trailing NUL characters. The final directory separator character + ** has already added if it was not already present. + */ + nLen = sqlite3Strlen30(zBuf); + if( (nLen + nPre + 17) > nBuf ){ + sqlite3_free(zBuf); + OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); + return winLogError(SQLITE_ERROR, 0, "winGetTempname5", 0); + } + + sqlite3_snprintf(nBuf-16-nLen, zBuf+nLen, SQLITE_TEMP_FILE_PREFIX); + + j = sqlite3Strlen30(zBuf); + sqlite3_randomness(15, &zBuf[j]); + for(i=0; i<15; i++, j++){ + zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; + } + zBuf[j] = 0; + zBuf[j+1] = 0; + *pzBuf = zBuf; + + OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf)); + return SQLITE_OK; +} + +/* +** Return TRUE if the named file is really a directory. Return false if +** it is something other than a directory, or if there is any kind of memory +** allocation failure. +*/ +static int winIsDir(const void *zConverted){ + DWORD attr; + int rc = 0; + DWORD lastErrno; + + if( osIsNT() ){ + int cnt = 0; + WIN32_FILE_ATTRIBUTE_DATA sAttrData; + memset(&sAttrData, 0, sizeof(sAttrData)); + while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted, + GetFileExInfoStandard, + &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){} + if( !rc ){ + return 0; /* Invalid name? */ + } + attr = sAttrData.dwFileAttributes; +#if SQLITE_OS_WINCE==0 + }else{ + attr = osGetFileAttributesA((char*)zConverted); +#endif + } + return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY); +} + +/* +** Open a file. +*/ +static int winOpen( + sqlite3_vfs *pVfs, /* Used to get maximum path name length */ + const char *zName, /* Name of the file (UTF-8) */ + sqlite3_file *id, /* Write the SQLite file handle here */ + int flags, /* Open mode flags */ + int *pOutFlags /* Status return flags */ +){ + HANDLE h; + DWORD lastErrno = 0; + DWORD dwDesiredAccess; + DWORD dwShareMode; + DWORD dwCreationDisposition; + DWORD dwFlagsAndAttributes = 0; +#if SQLITE_OS_WINCE + int isTemp = 0; +#endif + winFile *pFile = (winFile*)id; + void *zConverted; /* Filename in OS encoding */ + const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ + int cnt = 0; + + /* If argument zPath is a NULL pointer, this function is required to open + ** a temporary file. Use this buffer to store the file name in. + */ + char *zTmpname = 0; /* For temporary filename, if necessary. */ + + int rc = SQLITE_OK; /* Function Return Code */ +#if !defined(NDEBUG) || SQLITE_OS_WINCE + int eType = flags&0xFFFFFF00; /* Type of file to open */ +#endif + + int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); + int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); + int isCreate = (flags & SQLITE_OPEN_CREATE); + int isReadonly = (flags & SQLITE_OPEN_READONLY); + int isReadWrite = (flags & SQLITE_OPEN_READWRITE); + +#ifndef NDEBUG + int isOpenJournal = (isCreate && ( + eType==SQLITE_OPEN_MASTER_JOURNAL + || eType==SQLITE_OPEN_MAIN_JOURNAL + || eType==SQLITE_OPEN_WAL + )); +#endif + + OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n", + zUtf8Name, id, flags, pOutFlags)); + + /* Check the following statements are true: + ** + ** (a) Exactly one of the READWRITE and READONLY flags must be set, and + ** (b) if CREATE is set, then READWRITE must also be set, and + ** (c) if EXCLUSIVE is set, then CREATE must also be set. + ** (d) if DELETEONCLOSE is set, then CREATE must also be set. + */ + assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); + assert(isCreate==0 || isReadWrite); + assert(isExclusive==0 || isCreate); + assert(isDelete==0 || isCreate); + + /* The main DB, main journal, WAL file and master journal are never + ** automatically deleted. Nor are they ever temporary files. */ + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB ); + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL ); + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL ); + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); + + /* Assert that the upper layer has set one of the "file-type" flags. */ + assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB + || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL + || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL + || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL + ); + + assert( pFile!=0 ); + memset(pFile, 0, sizeof(winFile)); + pFile->h = INVALID_HANDLE_VALUE; + +#if SQLITE_OS_WINRT + if( !zUtf8Name && !sqlite3_temp_directory ){ + sqlite3_log(SQLITE_ERROR, + "sqlite3_temp_directory variable should be set for WinRT"); + } +#endif + + /* If the second argument to this function is NULL, generate a + ** temporary file name to use + */ + if( !zUtf8Name ){ + assert( isDelete && !isOpenJournal ); + rc = winGetTempname(pVfs, &zTmpname); + if( rc!=SQLITE_OK ){ + OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc))); + return rc; + } + zUtf8Name = zTmpname; + } + + /* Database filenames are double-zero terminated if they are not + ** URIs with parameters. Hence, they can always be passed into + ** sqlite3_uri_parameter(). + */ + assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) || + zUtf8Name[sqlite3Strlen30(zUtf8Name)+1]==0 ); + + /* Convert the filename to the system encoding. */ + zConverted = winConvertFromUtf8Filename(zUtf8Name); + if( zConverted==0 ){ + sqlite3_free(zTmpname); + OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name)); + return SQLITE_IOERR_NOMEM; + } + + if( winIsDir(zConverted) ){ + sqlite3_free(zConverted); + sqlite3_free(zTmpname); + OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name)); + return SQLITE_CANTOPEN_ISDIR; + } + + if( isReadWrite ){ + dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; + }else{ + dwDesiredAccess = GENERIC_READ; + } + + /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is + ** created. SQLite doesn't use it to indicate "exclusive access" + ** as it is usually understood. + */ + if( isExclusive ){ + /* Creates a new file, only if it does not already exist. */ + /* If the file exists, it fails. */ + dwCreationDisposition = CREATE_NEW; + }else if( isCreate ){ + /* Open existing file, or create if it doesn't exist */ + dwCreationDisposition = OPEN_ALWAYS; + }else{ + /* Opens a file, only if it exists. */ + dwCreationDisposition = OPEN_EXISTING; + } + + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + + if( isDelete ){ +#if SQLITE_OS_WINCE + dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN; + isTemp = 1; +#else + dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY + | FILE_ATTRIBUTE_HIDDEN + | FILE_FLAG_DELETE_ON_CLOSE; +#endif + }else{ + dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; + } + /* Reports from the internet are that performance is always + ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */ +#if SQLITE_OS_WINCE + dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; +#endif + + if( osIsNT() ){ +#if SQLITE_OS_WINRT + CREATEFILE2_EXTENDED_PARAMETERS extendedParameters; + extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); + extendedParameters.dwFileAttributes = + dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK; + extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK; + extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; + extendedParameters.lpSecurityAttributes = NULL; + extendedParameters.hTemplateFile = NULL; + while( (h = osCreateFile2((LPCWSTR)zConverted, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + &extendedParameters))==INVALID_HANDLE_VALUE && + winRetryIoerr(&cnt, &lastErrno) ){ + /* Noop */ + } +#else + while( (h = osCreateFileW((LPCWSTR)zConverted, + dwDesiredAccess, + dwShareMode, NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL))==INVALID_HANDLE_VALUE && + winRetryIoerr(&cnt, &lastErrno) ){ + /* Noop */ + } +#endif + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + while( (h = osCreateFileA((LPCSTR)zConverted, + dwDesiredAccess, + dwShareMode, NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL))==INVALID_HANDLE_VALUE && + winRetryIoerr(&cnt, &lastErrno) ){ + /* Noop */ + } + } +#endif + winLogIoerr(cnt, __LINE__); + + OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name, + dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); + + if( h==INVALID_HANDLE_VALUE ){ + pFile->lastErrno = lastErrno; + winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name); + sqlite3_free(zConverted); + sqlite3_free(zTmpname); + if( isReadWrite && !isExclusive ){ + return winOpen(pVfs, zName, id, + ((flags|SQLITE_OPEN_READONLY) & + ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), + pOutFlags); + }else{ + return SQLITE_CANTOPEN_BKPT; + } + } + + if( pOutFlags ){ + if( isReadWrite ){ + *pOutFlags = SQLITE_OPEN_READWRITE; + }else{ + *pOutFlags = SQLITE_OPEN_READONLY; + } + } + + OSTRACE(("OPEN file=%p, name=%s, access=%lx, pOutFlags=%p, *pOutFlags=%d, " + "rc=%s\n", h, zUtf8Name, dwDesiredAccess, pOutFlags, pOutFlags ? + *pOutFlags : 0, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); + +#if SQLITE_OS_WINCE + if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB + && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK + ){ + osCloseHandle(h); + sqlite3_free(zConverted); + sqlite3_free(zTmpname); + OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc))); + return rc; + } + if( isTemp ){ + pFile->zDeleteOnClose = zConverted; + }else +#endif + { + sqlite3_free(zConverted); + } + + sqlite3_free(zTmpname); + pFile->pMethod = &winIoMethod; + pFile->pVfs = pVfs; + pFile->h = h; + if( isReadonly ){ + pFile->ctrlFlags |= WINFILE_RDONLY; + } + if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){ + pFile->ctrlFlags |= WINFILE_PSOW; + } + pFile->lastErrno = NO_ERROR; + pFile->zPath = zName; +#if SQLITE_MAX_MMAP_SIZE>0 + pFile->hMap = NULL; + pFile->pMapRegion = 0; + pFile->mmapSize = 0; + pFile->mmapSizeActual = 0; + pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap; +#endif + + OpenCounter(+1); + return rc; +} + +/* +** Delete the named file. +** +** Note that Windows does not allow a file to be deleted if some other +** process has it open. Sometimes a virus scanner or indexing program +** will open a journal file shortly after it is created in order to do +** whatever it does. While this other process is holding the +** file open, we will be unable to delete it. To work around this +** problem, we delay 100 milliseconds and try to delete again. Up +** to MX_DELETION_ATTEMPTs deletion attempts are run before giving +** up and returning an error. +*/ +static int winDelete( + sqlite3_vfs *pVfs, /* Not used on win32 */ + const char *zFilename, /* Name of file to delete */ + int syncDir /* Not used on win32 */ +){ + int cnt = 0; + int rc; + DWORD attr; + DWORD lastErrno = 0; + void *zConverted; + UNUSED_PARAMETER(pVfs); + UNUSED_PARAMETER(syncDir); + + SimulateIOError(return SQLITE_IOERR_DELETE); + OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir)); + + zConverted = winConvertFromUtf8Filename(zFilename); + if( zConverted==0 ){ + OSTRACE(("DELETE name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename)); + return SQLITE_IOERR_NOMEM; + } + if( osIsNT() ){ + do { +#if SQLITE_OS_WINRT + WIN32_FILE_ATTRIBUTE_DATA sAttrData; + memset(&sAttrData, 0, sizeof(sAttrData)); + if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard, + &sAttrData) ){ + attr = sAttrData.dwFileAttributes; + }else{ + lastErrno = osGetLastError(); + if( lastErrno==ERROR_FILE_NOT_FOUND + || lastErrno==ERROR_PATH_NOT_FOUND ){ + rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ + }else{ + rc = SQLITE_ERROR; + } + break; + } +#else + attr = osGetFileAttributesW(zConverted); +#endif + if ( attr==INVALID_FILE_ATTRIBUTES ){ + lastErrno = osGetLastError(); + if( lastErrno==ERROR_FILE_NOT_FOUND + || lastErrno==ERROR_PATH_NOT_FOUND ){ + rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ + }else{ + rc = SQLITE_ERROR; + } + break; + } + if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ + rc = SQLITE_ERROR; /* Files only. */ + break; + } + if ( osDeleteFileW(zConverted) ){ + rc = SQLITE_OK; /* Deleted OK. */ + break; + } + if ( !winRetryIoerr(&cnt, &lastErrno) ){ + rc = SQLITE_ERROR; /* No more retries. */ + break; + } + } while(1); + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + do { + attr = osGetFileAttributesA(zConverted); + if ( attr==INVALID_FILE_ATTRIBUTES ){ + lastErrno = osGetLastError(); + if( lastErrno==ERROR_FILE_NOT_FOUND + || lastErrno==ERROR_PATH_NOT_FOUND ){ + rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ + }else{ + rc = SQLITE_ERROR; + } + break; + } + if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ + rc = SQLITE_ERROR; /* Files only. */ + break; + } + if ( osDeleteFileA(zConverted) ){ + rc = SQLITE_OK; /* Deleted OK. */ + break; + } + if ( !winRetryIoerr(&cnt, &lastErrno) ){ + rc = SQLITE_ERROR; /* No more retries. */ + break; + } + } while(1); + } +#endif + if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){ + rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename); + }else{ + winLogIoerr(cnt, __LINE__); + } + sqlite3_free(zConverted); + OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc))); + return rc; +} + +/* +** Check the existence and status of a file. +*/ +static int winAccess( + sqlite3_vfs *pVfs, /* Not used on win32 */ + const char *zFilename, /* Name of file to check */ + int flags, /* Type of test to make on this file */ + int *pResOut /* OUT: Result */ +){ + DWORD attr; + int rc = 0; + DWORD lastErrno = 0; + void *zConverted; + UNUSED_PARAMETER(pVfs); + + SimulateIOError( return SQLITE_IOERR_ACCESS; ); + OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n", + zFilename, flags, pResOut)); + + zConverted = winConvertFromUtf8Filename(zFilename); + if( zConverted==0 ){ + OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename)); + return SQLITE_IOERR_NOMEM; + } + if( osIsNT() ){ + int cnt = 0; + WIN32_FILE_ATTRIBUTE_DATA sAttrData; + memset(&sAttrData, 0, sizeof(sAttrData)); + while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted, + GetFileExInfoStandard, + &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){} + if( rc ){ + /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file + ** as if it does not exist. + */ + if( flags==SQLITE_ACCESS_EXISTS + && sAttrData.nFileSizeHigh==0 + && sAttrData.nFileSizeLow==0 ){ + attr = INVALID_FILE_ATTRIBUTES; + }else{ + attr = sAttrData.dwFileAttributes; + } + }else{ + winLogIoerr(cnt, __LINE__); + if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){ + sqlite3_free(zConverted); + return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", + zFilename); + }else{ + attr = INVALID_FILE_ATTRIBUTES; + } + } + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + attr = osGetFileAttributesA((char*)zConverted); + } +#endif + sqlite3_free(zConverted); + switch( flags ){ + case SQLITE_ACCESS_READ: + case SQLITE_ACCESS_EXISTS: + rc = attr!=INVALID_FILE_ATTRIBUTES; + break; + case SQLITE_ACCESS_READWRITE: + rc = attr!=INVALID_FILE_ATTRIBUTES && + (attr & FILE_ATTRIBUTE_READONLY)==0; + break; + default: + assert(!"Invalid flags argument"); + } + *pResOut = rc; + OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n", + zFilename, pResOut, *pResOut)); + return SQLITE_OK; +} + +/* +** Returns non-zero if the specified path name starts with a drive letter +** followed by a colon character. +*/ +static BOOL winIsDriveLetterAndColon( + const char *zPathname +){ + return ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ); +} + +/* +** Returns non-zero if the specified path name should be used verbatim. If +** non-zero is returned from this function, the calling function must simply +** use the provided path name verbatim -OR- resolve it into a full path name +** using the GetFullPathName Win32 API function (if available). +*/ +static BOOL winIsVerbatimPathname( + const char *zPathname +){ + /* + ** If the path name starts with a forward slash or a backslash, it is either + ** a legal UNC name, a volume relative path, or an absolute path name in the + ** "Unix" format on Windows. There is no easy way to differentiate between + ** the final two cases; therefore, we return the safer return value of TRUE + ** so that callers of this function will simply use it verbatim. + */ + if ( winIsDirSep(zPathname[0]) ){ + return TRUE; + } + + /* + ** If the path name starts with a letter and a colon it is either a volume + ** relative path or an absolute path. Callers of this function must not + ** attempt to treat it as a relative path name (i.e. they should simply use + ** it verbatim). + */ + if ( winIsDriveLetterAndColon(zPathname) ){ + return TRUE; + } + + /* + ** If we get to this point, the path name should almost certainly be a purely + ** relative one (i.e. not a UNC name, not absolute, and not volume relative). + */ + return FALSE; +} + +/* +** Turn a relative pathname into a full pathname. Write the full +** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname +** bytes in size. +*/ +static int winFullPathname( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + const char *zRelative, /* Possibly relative input path */ + int nFull, /* Size of output buffer in bytes */ + char *zFull /* Output buffer */ +){ + +#if defined(__CYGWIN__) + SimulateIOError( return SQLITE_ERROR ); + UNUSED_PARAMETER(nFull); + assert( nFull>=pVfs->mxPathname ); + if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ + /* + ** NOTE: We are dealing with a relative path name and the data + ** directory has been set. Therefore, use it as the basis + ** for converting the relative path name to an absolute + ** one by prepending the data directory and a slash. + */ + char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 ); + if( !zOut ){ + return SQLITE_IOERR_NOMEM; + } + if( cygwin_conv_path( + (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A) | + CCP_RELATIVE, zRelative, zOut, pVfs->mxPathname+1)<0 ){ + sqlite3_free(zOut); + return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno, + "winFullPathname1", zRelative); + }else{ + char *zUtf8 = winConvertToUtf8Filename(zOut); + if( !zUtf8 ){ + sqlite3_free(zOut); + return SQLITE_IOERR_NOMEM; + } + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s", + sqlite3_data_directory, winGetDirSep(), zUtf8); + sqlite3_free(zUtf8); + sqlite3_free(zOut); + } + }else{ + char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 ); + if( !zOut ){ + return SQLITE_IOERR_NOMEM; + } + if( cygwin_conv_path( + (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A), + zRelative, zOut, pVfs->mxPathname+1)<0 ){ + sqlite3_free(zOut); + return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno, + "winFullPathname2", zRelative); + }else{ + char *zUtf8 = winConvertToUtf8Filename(zOut); + if( !zUtf8 ){ + sqlite3_free(zOut); + return SQLITE_IOERR_NOMEM; + } + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8); + sqlite3_free(zUtf8); + sqlite3_free(zOut); + } + } + return SQLITE_OK; +#endif + +#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__) + SimulateIOError( return SQLITE_ERROR ); + /* WinCE has no concept of a relative pathname, or so I am told. */ + /* WinRT has no way to convert a relative path to an absolute one. */ + if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ + /* + ** NOTE: We are dealing with a relative path name and the data + ** directory has been set. Therefore, use it as the basis + ** for converting the relative path name to an absolute + ** one by prepending the data directory and a backslash. + */ + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s", + sqlite3_data_directory, winGetDirSep(), zRelative); + }else{ + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative); + } + return SQLITE_OK; +#endif + +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__) + DWORD nByte; + void *zConverted; + char *zOut; + + /* If this path name begins with "/X:", where "X" is any alphabetic + ** character, discard the initial "/" from the pathname. + */ + if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){ + zRelative++; + } + + /* It's odd to simulate an io-error here, but really this is just + ** using the io-error infrastructure to test that SQLite handles this + ** function failing. This function could fail if, for example, the + ** current working directory has been unlinked. + */ + SimulateIOError( return SQLITE_ERROR ); + if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ + /* + ** NOTE: We are dealing with a relative path name and the data + ** directory has been set. Therefore, use it as the basis + ** for converting the relative path name to an absolute + ** one by prepending the data directory and a backslash. + */ + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s", + sqlite3_data_directory, winGetDirSep(), zRelative); + return SQLITE_OK; + } + zConverted = winConvertFromUtf8Filename(zRelative); + if( zConverted==0 ){ + return SQLITE_IOERR_NOMEM; + } + if( osIsNT() ){ + LPWSTR zTemp; + nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0); + if( nByte==0 ){ + sqlite3_free(zConverted); + return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), + "winFullPathname1", zRelative); + } + nByte += 3; + zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); + if( zTemp==0 ){ + sqlite3_free(zConverted); + return SQLITE_IOERR_NOMEM; + } + nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0); + if( nByte==0 ){ + sqlite3_free(zConverted); + sqlite3_free(zTemp); + return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), + "winFullPathname2", zRelative); + } + sqlite3_free(zConverted); + zOut = winUnicodeToUtf8(zTemp); + sqlite3_free(zTemp); + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + char *zTemp; + nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0); + if( nByte==0 ){ + sqlite3_free(zConverted); + return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), + "winFullPathname3", zRelative); + } + nByte += 3; + zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); + if( zTemp==0 ){ + sqlite3_free(zConverted); + return SQLITE_IOERR_NOMEM; + } + nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0); + if( nByte==0 ){ + sqlite3_free(zConverted); + sqlite3_free(zTemp); + return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), + "winFullPathname4", zRelative); + } + sqlite3_free(zConverted); + zOut = sqlite3_win32_mbcs_to_utf8(zTemp); + sqlite3_free(zTemp); + } +#endif + if( zOut ){ + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut); + sqlite3_free(zOut); + return SQLITE_OK; + }else{ + return SQLITE_IOERR_NOMEM; + } +#endif +} + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ + HANDLE h; +#if defined(__CYGWIN__) + int nFull = pVfs->mxPathname+1; + char *zFull = sqlite3MallocZero( nFull ); + void *zConverted = 0; + if( zFull==0 ){ + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); + return 0; + } + if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){ + sqlite3_free(zFull); + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); + return 0; + } + zConverted = winConvertFromUtf8Filename(zFull); + sqlite3_free(zFull); +#else + void *zConverted = winConvertFromUtf8Filename(zFilename); + UNUSED_PARAMETER(pVfs); +#endif + if( zConverted==0 ){ + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); + return 0; + } + if( osIsNT() ){ +#if SQLITE_OS_WINRT + h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0); +#else + h = osLoadLibraryW((LPCWSTR)zConverted); +#endif + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + h = osLoadLibraryA((char*)zConverted); + } +#endif + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)h)); + sqlite3_free(zConverted); + return (void*)h; +} +static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ + UNUSED_PARAMETER(pVfs); + winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut); +} +static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){ + FARPROC proc; + UNUSED_PARAMETER(pVfs); + proc = osGetProcAddressA((HANDLE)pH, zSym); + OSTRACE(("DLSYM handle=%p, symbol=%s, address=%p\n", + (void*)pH, zSym, (void*)proc)); + return (void(*)(void))proc; +} +static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ + UNUSED_PARAMETER(pVfs); + osFreeLibrary((HANDLE)pHandle); + OSTRACE(("DLCLOSE handle=%p\n", (void*)pHandle)); +} +#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ + #define winDlOpen 0 + #define winDlError 0 + #define winDlSym 0 + #define winDlClose 0 +#endif + + +/* +** Write up to nBuf bytes of randomness into zBuf. +*/ +static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ + int n = 0; + UNUSED_PARAMETER(pVfs); +#if defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) + n = nBuf; + memset(zBuf, 0, nBuf); +#else + if( sizeof(SYSTEMTIME)<=nBuf-n ){ + SYSTEMTIME x; + osGetSystemTime(&x); + memcpy(&zBuf[n], &x, sizeof(x)); + n += sizeof(x); + } + if( sizeof(DWORD)<=nBuf-n ){ + DWORD pid = osGetCurrentProcessId(); + memcpy(&zBuf[n], &pid, sizeof(pid)); + n += sizeof(pid); + } +#if SQLITE_OS_WINRT + if( sizeof(ULONGLONG)<=nBuf-n ){ + ULONGLONG cnt = osGetTickCount64(); + memcpy(&zBuf[n], &cnt, sizeof(cnt)); + n += sizeof(cnt); + } +#else + if( sizeof(DWORD)<=nBuf-n ){ + DWORD cnt = osGetTickCount(); + memcpy(&zBuf[n], &cnt, sizeof(cnt)); + n += sizeof(cnt); + } +#endif + if( sizeof(LARGE_INTEGER)<=nBuf-n ){ + LARGE_INTEGER i; + osQueryPerformanceCounter(&i); + memcpy(&zBuf[n], &i, sizeof(i)); + n += sizeof(i); + } +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID + if( sizeof(UUID)<=nBuf-n ){ + UUID id; + memset(&id, 0, sizeof(UUID)); + osUuidCreate(&id); + memcpy(&zBuf[n], &id, sizeof(UUID)); + n += sizeof(UUID); + } + if( sizeof(UUID)<=nBuf-n ){ + UUID id; + memset(&id, 0, sizeof(UUID)); + osUuidCreateSequential(&id); + memcpy(&zBuf[n], &id, sizeof(UUID)); + n += sizeof(UUID); + } +#endif +#endif /* defined(SQLITE_TEST) || defined(SQLITE_ZERO_PRNG_SEED) */ + return n; +} + + +/* +** Sleep for a little while. Return the amount of time slept. +*/ +static int winSleep(sqlite3_vfs *pVfs, int microsec){ + sqlite3_win32_sleep((microsec+999)/1000); + UNUSED_PARAMETER(pVfs); + return ((microsec+999)/1000)*1000; +} + +/* +** The following variable, if set to a non-zero value, is interpreted as +** the number of seconds since 1970 and is used to set the result of +** sqlite3OsCurrentTime() during testing. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */ +#endif + +/* +** Find the current time (in Universal Coordinated Time). Write into *piNow +** the current time and date as a Julian Day number times 86_400_000. In +** other words, write into *piNow the number of milliseconds since the Julian +** epoch of noon in Greenwich on November 24, 4714 B.C according to the +** proleptic Gregorian calendar. +** +** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date +** cannot be found. +*/ +static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){ + /* FILETIME structure is a 64-bit value representing the number of + 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). + */ + FILETIME ft; + static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000; +#ifdef SQLITE_TEST + static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; +#endif + /* 2^32 - to avoid use of LL and warnings in gcc */ + static const sqlite3_int64 max32BitValue = + (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + + (sqlite3_int64)294967296; + +#if SQLITE_OS_WINCE + SYSTEMTIME time; + osGetSystemTime(&time); + /* if SystemTimeToFileTime() fails, it returns zero. */ + if (!osSystemTimeToFileTime(&time,&ft)){ + return SQLITE_ERROR; + } +#else + osGetSystemTimeAsFileTime( &ft ); +#endif + + *piNow = winFiletimeEpoch + + ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + + (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000; + +#ifdef SQLITE_TEST + if( sqlite3_current_time ){ + *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch; + } +#endif + UNUSED_PARAMETER(pVfs); + return SQLITE_OK; +} + +/* +** Find the current time (in Universal Coordinated Time). Write the +** current time and date as a Julian Day number into *prNow and +** return 0. Return 1 if the time and date cannot be found. +*/ +static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){ + int rc; + sqlite3_int64 i; + rc = winCurrentTimeInt64(pVfs, &i); + if( !rc ){ + *prNow = i/86400000.0; + } + return rc; +} + +/* +** The idea is that this function works like a combination of +** GetLastError() and FormatMessage() on Windows (or errno and +** strerror_r() on Unix). After an error is returned by an OS +** function, SQLite calls this function with zBuf pointing to +** a buffer of nBuf bytes. The OS layer should populate the +** buffer with a nul-terminated UTF-8 encoded error message +** describing the last IO error to have occurred within the calling +** thread. +** +** If the error message is too large for the supplied buffer, +** it should be truncated. The return value of xGetLastError +** is zero if the error message fits in the buffer, or non-zero +** otherwise (if the message was truncated). If non-zero is returned, +** then it is not necessary to include the nul-terminator character +** in the output buffer. +** +** Not supplying an error message will have no adverse effect +** on SQLite. It is fine to have an implementation that never +** returns an error message: +** +** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ +** assert(zBuf[0]=='\0'); +** return 0; +** } +** +** However if an error message is supplied, it will be incorporated +** by sqlite into the error message available to the user using +** sqlite3_errmsg(), possibly making IO errors easier to debug. +*/ +static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ + UNUSED_PARAMETER(pVfs); + return winGetLastErrorMsg(osGetLastError(), nBuf, zBuf); +} + +/* +** Initialize and deinitialize the operating system interface. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ + static sqlite3_vfs winVfs = { + 3, /* iVersion */ + sizeof(winFile), /* szOsFile */ + SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */ + 0, /* pNext */ + "win32", /* zName */ + 0, /* pAppData */ + winOpen, /* xOpen */ + winDelete, /* xDelete */ + winAccess, /* xAccess */ + winFullPathname, /* xFullPathname */ + winDlOpen, /* xDlOpen */ + winDlError, /* xDlError */ + winDlSym, /* xDlSym */ + winDlClose, /* xDlClose */ + winRandomness, /* xRandomness */ + winSleep, /* xSleep */ + winCurrentTime, /* xCurrentTime */ + winGetLastError, /* xGetLastError */ + winCurrentTimeInt64, /* xCurrentTimeInt64 */ + winSetSystemCall, /* xSetSystemCall */ + winGetSystemCall, /* xGetSystemCall */ + winNextSystemCall, /* xNextSystemCall */ + }; +#if defined(SQLITE_WIN32_HAS_WIDE) + static sqlite3_vfs winLongPathVfs = { + 3, /* iVersion */ + sizeof(winFile), /* szOsFile */ + SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */ + 0, /* pNext */ + "win32-longpath", /* zName */ + 0, /* pAppData */ + winOpen, /* xOpen */ + winDelete, /* xDelete */ + winAccess, /* xAccess */ + winFullPathname, /* xFullPathname */ + winDlOpen, /* xDlOpen */ + winDlError, /* xDlError */ + winDlSym, /* xDlSym */ + winDlClose, /* xDlClose */ + winRandomness, /* xRandomness */ + winSleep, /* xSleep */ + winCurrentTime, /* xCurrentTime */ + winGetLastError, /* xGetLastError */ + winCurrentTimeInt64, /* xCurrentTimeInt64 */ + winSetSystemCall, /* xSetSystemCall */ + winGetSystemCall, /* xGetSystemCall */ + winNextSystemCall, /* xNextSystemCall */ + }; +#endif + + /* Double-check that the aSyscall[] array has been constructed + ** correctly. See ticket [bb3a86e890c8e96ab] */ + assert( ArraySize(aSyscall)==80 ); + + /* get memory map allocation granularity */ + memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); +#if SQLITE_OS_WINRT + osGetNativeSystemInfo(&winSysInfo); +#else + osGetSystemInfo(&winSysInfo); +#endif + assert( winSysInfo.dwAllocationGranularity>0 ); + assert( winSysInfo.dwPageSize>0 ); + + sqlite3_vfs_register(&winVfs, 1); + +#if defined(SQLITE_WIN32_HAS_WIDE) + sqlite3_vfs_register(&winLongPathVfs, 0); +#endif + + return SQLITE_OK; +} + +SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ +#if SQLITE_OS_WINRT + if( sleepObj!=NULL ){ + osCloseHandle(sleepObj); + sleepObj = NULL; + } +#endif + return SQLITE_OK; +} + +#endif /* SQLITE_OS_WIN */ + +/************** End of os_win.c **********************************************/ +/************** Begin file bitvec.c ******************************************/ +/* +** 2008 February 16 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file implements an object that represents a fixed-length +** bitmap. Bits are numbered starting with 1. +** +** A bitmap is used to record which pages of a database file have been +** journalled during a transaction, or which pages have the "dont-write" +** property. Usually only a few pages are meet either condition. +** So the bitmap is usually sparse and has low cardinality. +** But sometimes (for example when during a DROP of a large table) most +** or all of the pages in a database can get journalled. In those cases, +** the bitmap becomes dense with high cardinality. The algorithm needs +** to handle both cases well. +** +** The size of the bitmap is fixed when the object is created. +** +** All bits are clear when the bitmap is created. Individual bits +** may be set or cleared one at a time. +** +** Test operations are about 100 times more common that set operations. +** Clear operations are exceedingly rare. There are usually between +** 5 and 500 set operations per Bitvec object, though the number of sets can +** sometimes grow into tens of thousands or larger. The size of the +** Bitvec object is the number of pages in the database file at the +** start of a transaction, and is thus usually less than a few thousand, +** but can be as large as 2 billion for a really big database. +*/ +/* #include "sqliteInt.h" */ + +/* Size of the Bitvec structure in bytes. */ +#define BITVEC_SZ 512 + +/* Round the union size down to the nearest pointer boundary, since that's how +** it will be aligned within the Bitvec struct. */ +#define BITVEC_USIZE (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*)) + +/* Type of the array "element" for the bitmap representation. +** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE. +** Setting this to the "natural word" size of your CPU may improve +** performance. */ +#define BITVEC_TELEM u8 +/* Size, in bits, of the bitmap element. */ +#define BITVEC_SZELEM 8 +/* Number of elements in a bitmap array. */ +#define BITVEC_NELEM (BITVEC_USIZE/sizeof(BITVEC_TELEM)) +/* Number of bits in the bitmap array. */ +#define BITVEC_NBIT (BITVEC_NELEM*BITVEC_SZELEM) + +/* Number of u32 values in hash table. */ +#define BITVEC_NINT (BITVEC_USIZE/sizeof(u32)) +/* Maximum number of entries in hash table before +** sub-dividing and re-hashing. */ +#define BITVEC_MXHASH (BITVEC_NINT/2) +/* Hashing function for the aHash representation. +** Empirical testing showed that the *37 multiplier +** (an arbitrary prime)in the hash function provided +** no fewer collisions than the no-op *1. */ +#define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT) + +#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *)) + + +/* +** A bitmap is an instance of the following structure. +** +** This bitmap records the existence of zero or more bits +** with values between 1 and iSize, inclusive. +** +** There are three possible representations of the bitmap. +** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight +** bitmap. The least significant bit is bit 1. +** +** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is +** a hash table that will hold up to BITVEC_MXHASH distinct values. +** +** Otherwise, the value i is redirected into one of BITVEC_NPTR +** sub-bitmaps pointed to by Bitvec.u.apSub[]. Each subbitmap +** handles up to iDivisor separate values of i. apSub[0] holds +** values between 1 and iDivisor. apSub[1] holds values between +** iDivisor+1 and 2*iDivisor. apSub[N] holds values between +** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized +** to hold deal with values between 1 and iDivisor. +*/ +struct Bitvec { + u32 iSize; /* Maximum bit index. Max iSize is 4,294,967,296. */ + u32 nSet; /* Number of bits that are set - only valid for aHash + ** element. Max is BITVEC_NINT. For BITVEC_SZ of 512, + ** this would be 125. */ + u32 iDivisor; /* Number of bits handled by each apSub[] entry. */ + /* Should >=0 for apSub element. */ + /* Max iDivisor is max(u32) / BITVEC_NPTR + 1. */ + /* For a BITVEC_SZ of 512, this would be 34,359,739. */ + union { + BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* Bitmap representation */ + u32 aHash[BITVEC_NINT]; /* Hash table representation */ + Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */ + } u; +}; + +/* +** Create a new bitmap object able to handle bits between 0 and iSize, +** inclusive. Return a pointer to the new object. Return NULL if +** malloc fails. +*/ +SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){ + Bitvec *p; + assert( sizeof(*p)==BITVEC_SZ ); + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ + p->iSize = iSize; + } + return p; +} + +/* +** Check to see if the i-th bit is set. Return true or false. +** If p is NULL (if the bitmap has not been created) or if +** i is out of range, then return false. +*/ +SQLITE_PRIVATE int sqlite3BitvecTestNotNull(Bitvec *p, u32 i){ + assert( p!=0 ); + i--; + if( i>=p->iSize ) return 0; + while( p->iDivisor ){ + u32 bin = i/p->iDivisor; + i = i%p->iDivisor; + p = p->u.apSub[bin]; + if (!p) { + return 0; + } + } + if( p->iSize<=BITVEC_NBIT ){ + return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0; + } else{ + u32 h = BITVEC_HASH(i++); + while( p->u.aHash[h] ){ + if( p->u.aHash[h]==i ) return 1; + h = (h+1) % BITVEC_NINT; + } + return 0; + } +} +SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){ + return p!=0 && sqlite3BitvecTestNotNull(p,i); +} + +/* +** Set the i-th bit. Return 0 on success and an error code if +** anything goes wrong. +** +** This routine might cause sub-bitmaps to be allocated. Failing +** to get the memory needed to hold the sub-bitmap is the only +** that can go wrong with an insert, assuming p and i are valid. +** +** The calling function must ensure that p is a valid Bitvec object +** and that the value for "i" is within range of the Bitvec object. +** Otherwise the behavior is undefined. +*/ +SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){ + u32 h; + if( p==0 ) return SQLITE_OK; + assert( i>0 ); + assert( i<=p->iSize ); + i--; + while((p->iSize > BITVEC_NBIT) && p->iDivisor) { + u32 bin = i/p->iDivisor; + i = i%p->iDivisor; + if( p->u.apSub[bin]==0 ){ + p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor ); + if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM; + } + p = p->u.apSub[bin]; + } + if( p->iSize<=BITVEC_NBIT ){ + p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1)); + return SQLITE_OK; + } + h = BITVEC_HASH(i++); + /* if there wasn't a hash collision, and this doesn't */ + /* completely fill the hash, then just add it without */ + /* worring about sub-dividing and re-hashing. */ + if( !p->u.aHash[h] ){ + if (p->nSet<(BITVEC_NINT-1)) { + goto bitvec_set_end; + } else { + goto bitvec_set_rehash; + } + } + /* there was a collision, check to see if it's already */ + /* in hash, if not, try to find a spot for it */ + do { + if( p->u.aHash[h]==i ) return SQLITE_OK; + h++; + if( h>=BITVEC_NINT ) h = 0; + } while( p->u.aHash[h] ); + /* we didn't find it in the hash. h points to the first */ + /* available free spot. check to see if this is going to */ + /* make our hash too "full". */ +bitvec_set_rehash: + if( p->nSet>=BITVEC_MXHASH ){ + unsigned int j; + int rc; + u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash)); + if( aiValues==0 ){ + return SQLITE_NOMEM; + }else{ + memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash)); + memset(p->u.apSub, 0, sizeof(p->u.apSub)); + p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR; + rc = sqlite3BitvecSet(p, i); + for(j=0; jnSet++; + p->u.aHash[h] = i; + return SQLITE_OK; +} + +/* +** Clear the i-th bit. +** +** pBuf must be a pointer to at least BITVEC_SZ bytes of temporary storage +** that BitvecClear can use to rebuilt its hash table. +*/ +SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){ + if( p==0 ) return; + assert( i>0 ); + i--; + while( p->iDivisor ){ + u32 bin = i/p->iDivisor; + i = i%p->iDivisor; + p = p->u.apSub[bin]; + if (!p) { + return; + } + } + if( p->iSize<=BITVEC_NBIT ){ + p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1))); + }else{ + unsigned int j; + u32 *aiValues = pBuf; + memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash)); + memset(p->u.aHash, 0, sizeof(p->u.aHash)); + p->nSet = 0; + for(j=0; jnSet++; + while( p->u.aHash[h] ){ + h++; + if( h>=BITVEC_NINT ) h = 0; + } + p->u.aHash[h] = aiValues[j]; + } + } + } +} + +/* +** Destroy a bitmap object. Reclaim all memory used. +*/ +SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){ + if( p==0 ) return; + if( p->iDivisor ){ + unsigned int i; + for(i=0; iu.apSub[i]); + } + } + sqlite3_free(p); +} + +/* +** Return the value of the iSize parameter specified when Bitvec *p +** was created. +*/ +SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){ + return p->iSize; +} + +#ifndef SQLITE_OMIT_BUILTIN_TEST +/* +** Let V[] be an array of unsigned characters sufficient to hold +** up to N bits. Let I be an integer between 0 and N. 0<=I>3] |= (1<<(I&7)) +#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7)) +#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0 + +/* +** This routine runs an extensive test of the Bitvec code. +** +** The input is an array of integers that acts as a program +** to test the Bitvec. The integers are opcodes followed +** by 0, 1, or 3 operands, depending on the opcode. Another +** opcode follows immediately after the last operand. +** +** There are 6 opcodes numbered from 0 through 5. 0 is the +** "halt" opcode and causes the test to end. +** +** 0 Halt and return the number of errors +** 1 N S X Set N bits beginning with S and incrementing by X +** 2 N S X Clear N bits beginning with S and incrementing by X +** 3 N Set N randomly chosen bits +** 4 N Clear N randomly chosen bits +** 5 N S X Set N bits from S increment X in array only, not in bitvec +** +** The opcodes 1 through 4 perform set and clear operations are performed +** on both a Bitvec object and on a linear array of bits obtained from malloc. +** Opcode 5 works on the linear array only, not on the Bitvec. +** Opcode 5 is used to deliberately induce a fault in order to +** confirm that error detection works. +** +** At the conclusion of the test the linear array is compared +** against the Bitvec object. If there are any differences, +** an error is returned. If they are the same, zero is returned. +** +** If a memory allocation error occurs, return -1. +*/ +SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ + Bitvec *pBitvec = 0; + unsigned char *pV = 0; + int rc = -1; + int i, nx, pc, op; + void *pTmpSpace; + + /* Allocate the Bitvec to be tested and a linear array of + ** bits to act as the reference */ + pBitvec = sqlite3BitvecCreate( sz ); + pV = sqlite3MallocZero( (sz+7)/8 + 1 ); + pTmpSpace = sqlite3_malloc64(BITVEC_SZ); + if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end; + + /* NULL pBitvec tests */ + sqlite3BitvecSet(0, 1); + sqlite3BitvecClear(0, 1, pTmpSpace); + + /* Run the program */ + pc = 0; + while( (op = aOp[pc])!=0 ){ + switch( op ){ + case 1: + case 2: + case 5: { + nx = 4; + i = aOp[pc+2] - 1; + aOp[pc+2] += aOp[pc+3]; + break; + } + case 3: + case 4: + default: { + nx = 2; + sqlite3_randomness(sizeof(i), &i); + break; + } + } + if( (--aOp[pc+1]) > 0 ) nx = 0; + pc += nx; + i = (i & 0x7fffffff)%sz; + if( (op & 1)!=0 ){ + SETBIT(pV, (i+1)); + if( op!=5 ){ + if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end; + } + }else{ + CLEARBIT(pV, (i+1)); + sqlite3BitvecClear(pBitvec, i+1, pTmpSpace); + } + } + + /* Test to make sure the linear array exactly matches the + ** Bitvec object. Start with the assumption that they do + ** match (rc==0). Change rc to non-zero if a discrepancy + ** is found. + */ + rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1) + + sqlite3BitvecTest(pBitvec, 0) + + (sqlite3BitvecSize(pBitvec) - sz); + for(i=1; i<=sz; i++){ + if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){ + rc = i; + break; + } + } + + /* Free allocated structure */ +bitvec_end: + sqlite3_free(pTmpSpace); + sqlite3_free(pV); + sqlite3BitvecDestroy(pBitvec); + return rc; +} +#endif /* SQLITE_OMIT_BUILTIN_TEST */ + +/************** End of bitvec.c **********************************************/ +/************** Begin file pcache.c ******************************************/ +/* +** 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 file implements that page cache. +*/ +/* #include "sqliteInt.h" */ + +/* +** A complete page cache is an instance of this structure. +*/ +struct PCache { + PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ + PgHdr *pSynced; /* Last synced page in dirty page list */ + int nRef; /* Number of referenced pages */ + int szCache; /* Configured cache size */ + int szPage; /* Size of every page in this cache */ + int szExtra; /* Size of extra space for each page */ + u8 bPurgeable; /* True if pages are on backing store */ + u8 eCreate; /* eCreate value for for xFetch() */ + int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */ + void *pStress; /* Argument to xStress */ + sqlite3_pcache *pCache; /* Pluggable cache module */ +}; + +/********************************** Linked List Management ********************/ + +/* Allowed values for second argument to pcacheManageDirtyList() */ +#define PCACHE_DIRTYLIST_REMOVE 1 /* Remove pPage from dirty list */ +#define PCACHE_DIRTYLIST_ADD 2 /* Add pPage to the dirty list */ +#define PCACHE_DIRTYLIST_FRONT 3 /* Move pPage to the front of the list */ + +/* +** Manage pPage's participation on the dirty list. Bits of the addRemove +** argument determines what operation to do. The 0x01 bit means first +** remove pPage from the dirty list. The 0x02 means add pPage back to +** the dirty list. Doing both moves pPage to the front of the dirty list. +*/ +static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){ + PCache *p = pPage->pCache; + + if( addRemove & PCACHE_DIRTYLIST_REMOVE ){ + assert( pPage->pDirtyNext || pPage==p->pDirtyTail ); + assert( pPage->pDirtyPrev || pPage==p->pDirty ); + + /* Update the PCache1.pSynced variable if necessary. */ + if( p->pSynced==pPage ){ + PgHdr *pSynced = pPage->pDirtyPrev; + while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){ + pSynced = pSynced->pDirtyPrev; + } + p->pSynced = pSynced; + } + + if( pPage->pDirtyNext ){ + pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev; + }else{ + assert( pPage==p->pDirtyTail ); + p->pDirtyTail = pPage->pDirtyPrev; + } + if( pPage->pDirtyPrev ){ + pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext; + }else{ + assert( pPage==p->pDirty ); + p->pDirty = pPage->pDirtyNext; + if( p->pDirty==0 && p->bPurgeable ){ + assert( p->eCreate==1 ); + p->eCreate = 2; + } + } + pPage->pDirtyNext = 0; + pPage->pDirtyPrev = 0; + } + if( addRemove & PCACHE_DIRTYLIST_ADD ){ + assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage ); + + pPage->pDirtyNext = p->pDirty; + if( pPage->pDirtyNext ){ + assert( pPage->pDirtyNext->pDirtyPrev==0 ); + pPage->pDirtyNext->pDirtyPrev = pPage; + }else{ + p->pDirtyTail = pPage; + if( p->bPurgeable ){ + assert( p->eCreate==2 ); + p->eCreate = 1; + } + } + p->pDirty = pPage; + if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){ + p->pSynced = pPage; + } + } +} + +/* +** Wrapper around the pluggable caches xUnpin method. If the cache is +** being used for an in-memory database, this function is a no-op. +*/ +static void pcacheUnpin(PgHdr *p){ + if( p->pCache->bPurgeable ){ + sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0); + } +} + +/* +** Compute the number of pages of cache requested. p->szCache is the +** cache size requested by the "PRAGMA cache_size" statement. +** +** +*/ +static int numberOfCachePages(PCache *p){ + if( p->szCache>=0 ){ + /* IMPLEMENTATION-OF: R-42059-47211 If the argument N is positive then the + ** suggested cache size is set to N. */ + return p->szCache; + }else{ + /* IMPLEMENTATION-OF: R-61436-13639 If the argument N is negative, then + ** the number of cache pages is adjusted to use approximately abs(N*1024) + ** bytes of memory. */ + return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra)); + } +} + +/*************************************************** General Interfaces ****** +** +** Initialize and shutdown the page cache subsystem. Neither of these +** functions are threadsafe. +*/ +SQLITE_PRIVATE int sqlite3PcacheInitialize(void){ + if( sqlite3GlobalConfig.pcache2.xInit==0 ){ + /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the + ** built-in default page cache is used instead of the application defined + ** page cache. */ + sqlite3PCacheSetDefault(); + } + return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg); +} +SQLITE_PRIVATE void sqlite3PcacheShutdown(void){ + if( sqlite3GlobalConfig.pcache2.xShutdown ){ + /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */ + sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg); + } +} + +/* +** Return the size in bytes of a PCache object. +*/ +SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); } + +/* +** Create a new PCache object. Storage space to hold the object +** has already been allocated and is passed in as the p pointer. +** The caller discovers how much space needs to be allocated by +** calling sqlite3PcacheSize(). +*/ +SQLITE_PRIVATE int sqlite3PcacheOpen( + int szPage, /* Size of every page */ + int szExtra, /* Extra space associated with each page */ + int bPurgeable, /* True if pages are on backing store */ + int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */ + void *pStress, /* Argument to xStress */ + PCache *p /* Preallocated space for the PCache */ +){ + memset(p, 0, sizeof(PCache)); + p->szPage = 1; + p->szExtra = szExtra; + p->bPurgeable = bPurgeable; + p->eCreate = 2; + p->xStress = xStress; + p->pStress = pStress; + p->szCache = 100; + return sqlite3PcacheSetPageSize(p, szPage); +} + +/* +** Change the page size for PCache object. The caller must ensure that there +** are no outstanding page references when this function is called. +*/ +SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ + assert( pCache->nRef==0 && pCache->pDirty==0 ); + if( pCache->szPage ){ + sqlite3_pcache *pNew; + pNew = sqlite3GlobalConfig.pcache2.xCreate( + szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)), + pCache->bPurgeable + ); + if( pNew==0 ) return SQLITE_NOMEM; + sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache)); + if( pCache->pCache ){ + sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); + } + pCache->pCache = pNew; + pCache->szPage = szPage; + } + return SQLITE_OK; +} + +/* +** Try to obtain a page from the cache. +** +** This routine returns a pointer to an sqlite3_pcache_page object if +** such an object is already in cache, or if a new one is created. +** This routine returns a NULL pointer if the object was not in cache +** and could not be created. +** +** The createFlags should be 0 to check for existing pages and should +** be 3 (not 1, but 3) to try to create a new page. +** +** If the createFlag is 0, then NULL is always returned if the page +** is not already in the cache. If createFlag is 1, then a new page +** is created only if that can be done without spilling dirty pages +** and without exceeding the cache size limit. +** +** The caller needs to invoke sqlite3PcacheFetchFinish() to properly +** initialize the sqlite3_pcache_page object and convert it into a +** PgHdr object. The sqlite3PcacheFetch() and sqlite3PcacheFetchFinish() +** routines are split this way for performance reasons. When separated +** they can both (usually) operate without having to push values to +** the stack on entry and pop them back off on exit, which saves a +** lot of pushing and popping. +*/ +SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch( + PCache *pCache, /* Obtain the page from this cache */ + Pgno pgno, /* Page number to obtain */ + int createFlag /* If true, create page if it does not exist already */ +){ + int eCreate; + + assert( pCache!=0 ); + assert( pCache->pCache!=0 ); + assert( createFlag==3 || createFlag==0 ); + assert( pgno>0 ); + + /* eCreate defines what to do if the page does not exist. + ** 0 Do not allocate a new page. (createFlag==0) + ** 1 Allocate a new page if doing so is inexpensive. + ** (createFlag==1 AND bPurgeable AND pDirty) + ** 2 Allocate a new page even it doing so is difficult. + ** (createFlag==1 AND !(bPurgeable AND pDirty) + */ + eCreate = createFlag & pCache->eCreate; + assert( eCreate==0 || eCreate==1 || eCreate==2 ); + assert( createFlag==0 || pCache->eCreate==eCreate ); + assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) ); + return sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate); +} + +/* +** If the sqlite3PcacheFetch() routine is unable to allocate a new +** page because new clean pages are available for reuse and the cache +** size limit has been reached, then this routine can be invoked to +** try harder to allocate a page. This routine might invoke the stress +** callback to spill dirty pages to the journal. It will then try to +** allocate the new page and will only fail to allocate a new page on +** an OOM error. +** +** This routine should be invoked only after sqlite3PcacheFetch() fails. +*/ +SQLITE_PRIVATE int sqlite3PcacheFetchStress( + PCache *pCache, /* Obtain the page from this cache */ + Pgno pgno, /* Page number to obtain */ + sqlite3_pcache_page **ppPage /* Write result here */ +){ + PgHdr *pPg; + if( pCache->eCreate==2 ) return 0; + + + /* Find a dirty page to write-out and recycle. First try to find a + ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC + ** cleared), but if that is not possible settle for any other + ** unreferenced dirty page. + */ + for(pPg=pCache->pSynced; + pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); + pPg=pPg->pDirtyPrev + ); + pCache->pSynced = pPg; + if( !pPg ){ + for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev); + } + if( pPg ){ + int rc; +#ifdef SQLITE_LOG_CACHE_SPILL + sqlite3_log(SQLITE_FULL, + "spill page %d making room for %d - cache used: %d/%d", + pPg->pgno, pgno, + sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache), + numberOfCachePages(pCache)); +#endif + rc = pCache->xStress(pCache->pStress, pPg); + if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ + return rc; + } + } + *ppPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2); + return *ppPage==0 ? SQLITE_NOMEM : SQLITE_OK; +} + +/* +** This is a helper routine for sqlite3PcacheFetchFinish() +** +** In the uncommon case where the page being fetched has not been +** initialized, this routine is invoked to do the initialization. +** This routine is broken out into a separate function since it +** requires extra stack manipulation that can be avoided in the common +** case. +*/ +static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit( + PCache *pCache, /* Obtain the page from this cache */ + Pgno pgno, /* Page number obtained */ + sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */ +){ + PgHdr *pPgHdr; + assert( pPage!=0 ); + pPgHdr = (PgHdr*)pPage->pExtra; + assert( pPgHdr->pPage==0 ); + memset(pPgHdr, 0, sizeof(PgHdr)); + pPgHdr->pPage = pPage; + pPgHdr->pData = pPage->pBuf; + pPgHdr->pExtra = (void *)&pPgHdr[1]; + memset(pPgHdr->pExtra, 0, pCache->szExtra); + pPgHdr->pCache = pCache; + pPgHdr->pgno = pgno; + pPgHdr->flags = PGHDR_CLEAN; + return sqlite3PcacheFetchFinish(pCache,pgno,pPage); +} + +/* +** This routine converts the sqlite3_pcache_page object returned by +** sqlite3PcacheFetch() into an initialized PgHdr object. This routine +** must be called after sqlite3PcacheFetch() in order to get a usable +** result. +*/ +SQLITE_PRIVATE PgHdr *sqlite3PcacheFetchFinish( + PCache *pCache, /* Obtain the page from this cache */ + Pgno pgno, /* Page number obtained */ + sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */ +){ + PgHdr *pPgHdr; + + assert( pPage!=0 ); + pPgHdr = (PgHdr *)pPage->pExtra; + + if( !pPgHdr->pPage ){ + return pcacheFetchFinishWithInit(pCache, pgno, pPage); + } + if( 0==pPgHdr->nRef ){ + pCache->nRef++; + } + pPgHdr->nRef++; + return pPgHdr; +} + +/* +** Decrement the reference count on a page. If the page is clean and the +** reference count drops to 0, then it is made eligible for recycling. +*/ +SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){ + assert( p->nRef>0 ); + p->nRef--; + if( p->nRef==0 ){ + p->pCache->nRef--; + if( p->flags&PGHDR_CLEAN ){ + pcacheUnpin(p); + }else if( p->pDirtyPrev!=0 ){ + /* Move the page to the head of the dirty list. */ + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); + } + } +} + +/* +** Increase the reference count of a supplied page by 1. +*/ +SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){ + assert(p->nRef>0); + p->nRef++; +} + +/* +** Drop a page from the cache. There must be exactly one reference to the +** page. This function deletes that reference, so after it returns the +** page pointed to by p is invalid. +*/ +SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){ + assert( p->nRef==1 ); + if( p->flags&PGHDR_DIRTY ){ + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); + } + p->pCache->nRef--; + sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1); +} + +/* +** Make sure the page is marked as dirty. If it isn't dirty already, +** make it so. +*/ +SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){ + assert( p->nRef>0 ); + if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){ + p->flags &= ~PGHDR_DONT_WRITE; + if( p->flags & PGHDR_CLEAN ){ + p->flags ^= (PGHDR_DIRTY|PGHDR_CLEAN); + assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY ); + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD); + } + } +} + +/* +** Make sure the page is marked as clean. If it isn't clean already, +** make it so. +*/ +SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){ + if( (p->flags & PGHDR_DIRTY) ){ + assert( (p->flags & PGHDR_CLEAN)==0 ); + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); + p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE); + p->flags |= PGHDR_CLEAN; + if( p->nRef==0 ){ + pcacheUnpin(p); + } + } +} + +/* +** Make every page in the cache clean. +*/ +SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){ + PgHdr *p; + while( (p = pCache->pDirty)!=0 ){ + sqlite3PcacheMakeClean(p); + } +} + +/* +** Clear the PGHDR_NEED_SYNC flag from all dirty pages. +*/ +SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){ + PgHdr *p; + for(p=pCache->pDirty; p; p=p->pDirtyNext){ + p->flags &= ~PGHDR_NEED_SYNC; + } + pCache->pSynced = pCache->pDirtyTail; +} + +/* +** Change the page number of page p to newPgno. +*/ +SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ + PCache *pCache = p->pCache; + assert( p->nRef>0 ); + assert( newPgno>0 ); + sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno); + p->pgno = newPgno; + if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){ + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); + } +} + +/* +** Drop every cache entry whose page number is greater than "pgno". The +** caller must ensure that there are no outstanding references to any pages +** other than page 1 with a page number greater than pgno. +** +** If there is a reference to page 1 and the pgno parameter passed to this +** function is 0, then the data area associated with page 1 is zeroed, but +** the page object is not dropped. +*/ +SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){ + if( pCache->pCache ){ + PgHdr *p; + PgHdr *pNext; + for(p=pCache->pDirty; p; p=pNext){ + pNext = p->pDirtyNext; + /* This routine never gets call with a positive pgno except right + ** after sqlite3PcacheCleanAll(). So if there are dirty pages, + ** it must be that pgno==0. + */ + assert( p->pgno>0 ); + if( ALWAYS(p->pgno>pgno) ){ + assert( p->flags&PGHDR_DIRTY ); + sqlite3PcacheMakeClean(p); + } + } + if( pgno==0 && pCache->nRef ){ + sqlite3_pcache_page *pPage1; + pPage1 = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache,1,0); + if( ALWAYS(pPage1) ){ /* Page 1 is always available in cache, because + ** pCache->nRef>0 */ + memset(pPage1->pBuf, 0, pCache->szPage); + pgno = 1; + } + } + sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1); + } +} + +/* +** Close a cache. +*/ +SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){ + assert( pCache->pCache!=0 ); + sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); +} + +/* +** Discard the contents of the cache. +*/ +SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){ + sqlite3PcacheTruncate(pCache, 0); +} + +/* +** Merge two lists of pages connected by pDirty and in pgno order. +** Do not both fixing the pDirtyPrev pointers. +*/ +static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){ + PgHdr result, *pTail; + pTail = &result; + while( pA && pB ){ + if( pA->pgnopgno ){ + pTail->pDirty = pA; + pTail = pA; + pA = pA->pDirty; + }else{ + pTail->pDirty = pB; + pTail = pB; + pB = pB->pDirty; + } + } + if( pA ){ + pTail->pDirty = pA; + }else if( pB ){ + pTail->pDirty = pB; + }else{ + pTail->pDirty = 0; + } + return result.pDirty; +} + +/* +** Sort the list of pages in accending order by pgno. Pages are +** connected by pDirty pointers. The pDirtyPrev pointers are +** corrupted by this sort. +** +** Since there cannot be more than 2^31 distinct pages in a database, +** there cannot be more than 31 buckets required by the merge sorter. +** One extra bucket is added to catch overflow in case something +** ever changes to make the previous sentence incorrect. +*/ +#define N_SORT_BUCKET 32 +static PgHdr *pcacheSortDirtyList(PgHdr *pIn){ + PgHdr *a[N_SORT_BUCKET], *p; + int i; + memset(a, 0, sizeof(a)); + while( pIn ){ + p = pIn; + pIn = p->pDirty; + p->pDirty = 0; + for(i=0; ALWAYS(ipDirty; p; p=p->pDirtyNext){ + p->pDirty = p->pDirtyNext; + } + return pcacheSortDirtyList(pCache->pDirty); +} + +/* +** Return the total number of referenced pages held by the cache. +*/ +SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){ + return pCache->nRef; +} + +/* +** Return the number of references to the page supplied as an argument. +*/ +SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){ + return p->nRef; +} + +/* +** Return the total number of pages in the cache. +*/ +SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){ + assert( pCache->pCache!=0 ); + return sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache); +} + +#ifdef SQLITE_TEST +/* +** Get the suggested cache-size value. +*/ +SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){ + return numberOfCachePages(pCache); +} +#endif + +/* +** Set the suggested cache-size value. +*/ +SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){ + assert( pCache->pCache!=0 ); + pCache->szCache = mxPage; + sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache, + numberOfCachePages(pCache)); +} + +/* +** Free up as much memory as possible from the page cache. +*/ +SQLITE_PRIVATE void sqlite3PcacheShrink(PCache *pCache){ + assert( pCache->pCache!=0 ); + sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache); +} + +/* +** Return the size of the header added by this middleware layer +** in the page-cache hierarchy. +*/ +SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); } + + +#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) +/* +** For all dirty pages currently in the cache, invoke the specified +** callback. This is only used if the SQLITE_CHECK_PAGES macro is +** defined. +*/ +SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){ + PgHdr *pDirty; + for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext){ + xIter(pDirty); + } +} +#endif + +/************** End of pcache.c **********************************************/ +/************** Begin file pcache1.c *****************************************/ +/* +** 2008 November 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 file implements the default page cache implementation (the +** sqlite3_pcache interface). It also contains part of the implementation +** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features. +** If the default page cache implementation is overridden, then neither of +** these two features are available. +** +** A Page cache line looks like this: +** +** ------------------------------------------------------------- +** | database page content | PgHdr1 | MemPage | PgHdr | +** ------------------------------------------------------------- +** +** The database page content is up front (so that buffer overreads tend to +** flow harmlessly into the PgHdr1, MemPage, and PgHdr extensions). MemPage +** is the extension added by the btree.c module containing information such +** as the database page number and how that database page is used. PgHdr +** is added by the pcache.c layer and contains information used to keep track +** of which pages are "dirty". PgHdr1 is an extension added by this +** module (pcache1.c). The PgHdr1 header is a subclass of sqlite3_pcache_page. +** PgHdr1 contains information needed to look up a page by its page number. +** The superclass sqlite3_pcache_page.pBuf points to the start of the +** database page content and sqlite3_pcache_page.pExtra points to PgHdr. +** +** The size of the extension (MemPage+PgHdr+PgHdr1) can be determined at +** runtime using sqlite3_config(SQLITE_CONFIG_PCACHE_HDRSZ, &size). The +** sizes of the extensions sum to 272 bytes on x64 for 3.8.10, but this +** size can vary according to architecture, compile-time options, and +** SQLite library version number. +** +** If SQLITE_PCACHE_SEPARATE_HEADER is defined, then the extension is obtained +** using a separate memory allocation from the database page content. This +** seeks to overcome the "clownshoe" problem (also called "internal +** fragmentation" in academic literature) of allocating a few bytes more +** than a power of two with the memory allocator rounding up to the next +** power of two, and leaving the rounded-up space unused. +** +** This module tracks pointers to PgHdr1 objects. Only pcache.c communicates +** with this module. Information is passed back and forth as PgHdr1 pointers. +** +** The pcache.c and pager.c modules deal pointers to PgHdr objects. +** The btree.c module deals with pointers to MemPage objects. +** +** SOURCE OF PAGE CACHE MEMORY: +** +** Memory for a page might come from any of three sources: +** +** (1) The general-purpose memory allocator - sqlite3Malloc() +** (2) Global page-cache memory provided using sqlite3_config() with +** SQLITE_CONFIG_PAGECACHE. +** (3) PCache-local bulk allocation. +** +** The third case is a chunk of heap memory (defaulting to 100 pages worth) +** that is allocated when the page cache is created. The size of the local +** bulk allocation can be adjusted using +** +** sqlite3_config(SQLITE_CONFIG_PCACHE, 0, 0, N). +** +** If N is positive, then N pages worth of memory are allocated using a single +** sqlite3Malloc() call and that memory is used for the first N pages allocated. +** Or if N is negative, then -1024*N bytes of memory are allocated and used +** for as many pages as can be accomodated. +** +** Only one of (2) or (3) can be used. Once the memory available to (2) or +** (3) is exhausted, subsequent allocations fail over to the general-purpose +** memory allocator (1). +** +** Earlier versions of SQLite used only methods (1) and (2). But experiments +** show that method (3) with N==100 provides about a 5% performance boost for +** common workloads. +*/ +/* #include "sqliteInt.h" */ + +typedef struct PCache1 PCache1; +typedef struct PgHdr1 PgHdr1; +typedef struct PgFreeslot PgFreeslot; +typedef struct PGroup PGroup; + +/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set +** of one or more PCaches that are able to recycle each other's unpinned +** pages when they are under memory pressure. A PGroup is an instance of +** the following object. +** +** This page cache implementation works in one of two modes: +** +** (1) Every PCache is the sole member of its own PGroup. There is +** one PGroup per PCache. +** +** (2) There is a single global PGroup that all PCaches are a member +** of. +** +** Mode 1 uses more memory (since PCache instances are not able to rob +** unused pages from other PCaches) but it also operates without a mutex, +** and is therefore often faster. Mode 2 requires a mutex in order to be +** threadsafe, but recycles pages more efficiently. +** +** For mode (1), PGroup.mutex is NULL. For mode (2) there is only a single +** PGroup which is the pcache1.grp global variable and its mutex is +** SQLITE_MUTEX_STATIC_LRU. +*/ +struct PGroup { + sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */ + unsigned int nMaxPage; /* Sum of nMax for purgeable caches */ + unsigned int nMinPage; /* Sum of nMin for purgeable caches */ + unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */ + unsigned int nCurrentPage; /* Number of purgeable pages allocated */ + PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */ +}; + +/* Each page cache is an instance of the following object. Every +** open database file (including each in-memory database and each +** temporary or transient database) has a single page cache which +** is an instance of this object. +** +** Pointers to structures of this type are cast and returned as +** opaque sqlite3_pcache* handles. +*/ +struct PCache1 { + /* Cache configuration parameters. Page size (szPage) and the purgeable + ** flag (bPurgeable) are set when the cache is created. nMax may be + ** modified at any time by a call to the pcache1Cachesize() method. + ** The PGroup mutex must be held when accessing nMax. + */ + PGroup *pGroup; /* PGroup this cache belongs to */ + int szPage; /* Size of database content section */ + int szExtra; /* sizeof(MemPage)+sizeof(PgHdr) */ + int szAlloc; /* Total size of one pcache line */ + int bPurgeable; /* True if cache is purgeable */ + unsigned int nMin; /* Minimum number of pages reserved */ + unsigned int nMax; /* Configured "cache_size" value */ + unsigned int n90pct; /* nMax*9/10 */ + unsigned int iMaxKey; /* Largest key seen since xTruncate() */ + + /* Hash table of all pages. The following variables may only be accessed + ** when the accessor is holding the PGroup mutex. + */ + unsigned int nRecyclable; /* Number of pages in the LRU list */ + unsigned int nPage; /* Total number of pages in apHash */ + unsigned int nHash; /* Number of slots in apHash[] */ + PgHdr1 **apHash; /* Hash table for fast lookup by key */ + PgHdr1 *pFree; /* List of unused pcache-local pages */ + void *pBulk; /* Bulk memory used by pcache-local */ +}; + +/* +** Each cache entry is represented by an instance of the following +** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of +** PgHdr1.pCache->szPage bytes is allocated directly before this structure +** in memory. +*/ +struct PgHdr1 { + sqlite3_pcache_page page; + unsigned int iKey; /* Key value (page number) */ + u8 isPinned; /* Page in use, not on the LRU list */ + u8 isBulkLocal; /* This page from bulk local storage */ + PgHdr1 *pNext; /* Next in hash table chain */ + PCache1 *pCache; /* Cache that currently owns this page */ + PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */ + PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ +}; + +/* +** Free slots in the allocator used to divide up the global page cache +** buffer provided using the SQLITE_CONFIG_PAGECACHE mechanism. +*/ +struct PgFreeslot { + PgFreeslot *pNext; /* Next free slot */ +}; + +/* +** Global data used by this cache. +*/ +static SQLITE_WSD struct PCacheGlobal { + PGroup grp; /* The global PGroup for mode (2) */ + + /* Variables related to SQLITE_CONFIG_PAGECACHE settings. The + ** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all + ** fixed at sqlite3_initialize() time and do not require mutex protection. + ** The nFreeSlot and pFree values do require mutex protection. + */ + int isInit; /* True if initialized */ + int separateCache; /* Use a new PGroup for each PCache */ + int nInitPage; /* Initial bulk allocation size */ + int szSlot; /* Size of each free slot */ + int nSlot; /* The number of pcache slots */ + int nReserve; /* Try to keep nFreeSlot above this */ + void *pStart, *pEnd; /* Bounds of global page cache memory */ + /* Above requires no mutex. Use mutex below for variable that follow. */ + sqlite3_mutex *mutex; /* Mutex for accessing the following: */ + PgFreeslot *pFree; /* Free page blocks */ + int nFreeSlot; /* Number of unused pcache slots */ + /* The following value requires a mutex to change. We skip the mutex on + ** reading because (1) most platforms read a 32-bit integer atomically and + ** (2) even if an incorrect value is read, no great harm is done since this + ** is really just an optimization. */ + int bUnderPressure; /* True if low on PAGECACHE memory */ +} pcache1_g; + +/* +** All code in this file should access the global structure above via the +** alias "pcache1". This ensures that the WSD emulation is used when +** compiling for systems that do not support real WSD. +*/ +#define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g)) + +/* +** Macros to enter and leave the PCache LRU mutex. +*/ +#if !defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0 +# define pcache1EnterMutex(X) assert((X)->mutex==0) +# define pcache1LeaveMutex(X) assert((X)->mutex==0) +# define PCACHE1_MIGHT_USE_GROUP_MUTEX 0 +#else +# define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex) +# define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex) +# define PCACHE1_MIGHT_USE_GROUP_MUTEX 1 +#endif + +/******************************************************************************/ +/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/ + +/* +** This function is called during initialization if a static buffer is +** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE +** verb to sqlite3_config(). Parameter pBuf points to an allocation large +** enough to contain 'n' buffers of 'sz' bytes each. +** +** This routine is called from sqlite3_initialize() and so it is guaranteed +** to be serialized already. There is no need for further mutexing. +*/ +SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){ + if( pcache1.isInit ){ + PgFreeslot *p; + if( pBuf==0 ) sz = n = 0; + sz = ROUNDDOWN8(sz); + pcache1.szSlot = sz; + pcache1.nSlot = pcache1.nFreeSlot = n; + pcache1.nReserve = n>90 ? 10 : (n/10 + 1); + pcache1.pStart = pBuf; + pcache1.pFree = 0; + pcache1.bUnderPressure = 0; + while( n-- ){ + p = (PgFreeslot*)pBuf; + p->pNext = pcache1.pFree; + pcache1.pFree = p; + pBuf = (void*)&((char*)pBuf)[sz]; + } + pcache1.pEnd = pBuf; + } +} + +/* +** Try to initialize the pCache->pFree and pCache->pBulk fields. Return +** true if pCache->pFree ends up containing one or more free pages. +*/ +static int pcache1InitBulk(PCache1 *pCache){ + i64 szBulk; + char *zBulk; + if( pcache1.nInitPage==0 ) return 0; + /* Do not bother with a bulk allocation if the cache size very small */ + if( pCache->nMax<3 ) return 0; + sqlite3BeginBenignMalloc(); + if( pcache1.nInitPage>0 ){ + szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; + }else{ + szBulk = -1024 * (i64)pcache1.nInitPage; + } + if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ + szBulk = pCache->szAlloc*pCache->nMax; + } + zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); + sqlite3EndBenignMalloc(); + if( zBulk ){ + int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; + int i; + for(i=0; iszPage]; + pX->page.pBuf = zBulk; + pX->page.pExtra = &pX[1]; + pX->isBulkLocal = 1; + pX->pNext = pCache->pFree; + pCache->pFree = pX; + zBulk += pCache->szAlloc; + } + } + return pCache->pFree!=0; +} + +/* +** Malloc function used within this file to allocate space from the buffer +** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no +** such buffer exists or there is no space left in it, this function falls +** back to sqlite3Malloc(). +** +** Multiple threads can run this routine at the same time. Global variables +** in pcache1 need to be protected via mutex. +*/ +static void *pcache1Alloc(int nByte){ + void *p = 0; + assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); + if( nByte<=pcache1.szSlot ){ + sqlite3_mutex_enter(pcache1.mutex); + p = (PgHdr1 *)pcache1.pFree; + if( p ){ + pcache1.pFree = pcache1.pFree->pNext; + pcache1.nFreeSlot--; + pcache1.bUnderPressure = pcache1.nFreeSlot=0 ); + sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte); + sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1); + } + sqlite3_mutex_leave(pcache1.mutex); + } + if( p==0 ){ + /* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool. Get + ** it from sqlite3Malloc instead. + */ + p = sqlite3Malloc(nByte); +#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS + if( p ){ + int sz = sqlite3MallocSize(p); + sqlite3_mutex_enter(pcache1.mutex); + sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte); + sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); + sqlite3_mutex_leave(pcache1.mutex); + } +#endif + sqlite3MemdebugSetType(p, MEMTYPE_PCACHE); + } + return p; +} + +/* +** Free an allocated buffer obtained from pcache1Alloc(). +*/ +static void pcache1Free(void *p){ + int nFreed = 0; + if( p==0 ) return; + if( p>=pcache1.pStart && ppNext = pcache1.pFree; + pcache1.pFree = pSlot; + pcache1.nFreeSlot++; + pcache1.bUnderPressure = pcache1.nFreeSlot=pcache1.pStart && ppGroup->mutex) ); + if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){ + p = pCache->pFree; + pCache->pFree = p->pNext; + p->pNext = 0; + }else{ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + /* The group mutex must be released before pcache1Alloc() is called. This + ** is because it might call sqlite3_release_memory(), which assumes that + ** this mutex is not held. */ + assert( pcache1.separateCache==0 ); + assert( pCache->pGroup==&pcache1.grp ); + pcache1LeaveMutex(pCache->pGroup); +#endif +#ifdef SQLITE_PCACHE_SEPARATE_HEADER + pPg = pcache1Alloc(pCache->szPage); + p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra); + if( !pPg || !p ){ + pcache1Free(pPg); + sqlite3_free(p); + pPg = 0; + } +#else + pPg = pcache1Alloc(pCache->szAlloc); + p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; +#endif +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + pcache1EnterMutex(pCache->pGroup); +#endif + if( pPg==0 ) return 0; + p->page.pBuf = pPg; + p->page.pExtra = &p[1]; + p->isBulkLocal = 0; + } + if( pCache->bPurgeable ){ + pCache->pGroup->nCurrentPage++; + } + return p; +} + +/* +** Free a page object allocated by pcache1AllocPage(). +*/ +static void pcache1FreePage(PgHdr1 *p){ + PCache1 *pCache; + assert( p!=0 ); + pCache = p->pCache; + assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) ); + if( p->isBulkLocal ){ + p->pNext = pCache->pFree; + pCache->pFree = p; + }else{ + pcache1Free(p->page.pBuf); +#ifdef SQLITE_PCACHE_SEPARATE_HEADER + sqlite3_free(p); +#endif + } + if( pCache->bPurgeable ){ + pCache->pGroup->nCurrentPage--; + } +} + +/* +** Malloc function used by SQLite to obtain space from the buffer configured +** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer +** exists, this function falls back to sqlite3Malloc(). +*/ +SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){ + return pcache1Alloc(sz); +} + +/* +** Free an allocated buffer obtained from sqlite3PageMalloc(). +*/ +SQLITE_PRIVATE void sqlite3PageFree(void *p){ + pcache1Free(p); +} + + +/* +** Return true if it desirable to avoid allocating a new page cache +** entry. +** +** If memory was allocated specifically to the page cache using +** SQLITE_CONFIG_PAGECACHE but that memory has all been used, then +** it is desirable to avoid allocating a new page cache entry because +** presumably SQLITE_CONFIG_PAGECACHE was suppose to be sufficient +** for all page cache needs and we should not need to spill the +** allocation onto the heap. +** +** Or, the heap is used for all page cache memory but the heap is +** under memory pressure, then again it is desirable to avoid +** allocating a new page cache entry in order to avoid stressing +** the heap even further. +*/ +static int pcache1UnderMemoryPressure(PCache1 *pCache){ + if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){ + return pcache1.bUnderPressure; + }else{ + return sqlite3HeapNearlyFull(); + } +} + +/******************************************************************************/ +/******** General Implementation Functions ************************************/ + +/* +** This function is used to resize the hash table used by the cache passed +** as the first argument. +** +** The PCache mutex must be held when this function is called. +*/ +static void pcache1ResizeHash(PCache1 *p){ + PgHdr1 **apNew; + unsigned int nNew; + unsigned int i; + + assert( sqlite3_mutex_held(p->pGroup->mutex) ); + + nNew = p->nHash*2; + if( nNew<256 ){ + nNew = 256; + } + + pcache1LeaveMutex(p->pGroup); + if( p->nHash ){ sqlite3BeginBenignMalloc(); } + apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew); + if( p->nHash ){ sqlite3EndBenignMalloc(); } + pcache1EnterMutex(p->pGroup); + if( apNew ){ + for(i=0; inHash; i++){ + PgHdr1 *pPage; + PgHdr1 *pNext = p->apHash[i]; + while( (pPage = pNext)!=0 ){ + unsigned int h = pPage->iKey % nNew; + pNext = pPage->pNext; + pPage->pNext = apNew[h]; + apNew[h] = pPage; + } + } + sqlite3_free(p->apHash); + p->apHash = apNew; + p->nHash = nNew; + } +} + +/* +** This function is used internally to remove the page pPage from the +** PGroup LRU list, if is part of it. If pPage is not part of the PGroup +** LRU list, then this function is a no-op. +** +** The PGroup mutex must be held when this function is called. +*/ +static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){ + PCache1 *pCache; + + assert( pPage!=0 ); + assert( pPage->isPinned==0 ); + pCache = pPage->pCache; + assert( pPage->pLruNext || pPage==pCache->pGroup->pLruTail ); + assert( pPage->pLruPrev || pPage==pCache->pGroup->pLruHead ); + assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); + if( pPage->pLruPrev ){ + pPage->pLruPrev->pLruNext = pPage->pLruNext; + }else{ + pCache->pGroup->pLruHead = pPage->pLruNext; + } + if( pPage->pLruNext ){ + pPage->pLruNext->pLruPrev = pPage->pLruPrev; + }else{ + pCache->pGroup->pLruTail = pPage->pLruPrev; + } + pPage->pLruNext = 0; + pPage->pLruPrev = 0; + pPage->isPinned = 1; + pCache->nRecyclable--; + return pPage; +} + + +/* +** Remove the page supplied as an argument from the hash table +** (PCache1.apHash structure) that it is currently stored in. +** Also free the page if freePage is true. +** +** The PGroup mutex must be held when this function is called. +*/ +static void pcache1RemoveFromHash(PgHdr1 *pPage, int freeFlag){ + unsigned int h; + PCache1 *pCache = pPage->pCache; + PgHdr1 **pp; + + assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); + h = pPage->iKey % pCache->nHash; + for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext); + *pp = (*pp)->pNext; + + pCache->nPage--; + if( freeFlag ) pcache1FreePage(pPage); +} + +/* +** If there are currently more than nMaxPage pages allocated, try +** to recycle pages to reduce the number allocated to nMaxPage. +*/ +static void pcache1EnforceMaxPage(PCache1 *pCache){ + PGroup *pGroup = pCache->pGroup; + assert( sqlite3_mutex_held(pGroup->mutex) ); + while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){ + PgHdr1 *p = pGroup->pLruTail; + assert( p->pCache->pGroup==pGroup ); + assert( p->isPinned==0 ); + pcache1PinPage(p); + pcache1RemoveFromHash(p, 1); + } + if( pCache->nPage==0 && pCache->pBulk ){ + sqlite3_free(pCache->pBulk); + pCache->pBulk = pCache->pFree = 0; + } +} + +/* +** Discard all pages from cache pCache with a page number (key value) +** greater than or equal to iLimit. Any pinned pages that meet this +** criteria are unpinned before they are discarded. +** +** The PCache mutex must be held when this function is called. +*/ +static void pcache1TruncateUnsafe( + PCache1 *pCache, /* The cache to truncate */ + unsigned int iLimit /* Drop pages with this pgno or larger */ +){ + TESTONLY( unsigned int nPage = 0; ) /* To assert pCache->nPage is correct */ + unsigned int h; + assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); + for(h=0; hnHash; h++){ + PgHdr1 **pp = &pCache->apHash[h]; + PgHdr1 *pPage; + while( (pPage = *pp)!=0 ){ + if( pPage->iKey>=iLimit ){ + pCache->nPage--; + *pp = pPage->pNext; + if( !pPage->isPinned ) pcache1PinPage(pPage); + pcache1FreePage(pPage); + }else{ + pp = &pPage->pNext; + TESTONLY( nPage++; ) + } + } + } + assert( pCache->nPage==nPage ); +} + +/******************************************************************************/ +/******** sqlite3_pcache Methods **********************************************/ + +/* +** Implementation of the sqlite3_pcache.xInit method. +*/ +static int pcache1Init(void *NotUsed){ + UNUSED_PARAMETER(NotUsed); + assert( pcache1.isInit==0 ); + memset(&pcache1, 0, sizeof(pcache1)); + + + /* + ** The pcache1.separateCache variable is true if each PCache has its own + ** private PGroup (mode-1). pcache1.separateCache is false if the single + ** PGroup in pcache1.grp is used for all page caches (mode-2). + ** + ** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT + ** + ** * Use a unified cache in single-threaded applications that have + ** configured a start-time buffer for use as page-cache memory using + ** sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N) with non-NULL + ** pBuf argument. + ** + ** * Otherwise use separate caches (mode-1) + */ +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) + pcache1.separateCache = 0; +#elif SQLITE_THREADSAFE + pcache1.separateCache = sqlite3GlobalConfig.pPage==0 + || sqlite3GlobalConfig.bCoreMutex>0; +#else + pcache1.separateCache = sqlite3GlobalConfig.pPage==0; +#endif + +#if SQLITE_THREADSAFE + if( sqlite3GlobalConfig.bCoreMutex ){ + pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU); + pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM); + } +#endif + if( pcache1.separateCache + && sqlite3GlobalConfig.nPage!=0 + && sqlite3GlobalConfig.pPage==0 + ){ + pcache1.nInitPage = sqlite3GlobalConfig.nPage; + }else{ + pcache1.nInitPage = 0; + } + pcache1.grp.mxPinned = 10; + pcache1.isInit = 1; + return SQLITE_OK; +} + +/* +** Implementation of the sqlite3_pcache.xShutdown method. +** Note that the static mutex allocated in xInit does +** not need to be freed. +*/ +static void pcache1Shutdown(void *NotUsed){ + UNUSED_PARAMETER(NotUsed); + assert( pcache1.isInit!=0 ); + memset(&pcache1, 0, sizeof(pcache1)); +} + +/* forward declaration */ +static void pcache1Destroy(sqlite3_pcache *p); + +/* +** Implementation of the sqlite3_pcache.xCreate method. +** +** Allocate a new cache. +*/ +static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){ + PCache1 *pCache; /* The newly created page cache */ + PGroup *pGroup; /* The group the new page cache will belong to */ + int sz; /* Bytes of memory required to allocate the new cache */ + + assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 ); + assert( szExtra < 300 ); + + sz = sizeof(PCache1) + sizeof(PGroup)*pcache1.separateCache; + pCache = (PCache1 *)sqlite3MallocZero(sz); + if( pCache ){ + if( pcache1.separateCache ){ + pGroup = (PGroup*)&pCache[1]; + pGroup->mxPinned = 10; + }else{ + pGroup = &pcache1.grp; + } + pCache->pGroup = pGroup; + pCache->szPage = szPage; + pCache->szExtra = szExtra; + pCache->szAlloc = szPage + szExtra + ROUND8(sizeof(PgHdr1)); + pCache->bPurgeable = (bPurgeable ? 1 : 0); + pcache1EnterMutex(pGroup); + pcache1ResizeHash(pCache); + if( bPurgeable ){ + pCache->nMin = 10; + pGroup->nMinPage += pCache->nMin; + pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; + } + pcache1LeaveMutex(pGroup); + if( pCache->nHash==0 ){ + pcache1Destroy((sqlite3_pcache*)pCache); + pCache = 0; + } + } + return (sqlite3_pcache *)pCache; +} + +/* +** Implementation of the sqlite3_pcache.xCachesize method. +** +** Configure the cache_size limit for a cache. +*/ +static void pcache1Cachesize(sqlite3_pcache *p, int nMax){ + PCache1 *pCache = (PCache1 *)p; + if( pCache->bPurgeable ){ + PGroup *pGroup = pCache->pGroup; + pcache1EnterMutex(pGroup); + pGroup->nMaxPage += (nMax - pCache->nMax); + pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; + pCache->nMax = nMax; + pCache->n90pct = pCache->nMax*9/10; + pcache1EnforceMaxPage(pCache); + pcache1LeaveMutex(pGroup); + } +} + +/* +** Implementation of the sqlite3_pcache.xShrink method. +** +** Free up as much memory as possible. +*/ +static void pcache1Shrink(sqlite3_pcache *p){ + PCache1 *pCache = (PCache1*)p; + if( pCache->bPurgeable ){ + PGroup *pGroup = pCache->pGroup; + int savedMaxPage; + pcache1EnterMutex(pGroup); + savedMaxPage = pGroup->nMaxPage; + pGroup->nMaxPage = 0; + pcache1EnforceMaxPage(pCache); + pGroup->nMaxPage = savedMaxPage; + pcache1LeaveMutex(pGroup); + } +} + +/* +** Implementation of the sqlite3_pcache.xPagecount method. +*/ +static int pcache1Pagecount(sqlite3_pcache *p){ + int n; + PCache1 *pCache = (PCache1*)p; + pcache1EnterMutex(pCache->pGroup); + n = pCache->nPage; + pcache1LeaveMutex(pCache->pGroup); + return n; +} + + +/* +** Implement steps 3, 4, and 5 of the pcache1Fetch() algorithm described +** in the header of the pcache1Fetch() procedure. +** +** This steps are broken out into a separate procedure because they are +** usually not needed, and by avoiding the stack initialization required +** for these steps, the main pcache1Fetch() procedure can run faster. +*/ +static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2( + PCache1 *pCache, + unsigned int iKey, + int createFlag +){ + unsigned int nPinned; + PGroup *pGroup = pCache->pGroup; + PgHdr1 *pPage = 0; + + /* Step 3: Abort if createFlag is 1 but the cache is nearly full */ + assert( pCache->nPage >= pCache->nRecyclable ); + nPinned = pCache->nPage - pCache->nRecyclable; + assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage ); + assert( pCache->n90pct == pCache->nMax*9/10 ); + if( createFlag==1 && ( + nPinned>=pGroup->mxPinned + || nPinned>=pCache->n90pct + || (pcache1UnderMemoryPressure(pCache) && pCache->nRecyclablenPage>=pCache->nHash ) pcache1ResizeHash(pCache); + assert( pCache->nHash>0 && pCache->apHash ); + + /* Step 4. Try to recycle a page. */ + if( pCache->bPurgeable + && pGroup->pLruTail + && ((pCache->nPage+1>=pCache->nMax) || pcache1UnderMemoryPressure(pCache)) + ){ + PCache1 *pOther; + pPage = pGroup->pLruTail; + assert( pPage->isPinned==0 ); + pcache1RemoveFromHash(pPage, 0); + pcache1PinPage(pPage); + pOther = pPage->pCache; + if( pOther->szAlloc != pCache->szAlloc ){ + pcache1FreePage(pPage); + pPage = 0; + }else{ + pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable); + } + } + + /* Step 5. If a usable page buffer has still not been found, + ** attempt to allocate a new one. + */ + if( !pPage ){ + if( createFlag==1 ){ sqlite3BeginBenignMalloc(); } + pPage = pcache1AllocPage(pCache); + if( createFlag==1 ){ sqlite3EndBenignMalloc(); } + } + + if( pPage ){ + unsigned int h = iKey % pCache->nHash; + pCache->nPage++; + pPage->iKey = iKey; + pPage->pNext = pCache->apHash[h]; + pPage->pCache = pCache; + pPage->pLruPrev = 0; + pPage->pLruNext = 0; + pPage->isPinned = 1; + *(void **)pPage->page.pExtra = 0; + pCache->apHash[h] = pPage; + if( iKey>pCache->iMaxKey ){ + pCache->iMaxKey = iKey; + } + } + return pPage; +} + +/* +** Implementation of the sqlite3_pcache.xFetch method. +** +** Fetch a page by key value. +** +** Whether or not a new page may be allocated by this function depends on +** the value of the createFlag argument. 0 means do not allocate a new +** page. 1 means allocate a new page if space is easily available. 2 +** means to try really hard to allocate a new page. +** +** For a non-purgeable cache (a cache used as the storage for an in-memory +** database) there is really no difference between createFlag 1 and 2. So +** the calling function (pcache.c) will never have a createFlag of 1 on +** a non-purgeable cache. +** +** There are three different approaches to obtaining space for a page, +** depending on the value of parameter createFlag (which may be 0, 1 or 2). +** +** 1. Regardless of the value of createFlag, the cache is searched for a +** copy of the requested page. If one is found, it is returned. +** +** 2. If createFlag==0 and the page is not already in the cache, NULL is +** returned. +** +** 3. If createFlag is 1, and the page is not already in the cache, then +** return NULL (do not allocate a new page) if any of the following +** conditions are true: +** +** (a) the number of pages pinned by the cache is greater than +** PCache1.nMax, or +** +** (b) the number of pages pinned by the cache is greater than +** the sum of nMax for all purgeable caches, less the sum of +** nMin for all other purgeable caches, or +** +** 4. If none of the first three conditions apply and the cache is marked +** as purgeable, and if one of the following is true: +** +** (a) The number of pages allocated for the cache is already +** PCache1.nMax, or +** +** (b) The number of pages allocated for all purgeable caches is +** already equal to or greater than the sum of nMax for all +** purgeable caches, +** +** (c) The system is under memory pressure and wants to avoid +** unnecessary pages cache entry allocations +** +** then attempt to recycle a page from the LRU list. If it is the right +** size, return the recycled buffer. Otherwise, free the buffer and +** proceed to step 5. +** +** 5. Otherwise, allocate and return a new page buffer. +** +** There are two versions of this routine. pcache1FetchWithMutex() is +** the general case. pcache1FetchNoMutex() is a faster implementation for +** the common case where pGroup->mutex is NULL. The pcache1Fetch() wrapper +** invokes the appropriate routine. +*/ +static PgHdr1 *pcache1FetchNoMutex( + sqlite3_pcache *p, + unsigned int iKey, + int createFlag +){ + PCache1 *pCache = (PCache1 *)p; + PgHdr1 *pPage = 0; + + /* Step 1: Search the hash table for an existing entry. */ + pPage = pCache->apHash[iKey % pCache->nHash]; + while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; } + + /* Step 2: Abort if no existing page is found and createFlag is 0 */ + if( pPage ){ + if( !pPage->isPinned ){ + return pcache1PinPage(pPage); + }else{ + return pPage; + } + }else if( createFlag ){ + /* Steps 3, 4, and 5 implemented by this subroutine */ + return pcache1FetchStage2(pCache, iKey, createFlag); + }else{ + return 0; + } +} +#if PCACHE1_MIGHT_USE_GROUP_MUTEX +static PgHdr1 *pcache1FetchWithMutex( + sqlite3_pcache *p, + unsigned int iKey, + int createFlag +){ + PCache1 *pCache = (PCache1 *)p; + PgHdr1 *pPage; + + pcache1EnterMutex(pCache->pGroup); + pPage = pcache1FetchNoMutex(p, iKey, createFlag); + assert( pPage==0 || pCache->iMaxKey>=iKey ); + pcache1LeaveMutex(pCache->pGroup); + return pPage; +} +#endif +static sqlite3_pcache_page *pcache1Fetch( + sqlite3_pcache *p, + unsigned int iKey, + int createFlag +){ +#if PCACHE1_MIGHT_USE_GROUP_MUTEX || defined(SQLITE_DEBUG) + PCache1 *pCache = (PCache1 *)p; +#endif + + assert( offsetof(PgHdr1,page)==0 ); + assert( pCache->bPurgeable || createFlag!=1 ); + assert( pCache->bPurgeable || pCache->nMin==0 ); + assert( pCache->bPurgeable==0 || pCache->nMin==10 ); + assert( pCache->nMin==0 || pCache->bPurgeable ); + assert( pCache->nHash>0 ); +#if PCACHE1_MIGHT_USE_GROUP_MUTEX + if( pCache->pGroup->mutex ){ + return (sqlite3_pcache_page*)pcache1FetchWithMutex(p, iKey, createFlag); + }else +#endif + { + return (sqlite3_pcache_page*)pcache1FetchNoMutex(p, iKey, createFlag); + } +} + + +/* +** Implementation of the sqlite3_pcache.xUnpin method. +** +** Mark a page as unpinned (eligible for asynchronous recycling). +*/ +static void pcache1Unpin( + sqlite3_pcache *p, + sqlite3_pcache_page *pPg, + int reuseUnlikely +){ + PCache1 *pCache = (PCache1 *)p; + PgHdr1 *pPage = (PgHdr1 *)pPg; + PGroup *pGroup = pCache->pGroup; + + assert( pPage->pCache==pCache ); + pcache1EnterMutex(pGroup); + + /* It is an error to call this function if the page is already + ** part of the PGroup LRU list. + */ + assert( pPage->pLruPrev==0 && pPage->pLruNext==0 ); + assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage ); + assert( pPage->isPinned==1 ); + + if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){ + pcache1RemoveFromHash(pPage, 1); + }else{ + /* Add the page to the PGroup LRU list. */ + if( pGroup->pLruHead ){ + pGroup->pLruHead->pLruPrev = pPage; + pPage->pLruNext = pGroup->pLruHead; + pGroup->pLruHead = pPage; + }else{ + pGroup->pLruTail = pPage; + pGroup->pLruHead = pPage; + } + pCache->nRecyclable++; + pPage->isPinned = 0; + } + + pcache1LeaveMutex(pCache->pGroup); +} + +/* +** Implementation of the sqlite3_pcache.xRekey method. +*/ +static void pcache1Rekey( + sqlite3_pcache *p, + sqlite3_pcache_page *pPg, + unsigned int iOld, + unsigned int iNew +){ + PCache1 *pCache = (PCache1 *)p; + PgHdr1 *pPage = (PgHdr1 *)pPg; + PgHdr1 **pp; + unsigned int h; + assert( pPage->iKey==iOld ); + assert( pPage->pCache==pCache ); + + pcache1EnterMutex(pCache->pGroup); + + h = iOld%pCache->nHash; + pp = &pCache->apHash[h]; + while( (*pp)!=pPage ){ + pp = &(*pp)->pNext; + } + *pp = pPage->pNext; + + h = iNew%pCache->nHash; + pPage->iKey = iNew; + pPage->pNext = pCache->apHash[h]; + pCache->apHash[h] = pPage; + if( iNew>pCache->iMaxKey ){ + pCache->iMaxKey = iNew; + } + + pcache1LeaveMutex(pCache->pGroup); +} + +/* +** Implementation of the sqlite3_pcache.xTruncate method. +** +** Discard all unpinned pages in the cache with a page number equal to +** or greater than parameter iLimit. Any pinned pages with a page number +** equal to or greater than iLimit are implicitly unpinned. +*/ +static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){ + PCache1 *pCache = (PCache1 *)p; + pcache1EnterMutex(pCache->pGroup); + if( iLimit<=pCache->iMaxKey ){ + pcache1TruncateUnsafe(pCache, iLimit); + pCache->iMaxKey = iLimit-1; + } + pcache1LeaveMutex(pCache->pGroup); +} + +/* +** Implementation of the sqlite3_pcache.xDestroy method. +** +** Destroy a cache allocated using pcache1Create(). +*/ +static void pcache1Destroy(sqlite3_pcache *p){ + PCache1 *pCache = (PCache1 *)p; + PGroup *pGroup = pCache->pGroup; + assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) ); + pcache1EnterMutex(pGroup); + pcache1TruncateUnsafe(pCache, 0); + assert( pGroup->nMaxPage >= pCache->nMax ); + pGroup->nMaxPage -= pCache->nMax; + assert( pGroup->nMinPage >= pCache->nMin ); + pGroup->nMinPage -= pCache->nMin; + pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; + pcache1EnforceMaxPage(pCache); + pcache1LeaveMutex(pGroup); + sqlite3_free(pCache->pBulk); + sqlite3_free(pCache->apHash); + sqlite3_free(pCache); +} + +/* +** This function is called during initialization (sqlite3_initialize()) to +** install the default pluggable cache module, assuming the user has not +** already provided an alternative. +*/ +SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){ + static const sqlite3_pcache_methods2 defaultMethods = { + 1, /* iVersion */ + 0, /* pArg */ + pcache1Init, /* xInit */ + pcache1Shutdown, /* xShutdown */ + pcache1Create, /* xCreate */ + pcache1Cachesize, /* xCachesize */ + pcache1Pagecount, /* xPagecount */ + pcache1Fetch, /* xFetch */ + pcache1Unpin, /* xUnpin */ + pcache1Rekey, /* xRekey */ + pcache1Truncate, /* xTruncate */ + pcache1Destroy, /* xDestroy */ + pcache1Shrink /* xShrink */ + }; + sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods); +} + +/* +** Return the size of the header on each page of this PCACHE implementation. +*/ +SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); } + +/* +** Return the global mutex used by this PCACHE implementation. The +** sqlite3_status() routine needs access to this mutex. +*/ +SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void){ + return pcache1.mutex; +} + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +/* +** This function is called to free superfluous dynamically allocated memory +** held by the pager system. Memory in use by any SQLite pager allocated +** by the current thread may be sqlite3_free()ed. +** +** nReq is the number of bytes of memory required. Once this much has +** been released, the function returns. The return value is the total number +** of bytes of memory released. +*/ +SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){ + int nFree = 0; + assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); + assert( sqlite3_mutex_notheld(pcache1.mutex) ); + if( sqlite3GlobalConfig.nPage==0 ){ + PgHdr1 *p; + pcache1EnterMutex(&pcache1.grp); + while( (nReq<0 || nFreepage.pBuf); +#ifdef SQLITE_PCACHE_SEPARATE_HEADER + nFree += sqlite3MemSize(p); +#endif + assert( p->isPinned==0 ); + pcache1PinPage(p); + pcache1RemoveFromHash(p, 1); + } + pcache1LeaveMutex(&pcache1.grp); + } + return nFree; +} +#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ + +#ifdef SQLITE_TEST +/* +** This function is used by test procedures to inspect the internal state +** of the global cache. +*/ +SQLITE_PRIVATE void sqlite3PcacheStats( + int *pnCurrent, /* OUT: Total number of pages cached */ + int *pnMax, /* OUT: Global maximum cache size */ + int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */ + int *pnRecyclable /* OUT: Total number of pages available for recycling */ +){ + PgHdr1 *p; + int nRecyclable = 0; + for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){ + assert( p->isPinned==0 ); + nRecyclable++; + } + *pnCurrent = pcache1.grp.nCurrentPage; + *pnMax = (int)pcache1.grp.nMaxPage; + *pnMin = (int)pcache1.grp.nMinPage; + *pnRecyclable = nRecyclable; +} +#endif + +/************** End of pcache1.c *********************************************/ +/************** Begin file rowset.c ******************************************/ +/* +** 2008 December 3 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This module implements an object we call a "RowSet". +** +** The RowSet object is a collection of rowids. Rowids +** are inserted into the RowSet in an arbitrary order. Inserts +** can be intermixed with tests to see if a given rowid has been +** previously inserted into the RowSet. +** +** After all inserts are finished, it is possible to extract the +** elements of the RowSet in sorted order. Once this extraction +** process has started, no new elements may be inserted. +** +** Hence, the primitive operations for a RowSet are: +** +** CREATE +** INSERT +** TEST +** SMALLEST +** DESTROY +** +** The CREATE and DESTROY primitives are the constructor and destructor, +** obviously. The INSERT primitive adds a new element to the RowSet. +** TEST checks to see if an element is already in the RowSet. SMALLEST +** extracts the least value from the RowSet. +** +** The INSERT primitive might allocate additional memory. Memory is +** allocated in chunks so most INSERTs do no allocation. There is an +** upper bound on the size of allocated memory. No memory is freed +** until DESTROY. +** +** The TEST primitive includes a "batch" number. The TEST primitive +** will only see elements that were inserted before the last change +** in the batch number. In other words, if an INSERT occurs between +** two TESTs where the TESTs have the same batch nubmer, then the +** value added by the INSERT will not be visible to the second TEST. +** The initial batch number is zero, so if the very first TEST contains +** a non-zero batch number, it will see all prior INSERTs. +** +** No INSERTs may occurs after a SMALLEST. An assertion will fail if +** that is attempted. +** +** The cost of an INSERT is roughly constant. (Sometimes new memory +** has to be allocated on an INSERT.) The cost of a TEST with a new +** batch number is O(NlogN) where N is the number of elements in the RowSet. +** The cost of a TEST using the same batch number is O(logN). The cost +** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST +** primitives are constant time. The cost of DESTROY is O(N). +** +** There is an added cost of O(N) when switching between TEST and +** SMALLEST primitives. +*/ +/* #include "sqliteInt.h" */ + + +/* +** Target size for allocation chunks. +*/ +#define ROWSET_ALLOCATION_SIZE 1024 + +/* +** The number of rowset entries per allocation chunk. +*/ +#define ROWSET_ENTRY_PER_CHUNK \ + ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry)) + +/* +** Each entry in a RowSet is an instance of the following object. +** +** This same object is reused to store a linked list of trees of RowSetEntry +** objects. In that alternative use, pRight points to the next entry +** in the list, pLeft points to the tree, and v is unused. The +** RowSet.pForest value points to the head of this forest list. +*/ +struct RowSetEntry { + i64 v; /* ROWID value for this entry */ + struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */ + struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */ +}; + +/* +** RowSetEntry objects are allocated in large chunks (instances of the +** following structure) to reduce memory allocation overhead. The +** chunks are kept on a linked list so that they can be deallocated +** when the RowSet is destroyed. +*/ +struct RowSetChunk { + struct RowSetChunk *pNextChunk; /* Next chunk on list of them all */ + struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */ +}; + +/* +** A RowSet in an instance of the following structure. +** +** A typedef of this structure if found in sqliteInt.h. +*/ +struct RowSet { + struct RowSetChunk *pChunk; /* List of all chunk allocations */ + sqlite3 *db; /* The database connection */ + struct RowSetEntry *pEntry; /* List of entries using pRight */ + struct RowSetEntry *pLast; /* Last entry on the pEntry list */ + struct RowSetEntry *pFresh; /* Source of new entry objects */ + struct RowSetEntry *pForest; /* List of binary trees of entries */ + u16 nFresh; /* Number of objects on pFresh */ + u16 rsFlags; /* Various flags */ + int iBatch; /* Current insert batch */ +}; + +/* +** Allowed values for RowSet.rsFlags +*/ +#define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */ +#define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */ + +/* +** Turn bulk memory into a RowSet object. N bytes of memory +** are available at pSpace. The db pointer is used as a memory context +** for any subsequent allocations that need to occur. +** Return a pointer to the new RowSet object. +** +** It must be the case that N is sufficient to make a Rowset. If not +** an assertion fault occurs. +** +** If N is larger than the minimum, use the surplus as an initial +** allocation of entries available to be filled. +*/ +SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){ + RowSet *p; + assert( N >= ROUND8(sizeof(*p)) ); + p = pSpace; + p->pChunk = 0; + p->db = db; + p->pEntry = 0; + p->pLast = 0; + p->pForest = 0; + p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); + p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); + p->rsFlags = ROWSET_SORTED; + p->iBatch = 0; + return p; +} + +/* +** Deallocate all chunks from a RowSet. This frees all memory that +** the RowSet has allocated over its lifetime. This routine is +** the destructor for the RowSet. +*/ +SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){ + struct RowSetChunk *pChunk, *pNextChunk; + for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){ + pNextChunk = pChunk->pNextChunk; + sqlite3DbFree(p->db, pChunk); + } + p->pChunk = 0; + p->nFresh = 0; + p->pEntry = 0; + p->pLast = 0; + p->pForest = 0; + p->rsFlags = ROWSET_SORTED; +} + +/* +** Allocate a new RowSetEntry object that is associated with the +** given RowSet. Return a pointer to the new and completely uninitialized +** objected. +** +** In an OOM situation, the RowSet.db->mallocFailed flag is set and this +** routine returns NULL. +*/ +static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ + assert( p!=0 ); + if( p->nFresh==0 ){ + struct RowSetChunk *pNew; + pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); + if( pNew==0 ){ + return 0; + } + pNew->pNextChunk = p->pChunk; + p->pChunk = pNew; + p->pFresh = pNew->aEntry; + p->nFresh = ROWSET_ENTRY_PER_CHUNK; + } + p->nFresh--; + return p->pFresh++; +} + +/* +** Insert a new value into a RowSet. +** +** The mallocFailed flag of the database connection is set if a +** memory allocation fails. +*/ +SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){ + struct RowSetEntry *pEntry; /* The new entry */ + struct RowSetEntry *pLast; /* The last prior entry */ + + /* This routine is never called after sqlite3RowSetNext() */ + assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); + + pEntry = rowSetEntryAlloc(p); + if( pEntry==0 ) return; + pEntry->v = rowid; + pEntry->pRight = 0; + pLast = p->pLast; + if( pLast ){ + if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){ + p->rsFlags &= ~ROWSET_SORTED; + } + pLast->pRight = pEntry; + }else{ + p->pEntry = pEntry; + } + p->pLast = pEntry; +} + +/* +** Merge two lists of RowSetEntry objects. Remove duplicates. +** +** The input lists are connected via pRight pointers and are +** assumed to each already be in sorted order. +*/ +static struct RowSetEntry *rowSetEntryMerge( + struct RowSetEntry *pA, /* First sorted list to be merged */ + struct RowSetEntry *pB /* Second sorted list to be merged */ +){ + struct RowSetEntry head; + struct RowSetEntry *pTail; + + pTail = &head; + while( pA && pB ){ + assert( pA->pRight==0 || pA->v<=pA->pRight->v ); + assert( pB->pRight==0 || pB->v<=pB->pRight->v ); + if( pA->vv ){ + pTail->pRight = pA; + pA = pA->pRight; + pTail = pTail->pRight; + }else if( pB->vv ){ + pTail->pRight = pB; + pB = pB->pRight; + pTail = pTail->pRight; + }else{ + pA = pA->pRight; + } + } + if( pA ){ + assert( pA->pRight==0 || pA->v<=pA->pRight->v ); + pTail->pRight = pA; + }else{ + assert( pB==0 || pB->pRight==0 || pB->v<=pB->pRight->v ); + pTail->pRight = pB; + } + return head.pRight; +} + +/* +** Sort all elements on the list of RowSetEntry objects into order of +** increasing v. +*/ +static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){ + unsigned int i; + struct RowSetEntry *pNext, *aBucket[40]; + + memset(aBucket, 0, sizeof(aBucket)); + while( pIn ){ + pNext = pIn->pRight; + pIn->pRight = 0; + for(i=0; aBucket[i]; i++){ + pIn = rowSetEntryMerge(aBucket[i], pIn); + aBucket[i] = 0; + } + aBucket[i] = pIn; + pIn = pNext; + } + pIn = 0; + for(i=0; ipLeft ){ + struct RowSetEntry *p; + rowSetTreeToList(pIn->pLeft, ppFirst, &p); + p->pRight = pIn; + }else{ + *ppFirst = pIn; + } + if( pIn->pRight ){ + rowSetTreeToList(pIn->pRight, &pIn->pRight, ppLast); + }else{ + *ppLast = pIn; + } + assert( (*ppLast)->pRight==0 ); +} + + +/* +** Convert a sorted list of elements (connected by pRight) into a binary +** tree with depth of iDepth. A depth of 1 means the tree contains a single +** node taken from the head of *ppList. A depth of 2 means a tree with +** three nodes. And so forth. +** +** Use as many entries from the input list as required and update the +** *ppList to point to the unused elements of the list. If the input +** list contains too few elements, then construct an incomplete tree +** and leave *ppList set to NULL. +** +** Return a pointer to the root of the constructed binary tree. +*/ +static struct RowSetEntry *rowSetNDeepTree( + struct RowSetEntry **ppList, + int iDepth +){ + struct RowSetEntry *p; /* Root of the new tree */ + struct RowSetEntry *pLeft; /* Left subtree */ + if( *ppList==0 ){ + return 0; + } + if( iDepth==1 ){ + p = *ppList; + *ppList = p->pRight; + p->pLeft = p->pRight = 0; + return p; + } + pLeft = rowSetNDeepTree(ppList, iDepth-1); + p = *ppList; + if( p==0 ){ + return pLeft; + } + p->pLeft = pLeft; + *ppList = p->pRight; + p->pRight = rowSetNDeepTree(ppList, iDepth-1); + return p; +} + +/* +** Convert a sorted list of elements into a binary tree. Make the tree +** as deep as it needs to be in order to contain the entire list. +*/ +static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){ + int iDepth; /* Depth of the tree so far */ + struct RowSetEntry *p; /* Current tree root */ + struct RowSetEntry *pLeft; /* Left subtree */ + + assert( pList!=0 ); + p = pList; + pList = p->pRight; + p->pLeft = p->pRight = 0; + for(iDepth=1; pList; iDepth++){ + pLeft = p; + p = pList; + pList = p->pRight; + p->pLeft = pLeft; + p->pRight = rowSetNDeepTree(&pList, iDepth); + } + return p; +} + +/* +** Take all the entries on p->pEntry and on the trees in p->pForest and +** sort them all together into one big ordered list on p->pEntry. +** +** This routine should only be called once in the life of a RowSet. +*/ +static void rowSetToList(RowSet *p){ + + /* This routine is called only once */ + assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); + + if( (p->rsFlags & ROWSET_SORTED)==0 ){ + p->pEntry = rowSetEntrySort(p->pEntry); + } + + /* While this module could theoretically support it, sqlite3RowSetNext() + ** is never called after sqlite3RowSetText() for the same RowSet. So + ** there is never a forest to deal with. Should this change, simply + ** remove the assert() and the #if 0. */ + assert( p->pForest==0 ); +#if 0 + while( p->pForest ){ + struct RowSetEntry *pTree = p->pForest->pLeft; + if( pTree ){ + struct RowSetEntry *pHead, *pTail; + rowSetTreeToList(pTree, &pHead, &pTail); + p->pEntry = rowSetEntryMerge(p->pEntry, pHead); + } + p->pForest = p->pForest->pRight; + } +#endif + p->rsFlags |= ROWSET_NEXT; /* Verify this routine is never called again */ +} + +/* +** Extract the smallest element from the RowSet. +** Write the element into *pRowid. Return 1 on success. Return +** 0 if the RowSet is already empty. +** +** After this routine has been called, the sqlite3RowSetInsert() +** routine may not be called again. +*/ +SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ + assert( p!=0 ); + + /* Merge the forest into a single sorted list on first call */ + if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p); + + /* Return the next entry on the list */ + if( p->pEntry ){ + *pRowid = p->pEntry->v; + p->pEntry = p->pEntry->pRight; + if( p->pEntry==0 ){ + sqlite3RowSetClear(p); + } + return 1; + }else{ + return 0; + } +} + +/* +** Check to see if element iRowid was inserted into the rowset as +** part of any insert batch prior to iBatch. Return 1 or 0. +** +** If this is the first test of a new batch and if there exist entries +** on pRowSet->pEntry, then sort those entries into the forest at +** pRowSet->pForest so that they can be tested. +*/ +SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){ + struct RowSetEntry *p, *pTree; + + /* This routine is never called after sqlite3RowSetNext() */ + assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 ); + + /* Sort entries into the forest on the first test of a new batch + */ + if( iBatch!=pRowSet->iBatch ){ + p = pRowSet->pEntry; + if( p ){ + struct RowSetEntry **ppPrevTree = &pRowSet->pForest; + if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ + p = rowSetEntrySort(p); + } + for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ + ppPrevTree = &pTree->pRight; + if( pTree->pLeft==0 ){ + pTree->pLeft = rowSetListToTree(p); + break; + }else{ + struct RowSetEntry *pAux, *pTail; + rowSetTreeToList(pTree->pLeft, &pAux, &pTail); + pTree->pLeft = 0; + p = rowSetEntryMerge(pAux, p); + } + } + if( pTree==0 ){ + *ppPrevTree = pTree = rowSetEntryAlloc(pRowSet); + if( pTree ){ + pTree->v = 0; + pTree->pRight = 0; + pTree->pLeft = rowSetListToTree(p); + } + } + pRowSet->pEntry = 0; + pRowSet->pLast = 0; + pRowSet->rsFlags |= ROWSET_SORTED; + } + pRowSet->iBatch = iBatch; + } + + /* Test to see if the iRowid value appears anywhere in the forest. + ** Return 1 if it does and 0 if not. + */ + for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ + p = pTree->pLeft; + while( p ){ + if( p->vpRight; + }else if( p->v>iRowid ){ + p = p->pLeft; + }else{ + return 1; + } + } + } + return 0; +} + +/************** End of rowset.c **********************************************/ +/************** Begin file pager.c *******************************************/ +/* +** 2001 September 15 +** +** 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 is the implementation of the page cache subsystem or "pager". +** +** The pager is used to access a database disk file. It implements +** atomic commit and rollback through the use of a journal file that +** is separate from the database file. The pager also implements file +** locking to prevent two processes from writing the same database +** file simultaneously, or one process from reading the database while +** another is writing. +*/ +#ifndef SQLITE_OMIT_DISKIO +/* #include "sqliteInt.h" */ +/************** Include wal.h in the middle of pager.c ***********************/ +/************** Begin file wal.h *********************************************/ +/* +** 2010 February 1 +** +** 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 to the write-ahead logging +** system. Refer to the comments below and the header comment attached to +** the implementation of each function in log.c for further details. +*/ + +#ifndef _WAL_H_ +#define _WAL_H_ + +/* #include "sqliteInt.h" */ + +/* Additional values that can be added to the sync_flags argument of +** sqlite3WalFrames(): +*/ +#define WAL_SYNC_TRANSACTIONS 0x20 /* Sync at the end of each transaction */ +#define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ + +#ifdef SQLITE_OMIT_WAL +# define sqlite3WalOpen(x,y,z) 0 +# define sqlite3WalLimit(x,y) +# define sqlite3WalClose(w,x,y,z) 0 +# define sqlite3WalBeginReadTransaction(y,z) 0 +# define sqlite3WalEndReadTransaction(z) +# define sqlite3WalDbsize(y) 0 +# define sqlite3WalBeginWriteTransaction(y) 0 +# define sqlite3WalEndWriteTransaction(x) 0 +# define sqlite3WalUndo(x,y,z) 0 +# define sqlite3WalSavepoint(y,z) +# define sqlite3WalSavepointUndo(y,z) 0 +# define sqlite3WalFrames(u,v,w,x,y,z) 0 +# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 +# define sqlite3WalCallback(z) 0 +# define sqlite3WalExclusiveMode(y,z) 0 +# define sqlite3WalHeapMemory(z) 0 +# define sqlite3WalFramesize(z) 0 +# define sqlite3WalFindFrame(x,y,z) 0 +#else + +#define WAL_SAVEPOINT_NDATA 4 + +/* Connection to a write-ahead log (WAL) file. +** There is one object of this type for each pager. +*/ +typedef struct Wal Wal; + +/* Open and close a connection to a write-ahead log. */ +SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**); +SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *); + +/* Set the limiting size of a WAL file. */ +SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64); + +/* Used by readers to open (lock) and close (unlock) a snapshot. A +** snapshot is like a read-transaction. It is the state of the database +** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and +** preserves the current state even if the other threads or processes +** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the +** transaction and releases the lock. +*/ +SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *); +SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal); + +/* Read a page from the write-ahead log, if it is present. */ +SQLITE_PRIVATE int sqlite3WalFindFrame(Wal *, Pgno, u32 *); +SQLITE_PRIVATE int sqlite3WalReadFrame(Wal *, u32, int, u8 *); + +/* If the WAL is not empty, return the size of the database. */ +SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal); + +/* Obtain or release the WRITER lock. */ +SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal); +SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal); + +/* Undo any frames written (but not committed) to the log */ +SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx); + +/* Return an integer that records the current (uncommitted) write +** position in the WAL */ +SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData); + +/* Move the write position of the WAL back to iFrame. Called in +** response to a ROLLBACK TO command. */ +SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData); + +/* Write a frame or frames to the log. */ +SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); + +/* Copy pages from the log to the database file */ +SQLITE_PRIVATE int sqlite3WalCheckpoint( + Wal *pWal, /* Write-ahead log connection */ + int eMode, /* One of PASSIVE, FULL and RESTART */ + int (*xBusy)(void*), /* Function to call when busy */ + void *pBusyArg, /* Context argument for xBusyHandler */ + int sync_flags, /* Flags to sync db file with (or 0) */ + int nBuf, /* Size of buffer nBuf */ + u8 *zBuf, /* Temporary buffer to use */ + int *pnLog, /* OUT: Number of frames in WAL */ + int *pnCkpt /* OUT: Number of backfilled frames in WAL */ +); + +/* Return the value to pass to a sqlite3_wal_hook callback, the +** number of frames in the WAL at the point of the last commit since +** sqlite3WalCallback() was called. If no commits have occurred since +** the last call, then return 0. +*/ +SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal); + +/* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released) +** by the pager layer on the database file. +*/ +SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op); + +/* Return true if the argument is non-NULL and the WAL module is using +** heap-memory for the wal-index. Otherwise, if the argument is NULL or the +** WAL module is using shared-memory, return false. +*/ +SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal); + +#ifdef SQLITE_ENABLE_ZIPVFS +/* If the WAL file is not empty, return the number of bytes of content +** stored in each frame (i.e. the db page-size when the WAL was created). +*/ +SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal); +#endif + +#endif /* ifndef SQLITE_OMIT_WAL */ +#endif /* _WAL_H_ */ + +/************** End of wal.h *************************************************/ +/************** Continuing where we left off in pager.c **********************/ + + +/******************* NOTES ON THE DESIGN OF THE PAGER ************************ +** +** This comment block describes invariants that hold when using a rollback +** journal. These invariants do not apply for journal_mode=WAL, +** journal_mode=MEMORY, or journal_mode=OFF. +** +** Within this comment block, a page is deemed to have been synced +** automatically as soon as it is written when PRAGMA synchronous=OFF. +** Otherwise, the page is not synced until the xSync method of the VFS +** is called successfully on the file containing the page. +** +** Definition: A page of the database file is said to be "overwriteable" if +** one or more of the following are true about the page: +** +** (a) The original content of the page as it was at the beginning of +** the transaction has been written into the rollback journal and +** synced. +** +** (b) The page was a freelist leaf page at the start of the transaction. +** +** (c) The page number is greater than the largest page that existed in +** the database file at the start of the transaction. +** +** (1) A page of the database file is never overwritten unless one of the +** following are true: +** +** (a) The page and all other pages on the same sector are overwriteable. +** +** (b) The atomic page write optimization is enabled, and the entire +** transaction other than the update of the transaction sequence +** number consists of a single page change. +** +** (2) The content of a page written into the rollback journal exactly matches +** both the content in the database when the rollback journal was written +** and the content in the database at the beginning of the current +** transaction. +** +** (3) Writes to the database file are an integer multiple of the page size +** in length and are aligned on a page boundary. +** +** (4) Reads from the database file are either aligned on a page boundary and +** an integer multiple of the page size in length or are taken from the +** first 100 bytes of the database file. +** +** (5) All writes to the database file are synced prior to the rollback journal +** being deleted, truncated, or zeroed. +** +** (6) If a master journal file is used, then all writes to the database file +** are synced prior to the master journal being deleted. +** +** Definition: Two databases (or the same database at two points it time) +** are said to be "logically equivalent" if they give the same answer to +** all queries. Note in particular the content of freelist leaf +** pages can be changed arbitrarily without affecting the logical equivalence +** of the database. +** +** (7) At any time, if any subset, including the empty set and the total set, +** of the unsynced changes to a rollback journal are removed and the +** journal is rolled back, the resulting database file will be logically +** equivalent to the database file at the beginning of the transaction. +** +** (8) When a transaction is rolled back, the xTruncate method of the VFS +** is called to restore the database file to the same size it was at +** the beginning of the transaction. (In some VFSes, the xTruncate +** method is a no-op, but that does not change the fact the SQLite will +** invoke it.) +** +** (9) Whenever the database file is modified, at least one bit in the range +** of bytes from 24 through 39 inclusive will be changed prior to releasing +** the EXCLUSIVE lock, thus signaling other connections on the same +** database to flush their caches. +** +** (10) The pattern of bits in bytes 24 through 39 shall not repeat in less +** than one billion transactions. +** +** (11) A database file is well-formed at the beginning and at the conclusion +** of every transaction. +** +** (12) An EXCLUSIVE lock is held on the database file when writing to +** the database file. +** +** (13) A SHARED lock is held on the database file while reading any +** content out of the database file. +** +******************************************************************************/ + +/* +** Macros for troubleshooting. Normally turned off +*/ +#if 0 +int sqlite3PagerTrace=1; /* True to enable tracing */ +#define sqlite3DebugPrintf printf +#define PAGERTRACE(X) if( sqlite3PagerTrace ){ sqlite3DebugPrintf X; } +#else +#define PAGERTRACE(X) +#endif + +/* +** The following two macros are used within the PAGERTRACE() macros above +** to print out file-descriptors. +** +** PAGERID() takes a pointer to a Pager struct as its argument. The +** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file +** struct as its argument. +*/ +#define PAGERID(p) ((int)(p->fd)) +#define FILEHANDLEID(fd) ((int)fd) + +/* +** The Pager.eState variable stores the current 'state' of a pager. A +** pager may be in any one of the seven states shown in the following +** state diagram. +** +** OPEN <------+------+ +** | | | +** V | | +** +---------> READER-------+ | +** | | | +** | V | +** |<-------WRITER_LOCKED------> ERROR +** | | ^ +** | V | +** |<------WRITER_CACHEMOD-------->| +** | | | +** | V | +** |<-------WRITER_DBMOD---------->| +** | | | +** | V | +** +<------WRITER_FINISHED-------->+ +** +** +** List of state transitions and the C [function] that performs each: +** +** OPEN -> READER [sqlite3PagerSharedLock] +** READER -> OPEN [pager_unlock] +** +** READER -> WRITER_LOCKED [sqlite3PagerBegin] +** WRITER_LOCKED -> WRITER_CACHEMOD [pager_open_journal] +** WRITER_CACHEMOD -> WRITER_DBMOD [syncJournal] +** WRITER_DBMOD -> WRITER_FINISHED [sqlite3PagerCommitPhaseOne] +** WRITER_*** -> READER [pager_end_transaction] +** +** WRITER_*** -> ERROR [pager_error] +** ERROR -> OPEN [pager_unlock] +** +** +** OPEN: +** +** The pager starts up in this state. Nothing is guaranteed in this +** state - the file may or may not be locked and the database size is +** unknown. The database may not be read or written. +** +** * No read or write transaction is active. +** * Any lock, or no lock at all, may be held on the database file. +** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted. +** +** READER: +** +** In this state all the requirements for reading the database in +** rollback (non-WAL) mode are met. Unless the pager is (or recently +** was) in exclusive-locking mode, a user-level read transaction is +** open. The database size is known in this state. +** +** A connection running with locking_mode=normal enters this state when +** it opens a read-transaction on the database and returns to state +** OPEN after the read-transaction is completed. However a connection +** running in locking_mode=exclusive (including temp databases) remains in +** this state even after the read-transaction is closed. The only way +** a locking_mode=exclusive connection can transition from READER to OPEN +** is via the ERROR state (see below). +** +** * A read transaction may be active (but a write-transaction cannot). +** * A SHARED or greater lock is held on the database file. +** * The dbSize variable may be trusted (even if a user-level read +** transaction is not active). The dbOrigSize and dbFileSize variables +** may not be trusted at this point. +** * If the database is a WAL database, then the WAL connection is open. +** * Even if a read-transaction is not open, it is guaranteed that +** there is no hot-journal in the file-system. +** +** WRITER_LOCKED: +** +** The pager moves to this state from READER when a write-transaction +** is first opened on the database. In WRITER_LOCKED state, all locks +** required to start a write-transaction are held, but no actual +** modifications to the cache or database have taken place. +** +** In rollback mode, a RESERVED or (if the transaction was opened with +** BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when +** moving to this state, but the journal file is not written to or opened +** to in this state. If the transaction is committed or rolled back while +** in WRITER_LOCKED state, all that is required is to unlock the database +** file. +** +** IN WAL mode, WalBeginWriteTransaction() is called to lock the log file. +** If the connection is running with locking_mode=exclusive, an attempt +** is made to obtain an EXCLUSIVE lock on the database file. +** +** * A write transaction is active. +** * If the connection is open in rollback-mode, a RESERVED or greater +** lock is held on the database file. +** * If the connection is open in WAL-mode, a WAL write transaction +** is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully +** called). +** * The dbSize, dbOrigSize and dbFileSize variables are all valid. +** * The contents of the pager cache have not been modified. +** * The journal file may or may not be open. +** * Nothing (not even the first header) has been written to the journal. +** +** WRITER_CACHEMOD: +** +** A pager moves from WRITER_LOCKED state to this state when a page is +** first modified by the upper layer. In rollback mode the journal file +** is opened (if it is not already open) and a header written to the +** start of it. The database file on disk has not been modified. +** +** * A write transaction is active. +** * A RESERVED or greater lock is held on the database file. +** * The journal file is open and the first header has been written +** to it, but the header has not been synced to disk. +** * The contents of the page cache have been modified. +** +** WRITER_DBMOD: +** +** The pager transitions from WRITER_CACHEMOD into WRITER_DBMOD state +** when it modifies the contents of the database file. WAL connections +** never enter this state (since they do not modify the database file, +** just the log file). +** +** * A write transaction is active. +** * An EXCLUSIVE or greater lock is held on the database file. +** * The journal file is open and the first header has been written +** and synced to disk. +** * The contents of the page cache have been modified (and possibly +** written to disk). +** +** WRITER_FINISHED: +** +** It is not possible for a WAL connection to enter this state. +** +** A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD +** state after the entire transaction has been successfully written into the +** database file. In this state the transaction may be committed simply +** by finalizing the journal file. Once in WRITER_FINISHED state, it is +** not possible to modify the database further. At this point, the upper +** layer must either commit or rollback the transaction. +** +** * A write transaction is active. +** * An EXCLUSIVE or greater lock is held on the database file. +** * All writing and syncing of journal and database data has finished. +** If no error occurred, all that remains is to finalize the journal to +** commit the transaction. If an error did occur, the caller will need +** to rollback the transaction. +** +** ERROR: +** +** The ERROR state is entered when an IO or disk-full error (including +** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it +** difficult to be sure that the in-memory pager state (cache contents, +** db size etc.) are consistent with the contents of the file-system. +** +** Temporary pager files may enter the ERROR state, but in-memory pagers +** cannot. +** +** For example, if an IO error occurs while performing a rollback, +** the contents of the page-cache may be left in an inconsistent state. +** At this point it would be dangerous to change back to READER state +** (as usually happens after a rollback). Any subsequent readers might +** report database corruption (due to the inconsistent cache), and if +** they upgrade to writers, they may inadvertently corrupt the database +** file. To avoid this hazard, the pager switches into the ERROR state +** instead of READER following such an error. +** +** Once it has entered the ERROR state, any attempt to use the pager +** to read or write data returns an error. Eventually, once all +** outstanding transactions have been abandoned, the pager is able to +** transition back to OPEN state, discarding the contents of the +** page-cache and any other in-memory state at the same time. Everything +** is reloaded from disk (and, if necessary, hot-journal rollback peformed) +** when a read-transaction is next opened on the pager (transitioning +** the pager into READER state). At that point the system has recovered +** from the error. +** +** Specifically, the pager jumps into the ERROR state if: +** +** 1. An error occurs while attempting a rollback. This happens in +** function sqlite3PagerRollback(). +** +** 2. An error occurs while attempting to finalize a journal file +** following a commit in function sqlite3PagerCommitPhaseTwo(). +** +** 3. An error occurs while attempting to write to the journal or +** database file in function pagerStress() in order to free up +** memory. +** +** In other cases, the error is returned to the b-tree layer. The b-tree +** layer then attempts a rollback operation. If the error condition +** persists, the pager enters the ERROR state via condition (1) above. +** +** Condition (3) is necessary because it can be triggered by a read-only +** statement executed within a transaction. In this case, if the error +** code were simply returned to the user, the b-tree layer would not +** automatically attempt a rollback, as it assumes that an error in a +** read-only statement cannot leave the pager in an internally inconsistent +** state. +** +** * The Pager.errCode variable is set to something other than SQLITE_OK. +** * There are one or more outstanding references to pages (after the +** last reference is dropped the pager should move back to OPEN state). +** * The pager is not an in-memory pager. +** +** +** Notes: +** +** * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the +** connection is open in WAL mode. A WAL connection is always in one +** of the first four states. +** +** * Normally, a connection open in exclusive mode is never in PAGER_OPEN +** state. There are two exceptions: immediately after exclusive-mode has +** been turned on (and before any read or write transactions are +** executed), and when the pager is leaving the "error state". +** +** * See also: assert_pager_state(). +*/ +#define PAGER_OPEN 0 +#define PAGER_READER 1 +#define PAGER_WRITER_LOCKED 2 +#define PAGER_WRITER_CACHEMOD 3 +#define PAGER_WRITER_DBMOD 4 +#define PAGER_WRITER_FINISHED 5 +#define PAGER_ERROR 6 + +/* +** The Pager.eLock variable is almost always set to one of the +** following locking-states, according to the lock currently held on +** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK. +** This variable is kept up to date as locks are taken and released by +** the pagerLockDb() and pagerUnlockDb() wrappers. +** +** If the VFS xLock() or xUnlock() returns an error other than SQLITE_BUSY +** (i.e. one of the SQLITE_IOERR subtypes), it is not clear whether or not +** the operation was successful. In these circumstances pagerLockDb() and +** pagerUnlockDb() take a conservative approach - eLock is always updated +** when unlocking the file, and only updated when locking the file if the +** VFS call is successful. This way, the Pager.eLock variable may be set +** to a less exclusive (lower) value than the lock that is actually held +** at the system level, but it is never set to a more exclusive value. +** +** This is usually safe. If an xUnlock fails or appears to fail, there may +** be a few redundant xLock() calls or a lock may be held for longer than +** required, but nothing really goes wrong. +** +** The exception is when the database file is unlocked as the pager moves +** from ERROR to OPEN state. At this point there may be a hot-journal file +** in the file-system that needs to be rolled back (as part of an OPEN->SHARED +** transition, by the same pager or any other). If the call to xUnlock() +** fails at this point and the pager is left holding an EXCLUSIVE lock, this +** can confuse the call to xCheckReservedLock() call made later as part +** of hot-journal detection. +** +** xCheckReservedLock() is defined as returning true "if there is a RESERVED +** lock held by this process or any others". So xCheckReservedLock may +** return true because the caller itself is holding an EXCLUSIVE lock (but +** doesn't know it because of a previous error in xUnlock). If this happens +** a hot-journal may be mistaken for a journal being created by an active +** transaction in another process, causing SQLite to read from the database +** without rolling it back. +** +** To work around this, if a call to xUnlock() fails when unlocking the +** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It +** is only changed back to a real locking state after a successful call +** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition +** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK +** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE +** lock on the database file before attempting to roll it back. See function +** PagerSharedLock() for more detail. +** +** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in +** PAGER_OPEN state. +*/ +#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1) + +/* +** A macro used for invoking the codec if there is one +*/ +#ifdef SQLITE_HAS_CODEC +# define CODEC1(P,D,N,X,E) \ + if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; } +# define CODEC2(P,D,N,X,E,O) \ + if( P->xCodec==0 ){ O=(char*)D; }else \ + if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; } +#else +# define CODEC1(P,D,N,X,E) /* NO-OP */ +# define CODEC2(P,D,N,X,E,O) O=(char*)D +#endif + +/* +** The maximum allowed sector size. 64KiB. If the xSectorsize() method +** returns a value larger than this, then MAX_SECTOR_SIZE is used instead. +** This could conceivably cause corruption following a power failure on +** such a system. This is currently an undocumented limit. +*/ +#define MAX_SECTOR_SIZE 0x10000 + +/* +** An instance of the following structure is allocated for each active +** savepoint and statement transaction in the system. All such structures +** are stored in the Pager.aSavepoint[] array, which is allocated and +** resized using sqlite3Realloc(). +** +** When a savepoint is created, the PagerSavepoint.iHdrOffset field is +** set to 0. If a journal-header is written into the main journal while +** the savepoint is active, then iHdrOffset is set to the byte offset +** immediately following the last journal record written into the main +** journal before the journal-header. This is required during savepoint +** rollback (see pagerPlaybackSavepoint()). +*/ +typedef struct PagerSavepoint PagerSavepoint; +struct PagerSavepoint { + i64 iOffset; /* Starting offset in main journal */ + i64 iHdrOffset; /* See above */ + Bitvec *pInSavepoint; /* Set of pages in this savepoint */ + Pgno nOrig; /* Original number of pages in file */ + Pgno iSubRec; /* Index of first record in sub-journal */ +#ifndef SQLITE_OMIT_WAL + u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */ +#endif +}; + +/* +** Bits of the Pager.doNotSpill flag. See further description below. +*/ +#define SPILLFLAG_OFF 0x01 /* Never spill cache. Set via pragma */ +#define SPILLFLAG_ROLLBACK 0x02 /* Current rolling back, so do not spill */ +#define SPILLFLAG_NOSYNC 0x04 /* Spill is ok, but do not sync */ + +/* +** An open page cache is an instance of struct Pager. A description of +** some of the more important member variables follows: +** +** eState +** +** The current 'state' of the pager object. See the comment and state +** diagram above for a description of the pager state. +** +** eLock +** +** For a real on-disk database, the current lock held on the database file - +** NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK. +** +** For a temporary or in-memory database (neither of which require any +** locks), this variable is always set to EXCLUSIVE_LOCK. Since such +** databases always have Pager.exclusiveMode==1, this tricks the pager +** logic into thinking that it already has all the locks it will ever +** need (and no reason to release them). +** +** In some (obscure) circumstances, this variable may also be set to +** UNKNOWN_LOCK. See the comment above the #define of UNKNOWN_LOCK for +** details. +** +** changeCountDone +** +** This boolean variable is used to make sure that the change-counter +** (the 4-byte header field at byte offset 24 of the database file) is +** not updated more often than necessary. +** +** It is set to true when the change-counter field is updated, which +** can only happen if an exclusive lock is held on the database file. +** It is cleared (set to false) whenever an exclusive lock is +** relinquished on the database file. Each time a transaction is committed, +** The changeCountDone flag is inspected. If it is true, the work of +** updating the change-counter is omitted for the current transaction. +** +** This mechanism means that when running in exclusive mode, a connection +** need only update the change-counter once, for the first transaction +** committed. +** +** setMaster +** +** When PagerCommitPhaseOne() is called to commit a transaction, it may +** (or may not) specify a master-journal name to be written into the +** journal file before it is synced to disk. +** +** Whether or not a journal file contains a master-journal pointer affects +** the way in which the journal file is finalized after the transaction is +** committed or rolled back when running in "journal_mode=PERSIST" mode. +** If a journal file does not contain a master-journal pointer, it is +** finalized by overwriting the first journal header with zeroes. If +** it does contain a master-journal pointer the journal file is finalized +** by truncating it to zero bytes, just as if the connection were +** running in "journal_mode=truncate" mode. +** +** Journal files that contain master journal pointers cannot be finalized +** simply by overwriting the first journal-header with zeroes, as the +** master journal pointer could interfere with hot-journal rollback of any +** subsequently interrupted transaction that reuses the journal file. +** +** The flag is cleared as soon as the journal file is finalized (either +** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the +** journal file from being successfully finalized, the setMaster flag +** is cleared anyway (and the pager will move to ERROR state). +** +** doNotSpill +** +** This variables control the behavior of cache-spills (calls made by +** the pcache module to the pagerStress() routine to write cached data +** to the file-system in order to free up memory). +** +** When bits SPILLFLAG_OFF or SPILLFLAG_ROLLBACK of doNotSpill are set, +** writing to the database from pagerStress() is disabled altogether. +** The SPILLFLAG_ROLLBACK case is done in a very obscure case that +** comes up during savepoint rollback that requires the pcache module +** to allocate a new page to prevent the journal file from being written +** while it is being traversed by code in pager_playback(). The SPILLFLAG_OFF +** case is a user preference. +** +** If the SPILLFLAG_NOSYNC bit is set, writing to the database from +** pagerStress() is permitted, but syncing the journal file is not. +** This flag is set by sqlite3PagerWrite() when the file-system sector-size +** is larger than the database page-size in order to prevent a journal sync +** from happening in between the journalling of two pages on the same sector. +** +** subjInMemory +** +** This is a boolean variable. If true, then any required sub-journal +** is opened as an in-memory journal file. If false, then in-memory +** sub-journals are only used for in-memory pager files. +** +** This variable is updated by the upper layer each time a new +** write-transaction is opened. +** +** dbSize, dbOrigSize, dbFileSize +** +** Variable dbSize is set to the number of pages in the database file. +** It is valid in PAGER_READER and higher states (all states except for +** OPEN and ERROR). +** +** dbSize is set based on the size of the database file, which may be +** larger than the size of the database (the value stored at offset +** 28 of the database header by the btree). If the size of the file +** is not an integer multiple of the page-size, the value stored in +** dbSize is rounded down (i.e. a 5KB file with 2K page-size has dbSize==2). +** Except, any file that is greater than 0 bytes in size is considered +** to have at least one page. (i.e. a 1KB file with 2K page-size leads +** to dbSize==1). +** +** During a write-transaction, if pages with page-numbers greater than +** dbSize are modified in the cache, dbSize is updated accordingly. +** Similarly, if the database is truncated using PagerTruncateImage(), +** dbSize is updated. +** +** Variables dbOrigSize and dbFileSize are valid in states +** PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize +** variable at the start of the transaction. It is used during rollback, +** and to determine whether or not pages need to be journalled before +** being modified. +** +** Throughout a write-transaction, dbFileSize contains the size of +** the file on disk in pages. It is set to a copy of dbSize when the +** write-transaction is first opened, and updated when VFS calls are made +** to write or truncate the database file on disk. +** +** The only reason the dbFileSize variable is required is to suppress +** unnecessary calls to xTruncate() after committing a transaction. If, +** when a transaction is committed, the dbFileSize variable indicates +** that the database file is larger than the database image (Pager.dbSize), +** pager_truncate() is called. The pager_truncate() call uses xFilesize() +** to measure the database file on disk, and then truncates it if required. +** dbFileSize is not used when rolling back a transaction. In this case +** pager_truncate() is called unconditionally (which means there may be +** a call to xFilesize() that is not strictly required). In either case, +** pager_truncate() may cause the file to become smaller or larger. +** +** dbHintSize +** +** The dbHintSize variable is used to limit the number of calls made to +** the VFS xFileControl(FCNTL_SIZE_HINT) method. +** +** dbHintSize is set to a copy of the dbSize variable when a +** write-transaction is opened (at the same time as dbFileSize and +** dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called, +** dbHintSize is increased to the number of pages that correspond to the +** size-hint passed to the method call. See pager_write_pagelist() for +** details. +** +** errCode +** +** The Pager.errCode variable is only ever used in PAGER_ERROR state. It +** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode +** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX +** sub-codes. +*/ +struct Pager { + sqlite3_vfs *pVfs; /* OS functions to use for IO */ + u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ + u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ + u8 useJournal; /* Use a rollback journal on this file */ + u8 noSync; /* Do not sync the journal if true */ + u8 fullSync; /* Do extra syncs of the journal for robustness */ + u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ + u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */ + u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ + u8 tempFile; /* zFilename is a temporary or immutable file */ + u8 noLock; /* Do not lock (except in WAL mode) */ + u8 readOnly; /* True for a read-only database */ + u8 memDb; /* True to inhibit all file I/O */ + + /************************************************************************** + ** The following block contains those class members that change during + ** routine operation. Class members not in this block are either fixed + ** when the pager is first created or else only change when there is a + ** significant mode change (such as changing the page_size, locking_mode, + ** or the journal_mode). From another view, these class members describe + ** the "state" of the pager, while other class members describe the + ** "configuration" of the pager. + */ + u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */ + u8 eLock; /* Current lock held on database file */ + u8 changeCountDone; /* Set after incrementing the change-counter */ + u8 setMaster; /* True if a m-j name has been written to jrnl */ + u8 doNotSpill; /* Do not spill the cache when non-zero */ + u8 subjInMemory; /* True to use in-memory sub-journals */ + u8 bUseFetch; /* True to use xFetch() */ + u8 hasBeenUsed; /* True if any content previously read */ + Pgno dbSize; /* Number of pages in the database */ + Pgno dbOrigSize; /* dbSize before the current transaction */ + Pgno dbFileSize; /* Number of pages in the database file */ + Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */ + int errCode; /* One of several kinds of errors */ + int nRec; /* Pages journalled since last j-header written */ + u32 cksumInit; /* Quasi-random value added to every checksum */ + u32 nSubRec; /* Number of records written to sub-journal */ + Bitvec *pInJournal; /* One bit for each page in the database file */ + sqlite3_file *fd; /* File descriptor for database */ + sqlite3_file *jfd; /* File descriptor for main journal */ + sqlite3_file *sjfd; /* File descriptor for sub-journal */ + i64 journalOff; /* Current write offset in the journal file */ + i64 journalHdr; /* Byte offset to previous journal header */ + sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ + PagerSavepoint *aSavepoint; /* Array of active savepoints */ + int nSavepoint; /* Number of elements in aSavepoint[] */ + u32 iDataVersion; /* Changes whenever database content changes */ + char dbFileVers[16]; /* Changes whenever database file changes */ + + int nMmapOut; /* Number of mmap pages currently outstanding */ + sqlite3_int64 szMmap; /* Desired maximum mmap size */ + PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */ + /* + ** End of the routinely-changing class members + ***************************************************************************/ + + u16 nExtra; /* Add this many bytes to each in-memory page */ + i16 nReserve; /* Number of unused bytes at end of each page */ + u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ + u32 sectorSize; /* Assumed sector size during rollback */ + int pageSize; /* Number of bytes in a page */ + Pgno mxPgno; /* Maximum allowed size of the database */ + i64 journalSizeLimit; /* Size limit for persistent journal files */ + char *zFilename; /* Name of the database file */ + char *zJournal; /* Name of the journal file */ + int (*xBusyHandler)(void*); /* Function to call when busy */ + void *pBusyHandlerArg; /* Context argument for xBusyHandler */ + int aStat[3]; /* Total cache hits, misses and writes */ +#ifdef SQLITE_TEST + int nRead; /* Database pages read */ +#endif + void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */ +#ifdef SQLITE_HAS_CODEC + void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ + void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */ + void (*xCodecFree)(void*); /* Destructor for the codec */ + void *pCodec; /* First argument to xCodec... methods */ +#endif + char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ + PCache *pPCache; /* Pointer to page cache object */ +#ifndef SQLITE_OMIT_WAL + Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */ + char *zWal; /* File name for write-ahead log */ +#endif +}; + +/* +** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains +** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS +** or CACHE_WRITE to sqlite3_db_status(). +*/ +#define PAGER_STAT_HIT 0 +#define PAGER_STAT_MISS 1 +#define PAGER_STAT_WRITE 2 + +/* +** The following global variables hold counters used for +** testing purposes only. These variables do not exist in +** a non-testing build. These variables are not thread-safe. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */ +SQLITE_API int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */ +SQLITE_API int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */ +# define PAGER_INCR(v) v++ +#else +# define PAGER_INCR(v) +#endif + + + +/* +** Journal files begin with the following magic string. The data +** was obtained from /dev/random. It is used only as a sanity check. +** +** Since version 2.8.0, the journal format contains additional sanity +** checking information. If the power fails while the journal is being +** written, semi-random garbage data might appear in the journal +** file after power is restored. If an attempt is then made +** to roll the journal back, the database could be corrupted. The additional +** sanity checking data is an attempt to discover the garbage in the +** journal and ignore it. +** +** The sanity checking information for the new journal format consists +** of a 32-bit checksum on each page of data. The checksum covers both +** the page number and the pPager->pageSize bytes of data for the page. +** This cksum is initialized to a 32-bit random value that appears in the +** journal file right after the header. The random initializer is important, +** because garbage data that appears at the end of a journal is likely +** data that was once in other files that have now been deleted. If the +** garbage data came from an obsolete journal file, the checksums might +** be correct. But by initializing the checksum to random value which +** is different for every journal, we minimize that risk. +*/ +static const unsigned char aJournalMagic[] = { + 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7, +}; + +/* +** The size of the of each page record in the journal is given by +** the following macro. +*/ +#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8) + +/* +** The journal header size for this pager. This is usually the same +** size as a single disk sector. See also setSectorSize(). +*/ +#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize) + +/* +** The macro MEMDB is true if we are dealing with an in-memory database. +** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set, +** the value of MEMDB will be a constant and the compiler will optimize +** out code that would never execute. +*/ +#ifdef SQLITE_OMIT_MEMORYDB +# define MEMDB 0 +#else +# define MEMDB pPager->memDb +#endif + +/* +** The macro USEFETCH is true if we are allowed to use the xFetch and xUnfetch +** interfaces to access the database using memory-mapped I/O. +*/ +#if SQLITE_MAX_MMAP_SIZE>0 +# define USEFETCH(x) ((x)->bUseFetch) +#else +# define USEFETCH(x) 0 +#endif + +/* +** The maximum legal page number is (2^31 - 1). +*/ +#define PAGER_MAX_PGNO 2147483647 + +/* +** The argument to this macro is a file descriptor (type sqlite3_file*). +** Return 0 if it is not open, or non-zero (but not 1) if it is. +** +** This is so that expressions can be written as: +** +** if( isOpen(pPager->jfd) ){ ... +** +** instead of +** +** if( pPager->jfd->pMethods ){ ... +*/ +#define isOpen(pFd) ((pFd)->pMethods!=0) + +/* +** Return true if this pager uses a write-ahead log instead of the usual +** rollback journal. Otherwise false. +*/ +#ifndef SQLITE_OMIT_WAL +static int pagerUseWal(Pager *pPager){ + return (pPager->pWal!=0); +} +#else +# define pagerUseWal(x) 0 +# define pagerRollbackWal(x) 0 +# define pagerWalFrames(v,w,x,y) 0 +# define pagerOpenWalIfPresent(z) SQLITE_OK +# define pagerBeginReadTransaction(z) SQLITE_OK +#endif + +#ifndef NDEBUG +/* +** Usage: +** +** assert( assert_pager_state(pPager) ); +** +** This function runs many asserts to try to find inconsistencies in +** the internal state of the Pager object. +*/ +static int assert_pager_state(Pager *p){ + Pager *pPager = p; + + /* State must be valid. */ + assert( p->eState==PAGER_OPEN + || p->eState==PAGER_READER + || p->eState==PAGER_WRITER_LOCKED + || p->eState==PAGER_WRITER_CACHEMOD + || p->eState==PAGER_WRITER_DBMOD + || p->eState==PAGER_WRITER_FINISHED + || p->eState==PAGER_ERROR + ); + + /* Regardless of the current state, a temp-file connection always behaves + ** as if it has an exclusive lock on the database file. It never updates + ** the change-counter field, so the changeCountDone flag is always set. + */ + assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK ); + assert( p->tempFile==0 || pPager->changeCountDone ); + + /* If the useJournal flag is clear, the journal-mode must be "OFF". + ** And if the journal-mode is "OFF", the journal file must not be open. + */ + assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal ); + assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) ); + + /* Check that MEMDB implies noSync. And an in-memory journal. Since + ** this means an in-memory pager performs no IO at all, it cannot encounter + ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing + ** a journal file. (although the in-memory journal implementation may + ** return SQLITE_IOERR_NOMEM while the journal file is being written). It + ** is therefore not possible for an in-memory pager to enter the ERROR + ** state. + */ + if( MEMDB ){ + assert( p->noSync ); + assert( p->journalMode==PAGER_JOURNALMODE_OFF + || p->journalMode==PAGER_JOURNALMODE_MEMORY + ); + assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN ); + assert( pagerUseWal(p)==0 ); + } + + /* If changeCountDone is set, a RESERVED lock or greater must be held + ** on the file. + */ + assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK ); + assert( p->eLock!=PENDING_LOCK ); + + switch( p->eState ){ + case PAGER_OPEN: + assert( !MEMDB ); + assert( pPager->errCode==SQLITE_OK ); + assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile ); + break; + + case PAGER_READER: + assert( pPager->errCode==SQLITE_OK ); + assert( p->eLock!=UNKNOWN_LOCK ); + assert( p->eLock>=SHARED_LOCK ); + break; + + case PAGER_WRITER_LOCKED: + assert( p->eLock!=UNKNOWN_LOCK ); + assert( pPager->errCode==SQLITE_OK ); + if( !pagerUseWal(pPager) ){ + assert( p->eLock>=RESERVED_LOCK ); + } + assert( pPager->dbSize==pPager->dbOrigSize ); + assert( pPager->dbOrigSize==pPager->dbFileSize ); + assert( pPager->dbOrigSize==pPager->dbHintSize ); + assert( pPager->setMaster==0 ); + break; + + case PAGER_WRITER_CACHEMOD: + assert( p->eLock!=UNKNOWN_LOCK ); + assert( pPager->errCode==SQLITE_OK ); + if( !pagerUseWal(pPager) ){ + /* It is possible that if journal_mode=wal here that neither the + ** journal file nor the WAL file are open. This happens during + ** a rollback transaction that switches from journal_mode=off + ** to journal_mode=wal. + */ + assert( p->eLock>=RESERVED_LOCK ); + assert( isOpen(p->jfd) + || p->journalMode==PAGER_JOURNALMODE_OFF + || p->journalMode==PAGER_JOURNALMODE_WAL + ); + } + assert( pPager->dbOrigSize==pPager->dbFileSize ); + assert( pPager->dbOrigSize==pPager->dbHintSize ); + break; + + case PAGER_WRITER_DBMOD: + assert( p->eLock==EXCLUSIVE_LOCK ); + assert( pPager->errCode==SQLITE_OK ); + assert( !pagerUseWal(pPager) ); + assert( p->eLock>=EXCLUSIVE_LOCK ); + assert( isOpen(p->jfd) + || p->journalMode==PAGER_JOURNALMODE_OFF + || p->journalMode==PAGER_JOURNALMODE_WAL + ); + assert( pPager->dbOrigSize<=pPager->dbHintSize ); + break; + + case PAGER_WRITER_FINISHED: + assert( p->eLock==EXCLUSIVE_LOCK ); + assert( pPager->errCode==SQLITE_OK ); + assert( !pagerUseWal(pPager) ); + assert( isOpen(p->jfd) + || p->journalMode==PAGER_JOURNALMODE_OFF + || p->journalMode==PAGER_JOURNALMODE_WAL + ); + break; + + case PAGER_ERROR: + /* There must be at least one outstanding reference to the pager if + ** in ERROR state. Otherwise the pager should have already dropped + ** back to OPEN state. + */ + assert( pPager->errCode!=SQLITE_OK ); + assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); + break; + } + + return 1; +} +#endif /* ifndef NDEBUG */ + +#ifdef SQLITE_DEBUG +/* +** Return a pointer to a human readable string in a static buffer +** containing the state of the Pager object passed as an argument. This +** is intended to be used within debuggers. For example, as an alternative +** to "print *pPager" in gdb: +** +** (gdb) printf "%s", print_pager_state(pPager) +*/ +static char *print_pager_state(Pager *p){ + static char zRet[1024]; + + sqlite3_snprintf(1024, zRet, + "Filename: %s\n" + "State: %s errCode=%d\n" + "Lock: %s\n" + "Locking mode: locking_mode=%s\n" + "Journal mode: journal_mode=%s\n" + "Backing store: tempFile=%d memDb=%d useJournal=%d\n" + "Journal: journalOff=%lld journalHdr=%lld\n" + "Size: dbsize=%d dbOrigSize=%d dbFileSize=%d\n" + , p->zFilename + , p->eState==PAGER_OPEN ? "OPEN" : + p->eState==PAGER_READER ? "READER" : + p->eState==PAGER_WRITER_LOCKED ? "WRITER_LOCKED" : + p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" : + p->eState==PAGER_WRITER_DBMOD ? "WRITER_DBMOD" : + p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" : + p->eState==PAGER_ERROR ? "ERROR" : "?error?" + , (int)p->errCode + , p->eLock==NO_LOCK ? "NO_LOCK" : + p->eLock==RESERVED_LOCK ? "RESERVED" : + p->eLock==EXCLUSIVE_LOCK ? "EXCLUSIVE" : + p->eLock==SHARED_LOCK ? "SHARED" : + p->eLock==UNKNOWN_LOCK ? "UNKNOWN" : "?error?" + , p->exclusiveMode ? "exclusive" : "normal" + , p->journalMode==PAGER_JOURNALMODE_MEMORY ? "memory" : + p->journalMode==PAGER_JOURNALMODE_OFF ? "off" : + p->journalMode==PAGER_JOURNALMODE_DELETE ? "delete" : + p->journalMode==PAGER_JOURNALMODE_PERSIST ? "persist" : + p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" : + p->journalMode==PAGER_JOURNALMODE_WAL ? "wal" : "?error?" + , (int)p->tempFile, (int)p->memDb, (int)p->useJournal + , p->journalOff, p->journalHdr + , (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize + ); + + return zRet; +} +#endif + +/* +** Return true if it is necessary to write page *pPg into the sub-journal. +** A page needs to be written into the sub-journal if there exists one +** or more open savepoints for which: +** +** * The page-number is less than or equal to PagerSavepoint.nOrig, and +** * The bit corresponding to the page-number is not set in +** PagerSavepoint.pInSavepoint. +*/ +static int subjRequiresPage(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + PagerSavepoint *p; + Pgno pgno = pPg->pgno; + int i; + for(i=0; inSavepoint; i++){ + p = &pPager->aSavepoint[i]; + if( p->nOrig>=pgno && 0==sqlite3BitvecTestNotNull(p->pInSavepoint, pgno) ){ + return 1; + } + } + return 0; +} + +#ifdef SQLITE_DEBUG +/* +** Return true if the page is already in the journal file. +*/ +static int pageInJournal(Pager *pPager, PgHdr *pPg){ + return sqlite3BitvecTest(pPager->pInJournal, pPg->pgno); +} +#endif + +/* +** Read a 32-bit integer from the given file descriptor. Store the integer +** that is read in *pRes. Return SQLITE_OK if everything worked, or an +** error code is something goes wrong. +** +** All values are stored on disk as big-endian. +*/ +static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){ + unsigned char ac[4]; + int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset); + if( rc==SQLITE_OK ){ + *pRes = sqlite3Get4byte(ac); + } + return rc; +} + +/* +** Write a 32-bit integer into a string buffer in big-endian byte order. +*/ +#define put32bits(A,B) sqlite3Put4byte((u8*)A,B) + + +/* +** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK +** on success or an error code is something goes wrong. +*/ +static int write32bits(sqlite3_file *fd, i64 offset, u32 val){ + char ac[4]; + put32bits(ac, val); + return sqlite3OsWrite(fd, ac, 4, offset); +} + +/* +** Unlock the database file to level eLock, which must be either NO_LOCK +** or SHARED_LOCK. Regardless of whether or not the call to xUnlock() +** succeeds, set the Pager.eLock variable to match the (attempted) new lock. +** +** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is +** called, do not modify it. See the comment above the #define of +** UNKNOWN_LOCK for an explanation of this. +*/ +static int pagerUnlockDb(Pager *pPager, int eLock){ + int rc = SQLITE_OK; + + assert( !pPager->exclusiveMode || pPager->eLock==eLock ); + assert( eLock==NO_LOCK || eLock==SHARED_LOCK ); + assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 ); + if( isOpen(pPager->fd) ){ + assert( pPager->eLock>=eLock ); + rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock); + if( pPager->eLock!=UNKNOWN_LOCK ){ + pPager->eLock = (u8)eLock; + } + IOTRACE(("UNLOCK %p %d\n", pPager, eLock)) + } + return rc; +} + +/* +** Lock the database file to level eLock, which must be either SHARED_LOCK, +** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the +** Pager.eLock variable to the new locking state. +** +** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is +** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK. +** See the comment above the #define of UNKNOWN_LOCK for an explanation +** of this. +*/ +static int pagerLockDb(Pager *pPager, int eLock){ + int rc = SQLITE_OK; + + assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK ); + if( pPager->eLockeLock==UNKNOWN_LOCK ){ + rc = pPager->noLock ? SQLITE_OK : sqlite3OsLock(pPager->fd, eLock); + if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){ + pPager->eLock = (u8)eLock; + IOTRACE(("LOCK %p %d\n", pPager, eLock)) + } + } + return rc; +} + +/* +** This function determines whether or not the atomic-write optimization +** can be used with this pager. The optimization can be used if: +** +** (a) the value returned by OsDeviceCharacteristics() indicates that +** a database page may be written atomically, and +** (b) the value returned by OsSectorSize() is less than or equal +** to the page size. +** +** The optimization is also always enabled for temporary files. It is +** an error to call this function if pPager is opened on an in-memory +** database. +** +** If the optimization cannot be used, 0 is returned. If it can be used, +** then the value returned is the size of the journal file when it +** contains rollback data for exactly one page. +*/ +#ifdef SQLITE_ENABLE_ATOMIC_WRITE +static int jrnlBufferSize(Pager *pPager){ + assert( !MEMDB ); + if( !pPager->tempFile ){ + int dc; /* Device characteristics */ + int nSector; /* Sector size */ + int szPage; /* Page size */ + + assert( isOpen(pPager->fd) ); + dc = sqlite3OsDeviceCharacteristics(pPager->fd); + nSector = pPager->sectorSize; + szPage = pPager->pageSize; + + assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); + assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); + if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){ + return 0; + } + } + + return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager); +} +#endif + +/* +** If SQLITE_CHECK_PAGES is defined then we do some sanity checking +** on the cache using a hash function. This is used for testing +** and debugging only. +*/ +#ifdef SQLITE_CHECK_PAGES +/* +** Return a 32-bit hash of the page data for pPage. +*/ +static u32 pager_datahash(int nByte, unsigned char *pData){ + u32 hash = 0; + int i; + for(i=0; ipPager->pageSize, (unsigned char *)pPage->pData); +} +static void pager_set_pagehash(PgHdr *pPage){ + pPage->pageHash = pager_pagehash(pPage); +} + +/* +** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES +** is defined, and NDEBUG is not defined, an assert() statement checks +** that the page is either dirty or still matches the calculated page-hash. +*/ +#define CHECK_PAGE(x) checkPage(x) +static void checkPage(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + assert( pPager->eState!=PAGER_ERROR ); + assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) ); +} + +#else +#define pager_datahash(X,Y) 0 +#define pager_pagehash(X) 0 +#define pager_set_pagehash(X) +#define CHECK_PAGE(x) +#endif /* SQLITE_CHECK_PAGES */ + +/* +** When this is called the journal file for pager pPager must be open. +** This function attempts to read a master journal file name from the +** end of the file and, if successful, copies it into memory supplied +** by the caller. See comments above writeMasterJournal() for the format +** used to store a master journal file name at the end of a journal file. +** +** zMaster must point to a buffer of at least nMaster bytes allocated by +** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is +** enough space to write the master journal name). If the master journal +** name in the journal is longer than nMaster bytes (including a +** nul-terminator), then this is handled as if no master journal name +** were present in the journal. +** +** If a master journal file name is present at the end of the journal +** file, then it is copied into the buffer pointed to by zMaster. A +** nul-terminator byte is appended to the buffer following the master +** journal file name. +** +** If it is determined that no master journal file name is present +** zMaster[0] is set to 0 and SQLITE_OK returned. +** +** If an error occurs while reading from the journal file, an SQLite +** error code is returned. +*/ +static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){ + int rc; /* Return code */ + u32 len; /* Length in bytes of master journal name */ + i64 szJ; /* Total size in bytes of journal file pJrnl */ + u32 cksum; /* MJ checksum value read from journal */ + u32 u; /* Unsigned loop counter */ + unsigned char aMagic[8]; /* A buffer to hold the magic header */ + zMaster[0] = '\0'; + + if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ)) + || szJ<16 + || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len)) + || len>=nMaster + || len==0 + || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum)) + || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8)) + || memcmp(aMagic, aJournalMagic, 8) + || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len)) + ){ + return rc; + } + + /* See if the checksum matches the master journal name */ + for(u=0; ujournalOff, assuming a sector +** size of pPager->sectorSize bytes. +** +** i.e for a sector size of 512: +** +** Pager.journalOff Return value +** --------------------------------------- +** 0 0 +** 512 512 +** 100 512 +** 2000 2048 +** +*/ +static i64 journalHdrOffset(Pager *pPager){ + i64 offset = 0; + i64 c = pPager->journalOff; + if( c ){ + offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager); + } + assert( offset%JOURNAL_HDR_SZ(pPager)==0 ); + assert( offset>=c ); + assert( (offset-c)jfd) ); + if( pPager->journalOff ){ + const i64 iLimit = pPager->journalSizeLimit; /* Local cache of jsl */ + + IOTRACE(("JZEROHDR %p\n", pPager)) + if( doTruncate || iLimit==0 ){ + rc = sqlite3OsTruncate(pPager->jfd, 0); + }else{ + static const char zeroHdr[28] = {0}; + rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0); + } + if( rc==SQLITE_OK && !pPager->noSync ){ + rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags); + } + + /* At this point the transaction is committed but the write lock + ** is still held on the file. If there is a size limit configured for + ** the persistent journal and the journal file currently consumes more + ** space than that limit allows for, truncate it now. There is no need + ** to sync the file following this operation. + */ + if( rc==SQLITE_OK && iLimit>0 ){ + i64 sz; + rc = sqlite3OsFileSize(pPager->jfd, &sz); + if( rc==SQLITE_OK && sz>iLimit ){ + rc = sqlite3OsTruncate(pPager->jfd, iLimit); + } + } + } + return rc; +} + +/* +** The journal file must be open when this routine is called. A journal +** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the +** current location. +** +** The format for the journal header is as follows: +** - 8 bytes: Magic identifying journal format. +** - 4 bytes: Number of records in journal, or -1 no-sync mode is on. +** - 4 bytes: Random number used for page hash. +** - 4 bytes: Initial database page count. +** - 4 bytes: Sector size used by the process that wrote this journal. +** - 4 bytes: Database page size. +** +** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space. +*/ +static int writeJournalHdr(Pager *pPager){ + int rc = SQLITE_OK; /* Return code */ + char *zHeader = pPager->pTmpSpace; /* Temporary space used to build header */ + u32 nHeader = (u32)pPager->pageSize;/* Size of buffer pointed to by zHeader */ + u32 nWrite; /* Bytes of header sector written */ + int ii; /* Loop counter */ + + assert( isOpen(pPager->jfd) ); /* Journal file must be open. */ + + if( nHeader>JOURNAL_HDR_SZ(pPager) ){ + nHeader = JOURNAL_HDR_SZ(pPager); + } + + /* If there are active savepoints and any of them were created + ** since the most recent journal header was written, update the + ** PagerSavepoint.iHdrOffset fields now. + */ + for(ii=0; iinSavepoint; ii++){ + if( pPager->aSavepoint[ii].iHdrOffset==0 ){ + pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff; + } + } + + pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager); + + /* + ** Write the nRec Field - the number of page records that follow this + ** journal header. Normally, zero is written to this value at this time. + ** After the records are added to the journal (and the journal synced, + ** if in full-sync mode), the zero is overwritten with the true number + ** of records (see syncJournal()). + ** + ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When + ** reading the journal this value tells SQLite to assume that the + ** rest of the journal file contains valid page records. This assumption + ** is dangerous, as if a failure occurred whilst writing to the journal + ** file it may contain some garbage data. There are two scenarios + ** where this risk can be ignored: + ** + ** * When the pager is in no-sync mode. Corruption can follow a + ** power failure in this case anyway. + ** + ** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees + ** that garbage data is never appended to the journal file. + */ + assert( isOpen(pPager->fd) || pPager->noSync ); + if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY) + || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) + ){ + memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); + put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff); + }else{ + memset(zHeader, 0, sizeof(aJournalMagic)+4); + } + + /* The random check-hash initializer */ + sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); + put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit); + /* The initial database size */ + put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize); + /* The assumed sector size for this process */ + put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize); + + /* The page size */ + put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize); + + /* Initializing the tail of the buffer is not necessary. Everything + ** works find if the following memset() is omitted. But initializing + ** the memory prevents valgrind from complaining, so we are willing to + ** take the performance hit. + */ + memset(&zHeader[sizeof(aJournalMagic)+20], 0, + nHeader-(sizeof(aJournalMagic)+20)); + + /* In theory, it is only necessary to write the 28 bytes that the + ** journal header consumes to the journal file here. Then increment the + ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next + ** record is written to the following sector (leaving a gap in the file + ** that will be implicitly filled in by the OS). + ** + ** However it has been discovered that on some systems this pattern can + ** be significantly slower than contiguously writing data to the file, + ** even if that means explicitly writing data to the block of + ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what + ** is done. + ** + ** The loop is required here in case the sector-size is larger than the + ** database page size. Since the zHeader buffer is only Pager.pageSize + ** bytes in size, more than one call to sqlite3OsWrite() may be required + ** to populate the entire journal header sector. + */ + for(nWrite=0; rc==SQLITE_OK&&nWritejournalHdr, nHeader)) + rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff); + assert( pPager->journalHdr <= pPager->journalOff ); + pPager->journalOff += nHeader; + } + + return rc; +} + +/* +** The journal file must be open when this is called. A journal header file +** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal +** file. The current location in the journal file is given by +** pPager->journalOff. See comments above function writeJournalHdr() for +** a description of the journal header format. +** +** If the header is read successfully, *pNRec is set to the number of +** page records following this header and *pDbSize is set to the size of the +** database before the transaction began, in pages. Also, pPager->cksumInit +** is set to the value read from the journal header. SQLITE_OK is returned +** in this case. +** +** If the journal header file appears to be corrupted, SQLITE_DONE is +** returned and *pNRec and *PDbSize are undefined. If JOURNAL_HDR_SZ bytes +** cannot be read from the journal file an error code is returned. +*/ +static int readJournalHdr( + Pager *pPager, /* Pager object */ + int isHot, + i64 journalSize, /* Size of the open journal file in bytes */ + u32 *pNRec, /* OUT: Value read from the nRec field */ + u32 *pDbSize /* OUT: Value of original database size field */ +){ + int rc; /* Return code */ + unsigned char aMagic[8]; /* A buffer to hold the magic header */ + i64 iHdrOff; /* Offset of journal header being read */ + + assert( isOpen(pPager->jfd) ); /* Journal file must be open. */ + + /* Advance Pager.journalOff to the start of the next sector. If the + ** journal file is too small for there to be a header stored at this + ** point, return SQLITE_DONE. + */ + pPager->journalOff = journalHdrOffset(pPager); + if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){ + return SQLITE_DONE; + } + iHdrOff = pPager->journalOff; + + /* Read in the first 8 bytes of the journal header. If they do not match + ** the magic string found at the start of each journal header, return + ** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise, + ** proceed. + */ + if( isHot || iHdrOff!=pPager->journalHdr ){ + rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff); + if( rc ){ + return rc; + } + if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ + return SQLITE_DONE; + } + } + + /* Read the first three 32-bit fields of the journal header: The nRec + ** field, the checksum-initializer and the database size at the start + ** of the transaction. Return an error code if anything goes wrong. + */ + if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+8, pNRec)) + || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+12, &pPager->cksumInit)) + || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+16, pDbSize)) + ){ + return rc; + } + + if( pPager->journalOff==0 ){ + u32 iPageSize; /* Page-size field of journal header */ + u32 iSectorSize; /* Sector-size field of journal header */ + + /* Read the page-size and sector-size journal header fields. */ + if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize)) + || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize)) + ){ + return rc; + } + + /* Versions of SQLite prior to 3.5.8 set the page-size field of the + ** journal header to zero. In this case, assume that the Pager.pageSize + ** variable is already set to the correct page size. + */ + if( iPageSize==0 ){ + iPageSize = pPager->pageSize; + } + + /* Check that the values read from the page-size and sector-size fields + ** are within range. To be 'in range', both values need to be a power + ** of two greater than or equal to 512 or 32, and not greater than their + ** respective compile time maximum limits. + */ + if( iPageSize<512 || iSectorSize<32 + || iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE + || ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0 + ){ + /* If the either the page-size or sector-size in the journal-header is + ** invalid, then the process that wrote the journal-header must have + ** crashed before the header was synced. In this case stop reading + ** the journal file here. + */ + return SQLITE_DONE; + } + + /* Update the page-size to match the value read from the journal. + ** Use a testcase() macro to make sure that malloc failure within + ** PagerSetPagesize() is tested. + */ + rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1); + testcase( rc!=SQLITE_OK ); + + /* Update the assumed sector-size to match the value used by + ** the process that created this journal. If this journal was + ** created by a process other than this one, then this routine + ** is being called from within pager_playback(). The local value + ** of Pager.sectorSize is restored at the end of that routine. + */ + pPager->sectorSize = iSectorSize; + } + + pPager->journalOff += JOURNAL_HDR_SZ(pPager); + return rc; +} + + +/* +** Write the supplied master journal name into the journal file for pager +** pPager at the current location. The master journal name must be the last +** thing written to a journal file. If the pager is in full-sync mode, the +** journal file descriptor is advanced to the next sector boundary before +** anything is written. The format is: +** +** + 4 bytes: PAGER_MJ_PGNO. +** + N bytes: Master journal filename in utf-8. +** + 4 bytes: N (length of master journal name in bytes, no nul-terminator). +** + 4 bytes: Master journal name checksum. +** + 8 bytes: aJournalMagic[]. +** +** The master journal page checksum is the sum of the bytes in the master +** journal name, where each byte is interpreted as a signed 8-bit integer. +** +** If zMaster is a NULL pointer (occurs for a single database transaction), +** this call is a no-op. +*/ +static int writeMasterJournal(Pager *pPager, const char *zMaster){ + int rc; /* Return code */ + int nMaster; /* Length of string zMaster */ + i64 iHdrOff; /* Offset of header in journal file */ + i64 jrnlSize; /* Size of journal file on disk */ + u32 cksum = 0; /* Checksum of string zMaster */ + + assert( pPager->setMaster==0 ); + assert( !pagerUseWal(pPager) ); + + if( !zMaster + || pPager->journalMode==PAGER_JOURNALMODE_MEMORY + || !isOpen(pPager->jfd) + ){ + return SQLITE_OK; + } + pPager->setMaster = 1; + assert( pPager->journalHdr <= pPager->journalOff ); + + /* Calculate the length in bytes and the checksum of zMaster */ + for(nMaster=0; zMaster[nMaster]; nMaster++){ + cksum += zMaster[nMaster]; + } + + /* If in full-sync mode, advance to the next disk sector before writing + ** the master journal name. This is in case the previous page written to + ** the journal has already been synced. + */ + if( pPager->fullSync ){ + pPager->journalOff = journalHdrOffset(pPager); + } + iHdrOff = pPager->journalOff; + + /* Write the master journal data to the end of the journal file. If + ** an error occurs, return the error code to the caller. + */ + if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager)))) + || (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4))) + || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster))) + || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum))) + || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8, + iHdrOff+4+nMaster+8))) + ){ + return rc; + } + pPager->journalOff += (nMaster+20); + + /* If the pager is in peristent-journal mode, then the physical + ** journal-file may extend past the end of the master-journal name + ** and 8 bytes of magic data just written to the file. This is + ** dangerous because the code to rollback a hot-journal file + ** will not be able to find the master-journal name to determine + ** whether or not the journal is hot. + ** + ** Easiest thing to do in this scenario is to truncate the journal + ** file to the required size. + */ + if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize)) + && jrnlSize>pPager->journalOff + ){ + rc = sqlite3OsTruncate(pPager->jfd, pPager->journalOff); + } + return rc; +} + +/* +** Discard the entire contents of the in-memory page-cache. +*/ +static void pager_reset(Pager *pPager){ + pPager->iDataVersion++; + sqlite3BackupRestart(pPager->pBackup); + sqlite3PcacheClear(pPager->pPCache); +} + +/* +** Return the pPager->iDataVersion value +*/ +SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){ + assert( pPager->eState>PAGER_OPEN ); + return pPager->iDataVersion; +} + +/* +** Free all structures in the Pager.aSavepoint[] array and set both +** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal +** if it is open and the pager is not in exclusive mode. +*/ +static void releaseAllSavepoints(Pager *pPager){ + int ii; /* Iterator for looping through Pager.aSavepoint */ + for(ii=0; iinSavepoint; ii++){ + sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); + } + if( !pPager->exclusiveMode || sqlite3IsMemJournal(pPager->sjfd) ){ + sqlite3OsClose(pPager->sjfd); + } + sqlite3_free(pPager->aSavepoint); + pPager->aSavepoint = 0; + pPager->nSavepoint = 0; + pPager->nSubRec = 0; +} + +/* +** Set the bit number pgno in the PagerSavepoint.pInSavepoint +** bitvecs of all open savepoints. Return SQLITE_OK if successful +** or SQLITE_NOMEM if a malloc failure occurs. +*/ +static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){ + int ii; /* Loop counter */ + int rc = SQLITE_OK; /* Result code */ + + for(ii=0; iinSavepoint; ii++){ + PagerSavepoint *p = &pPager->aSavepoint[ii]; + if( pgno<=p->nOrig ){ + rc |= sqlite3BitvecSet(p->pInSavepoint, pgno); + testcase( rc==SQLITE_NOMEM ); + assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); + } + } + return rc; +} + +/* +** This function is a no-op if the pager is in exclusive mode and not +** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN +** state. +** +** If the pager is not in exclusive-access mode, the database file is +** completely unlocked. If the file is unlocked and the file-system does +** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is +** closed (if it is open). +** +** If the pager is in ERROR state when this function is called, the +** contents of the pager cache are discarded before switching back to +** the OPEN state. Regardless of whether the pager is in exclusive-mode +** or not, any journal file left in the file-system will be treated +** as a hot-journal and rolled back the next time a read-transaction +** is opened (by this or by any other connection). +*/ +static void pager_unlock(Pager *pPager){ + + assert( pPager->eState==PAGER_READER + || pPager->eState==PAGER_OPEN + || pPager->eState==PAGER_ERROR + ); + + sqlite3BitvecDestroy(pPager->pInJournal); + pPager->pInJournal = 0; + releaseAllSavepoints(pPager); + + if( pagerUseWal(pPager) ){ + assert( !isOpen(pPager->jfd) ); + sqlite3WalEndReadTransaction(pPager->pWal); + pPager->eState = PAGER_OPEN; + }else if( !pPager->exclusiveMode ){ + int rc; /* Error code returned by pagerUnlockDb() */ + int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0; + + /* If the operating system support deletion of open files, then + ** close the journal file when dropping the database lock. Otherwise + ** another connection with journal_mode=delete might delete the file + ** out from under us. + */ + assert( (PAGER_JOURNALMODE_MEMORY & 5)!=1 ); + assert( (PAGER_JOURNALMODE_OFF & 5)!=1 ); + assert( (PAGER_JOURNALMODE_WAL & 5)!=1 ); + assert( (PAGER_JOURNALMODE_DELETE & 5)!=1 ); + assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 ); + assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 ); + if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN) + || 1!=(pPager->journalMode & 5) + ){ + sqlite3OsClose(pPager->jfd); + } + + /* If the pager is in the ERROR state and the call to unlock the database + ** file fails, set the current lock to UNKNOWN_LOCK. See the comment + ** above the #define for UNKNOWN_LOCK for an explanation of why this + ** is necessary. + */ + rc = pagerUnlockDb(pPager, NO_LOCK); + if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){ + pPager->eLock = UNKNOWN_LOCK; + } + + /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here + ** without clearing the error code. This is intentional - the error + ** code is cleared and the cache reset in the block below. + */ + assert( pPager->errCode || pPager->eState!=PAGER_ERROR ); + pPager->changeCountDone = 0; + pPager->eState = PAGER_OPEN; + } + + /* If Pager.errCode is set, the contents of the pager cache cannot be + ** trusted. Now that there are no outstanding references to the pager, + ** it can safely move back to PAGER_OPEN state. This happens in both + ** normal and exclusive-locking mode. + */ + if( pPager->errCode ){ + assert( !MEMDB ); + pager_reset(pPager); + pPager->changeCountDone = pPager->tempFile; + pPager->eState = PAGER_OPEN; + pPager->errCode = SQLITE_OK; + if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0); + } + + pPager->journalOff = 0; + pPager->journalHdr = 0; + pPager->setMaster = 0; +} + +/* +** This function is called whenever an IOERR or FULL error that requires +** the pager to transition into the ERROR state may ahve occurred. +** The first argument is a pointer to the pager structure, the second +** the error-code about to be returned by a pager API function. The +** value returned is a copy of the second argument to this function. +** +** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the +** IOERR sub-codes, the pager enters the ERROR state and the error code +** is stored in Pager.errCode. While the pager remains in the ERROR state, +** all major API calls on the Pager will immediately return Pager.errCode. +** +** The ERROR state indicates that the contents of the pager-cache +** cannot be trusted. This state can be cleared by completely discarding +** the contents of the pager-cache. If a transaction was active when +** the persistent error occurred, then the rollback journal may need +** to be replayed to restore the contents of the database file (as if +** it were a hot-journal). +*/ +static int pager_error(Pager *pPager, int rc){ + int rc2 = rc & 0xff; + assert( rc==SQLITE_OK || !MEMDB ); + assert( + pPager->errCode==SQLITE_FULL || + pPager->errCode==SQLITE_OK || + (pPager->errCode & 0xff)==SQLITE_IOERR + ); + if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ + pPager->errCode = rc; + pPager->eState = PAGER_ERROR; + } + return rc; +} + +static int pager_truncate(Pager *pPager, Pgno nPage); + +/* +** This routine ends a transaction. A transaction is usually ended by +** either a COMMIT or a ROLLBACK operation. This routine may be called +** after rollback of a hot-journal, or if an error occurs while opening +** the journal file or writing the very first journal-header of a +** database transaction. +** +** This routine is never called in PAGER_ERROR state. If it is called +** in PAGER_NONE or PAGER_SHARED state and the lock held is less +** exclusive than a RESERVED lock, it is a no-op. +** +** Otherwise, any active savepoints are released. +** +** If the journal file is open, then it is "finalized". Once a journal +** file has been finalized it is not possible to use it to roll back a +** transaction. Nor will it be considered to be a hot-journal by this +** or any other database connection. Exactly how a journal is finalized +** depends on whether or not the pager is running in exclusive mode and +** the current journal-mode (Pager.journalMode value), as follows: +** +** journalMode==MEMORY +** Journal file descriptor is simply closed. This destroys an +** in-memory journal. +** +** journalMode==TRUNCATE +** Journal file is truncated to zero bytes in size. +** +** journalMode==PERSIST +** The first 28 bytes of the journal file are zeroed. This invalidates +** the first journal header in the file, and hence the entire journal +** file. An invalid journal file cannot be rolled back. +** +** journalMode==DELETE +** The journal file is closed and deleted using sqlite3OsDelete(). +** +** If the pager is running in exclusive mode, this method of finalizing +** the journal file is never used. Instead, if the journalMode is +** DELETE and the pager is in exclusive mode, the method described under +** journalMode==PERSIST is used instead. +** +** After the journal is finalized, the pager moves to PAGER_READER state. +** If running in non-exclusive rollback mode, the lock on the file is +** downgraded to a SHARED_LOCK. +** +** SQLITE_OK is returned if no error occurs. If an error occurs during +** any of the IO operations to finalize the journal file or unlock the +** database then the IO error code is returned to the user. If the +** operation to finalize the journal file fails, then the code still +** tries to unlock the database file if not in exclusive mode. If the +** unlock operation fails as well, then the first error code related +** to the first error encountered (the journal finalization one) is +** returned. +*/ +static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ + int rc = SQLITE_OK; /* Error code from journal finalization operation */ + int rc2 = SQLITE_OK; /* Error code from db file unlock operation */ + + /* Do nothing if the pager does not have an open write transaction + ** or at least a RESERVED lock. This function may be called when there + ** is no write-transaction active but a RESERVED or greater lock is + ** held under two circumstances: + ** + ** 1. After a successful hot-journal rollback, it is called with + ** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK. + ** + ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE + ** lock switches back to locking_mode=normal and then executes a + ** read-transaction, this function is called with eState==PAGER_READER + ** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed. + */ + assert( assert_pager_state(pPager) ); + assert( pPager->eState!=PAGER_ERROR ); + if( pPager->eStateeLockjfd) || pPager->pInJournal==0 ); + if( isOpen(pPager->jfd) ){ + assert( !pagerUseWal(pPager) ); + + /* Finalize the journal file. */ + if( sqlite3IsMemJournal(pPager->jfd) ){ + assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ); + sqlite3OsClose(pPager->jfd); + }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){ + if( pPager->journalOff==0 ){ + rc = SQLITE_OK; + }else{ + rc = sqlite3OsTruncate(pPager->jfd, 0); + if( rc==SQLITE_OK && pPager->fullSync ){ + /* Make sure the new file size is written into the inode right away. + ** Otherwise the journal might resurrect following a power loss and + ** cause the last transaction to roll back. See + ** https://bugzilla.mozilla.org/show_bug.cgi?id=1072773 + */ + rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags); + } + } + pPager->journalOff = 0; + }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST + || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL) + ){ + rc = zeroJournalHdr(pPager, hasMaster); + pPager->journalOff = 0; + }else{ + /* This branch may be executed with Pager.journalMode==MEMORY if + ** a hot-journal was just rolled back. In this case the journal + ** file should be closed and deleted. If this connection writes to + ** the database file, it will do so using an in-memory journal. + */ + int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd)); + assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE + || pPager->journalMode==PAGER_JOURNALMODE_MEMORY + || pPager->journalMode==PAGER_JOURNALMODE_WAL + ); + sqlite3OsClose(pPager->jfd); + if( bDelete ){ + rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); + } + } + } + +#ifdef SQLITE_CHECK_PAGES + sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); + if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){ + PgHdr *p = sqlite3PagerLookup(pPager, 1); + if( p ){ + p->pageHash = 0; + sqlite3PagerUnrefNotNull(p); + } + } +#endif + + sqlite3BitvecDestroy(pPager->pInJournal); + pPager->pInJournal = 0; + pPager->nRec = 0; + sqlite3PcacheCleanAll(pPager->pPCache); + sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); + + if( pagerUseWal(pPager) ){ + /* Drop the WAL write-lock, if any. Also, if the connection was in + ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE + ** lock held on the database file. + */ + rc2 = sqlite3WalEndWriteTransaction(pPager->pWal); + assert( rc2==SQLITE_OK ); + }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){ + /* This branch is taken when committing a transaction in rollback-journal + ** mode if the database file on disk is larger than the database image. + ** At this point the journal has been finalized and the transaction + ** successfully committed, but the EXCLUSIVE lock is still held on the + ** file. So it is safe to truncate the database file to its minimum + ** required size. */ + assert( pPager->eLock==EXCLUSIVE_LOCK ); + rc = pager_truncate(pPager, pPager->dbSize); + } + + if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){ + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0); + if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; + } + + if( !pPager->exclusiveMode + && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) + ){ + rc2 = pagerUnlockDb(pPager, SHARED_LOCK); + pPager->changeCountDone = 0; + } + pPager->eState = PAGER_READER; + pPager->setMaster = 0; + + return (rc==SQLITE_OK?rc2:rc); +} + +/* +** Execute a rollback if a transaction is active and unlock the +** database file. +** +** If the pager has already entered the ERROR state, do not attempt +** the rollback at this time. Instead, pager_unlock() is called. The +** call to pager_unlock() will discard all in-memory pages, unlock +** the database file and move the pager back to OPEN state. If this +** means that there is a hot-journal left in the file-system, the next +** connection to obtain a shared lock on the pager (which may be this one) +** will roll it back. +** +** If the pager has not already entered the ERROR state, but an IO or +** malloc error occurs during a rollback, then this will itself cause +** the pager to enter the ERROR state. Which will be cleared by the +** call to pager_unlock(), as described above. +*/ +static void pagerUnlockAndRollback(Pager *pPager){ + if( pPager->eState!=PAGER_ERROR && pPager->eState!=PAGER_OPEN ){ + assert( assert_pager_state(pPager) ); + if( pPager->eState>=PAGER_WRITER_LOCKED ){ + sqlite3BeginBenignMalloc(); + sqlite3PagerRollback(pPager); + sqlite3EndBenignMalloc(); + }else if( !pPager->exclusiveMode ){ + assert( pPager->eState==PAGER_READER ); + pager_end_transaction(pPager, 0, 0); + } + } + pager_unlock(pPager); +} + +/* +** Parameter aData must point to a buffer of pPager->pageSize bytes +** of data. Compute and return a checksum based ont the contents of the +** page of data and the current value of pPager->cksumInit. +** +** This is not a real checksum. It is really just the sum of the +** random initial value (pPager->cksumInit) and every 200th byte +** of the page data, starting with byte offset (pPager->pageSize%200). +** Each byte is interpreted as an 8-bit unsigned integer. +** +** Changing the formula used to compute this checksum results in an +** incompatible journal file format. +** +** If journal corruption occurs due to a power failure, the most likely +** scenario is that one end or the other of the record will be changed. +** It is much less likely that the two ends of the journal record will be +** correct and the middle be corrupt. Thus, this "checksum" scheme, +** though fast and simple, catches the mostly likely kind of corruption. +*/ +static u32 pager_cksum(Pager *pPager, const u8 *aData){ + u32 cksum = pPager->cksumInit; /* Checksum value to return */ + int i = pPager->pageSize-200; /* Loop counter */ + while( i>0 ){ + cksum += aData[i]; + i -= 200; + } + return cksum; +} + +/* +** Report the current page size and number of reserved bytes back +** to the codec. +*/ +#ifdef SQLITE_HAS_CODEC +static void pagerReportSize(Pager *pPager){ + if( pPager->xCodecSizeChng ){ + pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize, + (int)pPager->nReserve); + } +} +#else +# define pagerReportSize(X) /* No-op if we do not support a codec */ +#endif + +/* +** Read a single page from either the journal file (if isMainJrnl==1) or +** from the sub-journal (if isMainJrnl==0) and playback that page. +** The page begins at offset *pOffset into the file. The *pOffset +** value is increased to the start of the next page in the journal. +** +** The main rollback journal uses checksums - the statement journal does +** not. +** +** If the page number of the page record read from the (sub-)journal file +** is greater than the current value of Pager.dbSize, then playback is +** skipped and SQLITE_OK is returned. +** +** If pDone is not NULL, then it is a record of pages that have already +** been played back. If the page at *pOffset has already been played back +** (if the corresponding pDone bit is set) then skip the playback. +** Make sure the pDone bit corresponding to the *pOffset page is set +** prior to returning. +** +** If the page record is successfully read from the (sub-)journal file +** and played back, then SQLITE_OK is returned. If an IO error occurs +** while reading the record from the (sub-)journal file or while writing +** to the database file, then the IO error code is returned. If data +** is successfully read from the (sub-)journal file but appears to be +** corrupted, SQLITE_DONE is returned. Data is considered corrupted in +** two circumstances: +** +** * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or +** * If the record is being rolled back from the main journal file +** and the checksum field does not match the record content. +** +** Neither of these two scenarios are possible during a savepoint rollback. +** +** If this is a savepoint rollback, then memory may have to be dynamically +** allocated by this function. If this is the case and an allocation fails, +** SQLITE_NOMEM is returned. +*/ +static int pager_playback_one_page( + Pager *pPager, /* The pager being played back */ + i64 *pOffset, /* Offset of record to playback */ + Bitvec *pDone, /* Bitvec of pages already played back */ + int isMainJrnl, /* 1 -> main journal. 0 -> sub-journal. */ + int isSavepnt /* True for a savepoint rollback */ +){ + int rc; + PgHdr *pPg; /* An existing page in the cache */ + Pgno pgno; /* The page number of a page in journal */ + u32 cksum; /* Checksum used for sanity checking */ + char *aData; /* Temporary storage for the page */ + sqlite3_file *jfd; /* The file descriptor for the journal file */ + int isSynced; /* True if journal page is synced */ + + assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */ + assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */ + assert( isMainJrnl || pDone ); /* pDone always used on sub-journals */ + assert( isSavepnt || pDone==0 ); /* pDone never used on non-savepoint */ + + aData = pPager->pTmpSpace; + assert( aData ); /* Temp storage must have already been allocated */ + assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) ); + + /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction + ** or savepoint rollback done at the request of the caller) or this is + ** a hot-journal rollback. If it is a hot-journal rollback, the pager + ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback + ** only reads from the main journal, not the sub-journal. + */ + assert( pPager->eState>=PAGER_WRITER_CACHEMOD + || (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK) + ); + assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl ); + + /* Read the page number and page data from the journal or sub-journal + ** file. Return an error code to the caller if an IO error occurs. + */ + jfd = isMainJrnl ? pPager->jfd : pPager->sjfd; + rc = read32bits(jfd, *pOffset, &pgno); + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4); + if( rc!=SQLITE_OK ) return rc; + *pOffset += pPager->pageSize + 4 + isMainJrnl*4; + + /* Sanity checking on the page. This is more important that I originally + ** thought. If a power failure occurs while the journal is being written, + ** it could cause invalid data to be written into the journal. We need to + ** detect this invalid data (with high probability) and ignore it. + */ + if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){ + assert( !isSavepnt ); + return SQLITE_DONE; + } + if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){ + return SQLITE_OK; + } + if( isMainJrnl ){ + rc = read32bits(jfd, (*pOffset)-4, &cksum); + if( rc ) return rc; + if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){ + return SQLITE_DONE; + } + } + + /* If this page has already been played back before during the current + ** rollback, then don't bother to play it back again. + */ + if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){ + return rc; + } + + /* When playing back page 1, restore the nReserve setting + */ + if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){ + pPager->nReserve = ((u8*)aData)[20]; + pagerReportSize(pPager); + } + + /* If the pager is in CACHEMOD state, then there must be a copy of this + ** page in the pager cache. In this case just update the pager cache, + ** not the database file. The page is left marked dirty in this case. + ** + ** An exception to the above rule: If the database is in no-sync mode + ** and a page is moved during an incremental vacuum then the page may + ** not be in the pager cache. Later: if a malloc() or IO error occurs + ** during a Movepage() call, then the page may not be in the cache + ** either. So the condition described in the above paragraph is not + ** assert()able. + ** + ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the + ** pager cache if it exists and the main file. The page is then marked + ** not dirty. Since this code is only executed in PAGER_OPEN state for + ** a hot-journal rollback, it is guaranteed that the page-cache is empty + ** if the pager is in OPEN state. + ** + ** Ticket #1171: The statement journal might contain page content that is + ** different from the page content at the start of the transaction. + ** This occurs when a page is changed prior to the start of a statement + ** then changed again within the statement. When rolling back such a + ** statement we must not write to the original database unless we know + ** for certain that original page contents are synced into the main rollback + ** journal. Otherwise, a power loss might leave modified data in the + ** database file without an entry in the rollback journal that can + ** restore the database to its original form. Two conditions must be + ** met before writing to the database files. (1) the database must be + ** locked. (2) we know that the original page content is fully synced + ** in the main journal either because the page is not in cache or else + ** the page is marked as needSync==0. + ** + ** 2008-04-14: When attempting to vacuum a corrupt database file, it + ** is possible to fail a statement on a database that does not yet exist. + ** Do not attempt to write if database file has never been opened. + */ + if( pagerUseWal(pPager) ){ + pPg = 0; + }else{ + pPg = sqlite3PagerLookup(pPager, pgno); + } + assert( pPg || !MEMDB ); + assert( pPager->eState!=PAGER_OPEN || pPg==0 ); + PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n", + PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData), + (isMainJrnl?"main-journal":"sub-journal") + )); + if( isMainJrnl ){ + isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr); + }else{ + isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC)); + } + if( isOpen(pPager->fd) + && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) + && isSynced + ){ + i64 ofst = (pgno-1)*(i64)pPager->pageSize; + testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 ); + assert( !pagerUseWal(pPager) ); + rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst); + if( pgno>pPager->dbFileSize ){ + pPager->dbFileSize = pgno; + } + if( pPager->pBackup ){ + CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM); + sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData); + CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData); + } + }else if( !isMainJrnl && pPg==0 ){ + /* If this is a rollback of a savepoint and data was not written to + ** the database and the page is not in-memory, there is a potential + ** problem. When the page is next fetched by the b-tree layer, it + ** will be read from the database file, which may or may not be + ** current. + ** + ** There are a couple of different ways this can happen. All are quite + ** obscure. When running in synchronous mode, this can only happen + ** if the page is on the free-list at the start of the transaction, then + ** populated, then moved using sqlite3PagerMovepage(). + ** + ** The solution is to add an in-memory page to the cache containing + ** the data just read from the sub-journal. Mark the page as dirty + ** and if the pager requires a journal-sync, then mark the page as + ** requiring a journal-sync before it is written. + */ + assert( isSavepnt ); + assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 ); + pPager->doNotSpill |= SPILLFLAG_ROLLBACK; + rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1); + assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 ); + pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK; + if( rc!=SQLITE_OK ) return rc; + pPg->flags &= ~PGHDR_NEED_READ; + sqlite3PcacheMakeDirty(pPg); + } + if( pPg ){ + /* No page should ever be explicitly rolled back that is in use, except + ** for page 1 which is held in use in order to keep the lock on the + ** database active. However such a page may be rolled back as a result + ** of an internal error resulting in an automatic call to + ** sqlite3PagerRollback(). + */ + void *pData; + pData = pPg->pData; + memcpy(pData, (u8*)aData, pPager->pageSize); + pPager->xReiniter(pPg); + if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){ + /* If the contents of this page were just restored from the main + ** journal file, then its content must be as they were when the + ** transaction was first opened. In this case we can mark the page + ** as clean, since there will be no need to write it out to the + ** database. + ** + ** There is one exception to this rule. If the page is being rolled + ** back as part of a savepoint (or statement) rollback from an + ** unsynced portion of the main journal file, then it is not safe + ** to mark the page as clean. This is because marking the page as + ** clean will clear the PGHDR_NEED_SYNC flag. Since the page is + ** already in the journal file (recorded in Pager.pInJournal) and + ** the PGHDR_NEED_SYNC flag is cleared, if the page is written to + ** again within this transaction, it will be marked as dirty but + ** the PGHDR_NEED_SYNC flag will not be set. It could then potentially + ** be written out into the database file before its journal file + ** segment is synced. If a crash occurs during or following this, + ** database corruption may ensue. + */ + assert( !pagerUseWal(pPager) ); + sqlite3PcacheMakeClean(pPg); + } + pager_set_pagehash(pPg); + + /* If this was page 1, then restore the value of Pager.dbFileVers. + ** Do this before any decoding. */ + if( pgno==1 ){ + memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers)); + } + + /* Decode the page just read from disk */ + CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM); + sqlite3PcacheRelease(pPg); + } + return rc; +} + +/* +** Parameter zMaster is the name of a master journal file. A single journal +** file that referred to the master journal file has just been rolled back. +** This routine checks if it is possible to delete the master journal file, +** and does so if it is. +** +** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not +** available for use within this function. +** +** When a master journal file is created, it is populated with the names +** of all of its child journals, one after another, formatted as utf-8 +** encoded text. The end of each child journal file is marked with a +** nul-terminator byte (0x00). i.e. the entire contents of a master journal +** file for a transaction involving two databases might be: +** +** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00" +** +** A master journal file may only be deleted once all of its child +** journals have been rolled back. +** +** This function reads the contents of the master-journal file into +** memory and loops through each of the child journal names. For +** each child journal, it checks if: +** +** * if the child journal exists, and if so +** * if the child journal contains a reference to master journal +** file zMaster +** +** If a child journal can be found that matches both of the criteria +** above, this function returns without doing anything. Otherwise, if +** no such child journal can be found, file zMaster is deleted from +** the file-system using sqlite3OsDelete(). +** +** If an IO error within this function, an error code is returned. This +** function allocates memory by calling sqlite3Malloc(). If an allocation +** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors +** occur, SQLITE_OK is returned. +** +** TODO: This function allocates a single block of memory to load +** the entire contents of the master journal file. This could be +** a couple of kilobytes or so - potentially larger than the page +** size. +*/ +static int pager_delmaster(Pager *pPager, const char *zMaster){ + sqlite3_vfs *pVfs = pPager->pVfs; + int rc; /* Return code */ + sqlite3_file *pMaster; /* Malloc'd master-journal file descriptor */ + sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */ + char *zMasterJournal = 0; /* Contents of master journal file */ + i64 nMasterJournal; /* Size of master journal file */ + char *zJournal; /* Pointer to one journal within MJ file */ + char *zMasterPtr; /* Space to hold MJ filename from a journal file */ + int nMasterPtr; /* Amount of space allocated to zMasterPtr[] */ + + /* Allocate space for both the pJournal and pMaster file descriptors. + ** If successful, open the master journal file for reading. + */ + pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2); + pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile); + if( !pMaster ){ + rc = SQLITE_NOMEM; + }else{ + const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL); + rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0); + } + if( rc!=SQLITE_OK ) goto delmaster_out; + + /* Load the entire master journal file into space obtained from + ** sqlite3_malloc() and pointed to by zMasterJournal. Also obtain + ** sufficient space (in zMasterPtr) to hold the names of master + ** journal files extracted from regular rollback-journals. + */ + rc = sqlite3OsFileSize(pMaster, &nMasterJournal); + if( rc!=SQLITE_OK ) goto delmaster_out; + nMasterPtr = pVfs->mxPathname+1; + zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 1); + if( !zMasterJournal ){ + rc = SQLITE_NOMEM; + goto delmaster_out; + } + zMasterPtr = &zMasterJournal[nMasterJournal+1]; + rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0); + if( rc!=SQLITE_OK ) goto delmaster_out; + zMasterJournal[nMasterJournal] = 0; + + zJournal = zMasterJournal; + while( (zJournal-zMasterJournal)pageSize bytes). +** If the file on disk is currently larger than nPage pages, then use the VFS +** xTruncate() method to truncate it. +** +** Or, it might be the case that the file on disk is smaller than +** nPage pages. Some operating system implementations can get confused if +** you try to truncate a file to some size that is larger than it +** currently is, so detect this case and write a single zero byte to +** the end of the new file instead. +** +** If successful, return SQLITE_OK. If an IO error occurs while modifying +** the database file, return the error code to the caller. +*/ +static int pager_truncate(Pager *pPager, Pgno nPage){ + int rc = SQLITE_OK; + assert( pPager->eState!=PAGER_ERROR ); + assert( pPager->eState!=PAGER_READER ); + + if( isOpen(pPager->fd) + && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) + ){ + i64 currentSize, newSize; + int szPage = pPager->pageSize; + assert( pPager->eLock==EXCLUSIVE_LOCK ); + /* TODO: Is it safe to use Pager.dbFileSize here? */ + rc = sqlite3OsFileSize(pPager->fd, ¤tSize); + newSize = szPage*(i64)nPage; + if( rc==SQLITE_OK && currentSize!=newSize ){ + if( currentSize>newSize ){ + rc = sqlite3OsTruncate(pPager->fd, newSize); + }else if( (currentSize+szPage)<=newSize ){ + char *pTmp = pPager->pTmpSpace; + memset(pTmp, 0, szPage); + testcase( (newSize-szPage) == currentSize ); + testcase( (newSize-szPage) > currentSize ); + rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage); + } + if( rc==SQLITE_OK ){ + pPager->dbFileSize = nPage; + } + } + } + return rc; +} + +/* +** Return a sanitized version of the sector-size of OS file pFile. The +** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE. +*/ +SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){ + int iRet = sqlite3OsSectorSize(pFile); + if( iRet<32 ){ + iRet = 512; + }else if( iRet>MAX_SECTOR_SIZE ){ + assert( MAX_SECTOR_SIZE>=512 ); + iRet = MAX_SECTOR_SIZE; + } + return iRet; +} + +/* +** Set the value of the Pager.sectorSize variable for the given +** pager based on the value returned by the xSectorSize method +** of the open database file. The sector size will be used +** to determine the size and alignment of journal header and +** master journal pointers within created journal files. +** +** For temporary files the effective sector size is always 512 bytes. +** +** Otherwise, for non-temporary files, the effective sector size is +** the value returned by the xSectorSize() method rounded up to 32 if +** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it +** is greater than MAX_SECTOR_SIZE. +** +** If the file has the SQLITE_IOCAP_POWERSAFE_OVERWRITE property, then set +** the effective sector size to its minimum value (512). The purpose of +** pPager->sectorSize is to define the "blast radius" of bytes that +** might change if a crash occurs while writing to a single byte in +** that range. But with POWERSAFE_OVERWRITE, the blast radius is zero +** (that is what POWERSAFE_OVERWRITE means), so we minimize the sector +** size. For backwards compatibility of the rollback journal file format, +** we cannot reduce the effective sector size below 512. +*/ +static void setSectorSize(Pager *pPager){ + assert( isOpen(pPager->fd) || pPager->tempFile ); + + if( pPager->tempFile + || (sqlite3OsDeviceCharacteristics(pPager->fd) & + SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0 + ){ + /* Sector size doesn't matter for temporary files. Also, the file + ** may not have been opened yet, in which case the OsSectorSize() + ** call will segfault. */ + pPager->sectorSize = 512; + }else{ + pPager->sectorSize = sqlite3SectorSize(pPager->fd); + } +} + +/* +** Playback the journal and thus restore the database file to +** the state it was in before we started making changes. +** +** The journal file format is as follows: +** +** (1) 8 byte prefix. A copy of aJournalMagic[]. +** (2) 4 byte big-endian integer which is the number of valid page records +** in the journal. If this value is 0xffffffff, then compute the +** number of page records from the journal size. +** (3) 4 byte big-endian integer which is the initial value for the +** sanity checksum. +** (4) 4 byte integer which is the number of pages to truncate the +** database to during a rollback. +** (5) 4 byte big-endian integer which is the sector size. The header +** is this many bytes in size. +** (6) 4 byte big-endian integer which is the page size. +** (7) zero padding out to the next sector size. +** (8) Zero or more pages instances, each as follows: +** + 4 byte page number. +** + pPager->pageSize bytes of data. +** + 4 byte checksum +** +** When we speak of the journal header, we mean the first 7 items above. +** Each entry in the journal is an instance of the 8th item. +** +** Call the value from the second bullet "nRec". nRec is the number of +** valid page entries in the journal. In most cases, you can compute the +** value of nRec from the size of the journal file. But if a power +** failure occurred while the journal was being written, it could be the +** case that the size of the journal file had already been increased but +** the extra entries had not yet made it safely to disk. In such a case, +** the value of nRec computed from the file size would be too large. For +** that reason, we always use the nRec value in the header. +** +** If the nRec value is 0xffffffff it means that nRec should be computed +** from the file size. This value is used when the user selects the +** no-sync option for the journal. A power failure could lead to corruption +** in this case. But for things like temporary table (which will be +** deleted when the power is restored) we don't care. +** +** If the file opened as the journal file is not a well-formed +** journal file then all pages up to the first corrupted page are rolled +** back (or no pages if the journal header is corrupted). The journal file +** is then deleted and SQLITE_OK returned, just as if no corruption had +** been encountered. +** +** If an I/O or malloc() error occurs, the journal-file is not deleted +** and an error code is returned. +** +** The isHot parameter indicates that we are trying to rollback a journal +** that might be a hot journal. Or, it could be that the journal is +** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE. +** If the journal really is hot, reset the pager cache prior rolling +** back any content. If the journal is merely persistent, no reset is +** needed. +*/ +static int pager_playback(Pager *pPager, int isHot){ + sqlite3_vfs *pVfs = pPager->pVfs; + i64 szJ; /* Size of the journal file in bytes */ + u32 nRec; /* Number of Records in the journal */ + u32 u; /* Unsigned loop counter */ + Pgno mxPg = 0; /* Size of the original file in pages */ + int rc; /* Result code of a subroutine */ + int res = 1; /* Value returned by sqlite3OsAccess() */ + char *zMaster = 0; /* Name of master journal file if any */ + int needPagerReset; /* True to reset page prior to first page rollback */ + int nPlayback = 0; /* Total number of pages restored from journal */ + + /* Figure out how many records are in the journal. Abort early if + ** the journal is empty. + */ + assert( isOpen(pPager->jfd) ); + rc = sqlite3OsFileSize(pPager->jfd, &szJ); + if( rc!=SQLITE_OK ){ + goto end_playback; + } + + /* Read the master journal name from the journal, if it is present. + ** If a master journal file name is specified, but the file is not + ** present on disk, then the journal is not hot and does not need to be + ** played back. + ** + ** TODO: Technically the following is an error because it assumes that + ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that + ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c, + ** mxPathname is 512, which is the same as the minimum allowable value + ** for pageSize. + */ + zMaster = pPager->pTmpSpace; + rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); + if( rc==SQLITE_OK && zMaster[0] ){ + rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res); + } + zMaster = 0; + if( rc!=SQLITE_OK || !res ){ + goto end_playback; + } + pPager->journalOff = 0; + needPagerReset = isHot; + + /* This loop terminates either when a readJournalHdr() or + ** pager_playback_one_page() call returns SQLITE_DONE or an IO error + ** occurs. + */ + while( 1 ){ + /* Read the next journal header from the journal file. If there are + ** not enough bytes left in the journal file for a complete header, or + ** it is corrupted, then a process must have failed while writing it. + ** This indicates nothing more needs to be rolled back. + */ + rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_DONE ){ + rc = SQLITE_OK; + } + goto end_playback; + } + + /* If nRec is 0xffffffff, then this journal was created by a process + ** working in no-sync mode. This means that the rest of the journal + ** file consists of pages, there are no more journal headers. Compute + ** the value of nRec based on this assumption. + */ + if( nRec==0xffffffff ){ + assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ); + nRec = (int)((szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager)); + } + + /* If nRec is 0 and this rollback is of a transaction created by this + ** process and if this is the final header in the journal, then it means + ** that this part of the journal was being filled but has not yet been + ** synced to disk. Compute the number of pages based on the remaining + ** size of the file. + ** + ** The third term of the test was added to fix ticket #2565. + ** When rolling back a hot journal, nRec==0 always means that the next + ** chunk of the journal contains zero pages to be rolled back. But + ** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in + ** the journal, it means that the journal might contain additional + ** pages that need to be rolled back and that the number of pages + ** should be computed based on the journal file size. + */ + if( nRec==0 && !isHot && + pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){ + nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager)); + } + + /* If this is the first header read from the journal, truncate the + ** database file back to its original size. + */ + if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){ + rc = pager_truncate(pPager, mxPg); + if( rc!=SQLITE_OK ){ + goto end_playback; + } + pPager->dbSize = mxPg; + } + + /* Copy original pages out of the journal and back into the + ** database file and/or page cache. + */ + for(u=0; ujournalOff,0,1,0); + if( rc==SQLITE_OK ){ + nPlayback++; + }else{ + if( rc==SQLITE_DONE ){ + pPager->journalOff = szJ; + break; + }else if( rc==SQLITE_IOERR_SHORT_READ ){ + /* If the journal has been truncated, simply stop reading and + ** processing the journal. This might happen if the journal was + ** not completely written and synced prior to a crash. In that + ** case, the database should have never been written in the + ** first place so it is OK to simply abandon the rollback. */ + rc = SQLITE_OK; + goto end_playback; + }else{ + /* If we are unable to rollback, quit and return the error + ** code. This will cause the pager to enter the error state + ** so that no further harm will be done. Perhaps the next + ** process to come along will be able to rollback the database. + */ + goto end_playback; + } + } + } + } + /*NOTREACHED*/ + assert( 0 ); + +end_playback: + /* Following a rollback, the database file should be back in its original + ** state prior to the start of the transaction, so invoke the + ** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the + ** assertion that the transaction counter was modified. + */ +#ifdef SQLITE_DEBUG + if( pPager->fd->pMethods ){ + sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0); + } +#endif + + /* If this playback is happening automatically as a result of an IO or + ** malloc error that occurred after the change-counter was updated but + ** before the transaction was committed, then the change-counter + ** modification may just have been reverted. If this happens in exclusive + ** mode, then subsequent transactions performed by the connection will not + ** update the change-counter at all. This may lead to cache inconsistency + ** problems for other processes at some point in the future. So, just + ** in case this has happened, clear the changeCountDone flag now. + */ + pPager->changeCountDone = pPager->tempFile; + + if( rc==SQLITE_OK ){ + zMaster = pPager->pTmpSpace; + rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); + testcase( rc!=SQLITE_OK ); + } + if( rc==SQLITE_OK + && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) + ){ + rc = sqlite3PagerSync(pPager, 0); + } + if( rc==SQLITE_OK ){ + rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0); + testcase( rc!=SQLITE_OK ); + } + if( rc==SQLITE_OK && zMaster[0] && res ){ + /* If there was a master journal and this routine will return success, + ** see if it is possible to delete the master journal. + */ + rc = pager_delmaster(pPager, zMaster); + testcase( rc!=SQLITE_OK ); + } + if( isHot && nPlayback ){ + sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s", + nPlayback, pPager->zJournal); + } + + /* The Pager.sectorSize variable may have been updated while rolling + ** back a journal created by a process with a different sector size + ** value. Reset it to the correct value for this process. + */ + setSectorSize(pPager); + return rc; +} + + +/* +** Read the content for page pPg out of the database file and into +** pPg->pData. A shared lock or greater must be held on the database +** file before this function is called. +** +** If page 1 is read, then the value of Pager.dbFileVers[] is set to +** the value read from the database file. +** +** If an IO error occurs, then the IO error is returned to the caller. +** Otherwise, SQLITE_OK is returned. +*/ +static int readDbPage(PgHdr *pPg, u32 iFrame){ + Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */ + Pgno pgno = pPg->pgno; /* Page number to read */ + int rc = SQLITE_OK; /* Return code */ + int pgsz = pPager->pageSize; /* Number of bytes to read */ + + assert( pPager->eState>=PAGER_READER && !MEMDB ); + assert( isOpen(pPager->fd) ); + +#ifndef SQLITE_OMIT_WAL + if( iFrame ){ + /* Try to pull the page from the write-ahead log. */ + rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData); + }else +#endif + { + i64 iOffset = (pgno-1)*(i64)pPager->pageSize; + rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset); + if( rc==SQLITE_IOERR_SHORT_READ ){ + rc = SQLITE_OK; + } + } + + if( pgno==1 ){ + if( rc ){ + /* If the read is unsuccessful, set the dbFileVers[] to something + ** that will never be a valid file version. dbFileVers[] is a copy + ** of bytes 24..39 of the database. Bytes 28..31 should always be + ** zero or the size of the database in page. Bytes 32..35 and 35..39 + ** should be page numbers which are never 0xffffffff. So filling + ** pPager->dbFileVers[] with all 0xff bytes should suffice. + ** + ** For an encrypted database, the situation is more complex: bytes + ** 24..39 of the database are white noise. But the probability of + ** white noise equaling 16 bytes of 0xff is vanishingly small so + ** we should still be ok. + */ + memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers)); + }else{ + u8 *dbFileVers = &((u8*)pPg->pData)[24]; + memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers)); + } + } + CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM); + + PAGER_INCR(sqlite3_pager_readdb_count); + PAGER_INCR(pPager->nRead); + IOTRACE(("PGIN %p %d\n", pPager, pgno)); + PAGERTRACE(("FETCH %d page %d hash(%08x)\n", + PAGERID(pPager), pgno, pager_pagehash(pPg))); + + return rc; +} + +/* +** Update the value of the change-counter at offsets 24 and 92 in +** the header and the sqlite version number at offset 96. +** +** This is an unconditional update. See also the pager_incr_changecounter() +** routine which only updates the change-counter if the update is actually +** needed, as determined by the pPager->changeCountDone state variable. +*/ +static void pager_write_changecounter(PgHdr *pPg){ + u32 change_counter; + + /* Increment the value just read and write it back to byte 24. */ + change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1; + put32bits(((char*)pPg->pData)+24, change_counter); + + /* Also store the SQLite version number in bytes 96..99 and in + ** bytes 92..95 store the change counter for which the version number + ** is valid. */ + put32bits(((char*)pPg->pData)+92, change_counter); + put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER); +} + +#ifndef SQLITE_OMIT_WAL +/* +** This function is invoked once for each page that has already been +** written into the log file when a WAL transaction is rolled back. +** Parameter iPg is the page number of said page. The pCtx argument +** is actually a pointer to the Pager structure. +** +** If page iPg is present in the cache, and has no outstanding references, +** it is discarded. Otherwise, if there are one or more outstanding +** references, the page content is reloaded from the database. If the +** attempt to reload content from the database is required and fails, +** return an SQLite error code. Otherwise, SQLITE_OK. +*/ +static int pagerUndoCallback(void *pCtx, Pgno iPg){ + int rc = SQLITE_OK; + Pager *pPager = (Pager *)pCtx; + PgHdr *pPg; + + assert( pagerUseWal(pPager) ); + pPg = sqlite3PagerLookup(pPager, iPg); + if( pPg ){ + if( sqlite3PcachePageRefcount(pPg)==1 ){ + sqlite3PcacheDrop(pPg); + }else{ + u32 iFrame = 0; + rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame); + if( rc==SQLITE_OK ){ + rc = readDbPage(pPg, iFrame); + } + if( rc==SQLITE_OK ){ + pPager->xReiniter(pPg); + } + sqlite3PagerUnrefNotNull(pPg); + } + } + + /* Normally, if a transaction is rolled back, any backup processes are + ** updated as data is copied out of the rollback journal and into the + ** database. This is not generally possible with a WAL database, as + ** rollback involves simply truncating the log file. Therefore, if one + ** or more frames have already been written to the log (and therefore + ** also copied into the backup databases) as part of this transaction, + ** the backups must be restarted. + */ + sqlite3BackupRestart(pPager->pBackup); + + return rc; +} + +/* +** This function is called to rollback a transaction on a WAL database. +*/ +static int pagerRollbackWal(Pager *pPager){ + int rc; /* Return Code */ + PgHdr *pList; /* List of dirty pages to revert */ + + /* For all pages in the cache that are currently dirty or have already + ** been written (but not committed) to the log file, do one of the + ** following: + ** + ** + Discard the cached page (if refcount==0), or + ** + Reload page content from the database (if refcount>0). + */ + pPager->dbSize = pPager->dbOrigSize; + rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager); + pList = sqlite3PcacheDirtyList(pPager->pPCache); + while( pList && rc==SQLITE_OK ){ + PgHdr *pNext = pList->pDirty; + rc = pagerUndoCallback((void *)pPager, pList->pgno); + pList = pNext; + } + + return rc; +} + +/* +** This function is a wrapper around sqlite3WalFrames(). As well as logging +** the contents of the list of pages headed by pList (connected by pDirty), +** this function notifies any active backup processes that the pages have +** changed. +** +** The list of pages passed into this routine is always sorted by page number. +** Hence, if page 1 appears anywhere on the list, it will be the first page. +*/ +static int pagerWalFrames( + Pager *pPager, /* Pager object */ + PgHdr *pList, /* List of frames to log */ + Pgno nTruncate, /* Database size after this commit */ + int isCommit /* True if this is a commit */ +){ + int rc; /* Return code */ + int nList; /* Number of pages in pList */ + PgHdr *p; /* For looping over pages */ + + assert( pPager->pWal ); + assert( pList ); +#ifdef SQLITE_DEBUG + /* Verify that the page list is in accending order */ + for(p=pList; p && p->pDirty; p=p->pDirty){ + assert( p->pgno < p->pDirty->pgno ); + } +#endif + + assert( pList->pDirty==0 || isCommit ); + if( isCommit ){ + /* If a WAL transaction is being committed, there is no point in writing + ** any pages with page numbers greater than nTruncate into the WAL file. + ** They will never be read by any client. So remove them from the pDirty + ** list here. */ + PgHdr **ppNext = &pList; + nList = 0; + for(p=pList; (*ppNext = p)!=0; p=p->pDirty){ + if( p->pgno<=nTruncate ){ + ppNext = &p->pDirty; + nList++; + } + } + assert( pList ); + }else{ + nList = 1; + } + pPager->aStat[PAGER_STAT_WRITE] += nList; + + if( pList->pgno==1 ) pager_write_changecounter(pList); + rc = sqlite3WalFrames(pPager->pWal, + pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags + ); + if( rc==SQLITE_OK && pPager->pBackup ){ + for(p=pList; p; p=p->pDirty){ + sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); + } + } + +#ifdef SQLITE_CHECK_PAGES + pList = sqlite3PcacheDirtyList(pPager->pPCache); + for(p=pList; p; p=p->pDirty){ + pager_set_pagehash(p); + } +#endif + + return rc; +} + +/* +** Begin a read transaction on the WAL. +** +** This routine used to be called "pagerOpenSnapshot()" because it essentially +** makes a snapshot of the database at the current point in time and preserves +** that snapshot for use by the reader in spite of concurrently changes by +** other writers or checkpointers. +*/ +static int pagerBeginReadTransaction(Pager *pPager){ + int rc; /* Return code */ + int changed = 0; /* True if cache must be reset */ + + assert( pagerUseWal(pPager) ); + assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER ); + + /* sqlite3WalEndReadTransaction() was not called for the previous + ** transaction in locking_mode=EXCLUSIVE. So call it now. If we + ** are in locking_mode=NORMAL and EndRead() was previously called, + ** the duplicate call is harmless. + */ + sqlite3WalEndReadTransaction(pPager->pWal); + + rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed); + if( rc!=SQLITE_OK || changed ){ + pager_reset(pPager); + if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0); + } + + return rc; +} +#endif + +/* +** This function is called as part of the transition from PAGER_OPEN +** to PAGER_READER state to determine the size of the database file +** in pages (assuming the page size currently stored in Pager.pageSize). +** +** If no error occurs, SQLITE_OK is returned and the size of the database +** in pages is stored in *pnPage. Otherwise, an error code (perhaps +** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified. +*/ +static int pagerPagecount(Pager *pPager, Pgno *pnPage){ + Pgno nPage; /* Value to return via *pnPage */ + + /* Query the WAL sub-system for the database size. The WalDbsize() + ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or + ** if the database size is not available. The database size is not + ** available from the WAL sub-system if the log file is empty or + ** contains no valid committed transactions. + */ + assert( pPager->eState==PAGER_OPEN ); + assert( pPager->eLock>=SHARED_LOCK ); + nPage = sqlite3WalDbsize(pPager->pWal); + + /* If the number of pages in the database is not available from the + ** WAL sub-system, determine the page counte based on the size of + ** the database file. If the size of the database file is not an + ** integer multiple of the page-size, round up the result. + */ + if( nPage==0 ){ + i64 n = 0; /* Size of db file in bytes */ + assert( isOpen(pPager->fd) || pPager->tempFile ); + if( isOpen(pPager->fd) ){ + int rc = sqlite3OsFileSize(pPager->fd, &n); + if( rc!=SQLITE_OK ){ + return rc; + } + } + nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize); + } + + /* If the current number of pages in the file is greater than the + ** configured maximum pager number, increase the allowed limit so + ** that the file can be read. + */ + if( nPage>pPager->mxPgno ){ + pPager->mxPgno = (Pgno)nPage; + } + + *pnPage = nPage; + return SQLITE_OK; +} + +#ifndef SQLITE_OMIT_WAL +/* +** Check if the *-wal file that corresponds to the database opened by pPager +** exists if the database is not empy, or verify that the *-wal file does +** not exist (by deleting it) if the database file is empty. +** +** If the database is not empty and the *-wal file exists, open the pager +** in WAL mode. If the database is empty or if no *-wal file exists and +** if no error occurs, make sure Pager.journalMode is not set to +** PAGER_JOURNALMODE_WAL. +** +** Return SQLITE_OK or an error code. +** +** The caller must hold a SHARED lock on the database file to call this +** function. Because an EXCLUSIVE lock on the db file is required to delete +** a WAL on a none-empty database, this ensures there is no race condition +** between the xAccess() below and an xDelete() being executed by some +** other connection. +*/ +static int pagerOpenWalIfPresent(Pager *pPager){ + int rc = SQLITE_OK; + assert( pPager->eState==PAGER_OPEN ); + assert( pPager->eLock>=SHARED_LOCK ); + + if( !pPager->tempFile ){ + int isWal; /* True if WAL file exists */ + Pgno nPage; /* Size of the database file */ + + rc = pagerPagecount(pPager, &nPage); + if( rc ) return rc; + if( nPage==0 ){ + rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0); + if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK; + isWal = 0; + }else{ + rc = sqlite3OsAccess( + pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal + ); + } + if( rc==SQLITE_OK ){ + if( isWal ){ + testcase( sqlite3PcachePagecount(pPager->pPCache)==0 ); + rc = sqlite3PagerOpenWal(pPager, 0); + }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){ + pPager->journalMode = PAGER_JOURNALMODE_DELETE; + } + } + } + return rc; +} +#endif + +/* +** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback +** the entire master journal file. The case pSavepoint==NULL occurs when +** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction +** savepoint. +** +** When pSavepoint is not NULL (meaning a non-transaction savepoint is +** being rolled back), then the rollback consists of up to three stages, +** performed in the order specified: +** +** * Pages are played back from the main journal starting at byte +** offset PagerSavepoint.iOffset and continuing to +** PagerSavepoint.iHdrOffset, or to the end of the main journal +** file if PagerSavepoint.iHdrOffset is zero. +** +** * If PagerSavepoint.iHdrOffset is not zero, then pages are played +** back starting from the journal header immediately following +** PagerSavepoint.iHdrOffset to the end of the main journal file. +** +** * Pages are then played back from the sub-journal file, starting +** with the PagerSavepoint.iSubRec and continuing to the end of +** the journal file. +** +** Throughout the rollback process, each time a page is rolled back, the +** corresponding bit is set in a bitvec structure (variable pDone in the +** implementation below). This is used to ensure that a page is only +** rolled back the first time it is encountered in either journal. +** +** If pSavepoint is NULL, then pages are only played back from the main +** journal file. There is no need for a bitvec in this case. +** +** In either case, before playback commences the Pager.dbSize variable +** is reset to the value that it held at the start of the savepoint +** (or transaction). No page with a page-number greater than this value +** is played back. If one is encountered it is simply skipped. +*/ +static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){ + i64 szJ; /* Effective size of the main journal */ + i64 iHdrOff; /* End of first segment of main-journal records */ + int rc = SQLITE_OK; /* Return code */ + Bitvec *pDone = 0; /* Bitvec to ensure pages played back only once */ + + assert( pPager->eState!=PAGER_ERROR ); + assert( pPager->eState>=PAGER_WRITER_LOCKED ); + + /* Allocate a bitvec to use to store the set of pages rolled back */ + if( pSavepoint ){ + pDone = sqlite3BitvecCreate(pSavepoint->nOrig); + if( !pDone ){ + return SQLITE_NOMEM; + } + } + + /* Set the database size back to the value it was before the savepoint + ** being reverted was opened. + */ + pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize; + pPager->changeCountDone = pPager->tempFile; + + if( !pSavepoint && pagerUseWal(pPager) ){ + return pagerRollbackWal(pPager); + } + + /* Use pPager->journalOff as the effective size of the main rollback + ** journal. The actual file might be larger than this in + ** PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST. But anything + ** past pPager->journalOff is off-limits to us. + */ + szJ = pPager->journalOff; + assert( pagerUseWal(pPager)==0 || szJ==0 ); + + /* Begin by rolling back records from the main journal starting at + ** PagerSavepoint.iOffset and continuing to the next journal header. + ** There might be records in the main journal that have a page number + ** greater than the current database size (pPager->dbSize) but those + ** will be skipped automatically. Pages are added to pDone as they + ** are played back. + */ + if( pSavepoint && !pagerUseWal(pPager) ){ + iHdrOff = pSavepoint->iHdrOffset ? pSavepoint->iHdrOffset : szJ; + pPager->journalOff = pSavepoint->iOffset; + while( rc==SQLITE_OK && pPager->journalOffjournalOff, pDone, 1, 1); + } + assert( rc!=SQLITE_DONE ); + }else{ + pPager->journalOff = 0; + } + + /* Continue rolling back records out of the main journal starting at + ** the first journal header seen and continuing until the effective end + ** of the main journal file. Continue to skip out-of-range pages and + ** continue adding pages rolled back to pDone. + */ + while( rc==SQLITE_OK && pPager->journalOffjournalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff" + ** test is related to ticket #2565. See the discussion in the + ** pager_playback() function for additional information. + */ + if( nJRec==0 + && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff + ){ + nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager)); + } + for(ii=0; rc==SQLITE_OK && iijournalOffjournalOff, pDone, 1, 1); + } + assert( rc!=SQLITE_DONE ); + } + assert( rc!=SQLITE_OK || pPager->journalOff>=szJ ); + + /* Finally, rollback pages from the sub-journal. Page that were + ** previously rolled back out of the main journal (and are hence in pDone) + ** will be skipped. Out-of-range pages are also skipped. + */ + if( pSavepoint ){ + u32 ii; /* Loop counter */ + i64 offset = (i64)pSavepoint->iSubRec*(4+pPager->pageSize); + + if( pagerUseWal(pPager) ){ + rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->aWalData); + } + for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && iinSubRec; ii++){ + assert( offset==(i64)ii*(4+pPager->pageSize) ); + rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1); + } + assert( rc!=SQLITE_DONE ); + } + + sqlite3BitvecDestroy(pDone); + if( rc==SQLITE_OK ){ + pPager->journalOff = szJ; + } + + return rc; +} + +/* +** Change the maximum number of in-memory pages that are allowed. +*/ +SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){ + sqlite3PcacheSetCachesize(pPager->pPCache, mxPage); +} + +/* +** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap. +*/ +static void pagerFixMaplimit(Pager *pPager){ +#if SQLITE_MAX_MMAP_SIZE>0 + sqlite3_file *fd = pPager->fd; + if( isOpen(fd) && fd->pMethods->iVersion>=3 ){ + sqlite3_int64 sz; + sz = pPager->szMmap; + pPager->bUseFetch = (sz>0); + sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz); + } +#endif +} + +/* +** Change the maximum size of any memory mapping made of the database file. +*/ +SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *pPager, sqlite3_int64 szMmap){ + pPager->szMmap = szMmap; + pagerFixMaplimit(pPager); +} + +/* +** Free as much memory as possible from the pager. +*/ +SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){ + sqlite3PcacheShrink(pPager->pPCache); +} + +/* +** Adjust settings of the pager to those specified in the pgFlags parameter. +** +** The "level" in pgFlags & PAGER_SYNCHRONOUS_MASK sets the robustness +** of the database to damage due to OS crashes or power failures by +** changing the number of syncs()s when writing the journals. +** There are three levels: +** +** OFF sqlite3OsSync() is never called. This is the default +** for temporary and transient files. +** +** NORMAL The journal is synced once before writes begin on the +** database. This is normally adequate protection, but +** it is theoretically possible, though very unlikely, +** that an inopertune power failure could leave the journal +** in a state which would cause damage to the database +** when it is rolled back. +** +** FULL The journal is synced twice before writes begin on the +** database (with some additional information - the nRec field +** of the journal header - being written in between the two +** syncs). If we assume that writing a +** single disk sector is atomic, then this mode provides +** assurance that the journal will not be corrupted to the +** point of causing damage to the database during rollback. +** +** The above is for a rollback-journal mode. For WAL mode, OFF continues +** to mean that no syncs ever occur. NORMAL means that the WAL is synced +** prior to the start of checkpoint and that the database file is synced +** at the conclusion of the checkpoint if the entire content of the WAL +** was written back into the database. But no sync operations occur for +** an ordinary commit in NORMAL mode with WAL. FULL means that the WAL +** file is synced following each commit operation, in addition to the +** syncs associated with NORMAL. +** +** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL. The +** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync +** using fcntl(F_FULLFSYNC). SQLITE_SYNC_NORMAL means to do an +** ordinary fsync() call. There is no difference between SQLITE_SYNC_FULL +** and SQLITE_SYNC_NORMAL on platforms other than MacOSX. But the +** synchronous=FULL versus synchronous=NORMAL setting determines when +** the xSync primitive is called and is relevant to all platforms. +** +** Numeric values associated with these states are OFF==1, NORMAL=2, +** and FULL=3. +*/ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +SQLITE_PRIVATE void sqlite3PagerSetFlags( + Pager *pPager, /* The pager to set safety level for */ + unsigned pgFlags /* Various flags */ +){ + unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK; + assert( level>=1 && level<=3 ); + pPager->noSync = (level==1 || pPager->tempFile) ?1:0; + pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0; + if( pPager->noSync ){ + pPager->syncFlags = 0; + pPager->ckptSyncFlags = 0; + }else if( pgFlags & PAGER_FULLFSYNC ){ + pPager->syncFlags = SQLITE_SYNC_FULL; + pPager->ckptSyncFlags = SQLITE_SYNC_FULL; + }else if( pgFlags & PAGER_CKPT_FULLFSYNC ){ + pPager->syncFlags = SQLITE_SYNC_NORMAL; + pPager->ckptSyncFlags = SQLITE_SYNC_FULL; + }else{ + pPager->syncFlags = SQLITE_SYNC_NORMAL; + pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; + } + pPager->walSyncFlags = pPager->syncFlags; + if( pPager->fullSync ){ + pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS; + } + if( pgFlags & PAGER_CACHESPILL ){ + pPager->doNotSpill &= ~SPILLFLAG_OFF; + }else{ + pPager->doNotSpill |= SPILLFLAG_OFF; + } +} +#endif + +/* +** The following global variable is incremented whenever the library +** attempts to open a temporary file. This information is used for +** testing and analysis only. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_opentemp_count = 0; +#endif + +/* +** Open a temporary file. +** +** Write the file descriptor into *pFile. Return SQLITE_OK on success +** or some other error code if we fail. The OS will automatically +** delete the temporary file when it is closed. +** +** The flags passed to the VFS layer xOpen() call are those specified +** by parameter vfsFlags ORed with the following: +** +** SQLITE_OPEN_READWRITE +** SQLITE_OPEN_CREATE +** SQLITE_OPEN_EXCLUSIVE +** SQLITE_OPEN_DELETEONCLOSE +*/ +static int pagerOpentemp( + Pager *pPager, /* The pager object */ + sqlite3_file *pFile, /* Write the file descriptor here */ + int vfsFlags /* Flags passed through to the VFS */ +){ + int rc; /* Return code */ + +#ifdef SQLITE_TEST + sqlite3_opentemp_count++; /* Used for testing and analysis only */ +#endif + + vfsFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | + SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE; + rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0); + assert( rc!=SQLITE_OK || isOpen(pFile) ); + return rc; +} + +/* +** Set the busy handler function. +** +** The pager invokes the busy-handler if sqlite3OsLock() returns +** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock, +** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE +** lock. It does *not* invoke the busy handler when upgrading from +** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE +** (which occurs during hot-journal rollback). Summary: +** +** Transition | Invokes xBusyHandler +** -------------------------------------------------------- +** NO_LOCK -> SHARED_LOCK | Yes +** SHARED_LOCK -> RESERVED_LOCK | No +** SHARED_LOCK -> EXCLUSIVE_LOCK | No +** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes +** +** If the busy-handler callback returns non-zero, the lock is +** retried. If it returns zero, then the SQLITE_BUSY error is +** returned to the caller of the pager API function. +*/ +SQLITE_PRIVATE void sqlite3PagerSetBusyhandler( + Pager *pPager, /* Pager object */ + int (*xBusyHandler)(void *), /* Pointer to busy-handler function */ + void *pBusyHandlerArg /* Argument to pass to xBusyHandler */ +){ + pPager->xBusyHandler = xBusyHandler; + pPager->pBusyHandlerArg = pBusyHandlerArg; + + if( isOpen(pPager->fd) ){ + void **ap = (void **)&pPager->xBusyHandler; + assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); + assert( ap[1]==pBusyHandlerArg ); + sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); + } +} + +/* +** Change the page size used by the Pager object. The new page size +** is passed in *pPageSize. +** +** If the pager is in the error state when this function is called, it +** is a no-op. The value returned is the error state error code (i.e. +** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL). +** +** Otherwise, if all of the following are true: +** +** * the new page size (value of *pPageSize) is valid (a power +** of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and +** +** * there are no outstanding page references, and +** +** * the database is either not an in-memory database or it is +** an in-memory database that currently consists of zero pages. +** +** then the pager object page size is set to *pPageSize. +** +** If the page size is changed, then this function uses sqlite3PagerMalloc() +** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt +** fails, SQLITE_NOMEM is returned and the page size remains unchanged. +** In all other cases, SQLITE_OK is returned. +** +** If the page size is not changed, either because one of the enumerated +** conditions above is not true, the pager was in error state when this +** function was called, or because the memory allocation attempt failed, +** then *pPageSize is set to the old, retained page size before returning. +*/ +SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){ + int rc = SQLITE_OK; + + /* It is not possible to do a full assert_pager_state() here, as this + ** function may be called from within PagerOpen(), before the state + ** of the Pager object is internally consistent. + ** + ** At one point this function returned an error if the pager was in + ** PAGER_ERROR state. But since PAGER_ERROR state guarantees that + ** there is at least one outstanding page reference, this function + ** is a no-op for that case anyhow. + */ + + u32 pageSize = *pPageSize; + assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) ); + if( (pPager->memDb==0 || pPager->dbSize==0) + && sqlite3PcacheRefCount(pPager->pPCache)==0 + && pageSize && pageSize!=(u32)pPager->pageSize + ){ + char *pNew = NULL; /* New temp space */ + i64 nByte = 0; + + if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){ + rc = sqlite3OsFileSize(pPager->fd, &nByte); + } + if( rc==SQLITE_OK ){ + pNew = (char *)sqlite3PageMalloc(pageSize); + if( !pNew ) rc = SQLITE_NOMEM; + } + + if( rc==SQLITE_OK ){ + pager_reset(pPager); + rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize); + } + if( rc==SQLITE_OK ){ + sqlite3PageFree(pPager->pTmpSpace); + pPager->pTmpSpace = pNew; + pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize); + pPager->pageSize = pageSize; + }else{ + sqlite3PageFree(pNew); + } + } + + *pPageSize = pPager->pageSize; + if( rc==SQLITE_OK ){ + if( nReserve<0 ) nReserve = pPager->nReserve; + assert( nReserve>=0 && nReserve<1000 ); + pPager->nReserve = (i16)nReserve; + pagerReportSize(pPager); + pagerFixMaplimit(pPager); + } + return rc; +} + +/* +** Return a pointer to the "temporary page" buffer held internally +** by the pager. This is a buffer that is big enough to hold the +** entire content of a database page. This buffer is used internally +** during rollback and will be overwritten whenever a rollback +** occurs. But other modules are free to use it too, as long as +** no rollbacks are happening. +*/ +SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager *pPager){ + return pPager->pTmpSpace; +} + +/* +** Attempt to set the maximum database page count if mxPage is positive. +** Make no changes if mxPage is zero or negative. And never reduce the +** maximum page count below the current size of the database. +** +** Regardless of mxPage, return the current maximum page count. +*/ +SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ + if( mxPage>0 ){ + pPager->mxPgno = mxPage; + } + assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */ + assert( pPager->mxPgno>=pPager->dbSize ); /* OP_MaxPgcnt enforces this */ + return pPager->mxPgno; +} + +/* +** The following set of routines are used to disable the simulated +** I/O error mechanism. These routines are used to avoid simulated +** errors in places where we do not care about errors. +** +** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops +** and generate no code. +*/ +#ifdef SQLITE_TEST +SQLITE_API extern int sqlite3_io_error_pending; +SQLITE_API extern int sqlite3_io_error_hit; +static int saved_cnt; +void disable_simulated_io_errors(void){ + saved_cnt = sqlite3_io_error_pending; + sqlite3_io_error_pending = -1; +} +void enable_simulated_io_errors(void){ + sqlite3_io_error_pending = saved_cnt; +} +#else +# define disable_simulated_io_errors() +# define enable_simulated_io_errors() +#endif + +/* +** Read the first N bytes from the beginning of the file into memory +** that pDest points to. +** +** If the pager was opened on a transient file (zFilename==""), or +** opened on a file less than N bytes in size, the output buffer is +** zeroed and SQLITE_OK returned. The rationale for this is that this +** function is used to read database headers, and a new transient or +** zero sized database has a header than consists entirely of zeroes. +** +** If any IO error apart from SQLITE_IOERR_SHORT_READ is encountered, +** the error code is returned to the caller and the contents of the +** output buffer undefined. +*/ +SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){ + int rc = SQLITE_OK; + memset(pDest, 0, N); + assert( isOpen(pPager->fd) || pPager->tempFile ); + + /* This routine is only called by btree immediately after creating + ** the Pager object. There has not been an opportunity to transition + ** to WAL mode yet. + */ + assert( !pagerUseWal(pPager) ); + + if( isOpen(pPager->fd) ){ + IOTRACE(("DBHDR %p 0 %d\n", pPager, N)) + rc = sqlite3OsRead(pPager->fd, pDest, N, 0); + if( rc==SQLITE_IOERR_SHORT_READ ){ + rc = SQLITE_OK; + } + } + return rc; +} + +/* +** This function may only be called when a read-transaction is open on +** the pager. It returns the total number of pages in the database. +** +** However, if the file is between 1 and bytes in size, then +** this is considered a 1 page file. +*/ +SQLITE_PRIVATE void sqlite3PagerPagecount(Pager *pPager, int *pnPage){ + assert( pPager->eState>=PAGER_READER ); + assert( pPager->eState!=PAGER_WRITER_FINISHED ); + *pnPage = (int)pPager->dbSize; +} + + +/* +** Try to obtain a lock of type locktype on the database file. If +** a similar or greater lock is already held, this function is a no-op +** (returning SQLITE_OK immediately). +** +** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke +** the busy callback if the lock is currently not available. Repeat +** until the busy callback returns false or until the attempt to +** obtain the lock succeeds. +** +** Return SQLITE_OK on success and an error code if we cannot obtain +** the lock. If the lock is obtained successfully, set the Pager.state +** variable to locktype before returning. +*/ +static int pager_wait_on_lock(Pager *pPager, int locktype){ + int rc; /* Return code */ + + /* Check that this is either a no-op (because the requested lock is + ** already held), or one of the transitions that the busy-handler + ** may be invoked during, according to the comment above + ** sqlite3PagerSetBusyhandler(). + */ + assert( (pPager->eLock>=locktype) + || (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK) + || (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK) + ); + + do { + rc = pagerLockDb(pPager, locktype); + }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) ); + return rc; +} + +/* +** Function assertTruncateConstraint(pPager) checks that one of the +** following is true for all dirty pages currently in the page-cache: +** +** a) The page number is less than or equal to the size of the +** current database image, in pages, OR +** +** b) if the page content were written at this time, it would not +** be necessary to write the current content out to the sub-journal +** (as determined by function subjRequiresPage()). +** +** If the condition asserted by this function were not true, and the +** dirty page were to be discarded from the cache via the pagerStress() +** routine, pagerStress() would not write the current page content to +** the database file. If a savepoint transaction were rolled back after +** this happened, the correct behavior would be to restore the current +** content of the page. However, since this content is not present in either +** the database file or the portion of the rollback journal and +** sub-journal rolled back the content could not be restored and the +** database image would become corrupt. It is therefore fortunate that +** this circumstance cannot arise. +*/ +#if defined(SQLITE_DEBUG) +static void assertTruncateConstraintCb(PgHdr *pPg){ + assert( pPg->flags&PGHDR_DIRTY ); + assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize ); +} +static void assertTruncateConstraint(Pager *pPager){ + sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb); +} +#else +# define assertTruncateConstraint(pPager) +#endif + +/* +** Truncate the in-memory database file image to nPage pages. This +** function does not actually modify the database file on disk. It +** just sets the internal state of the pager object so that the +** truncation will be done when the current transaction is committed. +** +** This function is only called right before committing a transaction. +** Once this function has been called, the transaction must either be +** rolled back or committed. It is not safe to call this function and +** then continue writing to the database. +*/ +SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){ + assert( pPager->dbSize>=nPage ); + assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); + pPager->dbSize = nPage; + + /* At one point the code here called assertTruncateConstraint() to + ** ensure that all pages being truncated away by this operation are, + ** if one or more savepoints are open, present in the savepoint + ** journal so that they can be restored if the savepoint is rolled + ** back. This is no longer necessary as this function is now only + ** called right before committing a transaction. So although the + ** Pager object may still have open savepoints (Pager.nSavepoint!=0), + ** they cannot be rolled back. So the assertTruncateConstraint() call + ** is no longer correct. */ +} + + +/* +** This function is called before attempting a hot-journal rollback. It +** syncs the journal file to disk, then sets pPager->journalHdr to the +** size of the journal file so that the pager_playback() routine knows +** that the entire journal file has been synced. +** +** Syncing a hot-journal to disk before attempting to roll it back ensures +** that if a power-failure occurs during the rollback, the process that +** attempts rollback following system recovery sees the same journal +** content as this process. +** +** If everything goes as planned, SQLITE_OK is returned. Otherwise, +** an SQLite error code. +*/ +static int pagerSyncHotJournal(Pager *pPager){ + int rc = SQLITE_OK; + if( !pPager->noSync ){ + rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL); + } + if( rc==SQLITE_OK ){ + rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr); + } + return rc; +} + +/* +** Obtain a reference to a memory mapped page object for page number pgno. +** The new object will use the pointer pData, obtained from xFetch(). +** If successful, set *ppPage to point to the new page reference +** and return SQLITE_OK. Otherwise, return an SQLite error code and set +** *ppPage to zero. +** +** Page references obtained by calling this function should be released +** by calling pagerReleaseMapPage(). +*/ +static int pagerAcquireMapPage( + Pager *pPager, /* Pager object */ + Pgno pgno, /* Page number */ + void *pData, /* xFetch()'d data for this page */ + PgHdr **ppPage /* OUT: Acquired page object */ +){ + PgHdr *p; /* Memory mapped page to return */ + + if( pPager->pMmapFreelist ){ + *ppPage = p = pPager->pMmapFreelist; + pPager->pMmapFreelist = p->pDirty; + p->pDirty = 0; + memset(p->pExtra, 0, pPager->nExtra); + }else{ + *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra); + if( p==0 ){ + sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData); + return SQLITE_NOMEM; + } + p->pExtra = (void *)&p[1]; + p->flags = PGHDR_MMAP; + p->nRef = 1; + p->pPager = pPager; + } + + assert( p->pExtra==(void *)&p[1] ); + assert( p->pPage==0 ); + assert( p->flags==PGHDR_MMAP ); + assert( p->pPager==pPager ); + assert( p->nRef==1 ); + + p->pgno = pgno; + p->pData = pData; + pPager->nMmapOut++; + + return SQLITE_OK; +} + +/* +** Release a reference to page pPg. pPg must have been returned by an +** earlier call to pagerAcquireMapPage(). +*/ +static void pagerReleaseMapPage(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + pPager->nMmapOut--; + pPg->pDirty = pPager->pMmapFreelist; + pPager->pMmapFreelist = pPg; + + assert( pPager->fd->pMethods->iVersion>=3 ); + sqlite3OsUnfetch(pPager->fd, (i64)(pPg->pgno-1)*pPager->pageSize, pPg->pData); +} + +/* +** Free all PgHdr objects stored in the Pager.pMmapFreelist list. +*/ +static void pagerFreeMapHdrs(Pager *pPager){ + PgHdr *p; + PgHdr *pNext; + for(p=pPager->pMmapFreelist; p; p=pNext){ + pNext = p->pDirty; + sqlite3_free(p); + } +} + + +/* +** Shutdown the page cache. Free all memory and close all files. +** +** If a transaction was in progress when this routine is called, that +** transaction is rolled back. All outstanding pages are invalidated +** and their memory is freed. Any attempt to use a page associated +** with this page cache after this function returns will likely +** result in a coredump. +** +** This function always succeeds. If a transaction is active an attempt +** is made to roll it back. If an error occurs during the rollback +** a hot journal may be left in the filesystem but no error is returned +** to the caller. +*/ +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ + u8 *pTmp = (u8 *)pPager->pTmpSpace; + + assert( assert_pager_state(pPager) ); + disable_simulated_io_errors(); + sqlite3BeginBenignMalloc(); + pagerFreeMapHdrs(pPager); + /* pPager->errCode = 0; */ + pPager->exclusiveMode = 0; +#ifndef SQLITE_OMIT_WAL + sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); + pPager->pWal = 0; +#endif + pager_reset(pPager); + if( MEMDB ){ + pager_unlock(pPager); + }else{ + /* If it is open, sync the journal file before calling UnlockAndRollback. + ** If this is not done, then an unsynced portion of the open journal + ** file may be played back into the database. If a power failure occurs + ** while this is happening, the database could become corrupt. + ** + ** If an error occurs while trying to sync the journal, shift the pager + ** into the ERROR state. This causes UnlockAndRollback to unlock the + ** database and close the journal file without attempting to roll it + ** back or finalize it. The next database user will have to do hot-journal + ** rollback before accessing the database file. + */ + if( isOpen(pPager->jfd) ){ + pager_error(pPager, pagerSyncHotJournal(pPager)); + } + pagerUnlockAndRollback(pPager); + } + sqlite3EndBenignMalloc(); + enable_simulated_io_errors(); + PAGERTRACE(("CLOSE %d\n", PAGERID(pPager))); + IOTRACE(("CLOSE %p\n", pPager)) + sqlite3OsClose(pPager->jfd); + sqlite3OsClose(pPager->fd); + sqlite3PageFree(pTmp); + sqlite3PcacheClose(pPager->pPCache); + +#ifdef SQLITE_HAS_CODEC + if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); +#endif + + assert( !pPager->aSavepoint && !pPager->pInJournal ); + assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) ); + + sqlite3_free(pPager); + return SQLITE_OK; +} + +#if !defined(NDEBUG) || defined(SQLITE_TEST) +/* +** Return the page number for page pPg. +*/ +SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage *pPg){ + return pPg->pgno; +} +#endif + +/* +** Increment the reference count for page pPg. +*/ +SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){ + sqlite3PcacheRef(pPg); +} + +/* +** Sync the journal. In other words, make sure all the pages that have +** been written to the journal have actually reached the surface of the +** disk and can be restored in the event of a hot-journal rollback. +** +** If the Pager.noSync flag is set, then this function is a no-op. +** Otherwise, the actions required depend on the journal-mode and the +** device characteristics of the file-system, as follows: +** +** * If the journal file is an in-memory journal file, no action need +** be taken. +** +** * Otherwise, if the device does not support the SAFE_APPEND property, +** then the nRec field of the most recently written journal header +** is updated to contain the number of journal records that have +** been written following it. If the pager is operating in full-sync +** mode, then the journal file is synced before this field is updated. +** +** * If the device does not support the SEQUENTIAL property, then +** journal file is synced. +** +** Or, in pseudo-code: +** +** if( NOT ){ +** if( NOT SAFE_APPEND ){ +** if( ) xSync(); +** +** } +** if( NOT SEQUENTIAL ) xSync(); +** } +** +** If successful, this routine clears the PGHDR_NEED_SYNC flag of every +** page currently held in memory before returning SQLITE_OK. If an IO +** error is encountered, then the IO error code is returned to the caller. +*/ +static int syncJournal(Pager *pPager, int newHdr){ + int rc; /* Return code */ + + assert( pPager->eState==PAGER_WRITER_CACHEMOD + || pPager->eState==PAGER_WRITER_DBMOD + ); + assert( assert_pager_state(pPager) ); + assert( !pagerUseWal(pPager) ); + + rc = sqlite3PagerExclusiveLock(pPager); + if( rc!=SQLITE_OK ) return rc; + + if( !pPager->noSync ){ + assert( !pPager->tempFile ); + if( isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){ + const int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); + assert( isOpen(pPager->jfd) ); + + if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ + /* This block deals with an obscure problem. If the last connection + ** that wrote to this database was operating in persistent-journal + ** mode, then the journal file may at this point actually be larger + ** than Pager.journalOff bytes. If the next thing in the journal + ** file happens to be a journal-header (written as part of the + ** previous connection's transaction), and a crash or power-failure + ** occurs after nRec is updated but before this connection writes + ** anything else to the journal file (or commits/rolls back its + ** transaction), then SQLite may become confused when doing the + ** hot-journal rollback following recovery. It may roll back all + ** of this connections data, then proceed to rolling back the old, + ** out-of-date data that follows it. Database corruption. + ** + ** To work around this, if the journal file does appear to contain + ** a valid header following Pager.journalOff, then write a 0x00 + ** byte to the start of it to prevent it from being recognized. + ** + ** Variable iNextHdrOffset is set to the offset at which this + ** problematic header will occur, if it exists. aMagic is used + ** as a temporary buffer to inspect the first couple of bytes of + ** the potential journal header. + */ + i64 iNextHdrOffset; + u8 aMagic[8]; + u8 zHeader[sizeof(aJournalMagic)+4]; + + memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); + put32bits(&zHeader[sizeof(aJournalMagic)], pPager->nRec); + + iNextHdrOffset = journalHdrOffset(pPager); + rc = sqlite3OsRead(pPager->jfd, aMagic, 8, iNextHdrOffset); + if( rc==SQLITE_OK && 0==memcmp(aMagic, aJournalMagic, 8) ){ + static const u8 zerobyte = 0; + rc = sqlite3OsWrite(pPager->jfd, &zerobyte, 1, iNextHdrOffset); + } + if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){ + return rc; + } + + /* Write the nRec value into the journal file header. If in + ** full-synchronous mode, sync the journal first. This ensures that + ** all data has really hit the disk before nRec is updated to mark + ** it as a candidate for rollback. + ** + ** This is not required if the persistent media supports the + ** SAFE_APPEND property. Because in this case it is not possible + ** for garbage data to be appended to the file, the nRec field + ** is populated with 0xFFFFFFFF when the journal header is written + ** and never needs to be updated. + */ + if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ + PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); + IOTRACE(("JSYNC %p\n", pPager)) + rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags); + if( rc!=SQLITE_OK ) return rc; + } + IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr)); + rc = sqlite3OsWrite( + pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr + ); + if( rc!=SQLITE_OK ) return rc; + } + if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ + PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); + IOTRACE(("JSYNC %p\n", pPager)) + rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags| + (pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0) + ); + if( rc!=SQLITE_OK ) return rc; + } + + pPager->journalHdr = pPager->journalOff; + if( newHdr && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ + pPager->nRec = 0; + rc = writeJournalHdr(pPager); + if( rc!=SQLITE_OK ) return rc; + } + }else{ + pPager->journalHdr = pPager->journalOff; + } + } + + /* Unless the pager is in noSync mode, the journal file was just + ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on + ** all pages. + */ + sqlite3PcacheClearSyncFlags(pPager->pPCache); + pPager->eState = PAGER_WRITER_DBMOD; + assert( assert_pager_state(pPager) ); + return SQLITE_OK; +} + +/* +** The argument is the first in a linked list of dirty pages connected +** by the PgHdr.pDirty pointer. This function writes each one of the +** in-memory pages in the list to the database file. The argument may +** be NULL, representing an empty list. In this case this function is +** a no-op. +** +** The pager must hold at least a RESERVED lock when this function +** is called. Before writing anything to the database file, this lock +** is upgraded to an EXCLUSIVE lock. If the lock cannot be obtained, +** SQLITE_BUSY is returned and no data is written to the database file. +** +** If the pager is a temp-file pager and the actual file-system file +** is not yet open, it is created and opened before any data is +** written out. +** +** Once the lock has been upgraded and, if necessary, the file opened, +** the pages are written out to the database file in list order. Writing +** a page is skipped if it meets either of the following criteria: +** +** * The page number is greater than Pager.dbSize, or +** * The PGHDR_DONT_WRITE flag is set on the page. +** +** If writing out a page causes the database file to grow, Pager.dbFileSize +** is updated accordingly. If page 1 is written out, then the value cached +** in Pager.dbFileVers[] is updated to match the new value stored in +** the database file. +** +** If everything is successful, SQLITE_OK is returned. If an IO error +** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot +** be obtained, SQLITE_BUSY is returned. +*/ +static int pager_write_pagelist(Pager *pPager, PgHdr *pList){ + int rc = SQLITE_OK; /* Return code */ + + /* This function is only called for rollback pagers in WRITER_DBMOD state. */ + assert( !pagerUseWal(pPager) ); + assert( pPager->eState==PAGER_WRITER_DBMOD ); + assert( pPager->eLock==EXCLUSIVE_LOCK ); + + /* If the file is a temp-file has not yet been opened, open it now. It + ** is not possible for rc to be other than SQLITE_OK if this branch + ** is taken, as pager_wait_on_lock() is a no-op for temp-files. + */ + if( !isOpen(pPager->fd) ){ + assert( pPager->tempFile && rc==SQLITE_OK ); + rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags); + } + + /* Before the first write, give the VFS a hint of what the final + ** file size will be. + */ + assert( rc!=SQLITE_OK || isOpen(pPager->fd) ); + if( rc==SQLITE_OK + && pPager->dbHintSizedbSize + && (pList->pDirty || pList->pgno>pPager->dbHintSize) + ){ + sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize; + sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile); + pPager->dbHintSize = pPager->dbSize; + } + + while( rc==SQLITE_OK && pList ){ + Pgno pgno = pList->pgno; + + /* If there are dirty pages in the page cache with page numbers greater + ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to + ** make the file smaller (presumably by auto-vacuum code). Do not write + ** any such pages to the file. + ** + ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag + ** set (set by sqlite3PagerDontWrite()). + */ + if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){ + i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */ + char *pData; /* Data to write */ + + assert( (pList->flags&PGHDR_NEED_SYNC)==0 ); + if( pList->pgno==1 ) pager_write_changecounter(pList); + + /* Encode the database */ + CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData); + + /* Write out the page data. */ + rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset); + + /* If page 1 was just written, update Pager.dbFileVers to match + ** the value now stored in the database file. If writing this + ** page caused the database file to grow, update dbFileSize. + */ + if( pgno==1 ){ + memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers)); + } + if( pgno>pPager->dbFileSize ){ + pPager->dbFileSize = pgno; + } + pPager->aStat[PAGER_STAT_WRITE]++; + + /* Update any backup objects copying the contents of this pager. */ + sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData); + + PAGERTRACE(("STORE %d page %d hash(%08x)\n", + PAGERID(pPager), pgno, pager_pagehash(pList))); + IOTRACE(("PGOUT %p %d\n", pPager, pgno)); + PAGER_INCR(sqlite3_pager_writedb_count); + }else{ + PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno)); + } + pager_set_pagehash(pList); + pList = pList->pDirty; + } + + return rc; +} + +/* +** Ensure that the sub-journal file is open. If it is already open, this +** function is a no-op. +** +** SQLITE_OK is returned if everything goes according to plan. An +** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen() +** fails. +*/ +static int openSubJournal(Pager *pPager){ + int rc = SQLITE_OK; + if( !isOpen(pPager->sjfd) ){ + if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){ + sqlite3MemJournalOpen(pPager->sjfd); + }else{ + rc = pagerOpentemp(pPager, pPager->sjfd, SQLITE_OPEN_SUBJOURNAL); + } + } + return rc; +} + +/* +** Append a record of the current state of page pPg to the sub-journal. +** +** If successful, set the bit corresponding to pPg->pgno in the bitvecs +** for all open savepoints before returning. +** +** This function returns SQLITE_OK if everything is successful, an IO +** error code if the attempt to write to the sub-journal fails, or +** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint +** bitvec. +*/ +static int subjournalPage(PgHdr *pPg){ + int rc = SQLITE_OK; + Pager *pPager = pPg->pPager; + if( pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ + + /* Open the sub-journal, if it has not already been opened */ + assert( pPager->useJournal ); + assert( isOpen(pPager->jfd) || pagerUseWal(pPager) ); + assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 ); + assert( pagerUseWal(pPager) + || pageInJournal(pPager, pPg) + || pPg->pgno>pPager->dbOrigSize + ); + rc = openSubJournal(pPager); + + /* If the sub-journal was opened successfully (or was already open), + ** write the journal record into the file. */ + if( rc==SQLITE_OK ){ + void *pData = pPg->pData; + i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize); + char *pData2; + + CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); + PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno)); + rc = write32bits(pPager->sjfd, offset, pPg->pgno); + if( rc==SQLITE_OK ){ + rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4); + } + } + } + if( rc==SQLITE_OK ){ + pPager->nSubRec++; + assert( pPager->nSavepoint>0 ); + rc = addToSavepointBitvecs(pPager, pPg->pgno); + } + return rc; +} +static int subjournalPageIfRequired(PgHdr *pPg){ + if( subjRequiresPage(pPg) ){ + return subjournalPage(pPg); + }else{ + return SQLITE_OK; + } +} + +/* +** This function is called by the pcache layer when it has reached some +** soft memory limit. The first argument is a pointer to a Pager object +** (cast as a void*). The pager is always 'purgeable' (not an in-memory +** database). The second argument is a reference to a page that is +** currently dirty but has no outstanding references. The page +** is always associated with the Pager object passed as the first +** argument. +** +** The job of this function is to make pPg clean by writing its contents +** out to the database file, if possible. This may involve syncing the +** journal file. +** +** If successful, sqlite3PcacheMakeClean() is called on the page and +** SQLITE_OK returned. If an IO error occurs while trying to make the +** page clean, the IO error code is returned. If the page cannot be +** made clean for some other reason, but no error occurs, then SQLITE_OK +** is returned by sqlite3PcacheMakeClean() is not called. +*/ +static int pagerStress(void *p, PgHdr *pPg){ + Pager *pPager = (Pager *)p; + int rc = SQLITE_OK; + + assert( pPg->pPager==pPager ); + assert( pPg->flags&PGHDR_DIRTY ); + + /* The doNotSpill NOSYNC bit is set during times when doing a sync of + ** journal (and adding a new header) is not allowed. This occurs + ** during calls to sqlite3PagerWrite() while trying to journal multiple + ** pages belonging to the same sector. + ** + ** The doNotSpill ROLLBACK and OFF bits inhibits all cache spilling + ** regardless of whether or not a sync is required. This is set during + ** a rollback or by user request, respectively. + ** + ** Spilling is also prohibited when in an error state since that could + ** lead to database corruption. In the current implementation it + ** is impossible for sqlite3PcacheFetch() to be called with createFlag==3 + ** while in the error state, hence it is impossible for this routine to + ** be called in the error state. Nevertheless, we include a NEVER() + ** test for the error state as a safeguard against future changes. + */ + if( NEVER(pPager->errCode) ) return SQLITE_OK; + testcase( pPager->doNotSpill & SPILLFLAG_ROLLBACK ); + testcase( pPager->doNotSpill & SPILLFLAG_OFF ); + testcase( pPager->doNotSpill & SPILLFLAG_NOSYNC ); + if( pPager->doNotSpill + && ((pPager->doNotSpill & (SPILLFLAG_ROLLBACK|SPILLFLAG_OFF))!=0 + || (pPg->flags & PGHDR_NEED_SYNC)!=0) + ){ + return SQLITE_OK; + } + + pPg->pDirty = 0; + if( pagerUseWal(pPager) ){ + /* Write a single frame for this page to the log. */ + rc = subjournalPageIfRequired(pPg); + if( rc==SQLITE_OK ){ + rc = pagerWalFrames(pPager, pPg, 0, 0); + } + }else{ + + /* Sync the journal file if required. */ + if( pPg->flags&PGHDR_NEED_SYNC + || pPager->eState==PAGER_WRITER_CACHEMOD + ){ + rc = syncJournal(pPager, 1); + } + + /* Write the contents of the page out to the database file. */ + if( rc==SQLITE_OK ){ + assert( (pPg->flags&PGHDR_NEED_SYNC)==0 ); + rc = pager_write_pagelist(pPager, pPg); + } + } + + /* Mark the page as clean. */ + if( rc==SQLITE_OK ){ + PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno)); + sqlite3PcacheMakeClean(pPg); + } + + return pager_error(pPager, rc); +} + + +/* +** Allocate and initialize a new Pager object and put a pointer to it +** in *ppPager. The pager should eventually be freed by passing it +** to sqlite3PagerClose(). +** +** The zFilename argument is the path to the database file to open. +** If zFilename is NULL then a randomly-named temporary file is created +** and used as the file to be cached. Temporary files are be deleted +** automatically when they are closed. If zFilename is ":memory:" then +** all information is held in cache. It is never written to disk. +** This can be used to implement an in-memory database. +** +** The nExtra parameter specifies the number of bytes of space allocated +** along with each page reference. This space is available to the user +** via the sqlite3PagerGetExtra() API. +** +** The flags argument is used to specify properties that affect the +** operation of the pager. It should be passed some bitwise combination +** of the PAGER_* flags. +** +** The vfsFlags parameter is a bitmask to pass to the flags parameter +** of the xOpen() method of the supplied VFS when opening files. +** +** If the pager object is allocated and the specified file opened +** successfully, SQLITE_OK is returned and *ppPager set to point to +** the new pager object. If an error occurs, *ppPager is set to NULL +** and error code returned. This function may return SQLITE_NOMEM +** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or +** various SQLITE_IO_XXX errors. +*/ +SQLITE_PRIVATE int sqlite3PagerOpen( + sqlite3_vfs *pVfs, /* The virtual file system to use */ + Pager **ppPager, /* OUT: Return the Pager structure here */ + const char *zFilename, /* Name of the database file to open */ + int nExtra, /* Extra bytes append to each in-memory page */ + int flags, /* flags controlling this file */ + int vfsFlags, /* flags passed through to sqlite3_vfs.xOpen() */ + void (*xReinit)(DbPage*) /* Function to reinitialize pages */ +){ + u8 *pPtr; + Pager *pPager = 0; /* Pager object to allocate and return */ + int rc = SQLITE_OK; /* Return code */ + int tempFile = 0; /* True for temp files (incl. in-memory files) */ + int memDb = 0; /* True if this is an in-memory file */ + int readOnly = 0; /* True if this is a read-only file */ + int journalFileSize; /* Bytes to allocate for each journal fd */ + char *zPathname = 0; /* Full path to database file */ + int nPathname = 0; /* Number of bytes in zPathname */ + int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */ + int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */ + u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */ + const char *zUri = 0; /* URI args to copy */ + int nUri = 0; /* Number of bytes of URI args at *zUri */ + + /* Figure out how much space is required for each journal file-handle + ** (there are two of them, the main journal and the sub-journal). This + ** is the maximum space required for an in-memory journal file handle + ** and a regular journal file-handle. Note that a "regular journal-handle" + ** may be a wrapper capable of caching the first portion of the journal + ** file in memory to implement the atomic-write optimization (see + ** source file journal.c). + */ + if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){ + journalFileSize = ROUND8(sqlite3JournalSize(pVfs)); + }else{ + journalFileSize = ROUND8(sqlite3MemJournalSize()); + } + + /* Set the output variable to NULL in case an error occurs. */ + *ppPager = 0; + +#ifndef SQLITE_OMIT_MEMORYDB + if( flags & PAGER_MEMORY ){ + memDb = 1; + if( zFilename && zFilename[0] ){ + zPathname = sqlite3DbStrDup(0, zFilename); + if( zPathname==0 ) return SQLITE_NOMEM; + nPathname = sqlite3Strlen30(zPathname); + zFilename = 0; + } + } +#endif + + /* Compute and store the full pathname in an allocated buffer pointed + ** to by zPathname, length nPathname. Or, if this is a temporary file, + ** leave both nPathname and zPathname set to 0. + */ + if( zFilename && zFilename[0] ){ + const char *z; + nPathname = pVfs->mxPathname+1; + zPathname = sqlite3DbMallocRaw(0, nPathname*2); + if( zPathname==0 ){ + return SQLITE_NOMEM; + } + zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */ + rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname); + nPathname = sqlite3Strlen30(zPathname); + z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1]; + while( *z ){ + z += sqlite3Strlen30(z)+1; + z += sqlite3Strlen30(z)+1; + } + nUri = (int)(&z[1] - zUri); + assert( nUri>=0 ); + if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){ + /* This branch is taken when the journal path required by + ** the database being opened will be more than pVfs->mxPathname + ** bytes in length. This means the database cannot be opened, + ** as it will not be possible to open the journal file or even + ** check for a hot-journal before reading. + */ + rc = SQLITE_CANTOPEN_BKPT; + } + if( rc!=SQLITE_OK ){ + sqlite3DbFree(0, zPathname); + return rc; + } + } + + /* Allocate memory for the Pager structure, PCache object, the + ** three file descriptors, the database file name and the journal + ** file name. The layout in memory is as follows: + ** + ** Pager object (sizeof(Pager) bytes) + ** PCache object (sqlite3PcacheSize() bytes) + ** Database file handle (pVfs->szOsFile bytes) + ** Sub-journal file handle (journalFileSize bytes) + ** Main journal file handle (journalFileSize bytes) + ** Database file name (nPathname+1 bytes) + ** Journal file name (nPathname+8+1 bytes) + */ + pPtr = (u8 *)sqlite3MallocZero( + ROUND8(sizeof(*pPager)) + /* Pager structure */ + ROUND8(pcacheSize) + /* PCache object */ + ROUND8(pVfs->szOsFile) + /* The main db file */ + journalFileSize * 2 + /* The two journal files */ + nPathname + 1 + nUri + /* zFilename */ + nPathname + 8 + 2 /* zJournal */ +#ifndef SQLITE_OMIT_WAL + + nPathname + 4 + 2 /* zWal */ +#endif + ); + assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) ); + if( !pPtr ){ + sqlite3DbFree(0, zPathname); + return SQLITE_NOMEM; + } + pPager = (Pager*)(pPtr); + pPager->pPCache = (PCache*)(pPtr += ROUND8(sizeof(*pPager))); + pPager->fd = (sqlite3_file*)(pPtr += ROUND8(pcacheSize)); + pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile)); + pPager->jfd = (sqlite3_file*)(pPtr += journalFileSize); + pPager->zFilename = (char*)(pPtr += journalFileSize); + assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) ); + + /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */ + if( zPathname ){ + assert( nPathname>0 ); + pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri); + memcpy(pPager->zFilename, zPathname, nPathname); + if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri); + memcpy(pPager->zJournal, zPathname, nPathname); + memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2); + sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal); +#ifndef SQLITE_OMIT_WAL + pPager->zWal = &pPager->zJournal[nPathname+8+1]; + memcpy(pPager->zWal, zPathname, nPathname); + memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1); + sqlite3FileSuffix3(pPager->zFilename, pPager->zWal); +#endif + sqlite3DbFree(0, zPathname); + } + pPager->pVfs = pVfs; + pPager->vfsFlags = vfsFlags; + + /* Open the pager file. + */ + if( zFilename && zFilename[0] ){ + int fout = 0; /* VFS flags returned by xOpen() */ + rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout); + assert( !memDb ); + readOnly = (fout&SQLITE_OPEN_READONLY); + + /* If the file was successfully opened for read/write access, + ** choose a default page size in case we have to create the + ** database file. The default page size is the maximum of: + ** + ** + SQLITE_DEFAULT_PAGE_SIZE, + ** + The value returned by sqlite3OsSectorSize() + ** + The largest page size that can be written atomically. + */ + if( rc==SQLITE_OK ){ + int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); + if( !readOnly ){ + setSectorSize(pPager); + assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE); + if( szPageDfltsectorSize ){ + if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){ + szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE; + }else{ + szPageDflt = (u32)pPager->sectorSize; + } + } +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + { + int ii; + assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); + assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); + assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536); + for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){ + if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){ + szPageDflt = ii; + } + } + } +#endif + } + pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0); + if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0 + || sqlite3_uri_boolean(zFilename, "immutable", 0) ){ + vfsFlags |= SQLITE_OPEN_READONLY; + goto act_like_temp_file; + } + } + }else{ + /* If a temporary file is requested, it is not opened immediately. + ** In this case we accept the default page size and delay actually + ** opening the file until the first call to OsWrite(). + ** + ** This branch is also run for an in-memory database. An in-memory + ** database is the same as a temp-file that is never written out to + ** disk and uses an in-memory rollback journal. + ** + ** This branch also runs for files marked as immutable. + */ +act_like_temp_file: + tempFile = 1; + pPager->eState = PAGER_READER; /* Pretend we already have a lock */ + pPager->eLock = EXCLUSIVE_LOCK; /* Pretend we are in EXCLUSIVE mode */ + pPager->noLock = 1; /* Do no locking */ + readOnly = (vfsFlags&SQLITE_OPEN_READONLY); + } + + /* The following call to PagerSetPagesize() serves to set the value of + ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer. + */ + if( rc==SQLITE_OK ){ + assert( pPager->memDb==0 ); + rc = sqlite3PagerSetPagesize(pPager, &szPageDflt, -1); + testcase( rc!=SQLITE_OK ); + } + + /* Initialize the PCache object. */ + if( rc==SQLITE_OK ){ + assert( nExtra<1000 ); + nExtra = ROUND8(nExtra); + rc = sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, + !memDb?pagerStress:0, (void *)pPager, pPager->pPCache); + } + + /* If an error occurred above, free the Pager structure and close the file. + */ + if( rc!=SQLITE_OK ){ + sqlite3OsClose(pPager->fd); + sqlite3PageFree(pPager->pTmpSpace); + sqlite3_free(pPager); + return rc; + } + + PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename)); + IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename)) + + pPager->useJournal = (u8)useJournal; + /* pPager->stmtOpen = 0; */ + /* pPager->stmtInUse = 0; */ + /* pPager->nRef = 0; */ + /* pPager->stmtSize = 0; */ + /* pPager->stmtJSize = 0; */ + /* pPager->nPage = 0; */ + pPager->mxPgno = SQLITE_MAX_PAGE_COUNT; + /* pPager->state = PAGER_UNLOCK; */ + /* pPager->errMask = 0; */ + pPager->tempFile = (u8)tempFile; + assert( tempFile==PAGER_LOCKINGMODE_NORMAL + || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE ); + assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 ); + pPager->exclusiveMode = (u8)tempFile; + pPager->changeCountDone = pPager->tempFile; + pPager->memDb = (u8)memDb; + pPager->readOnly = (u8)readOnly; + assert( useJournal || pPager->tempFile ); + pPager->noSync = pPager->tempFile; + if( pPager->noSync ){ + assert( pPager->fullSync==0 ); + assert( pPager->syncFlags==0 ); + assert( pPager->walSyncFlags==0 ); + assert( pPager->ckptSyncFlags==0 ); + }else{ + pPager->fullSync = 1; + pPager->syncFlags = SQLITE_SYNC_NORMAL; + pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS; + pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; + } + /* pPager->pFirst = 0; */ + /* pPager->pFirstSynced = 0; */ + /* pPager->pLast = 0; */ + pPager->nExtra = (u16)nExtra; + pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; + assert( isOpen(pPager->fd) || tempFile ); + setSectorSize(pPager); + if( !useJournal ){ + pPager->journalMode = PAGER_JOURNALMODE_OFF; + }else if( memDb ){ + pPager->journalMode = PAGER_JOURNALMODE_MEMORY; + } + /* pPager->xBusyHandler = 0; */ + /* pPager->pBusyHandlerArg = 0; */ + pPager->xReiniter = xReinit; + /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ + /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */ + + *ppPager = pPager; + return SQLITE_OK; +} + + +/* Verify that the database file has not be deleted or renamed out from +** under the pager. Return SQLITE_OK if the database is still were it ought +** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error +** code from sqlite3OsAccess()) if the database has gone missing. +*/ +static int databaseIsUnmoved(Pager *pPager){ + int bHasMoved = 0; + int rc; + + if( pPager->tempFile ) return SQLITE_OK; + if( pPager->dbSize==0 ) return SQLITE_OK; + assert( pPager->zFilename && pPager->zFilename[0] ); + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved); + if( rc==SQLITE_NOTFOUND ){ + /* If the HAS_MOVED file-control is unimplemented, assume that the file + ** has not been moved. That is the historical behavior of SQLite: prior to + ** version 3.8.3, it never checked */ + rc = SQLITE_OK; + }else if( rc==SQLITE_OK && bHasMoved ){ + rc = SQLITE_READONLY_DBMOVED; + } + return rc; +} + + +/* +** This function is called after transitioning from PAGER_UNLOCK to +** PAGER_SHARED state. It tests if there is a hot journal present in +** the file-system for the given pager. A hot journal is one that +** needs to be played back. According to this function, a hot-journal +** file exists if the following criteria are met: +** +** * The journal file exists in the file system, and +** * No process holds a RESERVED or greater lock on the database file, and +** * The database file itself is greater than 0 bytes in size, and +** * The first byte of the journal file exists and is not 0x00. +** +** If the current size of the database file is 0 but a journal file +** exists, that is probably an old journal left over from a prior +** database with the same name. In this case the journal file is +** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK +** is returned. +** +** This routine does not check if there is a master journal filename +** at the end of the file. If there is, and that master journal file +** does not exist, then the journal file is not really hot. In this +** case this routine will return a false-positive. The pager_playback() +** routine will discover that the journal file is not really hot and +** will not roll it back. +** +** If a hot-journal file is found to exist, *pExists is set to 1 and +** SQLITE_OK returned. If no hot-journal file is present, *pExists is +** set to 0 and SQLITE_OK returned. If an IO error occurs while trying +** to determine whether or not a hot-journal file exists, the IO error +** code is returned and the value of *pExists is undefined. +*/ +static int hasHotJournal(Pager *pPager, int *pExists){ + sqlite3_vfs * const pVfs = pPager->pVfs; + int rc = SQLITE_OK; /* Return code */ + int exists = 1; /* True if a journal file is present */ + int jrnlOpen = !!isOpen(pPager->jfd); + + assert( pPager->useJournal ); + assert( isOpen(pPager->fd) ); + assert( pPager->eState==PAGER_OPEN ); + + assert( jrnlOpen==0 || ( sqlite3OsDeviceCharacteristics(pPager->jfd) & + SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN + )); + + *pExists = 0; + if( !jrnlOpen ){ + rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists); + } + if( rc==SQLITE_OK && exists ){ + int locked = 0; /* True if some process holds a RESERVED lock */ + + /* Race condition here: Another process might have been holding the + ** the RESERVED lock and have a journal open at the sqlite3OsAccess() + ** call above, but then delete the journal and drop the lock before + ** we get to the following sqlite3OsCheckReservedLock() call. If that + ** is the case, this routine might think there is a hot journal when + ** in fact there is none. This results in a false-positive which will + ** be dealt with by the playback routine. Ticket #3883. + */ + rc = sqlite3OsCheckReservedLock(pPager->fd, &locked); + if( rc==SQLITE_OK && !locked ){ + Pgno nPage; /* Number of pages in database file */ + + rc = pagerPagecount(pPager, &nPage); + if( rc==SQLITE_OK ){ + /* If the database is zero pages in size, that means that either (1) the + ** journal is a remnant from a prior database with the same name where + ** the database file but not the journal was deleted, or (2) the initial + ** transaction that populates a new database is being rolled back. + ** In either case, the journal file can be deleted. However, take care + ** not to delete the journal file if it is already open due to + ** journal_mode=PERSIST. + */ + if( nPage==0 && !jrnlOpen ){ + sqlite3BeginBenignMalloc(); + if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){ + sqlite3OsDelete(pVfs, pPager->zJournal, 0); + if( !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); + } + sqlite3EndBenignMalloc(); + }else{ + /* The journal file exists and no other connection has a reserved + ** or greater lock on the database file. Now check that there is + ** at least one non-zero bytes at the start of the journal file. + ** If there is, then we consider this journal to be hot. If not, + ** it can be ignored. + */ + if( !jrnlOpen ){ + int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL; + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f); + } + if( rc==SQLITE_OK ){ + u8 first = 0; + rc = sqlite3OsRead(pPager->jfd, (void *)&first, 1, 0); + if( rc==SQLITE_IOERR_SHORT_READ ){ + rc = SQLITE_OK; + } + if( !jrnlOpen ){ + sqlite3OsClose(pPager->jfd); + } + *pExists = (first!=0); + }else if( rc==SQLITE_CANTOPEN ){ + /* If we cannot open the rollback journal file in order to see if + ** it has a zero header, that might be due to an I/O error, or + ** it might be due to the race condition described above and in + ** ticket #3883. Either way, assume that the journal is hot. + ** This might be a false positive. But if it is, then the + ** automatic journal playback and recovery mechanism will deal + ** with it under an EXCLUSIVE lock where we do not need to + ** worry so much with race conditions. + */ + *pExists = 1; + rc = SQLITE_OK; + } + } + } + } + } + + return rc; +} + +/* +** This function is called to obtain a shared lock on the database file. +** It is illegal to call sqlite3PagerAcquire() until after this function +** has been successfully called. If a shared-lock is already held when +** this function is called, it is a no-op. +** +** The following operations are also performed by this function. +** +** 1) If the pager is currently in PAGER_OPEN state (no lock held +** on the database file), then an attempt is made to obtain a +** SHARED lock on the database file. Immediately after obtaining +** the SHARED lock, the file-system is checked for a hot-journal, +** which is played back if present. Following any hot-journal +** rollback, the contents of the cache are validated by checking +** the 'change-counter' field of the database file header and +** discarded if they are found to be invalid. +** +** 2) If the pager is running in exclusive-mode, and there are currently +** no outstanding references to any pages, and is in the error state, +** then an attempt is made to clear the error state by discarding +** the contents of the page cache and rolling back any open journal +** file. +** +** If everything is successful, SQLITE_OK is returned. If an IO error +** occurs while locking the database, checking for a hot-journal file or +** rolling back a journal file, the IO error code is returned. +*/ +SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ + int rc = SQLITE_OK; /* Return code */ + + /* This routine is only called from b-tree and only when there are no + ** outstanding pages. This implies that the pager state should either + ** be OPEN or READER. READER is only possible if the pager is or was in + ** exclusive access mode. + */ + assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); + assert( assert_pager_state(pPager) ); + assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER ); + if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; } + + if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){ + int bHotJournal = 1; /* True if there exists a hot journal-file */ + + assert( !MEMDB ); + + rc = pager_wait_on_lock(pPager, SHARED_LOCK); + if( rc!=SQLITE_OK ){ + assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK ); + goto failed; + } + + /* If a journal file exists, and there is no RESERVED lock on the + ** database file, then it either needs to be played back or deleted. + */ + if( pPager->eLock<=SHARED_LOCK ){ + rc = hasHotJournal(pPager, &bHotJournal); + } + if( rc!=SQLITE_OK ){ + goto failed; + } + if( bHotJournal ){ + if( pPager->readOnly ){ + rc = SQLITE_READONLY_ROLLBACK; + goto failed; + } + + /* Get an EXCLUSIVE lock on the database file. At this point it is + ** important that a RESERVED lock is not obtained on the way to the + ** EXCLUSIVE lock. If it were, another process might open the + ** database file, detect the RESERVED lock, and conclude that the + ** database is safe to read while this process is still rolling the + ** hot-journal back. + ** + ** Because the intermediate RESERVED lock is not requested, any + ** other process attempting to access the database file will get to + ** this point in the code and fail to obtain its own EXCLUSIVE lock + ** on the database file. + ** + ** Unless the pager is in locking_mode=exclusive mode, the lock is + ** downgraded to SHARED_LOCK before this function returns. + */ + rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); + if( rc!=SQLITE_OK ){ + goto failed; + } + + /* If it is not already open and the file exists on disk, open the + ** journal for read/write access. Write access is required because + ** in exclusive-access mode the file descriptor will be kept open + ** and possibly used for a transaction later on. Also, write-access + ** is usually required to finalize the journal in journal_mode=persist + ** mode (and also for journal_mode=truncate on some systems). + ** + ** If the journal does not exist, it usually means that some + ** other connection managed to get in and roll it back before + ** this connection obtained the exclusive lock above. Or, it + ** may mean that the pager was in the error-state when this + ** function was called and the journal file does not exist. + */ + if( !isOpen(pPager->jfd) ){ + sqlite3_vfs * const pVfs = pPager->pVfs; + int bExists; /* True if journal file exists */ + rc = sqlite3OsAccess( + pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists); + if( rc==SQLITE_OK && bExists ){ + int fout = 0; + int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; + assert( !pPager->tempFile ); + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout); + assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); + if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){ + rc = SQLITE_CANTOPEN_BKPT; + sqlite3OsClose(pPager->jfd); + } + } + } + + /* Playback and delete the journal. Drop the database write + ** lock and reacquire the read lock. Purge the cache before + ** playing back the hot-journal so that we don't end up with + ** an inconsistent cache. Sync the hot journal before playing + ** it back since the process that crashed and left the hot journal + ** probably did not sync it and we are required to always sync + ** the journal before playing it back. + */ + if( isOpen(pPager->jfd) ){ + assert( rc==SQLITE_OK ); + rc = pagerSyncHotJournal(pPager); + if( rc==SQLITE_OK ){ + rc = pager_playback(pPager, 1); + pPager->eState = PAGER_OPEN; + } + }else if( !pPager->exclusiveMode ){ + pagerUnlockDb(pPager, SHARED_LOCK); + } + + if( rc!=SQLITE_OK ){ + /* This branch is taken if an error occurs while trying to open + ** or roll back a hot-journal while holding an EXCLUSIVE lock. The + ** pager_unlock() routine will be called before returning to unlock + ** the file. If the unlock attempt fails, then Pager.eLock must be + ** set to UNKNOWN_LOCK (see the comment above the #define for + ** UNKNOWN_LOCK above for an explanation). + ** + ** In order to get pager_unlock() to do this, set Pager.eState to + ** PAGER_ERROR now. This is not actually counted as a transition + ** to ERROR state in the state diagram at the top of this file, + ** since we know that the same call to pager_unlock() will very + ** shortly transition the pager object to the OPEN state. Calling + ** assert_pager_state() would fail now, as it should not be possible + ** to be in ERROR state when there are zero outstanding page + ** references. + */ + pager_error(pPager, rc); + goto failed; + } + + assert( pPager->eState==PAGER_OPEN ); + assert( (pPager->eLock==SHARED_LOCK) + || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK) + ); + } + + if( !pPager->tempFile && pPager->hasBeenUsed ){ + /* The shared-lock has just been acquired then check to + ** see if the database has been modified. If the database has changed, + ** flush the cache. The pPager->hasBeenUsed flag prevents this from + ** occurring on the very first access to a file, in order to save a + ** single unnecessary sqlite3OsRead() call at the start-up. + ** + ** Database changes are detected by looking at 15 bytes beginning + ** at offset 24 into the file. The first 4 of these 16 bytes are + ** a 32-bit counter that is incremented with each change. The + ** other bytes change randomly with each file change when + ** a codec is in use. + ** + ** There is a vanishingly small chance that a change will not be + ** detected. The chance of an undetected change is so small that + ** it can be neglected. + */ + Pgno nPage = 0; + char dbFileVers[sizeof(pPager->dbFileVers)]; + + rc = pagerPagecount(pPager, &nPage); + if( rc ) goto failed; + + if( nPage>0 ){ + IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers))); + rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24); + if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){ + goto failed; + } + }else{ + memset(dbFileVers, 0, sizeof(dbFileVers)); + } + + if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){ + pager_reset(pPager); + + /* Unmap the database file. It is possible that external processes + ** may have truncated the database file and then extended it back + ** to its original size while this process was not holding a lock. + ** In this case there may exist a Pager.pMap mapping that appears + ** to be the right size but is not actually valid. Avoid this + ** possibility by unmapping the db here. */ + if( USEFETCH(pPager) ){ + sqlite3OsUnfetch(pPager->fd, 0, 0); + } + } + } + + /* If there is a WAL file in the file-system, open this database in WAL + ** mode. Otherwise, the following function call is a no-op. + */ + rc = pagerOpenWalIfPresent(pPager); +#ifndef SQLITE_OMIT_WAL + assert( pPager->pWal==0 || rc==SQLITE_OK ); +#endif + } + + if( pagerUseWal(pPager) ){ + assert( rc==SQLITE_OK ); + rc = pagerBeginReadTransaction(pPager); + } + + if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){ + rc = pagerPagecount(pPager, &pPager->dbSize); + } + + failed: + if( rc!=SQLITE_OK ){ + assert( !MEMDB ); + pager_unlock(pPager); + assert( pPager->eState==PAGER_OPEN ); + }else{ + pPager->eState = PAGER_READER; + } + return rc; +} + +/* +** If the reference count has reached zero, rollback any active +** transaction and unlock the pager. +** +** Except, in locking_mode=EXCLUSIVE when there is nothing to in +** the rollback journal, the unlock is not performed and there is +** nothing to rollback, so this routine is a no-op. +*/ +static void pagerUnlockIfUnused(Pager *pPager){ + if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){ + pagerUnlockAndRollback(pPager); + } +} + +/* +** Acquire a reference to page number pgno in pager pPager (a page +** reference has type DbPage*). If the requested reference is +** successfully obtained, it is copied to *ppPage and SQLITE_OK returned. +** +** If the requested page is already in the cache, it is returned. +** Otherwise, a new page object is allocated and populated with data +** read from the database file. In some cases, the pcache module may +** choose not to allocate a new page object and may reuse an existing +** object with no outstanding references. +** +** The extra data appended to a page is always initialized to zeros the +** first time a page is loaded into memory. If the page requested is +** already in the cache when this function is called, then the extra +** data is left as it was when the page object was last used. +** +** If the database image is smaller than the requested page or if a +** non-zero value is passed as the noContent parameter and the +** requested page is not already stored in the cache, then no +** actual disk read occurs. In this case the memory image of the +** page is initialized to all zeros. +** +** If noContent is true, it means that we do not care about the contents +** of the page. This occurs in two scenarios: +** +** a) When reading a free-list leaf page from the database, and +** +** b) When a savepoint is being rolled back and we need to load +** a new page into the cache to be filled with the data read +** from the savepoint journal. +** +** If noContent is true, then the data returned is zeroed instead of +** being read from the database. Additionally, the bits corresponding +** to pgno in Pager.pInJournal (bitvec of pages already written to the +** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open +** savepoints are set. This means if the page is made writable at any +** point in the future, using a call to sqlite3PagerWrite(), its contents +** will not be journaled. This saves IO. +** +** The acquisition might fail for several reasons. In all cases, +** an appropriate error code is returned and *ppPage is set to NULL. +** +** See also sqlite3PagerLookup(). Both this routine and Lookup() attempt +** to find a page in the in-memory cache first. If the page is not already +** in memory, this routine goes to disk to read it in whereas Lookup() +** just returns 0. This routine acquires a read-lock the first time it +** has to go to disk, and could also playback an old journal if necessary. +** Since Lookup() never goes to disk, it never has to deal with locks +** or journal files. +*/ +SQLITE_PRIVATE int sqlite3PagerAcquire( + Pager *pPager, /* The pager open on the database file */ + Pgno pgno, /* Page number to fetch */ + DbPage **ppPage, /* Write a pointer to the page here */ + int flags /* PAGER_GET_XXX flags */ +){ + int rc = SQLITE_OK; + PgHdr *pPg = 0; + u32 iFrame = 0; /* Frame to read from WAL file */ + const int noContent = (flags & PAGER_GET_NOCONTENT); + + /* It is acceptable to use a read-only (mmap) page for any page except + ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY + ** flag was specified by the caller. And so long as the db is not a + ** temporary or in-memory database. */ + const int bMmapOk = (pgno!=1 && USEFETCH(pPager) + && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY)) +#ifdef SQLITE_HAS_CODEC + && pPager->xCodec==0 +#endif + ); + + assert( pPager->eState>=PAGER_READER ); + assert( assert_pager_state(pPager) ); + assert( noContent==0 || bMmapOk==0 ); + + if( pgno==0 ){ + return SQLITE_CORRUPT_BKPT; + } + pPager->hasBeenUsed = 1; + + /* If the pager is in the error state, return an error immediately. + ** Otherwise, request the page from the PCache layer. */ + if( pPager->errCode!=SQLITE_OK ){ + rc = pPager->errCode; + }else{ + if( bMmapOk && pagerUseWal(pPager) ){ + rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); + if( rc!=SQLITE_OK ) goto pager_acquire_err; + } + + if( bMmapOk && iFrame==0 ){ + void *pData = 0; + + rc = sqlite3OsFetch(pPager->fd, + (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData + ); + + if( rc==SQLITE_OK && pData ){ + if( pPager->eState>PAGER_READER ){ + pPg = sqlite3PagerLookup(pPager, pgno); + } + if( pPg==0 ){ + rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg); + }else{ + sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData); + } + if( pPg ){ + assert( rc==SQLITE_OK ); + *ppPage = pPg; + return SQLITE_OK; + } + } + if( rc!=SQLITE_OK ){ + goto pager_acquire_err; + } + } + + { + sqlite3_pcache_page *pBase; + pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3); + if( pBase==0 ){ + rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase); + if( rc!=SQLITE_OK ) goto pager_acquire_err; + if( pBase==0 ){ + pPg = *ppPage = 0; + rc = SQLITE_NOMEM; + goto pager_acquire_err; + } + } + pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase); + assert( pPg!=0 ); + } + } + + if( rc!=SQLITE_OK ){ + /* Either the call to sqlite3PcacheFetch() returned an error or the + ** pager was already in the error-state when this function was called. + ** Set pPg to 0 and jump to the exception handler. */ + pPg = 0; + goto pager_acquire_err; + } + assert( pPg==(*ppPage) ); + assert( pPg->pgno==pgno ); + assert( pPg->pPager==pPager || pPg->pPager==0 ); + + if( pPg->pPager && !noContent ){ + /* In this case the pcache already contains an initialized copy of + ** the page. Return without further ado. */ + assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) ); + pPager->aStat[PAGER_STAT_HIT]++; + return SQLITE_OK; + + }else{ + /* The pager cache has created a new page. Its content needs to + ** be initialized. */ + + pPg->pPager = pPager; + + /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page + ** number greater than this, or the unused locking-page, is requested. */ + if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){ + rc = SQLITE_CORRUPT_BKPT; + goto pager_acquire_err; + } + + if( MEMDB || pPager->dbSizefd) ){ + if( pgno>pPager->mxPgno ){ + rc = SQLITE_FULL; + goto pager_acquire_err; + } + if( noContent ){ + /* Failure to set the bits in the InJournal bit-vectors is benign. + ** It merely means that we might do some extra work to journal a + ** page that does not need to be journaled. Nevertheless, be sure + ** to test the case where a malloc error occurs while trying to set + ** a bit in a bit vector. + */ + sqlite3BeginBenignMalloc(); + if( pgno<=pPager->dbOrigSize ){ + TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno); + testcase( rc==SQLITE_NOMEM ); + } + TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno); + testcase( rc==SQLITE_NOMEM ); + sqlite3EndBenignMalloc(); + } + memset(pPg->pData, 0, pPager->pageSize); + IOTRACE(("ZERO %p %d\n", pPager, pgno)); + }else{ + if( pagerUseWal(pPager) && bMmapOk==0 ){ + rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); + if( rc!=SQLITE_OK ) goto pager_acquire_err; + } + assert( pPg->pPager==pPager ); + pPager->aStat[PAGER_STAT_MISS]++; + rc = readDbPage(pPg, iFrame); + if( rc!=SQLITE_OK ){ + goto pager_acquire_err; + } + } + pager_set_pagehash(pPg); + } + + return SQLITE_OK; + +pager_acquire_err: + assert( rc!=SQLITE_OK ); + if( pPg ){ + sqlite3PcacheDrop(pPg); + } + pagerUnlockIfUnused(pPager); + + *ppPage = 0; + return rc; +} + +/* +** Acquire a page if it is already in the in-memory cache. Do +** not read the page from disk. Return a pointer to the page, +** or 0 if the page is not in cache. +** +** See also sqlite3PagerGet(). The difference between this routine +** and sqlite3PagerGet() is that _get() will go to the disk and read +** in the page if the page is not already in cache. This routine +** returns NULL if the page is not in cache or if a disk I/O error +** has ever happened. +*/ +SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ + sqlite3_pcache_page *pPage; + assert( pPager!=0 ); + assert( pgno!=0 ); + assert( pPager->pPCache!=0 ); + pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0); + assert( pPage==0 || pPager->hasBeenUsed ); + if( pPage==0 ) return 0; + return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage); +} + +/* +** Release a page reference. +** +** If the number of references to the page drop to zero, then the +** page is added to the LRU list. When all references to all pages +** are released, a rollback occurs and the lock on the database is +** removed. +*/ +SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage *pPg){ + Pager *pPager; + assert( pPg!=0 ); + pPager = pPg->pPager; + if( pPg->flags & PGHDR_MMAP ){ + pagerReleaseMapPage(pPg); + }else{ + sqlite3PcacheRelease(pPg); + } + pagerUnlockIfUnused(pPager); +} +SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){ + if( pPg ) sqlite3PagerUnrefNotNull(pPg); +} + +/* +** This function is called at the start of every write transaction. +** There must already be a RESERVED or EXCLUSIVE lock on the database +** file when this routine is called. +** +** Open the journal file for pager pPager and write a journal header +** to the start of it. If there are active savepoints, open the sub-journal +** as well. This function is only used when the journal file is being +** opened to write a rollback log for a transaction. It is not used +** when opening a hot journal file to roll it back. +** +** If the journal file is already open (as it may be in exclusive mode), +** then this function just writes a journal header to the start of the +** already open file. +** +** Whether or not the journal file is opened by this function, the +** Pager.pInJournal bitvec structure is allocated. +** +** Return SQLITE_OK if everything is successful. Otherwise, return +** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or +** an IO error code if opening or writing the journal file fails. +*/ +static int pager_open_journal(Pager *pPager){ + int rc = SQLITE_OK; /* Return code */ + sqlite3_vfs * const pVfs = pPager->pVfs; /* Local cache of vfs pointer */ + + assert( pPager->eState==PAGER_WRITER_LOCKED ); + assert( assert_pager_state(pPager) ); + assert( pPager->pInJournal==0 ); + + /* If already in the error state, this function is a no-op. But on + ** the other hand, this routine is never called if we are already in + ** an error state. */ + if( NEVER(pPager->errCode) ) return pPager->errCode; + + if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ + pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize); + if( pPager->pInJournal==0 ){ + return SQLITE_NOMEM; + } + + /* Open the journal file if it is not already open. */ + if( !isOpen(pPager->jfd) ){ + if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ + sqlite3MemJournalOpen(pPager->jfd); + }else{ + const int flags = /* VFS flags to open journal file */ + SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| + (pPager->tempFile ? + (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL): + (SQLITE_OPEN_MAIN_JOURNAL) + ); + + /* Verify that the database still has the same name as it did when + ** it was originally opened. */ + rc = databaseIsUnmoved(pPager); + if( rc==SQLITE_OK ){ +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + rc = sqlite3JournalOpen( + pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager) + ); +#else + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); +#endif + } + } + assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); + } + + + /* Write the first journal header to the journal file and open + ** the sub-journal if necessary. + */ + if( rc==SQLITE_OK ){ + /* TODO: Check if all of these are really required. */ + pPager->nRec = 0; + pPager->journalOff = 0; + pPager->setMaster = 0; + pPager->journalHdr = 0; + rc = writeJournalHdr(pPager); + } + } + + if( rc!=SQLITE_OK ){ + sqlite3BitvecDestroy(pPager->pInJournal); + pPager->pInJournal = 0; + }else{ + assert( pPager->eState==PAGER_WRITER_LOCKED ); + pPager->eState = PAGER_WRITER_CACHEMOD; + } + + return rc; +} + +/* +** Begin a write-transaction on the specified pager object. If a +** write-transaction has already been opened, this function is a no-op. +** +** If the exFlag argument is false, then acquire at least a RESERVED +** lock on the database file. If exFlag is true, then acquire at least +** an EXCLUSIVE lock. If such a lock is already held, no locking +** functions need be called. +** +** If the subjInMemory argument is non-zero, then any sub-journal opened +** within this transaction will be opened as an in-memory file. This +** has no effect if the sub-journal is already opened (as it may be when +** running in exclusive mode) or if the transaction does not require a +** sub-journal. If the subjInMemory argument is zero, then any required +** sub-journal is implemented in-memory if pPager is an in-memory database, +** or using a temporary file otherwise. +*/ +SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){ + int rc = SQLITE_OK; + + if( pPager->errCode ) return pPager->errCode; + assert( pPager->eState>=PAGER_READER && pPager->eStatesubjInMemory = (u8)subjInMemory; + + if( ALWAYS(pPager->eState==PAGER_READER) ){ + assert( pPager->pInJournal==0 ); + + if( pagerUseWal(pPager) ){ + /* If the pager is configured to use locking_mode=exclusive, and an + ** exclusive lock on the database is not already held, obtain it now. + */ + if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){ + rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); + if( rc!=SQLITE_OK ){ + return rc; + } + sqlite3WalExclusiveMode(pPager->pWal, 1); + } + + /* Grab the write lock on the log file. If successful, upgrade to + ** PAGER_RESERVED state. Otherwise, return an error code to the caller. + ** The busy-handler is not invoked if another connection already + ** holds the write-lock. If possible, the upper layer will call it. + */ + rc = sqlite3WalBeginWriteTransaction(pPager->pWal); + }else{ + /* Obtain a RESERVED lock on the database file. If the exFlag parameter + ** is true, then immediately upgrade this to an EXCLUSIVE lock. The + ** busy-handler callback can be used when upgrading to the EXCLUSIVE + ** lock, but not when obtaining the RESERVED lock. + */ + rc = pagerLockDb(pPager, RESERVED_LOCK); + if( rc==SQLITE_OK && exFlag ){ + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); + } + } + + if( rc==SQLITE_OK ){ + /* Change to WRITER_LOCKED state. + ** + ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD + ** when it has an open transaction, but never to DBMOD or FINISHED. + ** This is because in those states the code to roll back savepoint + ** transactions may copy data from the sub-journal into the database + ** file as well as into the page cache. Which would be incorrect in + ** WAL mode. + */ + pPager->eState = PAGER_WRITER_LOCKED; + pPager->dbHintSize = pPager->dbSize; + pPager->dbFileSize = pPager->dbSize; + pPager->dbOrigSize = pPager->dbSize; + pPager->journalOff = 0; + } + + assert( rc==SQLITE_OK || pPager->eState==PAGER_READER ); + assert( rc!=SQLITE_OK || pPager->eState==PAGER_WRITER_LOCKED ); + assert( assert_pager_state(pPager) ); + } + + PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager))); + return rc; +} + +/* +** Write page pPg onto the end of the rollback journal. +*/ +static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + int rc; + u32 cksum; + char *pData2; + i64 iOff = pPager->journalOff; + + /* We should never write to the journal file the page that + ** contains the database locks. The following assert verifies + ** that we do not. */ + assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); + + assert( pPager->journalHdr<=pPager->journalOff ); + CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); + cksum = pager_cksum(pPager, (u8*)pData2); + + /* Even if an IO or diskfull error occurs while journalling the + ** page in the block above, set the need-sync flag for the page. + ** Otherwise, when the transaction is rolled back, the logic in + ** playback_one_page() will think that the page needs to be restored + ** in the database file. And if an IO error occurs while doing so, + ** then corruption may follow. + */ + pPg->flags |= PGHDR_NEED_SYNC; + + rc = write32bits(pPager->jfd, iOff, pPg->pgno); + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4); + if( rc!=SQLITE_OK ) return rc; + rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum); + if( rc!=SQLITE_OK ) return rc; + + IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, + pPager->journalOff, pPager->pageSize)); + PAGER_INCR(sqlite3_pager_writej_count); + PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n", + PAGERID(pPager), pPg->pgno, + ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg))); + + pPager->journalOff += 8 + pPager->pageSize; + pPager->nRec++; + assert( pPager->pInJournal!=0 ); + rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); + testcase( rc==SQLITE_NOMEM ); + assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); + rc |= addToSavepointBitvecs(pPager, pPg->pgno); + assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); + return rc; +} + +/* +** Mark a single data page as writeable. The page is written into the +** main journal or sub-journal as required. If the page is written into +** one of the journals, the corresponding bit is set in the +** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs +** of any open savepoints as appropriate. +*/ +static int pager_write(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + int rc = SQLITE_OK; + + /* This routine is not called unless a write-transaction has already + ** been started. The journal file may or may not be open at this point. + ** It is never called in the ERROR state. + */ + assert( pPager->eState==PAGER_WRITER_LOCKED + || pPager->eState==PAGER_WRITER_CACHEMOD + || pPager->eState==PAGER_WRITER_DBMOD + ); + assert( assert_pager_state(pPager) ); + assert( pPager->errCode==0 ); + assert( pPager->readOnly==0 ); + CHECK_PAGE(pPg); + + /* The journal file needs to be opened. Higher level routines have already + ** obtained the necessary locks to begin the write-transaction, but the + ** rollback journal might not yet be open. Open it now if this is the case. + ** + ** This is done before calling sqlite3PcacheMakeDirty() on the page. + ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then + ** an error might occur and the pager would end up in WRITER_LOCKED state + ** with pages marked as dirty in the cache. + */ + if( pPager->eState==PAGER_WRITER_LOCKED ){ + rc = pager_open_journal(pPager); + if( rc!=SQLITE_OK ) return rc; + } + assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); + assert( assert_pager_state(pPager) ); + + /* Mark the page that is about to be modified as dirty. */ + sqlite3PcacheMakeDirty(pPg); + + /* If a rollback journal is in use, them make sure the page that is about + ** to change is in the rollback journal, or if the page is a new page off + ** then end of the file, make sure it is marked as PGHDR_NEED_SYNC. + */ + assert( (pPager->pInJournal!=0) == isOpen(pPager->jfd) ); + if( pPager->pInJournal!=0 + && sqlite3BitvecTestNotNull(pPager->pInJournal, pPg->pgno)==0 + ){ + assert( pagerUseWal(pPager)==0 ); + if( pPg->pgno<=pPager->dbOrigSize ){ + rc = pagerAddPageToRollbackJournal(pPg); + if( rc!=SQLITE_OK ){ + return rc; + } + }else{ + if( pPager->eState!=PAGER_WRITER_DBMOD ){ + pPg->flags |= PGHDR_NEED_SYNC; + } + PAGERTRACE(("APPEND %d page %d needSync=%d\n", + PAGERID(pPager), pPg->pgno, + ((pPg->flags&PGHDR_NEED_SYNC)?1:0))); + } + } + + /* The PGHDR_DIRTY bit is set above when the page was added to the dirty-list + ** and before writing the page into the rollback journal. Wait until now, + ** after the page has been successfully journalled, before setting the + ** PGHDR_WRITEABLE bit that indicates that the page can be safely modified. + */ + pPg->flags |= PGHDR_WRITEABLE; + + /* If the statement journal is open and the page is not in it, + ** then write the page into the statement journal. + */ + if( pPager->nSavepoint>0 ){ + rc = subjournalPageIfRequired(pPg); + } + + /* Update the database size and return. */ + if( pPager->dbSizepgno ){ + pPager->dbSize = pPg->pgno; + } + return rc; +} + +/* +** This is a variant of sqlite3PagerWrite() that runs when the sector size +** is larger than the page size. SQLite makes the (reasonable) assumption that +** all bytes of a sector are written together by hardware. Hence, all bytes of +** a sector need to be journalled in case of a power loss in the middle of +** a write. +** +** Usually, the sector size is less than or equal to the page size, in which +** case pages can be individually written. This routine only runs in the +** exceptional case where the page size is smaller than the sector size. +*/ +static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){ + int rc = SQLITE_OK; /* Return code */ + Pgno nPageCount; /* Total number of pages in database file */ + Pgno pg1; /* First page of the sector pPg is located on. */ + int nPage = 0; /* Number of pages starting at pg1 to journal */ + int ii; /* Loop counter */ + int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ + Pager *pPager = pPg->pPager; /* The pager that owns pPg */ + Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); + + /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow + ** a journal header to be written between the pages journaled by + ** this function. + */ + assert( !MEMDB ); + assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 ); + pPager->doNotSpill |= SPILLFLAG_NOSYNC; + + /* This trick assumes that both the page-size and sector-size are + ** an integer power of 2. It sets variable pg1 to the identifier + ** of the first page of the sector pPg is located on. + */ + pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; + + nPageCount = pPager->dbSize; + if( pPg->pgno>nPageCount ){ + nPage = (pPg->pgno - pg1)+1; + }else if( (pg1+nPagePerSector-1)>nPageCount ){ + nPage = nPageCount+1-pg1; + }else{ + nPage = nPagePerSector; + } + assert(nPage>0); + assert(pg1<=pPg->pgno); + assert((pg1+nPage)>pPg->pgno); + + for(ii=0; iipgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ + if( pg!=PAGER_MJ_PGNO(pPager) ){ + rc = sqlite3PagerGet(pPager, pg, &pPage); + if( rc==SQLITE_OK ){ + rc = pager_write(pPage); + if( pPage->flags&PGHDR_NEED_SYNC ){ + needSync = 1; + } + sqlite3PagerUnrefNotNull(pPage); + } + } + }else if( (pPage = sqlite3PagerLookup(pPager, pg))!=0 ){ + if( pPage->flags&PGHDR_NEED_SYNC ){ + needSync = 1; + } + sqlite3PagerUnrefNotNull(pPage); + } + } + + /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages + ** starting at pg1, then it needs to be set for all of them. Because + ** writing to any of these nPage pages may damage the others, the + ** journal file must contain sync()ed copies of all of them + ** before any of them can be written out to the database file. + */ + if( rc==SQLITE_OK && needSync ){ + assert( !MEMDB ); + for(ii=0; iiflags |= PGHDR_NEED_SYNC; + sqlite3PagerUnrefNotNull(pPage); + } + } + } + + assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 ); + pPager->doNotSpill &= ~SPILLFLAG_NOSYNC; + return rc; +} + +/* +** Mark a data page as writeable. This routine must be called before +** making changes to a page. The caller must check the return value +** of this function and be careful not to change any page data unless +** this routine returns SQLITE_OK. +** +** The difference between this function and pager_write() is that this +** function also deals with the special case where 2 or more pages +** fit on a single disk sector. In this case all co-resident pages +** must have been written to the journal file before returning. +** +** If an error occurs, SQLITE_NOMEM or an IO error code is returned +** as appropriate. Otherwise, SQLITE_OK. +*/ +SQLITE_PRIVATE int sqlite3PagerWrite(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + assert( (pPg->flags & PGHDR_MMAP)==0 ); + assert( pPager->eState>=PAGER_WRITER_LOCKED ); + assert( pPager->eState!=PAGER_ERROR ); + assert( assert_pager_state(pPager) ); + if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){ + if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg); + return SQLITE_OK; + }else if( pPager->sectorSize > (u32)pPager->pageSize ){ + return pagerWriteLargeSector(pPg); + }else{ + return pager_write(pPg); + } +} + +/* +** Return TRUE if the page given in the argument was previously passed +** to sqlite3PagerWrite(). In other words, return TRUE if it is ok +** to change the content of the page. +*/ +#ifndef NDEBUG +SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){ + return pPg->flags & PGHDR_WRITEABLE; +} +#endif + +/* +** A call to this routine tells the pager that it is not necessary to +** write the information on page pPg back to the disk, even though +** that page might be marked as dirty. This happens, for example, when +** the page has been added as a leaf of the freelist and so its +** content no longer matters. +** +** The overlying software layer calls this routine when all of the data +** on the given page is unused. The pager marks the page as clean so +** that it does not get written to disk. +** +** Tests show that this optimization can quadruple the speed of large +** DELETE operations. +*/ +SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){ + PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager))); + IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) + pPg->flags |= PGHDR_DONT_WRITE; + pPg->flags &= ~PGHDR_WRITEABLE; + pager_set_pagehash(pPg); + } +} + +/* +** This routine is called to increment the value of the database file +** change-counter, stored as a 4-byte big-endian integer starting at +** byte offset 24 of the pager file. The secondary change counter at +** 92 is also updated, as is the SQLite version number at offset 96. +** +** But this only happens if the pPager->changeCountDone flag is false. +** To avoid excess churning of page 1, the update only happens once. +** See also the pager_write_changecounter() routine that does an +** unconditional update of the change counters. +** +** If the isDirectMode flag is zero, then this is done by calling +** sqlite3PagerWrite() on page 1, then modifying the contents of the +** page data. In this case the file will be updated when the current +** transaction is committed. +** +** The isDirectMode flag may only be non-zero if the library was compiled +** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case, +** if isDirect is non-zero, then the database file is updated directly +** by writing an updated version of page 1 using a call to the +** sqlite3OsWrite() function. +*/ +static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ + int rc = SQLITE_OK; + + assert( pPager->eState==PAGER_WRITER_CACHEMOD + || pPager->eState==PAGER_WRITER_DBMOD + ); + assert( assert_pager_state(pPager) ); + + /* Declare and initialize constant integer 'isDirect'. If the + ** atomic-write optimization is enabled in this build, then isDirect + ** is initialized to the value passed as the isDirectMode parameter + ** to this function. Otherwise, it is always set to zero. + ** + ** The idea is that if the atomic-write optimization is not + ** enabled at compile time, the compiler can omit the tests of + ** 'isDirect' below, as well as the block enclosed in the + ** "if( isDirect )" condition. + */ +#ifndef SQLITE_ENABLE_ATOMIC_WRITE +# define DIRECT_MODE 0 + assert( isDirectMode==0 ); + UNUSED_PARAMETER(isDirectMode); +#else +# define DIRECT_MODE isDirectMode +#endif + + if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){ + PgHdr *pPgHdr; /* Reference to page 1 */ + + assert( !pPager->tempFile && isOpen(pPager->fd) ); + + /* Open page 1 of the file for writing. */ + rc = sqlite3PagerGet(pPager, 1, &pPgHdr); + assert( pPgHdr==0 || rc==SQLITE_OK ); + + /* If page one was fetched successfully, and this function is not + ** operating in direct-mode, make page 1 writable. When not in + ** direct mode, page 1 is always held in cache and hence the PagerGet() + ** above is always successful - hence the ALWAYS on rc==SQLITE_OK. + */ + if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){ + rc = sqlite3PagerWrite(pPgHdr); + } + + if( rc==SQLITE_OK ){ + /* Actually do the update of the change counter */ + pager_write_changecounter(pPgHdr); + + /* If running in direct mode, write the contents of page 1 to the file. */ + if( DIRECT_MODE ){ + const void *zBuf; + assert( pPager->dbFileSize>0 ); + CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf); + if( rc==SQLITE_OK ){ + rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0); + pPager->aStat[PAGER_STAT_WRITE]++; + } + if( rc==SQLITE_OK ){ + /* Update the pager's copy of the change-counter. Otherwise, the + ** next time a read transaction is opened the cache will be + ** flushed (as the change-counter values will not match). */ + const void *pCopy = (const void *)&((const char *)zBuf)[24]; + memcpy(&pPager->dbFileVers, pCopy, sizeof(pPager->dbFileVers)); + pPager->changeCountDone = 1; + } + }else{ + pPager->changeCountDone = 1; + } + } + + /* Release the page reference. */ + sqlite3PagerUnref(pPgHdr); + } + return rc; +} + +/* +** Sync the database file to disk. This is a no-op for in-memory databases +** or pages with the Pager.noSync flag set. +** +** If successful, or if called on a pager for which it is a no-op, this +** function returns SQLITE_OK. Otherwise, an IO error code is returned. +*/ +SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){ + int rc = SQLITE_OK; + + if( isOpen(pPager->fd) ){ + void *pArg = (void*)zMaster; + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg); + if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; + } + if( rc==SQLITE_OK && !pPager->noSync ){ + assert( !MEMDB ); + rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); + } + return rc; +} + +/* +** This function may only be called while a write-transaction is active in +** rollback. If the connection is in WAL mode, this call is a no-op. +** Otherwise, if the connection does not already have an EXCLUSIVE lock on +** the database file, an attempt is made to obtain one. +** +** If the EXCLUSIVE lock is already held or the attempt to obtain it is +** successful, or the connection is in WAL mode, SQLITE_OK is returned. +** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is +** returned. +*/ +SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){ + int rc = SQLITE_OK; + assert( pPager->eState==PAGER_WRITER_CACHEMOD + || pPager->eState==PAGER_WRITER_DBMOD + || pPager->eState==PAGER_WRITER_LOCKED + ); + assert( assert_pager_state(pPager) ); + if( 0==pagerUseWal(pPager) ){ + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); + } + return rc; +} + +/* +** Sync the database file for the pager pPager. zMaster points to the name +** of a master journal file that should be written into the individual +** journal file. zMaster may be NULL, which is interpreted as no master +** journal (a single database transaction). +** +** This routine ensures that: +** +** * The database file change-counter is updated, +** * the journal is synced (unless the atomic-write optimization is used), +** * all dirty pages are written to the database file, +** * the database file is truncated (if required), and +** * the database file synced. +** +** The only thing that remains to commit the transaction is to finalize +** (delete, truncate or zero the first part of) the journal file (or +** delete the master journal file if specified). +** +** Note that if zMaster==NULL, this does not overwrite a previous value +** passed to an sqlite3PagerCommitPhaseOne() call. +** +** If the final parameter - noSync - is true, then the database file itself +** is not synced. The caller must call sqlite3PagerSync() directly to +** sync the database file before calling CommitPhaseTwo() to delete the +** journal file in this case. +*/ +SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( + Pager *pPager, /* Pager object */ + const char *zMaster, /* If not NULL, the master journal name */ + int noSync /* True to omit the xSync on the db file */ +){ + int rc = SQLITE_OK; /* Return code */ + + assert( pPager->eState==PAGER_WRITER_LOCKED + || pPager->eState==PAGER_WRITER_CACHEMOD + || pPager->eState==PAGER_WRITER_DBMOD + || pPager->eState==PAGER_ERROR + ); + assert( assert_pager_state(pPager) ); + + /* If a prior error occurred, report that error again. */ + if( NEVER(pPager->errCode) ) return pPager->errCode; + + PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", + pPager->zFilename, zMaster, pPager->dbSize)); + + /* If no database changes have been made, return early. */ + if( pPager->eStatepBackup); + }else{ + if( pagerUseWal(pPager) ){ + PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); + PgHdr *pPageOne = 0; + if( pList==0 ){ + /* Must have at least one page for the WAL commit flag. + ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */ + rc = sqlite3PagerGet(pPager, 1, &pPageOne); + pList = pPageOne; + pList->pDirty = 0; + } + assert( rc==SQLITE_OK ); + if( ALWAYS(pList) ){ + rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1); + } + sqlite3PagerUnref(pPageOne); + if( rc==SQLITE_OK ){ + sqlite3PcacheCleanAll(pPager->pPCache); + } + }else{ + /* The following block updates the change-counter. Exactly how it + ** does this depends on whether or not the atomic-update optimization + ** was enabled at compile time, and if this transaction meets the + ** runtime criteria to use the operation: + ** + ** * The file-system supports the atomic-write property for + ** blocks of size page-size, and + ** * This commit is not part of a multi-file transaction, and + ** * Exactly one page has been modified and store in the journal file. + ** + ** If the optimization was not enabled at compile time, then the + ** pager_incr_changecounter() function is called to update the change + ** counter in 'indirect-mode'. If the optimization is compiled in but + ** is not applicable to this transaction, call sqlite3JournalCreate() + ** to make sure the journal file has actually been created, then call + ** pager_incr_changecounter() to update the change-counter in indirect + ** mode. + ** + ** Otherwise, if the optimization is both enabled and applicable, + ** then call pager_incr_changecounter() to update the change-counter + ** in 'direct' mode. In this case the journal file will never be + ** created for this transaction. + */ + #ifdef SQLITE_ENABLE_ATOMIC_WRITE + PgHdr *pPg; + assert( isOpen(pPager->jfd) + || pPager->journalMode==PAGER_JOURNALMODE_OFF + || pPager->journalMode==PAGER_JOURNALMODE_WAL + ); + if( !zMaster && isOpen(pPager->jfd) + && pPager->journalOff==jrnlBufferSize(pPager) + && pPager->dbSize>=pPager->dbOrigSize + && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty) + ){ + /* Update the db file change counter via the direct-write method. The + ** following call will modify the in-memory representation of page 1 + ** to include the updated change counter and then write page 1 + ** directly to the database file. Because of the atomic-write + ** property of the host file-system, this is safe. + */ + rc = pager_incr_changecounter(pPager, 1); + }else{ + rc = sqlite3JournalCreate(pPager->jfd); + if( rc==SQLITE_OK ){ + rc = pager_incr_changecounter(pPager, 0); + } + } + #else + rc = pager_incr_changecounter(pPager, 0); + #endif + if( rc!=SQLITE_OK ) goto commit_phase_one_exit; + + /* Write the master journal name into the journal file. If a master + ** journal file name has already been written to the journal file, + ** or if zMaster is NULL (no master journal), then this call is a no-op. + */ + rc = writeMasterJournal(pPager, zMaster); + if( rc!=SQLITE_OK ) goto commit_phase_one_exit; + + /* Sync the journal file and write all dirty pages to the database. + ** If the atomic-update optimization is being used, this sync will not + ** create the journal file or perform any real IO. + ** + ** Because the change-counter page was just modified, unless the + ** atomic-update optimization is used it is almost certain that the + ** journal requires a sync here. However, in locking_mode=exclusive + ** on a system under memory pressure it is just possible that this is + ** not the case. In this case it is likely enough that the redundant + ** xSync() call will be changed to a no-op by the OS anyhow. + */ + rc = syncJournal(pPager, 0); + if( rc!=SQLITE_OK ) goto commit_phase_one_exit; + + rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); + if( rc!=SQLITE_OK ){ + assert( rc!=SQLITE_IOERR_BLOCKED ); + goto commit_phase_one_exit; + } + sqlite3PcacheCleanAll(pPager->pPCache); + + /* If the file on disk is smaller than the database image, use + ** pager_truncate to grow the file here. This can happen if the database + ** image was extended as part of the current transaction and then the + ** last page in the db image moved to the free-list. In this case the + ** last page is never written out to disk, leaving the database file + ** undersized. Fix this now if it is the case. */ + if( pPager->dbSize>pPager->dbFileSize ){ + Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager)); + assert( pPager->eState==PAGER_WRITER_DBMOD ); + rc = pager_truncate(pPager, nNew); + if( rc!=SQLITE_OK ) goto commit_phase_one_exit; + } + + /* Finally, sync the database file. */ + if( !noSync ){ + rc = sqlite3PagerSync(pPager, zMaster); + } + IOTRACE(("DBSYNC %p\n", pPager)) + } + } + +commit_phase_one_exit: + if( rc==SQLITE_OK && !pagerUseWal(pPager) ){ + pPager->eState = PAGER_WRITER_FINISHED; + } + return rc; +} + + +/* +** When this function is called, the database file has been completely +** updated to reflect the changes made by the current transaction and +** synced to disk. The journal file still exists in the file-system +** though, and if a failure occurs at this point it will eventually +** be used as a hot-journal and the current transaction rolled back. +** +** This function finalizes the journal file, either by deleting, +** truncating or partially zeroing it, so that it cannot be used +** for hot-journal rollback. Once this is done the transaction is +** irrevocably committed. +** +** If an error occurs, an IO error code is returned and the pager +** moves into the error state. Otherwise, SQLITE_OK is returned. +*/ +SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){ + int rc = SQLITE_OK; /* Return code */ + + /* This routine should not be called if a prior error has occurred. + ** But if (due to a coding error elsewhere in the system) it does get + ** called, just return the same error code without doing anything. */ + if( NEVER(pPager->errCode) ) return pPager->errCode; + + assert( pPager->eState==PAGER_WRITER_LOCKED + || pPager->eState==PAGER_WRITER_FINISHED + || (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD) + ); + assert( assert_pager_state(pPager) ); + + /* An optimization. If the database was not actually modified during + ** this transaction, the pager is running in exclusive-mode and is + ** using persistent journals, then this function is a no-op. + ** + ** The start of the journal file currently contains a single journal + ** header with the nRec field set to 0. If such a journal is used as + ** a hot-journal during hot-journal rollback, 0 changes will be made + ** to the database file. So there is no need to zero the journal + ** header. Since the pager is in exclusive mode, there is no need + ** to drop any locks either. + */ + if( pPager->eState==PAGER_WRITER_LOCKED + && pPager->exclusiveMode + && pPager->journalMode==PAGER_JOURNALMODE_PERSIST + ){ + assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff ); + pPager->eState = PAGER_READER; + return SQLITE_OK; + } + + PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); + pPager->iDataVersion++; + rc = pager_end_transaction(pPager, pPager->setMaster, 1); + return pager_error(pPager, rc); +} + +/* +** If a write transaction is open, then all changes made within the +** transaction are reverted and the current write-transaction is closed. +** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR +** state if an error occurs. +** +** If the pager is already in PAGER_ERROR state when this function is called, +** it returns Pager.errCode immediately. No work is performed in this case. +** +** Otherwise, in rollback mode, this function performs two functions: +** +** 1) It rolls back the journal file, restoring all database file and +** in-memory cache pages to the state they were in when the transaction +** was opened, and +** +** 2) It finalizes the journal file, so that it is not used for hot +** rollback at any point in the future. +** +** Finalization of the journal file (task 2) is only performed if the +** rollback is successful. +** +** In WAL mode, all cache-entries containing data modified within the +** current transaction are either expelled from the cache or reverted to +** their pre-transaction state by re-reading data from the database or +** WAL files. The WAL transaction is then closed. +*/ +SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){ + int rc = SQLITE_OK; /* Return code */ + PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager))); + + /* PagerRollback() is a no-op if called in READER or OPEN state. If + ** the pager is already in the ERROR state, the rollback is not + ** attempted here. Instead, the error code is returned to the caller. + */ + assert( assert_pager_state(pPager) ); + if( pPager->eState==PAGER_ERROR ) return pPager->errCode; + if( pPager->eState<=PAGER_READER ) return SQLITE_OK; + + if( pagerUseWal(pPager) ){ + int rc2; + rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1); + rc2 = pager_end_transaction(pPager, pPager->setMaster, 0); + if( rc==SQLITE_OK ) rc = rc2; + }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){ + int eState = pPager->eState; + rc = pager_end_transaction(pPager, 0, 0); + if( !MEMDB && eState>PAGER_WRITER_LOCKED ){ + /* This can happen using journal_mode=off. Move the pager to the error + ** state to indicate that the contents of the cache may not be trusted. + ** Any active readers will get SQLITE_ABORT. + */ + pPager->errCode = SQLITE_ABORT; + pPager->eState = PAGER_ERROR; + return rc; + } + }else{ + rc = pager_playback(pPager, 0); + } + + assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK ); + assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT + || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR + || rc==SQLITE_CANTOPEN + ); + + /* If an error occurs during a ROLLBACK, we can no longer trust the pager + ** cache. So call pager_error() on the way out to make any error persistent. + */ + return pager_error(pPager, rc); +} + +/* +** Return TRUE if the database file is opened read-only. Return FALSE +** if the database is (in theory) writable. +*/ +SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager *pPager){ + return pPager->readOnly; +} + +#ifdef SQLITE_DEBUG +/* +** Return the number of references to the pager. +*/ +SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){ + return sqlite3PcacheRefCount(pPager->pPCache); +} +#endif + +/* +** Return the approximate number of bytes of memory currently +** used by the pager and its associated cache. +*/ +SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager *pPager){ + int perPageSize = pPager->pageSize + pPager->nExtra + sizeof(PgHdr) + + 5*sizeof(void*); + return perPageSize*sqlite3PcachePagecount(pPager->pPCache) + + sqlite3MallocSize(pPager) + + pPager->pageSize; +} + +/* +** Return the number of references to the specified page. +*/ +SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage *pPage){ + return sqlite3PcachePageRefcount(pPage); +} + +#ifdef SQLITE_TEST +/* +** This routine is used for testing and analysis only. +*/ +SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){ + static int a[11]; + a[0] = sqlite3PcacheRefCount(pPager->pPCache); + a[1] = sqlite3PcachePagecount(pPager->pPCache); + a[2] = sqlite3PcacheGetCachesize(pPager->pPCache); + a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize; + a[4] = pPager->eState; + a[5] = pPager->errCode; + a[6] = pPager->aStat[PAGER_STAT_HIT]; + a[7] = pPager->aStat[PAGER_STAT_MISS]; + a[8] = 0; /* Used to be pPager->nOvfl */ + a[9] = pPager->nRead; + a[10] = pPager->aStat[PAGER_STAT_WRITE]; + return a; +} +#endif + +/* +** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or +** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the +** current cache hit or miss count, according to the value of eStat. If the +** reset parameter is non-zero, the cache hit or miss count is zeroed before +** returning. +*/ +SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){ + + assert( eStat==SQLITE_DBSTATUS_CACHE_HIT + || eStat==SQLITE_DBSTATUS_CACHE_MISS + || eStat==SQLITE_DBSTATUS_CACHE_WRITE + ); + + assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS ); + assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE ); + assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 ); + + *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT]; + if( reset ){ + pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0; + } +} + +/* +** Return true if this is an in-memory pager. +*/ +SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){ + return MEMDB; +} + +/* +** Check that there are at least nSavepoint savepoints open. If there are +** currently less than nSavepoints open, then open one or more savepoints +** to make up the difference. If the number of savepoints is already +** equal to nSavepoint, then this function is a no-op. +** +** If a memory allocation fails, SQLITE_NOMEM is returned. If an error +** occurs while opening the sub-journal file, then an IO error code is +** returned. Otherwise, SQLITE_OK. +*/ +static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){ + int rc = SQLITE_OK; /* Return code */ + int nCurrent = pPager->nSavepoint; /* Current number of savepoints */ + int ii; /* Iterator variable */ + PagerSavepoint *aNew; /* New Pager.aSavepoint array */ + + assert( pPager->eState>=PAGER_WRITER_LOCKED ); + assert( assert_pager_state(pPager) ); + assert( nSavepoint>nCurrent && pPager->useJournal ); + + /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM + ** if the allocation fails. Otherwise, zero the new portion in case a + ** malloc failure occurs while populating it in the for(...) loop below. + */ + aNew = (PagerSavepoint *)sqlite3Realloc( + pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint + ); + if( !aNew ){ + return SQLITE_NOMEM; + } + memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint)); + pPager->aSavepoint = aNew; + + /* Populate the PagerSavepoint structures just allocated. */ + for(ii=nCurrent; iidbSize; + if( isOpen(pPager->jfd) && pPager->journalOff>0 ){ + aNew[ii].iOffset = pPager->journalOff; + }else{ + aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager); + } + aNew[ii].iSubRec = pPager->nSubRec; + aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize); + if( !aNew[ii].pInSavepoint ){ + return SQLITE_NOMEM; + } + if( pagerUseWal(pPager) ){ + sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData); + } + pPager->nSavepoint = ii+1; + } + assert( pPager->nSavepoint==nSavepoint ); + assertTruncateConstraint(pPager); + return rc; +} +SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){ + assert( pPager->eState>=PAGER_WRITER_LOCKED ); + assert( assert_pager_state(pPager) ); + + if( nSavepoint>pPager->nSavepoint && pPager->useJournal ){ + return pagerOpenSavepoint(pPager, nSavepoint); + }else{ + return SQLITE_OK; + } +} + + +/* +** This function is called to rollback or release (commit) a savepoint. +** The savepoint to release or rollback need not be the most recently +** created savepoint. +** +** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE. +** If it is SAVEPOINT_RELEASE, then release and destroy the savepoint with +** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes +** that have occurred since the specified savepoint was created. +** +** The savepoint to rollback or release is identified by parameter +** iSavepoint. A value of 0 means to operate on the outermost savepoint +** (the first created). A value of (Pager.nSavepoint-1) means operate +** on the most recently created savepoint. If iSavepoint is greater than +** (Pager.nSavepoint-1), then this function is a no-op. +** +** If a negative value is passed to this function, then the current +** transaction is rolled back. This is different to calling +** sqlite3PagerRollback() because this function does not terminate +** the transaction or unlock the database, it just restores the +** contents of the database to its original state. +** +** In any case, all savepoints with an index greater than iSavepoint +** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE), +** then savepoint iSavepoint is also destroyed. +** +** This function may return SQLITE_NOMEM if a memory allocation fails, +** or an IO error code if an IO error occurs while rolling back a +** savepoint. If no errors occur, SQLITE_OK is returned. +*/ +SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ + int rc = pPager->errCode; /* Return code */ + + assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK ); + assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK ); + + if( rc==SQLITE_OK && iSavepointnSavepoint ){ + int ii; /* Iterator variable */ + int nNew; /* Number of remaining savepoints after this op. */ + + /* Figure out how many savepoints will still be active after this + ** operation. Store this value in nNew. Then free resources associated + ** with any savepoints that are destroyed by this operation. + */ + nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1); + for(ii=nNew; iinSavepoint; ii++){ + sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); + } + pPager->nSavepoint = nNew; + + /* If this is a release of the outermost savepoint, truncate + ** the sub-journal to zero bytes in size. */ + if( op==SAVEPOINT_RELEASE ){ + if( nNew==0 && isOpen(pPager->sjfd) ){ + /* Only truncate if it is an in-memory sub-journal. */ + if( sqlite3IsMemJournal(pPager->sjfd) ){ + rc = sqlite3OsTruncate(pPager->sjfd, 0); + assert( rc==SQLITE_OK ); + } + pPager->nSubRec = 0; + } + } + /* Else this is a rollback operation, playback the specified savepoint. + ** If this is a temp-file, it is possible that the journal file has + ** not yet been opened. In this case there have been no changes to + ** the database file, so the playback operation can be skipped. + */ + else if( pagerUseWal(pPager) || isOpen(pPager->jfd) ){ + PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1]; + rc = pagerPlaybackSavepoint(pPager, pSavepoint); + assert(rc!=SQLITE_DONE); + } + } + + return rc; +} + +/* +** Return the full pathname of the database file. +** +** Except, if the pager is in-memory only, then return an empty string if +** nullIfMemDb is true. This routine is called with nullIfMemDb==1 when +** used to report the filename to the user, for compatibility with legacy +** behavior. But when the Btree needs to know the filename for matching to +** shared cache, it uses nullIfMemDb==0 so that in-memory databases can +** participate in shared-cache. +*/ +SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){ + return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename; +} + +/* +** Return the VFS structure for the pager. +*/ +SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){ + return pPager->pVfs; +} + +/* +** Return the file handle for the database file associated +** with the pager. This might return NULL if the file has +** not yet been opened. +*/ +SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){ + return pPager->fd; +} + +/* +** Return the full pathname of the journal file. +*/ +SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager *pPager){ + return pPager->zJournal; +} + +/* +** Return true if fsync() calls are disabled for this pager. Return FALSE +** if fsync()s are executed normally. +*/ +SQLITE_PRIVATE int sqlite3PagerNosync(Pager *pPager){ + return pPager->noSync; +} + +#ifdef SQLITE_HAS_CODEC +/* +** Set or retrieve the codec for this pager +*/ +SQLITE_PRIVATE void sqlite3PagerSetCodec( + Pager *pPager, + void *(*xCodec)(void*,void*,Pgno,int), + void (*xCodecSizeChng)(void*,int,int), + void (*xCodecFree)(void*), + void *pCodec +){ + if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); + pPager->xCodec = pPager->memDb ? 0 : xCodec; + pPager->xCodecSizeChng = xCodecSizeChng; + pPager->xCodecFree = xCodecFree; + pPager->pCodec = pCodec; + pagerReportSize(pPager); +} +SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){ + return pPager->pCodec; +} + +/* +** This function is called by the wal module when writing page content +** into the log file. +** +** This function returns a pointer to a buffer containing the encrypted +** page content. If a malloc fails, this function may return NULL. +*/ +SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){ + void *aData = 0; + CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData); + return aData; +} + +/* +** Return the current pager state +*/ +SQLITE_PRIVATE int sqlite3PagerState(Pager *pPager){ + return pPager->eState; +} +#endif /* SQLITE_HAS_CODEC */ + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** Move the page pPg to location pgno in the file. +** +** There must be no references to the page previously located at +** pgno (which we call pPgOld) though that page is allowed to be +** in cache. If the page previously located at pgno is not already +** in the rollback journal, it is not put there by by this routine. +** +** References to the page pPg remain valid. Updating any +** meta-data associated with pPg (i.e. data stored in the nExtra bytes +** allocated along with the page) is the responsibility of the caller. +** +** A transaction must be active when this routine is called. It used to be +** required that a statement transaction was not active, but this restriction +** has been removed (CREATE INDEX needs to move a page when a statement +** transaction is active). +** +** If the fourth argument, isCommit, is non-zero, then this page is being +** moved as part of a database reorganization just before the transaction +** is being committed. In this case, it is guaranteed that the database page +** pPg refers to will not be written to again within this transaction. +** +** This function may return SQLITE_NOMEM or an IO error code if an error +** occurs. Otherwise, it returns SQLITE_OK. +*/ +SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){ + PgHdr *pPgOld; /* The page being overwritten. */ + Pgno needSyncPgno = 0; /* Old value of pPg->pgno, if sync is required */ + int rc; /* Return code */ + Pgno origPgno; /* The original page number */ + + assert( pPg->nRef>0 ); + assert( pPager->eState==PAGER_WRITER_CACHEMOD + || pPager->eState==PAGER_WRITER_DBMOD + ); + assert( assert_pager_state(pPager) ); + + /* In order to be able to rollback, an in-memory database must journal + ** the page we are moving from. + */ + if( MEMDB ){ + rc = sqlite3PagerWrite(pPg); + if( rc ) return rc; + } + + /* If the page being moved is dirty and has not been saved by the latest + ** savepoint, then save the current contents of the page into the + ** sub-journal now. This is required to handle the following scenario: + ** + ** BEGIN; + ** + ** SAVEPOINT one; + ** + ** ROLLBACK TO one; + ** + ** If page X were not written to the sub-journal here, it would not + ** be possible to restore its contents when the "ROLLBACK TO one" + ** statement were is processed. + ** + ** subjournalPage() may need to allocate space to store pPg->pgno into + ** one or more savepoint bitvecs. This is the reason this function + ** may return SQLITE_NOMEM. + */ + if( (pPg->flags & PGHDR_DIRTY)!=0 + && SQLITE_OK!=(rc = subjournalPageIfRequired(pPg)) + ){ + return rc; + } + + PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n", + PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno)); + IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno)) + + /* If the journal needs to be sync()ed before page pPg->pgno can + ** be written to, store pPg->pgno in local variable needSyncPgno. + ** + ** If the isCommit flag is set, there is no need to remember that + ** the journal needs to be sync()ed before database page pPg->pgno + ** can be written to. The caller has already promised not to write to it. + */ + if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){ + needSyncPgno = pPg->pgno; + assert( pPager->journalMode==PAGER_JOURNALMODE_OFF || + pageInJournal(pPager, pPg) || pPg->pgno>pPager->dbOrigSize ); + assert( pPg->flags&PGHDR_DIRTY ); + } + + /* If the cache contains a page with page-number pgno, remove it + ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for + ** page pgno before the 'move' operation, it needs to be retained + ** for the page moved there. + */ + pPg->flags &= ~PGHDR_NEED_SYNC; + pPgOld = sqlite3PagerLookup(pPager, pgno); + assert( !pPgOld || pPgOld->nRef==1 ); + if( pPgOld ){ + pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC); + if( MEMDB ){ + /* Do not discard pages from an in-memory database since we might + ** need to rollback later. Just move the page out of the way. */ + sqlite3PcacheMove(pPgOld, pPager->dbSize+1); + }else{ + sqlite3PcacheDrop(pPgOld); + } + } + + origPgno = pPg->pgno; + sqlite3PcacheMove(pPg, pgno); + sqlite3PcacheMakeDirty(pPg); + + /* For an in-memory database, make sure the original page continues + ** to exist, in case the transaction needs to roll back. Use pPgOld + ** as the original page since it has already been allocated. + */ + if( MEMDB ){ + assert( pPgOld ); + sqlite3PcacheMove(pPgOld, origPgno); + sqlite3PagerUnrefNotNull(pPgOld); + } + + if( needSyncPgno ){ + /* If needSyncPgno is non-zero, then the journal file needs to be + ** sync()ed before any data is written to database file page needSyncPgno. + ** Currently, no such page exists in the page-cache and the + ** "is journaled" bitvec flag has been set. This needs to be remedied by + ** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC + ** flag. + ** + ** If the attempt to load the page into the page-cache fails, (due + ** to a malloc() or IO failure), clear the bit in the pInJournal[] + ** array. Otherwise, if the page is loaded and written again in + ** this transaction, it may be written to the database file before + ** it is synced into the journal file. This way, it may end up in + ** the journal file twice, but that is not a problem. + */ + PgHdr *pPgHdr; + rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr); + if( rc!=SQLITE_OK ){ + if( needSyncPgno<=pPager->dbOrigSize ){ + assert( pPager->pTmpSpace!=0 ); + sqlite3BitvecClear(pPager->pInJournal, needSyncPgno, pPager->pTmpSpace); + } + return rc; + } + pPgHdr->flags |= PGHDR_NEED_SYNC; + sqlite3PcacheMakeDirty(pPgHdr); + sqlite3PagerUnrefNotNull(pPgHdr); + } + + return SQLITE_OK; +} +#endif + +/* +** The page handle passed as the first argument refers to a dirty page +** with a page number other than iNew. This function changes the page's +** page number to iNew and sets the value of the PgHdr.flags field to +** the value passed as the third parameter. +*/ +SQLITE_PRIVATE void sqlite3PagerRekey(DbPage *pPg, Pgno iNew, u16 flags){ + assert( pPg->pgno!=iNew ); + pPg->flags = flags; + sqlite3PcacheMove(pPg, iNew); +} + +/* +** Return a pointer to the data for the specified page. +*/ +SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){ + assert( pPg->nRef>0 || pPg->pPager->memDb ); + return pPg->pData; +} + +/* +** Return a pointer to the Pager.nExtra bytes of "extra" space +** allocated along with the specified page. +*/ +SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){ + return pPg->pExtra; +} + +/* +** Get/set the locking-mode for this pager. Parameter eMode must be one +** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or +** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then +** the locking-mode is set to the value specified. +** +** The returned value is either PAGER_LOCKINGMODE_NORMAL or +** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated) +** locking-mode. +*/ +SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){ + assert( eMode==PAGER_LOCKINGMODE_QUERY + || eMode==PAGER_LOCKINGMODE_NORMAL + || eMode==PAGER_LOCKINGMODE_EXCLUSIVE ); + assert( PAGER_LOCKINGMODE_QUERY<0 ); + assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 ); + assert( pPager->exclusiveMode || 0==sqlite3WalHeapMemory(pPager->pWal) ); + if( eMode>=0 && !pPager->tempFile && !sqlite3WalHeapMemory(pPager->pWal) ){ + pPager->exclusiveMode = (u8)eMode; + } + return (int)pPager->exclusiveMode; +} + +/* +** Set the journal-mode for this pager. Parameter eMode must be one of: +** +** PAGER_JOURNALMODE_DELETE +** PAGER_JOURNALMODE_TRUNCATE +** PAGER_JOURNALMODE_PERSIST +** PAGER_JOURNALMODE_OFF +** PAGER_JOURNALMODE_MEMORY +** PAGER_JOURNALMODE_WAL +** +** The journalmode is set to the value specified if the change is allowed. +** The change may be disallowed for the following reasons: +** +** * An in-memory database can only have its journal_mode set to _OFF +** or _MEMORY. +** +** * Temporary databases cannot have _WAL journalmode. +** +** The returned indicate the current (possibly updated) journal-mode. +*/ +SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ + u8 eOld = pPager->journalMode; /* Prior journalmode */ + +#ifdef SQLITE_DEBUG + /* The print_pager_state() routine is intended to be used by the debugger + ** only. We invoke it once here to suppress a compiler warning. */ + print_pager_state(pPager); +#endif + + + /* The eMode parameter is always valid */ + assert( eMode==PAGER_JOURNALMODE_DELETE + || eMode==PAGER_JOURNALMODE_TRUNCATE + || eMode==PAGER_JOURNALMODE_PERSIST + || eMode==PAGER_JOURNALMODE_OFF + || eMode==PAGER_JOURNALMODE_WAL + || eMode==PAGER_JOURNALMODE_MEMORY ); + + /* This routine is only called from the OP_JournalMode opcode, and + ** the logic there will never allow a temporary file to be changed + ** to WAL mode. + */ + assert( pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL ); + + /* Do allow the journalmode of an in-memory database to be set to + ** anything other than MEMORY or OFF + */ + if( MEMDB ){ + assert( eOld==PAGER_JOURNALMODE_MEMORY || eOld==PAGER_JOURNALMODE_OFF ); + if( eMode!=PAGER_JOURNALMODE_MEMORY && eMode!=PAGER_JOURNALMODE_OFF ){ + eMode = eOld; + } + } + + if( eMode!=eOld ){ + + /* Change the journal mode. */ + assert( pPager->eState!=PAGER_ERROR ); + pPager->journalMode = (u8)eMode; + + /* When transistioning from TRUNCATE or PERSIST to any other journal + ** mode except WAL, unless the pager is in locking_mode=exclusive mode, + ** delete the journal file. + */ + assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 ); + assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 ); + assert( (PAGER_JOURNALMODE_DELETE & 5)==0 ); + assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 ); + assert( (PAGER_JOURNALMODE_OFF & 5)==0 ); + assert( (PAGER_JOURNALMODE_WAL & 5)==5 ); + + assert( isOpen(pPager->fd) || pPager->exclusiveMode ); + if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){ + + /* In this case we would like to delete the journal file. If it is + ** not possible, then that is not a problem. Deleting the journal file + ** here is an optimization only. + ** + ** Before deleting the journal file, obtain a RESERVED lock on the + ** database file. This ensures that the journal file is not deleted + ** while it is in use by some other client. + */ + sqlite3OsClose(pPager->jfd); + if( pPager->eLock>=RESERVED_LOCK ){ + sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); + }else{ + int rc = SQLITE_OK; + int state = pPager->eState; + assert( state==PAGER_OPEN || state==PAGER_READER ); + if( state==PAGER_OPEN ){ + rc = sqlite3PagerSharedLock(pPager); + } + if( pPager->eState==PAGER_READER ){ + assert( rc==SQLITE_OK ); + rc = pagerLockDb(pPager, RESERVED_LOCK); + } + if( rc==SQLITE_OK ){ + sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); + } + if( rc==SQLITE_OK && state==PAGER_READER ){ + pagerUnlockDb(pPager, SHARED_LOCK); + }else if( state==PAGER_OPEN ){ + pager_unlock(pPager); + } + assert( state==pPager->eState ); + } + }else if( eMode==PAGER_JOURNALMODE_OFF ){ + sqlite3OsClose(pPager->jfd); + } + } + + /* Return the new journal mode */ + return (int)pPager->journalMode; +} + +/* +** Return the current journal mode. +*/ +SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){ + return (int)pPager->journalMode; +} + +/* +** Return TRUE if the pager is in a state where it is OK to change the +** journalmode. Journalmode changes can only happen when the database +** is unmodified. +*/ +SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){ + assert( assert_pager_state(pPager) ); + if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0; + if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0; + return 1; +} + +/* +** Get/set the size-limit used for persistent journal files. +** +** Setting the size limit to -1 means no limit is enforced. +** An attempt to set a limit smaller than -1 is a no-op. +*/ +SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){ + if( iLimit>=-1 ){ + pPager->journalSizeLimit = iLimit; + sqlite3WalLimit(pPager->pWal, iLimit); + } + return pPager->journalSizeLimit; +} + +/* +** Return a pointer to the pPager->pBackup variable. The backup module +** in backup.c maintains the content of this variable. This module +** uses it opaquely as an argument to sqlite3BackupRestart() and +** sqlite3BackupUpdate() only. +*/ +SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){ + return &pPager->pBackup; +} + +#ifndef SQLITE_OMIT_VACUUM +/* +** Unless this is an in-memory or temporary database, clear the pager cache. +*/ +SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *pPager){ + if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager); +} +#endif + +#ifndef SQLITE_OMIT_WAL +/* +** This function is called when the user invokes "PRAGMA wal_checkpoint", +** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint() +** or wal_blocking_checkpoint() API functions. +** +** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. +*/ +SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ + int rc = SQLITE_OK; + if( pPager->pWal ){ + rc = sqlite3WalCheckpoint(pPager->pWal, eMode, + (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), + pPager->pBusyHandlerArg, + pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, + pnLog, pnCkpt + ); + } + return rc; +} + +SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){ + return sqlite3WalCallback(pPager->pWal); +} + +/* +** Return true if the underlying VFS for the given pager supports the +** primitives necessary for write-ahead logging. +*/ +SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){ + const sqlite3_io_methods *pMethods = pPager->fd->pMethods; + return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap); +} + +/* +** Attempt to take an exclusive lock on the database file. If a PENDING lock +** is obtained instead, immediately release it. +*/ +static int pagerExclusiveLock(Pager *pPager){ + int rc; /* Return code */ + + assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK ); + rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); + if( rc!=SQLITE_OK ){ + /* If the attempt to grab the exclusive lock failed, release the + ** pending lock that may have been obtained instead. */ + pagerUnlockDb(pPager, SHARED_LOCK); + } + + return rc; +} + +/* +** Call sqlite3WalOpen() to open the WAL handle. If the pager is in +** exclusive-locking mode when this function is called, take an EXCLUSIVE +** lock on the database file and use heap-memory to store the wal-index +** in. Otherwise, use the normal shared-memory. +*/ +static int pagerOpenWal(Pager *pPager){ + int rc = SQLITE_OK; + + assert( pPager->pWal==0 && pPager->tempFile==0 ); + assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK ); + + /* If the pager is already in exclusive-mode, the WAL module will use + ** heap-memory for the wal-index instead of the VFS shared-memory + ** implementation. Take the exclusive lock now, before opening the WAL + ** file, to make sure this is safe. + */ + if( pPager->exclusiveMode ){ + rc = pagerExclusiveLock(pPager); + } + + /* Open the connection to the log file. If this operation fails, + ** (e.g. due to malloc() failure), return an error code. + */ + if( rc==SQLITE_OK ){ + rc = sqlite3WalOpen(pPager->pVfs, + pPager->fd, pPager->zWal, pPager->exclusiveMode, + pPager->journalSizeLimit, &pPager->pWal + ); + } + pagerFixMaplimit(pPager); + + return rc; +} + + +/* +** The caller must be holding a SHARED lock on the database file to call +** this function. +** +** If the pager passed as the first argument is open on a real database +** file (not a temp file or an in-memory database), and the WAL file +** is not already open, make an attempt to open it now. If successful, +** return SQLITE_OK. If an error occurs or the VFS used by the pager does +** not support the xShmXXX() methods, return an error code. *pbOpen is +** not modified in either case. +** +** If the pager is open on a temp-file (or in-memory database), or if +** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK +** without doing anything. +*/ +SQLITE_PRIVATE int sqlite3PagerOpenWal( + Pager *pPager, /* Pager object */ + int *pbOpen /* OUT: Set to true if call is a no-op */ +){ + int rc = SQLITE_OK; /* Return code */ + + assert( assert_pager_state(pPager) ); + assert( pPager->eState==PAGER_OPEN || pbOpen ); + assert( pPager->eState==PAGER_READER || !pbOpen ); + assert( pbOpen==0 || *pbOpen==0 ); + assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) ); + + if( !pPager->tempFile && !pPager->pWal ){ + if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN; + + /* Close any rollback journal previously open */ + sqlite3OsClose(pPager->jfd); + + rc = pagerOpenWal(pPager); + if( rc==SQLITE_OK ){ + pPager->journalMode = PAGER_JOURNALMODE_WAL; + pPager->eState = PAGER_OPEN; + } + }else{ + *pbOpen = 1; + } + + return rc; +} + +/* +** This function is called to close the connection to the log file prior +** to switching from WAL to rollback mode. +** +** Before closing the log file, this function attempts to take an +** EXCLUSIVE lock on the database file. If this cannot be obtained, an +** error (SQLITE_BUSY) is returned and the log connection is not closed. +** If successful, the EXCLUSIVE lock is not released before returning. +*/ +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){ + int rc = SQLITE_OK; + + assert( pPager->journalMode==PAGER_JOURNALMODE_WAL ); + + /* If the log file is not already open, but does exist in the file-system, + ** it may need to be checkpointed before the connection can switch to + ** rollback mode. Open it now so this can happen. + */ + if( !pPager->pWal ){ + int logexists = 0; + rc = pagerLockDb(pPager, SHARED_LOCK); + if( rc==SQLITE_OK ){ + rc = sqlite3OsAccess( + pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists + ); + } + if( rc==SQLITE_OK && logexists ){ + rc = pagerOpenWal(pPager); + } + } + + /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on + ** the database file, the log and log-summary files will be deleted. + */ + if( rc==SQLITE_OK && pPager->pWal ){ + rc = pagerExclusiveLock(pPager); + if( rc==SQLITE_OK ){ + rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, + pPager->pageSize, (u8*)pPager->pTmpSpace); + pPager->pWal = 0; + pagerFixMaplimit(pPager); + } + } + return rc; +} + +#endif /* !SQLITE_OMIT_WAL */ + +#ifdef SQLITE_ENABLE_ZIPVFS +/* +** A read-lock must be held on the pager when this function is called. If +** the pager is in WAL mode and the WAL file currently contains one or more +** frames, return the size in bytes of the page images stored within the +** WAL frames. Otherwise, if this is not a WAL database or the WAL file +** is empty, return 0. +*/ +SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ + assert( pPager->eState>=PAGER_READER ); + return sqlite3WalFramesize(pPager->pWal); +} +#endif + + +#endif /* SQLITE_OMIT_DISKIO */ + +/************** End of pager.c ***********************************************/ +/************** Begin file wal.c *********************************************/ +/* +** 2010 February 1 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains the implementation of a write-ahead log (WAL) used in +** "journal_mode=WAL" mode. +** +** WRITE-AHEAD LOG (WAL) FILE FORMAT +** +** A WAL file consists of a header followed by zero or more "frames". +** Each frame records the revised content of a single page from the +** database file. All changes to the database are recorded by writing +** frames into the WAL. Transactions commit when a frame is written that +** contains a commit marker. A single WAL can and usually does record +** multiple transactions. Periodically, the content of the WAL is +** transferred back into the database file in an operation called a +** "checkpoint". +** +** A single WAL file can be used multiple times. In other words, the +** WAL can fill up with frames and then be checkpointed and then new +** frames can overwrite the old ones. A WAL always grows from beginning +** toward the end. Checksums and counters attached to each frame are +** used to determine which frames within the WAL are valid and which +** are leftovers from prior checkpoints. +** +** The WAL header is 32 bytes in size and consists of the following eight +** big-endian 32-bit unsigned integer values: +** +** 0: Magic number. 0x377f0682 or 0x377f0683 +** 4: File format version. Currently 3007000 +** 8: Database page size. Example: 1024 +** 12: Checkpoint sequence number +** 16: Salt-1, random integer incremented with each checkpoint +** 20: Salt-2, a different random integer changing with each ckpt +** 24: Checksum-1 (first part of checksum for first 24 bytes of header). +** 28: Checksum-2 (second part of checksum for first 24 bytes of header). +** +** Immediately following the wal-header are zero or more frames. Each +** frame consists of a 24-byte frame-header followed by a bytes +** of page data. The frame-header is six big-endian 32-bit unsigned +** integer values, as follows: +** +** 0: Page number. +** 4: For commit records, the size of the database image in pages +** after the commit. For all other records, zero. +** 8: Salt-1 (copied from the header) +** 12: Salt-2 (copied from the header) +** 16: Checksum-1. +** 20: Checksum-2. +** +** A frame is considered valid if and only if the following conditions are +** true: +** +** (1) The salt-1 and salt-2 values in the frame-header match +** salt values in the wal-header +** +** (2) The checksum values in the final 8 bytes of the frame-header +** exactly match the checksum computed consecutively on the +** WAL header and the first 8 bytes and the content of all frames +** up to and including the current frame. +** +** The checksum is computed using 32-bit big-endian integers if the +** magic number in the first 4 bytes of the WAL is 0x377f0683 and it +** is computed using little-endian if the magic number is 0x377f0682. +** The checksum values are always stored in the frame header in a +** big-endian format regardless of which byte order is used to compute +** the checksum. The checksum is computed by interpreting the input as +** an even number of unsigned 32-bit integers: x[0] through x[N]. The +** algorithm used for the checksum is as follows: +** +** for i from 0 to n-1 step 2: +** s0 += x[i] + s1; +** s1 += x[i+1] + s0; +** endfor +** +** Note that s0 and s1 are both weighted checksums using fibonacci weights +** in reverse order (the largest fibonacci weight occurs on the first element +** of the sequence being summed.) The s1 value spans all 32-bit +** terms of the sequence whereas s0 omits the final term. +** +** On a checkpoint, the WAL is first VFS.xSync-ed, then valid content of the +** WAL is transferred into the database, then the database is VFS.xSync-ed. +** The VFS.xSync operations serve as write barriers - all writes launched +** before the xSync must complete before any write that launches after the +** xSync begins. +** +** After each checkpoint, the salt-1 value is incremented and the salt-2 +** value is randomized. This prevents old and new frames in the WAL from +** being considered valid at the same time and being checkpointing together +** following a crash. +** +** READER ALGORITHM +** +** To read a page from the database (call it page number P), a reader +** first checks the WAL to see if it contains page P. If so, then the +** last valid instance of page P that is a followed by a commit frame +** or is a commit frame itself becomes the value read. If the WAL +** contains no copies of page P that are valid and which are a commit +** frame or are followed by a commit frame, then page P is read from +** the database file. +** +** To start a read transaction, the reader records the index of the last +** valid frame in the WAL. The reader uses this recorded "mxFrame" value +** for all subsequent read operations. New transactions can be appended +** to the WAL, but as long as the reader uses its original mxFrame value +** and ignores the newly appended content, it will see a consistent snapshot +** of the database from a single point in time. This technique allows +** multiple concurrent readers to view different versions of the database +** content simultaneously. +** +** The reader algorithm in the previous paragraphs works correctly, but +** because frames for page P can appear anywhere within the WAL, the +** reader has to scan the entire WAL looking for page P frames. If the +** WAL is large (multiple megabytes is typical) that scan can be slow, +** and read performance suffers. To overcome this problem, a separate +** data structure called the wal-index is maintained to expedite the +** search for frames of a particular page. +** +** WAL-INDEX FORMAT +** +** Conceptually, the wal-index is shared memory, though VFS implementations +** might choose to implement the wal-index using a mmapped file. Because +** the wal-index is shared memory, SQLite does not support journal_mode=WAL +** on a network filesystem. All users of the database must be able to +** share memory. +** +** The wal-index is transient. After a crash, the wal-index can (and should +** be) reconstructed from the original WAL file. In fact, the VFS is required +** to either truncate or zero the header of the wal-index when the last +** connection to it closes. Because the wal-index is transient, it can +** use an architecture-specific format; it does not have to be cross-platform. +** Hence, unlike the database and WAL file formats which store all values +** as big endian, the wal-index can store multi-byte values in the native +** byte order of the host computer. +** +** The purpose of the wal-index is to answer this question quickly: Given +** a page number P and a maximum frame index M, return the index of the +** last frame in the wal before frame M for page P in the WAL, or return +** NULL if there are no frames for page P in the WAL prior to M. +** +** The wal-index consists of a header region, followed by an one or +** more index blocks. +** +** The wal-index header contains the total number of frames within the WAL +** in the mxFrame field. +** +** Each index block except for the first contains information on +** HASHTABLE_NPAGE frames. The first index block contains information on +** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and +** HASHTABLE_NPAGE are selected so that together the wal-index header and +** first index block are the same size as all other index blocks in the +** wal-index. +** +** Each index block contains two sections, a page-mapping that contains the +** database page number associated with each wal frame, and a hash-table +** that allows readers to query an index block for a specific page number. +** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE +** for the first index block) 32-bit page numbers. The first entry in the +** first index-block contains the database page number corresponding to the +** first frame in the WAL file. The first entry in the second index block +** in the WAL file corresponds to the (HASHTABLE_NPAGE_ONE+1)th frame in +** the log, and so on. +** +** The last index block in a wal-index usually contains less than the full +** complement of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE) page-numbers, +** depending on the contents of the WAL file. This does not change the +** allocated size of the page-mapping array - the page-mapping array merely +** contains unused entries. +** +** Even without using the hash table, the last frame for page P +** can be found by scanning the page-mapping sections of each index block +** starting with the last index block and moving toward the first, and +** within each index block, starting at the end and moving toward the +** beginning. The first entry that equals P corresponds to the frame +** holding the content for that page. +** +** The hash table consists of HASHTABLE_NSLOT 16-bit unsigned integers. +** HASHTABLE_NSLOT = 2*HASHTABLE_NPAGE, and there is one entry in the +** hash table for each page number in the mapping section, so the hash +** table is never more than half full. The expected number of collisions +** prior to finding a match is 1. Each entry of the hash table is an +** 1-based index of an entry in the mapping section of the same +** index block. Let K be the 1-based index of the largest entry in +** the mapping section. (For index blocks other than the last, K will +** always be exactly HASHTABLE_NPAGE (4096) and for the last index block +** K will be (mxFrame%HASHTABLE_NPAGE).) Unused slots of the hash table +** contain a value of 0. +** +** To look for page P in the hash table, first compute a hash iKey on +** P as follows: +** +** iKey = (P * 383) % HASHTABLE_NSLOT +** +** Then start scanning entries of the hash table, starting with iKey +** (wrapping around to the beginning when the end of the hash table is +** reached) until an unused hash slot is found. Let the first unused slot +** be at index iUnused. (iUnused might be less than iKey if there was +** wrap-around.) Because the hash table is never more than half full, +** the search is guaranteed to eventually hit an unused entry. Let +** iMax be the value between iKey and iUnused, closest to iUnused, +** where aHash[iMax]==P. If there is no iMax entry (if there exists +** no hash slot such that aHash[i]==p) then page P is not in the +** current index block. Otherwise the iMax-th mapping entry of the +** current index block corresponds to the last entry that references +** page P. +** +** A hash search begins with the last index block and moves toward the +** first index block, looking for entries corresponding to page P. On +** average, only two or three slots in each index block need to be +** examined in order to either find the last entry for page P, or to +** establish that no such entry exists in the block. Each index block +** holds over 4000 entries. So two or three index blocks are sufficient +** to cover a typical 10 megabyte WAL file, assuming 1K pages. 8 or 10 +** comparisons (on average) suffice to either locate a frame in the +** WAL or to establish that the frame does not exist in the WAL. This +** is much faster than scanning the entire 10MB WAL. +** +** Note that entries are added in order of increasing K. Hence, one +** reader might be using some value K0 and a second reader that started +** at a later time (after additional transactions were added to the WAL +** and to the wal-index) might be using a different value K1, where K1>K0. +** Both readers can use the same hash table and mapping section to get +** the correct result. There may be entries in the hash table with +** K>K0 but to the first reader, those entries will appear to be unused +** slots in the hash table and so the first reader will get an answer as +** if no values greater than K0 had ever been inserted into the hash table +** in the first place - which is what reader one wants. Meanwhile, the +** second reader using K1 will see additional values that were inserted +** later, which is exactly what reader two wants. +** +** When a rollback occurs, the value of K is decreased. Hash table entries +** that correspond to frames greater than the new K value are removed +** from the hash table at this point. +*/ +#ifndef SQLITE_OMIT_WAL + +/* #include "wal.h" */ + +/* +** Trace output macros +*/ +#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) +SQLITE_PRIVATE int sqlite3WalTrace = 0; +# define WALTRACE(X) if(sqlite3WalTrace) sqlite3DebugPrintf X +#else +# define WALTRACE(X) +#endif + +/* +** The maximum (and only) versions of the wal and wal-index formats +** that may be interpreted by this version of SQLite. +** +** If a client begins recovering a WAL file and finds that (a) the checksum +** values in the wal-header are correct and (b) the version field is not +** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN. +** +** Similarly, if a client successfully reads a wal-index header (i.e. the +** checksum test is successful) and finds that the version field is not +** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite +** returns SQLITE_CANTOPEN. +*/ +#define WAL_MAX_VERSION 3007000 +#define WALINDEX_MAX_VERSION 3007000 + +/* +** Indices of various locking bytes. WAL_NREADER is the number +** of available reader locks and should be at least 3. +*/ +#define WAL_WRITE_LOCK 0 +#define WAL_ALL_BUT_WRITE 1 +#define WAL_CKPT_LOCK 1 +#define WAL_RECOVER_LOCK 2 +#define WAL_READ_LOCK(I) (3+(I)) +#define WAL_NREADER (SQLITE_SHM_NLOCK-3) + + +/* Object declarations */ +typedef struct WalIndexHdr WalIndexHdr; +typedef struct WalIterator WalIterator; +typedef struct WalCkptInfo WalCkptInfo; + + +/* +** The following object holds a copy of the wal-index header content. +** +** The actual header in the wal-index consists of two copies of this +** object. +** +** The szPage value can be any power of 2 between 512 and 32768, inclusive. +** Or it can be 1 to represent a 65536-byte page. The latter case was +** added in 3.7.1 when support for 64K pages was added. +*/ +struct WalIndexHdr { + u32 iVersion; /* Wal-index version */ + u32 unused; /* Unused (padding) field */ + u32 iChange; /* Counter incremented each transaction */ + u8 isInit; /* 1 when initialized */ + u8 bigEndCksum; /* True if checksums in WAL are big-endian */ + u16 szPage; /* Database page size in bytes. 1==64K */ + u32 mxFrame; /* Index of last valid frame in the WAL */ + u32 nPage; /* Size of database in pages */ + u32 aFrameCksum[2]; /* Checksum of last frame in log */ + u32 aSalt[2]; /* Two salt values copied from WAL header */ + u32 aCksum[2]; /* Checksum over all prior fields */ +}; + +/* +** A copy of the following object occurs in the wal-index immediately +** following the second copy of the WalIndexHdr. This object stores +** information used by checkpoint. +** +** nBackfill is the number of frames in the WAL that have been written +** back into the database. (We call the act of moving content from WAL to +** database "backfilling".) The nBackfill number is never greater than +** WalIndexHdr.mxFrame. nBackfill can only be increased by threads +** holding the WAL_CKPT_LOCK lock (which includes a recovery thread). +** However, a WAL_WRITE_LOCK thread can move the value of nBackfill from +** mxFrame back to zero when the WAL is reset. +** +** There is one entry in aReadMark[] for each reader lock. If a reader +** holds read-lock K, then the value in aReadMark[K] is no greater than +** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff) +** for any aReadMark[] means that entry is unused. aReadMark[0] is +** a special case; its value is never used and it exists as a place-holder +** to avoid having to offset aReadMark[] indexs by one. Readers holding +** WAL_READ_LOCK(0) always ignore the entire WAL and read all content +** directly from the database. +** +** The value of aReadMark[K] may only be changed by a thread that +** is holding an exclusive lock on WAL_READ_LOCK(K). Thus, the value of +** aReadMark[K] cannot changed while there is a reader is using that mark +** since the reader will be holding a shared lock on WAL_READ_LOCK(K). +** +** The checkpointer may only transfer frames from WAL to database where +** the frame numbers are less than or equal to every aReadMark[] that is +** in use (that is, every aReadMark[j] for which there is a corresponding +** WAL_READ_LOCK(j)). New readers (usually) pick the aReadMark[] with the +** largest value and will increase an unused aReadMark[] to mxFrame if there +** is not already an aReadMark[] equal to mxFrame. The exception to the +** previous sentence is when nBackfill equals mxFrame (meaning that everything +** in the WAL has been backfilled into the database) then new readers +** will choose aReadMark[0] which has value 0 and hence such reader will +** get all their all content directly from the database file and ignore +** the WAL. +** +** Writers normally append new frames to the end of the WAL. However, +** if nBackfill equals mxFrame (meaning that all WAL content has been +** written back into the database) and if no readers are using the WAL +** (in other words, if there are no WAL_READ_LOCK(i) where i>0) then +** the writer will first "reset" the WAL back to the beginning and start +** writing new content beginning at frame 1. +** +** We assume that 32-bit loads are atomic and so no locks are needed in +** order to read from any aReadMark[] entries. +*/ +struct WalCkptInfo { + u32 nBackfill; /* Number of WAL frames backfilled into DB */ + u32 aReadMark[WAL_NREADER]; /* Reader marks */ +}; +#define READMARK_NOT_USED 0xffffffff + + +/* A block of WALINDEX_LOCK_RESERVED bytes beginning at +** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems +** only support mandatory file-locks, we do not read or write data +** from the region of the file on which locks are applied. +*/ +#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2 + sizeof(WalCkptInfo)) +#define WALINDEX_LOCK_RESERVED 16 +#define WALINDEX_HDR_SIZE (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED) + +/* Size of header before each frame in wal */ +#define WAL_FRAME_HDRSIZE 24 + +/* Size of write ahead log header, including checksum. */ +/* #define WAL_HDRSIZE 24 */ +#define WAL_HDRSIZE 32 + +/* WAL magic value. Either this value, or the same value with the least +** significant bit also set (WAL_MAGIC | 0x00000001) is stored in 32-bit +** big-endian format in the first 4 bytes of a WAL file. +** +** If the LSB is set, then the checksums for each frame within the WAL +** file are calculated by treating all data as an array of 32-bit +** big-endian words. Otherwise, they are calculated by interpreting +** all data as 32-bit little-endian words. +*/ +#define WAL_MAGIC 0x377f0682 + +/* +** Return the offset of frame iFrame in the write-ahead log file, +** assuming a database page size of szPage bytes. The offset returned +** is to the start of the write-ahead log frame-header. +*/ +#define walFrameOffset(iFrame, szPage) ( \ + WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE) \ +) + +/* +** An open write-ahead log file is represented by an instance of the +** following object. +*/ +struct Wal { + sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */ + sqlite3_file *pDbFd; /* File handle for the database file */ + sqlite3_file *pWalFd; /* File handle for WAL file */ + u32 iCallback; /* Value to pass to log callback (or 0) */ + i64 mxWalSize; /* Truncate WAL to this size upon reset */ + int nWiData; /* Size of array apWiData */ + int szFirstBlock; /* Size of first block written to WAL file */ + volatile u32 **apWiData; /* Pointer to wal-index content in memory */ + u32 szPage; /* Database page size */ + i16 readLock; /* Which read lock is being held. -1 for none */ + u8 syncFlags; /* Flags to use to sync header writes */ + u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */ + u8 writeLock; /* True if in a write transaction */ + u8 ckptLock; /* True if holding a checkpoint lock */ + u8 readOnly; /* WAL_RDWR, WAL_RDONLY, or WAL_SHM_RDONLY */ + u8 truncateOnCommit; /* True to truncate WAL file on commit */ + u8 syncHeader; /* Fsync the WAL header if true */ + u8 padToSectorBoundary; /* Pad transactions out to the next sector */ + WalIndexHdr hdr; /* Wal-index header for current transaction */ + const char *zWalName; /* Name of WAL file */ + u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ +#ifdef SQLITE_DEBUG + u8 lockError; /* True if a locking error has occurred */ +#endif +}; + +/* +** Candidate values for Wal.exclusiveMode. +*/ +#define WAL_NORMAL_MODE 0 +#define WAL_EXCLUSIVE_MODE 1 +#define WAL_HEAPMEMORY_MODE 2 + +/* +** Possible values for WAL.readOnly +*/ +#define WAL_RDWR 0 /* Normal read/write connection */ +#define WAL_RDONLY 1 /* The WAL file is readonly */ +#define WAL_SHM_RDONLY 2 /* The SHM file is readonly */ + +/* +** Each page of the wal-index mapping contains a hash-table made up of +** an array of HASHTABLE_NSLOT elements of the following type. +*/ +typedef u16 ht_slot; + +/* +** This structure is used to implement an iterator that loops through +** all frames in the WAL in database page order. Where two or more frames +** correspond to the same database page, the iterator visits only the +** frame most recently written to the WAL (in other words, the frame with +** the largest index). +** +** The internals of this structure are only accessed by: +** +** walIteratorInit() - Create a new iterator, +** walIteratorNext() - Step an iterator, +** walIteratorFree() - Free an iterator. +** +** This functionality is used by the checkpoint code (see walCheckpoint()). +*/ +struct WalIterator { + int iPrior; /* Last result returned from the iterator */ + int nSegment; /* Number of entries in aSegment[] */ + struct WalSegment { + int iNext; /* Next slot in aIndex[] not yet returned */ + ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */ + u32 *aPgno; /* Array of page numbers. */ + int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */ + int iZero; /* Frame number associated with aPgno[0] */ + } aSegment[1]; /* One for every 32KB page in the wal-index */ +}; + +/* +** Define the parameters of the hash tables in the wal-index file. There +** is a hash-table following every HASHTABLE_NPAGE page numbers in the +** wal-index. +** +** Changing any of these constants will alter the wal-index format and +** create incompatibilities. +*/ +#define HASHTABLE_NPAGE 4096 /* Must be power of 2 */ +#define HASHTABLE_HASH_1 383 /* Should be prime */ +#define HASHTABLE_NSLOT (HASHTABLE_NPAGE*2) /* Must be a power of 2 */ + +/* +** The block of page numbers associated with the first hash-table in a +** wal-index is smaller than usual. This is so that there is a complete +** hash-table on each aligned 32KB page of the wal-index. +*/ +#define HASHTABLE_NPAGE_ONE (HASHTABLE_NPAGE - (WALINDEX_HDR_SIZE/sizeof(u32))) + +/* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */ +#define WALINDEX_PGSZ ( \ + sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \ +) + +/* +** Obtain a pointer to the iPage'th page of the wal-index. The wal-index +** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are +** numbered from zero. +** +** If this call is successful, *ppPage is set to point to the wal-index +** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs, +** then an SQLite error code is returned and *ppPage is set to 0. +*/ +static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ + int rc = SQLITE_OK; + + /* Enlarge the pWal->apWiData[] array if required */ + if( pWal->nWiData<=iPage ){ + int nByte = sizeof(u32*)*(iPage+1); + volatile u32 **apNew; + apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte); + if( !apNew ){ + *ppPage = 0; + return SQLITE_NOMEM; + } + memset((void*)&apNew[pWal->nWiData], 0, + sizeof(u32*)*(iPage+1-pWal->nWiData)); + pWal->apWiData = apNew; + pWal->nWiData = iPage+1; + } + + /* Request a pointer to the required page from the VFS */ + if( pWal->apWiData[iPage]==0 ){ + if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ + pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ); + if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM; + }else{ + rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, + pWal->writeLock, (void volatile **)&pWal->apWiData[iPage] + ); + if( rc==SQLITE_READONLY ){ + pWal->readOnly |= WAL_SHM_RDONLY; + rc = SQLITE_OK; + } + } + } + + *ppPage = pWal->apWiData[iPage]; + assert( iPage==0 || *ppPage || rc!=SQLITE_OK ); + return rc; +} + +/* +** Return a pointer to the WalCkptInfo structure in the wal-index. +*/ +static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ + assert( pWal->nWiData>0 && pWal->apWiData[0] ); + return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]); +} + +/* +** Return a pointer to the WalIndexHdr structure in the wal-index. +*/ +static volatile WalIndexHdr *walIndexHdr(Wal *pWal){ + assert( pWal->nWiData>0 && pWal->apWiData[0] ); + return (volatile WalIndexHdr*)pWal->apWiData[0]; +} + +/* +** The argument to this macro must be of type u32. On a little-endian +** architecture, it returns the u32 value that results from interpreting +** the 4 bytes as a big-endian value. On a big-endian architecture, it +** returns the value that would be produced by interpreting the 4 bytes +** of the input value as a little-endian integer. +*/ +#define BYTESWAP32(x) ( \ + (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8) \ + + (((x)&0x00FF0000)>>8) + (((x)&0xFF000000)>>24) \ +) + +/* +** Generate or extend an 8 byte checksum based on the data in +** array aByte[] and the initial values of aIn[0] and aIn[1] (or +** initial values of 0 and 0 if aIn==NULL). +** +** The checksum is written back into aOut[] before returning. +** +** nByte must be a positive multiple of 8. +*/ +static void walChecksumBytes( + int nativeCksum, /* True for native byte-order, false for non-native */ + u8 *a, /* Content to be checksummed */ + int nByte, /* Bytes of content in a[]. Must be a multiple of 8. */ + const u32 *aIn, /* Initial checksum value input */ + u32 *aOut /* OUT: Final checksum value output */ +){ + u32 s1, s2; + u32 *aData = (u32 *)a; + u32 *aEnd = (u32 *)&a[nByte]; + + if( aIn ){ + s1 = aIn[0]; + s2 = aIn[1]; + }else{ + s1 = s2 = 0; + } + + assert( nByte>=8 ); + assert( (nByte&0x00000007)==0 ); + + if( nativeCksum ){ + do { + s1 += *aData++ + s2; + s2 += *aData++ + s1; + }while( aDataexclusiveMode!=WAL_HEAPMEMORY_MODE ){ + sqlite3OsShmBarrier(pWal->pDbFd); + } +} + +/* +** Write the header information in pWal->hdr into the wal-index. +** +** The checksum on pWal->hdr is updated before it is written. +*/ +static void walIndexWriteHdr(Wal *pWal){ + volatile WalIndexHdr *aHdr = walIndexHdr(pWal); + const int nCksum = offsetof(WalIndexHdr, aCksum); + + assert( pWal->writeLock ); + pWal->hdr.isInit = 1; + pWal->hdr.iVersion = WALINDEX_MAX_VERSION; + walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum); + memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr)); + walShmBarrier(pWal); + memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr)); +} + +/* +** This function encodes a single frame header and writes it to a buffer +** supplied by the caller. A frame-header is made up of a series of +** 4-byte big-endian integers, as follows: +** +** 0: Page number. +** 4: For commit records, the size of the database image in pages +** after the commit. For all other records, zero. +** 8: Salt-1 (copied from the wal-header) +** 12: Salt-2 (copied from the wal-header) +** 16: Checksum-1. +** 20: Checksum-2. +*/ +static void walEncodeFrame( + Wal *pWal, /* The write-ahead log */ + u32 iPage, /* Database page number for frame */ + u32 nTruncate, /* New db size (or 0 for non-commit frames) */ + u8 *aData, /* Pointer to page data */ + u8 *aFrame /* OUT: Write encoded frame here */ +){ + int nativeCksum; /* True for native byte-order checksums */ + u32 *aCksum = pWal->hdr.aFrameCksum; + assert( WAL_FRAME_HDRSIZE==24 ); + sqlite3Put4byte(&aFrame[0], iPage); + sqlite3Put4byte(&aFrame[4], nTruncate); + memcpy(&aFrame[8], pWal->hdr.aSalt, 8); + + nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN); + walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum); + walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum); + + sqlite3Put4byte(&aFrame[16], aCksum[0]); + sqlite3Put4byte(&aFrame[20], aCksum[1]); +} + +/* +** Check to see if the frame with header in aFrame[] and content +** in aData[] is valid. If it is a valid frame, fill *piPage and +** *pnTruncate and return true. Return if the frame is not valid. +*/ +static int walDecodeFrame( + Wal *pWal, /* The write-ahead log */ + u32 *piPage, /* OUT: Database page number for frame */ + u32 *pnTruncate, /* OUT: New db size (or 0 if not commit) */ + u8 *aData, /* Pointer to page data (for checksum) */ + u8 *aFrame /* Frame data */ +){ + int nativeCksum; /* True for native byte-order checksums */ + u32 *aCksum = pWal->hdr.aFrameCksum; + u32 pgno; /* Page number of the frame */ + assert( WAL_FRAME_HDRSIZE==24 ); + + /* A frame is only valid if the salt values in the frame-header + ** match the salt values in the wal-header. + */ + if( memcmp(&pWal->hdr.aSalt, &aFrame[8], 8)!=0 ){ + return 0; + } + + /* A frame is only valid if the page number is creater than zero. + */ + pgno = sqlite3Get4byte(&aFrame[0]); + if( pgno==0 ){ + return 0; + } + + /* A frame is only valid if a checksum of the WAL header, + ** all prior frams, the first 16 bytes of this frame-header, + ** and the frame-data matches the checksum in the last 8 + ** bytes of this frame-header. + */ + nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN); + walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum); + walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum); + if( aCksum[0]!=sqlite3Get4byte(&aFrame[16]) + || aCksum[1]!=sqlite3Get4byte(&aFrame[20]) + ){ + /* Checksum failed. */ + return 0; + } + + /* If we reach this point, the frame is valid. Return the page number + ** and the new database size. + */ + *piPage = pgno; + *pnTruncate = sqlite3Get4byte(&aFrame[4]); + return 1; +} + + +#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) +/* +** Names of locks. This routine is used to provide debugging output and is not +** a part of an ordinary build. +*/ +static const char *walLockName(int lockIdx){ + if( lockIdx==WAL_WRITE_LOCK ){ + return "WRITE-LOCK"; + }else if( lockIdx==WAL_CKPT_LOCK ){ + return "CKPT-LOCK"; + }else if( lockIdx==WAL_RECOVER_LOCK ){ + return "RECOVER-LOCK"; + }else{ + static char zName[15]; + sqlite3_snprintf(sizeof(zName), zName, "READ-LOCK[%d]", + lockIdx-WAL_READ_LOCK(0)); + return zName; + } +} +#endif /*defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */ + + +/* +** Set or release locks on the WAL. Locks are either shared or exclusive. +** A lock cannot be moved directly between shared and exclusive - it must go +** through the unlocked state first. +** +** In locking_mode=EXCLUSIVE, all of these routines become no-ops. +*/ +static int walLockShared(Wal *pWal, int lockIdx){ + int rc; + if( pWal->exclusiveMode ) return SQLITE_OK; + rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, + SQLITE_SHM_LOCK | SQLITE_SHM_SHARED); + WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal, + walLockName(lockIdx), rc ? "failed" : "ok")); + VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); ) + return rc; +} +static void walUnlockShared(Wal *pWal, int lockIdx){ + if( pWal->exclusiveMode ) return; + (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, + SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); + WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); +} +static int walLockExclusive(Wal *pWal, int lockIdx, int n, int fBlock){ + int rc; + if( pWal->exclusiveMode ) return SQLITE_OK; + if( fBlock ) sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_WAL_BLOCK, 0); + rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, + SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE); + WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, + walLockName(lockIdx), n, rc ? "failed" : "ok")); + VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); ) + return rc; +} +static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){ + if( pWal->exclusiveMode ) return; + (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, + SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE); + WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal, + walLockName(lockIdx), n)); +} + +/* +** Compute a hash on a page number. The resulting hash value must land +** between 0 and (HASHTABLE_NSLOT-1). The walHashNext() function advances +** the hash to the next value in the event of a collision. +*/ +static int walHash(u32 iPage){ + assert( iPage>0 ); + assert( (HASHTABLE_NSLOT & (HASHTABLE_NSLOT-1))==0 ); + return (iPage*HASHTABLE_HASH_1) & (HASHTABLE_NSLOT-1); +} +static int walNextHash(int iPriorHash){ + return (iPriorHash+1)&(HASHTABLE_NSLOT-1); +} + +/* +** Return pointers to the hash table and page number array stored on +** page iHash of the wal-index. The wal-index is broken into 32KB pages +** numbered starting from 0. +** +** Set output variable *paHash to point to the start of the hash table +** in the wal-index file. Set *piZero to one less than the frame +** number of the first frame indexed by this hash table. If a +** slot in the hash table is set to N, it refers to frame number +** (*piZero+N) in the log. +** +** Finally, set *paPgno so that *paPgno[1] is the page number of the +** first frame indexed by the hash table, frame (*piZero+1). +*/ +static int walHashGet( + Wal *pWal, /* WAL handle */ + int iHash, /* Find the iHash'th table */ + volatile ht_slot **paHash, /* OUT: Pointer to hash index */ + volatile u32 **paPgno, /* OUT: Pointer to page number array */ + u32 *piZero /* OUT: Frame associated with *paPgno[0] */ +){ + int rc; /* Return code */ + volatile u32 *aPgno; + + rc = walIndexPage(pWal, iHash, &aPgno); + assert( rc==SQLITE_OK || iHash>0 ); + + if( rc==SQLITE_OK ){ + u32 iZero; + volatile ht_slot *aHash; + + aHash = (volatile ht_slot *)&aPgno[HASHTABLE_NPAGE]; + if( iHash==0 ){ + aPgno = &aPgno[WALINDEX_HDR_SIZE/sizeof(u32)]; + iZero = 0; + }else{ + iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE; + } + + *paPgno = &aPgno[-1]; + *paHash = aHash; + *piZero = iZero; + } + return rc; +} + +/* +** Return the number of the wal-index page that contains the hash-table +** and page-number array that contain entries corresponding to WAL frame +** iFrame. The wal-index is broken up into 32KB pages. Wal-index pages +** are numbered starting from 0. +*/ +static int walFramePage(u32 iFrame){ + int iHash = (iFrame+HASHTABLE_NPAGE-HASHTABLE_NPAGE_ONE-1) / HASHTABLE_NPAGE; + assert( (iHash==0 || iFrame>HASHTABLE_NPAGE_ONE) + && (iHash>=1 || iFrame<=HASHTABLE_NPAGE_ONE) + && (iHash<=1 || iFrame>(HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE)) + && (iHash>=2 || iFrame<=HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE) + && (iHash<=2 || iFrame>(HASHTABLE_NPAGE_ONE+2*HASHTABLE_NPAGE)) + ); + return iHash; +} + +/* +** Return the page number associated with frame iFrame in this WAL. +*/ +static u32 walFramePgno(Wal *pWal, u32 iFrame){ + int iHash = walFramePage(iFrame); + if( iHash==0 ){ + return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1]; + } + return pWal->apWiData[iHash][(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE]; +} + +/* +** Remove entries from the hash table that point to WAL slots greater +** than pWal->hdr.mxFrame. +** +** This function is called whenever pWal->hdr.mxFrame is decreased due +** to a rollback or savepoint. +** +** At most only the hash table containing pWal->hdr.mxFrame needs to be +** updated. Any later hash tables will be automatically cleared when +** pWal->hdr.mxFrame advances to the point where those hash tables are +** actually needed. +*/ +static void walCleanupHash(Wal *pWal){ + volatile ht_slot *aHash = 0; /* Pointer to hash table to clear */ + volatile u32 *aPgno = 0; /* Page number array for hash table */ + u32 iZero = 0; /* frame == (aHash[x]+iZero) */ + int iLimit = 0; /* Zero values greater than this */ + int nByte; /* Number of bytes to zero in aPgno[] */ + int i; /* Used to iterate through aHash[] */ + + assert( pWal->writeLock ); + testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 ); + testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE ); + testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE+1 ); + + if( pWal->hdr.mxFrame==0 ) return; + + /* Obtain pointers to the hash-table and page-number array containing + ** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed + ** that the page said hash-table and array reside on is already mapped. + */ + assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) ); + assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] ); + walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &aHash, &aPgno, &iZero); + + /* Zero all hash-table entries that correspond to frame numbers greater + ** than pWal->hdr.mxFrame. + */ + iLimit = pWal->hdr.mxFrame - iZero; + assert( iLimit>0 ); + for(i=0; iiLimit ){ + aHash[i] = 0; + } + } + + /* Zero the entries in the aPgno array that correspond to frames with + ** frame numbers greater than pWal->hdr.mxFrame. + */ + nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]); + memset((void *)&aPgno[iLimit+1], 0, nByte); + +#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT + /* Verify that the every entry in the mapping region is still reachable + ** via the hash table even after the cleanup. + */ + if( iLimit ){ + int j; /* Loop counter */ + int iKey; /* Hash key */ + for(j=1; j<=iLimit; j++){ + for(iKey=walHash(aPgno[j]); aHash[iKey]; iKey=walNextHash(iKey)){ + if( aHash[iKey]==j ) break; + } + assert( aHash[iKey]==j ); + } + } +#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */ +} + + +/* +** Set an entry in the wal-index that will map database page number +** pPage into WAL frame iFrame. +*/ +static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){ + int rc; /* Return code */ + u32 iZero = 0; /* One less than frame number of aPgno[1] */ + volatile u32 *aPgno = 0; /* Page number array */ + volatile ht_slot *aHash = 0; /* Hash table */ + + rc = walHashGet(pWal, walFramePage(iFrame), &aHash, &aPgno, &iZero); + + /* Assuming the wal-index file was successfully mapped, populate the + ** page number array and hash table entry. + */ + if( rc==SQLITE_OK ){ + int iKey; /* Hash table key */ + int idx; /* Value to write to hash-table slot */ + int nCollide; /* Number of hash collisions */ + + idx = iFrame - iZero; + assert( idx <= HASHTABLE_NSLOT/2 + 1 ); + + /* If this is the first entry to be added to this hash-table, zero the + ** entire hash table and aPgno[] array before proceeding. + */ + if( idx==1 ){ + int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]); + memset((void*)&aPgno[1], 0, nByte); + } + + /* If the entry in aPgno[] is already set, then the previous writer + ** must have exited unexpectedly in the middle of a transaction (after + ** writing one or more dirty pages to the WAL to free up memory). + ** Remove the remnants of that writers uncommitted transaction from + ** the hash-table before writing any new entries. + */ + if( aPgno[idx] ){ + walCleanupHash(pWal); + assert( !aPgno[idx] ); + } + + /* Write the aPgno[] array entry and the hash-table slot. */ + nCollide = idx; + for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){ + if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT; + } + aPgno[idx] = iPage; + aHash[iKey] = (ht_slot)idx; + +#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT + /* Verify that the number of entries in the hash table exactly equals + ** the number of entries in the mapping region. + */ + { + int i; /* Loop counter */ + int nEntry = 0; /* Number of entries in the hash table */ + for(i=0; ickptLock==1 || pWal->ckptLock==0 ); + assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 ); + assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE ); + assert( pWal->writeLock ); + iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock; + nLock = SQLITE_SHM_NLOCK - iLock; + rc = walLockExclusive(pWal, iLock, nLock, 0); + if( rc ){ + return rc; + } + WALTRACE(("WAL%p: recovery begin...\n", pWal)); + + memset(&pWal->hdr, 0, sizeof(WalIndexHdr)); + + rc = sqlite3OsFileSize(pWal->pWalFd, &nSize); + if( rc!=SQLITE_OK ){ + goto recovery_error; + } + + if( nSize>WAL_HDRSIZE ){ + u8 aBuf[WAL_HDRSIZE]; /* Buffer to load WAL header into */ + u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */ + int szFrame; /* Number of bytes in buffer aFrame[] */ + u8 *aData; /* Pointer to data part of aFrame buffer */ + int iFrame; /* Index of last frame read */ + i64 iOffset; /* Next offset to read from log file */ + int szPage; /* Page size according to the log */ + u32 magic; /* Magic value read from WAL header */ + u32 version; /* Magic value read from WAL header */ + int isValid; /* True if this frame is valid */ + + /* Read in the WAL header. */ + rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0); + if( rc!=SQLITE_OK ){ + goto recovery_error; + } + + /* If the database page size is not a power of two, or is greater than + ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid + ** data. Similarly, if the 'magic' value is invalid, ignore the whole + ** WAL file. + */ + magic = sqlite3Get4byte(&aBuf[0]); + szPage = sqlite3Get4byte(&aBuf[8]); + if( (magic&0xFFFFFFFE)!=WAL_MAGIC + || szPage&(szPage-1) + || szPage>SQLITE_MAX_PAGE_SIZE + || szPage<512 + ){ + goto finished; + } + pWal->hdr.bigEndCksum = (u8)(magic&0x00000001); + pWal->szPage = szPage; + pWal->nCkpt = sqlite3Get4byte(&aBuf[12]); + memcpy(&pWal->hdr.aSalt, &aBuf[16], 8); + + /* Verify that the WAL header checksum is correct */ + walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, + aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum + ); + if( pWal->hdr.aFrameCksum[0]!=sqlite3Get4byte(&aBuf[24]) + || pWal->hdr.aFrameCksum[1]!=sqlite3Get4byte(&aBuf[28]) + ){ + goto finished; + } + + /* Verify that the version number on the WAL format is one that + ** are able to understand */ + version = sqlite3Get4byte(&aBuf[4]); + if( version!=WAL_MAX_VERSION ){ + rc = SQLITE_CANTOPEN_BKPT; + goto finished; + } + + /* Malloc a buffer to read frames into. */ + szFrame = szPage + WAL_FRAME_HDRSIZE; + aFrame = (u8 *)sqlite3_malloc64(szFrame); + if( !aFrame ){ + rc = SQLITE_NOMEM; + goto recovery_error; + } + aData = &aFrame[WAL_FRAME_HDRSIZE]; + + /* Read all frames from the log file. */ + iFrame = 0; + for(iOffset=WAL_HDRSIZE; (iOffset+szFrame)<=nSize; iOffset+=szFrame){ + u32 pgno; /* Database page number for frame */ + u32 nTruncate; /* dbsize field from frame header */ + + /* Read and decode the next log frame. */ + iFrame++; + rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset); + if( rc!=SQLITE_OK ) break; + isValid = walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame); + if( !isValid ) break; + rc = walIndexAppend(pWal, iFrame, pgno); + if( rc!=SQLITE_OK ) break; + + /* If nTruncate is non-zero, this is a commit record. */ + if( nTruncate ){ + pWal->hdr.mxFrame = iFrame; + pWal->hdr.nPage = nTruncate; + pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16)); + testcase( szPage<=32768 ); + testcase( szPage>=65536 ); + aFrameCksum[0] = pWal->hdr.aFrameCksum[0]; + aFrameCksum[1] = pWal->hdr.aFrameCksum[1]; + } + } + + sqlite3_free(aFrame); + } + +finished: + if( rc==SQLITE_OK ){ + volatile WalCkptInfo *pInfo; + int i; + pWal->hdr.aFrameCksum[0] = aFrameCksum[0]; + pWal->hdr.aFrameCksum[1] = aFrameCksum[1]; + walIndexWriteHdr(pWal); + + /* Reset the checkpoint-header. This is safe because this thread is + ** currently holding locks that exclude all other readers, writers and + ** checkpointers. + */ + pInfo = walCkptInfo(pWal); + pInfo->nBackfill = 0; + pInfo->aReadMark[0] = 0; + for(i=1; iaReadMark[i] = READMARK_NOT_USED; + if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame; + + /* If more than one frame was recovered from the log file, report an + ** event via sqlite3_log(). This is to help with identifying performance + ** problems caused by applications routinely shutting down without + ** checkpointing the log file. + */ + if( pWal->hdr.nPage ){ + sqlite3_log(SQLITE_NOTICE_RECOVER_WAL, + "recovered %d frames from WAL file %s", + pWal->hdr.mxFrame, pWal->zWalName + ); + } + } + +recovery_error: + WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok")); + walUnlockExclusive(pWal, iLock, nLock); + return rc; +} + +/* +** Close an open wal-index. +*/ +static void walIndexClose(Wal *pWal, int isDelete){ + if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ + int i; + for(i=0; inWiData; i++){ + sqlite3_free((void *)pWal->apWiData[i]); + pWal->apWiData[i] = 0; + } + }else{ + sqlite3OsShmUnmap(pWal->pDbFd, isDelete); + } +} + +/* +** Open a connection to the WAL file zWalName. The database file must +** already be opened on connection pDbFd. The buffer that zWalName points +** to must remain valid for the lifetime of the returned Wal* handle. +** +** A SHARED lock should be held on the database file when this function +** is called. The purpose of this SHARED lock is to prevent any other +** client from unlinking the WAL or wal-index file. If another process +** were to do this just after this client opened one of these files, the +** system would be badly broken. +** +** If the log file is successfully opened, SQLITE_OK is returned and +** *ppWal is set to point to a new WAL handle. If an error occurs, +** an SQLite error code is returned and *ppWal is left unmodified. +*/ +SQLITE_PRIVATE int sqlite3WalOpen( + sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */ + sqlite3_file *pDbFd, /* The open database file */ + const char *zWalName, /* Name of the WAL file */ + int bNoShm, /* True to run in heap-memory mode */ + i64 mxWalSize, /* Truncate WAL to this size on reset */ + Wal **ppWal /* OUT: Allocated Wal handle */ +){ + int rc; /* Return Code */ + Wal *pRet; /* Object to allocate and return */ + int flags; /* Flags passed to OsOpen() */ + + assert( zWalName && zWalName[0] ); + assert( pDbFd ); + + /* In the amalgamation, the os_unix.c and os_win.c source files come before + ** this source file. Verify that the #defines of the locking byte offsets + ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value. + */ +#ifdef WIN_SHM_BASE + assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET ); +#endif +#ifdef UNIX_SHM_BASE + assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET ); +#endif + + + /* Allocate an instance of struct Wal to return. */ + *ppWal = 0; + pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile); + if( !pRet ){ + return SQLITE_NOMEM; + } + + pRet->pVfs = pVfs; + pRet->pWalFd = (sqlite3_file *)&pRet[1]; + pRet->pDbFd = pDbFd; + pRet->readLock = -1; + pRet->mxWalSize = mxWalSize; + pRet->zWalName = zWalName; + pRet->syncHeader = 1; + pRet->padToSectorBoundary = 1; + pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE); + + /* Open file handle on the write-ahead log file. */ + flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL); + rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags); + if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){ + pRet->readOnly = WAL_RDONLY; + } + + if( rc!=SQLITE_OK ){ + walIndexClose(pRet, 0); + sqlite3OsClose(pRet->pWalFd); + sqlite3_free(pRet); + }else{ + int iDC = sqlite3OsDeviceCharacteristics(pDbFd); + if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; } + if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){ + pRet->padToSectorBoundary = 0; + } + *ppWal = pRet; + WALTRACE(("WAL%d: opened\n", pRet)); + } + return rc; +} + +/* +** Change the size to which the WAL file is trucated on each reset. +*/ +SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){ + if( pWal ) pWal->mxWalSize = iLimit; +} + +/* +** Find the smallest page number out of all pages held in the WAL that +** has not been returned by any prior invocation of this method on the +** same WalIterator object. Write into *piFrame the frame index where +** that page was last written into the WAL. Write into *piPage the page +** number. +** +** Return 0 on success. If there are no pages in the WAL with a page +** number larger than *piPage, then return 1. +*/ +static int walIteratorNext( + WalIterator *p, /* Iterator */ + u32 *piPage, /* OUT: The page number of the next page */ + u32 *piFrame /* OUT: Wal frame index of next page */ +){ + u32 iMin; /* Result pgno must be greater than iMin */ + u32 iRet = 0xFFFFFFFF; /* 0xffffffff is never a valid page number */ + int i; /* For looping through segments */ + + iMin = p->iPrior; + assert( iMin<0xffffffff ); + for(i=p->nSegment-1; i>=0; i--){ + struct WalSegment *pSegment = &p->aSegment[i]; + while( pSegment->iNextnEntry ){ + u32 iPg = pSegment->aPgno[pSegment->aIndex[pSegment->iNext]]; + if( iPg>iMin ){ + if( iPgiZero + pSegment->aIndex[pSegment->iNext]; + } + break; + } + pSegment->iNext++; + } + } + + *piPage = p->iPrior = iRet; + return (iRet==0xFFFFFFFF); +} + +/* +** This function merges two sorted lists into a single sorted list. +** +** aLeft[] and aRight[] are arrays of indices. The sort key is +** aContent[aLeft[]] and aContent[aRight[]]. Upon entry, the following +** is guaranteed for all J0 && nRight>0 ); + while( iRight=nRight || aContent[aLeft[iLeft]]=nLeft || aContent[aLeft[iLeft]]>dbpage ); + assert( iRight>=nRight || aContent[aRight[iRight]]>dbpage ); + } + + *paRight = aLeft; + *pnRight = iOut; + memcpy(aLeft, aTmp, sizeof(aTmp[0])*iOut); +} + +/* +** Sort the elements in list aList using aContent[] as the sort key. +** Remove elements with duplicate keys, preferring to keep the +** larger aList[] values. +** +** The aList[] entries are indices into aContent[]. The values in +** aList[] are to be sorted so that for all J0 ); + assert( HASHTABLE_NPAGE==(1<<(ArraySize(aSub)-1)) ); + + for(iList=0; iListaList && p->nList<=(1<aList==&aList[iList&~((2<aList, p->nList, &aMerge, &nMerge, aBuffer); + } + aSub[iSub].aList = aMerge; + aSub[iSub].nList = nMerge; + } + + for(iSub++; iSubnList<=(1<aList==&aList[nList&~((2<aList, p->nList, &aMerge, &nMerge, aBuffer); + } + } + assert( aMerge==aList ); + *pnList = nMerge; + +#ifdef SQLITE_DEBUG + { + int i; + for(i=1; i<*pnList; i++){ + assert( aContent[aList[i]] > aContent[aList[i-1]] ); + } + } +#endif +} + +/* +** Free an iterator allocated by walIteratorInit(). +*/ +static void walIteratorFree(WalIterator *p){ + sqlite3_free(p); +} + +/* +** Construct a WalInterator object that can be used to loop over all +** pages in the WAL in ascending order. The caller must hold the checkpoint +** lock. +** +** On success, make *pp point to the newly allocated WalInterator object +** return SQLITE_OK. Otherwise, return an error code. If this routine +** returns an error, the value of *pp is undefined. +** +** The calling routine should invoke walIteratorFree() to destroy the +** WalIterator object when it has finished with it. +*/ +static int walIteratorInit(Wal *pWal, WalIterator **pp){ + WalIterator *p; /* Return value */ + int nSegment; /* Number of segments to merge */ + u32 iLast; /* Last frame in log */ + int nByte; /* Number of bytes to allocate */ + int i; /* Iterator variable */ + ht_slot *aTmp; /* Temp space used by merge-sort */ + int rc = SQLITE_OK; /* Return Code */ + + /* This routine only runs while holding the checkpoint lock. And + ** it only runs if there is actually content in the log (mxFrame>0). + */ + assert( pWal->ckptLock && pWal->hdr.mxFrame>0 ); + iLast = pWal->hdr.mxFrame; + + /* Allocate space for the WalIterator object. */ + nSegment = walFramePage(iLast) + 1; + nByte = sizeof(WalIterator) + + (nSegment-1)*sizeof(struct WalSegment) + + iLast*sizeof(ht_slot); + p = (WalIterator *)sqlite3_malloc64(nByte); + if( !p ){ + return SQLITE_NOMEM; + } + memset(p, 0, nByte); + p->nSegment = nSegment; + + /* Allocate temporary space used by the merge-sort routine. This block + ** of memory will be freed before this function returns. + */ + aTmp = (ht_slot *)sqlite3_malloc64( + sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) + ); + if( !aTmp ){ + rc = SQLITE_NOMEM; + } + + for(i=0; rc==SQLITE_OK && iaSegment[p->nSegment])[iZero]; + iZero++; + + for(j=0; jaSegment[i].iZero = iZero; + p->aSegment[i].nEntry = nEntry; + p->aSegment[i].aIndex = aIndex; + p->aSegment[i].aPgno = (u32 *)aPgno; + } + } + sqlite3_free(aTmp); + + if( rc!=SQLITE_OK ){ + walIteratorFree(p); + } + *pp = p; + return rc; +} + +/* +** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and +** n. If the attempt fails and parameter xBusy is not NULL, then it is a +** busy-handler function. Invoke it and retry the lock until either the +** lock is successfully obtained or the busy-handler returns 0. +*/ +static int walBusyLock( + Wal *pWal, /* WAL connection */ + int (*xBusy)(void*), /* Function to call when busy */ + void *pBusyArg, /* Context argument for xBusyHandler */ + int lockIdx, /* Offset of first byte to lock */ + int n /* Number of bytes to lock */ +){ + int rc; + do { + rc = walLockExclusive(pWal, lockIdx, n, 0); + }while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) ); + return rc; +} + +/* +** The cache of the wal-index header must be valid to call this function. +** Return the page-size in bytes used by the database. +*/ +static int walPagesize(Wal *pWal){ + return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); +} + +/* +** The following is guaranteed when this function is called: +** +** a) the WRITER lock is held, +** b) the entire log file has been checkpointed, and +** c) any existing readers are reading exclusively from the database +** file - there are no readers that may attempt to read a frame from +** the log file. +** +** This function updates the shared-memory structures so that the next +** client to write to the database (which may be this one) does so by +** writing frames into the start of the log file. +** +** The value of parameter salt1 is used as the aSalt[1] value in the +** new wal-index header. It should be passed a pseudo-random value (i.e. +** one obtained from sqlite3_randomness()). +*/ +static void walRestartHdr(Wal *pWal, u32 salt1){ + volatile WalCkptInfo *pInfo = walCkptInfo(pWal); + int i; /* Loop counter */ + u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */ + pWal->nCkpt++; + pWal->hdr.mxFrame = 0; + sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); + memcpy(&pWal->hdr.aSalt[1], &salt1, 4); + walIndexWriteHdr(pWal); + pInfo->nBackfill = 0; + pInfo->aReadMark[1] = 0; + for(i=2; iaReadMark[i] = READMARK_NOT_USED; + assert( pInfo->aReadMark[0]==0 ); +} + +/* +** Copy as much content as we can from the WAL back into the database file +** in response to an sqlite3_wal_checkpoint() request or the equivalent. +** +** The amount of information copies from WAL to database might be limited +** by active readers. This routine will never overwrite a database page +** that a concurrent reader might be using. +** +** All I/O barrier operations (a.k.a fsyncs) occur in this routine when +** SQLite is in WAL-mode in synchronous=NORMAL. That means that if +** checkpoints are always run by a background thread or background +** process, foreground threads will never block on a lengthy fsync call. +** +** Fsync is called on the WAL before writing content out of the WAL and +** into the database. This ensures that if the new content is persistent +** in the WAL and can be recovered following a power-loss or hard reset. +** +** Fsync is also called on the database file if (and only if) the entire +** WAL content is copied into the database file. This second fsync makes +** it safe to delete the WAL since the new content will persist in the +** database file. +** +** This routine uses and updates the nBackfill field of the wal-index header. +** This is the only routine that will increase the value of nBackfill. +** (A WAL reset or recovery will revert nBackfill to zero, but not increase +** its value.) +** +** The caller must be holding sufficient locks to ensure that no other +** checkpoint is running (in any other thread or process) at the same +** time. +*/ +static int walCheckpoint( + Wal *pWal, /* Wal connection */ + int eMode, /* One of PASSIVE, FULL or RESTART */ + int (*xBusy)(void*), /* Function to call when busy */ + void *pBusyArg, /* Context argument for xBusyHandler */ + int sync_flags, /* Flags for OsSync() (or 0) */ + u8 *zBuf /* Temporary buffer to use */ +){ + int rc = SQLITE_OK; /* Return code */ + int szPage; /* Database page-size */ + WalIterator *pIter = 0; /* Wal iterator context */ + u32 iDbpage = 0; /* Next database page to write */ + u32 iFrame = 0; /* Wal frame containing data for iDbpage */ + u32 mxSafeFrame; /* Max frame that can be backfilled */ + u32 mxPage; /* Max database page to write */ + int i; /* Loop counter */ + volatile WalCkptInfo *pInfo; /* The checkpoint status information */ + + szPage = walPagesize(pWal); + testcase( szPage<=32768 ); + testcase( szPage>=65536 ); + pInfo = walCkptInfo(pWal); + if( pInfo->nBackfillhdr.mxFrame ){ + + /* Allocate the iterator */ + rc = walIteratorInit(pWal, &pIter); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pIter ); + + /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked + ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ + assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); + + /* Compute in mxSafeFrame the index of the last frame of the WAL that is + ** safe to write into the database. Frames beyond mxSafeFrame might + ** overwrite database pages that are in use by active readers and thus + ** cannot be backfilled from the WAL. + */ + mxSafeFrame = pWal->hdr.mxFrame; + mxPage = pWal->hdr.nPage; + for(i=1; iaReadMark[i]; + if( mxSafeFrame>y ){ + assert( y<=pWal->hdr.mxFrame ); + rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); + if( rc==SQLITE_OK ){ + pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED); + walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); + }else if( rc==SQLITE_BUSY ){ + mxSafeFrame = y; + xBusy = 0; + }else{ + goto walcheckpoint_out; + } + } + } + + if( pInfo->nBackfillnBackfill; + + /* Sync the WAL to disk */ + if( sync_flags ){ + rc = sqlite3OsSync(pWal->pWalFd, sync_flags); + } + + /* If the database may grow as a result of this checkpoint, hint + ** about the eventual size of the db file to the VFS layer. + */ + if( rc==SQLITE_OK ){ + i64 nReq = ((i64)mxPage * szPage); + rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); + if( rc==SQLITE_OK && nSizepDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq); + } + } + + + /* Iterate through the contents of the WAL, copying data to the db file */ + while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ + i64 iOffset; + assert( walFramePgno(pWal, iFrame)==iDbpage ); + if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ + continue; + } + iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; + /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ + rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset); + if( rc!=SQLITE_OK ) break; + iOffset = (iDbpage-1)*(i64)szPage; + testcase( IS_BIG_INT(iOffset) ); + rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); + if( rc!=SQLITE_OK ) break; + } + + /* If work was actually accomplished... */ + if( rc==SQLITE_OK ){ + if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){ + i64 szDb = pWal->hdr.nPage*(i64)szPage; + testcase( IS_BIG_INT(szDb) ); + rc = sqlite3OsTruncate(pWal->pDbFd, szDb); + if( rc==SQLITE_OK && sync_flags ){ + rc = sqlite3OsSync(pWal->pDbFd, sync_flags); + } + } + if( rc==SQLITE_OK ){ + pInfo->nBackfill = mxSafeFrame; + } + } + + /* Release the reader lock held while backfilling */ + walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1); + } + + if( rc==SQLITE_BUSY ){ + /* Reset the return code so as not to report a checkpoint failure + ** just because there are active readers. */ + rc = SQLITE_OK; + } + } + + /* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the + ** entire wal file has been copied into the database file, then block + ** until all readers have finished using the wal file. This ensures that + ** the next process to write to the database restarts the wal file. + */ + if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ + assert( pWal->writeLock ); + if( pInfo->nBackfillhdr.mxFrame ){ + rc = SQLITE_BUSY; + }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ + u32 salt1; + sqlite3_randomness(4, &salt1); + assert( pInfo->nBackfill==pWal->hdr.mxFrame ); + rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1); + if( rc==SQLITE_OK ){ + if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){ + /* IMPLEMENTATION-OF: R-44699-57140 This mode works the same way as + ** SQLITE_CHECKPOINT_RESTART with the addition that it also + ** truncates the log file to zero bytes just prior to a + ** successful return. + ** + ** In theory, it might be safe to do this without updating the + ** wal-index header in shared memory, as all subsequent reader or + ** writer clients should see that the entire log file has been + ** checkpointed and behave accordingly. This seems unsafe though, + ** as it would leave the system in a state where the contents of + ** the wal-index header do not match the contents of the + ** file-system. To avoid this, update the wal-index header to + ** indicate that the log file contains zero valid frames. */ + walRestartHdr(pWal, salt1); + rc = sqlite3OsTruncate(pWal->pWalFd, 0); + } + walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); + } + } + } + + walcheckpoint_out: + walIteratorFree(pIter); + return rc; +} + +/* +** If the WAL file is currently larger than nMax bytes in size, truncate +** it to exactly nMax bytes. If an error occurs while doing so, ignore it. +*/ +static void walLimitSize(Wal *pWal, i64 nMax){ + i64 sz; + int rx; + sqlite3BeginBenignMalloc(); + rx = sqlite3OsFileSize(pWal->pWalFd, &sz); + if( rx==SQLITE_OK && (sz > nMax ) ){ + rx = sqlite3OsTruncate(pWal->pWalFd, nMax); + } + sqlite3EndBenignMalloc(); + if( rx ){ + sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName); + } +} + +/* +** Close a connection to a log file. +*/ +SQLITE_PRIVATE int sqlite3WalClose( + Wal *pWal, /* Wal to close */ + int sync_flags, /* Flags to pass to OsSync() (or 0) */ + int nBuf, + u8 *zBuf /* Buffer of at least nBuf bytes */ +){ + int rc = SQLITE_OK; + if( pWal ){ + int isDelete = 0; /* True to unlink wal and wal-index files */ + + /* If an EXCLUSIVE lock can be obtained on the database file (using the + ** ordinary, rollback-mode locking methods, this guarantees that the + ** connection associated with this log file is the only connection to + ** the database. In this case checkpoint the database and unlink both + ** the wal and wal-index files. + ** + ** The EXCLUSIVE lock is not released before returning. + */ + rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE); + if( rc==SQLITE_OK ){ + if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ + pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; + } + rc = sqlite3WalCheckpoint( + pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 + ); + if( rc==SQLITE_OK ){ + int bPersist = -1; + sqlite3OsFileControlHint( + pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist + ); + if( bPersist!=1 ){ + /* Try to delete the WAL file if the checkpoint completed and + ** fsyned (rc==SQLITE_OK) and if we are not in persistent-wal + ** mode (!bPersist) */ + isDelete = 1; + }else if( pWal->mxWalSize>=0 ){ + /* Try to truncate the WAL file to zero bytes if the checkpoint + ** completed and fsynced (rc==SQLITE_OK) and we are in persistent + ** WAL mode (bPersist) and if the PRAGMA journal_size_limit is a + ** non-negative value (pWal->mxWalSize>=0). Note that we truncate + ** to zero bytes as truncating to the journal_size_limit might + ** leave a corrupt WAL file on disk. */ + walLimitSize(pWal, 0); + } + } + } + + walIndexClose(pWal, isDelete); + sqlite3OsClose(pWal->pWalFd); + if( isDelete ){ + sqlite3BeginBenignMalloc(); + sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0); + sqlite3EndBenignMalloc(); + } + WALTRACE(("WAL%p: closed\n", pWal)); + sqlite3_free((void *)pWal->apWiData); + sqlite3_free(pWal); + } + return rc; +} + +/* +** Try to read the wal-index header. Return 0 on success and 1 if +** there is a problem. +** +** The wal-index is in shared memory. Another thread or process might +** be writing the header at the same time this procedure is trying to +** read it, which might result in inconsistency. A dirty read is detected +** by verifying that both copies of the header are the same and also by +** a checksum on the header. +** +** If and only if the read is consistent and the header is different from +** pWal->hdr, then pWal->hdr is updated to the content of the new header +** and *pChanged is set to 1. +** +** If the checksum cannot be verified return non-zero. If the header +** is read successfully and the checksum verified, return zero. +*/ +static int walIndexTryHdr(Wal *pWal, int *pChanged){ + u32 aCksum[2]; /* Checksum on the header content */ + WalIndexHdr h1, h2; /* Two copies of the header content */ + WalIndexHdr volatile *aHdr; /* Header in shared memory */ + + /* The first page of the wal-index must be mapped at this point. */ + assert( pWal->nWiData>0 && pWal->apWiData[0] ); + + /* Read the header. This might happen concurrently with a write to the + ** same area of shared memory on a different CPU in a SMP, + ** meaning it is possible that an inconsistent snapshot is read + ** from the file. If this happens, return non-zero. + ** + ** There are two copies of the header at the beginning of the wal-index. + ** When reading, read [0] first then [1]. Writes are in the reverse order. + ** Memory barriers are used to prevent the compiler or the hardware from + ** reordering the reads and writes. + */ + aHdr = walIndexHdr(pWal); + memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); + walShmBarrier(pWal); + memcpy(&h2, (void *)&aHdr[1], sizeof(h2)); + + if( memcmp(&h1, &h2, sizeof(h1))!=0 ){ + return 1; /* Dirty read */ + } + if( h1.isInit==0 ){ + return 1; /* Malformed header - probably all zeros */ + } + walChecksumBytes(1, (u8*)&h1, sizeof(h1)-sizeof(h1.aCksum), 0, aCksum); + if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){ + return 1; /* Checksum does not match */ + } + + if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){ + *pChanged = 1; + memcpy(&pWal->hdr, &h1, sizeof(WalIndexHdr)); + pWal->szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); + testcase( pWal->szPage<=32768 ); + testcase( pWal->szPage>=65536 ); + } + + /* The header was successfully read. Return zero. */ + return 0; +} + +/* +** Read the wal-index header from the wal-index and into pWal->hdr. +** If the wal-header appears to be corrupt, try to reconstruct the +** wal-index from the WAL before returning. +** +** Set *pChanged to 1 if the wal-index header value in pWal->hdr is +** changed by this operation. If pWal->hdr is unchanged, set *pChanged +** to 0. +** +** If the wal-index header is successfully read, return SQLITE_OK. +** Otherwise an SQLite error code. +*/ +static int walIndexReadHdr(Wal *pWal, int *pChanged){ + int rc; /* Return code */ + int badHdr; /* True if a header read failed */ + volatile u32 *page0; /* Chunk of wal-index containing header */ + + /* Ensure that page 0 of the wal-index (the page that contains the + ** wal-index header) is mapped. Return early if an error occurs here. + */ + assert( pChanged ); + rc = walIndexPage(pWal, 0, &page0); + if( rc!=SQLITE_OK ){ + return rc; + }; + assert( page0 || pWal->writeLock==0 ); + + /* If the first page of the wal-index has been mapped, try to read the + ** wal-index header immediately, without holding any lock. This usually + ** works, but may fail if the wal-index header is corrupt or currently + ** being modified by another thread or process. + */ + badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1); + + /* If the first attempt failed, it might have been due to a race + ** with a writer. So get a WRITE lock and try again. + */ + assert( badHdr==0 || pWal->writeLock==0 ); + if( badHdr ){ + if( pWal->readOnly & WAL_SHM_RDONLY ){ + if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){ + walUnlockShared(pWal, WAL_WRITE_LOCK); + rc = SQLITE_READONLY_RECOVERY; + } + }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 1)) ){ + pWal->writeLock = 1; + if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ + badHdr = walIndexTryHdr(pWal, pChanged); + if( badHdr ){ + /* If the wal-index header is still malformed even while holding + ** a WRITE lock, it can only mean that the header is corrupted and + ** needs to be reconstructed. So run recovery to do exactly that. + */ + rc = walIndexRecover(pWal); + *pChanged = 1; + } + } + pWal->writeLock = 0; + walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); + } + } + + /* If the header is read successfully, check the version number to make + ** sure the wal-index was not constructed with some future format that + ** this version of SQLite cannot understand. + */ + if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){ + rc = SQLITE_CANTOPEN_BKPT; + } + + return rc; +} + +/* +** This is the value that walTryBeginRead returns when it needs to +** be retried. +*/ +#define WAL_RETRY (-1) + +/* +** Attempt to start a read transaction. This might fail due to a race or +** other transient condition. When that happens, it returns WAL_RETRY to +** indicate to the caller that it is safe to retry immediately. +** +** On success return SQLITE_OK. On a permanent failure (such an +** I/O error or an SQLITE_BUSY because another process is running +** recovery) return a positive error code. +** +** The useWal parameter is true to force the use of the WAL and disable +** the case where the WAL is bypassed because it has been completely +** checkpointed. If useWal==0 then this routine calls walIndexReadHdr() +** to make a copy of the wal-index header into pWal->hdr. If the +** wal-index header has changed, *pChanged is set to 1 (as an indication +** to the caller that the local paget cache is obsolete and needs to be +** flushed.) When useWal==1, the wal-index header is assumed to already +** be loaded and the pChanged parameter is unused. +** +** The caller must set the cnt parameter to the number of prior calls to +** this routine during the current read attempt that returned WAL_RETRY. +** This routine will start taking more aggressive measures to clear the +** race conditions after multiple WAL_RETRY returns, and after an excessive +** number of errors will ultimately return SQLITE_PROTOCOL. The +** SQLITE_PROTOCOL return indicates that some other process has gone rogue +** and is not honoring the locking protocol. There is a vanishingly small +** chance that SQLITE_PROTOCOL could be returned because of a run of really +** bad luck when there is lots of contention for the wal-index, but that +** possibility is so small that it can be safely neglected, we believe. +** +** On success, this routine obtains a read lock on +** WAL_READ_LOCK(pWal->readLock). The pWal->readLock integer is +** in the range 0 <= pWal->readLock < WAL_NREADER. If pWal->readLock==(-1) +** that means the Wal does not hold any read lock. The reader must not +** access any database page that is modified by a WAL frame up to and +** including frame number aReadMark[pWal->readLock]. The reader will +** use WAL frames up to and including pWal->hdr.mxFrame if pWal->readLock>0 +** Or if pWal->readLock==0, then the reader will ignore the WAL +** completely and get all content directly from the database file. +** If the useWal parameter is 1 then the WAL will never be ignored and +** this routine will always set pWal->readLock>0 on success. +** When the read transaction is completed, the caller must release the +** lock on WAL_READ_LOCK(pWal->readLock) and set pWal->readLock to -1. +** +** This routine uses the nBackfill and aReadMark[] fields of the header +** to select a particular WAL_READ_LOCK() that strives to let the +** checkpoint process do as much work as possible. This routine might +** update values of the aReadMark[] array in the header, but if it does +** so it takes care to hold an exclusive lock on the corresponding +** WAL_READ_LOCK() while changing values. +*/ +static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ + volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */ + u32 mxReadMark; /* Largest aReadMark[] value */ + int mxI; /* Index of largest aReadMark[] value */ + int i; /* Loop counter */ + int rc = SQLITE_OK; /* Return code */ + + assert( pWal->readLock<0 ); /* Not currently locked */ + + /* Take steps to avoid spinning forever if there is a protocol error. + ** + ** Circumstances that cause a RETRY should only last for the briefest + ** instances of time. No I/O or other system calls are done while the + ** locks are held, so the locks should not be held for very long. But + ** if we are unlucky, another process that is holding a lock might get + ** paged out or take a page-fault that is time-consuming to resolve, + ** during the few nanoseconds that it is holding the lock. In that case, + ** it might take longer than normal for the lock to free. + ** + ** After 5 RETRYs, we begin calling sqlite3OsSleep(). The first few + ** calls to sqlite3OsSleep() have a delay of 1 microsecond. Really this + ** is more of a scheduler yield than an actual delay. But on the 10th + ** an subsequent retries, the delays start becoming longer and longer, + ** so that on the 100th (and last) RETRY we delay for 323 milliseconds. + ** The total delay time before giving up is less than 10 seconds. + */ + if( cnt>5 ){ + int nDelay = 1; /* Pause time in microseconds */ + if( cnt>100 ){ + VVA_ONLY( pWal->lockError = 1; ) + return SQLITE_PROTOCOL; + } + if( cnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39; + sqlite3OsSleep(pWal->pVfs, nDelay); + } + + if( !useWal ){ + rc = walIndexReadHdr(pWal, pChanged); + if( rc==SQLITE_BUSY ){ + /* If there is not a recovery running in another thread or process + ** then convert BUSY errors to WAL_RETRY. If recovery is known to + ** be running, convert BUSY to BUSY_RECOVERY. There is a race here + ** which might cause WAL_RETRY to be returned even if BUSY_RECOVERY + ** would be technically correct. But the race is benign since with + ** WAL_RETRY this routine will be called again and will probably be + ** right on the second iteration. + */ + if( pWal->apWiData[0]==0 ){ + /* This branch is taken when the xShmMap() method returns SQLITE_BUSY. + ** We assume this is a transient condition, so return WAL_RETRY. The + ** xShmMap() implementation used by the default unix and win32 VFS + ** modules may return SQLITE_BUSY due to a race condition in the + ** code that determines whether or not the shared-memory region + ** must be zeroed before the requested page is returned. + */ + rc = WAL_RETRY; + }else if( SQLITE_OK==(rc = walLockShared(pWal, WAL_RECOVER_LOCK)) ){ + walUnlockShared(pWal, WAL_RECOVER_LOCK); + rc = WAL_RETRY; + }else if( rc==SQLITE_BUSY ){ + rc = SQLITE_BUSY_RECOVERY; + } + } + if( rc!=SQLITE_OK ){ + return rc; + } + } + + pInfo = walCkptInfo(pWal); + if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ){ + /* The WAL has been completely backfilled (or it is empty). + ** and can be safely ignored. + */ + rc = walLockShared(pWal, WAL_READ_LOCK(0)); + walShmBarrier(pWal); + if( rc==SQLITE_OK ){ + if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){ + /* It is not safe to allow the reader to continue here if frames + ** may have been appended to the log before READ_LOCK(0) was obtained. + ** When holding READ_LOCK(0), the reader ignores the entire log file, + ** which implies that the database file contains a trustworthy + ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from + ** happening, this is usually correct. + ** + ** However, if frames have been appended to the log (or if the log + ** is wrapped and written for that matter) before the READ_LOCK(0) + ** is obtained, that is not necessarily true. A checkpointer may + ** have started to backfill the appended frames but crashed before + ** it finished. Leaving a corrupt image in the database file. + */ + walUnlockShared(pWal, WAL_READ_LOCK(0)); + return WAL_RETRY; + } + pWal->readLock = 0; + return SQLITE_OK; + }else if( rc!=SQLITE_BUSY ){ + return rc; + } + } + + /* If we get this far, it means that the reader will want to use + ** the WAL to get at content from recent commits. The job now is + ** to select one of the aReadMark[] entries that is closest to + ** but not exceeding pWal->hdr.mxFrame and lock that entry. + */ + mxReadMark = 0; + mxI = 0; + for(i=1; iaReadMark[i]; + if( mxReadMark<=thisMark && thisMark<=pWal->hdr.mxFrame ){ + assert( thisMark!=READMARK_NOT_USED ); + mxReadMark = thisMark; + mxI = i; + } + } + /* There was once an "if" here. The extra "{" is to preserve indentation. */ + { + if( (pWal->readOnly & WAL_SHM_RDONLY)==0 + && (mxReadMarkhdr.mxFrame || mxI==0) + ){ + for(i=1; iaReadMark[i] = pWal->hdr.mxFrame; + mxI = i; + walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); + break; + }else if( rc!=SQLITE_BUSY ){ + return rc; + } + } + } + if( mxI==0 ){ + assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 ); + return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK; + } + + rc = walLockShared(pWal, WAL_READ_LOCK(mxI)); + if( rc ){ + return rc==SQLITE_BUSY ? WAL_RETRY : rc; + } + /* Now that the read-lock has been obtained, check that neither the + ** value in the aReadMark[] array or the contents of the wal-index + ** header have changed. + ** + ** It is necessary to check that the wal-index header did not change + ** between the time it was read and when the shared-lock was obtained + ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility + ** that the log file may have been wrapped by a writer, or that frames + ** that occur later in the log than pWal->hdr.mxFrame may have been + ** copied into the database by a checkpointer. If either of these things + ** happened, then reading the database with the current value of + ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry + ** instead. + ** + ** This does not guarantee that the copy of the wal-index header is up to + ** date before proceeding. That would not be possible without somehow + ** blocking writers. It only guarantees that a dangerous checkpoint or + ** log-wrap (either of which would require an exclusive lock on + ** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid. + */ + walShmBarrier(pWal); + if( pInfo->aReadMark[mxI]!=mxReadMark + || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) + ){ + walUnlockShared(pWal, WAL_READ_LOCK(mxI)); + return WAL_RETRY; + }else{ + assert( mxReadMark<=pWal->hdr.mxFrame ); + pWal->readLock = (i16)mxI; + } + } + return rc; +} + +/* +** Begin a read transaction on the database. +** +** This routine used to be called sqlite3OpenSnapshot() and with good reason: +** it takes a snapshot of the state of the WAL and wal-index for the current +** instant in time. The current thread will continue to use this snapshot. +** Other threads might append new content to the WAL and wal-index but +** that extra content is ignored by the current thread. +** +** If the database contents have changes since the previous read +** transaction, then *pChanged is set to 1 before returning. The +** Pager layer will use this to know that is cache is stale and +** needs to be flushed. +*/ +SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ + int rc; /* Return code */ + int cnt = 0; /* Number of TryBeginRead attempts */ + + do{ + rc = walTryBeginRead(pWal, pChanged, 0, ++cnt); + }while( rc==WAL_RETRY ); + testcase( (rc&0xff)==SQLITE_BUSY ); + testcase( (rc&0xff)==SQLITE_IOERR ); + testcase( rc==SQLITE_PROTOCOL ); + testcase( rc==SQLITE_OK ); + return rc; +} + +/* +** Finish with a read transaction. All this does is release the +** read-lock. +*/ +SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){ + sqlite3WalEndWriteTransaction(pWal); + if( pWal->readLock>=0 ){ + walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); + pWal->readLock = -1; + } +} + +/* +** Search the wal file for page pgno. If found, set *piRead to the frame that +** contains the page. Otherwise, if pgno is not in the wal file, set *piRead +** to zero. +** +** Return SQLITE_OK if successful, or an error code if an error occurs. If an +** error does occur, the final value of *piRead is undefined. +*/ +SQLITE_PRIVATE int sqlite3WalFindFrame( + Wal *pWal, /* WAL handle */ + Pgno pgno, /* Database page number to read data for */ + u32 *piRead /* OUT: Frame number (or zero) */ +){ + u32 iRead = 0; /* If !=0, WAL frame to return data from */ + u32 iLast = pWal->hdr.mxFrame; /* Last page in WAL for this reader */ + int iHash; /* Used to loop through N hash tables */ + + /* This routine is only be called from within a read transaction. */ + assert( pWal->readLock>=0 || pWal->lockError ); + + /* If the "last page" field of the wal-index header snapshot is 0, then + ** no data will be read from the wal under any circumstances. Return early + ** in this case as an optimization. Likewise, if pWal->readLock==0, + ** then the WAL is ignored by the reader so return early, as if the + ** WAL were empty. + */ + if( iLast==0 || pWal->readLock==0 ){ + *piRead = 0; + return SQLITE_OK; + } + + /* Search the hash table or tables for an entry matching page number + ** pgno. Each iteration of the following for() loop searches one + ** hash table (each hash table indexes up to HASHTABLE_NPAGE frames). + ** + ** This code might run concurrently to the code in walIndexAppend() + ** that adds entries to the wal-index (and possibly to this hash + ** table). This means the value just read from the hash + ** slot (aHash[iKey]) may have been added before or after the + ** current read transaction was opened. Values added after the + ** read transaction was opened may have been written incorrectly - + ** i.e. these slots may contain garbage data. However, we assume + ** that any slots written before the current read transaction was + ** opened remain unmodified. + ** + ** For the reasons above, the if(...) condition featured in the inner + ** loop of the following block is more stringent that would be required + ** if we had exclusive access to the hash-table: + ** + ** (aPgno[iFrame]==pgno): + ** This condition filters out normal hash-table collisions. + ** + ** (iFrame<=iLast): + ** This condition filters out entries that were added to the hash + ** table after the current read-transaction had started. + */ + for(iHash=walFramePage(iLast); iHash>=0 && iRead==0; iHash--){ + volatile ht_slot *aHash; /* Pointer to hash table */ + volatile u32 *aPgno; /* Pointer to array of page numbers */ + u32 iZero; /* Frame number corresponding to aPgno[0] */ + int iKey; /* Hash slot index */ + int nCollide; /* Number of hash collisions remaining */ + int rc; /* Error code */ + + rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero); + if( rc!=SQLITE_OK ){ + return rc; + } + nCollide = HASHTABLE_NSLOT; + for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ + u32 iFrame = aHash[iKey] + iZero; + if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){ + assert( iFrame>iRead || CORRUPT_DB ); + iRead = iFrame; + } + if( (nCollide--)==0 ){ + return SQLITE_CORRUPT_BKPT; + } + } + } + +#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT + /* If expensive assert() statements are available, do a linear search + ** of the wal-index file content. Make sure the results agree with the + ** result obtained using the hash indexes above. */ + { + u32 iRead2 = 0; + u32 iTest; + for(iTest=iLast; iTest>0; iTest--){ + if( walFramePgno(pWal, iTest)==pgno ){ + iRead2 = iTest; + break; + } + } + assert( iRead==iRead2 ); + } +#endif + + *piRead = iRead; + return SQLITE_OK; +} + +/* +** Read the contents of frame iRead from the wal file into buffer pOut +** (which is nOut bytes in size). Return SQLITE_OK if successful, or an +** error code otherwise. +*/ +SQLITE_PRIVATE int sqlite3WalReadFrame( + Wal *pWal, /* WAL handle */ + u32 iRead, /* Frame to read */ + int nOut, /* Size of buffer pOut in bytes */ + u8 *pOut /* Buffer to write page data to */ +){ + int sz; + i64 iOffset; + sz = pWal->hdr.szPage; + sz = (sz&0xfe00) + ((sz&0x0001)<<16); + testcase( sz<=32768 ); + testcase( sz>=65536 ); + iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE; + /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */ + return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset); +} + +/* +** Return the size of the database in pages (or zero, if unknown). +*/ +SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){ + if( pWal && ALWAYS(pWal->readLock>=0) ){ + return pWal->hdr.nPage; + } + return 0; +} + + +/* +** This function starts a write transaction on the WAL. +** +** A read transaction must have already been started by a prior call +** to sqlite3WalBeginReadTransaction(). +** +** If another thread or process has written into the database since +** the read transaction was started, then it is not possible for this +** thread to write as doing so would cause a fork. So this routine +** returns SQLITE_BUSY in that case and no write transaction is started. +** +** There can only be a single writer active at a time. +*/ +SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){ + int rc; + + /* Cannot start a write transaction without first holding a read + ** transaction. */ + assert( pWal->readLock>=0 ); + + if( pWal->readOnly ){ + return SQLITE_READONLY; + } + + /* Only one writer allowed at a time. Get the write lock. Return + ** SQLITE_BUSY if unable. + */ + rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 0); + if( rc ){ + return rc; + } + pWal->writeLock = 1; + + /* If another connection has written to the database file since the + ** time the read transaction on this connection was started, then + ** the write is disallowed. + */ + if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ + walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); + pWal->writeLock = 0; + rc = SQLITE_BUSY_SNAPSHOT; + } + + return rc; +} + +/* +** End a write transaction. The commit has already been done. This +** routine merely releases the lock. +*/ +SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal){ + if( pWal->writeLock ){ + walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); + pWal->writeLock = 0; + pWal->truncateOnCommit = 0; + } + return SQLITE_OK; +} + +/* +** If any data has been written (but not committed) to the log file, this +** function moves the write-pointer back to the start of the transaction. +** +** Additionally, the callback function is invoked for each frame written +** to the WAL since the start of the transaction. If the callback returns +** other than SQLITE_OK, it is not invoked again and the error code is +** returned to the caller. +** +** Otherwise, if the callback function does not return an error, this +** function returns SQLITE_OK. +*/ +SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){ + int rc = SQLITE_OK; + if( ALWAYS(pWal->writeLock) ){ + Pgno iMax = pWal->hdr.mxFrame; + Pgno iFrame; + + /* Restore the clients cache of the wal-index header to the state it + ** was in before the client began writing to the database. + */ + memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); + + for(iFrame=pWal->hdr.mxFrame+1; + ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; + iFrame++ + ){ + /* This call cannot fail. Unless the page for which the page number + ** is passed as the second argument is (a) in the cache and + ** (b) has an outstanding reference, then xUndo is either a no-op + ** (if (a) is false) or simply expels the page from the cache (if (b) + ** is false). + ** + ** If the upper layer is doing a rollback, it is guaranteed that there + ** are no outstanding references to any page other than page 1. And + ** page 1 is never written to the log until the transaction is + ** committed. As a result, the call to xUndo may not fail. + */ + assert( walFramePgno(pWal, iFrame)!=1 ); + rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); + } + if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); + } + return rc; +} + +/* +** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 +** values. This function populates the array with values required to +** "rollback" the write position of the WAL handle back to the current +** point in the event of a savepoint rollback (via WalSavepointUndo()). +*/ +SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData){ + assert( pWal->writeLock ); + aWalData[0] = pWal->hdr.mxFrame; + aWalData[1] = pWal->hdr.aFrameCksum[0]; + aWalData[2] = pWal->hdr.aFrameCksum[1]; + aWalData[3] = pWal->nCkpt; +} + +/* +** Move the write position of the WAL back to the point identified by +** the values in the aWalData[] array. aWalData must point to an array +** of WAL_SAVEPOINT_NDATA u32 values that has been previously populated +** by a call to WalSavepoint(). +*/ +SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ + int rc = SQLITE_OK; + + assert( pWal->writeLock ); + assert( aWalData[3]!=pWal->nCkpt || aWalData[0]<=pWal->hdr.mxFrame ); + + if( aWalData[3]!=pWal->nCkpt ){ + /* This savepoint was opened immediately after the write-transaction + ** was started. Right after that, the writer decided to wrap around + ** to the start of the log. Update the savepoint values to match. + */ + aWalData[0] = 0; + aWalData[3] = pWal->nCkpt; + } + + if( aWalData[0]hdr.mxFrame ){ + pWal->hdr.mxFrame = aWalData[0]; + pWal->hdr.aFrameCksum[0] = aWalData[1]; + pWal->hdr.aFrameCksum[1] = aWalData[2]; + walCleanupHash(pWal); + } + + return rc; +} + +/* +** This function is called just before writing a set of frames to the log +** file (see sqlite3WalFrames()). It checks to see if, instead of appending +** to the current log file, it is possible to overwrite the start of the +** existing log file with the new frames (i.e. "reset" the log). If so, +** it sets pWal->hdr.mxFrame to 0. Otherwise, pWal->hdr.mxFrame is left +** unchanged. +** +** SQLITE_OK is returned if no error is encountered (regardless of whether +** or not pWal->hdr.mxFrame is modified). An SQLite error code is returned +** if an error occurs. +*/ +static int walRestartLog(Wal *pWal){ + int rc = SQLITE_OK; + int cnt; + + if( pWal->readLock==0 ){ + volatile WalCkptInfo *pInfo = walCkptInfo(pWal); + assert( pInfo->nBackfill==pWal->hdr.mxFrame ); + if( pInfo->nBackfill>0 ){ + u32 salt1; + sqlite3_randomness(4, &salt1); + rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1, 0); + if( rc==SQLITE_OK ){ + /* If all readers are using WAL_READ_LOCK(0) (in other words if no + ** readers are currently using the WAL), then the transactions + ** frames will overwrite the start of the existing log. Update the + ** wal-index header to reflect this. + ** + ** In theory it would be Ok to update the cache of the header only + ** at this point. But updating the actual wal-index header is also + ** safe and means there is no special case for sqlite3WalUndo() + ** to handle if this transaction is rolled back. */ + walRestartHdr(pWal, salt1); + walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); + }else if( rc!=SQLITE_BUSY ){ + return rc; + } + } + walUnlockShared(pWal, WAL_READ_LOCK(0)); + pWal->readLock = -1; + cnt = 0; + do{ + int notUsed; + rc = walTryBeginRead(pWal, ¬Used, 1, ++cnt); + }while( rc==WAL_RETRY ); + assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */ + testcase( (rc&0xff)==SQLITE_IOERR ); + testcase( rc==SQLITE_PROTOCOL ); + testcase( rc==SQLITE_OK ); + } + return rc; +} + +/* +** Information about the current state of the WAL file and where +** the next fsync should occur - passed from sqlite3WalFrames() into +** walWriteToLog(). +*/ +typedef struct WalWriter { + Wal *pWal; /* The complete WAL information */ + sqlite3_file *pFd; /* The WAL file to which we write */ + sqlite3_int64 iSyncPoint; /* Fsync at this offset */ + int syncFlags; /* Flags for the fsync */ + int szPage; /* Size of one page */ +} WalWriter; + +/* +** Write iAmt bytes of content into the WAL file beginning at iOffset. +** Do a sync when crossing the p->iSyncPoint boundary. +** +** In other words, if iSyncPoint is in between iOffset and iOffset+iAmt, +** first write the part before iSyncPoint, then sync, then write the +** rest. +*/ +static int walWriteToLog( + WalWriter *p, /* WAL to write to */ + void *pContent, /* Content to be written */ + int iAmt, /* Number of bytes to write */ + sqlite3_int64 iOffset /* Start writing at this offset */ +){ + int rc; + if( iOffsetiSyncPoint && iOffset+iAmt>=p->iSyncPoint ){ + int iFirstAmt = (int)(p->iSyncPoint - iOffset); + rc = sqlite3OsWrite(p->pFd, pContent, iFirstAmt, iOffset); + if( rc ) return rc; + iOffset += iFirstAmt; + iAmt -= iFirstAmt; + pContent = (void*)(iFirstAmt + (char*)pContent); + assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) ); + rc = sqlite3OsSync(p->pFd, p->syncFlags & SQLITE_SYNC_MASK); + if( iAmt==0 || rc ) return rc; + } + rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset); + return rc; +} + +/* +** Write out a single frame of the WAL +*/ +static int walWriteOneFrame( + WalWriter *p, /* Where to write the frame */ + PgHdr *pPage, /* The page of the frame to be written */ + int nTruncate, /* The commit flag. Usually 0. >0 for commit */ + sqlite3_int64 iOffset /* Byte offset at which to write */ +){ + int rc; /* Result code from subfunctions */ + void *pData; /* Data actually written */ + u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */ +#if defined(SQLITE_HAS_CODEC) + if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM; +#else + pData = pPage->pData; +#endif + walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame); + rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset); + if( rc ) return rc; + /* Write the page data */ + rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame)); + return rc; +} + +/* +** Write a set of frames to the log. The caller must hold the write-lock +** on the log file (obtained using sqlite3WalBeginWriteTransaction()). +*/ +SQLITE_PRIVATE int sqlite3WalFrames( + Wal *pWal, /* Wal handle to write to */ + int szPage, /* Database page-size in bytes */ + PgHdr *pList, /* List of dirty pages to write */ + Pgno nTruncate, /* Database size after this commit */ + int isCommit, /* True if this is a commit */ + int sync_flags /* Flags to pass to OsSync() (or 0) */ +){ + int rc; /* Used to catch return codes */ + u32 iFrame; /* Next frame address */ + PgHdr *p; /* Iterator to run through pList with. */ + PgHdr *pLast = 0; /* Last frame in list */ + int nExtra = 0; /* Number of extra copies of last page */ + int szFrame; /* The size of a single frame */ + i64 iOffset; /* Next byte to write in WAL file */ + WalWriter w; /* The writer */ + + assert( pList ); + assert( pWal->writeLock ); + + /* If this frame set completes a transaction, then nTruncate>0. If + ** nTruncate==0 then this frame set does not complete the transaction. */ + assert( (isCommit!=0)==(nTruncate!=0) ); + +#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) + { int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){} + WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n", + pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill")); + } +#endif + + /* See if it is possible to write these frames into the start of the + ** log file, instead of appending to it at pWal->hdr.mxFrame. + */ + if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){ + return rc; + } + + /* If this is the first frame written into the log, write the WAL + ** header to the start of the WAL file. See comments at the top of + ** this source file for a description of the WAL header format. + */ + iFrame = pWal->hdr.mxFrame; + if( iFrame==0 ){ + u8 aWalHdr[WAL_HDRSIZE]; /* Buffer to assemble wal-header in */ + u32 aCksum[2]; /* Checksum for wal-header */ + + sqlite3Put4byte(&aWalHdr[0], (WAL_MAGIC | SQLITE_BIGENDIAN)); + sqlite3Put4byte(&aWalHdr[4], WAL_MAX_VERSION); + sqlite3Put4byte(&aWalHdr[8], szPage); + sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt); + if( pWal->nCkpt==0 ) sqlite3_randomness(8, pWal->hdr.aSalt); + memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8); + walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum); + sqlite3Put4byte(&aWalHdr[24], aCksum[0]); + sqlite3Put4byte(&aWalHdr[28], aCksum[1]); + + pWal->szPage = szPage; + pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN; + pWal->hdr.aFrameCksum[0] = aCksum[0]; + pWal->hdr.aFrameCksum[1] = aCksum[1]; + pWal->truncateOnCommit = 1; + + rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0); + WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok")); + if( rc!=SQLITE_OK ){ + return rc; + } + + /* Sync the header (unless SQLITE_IOCAP_SEQUENTIAL is true or unless + ** all syncing is turned off by PRAGMA synchronous=OFF). Otherwise + ** an out-of-order write following a WAL restart could result in + ** database corruption. See the ticket: + ** + ** http://localhost:591/sqlite/info/ff5be73dee + */ + if( pWal->syncHeader && sync_flags ){ + rc = sqlite3OsSync(pWal->pWalFd, sync_flags & SQLITE_SYNC_MASK); + if( rc ) return rc; + } + } + assert( (int)pWal->szPage==szPage ); + + /* Setup information needed to write frames into the WAL */ + w.pWal = pWal; + w.pFd = pWal->pWalFd; + w.iSyncPoint = 0; + w.syncFlags = sync_flags; + w.szPage = szPage; + iOffset = walFrameOffset(iFrame+1, szPage); + szFrame = szPage + WAL_FRAME_HDRSIZE; + + /* Write all frames into the log file exactly once */ + for(p=pList; p; p=p->pDirty){ + int nDbSize; /* 0 normally. Positive == commit flag */ + iFrame++; + assert( iOffset==walFrameOffset(iFrame, szPage) ); + nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0; + rc = walWriteOneFrame(&w, p, nDbSize, iOffset); + if( rc ) return rc; + pLast = p; + iOffset += szFrame; + } + + /* If this is the end of a transaction, then we might need to pad + ** the transaction and/or sync the WAL file. + ** + ** Padding and syncing only occur if this set of frames complete a + ** transaction and if PRAGMA synchronous=FULL. If synchronous==NORMAL + ** or synchronous==OFF, then no padding or syncing are needed. + ** + ** If SQLITE_IOCAP_POWERSAFE_OVERWRITE is defined, then padding is not + ** needed and only the sync is done. If padding is needed, then the + ** final frame is repeated (with its commit mark) until the next sector + ** boundary is crossed. Only the part of the WAL prior to the last + ** sector boundary is synced; the part of the last frame that extends + ** past the sector boundary is written after the sync. + */ + if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){ + if( pWal->padToSectorBoundary ){ + int sectorSize = sqlite3SectorSize(pWal->pWalFd); + w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize; + while( iOffsettruncateOnCommit && pWal->mxWalSize>=0 ){ + i64 sz = pWal->mxWalSize; + if( walFrameOffset(iFrame+nExtra+1, szPage)>pWal->mxWalSize ){ + sz = walFrameOffset(iFrame+nExtra+1, szPage); + } + walLimitSize(pWal, sz); + pWal->truncateOnCommit = 0; + } + + /* Append data to the wal-index. It is not necessary to lock the + ** wal-index to do this as the SQLITE_SHM_WRITE lock held on the wal-index + ** guarantees that there are no other writers, and no data that may + ** be in use by existing readers is being overwritten. + */ + iFrame = pWal->hdr.mxFrame; + for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){ + iFrame++; + rc = walIndexAppend(pWal, iFrame, p->pgno); + } + while( rc==SQLITE_OK && nExtra>0 ){ + iFrame++; + nExtra--; + rc = walIndexAppend(pWal, iFrame, pLast->pgno); + } + + if( rc==SQLITE_OK ){ + /* Update the private copy of the header. */ + pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16)); + testcase( szPage<=32768 ); + testcase( szPage>=65536 ); + pWal->hdr.mxFrame = iFrame; + if( isCommit ){ + pWal->hdr.iChange++; + pWal->hdr.nPage = nTruncate; + } + /* If this is a commit, update the wal-index header too. */ + if( isCommit ){ + walIndexWriteHdr(pWal); + pWal->iCallback = iFrame; + } + } + + WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok")); + return rc; +} + +/* +** This routine is called to implement sqlite3_wal_checkpoint() and +** related interfaces. +** +** Obtain a CHECKPOINT lock and then backfill as much information as +** we can from WAL into the database. +** +** If parameter xBusy is not NULL, it is a pointer to a busy-handler +** callback. In this case this function runs a blocking checkpoint. +*/ +SQLITE_PRIVATE int sqlite3WalCheckpoint( + Wal *pWal, /* Wal connection */ + int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ + int (*xBusy)(void*), /* Function to call when busy */ + void *pBusyArg, /* Context argument for xBusyHandler */ + int sync_flags, /* Flags to sync db file with (or 0) */ + int nBuf, /* Size of temporary buffer */ + u8 *zBuf, /* Temporary buffer to use */ + int *pnLog, /* OUT: Number of frames in WAL */ + int *pnCkpt /* OUT: Number of backfilled frames in WAL */ +){ + int rc; /* Return code */ + int isChanged = 0; /* True if a new wal-index header is loaded */ + int eMode2 = eMode; /* Mode to pass to walCheckpoint() */ + int (*xBusy2)(void*) = xBusy; /* Busy handler for eMode2 */ + + assert( pWal->ckptLock==0 ); + assert( pWal->writeLock==0 ); + + /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked + ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ + assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); + + if( pWal->readOnly ) return SQLITE_READONLY; + WALTRACE(("WAL%p: checkpoint begins\n", pWal)); + + /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive + ** "checkpoint" lock on the database file. */ + rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1, 0); + if( rc ){ + /* EVIDENCE-OF: R-10421-19736 If any other process is running a + ** checkpoint operation at the same time, the lock cannot be obtained and + ** SQLITE_BUSY is returned. + ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured, + ** it will not be invoked in this case. + */ + testcase( rc==SQLITE_BUSY ); + testcase( xBusy!=0 ); + return rc; + } + pWal->ckptLock = 1; + + /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and + ** TRUNCATE modes also obtain the exclusive "writer" lock on the database + ** file. + ** + ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained + ** immediately, and a busy-handler is configured, it is invoked and the + ** writer lock retried until either the busy-handler returns 0 or the + ** lock is successfully obtained. + */ + if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ + rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1); + if( rc==SQLITE_OK ){ + pWal->writeLock = 1; + }else if( rc==SQLITE_BUSY ){ + eMode2 = SQLITE_CHECKPOINT_PASSIVE; + xBusy2 = 0; + rc = SQLITE_OK; + } + } + + /* Read the wal-index header. */ + if( rc==SQLITE_OK ){ + rc = walIndexReadHdr(pWal, &isChanged); + if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ + sqlite3OsUnfetch(pWal->pDbFd, 0, 0); + } + } + + /* Copy data from the log to the database file. */ + if( rc==SQLITE_OK ){ + if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); + } + + /* If no error occurred, set the output variables. */ + if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ + if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; + if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); + } + } + + if( isChanged ){ + /* If a new wal-index header was loaded before the checkpoint was + ** performed, then the pager-cache associated with pWal is now + ** out of date. So zero the cached wal-index header to ensure that + ** next time the pager opens a snapshot on this database it knows that + ** the cache needs to be reset. + */ + memset(&pWal->hdr, 0, sizeof(WalIndexHdr)); + } + + /* Release the locks. */ + sqlite3WalEndWriteTransaction(pWal); + walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); + pWal->ckptLock = 0; + WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok")); + return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc); +} + +/* Return the value to pass to a sqlite3_wal_hook callback, the +** number of frames in the WAL at the point of the last commit since +** sqlite3WalCallback() was called. If no commits have occurred since +** the last call, then return 0. +*/ +SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal){ + u32 ret = 0; + if( pWal ){ + ret = pWal->iCallback; + pWal->iCallback = 0; + } + return (int)ret; +} + +/* +** This function is called to change the WAL subsystem into or out +** of locking_mode=EXCLUSIVE. +** +** If op is zero, then attempt to change from locking_mode=EXCLUSIVE +** into locking_mode=NORMAL. This means that we must acquire a lock +** on the pWal->readLock byte. If the WAL is already in locking_mode=NORMAL +** or if the acquisition of the lock fails, then return 0. If the +** transition out of exclusive-mode is successful, return 1. This +** operation must occur while the pager is still holding the exclusive +** lock on the main database file. +** +** If op is one, then change from locking_mode=NORMAL into +** locking_mode=EXCLUSIVE. This means that the pWal->readLock must +** be released. Return 1 if the transition is made and 0 if the +** WAL is already in exclusive-locking mode - meaning that this +** routine is a no-op. The pager must already hold the exclusive lock +** on the main database file before invoking this operation. +** +** If op is negative, then do a dry-run of the op==1 case but do +** not actually change anything. The pager uses this to see if it +** should acquire the database exclusive lock prior to invoking +** the op==1 case. +*/ +SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){ + int rc; + assert( pWal->writeLock==0 ); + assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 ); + + /* pWal->readLock is usually set, but might be -1 if there was a + ** prior error while attempting to acquire are read-lock. This cannot + ** happen if the connection is actually in exclusive mode (as no xShmLock + ** locks are taken in this case). Nor should the pager attempt to + ** upgrade to exclusive-mode following such an error. + */ + assert( pWal->readLock>=0 || pWal->lockError ); + assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) ); + + if( op==0 ){ + if( pWal->exclusiveMode ){ + pWal->exclusiveMode = 0; + if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){ + pWal->exclusiveMode = 1; + } + rc = pWal->exclusiveMode==0; + }else{ + /* Already in locking_mode=NORMAL */ + rc = 0; + } + }else if( op>0 ){ + assert( pWal->exclusiveMode==0 ); + assert( pWal->readLock>=0 ); + walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); + pWal->exclusiveMode = 1; + rc = 1; + }else{ + rc = pWal->exclusiveMode==0; + } + return rc; +} + +/* +** Return true if the argument is non-NULL and the WAL module is using +** heap-memory for the wal-index. Otherwise, if the argument is NULL or the +** WAL module is using shared-memory, return false. +*/ +SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){ + return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ); +} + +#ifdef SQLITE_ENABLE_ZIPVFS +/* +** If the argument is not NULL, it points to a Wal object that holds a +** read-lock. This function returns the database page-size if it is known, +** or zero if it is not (or if pWal is NULL). +*/ +SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){ + assert( pWal==0 || pWal->readLock>=0 ); + return (pWal ? pWal->szPage : 0); +} +#endif + +#endif /* #ifndef SQLITE_OMIT_WAL */ + +/************** End of wal.c *************************************************/ +/************** Begin file btmutex.c *****************************************/ +/* +** 2007 August 27 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains code used to implement mutexes on Btree objects. +** This code really belongs in btree.c. But btree.c is getting too +** big and we want to break it down some. This packaged seemed like +** a good breakout. +*/ +/************** Include btreeInt.h in the middle of btmutex.c ****************/ +/************** Begin file btreeInt.h ****************************************/ +/* +** 2004 April 6 +** +** 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 an external (disk-based) database using BTrees. +** For a detailed discussion of BTrees, refer to +** +** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: +** "Sorting And Searching", pages 473-480. Addison-Wesley +** Publishing Company, Reading, Massachusetts. +** +** The basic idea is that each page of the file contains N database +** entries and N+1 pointers to subpages. +** +** ---------------------------------------------------------------- +** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N-1) | Ptr(N) | +** ---------------------------------------------------------------- +** +** All of the keys on the page that Ptr(0) points to have values less +** than Key(0). All of the keys on page Ptr(1) and its subpages have +** values greater than Key(0) and less than Key(1). All of the keys +** on Ptr(N) and its subpages have values greater than Key(N-1). And +** so forth. +** +** Finding a particular key requires reading O(log(M)) pages from the +** disk where M is the number of entries in the tree. +** +** In this implementation, a single file can hold one or more separate +** BTrees. Each BTree is identified by the index of its root page. The +** key and data for any entry are combined to form the "payload". A +** fixed amount of payload can be carried directly on the database +** page. If the payload is larger than the preset amount then surplus +** bytes are stored on overflow pages. The payload for an entry +** and the preceding pointer are combined to form a "Cell". Each +** page has a small header which contains the Ptr(N) pointer and other +** information such as the size of key and data. +** +** FORMAT DETAILS +** +** The file is divided into pages. The first page is called page 1, +** the second is page 2, and so forth. A page number of zero indicates +** "no such page". The page size can be any power of 2 between 512 and 65536. +** Each page can be either a btree page, a freelist page, an overflow +** page, or a pointer-map page. +** +** The first page is always a btree page. The first 100 bytes of the first +** page contain a special header (the "file header") that describes the file. +** The format of the file header is as follows: +** +** OFFSET SIZE DESCRIPTION +** 0 16 Header string: "SQLite format 3\000" +** 16 2 Page size in bytes. (1 means 65536) +** 18 1 File format write version +** 19 1 File format read version +** 20 1 Bytes of unused space at the end of each page +** 21 1 Max embedded payload fraction (must be 64) +** 22 1 Min embedded payload fraction (must be 32) +** 23 1 Min leaf payload fraction (must be 32) +** 24 4 File change counter +** 28 4 Reserved for future use +** 32 4 First freelist page +** 36 4 Number of freelist pages in the file +** 40 60 15 4-byte meta values passed to higher layers +** +** 40 4 Schema cookie +** 44 4 File format of schema layer +** 48 4 Size of page cache +** 52 4 Largest root-page (auto/incr_vacuum) +** 56 4 1=UTF-8 2=UTF16le 3=UTF16be +** 60 4 User version +** 64 4 Incremental vacuum mode +** 68 4 Application-ID +** 72 20 unused +** 92 4 The version-valid-for number +** 96 4 SQLITE_VERSION_NUMBER +** +** All of the integer values are big-endian (most significant byte first). +** +** The file change counter is incremented when the database is changed +** This counter allows other processes to know when the file has changed +** and thus when they need to flush their cache. +** +** The max embedded payload fraction is the amount of the total usable +** space in a page that can be consumed by a single cell for standard +** B-tree (non-LEAFDATA) tables. A value of 255 means 100%. The default +** is to limit the maximum cell size so that at least 4 cells will fit +** on one page. Thus the default max embedded payload fraction is 64. +** +** If the payload for a cell is larger than the max payload, then extra +** payload is spilled to overflow pages. Once an overflow page is allocated, +** as many bytes as possible are moved into the overflow pages without letting +** the cell size drop below the min embedded payload fraction. +** +** The min leaf payload fraction is like the min embedded payload fraction +** except that it applies to leaf nodes in a LEAFDATA tree. The maximum +** payload fraction for a LEAFDATA tree is always 100% (or 255) and it +** not specified in the header. +** +** Each btree pages is divided into three sections: The header, the +** cell pointer array, and the cell content area. Page 1 also has a 100-byte +** file header that occurs before the page header. +** +** |----------------| +** | file header | 100 bytes. Page 1 only. +** |----------------| +** | page header | 8 bytes for leaves. 12 bytes for interior nodes +** |----------------| +** | cell pointer | | 2 bytes per cell. Sorted order. +** | array | | Grows downward +** | | v +** |----------------| +** | unallocated | +** | space | +** |----------------| ^ Grows upwards +** | cell content | | Arbitrary order interspersed with freeblocks. +** | area | | and free space fragments. +** |----------------| +** +** The page headers looks like this: +** +** OFFSET SIZE DESCRIPTION +** 0 1 Flags. 1: intkey, 2: zerodata, 4: leafdata, 8: leaf +** 1 2 byte offset to the first freeblock +** 3 2 number of cells on this page +** 5 2 first byte of the cell content area +** 7 1 number of fragmented free bytes +** 8 4 Right child (the Ptr(N) value). Omitted on leaves. +** +** The flags define the format of this btree page. The leaf flag means that +** this page has no children. The zerodata flag means that this page carries +** only keys and no data. The intkey flag means that the key is an integer +** which is stored in the key size entry of the cell header rather than in +** the payload area. +** +** The cell pointer array begins on the first byte after the page header. +** The cell pointer array contains zero or more 2-byte numbers which are +** offsets from the beginning of the page to the cell content in the cell +** content area. The cell pointers occur in sorted order. The system strives +** to keep free space after the last cell pointer so that new cells can +** be easily added without having to defragment the page. +** +** Cell content is stored at the very end of the page and grows toward the +** beginning of the page. +** +** Unused space within the cell content area is collected into a linked list of +** freeblocks. Each freeblock is at least 4 bytes in size. The byte offset +** to the first freeblock is given in the header. Freeblocks occur in +** increasing order. Because a freeblock must be at least 4 bytes in size, +** any group of 3 or fewer unused bytes in the cell content area cannot +** exist on the freeblock chain. A group of 3 or fewer free bytes is called +** a fragment. The total number of bytes in all fragments is recorded. +** in the page header at offset 7. +** +** SIZE DESCRIPTION +** 2 Byte offset of the next freeblock +** 2 Bytes in this freeblock +** +** Cells are of variable length. Cells are stored in the cell content area at +** the end of the page. Pointers to the cells are in the cell pointer array +** that immediately follows the page header. Cells is not necessarily +** contiguous or in order, but cell pointers are contiguous and in order. +** +** Cell content makes use of variable length integers. A variable +** length integer is 1 to 9 bytes where the lower 7 bits of each +** byte are used. The integer consists of all bytes that have bit 8 set and +** the first byte with bit 8 clear. The most significant byte of the integer +** appears first. A variable-length integer may not be more than 9 bytes long. +** As a special case, all 8 bytes of the 9th byte are used as data. This +** allows a 64-bit integer to be encoded in 9 bytes. +** +** 0x00 becomes 0x00000000 +** 0x7f becomes 0x0000007f +** 0x81 0x00 becomes 0x00000080 +** 0x82 0x00 becomes 0x00000100 +** 0x80 0x7f becomes 0x0000007f +** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678 +** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081 +** +** Variable length integers are used for rowids and to hold the number of +** bytes of key and data in a btree cell. +** +** The content of a cell looks like this: +** +** SIZE DESCRIPTION +** 4 Page number of the left child. Omitted if leaf flag is set. +** var Number of bytes of data. Omitted if the zerodata flag is set. +** var Number of bytes of key. Or the key itself if intkey flag is set. +** * Payload +** 4 First page of the overflow chain. Omitted if no overflow +** +** Overflow pages form a linked list. Each page except the last is completely +** filled with data (pagesize - 4 bytes). The last page can have as little +** as 1 byte of data. +** +** SIZE DESCRIPTION +** 4 Page number of next overflow page +** * Data +** +** Freelist pages come in two subtypes: trunk pages and leaf pages. The +** file header points to the first in a linked list of trunk page. Each trunk +** page points to multiple leaf pages. The content of a leaf page is +** unspecified. A trunk page looks like this: +** +** SIZE DESCRIPTION +** 4 Page number of next trunk page +** 4 Number of leaf pointers on this page +** * zero or more pages numbers of leaves +*/ +/* #include "sqliteInt.h" */ + + +/* The following value is the maximum cell size assuming a maximum page +** size give above. +*/ +#define MX_CELL_SIZE(pBt) ((int)(pBt->pageSize-8)) + +/* The maximum number of cells on a single page of the database. This +** assumes a minimum cell size of 6 bytes (4 bytes for the cell itself +** plus 2 bytes for the index to the cell in the page header). Such +** small cells will be rare, but they are possible. +*/ +#define MX_CELL(pBt) ((pBt->pageSize-8)/6) + +/* Forward declarations */ +typedef struct MemPage MemPage; +typedef struct BtLock BtLock; +typedef struct CellInfo CellInfo; + +/* +** This is a magic string that appears at the beginning of every +** SQLite database in order to identify the file as a real database. +** +** You can change this value at compile-time by specifying a +** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The +** header must be exactly 16 bytes including the zero-terminator so +** the string itself should be 15 characters long. If you change +** the header, then your custom library will not be able to read +** databases generated by the standard tools and the standard tools +** will not be able to read databases created by your custom library. +*/ +#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */ +# define SQLITE_FILE_HEADER "SQLite format 3" +#endif + +/* +** Page type flags. An ORed combination of these flags appear as the +** first byte of on-disk image of every BTree page. +*/ +#define PTF_INTKEY 0x01 +#define PTF_ZERODATA 0x02 +#define PTF_LEAFDATA 0x04 +#define PTF_LEAF 0x08 + +/* +** As each page of the file is loaded into memory, an instance of the following +** structure is appended and initialized to zero. This structure stores +** information about the page that is decoded from the raw file page. +** +** The pParent field points back to the parent page. This allows us to +** walk up the BTree from any leaf to the root. Care must be taken to +** unref() the parent page pointer when this page is no longer referenced. +** The pageDestructor() routine handles that chore. +** +** Access to all fields of this structure is controlled by the mutex +** stored in MemPage.pBt->mutex. +*/ +struct MemPage { + u8 isInit; /* True if previously initialized. MUST BE FIRST! */ + u8 nOverflow; /* Number of overflow cell bodies in aCell[] */ + u8 intKey; /* True if table b-trees. False for index b-trees */ + u8 intKeyLeaf; /* True if the leaf of an intKey table */ + u8 noPayload; /* True if internal intKey page (thus w/o data) */ + u8 leaf; /* True if a leaf page */ + u8 hdrOffset; /* 100 for page 1. 0 otherwise */ + u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */ + u8 max1bytePayload; /* min(maxLocal,127) */ + u8 bBusy; /* Prevent endless loops on corrupt database files */ + u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */ + u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */ + u16 cellOffset; /* Index in aData of first cell pointer */ + u16 nFree; /* Number of free bytes on the page */ + u16 nCell; /* Number of cells on this page, local and ovfl */ + u16 maskPage; /* Mask for page offset */ + u16 aiOvfl[5]; /* Insert the i-th overflow cell before the aiOvfl-th + ** non-overflow cell */ + u8 *apOvfl[5]; /* Pointers to the body of overflow cells */ + BtShared *pBt; /* Pointer to BtShared that this page is part of */ + u8 *aData; /* Pointer to disk image of the page data */ + u8 *aDataEnd; /* One byte past the end of usable data */ + u8 *aCellIdx; /* The cell index area */ + u8 *aDataOfst; /* Same as aData for leaves. aData+4 for interior */ + DbPage *pDbPage; /* Pager page handle */ + u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */ + void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */ + Pgno pgno; /* Page number for this page */ +}; + +/* +** The in-memory image of a disk page has the auxiliary information appended +** to the end. EXTRA_SIZE is the number of bytes of space needed to hold +** that extra information. +*/ +#define EXTRA_SIZE sizeof(MemPage) + +/* +** A linked list of the following structures is stored at BtShared.pLock. +** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor +** is opened on the table with root page BtShared.iTable. Locks are removed +** from this list when a transaction is committed or rolled back, or when +** a btree handle is closed. +*/ +struct BtLock { + Btree *pBtree; /* Btree handle holding this lock */ + Pgno iTable; /* Root page of table */ + u8 eLock; /* READ_LOCK or WRITE_LOCK */ + BtLock *pNext; /* Next in BtShared.pLock list */ +}; + +/* Candidate values for BtLock.eLock */ +#define READ_LOCK 1 +#define WRITE_LOCK 2 + +/* A Btree handle +** +** A database connection contains a pointer to an instance of +** this object for every database file that it has open. This structure +** is opaque to the database connection. The database connection cannot +** see the internals of this structure and only deals with pointers to +** this structure. +** +** For some database files, the same underlying database cache might be +** shared between multiple connections. In that case, each connection +** has it own instance of this object. But each instance of this object +** points to the same BtShared object. The database cache and the +** schema associated with the database file are all contained within +** the BtShared object. +** +** All fields in this structure are accessed under sqlite3.mutex. +** The pBt pointer itself may not be changed while there exists cursors +** in the referenced BtShared that point back to this Btree since those +** cursors have to go through this Btree to find their BtShared and +** they often do so without holding sqlite3.mutex. +*/ +struct Btree { + sqlite3 *db; /* The database connection holding this btree */ + BtShared *pBt; /* Sharable content of this btree */ + u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ + u8 sharable; /* True if we can share pBt with another db */ + u8 locked; /* True if db currently has pBt locked */ + u8 hasIncrblobCur; /* True if there are one or more Incrblob cursors */ + int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ + int nBackup; /* Number of backup operations reading this btree */ + u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */ + Btree *pNext; /* List of other sharable Btrees from the same db */ + Btree *pPrev; /* Back pointer of the same list */ +#ifndef SQLITE_OMIT_SHARED_CACHE + BtLock lock; /* Object used to lock page 1 */ +#endif +}; + +/* +** Btree.inTrans may take one of the following values. +** +** If the shared-data extension is enabled, there may be multiple users +** of the Btree structure. At most one of these may open a write transaction, +** but any number may have active read transactions. +*/ +#define TRANS_NONE 0 +#define TRANS_READ 1 +#define TRANS_WRITE 2 + +/* +** An instance of this object represents a single database file. +** +** A single database file can be in use at the same time by two +** or more database connections. When two or more connections are +** sharing the same database file, each connection has it own +** private Btree object for the file and each of those Btrees points +** to this one BtShared object. BtShared.nRef is the number of +** connections currently sharing this database file. +** +** Fields in this structure are accessed under the BtShared.mutex +** mutex, except for nRef and pNext which are accessed under the +** global SQLITE_MUTEX_STATIC_MASTER mutex. The pPager field +** may not be modified once it is initially set as long as nRef>0. +** The pSchema field may be set once under BtShared.mutex and +** thereafter is unchanged as long as nRef>0. +** +** isPending: +** +** If a BtShared client fails to obtain a write-lock on a database +** table (because there exists one or more read-locks on the table), +** the shared-cache enters 'pending-lock' state and isPending is +** set to true. +** +** The shared-cache leaves the 'pending lock' state when either of +** the following occur: +** +** 1) The current writer (BtShared.pWriter) concludes its transaction, OR +** 2) The number of locks held by other connections drops to zero. +** +** while in the 'pending-lock' state, no connection may start a new +** transaction. +** +** This feature is included to help prevent writer-starvation. +*/ +struct BtShared { + Pager *pPager; /* The page cache */ + sqlite3 *db; /* Database connection currently using this Btree */ + BtCursor *pCursor; /* A list of all open cursors */ + MemPage *pPage1; /* First page of the database */ + u8 openFlags; /* Flags to sqlite3BtreeOpen() */ +#ifndef SQLITE_OMIT_AUTOVACUUM + u8 autoVacuum; /* True if auto-vacuum is enabled */ + u8 incrVacuum; /* True if incr-vacuum is enabled */ + u8 bDoTruncate; /* True to truncate db on commit */ +#endif + u8 inTransaction; /* Transaction state */ + u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */ +#ifdef SQLITE_HAS_CODEC + u8 optimalReserve; /* Desired amount of reserved space per page */ +#endif + u16 btsFlags; /* Boolean parameters. See BTS_* macros below */ + u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */ + u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */ + u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */ + u16 minLeaf; /* Minimum local payload in a LEAFDATA table */ + u32 pageSize; /* Total number of bytes on a page */ + u32 usableSize; /* Number of usable bytes on each page */ + int nTransaction; /* Number of open transactions (read + write) */ + u32 nPage; /* Number of pages in the database */ + void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */ + void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ + sqlite3_mutex *mutex; /* Non-recursive mutex required to access this object */ + Bitvec *pHasContent; /* Set of pages moved to free-list this transaction */ +#ifndef SQLITE_OMIT_SHARED_CACHE + int nRef; /* Number of references to this structure */ + BtShared *pNext; /* Next on a list of sharable BtShared structs */ + BtLock *pLock; /* List of locks held on this shared-btree struct */ + Btree *pWriter; /* Btree with currently open write transaction */ +#endif + u8 *pTmpSpace; /* Temp space sufficient to hold a single cell */ +}; + +/* +** Allowed values for BtShared.btsFlags +*/ +#define BTS_READ_ONLY 0x0001 /* Underlying file is readonly */ +#define BTS_PAGESIZE_FIXED 0x0002 /* Page size can no longer be changed */ +#define BTS_SECURE_DELETE 0x0004 /* PRAGMA secure_delete is enabled */ +#define BTS_INITIALLY_EMPTY 0x0008 /* Database was empty at trans start */ +#define BTS_NO_WAL 0x0010 /* Do not open write-ahead-log files */ +#define BTS_EXCLUSIVE 0x0020 /* pWriter has an exclusive lock */ +#define BTS_PENDING 0x0040 /* Waiting for read-locks to clear */ + +/* +** An instance of the following structure is used to hold information +** about a cell. The parseCellPtr() function fills in this structure +** based on information extract from the raw disk page. +*/ +struct CellInfo { + i64 nKey; /* The key for INTKEY tables, or nPayload otherwise */ + u8 *pPayload; /* Pointer to the start of payload */ + u32 nPayload; /* Bytes of payload */ + u16 nLocal; /* Amount of payload held locally, not on overflow */ + u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */ + u16 nSize; /* Size of the cell content on the main b-tree page */ +}; + +/* +** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than +** this will be declared corrupt. This value is calculated based on a +** maximum database size of 2^31 pages a minimum fanout of 2 for a +** root-node and 3 for all other internal nodes. +** +** If a tree that appears to be taller than this is encountered, it is +** assumed that the database is corrupt. +*/ +#define BTCURSOR_MAX_DEPTH 20 + +/* +** A cursor is a pointer to a particular entry within a particular +** b-tree within a database file. +** +** The entry is identified by its MemPage and the index in +** MemPage.aCell[] of the entry. +** +** A single database file can be shared by two more database connections, +** but cursors cannot be shared. Each cursor is associated with a +** particular database connection identified BtCursor.pBtree.db. +** +** Fields in this structure are accessed under the BtShared.mutex +** found at self->pBt->mutex. +** +** skipNext meaning: +** eState==SKIPNEXT && skipNext>0: Next sqlite3BtreeNext() is no-op. +** eState==SKIPNEXT && skipNext<0: Next sqlite3BtreePrevious() is no-op. +** eState==FAULT: Cursor fault with skipNext as error code. +*/ +struct BtCursor { + Btree *pBtree; /* The Btree to which this cursor belongs */ + BtShared *pBt; /* The BtShared this cursor points to */ + BtCursor *pNext; /* Forms a linked list of all cursors */ + Pgno *aOverflow; /* Cache of overflow page locations */ + CellInfo info; /* A parse of the cell we are pointing at */ + i64 nKey; /* Size of pKey, or last integer key */ + void *pKey; /* Saved key that was cursor last known position */ + Pgno pgnoRoot; /* The root page of this tree */ + int nOvflAlloc; /* Allocated size of aOverflow[] array */ + int skipNext; /* Prev() is noop if negative. Next() is noop if positive. + ** Error code if eState==CURSOR_FAULT */ + u8 curFlags; /* zero or more BTCF_* flags defined below */ + u8 curPagerFlags; /* Flags to send to sqlite3PagerAcquire() */ + u8 eState; /* One of the CURSOR_XXX constants (see below) */ + u8 hints; /* As configured by CursorSetHints() */ + /* All fields above are zeroed when the cursor is allocated. See + ** sqlite3BtreeCursorZero(). Fields that follow must be manually + ** initialized. */ + i8 iPage; /* Index of current page in apPage */ + u8 curIntKey; /* Value of apPage[0]->intKey */ + struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ + void *padding1; /* Make object size a multiple of 16 */ + u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */ + MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ +}; + +/* +** Legal values for BtCursor.curFlags +*/ +#define BTCF_WriteFlag 0x01 /* True if a write cursor */ +#define BTCF_ValidNKey 0x02 /* True if info.nKey is valid */ +#define BTCF_ValidOvfl 0x04 /* True if aOverflow is valid */ +#define BTCF_AtLast 0x08 /* Cursor is pointing ot the last entry */ +#define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */ +#define BTCF_Multiple 0x20 /* Maybe another cursor on the same btree */ + +/* +** Potential values for BtCursor.eState. +** +** CURSOR_INVALID: +** Cursor does not point to a valid entry. This can happen (for example) +** because the table is empty or because BtreeCursorFirst() has not been +** called. +** +** CURSOR_VALID: +** Cursor points to a valid entry. getPayload() etc. may be called. +** +** CURSOR_SKIPNEXT: +** Cursor is valid except that the Cursor.skipNext field is non-zero +** indicating that the next sqlite3BtreeNext() or sqlite3BtreePrevious() +** operation should be a no-op. +** +** CURSOR_REQUIRESEEK: +** The table that this cursor was opened on still exists, but has been +** modified since the cursor was last used. The cursor position is saved +** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in +** this state, restoreCursorPosition() can be called to attempt to +** seek the cursor to the saved position. +** +** CURSOR_FAULT: +** An unrecoverable error (an I/O error or a malloc failure) has occurred +** on a different connection that shares the BtShared cache with this +** cursor. The error has left the cache in an inconsistent state. +** Do nothing else with this cursor. Any attempt to use the cursor +** should return the error code stored in BtCursor.skipNext +*/ +#define CURSOR_INVALID 0 +#define CURSOR_VALID 1 +#define CURSOR_SKIPNEXT 2 +#define CURSOR_REQUIRESEEK 3 +#define CURSOR_FAULT 4 + +/* +** The database page the PENDING_BYTE occupies. This page is never used. +*/ +# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt) + +/* +** These macros define the location of the pointer-map entry for a +** database page. The first argument to each is the number of usable +** bytes on each page of the database (often 1024). The second is the +** page number to look up in the pointer map. +** +** PTRMAP_PAGENO returns the database page number of the pointer-map +** page that stores the required pointer. PTRMAP_PTROFFSET returns +** the offset of the requested map entry. +** +** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page, +** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be +** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements +** this test. +*/ +#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno) +#define PTRMAP_PTROFFSET(pgptrmap, pgno) (5*(pgno-pgptrmap-1)) +#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno)) + +/* +** The pointer map is a lookup table that identifies the parent page for +** each child page in the database file. The parent page is the page that +** contains a pointer to the child. Every page in the database contains +** 0 or 1 parent pages. (In this context 'database page' refers +** to any page that is not part of the pointer map itself.) Each pointer map +** entry consists of a single byte 'type' and a 4 byte parent page number. +** The PTRMAP_XXX identifiers below are the valid types. +** +** The purpose of the pointer map is to facility moving pages from one +** position in the file to another as part of autovacuum. When a page +** is moved, the pointer in its parent must be updated to point to the +** new location. The pointer map is used to locate the parent page quickly. +** +** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not +** used in this case. +** +** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number +** is not used in this case. +** +** PTRMAP_OVERFLOW1: The database page is the first page in a list of +** overflow pages. The page number identifies the page that +** contains the cell with a pointer to this overflow page. +** +** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of +** overflow pages. The page-number identifies the previous +** page in the overflow page list. +** +** PTRMAP_BTREE: The database page is a non-root btree page. The page number +** identifies the parent page in the btree. +*/ +#define PTRMAP_ROOTPAGE 1 +#define PTRMAP_FREEPAGE 2 +#define PTRMAP_OVERFLOW1 3 +#define PTRMAP_OVERFLOW2 4 +#define PTRMAP_BTREE 5 + +/* A bunch of assert() statements to check the transaction state variables +** of handle p (type Btree*) are internally consistent. +*/ +#define btreeIntegrity(p) \ + assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \ + assert( p->pBt->inTransaction>=p->inTrans ); + + +/* +** The ISAUTOVACUUM macro is used within balance_nonroot() to determine +** if the database supports auto-vacuum or not. Because it is used +** within an expression that is an argument to another macro +** (sqliteMallocRaw), it is not possible to use conditional compilation. +** So, this macro is defined instead. +*/ +#ifndef SQLITE_OMIT_AUTOVACUUM +#define ISAUTOVACUUM (pBt->autoVacuum) +#else +#define ISAUTOVACUUM 0 +#endif + + +/* +** This structure is passed around through all the sanity checking routines +** in order to keep track of some global state information. +** +** The aRef[] array is allocated so that there is 1 bit for each page in +** the database. As the integrity-check proceeds, for each page used in +** the database the corresponding bit is set. This allows integrity-check to +** detect pages that are used twice and orphaned pages (both of which +** indicate corruption). +*/ +typedef struct IntegrityCk IntegrityCk; +struct IntegrityCk { + BtShared *pBt; /* The tree being checked out */ + Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ + u8 *aPgRef; /* 1 bit per page in the db (see above) */ + Pgno nPage; /* Number of pages in the database */ + int mxErr; /* Stop accumulating errors when this reaches zero */ + int nErr; /* Number of messages written to zErrMsg so far */ + int mallocFailed; /* A memory allocation error has occurred */ + const char *zPfx; /* Error message prefix */ + int v1, v2; /* Values for up to two %d fields in zPfx */ + StrAccum errMsg; /* Accumulate the error message text here */ + u32 *heap; /* Min-heap used for analyzing cell coverage */ +}; + +/* +** Routines to read or write a two- and four-byte big-endian integer values. +*/ +#define get2byte(x) ((x)[0]<<8 | (x)[1]) +#define put2byte(p,v) ((p)[0] = (u8)((v)>>8), (p)[1] = (u8)(v)) +#define get4byte sqlite3Get4byte +#define put4byte sqlite3Put4byte + +/* +** get2byteAligned(), unlike get2byte(), requires that its argument point to a +** two-byte aligned address. get2bytea() is only used for accessing the +** cell addresses in a btree header. +*/ +#if SQLITE_BYTEORDER==4321 +# define get2byteAligned(x) (*(u16*)(x)) +#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4008000 +# define get2byteAligned(x) __builtin_bswap16(*(u16*)(x)) +#elif SQLITE_BYTEORDER==1234 && defined(_MSC_VER) && _MSC_VER>=1300 +# define get2byteAligned(x) _byteswap_ushort(*(u16*)(x)) +#else +# define get2byteAligned(x) ((x)[0]<<8 | (x)[1]) +#endif + +/************** End of btreeInt.h ********************************************/ +/************** Continuing where we left off in btmutex.c ********************/ +#ifndef SQLITE_OMIT_SHARED_CACHE +#if SQLITE_THREADSAFE + +/* +** Obtain the BtShared mutex associated with B-Tree handle p. Also, +** set BtShared.db to the database handle associated with p and the +** p->locked boolean to true. +*/ +static void lockBtreeMutex(Btree *p){ + assert( p->locked==0 ); + assert( sqlite3_mutex_notheld(p->pBt->mutex) ); + assert( sqlite3_mutex_held(p->db->mutex) ); + + sqlite3_mutex_enter(p->pBt->mutex); + p->pBt->db = p->db; + p->locked = 1; +} + +/* +** Release the BtShared mutex associated with B-Tree handle p and +** clear the p->locked boolean. +*/ +static void SQLITE_NOINLINE unlockBtreeMutex(Btree *p){ + BtShared *pBt = p->pBt; + assert( p->locked==1 ); + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( sqlite3_mutex_held(p->db->mutex) ); + assert( p->db==pBt->db ); + + sqlite3_mutex_leave(pBt->mutex); + p->locked = 0; +} + +/* Forward reference */ +static void SQLITE_NOINLINE btreeLockCarefully(Btree *p); + +/* +** Enter a mutex on the given BTree object. +** +** If the object is not sharable, then no mutex is ever required +** and this routine is a no-op. The underlying mutex is non-recursive. +** But we keep a reference count in Btree.wantToLock so the behavior +** of this interface is recursive. +** +** To avoid deadlocks, multiple Btrees are locked in the same order +** by all database connections. The p->pNext is a list of other +** Btrees belonging to the same database connection as the p Btree +** which need to be locked after p. If we cannot get a lock on +** p, then first unlock all of the others on p->pNext, then wait +** for the lock to become available on p, then relock all of the +** subsequent Btrees that desire a lock. +*/ +SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){ + /* Some basic sanity checking on the Btree. The list of Btrees + ** connected by pNext and pPrev should be in sorted order by + ** Btree.pBt value. All elements of the list should belong to + ** the same connection. Only shared Btrees are on the list. */ + assert( p->pNext==0 || p->pNext->pBt>p->pBt ); + assert( p->pPrev==0 || p->pPrev->pBtpBt ); + assert( p->pNext==0 || p->pNext->db==p->db ); + assert( p->pPrev==0 || p->pPrev->db==p->db ); + assert( p->sharable || (p->pNext==0 && p->pPrev==0) ); + + /* Check for locking consistency */ + assert( !p->locked || p->wantToLock>0 ); + assert( p->sharable || p->wantToLock==0 ); + + /* We should already hold a lock on the database connection */ + assert( sqlite3_mutex_held(p->db->mutex) ); + + /* Unless the database is sharable and unlocked, then BtShared.db + ** should already be set correctly. */ + assert( (p->locked==0 && p->sharable) || p->pBt->db==p->db ); + + if( !p->sharable ) return; + p->wantToLock++; + if( p->locked ) return; + btreeLockCarefully(p); +} + +/* This is a helper function for sqlite3BtreeLock(). By moving +** complex, but seldom used logic, out of sqlite3BtreeLock() and +** into this routine, we avoid unnecessary stack pointer changes +** and thus help the sqlite3BtreeLock() routine to run much faster +** in the common case. +*/ +static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){ + Btree *pLater; + + /* In most cases, we should be able to acquire the lock we + ** want without having to go through the ascending lock + ** procedure that follows. Just be sure not to block. + */ + if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){ + p->pBt->db = p->db; + p->locked = 1; + return; + } + + /* To avoid deadlock, first release all locks with a larger + ** BtShared address. Then acquire our lock. Then reacquire + ** the other BtShared locks that we used to hold in ascending + ** order. + */ + for(pLater=p->pNext; pLater; pLater=pLater->pNext){ + assert( pLater->sharable ); + assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt ); + assert( !pLater->locked || pLater->wantToLock>0 ); + if( pLater->locked ){ + unlockBtreeMutex(pLater); + } + } + lockBtreeMutex(p); + for(pLater=p->pNext; pLater; pLater=pLater->pNext){ + if( pLater->wantToLock ){ + lockBtreeMutex(pLater); + } + } +} + + +/* +** Exit the recursive mutex on a Btree. +*/ +SQLITE_PRIVATE void sqlite3BtreeLeave(Btree *p){ + assert( sqlite3_mutex_held(p->db->mutex) ); + if( p->sharable ){ + assert( p->wantToLock>0 ); + p->wantToLock--; + if( p->wantToLock==0 ){ + unlockBtreeMutex(p); + } + } +} + +#ifndef NDEBUG +/* +** Return true if the BtShared mutex is held on the btree, or if the +** B-Tree is not marked as sharable. +** +** This routine is used only from within assert() statements. +*/ +SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){ + assert( p->sharable==0 || p->locked==0 || p->wantToLock>0 ); + assert( p->sharable==0 || p->locked==0 || p->db==p->pBt->db ); + assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->pBt->mutex) ); + assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->db->mutex) ); + + return (p->sharable==0 || p->locked); +} +#endif + + +#ifndef SQLITE_OMIT_INCRBLOB +/* +** Enter and leave a mutex on a Btree given a cursor owned by that +** Btree. These entry points are used by incremental I/O and can be +** omitted if that module is not used. +*/ +SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor *pCur){ + sqlite3BtreeEnter(pCur->pBtree); +} +SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){ + sqlite3BtreeLeave(pCur->pBtree); +} +#endif /* SQLITE_OMIT_INCRBLOB */ + + +/* +** Enter the mutex on every Btree associated with a database +** connection. This is needed (for example) prior to parsing +** a statement since we will be comparing table and column names +** against all schemas and we do not want those schemas being +** reset out from under us. +** +** There is a corresponding leave-all procedures. +** +** Enter the mutexes in accending order by BtShared pointer address +** to avoid the possibility of deadlock when two threads with +** two or more btrees in common both try to lock all their btrees +** at the same instant. +*/ +SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ + int i; + Btree *p; + assert( sqlite3_mutex_held(db->mutex) ); + for(i=0; inDb; i++){ + p = db->aDb[i].pBt; + if( p ) sqlite3BtreeEnter(p); + } +} +SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){ + int i; + Btree *p; + assert( sqlite3_mutex_held(db->mutex) ); + for(i=0; inDb; i++){ + p = db->aDb[i].pBt; + if( p ) sqlite3BtreeLeave(p); + } +} + +/* +** Return true if a particular Btree requires a lock. Return FALSE if +** no lock is ever required since it is not sharable. +*/ +SQLITE_PRIVATE int sqlite3BtreeSharable(Btree *p){ + return p->sharable; +} + +#ifndef NDEBUG +/* +** Return true if the current thread holds the database connection +** mutex and all required BtShared mutexes. +** +** This routine is used inside assert() statements only. +*/ +SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){ + int i; + if( !sqlite3_mutex_held(db->mutex) ){ + return 0; + } + for(i=0; inDb; i++){ + Btree *p; + p = db->aDb[i].pBt; + if( p && p->sharable && + (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){ + return 0; + } + } + return 1; +} +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* +** Return true if the correct mutexes are held for accessing the +** db->aDb[iDb].pSchema structure. The mutexes required for schema +** access are: +** +** (1) The mutex on db +** (2) if iDb!=1, then the mutex on db->aDb[iDb].pBt. +** +** If pSchema is not NULL, then iDb is computed from pSchema and +** db using sqlite3SchemaToIndex(). +*/ +SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){ + Btree *p; + assert( db!=0 ); + if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema); + assert( iDb>=0 && iDbnDb ); + if( !sqlite3_mutex_held(db->mutex) ) return 0; + if( iDb==1 ) return 1; + p = db->aDb[iDb].pBt; + assert( p!=0 ); + return p->sharable==0 || p->locked==1; +} +#endif /* NDEBUG */ + +#else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */ +/* +** The following are special cases for mutex enter routines for use +** in single threaded applications that use shared cache. Except for +** these two routines, all mutex operations are no-ops in that case and +** are null #defines in btree.h. +** +** If shared cache is disabled, then all btree mutex routines, including +** the ones below, are no-ops and are null #defines in btree.h. +*/ + +SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){ + p->pBt->db = p->db; +} +SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ + int i; + for(i=0; inDb; i++){ + Btree *p = db->aDb[i].pBt; + if( p ){ + p->pBt->db = p->db; + } + } +} +#endif /* if SQLITE_THREADSAFE */ +#endif /* ifndef SQLITE_OMIT_SHARED_CACHE */ + +/************** End of btmutex.c *********************************************/ +/************** Begin file btree.c *******************************************/ +/* +** 2004 April 6 +** +** 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 an external (disk-based) database using BTrees. +** See the header comment on "btreeInt.h" for additional information. +** Including a description of file format and an overview of operation. +*/ +/* #include "btreeInt.h" */ + +/* +** The header string that appears at the beginning of every +** SQLite database. +*/ +static const char zMagicHeader[] = SQLITE_FILE_HEADER; + +/* +** Set this global variable to 1 to enable tracing using the TRACE +** macro. +*/ +#if 0 +int sqlite3BtreeTrace=1; /* True to enable tracing */ +# define TRACE(X) if(sqlite3BtreeTrace){printf X;fflush(stdout);} +#else +# define TRACE(X) +#endif + +/* +** Extract a 2-byte big-endian integer from an array of unsigned bytes. +** But if the value is zero, make it 65536. +** +** This routine is used to extract the "offset to cell content area" value +** from the header of a btree page. If the page size is 65536 and the page +** is empty, the offset should be 65536, but the 2-byte value stores zero. +** This routine makes the necessary adjustment to 65536. +*/ +#define get2byteNotZero(X) (((((int)get2byte(X))-1)&0xffff)+1) + +/* +** Values passed as the 5th argument to allocateBtreePage() +*/ +#define BTALLOC_ANY 0 /* Allocate any page */ +#define BTALLOC_EXACT 1 /* Allocate exact page if possible */ +#define BTALLOC_LE 2 /* Allocate any page <= the parameter */ + +/* +** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not +** defined, or 0 if it is. For example: +** +** bIncrVacuum = IfNotOmitAV(pBtShared->incrVacuum); +*/ +#ifndef SQLITE_OMIT_AUTOVACUUM +#define IfNotOmitAV(expr) (expr) +#else +#define IfNotOmitAV(expr) 0 +#endif + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** A list of BtShared objects that are eligible for participation +** in shared cache. This variable has file scope during normal builds, +** but the test harness needs to access it so we make it global for +** test builds. +** +** Access to this variable is protected by SQLITE_MUTEX_STATIC_MASTER. +*/ +#ifdef SQLITE_TEST +SQLITE_PRIVATE BtShared *SQLITE_WSD sqlite3SharedCacheList = 0; +#else +static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0; +#endif +#endif /* SQLITE_OMIT_SHARED_CACHE */ + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Enable or disable the shared pager and schema features. +** +** This routine has no effect on existing database connections. +** The shared cache setting effects only future calls to +** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2(). +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int enable){ + sqlite3GlobalConfig.sharedCacheEnabled = enable; + return SQLITE_OK; +} +#endif + + + +#ifdef SQLITE_OMIT_SHARED_CACHE + /* + ** The functions querySharedCacheTableLock(), setSharedCacheTableLock(), + ** and clearAllSharedCacheTableLocks() + ** manipulate entries in the BtShared.pLock linked list used to store + ** shared-cache table level locks. If the library is compiled with the + ** shared-cache feature disabled, then there is only ever one user + ** of each BtShared structure and so this locking is not necessary. + ** So define the lock related functions as no-ops. + */ + #define querySharedCacheTableLock(a,b,c) SQLITE_OK + #define setSharedCacheTableLock(a,b,c) SQLITE_OK + #define clearAllSharedCacheTableLocks(a) + #define downgradeAllSharedCacheTableLocks(a) + #define hasSharedCacheTableLock(a,b,c,d) 1 + #define hasReadConflicts(a, b) 0 +#endif + +#ifndef SQLITE_OMIT_SHARED_CACHE + +#ifdef SQLITE_DEBUG +/* +**** This function is only used as part of an assert() statement. *** +** +** Check to see if pBtree holds the required locks to read or write to the +** table with root page iRoot. Return 1 if it does and 0 if not. +** +** For example, when writing to a table with root-page iRoot via +** Btree connection pBtree: +** +** assert( hasSharedCacheTableLock(pBtree, iRoot, 0, WRITE_LOCK) ); +** +** When writing to an index that resides in a sharable database, the +** caller should have first obtained a lock specifying the root page of +** the corresponding table. This makes things a bit more complicated, +** as this module treats each table as a separate structure. To determine +** the table corresponding to the index being written, this +** function has to search through the database schema. +** +** Instead of a lock on the table/index rooted at page iRoot, the caller may +** hold a write-lock on the schema table (root page 1). This is also +** acceptable. +*/ +static int hasSharedCacheTableLock( + Btree *pBtree, /* Handle that must hold lock */ + Pgno iRoot, /* Root page of b-tree */ + int isIndex, /* True if iRoot is the root of an index b-tree */ + int eLockType /* Required lock type (READ_LOCK or WRITE_LOCK) */ +){ + Schema *pSchema = (Schema *)pBtree->pBt->pSchema; + Pgno iTab = 0; + BtLock *pLock; + + /* If this database is not shareable, or if the client is reading + ** and has the read-uncommitted flag set, then no lock is required. + ** Return true immediately. + */ + if( (pBtree->sharable==0) + || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommitted)) + ){ + return 1; + } + + /* If the client is reading or writing an index and the schema is + ** not loaded, then it is too difficult to actually check to see if + ** the correct locks are held. So do not bother - just return true. + ** This case does not come up very often anyhow. + */ + if( isIndex && (!pSchema || (pSchema->schemaFlags&DB_SchemaLoaded)==0) ){ + return 1; + } + + /* Figure out the root-page that the lock should be held on. For table + ** b-trees, this is just the root page of the b-tree being read or + ** written. For index b-trees, it is the root page of the associated + ** table. */ + if( isIndex ){ + HashElem *p; + for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){ + Index *pIdx = (Index *)sqliteHashData(p); + if( pIdx->tnum==(int)iRoot ){ + if( iTab ){ + /* Two or more indexes share the same root page. There must + ** be imposter tables. So just return true. The assert is not + ** useful in that case. */ + return 1; + } + iTab = pIdx->pTable->tnum; + } + } + }else{ + iTab = iRoot; + } + + /* Search for the required lock. Either a write-lock on root-page iTab, a + ** write-lock on the schema table, or (if the client is reading) a + ** read-lock on iTab will suffice. Return 1 if any of these are found. */ + for(pLock=pBtree->pBt->pLock; pLock; pLock=pLock->pNext){ + if( pLock->pBtree==pBtree + && (pLock->iTable==iTab || (pLock->eLock==WRITE_LOCK && pLock->iTable==1)) + && pLock->eLock>=eLockType + ){ + return 1; + } + } + + /* Failed to find the required lock. */ + return 0; +} +#endif /* SQLITE_DEBUG */ + +#ifdef SQLITE_DEBUG +/* +**** This function may be used as part of assert() statements only. **** +** +** Return true if it would be illegal for pBtree to write into the +** table or index rooted at iRoot because other shared connections are +** simultaneously reading that same table or index. +** +** It is illegal for pBtree to write if some other Btree object that +** shares the same BtShared object is currently reading or writing +** the iRoot table. Except, if the other Btree object has the +** read-uncommitted flag set, then it is OK for the other object to +** have a read cursor. +** +** For example, before writing to any part of the table or index +** rooted at page iRoot, one should call: +** +** assert( !hasReadConflicts(pBtree, iRoot) ); +*/ +static int hasReadConflicts(Btree *pBtree, Pgno iRoot){ + BtCursor *p; + for(p=pBtree->pBt->pCursor; p; p=p->pNext){ + if( p->pgnoRoot==iRoot + && p->pBtree!=pBtree + && 0==(p->pBtree->db->flags & SQLITE_ReadUncommitted) + ){ + return 1; + } + } + return 0; +} +#endif /* #ifdef SQLITE_DEBUG */ + +/* +** Query to see if Btree handle p may obtain a lock of type eLock +** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return +** SQLITE_OK if the lock may be obtained (by calling +** setSharedCacheTableLock()), or SQLITE_LOCKED if not. +*/ +static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){ + BtShared *pBt = p->pBt; + BtLock *pIter; + + assert( sqlite3BtreeHoldsMutex(p) ); + assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); + assert( p->db!=0 ); + assert( !(p->db->flags&SQLITE_ReadUncommitted)||eLock==WRITE_LOCK||iTab==1 ); + + /* If requesting a write-lock, then the Btree must have an open write + ** transaction on this file. And, obviously, for this to be so there + ** must be an open write transaction on the file itself. + */ + assert( eLock==READ_LOCK || (p==pBt->pWriter && p->inTrans==TRANS_WRITE) ); + assert( eLock==READ_LOCK || pBt->inTransaction==TRANS_WRITE ); + + /* This routine is a no-op if the shared-cache is not enabled */ + if( !p->sharable ){ + return SQLITE_OK; + } + + /* If some other connection is holding an exclusive lock, the + ** requested lock may not be obtained. + */ + if( pBt->pWriter!=p && (pBt->btsFlags & BTS_EXCLUSIVE)!=0 ){ + sqlite3ConnectionBlocked(p->db, pBt->pWriter->db); + return SQLITE_LOCKED_SHAREDCACHE; + } + + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + /* The condition (pIter->eLock!=eLock) in the following if(...) + ** statement is a simplification of: + ** + ** (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK) + ** + ** since we know that if eLock==WRITE_LOCK, then no other connection + ** may hold a WRITE_LOCK on any table in this file (since there can + ** only be a single writer). + */ + assert( pIter->eLock==READ_LOCK || pIter->eLock==WRITE_LOCK ); + assert( eLock==READ_LOCK || pIter->pBtree==p || pIter->eLock==READ_LOCK); + if( pIter->pBtree!=p && pIter->iTable==iTab && pIter->eLock!=eLock ){ + sqlite3ConnectionBlocked(p->db, pIter->pBtree->db); + if( eLock==WRITE_LOCK ){ + assert( p==pBt->pWriter ); + pBt->btsFlags |= BTS_PENDING; + } + return SQLITE_LOCKED_SHAREDCACHE; + } + } + return SQLITE_OK; +} +#endif /* !SQLITE_OMIT_SHARED_CACHE */ + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Add a lock on the table with root-page iTable to the shared-btree used +** by Btree handle p. Parameter eLock must be either READ_LOCK or +** WRITE_LOCK. +** +** This function assumes the following: +** +** (a) The specified Btree object p is connected to a sharable +** database (one with the BtShared.sharable flag set), and +** +** (b) No other Btree objects hold a lock that conflicts +** with the requested lock (i.e. querySharedCacheTableLock() has +** already been called and returned SQLITE_OK). +** +** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM +** is returned if a malloc attempt fails. +*/ +static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){ + BtShared *pBt = p->pBt; + BtLock *pLock = 0; + BtLock *pIter; + + assert( sqlite3BtreeHoldsMutex(p) ); + assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); + assert( p->db!=0 ); + + /* A connection with the read-uncommitted flag set will never try to + ** obtain a read-lock using this function. The only read-lock obtained + ** by a connection in read-uncommitted mode is on the sqlite_master + ** table, and that lock is obtained in BtreeBeginTrans(). */ + assert( 0==(p->db->flags&SQLITE_ReadUncommitted) || eLock==WRITE_LOCK ); + + /* This function should only be called on a sharable b-tree after it + ** has been determined that no other b-tree holds a conflicting lock. */ + assert( p->sharable ); + assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) ); + + /* First search the list for an existing lock on this table. */ + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + if( pIter->iTable==iTable && pIter->pBtree==p ){ + pLock = pIter; + break; + } + } + + /* If the above search did not find a BtLock struct associating Btree p + ** with table iTable, allocate one and link it into the list. + */ + if( !pLock ){ + pLock = (BtLock *)sqlite3MallocZero(sizeof(BtLock)); + if( !pLock ){ + return SQLITE_NOMEM; + } + pLock->iTable = iTable; + pLock->pBtree = p; + pLock->pNext = pBt->pLock; + pBt->pLock = pLock; + } + + /* Set the BtLock.eLock variable to the maximum of the current lock + ** and the requested lock. This means if a write-lock was already held + ** and a read-lock requested, we don't incorrectly downgrade the lock. + */ + assert( WRITE_LOCK>READ_LOCK ); + if( eLock>pLock->eLock ){ + pLock->eLock = eLock; + } + + return SQLITE_OK; +} +#endif /* !SQLITE_OMIT_SHARED_CACHE */ + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Release all the table locks (locks obtained via calls to +** the setSharedCacheTableLock() procedure) held by Btree object p. +** +** This function assumes that Btree p has an open read or write +** transaction. If it does not, then the BTS_PENDING flag +** may be incorrectly cleared. +*/ +static void clearAllSharedCacheTableLocks(Btree *p){ + BtShared *pBt = p->pBt; + BtLock **ppIter = &pBt->pLock; + + assert( sqlite3BtreeHoldsMutex(p) ); + assert( p->sharable || 0==*ppIter ); + assert( p->inTrans>0 ); + + while( *ppIter ){ + BtLock *pLock = *ppIter; + assert( (pBt->btsFlags & BTS_EXCLUSIVE)==0 || pBt->pWriter==pLock->pBtree ); + assert( pLock->pBtree->inTrans>=pLock->eLock ); + if( pLock->pBtree==p ){ + *ppIter = pLock->pNext; + assert( pLock->iTable!=1 || pLock==&p->lock ); + if( pLock->iTable!=1 ){ + sqlite3_free(pLock); + } + }else{ + ppIter = &pLock->pNext; + } + } + + assert( (pBt->btsFlags & BTS_PENDING)==0 || pBt->pWriter ); + if( pBt->pWriter==p ){ + pBt->pWriter = 0; + pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING); + }else if( pBt->nTransaction==2 ){ + /* This function is called when Btree p is concluding its + ** transaction. If there currently exists a writer, and p is not + ** that writer, then the number of locks held by connections other + ** than the writer must be about to drop to zero. In this case + ** set the BTS_PENDING flag to 0. + ** + ** If there is not currently a writer, then BTS_PENDING must + ** be zero already. So this next line is harmless in that case. + */ + pBt->btsFlags &= ~BTS_PENDING; + } +} + +/* +** This function changes all write-locks held by Btree p into read-locks. +*/ +static void downgradeAllSharedCacheTableLocks(Btree *p){ + BtShared *pBt = p->pBt; + if( pBt->pWriter==p ){ + BtLock *pLock; + pBt->pWriter = 0; + pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING); + for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){ + assert( pLock->eLock==READ_LOCK || pLock->pBtree==p ); + pLock->eLock = READ_LOCK; + } + } +} + +#endif /* SQLITE_OMIT_SHARED_CACHE */ + +static void releasePage(MemPage *pPage); /* Forward reference */ + +/* +***** This routine is used inside of assert() only **** +** +** Verify that the cursor holds the mutex on its BtShared +*/ +#ifdef SQLITE_DEBUG +static int cursorHoldsMutex(BtCursor *p){ + return sqlite3_mutex_held(p->pBt->mutex); +} +#endif + +/* +** Invalidate the overflow cache of the cursor passed as the first argument. +** on the shared btree structure pBt. +*/ +#define invalidateOverflowCache(pCur) (pCur->curFlags &= ~BTCF_ValidOvfl) + +/* +** Invalidate the overflow page-list cache for all cursors opened +** on the shared btree structure pBt. +*/ +static void invalidateAllOverflowCache(BtShared *pBt){ + BtCursor *p; + assert( sqlite3_mutex_held(pBt->mutex) ); + for(p=pBt->pCursor; p; p=p->pNext){ + invalidateOverflowCache(p); + } +} + +#ifndef SQLITE_OMIT_INCRBLOB +/* +** This function is called before modifying the contents of a table +** to invalidate any incrblob cursors that are open on the +** row or one of the rows being modified. +** +** If argument isClearTable is true, then the entire contents of the +** table is about to be deleted. In this case invalidate all incrblob +** cursors open on any row within the table with root-page pgnoRoot. +** +** Otherwise, if argument isClearTable is false, then the row with +** rowid iRow is being replaced or deleted. In this case invalidate +** only those incrblob cursors open on that specific row. +*/ +static void invalidateIncrblobCursors( + Btree *pBtree, /* The database file to check */ + i64 iRow, /* The rowid that might be changing */ + int isClearTable /* True if all rows are being deleted */ +){ + BtCursor *p; + if( pBtree->hasIncrblobCur==0 ) return; + assert( sqlite3BtreeHoldsMutex(pBtree) ); + pBtree->hasIncrblobCur = 0; + for(p=pBtree->pBt->pCursor; p; p=p->pNext){ + if( (p->curFlags & BTCF_Incrblob)!=0 ){ + pBtree->hasIncrblobCur = 1; + if( isClearTable || p->info.nKey==iRow ){ + p->eState = CURSOR_INVALID; + } + } + } +} + +#else + /* Stub function when INCRBLOB is omitted */ + #define invalidateIncrblobCursors(x,y,z) +#endif /* SQLITE_OMIT_INCRBLOB */ + +/* +** Set bit pgno of the BtShared.pHasContent bitvec. This is called +** when a page that previously contained data becomes a free-list leaf +** page. +** +** The BtShared.pHasContent bitvec exists to work around an obscure +** bug caused by the interaction of two useful IO optimizations surrounding +** free-list leaf pages: +** +** 1) When all data is deleted from a page and the page becomes +** a free-list leaf page, the page is not written to the database +** (as free-list leaf pages contain no meaningful data). Sometimes +** such a page is not even journalled (as it will not be modified, +** why bother journalling it?). +** +** 2) When a free-list leaf page is reused, its content is not read +** from the database or written to the journal file (why should it +** be, if it is not at all meaningful?). +** +** By themselves, these optimizations work fine and provide a handy +** performance boost to bulk delete or insert operations. However, if +** a page is moved to the free-list and then reused within the same +** transaction, a problem comes up. If the page is not journalled when +** it is moved to the free-list and it is also not journalled when it +** is extracted from the free-list and reused, then the original data +** may be lost. In the event of a rollback, it may not be possible +** to restore the database to its original configuration. +** +** The solution is the BtShared.pHasContent bitvec. Whenever a page is +** moved to become a free-list leaf page, the corresponding bit is +** set in the bitvec. Whenever a leaf page is extracted from the free-list, +** optimization 2 above is omitted if the corresponding bit is already +** set in BtShared.pHasContent. The contents of the bitvec are cleared +** at the end of every transaction. +*/ +static int btreeSetHasContent(BtShared *pBt, Pgno pgno){ + int rc = SQLITE_OK; + if( !pBt->pHasContent ){ + assert( pgno<=pBt->nPage ); + pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage); + if( !pBt->pHasContent ){ + rc = SQLITE_NOMEM; + } + } + if( rc==SQLITE_OK && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){ + rc = sqlite3BitvecSet(pBt->pHasContent, pgno); + } + return rc; +} + +/* +** Query the BtShared.pHasContent vector. +** +** This function is called when a free-list leaf page is removed from the +** free-list for reuse. It returns false if it is safe to retrieve the +** page from the pager layer with the 'no-content' flag set. True otherwise. +*/ +static int btreeGetHasContent(BtShared *pBt, Pgno pgno){ + Bitvec *p = pBt->pHasContent; + return (p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTest(p, pgno))); +} + +/* +** Clear (destroy) the BtShared.pHasContent bitvec. This should be +** invoked at the conclusion of each write-transaction. +*/ +static void btreeClearHasContent(BtShared *pBt){ + sqlite3BitvecDestroy(pBt->pHasContent); + pBt->pHasContent = 0; +} + +/* +** Release all of the apPage[] pages for a cursor. +*/ +static void btreeReleaseAllCursorPages(BtCursor *pCur){ + int i; + for(i=0; i<=pCur->iPage; i++){ + releasePage(pCur->apPage[i]); + pCur->apPage[i] = 0; + } + pCur->iPage = -1; +} + + +/* +** Save the current cursor position in the variables BtCursor.nKey +** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. +** +** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID) +** prior to calling this routine. +*/ +static int saveCursorPosition(BtCursor *pCur){ + int rc; + + assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState ); + assert( 0==pCur->pKey ); + assert( cursorHoldsMutex(pCur) ); + + if( pCur->eState==CURSOR_SKIPNEXT ){ + pCur->eState = CURSOR_VALID; + }else{ + pCur->skipNext = 0; + } + rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); + assert( rc==SQLITE_OK ); /* KeySize() cannot fail */ + + /* If this is an intKey table, then the above call to BtreeKeySize() + ** stores the integer key in pCur->nKey. In this case this value is + ** all that is required. Otherwise, if pCur is not open on an intKey + ** table, then malloc space for and store the pCur->nKey bytes of key + ** data. + */ + if( 0==pCur->curIntKey ){ + void *pKey = sqlite3Malloc( pCur->nKey ); + if( pKey ){ + rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey); + if( rc==SQLITE_OK ){ + pCur->pKey = pKey; + }else{ + sqlite3_free(pKey); + } + }else{ + rc = SQLITE_NOMEM; + } + } + assert( !pCur->curIntKey || !pCur->pKey ); + + if( rc==SQLITE_OK ){ + btreeReleaseAllCursorPages(pCur); + pCur->eState = CURSOR_REQUIRESEEK; + } + + invalidateOverflowCache(pCur); + return rc; +} + +/* Forward reference */ +static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*); + +/* +** Save the positions of all cursors (except pExcept) that are open on +** the table with root-page iRoot. "Saving the cursor position" means that +** the location in the btree is remembered in such a way that it can be +** moved back to the same spot after the btree has been modified. This +** routine is called just before cursor pExcept is used to modify the +** table, for example in BtreeDelete() or BtreeInsert(). +** +** If there are two or more cursors on the same btree, then all such +** cursors should have their BTCF_Multiple flag set. The btreeCursor() +** routine enforces that rule. This routine only needs to be called in +** the uncommon case when pExpect has the BTCF_Multiple flag set. +** +** If pExpect!=NULL and if no other cursors are found on the same root-page, +** then the BTCF_Multiple flag on pExpect is cleared, to avoid another +** pointless call to this routine. +** +** Implementation note: This routine merely checks to see if any cursors +** need to be saved. It calls out to saveCursorsOnList() in the (unusual) +** event that cursors are in need to being saved. +*/ +static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ + BtCursor *p; + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pExcept==0 || pExcept->pBt==pBt ); + for(p=pBt->pCursor; p; p=p->pNext){ + if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ) break; + } + if( p ) return saveCursorsOnList(p, iRoot, pExcept); + if( pExcept ) pExcept->curFlags &= ~BTCF_Multiple; + return SQLITE_OK; +} + +/* This helper routine to saveAllCursors does the actual work of saving +** the cursors if and when a cursor is found that actually requires saving. +** The common case is that no cursors need to be saved, so this routine is +** broken out from its caller to avoid unnecessary stack pointer movement. +*/ +static int SQLITE_NOINLINE saveCursorsOnList( + BtCursor *p, /* The first cursor that needs saving */ + Pgno iRoot, /* Only save cursor with this iRoot. Save all if zero */ + BtCursor *pExcept /* Do not save this cursor */ +){ + do{ + if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){ + if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ + int rc = saveCursorPosition(p); + if( SQLITE_OK!=rc ){ + return rc; + } + }else{ + testcase( p->iPage>0 ); + btreeReleaseAllCursorPages(p); + } + } + p = p->pNext; + }while( p ); + return SQLITE_OK; +} + +/* +** Clear the current cursor position. +*/ +SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); + sqlite3_free(pCur->pKey); + pCur->pKey = 0; + pCur->eState = CURSOR_INVALID; +} + +/* +** In this version of BtreeMoveto, pKey is a packed index record +** such as is generated by the OP_MakeRecord opcode. Unpack the +** record and then call BtreeMovetoUnpacked() to do the work. +*/ +static int btreeMoveto( + BtCursor *pCur, /* Cursor open on the btree to be searched */ + const void *pKey, /* Packed key if the btree is an index */ + i64 nKey, /* Integer key for tables. Size of pKey for indices */ + int bias, /* Bias search to the high end */ + int *pRes /* Write search results here */ +){ + int rc; /* Status code */ + UnpackedRecord *pIdxKey; /* Unpacked index key */ + char aSpace[200]; /* Temp space for pIdxKey - to avoid a malloc */ + char *pFree = 0; + + if( pKey ){ + assert( nKey==(i64)(int)nKey ); + pIdxKey = sqlite3VdbeAllocUnpackedRecord( + pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree + ); + if( pIdxKey==0 ) return SQLITE_NOMEM; + sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey); + if( pIdxKey->nField==0 ){ + sqlite3DbFree(pCur->pKeyInfo->db, pFree); + return SQLITE_CORRUPT_BKPT; + } + }else{ + pIdxKey = 0; + } + rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes); + if( pFree ){ + sqlite3DbFree(pCur->pKeyInfo->db, pFree); + } + return rc; +} + +/* +** Restore the cursor to the position it was in (or as close to as possible) +** when saveCursorPosition() was called. Note that this call deletes the +** saved position info stored by saveCursorPosition(), so there can be +** at most one effective restoreCursorPosition() call after each +** saveCursorPosition(). +*/ +static int btreeRestoreCursorPosition(BtCursor *pCur){ + int rc; + int skipNext; + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState>=CURSOR_REQUIRESEEK ); + if( pCur->eState==CURSOR_FAULT ){ + return pCur->skipNext; + } + pCur->eState = CURSOR_INVALID; + rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext); + if( rc==SQLITE_OK ){ + sqlite3_free(pCur->pKey); + pCur->pKey = 0; + assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); + pCur->skipNext |= skipNext; + if( pCur->skipNext && pCur->eState==CURSOR_VALID ){ + pCur->eState = CURSOR_SKIPNEXT; + } + } + return rc; +} + +#define restoreCursorPosition(p) \ + (p->eState>=CURSOR_REQUIRESEEK ? \ + btreeRestoreCursorPosition(p) : \ + SQLITE_OK) + +/* +** Determine whether or not a cursor has moved from the position where +** it was last placed, or has been invalidated for any other reason. +** Cursors can move when the row they are pointing at is deleted out +** from under them, for example. Cursor might also move if a btree +** is rebalanced. +** +** Calling this routine with a NULL cursor pointer returns false. +** +** Use the separate sqlite3BtreeCursorRestore() routine to restore a cursor +** back to where it ought to be if this routine returns true. +*/ +SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur){ + return pCur->eState!=CURSOR_VALID; +} + +/* +** This routine restores a cursor back to its original position after it +** has been moved by some outside activity (such as a btree rebalance or +** a row having been deleted out from under the cursor). +** +** On success, the *pDifferentRow parameter is false if the cursor is left +** pointing at exactly the same row. *pDifferntRow is the row the cursor +** was pointing to has been deleted, forcing the cursor to point to some +** nearby row. +** +** This routine should only be called for a cursor that just returned +** TRUE from sqlite3BtreeCursorHasMoved(). +*/ +SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){ + int rc; + + assert( pCur!=0 ); + assert( pCur->eState!=CURSOR_VALID ); + rc = restoreCursorPosition(pCur); + if( rc ){ + *pDifferentRow = 1; + return rc; + } + if( pCur->eState!=CURSOR_VALID ){ + *pDifferentRow = 1; + }else{ + assert( pCur->skipNext==0 ); + *pDifferentRow = 0; + } + return SQLITE_OK; +} + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** Given a page number of a regular database page, return the page +** number for the pointer-map page that contains the entry for the +** input page number. +** +** Return 0 (not a valid page) for pgno==1 since there is +** no pointer map associated with page 1. The integrity_check logic +** requires that ptrmapPageno(*,1)!=1. +*/ +static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ + int nPagesPerMapPage; + Pgno iPtrMap, ret; + assert( sqlite3_mutex_held(pBt->mutex) ); + if( pgno<2 ) return 0; + nPagesPerMapPage = (pBt->usableSize/5)+1; + iPtrMap = (pgno-2)/nPagesPerMapPage; + ret = (iPtrMap*nPagesPerMapPage) + 2; + if( ret==PENDING_BYTE_PAGE(pBt) ){ + ret++; + } + return ret; +} + +/* +** Write an entry into the pointer map. +** +** This routine updates the pointer map entry for page number 'key' +** so that it maps to type 'eType' and parent page number 'pgno'. +** +** If *pRC is initially non-zero (non-SQLITE_OK) then this routine is +** a no-op. If an error occurs, the appropriate error code is written +** into *pRC. +*/ +static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){ + DbPage *pDbPage; /* The pointer map page */ + u8 *pPtrmap; /* The pointer map data */ + Pgno iPtrmap; /* The pointer map page number */ + int offset; /* Offset in pointer map page */ + int rc; /* Return code from subfunctions */ + + if( *pRC ) return; + + assert( sqlite3_mutex_held(pBt->mutex) ); + /* The master-journal page number must never be used as a pointer map page */ + assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) ); + + assert( pBt->autoVacuum ); + if( key==0 ){ + *pRC = SQLITE_CORRUPT_BKPT; + return; + } + iPtrmap = PTRMAP_PAGENO(pBt, key); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); + if( rc!=SQLITE_OK ){ + *pRC = rc; + return; + } + offset = PTRMAP_PTROFFSET(iPtrmap, key); + if( offset<0 ){ + *pRC = SQLITE_CORRUPT_BKPT; + goto ptrmap_exit; + } + assert( offset <= (int)pBt->usableSize-5 ); + pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); + + if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ + TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); + *pRC= rc = sqlite3PagerWrite(pDbPage); + if( rc==SQLITE_OK ){ + pPtrmap[offset] = eType; + put4byte(&pPtrmap[offset+1], parent); + } + } + +ptrmap_exit: + sqlite3PagerUnref(pDbPage); +} + +/* +** Read an entry from the pointer map. +** +** This routine retrieves the pointer map entry for page 'key', writing +** the type and parent page number to *pEType and *pPgno respectively. +** An error code is returned if something goes wrong, otherwise SQLITE_OK. +*/ +static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ + DbPage *pDbPage; /* The pointer map page */ + int iPtrmap; /* Pointer map page index */ + u8 *pPtrmap; /* Pointer map page data */ + int offset; /* Offset of entry in pointer map */ + int rc; + + assert( sqlite3_mutex_held(pBt->mutex) ); + + iPtrmap = PTRMAP_PAGENO(pBt, key); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); + if( rc!=0 ){ + return rc; + } + pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); + + offset = PTRMAP_PTROFFSET(iPtrmap, key); + if( offset<0 ){ + sqlite3PagerUnref(pDbPage); + return SQLITE_CORRUPT_BKPT; + } + assert( offset <= (int)pBt->usableSize-5 ); + assert( pEType!=0 ); + *pEType = pPtrmap[offset]; + if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); + + sqlite3PagerUnref(pDbPage); + if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT; + return SQLITE_OK; +} + +#else /* if defined SQLITE_OMIT_AUTOVACUUM */ + #define ptrmapPut(w,x,y,z,rc) + #define ptrmapGet(w,x,y,z) SQLITE_OK + #define ptrmapPutOvflPtr(x, y, rc) +#endif + +/* +** Given a btree page and a cell index (0 means the first cell on +** the page, 1 means the second cell, and so forth) return a pointer +** to the cell content. +** +** findCellPastPtr() does the same except it skips past the initial +** 4-byte child pointer found on interior pages, if there is one. +** +** This routine works only for pages that do not contain overflow cells. +*/ +#define findCell(P,I) \ + ((P)->aData + ((P)->maskPage & get2byteAligned(&(P)->aCellIdx[2*(I)]))) +#define findCellPastPtr(P,I) \ + ((P)->aDataOfst + ((P)->maskPage & get2byteAligned(&(P)->aCellIdx[2*(I)]))) + + +/* +** This is common tail processing for btreeParseCellPtr() and +** btreeParseCellPtrIndex() for the case when the cell does not fit entirely +** on a single B-tree page. Make necessary adjustments to the CellInfo +** structure. +*/ +static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow( + MemPage *pPage, /* Page containing the cell */ + u8 *pCell, /* Pointer to the cell text. */ + CellInfo *pInfo /* Fill in this structure */ +){ + /* If the payload will not fit completely on the local page, we have + ** to decide how much to store locally and how much to spill onto + ** overflow pages. The strategy is to minimize the amount of unused + ** space on overflow pages while keeping the amount of local storage + ** in between minLocal and maxLocal. + ** + ** Warning: changing the way overflow payload is distributed in any + ** way will result in an incompatible file format. + */ + int minLocal; /* Minimum amount of payload held locally */ + int maxLocal; /* Maximum amount of payload held locally */ + int surplus; /* Overflow payload available for local storage */ + + minLocal = pPage->minLocal; + maxLocal = pPage->maxLocal; + surplus = minLocal + (pInfo->nPayload - minLocal)%(pPage->pBt->usableSize-4); + testcase( surplus==maxLocal ); + testcase( surplus==maxLocal+1 ); + if( surplus <= maxLocal ){ + pInfo->nLocal = (u16)surplus; + }else{ + pInfo->nLocal = (u16)minLocal; + } + pInfo->iOverflow = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell); + pInfo->nSize = pInfo->iOverflow + 4; +} + +/* +** The following routines are implementations of the MemPage.xParseCell() +** method. +** +** Parse a cell content block and fill in the CellInfo structure. +** +** btreeParseCellPtr() => table btree leaf nodes +** btreeParseCellNoPayload() => table btree internal nodes +** btreeParseCellPtrIndex() => index btree nodes +** +** There is also a wrapper function btreeParseCell() that works for +** all MemPage types and that references the cell by index rather than +** by pointer. +*/ +static void btreeParseCellPtrNoPayload( + MemPage *pPage, /* Page containing the cell */ + u8 *pCell, /* Pointer to the cell text. */ + CellInfo *pInfo /* Fill in this structure */ +){ + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( pPage->leaf==0 ); + assert( pPage->noPayload ); + assert( pPage->childPtrSize==4 ); +#ifndef SQLITE_DEBUG + UNUSED_PARAMETER(pPage); +#endif + pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey); + pInfo->nPayload = 0; + pInfo->nLocal = 0; + pInfo->iOverflow = 0; + pInfo->pPayload = 0; + return; +} +static void btreeParseCellPtr( + MemPage *pPage, /* Page containing the cell */ + u8 *pCell, /* Pointer to the cell text. */ + CellInfo *pInfo /* Fill in this structure */ +){ + u8 *pIter; /* For scanning through pCell */ + u32 nPayload; /* Number of bytes of cell payload */ + u64 iKey; /* Extracted Key value */ + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( pPage->leaf==0 || pPage->leaf==1 ); + assert( pPage->intKeyLeaf || pPage->noPayload ); + assert( pPage->noPayload==0 ); + assert( pPage->intKeyLeaf ); + assert( pPage->childPtrSize==0 ); + pIter = pCell; + + /* The next block of code is equivalent to: + ** + ** pIter += getVarint32(pIter, nPayload); + ** + ** The code is inlined to avoid a function call. + */ + nPayload = *pIter; + if( nPayload>=0x80 ){ + u8 *pEnd = &pIter[8]; + nPayload &= 0x7f; + do{ + nPayload = (nPayload<<7) | (*++pIter & 0x7f); + }while( (*pIter)>=0x80 && pIternKey); + ** + ** The code is inlined to avoid a function call. + */ + iKey = *pIter; + if( iKey>=0x80 ){ + u8 *pEnd = &pIter[7]; + iKey &= 0x7f; + while(1){ + iKey = (iKey<<7) | (*++pIter & 0x7f); + if( (*pIter)<0x80 ) break; + if( pIter>=pEnd ){ + iKey = (iKey<<8) | *++pIter; + break; + } + } + } + pIter++; + + pInfo->nKey = *(i64*)&iKey; + pInfo->nPayload = nPayload; + pInfo->pPayload = pIter; + testcase( nPayload==pPage->maxLocal ); + testcase( nPayload==pPage->maxLocal+1 ); + if( nPayload<=pPage->maxLocal ){ + /* This is the (easy) common case where the entire payload fits + ** on the local page. No overflow is required. + */ + pInfo->nSize = nPayload + (u16)(pIter - pCell); + if( pInfo->nSize<4 ) pInfo->nSize = 4; + pInfo->nLocal = (u16)nPayload; + pInfo->iOverflow = 0; + }else{ + btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo); + } +} +static void btreeParseCellPtrIndex( + MemPage *pPage, /* Page containing the cell */ + u8 *pCell, /* Pointer to the cell text. */ + CellInfo *pInfo /* Fill in this structure */ +){ + u8 *pIter; /* For scanning through pCell */ + u32 nPayload; /* Number of bytes of cell payload */ + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( pPage->leaf==0 || pPage->leaf==1 ); + assert( pPage->intKeyLeaf==0 ); + assert( pPage->noPayload==0 ); + pIter = pCell + pPage->childPtrSize; + nPayload = *pIter; + if( nPayload>=0x80 ){ + u8 *pEnd = &pIter[8]; + nPayload &= 0x7f; + do{ + nPayload = (nPayload<<7) | (*++pIter & 0x7f); + }while( *(pIter)>=0x80 && pIternKey = nPayload; + pInfo->nPayload = nPayload; + pInfo->pPayload = pIter; + testcase( nPayload==pPage->maxLocal ); + testcase( nPayload==pPage->maxLocal+1 ); + if( nPayload<=pPage->maxLocal ){ + /* This is the (easy) common case where the entire payload fits + ** on the local page. No overflow is required. + */ + pInfo->nSize = nPayload + (u16)(pIter - pCell); + if( pInfo->nSize<4 ) pInfo->nSize = 4; + pInfo->nLocal = (u16)nPayload; + pInfo->iOverflow = 0; + }else{ + btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo); + } +} +static void btreeParseCell( + MemPage *pPage, /* Page containing the cell */ + int iCell, /* The cell index. First cell is 0 */ + CellInfo *pInfo /* Fill in this structure */ +){ + pPage->xParseCell(pPage, findCell(pPage, iCell), pInfo); +} + +/* +** The following routines are implementations of the MemPage.xCellSize +** method. +** +** Compute the total number of bytes that a Cell needs in the cell +** data area of the btree-page. The return number includes the cell +** data header and the local payload, but not any overflow page or +** the space used by the cell pointer. +** +** cellSizePtrNoPayload() => table internal nodes +** cellSizePtr() => all index nodes & table leaf nodes +*/ +static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ + u8 *pIter = pCell + pPage->childPtrSize; /* For looping over bytes of pCell */ + u8 *pEnd; /* End mark for a varint */ + u32 nSize; /* Size value to return */ + +#ifdef SQLITE_DEBUG + /* The value returned by this function should always be the same as + ** the (CellInfo.nSize) value found by doing a full parse of the + ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of + ** this function verifies that this invariant is not violated. */ + CellInfo debuginfo; + pPage->xParseCell(pPage, pCell, &debuginfo); +#endif + + assert( pPage->noPayload==0 ); + nSize = *pIter; + if( nSize>=0x80 ){ + pEnd = &pIter[8]; + nSize &= 0x7f; + do{ + nSize = (nSize<<7) | (*++pIter & 0x7f); + }while( *(pIter)>=0x80 && pIterintKey ){ + /* pIter now points at the 64-bit integer key value, a variable length + ** integer. The following block moves pIter to point at the first byte + ** past the end of the key value. */ + pEnd = &pIter[9]; + while( (*pIter++)&0x80 && pItermaxLocal ); + testcase( nSize==pPage->maxLocal+1 ); + if( nSize<=pPage->maxLocal ){ + nSize += (u32)(pIter - pCell); + if( nSize<4 ) nSize = 4; + }else{ + int minLocal = pPage->minLocal; + nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4); + testcase( nSize==pPage->maxLocal ); + testcase( nSize==pPage->maxLocal+1 ); + if( nSize>pPage->maxLocal ){ + nSize = minLocal; + } + nSize += 4 + (u16)(pIter - pCell); + } + assert( nSize==debuginfo.nSize || CORRUPT_DB ); + return (u16)nSize; +} +static u16 cellSizePtrNoPayload(MemPage *pPage, u8 *pCell){ + u8 *pIter = pCell + 4; /* For looping over bytes of pCell */ + u8 *pEnd; /* End mark for a varint */ + +#ifdef SQLITE_DEBUG + /* The value returned by this function should always be the same as + ** the (CellInfo.nSize) value found by doing a full parse of the + ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of + ** this function verifies that this invariant is not violated. */ + CellInfo debuginfo; + pPage->xParseCell(pPage, pCell, &debuginfo); +#else + UNUSED_PARAMETER(pPage); +#endif + + assert( pPage->childPtrSize==4 ); + pEnd = pIter + 9; + while( (*pIter++)&0x80 && pIterxCellSize(pPage, findCell(pPage, iCell)); +} +#endif + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** If the cell pCell, part of page pPage contains a pointer +** to an overflow page, insert an entry into the pointer-map +** for the overflow page. +*/ +static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){ + CellInfo info; + if( *pRC ) return; + assert( pCell!=0 ); + pPage->xParseCell(pPage, pCell, &info); + if( info.iOverflow ){ + Pgno ovfl = get4byte(&pCell[info.iOverflow]); + ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC); + } +} +#endif + + +/* +** Defragment the page given. All Cells are moved to the +** end of the page and all free space is collected into one +** big FreeBlk that occurs in between the header and cell +** pointer array and the cell content area. +** +** EVIDENCE-OF: R-44582-60138 SQLite may from time to time reorganize a +** b-tree page so that there are no freeblocks or fragment bytes, all +** unused bytes are contained in the unallocated space region, and all +** cells are packed tightly at the end of the page. +*/ +static int defragmentPage(MemPage *pPage){ + int i; /* Loop counter */ + int pc; /* Address of the i-th cell */ + int hdr; /* Offset to the page header */ + int size; /* Size of a cell */ + int usableSize; /* Number of usable bytes on a page */ + int cellOffset; /* Offset to the cell pointer array */ + int cbrk; /* Offset to the cell content area */ + int nCell; /* Number of cells on the page */ + unsigned char *data; /* The page data */ + unsigned char *temp; /* Temp area for cell content */ + unsigned char *src; /* Source of content */ + int iCellFirst; /* First allowable cell index */ + int iCellLast; /* Last possible cell index */ + + + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( pPage->pBt!=0 ); + assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); + assert( pPage->nOverflow==0 ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + temp = 0; + src = data = pPage->aData; + hdr = pPage->hdrOffset; + cellOffset = pPage->cellOffset; + nCell = pPage->nCell; + assert( nCell==get2byte(&data[hdr+3]) ); + usableSize = pPage->pBt->usableSize; + cbrk = usableSize; + iCellFirst = cellOffset + 2*nCell; + iCellLast = usableSize - 4; + for(i=0; iiCellLast ){ + return SQLITE_CORRUPT_BKPT; + } + assert( pc>=iCellFirst && pc<=iCellLast ); + size = pPage->xCellSize(pPage, &src[pc]); + cbrk -= size; + if( cbrkusableSize ){ + return SQLITE_CORRUPT_BKPT; + } + assert( cbrk+size<=usableSize && cbrk>=iCellFirst ); + testcase( cbrk+size==usableSize ); + testcase( pc+size==usableSize ); + put2byte(pAddr, cbrk); + if( temp==0 ){ + int x; + if( cbrk==pc ) continue; + temp = sqlite3PagerTempSpace(pPage->pBt->pPager); + x = get2byte(&data[hdr+5]); + memcpy(&temp[x], &data[x], (cbrk+size) - x); + src = temp; + } + memcpy(&data[cbrk], &src[pc], size); + } + assert( cbrk>=iCellFirst ); + put2byte(&data[hdr+5], cbrk); + data[hdr+1] = 0; + data[hdr+2] = 0; + data[hdr+7] = 0; + memset(&data[iCellFirst], 0, cbrk-iCellFirst); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + if( cbrk-iCellFirst!=pPage->nFree ){ + return SQLITE_CORRUPT_BKPT; + } + return SQLITE_OK; +} + +/* +** Search the free-list on page pPg for space to store a cell nByte bytes in +** size. If one can be found, return a pointer to the space and remove it +** from the free-list. +** +** If no suitable space can be found on the free-list, return NULL. +** +** This function may detect corruption within pPg. If corruption is +** detected then *pRc is set to SQLITE_CORRUPT and NULL is returned. +** +** Slots on the free list that are between 1 and 3 bytes larger than nByte +** will be ignored if adding the extra space to the fragmentation count +** causes the fragmentation count to exceed 60. +*/ +static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ + const int hdr = pPg->hdrOffset; + u8 * const aData = pPg->aData; + int iAddr = hdr + 1; + int pc = get2byte(&aData[iAddr]); + int x; + int usableSize = pPg->pBt->usableSize; + + assert( pc>0 ); + do{ + int size; /* Size of the free slot */ + /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of + ** increasing offset. */ + if( pc>usableSize-4 || pc=0 ){ + testcase( x==4 ); + testcase( x==3 ); + if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){ + *pRc = SQLITE_CORRUPT_BKPT; + return 0; + }else if( x<4 ){ + /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total + ** number of bytes in fragments may not exceed 60. */ + if( aData[hdr+7]>57 ) return 0; + + /* Remove the slot from the free-list. Update the number of + ** fragmented bytes within the page. */ + memcpy(&aData[iAddr], &aData[pc], 2); + aData[hdr+7] += (u8)x; + }else{ + /* The slot remains on the free-list. Reduce its size to account + ** for the portion used by the new allocation. */ + put2byte(&aData[pc+2], x); + } + return &aData[pc + x]; + } + iAddr = pc; + pc = get2byte(&aData[pc]); + }while( pc ); + + return 0; +} + +/* +** Allocate nByte bytes of space from within the B-Tree page passed +** as the first argument. Write into *pIdx the index into pPage->aData[] +** of the first byte of allocated space. Return either SQLITE_OK or +** an error code (usually SQLITE_CORRUPT). +** +** The caller guarantees that there is sufficient space to make the +** allocation. This routine might need to defragment in order to bring +** all the space together, however. This routine will avoid using +** the first two bytes past the cell pointer area since presumably this +** allocation is being made in order to insert a new cell, so we will +** also end up needing a new cell pointer. +*/ +static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ + const int hdr = pPage->hdrOffset; /* Local cache of pPage->hdrOffset */ + u8 * const data = pPage->aData; /* Local cache of pPage->aData */ + int top; /* First byte of cell content area */ + int rc = SQLITE_OK; /* Integer return code */ + int gap; /* First byte of gap between cell pointers and cell content */ + + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( pPage->pBt ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( nByte>=0 ); /* Minimum cell size is 4 */ + assert( pPage->nFree>=nByte ); + assert( pPage->nOverflow==0 ); + assert( nByte < (int)(pPage->pBt->usableSize-8) ); + + assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf ); + gap = pPage->cellOffset + 2*pPage->nCell; + assert( gap<=65536 ); + /* EVIDENCE-OF: R-29356-02391 If the database uses a 65536-byte page size + ** and the reserved space is zero (the usual value for reserved space) + ** then the cell content offset of an empty page wants to be 65536. + ** However, that integer is too large to be stored in a 2-byte unsigned + ** integer, so a value of 0 is used in its place. */ + top = get2byte(&data[hdr+5]); + assert( top<=(int)pPage->pBt->usableSize ); /* Prevent by getAndInitPage() */ + if( gap>top ){ + if( top==0 && pPage->pBt->usableSize==65536 ){ + top = 65536; + }else{ + return SQLITE_CORRUPT_BKPT; + } + } + + /* If there is enough space between gap and top for one more cell pointer + ** array entry offset, and if the freelist is not empty, then search the + ** freelist looking for a free slot big enough to satisfy the request. + */ + testcase( gap+2==top ); + testcase( gap+1==top ); + testcase( gap==top ); + if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){ + u8 *pSpace = pageFindSlot(pPage, nByte, &rc); + if( pSpace ){ + assert( pSpace>=data && (pSpace - data)<65536 ); + *pIdx = (int)(pSpace - data); + return SQLITE_OK; + }else if( rc ){ + return rc; + } + } + + /* The request could not be fulfilled using a freelist slot. Check + ** to see if defragmentation is necessary. + */ + testcase( gap+2+nByte==top ); + if( gap+2+nByte>top ){ + assert( pPage->nCell>0 || CORRUPT_DB ); + rc = defragmentPage(pPage); + if( rc ) return rc; + top = get2byteNotZero(&data[hdr+5]); + assert( gap+nByte<=top ); + } + + + /* Allocate memory from the gap in between the cell pointer array + ** and the cell content area. The btreeInitPage() call has already + ** validated the freelist. Given that the freelist is valid, there + ** is no way that the allocation can extend off the end of the page. + ** The assert() below verifies the previous sentence. + */ + top -= nByte; + put2byte(&data[hdr+5], top); + assert( top+nByte <= (int)pPage->pBt->usableSize ); + *pIdx = top; + return SQLITE_OK; +} + +/* +** Return a section of the pPage->aData to the freelist. +** The first byte of the new free block is pPage->aData[iStart] +** and the size of the block is iSize bytes. +** +** Adjacent freeblocks are coalesced. +** +** Note that even though the freeblock list was checked by btreeInitPage(), +** that routine will not detect overlap between cells or freeblocks. Nor +** does it detect cells or freeblocks that encrouch into the reserved bytes +** at the end of the page. So do additional corruption checks inside this +** routine and return SQLITE_CORRUPT if any problems are found. +*/ +static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ + u16 iPtr; /* Address of ptr to next freeblock */ + u16 iFreeBlk; /* Address of the next freeblock */ + u8 hdr; /* Page header size. 0 or 100 */ + u8 nFrag = 0; /* Reduction in fragmentation */ + u16 iOrigSize = iSize; /* Original value of iSize */ + u32 iLast = pPage->pBt->usableSize-4; /* Largest possible freeblock offset */ + u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */ + unsigned char *data = pPage->aData; /* Page content */ + + assert( pPage->pBt!=0 ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( CORRUPT_DB || iStart>=pPage->hdrOffset+6+pPage->childPtrSize ); + assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( iSize>=4 ); /* Minimum cell size is 4 */ + assert( iStart<=iLast ); + + /* Overwrite deleted information with zeros when the secure_delete + ** option is enabled */ + if( pPage->pBt->btsFlags & BTS_SECURE_DELETE ){ + memset(&data[iStart], 0, iSize); + } + + /* The list of freeblocks must be in ascending order. Find the + ** spot on the list where iStart should be inserted. + */ + hdr = pPage->hdrOffset; + iPtr = hdr + 1; + if( data[iPtr+1]==0 && data[iPtr]==0 ){ + iFreeBlk = 0; /* Shortcut for the case when the freelist is empty */ + }else{ + while( (iFreeBlk = get2byte(&data[iPtr]))>0 && iFreeBlkiLast ) return SQLITE_CORRUPT_BKPT; + assert( iFreeBlk>iPtr || iFreeBlk==0 ); + + /* At this point: + ** iFreeBlk: First freeblock after iStart, or zero if none + ** iPtr: The address of a pointer to iFreeBlk + ** + ** Check to see if iFreeBlk should be coalesced onto the end of iStart. + */ + if( iFreeBlk && iEnd+3>=iFreeBlk ){ + nFrag = iFreeBlk - iEnd; + if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT; + iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); + if( iEnd > pPage->pBt->usableSize ) return SQLITE_CORRUPT_BKPT; + iSize = iEnd - iStart; + iFreeBlk = get2byte(&data[iFreeBlk]); + } + + /* If iPtr is another freeblock (that is, if iPtr is not the freelist + ** pointer in the page header) then check to see if iStart should be + ** coalesced onto the end of iPtr. + */ + if( iPtr>hdr+1 ){ + int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); + if( iPtrEnd+3>=iStart ){ + if( iPtrEnd>iStart ) return SQLITE_CORRUPT_BKPT; + nFrag += iStart - iPtrEnd; + iSize = iEnd - iPtr; + iStart = iPtr; + } + } + if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_BKPT; + data[hdr+7] -= nFrag; + } + if( iStart==get2byte(&data[hdr+5]) ){ + /* The new freeblock is at the beginning of the cell content area, + ** so just extend the cell content area rather than create another + ** freelist entry */ + if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_BKPT; + put2byte(&data[hdr+1], iFreeBlk); + put2byte(&data[hdr+5], iEnd); + }else{ + /* Insert the new freeblock into the freelist */ + put2byte(&data[iPtr], iStart); + put2byte(&data[iStart], iFreeBlk); + put2byte(&data[iStart+2], iSize); + } + pPage->nFree += iOrigSize; + return SQLITE_OK; +} + +/* +** Decode the flags byte (the first byte of the header) for a page +** and initialize fields of the MemPage structure accordingly. +** +** Only the following combinations are supported. Anything different +** indicates a corrupt database files: +** +** PTF_ZERODATA +** PTF_ZERODATA | PTF_LEAF +** PTF_LEAFDATA | PTF_INTKEY +** PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF +*/ +static int decodeFlags(MemPage *pPage, int flagByte){ + BtShared *pBt; /* A copy of pPage->pBt */ + + assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 ); + flagByte &= ~PTF_LEAF; + pPage->childPtrSize = 4-4*pPage->leaf; + pPage->xCellSize = cellSizePtr; + pBt = pPage->pBt; + if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){ + /* EVIDENCE-OF: R-03640-13415 A value of 5 means the page is an interior + ** table b-tree page. */ + assert( (PTF_LEAFDATA|PTF_INTKEY)==5 ); + /* EVIDENCE-OF: R-20501-61796 A value of 13 means the page is a leaf + ** table b-tree page. */ + assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 ); + pPage->intKey = 1; + if( pPage->leaf ){ + pPage->intKeyLeaf = 1; + pPage->noPayload = 0; + pPage->xParseCell = btreeParseCellPtr; + }else{ + pPage->intKeyLeaf = 0; + pPage->noPayload = 1; + pPage->xCellSize = cellSizePtrNoPayload; + pPage->xParseCell = btreeParseCellPtrNoPayload; + } + pPage->maxLocal = pBt->maxLeaf; + pPage->minLocal = pBt->minLeaf; + }else if( flagByte==PTF_ZERODATA ){ + /* EVIDENCE-OF: R-27225-53936 A value of 2 means the page is an interior + ** index b-tree page. */ + assert( (PTF_ZERODATA)==2 ); + /* EVIDENCE-OF: R-16571-11615 A value of 10 means the page is a leaf + ** index b-tree page. */ + assert( (PTF_ZERODATA|PTF_LEAF)==10 ); + pPage->intKey = 0; + pPage->intKeyLeaf = 0; + pPage->noPayload = 0; + pPage->xParseCell = btreeParseCellPtrIndex; + pPage->maxLocal = pBt->maxLocal; + pPage->minLocal = pBt->minLocal; + }else{ + /* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is + ** an error. */ + return SQLITE_CORRUPT_BKPT; + } + pPage->max1bytePayload = pBt->max1bytePayload; + return SQLITE_OK; +} + +/* +** Initialize the auxiliary information for a disk block. +** +** Return SQLITE_OK on success. If we see that the page does +** not contain a well-formed database page, then return +** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not +** guarantee that the page is well-formed. It only shows that +** we failed to detect any corruption. +*/ +static int btreeInitPage(MemPage *pPage){ + + assert( pPage->pBt!=0 ); + assert( pPage->pBt->db!=0 ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); + assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); + assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); + + if( !pPage->isInit ){ + u16 pc; /* Address of a freeblock within pPage->aData[] */ + u8 hdr; /* Offset to beginning of page header */ + u8 *data; /* Equal to pPage->aData */ + BtShared *pBt; /* The main btree structure */ + int usableSize; /* Amount of usable space on each page */ + u16 cellOffset; /* Offset from start of page to first cell pointer */ + int nFree; /* Number of unused bytes on the page */ + int top; /* First byte of the cell content area */ + int iCellFirst; /* First allowable cell or freeblock offset */ + int iCellLast; /* Last possible cell or freeblock offset */ + + pBt = pPage->pBt; + + hdr = pPage->hdrOffset; + data = pPage->aData; + /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating + ** the b-tree page type. */ + if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT; + assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); + pPage->maskPage = (u16)(pBt->pageSize - 1); + pPage->nOverflow = 0; + usableSize = pBt->usableSize; + pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize; + pPage->aDataEnd = &data[usableSize]; + pPage->aCellIdx = &data[cellOffset]; + pPage->aDataOfst = &data[pPage->childPtrSize]; + /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates + ** the start of the cell content area. A zero value for this integer is + ** interpreted as 65536. */ + top = get2byteNotZero(&data[hdr+5]); + /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the + ** number of cells on the page. */ + pPage->nCell = get2byte(&data[hdr+3]); + if( pPage->nCell>MX_CELL(pBt) ){ + /* To many cells for a single page. The page must be corrupt */ + return SQLITE_CORRUPT_BKPT; + } + testcase( pPage->nCell==MX_CELL(pBt) ); + /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only + ** possible for a root page of a table that contains no rows) then the + ** offset to the cell content area will equal the page size minus the + ** bytes of reserved space. */ + assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB ); + + /* A malformed database page might cause us to read past the end + ** of page when parsing a cell. + ** + ** The following block of code checks early to see if a cell extends + ** past the end of a page boundary and causes SQLITE_CORRUPT to be + ** returned if it does. + */ + iCellFirst = cellOffset + 2*pPage->nCell; + iCellLast = usableSize - 4; + if( pBt->db->flags & SQLITE_CellSizeCk ){ + int i; /* Index into the cell pointer array */ + int sz; /* Size of a cell */ + + if( !pPage->leaf ) iCellLast--; + for(i=0; inCell; i++){ + pc = get2byteAligned(&data[cellOffset+i*2]); + testcase( pc==iCellFirst ); + testcase( pc==iCellLast ); + if( pciCellLast ){ + return SQLITE_CORRUPT_BKPT; + } + sz = pPage->xCellSize(pPage, &data[pc]); + testcase( pc+sz==usableSize ); + if( pc+sz>usableSize ){ + return SQLITE_CORRUPT_BKPT; + } + } + if( !pPage->leaf ) iCellLast++; + } + + /* Compute the total free space on the page + ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the + ** start of the first freeblock on the page, or is zero if there are no + ** freeblocks. */ + pc = get2byte(&data[hdr+1]); + nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */ + while( pc>0 ){ + u16 next, size; + if( pciCellLast ){ + /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will + ** always be at least one cell before the first freeblock. + ** + ** Or, the freeblock is off the end of the page + */ + return SQLITE_CORRUPT_BKPT; + } + next = get2byte(&data[pc]); + size = get2byte(&data[pc+2]); + if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){ + /* Free blocks must be in ascending order. And the last byte of + ** the free-block must lie on the database page. */ + return SQLITE_CORRUPT_BKPT; + } + nFree = nFree + size; + pc = next; + } + + /* At this point, nFree contains the sum of the offset to the start + ** of the cell-content area plus the number of free bytes within + ** the cell-content area. If this is greater than the usable-size + ** of the page, then the page must be corrupted. This check also + ** serves to verify that the offset to the start of the cell-content + ** area, according to the page header, lies within the page. + */ + if( nFree>usableSize ){ + return SQLITE_CORRUPT_BKPT; + } + pPage->nFree = (u16)(nFree - iCellFirst); + pPage->isInit = 1; + } + return SQLITE_OK; +} + +/* +** Set up a raw page so that it looks like a database page holding +** no entries. +*/ +static void zeroPage(MemPage *pPage, int flags){ + unsigned char *data = pPage->aData; + BtShared *pBt = pPage->pBt; + u8 hdr = pPage->hdrOffset; + u16 first; + + assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); + assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); + assert( sqlite3PagerGetData(pPage->pDbPage) == data ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( sqlite3_mutex_held(pBt->mutex) ); + if( pBt->btsFlags & BTS_SECURE_DELETE ){ + memset(&data[hdr], 0, pBt->usableSize - hdr); + } + data[hdr] = (char)flags; + first = hdr + ((flags&PTF_LEAF)==0 ? 12 : 8); + memset(&data[hdr+1], 0, 4); + data[hdr+7] = 0; + put2byte(&data[hdr+5], pBt->usableSize); + pPage->nFree = (u16)(pBt->usableSize - first); + decodeFlags(pPage, flags); + pPage->cellOffset = first; + pPage->aDataEnd = &data[pBt->usableSize]; + pPage->aCellIdx = &data[first]; + pPage->aDataOfst = &data[pPage->childPtrSize]; + pPage->nOverflow = 0; + assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); + pPage->maskPage = (u16)(pBt->pageSize - 1); + pPage->nCell = 0; + pPage->isInit = 1; +} + + +/* +** Convert a DbPage obtained from the pager into a MemPage used by +** the btree layer. +*/ +static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){ + MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); + pPage->aData = sqlite3PagerGetData(pDbPage); + pPage->pDbPage = pDbPage; + pPage->pBt = pBt; + pPage->pgno = pgno; + pPage->hdrOffset = pgno==1 ? 100 : 0; + return pPage; +} + +/* +** Get a page from the pager. Initialize the MemPage.pBt and +** MemPage.aData elements if needed. See also: btreeGetUnusedPage(). +** +** If the PAGER_GET_NOCONTENT flag is set, it means that we do not care +** about the content of the page at this time. So do not go to the disk +** to fetch the content. Just fill in the content with zeros for now. +** If in the future we call sqlite3PagerWrite() on this page, that +** means we have started to be concerned about content and the disk +** read should occur at that point. +*/ +static int btreeGetPage( + BtShared *pBt, /* The btree */ + Pgno pgno, /* Number of the page to fetch */ + MemPage **ppPage, /* Return the page in this parameter */ + int flags /* PAGER_GET_NOCONTENT or PAGER_GET_READONLY */ +){ + int rc; + DbPage *pDbPage; + + assert( flags==0 || flags==PAGER_GET_NOCONTENT || flags==PAGER_GET_READONLY ); + assert( sqlite3_mutex_held(pBt->mutex) ); + rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, flags); + if( rc ) return rc; + *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt); + return SQLITE_OK; +} + +/* +** Retrieve a page from the pager cache. If the requested page is not +** already in the pager cache return NULL. Initialize the MemPage.pBt and +** MemPage.aData elements if needed. +*/ +static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){ + DbPage *pDbPage; + assert( sqlite3_mutex_held(pBt->mutex) ); + pDbPage = sqlite3PagerLookup(pBt->pPager, pgno); + if( pDbPage ){ + return btreePageFromDbPage(pDbPage, pgno, pBt); + } + return 0; +} + +/* +** Return the size of the database file in pages. If there is any kind of +** error, return ((unsigned int)-1). +*/ +static Pgno btreePagecount(BtShared *pBt){ + return pBt->nPage; +} +SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){ + assert( sqlite3BtreeHoldsMutex(p) ); + assert( ((p->pBt->nPage)&0x8000000)==0 ); + return btreePagecount(p->pBt); +} + +/* +** Get a page from the pager and initialize it. +** +** If pCur!=0 then the page is being fetched as part of a moveToChild() +** call. Do additional sanity checking on the page in this case. +** And if the fetch fails, this routine must decrement pCur->iPage. +** +** The page is fetched as read-write unless pCur is not NULL and is +** a read-only cursor. +** +** If an error occurs, then *ppPage is undefined. It +** may remain unchanged, or it may be set to an invalid value. +*/ +static int getAndInitPage( + BtShared *pBt, /* The database file */ + Pgno pgno, /* Number of the page to get */ + MemPage **ppPage, /* Write the page pointer here */ + BtCursor *pCur, /* Cursor to receive the page, or NULL */ + int bReadOnly /* True for a read-only page */ +){ + int rc; + DbPage *pDbPage; + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pCur==0 || ppPage==&pCur->apPage[pCur->iPage] ); + assert( pCur==0 || bReadOnly==pCur->curPagerFlags ); + assert( pCur==0 || pCur->iPage>0 ); + + if( pgno>btreePagecount(pBt) ){ + rc = SQLITE_CORRUPT_BKPT; + goto getAndInitPage_error; + } + rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly); + if( rc ){ + goto getAndInitPage_error; + } + *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt); + if( (*ppPage)->isInit==0 ){ + rc = btreeInitPage(*ppPage); + if( rc!=SQLITE_OK ){ + releasePage(*ppPage); + goto getAndInitPage_error; + } + } + + /* If obtaining a child page for a cursor, we must verify that the page is + ** compatible with the root page. */ + if( pCur + && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) + ){ + rc = SQLITE_CORRUPT_BKPT; + releasePage(*ppPage); + goto getAndInitPage_error; + } + return SQLITE_OK; + +getAndInitPage_error: + if( pCur ) pCur->iPage--; + testcase( pgno==0 ); + assert( pgno!=0 || rc==SQLITE_CORRUPT ); + return rc; +} + +/* +** Release a MemPage. This should be called once for each prior +** call to btreeGetPage. +*/ +static void releasePageNotNull(MemPage *pPage){ + assert( pPage->aData ); + assert( pPage->pBt ); + assert( pPage->pDbPage!=0 ); + assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); + assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + sqlite3PagerUnrefNotNull(pPage->pDbPage); +} +static void releasePage(MemPage *pPage){ + if( pPage ) releasePageNotNull(pPage); +} + +/* +** Get an unused page. +** +** This works just like btreeGetPage() with the addition: +** +** * If the page is already in use for some other purpose, immediately +** release it and return an SQLITE_CURRUPT error. +** * Make sure the isInit flag is clear +*/ +static int btreeGetUnusedPage( + BtShared *pBt, /* The btree */ + Pgno pgno, /* Number of the page to fetch */ + MemPage **ppPage, /* Return the page in this parameter */ + int flags /* PAGER_GET_NOCONTENT or PAGER_GET_READONLY */ +){ + int rc = btreeGetPage(pBt, pgno, ppPage, flags); + if( rc==SQLITE_OK ){ + if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){ + releasePage(*ppPage); + *ppPage = 0; + return SQLITE_CORRUPT_BKPT; + } + (*ppPage)->isInit = 0; + }else{ + *ppPage = 0; + } + return rc; +} + + +/* +** During a rollback, when the pager reloads information into the cache +** so that the cache is restored to its original state at the start of +** the transaction, for each page restored this routine is called. +** +** This routine needs to reset the extra data section at the end of the +** page to agree with the restored data. +*/ +static void pageReinit(DbPage *pData){ + MemPage *pPage; + pPage = (MemPage *)sqlite3PagerGetExtra(pData); + assert( sqlite3PagerPageRefcount(pData)>0 ); + if( pPage->isInit ){ + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pPage->isInit = 0; + if( sqlite3PagerPageRefcount(pData)>1 ){ + /* pPage might not be a btree page; it might be an overflow page + ** or ptrmap page or a free page. In those cases, the following + ** call to btreeInitPage() will likely return SQLITE_CORRUPT. + ** But no harm is done by this. And it is very important that + ** btreeInitPage() be called on every btree page so we make + ** the call for every page that comes in for re-initing. */ + btreeInitPage(pPage); + } + } +} + +/* +** Invoke the busy handler for a btree. +*/ +static int btreeInvokeBusyHandler(void *pArg){ + BtShared *pBt = (BtShared*)pArg; + assert( pBt->db ); + assert( sqlite3_mutex_held(pBt->db->mutex) ); + return sqlite3InvokeBusyHandler(&pBt->db->busyHandler); +} + +/* +** Open a database file. +** +** zFilename is the name of the database file. If zFilename is NULL +** then an ephemeral database is created. The ephemeral database might +** be exclusively in memory, or it might use a disk-based memory cache. +** Either way, the ephemeral database will be automatically deleted +** when sqlite3BtreeClose() is called. +** +** If zFilename is ":memory:" then an in-memory database is created +** that is automatically destroyed when it is closed. +** +** The "flags" parameter is a bitmask that might contain bits like +** BTREE_OMIT_JOURNAL and/or BTREE_MEMORY. +** +** If the database is already opened in the same database connection +** and we are in shared cache mode, then the open will fail with an +** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared +** objects in the same database connection since doing so will lead +** to problems with locking. +*/ +SQLITE_PRIVATE int sqlite3BtreeOpen( + sqlite3_vfs *pVfs, /* VFS to use for this b-tree */ + const char *zFilename, /* Name of the file containing the BTree database */ + sqlite3 *db, /* Associated database handle */ + Btree **ppBtree, /* Pointer to new Btree object written here */ + int flags, /* Options */ + int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */ +){ + BtShared *pBt = 0; /* Shared part of btree structure */ + Btree *p; /* Handle to return */ + sqlite3_mutex *mutexOpen = 0; /* Prevents a race condition. Ticket #3537 */ + int rc = SQLITE_OK; /* Result code from this function */ + u8 nReserve; /* Byte of unused space on each page */ + unsigned char zDbHeader[100]; /* Database header content */ + + /* True if opening an ephemeral, temporary database */ + const int isTempDb = zFilename==0 || zFilename[0]==0; + + /* Set the variable isMemdb to true for an in-memory database, or + ** false for a file-based database. + */ +#ifdef SQLITE_OMIT_MEMORYDB + const int isMemdb = 0; +#else + const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0) + || (isTempDb && sqlite3TempInMemory(db)) + || (vfsFlags & SQLITE_OPEN_MEMORY)!=0; +#endif + + assert( db!=0 ); + assert( pVfs!=0 ); + assert( sqlite3_mutex_held(db->mutex) ); + assert( (flags&0xff)==flags ); /* flags fit in 8 bits */ + + /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */ + assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 ); + + /* A BTREE_SINGLE database is always a temporary and/or ephemeral */ + assert( (flags & BTREE_SINGLE)==0 || isTempDb ); + + if( isMemdb ){ + flags |= BTREE_MEMORY; + } + if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){ + vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; + } + p = sqlite3MallocZero(sizeof(Btree)); + if( !p ){ + return SQLITE_NOMEM; + } + p->inTrans = TRANS_NONE; + p->db = db; +#ifndef SQLITE_OMIT_SHARED_CACHE + p->lock.pBtree = p; + p->lock.iTable = 1; +#endif + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + /* + ** If this Btree is a candidate for shared cache, try to find an + ** existing BtShared object that we can share with + */ + if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){ + if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){ + int nFilename = sqlite3Strlen30(zFilename)+1; + int nFullPathname = pVfs->mxPathname+1; + char *zFullPathname = sqlite3Malloc(MAX(nFullPathname,nFilename)); + MUTEX_LOGIC( sqlite3_mutex *mutexShared; ) + + p->sharable = 1; + if( !zFullPathname ){ + sqlite3_free(p); + return SQLITE_NOMEM; + } + if( isMemdb ){ + memcpy(zFullPathname, zFilename, nFilename); + }else{ + rc = sqlite3OsFullPathname(pVfs, zFilename, + nFullPathname, zFullPathname); + if( rc ){ + sqlite3_free(zFullPathname); + sqlite3_free(p); + return rc; + } + } +#if SQLITE_THREADSAFE + mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN); + sqlite3_mutex_enter(mutexOpen); + mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); + sqlite3_mutex_enter(mutexShared); +#endif + for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){ + assert( pBt->nRef>0 ); + if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager, 0)) + && sqlite3PagerVfs(pBt->pPager)==pVfs ){ + int iDb; + for(iDb=db->nDb-1; iDb>=0; iDb--){ + Btree *pExisting = db->aDb[iDb].pBt; + if( pExisting && pExisting->pBt==pBt ){ + sqlite3_mutex_leave(mutexShared); + sqlite3_mutex_leave(mutexOpen); + sqlite3_free(zFullPathname); + sqlite3_free(p); + return SQLITE_CONSTRAINT; + } + } + p->pBt = pBt; + pBt->nRef++; + break; + } + } + sqlite3_mutex_leave(mutexShared); + sqlite3_free(zFullPathname); + } +#ifdef SQLITE_DEBUG + else{ + /* In debug mode, we mark all persistent databases as sharable + ** even when they are not. This exercises the locking code and + ** gives more opportunity for asserts(sqlite3_mutex_held()) + ** statements to find locking problems. + */ + p->sharable = 1; + } +#endif + } +#endif + if( pBt==0 ){ + /* + ** The following asserts make sure that structures used by the btree are + ** the right size. This is to guard against size changes that result + ** when compiling on a different architecture. + */ + assert( sizeof(i64)==8 ); + assert( sizeof(u64)==8 ); + assert( sizeof(u32)==4 ); + assert( sizeof(u16)==2 ); + assert( sizeof(Pgno)==4 ); + + pBt = sqlite3MallocZero( sizeof(*pBt) ); + if( pBt==0 ){ + rc = SQLITE_NOMEM; + goto btree_open_out; + } + rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, + EXTRA_SIZE, flags, vfsFlags, pageReinit); + if( rc==SQLITE_OK ){ + sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap); + rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); + } + if( rc!=SQLITE_OK ){ + goto btree_open_out; + } + pBt->openFlags = (u8)flags; + pBt->db = db; + sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt); + p->pBt = pBt; + + pBt->pCursor = 0; + pBt->pPage1 = 0; + if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY; +#ifdef SQLITE_SECURE_DELETE + pBt->btsFlags |= BTS_SECURE_DELETE; +#endif + /* EVIDENCE-OF: R-51873-39618 The page size for a database file is + ** determined by the 2-byte integer located at an offset of 16 bytes from + ** the beginning of the database file. */ + pBt->pageSize = (zDbHeader[16]<<8) | (zDbHeader[17]<<16); + if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE + || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ + pBt->pageSize = 0; +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If the magic name ":memory:" will create an in-memory database, then + ** leave the autoVacuum mode at 0 (do not auto-vacuum), even if + ** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if + ** SQLITE_OMIT_MEMORYDB has been defined, then ":memory:" is just a + ** regular file-name. In this case the auto-vacuum applies as per normal. + */ + if( zFilename && !isMemdb ){ + pBt->autoVacuum = (SQLITE_DEFAULT_AUTOVACUUM ? 1 : 0); + pBt->incrVacuum = (SQLITE_DEFAULT_AUTOVACUUM==2 ? 1 : 0); + } +#endif + nReserve = 0; + }else{ + /* EVIDENCE-OF: R-37497-42412 The size of the reserved region is + ** determined by the one-byte unsigned integer found at an offset of 20 + ** into the database file header. */ + nReserve = zDbHeader[20]; + pBt->btsFlags |= BTS_PAGESIZE_FIXED; +#ifndef SQLITE_OMIT_AUTOVACUUM + pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0); + pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0); +#endif + } + rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve); + if( rc ) goto btree_open_out; + pBt->usableSize = pBt->pageSize - nReserve; + assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */ + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + /* Add the new BtShared object to the linked list sharable BtShareds. + */ + if( p->sharable ){ + MUTEX_LOGIC( sqlite3_mutex *mutexShared; ) + pBt->nRef = 1; + MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);) + if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){ + pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST); + if( pBt->mutex==0 ){ + rc = SQLITE_NOMEM; + db->mallocFailed = 0; + goto btree_open_out; + } + } + sqlite3_mutex_enter(mutexShared); + pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList); + GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt; + sqlite3_mutex_leave(mutexShared); + } +#endif + } + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + /* If the new Btree uses a sharable pBtShared, then link the new + ** Btree into the list of all sharable Btrees for the same connection. + ** The list is kept in ascending order by pBt address. + */ + if( p->sharable ){ + int i; + Btree *pSib; + for(i=0; inDb; i++){ + if( (pSib = db->aDb[i].pBt)!=0 && pSib->sharable ){ + while( pSib->pPrev ){ pSib = pSib->pPrev; } + if( p->pBtpBt ){ + p->pNext = pSib; + p->pPrev = 0; + pSib->pPrev = p; + }else{ + while( pSib->pNext && pSib->pNext->pBtpBt ){ + pSib = pSib->pNext; + } + p->pNext = pSib->pNext; + p->pPrev = pSib; + if( p->pNext ){ + p->pNext->pPrev = p; + } + pSib->pNext = p; + } + break; + } + } + } +#endif + *ppBtree = p; + +btree_open_out: + if( rc!=SQLITE_OK ){ + if( pBt && pBt->pPager ){ + sqlite3PagerClose(pBt->pPager); + } + sqlite3_free(pBt); + sqlite3_free(p); + *ppBtree = 0; + }else{ + /* If the B-Tree was successfully opened, set the pager-cache size to the + ** default value. Except, when opening on an existing shared pager-cache, + ** do not change the pager-cache size. + */ + if( sqlite3BtreeSchema(p, 0, 0)==0 ){ + sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); + } + } + if( mutexOpen ){ + assert( sqlite3_mutex_held(mutexOpen) ); + sqlite3_mutex_leave(mutexOpen); + } + return rc; +} + +/* +** Decrement the BtShared.nRef counter. When it reaches zero, +** remove the BtShared structure from the sharing list. Return +** true if the BtShared.nRef counter reaches zero and return +** false if it is still positive. +*/ +static int removeFromSharingList(BtShared *pBt){ +#ifndef SQLITE_OMIT_SHARED_CACHE + MUTEX_LOGIC( sqlite3_mutex *pMaster; ) + BtShared *pList; + int removed = 0; + + assert( sqlite3_mutex_notheld(pBt->mutex) ); + MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) + sqlite3_mutex_enter(pMaster); + pBt->nRef--; + if( pBt->nRef<=0 ){ + if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){ + GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt->pNext; + }else{ + pList = GLOBAL(BtShared*,sqlite3SharedCacheList); + while( ALWAYS(pList) && pList->pNext!=pBt ){ + pList=pList->pNext; + } + if( ALWAYS(pList) ){ + pList->pNext = pBt->pNext; + } + } + if( SQLITE_THREADSAFE ){ + sqlite3_mutex_free(pBt->mutex); + } + removed = 1; + } + sqlite3_mutex_leave(pMaster); + return removed; +#else + return 1; +#endif +} + +/* +** Make sure pBt->pTmpSpace points to an allocation of +** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child +** pointer. +*/ +static void allocateTempSpace(BtShared *pBt){ + if( !pBt->pTmpSpace ){ + pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize ); + + /* One of the uses of pBt->pTmpSpace is to format cells before + ** inserting them into a leaf page (function fillInCell()). If + ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes + ** by the various routines that manipulate binary cells. Which + ** can mean that fillInCell() only initializes the first 2 or 3 + ** bytes of pTmpSpace, but that the first 4 bytes are copied from + ** it into a database page. This is not actually a problem, but it + ** does cause a valgrind error when the 1 or 2 bytes of unitialized + ** data is passed to system call write(). So to avoid this error, + ** zero the first 4 bytes of temp space here. + ** + ** Also: Provide four bytes of initialized space before the + ** beginning of pTmpSpace as an area available to prepend the + ** left-child pointer to the beginning of a cell. + */ + if( pBt->pTmpSpace ){ + memset(pBt->pTmpSpace, 0, 8); + pBt->pTmpSpace += 4; + } + } +} + +/* +** Free the pBt->pTmpSpace allocation +*/ +static void freeTempSpace(BtShared *pBt){ + if( pBt->pTmpSpace ){ + pBt->pTmpSpace -= 4; + sqlite3PageFree(pBt->pTmpSpace); + pBt->pTmpSpace = 0; + } +} + +/* +** Close an open database and invalidate all cursors. +*/ +SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){ + BtShared *pBt = p->pBt; + BtCursor *pCur; + + /* Close all cursors opened via this handle. */ + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + pCur = pBt->pCursor; + while( pCur ){ + BtCursor *pTmp = pCur; + pCur = pCur->pNext; + if( pTmp->pBtree==p ){ + sqlite3BtreeCloseCursor(pTmp); + } + } + + /* Rollback any active transaction and free the handle structure. + ** The call to sqlite3BtreeRollback() drops any table-locks held by + ** this handle. + */ + sqlite3BtreeRollback(p, SQLITE_OK, 0); + sqlite3BtreeLeave(p); + + /* If there are still other outstanding references to the shared-btree + ** structure, return now. The remainder of this procedure cleans + ** up the shared-btree. + */ + assert( p->wantToLock==0 && p->locked==0 ); + if( !p->sharable || removeFromSharingList(pBt) ){ + /* The pBt is no longer on the sharing list, so we can access + ** it without having to hold the mutex. + ** + ** Clean out and delete the BtShared object. + */ + assert( !pBt->pCursor ); + sqlite3PagerClose(pBt->pPager); + if( pBt->xFreeSchema && pBt->pSchema ){ + pBt->xFreeSchema(pBt->pSchema); + } + sqlite3DbFree(0, pBt->pSchema); + freeTempSpace(pBt); + sqlite3_free(pBt); + } + +#ifndef SQLITE_OMIT_SHARED_CACHE + assert( p->wantToLock==0 ); + assert( p->locked==0 ); + if( p->pPrev ) p->pPrev->pNext = p->pNext; + if( p->pNext ) p->pNext->pPrev = p->pPrev; +#endif + + sqlite3_free(p); + return SQLITE_OK; +} + +/* +** Change the limit on the number of pages allowed in the cache. +** +** The maximum number of cache pages is set to the absolute +** value of mxPage. If mxPage is negative, the pager will +** operate asynchronously - it will not stop to do fsync()s +** to insure data is written to the disk surface before +** continuing. Transactions still work if synchronous is off, +** and the database cannot be corrupted if this program +** crashes. But if the operating system crashes or there is +** an abrupt power failure when synchronous is off, the database +** could be left in an inconsistent and unrecoverable state. +** Synchronous is on by default so database corruption is not +** normally a worry. +*/ +SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ + BtShared *pBt = p->pBt; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + sqlite3PagerSetCachesize(pBt->pPager, mxPage); + sqlite3BtreeLeave(p); + return SQLITE_OK; +} + +#if SQLITE_MAX_MMAP_SIZE>0 +/* +** Change the limit on the amount of the database file that may be +** memory mapped. +*/ +SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){ + BtShared *pBt = p->pBt; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + sqlite3PagerSetMmapLimit(pBt->pPager, szMmap); + sqlite3BtreeLeave(p); + return SQLITE_OK; +} +#endif /* SQLITE_MAX_MMAP_SIZE>0 */ + +/* +** Change the way data is synced to disk in order to increase or decrease +** how well the database resists damage due to OS crashes and power +** failures. Level 1 is the same as asynchronous (no syncs() occur and +** there is a high probability of damage) Level 2 is the default. There +** is a very low but non-zero probability of damage. Level 3 reduces the +** probability of damage to near zero but with a write performance reduction. +*/ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags( + Btree *p, /* The btree to set the safety level on */ + unsigned pgFlags /* Various PAGER_* flags */ +){ + BtShared *pBt = p->pBt; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + sqlite3PagerSetFlags(pBt->pPager, pgFlags); + sqlite3BtreeLeave(p); + return SQLITE_OK; +} +#endif + +/* +** Return TRUE if the given btree is set to safety level 1. In other +** words, return TRUE if no sync() occurs on the disk files. +*/ +SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree *p){ + BtShared *pBt = p->pBt; + int rc; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + assert( pBt && pBt->pPager ); + rc = sqlite3PagerNosync(pBt->pPager); + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Change the default pages size and the number of reserved bytes per page. +** Or, if the page size has already been fixed, return SQLITE_READONLY +** without changing anything. +** +** The page size must be a power of 2 between 512 and 65536. If the page +** size supplied does not meet this constraint then the page size is not +** changed. +** +** Page sizes are constrained to be a power of two so that the region +** of the database file used for locking (beginning at PENDING_BYTE, +** the first byte past the 1GB boundary, 0x40000000) needs to occur +** at the beginning of a page. +** +** If parameter nReserve is less than zero, then the number of reserved +** bytes per page is left unchanged. +** +** If the iFix!=0 then the BTS_PAGESIZE_FIXED flag is set so that the page size +** and autovacuum mode can no longer be changed. +*/ +SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){ + int rc = SQLITE_OK; + BtShared *pBt = p->pBt; + assert( nReserve>=-1 && nReserve<=255 ); + sqlite3BtreeEnter(p); +#if SQLITE_HAS_CODEC + if( nReserve>pBt->optimalReserve ) pBt->optimalReserve = (u8)nReserve; +#endif + if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){ + sqlite3BtreeLeave(p); + return SQLITE_READONLY; + } + if( nReserve<0 ){ + nReserve = pBt->pageSize - pBt->usableSize; + } + assert( nReserve>=0 && nReserve<=255 ); + if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && + ((pageSize-1)&pageSize)==0 ){ + assert( (pageSize & 7)==0 ); + assert( !pBt->pCursor ); + pBt->pageSize = (u32)pageSize; + freeTempSpace(pBt); + } + rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve); + pBt->usableSize = pBt->pageSize - (u16)nReserve; + if( iFix ) pBt->btsFlags |= BTS_PAGESIZE_FIXED; + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Return the currently defined page size +*/ +SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){ + return p->pBt->pageSize; +} + +/* +** This function is similar to sqlite3BtreeGetReserve(), except that it +** may only be called if it is guaranteed that the b-tree mutex is already +** held. +** +** This is useful in one special case in the backup API code where it is +** known that the shared b-tree mutex is held, but the mutex on the +** database handle that owns *p is not. In this case if sqlite3BtreeEnter() +** were to be called, it might collide with some other operation on the +** database handle that owns *p, causing undefined behavior. +*/ +SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){ + int n; + assert( sqlite3_mutex_held(p->pBt->mutex) ); + n = p->pBt->pageSize - p->pBt->usableSize; + return n; +} + +/* +** Return the number of bytes of space at the end of every page that +** are intentually left unused. This is the "reserved" space that is +** sometimes used by extensions. +** +** If SQLITE_HAS_MUTEX is defined then the number returned is the +** greater of the current reserved space and the maximum requested +** reserve space. +*/ +SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree *p){ + int n; + sqlite3BtreeEnter(p); + n = sqlite3BtreeGetReserveNoMutex(p); +#ifdef SQLITE_HAS_CODEC + if( npBt->optimalReserve ) n = p->pBt->optimalReserve; +#endif + sqlite3BtreeLeave(p); + return n; +} + + +/* +** Set the maximum page count for a database if mxPage is positive. +** No changes are made if mxPage is 0 or negative. +** Regardless of the value of mxPage, return the maximum page count. +*/ +SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){ + int n; + sqlite3BtreeEnter(p); + n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage); + sqlite3BtreeLeave(p); + return n; +} + +/* +** Set the BTS_SECURE_DELETE flag if newFlag is 0 or 1. If newFlag is -1, +** then make no changes. Always return the value of the BTS_SECURE_DELETE +** setting after the change. +*/ +SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){ + int b; + if( p==0 ) return 0; + sqlite3BtreeEnter(p); + if( newFlag>=0 ){ + p->pBt->btsFlags &= ~BTS_SECURE_DELETE; + if( newFlag ) p->pBt->btsFlags |= BTS_SECURE_DELETE; + } + b = (p->pBt->btsFlags & BTS_SECURE_DELETE)!=0; + sqlite3BtreeLeave(p); + return b; +} + +/* +** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' +** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it +** is disabled. The default value for the auto-vacuum property is +** determined by the SQLITE_DEFAULT_AUTOVACUUM macro. +*/ +SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){ +#ifdef SQLITE_OMIT_AUTOVACUUM + return SQLITE_READONLY; +#else + BtShared *pBt = p->pBt; + int rc = SQLITE_OK; + u8 av = (u8)autoVacuum; + + sqlite3BtreeEnter(p); + if( (pBt->btsFlags & BTS_PAGESIZE_FIXED)!=0 && (av ?1:0)!=pBt->autoVacuum ){ + rc = SQLITE_READONLY; + }else{ + pBt->autoVacuum = av ?1:0; + pBt->incrVacuum = av==2 ?1:0; + } + sqlite3BtreeLeave(p); + return rc; +#endif +} + +/* +** Return the value of the 'auto-vacuum' property. If auto-vacuum is +** enabled 1 is returned. Otherwise 0. +*/ +SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *p){ +#ifdef SQLITE_OMIT_AUTOVACUUM + return BTREE_AUTOVACUUM_NONE; +#else + int rc; + sqlite3BtreeEnter(p); + rc = ( + (!p->pBt->autoVacuum)?BTREE_AUTOVACUUM_NONE: + (!p->pBt->incrVacuum)?BTREE_AUTOVACUUM_FULL: + BTREE_AUTOVACUUM_INCR + ); + sqlite3BtreeLeave(p); + return rc; +#endif +} + + +/* +** Get a reference to pPage1 of the database file. This will +** also acquire a readlock on that file. +** +** SQLITE_OK is returned on success. If the file is not a +** well-formed database file, then SQLITE_CORRUPT is returned. +** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM +** is returned if we run out of memory. +*/ +static int lockBtree(BtShared *pBt){ + int rc; /* Result code from subfunctions */ + MemPage *pPage1; /* Page 1 of the database file */ + int nPage; /* Number of pages in the database */ + int nPageFile = 0; /* Number of pages in the database file */ + int nPageHeader; /* Number of pages in the database according to hdr */ + + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pBt->pPage1==0 ); + rc = sqlite3PagerSharedLock(pBt->pPager); + if( rc!=SQLITE_OK ) return rc; + rc = btreeGetPage(pBt, 1, &pPage1, 0); + if( rc!=SQLITE_OK ) return rc; + + /* Do some checking to help insure the file we opened really is + ** a valid database file. + */ + nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData); + sqlite3PagerPagecount(pBt->pPager, &nPageFile); + if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){ + nPage = nPageFile; + } + if( nPage>0 ){ + u32 pageSize; + u32 usableSize; + u8 *page1 = pPage1->aData; + rc = SQLITE_NOTADB; + /* EVIDENCE-OF: R-43737-39999 Every valid SQLite database file begins + ** with the following 16 bytes (in hex): 53 51 4c 69 74 65 20 66 6f 72 6d + ** 61 74 20 33 00. */ + if( memcmp(page1, zMagicHeader, 16)!=0 ){ + goto page1_init_failed; + } + +#ifdef SQLITE_OMIT_WAL + if( page1[18]>1 ){ + pBt->btsFlags |= BTS_READ_ONLY; + } + if( page1[19]>1 ){ + goto page1_init_failed; + } +#else + if( page1[18]>2 ){ + pBt->btsFlags |= BTS_READ_ONLY; + } + if( page1[19]>2 ){ + goto page1_init_failed; + } + + /* If the write version is set to 2, this database should be accessed + ** in WAL mode. If the log is not already open, open it now. Then + ** return SQLITE_OK and return without populating BtShared.pPage1. + ** The caller detects this and calls this function again. This is + ** required as the version of page 1 currently in the page1 buffer + ** may not be the latest version - there may be a newer one in the log + ** file. + */ + if( page1[19]==2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){ + int isOpen = 0; + rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen); + if( rc!=SQLITE_OK ){ + goto page1_init_failed; + }else if( isOpen==0 ){ + releasePage(pPage1); + return SQLITE_OK; + } + rc = SQLITE_NOTADB; + } +#endif + + /* EVIDENCE-OF: R-15465-20813 The maximum and minimum embedded payload + ** fractions and the leaf payload fraction values must be 64, 32, and 32. + ** + ** The original design allowed these amounts to vary, but as of + ** version 3.6.0, we require them to be fixed. + */ + if( memcmp(&page1[21], "\100\040\040",3)!=0 ){ + goto page1_init_failed; + } + /* EVIDENCE-OF: R-51873-39618 The page size for a database file is + ** determined by the 2-byte integer located at an offset of 16 bytes from + ** the beginning of the database file. */ + pageSize = (page1[16]<<8) | (page1[17]<<16); + /* EVIDENCE-OF: R-25008-21688 The size of a page is a power of two + ** between 512 and 65536 inclusive. */ + if( ((pageSize-1)&pageSize)!=0 + || pageSize>SQLITE_MAX_PAGE_SIZE + || pageSize<=256 + ){ + goto page1_init_failed; + } + assert( (pageSize & 7)==0 ); + /* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte + ** integer at offset 20 is the number of bytes of space at the end of + ** each page to reserve for extensions. + ** + ** EVIDENCE-OF: R-37497-42412 The size of the reserved region is + ** determined by the one-byte unsigned integer found at an offset of 20 + ** into the database file header. */ + usableSize = pageSize - page1[20]; + if( (u32)pageSize!=pBt->pageSize ){ + /* After reading the first page of the database assuming a page size + ** of BtShared.pageSize, we have discovered that the page-size is + ** actually pageSize. Unlock the database, leave pBt->pPage1 at + ** zero and return SQLITE_OK. The caller will call this function + ** again with the correct page-size. + */ + releasePage(pPage1); + pBt->usableSize = usableSize; + pBt->pageSize = pageSize; + freeTempSpace(pBt); + rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, + pageSize-usableSize); + return rc; + } + if( (pBt->db->flags & SQLITE_RecoveryMode)==0 && nPage>nPageFile ){ + rc = SQLITE_CORRUPT_BKPT; + goto page1_init_failed; + } + /* EVIDENCE-OF: R-28312-64704 However, the usable size is not allowed to + ** be less than 480. In other words, if the page size is 512, then the + ** reserved space size cannot exceed 32. */ + if( usableSize<480 ){ + goto page1_init_failed; + } + pBt->pageSize = pageSize; + pBt->usableSize = usableSize; +#ifndef SQLITE_OMIT_AUTOVACUUM + pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0); + pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0); +#endif + } + + /* maxLocal is the maximum amount of payload to store locally for + ** a cell. Make sure it is small enough so that at least minFanout + ** cells can will fit on one page. We assume a 10-byte page header. + ** Besides the payload, the cell must store: + ** 2-byte pointer to the cell + ** 4-byte child pointer + ** 9-byte nKey value + ** 4-byte nData value + ** 4-byte overflow page pointer + ** So a cell consists of a 2-byte pointer, a header which is as much as + ** 17 bytes long, 0 to N bytes of payload, and an optional 4 byte overflow + ** page pointer. + */ + pBt->maxLocal = (u16)((pBt->usableSize-12)*64/255 - 23); + pBt->minLocal = (u16)((pBt->usableSize-12)*32/255 - 23); + pBt->maxLeaf = (u16)(pBt->usableSize - 35); + pBt->minLeaf = (u16)((pBt->usableSize-12)*32/255 - 23); + if( pBt->maxLocal>127 ){ + pBt->max1bytePayload = 127; + }else{ + pBt->max1bytePayload = (u8)pBt->maxLocal; + } + assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) ); + pBt->pPage1 = pPage1; + pBt->nPage = nPage; + return SQLITE_OK; + +page1_init_failed: + releasePage(pPage1); + pBt->pPage1 = 0; + return rc; +} + +#ifndef NDEBUG +/* +** Return the number of cursors open on pBt. This is for use +** in assert() expressions, so it is only compiled if NDEBUG is not +** defined. +** +** Only write cursors are counted if wrOnly is true. If wrOnly is +** false then all cursors are counted. +** +** For the purposes of this routine, a cursor is any cursor that +** is capable of reading or writing to the database. Cursors that +** have been tripped into the CURSOR_FAULT state are not counted. +*/ +static int countValidCursors(BtShared *pBt, int wrOnly){ + BtCursor *pCur; + int r = 0; + for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ + if( (wrOnly==0 || (pCur->curFlags & BTCF_WriteFlag)!=0) + && pCur->eState!=CURSOR_FAULT ) r++; + } + return r; +} +#endif + +/* +** If there are no outstanding cursors and we are not in the middle +** of a transaction but there is a read lock on the database, then +** this routine unrefs the first page of the database file which +** has the effect of releasing the read lock. +** +** If there is a transaction in progress, this routine is a no-op. +*/ +static void unlockBtreeIfUnused(BtShared *pBt){ + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>TRANS_NONE ); + if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){ + MemPage *pPage1 = pBt->pPage1; + assert( pPage1->aData ); + assert( sqlite3PagerRefcount(pBt->pPager)==1 ); + pBt->pPage1 = 0; + releasePageNotNull(pPage1); + } +} + +/* +** If pBt points to an empty file then convert that empty file +** into a new empty database by initializing the first page of +** the database. +*/ +static int newDatabase(BtShared *pBt){ + MemPage *pP1; + unsigned char *data; + int rc; + + assert( sqlite3_mutex_held(pBt->mutex) ); + if( pBt->nPage>0 ){ + return SQLITE_OK; + } + pP1 = pBt->pPage1; + assert( pP1!=0 ); + data = pP1->aData; + rc = sqlite3PagerWrite(pP1->pDbPage); + if( rc ) return rc; + memcpy(data, zMagicHeader, sizeof(zMagicHeader)); + assert( sizeof(zMagicHeader)==16 ); + data[16] = (u8)((pBt->pageSize>>8)&0xff); + data[17] = (u8)((pBt->pageSize>>16)&0xff); + data[18] = 1; + data[19] = 1; + assert( pBt->usableSize<=pBt->pageSize && pBt->usableSize+255>=pBt->pageSize); + data[20] = (u8)(pBt->pageSize - pBt->usableSize); + data[21] = 64; + data[22] = 32; + data[23] = 32; + memset(&data[24], 0, 100-24); + zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA ); + pBt->btsFlags |= BTS_PAGESIZE_FIXED; +#ifndef SQLITE_OMIT_AUTOVACUUM + assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 ); + assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 ); + put4byte(&data[36 + 4*4], pBt->autoVacuum); + put4byte(&data[36 + 7*4], pBt->incrVacuum); +#endif + pBt->nPage = 1; + data[31] = 1; + return SQLITE_OK; +} + +/* +** Initialize the first page of the database file (creating a database +** consisting of a single page and no schema objects). Return SQLITE_OK +** if successful, or an SQLite error code otherwise. +*/ +SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){ + int rc; + sqlite3BtreeEnter(p); + p->pBt->nPage = 0; + rc = newDatabase(p->pBt); + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Attempt to start a new transaction. A write-transaction +** is started if the second argument is nonzero, otherwise a read- +** transaction. If the second argument is 2 or more and exclusive +** transaction is started, meaning that no other process is allowed +** to access the database. A preexisting transaction may not be +** upgraded to exclusive by calling this routine a second time - the +** exclusivity flag only works for a new transaction. +** +** A write-transaction must be started before attempting any +** changes to the database. None of the following routines +** will work unless a transaction is started first: +** +** sqlite3BtreeCreateTable() +** sqlite3BtreeCreateIndex() +** sqlite3BtreeClearTable() +** sqlite3BtreeDropTable() +** sqlite3BtreeInsert() +** sqlite3BtreeDelete() +** sqlite3BtreeUpdateMeta() +** +** If an initial attempt to acquire the lock fails because of lock contention +** and the database was previously unlocked, then invoke the busy handler +** if there is one. But if there was previously a read-lock, do not +** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is +** returned when there is already a read-lock in order to avoid a deadlock. +** +** Suppose there are two processes A and B. A has a read lock and B has +** a reserved lock. B tries to promote to exclusive but is blocked because +** of A's read lock. A tries to promote to reserved but is blocked by B. +** One or the other of the two processes must give way or there can be +** no progress. By returning SQLITE_BUSY and not invoking the busy callback +** when A already has a read lock, we encourage A to give up and let B +** proceed. +*/ +SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ + sqlite3 *pBlock = 0; + BtShared *pBt = p->pBt; + int rc = SQLITE_OK; + + sqlite3BtreeEnter(p); + btreeIntegrity(p); + + /* If the btree is already in a write-transaction, or it + ** is already in a read-transaction and a read-transaction + ** is requested, this is a no-op. + */ + if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ + goto trans_begun; + } + assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 ); + + /* Write transactions are not possible on a read-only database */ + if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){ + rc = SQLITE_READONLY; + goto trans_begun; + } + +#ifndef SQLITE_OMIT_SHARED_CACHE + /* If another database handle has already opened a write transaction + ** on this shared-btree structure and a second write transaction is + ** requested, return SQLITE_LOCKED. + */ + if( (wrflag && pBt->inTransaction==TRANS_WRITE) + || (pBt->btsFlags & BTS_PENDING)!=0 + ){ + pBlock = pBt->pWriter->db; + }else if( wrflag>1 ){ + BtLock *pIter; + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + if( pIter->pBtree!=p ){ + pBlock = pIter->pBtree->db; + break; + } + } + } + if( pBlock ){ + sqlite3ConnectionBlocked(p->db, pBlock); + rc = SQLITE_LOCKED_SHAREDCACHE; + goto trans_begun; + } +#endif + + /* Any read-only or read-write transaction implies a read-lock on + ** page 1. So if some other shared-cache client already has a write-lock + ** on page 1, the transaction cannot be opened. */ + rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK); + if( SQLITE_OK!=rc ) goto trans_begun; + + pBt->btsFlags &= ~BTS_INITIALLY_EMPTY; + if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY; + do { + /* Call lockBtree() until either pBt->pPage1 is populated or + ** lockBtree() returns something other than SQLITE_OK. lockBtree() + ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after + ** reading page 1 it discovers that the page-size of the database + ** file is not pBt->pageSize. In this case lockBtree() will update + ** pBt->pageSize to the page-size of the file on disk. + */ + while( pBt->pPage1==0 && SQLITE_OK==(rc = lockBtree(pBt)) ); + + if( rc==SQLITE_OK && wrflag ){ + if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){ + rc = SQLITE_READONLY; + }else{ + rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db)); + if( rc==SQLITE_OK ){ + rc = newDatabase(pBt); + } + } + } + + if( rc!=SQLITE_OK ){ + unlockBtreeIfUnused(pBt); + } + }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && + btreeInvokeBusyHandler(pBt) ); + + if( rc==SQLITE_OK ){ + if( p->inTrans==TRANS_NONE ){ + pBt->nTransaction++; +#ifndef SQLITE_OMIT_SHARED_CACHE + if( p->sharable ){ + assert( p->lock.pBtree==p && p->lock.iTable==1 ); + p->lock.eLock = READ_LOCK; + p->lock.pNext = pBt->pLock; + pBt->pLock = &p->lock; + } +#endif + } + p->inTrans = (wrflag?TRANS_WRITE:TRANS_READ); + if( p->inTrans>pBt->inTransaction ){ + pBt->inTransaction = p->inTrans; + } + if( wrflag ){ + MemPage *pPage1 = pBt->pPage1; +#ifndef SQLITE_OMIT_SHARED_CACHE + assert( !pBt->pWriter ); + pBt->pWriter = p; + pBt->btsFlags &= ~BTS_EXCLUSIVE; + if( wrflag>1 ) pBt->btsFlags |= BTS_EXCLUSIVE; +#endif + + /* If the db-size header field is incorrect (as it may be if an old + ** client has been writing the database file), update it now. Doing + ** this sooner rather than later means the database size can safely + ** re-read the database size from page 1 if a savepoint or transaction + ** rollback occurs within the transaction. + */ + if( pBt->nPage!=get4byte(&pPage1->aData[28]) ){ + rc = sqlite3PagerWrite(pPage1->pDbPage); + if( rc==SQLITE_OK ){ + put4byte(&pPage1->aData[28], pBt->nPage); + } + } + } + } + + +trans_begun: + if( rc==SQLITE_OK && wrflag ){ + /* This call makes sure that the pager has the correct number of + ** open savepoints. If the second parameter is greater than 0 and + ** the sub-journal is not already open, then it will be opened here. + */ + rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint); + } + + btreeIntegrity(p); + sqlite3BtreeLeave(p); + return rc; +} + +#ifndef SQLITE_OMIT_AUTOVACUUM + +/* +** Set the pointer-map entries for all children of page pPage. Also, if +** pPage contains cells that point to overflow pages, set the pointer +** map entries for the overflow pages as well. +*/ +static int setChildPtrmaps(MemPage *pPage){ + int i; /* Counter variable */ + int nCell; /* Number of cells in page pPage */ + int rc; /* Return code */ + BtShared *pBt = pPage->pBt; + u8 isInitOrig = pPage->isInit; + Pgno pgno = pPage->pgno; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + rc = btreeInitPage(pPage); + if( rc!=SQLITE_OK ){ + goto set_child_ptrmaps_out; + } + nCell = pPage->nCell; + + for(i=0; ileaf ){ + Pgno childPgno = get4byte(pCell); + ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc); + } + } + + if( !pPage->leaf ){ + Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); + ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc); + } + +set_child_ptrmaps_out: + pPage->isInit = isInitOrig; + return rc; +} + +/* +** Somewhere on pPage is a pointer to page iFrom. Modify this pointer so +** that it points to iTo. Parameter eType describes the type of pointer to +** be modified, as follows: +** +** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child +** page of pPage. +** +** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow +** page pointed to by one of the cells on pPage. +** +** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next +** overflow page in the list. +*/ +static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + if( eType==PTRMAP_OVERFLOW2 ){ + /* The pointer is always the first 4 bytes of the page in this case. */ + if( get4byte(pPage->aData)!=iFrom ){ + return SQLITE_CORRUPT_BKPT; + } + put4byte(pPage->aData, iTo); + }else{ + u8 isInitOrig = pPage->isInit; + int i; + int nCell; + int rc; + + rc = btreeInitPage(pPage); + if( rc ) return rc; + nCell = pPage->nCell; + + for(i=0; ixParseCell(pPage, pCell, &info); + if( info.iOverflow + && pCell+info.iOverflow+3<=pPage->aData+pPage->maskPage + && iFrom==get4byte(&pCell[info.iOverflow]) + ){ + put4byte(&pCell[info.iOverflow], iTo); + break; + } + }else{ + if( get4byte(pCell)==iFrom ){ + put4byte(pCell, iTo); + break; + } + } + } + + if( i==nCell ){ + if( eType!=PTRMAP_BTREE || + get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ + return SQLITE_CORRUPT_BKPT; + } + put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); + } + + pPage->isInit = isInitOrig; + } + return SQLITE_OK; +} + + +/* +** Move the open database page pDbPage to location iFreePage in the +** database. The pDbPage reference remains valid. +** +** The isCommit flag indicates that there is no need to remember that +** the journal needs to be sync()ed before database page pDbPage->pgno +** can be written to. The caller has already promised not to write to that +** page. +*/ +static int relocatePage( + BtShared *pBt, /* Btree */ + MemPage *pDbPage, /* Open page to move */ + u8 eType, /* Pointer map 'type' entry for pDbPage */ + Pgno iPtrPage, /* Pointer map 'page-no' entry for pDbPage */ + Pgno iFreePage, /* The location to move pDbPage to */ + int isCommit /* isCommit flag passed to sqlite3PagerMovepage */ +){ + MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */ + Pgno iDbPage = pDbPage->pgno; + Pager *pPager = pBt->pPager; + int rc; + + assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || + eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pDbPage->pBt==pBt ); + + /* Move page iDbPage from its current location to page number iFreePage */ + TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", + iDbPage, iFreePage, iPtrPage, eType)); + rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit); + if( rc!=SQLITE_OK ){ + return rc; + } + pDbPage->pgno = iFreePage; + + /* If pDbPage was a btree-page, then it may have child pages and/or cells + ** that point to overflow pages. The pointer map entries for all these + ** pages need to be changed. + ** + ** If pDbPage is an overflow page, then the first 4 bytes may store a + ** pointer to a subsequent overflow page. If this is the case, then + ** the pointer map needs to be updated for the subsequent overflow page. + */ + if( eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ){ + rc = setChildPtrmaps(pDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + }else{ + Pgno nextOvfl = get4byte(pDbPage->aData); + if( nextOvfl!=0 ){ + ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage, &rc); + if( rc!=SQLITE_OK ){ + return rc; + } + } + } + + /* Fix the database pointer on page iPtrPage that pointed at iDbPage so + ** that it points at iFreePage. Also fix the pointer map entry for + ** iPtrPage. + */ + if( eType!=PTRMAP_ROOTPAGE ){ + rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3PagerWrite(pPtrPage->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pPtrPage); + return rc; + } + rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType); + releasePage(pPtrPage); + if( rc==SQLITE_OK ){ + ptrmapPut(pBt, iFreePage, eType, iPtrPage, &rc); + } + } + return rc; +} + +/* Forward declaration required by incrVacuumStep(). */ +static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); + +/* +** Perform a single step of an incremental-vacuum. If successful, return +** SQLITE_OK. If there is no work to do (and therefore no point in +** calling this function again), return SQLITE_DONE. Or, if an error +** occurs, return some other error code. +** +** More specifically, this function attempts to re-organize the database so +** that the last page of the file currently in use is no longer in use. +** +** Parameter nFin is the number of pages that this database would contain +** were this function called until it returns SQLITE_DONE. +** +** If the bCommit parameter is non-zero, this function assumes that the +** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE +** or an error. bCommit is passed true for an auto-vacuum-on-commit +** operation, or false for an incremental vacuum. +*/ +static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){ + Pgno nFreeList; /* Number of pages still on the free-list */ + int rc; + + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( iLastPg>nFin ); + + if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){ + u8 eType; + Pgno iPtrPage; + + nFreeList = get4byte(&pBt->pPage1->aData[36]); + if( nFreeList==0 ){ + return SQLITE_DONE; + } + + rc = ptrmapGet(pBt, iLastPg, &eType, &iPtrPage); + if( rc!=SQLITE_OK ){ + return rc; + } + if( eType==PTRMAP_ROOTPAGE ){ + return SQLITE_CORRUPT_BKPT; + } + + if( eType==PTRMAP_FREEPAGE ){ + if( bCommit==0 ){ + /* Remove the page from the files free-list. This is not required + ** if bCommit is non-zero. In that case, the free-list will be + ** truncated to zero after this function returns, so it doesn't + ** matter if it still contains some garbage entries. + */ + Pgno iFreePg; + MemPage *pFreePg; + rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, BTALLOC_EXACT); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( iFreePg==iLastPg ); + releasePage(pFreePg); + } + } else { + Pgno iFreePg; /* Index of free page to move pLastPg to */ + MemPage *pLastPg; + u8 eMode = BTALLOC_ANY; /* Mode parameter for allocateBtreePage() */ + Pgno iNear = 0; /* nearby parameter for allocateBtreePage() */ + + rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + + /* If bCommit is zero, this loop runs exactly once and page pLastPg + ** is swapped with the first free page pulled off the free list. + ** + ** On the other hand, if bCommit is greater than zero, then keep + ** looping until a free-page located within the first nFin pages + ** of the file is found. + */ + if( bCommit==0 ){ + eMode = BTALLOC_LE; + iNear = nFin; + } + do { + MemPage *pFreePg; + rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode); + if( rc!=SQLITE_OK ){ + releasePage(pLastPg); + return rc; + } + releasePage(pFreePg); + }while( bCommit && iFreePg>nFin ); + assert( iFreePgbDoTruncate = 1; + pBt->nPage = iLastPg; + } + return SQLITE_OK; +} + +/* +** The database opened by the first argument is an auto-vacuum database +** nOrig pages in size containing nFree free pages. Return the expected +** size of the database in pages following an auto-vacuum operation. +*/ +static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){ + int nEntry; /* Number of entries on one ptrmap page */ + Pgno nPtrmap; /* Number of PtrMap pages to be freed */ + Pgno nFin; /* Return value */ + + nEntry = pBt->usableSize/5; + nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry; + nFin = nOrig - nFree - nPtrmap; + if( nOrig>PENDING_BYTE_PAGE(pBt) && nFinpBt; + + sqlite3BtreeEnter(p); + assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE ); + if( !pBt->autoVacuum ){ + rc = SQLITE_DONE; + }else{ + Pgno nOrig = btreePagecount(pBt); + Pgno nFree = get4byte(&pBt->pPage1->aData[36]); + Pgno nFin = finalDbSize(pBt, nOrig, nFree); + + if( nOrig0 ){ + rc = saveAllCursors(pBt, 0, 0); + if( rc==SQLITE_OK ){ + invalidateAllOverflowCache(pBt); + rc = incrVacuumStep(pBt, nFin, nOrig, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + put4byte(&pBt->pPage1->aData[28], pBt->nPage); + } + }else{ + rc = SQLITE_DONE; + } + } + sqlite3BtreeLeave(p); + return rc; +} + +/* +** This routine is called prior to sqlite3PagerCommit when a transaction +** is committed for an auto-vacuum database. +** +** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages +** the database file should be truncated to during the commit process. +** i.e. the database has been reorganized so that only the first *pnTrunc +** pages are in use. +*/ +static int autoVacuumCommit(BtShared *pBt){ + int rc = SQLITE_OK; + Pager *pPager = pBt->pPager; + VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager); ) + + assert( sqlite3_mutex_held(pBt->mutex) ); + invalidateAllOverflowCache(pBt); + assert(pBt->autoVacuum); + if( !pBt->incrVacuum ){ + Pgno nFin; /* Number of pages in database after autovacuuming */ + Pgno nFree; /* Number of pages on the freelist initially */ + Pgno iFree; /* The next page to be freed */ + Pgno nOrig; /* Database size before freeing */ + + nOrig = btreePagecount(pBt); + if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){ + /* It is not possible to create a database for which the final page + ** is either a pointer-map page or the pending-byte page. If one + ** is encountered, this indicates corruption. + */ + return SQLITE_CORRUPT_BKPT; + } + + nFree = get4byte(&pBt->pPage1->aData[36]); + nFin = finalDbSize(pBt, nOrig, nFree); + if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT; + if( nFinnFin && rc==SQLITE_OK; iFree--){ + rc = incrVacuumStep(pBt, nFin, iFree, 1); + } + if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){ + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + put4byte(&pBt->pPage1->aData[32], 0); + put4byte(&pBt->pPage1->aData[36], 0); + put4byte(&pBt->pPage1->aData[28], nFin); + pBt->bDoTruncate = 1; + pBt->nPage = nFin; + } + if( rc!=SQLITE_OK ){ + sqlite3PagerRollback(pPager); + } + } + + assert( nRef>=sqlite3PagerRefcount(pPager) ); + return rc; +} + +#else /* ifndef SQLITE_OMIT_AUTOVACUUM */ +# define setChildPtrmaps(x) SQLITE_OK +#endif + +/* +** This routine does the first phase of a two-phase commit. This routine +** causes a rollback journal to be created (if it does not already exist) +** and populated with enough information so that if a power loss occurs +** the database can be restored to its original state by playing back +** the journal. Then the contents of the journal are flushed out to +** the disk. After the journal is safely on oxide, the changes to the +** database are written into the database file and flushed to oxide. +** At the end of this call, the rollback journal still exists on the +** disk and we are still holding all locks, so the transaction has not +** committed. See sqlite3BtreeCommitPhaseTwo() for the second phase of the +** commit process. +** +** This call is a no-op if no write-transaction is currently active on pBt. +** +** Otherwise, sync the database file for the btree pBt. zMaster points to +** the name of a master journal file that should be written into the +** individual journal file, or is NULL, indicating no master journal file +** (single database transaction). +** +** When this is called, the master journal should already have been +** created, populated with this journal pointer and synced to disk. +** +** Once this is routine has returned, the only thing required to commit +** the write-transaction for this database file is to delete the journal. +*/ +SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){ + int rc = SQLITE_OK; + if( p->inTrans==TRANS_WRITE ){ + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + rc = autoVacuumCommit(pBt); + if( rc!=SQLITE_OK ){ + sqlite3BtreeLeave(p); + return rc; + } + } + if( pBt->bDoTruncate ){ + sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage); + } +#endif + rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0); + sqlite3BtreeLeave(p); + } + return rc; +} + +/* +** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback() +** at the conclusion of a transaction. +*/ +static void btreeEndTransaction(Btree *p){ + BtShared *pBt = p->pBt; + sqlite3 *db = p->db; + assert( sqlite3BtreeHoldsMutex(p) ); + +#ifndef SQLITE_OMIT_AUTOVACUUM + pBt->bDoTruncate = 0; +#endif + if( p->inTrans>TRANS_NONE && db->nVdbeRead>1 ){ + /* If there are other active statements that belong to this database + ** handle, downgrade to a read-only transaction. The other statements + ** may still be reading from the database. */ + downgradeAllSharedCacheTableLocks(p); + p->inTrans = TRANS_READ; + }else{ + /* If the handle had any kind of transaction open, decrement the + ** transaction count of the shared btree. If the transaction count + ** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused() + ** call below will unlock the pager. */ + if( p->inTrans!=TRANS_NONE ){ + clearAllSharedCacheTableLocks(p); + pBt->nTransaction--; + if( 0==pBt->nTransaction ){ + pBt->inTransaction = TRANS_NONE; + } + } + + /* Set the current transaction state to TRANS_NONE and unlock the + ** pager if this call closed the only read or write transaction. */ + p->inTrans = TRANS_NONE; + unlockBtreeIfUnused(pBt); + } + + btreeIntegrity(p); +} + +/* +** Commit the transaction currently in progress. +** +** This routine implements the second phase of a 2-phase commit. The +** sqlite3BtreeCommitPhaseOne() routine does the first phase and should +** be invoked prior to calling this routine. The sqlite3BtreeCommitPhaseOne() +** routine did all the work of writing information out to disk and flushing the +** contents so that they are written onto the disk platter. All this +** routine has to do is delete or truncate or zero the header in the +** the rollback journal (which causes the transaction to commit) and +** drop locks. +** +** Normally, if an error occurs while the pager layer is attempting to +** finalize the underlying journal file, this function returns an error and +** the upper layer will attempt a rollback. However, if the second argument +** is non-zero then this b-tree transaction is part of a multi-file +** transaction. In this case, the transaction has already been committed +** (by deleting a master journal file) and the caller will ignore this +** functions return code. So, even if an error occurs in the pager layer, +** reset the b-tree objects internal state to indicate that the write +** transaction has been closed. This is quite safe, as the pager will have +** transitioned to the error state. +** +** This will release the write lock on the database file. If there +** are no active cursors, it also releases the read lock. +*/ +SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){ + + if( p->inTrans==TRANS_NONE ) return SQLITE_OK; + sqlite3BtreeEnter(p); + btreeIntegrity(p); + + /* If the handle has a write-transaction open, commit the shared-btrees + ** transaction and set the shared state to TRANS_READ. + */ + if( p->inTrans==TRANS_WRITE ){ + int rc; + BtShared *pBt = p->pBt; + assert( pBt->inTransaction==TRANS_WRITE ); + assert( pBt->nTransaction>0 ); + rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); + if( rc!=SQLITE_OK && bCleanup==0 ){ + sqlite3BtreeLeave(p); + return rc; + } + p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */ + pBt->inTransaction = TRANS_READ; + btreeClearHasContent(pBt); + } + + btreeEndTransaction(p); + sqlite3BtreeLeave(p); + return SQLITE_OK; +} + +/* +** Do both phases of a commit. +*/ +SQLITE_PRIVATE int sqlite3BtreeCommit(Btree *p){ + int rc; + sqlite3BtreeEnter(p); + rc = sqlite3BtreeCommitPhaseOne(p, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeCommitPhaseTwo(p, 0); + } + sqlite3BtreeLeave(p); + return rc; +} + +/* +** This routine sets the state to CURSOR_FAULT and the error +** code to errCode for every cursor on any BtShared that pBtree +** references. Or if the writeOnly flag is set to 1, then only +** trip write cursors and leave read cursors unchanged. +** +** Every cursor is a candidate to be tripped, including cursors +** that belong to other database connections that happen to be +** sharing the cache with pBtree. +** +** This routine gets called when a rollback occurs. If the writeOnly +** flag is true, then only write-cursors need be tripped - read-only +** cursors save their current positions so that they may continue +** following the rollback. Or, if writeOnly is false, all cursors are +** tripped. In general, writeOnly is false if the transaction being +** rolled back modified the database schema. In this case b-tree root +** pages may be moved or deleted from the database altogether, making +** it unsafe for read cursors to continue. +** +** If the writeOnly flag is true and an error is encountered while +** saving the current position of a read-only cursor, all cursors, +** including all read-cursors are tripped. +** +** SQLITE_OK is returned if successful, or if an error occurs while +** saving a cursor position, an SQLite error code. +*/ +SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){ + BtCursor *p; + int rc = SQLITE_OK; + + assert( (writeOnly==0 || writeOnly==1) && BTCF_WriteFlag==1 ); + if( pBtree ){ + sqlite3BtreeEnter(pBtree); + for(p=pBtree->pBt->pCursor; p; p=p->pNext){ + int i; + if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){ + if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ + rc = saveCursorPosition(p); + if( rc!=SQLITE_OK ){ + (void)sqlite3BtreeTripAllCursors(pBtree, rc, 0); + break; + } + } + }else{ + sqlite3BtreeClearCursor(p); + p->eState = CURSOR_FAULT; + p->skipNext = errCode; + } + for(i=0; i<=p->iPage; i++){ + releasePage(p->apPage[i]); + p->apPage[i] = 0; + } + } + sqlite3BtreeLeave(pBtree); + } + return rc; +} + +/* +** Rollback the transaction in progress. +** +** If tripCode is not SQLITE_OK then cursors will be invalidated (tripped). +** Only write cursors are tripped if writeOnly is true but all cursors are +** tripped if writeOnly is false. Any attempt to use +** a tripped cursor will result in an error. +** +** This will release the write lock on the database file. If there +** are no active cursors, it also releases the read lock. +*/ +SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){ + int rc; + BtShared *pBt = p->pBt; + MemPage *pPage1; + + assert( writeOnly==1 || writeOnly==0 ); + assert( tripCode==SQLITE_ABORT_ROLLBACK || tripCode==SQLITE_OK ); + sqlite3BtreeEnter(p); + if( tripCode==SQLITE_OK ){ + rc = tripCode = saveAllCursors(pBt, 0, 0); + if( rc ) writeOnly = 0; + }else{ + rc = SQLITE_OK; + } + if( tripCode ){ + int rc2 = sqlite3BtreeTripAllCursors(p, tripCode, writeOnly); + assert( rc==SQLITE_OK || (writeOnly==0 && rc2==SQLITE_OK) ); + if( rc2!=SQLITE_OK ) rc = rc2; + } + btreeIntegrity(p); + + if( p->inTrans==TRANS_WRITE ){ + int rc2; + + assert( TRANS_WRITE==pBt->inTransaction ); + rc2 = sqlite3PagerRollback(pBt->pPager); + if( rc2!=SQLITE_OK ){ + rc = rc2; + } + + /* The rollback may have destroyed the pPage1->aData value. So + ** call btreeGetPage() on page 1 again to make + ** sure pPage1->aData is set correctly. */ + if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){ + int nPage = get4byte(28+(u8*)pPage1->aData); + testcase( nPage==0 ); + if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage); + testcase( pBt->nPage!=nPage ); + pBt->nPage = nPage; + releasePage(pPage1); + } + assert( countValidCursors(pBt, 1)==0 ); + pBt->inTransaction = TRANS_READ; + btreeClearHasContent(pBt); + } + + btreeEndTransaction(p); + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Start a statement subtransaction. The subtransaction can be rolled +** back independently of the main transaction. You must start a transaction +** before starting a subtransaction. The subtransaction is ended automatically +** if the main transaction commits or rolls back. +** +** Statement subtransactions are used around individual SQL statements +** that are contained within a BEGIN...COMMIT block. If a constraint +** error occurs within the statement, the effect of that one statement +** can be rolled back without having to rollback the entire transaction. +** +** A statement sub-transaction is implemented as an anonymous savepoint. The +** value passed as the second parameter is the total number of savepoints, +** including the new anonymous savepoint, open on the B-Tree. i.e. if there +** are no active savepoints and no other statement-transactions open, +** iStatement is 1. This anonymous savepoint can be released or rolled back +** using the sqlite3BtreeSavepoint() function. +*/ +SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree *p, int iStatement){ + int rc; + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + assert( p->inTrans==TRANS_WRITE ); + assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); + assert( iStatement>0 ); + assert( iStatement>p->db->nSavepoint ); + assert( pBt->inTransaction==TRANS_WRITE ); + /* At the pager level, a statement transaction is a savepoint with + ** an index greater than all savepoints created explicitly using + ** SQL statements. It is illegal to open, release or rollback any + ** such savepoints while the statement transaction savepoint is active. + */ + rc = sqlite3PagerOpenSavepoint(pBt->pPager, iStatement); + sqlite3BtreeLeave(p); + return rc; +} + +/* +** The second argument to this function, op, is always SAVEPOINT_ROLLBACK +** or SAVEPOINT_RELEASE. This function either releases or rolls back the +** savepoint identified by parameter iSavepoint, depending on the value +** of op. +** +** Normally, iSavepoint is greater than or equal to zero. However, if op is +** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the +** contents of the entire transaction are rolled back. This is different +** from a normal transaction rollback, as no locks are released and the +** transaction remains open. +*/ +SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){ + int rc = SQLITE_OK; + if( p && p->inTrans==TRANS_WRITE ){ + BtShared *pBt = p->pBt; + assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK ); + assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) ); + sqlite3BtreeEnter(p); + rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint); + if( rc==SQLITE_OK ){ + if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){ + pBt->nPage = 0; + } + rc = newDatabase(pBt); + pBt->nPage = get4byte(28 + pBt->pPage1->aData); + + /* The database size was written into the offset 28 of the header + ** when the transaction started, so we know that the value at offset + ** 28 is nonzero. */ + assert( pBt->nPage>0 ); + } + sqlite3BtreeLeave(p); + } + return rc; +} + +/* +** Create a new cursor for the BTree whose root is on the page +** iTable. If a read-only cursor is requested, it is assumed that +** the caller already has at least a read-only transaction open +** on the database already. If a write-cursor is requested, then +** the caller is assumed to have an open write transaction. +** +** If wrFlag==0, then the cursor can only be used for reading. +** If wrFlag==1, then the cursor can be used for reading or for +** writing if other conditions for writing are also met. These +** are the conditions that must be met in order for writing to +** be allowed: +** +** 1: The cursor must have been opened with wrFlag==1 +** +** 2: Other database connections that share the same pager cache +** but which are not in the READ_UNCOMMITTED state may not have +** cursors open with wrFlag==0 on the same table. Otherwise +** the changes made by this write cursor would be visible to +** the read cursors in the other database connection. +** +** 3: The database must be writable (not on read-only media) +** +** 4: There must be an active transaction. +** +** No checking is done to make sure that page iTable really is the +** root page of a b-tree. If it is not, then the cursor acquired +** will not work correctly. +** +** It is assumed that the sqlite3BtreeCursorZero() has been called +** on pCur to initialize the memory space prior to invoking this routine. +*/ +static int btreeCursor( + Btree *p, /* The btree */ + int iTable, /* Root page of table to open */ + int wrFlag, /* 1 to write. 0 read-only */ + struct KeyInfo *pKeyInfo, /* First arg to comparison function */ + BtCursor *pCur /* Space for new cursor */ +){ + BtShared *pBt = p->pBt; /* Shared b-tree handle */ + BtCursor *pX; /* Looping over other all cursors */ + + assert( sqlite3BtreeHoldsMutex(p) ); + assert( wrFlag==0 || wrFlag==1 ); + + /* The following assert statements verify that if this is a sharable + ** b-tree database, the connection is holding the required table locks, + ** and that no other connection has any open cursor that conflicts with + ** this lock. */ + assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, wrFlag+1) ); + assert( wrFlag==0 || !hasReadConflicts(p, iTable) ); + + /* Assert that the caller has opened the required transaction. */ + assert( p->inTrans>TRANS_NONE ); + assert( wrFlag==0 || p->inTrans==TRANS_WRITE ); + assert( pBt->pPage1 && pBt->pPage1->aData ); + assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 ); + + if( wrFlag ){ + allocateTempSpace(pBt); + if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM; + } + if( iTable==1 && btreePagecount(pBt)==0 ){ + assert( wrFlag==0 ); + iTable = 0; + } + + /* Now that no other errors can occur, finish filling in the BtCursor + ** variables and link the cursor into the BtShared list. */ + pCur->pgnoRoot = (Pgno)iTable; + pCur->iPage = -1; + pCur->pKeyInfo = pKeyInfo; + pCur->pBtree = p; + pCur->pBt = pBt; + assert( wrFlag==0 || wrFlag==BTCF_WriteFlag ); + pCur->curFlags = wrFlag; + pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY; + /* If there are two or more cursors on the same btree, then all such + ** cursors *must* have the BTCF_Multiple flag set. */ + for(pX=pBt->pCursor; pX; pX=pX->pNext){ + if( pX->pgnoRoot==(Pgno)iTable ){ + pX->curFlags |= BTCF_Multiple; + pCur->curFlags |= BTCF_Multiple; + } + } + pCur->pNext = pBt->pCursor; + pBt->pCursor = pCur; + pCur->eState = CURSOR_INVALID; + return SQLITE_OK; +} +SQLITE_PRIVATE int sqlite3BtreeCursor( + Btree *p, /* The btree */ + int iTable, /* Root page of table to open */ + int wrFlag, /* 1 to write. 0 read-only */ + struct KeyInfo *pKeyInfo, /* First arg to xCompare() */ + BtCursor *pCur /* Write new cursor here */ +){ + int rc; + if( iTable<1 ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + sqlite3BtreeEnter(p); + rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); + sqlite3BtreeLeave(p); + } + return rc; +} + +/* +** Return the size of a BtCursor object in bytes. +** +** This interfaces is needed so that users of cursors can preallocate +** sufficient storage to hold a cursor. The BtCursor object is opaque +** to users so they cannot do the sizeof() themselves - they must call +** this routine. +*/ +SQLITE_PRIVATE int sqlite3BtreeCursorSize(void){ + return ROUND8(sizeof(BtCursor)); +} + +/* +** Initialize memory that will be converted into a BtCursor object. +** +** The simple approach here would be to memset() the entire object +** to zero. But it turns out that the apPage[] and aiIdx[] arrays +** do not need to be zeroed and they are large, so we can save a lot +** of run-time by skipping the initialization of those elements. +*/ +SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){ + memset(p, 0, offsetof(BtCursor, iPage)); +} + +/* +** Close a cursor. The read lock on the database file is released +** when the last cursor is closed. +*/ +SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ + Btree *pBtree = pCur->pBtree; + if( pBtree ){ + int i; + BtShared *pBt = pCur->pBt; + sqlite3BtreeEnter(pBtree); + sqlite3BtreeClearCursor(pCur); + assert( pBt->pCursor!=0 ); + if( pBt->pCursor==pCur ){ + pBt->pCursor = pCur->pNext; + }else{ + BtCursor *pPrev = pBt->pCursor; + do{ + if( pPrev->pNext==pCur ){ + pPrev->pNext = pCur->pNext; + break; + } + pPrev = pPrev->pNext; + }while( ALWAYS(pPrev) ); + } + for(i=0; i<=pCur->iPage; i++){ + releasePage(pCur->apPage[i]); + } + unlockBtreeIfUnused(pBt); + sqlite3_free(pCur->aOverflow); + /* sqlite3_free(pCur); */ + sqlite3BtreeLeave(pBtree); + } + return SQLITE_OK; +} + +/* +** Make sure the BtCursor* given in the argument has a valid +** BtCursor.info structure. If it is not already valid, call +** btreeParseCell() to fill it in. +** +** BtCursor.info is a cache of the information in the current cell. +** Using this cache reduces the number of calls to btreeParseCell(). +*/ +#ifndef NDEBUG + static void assertCellInfo(BtCursor *pCur){ + CellInfo info; + int iPage = pCur->iPage; + memset(&info, 0, sizeof(info)); + btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info); + assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 ); + } +#else + #define assertCellInfo(x) +#endif +static SQLITE_NOINLINE void getCellInfo(BtCursor *pCur){ + if( pCur->info.nSize==0 ){ + int iPage = pCur->iPage; + pCur->curFlags |= BTCF_ValidNKey; + btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); + }else{ + assertCellInfo(pCur); + } +} + +#ifndef NDEBUG /* The next routine used only within assert() statements */ +/* +** Return true if the given BtCursor is valid. A valid cursor is one +** that is currently pointing to a row in a (non-empty) table. +** This is a verification routine is used only within assert() statements. +*/ +SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){ + return pCur && pCur->eState==CURSOR_VALID; +} +#endif /* NDEBUG */ + +/* +** Set *pSize to the size of the buffer needed to hold the value of +** the key for the current entry. If the cursor is not pointing +** to a valid entry, *pSize is set to 0. +** +** For a table with the INTKEY flag set, this routine returns the key +** itself, not the number of bytes in the key. +** +** The caller must position the cursor prior to invoking this routine. +** +** This routine cannot fail. It always returns SQLITE_OK. +*/ +SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + getCellInfo(pCur); + *pSize = pCur->info.nKey; + return SQLITE_OK; +} + +/* +** Set *pSize to the number of bytes of data in the entry the +** cursor currently points to. +** +** The caller must guarantee that the cursor is pointing to a non-NULL +** valid entry. In other words, the calling procedure must guarantee +** that the cursor has Cursor.eState==CURSOR_VALID. +** +** Failure is not possible. This function always returns SQLITE_OK. +** It might just as well be a procedure (returning void) but we continue +** to return an integer result code for historical reasons. +*/ +SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->iPage>=0 ); + assert( pCur->iPageapPage[pCur->iPage]->intKeyLeaf==1 ); + getCellInfo(pCur); + *pSize = pCur->info.nPayload; + return SQLITE_OK; +} + +/* +** Given the page number of an overflow page in the database (parameter +** ovfl), this function finds the page number of the next page in the +** linked list of overflow pages. If possible, it uses the auto-vacuum +** pointer-map data instead of reading the content of page ovfl to do so. +** +** If an error occurs an SQLite error code is returned. Otherwise: +** +** The page number of the next overflow page in the linked list is +** written to *pPgnoNext. If page ovfl is the last page in its linked +** list, *pPgnoNext is set to zero. +** +** If ppPage is not NULL, and a reference to the MemPage object corresponding +** to page number pOvfl was obtained, then *ppPage is set to point to that +** reference. It is the responsibility of the caller to call releasePage() +** on *ppPage to free the reference. In no reference was obtained (because +** the pointer-map was used to obtain the value for *pPgnoNext), then +** *ppPage is set to zero. +*/ +static int getOverflowPage( + BtShared *pBt, /* The database file */ + Pgno ovfl, /* Current overflow page number */ + MemPage **ppPage, /* OUT: MemPage handle (may be NULL) */ + Pgno *pPgnoNext /* OUT: Next overflow page number */ +){ + Pgno next = 0; + MemPage *pPage = 0; + int rc = SQLITE_OK; + + assert( sqlite3_mutex_held(pBt->mutex) ); + assert(pPgnoNext); + +#ifndef SQLITE_OMIT_AUTOVACUUM + /* Try to find the next page in the overflow list using the + ** autovacuum pointer-map pages. Guess that the next page in + ** the overflow list is page number (ovfl+1). If that guess turns + ** out to be wrong, fall back to loading the data of page + ** number ovfl to determine the next page number. + */ + if( pBt->autoVacuum ){ + Pgno pgno; + Pgno iGuess = ovfl+1; + u8 eType; + + while( PTRMAP_ISPAGE(pBt, iGuess) || iGuess==PENDING_BYTE_PAGE(pBt) ){ + iGuess++; + } + + if( iGuess<=btreePagecount(pBt) ){ + rc = ptrmapGet(pBt, iGuess, &eType, &pgno); + if( rc==SQLITE_OK && eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){ + next = iGuess; + rc = SQLITE_DONE; + } + } + } +#endif + + assert( next==0 || rc==SQLITE_DONE ); + if( rc==SQLITE_OK ){ + rc = btreeGetPage(pBt, ovfl, &pPage, (ppPage==0) ? PAGER_GET_READONLY : 0); + assert( rc==SQLITE_OK || pPage==0 ); + if( rc==SQLITE_OK ){ + next = get4byte(pPage->aData); + } + } + + *pPgnoNext = next; + if( ppPage ){ + *ppPage = pPage; + }else{ + releasePage(pPage); + } + return (rc==SQLITE_DONE ? SQLITE_OK : rc); +} + +/* +** Copy data from a buffer to a page, or from a page to a buffer. +** +** pPayload is a pointer to data stored on database page pDbPage. +** If argument eOp is false, then nByte bytes of data are copied +** from pPayload to the buffer pointed at by pBuf. If eOp is true, +** then sqlite3PagerWrite() is called on pDbPage and nByte bytes +** of data are copied from the buffer pBuf to pPayload. +** +** SQLITE_OK is returned on success, otherwise an error code. +*/ +static int copyPayload( + void *pPayload, /* Pointer to page data */ + void *pBuf, /* Pointer to buffer */ + int nByte, /* Number of bytes to copy */ + int eOp, /* 0 -> copy from page, 1 -> copy to page */ + DbPage *pDbPage /* Page containing pPayload */ +){ + if( eOp ){ + /* Copy data from buffer to page (a write operation) */ + int rc = sqlite3PagerWrite(pDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + memcpy(pPayload, pBuf, nByte); + }else{ + /* Copy data from page to buffer (a read operation) */ + memcpy(pBuf, pPayload, nByte); + } + return SQLITE_OK; +} + +/* +** This function is used to read or overwrite payload information +** for the entry that the pCur cursor is pointing to. The eOp +** argument is interpreted as follows: +** +** 0: The operation is a read. Populate the overflow cache. +** 1: The operation is a write. Populate the overflow cache. +** 2: The operation is a read. Do not populate the overflow cache. +** +** A total of "amt" bytes are read or written beginning at "offset". +** Data is read to or from the buffer pBuf. +** +** The content being read or written might appear on the main page +** or be scattered out on multiple overflow pages. +** +** If the current cursor entry uses one or more overflow pages and the +** eOp argument is not 2, this function may allocate space for and lazily +** populates the overflow page-list cache array (BtCursor.aOverflow). +** Subsequent calls use this cache to make seeking to the supplied offset +** more efficient. +** +** Once an overflow page-list cache has been allocated, it may be +** invalidated if some other cursor writes to the same table, or if +** the cursor is moved to a different row. Additionally, in auto-vacuum +** mode, the following events may invalidate an overflow page-list cache. +** +** * An incremental vacuum, +** * A commit in auto_vacuum="full" mode, +** * Creating a table (may require moving an overflow page). +*/ +static int accessPayload( + BtCursor *pCur, /* Cursor pointing to entry to read from */ + u32 offset, /* Begin reading this far into payload */ + u32 amt, /* Read this many bytes */ + unsigned char *pBuf, /* Write the bytes into this buffer */ + int eOp /* zero to read. non-zero to write. */ +){ + unsigned char *aPayload; + int rc = SQLITE_OK; + int iIdx = 0; + MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */ + BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ +#ifdef SQLITE_DIRECT_OVERFLOW_READ + unsigned char * const pBufStart = pBuf; + int bEnd; /* True if reading to end of data */ +#endif + + assert( pPage ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->aiIdx[pCur->iPage]nCell ); + assert( cursorHoldsMutex(pCur) ); + assert( eOp!=2 || offset==0 ); /* Always start from beginning for eOp==2 */ + + getCellInfo(pCur); + aPayload = pCur->info.pPayload; +#ifdef SQLITE_DIRECT_OVERFLOW_READ + bEnd = offset+amt==pCur->info.nPayload; +#endif + assert( offset+amt <= pCur->info.nPayload ); + + if( &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] ){ + /* Trying to read or write past the end of the data is an error */ + return SQLITE_CORRUPT_BKPT; + } + + /* Check if data must be read/written to/from the btree page itself. */ + if( offsetinfo.nLocal ){ + int a = amt; + if( a+offset>pCur->info.nLocal ){ + a = pCur->info.nLocal - offset; + } + rc = copyPayload(&aPayload[offset], pBuf, a, (eOp & 0x01), pPage->pDbPage); + offset = 0; + pBuf += a; + amt -= a; + }else{ + offset -= pCur->info.nLocal; + } + + + if( rc==SQLITE_OK && amt>0 ){ + const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ + Pgno nextPage; + + nextPage = get4byte(&aPayload[pCur->info.nLocal]); + + /* If the BtCursor.aOverflow[] has not been allocated, allocate it now. + ** Except, do not allocate aOverflow[] for eOp==2. + ** + ** The aOverflow[] array is sized at one entry for each overflow page + ** in the overflow chain. The page number of the first overflow page is + ** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array + ** means "not yet known" (the cache is lazily populated). + */ + if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){ + int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; + if( nOvfl>pCur->nOvflAlloc ){ + Pgno *aNew = (Pgno*)sqlite3Realloc( + pCur->aOverflow, nOvfl*2*sizeof(Pgno) + ); + if( aNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + pCur->nOvflAlloc = nOvfl*2; + pCur->aOverflow = aNew; + } + } + if( rc==SQLITE_OK ){ + memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno)); + pCur->curFlags |= BTCF_ValidOvfl; + } + } + + /* If the overflow page-list cache has been allocated and the + ** entry for the first required overflow page is valid, skip + ** directly to it. + */ + if( (pCur->curFlags & BTCF_ValidOvfl)!=0 + && pCur->aOverflow[offset/ovflSize] + ){ + iIdx = (offset/ovflSize); + nextPage = pCur->aOverflow[iIdx]; + offset = (offset%ovflSize); + } + + for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){ + + /* If required, populate the overflow page-list cache. */ + if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){ + assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage); + pCur->aOverflow[iIdx] = nextPage; + } + + if( offset>=ovflSize ){ + /* The only reason to read this page is to obtain the page + ** number for the next page in the overflow chain. The page + ** data is not required. So first try to lookup the overflow + ** page-list cache, if any, then fall back to the getOverflowPage() + ** function. + ** + ** Note that the aOverflow[] array must be allocated because eOp!=2 + ** here. If eOp==2, then offset==0 and this branch is never taken. + */ + assert( eOp!=2 ); + assert( pCur->curFlags & BTCF_ValidOvfl ); + assert( pCur->pBtree->db==pBt->db ); + if( pCur->aOverflow[iIdx+1] ){ + nextPage = pCur->aOverflow[iIdx+1]; + }else{ + rc = getOverflowPage(pBt, nextPage, 0, &nextPage); + } + offset -= ovflSize; + }else{ + /* Need to read this page properly. It contains some of the + ** range of data that is being read (eOp==0) or written (eOp!=0). + */ +#ifdef SQLITE_DIRECT_OVERFLOW_READ + sqlite3_file *fd; +#endif + int a = amt; + if( a + offset > ovflSize ){ + a = ovflSize - offset; + } + +#ifdef SQLITE_DIRECT_OVERFLOW_READ + /* If all the following are true: + ** + ** 1) this is a read operation, and + ** 2) data is required from the start of this overflow page, and + ** 3) the database is file-backed, and + ** 4) there is no open write-transaction, and + ** 5) the database is not a WAL database, + ** 6) all data from the page is being read. + ** 7) at least 4 bytes have already been read into the output buffer + ** + ** then data can be read directly from the database file into the + ** output buffer, bypassing the page-cache altogether. This speeds + ** up loading large records that span many overflow pages. + */ + if( (eOp&0x01)==0 /* (1) */ + && offset==0 /* (2) */ + && (bEnd || a==ovflSize) /* (6) */ + && pBt->inTransaction==TRANS_READ /* (4) */ + && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ + && pBt->pPage1->aData[19]==0x01 /* (5) */ + && &pBuf[-4]>=pBufStart /* (7) */ + ){ + u8 aSave[4]; + u8 *aWrite = &pBuf[-4]; + assert( aWrite>=pBufStart ); /* hence (7) */ + memcpy(aSave, aWrite, 4); + rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1)); + nextPage = get4byte(aWrite); + memcpy(aWrite, aSave, 4); + }else +#endif + + { + DbPage *pDbPage; + rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage, + ((eOp&0x01)==0 ? PAGER_GET_READONLY : 0) + ); + if( rc==SQLITE_OK ){ + aPayload = sqlite3PagerGetData(pDbPage); + nextPage = get4byte(aPayload); + rc = copyPayload(&aPayload[offset+4], pBuf, a, (eOp&0x01), pDbPage); + sqlite3PagerUnref(pDbPage); + offset = 0; + } + } + amt -= a; + pBuf += a; + } + } + } + + if( rc==SQLITE_OK && amt>0 ){ + return SQLITE_CORRUPT_BKPT; + } + return rc; +} + +/* +** Read part of the key associated with cursor pCur. Exactly +** "amt" bytes will be transferred into pBuf[]. The transfer +** begins at "offset". +** +** The caller must ensure that pCur is pointing to a valid row +** in the table. +** +** Return SQLITE_OK on success or an error code if anything goes +** wrong. An error is returned if "offset+amt" is larger than +** the available payload. +*/ +SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); + assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); + return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); +} + +/* +** Read part of the data associated with cursor pCur. Exactly +** "amt" bytes will be transfered into pBuf[]. The transfer +** begins at "offset". +** +** Return SQLITE_OK on success or an error code if anything goes +** wrong. An error is returned if "offset+amt" is larger than +** the available payload. +*/ +SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ + int rc; + +#ifndef SQLITE_OMIT_INCRBLOB + if ( pCur->eState==CURSOR_INVALID ){ + return SQLITE_ABORT; + } +#endif + + assert( cursorHoldsMutex(pCur) ); + rc = restoreCursorPosition(pCur); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); + assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); + rc = accessPayload(pCur, offset, amt, pBuf, 0); + } + return rc; +} + +/* +** Return a pointer to payload information from the entry that the +** pCur cursor is pointing to. The pointer is to the beginning of +** the key if index btrees (pPage->intKey==0) and is the data for +** table btrees (pPage->intKey==1). The number of bytes of available +** key/data is written into *pAmt. If *pAmt==0, then the value +** returned will not be a valid pointer. +** +** This routine is an optimization. It is common for the entire key +** and data to fit on the local page and for there to be no overflow +** pages. When that is so, this routine can be used to access the +** key and data without making a copy. If the key and/or data spills +** onto overflow pages, then accessPayload() must be used to reassemble +** the key/data and copy it into a preallocated buffer. +** +** The pointer returned by this routine looks directly into the cached +** page of the database. The data might change or move the next time +** any btree routine is called. +*/ +static const void *fetchPayload( + BtCursor *pCur, /* Cursor pointing to entry to read from */ + u32 *pAmt /* Write the number of available bytes here */ +){ + u32 amt; + assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); + assert( pCur->eState==CURSOR_VALID ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + assert( cursorHoldsMutex(pCur) ); + assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); + assert( pCur->info.nSize>0 ); + assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB ); + assert( pCur->info.pPayloadapPage[pCur->iPage]->aDataEnd ||CORRUPT_DB); + amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload); + if( pCur->info.nLocalinfo.nLocal; + *pAmt = amt; + return (void*)pCur->info.pPayload; +} + + +/* +** For the entry that cursor pCur is point to, return as +** many bytes of the key or data as are available on the local +** b-tree page. Write the number of available bytes into *pAmt. +** +** The pointer returned is ephemeral. The key/data may move +** or be destroyed on the next call to any Btree routine, +** including calls from other threads against the same cache. +** Hence, a mutex on the BtShared should be held prior to calling +** this routine. +** +** These routines is used to get quick access to key and data +** in the common case where no overflow pages are used. +*/ +SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor *pCur, u32 *pAmt){ + return fetchPayload(pCur, pAmt); +} +SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){ + return fetchPayload(pCur, pAmt); +} + + +/* +** Move the cursor down to a new child page. The newPgno argument is the +** page number of the child page to move to. +** +** This function returns SQLITE_CORRUPT if the page-header flags field of +** the new child page does not match the flags field of the parent (i.e. +** if an intkey page appears to be the parent of a non-intkey page, or +** vice-versa). +*/ +static int moveToChild(BtCursor *pCur, u32 newPgno){ + BtShared *pBt = pCur->pBt; + + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->iPageiPage>=0 ); + if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){ + return SQLITE_CORRUPT_BKPT; + } + pCur->info.nSize = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); + pCur->iPage++; + pCur->aiIdx[pCur->iPage] = 0; + return getAndInitPage(pBt, newPgno, &pCur->apPage[pCur->iPage], + pCur, pCur->curPagerFlags); +} + +#if SQLITE_DEBUG +/* +** Page pParent is an internal (non-leaf) tree page. This function +** asserts that page number iChild is the left-child if the iIdx'th +** cell in page pParent. Or, if iIdx is equal to the total number of +** cells in pParent, that page number iChild is the right-child of +** the page. +*/ +static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){ + if( CORRUPT_DB ) return; /* The conditions tested below might not be true + ** in a corrupt database */ + assert( iIdx<=pParent->nCell ); + if( iIdx==pParent->nCell ){ + assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild ); + }else{ + assert( get4byte(findCell(pParent, iIdx))==iChild ); + } +} +#else +# define assertParentIndex(x,y,z) +#endif + +/* +** Move the cursor up to the parent page. +** +** pCur->idx is set to the cell index that contains the pointer +** to the page we are coming from. If we are coming from the +** right-most child page then pCur->idx is set to one more than +** the largest cell index. +*/ +static void moveToParent(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->iPage>0 ); + assert( pCur->apPage[pCur->iPage] ); + assertParentIndex( + pCur->apPage[pCur->iPage-1], + pCur->aiIdx[pCur->iPage-1], + pCur->apPage[pCur->iPage]->pgno + ); + testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell ); + pCur->info.nSize = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); + releasePageNotNull(pCur->apPage[pCur->iPage--]); +} + +/* +** Move the cursor to point to the root page of its b-tree structure. +** +** If the table has a virtual root page, then the cursor is moved to point +** to the virtual root page instead of the actual root page. A table has a +** virtual root page when the actual root page contains no cells and a +** single child page. This can only happen with the table rooted at page 1. +** +** If the b-tree structure is empty, the cursor state is set to +** CURSOR_INVALID. Otherwise, the cursor is set to point to the first +** cell located on the root (or virtual root) page and the cursor state +** is set to CURSOR_VALID. +** +** If this function returns successfully, it may be assumed that the +** page-header flags indicate that the [virtual] root-page is the expected +** kind of b-tree page (i.e. if when opening the cursor the caller did not +** specify a KeyInfo structure the flags byte is set to 0x05 or 0x0D, +** indicating a table b-tree, or if the caller did specify a KeyInfo +** structure the flags byte is set to 0x02 or 0x0A, indicating an index +** b-tree). +*/ +static int moveToRoot(BtCursor *pCur){ + MemPage *pRoot; + int rc = SQLITE_OK; + + assert( cursorHoldsMutex(pCur) ); + assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); + assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); + assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); + if( pCur->eState>=CURSOR_REQUIRESEEK ){ + if( pCur->eState==CURSOR_FAULT ){ + assert( pCur->skipNext!=SQLITE_OK ); + return pCur->skipNext; + } + sqlite3BtreeClearCursor(pCur); + } + + if( pCur->iPage>=0 ){ + while( pCur->iPage ){ + assert( pCur->apPage[pCur->iPage]!=0 ); + releasePageNotNull(pCur->apPage[pCur->iPage--]); + } + }else if( pCur->pgnoRoot==0 ){ + pCur->eState = CURSOR_INVALID; + return SQLITE_OK; + }else{ + assert( pCur->iPage==(-1) ); + rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], + 0, pCur->curPagerFlags); + if( rc!=SQLITE_OK ){ + pCur->eState = CURSOR_INVALID; + return rc; + } + pCur->iPage = 0; + pCur->curIntKey = pCur->apPage[0]->intKey; + } + pRoot = pCur->apPage[0]; + assert( pRoot->pgno==pCur->pgnoRoot ); + + /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor + ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is + ** NULL, the caller expects a table b-tree. If this is not the case, + ** return an SQLITE_CORRUPT error. + ** + ** Earlier versions of SQLite assumed that this test could not fail + ** if the root page was already loaded when this function was called (i.e. + ** if pCur->iPage>=0). But this is not so if the database is corrupted + ** in such a way that page pRoot is linked into a second b-tree table + ** (or the freelist). */ + assert( pRoot->intKey==1 || pRoot->intKey==0 ); + if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ + return SQLITE_CORRUPT_BKPT; + } + + pCur->aiIdx[0] = 0; + pCur->info.nSize = 0; + pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); + + if( pRoot->nCell>0 ){ + pCur->eState = CURSOR_VALID; + }else if( !pRoot->leaf ){ + Pgno subpage; + if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; + subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); + pCur->eState = CURSOR_VALID; + rc = moveToChild(pCur, subpage); + }else{ + pCur->eState = CURSOR_INVALID; + } + return rc; +} + +/* +** Move the cursor down to the left-most leaf entry beneath the +** entry to which it is currently pointing. +** +** The left-most leaf is the one with the smallest key - the first +** in ascending order. +*/ +static int moveToLeftmost(BtCursor *pCur){ + Pgno pgno; + int rc = SQLITE_OK; + MemPage *pPage; + + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){ + assert( pCur->aiIdx[pCur->iPage]nCell ); + pgno = get4byte(findCell(pPage, pCur->aiIdx[pCur->iPage])); + rc = moveToChild(pCur, pgno); + } + return rc; +} + +/* +** Move the cursor down to the right-most leaf entry beneath the +** page to which it is currently pointing. Notice the difference +** between moveToLeftmost() and moveToRightmost(). moveToLeftmost() +** finds the left-most entry beneath the *entry* whereas moveToRightmost() +** finds the right-most entry beneath the *page*. +** +** The right-most entry is the one with the largest key - the last +** key in ascending order. +*/ +static int moveToRightmost(BtCursor *pCur){ + Pgno pgno; + int rc = SQLITE_OK; + MemPage *pPage = 0; + + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){ + pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); + pCur->aiIdx[pCur->iPage] = pPage->nCell; + rc = moveToChild(pCur, pgno); + if( rc ) return rc; + } + pCur->aiIdx[pCur->iPage] = pPage->nCell-1; + assert( pCur->info.nSize==0 ); + assert( (pCur->curFlags & BTCF_ValidNKey)==0 ); + return SQLITE_OK; +} + +/* Move the cursor to the first entry in the table. Return SQLITE_OK +** on success. Set *pRes to 0 if the cursor actually points to something +** or set *pRes to 1 if the table is empty. +*/ +SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + rc = moveToRoot(pCur); + if( rc==SQLITE_OK ){ + if( pCur->eState==CURSOR_INVALID ){ + assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); + *pRes = 1; + }else{ + assert( pCur->apPage[pCur->iPage]->nCell>0 ); + *pRes = 0; + rc = moveToLeftmost(pCur); + } + } + return rc; +} + +/* Move the cursor to the last entry in the table. Return SQLITE_OK +** on success. Set *pRes to 0 if the cursor actually points to something +** or set *pRes to 1 if the table is empty. +*/ +SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + + /* If the cursor already points to the last entry, this is a no-op. */ + if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){ +#ifdef SQLITE_DEBUG + /* This block serves to assert() that the cursor really does point + ** to the last entry in the b-tree. */ + int ii; + for(ii=0; iiiPage; ii++){ + assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell ); + } + assert( pCur->aiIdx[pCur->iPage]==pCur->apPage[pCur->iPage]->nCell-1 ); + assert( pCur->apPage[pCur->iPage]->leaf ); +#endif + return SQLITE_OK; + } + + rc = moveToRoot(pCur); + if( rc==SQLITE_OK ){ + if( CURSOR_INVALID==pCur->eState ){ + assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); + *pRes = 1; + }else{ + assert( pCur->eState==CURSOR_VALID ); + *pRes = 0; + rc = moveToRightmost(pCur); + if( rc==SQLITE_OK ){ + pCur->curFlags |= BTCF_AtLast; + }else{ + pCur->curFlags &= ~BTCF_AtLast; + } + + } + } + return rc; +} + +/* Move the cursor so that it points to an entry near the key +** specified by pIdxKey or intKey. Return a success code. +** +** For INTKEY tables, the intKey parameter is used. pIdxKey +** must be NULL. For index tables, pIdxKey is used and intKey +** is ignored. +** +** If an exact match is not found, then the cursor is always +** left pointing at a leaf page which would hold the entry if it +** were present. The cursor might point to an entry that comes +** before or after the key. +** +** An integer is written into *pRes which is the result of +** comparing the key with the entry to which the cursor is +** pointing. The meaning of the integer written into +** *pRes is as follows: +** +** *pRes<0 The cursor is left pointing at an entry that +** is smaller than intKey/pIdxKey or if the table is empty +** and the cursor is therefore left point to nothing. +** +** *pRes==0 The cursor is left pointing at an entry that +** exactly matches intKey/pIdxKey. +** +** *pRes>0 The cursor is left pointing at an entry that +** is larger than intKey/pIdxKey. +** +*/ +SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( + BtCursor *pCur, /* The cursor to be moved */ + UnpackedRecord *pIdxKey, /* Unpacked index key */ + i64 intKey, /* The table key */ + int biasRight, /* If true, bias the search to the high end */ + int *pRes /* Write search results here */ +){ + int rc; + RecordCompare xRecordCompare; + + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + assert( pRes ); + assert( (pIdxKey==0)==(pCur->pKeyInfo==0) ); + + /* If the cursor is already positioned at the point we are trying + ** to move to, then just return without doing any work */ + if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 + && pCur->curIntKey + ){ + if( pCur->info.nKey==intKey ){ + *pRes = 0; + return SQLITE_OK; + } + if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKeyerrCode = 0; + assert( pIdxKey->default_rc==1 + || pIdxKey->default_rc==0 + || pIdxKey->default_rc==-1 + ); + }else{ + xRecordCompare = 0; /* All keys are integers */ + } + + rc = moveToRoot(pCur); + if( rc ){ + return rc; + } + assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] ); + assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit ); + assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 ); + if( pCur->eState==CURSOR_INVALID ){ + *pRes = -1; + assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); + return SQLITE_OK; + } + assert( pCur->apPage[0]->intKey==pCur->curIntKey ); + assert( pCur->curIntKey || pIdxKey ); + for(;;){ + int lwr, upr, idx, c; + Pgno chldPg; + MemPage *pPage = pCur->apPage[pCur->iPage]; + u8 *pCell; /* Pointer to current cell in pPage */ + + /* pPage->nCell must be greater than zero. If this is the root-page + ** the cursor would have been INVALID above and this for(;;) loop + ** not run. If this is not the root-page, then the moveToChild() routine + ** would have already detected db corruption. Similarly, pPage must + ** be the right kind (index or table) of b-tree page. Otherwise + ** a moveToChild() or moveToRoot() call would have detected corruption. */ + assert( pPage->nCell>0 ); + assert( pPage->intKey==(pIdxKey==0) ); + lwr = 0; + upr = pPage->nCell-1; + assert( biasRight==0 || biasRight==1 ); + idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */ + pCur->aiIdx[pCur->iPage] = (u16)idx; + if( xRecordCompare==0 ){ + for(;;){ + i64 nCellKey; + pCell = findCellPastPtr(pPage, idx); + if( pPage->intKeyLeaf ){ + while( 0x80 <= *(pCell++) ){ + if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT; + } + } + getVarint(pCell, (u64*)&nCellKey); + if( nCellKeyupr ){ c = -1; break; } + }else if( nCellKey>intKey ){ + upr = idx-1; + if( lwr>upr ){ c = +1; break; } + }else{ + assert( nCellKey==intKey ); + pCur->curFlags |= BTCF_ValidNKey; + pCur->info.nKey = nCellKey; + pCur->aiIdx[pCur->iPage] = (u16)idx; + if( !pPage->leaf ){ + lwr = idx; + goto moveto_next_layer; + }else{ + *pRes = 0; + rc = SQLITE_OK; + goto moveto_finish; + } + } + assert( lwr+upr>=0 ); + idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */ + } + }else{ + for(;;){ + int nCell; /* Size of the pCell cell in bytes */ + pCell = findCellPastPtr(pPage, idx); + + /* The maximum supported page-size is 65536 bytes. This means that + ** the maximum number of record bytes stored on an index B-Tree + ** page is less than 16384 bytes and may be stored as a 2-byte + ** varint. This information is used to attempt to avoid parsing + ** the entire cell by checking for the cases where the record is + ** stored entirely within the b-tree page by inspecting the first + ** 2 bytes of the cell. + */ + nCell = pCell[0]; + if( nCell<=pPage->max1bytePayload ){ + /* This branch runs if the record-size field of the cell is a + ** single byte varint and the record fits entirely on the main + ** b-tree page. */ + testcase( pCell+nCell+1==pPage->aDataEnd ); + c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey); + }else if( !(pCell[1] & 0x80) + && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal + ){ + /* The record-size field is a 2 byte varint and the record + ** fits entirely on the main b-tree page. */ + testcase( pCell+nCell+2==pPage->aDataEnd ); + c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey); + }else{ + /* The record flows over onto one or more overflow pages. In + ** this case the whole cell needs to be parsed, a buffer allocated + ** and accessPayload() used to retrieve the record into the + ** buffer before VdbeRecordCompare() can be called. + ** + ** If the record is corrupt, the xRecordCompare routine may read + ** up to two varints past the end of the buffer. An extra 18 + ** bytes of padding is allocated at the end of the buffer in + ** case this happens. */ + void *pCellKey; + u8 * const pCellBody = pCell - pPage->childPtrSize; + pPage->xParseCell(pPage, pCellBody, &pCur->info); + nCell = (int)pCur->info.nKey; + testcase( nCell<0 ); /* True if key size is 2^32 or more */ + testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */ + testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */ + testcase( nCell==2 ); /* Minimum legal index key size */ + if( nCell<2 ){ + rc = SQLITE_CORRUPT_BKPT; + goto moveto_finish; + } + pCellKey = sqlite3Malloc( nCell+18 ); + if( pCellKey==0 ){ + rc = SQLITE_NOMEM; + goto moveto_finish; + } + pCur->aiIdx[pCur->iPage] = (u16)idx; + rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2); + if( rc ){ + sqlite3_free(pCellKey); + goto moveto_finish; + } + c = xRecordCompare(nCell, pCellKey, pIdxKey); + sqlite3_free(pCellKey); + } + assert( + (pIdxKey->errCode!=SQLITE_CORRUPT || c==0) + && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed) + ); + if( c<0 ){ + lwr = idx+1; + }else if( c>0 ){ + upr = idx-1; + }else{ + assert( c==0 ); + *pRes = 0; + rc = SQLITE_OK; + pCur->aiIdx[pCur->iPage] = (u16)idx; + if( pIdxKey->errCode ) rc = SQLITE_CORRUPT; + goto moveto_finish; + } + if( lwr>upr ) break; + assert( lwr+upr>=0 ); + idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */ + } + } + assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) ); + assert( pPage->isInit ); + if( pPage->leaf ){ + assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); + pCur->aiIdx[pCur->iPage] = (u16)idx; + *pRes = c; + rc = SQLITE_OK; + goto moveto_finish; + } +moveto_next_layer: + if( lwr>=pPage->nCell ){ + chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]); + }else{ + chldPg = get4byte(findCell(pPage, lwr)); + } + pCur->aiIdx[pCur->iPage] = (u16)lwr; + rc = moveToChild(pCur, chldPg); + if( rc ) break; + } +moveto_finish: + pCur->info.nSize = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); + return rc; +} + + +/* +** Return TRUE if the cursor is not pointing at an entry of the table. +** +** TRUE will be returned after a call to sqlite3BtreeNext() moves +** past the last entry in the table or sqlite3BtreePrev() moves past +** the first entry. TRUE is also returned if the table is empty. +*/ +SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){ + /* TODO: What if the cursor is in CURSOR_REQUIRESEEK but all table entries + ** have been deleted? This API will need to change to return an error code + ** as well as the boolean result value. + */ + return (CURSOR_VALID!=pCur->eState); +} + +/* +** Advance the cursor to the next entry in the database. If +** successful then set *pRes=0. If the cursor +** was already pointing to the last entry in the database before +** this routine was called, then set *pRes=1. +** +** The main entry point is sqlite3BtreeNext(). That routine is optimized +** for the common case of merely incrementing the cell counter BtCursor.aiIdx +** to the next cell on the current page. The (slower) btreeNext() helper +** routine is called when it is necessary to move to a different page or +** to restore the cursor. +** +** The calling function will set *pRes to 0 or 1. The initial *pRes value +** will be 1 if the cursor being stepped corresponds to an SQL index and +** if this routine could have been skipped if that SQL index had been +** a unique index. Otherwise the caller will have set *pRes to zero. +** Zero is the common case. The btree implementation is free to use the +** initial *pRes value as a hint to improve performance, but the current +** SQLite btree implementation does not. (Note that the comdb2 btree +** implementation does use this hint, however.) +*/ +static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){ + int rc; + int idx; + MemPage *pPage; + + assert( cursorHoldsMutex(pCur) ); + assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); + assert( *pRes==0 ); + if( pCur->eState!=CURSOR_VALID ){ + assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); + rc = restoreCursorPosition(pCur); + if( rc!=SQLITE_OK ){ + return rc; + } + if( CURSOR_INVALID==pCur->eState ){ + *pRes = 1; + return SQLITE_OK; + } + if( pCur->skipNext ){ + assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT ); + pCur->eState = CURSOR_VALID; + if( pCur->skipNext>0 ){ + pCur->skipNext = 0; + return SQLITE_OK; + } + pCur->skipNext = 0; + } + } + + pPage = pCur->apPage[pCur->iPage]; + idx = ++pCur->aiIdx[pCur->iPage]; + assert( pPage->isInit ); + + /* If the database file is corrupt, it is possible for the value of idx + ** to be invalid here. This can only occur if a second cursor modifies + ** the page while cursor pCur is holding a reference to it. Which can + ** only happen if the database is corrupt in such a way as to link the + ** page into more than one b-tree structure. */ + testcase( idx>pPage->nCell ); + + if( idx>=pPage->nCell ){ + if( !pPage->leaf ){ + rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); + if( rc ) return rc; + return moveToLeftmost(pCur); + } + do{ + if( pCur->iPage==0 ){ + *pRes = 1; + pCur->eState = CURSOR_INVALID; + return SQLITE_OK; + } + moveToParent(pCur); + pPage = pCur->apPage[pCur->iPage]; + }while( pCur->aiIdx[pCur->iPage]>=pPage->nCell ); + if( pPage->intKey ){ + return sqlite3BtreeNext(pCur, pRes); + }else{ + return SQLITE_OK; + } + } + if( pPage->leaf ){ + return SQLITE_OK; + }else{ + return moveToLeftmost(pCur); + } +} +SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ + MemPage *pPage; + assert( cursorHoldsMutex(pCur) ); + assert( pRes!=0 ); + assert( *pRes==0 || *pRes==1 ); + assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); + pCur->info.nSize = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); + *pRes = 0; + if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur, pRes); + pPage = pCur->apPage[pCur->iPage]; + if( (++pCur->aiIdx[pCur->iPage])>=pPage->nCell ){ + pCur->aiIdx[pCur->iPage]--; + return btreeNext(pCur, pRes); + } + if( pPage->leaf ){ + return SQLITE_OK; + }else{ + return moveToLeftmost(pCur); + } +} + +/* +** Step the cursor to the back to the previous entry in the database. If +** successful then set *pRes=0. If the cursor +** was already pointing to the first entry in the database before +** this routine was called, then set *pRes=1. +** +** The main entry point is sqlite3BtreePrevious(). That routine is optimized +** for the common case of merely decrementing the cell counter BtCursor.aiIdx +** to the previous cell on the current page. The (slower) btreePrevious() +** helper routine is called when it is necessary to move to a different page +** or to restore the cursor. +** +** The calling function will set *pRes to 0 or 1. The initial *pRes value +** will be 1 if the cursor being stepped corresponds to an SQL index and +** if this routine could have been skipped if that SQL index had been +** a unique index. Otherwise the caller will have set *pRes to zero. +** Zero is the common case. The btree implementation is free to use the +** initial *pRes value as a hint to improve performance, but the current +** SQLite btree implementation does not. (Note that the comdb2 btree +** implementation does use this hint, however.) +*/ +static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ + int rc; + MemPage *pPage; + + assert( cursorHoldsMutex(pCur) ); + assert( pRes!=0 ); + assert( *pRes==0 ); + assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); + assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 ); + assert( pCur->info.nSize==0 ); + if( pCur->eState!=CURSOR_VALID ){ + rc = restoreCursorPosition(pCur); + if( rc!=SQLITE_OK ){ + return rc; + } + if( CURSOR_INVALID==pCur->eState ){ + *pRes = 1; + return SQLITE_OK; + } + if( pCur->skipNext ){ + assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT ); + pCur->eState = CURSOR_VALID; + if( pCur->skipNext<0 ){ + pCur->skipNext = 0; + return SQLITE_OK; + } + pCur->skipNext = 0; + } + } + + pPage = pCur->apPage[pCur->iPage]; + assert( pPage->isInit ); + if( !pPage->leaf ){ + int idx = pCur->aiIdx[pCur->iPage]; + rc = moveToChild(pCur, get4byte(findCell(pPage, idx))); + if( rc ) return rc; + rc = moveToRightmost(pCur); + }else{ + while( pCur->aiIdx[pCur->iPage]==0 ){ + if( pCur->iPage==0 ){ + pCur->eState = CURSOR_INVALID; + *pRes = 1; + return SQLITE_OK; + } + moveToParent(pCur); + } + assert( pCur->info.nSize==0 ); + assert( (pCur->curFlags & (BTCF_ValidNKey|BTCF_ValidOvfl))==0 ); + + pCur->aiIdx[pCur->iPage]--; + pPage = pCur->apPage[pCur->iPage]; + if( pPage->intKey && !pPage->leaf ){ + rc = sqlite3BtreePrevious(pCur, pRes); + }else{ + rc = SQLITE_OK; + } + } + return rc; +} +SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ + assert( cursorHoldsMutex(pCur) ); + assert( pRes!=0 ); + assert( *pRes==0 || *pRes==1 ); + assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); + *pRes = 0; + pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey); + pCur->info.nSize = 0; + if( pCur->eState!=CURSOR_VALID + || pCur->aiIdx[pCur->iPage]==0 + || pCur->apPage[pCur->iPage]->leaf==0 + ){ + return btreePrevious(pCur, pRes); + } + pCur->aiIdx[pCur->iPage]--; + return SQLITE_OK; +} + +/* +** Allocate a new page from the database file. +** +** The new page is marked as dirty. (In other words, sqlite3PagerWrite() +** has already been called on the new page.) The new page has also +** been referenced and the calling routine is responsible for calling +** sqlite3PagerUnref() on the new page when it is done. +** +** SQLITE_OK is returned on success. Any other return value indicates +** an error. *ppPage is set to NULL in the event of an error. +** +** If the "nearby" parameter is not 0, then an effort is made to +** locate a page close to the page number "nearby". This can be used in an +** attempt to keep related pages close to each other in the database file, +** which in turn can make database access faster. +** +** If the eMode parameter is BTALLOC_EXACT and the nearby page exists +** anywhere on the free-list, then it is guaranteed to be returned. If +** eMode is BTALLOC_LT then the page returned will be less than or equal +** to nearby if any such page exists. If eMode is BTALLOC_ANY then there +** are no restrictions on which page is returned. +*/ +static int allocateBtreePage( + BtShared *pBt, /* The btree */ + MemPage **ppPage, /* Store pointer to the allocated page here */ + Pgno *pPgno, /* Store the page number here */ + Pgno nearby, /* Search for a page near this one */ + u8 eMode /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */ +){ + MemPage *pPage1; + int rc; + u32 n; /* Number of pages on the freelist */ + u32 k; /* Number of leaves on the trunk of the freelist */ + MemPage *pTrunk = 0; + MemPage *pPrevTrunk = 0; + Pgno mxPage; /* Total size of the database file */ + + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) ); + pPage1 = pBt->pPage1; + mxPage = btreePagecount(pBt); + /* EVIDENCE-OF: R-05119-02637 The 4-byte big-endian integer at offset 36 + ** stores stores the total number of pages on the freelist. */ + n = get4byte(&pPage1->aData[36]); + testcase( n==mxPage-1 ); + if( n>=mxPage ){ + return SQLITE_CORRUPT_BKPT; + } + if( n>0 ){ + /* There are pages on the freelist. Reuse one of those pages. */ + Pgno iTrunk; + u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ + u32 nSearch = 0; /* Count of the number of search attempts */ + + /* If eMode==BTALLOC_EXACT and a query of the pointer-map + ** shows that the page 'nearby' is somewhere on the free-list, then + ** the entire-list will be searched for that page. + */ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( eMode==BTALLOC_EXACT ){ + if( nearby<=mxPage ){ + u8 eType; + assert( nearby>0 ); + assert( pBt->autoVacuum ); + rc = ptrmapGet(pBt, nearby, &eType, 0); + if( rc ) return rc; + if( eType==PTRMAP_FREEPAGE ){ + searchList = 1; + } + } + }else if( eMode==BTALLOC_LE ){ + searchList = 1; + } +#endif + + /* Decrement the free-list count by 1. Set iTrunk to the index of the + ** first free-list trunk page. iPrevTrunk is initially 1. + */ + rc = sqlite3PagerWrite(pPage1->pDbPage); + if( rc ) return rc; + put4byte(&pPage1->aData[36], n-1); + + /* The code within this loop is run only once if the 'searchList' variable + ** is not true. Otherwise, it runs once for each trunk-page on the + ** free-list until the page 'nearby' is located (eMode==BTALLOC_EXACT) + ** or until a page less than 'nearby' is located (eMode==BTALLOC_LT) + */ + do { + pPrevTrunk = pTrunk; + if( pPrevTrunk ){ + /* EVIDENCE-OF: R-01506-11053 The first integer on a freelist trunk page + ** is the page number of the next freelist trunk page in the list or + ** zero if this is the last freelist trunk page. */ + iTrunk = get4byte(&pPrevTrunk->aData[0]); + }else{ + /* EVIDENCE-OF: R-59841-13798 The 4-byte big-endian integer at offset 32 + ** stores the page number of the first page of the freelist, or zero if + ** the freelist is empty. */ + iTrunk = get4byte(&pPage1->aData[32]); + } + testcase( iTrunk==mxPage ); + if( iTrunk>mxPage || nSearch++ > n ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0); + } + if( rc ){ + pTrunk = 0; + goto end_allocate_page; + } + assert( pTrunk!=0 ); + assert( pTrunk->aData!=0 ); + /* EVIDENCE-OF: R-13523-04394 The second integer on a freelist trunk page + ** is the number of leaf page pointers to follow. */ + k = get4byte(&pTrunk->aData[4]); + if( k==0 && !searchList ){ + /* The trunk has no leaves and the list is not being searched. + ** So extract the trunk page itself and use it as the newly + ** allocated page */ + assert( pPrevTrunk==0 ); + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + *pPgno = iTrunk; + memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); + *ppPage = pTrunk; + pTrunk = 0; + TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); + }else if( k>(u32)(pBt->usableSize/4 - 2) ){ + /* Value of k is out of range. Database corruption */ + rc = SQLITE_CORRUPT_BKPT; + goto end_allocate_page; +#ifndef SQLITE_OMIT_AUTOVACUUM + }else if( searchList + && (nearby==iTrunk || (iTrunkpDbPage); + if( rc ){ + goto end_allocate_page; + } + if( k==0 ){ + if( !pPrevTrunk ){ + memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); + }else{ + rc = sqlite3PagerWrite(pPrevTrunk->pDbPage); + if( rc!=SQLITE_OK ){ + goto end_allocate_page; + } + memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4); + } + }else{ + /* The trunk page is required by the caller but it contains + ** pointers to free-list leaves. The first leaf becomes a trunk + ** page in this case. + */ + MemPage *pNewTrunk; + Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); + if( iNewTrunk>mxPage ){ + rc = SQLITE_CORRUPT_BKPT; + goto end_allocate_page; + } + testcase( iNewTrunk==mxPage ); + rc = btreeGetUnusedPage(pBt, iNewTrunk, &pNewTrunk, 0); + if( rc!=SQLITE_OK ){ + goto end_allocate_page; + } + rc = sqlite3PagerWrite(pNewTrunk->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pNewTrunk); + goto end_allocate_page; + } + memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4); + put4byte(&pNewTrunk->aData[4], k-1); + memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4); + releasePage(pNewTrunk); + if( !pPrevTrunk ){ + assert( sqlite3PagerIswriteable(pPage1->pDbPage) ); + put4byte(&pPage1->aData[32], iNewTrunk); + }else{ + rc = sqlite3PagerWrite(pPrevTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + put4byte(&pPrevTrunk->aData[0], iNewTrunk); + } + } + pTrunk = 0; + TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); +#endif + }else if( k>0 ){ + /* Extract a leaf from the trunk */ + u32 closest; + Pgno iPage; + unsigned char *aData = pTrunk->aData; + if( nearby>0 ){ + u32 i; + closest = 0; + if( eMode==BTALLOC_LE ){ + for(i=0; imxPage ){ + rc = SQLITE_CORRUPT_BKPT; + goto end_allocate_page; + } + testcase( iPage==mxPage ); + if( !searchList + || (iPage==nearby || (iPagepgno, n-1)); + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc ) goto end_allocate_page; + if( closestpDbPage); + if( rc!=SQLITE_OK ){ + releasePage(*ppPage); + *ppPage = 0; + } + } + searchList = 0; + } + } + releasePage(pPrevTrunk); + pPrevTrunk = 0; + }while( searchList ); + }else{ + /* There are no pages on the freelist, so append a new page to the + ** database image. + ** + ** Normally, new pages allocated by this block can be requested from the + ** pager layer with the 'no-content' flag set. This prevents the pager + ** from trying to read the pages content from disk. However, if the + ** current transaction has already run one or more incremental-vacuum + ** steps, then the page we are about to allocate may contain content + ** that is required in the event of a rollback. In this case, do + ** not set the no-content flag. This causes the pager to load and journal + ** the current page content before overwriting it. + ** + ** Note that the pager will not actually attempt to load or journal + ** content for any page that really does lie past the end of the database + ** file on disk. So the effects of disabling the no-content optimization + ** here are confined to those pages that lie between the end of the + ** database image and the end of the database file. + */ + int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate))? PAGER_GET_NOCONTENT:0; + + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + if( rc ) return rc; + pBt->nPage++; + if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++; + +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){ + /* If *pPgno refers to a pointer-map page, allocate two new pages + ** at the end of the file instead of one. The first allocated page + ** becomes a new pointer-map page, the second is used by the caller. + */ + MemPage *pPg = 0; + TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage)); + assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) ); + rc = btreeGetUnusedPage(pBt, pBt->nPage, &pPg, bNoContent); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pPg->pDbPage); + releasePage(pPg); + } + if( rc ) return rc; + pBt->nPage++; + if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; } + } +#endif + put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage); + *pPgno = pBt->nPage; + + assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); + rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, bNoContent); + if( rc ) return rc; + rc = sqlite3PagerWrite((*ppPage)->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(*ppPage); + *ppPage = 0; + } + TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); + } + + assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); + +end_allocate_page: + releasePage(pTrunk); + releasePage(pPrevTrunk); + assert( rc!=SQLITE_OK || sqlite3PagerPageRefcount((*ppPage)->pDbPage)<=1 ); + assert( rc!=SQLITE_OK || (*ppPage)->isInit==0 ); + return rc; +} + +/* +** This function is used to add page iPage to the database file free-list. +** It is assumed that the page is not already a part of the free-list. +** +** The value passed as the second argument to this function is optional. +** If the caller happens to have a pointer to the MemPage object +** corresponding to page iPage handy, it may pass it as the second value. +** Otherwise, it may pass NULL. +** +** If a pointer to a MemPage object is passed as the second argument, +** its reference count is not altered by this function. +*/ +static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ + MemPage *pTrunk = 0; /* Free-list trunk page */ + Pgno iTrunk = 0; /* Page number of free-list trunk page */ + MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */ + MemPage *pPage; /* Page being freed. May be NULL. */ + int rc; /* Return Code */ + int nFree; /* Initial number of pages on free-list */ + + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( CORRUPT_DB || iPage>1 ); + assert( !pMemPage || pMemPage->pgno==iPage ); + + if( iPage<2 ) return SQLITE_CORRUPT_BKPT; + if( pMemPage ){ + pPage = pMemPage; + sqlite3PagerRef(pPage->pDbPage); + }else{ + pPage = btreePageLookup(pBt, iPage); + } + + /* Increment the free page count on pPage1 */ + rc = sqlite3PagerWrite(pPage1->pDbPage); + if( rc ) goto freepage_out; + nFree = get4byte(&pPage1->aData[36]); + put4byte(&pPage1->aData[36], nFree+1); + + if( pBt->btsFlags & BTS_SECURE_DELETE ){ + /* If the secure_delete option is enabled, then + ** always fully overwrite deleted information with zeros. + */ + if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) ) + || ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0) + ){ + goto freepage_out; + } + memset(pPage->aData, 0, pPage->pBt->pageSize); + } + + /* If the database supports auto-vacuum, write an entry in the pointer-map + ** to indicate that the page is free. + */ + if( ISAUTOVACUUM ){ + ptrmapPut(pBt, iPage, PTRMAP_FREEPAGE, 0, &rc); + if( rc ) goto freepage_out; + } + + /* Now manipulate the actual database free-list structure. There are two + ** possibilities. If the free-list is currently empty, or if the first + ** trunk page in the free-list is full, then this page will become a + ** new free-list trunk page. Otherwise, it will become a leaf of the + ** first trunk page in the current free-list. This block tests if it + ** is possible to add the page as a new free-list leaf. + */ + if( nFree!=0 ){ + u32 nLeaf; /* Initial number of leaf cells on trunk page */ + + iTrunk = get4byte(&pPage1->aData[32]); + rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0); + if( rc!=SQLITE_OK ){ + goto freepage_out; + } + + nLeaf = get4byte(&pTrunk->aData[4]); + assert( pBt->usableSize>32 ); + if( nLeaf > (u32)pBt->usableSize/4 - 2 ){ + rc = SQLITE_CORRUPT_BKPT; + goto freepage_out; + } + if( nLeaf < (u32)pBt->usableSize/4 - 8 ){ + /* In this case there is room on the trunk page to insert the page + ** being freed as a new leaf. + ** + ** Note that the trunk page is not really full until it contains + ** usableSize/4 - 2 entries, not usableSize/4 - 8 entries as we have + ** coded. But due to a coding error in versions of SQLite prior to + ** 3.6.0, databases with freelist trunk pages holding more than + ** usableSize/4 - 8 entries will be reported as corrupt. In order + ** to maintain backwards compatibility with older versions of SQLite, + ** we will continue to restrict the number of entries to usableSize/4 - 8 + ** for now. At some point in the future (once everyone has upgraded + ** to 3.6.0 or later) we should consider fixing the conditional above + ** to read "usableSize/4-2" instead of "usableSize/4-8". + ** + ** EVIDENCE-OF: R-19920-11576 However, newer versions of SQLite still + ** avoid using the last six entries in the freelist trunk page array in + ** order that database files created by newer versions of SQLite can be + ** read by older versions of SQLite. + */ + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc==SQLITE_OK ){ + put4byte(&pTrunk->aData[4], nLeaf+1); + put4byte(&pTrunk->aData[8+nLeaf*4], iPage); + if( pPage && (pBt->btsFlags & BTS_SECURE_DELETE)==0 ){ + sqlite3PagerDontWrite(pPage->pDbPage); + } + rc = btreeSetHasContent(pBt, iPage); + } + TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); + goto freepage_out; + } + } + + /* If control flows to this point, then it was not possible to add the + ** the page being freed as a leaf page of the first trunk in the free-list. + ** Possibly because the free-list is empty, or possibly because the + ** first trunk in the free-list is full. Either way, the page being freed + ** will become the new first trunk page in the free-list. + */ + if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){ + goto freepage_out; + } + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc!=SQLITE_OK ){ + goto freepage_out; + } + put4byte(pPage->aData, iTrunk); + put4byte(&pPage->aData[4], 0); + put4byte(&pPage1->aData[32], iPage); + TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", pPage->pgno, iTrunk)); + +freepage_out: + if( pPage ){ + pPage->isInit = 0; + } + releasePage(pPage); + releasePage(pTrunk); + return rc; +} +static void freePage(MemPage *pPage, int *pRC){ + if( (*pRC)==SQLITE_OK ){ + *pRC = freePage2(pPage->pBt, pPage, pPage->pgno); + } +} + +/* +** Free any overflow pages associated with the given Cell. Write the +** local Cell size (the number of bytes on the original page, omitting +** overflow) into *pnSize. +*/ +static int clearCell( + MemPage *pPage, /* The page that contains the Cell */ + unsigned char *pCell, /* First byte of the Cell */ + u16 *pnSize /* Write the size of the Cell here */ +){ + BtShared *pBt = pPage->pBt; + CellInfo info; + Pgno ovflPgno; + int rc; + int nOvfl; + u32 ovflPageSize; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pPage->xParseCell(pPage, pCell, &info); + *pnSize = info.nSize; + if( info.iOverflow==0 ){ + return SQLITE_OK; /* No overflow pages. Return without doing anything */ + } + if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){ + return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */ + } + ovflPgno = get4byte(&pCell[info.iOverflow]); + assert( pBt->usableSize > 4 ); + ovflPageSize = pBt->usableSize - 4; + nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; + assert( nOvfl>0 || + (CORRUPT_DB && (info.nPayload + ovflPageSize)btreePagecount(pBt) ){ + /* 0 is not a legal page number and page 1 cannot be an + ** overflow page. Therefore if ovflPgno<2 or past the end of the + ** file the database must be corrupt. */ + return SQLITE_CORRUPT_BKPT; + } + if( nOvfl ){ + rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext); + if( rc ) return rc; + } + + if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) ) + && sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1 + ){ + /* There is no reason any cursor should have an outstanding reference + ** to an overflow page belonging to a cell that is being deleted/updated. + ** So if there exists more than one reference to this page, then it + ** must not really be an overflow page and the database must be corrupt. + ** It is helpful to detect this before calling freePage2(), as + ** freePage2() may zero the page contents if secure-delete mode is + ** enabled. If this 'overflow' page happens to be a page that the + ** caller is iterating through or using in some other way, this + ** can be problematic. + */ + rc = SQLITE_CORRUPT_BKPT; + }else{ + rc = freePage2(pBt, pOvfl, ovflPgno); + } + + if( pOvfl ){ + sqlite3PagerUnref(pOvfl->pDbPage); + } + if( rc ) return rc; + ovflPgno = iNext; + } + return SQLITE_OK; +} + +/* +** Create the byte sequence used to represent a cell on page pPage +** and write that byte sequence into pCell[]. Overflow pages are +** allocated and filled in as necessary. The calling procedure +** is responsible for making sure sufficient space has been allocated +** for pCell[]. +** +** Note that pCell does not necessary need to point to the pPage->aData +** area. pCell might point to some temporary storage. The cell will +** be constructed in this temporary area then copied into pPage->aData +** later. +*/ +static int fillInCell( + MemPage *pPage, /* The page that contains the cell */ + unsigned char *pCell, /* Complete text of the cell */ + const void *pKey, i64 nKey, /* The key */ + const void *pData,int nData, /* The data */ + int nZero, /* Extra zero bytes to append to pData */ + int *pnSize /* Write cell size here */ +){ + int nPayload; + const u8 *pSrc; + int nSrc, n, rc; + int spaceLeft; + MemPage *pOvfl = 0; + MemPage *pToRelease = 0; + unsigned char *pPrior; + unsigned char *pPayload; + BtShared *pBt = pPage->pBt; + Pgno pgnoOvfl = 0; + int nHeader; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + + /* pPage is not necessarily writeable since pCell might be auxiliary + ** buffer space that is separate from the pPage buffer area */ + assert( pCellaData || pCell>=&pPage->aData[pBt->pageSize] + || sqlite3PagerIswriteable(pPage->pDbPage) ); + + /* Fill in the header. */ + nHeader = pPage->childPtrSize; + nPayload = nData + nZero; + if( pPage->intKeyLeaf ){ + nHeader += putVarint32(&pCell[nHeader], nPayload); + }else{ + assert( nData==0 ); + assert( nZero==0 ); + } + nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey); + + /* Fill in the payload size */ + if( pPage->intKey ){ + pSrc = pData; + nSrc = nData; + nData = 0; + }else{ + assert( nKey<=0x7fffffff && pKey!=0 ); + nPayload = (int)nKey; + pSrc = pKey; + nSrc = (int)nKey; + } + if( nPayload<=pPage->maxLocal ){ + n = nHeader + nPayload; + testcase( n==3 ); + testcase( n==4 ); + if( n<4 ) n = 4; + *pnSize = n; + spaceLeft = nPayload; + pPrior = pCell; + }else{ + int mn = pPage->minLocal; + n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4); + testcase( n==pPage->maxLocal ); + testcase( n==pPage->maxLocal+1 ); + if( n > pPage->maxLocal ) n = mn; + spaceLeft = n; + *pnSize = n + nHeader + 4; + pPrior = &pCell[nHeader+n]; + } + pPayload = &pCell[nHeader]; + + /* At this point variables should be set as follows: + ** + ** nPayload Total payload size in bytes + ** pPayload Begin writing payload here + ** spaceLeft Space available at pPayload. If nPayload>spaceLeft, + ** that means content must spill into overflow pages. + ** *pnSize Size of the local cell (not counting overflow pages) + ** pPrior Where to write the pgno of the first overflow page + ** + ** Use a call to btreeParseCellPtr() to verify that the values above + ** were computed correctly. + */ +#if SQLITE_DEBUG + { + CellInfo info; + pPage->xParseCell(pPage, pCell, &info); + assert( nHeader=(int)(info.pPayload - pCell) ); + assert( info.nKey==nKey ); + assert( *pnSize == info.nSize ); + assert( spaceLeft == info.nLocal ); + assert( pPrior == &pCell[info.iOverflow] ); + } +#endif + + /* Write the payload into the local Cell and any extra into overflow pages */ + while( nPayload>0 ){ + if( spaceLeft==0 ){ +#ifndef SQLITE_OMIT_AUTOVACUUM + Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */ + if( pBt->autoVacuum ){ + do{ + pgnoOvfl++; + } while( + PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt) + ); + } +#endif + rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0); +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If the database supports auto-vacuum, and the second or subsequent + ** overflow page is being allocated, add an entry to the pointer-map + ** for that page now. + ** + ** If this is the first overflow page, then write a partial entry + ** to the pointer-map. If we write nothing to this pointer-map slot, + ** then the optimistic overflow chain processing in clearCell() + ** may misinterpret the uninitialized values and delete the + ** wrong pages from the database. + */ + if( pBt->autoVacuum && rc==SQLITE_OK ){ + u8 eType = (pgnoPtrmap?PTRMAP_OVERFLOW2:PTRMAP_OVERFLOW1); + ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap, &rc); + if( rc ){ + releasePage(pOvfl); + } + } +#endif + if( rc ){ + releasePage(pToRelease); + return rc; + } + + /* If pToRelease is not zero than pPrior points into the data area + ** of pToRelease. Make sure pToRelease is still writeable. */ + assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) ); + + /* If pPrior is part of the data area of pPage, then make sure pPage + ** is still writeable */ + assert( pPrioraData || pPrior>=&pPage->aData[pBt->pageSize] + || sqlite3PagerIswriteable(pPage->pDbPage) ); + + put4byte(pPrior, pgnoOvfl); + releasePage(pToRelease); + pToRelease = pOvfl; + pPrior = pOvfl->aData; + put4byte(pPrior, 0); + pPayload = &pOvfl->aData[4]; + spaceLeft = pBt->usableSize - 4; + } + n = nPayload; + if( n>spaceLeft ) n = spaceLeft; + + /* If pToRelease is not zero than pPayload points into the data area + ** of pToRelease. Make sure pToRelease is still writeable. */ + assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) ); + + /* If pPayload is part of the data area of pPage, then make sure pPage + ** is still writeable */ + assert( pPayloadaData || pPayload>=&pPage->aData[pBt->pageSize] + || sqlite3PagerIswriteable(pPage->pDbPage) ); + + if( nSrc>0 ){ + if( n>nSrc ) n = nSrc; + assert( pSrc ); + memcpy(pPayload, pSrc, n); + }else{ + memset(pPayload, 0, n); + } + nPayload -= n; + pPayload += n; + pSrc += n; + nSrc -= n; + spaceLeft -= n; + if( nSrc==0 ){ + nSrc = nData; + pSrc = pData; + } + } + releasePage(pToRelease); + return SQLITE_OK; +} + +/* +** Remove the i-th cell from pPage. This routine effects pPage only. +** The cell content is not freed or deallocated. It is assumed that +** the cell content has been copied someplace else. This routine just +** removes the reference to the cell from pPage. +** +** "sz" must be the number of bytes in the cell. +*/ +static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ + u32 pc; /* Offset to cell content of cell being deleted */ + u8 *data; /* pPage->aData */ + u8 *ptr; /* Used to move bytes around within data[] */ + int rc; /* The return code */ + int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */ + + if( *pRC ) return; + + assert( idx>=0 && idxnCell ); + assert( CORRUPT_DB || sz==cellSize(pPage, idx) ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + data = pPage->aData; + ptr = &pPage->aCellIdx[2*idx]; + pc = get2byte(ptr); + hdr = pPage->hdrOffset; + testcase( pc==get2byte(&data[hdr+5]) ); + testcase( pc+sz==pPage->pBt->usableSize ); + if( pc < (u32)get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){ + *pRC = SQLITE_CORRUPT_BKPT; + return; + } + rc = freeSpace(pPage, pc, sz); + if( rc ){ + *pRC = rc; + return; + } + pPage->nCell--; + if( pPage->nCell==0 ){ + memset(&data[hdr+1], 0, 4); + data[hdr+7] = 0; + put2byte(&data[hdr+5], pPage->pBt->usableSize); + pPage->nFree = pPage->pBt->usableSize - pPage->hdrOffset + - pPage->childPtrSize - 8; + }else{ + memmove(ptr, ptr+2, 2*(pPage->nCell - idx)); + put2byte(&data[hdr+3], pPage->nCell); + pPage->nFree += 2; + } +} + +/* +** Insert a new cell on pPage at cell index "i". pCell points to the +** content of the cell. +** +** If the cell content will fit on the page, then put it there. If it +** will not fit, then make a copy of the cell content into pTemp if +** pTemp is not null. Regardless of pTemp, allocate a new entry +** in pPage->apOvfl[] and make it point to the cell content (either +** in pTemp or the original pCell) and also record its index. +** Allocating a new entry in pPage->aCell[] implies that +** pPage->nOverflow is incremented. +*/ +static void insertCell( + MemPage *pPage, /* Page into which we are copying */ + int i, /* New cell becomes the i-th cell of the page */ + u8 *pCell, /* Content of the new cell */ + int sz, /* Bytes of content in pCell */ + u8 *pTemp, /* Temp storage space for pCell, if needed */ + Pgno iChild, /* If non-zero, replace first 4 bytes with this value */ + int *pRC /* Read and write return code from here */ +){ + int idx = 0; /* Where to write new cell content in data[] */ + int j; /* Loop counter */ + u8 *data; /* The content of the whole page */ + u8 *pIns; /* The point in pPage->aCellIdx[] where no cell inserted */ + + if( *pRC ) return; + + assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); + assert( MX_CELL(pPage->pBt)<=10921 ); + assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB ); + assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) ); + assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + /* The cell should normally be sized correctly. However, when moving a + ** malformed cell from a leaf page to an interior page, if the cell size + ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size + ** might be less than 8 (leaf-size + pointer) on the interior node. Hence + ** the term after the || in the following assert(). */ + assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) ); + if( pPage->nOverflow || sz+2>pPage->nFree ){ + if( pTemp ){ + memcpy(pTemp, pCell, sz); + pCell = pTemp; + } + if( iChild ){ + put4byte(pCell, iChild); + } + j = pPage->nOverflow++; + assert( j<(int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])) ); + pPage->apOvfl[j] = pCell; + pPage->aiOvfl[j] = (u16)i; + + /* When multiple overflows occur, they are always sequential and in + ** sorted order. This invariants arise because multiple overflows can + ** only occur when inserting divider cells into the parent page during + ** balancing, and the dividers are adjacent and sorted. + */ + assert( j==0 || pPage->aiOvfl[j-1]<(u16)i ); /* Overflows in sorted order */ + assert( j==0 || i==pPage->aiOvfl[j-1]+1 ); /* Overflows are sequential */ + }else{ + int rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc!=SQLITE_OK ){ + *pRC = rc; + return; + } + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + data = pPage->aData; + assert( &data[pPage->cellOffset]==pPage->aCellIdx ); + rc = allocateSpace(pPage, sz, &idx); + if( rc ){ *pRC = rc; return; } + /* The allocateSpace() routine guarantees the following properties + ** if it returns successfully */ + assert( idx >= 0 ); + assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB ); + assert( idx+sz <= (int)pPage->pBt->usableSize ); + pPage->nFree -= (u16)(2 + sz); + memcpy(&data[idx], pCell, sz); + if( iChild ){ + put4byte(&data[idx], iChild); + } + pIns = pPage->aCellIdx + i*2; + memmove(pIns+2, pIns, 2*(pPage->nCell - i)); + put2byte(pIns, idx); + pPage->nCell++; + /* increment the cell count */ + if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++; + assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell ); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pPage->pBt->autoVacuum ){ + /* The cell may contain a pointer to an overflow page. If so, write + ** the entry for the overflow page into the pointer map. + */ + ptrmapPutOvflPtr(pPage, pCell, pRC); + } +#endif + } +} + +/* +** A CellArray object contains a cache of pointers and sizes for a +** consecutive sequence of cells that might be held multiple pages. +*/ +typedef struct CellArray CellArray; +struct CellArray { + int nCell; /* Number of cells in apCell[] */ + MemPage *pRef; /* Reference page */ + u8 **apCell; /* All cells begin balanced */ + u16 *szCell; /* Local size of all cells in apCell[] */ +}; + +/* +** Make sure the cell sizes at idx, idx+1, ..., idx+N-1 have been +** computed. +*/ +static void populateCellCache(CellArray *p, int idx, int N){ + assert( idx>=0 && idx+N<=p->nCell ); + while( N>0 ){ + assert( p->apCell[idx]!=0 ); + if( p->szCell[idx]==0 ){ + p->szCell[idx] = p->pRef->xCellSize(p->pRef, p->apCell[idx]); + }else{ + assert( CORRUPT_DB || + p->szCell[idx]==p->pRef->xCellSize(p->pRef, p->apCell[idx]) ); + } + idx++; + N--; + } +} + +/* +** Return the size of the Nth element of the cell array +*/ +static SQLITE_NOINLINE u16 computeCellSize(CellArray *p, int N){ + assert( N>=0 && NnCell ); + assert( p->szCell[N]==0 ); + p->szCell[N] = p->pRef->xCellSize(p->pRef, p->apCell[N]); + return p->szCell[N]; +} +static u16 cachedCellSize(CellArray *p, int N){ + assert( N>=0 && NnCell ); + if( p->szCell[N] ) return p->szCell[N]; + return computeCellSize(p, N); +} + +/* +** Array apCell[] contains pointers to nCell b-tree page cells. The +** szCell[] array contains the size in bytes of each cell. This function +** replaces the current contents of page pPg with the contents of the cell +** array. +** +** Some of the cells in apCell[] may currently be stored in pPg. This +** function works around problems caused by this by making a copy of any +** such cells before overwriting the page data. +** +** The MemPage.nFree field is invalidated by this function. It is the +** responsibility of the caller to set it correctly. +*/ +static int rebuildPage( + MemPage *pPg, /* Edit this page */ + int nCell, /* Final number of cells on page */ + u8 **apCell, /* Array of cells */ + u16 *szCell /* Array of cell sizes */ +){ + const int hdr = pPg->hdrOffset; /* Offset of header on pPg */ + u8 * const aData = pPg->aData; /* Pointer to data for pPg */ + const int usableSize = pPg->pBt->usableSize; + u8 * const pEnd = &aData[usableSize]; + int i; + u8 *pCellptr = pPg->aCellIdx; + u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager); + u8 *pData; + + i = get2byte(&aData[hdr+5]); + memcpy(&pTmp[i], &aData[i], usableSize - i); + + pData = pEnd; + for(i=0; iaData && pCellxCellSize(pPg, pCell) || CORRUPT_DB ); + testcase( szCell[i]!=pPg->xCellSize(pPg,pCell) ); + } + + /* The pPg->nFree field is now set incorrectly. The caller will fix it. */ + pPg->nCell = nCell; + pPg->nOverflow = 0; + + put2byte(&aData[hdr+1], 0); + put2byte(&aData[hdr+3], pPg->nCell); + put2byte(&aData[hdr+5], pData - aData); + aData[hdr+7] = 0x00; + return SQLITE_OK; +} + +/* +** Array apCell[] contains nCell pointers to b-tree cells. Array szCell +** contains the size in bytes of each such cell. This function attempts to +** add the cells stored in the array to page pPg. If it cannot (because +** the page needs to be defragmented before the cells will fit), non-zero +** is returned. Otherwise, if the cells are added successfully, zero is +** returned. +** +** Argument pCellptr points to the first entry in the cell-pointer array +** (part of page pPg) to populate. After cell apCell[0] is written to the +** page body, a 16-bit offset is written to pCellptr. And so on, for each +** cell in the array. It is the responsibility of the caller to ensure +** that it is safe to overwrite this part of the cell-pointer array. +** +** When this function is called, *ppData points to the start of the +** content area on page pPg. If the size of the content area is extended, +** *ppData is updated to point to the new start of the content area +** before returning. +** +** Finally, argument pBegin points to the byte immediately following the +** end of the space required by this page for the cell-pointer area (for +** all cells - not just those inserted by the current call). If the content +** area must be extended to before this point in order to accomodate all +** cells in apCell[], then the cells do not fit and non-zero is returned. +*/ +static int pageInsertArray( + MemPage *pPg, /* Page to add cells to */ + u8 *pBegin, /* End of cell-pointer array */ + u8 **ppData, /* IN/OUT: Page content -area pointer */ + u8 *pCellptr, /* Pointer to cell-pointer area */ + int iFirst, /* Index of first cell to add */ + int nCell, /* Number of cells to add to pPg */ + CellArray *pCArray /* Array of cells */ +){ + int i; + u8 *aData = pPg->aData; + u8 *pData = *ppData; + int iEnd = iFirst + nCell; + assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */ + for(i=iFirst; iapCell[i], sz); + put2byte(pCellptr, (pSlot - aData)); + pCellptr += 2; + } + *ppData = pData; + return 0; +} + +/* +** Array apCell[] contains nCell pointers to b-tree cells. Array szCell +** contains the size in bytes of each such cell. This function adds the +** space associated with each cell in the array that is currently stored +** within the body of pPg to the pPg free-list. The cell-pointers and other +** fields of the page are not updated. +** +** This function returns the total number of cells added to the free-list. +*/ +static int pageFreeArray( + MemPage *pPg, /* Page to edit */ + int iFirst, /* First cell to delete */ + int nCell, /* Cells to delete */ + CellArray *pCArray /* Array of cells */ +){ + u8 * const aData = pPg->aData; + u8 * const pEnd = &aData[pPg->pBt->usableSize]; + u8 * const pStart = &aData[pPg->hdrOffset + 8 + pPg->childPtrSize]; + int nRet = 0; + int i; + int iEnd = iFirst + nCell; + u8 *pFree = 0; + int szFree = 0; + + for(i=iFirst; iapCell[i]; + if( pCell>=pStart && pCellszCell[i]; assert( sz>0 ); + if( pFree!=(pCell + sz) ){ + if( pFree ){ + assert( pFree>aData && (pFree - aData)<65536 ); + freeSpace(pPg, (u16)(pFree - aData), szFree); + } + pFree = pCell; + szFree = sz; + if( pFree+sz>pEnd ) return 0; + }else{ + pFree = pCell; + szFree += sz; + } + nRet++; + } + } + if( pFree ){ + assert( pFree>aData && (pFree - aData)<65536 ); + freeSpace(pPg, (u16)(pFree - aData), szFree); + } + return nRet; +} + +/* +** apCell[] and szCell[] contains pointers to and sizes of all cells in the +** pages being balanced. The current page, pPg, has pPg->nCell cells starting +** with apCell[iOld]. After balancing, this page should hold nNew cells +** starting at apCell[iNew]. +** +** This routine makes the necessary adjustments to pPg so that it contains +** the correct cells after being balanced. +** +** The pPg->nFree field is invalid when this function returns. It is the +** responsibility of the caller to set it correctly. +*/ +static int editPage( + MemPage *pPg, /* Edit this page */ + int iOld, /* Index of first cell currently on page */ + int iNew, /* Index of new first cell on page */ + int nNew, /* Final number of cells on page */ + CellArray *pCArray /* Array of cells and sizes */ +){ + u8 * const aData = pPg->aData; + const int hdr = pPg->hdrOffset; + u8 *pBegin = &pPg->aCellIdx[nNew * 2]; + int nCell = pPg->nCell; /* Cells stored on pPg */ + u8 *pData; + u8 *pCellptr; + int i; + int iOldEnd = iOld + pPg->nCell + pPg->nOverflow; + int iNewEnd = iNew + nNew; + +#ifdef SQLITE_DEBUG + u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager); + memcpy(pTmp, aData, pPg->pBt->usableSize); +#endif + + /* Remove cells from the start and end of the page */ + if( iOldaCellIdx, &pPg->aCellIdx[nShift*2], nCell*2); + nCell -= nShift; + } + if( iNewEnd < iOldEnd ){ + nCell -= pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray); + } + + pData = &aData[get2byteNotZero(&aData[hdr+5])]; + if( pDataaCellIdx; + memmove(&pCellptr[nAdd*2], pCellptr, nCell*2); + if( pageInsertArray( + pPg, pBegin, &pData, pCellptr, + iNew, nAdd, pCArray + ) ) goto editpage_fail; + nCell += nAdd; + } + + /* Add any overflow cells */ + for(i=0; inOverflow; i++){ + int iCell = (iOld + pPg->aiOvfl[i]) - iNew; + if( iCell>=0 && iCellaCellIdx[iCell * 2]; + memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2); + nCell++; + if( pageInsertArray( + pPg, pBegin, &pData, pCellptr, + iCell+iNew, 1, pCArray + ) ) goto editpage_fail; + } + } + + /* Append cells to the end of the page */ + pCellptr = &pPg->aCellIdx[nCell*2]; + if( pageInsertArray( + pPg, pBegin, &pData, pCellptr, + iNew+nCell, nNew-nCell, pCArray + ) ) goto editpage_fail; + + pPg->nCell = nNew; + pPg->nOverflow = 0; + + put2byte(&aData[hdr+3], pPg->nCell); + put2byte(&aData[hdr+5], pData - aData); + +#ifdef SQLITE_DEBUG + for(i=0; iapCell[i+iNew]; + int iOff = get2byteAligned(&pPg->aCellIdx[i*2]); + if( pCell>=aData && pCell<&aData[pPg->pBt->usableSize] ){ + pCell = &pTmp[pCell - aData]; + } + assert( 0==memcmp(pCell, &aData[iOff], + pCArray->pRef->xCellSize(pCArray->pRef, pCArray->apCell[i+iNew])) ); + } +#endif + + return SQLITE_OK; + editpage_fail: + /* Unable to edit this page. Rebuild it from scratch instead. */ + populateCellCache(pCArray, iNew, nNew); + return rebuildPage(pPg, nNew, &pCArray->apCell[iNew], &pCArray->szCell[iNew]); +} + +/* +** The following parameters determine how many adjacent pages get involved +** in a balancing operation. NN is the number of neighbors on either side +** of the page that participate in the balancing operation. NB is the +** total number of pages that participate, including the target page and +** NN neighbors on either side. +** +** The minimum value of NN is 1 (of course). Increasing NN above 1 +** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance +** in exchange for a larger degradation in INSERT and UPDATE performance. +** The value of NN appears to give the best results overall. +*/ +#define NN 1 /* Number of neighbors on either side of pPage */ +#define NB (NN*2+1) /* Total pages involved in the balance */ + + +#ifndef SQLITE_OMIT_QUICKBALANCE +/* +** This version of balance() handles the common special case where +** a new entry is being inserted on the extreme right-end of the +** tree, in other words, when the new entry will become the largest +** entry in the tree. +** +** Instead of trying to balance the 3 right-most leaf pages, just add +** a new page to the right-hand side and put the one new entry in +** that page. This leaves the right side of the tree somewhat +** unbalanced. But odds are that we will be inserting new entries +** at the end soon afterwards so the nearly empty page will quickly +** fill up. On average. +** +** pPage is the leaf page which is the right-most page in the tree. +** pParent is its parent. pPage must have a single overflow entry +** which is also the right-most entry on the page. +** +** The pSpace buffer is used to store a temporary copy of the divider +** cell that will be inserted into pParent. Such a cell consists of a 4 +** byte page number followed by a variable length integer. In other +** words, at most 13 bytes. Hence the pSpace buffer must be at +** least 13 bytes in size. +*/ +static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){ + BtShared *const pBt = pPage->pBt; /* B-Tree Database */ + MemPage *pNew; /* Newly allocated page */ + int rc; /* Return Code */ + Pgno pgnoNew; /* Page number of pNew */ + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( sqlite3PagerIswriteable(pParent->pDbPage) ); + assert( pPage->nOverflow==1 ); + + /* This error condition is now caught prior to reaching this function */ + if( NEVER(pPage->nCell==0) ) return SQLITE_CORRUPT_BKPT; + + /* Allocate a new page. This page will become the right-sibling of + ** pPage. Make the parent page writable, so that the new divider cell + ** may be inserted. If both these operations are successful, proceed. + */ + rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); + + if( rc==SQLITE_OK ){ + + u8 *pOut = &pSpace[4]; + u8 *pCell = pPage->apOvfl[0]; + u16 szCell = pPage->xCellSize(pPage, pCell); + u8 *pStop; + + assert( sqlite3PagerIswriteable(pNew->pDbPage) ); + assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) ); + zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF); + rc = rebuildPage(pNew, 1, &pCell, &szCell); + if( NEVER(rc) ) return rc; + pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell; + + /* If this is an auto-vacuum database, update the pointer map + ** with entries for the new page, and any pointer from the + ** cell on the page to an overflow page. If either of these + ** operations fails, the return code is set, but the contents + ** of the parent page are still manipulated by thh code below. + ** That is Ok, at this point the parent page is guaranteed to + ** be marked as dirty. Returning an error code will cause a + ** rollback, undoing any changes made to the parent page. + */ + if( ISAUTOVACUUM ){ + ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno, &rc); + if( szCell>pNew->minLocal ){ + ptrmapPutOvflPtr(pNew, pCell, &rc); + } + } + + /* Create a divider cell to insert into pParent. The divider cell + ** consists of a 4-byte page number (the page number of pPage) and + ** a variable length key value (which must be the same value as the + ** largest key on pPage). + ** + ** To find the largest key value on pPage, first find the right-most + ** cell on pPage. The first two fields of this cell are the + ** record-length (a variable length integer at most 32-bits in size) + ** and the key value (a variable length integer, may have any value). + ** The first of the while(...) loops below skips over the record-length + ** field. The second while(...) loop copies the key value from the + ** cell on pPage into the pSpace buffer. + */ + pCell = findCell(pPage, pPage->nCell-1); + pStop = &pCell[9]; + while( (*(pCell++)&0x80) && pCellnCell, pSpace, (int)(pOut-pSpace), + 0, pPage->pgno, &rc); + + /* Set the right-child pointer of pParent to point to the new page. */ + put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew); + + /* Release the reference to the new page. */ + releasePage(pNew); + } + + return rc; +} +#endif /* SQLITE_OMIT_QUICKBALANCE */ + +#if 0 +/* +** This function does not contribute anything to the operation of SQLite. +** it is sometimes activated temporarily while debugging code responsible +** for setting pointer-map entries. +*/ +static int ptrmapCheckPages(MemPage **apPage, int nPage){ + int i, j; + for(i=0; ipBt; + assert( pPage->isInit ); + + for(j=0; jnCell; j++){ + CellInfo info; + u8 *z; + + z = findCell(pPage, j); + pPage->xParseCell(pPage, z, &info); + if( info.iOverflow ){ + Pgno ovfl = get4byte(&z[info.iOverflow]); + ptrmapGet(pBt, ovfl, &e, &n); + assert( n==pPage->pgno && e==PTRMAP_OVERFLOW1 ); + } + if( !pPage->leaf ){ + Pgno child = get4byte(z); + ptrmapGet(pBt, child, &e, &n); + assert( n==pPage->pgno && e==PTRMAP_BTREE ); + } + } + if( !pPage->leaf ){ + Pgno child = get4byte(&pPage->aData[pPage->hdrOffset+8]); + ptrmapGet(pBt, child, &e, &n); + assert( n==pPage->pgno && e==PTRMAP_BTREE ); + } + } + return 1; +} +#endif + +/* +** This function is used to copy the contents of the b-tree node stored +** on page pFrom to page pTo. If page pFrom was not a leaf page, then +** the pointer-map entries for each child page are updated so that the +** parent page stored in the pointer map is page pTo. If pFrom contained +** any cells with overflow page pointers, then the corresponding pointer +** map entries are also updated so that the parent page is page pTo. +** +** If pFrom is currently carrying any overflow cells (entries in the +** MemPage.apOvfl[] array), they are not copied to pTo. +** +** Before returning, page pTo is reinitialized using btreeInitPage(). +** +** The performance of this function is not critical. It is only used by +** the balance_shallower() and balance_deeper() procedures, neither of +** which are called often under normal circumstances. +*/ +static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){ + if( (*pRC)==SQLITE_OK ){ + BtShared * const pBt = pFrom->pBt; + u8 * const aFrom = pFrom->aData; + u8 * const aTo = pTo->aData; + int const iFromHdr = pFrom->hdrOffset; + int const iToHdr = ((pTo->pgno==1) ? 100 : 0); + int rc; + int iData; + + + assert( pFrom->isInit ); + assert( pFrom->nFree>=iToHdr ); + assert( get2byte(&aFrom[iFromHdr+5]) <= (int)pBt->usableSize ); + + /* Copy the b-tree node content from page pFrom to page pTo. */ + iData = get2byte(&aFrom[iFromHdr+5]); + memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData); + memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell); + + /* Reinitialize page pTo so that the contents of the MemPage structure + ** match the new data. The initialization of pTo can actually fail under + ** fairly obscure circumstances, even though it is a copy of initialized + ** page pFrom. + */ + pTo->isInit = 0; + rc = btreeInitPage(pTo); + if( rc!=SQLITE_OK ){ + *pRC = rc; + return; + } + + /* If this is an auto-vacuum database, update the pointer-map entries + ** for any b-tree or overflow pages that pTo now contains the pointers to. + */ + if( ISAUTOVACUUM ){ + *pRC = setChildPtrmaps(pTo); + } + } +} + +/* +** This routine redistributes cells on the iParentIdx'th child of pParent +** (hereafter "the page") and up to 2 siblings so that all pages have about the +** same amount of free space. Usually a single sibling on either side of the +** page are used in the balancing, though both siblings might come from one +** side if the page is the first or last child of its parent. If the page +** has fewer than 2 siblings (something which can only happen if the page +** is a root page or a child of a root page) then all available siblings +** participate in the balancing. +** +** The number of siblings of the page might be increased or decreased by +** one or two in an effort to keep pages nearly full but not over full. +** +** Note that when this routine is called, some of the cells on the page +** might not actually be stored in MemPage.aData[]. This can happen +** if the page is overfull. This routine ensures that all cells allocated +** to the page and its siblings fit into MemPage.aData[] before returning. +** +** In the course of balancing the page and its siblings, cells may be +** inserted into or removed from the parent page (pParent). Doing so +** may cause the parent page to become overfull or underfull. If this +** happens, it is the responsibility of the caller to invoke the correct +** balancing routine to fix this problem (see the balance() routine). +** +** If this routine fails for any reason, it might leave the database +** in a corrupted state. So if this routine fails, the database should +** be rolled back. +** +** The third argument to this function, aOvflSpace, is a pointer to a +** buffer big enough to hold one page. If while inserting cells into the parent +** page (pParent) the parent page becomes overfull, this buffer is +** used to store the parent's overflow cells. Because this function inserts +** a maximum of four divider cells into the parent page, and the maximum +** size of a cell stored within an internal node is always less than 1/4 +** of the page-size, the aOvflSpace[] buffer is guaranteed to be large +** enough for all overflow cells. +** +** If aOvflSpace is set to a null pointer, this function returns +** SQLITE_NOMEM. +*/ +#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM) +#pragma optimize("", off) +#endif +static int balance_nonroot( + MemPage *pParent, /* Parent page of siblings being balanced */ + int iParentIdx, /* Index of "the page" in pParent */ + u8 *aOvflSpace, /* page-size bytes of space for parent ovfl */ + int isRoot, /* True if pParent is a root-page */ + int bBulk /* True if this call is part of a bulk load */ +){ + BtShared *pBt; /* The whole database */ + int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */ + int nNew = 0; /* Number of pages in apNew[] */ + int nOld; /* Number of pages in apOld[] */ + int i, j, k; /* Loop counters */ + int nxDiv; /* Next divider slot in pParent->aCell[] */ + int rc = SQLITE_OK; /* The return code */ + u16 leafCorrection; /* 4 if pPage is a leaf. 0 if not */ + int leafData; /* True if pPage is a leaf of a LEAFDATA tree */ + int usableSpace; /* Bytes in pPage beyond the header */ + int pageFlags; /* Value of pPage->aData[0] */ + int iSpace1 = 0; /* First unused byte of aSpace1[] */ + int iOvflSpace = 0; /* First unused byte of aOvflSpace[] */ + int szScratch; /* Size of scratch memory requested */ + MemPage *apOld[NB]; /* pPage and up to two siblings */ + MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */ + u8 *pRight; /* Location in parent of right-sibling pointer */ + u8 *apDiv[NB-1]; /* Divider cells in pParent */ + int cntNew[NB+2]; /* Index in b.paCell[] of cell after i-th page */ + int cntOld[NB+2]; /* Old index in b.apCell[] */ + int szNew[NB+2]; /* Combined size of cells placed on i-th page */ + u8 *aSpace1; /* Space for copies of dividers cells */ + Pgno pgno; /* Temp var to store a page number in */ + u8 abDone[NB+2]; /* True after i'th new page is populated */ + Pgno aPgno[NB+2]; /* Page numbers of new pages before shuffling */ + Pgno aPgOrder[NB+2]; /* Copy of aPgno[] used for sorting pages */ + u16 aPgFlags[NB+2]; /* flags field of new pages before shuffling */ + CellArray b; /* Parsed information on cells being balanced */ + + memset(abDone, 0, sizeof(abDone)); + b.nCell = 0; + b.apCell = 0; + pBt = pParent->pBt; + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( sqlite3PagerIswriteable(pParent->pDbPage) ); + +#if 0 + TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); +#endif + + /* At this point pParent may have at most one overflow cell. And if + ** this overflow cell is present, it must be the cell with + ** index iParentIdx. This scenario comes about when this function + ** is called (indirectly) from sqlite3BtreeDelete(). + */ + assert( pParent->nOverflow==0 || pParent->nOverflow==1 ); + assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx ); + + if( !aOvflSpace ){ + return SQLITE_NOMEM; + } + + /* Find the sibling pages to balance. Also locate the cells in pParent + ** that divide the siblings. An attempt is made to find NN siblings on + ** either side of pPage. More siblings are taken from one side, however, + ** if there are fewer than NN siblings on the other side. If pParent + ** has NB or fewer children then all children of pParent are taken. + ** + ** This loop also drops the divider cells from the parent page. This + ** way, the remainder of the function does not have to deal with any + ** overflow cells in the parent page, since if any existed they will + ** have already been removed. + */ + i = pParent->nOverflow + pParent->nCell; + if( i<2 ){ + nxDiv = 0; + }else{ + assert( bBulk==0 || bBulk==1 ); + if( iParentIdx==0 ){ + nxDiv = 0; + }else if( iParentIdx==i ){ + nxDiv = i-2+bBulk; + }else{ + nxDiv = iParentIdx-1; + } + i = 2-bBulk; + } + nOld = i+1; + if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){ + pRight = &pParent->aData[pParent->hdrOffset+8]; + }else{ + pRight = findCell(pParent, i+nxDiv-pParent->nOverflow); + } + pgno = get4byte(pRight); + while( 1 ){ + rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0); + if( rc ){ + memset(apOld, 0, (i+1)*sizeof(MemPage*)); + goto balance_cleanup; + } + nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow; + if( (i--)==0 ) break; + + if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){ + apDiv[i] = pParent->apOvfl[0]; + pgno = get4byte(apDiv[i]); + szNew[i] = pParent->xCellSize(pParent, apDiv[i]); + pParent->nOverflow = 0; + }else{ + apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow); + pgno = get4byte(apDiv[i]); + szNew[i] = pParent->xCellSize(pParent, apDiv[i]); + + /* Drop the cell from the parent page. apDiv[i] still points to + ** the cell within the parent, even though it has been dropped. + ** This is safe because dropping a cell only overwrites the first + ** four bytes of it, and this function does not need the first + ** four bytes of the divider cell. So the pointer is safe to use + ** later on. + ** + ** But not if we are in secure-delete mode. In secure-delete mode, + ** the dropCell() routine will overwrite the entire cell with zeroes. + ** In this case, temporarily copy the cell into the aOvflSpace[] + ** buffer. It will be copied out again as soon as the aSpace[] buffer + ** is allocated. */ + if( pBt->btsFlags & BTS_SECURE_DELETE ){ + int iOff; + + iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData); + if( (iOff+szNew[i])>(int)pBt->usableSize ){ + rc = SQLITE_CORRUPT_BKPT; + memset(apOld, 0, (i+1)*sizeof(MemPage*)); + goto balance_cleanup; + }else{ + memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]); + apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData]; + } + } + dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc); + } + } + + /* Make nMaxCells a multiple of 4 in order to preserve 8-byte + ** alignment */ + nMaxCells = (nMaxCells + 3)&~3; + + /* + ** Allocate space for memory structures + */ + szScratch = + nMaxCells*sizeof(u8*) /* b.apCell */ + + nMaxCells*sizeof(u16) /* b.szCell */ + + pBt->pageSize; /* aSpace1 */ + + /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer + ** that is more than 6 times the database page size. */ + assert( szScratch<=6*(int)pBt->pageSize ); + b.apCell = sqlite3ScratchMalloc( szScratch ); + if( b.apCell==0 ){ + rc = SQLITE_NOMEM; + goto balance_cleanup; + } + b.szCell = (u16*)&b.apCell[nMaxCells]; + aSpace1 = (u8*)&b.szCell[nMaxCells]; + assert( EIGHT_BYTE_ALIGNMENT(aSpace1) ); + + /* + ** Load pointers to all cells on sibling pages and the divider cells + ** into the local b.apCell[] array. Make copies of the divider cells + ** into space obtained from aSpace1[]. The divider cells have already + ** been removed from pParent. + ** + ** If the siblings are on leaf pages, then the child pointers of the + ** divider cells are stripped from the cells before they are copied + ** into aSpace1[]. In this way, all cells in b.apCell[] are without + ** child pointers. If siblings are not leaves, then all cell in + ** b.apCell[] include child pointers. Either way, all cells in b.apCell[] + ** are alike. + ** + ** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf. + ** leafData: 1 if pPage holds key+data and pParent holds only keys. + */ + b.pRef = apOld[0]; + leafCorrection = b.pRef->leaf*4; + leafData = b.pRef->intKeyLeaf; + for(i=0; inCell; + u8 *aData = pOld->aData; + u16 maskPage = pOld->maskPage; + u8 *piCell = aData + pOld->cellOffset; + u8 *piEnd; + + /* Verify that all sibling pages are of the same "type" (table-leaf, + ** table-interior, index-leaf, or index-interior). + */ + if( pOld->aData[0]!=apOld[0]->aData[0] ){ + rc = SQLITE_CORRUPT_BKPT; + goto balance_cleanup; + } + + /* Load b.apCell[] with pointers to all cells in pOld. If pOld + ** constains overflow cells, include them in the b.apCell[] array + ** in the correct spot. + ** + ** Note that when there are multiple overflow cells, it is always the + ** case that they are sequential and adjacent. This invariant arises + ** because multiple overflows can only occurs when inserting divider + ** cells into a parent on a prior balance, and divider cells are always + ** adjacent and are inserted in order. There is an assert() tagged + ** with "NOTE 1" in the overflow cell insertion loop to prove this + ** invariant. + ** + ** This must be done in advance. Once the balance starts, the cell + ** offset section of the btree page will be overwritten and we will no + ** long be able to find the cells if a pointer to each cell is not saved + ** first. + */ + memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*limit); + if( pOld->nOverflow>0 ){ + memset(&b.szCell[b.nCell+limit], 0, sizeof(b.szCell[0])*pOld->nOverflow); + limit = pOld->aiOvfl[0]; + for(j=0; jnOverflow; k++){ + assert( k==0 || pOld->aiOvfl[k-1]+1==pOld->aiOvfl[k] );/* NOTE 1 */ + b.apCell[b.nCell] = pOld->apOvfl[k]; + b.nCell++; + } + } + piEnd = aData + pOld->cellOffset + 2*pOld->nCell; + while( piCellmaxLocal+23 ); + assert( iSpace1 <= (int)pBt->pageSize ); + memcpy(pTemp, apDiv[i], sz); + b.apCell[b.nCell] = pTemp+leafCorrection; + assert( leafCorrection==0 || leafCorrection==4 ); + b.szCell[b.nCell] = b.szCell[b.nCell] - leafCorrection; + if( !pOld->leaf ){ + assert( leafCorrection==0 ); + assert( pOld->hdrOffset==0 ); + /* The right pointer of the child page pOld becomes the left + ** pointer of the divider cell */ + memcpy(b.apCell[b.nCell], &pOld->aData[8], 4); + }else{ + assert( leafCorrection==4 ); + while( b.szCell[b.nCell]<4 ){ + /* Do not allow any cells smaller than 4 bytes. If a smaller cell + ** does exist, pad it with 0x00 bytes. */ + assert( b.szCell[b.nCell]==3 || CORRUPT_DB ); + assert( b.apCell[b.nCell]==&aSpace1[iSpace1-3] || CORRUPT_DB ); + aSpace1[iSpace1++] = 0x00; + b.szCell[b.nCell]++; + } + } + b.nCell++; + } + } + + /* + ** Figure out the number of pages needed to hold all b.nCell cells. + ** Store this number in "k". Also compute szNew[] which is the total + ** size of all cells on the i-th page and cntNew[] which is the index + ** in b.apCell[] of the cell that divides page i from page i+1. + ** cntNew[k] should equal b.nCell. + ** + ** Values computed by this block: + ** + ** k: The total number of sibling pages + ** szNew[i]: Spaced used on the i-th sibling page. + ** cntNew[i]: Index in b.apCell[] and b.szCell[] for the first cell to + ** the right of the i-th sibling page. + ** usableSpace: Number of bytes of space available on each sibling. + ** + */ + usableSpace = pBt->usableSize - 12 + leafCorrection; + for(i=0; inFree; + if( szNew[i]<0 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } + for(j=0; jnOverflow; j++){ + szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]); + } + cntNew[i] = cntOld[i]; + } + k = nOld; + for(i=0; iusableSpace ){ + if( i+1>=k ){ + k = i+2; + if( k>NB+2 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } + szNew[k-1] = 0; + cntNew[k-1] = b.nCell; + } + sz = 2 + cachedCellSize(&b, cntNew[i]-1); + szNew[i] -= sz; + if( !leafData ){ + if( cntNew[i]usableSpace ) break; + szNew[i] += sz; + cntNew[i]++; + if( !leafData ){ + if( cntNew[i]=b.nCell ){ + k = i+1; + }else if( cntNew[i] <= (i>0 ? cntNew[i-1] : 0) ){ + rc = SQLITE_CORRUPT_BKPT; + goto balance_cleanup; + } + } + + /* + ** The packing computed by the previous block is biased toward the siblings + ** on the left side (siblings with smaller keys). The left siblings are + ** always nearly full, while the right-most sibling might be nearly empty. + ** The next block of code attempts to adjust the packing of siblings to + ** get a better balance. + ** + ** This adjustment is more than an optimization. The packing above might + ** be so out of balance as to be illegal. For example, the right-most + ** sibling might be completely empty. This adjustment is not optional. + */ + for(i=k-1; i>0; i--){ + int szRight = szNew[i]; /* Size of sibling on the right */ + int szLeft = szNew[i-1]; /* Size of sibling on the left */ + int r; /* Index of right-most cell in left sibling */ + int d; /* Index of first cell to the left of right sibling */ + + r = cntNew[i-1] - 1; + d = r + 1 - leafData; + (void)cachedCellSize(&b, d); + do{ + assert( d szLeft-(b.szCell[r]+2)) ){ + break; + } + szRight += b.szCell[d] + 2; + szLeft -= b.szCell[r] + 2; + cntNew[i-1] = r; + r--; + d--; + }while( r>=0 ); + szNew[i] = szRight; + szNew[i-1] = szLeft; + if( cntNew[i-1] <= (i>1 ? cntNew[i-2] : 0) ){ + rc = SQLITE_CORRUPT_BKPT; + goto balance_cleanup; + } + } + + /* Sanity check: For a non-corrupt database file one of the follwing + ** must be true: + ** (1) We found one or more cells (cntNew[0])>0), or + ** (2) pPage is a virtual root page. A virtual root page is when + ** the real root page is page 1 and we are the only child of + ** that page. + */ + assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) || CORRUPT_DB); + TRACE(("BALANCE: old: %d(nc=%d) %d(nc=%d) %d(nc=%d)\n", + apOld[0]->pgno, apOld[0]->nCell, + nOld>=2 ? apOld[1]->pgno : 0, nOld>=2 ? apOld[1]->nCell : 0, + nOld>=3 ? apOld[2]->pgno : 0, nOld>=3 ? apOld[2]->nCell : 0 + )); + + /* + ** Allocate k new pages. Reuse old pages where possible. + */ + pageFlags = apOld[0]->aData[0]; + for(i=0; ipDbPage); + nNew++; + if( rc ) goto balance_cleanup; + }else{ + assert( i>0 ); + rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0); + if( rc ) goto balance_cleanup; + zeroPage(pNew, pageFlags); + apNew[i] = pNew; + nNew++; + cntOld[i] = b.nCell; + + /* Set the pointer-map entry for the new sibling page. */ + if( ISAUTOVACUUM ){ + ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno, &rc); + if( rc!=SQLITE_OK ){ + goto balance_cleanup; + } + } + } + } + + /* + ** Reassign page numbers so that the new pages are in ascending order. + ** This helps to keep entries in the disk file in order so that a scan + ** of the table is closer to a linear scan through the file. That in turn + ** helps the operating system to deliver pages from the disk more rapidly. + ** + ** An O(n^2) insertion sort algorithm is used, but since n is never more + ** than (NB+2) (a small constant), that should not be a problem. + ** + ** When NB==3, this one optimization makes the database about 25% faster + ** for large insertions and deletions. + */ + for(i=0; ipgno; + aPgFlags[i] = apNew[i]->pDbPage->flags; + for(j=0; ji ){ + sqlite3PagerRekey(apNew[iBest]->pDbPage, pBt->nPage+iBest+1, 0); + } + sqlite3PagerRekey(apNew[i]->pDbPage, pgno, aPgFlags[iBest]); + apNew[i]->pgno = pgno; + } + } + + TRACE(("BALANCE: new: %d(%d nc=%d) %d(%d nc=%d) %d(%d nc=%d) " + "%d(%d nc=%d) %d(%d nc=%d)\n", + apNew[0]->pgno, szNew[0], cntNew[0], + nNew>=2 ? apNew[1]->pgno : 0, nNew>=2 ? szNew[1] : 0, + nNew>=2 ? cntNew[1] - cntNew[0] - !leafData : 0, + nNew>=3 ? apNew[2]->pgno : 0, nNew>=3 ? szNew[2] : 0, + nNew>=3 ? cntNew[2] - cntNew[1] - !leafData : 0, + nNew>=4 ? apNew[3]->pgno : 0, nNew>=4 ? szNew[3] : 0, + nNew>=4 ? cntNew[3] - cntNew[2] - !leafData : 0, + nNew>=5 ? apNew[4]->pgno : 0, nNew>=5 ? szNew[4] : 0, + nNew>=5 ? cntNew[4] - cntNew[3] - !leafData : 0 + )); + + assert( sqlite3PagerIswriteable(pParent->pDbPage) ); + put4byte(pRight, apNew[nNew-1]->pgno); + + /* If the sibling pages are not leaves, ensure that the right-child pointer + ** of the right-most new sibling page is set to the value that was + ** originally in the same field of the right-most old sibling page. */ + if( (pageFlags & PTF_LEAF)==0 && nOld!=nNew ){ + MemPage *pOld = (nNew>nOld ? apNew : apOld)[nOld-1]; + memcpy(&apNew[nNew-1]->aData[8], &pOld->aData[8], 4); + } + + /* Make any required updates to pointer map entries associated with + ** cells stored on sibling pages following the balance operation. Pointer + ** map entries associated with divider cells are set by the insertCell() + ** routine. The associated pointer map entries are: + ** + ** a) if the cell contains a reference to an overflow chain, the + ** entry associated with the first page in the overflow chain, and + ** + ** b) if the sibling pages are not leaves, the child page associated + ** with the cell. + ** + ** If the sibling pages are not leaves, then the pointer map entry + ** associated with the right-child of each sibling may also need to be + ** updated. This happens below, after the sibling pages have been + ** populated, not here. + */ + if( ISAUTOVACUUM ){ + MemPage *pNew = apNew[0]; + u8 *aOld = pNew->aData; + int cntOldNext = pNew->nCell + pNew->nOverflow; + int usableSize = pBt->usableSize; + int iNew = 0; + int iOld = 0; + + for(i=0; inCell + pOld->nOverflow + !leafData; + aOld = pOld->aData; + } + if( i==cntNew[iNew] ){ + pNew = apNew[++iNew]; + if( !leafData ) continue; + } + + /* Cell pCell is destined for new sibling page pNew. Originally, it + ** was either part of sibling page iOld (possibly an overflow cell), + ** or else the divider cell to the left of sibling page iOld. So, + ** if sibling page iOld had the same page number as pNew, and if + ** pCell really was a part of sibling page iOld (not a divider or + ** overflow cell), we can skip updating the pointer map entries. */ + if( iOld>=nNew + || pNew->pgno!=aPgno[iOld] + || pCell=&aOld[usableSize] + ){ + if( !leafCorrection ){ + ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc); + } + if( cachedCellSize(&b,i)>pNew->minLocal ){ + ptrmapPutOvflPtr(pNew, pCell, &rc); + } + if( rc ) goto balance_cleanup; + } + } + } + + /* Insert new divider cells into pParent. */ + for(i=0; ileaf ){ + memcpy(&pNew->aData[8], pCell, 4); + }else if( leafData ){ + /* If the tree is a leaf-data tree, and the siblings are leaves, + ** then there is no divider cell in b.apCell[]. Instead, the divider + ** cell consists of the integer key for the right-most cell of + ** the sibling-page assembled above only. + */ + CellInfo info; + j--; + pNew->xParseCell(pNew, b.apCell[j], &info); + pCell = pTemp; + sz = 4 + putVarint(&pCell[4], info.nKey); + pTemp = 0; + }else{ + pCell -= 4; + /* Obscure case for non-leaf-data trees: If the cell at pCell was + ** previously stored on a leaf node, and its reported size was 4 + ** bytes, then it may actually be smaller than this + ** (see btreeParseCellPtr(), 4 bytes is the minimum size of + ** any cell). But it is important to pass the correct size to + ** insertCell(), so reparse the cell now. + ** + ** Note that this can never happen in an SQLite data file, as all + ** cells are at least 4 bytes. It only happens in b-trees used + ** to evaluate "IN (SELECT ...)" and similar clauses. + */ + if( b.szCell[j]==4 ){ + assert(leafCorrection==4); + sz = pParent->xCellSize(pParent, pCell); + } + } + iOvflSpace += sz; + assert( sz<=pBt->maxLocal+23 ); + assert( iOvflSpace <= (int)pBt->pageSize ); + insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc); + if( rc!=SQLITE_OK ) goto balance_cleanup; + assert( sqlite3PagerIswriteable(pParent->pDbPage) ); + } + + /* Now update the actual sibling pages. The order in which they are updated + ** is important, as this code needs to avoid disrupting any page from which + ** cells may still to be read. In practice, this means: + ** + ** (1) If cells are moving left (from apNew[iPg] to apNew[iPg-1]) + ** then it is not safe to update page apNew[iPg] until after + ** the left-hand sibling apNew[iPg-1] has been updated. + ** + ** (2) If cells are moving right (from apNew[iPg] to apNew[iPg+1]) + ** then it is not safe to update page apNew[iPg] until after + ** the right-hand sibling apNew[iPg+1] has been updated. + ** + ** If neither of the above apply, the page is safe to update. + ** + ** The iPg value in the following loop starts at nNew-1 goes down + ** to 0, then back up to nNew-1 again, thus making two passes over + ** the pages. On the initial downward pass, only condition (1) above + ** needs to be tested because (2) will always be true from the previous + ** step. On the upward pass, both conditions are always true, so the + ** upwards pass simply processes pages that were missed on the downward + ** pass. + */ + for(i=1-nNew; i=0 && iPg=0 /* On the upwards pass, or... */ + || cntOld[iPg-1]>=cntNew[iPg-1] /* Condition (1) is true */ + ){ + int iNew; + int iOld; + int nNewCell; + + /* Verify condition (1): If cells are moving left, update iPg + ** only after iPg-1 has already been updated. */ + assert( iPg==0 || cntOld[iPg-1]>=cntNew[iPg-1] || abDone[iPg-1] ); + + /* Verify condition (2): If cells are moving right, update iPg + ** only after iPg+1 has already been updated. */ + assert( cntNew[iPg]>=cntOld[iPg] || abDone[iPg+1] ); + + if( iPg==0 ){ + iNew = iOld = 0; + nNewCell = cntNew[0]; + }else{ + iOld = iPgnFree = usableSpace-szNew[iPg]; + assert( apNew[iPg]->nOverflow==0 ); + assert( apNew[iPg]->nCell==nNewCell ); + } + } + + /* All pages have been processed exactly once */ + assert( memcmp(abDone, "\01\01\01\01\01", nNew)==0 ); + + assert( nOld>0 ); + assert( nNew>0 ); + + if( isRoot && pParent->nCell==0 && pParent->hdrOffset<=apNew[0]->nFree ){ + /* The root page of the b-tree now contains no cells. The only sibling + ** page is the right-child of the parent. Copy the contents of the + ** child page into the parent, decreasing the overall height of the + ** b-tree structure by one. This is described as the "balance-shallower" + ** sub-algorithm in some documentation. + ** + ** If this is an auto-vacuum database, the call to copyNodeContent() + ** sets all pointer-map entries corresponding to database image pages + ** for which the pointer is stored within the content being copied. + ** + ** It is critical that the child page be defragmented before being + ** copied into the parent, because if the parent is page 1 then it will + ** by smaller than the child due to the database header, and so all the + ** free space needs to be up front. + */ + assert( nNew==1 ); + rc = defragmentPage(apNew[0]); + testcase( rc!=SQLITE_OK ); + assert( apNew[0]->nFree == + (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) + || rc!=SQLITE_OK + ); + copyNodeContent(apNew[0], pParent, &rc); + freePage(apNew[0], &rc); + }else if( ISAUTOVACUUM && !leafCorrection ){ + /* Fix the pointer map entries associated with the right-child of each + ** sibling page. All other pointer map entries have already been taken + ** care of. */ + for(i=0; iaData[8]); + ptrmapPut(pBt, key, PTRMAP_BTREE, apNew[i]->pgno, &rc); + } + } + + assert( pParent->isInit ); + TRACE(("BALANCE: finished: old=%d new=%d cells=%d\n", + nOld, nNew, b.nCell)); + + /* Free any old pages that were not reused as new pages. + */ + for(i=nNew; iisInit ){ + /* The ptrmapCheckPages() contains assert() statements that verify that + ** all pointer map pages are set correctly. This is helpful while + ** debugging. This is usually disabled because a corrupt database may + ** cause an assert() statement to fail. */ + ptrmapCheckPages(apNew, nNew); + ptrmapCheckPages(&pParent, 1); + } +#endif + + /* + ** Cleanup before returning. + */ +balance_cleanup: + sqlite3ScratchFree(b.apCell); + for(i=0; i= 1700 && defined(_M_ARM) +#pragma optimize("", on) +#endif + + +/* +** This function is called when the root page of a b-tree structure is +** overfull (has one or more overflow pages). +** +** A new child page is allocated and the contents of the current root +** page, including overflow cells, are copied into the child. The root +** page is then overwritten to make it an empty page with the right-child +** pointer pointing to the new page. +** +** Before returning, all pointer-map entries corresponding to pages +** that the new child-page now contains pointers to are updated. The +** entry corresponding to the new right-child pointer of the root +** page is also updated. +** +** If successful, *ppChild is set to contain a reference to the child +** page and SQLITE_OK is returned. In this case the caller is required +** to call releasePage() on *ppChild exactly once. If an error occurs, +** an error code is returned and *ppChild is set to 0. +*/ +static int balance_deeper(MemPage *pRoot, MemPage **ppChild){ + int rc; /* Return value from subprocedures */ + MemPage *pChild = 0; /* Pointer to a new child page */ + Pgno pgnoChild = 0; /* Page number of the new child page */ + BtShared *pBt = pRoot->pBt; /* The BTree */ + + assert( pRoot->nOverflow>0 ); + assert( sqlite3_mutex_held(pBt->mutex) ); + + /* Make pRoot, the root page of the b-tree, writable. Allocate a new + ** page that will become the new right-child of pPage. Copy the contents + ** of the node stored on pRoot into the new child page. + */ + rc = sqlite3PagerWrite(pRoot->pDbPage); + if( rc==SQLITE_OK ){ + rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0); + copyNodeContent(pRoot, pChild, &rc); + if( ISAUTOVACUUM ){ + ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc); + } + } + if( rc ){ + *ppChild = 0; + releasePage(pChild); + return rc; + } + assert( sqlite3PagerIswriteable(pChild->pDbPage) ); + assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); + assert( pChild->nCell==pRoot->nCell ); + + TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno)); + + /* Copy the overflow cells from pRoot to pChild */ + memcpy(pChild->aiOvfl, pRoot->aiOvfl, + pRoot->nOverflow*sizeof(pRoot->aiOvfl[0])); + memcpy(pChild->apOvfl, pRoot->apOvfl, + pRoot->nOverflow*sizeof(pRoot->apOvfl[0])); + pChild->nOverflow = pRoot->nOverflow; + + /* Zero the contents of pRoot. Then install pChild as the right-child. */ + zeroPage(pRoot, pChild->aData[0] & ~PTF_LEAF); + put4byte(&pRoot->aData[pRoot->hdrOffset+8], pgnoChild); + + *ppChild = pChild; + return SQLITE_OK; +} + +/* +** The page that pCur currently points to has just been modified in +** some way. This function figures out if this modification means the +** tree needs to be balanced, and if so calls the appropriate balancing +** routine. Balancing routines are: +** +** balance_quick() +** balance_deeper() +** balance_nonroot() +*/ +static int balance(BtCursor *pCur){ + int rc = SQLITE_OK; + const int nMin = pCur->pBt->usableSize * 2 / 3; + u8 aBalanceQuickSpace[13]; + u8 *pFree = 0; + + TESTONLY( int balance_quick_called = 0 ); + TESTONLY( int balance_deeper_called = 0 ); + + do { + int iPage = pCur->iPage; + MemPage *pPage = pCur->apPage[iPage]; + + if( iPage==0 ){ + if( pPage->nOverflow ){ + /* The root page of the b-tree is overfull. In this case call the + ** balance_deeper() function to create a new child for the root-page + ** and copy the current contents of the root-page to it. The + ** next iteration of the do-loop will balance the child page. + */ + assert( (balance_deeper_called++)==0 ); + rc = balance_deeper(pPage, &pCur->apPage[1]); + if( rc==SQLITE_OK ){ + pCur->iPage = 1; + pCur->aiIdx[0] = 0; + pCur->aiIdx[1] = 0; + assert( pCur->apPage[1]->nOverflow ); + } + }else{ + break; + } + }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){ + break; + }else{ + MemPage * const pParent = pCur->apPage[iPage-1]; + int const iIdx = pCur->aiIdx[iPage-1]; + + rc = sqlite3PagerWrite(pParent->pDbPage); + if( rc==SQLITE_OK ){ +#ifndef SQLITE_OMIT_QUICKBALANCE + if( pPage->intKeyLeaf + && pPage->nOverflow==1 + && pPage->aiOvfl[0]==pPage->nCell + && pParent->pgno!=1 + && pParent->nCell==iIdx + ){ + /* Call balance_quick() to create a new sibling of pPage on which + ** to store the overflow cell. balance_quick() inserts a new cell + ** into pParent, which may cause pParent overflow. If this + ** happens, the next iteration of the do-loop will balance pParent + ** use either balance_nonroot() or balance_deeper(). Until this + ** happens, the overflow cell is stored in the aBalanceQuickSpace[] + ** buffer. + ** + ** The purpose of the following assert() is to check that only a + ** single call to balance_quick() is made for each call to this + ** function. If this were not verified, a subtle bug involving reuse + ** of the aBalanceQuickSpace[] might sneak in. + */ + assert( (balance_quick_called++)==0 ); + rc = balance_quick(pParent, pPage, aBalanceQuickSpace); + }else +#endif + { + /* In this case, call balance_nonroot() to redistribute cells + ** between pPage and up to 2 of its sibling pages. This involves + ** modifying the contents of pParent, which may cause pParent to + ** become overfull or underfull. The next iteration of the do-loop + ** will balance the parent page to correct this. + ** + ** If the parent page becomes overfull, the overflow cell or cells + ** are stored in the pSpace buffer allocated immediately below. + ** A subsequent iteration of the do-loop will deal with this by + ** calling balance_nonroot() (balance_deeper() may be called first, + ** but it doesn't deal with overflow cells - just moves them to a + ** different page). Once this subsequent call to balance_nonroot() + ** has completed, it is safe to release the pSpace buffer used by + ** the previous call, as the overflow cell data will have been + ** copied either into the body of a database page or into the new + ** pSpace buffer passed to the latter call to balance_nonroot(). + */ + u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize); + rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, + pCur->hints&BTREE_BULKLOAD); + if( pFree ){ + /* If pFree is not NULL, it points to the pSpace buffer used + ** by a previous call to balance_nonroot(). Its contents are + ** now stored either on real database pages or within the + ** new pSpace buffer, so it may be safely freed here. */ + sqlite3PageFree(pFree); + } + + /* The pSpace buffer will be freed after the next call to + ** balance_nonroot(), or just before this function returns, whichever + ** comes first. */ + pFree = pSpace; + } + } + + pPage->nOverflow = 0; + + /* The next iteration of the do-loop balances the parent page. */ + releasePage(pPage); + pCur->iPage--; + assert( pCur->iPage>=0 ); + } + }while( rc==SQLITE_OK ); + + if( pFree ){ + sqlite3PageFree(pFree); + } + return rc; +} + + +/* +** Insert a new record into the BTree. The key is given by (pKey,nKey) +** and the data is given by (pData,nData). The cursor is used only to +** define what table the record should be inserted into. The cursor +** is left pointing at a random location. +** +** For an INTKEY table, only the nKey value of the key is used. pKey is +** ignored. For a ZERODATA table, the pData and nData are both ignored. +** +** If the seekResult parameter is non-zero, then a successful call to +** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already +** been performed. seekResult is the search result returned (a negative +** number if pCur points at an entry that is smaller than (pKey, nKey), or +** a positive value if pCur points at an entry that is larger than +** (pKey, nKey)). +** +** If the seekResult parameter is non-zero, then the caller guarantees that +** cursor pCur is pointing at the existing copy of a row that is to be +** overwritten. If the seekResult parameter is 0, then cursor pCur may +** point to any entry or to no entry at all and so this function has to seek +** the cursor before the new key can be inserted. +*/ +SQLITE_PRIVATE int sqlite3BtreeInsert( + BtCursor *pCur, /* Insert data into the table of this cursor */ + const void *pKey, i64 nKey, /* The key of the new record */ + const void *pData, int nData, /* The data of the new record */ + int nZero, /* Number of extra 0 bytes to append to data */ + int appendBias, /* True if this is likely an append */ + int seekResult /* Result of prior MovetoUnpacked() call */ +){ + int rc; + int loc = seekResult; /* -1: before desired location +1: after */ + int szNew = 0; + int idx; + MemPage *pPage; + Btree *p = pCur->pBtree; + BtShared *pBt = p->pBt; + unsigned char *oldCell; + unsigned char *newCell = 0; + + if( pCur->eState==CURSOR_FAULT ){ + assert( pCur->skipNext!=SQLITE_OK ); + return pCur->skipNext; + } + + assert( cursorHoldsMutex(pCur) ); + assert( (pCur->curFlags & BTCF_WriteFlag)!=0 + && pBt->inTransaction==TRANS_WRITE + && (pBt->btsFlags & BTS_READ_ONLY)==0 ); + assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); + + /* Assert that the caller has been consistent. If this cursor was opened + ** expecting an index b-tree, then the caller should be inserting blob + ** keys with no associated data. If the cursor was opened expecting an + ** intkey table, the caller should be inserting integer keys with a + ** blob of associated data. */ + assert( (pKey==0)==(pCur->pKeyInfo==0) ); + + /* Save the positions of any other cursors open on this table. + ** + ** In some cases, the call to btreeMoveto() below is a no-op. For + ** example, when inserting data into a table with auto-generated integer + ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the + ** integer key to use. It then calls this function to actually insert the + ** data into the intkey B-Tree. In this case btreeMoveto() recognizes + ** that the cursor is already where it needs to be and returns without + ** doing any work. To avoid thwarting these optimizations, it is important + ** not to clear the cursor here. + */ + if( pCur->curFlags & BTCF_Multiple ){ + rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); + if( rc ) return rc; + } + + if( pCur->pKeyInfo==0 ){ + assert( pKey==0 ); + /* If this is an insert into a table b-tree, invalidate any incrblob + ** cursors open on the row being replaced */ + invalidateIncrblobCursors(p, nKey, 0); + + /* If the cursor is currently on the last row and we are appending a + ** new row onto the end, set the "loc" to avoid an unnecessary + ** btreeMoveto() call */ + if( (pCur->curFlags&BTCF_ValidNKey)!=0 && nKey>0 + && pCur->info.nKey==nKey-1 ){ + loc = -1; + }else if( loc==0 ){ + rc = sqlite3BtreeMovetoUnpacked(pCur, 0, nKey, appendBias, &loc); + if( rc ) return rc; + } + }else if( loc==0 ){ + rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc); + if( rc ) return rc; + } + assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); + + pPage = pCur->apPage[pCur->iPage]; + assert( pPage->intKey || nKey>=0 ); + assert( pPage->leaf || !pPage->intKey ); + + TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", + pCur->pgnoRoot, nKey, nData, pPage->pgno, + loc==0 ? "overwrite" : "new entry")); + assert( pPage->isInit ); + newCell = pBt->pTmpSpace; + assert( newCell!=0 ); + rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew); + if( rc ) goto end_insert; + assert( szNew==pPage->xCellSize(pPage, newCell) ); + assert( szNew <= MX_CELL_SIZE(pBt) ); + idx = pCur->aiIdx[pCur->iPage]; + if( loc==0 ){ + u16 szOld; + assert( idxnCell ); + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ){ + goto end_insert; + } + oldCell = findCell(pPage, idx); + if( !pPage->leaf ){ + memcpy(newCell, oldCell, 4); + } + rc = clearCell(pPage, oldCell, &szOld); + dropCell(pPage, idx, szOld, &rc); + if( rc ) goto end_insert; + }else if( loc<0 && pPage->nCell>0 ){ + assert( pPage->leaf ); + idx = ++pCur->aiIdx[pCur->iPage]; + }else{ + assert( pPage->leaf ); + } + insertCell(pPage, idx, newCell, szNew, 0, 0, &rc); + assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); + + /* If no error has occurred and pPage has an overflow cell, call balance() + ** to redistribute the cells within the tree. Since balance() may move + ** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey + ** variables. + ** + ** Previous versions of SQLite called moveToRoot() to move the cursor + ** back to the root page as balance() used to invalidate the contents + ** of BtCursor.apPage[] and BtCursor.aiIdx[]. Instead of doing that, + ** set the cursor state to "invalid". This makes common insert operations + ** slightly faster. + ** + ** There is a subtle but important optimization here too. When inserting + ** multiple records into an intkey b-tree using a single cursor (as can + ** happen while processing an "INSERT INTO ... SELECT" statement), it + ** is advantageous to leave the cursor pointing to the last entry in + ** the b-tree if possible. If the cursor is left pointing to the last + ** entry in the table, and the next row inserted has an integer key + ** larger than the largest existing key, it is possible to insert the + ** row without seeking the cursor. This can be a big performance boost. + */ + pCur->info.nSize = 0; + if( rc==SQLITE_OK && pPage->nOverflow ){ + pCur->curFlags &= ~(BTCF_ValidNKey); + rc = balance(pCur); + + /* Must make sure nOverflow is reset to zero even if the balance() + ** fails. Internal data structure corruption will result otherwise. + ** Also, set the cursor state to invalid. This stops saveCursorPosition() + ** from trying to save the current position of the cursor. */ + pCur->apPage[pCur->iPage]->nOverflow = 0; + pCur->eState = CURSOR_INVALID; + } + assert( pCur->apPage[pCur->iPage]->nOverflow==0 ); + +end_insert: + return rc; +} + +/* +** Delete the entry that the cursor is pointing to. The cursor +** is left pointing at an arbitrary location. +*/ +SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ + Btree *p = pCur->pBtree; + BtShared *pBt = p->pBt; + int rc; /* Return code */ + MemPage *pPage; /* Page to delete cell from */ + unsigned char *pCell; /* Pointer to cell to delete */ + int iCellIdx; /* Index of cell to delete */ + int iCellDepth; /* Depth of node containing pCell */ + u16 szCell; /* Size of the cell being deleted */ + + assert( cursorHoldsMutex(pCur) ); + assert( pBt->inTransaction==TRANS_WRITE ); + assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); + assert( pCur->curFlags & BTCF_WriteFlag ); + assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); + assert( !hasReadConflicts(p, pCur->pgnoRoot) ); + assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); + assert( pCur->eState==CURSOR_VALID ); + + iCellDepth = pCur->iPage; + iCellIdx = pCur->aiIdx[iCellDepth]; + pPage = pCur->apPage[iCellDepth]; + pCell = findCell(pPage, iCellIdx); + + /* If the page containing the entry to delete is not a leaf page, move + ** the cursor to the largest entry in the tree that is smaller than + ** the entry being deleted. This cell will replace the cell being deleted + ** from the internal node. The 'previous' entry is used for this instead + ** of the 'next' entry, as the previous entry is always a part of the + ** sub-tree headed by the child page of the cell being deleted. This makes + ** balancing the tree following the delete operation easier. */ + if( !pPage->leaf ){ + int notUsed = 0; + rc = sqlite3BtreePrevious(pCur, ¬Used); + if( rc ) return rc; + } + + /* Save the positions of any other cursors open on this table before + ** making any modifications. Make the page containing the entry to be + ** deleted writable. Then free any overflow pages associated with the + ** entry and finally remove the cell itself from within the page. + */ + if( pCur->curFlags & BTCF_Multiple ){ + rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); + if( rc ) return rc; + } + + /* If this is a delete operation to remove a row from a table b-tree, + ** invalidate any incrblob cursors open on the row being deleted. */ + if( pCur->pKeyInfo==0 ){ + invalidateIncrblobCursors(p, pCur->info.nKey, 0); + } + + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ) return rc; + rc = clearCell(pPage, pCell, &szCell); + dropCell(pPage, iCellIdx, szCell, &rc); + if( rc ) return rc; + + /* If the cell deleted was not located on a leaf page, then the cursor + ** is currently pointing to the largest entry in the sub-tree headed + ** by the child-page of the cell that was just deleted from an internal + ** node. The cell from the leaf node needs to be moved to the internal + ** node to replace the deleted cell. */ + if( !pPage->leaf ){ + MemPage *pLeaf = pCur->apPage[pCur->iPage]; + int nCell; + Pgno n = pCur->apPage[iCellDepth+1]->pgno; + unsigned char *pTmp; + + pCell = findCell(pLeaf, pLeaf->nCell-1); + if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT; + nCell = pLeaf->xCellSize(pLeaf, pCell); + assert( MX_CELL_SIZE(pBt) >= nCell ); + pTmp = pBt->pTmpSpace; + assert( pTmp!=0 ); + rc = sqlite3PagerWrite(pLeaf->pDbPage); + insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc); + dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc); + if( rc ) return rc; + } + + /* Balance the tree. If the entry deleted was located on a leaf page, + ** then the cursor still points to that page. In this case the first + ** call to balance() repairs the tree, and the if(...) condition is + ** never true. + ** + ** Otherwise, if the entry deleted was on an internal node page, then + ** pCur is pointing to the leaf page from which a cell was removed to + ** replace the cell deleted from the internal node. This is slightly + ** tricky as the leaf node may be underfull, and the internal node may + ** be either under or overfull. In this case run the balancing algorithm + ** on the leaf node first. If the balance proceeds far enough up the + ** tree that we can be sure that any problem in the internal node has + ** been corrected, so be it. Otherwise, after balancing the leaf node, + ** walk the cursor up the tree to the internal node and balance it as + ** well. */ + rc = balance(pCur); + if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){ + while( pCur->iPage>iCellDepth ){ + releasePage(pCur->apPage[pCur->iPage--]); + } + rc = balance(pCur); + } + + if( rc==SQLITE_OK ){ + moveToRoot(pCur); + } + return rc; +} + +/* +** Create a new BTree table. Write into *piTable the page +** number for the root page of the new table. +** +** The type of type is determined by the flags parameter. Only the +** following values of flags are currently in use. Other values for +** flags might not work: +** +** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys +** BTREE_ZERODATA Used for SQL indices +*/ +static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){ + BtShared *pBt = p->pBt; + MemPage *pRoot; + Pgno pgnoRoot; + int rc; + int ptfFlags; /* Page-type flage for the root page of new table */ + + assert( sqlite3BtreeHoldsMutex(p) ); + assert( pBt->inTransaction==TRANS_WRITE ); + assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); + +#ifdef SQLITE_OMIT_AUTOVACUUM + rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); + if( rc ){ + return rc; + } +#else + if( pBt->autoVacuum ){ + Pgno pgnoMove; /* Move a page here to make room for the root-page */ + MemPage *pPageMove; /* The page to move to. */ + + /* Creating a new table may probably require moving an existing database + ** to make room for the new tables root page. In case this page turns + ** out to be an overflow page, delete all overflow page-map caches + ** held by open cursors. + */ + invalidateAllOverflowCache(pBt); + + /* Read the value of meta[3] from the database to determine where the + ** root page of the new table should go. meta[3] is the largest root-page + ** created so far, so the new root-page is (meta[3]+1). + */ + sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot); + pgnoRoot++; + + /* The new root-page may not be allocated on a pointer-map page, or the + ** PENDING_BYTE page. + */ + while( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) || + pgnoRoot==PENDING_BYTE_PAGE(pBt) ){ + pgnoRoot++; + } + assert( pgnoRoot>=3 || CORRUPT_DB ); + testcase( pgnoRoot<3 ); + + /* Allocate a page. The page that currently resides at pgnoRoot will + ** be moved to the allocated page (unless the allocated page happens + ** to reside at pgnoRoot). + */ + rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT); + if( rc!=SQLITE_OK ){ + return rc; + } + + if( pgnoMove!=pgnoRoot ){ + /* pgnoRoot is the page that will be used for the root-page of + ** the new table (assuming an error did not occur). But we were + ** allocated pgnoMove. If required (i.e. if it was not allocated + ** by extending the file), the current page at position pgnoMove + ** is already journaled. + */ + u8 eType = 0; + Pgno iPtrPage = 0; + + /* Save the positions of any open cursors. This is required in + ** case they are holding a reference to an xFetch reference + ** corresponding to page pgnoRoot. */ + rc = saveAllCursors(pBt, 0, 0); + releasePage(pPageMove); + if( rc!=SQLITE_OK ){ + return rc; + } + + /* Move the page currently at pgnoRoot to pgnoMove. */ + rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage); + if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){ + rc = SQLITE_CORRUPT_BKPT; + } + if( rc!=SQLITE_OK ){ + releasePage(pRoot); + return rc; + } + assert( eType!=PTRMAP_ROOTPAGE ); + assert( eType!=PTRMAP_FREEPAGE ); + rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0); + releasePage(pRoot); + + /* Obtain the page at pgnoRoot */ + if( rc!=SQLITE_OK ){ + return rc; + } + rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3PagerWrite(pRoot->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pRoot); + return rc; + } + }else{ + pRoot = pPageMove; + } + + /* Update the pointer-map and meta-data with the new root-page number. */ + ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0, &rc); + if( rc ){ + releasePage(pRoot); + return rc; + } + + /* When the new root page was allocated, page 1 was made writable in + ** order either to increase the database filesize, or to decrement the + ** freelist count. Hence, the sqlite3BtreeUpdateMeta() call cannot fail. + */ + assert( sqlite3PagerIswriteable(pBt->pPage1->pDbPage) ); + rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot); + if( NEVER(rc) ){ + releasePage(pRoot); + return rc; + } + + }else{ + rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); + if( rc ) return rc; + } +#endif + assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); + if( createTabFlags & BTREE_INTKEY ){ + ptfFlags = PTF_INTKEY | PTF_LEAFDATA | PTF_LEAF; + }else{ + ptfFlags = PTF_ZERODATA | PTF_LEAF; + } + zeroPage(pRoot, ptfFlags); + sqlite3PagerUnref(pRoot->pDbPage); + assert( (pBt->openFlags & BTREE_SINGLE)==0 || pgnoRoot==2 ); + *piTable = (int)pgnoRoot; + return SQLITE_OK; +} +SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){ + int rc; + sqlite3BtreeEnter(p); + rc = btreeCreateTable(p, piTable, flags); + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Erase the given database page and all its children. Return +** the page to the freelist. +*/ +static int clearDatabasePage( + BtShared *pBt, /* The BTree that contains the table */ + Pgno pgno, /* Page number to clear */ + int freePageFlag, /* Deallocate page if true */ + int *pnChange /* Add number of Cells freed to this counter */ +){ + MemPage *pPage; + int rc; + unsigned char *pCell; + int i; + int hdr; + u16 szCell; + + assert( sqlite3_mutex_held(pBt->mutex) ); + if( pgno>btreePagecount(pBt) ){ + return SQLITE_CORRUPT_BKPT; + } + rc = getAndInitPage(pBt, pgno, &pPage, 0, 0); + if( rc ) return rc; + if( pPage->bBusy ){ + rc = SQLITE_CORRUPT_BKPT; + goto cleardatabasepage_out; + } + pPage->bBusy = 1; + hdr = pPage->hdrOffset; + for(i=0; inCell; i++){ + pCell = findCell(pPage, i); + if( !pPage->leaf ){ + rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange); + if( rc ) goto cleardatabasepage_out; + } + rc = clearCell(pPage, pCell, &szCell); + if( rc ) goto cleardatabasepage_out; + } + if( !pPage->leaf ){ + rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange); + if( rc ) goto cleardatabasepage_out; + }else if( pnChange ){ + assert( pPage->intKey || CORRUPT_DB ); + testcase( !pPage->intKey ); + *pnChange += pPage->nCell; + } + if( freePageFlag ){ + freePage(pPage, &rc); + }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){ + zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF); + } + +cleardatabasepage_out: + pPage->bBusy = 0; + releasePage(pPage); + return rc; +} + +/* +** Delete all information from a single table in the database. iTable is +** the page number of the root of the table. After this routine returns, +** the root page is empty, but still exists. +** +** This routine will fail with SQLITE_LOCKED if there are any open +** read cursors on the table. Open write cursors are moved to the +** root of the table. +** +** If pnChange is not NULL, then table iTable must be an intkey table. The +** integer value pointed to by pnChange is incremented by the number of +** entries in the table. +*/ +SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){ + int rc; + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + assert( p->inTrans==TRANS_WRITE ); + + rc = saveAllCursors(pBt, (Pgno)iTable, 0); + + if( SQLITE_OK==rc ){ + /* Invalidate all incrblob cursors open on table iTable (assuming iTable + ** is the root of a table b-tree - if it is not, the following call is + ** a no-op). */ + invalidateIncrblobCursors(p, 0, 1); + rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange); + } + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Delete all information from the single table that pCur is open on. +** +** This routine only work for pCur on an ephemeral table. +*/ +SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor *pCur){ + return sqlite3BtreeClearTable(pCur->pBtree, pCur->pgnoRoot, 0); +} + +/* +** Erase all information in a table and add the root of the table to +** the freelist. Except, the root of the principle table (the one on +** page 1) is never added to the freelist. +** +** This routine will fail with SQLITE_LOCKED if there are any open +** cursors on the table. +** +** If AUTOVACUUM is enabled and the page at iTable is not the last +** root page in the database file, then the last root page +** in the database file is moved into the slot formerly occupied by +** iTable and that last slot formerly occupied by the last root page +** is added to the freelist instead of iTable. In this say, all +** root pages are kept at the beginning of the database file, which +** is necessary for AUTOVACUUM to work right. *piMoved is set to the +** page number that used to be the last root page in the file before +** the move. If no page gets moved, *piMoved is set to 0. +** The last root page is recorded in meta[3] and the value of +** meta[3] is updated by this procedure. +*/ +static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){ + int rc; + MemPage *pPage = 0; + BtShared *pBt = p->pBt; + + assert( sqlite3BtreeHoldsMutex(p) ); + assert( p->inTrans==TRANS_WRITE ); + + /* It is illegal to drop a table if any cursors are open on the + ** database. This is because in auto-vacuum mode the backend may + ** need to move another root-page to fill a gap left by the deleted + ** root page. If an open cursor was using this page a problem would + ** occur. + ** + ** This error is caught long before control reaches this point. + */ + if( NEVER(pBt->pCursor) ){ + sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db); + return SQLITE_LOCKED_SHAREDCACHE; + } + + rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0); + if( rc ) return rc; + rc = sqlite3BtreeClearTable(p, iTable, 0); + if( rc ){ + releasePage(pPage); + return rc; + } + + *piMoved = 0; + + if( iTable>1 ){ +#ifdef SQLITE_OMIT_AUTOVACUUM + freePage(pPage, &rc); + releasePage(pPage); +#else + if( pBt->autoVacuum ){ + Pgno maxRootPgno; + sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno); + + if( iTable==maxRootPgno ){ + /* If the table being dropped is the table with the largest root-page + ** number in the database, put the root page on the free list. + */ + freePage(pPage, &rc); + releasePage(pPage); + if( rc!=SQLITE_OK ){ + return rc; + } + }else{ + /* The table being dropped does not have the largest root-page + ** number in the database. So move the page that does into the + ** gap left by the deleted root-page. + */ + MemPage *pMove; + releasePage(pPage); + rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0); + releasePage(pMove); + if( rc!=SQLITE_OK ){ + return rc; + } + pMove = 0; + rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0); + freePage(pMove, &rc); + releasePage(pMove); + if( rc!=SQLITE_OK ){ + return rc; + } + *piMoved = maxRootPgno; + } + + /* Set the new 'max-root-page' value in the database header. This + ** is the old value less one, less one more if that happens to + ** be a root-page number, less one again if that is the + ** PENDING_BYTE_PAGE. + */ + maxRootPgno--; + while( maxRootPgno==PENDING_BYTE_PAGE(pBt) + || PTRMAP_ISPAGE(pBt, maxRootPgno) ){ + maxRootPgno--; + } + assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) ); + + rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno); + }else{ + freePage(pPage, &rc); + releasePage(pPage); + } +#endif + }else{ + /* If sqlite3BtreeDropTable was called on page 1. + ** This really never should happen except in a corrupt + ** database. + */ + zeroPage(pPage, PTF_INTKEY|PTF_LEAF ); + releasePage(pPage); + } + return rc; +} +SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){ + int rc; + sqlite3BtreeEnter(p); + rc = btreeDropTable(p, iTable, piMoved); + sqlite3BtreeLeave(p); + return rc; +} + + +/* +** This function may only be called if the b-tree connection already +** has a read or write transaction open on the database. +** +** Read the meta-information out of a database file. Meta[0] +** is the number of free pages currently in the database. Meta[1] +** through meta[15] are available for use by higher layers. Meta[0] +** is read-only, the others are read/write. +** +** The schema layer numbers meta values differently. At the schema +** layer (and the SetCookie and ReadCookie opcodes) the number of +** free pages is not visible. So Cookie[0] is the same as Meta[1]. +** +** This routine treats Meta[BTREE_DATA_VERSION] as a special case. Instead +** of reading the value out of the header, it instead loads the "DataVersion" +** from the pager. The BTREE_DATA_VERSION value is not actually stored in the +** database file. It is a number computed by the pager. But its access +** pattern is the same as header meta values, and so it is convenient to +** read it from this routine. +*/ +SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ + BtShared *pBt = p->pBt; + + sqlite3BtreeEnter(p); + assert( p->inTrans>TRANS_NONE ); + assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) ); + assert( pBt->pPage1 ); + assert( idx>=0 && idx<=15 ); + + if( idx==BTREE_DATA_VERSION ){ + *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion; + }else{ + *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); + } + + /* If auto-vacuum is disabled in this build and this is an auto-vacuum + ** database, mark the database as read-only. */ +#ifdef SQLITE_OMIT_AUTOVACUUM + if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){ + pBt->btsFlags |= BTS_READ_ONLY; + } +#endif + + sqlite3BtreeLeave(p); +} + +/* +** Write meta-information back into the database. Meta[0] is +** read-only and may not be written. +*/ +SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){ + BtShared *pBt = p->pBt; + unsigned char *pP1; + int rc; + assert( idx>=1 && idx<=15 ); + sqlite3BtreeEnter(p); + assert( p->inTrans==TRANS_WRITE ); + assert( pBt->pPage1!=0 ); + pP1 = pBt->pPage1->aData; + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + if( rc==SQLITE_OK ){ + put4byte(&pP1[36 + idx*4], iMeta); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( idx==BTREE_INCR_VACUUM ){ + assert( pBt->autoVacuum || iMeta==0 ); + assert( iMeta==0 || iMeta==1 ); + pBt->incrVacuum = (u8)iMeta; + } +#endif + } + sqlite3BtreeLeave(p); + return rc; +} + +#ifndef SQLITE_OMIT_BTREECOUNT +/* +** The first argument, pCur, is a cursor opened on some b-tree. Count the +** number of entries in the b-tree and write the result to *pnEntry. +** +** SQLITE_OK is returned if the operation is successfully executed. +** Otherwise, if an error is encountered (i.e. an IO error or database +** corruption) an SQLite error code is returned. +*/ +SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){ + i64 nEntry = 0; /* Value to return in *pnEntry */ + int rc; /* Return code */ + + if( pCur->pgnoRoot==0 ){ + *pnEntry = 0; + return SQLITE_OK; + } + rc = moveToRoot(pCur); + + /* Unless an error occurs, the following loop runs one iteration for each + ** page in the B-Tree structure (not including overflow pages). + */ + while( rc==SQLITE_OK ){ + int iIdx; /* Index of child node in parent */ + MemPage *pPage; /* Current page of the b-tree */ + + /* If this is a leaf page or the tree is not an int-key tree, then + ** this page contains countable entries. Increment the entry counter + ** accordingly. + */ + pPage = pCur->apPage[pCur->iPage]; + if( pPage->leaf || !pPage->intKey ){ + nEntry += pPage->nCell; + } + + /* pPage is a leaf node. This loop navigates the cursor so that it + ** points to the first interior cell that it points to the parent of + ** the next page in the tree that has not yet been visited. The + ** pCur->aiIdx[pCur->iPage] value is set to the index of the parent cell + ** of the page, or to the number of cells in the page if the next page + ** to visit is the right-child of its parent. + ** + ** If all pages in the tree have been visited, return SQLITE_OK to the + ** caller. + */ + if( pPage->leaf ){ + do { + if( pCur->iPage==0 ){ + /* All pages of the b-tree have been visited. Return successfully. */ + *pnEntry = nEntry; + return moveToRoot(pCur); + } + moveToParent(pCur); + }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell ); + + pCur->aiIdx[pCur->iPage]++; + pPage = pCur->apPage[pCur->iPage]; + } + + /* Descend to the child node of the cell that the cursor currently + ** points at. This is the right-child if (iIdx==pPage->nCell). + */ + iIdx = pCur->aiIdx[pCur->iPage]; + if( iIdx==pPage->nCell ){ + rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); + }else{ + rc = moveToChild(pCur, get4byte(findCell(pPage, iIdx))); + } + } + + /* An error has occurred. Return an error code. */ + return rc; +} +#endif + +/* +** Return the pager associated with a BTree. This routine is used for +** testing and debugging only. +*/ +SQLITE_PRIVATE Pager *sqlite3BtreePager(Btree *p){ + return p->pBt->pPager; +} + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** Append a message to the error message string. +*/ +static void checkAppendMsg( + IntegrityCk *pCheck, + const char *zFormat, + ... +){ + va_list ap; + char zBuf[200]; + if( !pCheck->mxErr ) return; + pCheck->mxErr--; + pCheck->nErr++; + va_start(ap, zFormat); + if( pCheck->errMsg.nChar ){ + sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); + } + if( pCheck->zPfx ){ + sqlite3_snprintf(sizeof(zBuf), zBuf, pCheck->zPfx, pCheck->v1, pCheck->v2); + sqlite3StrAccumAppendAll(&pCheck->errMsg, zBuf); + } + sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap); + va_end(ap); + if( pCheck->errMsg.accError==STRACCUM_NOMEM ){ + pCheck->mallocFailed = 1; + } +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK + +/* +** Return non-zero if the bit in the IntegrityCk.aPgRef[] array that +** corresponds to page iPg is already set. +*/ +static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ + assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); + return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07))); +} + +/* +** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg. +*/ +static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ + assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); + pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07)); +} + + +/* +** Add 1 to the reference count for page iPage. If this is the second +** reference to the page, add an error message to pCheck->zErrMsg. +** Return 1 if there are 2 or more references to the page and 0 if +** if this is the first reference to the page. +** +** Also check that the page number is in bounds. +*/ +static int checkRef(IntegrityCk *pCheck, Pgno iPage){ + if( iPage==0 ) return 1; + if( iPage>pCheck->nPage ){ + checkAppendMsg(pCheck, "invalid page number %d", iPage); + return 1; + } + if( getPageReferenced(pCheck, iPage) ){ + checkAppendMsg(pCheck, "2nd reference to page %d", iPage); + return 1; + } + setPageReferenced(pCheck, iPage); + return 0; +} + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** Check that the entry in the pointer-map for page iChild maps to +** page iParent, pointer type ptrType. If not, append an error message +** to pCheck. +*/ +static void checkPtrmap( + IntegrityCk *pCheck, /* Integrity check context */ + Pgno iChild, /* Child page number */ + u8 eType, /* Expected pointer map type */ + Pgno iParent /* Expected pointer map parent page number */ +){ + int rc; + u8 ePtrmapType; + Pgno iPtrmapParent; + + rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1; + checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild); + return; + } + + if( ePtrmapType!=eType || iPtrmapParent!=iParent ){ + checkAppendMsg(pCheck, + "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)", + iChild, eType, iParent, ePtrmapType, iPtrmapParent); + } +} +#endif + +/* +** Check the integrity of the freelist or of an overflow page list. +** Verify that the number of pages on the list is N. +*/ +static void checkList( + IntegrityCk *pCheck, /* Integrity checking context */ + int isFreeList, /* True for a freelist. False for overflow page list */ + int iPage, /* Page number for first page in the list */ + int N /* Expected number of pages in the list */ +){ + int i; + int expected = N; + int iFirst = iPage; + while( N-- > 0 && pCheck->mxErr ){ + DbPage *pOvflPage; + unsigned char *pOvflData; + if( iPage<1 ){ + checkAppendMsg(pCheck, + "%d of %d pages missing from overflow list starting at %d", + N+1, expected, iFirst); + break; + } + if( checkRef(pCheck, iPage) ) break; + if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage) ){ + checkAppendMsg(pCheck, "failed to get page %d", iPage); + break; + } + pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage); + if( isFreeList ){ + int n = get4byte(&pOvflData[4]); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pCheck->pBt->autoVacuum ){ + checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0); + } +#endif + if( n>(int)pCheck->pBt->usableSize/4-2 ){ + checkAppendMsg(pCheck, + "freelist leaf count too big on page %d", iPage); + N--; + }else{ + for(i=0; ipBt->autoVacuum ){ + checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0); + } +#endif + checkRef(pCheck, iFreePage); + } + N -= n; + } + } +#ifndef SQLITE_OMIT_AUTOVACUUM + else{ + /* If this database supports auto-vacuum and iPage is not the last + ** page in this overflow list, check that the pointer-map entry for + ** the following page matches iPage. + */ + if( pCheck->pBt->autoVacuum && N>0 ){ + i = get4byte(pOvflData); + checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage); + } + } +#endif + iPage = get4byte(pOvflData); + sqlite3PagerUnref(pOvflPage); + } +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +/* +** An implementation of a min-heap. +** +** aHeap[0] is the number of elements on the heap. aHeap[1] is the +** root element. The daughter nodes of aHeap[N] are aHeap[N*2] +** and aHeap[N*2+1]. +** +** The heap property is this: Every node is less than or equal to both +** of its daughter nodes. A consequence of the heap property is that the +** root node aHeap[1] is always the minimum value currently in the heap. +** +** The btreeHeapInsert() routine inserts an unsigned 32-bit number onto +** the heap, preserving the heap property. The btreeHeapPull() routine +** removes the root element from the heap (the minimum value in the heap) +** and then moves other nodes around as necessary to preserve the heap +** property. +** +** This heap is used for cell overlap and coverage testing. Each u32 +** entry represents the span of a cell or freeblock on a btree page. +** The upper 16 bits are the index of the first byte of a range and the +** lower 16 bits are the index of the last byte of that range. +*/ +static void btreeHeapInsert(u32 *aHeap, u32 x){ + u32 j, i = ++aHeap[0]; + aHeap[i] = x; + while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){ + x = aHeap[j]; + aHeap[j] = aHeap[i]; + aHeap[i] = x; + i = j; + } +} +static int btreeHeapPull(u32 *aHeap, u32 *pOut){ + u32 j, i, x; + if( (x = aHeap[0])==0 ) return 0; + *pOut = aHeap[1]; + aHeap[1] = aHeap[x]; + aHeap[x] = 0xffffffff; + aHeap[0]--; + i = 1; + while( (j = i*2)<=aHeap[0] ){ + if( aHeap[j]>aHeap[j+1] ) j++; + if( aHeap[i]zPfx; + int saved_v1 = pCheck->v1; + int saved_v2 = pCheck->v2; + u8 savedIsInit = 0; + + /* Check that the page exists + */ + pBt = pCheck->pBt; + usableSize = pBt->usableSize; + if( iPage==0 ) return 0; + if( checkRef(pCheck, iPage) ) return 0; + pCheck->zPfx = "Page %d: "; + pCheck->v1 = iPage; + if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){ + checkAppendMsg(pCheck, + "unable to get the page. error code=%d", rc); + goto end_of_check; + } + + /* Clear MemPage.isInit to make sure the corruption detection code in + ** btreeInitPage() is executed. */ + savedIsInit = pPage->isInit; + pPage->isInit = 0; + if( (rc = btreeInitPage(pPage))!=0 ){ + assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */ + checkAppendMsg(pCheck, + "btreeInitPage() returns error code %d", rc); + goto end_of_check; + } + data = pPage->aData; + hdr = pPage->hdrOffset; + + /* Set up for cell analysis */ + pCheck->zPfx = "On tree page %d cell %d: "; + contentOffset = get2byteNotZero(&data[hdr+5]); + assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ + + /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the + ** number of cells on the page. */ + nCell = get2byte(&data[hdr+3]); + assert( pPage->nCell==nCell ); + + /* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page + ** immediately follows the b-tree page header. */ + cellStart = hdr + 12 - 4*pPage->leaf; + assert( pPage->aCellIdx==&data[cellStart] ); + pCellIdx = &data[cellStart + 2*(nCell-1)]; + + if( !pPage->leaf ){ + /* Analyze the right-child page of internal pages */ + pgno = get4byte(&data[hdr+8]); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + pCheck->zPfx = "On page %d at right child: "; + checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage); + } +#endif + depth = checkTreePage(pCheck, pgno, &maxKey, maxKey); + keyCanBeEqual = 0; + }else{ + /* For leaf pages, the coverage check will occur in the same loop + ** as the other cell checks, so initialize the heap. */ + heap = pCheck->heap; + heap[0] = 0; + } + + /* EVIDENCE-OF: R-02776-14802 The cell pointer array consists of K 2-byte + ** integer offsets to the cell contents. */ + for(i=nCell-1; i>=0 && pCheck->mxErr; i--){ + CellInfo info; + + /* Check cell size */ + pCheck->v2 = i; + assert( pCellIdx==&data[cellStart + i*2] ); + pc = get2byteAligned(pCellIdx); + pCellIdx -= 2; + if( pcusableSize-4 ){ + checkAppendMsg(pCheck, "Offset %d out of range %d..%d", + pc, contentOffset, usableSize-4); + doCoverageCheck = 0; + continue; + } + pCell = &data[pc]; + pPage->xParseCell(pPage, pCell, &info); + if( pc+info.nSize>usableSize ){ + checkAppendMsg(pCheck, "Extends off end of page"); + doCoverageCheck = 0; + continue; + } + + /* Check for integer primary key out of range */ + if( pPage->intKey ){ + if( keyCanBeEqual ? (info.nKey > maxKey) : (info.nKey >= maxKey) ){ + checkAppendMsg(pCheck, "Rowid %lld out of order", info.nKey); + } + maxKey = info.nKey; + } + + /* Check the content overflow list */ + if( info.nPayload>info.nLocal ){ + int nPage; /* Number of pages on the overflow chain */ + Pgno pgnoOvfl; /* First page of the overflow chain */ + assert( pc + info.iOverflow <= usableSize ); + nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4); + pgnoOvfl = get4byte(&pCell[info.iOverflow]); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage); + } +#endif + checkList(pCheck, 0, pgnoOvfl, nPage); + } + + if( !pPage->leaf ){ + /* Check sanity of left child page for internal pages */ + pgno = get4byte(pCell); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage); + } +#endif + d2 = checkTreePage(pCheck, pgno, &maxKey, maxKey); + keyCanBeEqual = 0; + if( d2!=depth ){ + checkAppendMsg(pCheck, "Child page depth differs"); + depth = d2; + } + }else{ + /* Populate the coverage-checking heap for leaf pages */ + btreeHeapInsert(heap, (pc<<16)|(pc+info.nSize-1)); + } + } + *piMinKey = maxKey; + + /* Check for complete coverage of the page + */ + pCheck->zPfx = 0; + if( doCoverageCheck && pCheck->mxErr>0 ){ + /* For leaf pages, the min-heap has already been initialized and the + ** cells have already been inserted. But for internal pages, that has + ** not yet been done, so do it now */ + if( !pPage->leaf ){ + heap = pCheck->heap; + heap[0] = 0; + for(i=nCell-1; i>=0; i--){ + u32 size; + pc = get2byteAligned(&data[cellStart+i*2]); + size = pPage->xCellSize(pPage, &data[pc]); + btreeHeapInsert(heap, (pc<<16)|(pc+size-1)); + } + } + /* Add the freeblocks to the min-heap + ** + ** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header + ** is the offset of the first freeblock, or zero if there are no + ** freeblocks on the page. + */ + i = get2byte(&data[hdr+1]); + while( i>0 ){ + int size, j; + assert( (u32)i<=usableSize-4 ); /* Enforced by btreeInitPage() */ + size = get2byte(&data[i+2]); + assert( (u32)(i+size)<=usableSize ); /* Enforced by btreeInitPage() */ + btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1)); + /* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a + ** big-endian integer which is the offset in the b-tree page of the next + ** freeblock in the chain, or zero if the freeblock is the last on the + ** chain. */ + j = get2byte(&data[i]); + /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of + ** increasing offset. */ + assert( j==0 || j>i+size ); /* Enforced by btreeInitPage() */ + assert( (u32)j<=usableSize-4 ); /* Enforced by btreeInitPage() */ + i = j; + } + /* Analyze the min-heap looking for overlap between cells and/or + ** freeblocks, and counting the number of untracked bytes in nFrag. + ** + ** Each min-heap entry is of the form: (start_address<<16)|end_address. + ** There is an implied first entry the covers the page header, the cell + ** pointer index, and the gap between the cell pointer index and the start + ** of cell content. + ** + ** The loop below pulls entries from the min-heap in order and compares + ** the start_address against the previous end_address. If there is an + ** overlap, that means bytes are used multiple times. If there is a gap, + ** that gap is added to the fragmentation count. + */ + nFrag = 0; + prev = contentOffset - 1; /* Implied first min-heap entry */ + while( btreeHeapPull(heap,&x) ){ + if( (prev&0xffff)>=(x>>16) ){ + checkAppendMsg(pCheck, + "Multiple uses for byte %u of page %d", x>>16, iPage); + break; + }else{ + nFrag += (x>>16) - (prev&0xffff) - 1; + prev = x; + } + } + nFrag += usableSize - (prev&0xffff) - 1; + /* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments + ** is stored in the fifth field of the b-tree page header. + ** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the + ** number of fragmented free bytes within the cell content area. + */ + if( heap[0]==0 && nFrag!=data[hdr+7] ){ + checkAppendMsg(pCheck, + "Fragmentation of %d bytes reported as %d on page %d", + nFrag, data[hdr+7], iPage); + } + } + +end_of_check: + if( !doCoverageCheck ) pPage->isInit = savedIsInit; + releasePage(pPage); + pCheck->zPfx = saved_zPfx; + pCheck->v1 = saved_v1; + pCheck->v2 = saved_v2; + return depth+1; +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** This routine does a complete check of the given BTree file. aRoot[] is +** an array of pages numbers were each page number is the root page of +** a table. nRoot is the number of entries in aRoot. +** +** A read-only or read-write transaction must be opened before calling +** this function. +** +** Write the number of error seen in *pnErr. Except for some memory +** allocation errors, an error message held in memory obtained from +** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is +** returned. If a memory allocation error occurs, NULL is returned. +*/ +SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( + Btree *p, /* The btree to be checked */ + int *aRoot, /* An array of root pages numbers for individual trees */ + int nRoot, /* Number of entries in aRoot[] */ + int mxErr, /* Stop reporting errors after this many */ + int *pnErr /* Write number of errors seen to this variable */ +){ + Pgno i; + IntegrityCk sCheck; + BtShared *pBt = p->pBt; + int savedDbFlags = pBt->db->flags; + char zErr[100]; + VVA_ONLY( int nRef ); + + sqlite3BtreeEnter(p); + assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE ); + assert( (nRef = sqlite3PagerRefcount(pBt->pPager))>=0 ); + sCheck.pBt = pBt; + sCheck.pPager = pBt->pPager; + sCheck.nPage = btreePagecount(sCheck.pBt); + sCheck.mxErr = mxErr; + sCheck.nErr = 0; + sCheck.mallocFailed = 0; + sCheck.zPfx = 0; + sCheck.v1 = 0; + sCheck.v2 = 0; + sCheck.aPgRef = 0; + sCheck.heap = 0; + sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); + if( sCheck.nPage==0 ){ + goto integrity_ck_cleanup; + } + + sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); + if( !sCheck.aPgRef ){ + sCheck.mallocFailed = 1; + goto integrity_ck_cleanup; + } + sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize ); + if( sCheck.heap==0 ){ + sCheck.mallocFailed = 1; + goto integrity_ck_cleanup; + } + + i = PENDING_BYTE_PAGE(pBt); + if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); + + /* Check the integrity of the freelist + */ + sCheck.zPfx = "Main freelist: "; + checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), + get4byte(&pBt->pPage1->aData[36])); + sCheck.zPfx = 0; + + /* Check all the tables. + */ + testcase( pBt->db->flags & SQLITE_CellSizeCk ); + pBt->db->flags &= ~SQLITE_CellSizeCk; + for(i=0; (int)iautoVacuum && aRoot[i]>1 ){ + checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); + } +#endif + checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64); + } + pBt->db->flags = savedDbFlags; + + /* Make sure every page in the file is referenced + */ + for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ +#ifdef SQLITE_OMIT_AUTOVACUUM + if( getPageReferenced(&sCheck, i)==0 ){ + checkAppendMsg(&sCheck, "Page %d is never used", i); + } +#else + /* If the database supports auto-vacuum, make sure no tables contain + ** references to pointer-map pages. + */ + if( getPageReferenced(&sCheck, i)==0 && + (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ + checkAppendMsg(&sCheck, "Page %d is never used", i); + } + if( getPageReferenced(&sCheck, i)!=0 && + (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ + checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i); + } +#endif + } + + /* Clean up and report errors. + */ +integrity_ck_cleanup: + sqlite3PageFree(sCheck.heap); + sqlite3_free(sCheck.aPgRef); + if( sCheck.mallocFailed ){ + sqlite3StrAccumReset(&sCheck.errMsg); + sCheck.nErr++; + } + *pnErr = sCheck.nErr; + if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg); + /* Make sure this analysis did not leave any unref() pages. */ + assert( nRef==sqlite3PagerRefcount(pBt->pPager) ); + sqlite3BtreeLeave(p); + return sqlite3StrAccumFinish(&sCheck.errMsg); +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +/* +** Return the full pathname of the underlying database file. Return +** an empty string if the database is in-memory or a TEMP database. +** +** The pager filename is invariant as long as the pager is +** open so it is safe to access without the BtShared mutex. +*/ +SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3PagerFilename(p->pBt->pPager, 1); +} + +/* +** Return the pathname of the journal file for this database. The return +** value of this routine is the same regardless of whether the journal file +** has been created or not. +** +** The pager journal filename is invariant as long as the pager is +** open so it is safe to access without the BtShared mutex. +*/ +SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3PagerJournalname(p->pBt->pPager); +} + +/* +** Return non-zero if a transaction is active. +*/ +SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree *p){ + assert( p==0 || sqlite3_mutex_held(p->db->mutex) ); + return (p && (p->inTrans==TRANS_WRITE)); +} + +#ifndef SQLITE_OMIT_WAL +/* +** Run a checkpoint on the Btree passed as the first argument. +** +** Return SQLITE_LOCKED if this or any other connection has an open +** transaction on the shared-cache the argument Btree is connected to. +** +** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. +*/ +SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *pnCkpt){ + int rc = SQLITE_OK; + if( p ){ + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + if( pBt->inTransaction!=TRANS_NONE ){ + rc = SQLITE_LOCKED; + }else{ + rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt); + } + sqlite3BtreeLeave(p); + } + return rc; +} +#endif + +/* +** Return non-zero if a read (or write) transaction is active. +*/ +SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree *p){ + assert( p ); + assert( sqlite3_mutex_held(p->db->mutex) ); + return p->inTrans!=TRANS_NONE; +} + +SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree *p){ + assert( p ); + assert( sqlite3_mutex_held(p->db->mutex) ); + return p->nBackup!=0; +} + +/* +** This function returns a pointer to a blob of memory associated with +** a single shared-btree. The memory is used by client code for its own +** purposes (for example, to store a high-level schema associated with +** the shared-btree). The btree layer manages reference counting issues. +** +** The first time this is called on a shared-btree, nBytes bytes of memory +** are allocated, zeroed, and returned to the caller. For each subsequent +** call the nBytes parameter is ignored and a pointer to the same blob +** of memory returned. +** +** If the nBytes parameter is 0 and the blob of memory has not yet been +** allocated, a null pointer is returned. If the blob has already been +** allocated, it is returned as normal. +** +** Just before the shared-btree is closed, the function passed as the +** xFree argument when the memory allocation was made is invoked on the +** blob of allocated memory. The xFree function should not call sqlite3_free() +** on the memory, the btree layer does that. +*/ +SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + if( !pBt->pSchema && nBytes ){ + pBt->pSchema = sqlite3DbMallocZero(0, nBytes); + pBt->xFreeSchema = xFree; + } + sqlite3BtreeLeave(p); + return pBt->pSchema; +} + +/* +** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared +** btree as the argument handle holds an exclusive lock on the +** sqlite_master table. Otherwise SQLITE_OK. +*/ +SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *p){ + int rc; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK); + assert( rc==SQLITE_OK || rc==SQLITE_LOCKED_SHAREDCACHE ); + sqlite3BtreeLeave(p); + return rc; +} + + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Obtain a lock on the table whose root page is iTab. The +** lock is a write lock if isWritelock is true or a read lock +** if it is false. +*/ +SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){ + int rc = SQLITE_OK; + assert( p->inTrans!=TRANS_NONE ); + if( p->sharable ){ + u8 lockType = READ_LOCK + isWriteLock; + assert( READ_LOCK+1==WRITE_LOCK ); + assert( isWriteLock==0 || isWriteLock==1 ); + + sqlite3BtreeEnter(p); + rc = querySharedCacheTableLock(p, iTab, lockType); + if( rc==SQLITE_OK ){ + rc = setSharedCacheTableLock(p, iTab, lockType); + } + sqlite3BtreeLeave(p); + } + return rc; +} +#endif + +#ifndef SQLITE_OMIT_INCRBLOB +/* +** Argument pCsr must be a cursor opened for writing on an +** INTKEY table currently pointing at a valid table entry. +** This function modifies the data stored as part of that entry. +** +** Only the data content may only be modified, it is not possible to +** change the length of the data stored. If this function is called with +** parameters that attempt to write past the end of the existing data, +** no modifications are made and SQLITE_CORRUPT is returned. +*/ +SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ + int rc; + assert( cursorHoldsMutex(pCsr) ); + assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) ); + assert( pCsr->curFlags & BTCF_Incrblob ); + + rc = restoreCursorPosition(pCsr); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pCsr->eState!=CURSOR_REQUIRESEEK ); + if( pCsr->eState!=CURSOR_VALID ){ + return SQLITE_ABORT; + } + + /* Save the positions of all other cursors open on this table. This is + ** required in case any of them are holding references to an xFetch + ** version of the b-tree page modified by the accessPayload call below. + ** + ** Note that pCsr must be open on a INTKEY table and saveCursorPosition() + ** and hence saveAllCursors() cannot fail on a BTREE_INTKEY table, hence + ** saveAllCursors can only return SQLITE_OK. + */ + VVA_ONLY(rc =) saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr); + assert( rc==SQLITE_OK ); + + /* Check some assumptions: + ** (a) the cursor is open for writing, + ** (b) there is a read/write transaction open, + ** (c) the connection holds a write-lock on the table (if required), + ** (d) there are no conflicting read-locks, and + ** (e) the cursor points at a valid row of an intKey table. + */ + if( (pCsr->curFlags & BTCF_WriteFlag)==0 ){ + return SQLITE_READONLY; + } + assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0 + && pCsr->pBt->inTransaction==TRANS_WRITE ); + assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) ); + assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) ); + assert( pCsr->apPage[pCsr->iPage]->intKey ); + + return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1); +} + +/* +** Mark this cursor as an incremental blob cursor. +*/ +SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *pCur){ + pCur->curFlags |= BTCF_Incrblob; + pCur->pBtree->hasIncrblobCur = 1; +} +#endif + +/* +** Set both the "read version" (single byte at byte offset 18) and +** "write version" (single byte at byte offset 19) fields in the database +** header to iVersion. +*/ +SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){ + BtShared *pBt = pBtree->pBt; + int rc; /* Return code */ + + assert( iVersion==1 || iVersion==2 ); + + /* If setting the version fields to 1, do not automatically open the + ** WAL connection, even if the version fields are currently set to 2. + */ + pBt->btsFlags &= ~BTS_NO_WAL; + if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL; + + rc = sqlite3BtreeBeginTrans(pBtree, 0); + if( rc==SQLITE_OK ){ + u8 *aData = pBt->pPage1->aData; + if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){ + rc = sqlite3BtreeBeginTrans(pBtree, 2); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + if( rc==SQLITE_OK ){ + aData[18] = (u8)iVersion; + aData[19] = (u8)iVersion; + } + } + } + } + + pBt->btsFlags &= ~BTS_NO_WAL; + return rc; +} + +/* +** set the mask of hint flags for cursor pCsr. +*/ +SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){ + assert( mask==BTREE_BULKLOAD || mask==BTREE_SEEK_EQ || mask==0 ); + pCsr->hints = mask; +} + +#ifdef SQLITE_DEBUG +/* +** Return true if the cursor has a hint specified. This routine is +** only used from within assert() statements +*/ +SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){ + return (pCsr->hints & mask)!=0; +} +#endif + +/* +** Return true if the given Btree is read-only. +*/ +SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *p){ + return (p->pBt->btsFlags & BTS_READ_ONLY)!=0; +} + +/* +** Return the size of the header added to each page by this module. +*/ +SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); } + +/************** End of btree.c ***********************************************/ +/************** Begin file backup.c ******************************************/ +/* +** 2009 January 28 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains the implementation of the sqlite3_backup_XXX() +** API functions and the related features. +*/ +/* #include "sqliteInt.h" */ +/* #include "btreeInt.h" */ + +/* +** Structure allocated for each backup operation. +*/ +struct sqlite3_backup { + sqlite3* pDestDb; /* Destination database handle */ + Btree *pDest; /* Destination b-tree file */ + u32 iDestSchema; /* Original schema cookie in destination */ + int bDestLocked; /* True once a write-transaction is open on pDest */ + + Pgno iNext; /* Page number of the next source page to copy */ + sqlite3* pSrcDb; /* Source database handle */ + Btree *pSrc; /* Source b-tree file */ + + int rc; /* Backup process error code */ + + /* These two variables are set by every call to backup_step(). They are + ** read by calls to backup_remaining() and backup_pagecount(). + */ + Pgno nRemaining; /* Number of pages left to copy */ + Pgno nPagecount; /* Total number of pages to copy */ + + int isAttached; /* True once backup has been registered with pager */ + sqlite3_backup *pNext; /* Next backup associated with source pager */ +}; + +/* +** THREAD SAFETY NOTES: +** +** Once it has been created using backup_init(), a single sqlite3_backup +** structure may be accessed via two groups of thread-safe entry points: +** +** * Via the sqlite3_backup_XXX() API function backup_step() and +** backup_finish(). Both these functions obtain the source database +** handle mutex and the mutex associated with the source BtShared +** structure, in that order. +** +** * Via the BackupUpdate() and BackupRestart() functions, which are +** invoked by the pager layer to report various state changes in +** the page cache associated with the source database. The mutex +** associated with the source database BtShared structure will always +** be held when either of these functions are invoked. +** +** The other sqlite3_backup_XXX() API functions, backup_remaining() and +** backup_pagecount() are not thread-safe functions. If they are called +** while some other thread is calling backup_step() or backup_finish(), +** the values returned may be invalid. There is no way for a call to +** BackupUpdate() or BackupRestart() to interfere with backup_remaining() +** or backup_pagecount(). +** +** Depending on the SQLite configuration, the database handles and/or +** the Btree objects may have their own mutexes that require locking. +** Non-sharable Btrees (in-memory databases for example), do not have +** associated mutexes. +*/ + +/* +** Return a pointer corresponding to database zDb (i.e. "main", "temp") +** in connection handle pDb. If such a database cannot be found, return +** a NULL pointer and write an error message to pErrorDb. +** +** If the "temp" database is requested, it may need to be opened by this +** function. If an error occurs while doing so, return 0 and write an +** error message to pErrorDb. +*/ +static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ + int i = sqlite3FindDbName(pDb, zDb); + + if( i==1 ){ + Parse *pParse; + int rc = 0; + pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse)); + if( pParse==0 ){ + sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory"); + rc = SQLITE_NOMEM; + }else{ + pParse->db = pDb; + if( sqlite3OpenTempDatabase(pParse) ){ + sqlite3ErrorWithMsg(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); + rc = SQLITE_ERROR; + } + sqlite3DbFree(pErrorDb, pParse->zErrMsg); + sqlite3ParserReset(pParse); + sqlite3StackFree(pErrorDb, pParse); + } + if( rc ){ + return 0; + } + } + + if( i<0 ){ + sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); + return 0; + } + + return pDb->aDb[i].pBt; +} + +/* +** Attempt to set the page size of the destination to match the page size +** of the source. +*/ +static int setDestPgsz(sqlite3_backup *p){ + int rc; + rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0); + return rc; +} + +/* +** Check that there is no open read-transaction on the b-tree passed as the +** second argument. If there is not, return SQLITE_OK. Otherwise, if there +** is an open read-transaction, return SQLITE_ERROR and leave an error +** message in database handle db. +*/ +static int checkReadTransaction(sqlite3 *db, Btree *p){ + if( sqlite3BtreeIsInReadTrans(p) ){ + sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use"); + return SQLITE_ERROR; + } + return SQLITE_OK; +} + +/* +** Create an sqlite3_backup process to copy the contents of zSrcDb from +** connection handle pSrcDb to zDestDb in pDestDb. If successful, return +** a pointer to the new sqlite3_backup object. +** +** If an error occurs, NULL is returned and an error code and error message +** stored in database handle pDestDb. +*/ +SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( + sqlite3* pDestDb, /* Database to write to */ + const char *zDestDb, /* Name of database within pDestDb */ + sqlite3* pSrcDb, /* Database connection to read from */ + const char *zSrcDb /* Name of database within pSrcDb */ +){ + sqlite3_backup *p; /* Value to return */ + +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(pSrcDb)||!sqlite3SafetyCheckOk(pDestDb) ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + + /* Lock the source database handle. The destination database + ** handle is not locked in this routine, but it is locked in + ** sqlite3_backup_step(). The user is required to ensure that no + ** other thread accesses the destination handle for the duration + ** of the backup operation. Any attempt to use the destination + ** database connection while a backup is in progress may cause + ** a malfunction or a deadlock. + */ + sqlite3_mutex_enter(pSrcDb->mutex); + sqlite3_mutex_enter(pDestDb->mutex); + + if( pSrcDb==pDestDb ){ + sqlite3ErrorWithMsg( + pDestDb, SQLITE_ERROR, "source and destination must be distinct" + ); + p = 0; + }else { + /* Allocate space for a new sqlite3_backup object... + ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a + ** call to sqlite3_backup_init() and is destroyed by a call to + ** sqlite3_backup_finish(). */ + p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup)); + if( !p ){ + sqlite3Error(pDestDb, SQLITE_NOMEM); + } + } + + /* If the allocation succeeded, populate the new object. */ + if( p ){ + p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); + p->pDest = findBtree(pDestDb, pDestDb, zDestDb); + p->pDestDb = pDestDb; + p->pSrcDb = pSrcDb; + p->iNext = 1; + p->isAttached = 0; + + if( 0==p->pSrc || 0==p->pDest + || setDestPgsz(p)==SQLITE_NOMEM + || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK + ){ + /* One (or both) of the named databases did not exist or an OOM + ** error was hit. Or there is a transaction open on the destination + ** database. The error has already been written into the pDestDb + ** handle. All that is left to do here is free the sqlite3_backup + ** structure. */ + sqlite3_free(p); + p = 0; + } + } + if( p ){ + p->pSrc->nBackup++; + } + + sqlite3_mutex_leave(pDestDb->mutex); + sqlite3_mutex_leave(pSrcDb->mutex); + return p; +} + +/* +** Argument rc is an SQLite error code. Return true if this error is +** considered fatal if encountered during a backup operation. All errors +** are considered fatal except for SQLITE_BUSY and SQLITE_LOCKED. +*/ +static int isFatalError(int rc){ + return (rc!=SQLITE_OK && rc!=SQLITE_BUSY && ALWAYS(rc!=SQLITE_LOCKED)); +} + +/* +** Parameter zSrcData points to a buffer containing the data for +** page iSrcPg from the source database. Copy this data into the +** destination database. +*/ +static int backupOnePage( + sqlite3_backup *p, /* Backup handle */ + Pgno iSrcPg, /* Source database page to backup */ + const u8 *zSrcData, /* Source database page data */ + int bUpdate /* True for an update, false otherwise */ +){ + Pager * const pDestPager = sqlite3BtreePager(p->pDest); + const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); + int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); + const int nCopy = MIN(nSrcPgsz, nDestPgsz); + const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; +#ifdef SQLITE_HAS_CODEC + /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is + ** guaranteed that the shared-mutex is held by this thread, handle + ** p->pSrc may not actually be the owner. */ + int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc); + int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest); +#endif + int rc = SQLITE_OK; + i64 iOff; + + assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 ); + assert( p->bDestLocked ); + assert( !isFatalError(p->rc) ); + assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ); + assert( zSrcData ); + + /* Catch the case where the destination is an in-memory database and the + ** page sizes of the source and destination differ. + */ + if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){ + rc = SQLITE_READONLY; + } + +#ifdef SQLITE_HAS_CODEC + /* Backup is not possible if the page size of the destination is changing + ** and a codec is in use. + */ + if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){ + rc = SQLITE_READONLY; + } + + /* Backup is not possible if the number of bytes of reserve space differ + ** between source and destination. If there is a difference, try to + ** fix the destination to agree with the source. If that is not possible, + ** then the backup cannot proceed. + */ + if( nSrcReserve!=nDestReserve ){ + u32 newPgsz = nSrcPgsz; + rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve); + if( rc==SQLITE_OK && newPgsz!=nSrcPgsz ) rc = SQLITE_READONLY; + } +#endif + + /* This loop runs once for each destination page spanned by the source + ** page. For each iteration, variable iOff is set to the byte offset + ** of the destination page. + */ + for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOffpDest->pBt) ) continue; + if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg)) + && SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg)) + ){ + const u8 *zIn = &zSrcData[iOff%nSrcPgsz]; + u8 *zDestData = sqlite3PagerGetData(pDestPg); + u8 *zOut = &zDestData[iOff%nDestPgsz]; + + /* Copy the data from the source page into the destination page. + ** Then clear the Btree layer MemPage.isInit flag. Both this module + ** and the pager code use this trick (clearing the first byte + ** of the page 'extra' space to invalidate the Btree layers + ** cached parse of the page). MemPage.isInit is marked + ** "MUST BE FIRST" for this purpose. + */ + memcpy(zOut, zIn, nCopy); + ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; + if( iOff==0 && bUpdate==0 ){ + sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc)); + } + } + sqlite3PagerUnref(pDestPg); + } + + return rc; +} + +/* +** If pFile is currently larger than iSize bytes, then truncate it to +** exactly iSize bytes. If pFile is not larger than iSize bytes, then +** this function is a no-op. +** +** Return SQLITE_OK if everything is successful, or an SQLite error +** code if an error occurs. +*/ +static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){ + i64 iCurrent; + int rc = sqlite3OsFileSize(pFile, &iCurrent); + if( rc==SQLITE_OK && iCurrent>iSize ){ + rc = sqlite3OsTruncate(pFile, iSize); + } + return rc; +} + +/* +** Register this backup object with the associated source pager for +** callbacks when pages are changed or the cache invalidated. +*/ +static void attachBackupObject(sqlite3_backup *p){ + sqlite3_backup **pp; + assert( sqlite3BtreeHoldsMutex(p->pSrc) ); + pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); + p->pNext = *pp; + *pp = p; + p->isAttached = 1; +} + +/* +** Copy nPage pages from the source b-tree to the destination. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ + int rc; + int destMode; /* Destination journal mode */ + int pgszSrc = 0; /* Source page size */ + int pgszDest = 0; /* Destination page size */ + +#ifdef SQLITE_ENABLE_API_ARMOR + if( p==0 ) return SQLITE_MISUSE_BKPT; +#endif + sqlite3_mutex_enter(p->pSrcDb->mutex); + sqlite3BtreeEnter(p->pSrc); + if( p->pDestDb ){ + sqlite3_mutex_enter(p->pDestDb->mutex); + } + + rc = p->rc; + if( !isFatalError(rc) ){ + Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */ + Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */ + int ii; /* Iterator variable */ + int nSrcPage = -1; /* Size of source db in pages */ + int bCloseTrans = 0; /* True if src db requires unlocking */ + + /* If the source pager is currently in a write-transaction, return + ** SQLITE_BUSY immediately. + */ + if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){ + rc = SQLITE_BUSY; + }else{ + rc = SQLITE_OK; + } + + /* Lock the destination database, if it is not locked already. */ + if( SQLITE_OK==rc && p->bDestLocked==0 + && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2)) + ){ + p->bDestLocked = 1; + sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema); + } + + /* If there is no open read-transaction on the source database, open + ** one now. If a transaction is opened here, then it will be closed + ** before this function exits. + */ + if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){ + rc = sqlite3BtreeBeginTrans(p->pSrc, 0); + bCloseTrans = 1; + } + + /* Do not allow backup if the destination database is in WAL mode + ** and the page sizes are different between source and destination */ + pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); + pgszDest = sqlite3BtreeGetPageSize(p->pDest); + destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest)); + if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){ + rc = SQLITE_READONLY; + } + + /* Now that there is a read-lock on the source database, query the + ** source pager for the number of pages in the database. + */ + nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc); + assert( nSrcPage>=0 ); + for(ii=0; (nPage<0 || iiiNext<=(Pgno)nSrcPage && !rc; ii++){ + const Pgno iSrcPg = p->iNext; /* Source page number */ + if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ + DbPage *pSrcPg; /* Source page object */ + rc = sqlite3PagerAcquire(pSrcPager, iSrcPg, &pSrcPg, + PAGER_GET_READONLY); + if( rc==SQLITE_OK ){ + rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); + sqlite3PagerUnref(pSrcPg); + } + } + p->iNext++; + } + if( rc==SQLITE_OK ){ + p->nPagecount = nSrcPage; + p->nRemaining = nSrcPage+1-p->iNext; + if( p->iNext>(Pgno)nSrcPage ){ + rc = SQLITE_DONE; + }else if( !p->isAttached ){ + attachBackupObject(p); + } + } + + /* Update the schema version field in the destination database. This + ** is to make sure that the schema-version really does change in + ** the case where the source and destination databases have the + ** same schema version. + */ + if( rc==SQLITE_DONE ){ + if( nSrcPage==0 ){ + rc = sqlite3BtreeNewDb(p->pDest); + nSrcPage = 1; + } + if( rc==SQLITE_OK || rc==SQLITE_DONE ){ + rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1); + } + if( rc==SQLITE_OK ){ + if( p->pDestDb ){ + sqlite3ResetAllSchemasOfConnection(p->pDestDb); + } + if( destMode==PAGER_JOURNALMODE_WAL ){ + rc = sqlite3BtreeSetVersion(p->pDest, 2); + } + } + if( rc==SQLITE_OK ){ + int nDestTruncate; + /* Set nDestTruncate to the final number of pages in the destination + ** database. The complication here is that the destination page + ** size may be different to the source page size. + ** + ** If the source page size is smaller than the destination page size, + ** round up. In this case the call to sqlite3OsTruncate() below will + ** fix the size of the file. However it is important to call + ** sqlite3PagerTruncateImage() here so that any pages in the + ** destination file that lie beyond the nDestTruncate page mark are + ** journalled by PagerCommitPhaseOne() before they are destroyed + ** by the file truncation. + */ + assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) ); + assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) ); + if( pgszSrcpDest->pBt) ){ + nDestTruncate--; + } + }else{ + nDestTruncate = nSrcPage * (pgszSrc/pgszDest); + } + assert( nDestTruncate>0 ); + + if( pgszSrc= iSize || ( + nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1) + && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest + )); + + /* This block ensures that all data required to recreate the original + ** database has been stored in the journal for pDestPager and the + ** journal synced to disk. So at this point we may safely modify + ** the database file in any way, knowing that if a power failure + ** occurs, the original database will be reconstructed from the + ** journal file. */ + sqlite3PagerPagecount(pDestPager, &nDstPage); + for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){ + if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){ + DbPage *pPg; + rc = sqlite3PagerGet(pDestPager, iPg, &pPg); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pPg); + sqlite3PagerUnref(pPg); + } + } + } + if( rc==SQLITE_OK ){ + rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1); + } + + /* Write the extra pages and truncate the database file as required */ + iEnd = MIN(PENDING_BYTE + pgszDest, iSize); + for( + iOff=PENDING_BYTE+pgszSrc; + rc==SQLITE_OK && iOffpDest, 0)) + ){ + rc = SQLITE_DONE; + } + } + } + + /* If bCloseTrans is true, then this function opened a read transaction + ** on the source database. Close the read transaction here. There is + ** no need to check the return values of the btree methods here, as + ** "committing" a read-only transaction cannot fail. + */ + if( bCloseTrans ){ + TESTONLY( int rc2 ); + TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0); + TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0); + assert( rc2==SQLITE_OK ); + } + + if( rc==SQLITE_IOERR_NOMEM ){ + rc = SQLITE_NOMEM; + } + p->rc = rc; + } + if( p->pDestDb ){ + sqlite3_mutex_leave(p->pDestDb->mutex); + } + sqlite3BtreeLeave(p->pSrc); + sqlite3_mutex_leave(p->pSrcDb->mutex); + return rc; +} + +/* +** Release all resources associated with an sqlite3_backup* handle. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p){ + sqlite3_backup **pp; /* Ptr to head of pagers backup list */ + sqlite3 *pSrcDb; /* Source database connection */ + int rc; /* Value to return */ + + /* Enter the mutexes */ + if( p==0 ) return SQLITE_OK; + pSrcDb = p->pSrcDb; + sqlite3_mutex_enter(pSrcDb->mutex); + sqlite3BtreeEnter(p->pSrc); + if( p->pDestDb ){ + sqlite3_mutex_enter(p->pDestDb->mutex); + } + + /* Detach this backup from the source pager. */ + if( p->pDestDb ){ + p->pSrc->nBackup--; + } + if( p->isAttached ){ + pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); + while( *pp!=p ){ + pp = &(*pp)->pNext; + } + *pp = p->pNext; + } + + /* If a transaction is still open on the Btree, roll it back. */ + sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0); + + /* Set the error code of the destination database handle. */ + rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; + if( p->pDestDb ){ + sqlite3Error(p->pDestDb, rc); + + /* Exit the mutexes and free the backup context structure. */ + sqlite3LeaveMutexAndCloseZombie(p->pDestDb); + } + sqlite3BtreeLeave(p->pSrc); + if( p->pDestDb ){ + /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a + ** call to sqlite3_backup_init() and is destroyed by a call to + ** sqlite3_backup_finish(). */ + sqlite3_free(p); + } + sqlite3LeaveMutexAndCloseZombie(pSrcDb); + return rc; +} + +/* +** Return the number of pages still to be backed up as of the most recent +** call to sqlite3_backup_step(). +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( p==0 ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + return p->nRemaining; +} + +/* +** Return the total number of pages in the source database as of the most +** recent call to sqlite3_backup_step(). +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( p==0 ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + return p->nPagecount; +} + +/* +** This function is called after the contents of page iPage of the +** source database have been modified. If page iPage has already been +** copied into the destination database, then the data written to the +** destination is now invalidated. The destination copy of iPage needs +** to be updated with the new data before the backup operation is +** complete. +** +** It is assumed that the mutex associated with the BtShared object +** corresponding to the source database is held when this function is +** called. +*/ +static SQLITE_NOINLINE void backupUpdate( + sqlite3_backup *p, + Pgno iPage, + const u8 *aData +){ + assert( p!=0 ); + do{ + assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); + if( !isFatalError(p->rc) && iPageiNext ){ + /* The backup process p has already copied page iPage. But now it + ** has been modified by a transaction on the source pager. Copy + ** the new data into the backup. + */ + int rc; + assert( p->pDestDb ); + sqlite3_mutex_enter(p->pDestDb->mutex); + rc = backupOnePage(p, iPage, aData, 1); + sqlite3_mutex_leave(p->pDestDb->mutex); + assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); + if( rc!=SQLITE_OK ){ + p->rc = rc; + } + } + }while( (p = p->pNext)!=0 ); +} +SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){ + if( pBackup ) backupUpdate(pBackup, iPage, aData); +} + +/* +** Restart the backup process. This is called when the pager layer +** detects that the database has been modified by an external database +** connection. In this case there is no way of knowing which of the +** pages that have been copied into the destination database are still +** valid and which are not, so the entire process needs to be restarted. +** +** It is assumed that the mutex associated with the BtShared object +** corresponding to the source database is held when this function is +** called. +*/ +SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *pBackup){ + sqlite3_backup *p; /* Iterator variable */ + for(p=pBackup; p; p=p->pNext){ + assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); + p->iNext = 1; + } +} + +#ifndef SQLITE_OMIT_VACUUM +/* +** Copy the complete content of pBtFrom into pBtTo. A transaction +** must be active for both files. +** +** The size of file pTo may be reduced by this operation. If anything +** goes wrong, the transaction on pTo is rolled back. If successful, the +** transaction is committed before returning. +*/ +SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ + int rc; + sqlite3_file *pFd; /* File descriptor for database pTo */ + sqlite3_backup b; + sqlite3BtreeEnter(pTo); + sqlite3BtreeEnter(pFrom); + + assert( sqlite3BtreeIsInTrans(pTo) ); + pFd = sqlite3PagerFile(sqlite3BtreePager(pTo)); + if( pFd->pMethods ){ + i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom); + rc = sqlite3OsFileControl(pFd, SQLITE_FCNTL_OVERWRITE, &nByte); + if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; + if( rc ) goto copy_finished; + } + + /* Set up an sqlite3_backup object. sqlite3_backup.pDestDb must be set + ** to 0. This is used by the implementations of sqlite3_backup_step() + ** and sqlite3_backup_finish() to detect that they are being called + ** from this function, not directly by the user. + */ + memset(&b, 0, sizeof(b)); + b.pSrcDb = pFrom->db; + b.pSrc = pFrom; + b.pDest = pTo; + b.iNext = 1; + + /* 0x7FFFFFFF is the hard limit for the number of pages in a database + ** file. By passing this as the number of pages to copy to + ** sqlite3_backup_step(), we can guarantee that the copy finishes + ** within a single call (unless an error occurs). The assert() statement + ** checks this assumption - (p->rc) should be set to either SQLITE_DONE + ** or an error code. + */ + sqlite3_backup_step(&b, 0x7FFFFFFF); + assert( b.rc!=SQLITE_OK ); + rc = sqlite3_backup_finish(&b); + if( rc==SQLITE_OK ){ + pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; + }else{ + sqlite3PagerClearCache(sqlite3BtreePager(b.pDest)); + } + + assert( sqlite3BtreeIsInTrans(pTo)==0 ); +copy_finished: + sqlite3BtreeLeave(pFrom); + sqlite3BtreeLeave(pTo); + return rc; +} +#endif /* SQLITE_OMIT_VACUUM */ + +/************** End of backup.c **********************************************/ +/************** Begin file vdbemem.c *****************************************/ +/* +** 2004 May 26 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains code use to manipulate "Mem" structure. A "Mem" +** stores a single value in the VDBE. Mem is an opaque structure visible +** only within the VDBE. Interface routines refer to a Mem using the +** name sqlite_value +*/ +/* #include "sqliteInt.h" */ +/* #include "vdbeInt.h" */ + +#ifdef SQLITE_DEBUG +/* +** Check invariants on a Mem object. +** +** This routine is intended for use inside of assert() statements, like +** this: assert( sqlite3VdbeCheckMemInvariants(pMem) ); +*/ +SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){ + /* If MEM_Dyn is set then Mem.xDel!=0. + ** Mem.xDel is might not be initialized if MEM_Dyn is clear. + */ + assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 ); + + /* MEM_Dyn may only be set if Mem.szMalloc==0. In this way we + ** ensure that if Mem.szMalloc>0 then it is safe to do + ** Mem.z = Mem.zMalloc without having to check Mem.flags&MEM_Dyn. + ** That saves a few cycles in inner loops. */ + assert( (p->flags & MEM_Dyn)==0 || p->szMalloc==0 ); + + /* Cannot be both MEM_Int and MEM_Real at the same time */ + assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) ); + + /* The szMalloc field holds the correct memory allocation size */ + assert( p->szMalloc==0 + || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) ); + + /* If p holds a string or blob, the Mem.z must point to exactly + ** one of the following: + ** + ** (1) Memory in Mem.zMalloc and managed by the Mem object + ** (2) Memory to be freed using Mem.xDel + ** (3) An ephemeral string or blob + ** (4) A static string or blob + */ + if( (p->flags & (MEM_Str|MEM_Blob)) && p->n>0 ){ + assert( + ((p->szMalloc>0 && p->z==p->zMalloc)? 1 : 0) + + ((p->flags&MEM_Dyn)!=0 ? 1 : 0) + + ((p->flags&MEM_Ephem)!=0 ? 1 : 0) + + ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1 + ); + } + return 1; +} +#endif + + +/* +** If pMem is an object with a valid string representation, this routine +** ensures the internal encoding for the string representation is +** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE. +** +** If pMem is not a string object, or the encoding of the string +** representation is already stored using the requested encoding, then this +** routine is a no-op. +** +** SQLITE_OK is returned if the conversion is successful (or not required). +** SQLITE_NOMEM may be returned if a malloc() fails during conversion +** between formats. +*/ +SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ +#ifndef SQLITE_OMIT_UTF16 + int rc; +#endif + assert( (pMem->flags&MEM_RowSet)==0 ); + assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE + || desiredEnc==SQLITE_UTF16BE ); + if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){ + return SQLITE_OK; + } + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); +#ifdef SQLITE_OMIT_UTF16 + return SQLITE_ERROR; +#else + + /* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned, + ** then the encoding of the value may not have changed. + */ + rc = sqlite3VdbeMemTranslate(pMem, (u8)desiredEnc); + assert(rc==SQLITE_OK || rc==SQLITE_NOMEM); + assert(rc==SQLITE_OK || pMem->enc!=desiredEnc); + assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc); + return rc; +#endif +} + +/* +** Make sure pMem->z points to a writable allocation of at least +** min(n,32) bytes. +** +** If the bPreserve argument is true, then copy of the content of +** pMem->z into the new allocation. pMem must be either a string or +** blob if bPreserve is true. If bPreserve is false, any prior content +** in pMem->z is discarded. +*/ +SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ + assert( sqlite3VdbeCheckMemInvariants(pMem) ); + assert( (pMem->flags&MEM_RowSet)==0 ); + + /* If the bPreserve flag is set to true, then the memory cell must already + ** contain a valid string or blob value. */ + assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); + testcase( bPreserve && pMem->z==0 ); + + assert( pMem->szMalloc==0 + || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) ); + if( pMem->szMallocszMalloc>0 && pMem->z==pMem->zMalloc ){ + pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); + bPreserve = 0; + }else{ + if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc); + pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); + } + if( pMem->zMalloc==0 ){ + sqlite3VdbeMemSetNull(pMem); + pMem->z = 0; + pMem->szMalloc = 0; + return SQLITE_NOMEM; + }else{ + pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); + } + } + + if( bPreserve && pMem->z && pMem->z!=pMem->zMalloc ){ + memcpy(pMem->zMalloc, pMem->z, pMem->n); + } + if( (pMem->flags&MEM_Dyn)!=0 ){ + assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC ); + pMem->xDel((void *)(pMem->z)); + } + + pMem->z = pMem->zMalloc; + pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static); + return SQLITE_OK; +} + +/* +** Change the pMem->zMalloc allocation to be at least szNew bytes. +** If pMem->zMalloc already meets or exceeds the requested size, this +** routine is a no-op. +** +** Any prior string or blob content in the pMem object may be discarded. +** The pMem->xDel destructor is called, if it exists. Though MEM_Str +** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, and MEM_Null +** values are preserved. +** +** Return SQLITE_OK on success or an error code (probably SQLITE_NOMEM) +** if unable to complete the resizing. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ + assert( szNew>0 ); + assert( (pMem->flags & MEM_Dyn)==0 || pMem->szMalloc==0 ); + if( pMem->szMallocflags & MEM_Dyn)==0 ); + pMem->z = pMem->zMalloc; + pMem->flags &= (MEM_Null|MEM_Int|MEM_Real); + return SQLITE_OK; +} + +/* +** Change pMem so that its MEM_Str or MEM_Blob value is stored in +** MEM.zMalloc, where it can be safely written. +** +** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ + int f; + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( (pMem->flags&MEM_RowSet)==0 ); + ExpandBlob(pMem); + f = pMem->flags; + if( (f&(MEM_Str|MEM_Blob)) && (pMem->szMalloc==0 || pMem->z!=pMem->zMalloc) ){ + if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ + return SQLITE_NOMEM; + } + pMem->z[pMem->n] = 0; + pMem->z[pMem->n+1] = 0; + pMem->flags |= MEM_Term; + } + pMem->flags &= ~MEM_Ephem; +#ifdef SQLITE_DEBUG + pMem->pScopyFrom = 0; +#endif + + return SQLITE_OK; +} + +/* +** If the given Mem* has a zero-filled tail, turn it into an ordinary +** blob stored in dynamically allocated space. +*/ +#ifndef SQLITE_OMIT_INCRBLOB +SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){ + if( pMem->flags & MEM_Zero ){ + int nByte; + assert( pMem->flags&MEM_Blob ); + assert( (pMem->flags&MEM_RowSet)==0 ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + + /* Set nByte to the number of bytes required to store the expanded blob. */ + nByte = pMem->n + pMem->u.nZero; + if( nByte<=0 ){ + nByte = 1; + } + if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){ + return SQLITE_NOMEM; + } + + memset(&pMem->z[pMem->n], 0, pMem->u.nZero); + pMem->n += pMem->u.nZero; + pMem->flags &= ~(MEM_Zero|MEM_Term); + } + return SQLITE_OK; +} +#endif + +/* +** It is already known that pMem contains an unterminated string. +** Add the zero terminator. +*/ +static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ + if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){ + return SQLITE_NOMEM; + } + pMem->z[pMem->n] = 0; + pMem->z[pMem->n+1] = 0; + pMem->flags |= MEM_Term; + return SQLITE_OK; +} + +/* +** Make sure the given Mem is \u0000 terminated. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){ + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + testcase( (pMem->flags & (MEM_Term|MEM_Str))==(MEM_Term|MEM_Str) ); + testcase( (pMem->flags & (MEM_Term|MEM_Str))==0 ); + if( (pMem->flags & (MEM_Term|MEM_Str))!=MEM_Str ){ + return SQLITE_OK; /* Nothing to do */ + }else{ + return vdbeMemAddTerminator(pMem); + } +} + +/* +** Add MEM_Str to the set of representations for the given Mem. Numbers +** are converted using sqlite3_snprintf(). Converting a BLOB to a string +** is a no-op. +** +** Existing representations MEM_Int and MEM_Real are invalidated if +** bForce is true but are retained if bForce is false. +** +** A MEM_Null value will never be passed to this function. This function is +** used for converting values to text for returning to the user (i.e. via +** sqlite3_value_text()), or for ensuring that values to be used as btree +** keys are strings. In the former case a NULL pointer is returned the +** user and the latter is an internal programming error. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ + int fg = pMem->flags; + const int nByte = 32; + + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( !(fg&MEM_Zero) ); + assert( !(fg&(MEM_Str|MEM_Blob)) ); + assert( fg&(MEM_Int|MEM_Real) ); + assert( (pMem->flags&MEM_RowSet)==0 ); + assert( EIGHT_BYTE_ALIGNMENT(pMem) ); + + + if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){ + return SQLITE_NOMEM; + } + + /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8 + ** string representation of the value. Then, if the required encoding + ** is UTF-16le or UTF-16be do a translation. + ** + ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16. + */ + if( fg & MEM_Int ){ + sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i); + }else{ + assert( fg & MEM_Real ); + sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r); + } + pMem->n = sqlite3Strlen30(pMem->z); + pMem->enc = SQLITE_UTF8; + pMem->flags |= MEM_Str|MEM_Term; + if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real); + sqlite3VdbeChangeEncoding(pMem, enc); + return SQLITE_OK; +} + +/* +** Memory cell pMem contains the context of an aggregate function. +** This routine calls the finalize method for that function. The +** result of the aggregate is stored back into pMem. +** +** Return SQLITE_ERROR if the finalizer reports an error. SQLITE_OK +** otherwise. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ + int rc = SQLITE_OK; + if( ALWAYS(pFunc && pFunc->xFinalize) ){ + sqlite3_context ctx; + Mem t; + assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + memset(&ctx, 0, sizeof(ctx)); + memset(&t, 0, sizeof(t)); + t.flags = MEM_Null; + t.db = pMem->db; + ctx.pOut = &t; + ctx.pMem = pMem; + ctx.pFunc = pFunc; + pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */ + assert( (pMem->flags & MEM_Dyn)==0 ); + if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc); + memcpy(pMem, &t, sizeof(t)); + rc = ctx.isError; + } + return rc; +} + +/* +** If the memory cell contains a value that must be freed by +** invoking the external callback in Mem.xDel, then this routine +** will free that value. It also sets Mem.flags to MEM_Null. +** +** This is a helper routine for sqlite3VdbeMemSetNull() and +** for sqlite3VdbeMemRelease(). Use those other routines as the +** entry point for releasing Mem resources. +*/ +static SQLITE_NOINLINE void vdbeMemClearExternAndSetNull(Mem *p){ + assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); + assert( VdbeMemDynamic(p) ); + if( p->flags&MEM_Agg ){ + sqlite3VdbeMemFinalize(p, p->u.pDef); + assert( (p->flags & MEM_Agg)==0 ); + testcase( p->flags & MEM_Dyn ); + } + if( p->flags&MEM_Dyn ){ + assert( (p->flags&MEM_RowSet)==0 ); + assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 ); + p->xDel((void *)p->z); + }else if( p->flags&MEM_RowSet ){ + sqlite3RowSetClear(p->u.pRowSet); + }else if( p->flags&MEM_Frame ){ + VdbeFrame *pFrame = p->u.pFrame; + pFrame->pParent = pFrame->v->pDelFrame; + pFrame->v->pDelFrame = pFrame; + } + p->flags = MEM_Null; +} + +/* +** Release memory held by the Mem p, both external memory cleared +** by p->xDel and memory in p->zMalloc. +** +** This is a helper routine invoked by sqlite3VdbeMemRelease() in +** the unusual case where there really is memory in p that needs +** to be freed. +*/ +static SQLITE_NOINLINE void vdbeMemClear(Mem *p){ + if( VdbeMemDynamic(p) ){ + vdbeMemClearExternAndSetNull(p); + } + if( p->szMalloc ){ + sqlite3DbFree(p->db, p->zMalloc); + p->szMalloc = 0; + } + p->z = 0; +} + +/* +** Release any memory resources held by the Mem. Both the memory that is +** free by Mem.xDel and the Mem.zMalloc allocation are freed. +** +** Use this routine prior to clean up prior to abandoning a Mem, or to +** reset a Mem back to its minimum memory utilization. +** +** Use sqlite3VdbeMemSetNull() to release just the Mem.xDel space +** prior to inserting new content into the Mem. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){ + assert( sqlite3VdbeCheckMemInvariants(p) ); + if( VdbeMemDynamic(p) || p->szMalloc ){ + vdbeMemClear(p); + } +} + +/* +** Convert a 64-bit IEEE double into a 64-bit signed integer. +** If the double is out of range of a 64-bit signed integer then +** return the closest available 64-bit signed integer. +*/ +static i64 doubleToInt64(double r){ +#ifdef SQLITE_OMIT_FLOATING_POINT + /* When floating-point is omitted, double and int64 are the same thing */ + return r; +#else + /* + ** Many compilers we encounter do not define constants for the + ** minimum and maximum 64-bit integers, or they define them + ** inconsistently. And many do not understand the "LL" notation. + ** So we define our own static constants here using nothing + ** larger than a 32-bit integer constant. + */ + static const i64 maxInt = LARGEST_INT64; + static const i64 minInt = SMALLEST_INT64; + + if( r<=(double)minInt ){ + return minInt; + }else if( r>=(double)maxInt ){ + return maxInt; + }else{ + return (i64)r; + } +#endif +} + +/* +** Return some kind of integer value which is the best we can do +** at representing the value that *pMem describes as an integer. +** If pMem is an integer, then the value is exact. If pMem is +** a floating-point then the value returned is the integer part. +** If pMem is a string or blob, then we make an attempt to convert +** it into an integer and return that. If pMem represents an +** an SQL-NULL value, return 0. +** +** If pMem represents a string value, its encoding might be changed. +*/ +SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){ + int flags; + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( EIGHT_BYTE_ALIGNMENT(pMem) ); + flags = pMem->flags; + if( flags & MEM_Int ){ + return pMem->u.i; + }else if( flags & MEM_Real ){ + return doubleToInt64(pMem->u.r); + }else if( flags & (MEM_Str|MEM_Blob) ){ + i64 value = 0; + assert( pMem->z || pMem->n==0 ); + sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc); + return value; + }else{ + return 0; + } +} + +/* +** Return the best representation of pMem that we can get into a +** double. If pMem is already a double or an integer, return its +** value. If it is a string or blob, try to convert it to a double. +** If it is a NULL, return 0.0. +*/ +SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){ + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( EIGHT_BYTE_ALIGNMENT(pMem) ); + if( pMem->flags & MEM_Real ){ + return pMem->u.r; + }else if( pMem->flags & MEM_Int ){ + return (double)pMem->u.i; + }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ + /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ + double val = (double)0; + sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc); + return val; + }else{ + /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ + return (double)0; + } +} + +/* +** The MEM structure is already a MEM_Real. Try to also make it a +** MEM_Int if we can. +*/ +SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){ + i64 ix; + assert( pMem->flags & MEM_Real ); + assert( (pMem->flags & MEM_RowSet)==0 ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( EIGHT_BYTE_ALIGNMENT(pMem) ); + + ix = doubleToInt64(pMem->u.r); + + /* Only mark the value as an integer if + ** + ** (1) the round-trip conversion real->int->real is a no-op, and + ** (2) The integer is neither the largest nor the smallest + ** possible integer (ticket #3922) + ** + ** The second and third terms in the following conditional enforces + ** the second condition under the assumption that addition overflow causes + ** values to wrap around. + */ + if( pMem->u.r==ix && ix>SMALLEST_INT64 && ixu.i = ix; + MemSetTypeFlag(pMem, MEM_Int); + } +} + +/* +** Convert pMem to type integer. Invalidate any prior representations. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem *pMem){ + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( (pMem->flags & MEM_RowSet)==0 ); + assert( EIGHT_BYTE_ALIGNMENT(pMem) ); + + pMem->u.i = sqlite3VdbeIntValue(pMem); + MemSetTypeFlag(pMem, MEM_Int); + return SQLITE_OK; +} + +/* +** Convert pMem so that it is of type MEM_Real. +** Invalidate any prior representations. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){ + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( EIGHT_BYTE_ALIGNMENT(pMem) ); + + pMem->u.r = sqlite3VdbeRealValue(pMem); + MemSetTypeFlag(pMem, MEM_Real); + return SQLITE_OK; +} + +/* +** Convert pMem so that it has types MEM_Real or MEM_Int or both. +** Invalidate any prior representations. +** +** Every effort is made to force the conversion, even if the input +** is a string that does not look completely like a number. Convert +** as much of the string as we can and ignore the rest. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ + if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){ + assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){ + MemSetTypeFlag(pMem, MEM_Int); + }else{ + pMem->u.r = sqlite3VdbeRealValue(pMem); + MemSetTypeFlag(pMem, MEM_Real); + sqlite3VdbeIntegerAffinity(pMem); + } + } + assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 ); + pMem->flags &= ~(MEM_Str|MEM_Blob); + return SQLITE_OK; +} + +/* +** Cast the datatype of the value in pMem according to the affinity +** "aff". Casting is different from applying affinity in that a cast +** is forced. In other words, the value is converted into the desired +** affinity even if that results in loss of data. This routine is +** used (for example) to implement the SQL "cast()" operator. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ + if( pMem->flags & MEM_Null ) return; + switch( aff ){ + case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */ + if( (pMem->flags & MEM_Blob)==0 ){ + sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); + assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); + MemSetTypeFlag(pMem, MEM_Blob); + }else{ + pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); + } + break; + } + case SQLITE_AFF_NUMERIC: { + sqlite3VdbeMemNumerify(pMem); + break; + } + case SQLITE_AFF_INTEGER: { + sqlite3VdbeMemIntegerify(pMem); + break; + } + case SQLITE_AFF_REAL: { + sqlite3VdbeMemRealify(pMem); + break; + } + default: { + assert( aff==SQLITE_AFF_TEXT ); + assert( MEM_Str==(MEM_Blob>>3) ); + pMem->flags |= (pMem->flags&MEM_Blob)>>3; + sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); + assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); + pMem->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero); + break; + } + } +} + +/* +** Initialize bulk memory to be a consistent Mem object. +** +** The minimum amount of initialization feasible is performed. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem *pMem, sqlite3 *db, u16 flags){ + assert( (flags & ~MEM_TypeMask)==0 ); + pMem->flags = flags; + pMem->db = db; + pMem->szMalloc = 0; +} + + +/* +** Delete any previous value and set the value stored in *pMem to NULL. +** +** This routine calls the Mem.xDel destructor to dispose of values that +** require the destructor. But it preserves the Mem.zMalloc memory allocation. +** To free all resources, use sqlite3VdbeMemRelease(), which both calls this +** routine to invoke the destructor and deallocates Mem.zMalloc. +** +** Use this routine to reset the Mem prior to insert a new value. +** +** Use sqlite3VdbeMemRelease() to complete erase the Mem prior to abandoning it. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){ + if( VdbeMemDynamic(pMem) ){ + vdbeMemClearExternAndSetNull(pMem); + }else{ + pMem->flags = MEM_Null; + } +} +SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value *p){ + sqlite3VdbeMemSetNull((Mem*)p); +} + +/* +** Delete any previous value and set the value to be a BLOB of length +** n containing all zeros. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){ + sqlite3VdbeMemRelease(pMem); + pMem->flags = MEM_Blob|MEM_Zero; + pMem->n = 0; + if( n<0 ) n = 0; + pMem->u.nZero = n; + pMem->enc = SQLITE_UTF8; + pMem->z = 0; +} + +/* +** The pMem is known to contain content that needs to be destroyed prior +** to a value change. So invoke the destructor, then set the value to +** a 64-bit integer. +*/ +static SQLITE_NOINLINE void vdbeReleaseAndSetInt64(Mem *pMem, i64 val){ + sqlite3VdbeMemSetNull(pMem); + pMem->u.i = val; + pMem->flags = MEM_Int; +} + +/* +** Delete any previous value and set the value stored in *pMem to val, +** manifest type INTEGER. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ + if( VdbeMemDynamic(pMem) ){ + vdbeReleaseAndSetInt64(pMem, val); + }else{ + pMem->u.i = val; + pMem->flags = MEM_Int; + } +} + +#ifndef SQLITE_OMIT_FLOATING_POINT +/* +** Delete any previous value and set the value stored in *pMem to val, +** manifest type REAL. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ + sqlite3VdbeMemSetNull(pMem); + if( !sqlite3IsNaN(val) ){ + pMem->u.r = val; + pMem->flags = MEM_Real; + } +} +#endif + +/* +** Delete any previous value and set the value of pMem to be an +** empty boolean index. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){ + sqlite3 *db = pMem->db; + assert( db!=0 ); + assert( (pMem->flags & MEM_RowSet)==0 ); + sqlite3VdbeMemRelease(pMem); + pMem->zMalloc = sqlite3DbMallocRaw(db, 64); + if( db->mallocFailed ){ + pMem->flags = MEM_Null; + pMem->szMalloc = 0; + }else{ + assert( pMem->zMalloc ); + pMem->szMalloc = sqlite3DbMallocSize(db, pMem->zMalloc); + pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, pMem->szMalloc); + assert( pMem->u.pRowSet!=0 ); + pMem->flags = MEM_RowSet; + } +} + +/* +** Return true if the Mem object contains a TEXT or BLOB that is +** too large - whose size exceeds SQLITE_MAX_LENGTH. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){ + assert( p->db!=0 ); + if( p->flags & (MEM_Str|MEM_Blob) ){ + int n = p->n; + if( p->flags & MEM_Zero ){ + n += p->u.nZero; + } + return n>p->db->aLimit[SQLITE_LIMIT_LENGTH]; + } + return 0; +} + +#ifdef SQLITE_DEBUG +/* +** This routine prepares a memory cell for modification by breaking +** its link to a shallow copy and by marking any current shallow +** copies of this cell as invalid. +** +** This is used for testing and debugging only - to make sure shallow +** copies are not misused. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ + int i; + Mem *pX; + for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){ + if( pX->pScopyFrom==pMem ){ + pX->flags |= MEM_Undefined; + pX->pScopyFrom = 0; + } + } + pMem->pScopyFrom = 0; +} +#endif /* SQLITE_DEBUG */ + + +/* +** Make an shallow copy of pFrom into pTo. Prior contents of +** pTo are freed. The pFrom->z field is not duplicated. If +** pFrom->z is used, then pTo->z points to the same thing as pFrom->z +** and flags gets srcType (either MEM_Ephem or MEM_Static). +*/ +static SQLITE_NOINLINE void vdbeClrCopy(Mem *pTo, const Mem *pFrom, int eType){ + vdbeMemClearExternAndSetNull(pTo); + assert( !VdbeMemDynamic(pTo) ); + sqlite3VdbeMemShallowCopy(pTo, pFrom, eType); +} +SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ + assert( (pFrom->flags & MEM_RowSet)==0 ); + assert( pTo->db==pFrom->db ); + if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; } + memcpy(pTo, pFrom, MEMCELLSIZE); + if( (pFrom->flags&MEM_Static)==0 ){ + pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem); + assert( srcType==MEM_Ephem || srcType==MEM_Static ); + pTo->flags |= srcType; + } +} + +/* +** Make a full copy of pFrom into pTo. Prior contents of pTo are +** freed before the copy is made. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ + int rc = SQLITE_OK; + + /* The pFrom==0 case in the following assert() is when an sqlite3_value + ** from sqlite3_value_dup() is used as the argument + ** to sqlite3_result_value(). */ + assert( pTo->db==pFrom->db || pFrom->db==0 ); + assert( (pFrom->flags & MEM_RowSet)==0 ); + if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo); + memcpy(pTo, pFrom, MEMCELLSIZE); + pTo->flags &= ~MEM_Dyn; + if( pTo->flags&(MEM_Str|MEM_Blob) ){ + if( 0==(pFrom->flags&MEM_Static) ){ + pTo->flags |= MEM_Ephem; + rc = sqlite3VdbeMemMakeWriteable(pTo); + } + } + + return rc; +} + +/* +** Transfer the contents of pFrom to pTo. Any existing value in pTo is +** freed. If pFrom contains ephemeral data, a copy is made. +** +** pFrom contains an SQL NULL when this routine returns. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){ + assert( pFrom->db==0 || sqlite3_mutex_held(pFrom->db->mutex) ); + assert( pTo->db==0 || sqlite3_mutex_held(pTo->db->mutex) ); + assert( pFrom->db==0 || pTo->db==0 || pFrom->db==pTo->db ); + + sqlite3VdbeMemRelease(pTo); + memcpy(pTo, pFrom, sizeof(Mem)); + pFrom->flags = MEM_Null; + pFrom->szMalloc = 0; +} + +/* +** Change the value of a Mem to be a string or a BLOB. +** +** The memory management strategy depends on the value of the xDel +** parameter. If the value passed is SQLITE_TRANSIENT, then the +** string is copied into a (possibly existing) buffer managed by the +** Mem structure. Otherwise, any existing buffer is freed and the +** pointer copied. +** +** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH +** size limit) then no memory allocation occurs. If the string can be +** stored without allocating memory, then it is. If a memory allocation +** is required to store the string, then value of pMem is unchanged. In +** either case, SQLITE_TOOBIG is returned. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemSetStr( + Mem *pMem, /* Memory cell to set to string value */ + const char *z, /* String pointer */ + int n, /* Bytes in string, or negative */ + u8 enc, /* Encoding of z. 0 for BLOBs */ + void (*xDel)(void*) /* Destructor function */ +){ + int nByte = n; /* New value for pMem->n */ + int iLimit; /* Maximum allowed string or blob size */ + u16 flags = 0; /* New value for pMem->flags */ + + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( (pMem->flags & MEM_RowSet)==0 ); + + /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ + if( !z ){ + sqlite3VdbeMemSetNull(pMem); + return SQLITE_OK; + } + + if( pMem->db ){ + iLimit = pMem->db->aLimit[SQLITE_LIMIT_LENGTH]; + }else{ + iLimit = SQLITE_MAX_LENGTH; + } + flags = (enc==0?MEM_Blob:MEM_Str); + if( nByte<0 ){ + assert( enc!=0 ); + if( enc==SQLITE_UTF8 ){ + nByte = sqlite3Strlen30(z); + if( nByte>iLimit ) nByte = iLimit+1; + }else{ + for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){} + } + flags |= MEM_Term; + } + + /* The following block sets the new values of Mem.z and Mem.xDel. It + ** also sets a flag in local variable "flags" to indicate the memory + ** management (one of MEM_Dyn or MEM_Static). + */ + if( xDel==SQLITE_TRANSIENT ){ + int nAlloc = nByte; + if( flags&MEM_Term ){ + nAlloc += (enc==SQLITE_UTF8?1:2); + } + if( nByte>iLimit ){ + return SQLITE_TOOBIG; + } + testcase( nAlloc==0 ); + testcase( nAlloc==31 ); + testcase( nAlloc==32 ); + if( sqlite3VdbeMemClearAndResize(pMem, MAX(nAlloc,32)) ){ + return SQLITE_NOMEM; + } + memcpy(pMem->z, z, nAlloc); + }else if( xDel==SQLITE_DYNAMIC ){ + sqlite3VdbeMemRelease(pMem); + pMem->zMalloc = pMem->z = (char *)z; + pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); + }else{ + sqlite3VdbeMemRelease(pMem); + pMem->z = (char *)z; + pMem->xDel = xDel; + flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn); + } + + pMem->n = nByte; + pMem->flags = flags; + pMem->enc = (enc==0 ? SQLITE_UTF8 : enc); + +#ifndef SQLITE_OMIT_UTF16 + if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){ + return SQLITE_NOMEM; + } +#endif + + if( nByte>iLimit ){ + return SQLITE_TOOBIG; + } + + return SQLITE_OK; +} + +/* +** Move data out of a btree key or data field and into a Mem structure. +** The data or key is taken from the entry that pCur is currently pointing +** to. offset and amt determine what portion of the data or key to retrieve. +** key is true to get the key or false to get data. The result is written +** into the pMem element. +** +** The pMem object must have been initialized. This routine will use +** pMem->zMalloc to hold the content from the btree, if possible. New +** pMem->zMalloc space will be allocated if necessary. The calling routine +** is responsible for making sure that the pMem object is eventually +** destroyed. +** +** If this routine fails for any reason (malloc returns NULL or unable +** to read from the disk) then the pMem is left in an inconsistent state. +*/ +static SQLITE_NOINLINE int vdbeMemFromBtreeResize( + BtCursor *pCur, /* Cursor pointing at record to retrieve. */ + u32 offset, /* Offset from the start of data to return bytes from. */ + u32 amt, /* Number of bytes to return. */ + int key, /* If true, retrieve from the btree key, not data. */ + Mem *pMem /* OUT: Return data in this Mem structure. */ +){ + int rc; + pMem->flags = MEM_Null; + if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){ + if( key ){ + rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); + }else{ + rc = sqlite3BtreeData(pCur, offset, amt, pMem->z); + } + if( rc==SQLITE_OK ){ + pMem->z[amt] = 0; + pMem->z[amt+1] = 0; + pMem->flags = MEM_Blob|MEM_Term; + pMem->n = (int)amt; + }else{ + sqlite3VdbeMemRelease(pMem); + } + } + return rc; +} +SQLITE_PRIVATE int sqlite3VdbeMemFromBtree( + BtCursor *pCur, /* Cursor pointing at record to retrieve. */ + u32 offset, /* Offset from the start of data to return bytes from. */ + u32 amt, /* Number of bytes to return. */ + int key, /* If true, retrieve from the btree key, not data. */ + Mem *pMem /* OUT: Return data in this Mem structure. */ +){ + char *zData; /* Data from the btree layer */ + u32 available = 0; /* Number of bytes available on the local btree page */ + int rc = SQLITE_OK; /* Return code */ + + assert( sqlite3BtreeCursorIsValid(pCur) ); + assert( !VdbeMemDynamic(pMem) ); + + /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() + ** that both the BtShared and database handle mutexes are held. */ + assert( (pMem->flags & MEM_RowSet)==0 ); + if( key ){ + zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); + }else{ + zData = (char *)sqlite3BtreeDataFetch(pCur, &available); + } + assert( zData!=0 ); + + if( offset+amt<=available ){ + pMem->z = &zData[offset]; + pMem->flags = MEM_Blob|MEM_Ephem; + pMem->n = (int)amt; + }else{ + rc = vdbeMemFromBtreeResize(pCur, offset, amt, key, pMem); + } + + return rc; +} + +/* +** The pVal argument is known to be a value other than NULL. +** Convert it into a string with encoding enc and return a pointer +** to a zero-terminated version of that string. +*/ +static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){ + assert( pVal!=0 ); + assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); + assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); + assert( (pVal->flags & MEM_RowSet)==0 ); + assert( (pVal->flags & (MEM_Null))==0 ); + if( pVal->flags & (MEM_Blob|MEM_Str) ){ + pVal->flags |= MEM_Str; + if( pVal->flags & MEM_Zero ){ + sqlite3VdbeMemExpandBlob(pVal); + } + if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){ + sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); + } + if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&SQLITE_PTR_TO_INT(pVal->z)) ){ + assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 ); + if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){ + return 0; + } + } + sqlite3VdbeMemNulTerminate(pVal); /* IMP: R-31275-44060 */ + }else{ + sqlite3VdbeMemStringify(pVal, enc, 0); + assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) ); + } + assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 + || pVal->db->mallocFailed ); + if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){ + return pVal->z; + }else{ + return 0; + } +} + +/* This function is only available internally, it is not part of the +** external API. It works in a similar way to sqlite3_value_text(), +** except the data returned is in the encoding specified by the second +** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or +** SQLITE_UTF8. +** +** (2006-02-16:) The enc value can be or-ed with SQLITE_UTF16_ALIGNED. +** If that is the case, then the result must be aligned on an even byte +** boundary. +*/ +SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ + if( !pVal ) return 0; + assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); + assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); + assert( (pVal->flags & MEM_RowSet)==0 ); + if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){ + return pVal->z; + } + if( pVal->flags&MEM_Null ){ + return 0; + } + return valueToText(pVal, enc); +} + +/* +** Create a new sqlite3_value object. +*/ +SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){ + Mem *p = sqlite3DbMallocZero(db, sizeof(*p)); + if( p ){ + p->flags = MEM_Null; + p->db = db; + } + return p; +} + +/* +** Context object passed by sqlite3Stat4ProbeSetValue() through to +** valueNew(). See comments above valueNew() for details. +*/ +struct ValueNewStat4Ctx { + Parse *pParse; + Index *pIdx; + UnpackedRecord **ppRec; + int iVal; +}; + +/* +** Allocate and return a pointer to a new sqlite3_value object. If +** the second argument to this function is NULL, the object is allocated +** by calling sqlite3ValueNew(). +** +** Otherwise, if the second argument is non-zero, then this function is +** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not +** already been allocated, allocate the UnpackedRecord structure that +** that function will return to its caller here. Then return a pointer to +** an sqlite3_value within the UnpackedRecord.a[] array. +*/ +static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( p ){ + UnpackedRecord *pRec = p->ppRec[0]; + + if( pRec==0 ){ + Index *pIdx = p->pIdx; /* Index being probed */ + int nByte; /* Bytes of space to allocate */ + int i; /* Counter variable */ + int nCol = pIdx->nColumn; /* Number of index columns including rowid */ + + nByte = sizeof(Mem) * nCol + ROUND8(sizeof(UnpackedRecord)); + pRec = (UnpackedRecord*)sqlite3DbMallocZero(db, nByte); + if( pRec ){ + pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx); + if( pRec->pKeyInfo ){ + assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol ); + assert( pRec->pKeyInfo->enc==ENC(db) ); + pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord))); + for(i=0; iaMem[i].flags = MEM_Null; + pRec->aMem[i].db = db; + } + }else{ + sqlite3DbFree(db, pRec); + pRec = 0; + } + } + if( pRec==0 ) return 0; + p->ppRec[0] = pRec; + } + + pRec->nField = p->iVal+1; + return &pRec->aMem[p->iVal]; + } +#else + UNUSED_PARAMETER(p); +#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */ + return sqlite3ValueNew(db); +} + +/* +** The expression object indicated by the second argument is guaranteed +** to be a scalar SQL function. If +** +** * all function arguments are SQL literals, +** * the SQLITE_FUNC_CONSTANT function flag is set, and +** * the SQLITE_FUNC_NEEDCOLL function flag is not set, +** +** then this routine attempts to invoke the SQL function. Assuming no +** error occurs, output parameter (*ppVal) is set to point to a value +** object containing the result before returning SQLITE_OK. +** +** Affinity aff is applied to the result of the function before returning. +** If the result is a text value, the sqlite3_value object uses encoding +** enc. +** +** If the conditions above are not met, this function returns SQLITE_OK +** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to +** NULL and an SQLite error code returned. +*/ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +static int valueFromFunction( + sqlite3 *db, /* The database connection */ + Expr *p, /* The expression to evaluate */ + u8 enc, /* Encoding to use */ + u8 aff, /* Affinity to use */ + sqlite3_value **ppVal, /* Write the new value here */ + struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */ +){ + sqlite3_context ctx; /* Context object for function invocation */ + sqlite3_value **apVal = 0; /* Function arguments */ + int nVal = 0; /* Size of apVal[] array */ + FuncDef *pFunc = 0; /* Function definition */ + sqlite3_value *pVal = 0; /* New value */ + int rc = SQLITE_OK; /* Return code */ + int nName; /* Size of function name in bytes */ + ExprList *pList = 0; /* Function arguments */ + int i; /* Iterator variable */ + + assert( pCtx!=0 ); + assert( (p->flags & EP_TokenOnly)==0 ); + pList = p->x.pList; + if( pList ) nVal = pList->nExpr; + nName = sqlite3Strlen30(p->u.zToken); + pFunc = sqlite3FindFunction(db, p->u.zToken, nName, nVal, enc, 0); + assert( pFunc ); + if( (pFunc->funcFlags & SQLITE_FUNC_CONSTANT)==0 + || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) + ){ + return SQLITE_OK; + } + + if( pList ){ + apVal = (sqlite3_value**)sqlite3DbMallocZero(db, sizeof(apVal[0]) * nVal); + if( apVal==0 ){ + rc = SQLITE_NOMEM; + goto value_from_function_out; + } + for(i=0; ia[i].pExpr, enc, aff, &apVal[i]); + if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out; + } + } + + pVal = valueNew(db, pCtx); + if( pVal==0 ){ + rc = SQLITE_NOMEM; + goto value_from_function_out; + } + + assert( pCtx->pParse->rc==SQLITE_OK ); + memset(&ctx, 0, sizeof(ctx)); + ctx.pOut = pVal; + ctx.pFunc = pFunc; + pFunc->xFunc(&ctx, nVal, apVal); + if( ctx.isError ){ + rc = ctx.isError; + sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal)); + }else{ + sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8); + assert( rc==SQLITE_OK ); + rc = sqlite3VdbeChangeEncoding(pVal, enc); + if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){ + rc = SQLITE_TOOBIG; + pCtx->pParse->nErr++; + } + } + pCtx->pParse->rc = rc; + + value_from_function_out: + if( rc!=SQLITE_OK ){ + pVal = 0; + } + if( apVal ){ + for(i=0; iop)==TK_UPLUS ) pExpr = pExpr->pLeft; + if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; + + /* Compressed expressions only appear when parsing the DEFAULT clause + ** on a table column definition, and hence only when pCtx==0. This + ** check ensures that an EP_TokenOnly expression is never passed down + ** into valueFromFunction(). */ + assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 ); + + if( op==TK_CAST ){ + u8 aff = sqlite3AffinityType(pExpr->u.zToken,0); + rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx); + testcase( rc!=SQLITE_OK ); + if( *ppVal ){ + sqlite3VdbeMemCast(*ppVal, aff, SQLITE_UTF8); + sqlite3ValueApplyAffinity(*ppVal, affinity, SQLITE_UTF8); + } + return rc; + } + + /* Handle negative integers in a single step. This is needed in the + ** case when the value is -9223372036854775808. + */ + if( op==TK_UMINUS + && (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){ + pExpr = pExpr->pLeft; + op = pExpr->op; + negInt = -1; + zNeg = "-"; + } + + if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ + pVal = valueNew(db, pCtx); + if( pVal==0 ) goto no_mem; + if( ExprHasProperty(pExpr, EP_IntValue) ){ + sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt); + }else{ + zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken); + if( zVal==0 ) goto no_mem; + sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); + } + if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_BLOB ){ + sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); + }else{ + sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8); + } + if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str; + if( enc!=SQLITE_UTF8 ){ + rc = sqlite3VdbeChangeEncoding(pVal, enc); + } + }else if( op==TK_UMINUS ) { + /* This branch happens for multiple negative signs. Ex: -(-5) */ + if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) + && pVal!=0 + ){ + sqlite3VdbeMemNumerify(pVal); + if( pVal->flags & MEM_Real ){ + pVal->u.r = -pVal->u.r; + }else if( pVal->u.i==SMALLEST_INT64 ){ + pVal->u.r = -(double)SMALLEST_INT64; + MemSetTypeFlag(pVal, MEM_Real); + }else{ + pVal->u.i = -pVal->u.i; + } + sqlite3ValueApplyAffinity(pVal, affinity, enc); + } + }else if( op==TK_NULL ){ + pVal = valueNew(db, pCtx); + if( pVal==0 ) goto no_mem; + } +#ifndef SQLITE_OMIT_BLOB_LITERAL + else if( op==TK_BLOB ){ + int nVal; + assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); + assert( pExpr->u.zToken[1]=='\'' ); + pVal = valueNew(db, pCtx); + if( !pVal ) goto no_mem; + zVal = &pExpr->u.zToken[2]; + nVal = sqlite3Strlen30(zVal)-1; + assert( zVal[nVal]=='\'' ); + sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, + 0, SQLITE_DYNAMIC); + } +#endif + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + else if( op==TK_FUNCTION && pCtx!=0 ){ + rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx); + } +#endif + + *ppVal = pVal; + return rc; + +no_mem: + db->mallocFailed = 1; + sqlite3DbFree(db, zVal); + assert( *ppVal==0 ); +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( pCtx==0 ) sqlite3ValueFree(pVal); +#else + assert( pCtx==0 ); sqlite3ValueFree(pVal); +#endif + return SQLITE_NOMEM; +} + +/* +** Create a new sqlite3_value object, containing the value of pExpr. +** +** This only works for very simple expressions that consist of one constant +** token (i.e. "5", "5.1", "'a string'"). If the expression can +** be converted directly into a value, then the value is allocated and +** a pointer written to *ppVal. The caller is responsible for deallocating +** the value by passing it to sqlite3ValueFree() later on. If the expression +** cannot be converted to a value, then *ppVal is set to NULL. +*/ +SQLITE_PRIVATE int sqlite3ValueFromExpr( + sqlite3 *db, /* The database connection */ + Expr *pExpr, /* The expression to evaluate */ + u8 enc, /* Encoding to use */ + u8 affinity, /* Affinity to use */ + sqlite3_value **ppVal /* Write the new value here */ +){ + return valueFromExpr(db, pExpr, enc, affinity, ppVal, 0); +} + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +/* +** The implementation of the sqlite_record() function. This function accepts +** a single argument of any type. The return value is a formatted database +** record (a blob) containing the argument value. +** +** This is used to convert the value stored in the 'sample' column of the +** sqlite_stat3 table to the record format SQLite uses internally. +*/ +static void recordFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const int file_format = 1; + int iSerial; /* Serial type */ + int nSerial; /* Bytes of space for iSerial as varint */ + int nVal; /* Bytes of space required for argv[0] */ + int nRet; + sqlite3 *db; + u8 *aRet; + + UNUSED_PARAMETER( argc ); + iSerial = sqlite3VdbeSerialType(argv[0], file_format); + nSerial = sqlite3VarintLen(iSerial); + nVal = sqlite3VdbeSerialTypeLen(iSerial); + db = sqlite3_context_db_handle(context); + + nRet = 1 + nSerial + nVal; + aRet = sqlite3DbMallocRaw(db, nRet); + if( aRet==0 ){ + sqlite3_result_error_nomem(context); + }else{ + aRet[0] = nSerial+1; + putVarint32(&aRet[1], iSerial); + sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial); + sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT); + sqlite3DbFree(db, aRet); + } +} + +/* +** Register built-in functions used to help read ANALYZE data. +*/ +SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void){ + static SQLITE_WSD FuncDef aAnalyzeTableFuncs[] = { + FUNCTION(sqlite_record, 1, 0, 0, recordFunc), + }; + int i; + FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); + FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAnalyzeTableFuncs); + for(i=0; idb; + + /* Skip over any TK_COLLATE nodes */ + pExpr = sqlite3ExprSkipCollate(pExpr); + + if( !pExpr ){ + pVal = valueNew(db, pAlloc); + if( pVal ){ + sqlite3VdbeMemSetNull((Mem*)pVal); + } + }else if( pExpr->op==TK_VARIABLE + || NEVER(pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE) + ){ + Vdbe *v; + int iBindVar = pExpr->iColumn; + sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar); + if( (v = pParse->pReprepare)!=0 ){ + pVal = valueNew(db, pAlloc); + if( pVal ){ + rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]); + if( rc==SQLITE_OK ){ + sqlite3ValueApplyAffinity(pVal, affinity, ENC(db)); + } + pVal->db = pParse->db; + } + } + }else{ + rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, pAlloc); + } + + assert( pVal==0 || pVal->db==db ); + *ppVal = pVal; + return rc; +} + +/* +** This function is used to allocate and populate UnpackedRecord +** structures intended to be compared against sample index keys stored +** in the sqlite_stat4 table. +** +** A single call to this function attempts to populates field iVal (leftmost +** is 0 etc.) of the unpacked record with a value extracted from expression +** pExpr. Extraction of values is possible if: +** +** * (pExpr==0). In this case the value is assumed to be an SQL NULL, +** +** * The expression is a bound variable, and this is a reprepare, or +** +** * The sqlite3ValueFromExpr() function is able to extract a value +** from the expression (i.e. the expression is a literal value). +** +** If a value can be extracted, the affinity passed as the 5th argument +** is applied to it before it is copied into the UnpackedRecord. Output +** parameter *pbOk is set to true if a value is extracted, or false +** otherwise. +** +** When this function is called, *ppRec must either point to an object +** allocated by an earlier call to this function, or must be NULL. If it +** is NULL and a value can be successfully extracted, a new UnpackedRecord +** is allocated (and *ppRec set to point to it) before returning. +** +** Unless an error is encountered, SQLITE_OK is returned. It is not an +** error if a value cannot be extracted from pExpr. If an error does +** occur, an SQLite error code is returned. +*/ +SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue( + Parse *pParse, /* Parse context */ + Index *pIdx, /* Index being probed */ + UnpackedRecord **ppRec, /* IN/OUT: Probe record */ + Expr *pExpr, /* The expression to extract a value from */ + u8 affinity, /* Affinity to use */ + int iVal, /* Array element to populate */ + int *pbOk /* OUT: True if value was extracted */ +){ + int rc; + sqlite3_value *pVal = 0; + struct ValueNewStat4Ctx alloc; + + alloc.pParse = pParse; + alloc.pIdx = pIdx; + alloc.ppRec = ppRec; + alloc.iVal = iVal; + + rc = stat4ValueFromExpr(pParse, pExpr, affinity, &alloc, &pVal); + assert( pVal==0 || pVal->db==pParse->db ); + *pbOk = (pVal!=0); + return rc; +} + +/* +** Attempt to extract a value from expression pExpr using the methods +** as described for sqlite3Stat4ProbeSetValue() above. +** +** If successful, set *ppVal to point to a new value object and return +** SQLITE_OK. If no value can be extracted, but no other error occurs +** (e.g. OOM), return SQLITE_OK and set *ppVal to NULL. Or, if an error +** does occur, return an SQLite error code. The final value of *ppVal +** is undefined in this case. +*/ +SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr( + Parse *pParse, /* Parse context */ + Expr *pExpr, /* The expression to extract a value from */ + u8 affinity, /* Affinity to use */ + sqlite3_value **ppVal /* OUT: New value object (or NULL) */ +){ + return stat4ValueFromExpr(pParse, pExpr, affinity, 0, ppVal); +} + +/* +** Extract the iCol-th column from the nRec-byte record in pRec. Write +** the column value into *ppVal. If *ppVal is initially NULL then a new +** sqlite3_value object is allocated. +** +** If *ppVal is initially NULL then the caller is responsible for +** ensuring that the value written into *ppVal is eventually freed. +*/ +SQLITE_PRIVATE int sqlite3Stat4Column( + sqlite3 *db, /* Database handle */ + const void *pRec, /* Pointer to buffer containing record */ + int nRec, /* Size of buffer pRec in bytes */ + int iCol, /* Column to extract */ + sqlite3_value **ppVal /* OUT: Extracted value */ +){ + u32 t; /* a column type code */ + int nHdr; /* Size of the header in the record */ + int iHdr; /* Next unread header byte */ + int iField; /* Next unread data byte */ + int szField; /* Size of the current data field */ + int i; /* Column index */ + u8 *a = (u8*)pRec; /* Typecast byte array */ + Mem *pMem = *ppVal; /* Write result into this Mem object */ + + assert( iCol>0 ); + iHdr = getVarint32(a, nHdr); + if( nHdr>nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT; + iField = nHdr; + for(i=0; i<=iCol; i++){ + iHdr += getVarint32(&a[iHdr], t); + testcase( iHdr==nHdr ); + testcase( iHdr==nHdr+1 ); + if( iHdr>nHdr ) return SQLITE_CORRUPT_BKPT; + szField = sqlite3VdbeSerialTypeLen(t); + iField += szField; + } + testcase( iField==nRec ); + testcase( iField==nRec+1 ); + if( iField>nRec ) return SQLITE_CORRUPT_BKPT; + if( pMem==0 ){ + pMem = *ppVal = sqlite3ValueNew(db); + if( pMem==0 ) return SQLITE_NOMEM; + } + sqlite3VdbeSerialGet(&a[iField-szField], t, pMem); + pMem->enc = ENC(db); + return SQLITE_OK; +} + +/* +** Unless it is NULL, the argument must be an UnpackedRecord object returned +** by an earlier call to sqlite3Stat4ProbeSetValue(). This call deletes +** the object. +*/ +SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){ + if( pRec ){ + int i; + int nCol = pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField; + Mem *aMem = pRec->aMem; + sqlite3 *db = aMem[0].db; + for(i=0; ipKeyInfo); + sqlite3DbFree(db, pRec); + } +} +#endif /* ifdef SQLITE_ENABLE_STAT4 */ + +/* +** Change the string value of an sqlite3_value object +*/ +SQLITE_PRIVATE void sqlite3ValueSetStr( + sqlite3_value *v, /* Value to be set */ + int n, /* Length of string z */ + const void *z, /* Text of the new string */ + u8 enc, /* Encoding to use */ + void (*xDel)(void*) /* Destructor for the string */ +){ + if( v ) sqlite3VdbeMemSetStr((Mem *)v, z, n, enc, xDel); +} + +/* +** Free an sqlite3_value object +*/ +SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value *v){ + if( !v ) return; + sqlite3VdbeMemRelease((Mem *)v); + sqlite3DbFree(((Mem*)v)->db, v); +} + +/* +** The sqlite3ValueBytes() routine returns the number of bytes in the +** sqlite3_value object assuming that it uses the encoding "enc". +** The valueBytes() routine is a helper function. +*/ +static SQLITE_NOINLINE int valueBytes(sqlite3_value *pVal, u8 enc){ + return valueToText(pVal, enc)!=0 ? pVal->n : 0; +} +SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ + Mem *p = (Mem*)pVal; + assert( (p->flags & MEM_Null)==0 || (p->flags & (MEM_Str|MEM_Blob))==0 ); + if( (p->flags & MEM_Str)!=0 && pVal->enc==enc ){ + return p->n; + } + if( (p->flags & MEM_Blob)!=0 ){ + if( p->flags & MEM_Zero ){ + return p->n + p->u.nZero; + }else{ + return p->n; + } + } + if( p->flags & MEM_Null ) return 0; + return valueBytes(pVal, enc); +} + +/************** End of vdbemem.c *********************************************/ +/************** Begin file vdbeaux.c *****************************************/ +/* +** 2003 September 6 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code used for creating, destroying, and populating +** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) +*/ +/* #include "sqliteInt.h" */ +/* #include "vdbeInt.h" */ + +/* +** Create a new virtual database engine. +*/ +SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ + sqlite3 *db = pParse->db; + Vdbe *p; + p = sqlite3DbMallocZero(db, sizeof(Vdbe) ); + if( p==0 ) return 0; + p->db = db; + if( db->pVdbe ){ + db->pVdbe->pPrev = p; + } + p->pNext = db->pVdbe; + p->pPrev = 0; + db->pVdbe = p; + p->magic = VDBE_MAGIC_INIT; + p->pParse = pParse; + assert( pParse->aLabel==0 ); + assert( pParse->nLabel==0 ); + assert( pParse->nOpAlloc==0 ); + return p; +} + +/* +** Change the error string stored in Vdbe.zErrMsg +*/ +SQLITE_PRIVATE void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){ + va_list ap; + sqlite3DbFree(p->db, p->zErrMsg); + va_start(ap, zFormat); + p->zErrMsg = sqlite3VMPrintf(p->db, zFormat, ap); + va_end(ap); +} + +/* +** Remember the SQL string for a prepared statement. +*/ +SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ + assert( isPrepareV2==1 || isPrepareV2==0 ); + if( p==0 ) return; +#if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG) + if( !isPrepareV2 ) return; +#endif + assert( p->zSql==0 ); + p->zSql = sqlite3DbStrNDup(p->db, z, n); + p->isPrepareV2 = (u8)isPrepareV2; +} + +/* +** Return the SQL associated with a prepared statement +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt){ + Vdbe *p = (Vdbe *)pStmt; + return (p && p->isPrepareV2) ? p->zSql : 0; +} + +/* +** Swap all content between two VDBE structures. +*/ +SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){ + Vdbe tmp, *pTmp; + char *zTmp; + tmp = *pA; + *pA = *pB; + *pB = tmp; + pTmp = pA->pNext; + pA->pNext = pB->pNext; + pB->pNext = pTmp; + pTmp = pA->pPrev; + pA->pPrev = pB->pPrev; + pB->pPrev = pTmp; + zTmp = pA->zSql; + pA->zSql = pB->zSql; + pB->zSql = zTmp; + pB->isPrepareV2 = pA->isPrepareV2; +} + +/* +** Resize the Vdbe.aOp array so that it is at least nOp elements larger +** than its current size. nOp is guaranteed to be less than or equal +** to 1024/sizeof(Op). +** +** If an out-of-memory error occurs while resizing the array, return +** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.nOpAlloc remain +** unchanged (this is so that any opcodes already allocated can be +** correctly deallocated along with the rest of the Vdbe). +*/ +static int growOpArray(Vdbe *v, int nOp){ + VdbeOp *pNew; + Parse *p = v->pParse; + + /* The SQLITE_TEST_REALLOC_STRESS compile-time option is designed to force + ** more frequent reallocs and hence provide more opportunities for + ** simulated OOM faults. SQLITE_TEST_REALLOC_STRESS is generally used + ** during testing only. With SQLITE_TEST_REALLOC_STRESS grow the op array + ** by the minimum* amount required until the size reaches 512. Normal + ** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current + ** size of the op array or add 1KB of space, whichever is smaller. */ +#ifdef SQLITE_TEST_REALLOC_STRESS + int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp); +#else + int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op))); + UNUSED_PARAMETER(nOp); +#endif + + assert( nOp<=(1024/sizeof(Op)) ); + assert( nNew>=(p->nOpAlloc+nOp) ); + pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op)); + if( pNew ){ + p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op); + v->aOp = pNew; + } + return (pNew ? SQLITE_OK : SQLITE_NOMEM); +} + +#ifdef SQLITE_DEBUG +/* This routine is just a convenient place to set a breakpoint that will +** fire after each opcode is inserted and displayed using +** "PRAGMA vdbe_addoptrace=on". +*/ +static void test_addop_breakpoint(void){ + static int n = 0; + n++; +} +#endif + +/* +** Add a new instruction to the list of instructions current in the +** VDBE. Return the address of the new instruction. +** +** Parameters: +** +** p Pointer to the VDBE +** +** op The opcode for this instruction +** +** p1, p2, p3 Operands +** +** Use the sqlite3VdbeResolveLabel() function to fix an address and +** the sqlite3VdbeChangeP4() function to change the value of the P4 +** operand. +*/ +SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ + int i; + VdbeOp *pOp; + + i = p->nOp; + assert( p->magic==VDBE_MAGIC_INIT ); + assert( op>0 && op<0xff ); + if( p->pParse->nOpAlloc<=i ){ + if( growOpArray(p, 1) ){ + return 1; + } + } + p->nOp++; + pOp = &p->aOp[i]; + pOp->opcode = (u8)op; + pOp->p5 = 0; + pOp->p1 = p1; + pOp->p2 = p2; + pOp->p3 = p3; + pOp->p4.p = 0; + pOp->p4type = P4_NOTUSED; +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS + pOp->zComment = 0; +#endif +#ifdef SQLITE_DEBUG + if( p->db->flags & SQLITE_VdbeAddopTrace ){ + int jj, kk; + Parse *pParse = p->pParse; + for(jj=kk=0; jjaColCache + jj; + if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue; + printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn); + kk++; + } + if( kk ) printf("\n"); + sqlite3VdbePrintOp(0, i, &p->aOp[i]); + test_addop_breakpoint(); + } +#endif +#ifdef VDBE_PROFILE + pOp->cycles = 0; + pOp->cnt = 0; +#endif +#ifdef SQLITE_VDBE_COVERAGE + pOp->iSrcLine = 0; +#endif + return i; +} +SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe *p, int op){ + return sqlite3VdbeAddOp3(p, op, 0, 0, 0); +} +SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe *p, int op, int p1){ + return sqlite3VdbeAddOp3(p, op, p1, 0, 0); +} +SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe *p, int op, int p1, int p2){ + return sqlite3VdbeAddOp3(p, op, p1, p2, 0); +} + + +/* +** Add an opcode that includes the p4 value as a pointer. +*/ +SQLITE_PRIVATE int sqlite3VdbeAddOp4( + Vdbe *p, /* Add the opcode to this VM */ + int op, /* The new opcode */ + int p1, /* The P1 operand */ + int p2, /* The P2 operand */ + int p3, /* The P3 operand */ + const char *zP4, /* The P4 operand */ + int p4type /* P4 operand type */ +){ + int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); + sqlite3VdbeChangeP4(p, addr, zP4, p4type); + return addr; +} + +/* +** Add an opcode that includes the p4 value with a P4_INT64 type. +*/ +SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8( + Vdbe *p, /* Add the opcode to this VM */ + int op, /* The new opcode */ + int p1, /* The P1 operand */ + int p2, /* The P2 operand */ + int p3, /* The P3 operand */ + const u8 *zP4, /* The P4 operand */ + int p4type /* P4 operand type */ +){ + char *p4copy = sqlite3DbMallocRaw(sqlite3VdbeDb(p), 8); + if( p4copy ) memcpy(p4copy, zP4, 8); + return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type); +} + +/* +** Add an OP_ParseSchema opcode. This routine is broken out from +** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees +** as having been used. +** +** The zWhere string must have been obtained from sqlite3_malloc(). +** This routine will take ownership of the allocated memory. +*/ +SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){ + int j; + int addr = sqlite3VdbeAddOp3(p, OP_ParseSchema, iDb, 0, 0); + sqlite3VdbeChangeP4(p, addr, zWhere, P4_DYNAMIC); + for(j=0; jdb->nDb; j++) sqlite3VdbeUsesBtree(p, j); +} + +/* +** Add an opcode that includes the p4 value as an integer. +*/ +SQLITE_PRIVATE int sqlite3VdbeAddOp4Int( + Vdbe *p, /* Add the opcode to this VM */ + int op, /* The new opcode */ + int p1, /* The P1 operand */ + int p2, /* The P2 operand */ + int p3, /* The P3 operand */ + int p4 /* The P4 operand as an integer */ +){ + int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); + sqlite3VdbeChangeP4(p, addr, SQLITE_INT_TO_PTR(p4), P4_INT32); + return addr; +} + +/* +** Create a new symbolic label for an instruction that has yet to be +** coded. The symbolic label is really just a negative number. The +** label can be used as the P2 value of an operation. Later, when +** the label is resolved to a specific address, the VDBE will scan +** through its operation list and change all values of P2 which match +** the label into the resolved address. +** +** The VDBE knows that a P2 value is a label because labels are +** always negative and P2 values are suppose to be non-negative. +** Hence, a negative P2 value is a label that has yet to be resolved. +** +** Zero is returned if a malloc() fails. +*/ +SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *v){ + Parse *p = v->pParse; + int i = p->nLabel++; + assert( v->magic==VDBE_MAGIC_INIT ); + if( (i & (i-1))==0 ){ + p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel, + (i*2+1)*sizeof(p->aLabel[0])); + } + if( p->aLabel ){ + p->aLabel[i] = -1; + } + return -1-i; +} + +/* +** Resolve label "x" to be the address of the next instruction to +** be inserted. The parameter "x" must have been obtained from +** a prior call to sqlite3VdbeMakeLabel(). +*/ +SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){ + Parse *p = v->pParse; + int j = -1-x; + assert( v->magic==VDBE_MAGIC_INIT ); + assert( jnLabel ); + if( ALWAYS(j>=0) && p->aLabel ){ + p->aLabel[j] = v->nOp; + } + p->iFixedOp = v->nOp - 1; +} + +/* +** Mark the VDBE as one that can only be run one time. +*/ +SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe *p){ + p->runOnlyOnce = 1; +} + +#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */ + +/* +** The following type and function are used to iterate through all opcodes +** in a Vdbe main program and each of the sub-programs (triggers) it may +** invoke directly or indirectly. It should be used as follows: +** +** Op *pOp; +** VdbeOpIter sIter; +** +** memset(&sIter, 0, sizeof(sIter)); +** sIter.v = v; // v is of type Vdbe* +** while( (pOp = opIterNext(&sIter)) ){ +** // Do something with pOp +** } +** sqlite3DbFree(v->db, sIter.apSub); +** +*/ +typedef struct VdbeOpIter VdbeOpIter; +struct VdbeOpIter { + Vdbe *v; /* Vdbe to iterate through the opcodes of */ + SubProgram **apSub; /* Array of subprograms */ + int nSub; /* Number of entries in apSub */ + int iAddr; /* Address of next instruction to return */ + int iSub; /* 0 = main program, 1 = first sub-program etc. */ +}; +static Op *opIterNext(VdbeOpIter *p){ + Vdbe *v = p->v; + Op *pRet = 0; + Op *aOp; + int nOp; + + if( p->iSub<=p->nSub ){ + + if( p->iSub==0 ){ + aOp = v->aOp; + nOp = v->nOp; + }else{ + aOp = p->apSub[p->iSub-1]->aOp; + nOp = p->apSub[p->iSub-1]->nOp; + } + assert( p->iAddriAddr]; + p->iAddr++; + if( p->iAddr==nOp ){ + p->iSub++; + p->iAddr = 0; + } + + if( pRet->p4type==P4_SUBPROGRAM ){ + int nByte = (p->nSub+1)*sizeof(SubProgram*); + int j; + for(j=0; jnSub; j++){ + if( p->apSub[j]==pRet->p4.pProgram ) break; + } + if( j==p->nSub ){ + p->apSub = sqlite3DbReallocOrFree(v->db, p->apSub, nByte); + if( !p->apSub ){ + pRet = 0; + }else{ + p->apSub[p->nSub++] = pRet->p4.pProgram; + } + } + } + } + + return pRet; +} + +/* +** Check if the program stored in the VM associated with pParse may +** throw an ABORT exception (causing the statement, but not entire transaction +** to be rolled back). This condition is true if the main program or any +** sub-programs contains any of the following: +** +** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort. +** * OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort. +** * OP_Destroy +** * OP_VUpdate +** * OP_VRename +** * OP_FkCounter with P2==0 (immediate foreign key constraint) +** * OP_CreateTable and OP_InitCoroutine (for CREATE TABLE AS SELECT ...) +** +** Then check that the value of Parse.mayAbort is true if an +** ABORT may be thrown, or false otherwise. Return true if it does +** match, or false otherwise. This function is intended to be used as +** part of an assert statement in the compiler. Similar to: +** +** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) ); +*/ +SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ + int hasAbort = 0; + int hasFkCounter = 0; + int hasCreateTable = 0; + int hasInitCoroutine = 0; + Op *pOp; + VdbeOpIter sIter; + memset(&sIter, 0, sizeof(sIter)); + sIter.v = v; + + while( (pOp = opIterNext(&sIter))!=0 ){ + int opcode = pOp->opcode; + if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename + || ((opcode==OP_Halt || opcode==OP_HaltIfNull) + && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) + ){ + hasAbort = 1; + break; + } + if( opcode==OP_CreateTable ) hasCreateTable = 1; + if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1; +#ifndef SQLITE_OMIT_FOREIGN_KEY + if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){ + hasFkCounter = 1; + } +#endif + } + sqlite3DbFree(v->db, sIter.apSub); + + /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred. + ** If malloc failed, then the while() loop above may not have iterated + ** through all opcodes and hasAbort may be set incorrectly. Return + ** true for this case to prevent the assert() in the callers frame + ** from failing. */ + return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter + || (hasCreateTable && hasInitCoroutine) ); +} +#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ + +/* +** Loop through the program looking for P2 values that are negative +** on jump instructions. Each such value is a label. Resolve the +** label by setting the P2 value to its correct non-zero value. +** +** This routine is called once after all opcodes have been inserted. +** +** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument +** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by +** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array. +** +** The Op.opflags field is set on all opcodes. +*/ +static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ + int i; + int nMaxArgs = *pMaxFuncArgs; + Op *pOp; + Parse *pParse = p->pParse; + int *aLabel = pParse->aLabel; + p->readOnly = 1; + p->bIsReader = 0; + for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ + u8 opcode = pOp->opcode; + + /* NOTE: Be sure to update mkopcodeh.awk when adding or removing + ** cases from this switch! */ + switch( opcode ){ + case OP_Transaction: { + if( pOp->p2!=0 ) p->readOnly = 0; + /* fall thru */ + } + case OP_AutoCommit: + case OP_Savepoint: { + p->bIsReader = 1; + break; + } +#ifndef SQLITE_OMIT_WAL + case OP_Checkpoint: +#endif + case OP_Vacuum: + case OP_JournalMode: { + p->readOnly = 0; + p->bIsReader = 1; + break; + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + case OP_VUpdate: { + if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; + break; + } + case OP_VFilter: { + int n; + assert( p->nOp - i >= 3 ); + assert( pOp[-1].opcode==OP_Integer ); + n = pOp[-1].p1; + if( n>nMaxArgs ) nMaxArgs = n; + break; + } +#endif + case OP_Next: + case OP_NextIfOpen: + case OP_SorterNext: { + pOp->p4.xAdvance = sqlite3BtreeNext; + pOp->p4type = P4_ADVANCE; + break; + } + case OP_Prev: + case OP_PrevIfOpen: { + pOp->p4.xAdvance = sqlite3BtreePrevious; + pOp->p4type = P4_ADVANCE; + break; + } + } + + pOp->opflags = sqlite3OpcodeProperty[opcode]; + if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){ + assert( -1-pOp->p2nLabel ); + pOp->p2 = aLabel[-1-pOp->p2]; + } + } + sqlite3DbFree(p->db, pParse->aLabel); + pParse->aLabel = 0; + pParse->nLabel = 0; + *pMaxFuncArgs = nMaxArgs; + assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) ); +} + +/* +** Return the address of the next instruction to be inserted. +*/ +SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){ + assert( p->magic==VDBE_MAGIC_INIT ); + return p->nOp; +} + +/* +** This function returns a pointer to the array of opcodes associated with +** the Vdbe passed as the first argument. It is the callers responsibility +** to arrange for the returned array to be eventually freed using the +** vdbeFreeOpArray() function. +** +** Before returning, *pnOp is set to the number of entries in the returned +** array. Also, *pnMaxArg is set to the larger of its current value and +** the number of entries in the Vdbe.apArg[] array required to execute the +** returned program. +*/ +SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){ + VdbeOp *aOp = p->aOp; + assert( aOp && !p->db->mallocFailed ); + + /* Check that sqlite3VdbeUsesBtree() was not called on this VM */ + assert( DbMaskAllZero(p->btreeMask) ); + + resolveP2Values(p, pnMaxArg); + *pnOp = p->nOp; + p->aOp = 0; + return aOp; +} + +/* +** Add a whole list of operations to the operation stack. Return the +** address of the first operation added. +*/ +SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){ + int addr; + assert( p->magic==VDBE_MAGIC_INIT ); + if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){ + return 0; + } + addr = p->nOp; + if( ALWAYS(nOp>0) ){ + int i; + VdbeOpList const *pIn = aOp; + for(i=0; ip2; + VdbeOp *pOut = &p->aOp[i+addr]; + pOut->opcode = pIn->opcode; + pOut->p1 = pIn->p1; + if( p2<0 ){ + assert( sqlite3OpcodeProperty[pOut->opcode] & OPFLG_JUMP ); + pOut->p2 = addr + ADDR(p2); + }else{ + pOut->p2 = p2; + } + pOut->p3 = pIn->p3; + pOut->p4type = P4_NOTUSED; + pOut->p4.p = 0; + pOut->p5 = 0; +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS + pOut->zComment = 0; +#endif +#ifdef SQLITE_VDBE_COVERAGE + pOut->iSrcLine = iLineno+i; +#else + (void)iLineno; +#endif +#ifdef SQLITE_DEBUG + if( p->db->flags & SQLITE_VdbeAddopTrace ){ + sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]); + } +#endif + } + p->nOp += nOp; + } + return addr; +} + +#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) +/* +** Add an entry to the array of counters managed by sqlite3_stmt_scanstatus(). +*/ +SQLITE_PRIVATE void sqlite3VdbeScanStatus( + Vdbe *p, /* VM to add scanstatus() to */ + int addrExplain, /* Address of OP_Explain (or 0) */ + int addrLoop, /* Address of loop counter */ + int addrVisit, /* Address of rows visited counter */ + LogEst nEst, /* Estimated number of output rows */ + const char *zName /* Name of table or index being scanned */ +){ + int nByte = (p->nScan+1) * sizeof(ScanStatus); + ScanStatus *aNew; + aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte); + if( aNew ){ + ScanStatus *pNew = &aNew[p->nScan++]; + pNew->addrExplain = addrExplain; + pNew->addrLoop = addrLoop; + pNew->addrVisit = addrVisit; + pNew->nEst = nEst; + pNew->zName = sqlite3DbStrDup(p->db, zName); + p->aScan = aNew; + } +} +#endif + + +/* +** Change the value of the P1 operand for a specific instruction. +** This routine is useful when a large program is loaded from a +** static array using sqlite3VdbeAddOpList but we want to make a +** few minor changes to the program. +*/ +SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){ + assert( p!=0 ); + if( ((u32)p->nOp)>addr ){ + p->aOp[addr].p1 = val; + } +} + +/* +** Change the value of the P2 operand for a specific instruction. +** This routine is useful for setting a jump destination. +*/ +SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){ + assert( p!=0 ); + if( ((u32)p->nOp)>addr ){ + p->aOp[addr].p2 = val; + } +} + +/* +** Change the value of the P3 operand for a specific instruction. +*/ +SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){ + assert( p!=0 ); + if( ((u32)p->nOp)>addr ){ + p->aOp[addr].p3 = val; + } +} + +/* +** Change the value of the P5 operand for the most recently +** added operation. +*/ +SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 val){ + assert( p!=0 ); + if( p->aOp ){ + assert( p->nOp>0 ); + p->aOp[p->nOp-1].p5 = val; + } +} + +/* +** Change the P2 operand of instruction addr so that it points to +** the address of the next instruction to be coded. +*/ +SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){ + sqlite3VdbeChangeP2(p, addr, p->nOp); + p->pParse->iFixedOp = p->nOp - 1; +} + + +/* +** If the input FuncDef structure is ephemeral, then free it. If +** the FuncDef is not ephermal, then do nothing. +*/ +static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){ + if( ALWAYS(pDef) && (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){ + sqlite3DbFree(db, pDef); + } +} + +static void vdbeFreeOpArray(sqlite3 *, Op *, int); + +/* +** Delete a P4 value if necessary. +*/ +static void freeP4(sqlite3 *db, int p4type, void *p4){ + if( p4 ){ + assert( db ); + switch( p4type ){ + case P4_FUNCCTX: { + freeEphemeralFunction(db, ((sqlite3_context*)p4)->pFunc); + /* Fall through into the next case */ + } + case P4_REAL: + case P4_INT64: + case P4_DYNAMIC: + case P4_INTARRAY: { + sqlite3DbFree(db, p4); + break; + } + case P4_KEYINFO: { + if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4); + break; + } + case P4_MPRINTF: { + if( db->pnBytesFreed==0 ) sqlite3_free(p4); + break; + } + case P4_FUNCDEF: { + freeEphemeralFunction(db, (FuncDef*)p4); + break; + } + case P4_MEM: { + if( db->pnBytesFreed==0 ){ + sqlite3ValueFree((sqlite3_value*)p4); + }else{ + Mem *p = (Mem*)p4; + if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); + sqlite3DbFree(db, p); + } + break; + } + case P4_VTAB : { + if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4); + break; + } + } + } +} + +/* +** Free the space allocated for aOp and any p4 values allocated for the +** opcodes contained within. If aOp is not NULL it is assumed to contain +** nOp entries. +*/ +static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){ + if( aOp ){ + Op *pOp; + for(pOp=aOp; pOp<&aOp[nOp]; pOp++){ + freeP4(db, pOp->p4type, pOp->p4.p); +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS + sqlite3DbFree(db, pOp->zComment); +#endif + } + } + sqlite3DbFree(db, aOp); +} + +/* +** Link the SubProgram object passed as the second argument into the linked +** list at Vdbe.pSubProgram. This list is used to delete all sub-program +** objects when the VM is no longer required. +*/ +SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){ + p->pNext = pVdbe->pProgram; + pVdbe->pProgram = p; +} + +/* +** Change the opcode at addr into OP_Noop +*/ +SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){ + if( addrnOp ){ + VdbeOp *pOp = &p->aOp[addr]; + sqlite3 *db = p->db; + freeP4(db, pOp->p4type, pOp->p4.p); + memset(pOp, 0, sizeof(pOp[0])); + pOp->opcode = OP_Noop; + if( addr==p->nOp-1 ) p->nOp--; + } +} + +/* +** If the last opcode is "op" and it is not a jump destination, +** then remove it. Return true if and only if an opcode was removed. +*/ +SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){ + if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){ + sqlite3VdbeChangeToNoop(p, p->nOp-1); + return 1; + }else{ + return 0; + } +} + +/* +** Change the value of the P4 operand for a specific instruction. +** This routine is useful when a large program is loaded from a +** static array using sqlite3VdbeAddOpList but we want to make a +** few minor changes to the program. +** +** If n>=0 then the P4 operand is dynamic, meaning that a copy of +** the string is made into memory obtained from sqlite3_malloc(). +** A value of n==0 means copy bytes of zP4 up to and including the +** first null byte. If n>0 then copy n+1 bytes of zP4. +** +** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points +** to a string or structure that is guaranteed to exist for the lifetime of +** the Vdbe. In these cases we can just copy the pointer. +** +** If addr<0 then change P4 on the most recently inserted instruction. +*/ +SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){ + Op *pOp; + sqlite3 *db; + assert( p!=0 ); + db = p->db; + assert( p->magic==VDBE_MAGIC_INIT ); + if( p->aOp==0 || db->mallocFailed ){ + if( n!=P4_VTAB ){ + freeP4(db, n, (void*)*(char**)&zP4); + } + return; + } + assert( p->nOp>0 ); + assert( addrnOp ); + if( addr<0 ){ + addr = p->nOp - 1; + } + pOp = &p->aOp[addr]; + assert( pOp->p4type==P4_NOTUSED + || pOp->p4type==P4_INT32 + || pOp->p4type==P4_KEYINFO ); + freeP4(db, pOp->p4type, pOp->p4.p); + pOp->p4.p = 0; + if( n==P4_INT32 ){ + /* Note: this cast is safe, because the origin data point was an int + ** that was cast to a (const char *). */ + pOp->p4.i = SQLITE_PTR_TO_INT(zP4); + pOp->p4type = P4_INT32; + }else if( zP4==0 ){ + pOp->p4.p = 0; + pOp->p4type = P4_NOTUSED; + }else if( n==P4_KEYINFO ){ + pOp->p4.p = (void*)zP4; + pOp->p4type = P4_KEYINFO; + }else if( n==P4_VTAB ){ + pOp->p4.p = (void*)zP4; + pOp->p4type = P4_VTAB; + sqlite3VtabLock((VTable *)zP4); + assert( ((VTable *)zP4)->db==p->db ); + }else if( n<0 ){ + pOp->p4.p = (void*)zP4; + pOp->p4type = (signed char)n; + }else{ + if( n==0 ) n = sqlite3Strlen30(zP4); + pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n); + pOp->p4type = P4_DYNAMIC; + } +} + +/* +** Set the P4 on the most recently added opcode to the KeyInfo for the +** index given. +*/ +SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){ + Vdbe *v = pParse->pVdbe; + assert( v!=0 ); + assert( pIdx!=0 ); + sqlite3VdbeChangeP4(v, -1, (char*)sqlite3KeyInfoOfIndex(pParse, pIdx), + P4_KEYINFO); +} + +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS +/* +** Change the comment on the most recently coded instruction. Or +** insert a No-op and add the comment to that new instruction. This +** makes the code easier to read during debugging. None of this happens +** in a production build. +*/ +static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){ + assert( p->nOp>0 || p->aOp==0 ); + assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed ); + if( p->nOp ){ + assert( p->aOp ); + sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment); + p->aOp[p->nOp-1].zComment = sqlite3VMPrintf(p->db, zFormat, ap); + } +} +SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ + va_list ap; + if( p ){ + va_start(ap, zFormat); + vdbeVComment(p, zFormat, ap); + va_end(ap); + } +} +SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){ + va_list ap; + if( p ){ + sqlite3VdbeAddOp0(p, OP_Noop); + va_start(ap, zFormat); + vdbeVComment(p, zFormat, ap); + va_end(ap); + } +} +#endif /* NDEBUG */ + +#ifdef SQLITE_VDBE_COVERAGE +/* +** Set the value if the iSrcLine field for the previously coded instruction. +*/ +SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){ + sqlite3VdbeGetOp(v,-1)->iSrcLine = iLine; +} +#endif /* SQLITE_VDBE_COVERAGE */ + +/* +** Return the opcode for a given address. If the address is -1, then +** return the most recently inserted opcode. +** +** If a memory allocation error has occurred prior to the calling of this +** routine, then a pointer to a dummy VdbeOp will be returned. That opcode +** is readable but not writable, though it is cast to a writable value. +** The return of a dummy opcode allows the call to continue functioning +** after an OOM fault without having to check to see if the return from +** this routine is a valid pointer. But because the dummy.opcode is 0, +** dummy will never be written to. This is verified by code inspection and +** by running with Valgrind. +*/ +SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ + /* C89 specifies that the constant "dummy" will be initialized to all + ** zeros, which is correct. MSVC generates a warning, nevertheless. */ + static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */ + assert( p->magic==VDBE_MAGIC_INIT ); + if( addr<0 ){ + addr = p->nOp - 1; + } + assert( (addr>=0 && addrnOp) || p->db->mallocFailed ); + if( p->db->mallocFailed ){ + return (VdbeOp*)&dummy; + }else{ + return &p->aOp[addr]; + } +} + +#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) +/* +** Return an integer value for one of the parameters to the opcode pOp +** determined by character c. +*/ +static int translateP(char c, const Op *pOp){ + if( c=='1' ) return pOp->p1; + if( c=='2' ) return pOp->p2; + if( c=='3' ) return pOp->p3; + if( c=='4' ) return pOp->p4.i; + return pOp->p5; +} + +/* +** Compute a string for the "comment" field of a VDBE opcode listing. +** +** The Synopsis: field in comments in the vdbe.c source file gets converted +** to an extra string that is appended to the sqlite3OpcodeName(). In the +** absence of other comments, this synopsis becomes the comment on the opcode. +** Some translation occurs: +** +** "PX" -> "r[X]" +** "PX@PY" -> "r[X..X+Y-1]" or "r[x]" if y is 0 or 1 +** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0 +** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x +*/ +static int displayComment( + const Op *pOp, /* The opcode to be commented */ + const char *zP4, /* Previously obtained value for P4 */ + char *zTemp, /* Write result here */ + int nTemp /* Space available in zTemp[] */ +){ + const char *zOpName; + const char *zSynopsis; + int nOpName; + int ii, jj; + zOpName = sqlite3OpcodeName(pOp->opcode); + nOpName = sqlite3Strlen30(zOpName); + if( zOpName[nOpName+1] ){ + int seenCom = 0; + char c; + zSynopsis = zOpName += nOpName + 1; + for(ii=jj=0; jjzComment); + seenCom = 1; + }else{ + int v1 = translateP(c, pOp); + int v2; + sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v1); + if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){ + ii += 3; + jj += sqlite3Strlen30(zTemp+jj); + v2 = translateP(zSynopsis[ii], pOp); + if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){ + ii += 2; + v2++; + } + if( v2>1 ){ + sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1); + } + }else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){ + ii += 4; + } + } + jj += sqlite3Strlen30(zTemp+jj); + }else{ + zTemp[jj++] = c; + } + } + if( !seenCom && jjzComment ){ + sqlite3_snprintf(nTemp-jj, zTemp+jj, "; %s", pOp->zComment); + jj += sqlite3Strlen30(zTemp+jj); + } + if( jjzComment ){ + sqlite3_snprintf(nTemp, zTemp, "%s", pOp->zComment); + jj = sqlite3Strlen30(zTemp); + }else{ + zTemp[0] = 0; + jj = 0; + } + return jj; +} +#endif /* SQLITE_DEBUG */ + + +#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \ + || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) +/* +** Compute a string that describes the P4 parameter for an opcode. +** Use zTemp for any required temporary buffer space. +*/ +static char *displayP4(Op *pOp, char *zTemp, int nTemp){ + char *zP4 = zTemp; + assert( nTemp>=20 ); + switch( pOp->p4type ){ + case P4_KEYINFO: { + int i, j; + KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; + assert( pKeyInfo->aSortOrder!=0 ); + sqlite3_snprintf(nTemp, zTemp, "k(%d", pKeyInfo->nField); + i = sqlite3Strlen30(zTemp); + for(j=0; jnField; j++){ + CollSeq *pColl = pKeyInfo->aColl[j]; + const char *zColl = pColl ? pColl->zName : "nil"; + int n = sqlite3Strlen30(zColl); + if( n==6 && memcmp(zColl,"BINARY",6)==0 ){ + zColl = "B"; + n = 1; + } + if( i+n>nTemp-6 ){ + memcpy(&zTemp[i],",...",4); + break; + } + zTemp[i++] = ','; + if( pKeyInfo->aSortOrder[j] ){ + zTemp[i++] = '-'; + } + memcpy(&zTemp[i], zColl, n+1); + i += n; + } + zTemp[i++] = ')'; + zTemp[i] = 0; + assert( ip4.pColl; + sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName); + break; + } + case P4_FUNCDEF: { + FuncDef *pDef = pOp->p4.pFunc; + sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); + break; + } +#ifdef SQLITE_DEBUG + case P4_FUNCCTX: { + FuncDef *pDef = pOp->p4.pCtx->pFunc; + sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); + break; + } +#endif + case P4_INT64: { + sqlite3_snprintf(nTemp, zTemp, "%lld", *pOp->p4.pI64); + break; + } + case P4_INT32: { + sqlite3_snprintf(nTemp, zTemp, "%d", pOp->p4.i); + break; + } + case P4_REAL: { + sqlite3_snprintf(nTemp, zTemp, "%.16g", *pOp->p4.pReal); + break; + } + case P4_MEM: { + Mem *pMem = pOp->p4.pMem; + if( pMem->flags & MEM_Str ){ + zP4 = pMem->z; + }else if( pMem->flags & MEM_Int ){ + sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i); + }else if( pMem->flags & MEM_Real ){ + sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->u.r); + }else if( pMem->flags & MEM_Null ){ + sqlite3_snprintf(nTemp, zTemp, "NULL"); + }else{ + assert( pMem->flags & MEM_Blob ); + zP4 = "(blob)"; + } + break; + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + case P4_VTAB: { + sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; + sqlite3_snprintf(nTemp, zTemp, "vtab:%p", pVtab); + break; + } +#endif + case P4_INTARRAY: { + sqlite3_snprintf(nTemp, zTemp, "intarray"); + break; + } + case P4_SUBPROGRAM: { + sqlite3_snprintf(nTemp, zTemp, "program"); + break; + } + case P4_ADVANCE: { + zTemp[0] = 0; + break; + } + default: { + zP4 = pOp->p4.z; + if( zP4==0 ){ + zP4 = zTemp; + zTemp[0] = 0; + } + } + } + assert( zP4!=0 ); + return zP4; +} +#endif + +/* +** Declare to the Vdbe that the BTree object at db->aDb[i] is used. +** +** The prepared statements need to know in advance the complete set of +** attached databases that will be use. A mask of these databases +** is maintained in p->btreeMask. The p->lockMask value is the subset of +** p->btreeMask of databases that will require a lock. +*/ +SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){ + assert( i>=0 && idb->nDb && i<(int)sizeof(yDbMask)*8 ); + assert( i<(int)sizeof(p->btreeMask)*8 ); + DbMaskSet(p->btreeMask, i); + if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){ + DbMaskSet(p->lockMask, i); + } +} + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0 +/* +** If SQLite is compiled to support shared-cache mode and to be threadsafe, +** this routine obtains the mutex associated with each BtShared structure +** that may be accessed by the VM passed as an argument. In doing so it also +** sets the BtShared.db member of each of the BtShared structures, ensuring +** that the correct busy-handler callback is invoked if required. +** +** If SQLite is not threadsafe but does support shared-cache mode, then +** sqlite3BtreeEnter() is invoked to set the BtShared.db variables +** of all of BtShared structures accessible via the database handle +** associated with the VM. +** +** If SQLite is not threadsafe and does not support shared-cache mode, this +** function is a no-op. +** +** The p->btreeMask field is a bitmask of all btrees that the prepared +** statement p will ever use. Let N be the number of bits in p->btreeMask +** corresponding to btrees that use shared cache. Then the runtime of +** this routine is N*N. But as N is rarely more than 1, this should not +** be a problem. +*/ +SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe *p){ + int i; + sqlite3 *db; + Db *aDb; + int nDb; + if( DbMaskAllZero(p->lockMask) ) return; /* The common case */ + db = p->db; + aDb = db->aDb; + nDb = db->nDb; + for(i=0; ilockMask,i) && ALWAYS(aDb[i].pBt!=0) ){ + sqlite3BtreeEnter(aDb[i].pBt); + } + } +} +#endif + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0 +/* +** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter(). +*/ +static SQLITE_NOINLINE void vdbeLeave(Vdbe *p){ + int i; + sqlite3 *db; + Db *aDb; + int nDb; + db = p->db; + aDb = db->aDb; + nDb = db->nDb; + for(i=0; ilockMask,i) && ALWAYS(aDb[i].pBt!=0) ){ + sqlite3BtreeLeave(aDb[i].pBt); + } + } +} +SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){ + if( DbMaskAllZero(p->lockMask) ) return; /* The common case */ + vdbeLeave(p); +} +#endif + +#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) +/* +** Print a single opcode. This routine is used for debugging only. +*/ +SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ + char *zP4; + char zPtr[50]; + char zCom[100]; + static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n"; + if( pOut==0 ) pOut = stdout; + zP4 = displayP4(pOp, zPtr, sizeof(zPtr)); +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS + displayComment(pOp, zP4, zCom, sizeof(zCom)); +#else + zCom[0] = 0; +#endif + /* NB: The sqlite3OpcodeName() function is implemented by code created + ** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the + ** information from the vdbe.c source text */ + fprintf(pOut, zFormat1, pc, + sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5, + zCom + ); + fflush(pOut); +} +#endif + +/* +** Release an array of N Mem elements +*/ +static void releaseMemArray(Mem *p, int N){ + if( p && N ){ + Mem *pEnd = &p[N]; + sqlite3 *db = p->db; + u8 malloc_failed = db->mallocFailed; + if( db->pnBytesFreed ){ + do{ + if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); + }while( (++p)flags & MEM_Agg ); + testcase( p->flags & MEM_Dyn ); + testcase( p->flags & MEM_Frame ); + testcase( p->flags & MEM_RowSet ); + if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ + sqlite3VdbeMemRelease(p); + }else if( p->szMalloc ){ + sqlite3DbFree(db, p->zMalloc); + p->szMalloc = 0; + } + + p->flags = MEM_Undefined; + }while( (++p)mallocFailed = malloc_failed; + } +} + +/* +** Delete a VdbeFrame object and its contents. VdbeFrame objects are +** allocated by the OP_Program opcode in sqlite3VdbeExec(). +*/ +SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame *p){ + int i; + Mem *aMem = VdbeFrameMem(p); + VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem]; + for(i=0; inChildCsr; i++){ + sqlite3VdbeFreeCursor(p->v, apCsr[i]); + } + releaseMemArray(aMem, p->nChildMem); + sqlite3DbFree(p->v->db, p); +} + +#ifndef SQLITE_OMIT_EXPLAIN +/* +** Give a listing of the program in the virtual machine. +** +** The interface is the same as sqlite3VdbeExec(). But instead of +** running the code, it invokes the callback once for each instruction. +** This feature is used to implement "EXPLAIN". +** +** When p->explain==1, each instruction is listed. When +** p->explain==2, only OP_Explain instructions are listed and these +** are shown in a different format. p->explain==2 is used to implement +** EXPLAIN QUERY PLAN. +** +** When p->explain==1, first the main program is listed, then each of +** the trigger subprograms are listed one by one. +*/ +SQLITE_PRIVATE int sqlite3VdbeList( + Vdbe *p /* The VDBE */ +){ + int nRow; /* Stop when row count reaches this */ + int nSub = 0; /* Number of sub-vdbes seen so far */ + SubProgram **apSub = 0; /* Array of sub-vdbes */ + Mem *pSub = 0; /* Memory cell hold array of subprogs */ + sqlite3 *db = p->db; /* The database connection */ + int i; /* Loop counter */ + int rc = SQLITE_OK; /* Return code */ + Mem *pMem = &p->aMem[1]; /* First Mem of result set */ + + assert( p->explain ); + assert( p->magic==VDBE_MAGIC_RUN ); + assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM ); + + /* Even though this opcode does not use dynamic strings for + ** the result, result columns may become dynamic if the user calls + ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. + */ + releaseMemArray(pMem, 8); + p->pResultSet = 0; + + if( p->rc==SQLITE_NOMEM ){ + /* This happens if a malloc() inside a call to sqlite3_column_text() or + ** sqlite3_column_text16() failed. */ + db->mallocFailed = 1; + return SQLITE_ERROR; + } + + /* When the number of output rows reaches nRow, that means the + ** listing has finished and sqlite3_step() should return SQLITE_DONE. + ** nRow is the sum of the number of rows in the main program, plus + ** the sum of the number of rows in all trigger subprograms encountered + ** so far. The nRow value will increase as new trigger subprograms are + ** encountered, but p->pc will eventually catch up to nRow. + */ + nRow = p->nOp; + if( p->explain==1 ){ + /* The first 8 memory cells are used for the result set. So we will + ** commandeer the 9th cell to use as storage for an array of pointers + ** to trigger subprograms. The VDBE is guaranteed to have at least 9 + ** cells. */ + assert( p->nMem>9 ); + pSub = &p->aMem[9]; + if( pSub->flags&MEM_Blob ){ + /* On the first call to sqlite3_step(), pSub will hold a NULL. It is + ** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */ + nSub = pSub->n/sizeof(Vdbe*); + apSub = (SubProgram **)pSub->z; + } + for(i=0; inOp; + } + } + + do{ + i = p->pc++; + }while( iexplain==2 && p->aOp[i].opcode!=OP_Explain ); + if( i>=nRow ){ + p->rc = SQLITE_OK; + rc = SQLITE_DONE; + }else if( db->u1.isInterrupted ){ + p->rc = SQLITE_INTERRUPT; + rc = SQLITE_ERROR; + sqlite3VdbeError(p, sqlite3ErrStr(p->rc)); + }else{ + char *zP4; + Op *pOp; + if( inOp ){ + /* The output line number is small enough that we are still in the + ** main program. */ + pOp = &p->aOp[i]; + }else{ + /* We are currently listing subprograms. Figure out which one and + ** pick up the appropriate opcode. */ + int j; + i -= p->nOp; + for(j=0; i>=apSub[j]->nOp; j++){ + i -= apSub[j]->nOp; + } + pOp = &apSub[j]->aOp[i]; + } + if( p->explain==1 ){ + pMem->flags = MEM_Int; + pMem->u.i = i; /* Program counter */ + pMem++; + + pMem->flags = MEM_Static|MEM_Str|MEM_Term; + pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */ + assert( pMem->z!=0 ); + pMem->n = sqlite3Strlen30(pMem->z); + pMem->enc = SQLITE_UTF8; + pMem++; + + /* When an OP_Program opcode is encounter (the only opcode that has + ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms + ** kept in p->aMem[9].z to hold the new program - assuming this subprogram + ** has not already been seen. + */ + if( pOp->p4type==P4_SUBPROGRAM ){ + int nByte = (nSub+1)*sizeof(SubProgram*); + int j; + for(j=0; jp4.pProgram ) break; + } + if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, nSub!=0) ){ + apSub = (SubProgram **)pSub->z; + apSub[nSub++] = pOp->p4.pProgram; + pSub->flags |= MEM_Blob; + pSub->n = nSub*sizeof(SubProgram*); + } + } + } + + pMem->flags = MEM_Int; + pMem->u.i = pOp->p1; /* P1 */ + pMem++; + + pMem->flags = MEM_Int; + pMem->u.i = pOp->p2; /* P2 */ + pMem++; + + pMem->flags = MEM_Int; + pMem->u.i = pOp->p3; /* P3 */ + pMem++; + + if( sqlite3VdbeMemClearAndResize(pMem, 32) ){ /* P4 */ + assert( p->db->mallocFailed ); + return SQLITE_ERROR; + } + pMem->flags = MEM_Str|MEM_Term; + zP4 = displayP4(pOp, pMem->z, 32); + if( zP4!=pMem->z ){ + sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); + }else{ + assert( pMem->z!=0 ); + pMem->n = sqlite3Strlen30(pMem->z); + pMem->enc = SQLITE_UTF8; + } + pMem++; + + if( p->explain==1 ){ + if( sqlite3VdbeMemClearAndResize(pMem, 4) ){ + assert( p->db->mallocFailed ); + return SQLITE_ERROR; + } + pMem->flags = MEM_Str|MEM_Term; + pMem->n = 2; + sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */ + pMem->enc = SQLITE_UTF8; + pMem++; + +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS + if( sqlite3VdbeMemClearAndResize(pMem, 500) ){ + assert( p->db->mallocFailed ); + return SQLITE_ERROR; + } + pMem->flags = MEM_Str|MEM_Term; + pMem->n = displayComment(pOp, zP4, pMem->z, 500); + pMem->enc = SQLITE_UTF8; +#else + pMem->flags = MEM_Null; /* Comment */ +#endif + } + + p->nResColumn = 8 - 4*(p->explain-1); + p->pResultSet = &p->aMem[1]; + p->rc = SQLITE_OK; + rc = SQLITE_ROW; + } + return rc; +} +#endif /* SQLITE_OMIT_EXPLAIN */ + +#ifdef SQLITE_DEBUG +/* +** Print the SQL that was used to generate a VDBE program. +*/ +SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe *p){ + const char *z = 0; + if( p->zSql ){ + z = p->zSql; + }else if( p->nOp>=1 ){ + const VdbeOp *pOp = &p->aOp[0]; + if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){ + z = pOp->p4.z; + while( sqlite3Isspace(*z) ) z++; + } + } + if( z ) printf("SQL: [%s]\n", z); +} +#endif + +#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) +/* +** Print an IOTRACE message showing SQL content. +*/ +SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){ + int nOp = p->nOp; + VdbeOp *pOp; + if( sqlite3IoTrace==0 ) return; + if( nOp<1 ) return; + pOp = &p->aOp[0]; + if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){ + int i, j; + char z[1000]; + sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.z); + for(i=0; sqlite3Isspace(z[i]); i++){} + for(j=0; z[i]; i++){ + if( sqlite3Isspace(z[i]) ){ + if( z[i-1]!=' ' ){ + z[j++] = ' '; + } + }else{ + z[j++] = z[i]; + } + } + z[j] = 0; + sqlite3IoTrace("SQL %s\n", z); + } +} +#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */ + +/* +** Allocate space from a fixed size buffer and return a pointer to +** that space. If insufficient space is available, return NULL. +** +** The pBuf parameter is the initial value of a pointer which will +** receive the new memory. pBuf is normally NULL. If pBuf is not +** NULL, it means that memory space has already been allocated and that +** this routine should not allocate any new memory. When pBuf is not +** NULL simply return pBuf. Only allocate new memory space when pBuf +** is NULL. +** +** nByte is the number of bytes of space needed. +** +** *ppFrom points to available space and pEnd points to the end of the +** available space. When space is allocated, *ppFrom is advanced past +** the end of the allocated space. +** +** *pnByte is a counter of the number of bytes of space that have failed +** to allocate. If there is insufficient space in *ppFrom to satisfy the +** request, then increment *pnByte by the amount of the request. +*/ +static void *allocSpace( + void *pBuf, /* Where return pointer will be stored */ + int nByte, /* Number of bytes to allocate */ + u8 **ppFrom, /* IN/OUT: Allocate from *ppFrom */ + u8 *pEnd, /* Pointer to 1 byte past the end of *ppFrom buffer */ + int *pnByte /* If allocation cannot be made, increment *pnByte */ +){ + assert( EIGHT_BYTE_ALIGNMENT(*ppFrom) ); + if( pBuf ) return pBuf; + nByte = ROUND8(nByte); + if( &(*ppFrom)[nByte] <= pEnd ){ + pBuf = (void*)*ppFrom; + *ppFrom += nByte; + }else{ + *pnByte += nByte; + } + return pBuf; +} + +/* +** Rewind the VDBE back to the beginning in preparation for +** running it. +*/ +SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){ +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) + int i; +#endif + assert( p!=0 ); + assert( p->magic==VDBE_MAGIC_INIT ); + + /* There should be at least one opcode. + */ + assert( p->nOp>0 ); + + /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */ + p->magic = VDBE_MAGIC_RUN; + +#ifdef SQLITE_DEBUG + for(i=1; inMem; i++){ + assert( p->aMem[i].db==p->db ); + } +#endif + p->pc = -1; + p->rc = SQLITE_OK; + p->errorAction = OE_Abort; + p->magic = VDBE_MAGIC_RUN; + p->nChange = 0; + p->cacheCtr = 1; + p->minWriteFileFormat = 255; + p->iStatement = 0; + p->nFkConstraint = 0; +#ifdef VDBE_PROFILE + for(i=0; inOp; i++){ + p->aOp[i].cnt = 0; + p->aOp[i].cycles = 0; + } +#endif +} + +/* +** Prepare a virtual machine for execution for the first time after +** creating the virtual machine. This involves things such +** as allocating registers and initializing the program counter. +** After the VDBE has be prepped, it can be executed by one or more +** calls to sqlite3VdbeExec(). +** +** This function may be called exactly once on each virtual machine. +** After this routine is called the VM has been "packaged" and is ready +** to run. After this routine is called, further calls to +** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects +** the Vdbe from the Parse object that helped generate it so that the +** the Vdbe becomes an independent entity and the Parse object can be +** destroyed. +** +** Use the sqlite3VdbeRewind() procedure to restore a virtual machine back +** to its initial state after it has been run. +*/ +SQLITE_PRIVATE void sqlite3VdbeMakeReady( + Vdbe *p, /* The VDBE */ + Parse *pParse /* Parsing context */ +){ + sqlite3 *db; /* The database connection */ + int nVar; /* Number of parameters */ + int nMem; /* Number of VM memory registers */ + int nCursor; /* Number of cursors required */ + int nArg; /* Number of arguments in subprograms */ + int nOnce; /* Number of OP_Once instructions */ + int n; /* Loop counter */ + u8 *zCsr; /* Memory available for allocation */ + u8 *zEnd; /* First byte past allocated memory */ + int nByte; /* How much extra memory is needed */ + + assert( p!=0 ); + assert( p->nOp>0 ); + assert( pParse!=0 ); + assert( p->magic==VDBE_MAGIC_INIT ); + assert( pParse==p->pParse ); + db = p->db; + assert( db->mallocFailed==0 ); + nVar = pParse->nVar; + nMem = pParse->nMem; + nCursor = pParse->nTab; + nArg = pParse->nMaxArg; + nOnce = pParse->nOnce; + if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */ + + /* For each cursor required, also allocate a memory cell. Memory + ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by + ** the vdbe program. Instead they are used to allocate space for + ** VdbeCursor/BtCursor structures. The blob of memory associated with + ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1) + ** stores the blob of memory associated with cursor 1, etc. + ** + ** See also: allocateCursor(). + */ + nMem += nCursor; + + /* Allocate space for memory registers, SQL variables, VDBE cursors and + ** an array to marshal SQL function arguments in. + */ + zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */ + zEnd = (u8*)&p->aOp[pParse->nOpAlloc]; /* First byte past end of zCsr[] */ + + resolveP2Values(p, &nArg); + p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); + if( pParse->explain && nMem<10 ){ + nMem = 10; + } + memset(zCsr, 0, zEnd-zCsr); + zCsr += (zCsr - (u8*)0)&7; + assert( EIGHT_BYTE_ALIGNMENT(zCsr) ); + p->expired = 0; + + /* Memory for registers, parameters, cursor, etc, is allocated in two + ** passes. On the first pass, we try to reuse unused space at the + ** end of the opcode array. If we are unable to satisfy all memory + ** requirements by reusing the opcode array tail, then the second + ** pass will fill in the rest using a fresh allocation. + ** + ** This two-pass approach that reuses as much memory as possible from + ** the leftover space at the end of the opcode array can significantly + ** reduce the amount of memory held by a prepared statement. + */ + do { + nByte = 0; + p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte); + p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte); + p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte); + p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte); + p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*), + &zCsr, zEnd, &nByte); + p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte); +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), &zCsr, zEnd, &nByte); +#endif + if( nByte ){ + p->pFree = sqlite3DbMallocZero(db, nByte); + } + zCsr = p->pFree; + zEnd = &zCsr[nByte]; + }while( nByte && !db->mallocFailed ); + + p->nCursor = nCursor; + p->nOnceFlag = nOnce; + if( p->aVar ){ + p->nVar = (ynVar)nVar; + for(n=0; naVar[n].flags = MEM_Null; + p->aVar[n].db = db; + } + } + if( p->azVar && pParse->nzVar>0 ){ + p->nzVar = pParse->nzVar; + memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0])); + memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0])); + } + if( p->aMem ){ + p->aMem--; /* aMem[] goes from 1..nMem */ + p->nMem = nMem; /* not from 0..nMem-1 */ + for(n=1; n<=nMem; n++){ + p->aMem[n].flags = MEM_Undefined; + p->aMem[n].db = db; + } + } + p->explain = pParse->explain; + sqlite3VdbeRewind(p); +} + +/* +** Close a VDBE cursor and release all the resources that cursor +** happens to hold. +*/ +SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ + if( pCx==0 ){ + return; + } + sqlite3VdbeSorterClose(p->db, pCx); + if( pCx->pBt ){ + sqlite3BtreeClose(pCx->pBt); + /* The pCx->pCursor will be close automatically, if it exists, by + ** the call above. */ + }else if( pCx->pCursor ){ + sqlite3BtreeCloseCursor(pCx->pCursor); + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + else if( pCx->pVtabCursor ){ + sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor; + const sqlite3_module *pModule = pVtabCursor->pVtab->pModule; + assert( pVtabCursor->pVtab->nRef>0 ); + pVtabCursor->pVtab->nRef--; + pModule->xClose(pVtabCursor); + } +#endif +} + +/* +** Close all cursors in the current frame. +*/ +static void closeCursorsInFrame(Vdbe *p){ + if( p->apCsr ){ + int i; + for(i=0; inCursor; i++){ + VdbeCursor *pC = p->apCsr[i]; + if( pC ){ + sqlite3VdbeFreeCursor(p, pC); + p->apCsr[i] = 0; + } + } + } +} + +/* +** Copy the values stored in the VdbeFrame structure to its Vdbe. This +** is used, for example, when a trigger sub-program is halted to restore +** control to the main program. +*/ +SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ + Vdbe *v = pFrame->v; + closeCursorsInFrame(v); +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + v->anExec = pFrame->anExec; +#endif + v->aOnceFlag = pFrame->aOnceFlag; + v->nOnceFlag = pFrame->nOnceFlag; + v->aOp = pFrame->aOp; + v->nOp = pFrame->nOp; + v->aMem = pFrame->aMem; + v->nMem = pFrame->nMem; + v->apCsr = pFrame->apCsr; + v->nCursor = pFrame->nCursor; + v->db->lastRowid = pFrame->lastRowid; + v->nChange = pFrame->nChange; + v->db->nChange = pFrame->nDbChange; + return pFrame->pc; +} + +/* +** Close all cursors. +** +** Also release any dynamic memory held by the VM in the Vdbe.aMem memory +** cell array. This is necessary as the memory cell array may contain +** pointers to VdbeFrame objects, which may in turn contain pointers to +** open cursors. +*/ +static void closeAllCursors(Vdbe *p){ + if( p->pFrame ){ + VdbeFrame *pFrame; + for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); + sqlite3VdbeFrameRestore(pFrame); + p->pFrame = 0; + p->nFrame = 0; + } + assert( p->nFrame==0 ); + closeCursorsInFrame(p); + if( p->aMem ){ + releaseMemArray(&p->aMem[1], p->nMem); + } + while( p->pDelFrame ){ + VdbeFrame *pDel = p->pDelFrame; + p->pDelFrame = pDel->pParent; + sqlite3VdbeFrameDelete(pDel); + } + + /* Delete any auxdata allocations made by the VM */ + if( p->pAuxData ) sqlite3VdbeDeleteAuxData(p, -1, 0); + assert( p->pAuxData==0 ); +} + +/* +** Clean up the VM after a single run. +*/ +static void Cleanup(Vdbe *p){ + sqlite3 *db = p->db; + +#ifdef SQLITE_DEBUG + /* Execute assert() statements to ensure that the Vdbe.apCsr[] and + ** Vdbe.aMem[] arrays have already been cleaned up. */ + int i; + if( p->apCsr ) for(i=0; inCursor; i++) assert( p->apCsr[i]==0 ); + if( p->aMem ){ + for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined ); + } +#endif + + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = 0; + p->pResultSet = 0; +} + +/* +** Set the number of result columns that will be returned by this SQL +** statement. This is now set at compile time, rather than during +** execution of the vdbe program so that sqlite3_column_count() can +** be called on an SQL statement before sqlite3_step(). +*/ +SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ + Mem *pColName; + int n; + sqlite3 *db = p->db; + + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + sqlite3DbFree(db, p->aColName); + n = nResColumn*COLNAME_N; + p->nResColumn = (u16)nResColumn; + p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n ); + if( p->aColName==0 ) return; + while( n-- > 0 ){ + pColName->flags = MEM_Null; + pColName->db = p->db; + pColName++; + } +} + +/* +** Set the name of the idx'th column to be returned by the SQL statement. +** zName must be a pointer to a nul terminated string. +** +** This call must be made after a call to sqlite3VdbeSetNumCols(). +** +** The final parameter, xDel, must be one of SQLITE_DYNAMIC, SQLITE_STATIC +** or SQLITE_TRANSIENT. If it is SQLITE_DYNAMIC, then the buffer pointed +** to by zName will be freed by sqlite3DbFree() when the vdbe is destroyed. +*/ +SQLITE_PRIVATE int sqlite3VdbeSetColName( + Vdbe *p, /* Vdbe being configured */ + int idx, /* Index of column zName applies to */ + int var, /* One of the COLNAME_* constants */ + const char *zName, /* Pointer to buffer containing name */ + void (*xDel)(void*) /* Memory management strategy for zName */ +){ + int rc; + Mem *pColName; + assert( idxnResColumn ); + assert( vardb->mallocFailed ){ + assert( !zName || xDel!=SQLITE_DYNAMIC ); + return SQLITE_NOMEM; + } + assert( p->aColName!=0 ); + pColName = &(p->aColName[idx+var*p->nResColumn]); + rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel); + assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 ); + return rc; +} + +/* +** A read or write transaction may or may not be active on database handle +** db. If a transaction is active, commit it. If there is a +** write-transaction spanning more than one database file, this routine +** takes care of the master journal trickery. +*/ +static int vdbeCommit(sqlite3 *db, Vdbe *p){ + int i; + int nTrans = 0; /* Number of databases with an active write-transaction */ + int rc = SQLITE_OK; + int needXcommit = 0; + +#ifdef SQLITE_OMIT_VIRTUALTABLE + /* With this option, sqlite3VtabSync() is defined to be simply + ** SQLITE_OK so p is not used. + */ + UNUSED_PARAMETER(p); +#endif + + /* Before doing anything else, call the xSync() callback for any + ** virtual module tables written in this transaction. This has to + ** be done before determining whether a master journal file is + ** required, as an xSync() callback may add an attached database + ** to the transaction. + */ + rc = sqlite3VtabSync(db, p); + + /* This loop determines (a) if the commit hook should be invoked and + ** (b) how many database files have open write transactions, not + ** including the temp database. (b) is important because if more than + ** one database file has an open write transaction, a master journal + ** file is required for an atomic commit. + */ + for(i=0; rc==SQLITE_OK && inDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( sqlite3BtreeIsInTrans(pBt) ){ + needXcommit = 1; + if( i!=1 ) nTrans++; + sqlite3BtreeEnter(pBt); + rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt)); + sqlite3BtreeLeave(pBt); + } + } + if( rc!=SQLITE_OK ){ + return rc; + } + + /* If there are any write-transactions at all, invoke the commit hook */ + if( needXcommit && db->xCommitCallback ){ + rc = db->xCommitCallback(db->pCommitArg); + if( rc ){ + return SQLITE_CONSTRAINT_COMMITHOOK; + } + } + + /* The simple case - no more than one database file (not counting the + ** TEMP database) has a transaction active. There is no need for the + ** master-journal. + ** + ** If the return value of sqlite3BtreeGetFilename() is a zero length + ** string, it means the main database is :memory: or a temp file. In + ** that case we do not support atomic multi-file commits, so use the + ** simple case then too. + */ + if( 0==sqlite3Strlen30(sqlite3BtreeGetFilename(db->aDb[0].pBt)) + || nTrans<=1 + ){ + for(i=0; rc==SQLITE_OK && inDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + rc = sqlite3BtreeCommitPhaseOne(pBt, 0); + } + } + + /* Do the commit only if all databases successfully complete phase 1. + ** If one of the BtreeCommitPhaseOne() calls fails, this indicates an + ** IO error while deleting or truncating a journal file. It is unlikely, + ** but could happen. In this case abandon processing and return the error. + */ + for(i=0; rc==SQLITE_OK && inDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + rc = sqlite3BtreeCommitPhaseTwo(pBt, 0); + } + } + if( rc==SQLITE_OK ){ + sqlite3VtabCommit(db); + } + } + + /* The complex case - There is a multi-file write-transaction active. + ** This requires a master journal file to ensure the transaction is + ** committed atomically. + */ +#ifndef SQLITE_OMIT_DISKIO + else{ + sqlite3_vfs *pVfs = db->pVfs; + int needSync = 0; + char *zMaster = 0; /* File-name for the master journal */ + char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt); + sqlite3_file *pMaster = 0; + i64 offset = 0; + int res; + int retryCount = 0; + int nMainFile; + + /* Select a master journal file name */ + nMainFile = sqlite3Strlen30(zMainFile); + zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz", zMainFile); + if( zMaster==0 ) return SQLITE_NOMEM; + do { + u32 iRandom; + if( retryCount ){ + if( retryCount>100 ){ + sqlite3_log(SQLITE_FULL, "MJ delete: %s", zMaster); + sqlite3OsDelete(pVfs, zMaster, 0); + break; + }else if( retryCount==1 ){ + sqlite3_log(SQLITE_FULL, "MJ collide: %s", zMaster); + } + } + retryCount++; + sqlite3_randomness(sizeof(iRandom), &iRandom); + sqlite3_snprintf(13, &zMaster[nMainFile], "-mj%06X9%02X", + (iRandom>>8)&0xffffff, iRandom&0xff); + /* The antipenultimate character of the master journal name must + ** be "9" to avoid name collisions when using 8+3 filenames. */ + assert( zMaster[sqlite3Strlen30(zMaster)-3]=='9' ); + sqlite3FileSuffix3(zMainFile, zMaster); + rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res); + }while( rc==SQLITE_OK && res ); + if( rc==SQLITE_OK ){ + /* Open the master journal. */ + rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster, + SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| + SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0 + ); + } + if( rc!=SQLITE_OK ){ + sqlite3DbFree(db, zMaster); + return rc; + } + + /* Write the name of each database file in the transaction into the new + ** master journal file. If an error occurs at this point close + ** and delete the master journal file. All the individual journal files + ** still have 'null' as the master journal pointer, so they will roll + ** back independently if a failure occurs. + */ + for(i=0; inDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( sqlite3BtreeIsInTrans(pBt) ){ + char const *zFile = sqlite3BtreeGetJournalname(pBt); + if( zFile==0 ){ + continue; /* Ignore TEMP and :memory: databases */ + } + assert( zFile[0]!=0 ); + if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){ + needSync = 1; + } + rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset); + offset += sqlite3Strlen30(zFile)+1; + if( rc!=SQLITE_OK ){ + sqlite3OsCloseFree(pMaster); + sqlite3OsDelete(pVfs, zMaster, 0); + sqlite3DbFree(db, zMaster); + return rc; + } + } + } + + /* Sync the master journal file. If the IOCAP_SEQUENTIAL device + ** flag is set this is not required. + */ + if( needSync + && 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL) + && SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL)) + ){ + sqlite3OsCloseFree(pMaster); + sqlite3OsDelete(pVfs, zMaster, 0); + sqlite3DbFree(db, zMaster); + return rc; + } + + /* Sync all the db files involved in the transaction. The same call + ** sets the master journal pointer in each individual journal. If + ** an error occurs here, do not delete the master journal file. + ** + ** If the error occurs during the first call to + ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the + ** master journal file will be orphaned. But we cannot delete it, + ** in case the master journal file name was written into the journal + ** file before the failure occurred. + */ + for(i=0; rc==SQLITE_OK && inDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster); + } + } + sqlite3OsCloseFree(pMaster); + assert( rc!=SQLITE_BUSY ); + if( rc!=SQLITE_OK ){ + sqlite3DbFree(db, zMaster); + return rc; + } + + /* Delete the master journal file. This commits the transaction. After + ** doing this the directory is synced again before any individual + ** transaction files are deleted. + */ + rc = sqlite3OsDelete(pVfs, zMaster, needSync); + sqlite3DbFree(db, zMaster); + zMaster = 0; + if( rc ){ + return rc; + } + + /* All files and directories have already been synced, so the following + ** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and + ** deleting or truncating journals. If something goes wrong while + ** this is happening we don't really care. The integrity of the + ** transaction is already guaranteed, but some stray 'cold' journals + ** may be lying around. Returning an error code won't help matters. + */ + disable_simulated_io_errors(); + sqlite3BeginBenignMalloc(); + for(i=0; inDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + sqlite3BtreeCommitPhaseTwo(pBt, 1); + } + } + sqlite3EndBenignMalloc(); + enable_simulated_io_errors(); + + sqlite3VtabCommit(db); + } +#endif + + return rc; +} + +/* +** This routine checks that the sqlite3.nVdbeActive count variable +** matches the number of vdbe's in the list sqlite3.pVdbe that are +** currently active. An assertion fails if the two counts do not match. +** This is an internal self-check only - it is not an essential processing +** step. +** +** This is a no-op if NDEBUG is defined. +*/ +#ifndef NDEBUG +static void checkActiveVdbeCnt(sqlite3 *db){ + Vdbe *p; + int cnt = 0; + int nWrite = 0; + int nRead = 0; + p = db->pVdbe; + while( p ){ + if( sqlite3_stmt_busy((sqlite3_stmt*)p) ){ + cnt++; + if( p->readOnly==0 ) nWrite++; + if( p->bIsReader ) nRead++; + } + p = p->pNext; + } + assert( cnt==db->nVdbeActive ); + assert( nWrite==db->nVdbeWrite ); + assert( nRead==db->nVdbeRead ); +} +#else +#define checkActiveVdbeCnt(x) +#endif + +/* +** If the Vdbe passed as the first argument opened a statement-transaction, +** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or +** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement +** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the +** statement transaction is committed. +** +** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned. +** Otherwise SQLITE_OK. +*/ +SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ + sqlite3 *const db = p->db; + int rc = SQLITE_OK; + + /* If p->iStatement is greater than zero, then this Vdbe opened a + ** statement transaction that should be closed here. The only exception + ** is that an IO error may have occurred, causing an emergency rollback. + ** In this case (db->nStatement==0), and there is nothing to do. + */ + if( db->nStatement && p->iStatement ){ + int i; + const int iSavepoint = p->iStatement-1; + + assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE); + assert( db->nStatement>0 ); + assert( p->iStatement==(db->nStatement+db->nSavepoint) ); + + for(i=0; inDb; i++){ + int rc2 = SQLITE_OK; + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + if( eOp==SAVEPOINT_ROLLBACK ){ + rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint); + } + if( rc2==SQLITE_OK ){ + rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint); + } + if( rc==SQLITE_OK ){ + rc = rc2; + } + } + } + db->nStatement--; + p->iStatement = 0; + + if( rc==SQLITE_OK ){ + if( eOp==SAVEPOINT_ROLLBACK ){ + rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint); + } + if( rc==SQLITE_OK ){ + rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint); + } + } + + /* If the statement transaction is being rolled back, also restore the + ** database handles deferred constraint counter to the value it had when + ** the statement transaction was opened. */ + if( eOp==SAVEPOINT_ROLLBACK ){ + db->nDeferredCons = p->nStmtDefCons; + db->nDeferredImmCons = p->nStmtDefImmCons; + } + } + return rc; +} + +/* +** This function is called when a transaction opened by the database +** handle associated with the VM passed as an argument is about to be +** committed. If there are outstanding deferred foreign key constraint +** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK. +** +** If there are outstanding FK violations and this function returns +** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY +** and write an error message to it. Then return SQLITE_ERROR. +*/ +#ifndef SQLITE_OMIT_FOREIGN_KEY +SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ + sqlite3 *db = p->db; + if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0) + || (!deferred && p->nFkConstraint>0) + ){ + p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; + p->errorAction = OE_Abort; + sqlite3VdbeError(p, "FOREIGN KEY constraint failed"); + return SQLITE_ERROR; + } + return SQLITE_OK; +} +#endif + +/* +** This routine is called the when a VDBE tries to halt. If the VDBE +** has made changes and is in autocommit mode, then commit those +** changes. If a rollback is needed, then do the rollback. +** +** This routine is the only way to move the state of a VM from +** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. It is harmless to +** call this on a VM that is in the SQLITE_MAGIC_HALT state. +** +** Return an error code. If the commit could not complete because of +** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it +** means the close did not happen and needs to be repeated. +*/ +SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ + int rc; /* Used to store transient return codes */ + sqlite3 *db = p->db; + + /* This function contains the logic that determines if a statement or + ** transaction will be committed or rolled back as a result of the + ** execution of this virtual machine. + ** + ** If any of the following errors occur: + ** + ** SQLITE_NOMEM + ** SQLITE_IOERR + ** SQLITE_FULL + ** SQLITE_INTERRUPT + ** + ** Then the internal cache might have been left in an inconsistent + ** state. We need to rollback the statement transaction, if there is + ** one, or the complete transaction if there is no statement transaction. + */ + + if( p->db->mallocFailed ){ + p->rc = SQLITE_NOMEM; + } + if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag); + closeAllCursors(p); + if( p->magic!=VDBE_MAGIC_RUN ){ + return SQLITE_OK; + } + checkActiveVdbeCnt(db); + + /* No commit or rollback needed if the program never started or if the + ** SQL statement does not read or write a database file. */ + if( p->pc>=0 && p->bIsReader ){ + int mrc; /* Primary error code from p->rc */ + int eStatementOp = 0; + int isSpecialError; /* Set to true if a 'special' error */ + + /* Lock all btrees used by the statement */ + sqlite3VdbeEnter(p); + + /* Check for one of the special errors */ + mrc = p->rc & 0xff; + isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR + || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL; + if( isSpecialError ){ + /* If the query was read-only and the error code is SQLITE_INTERRUPT, + ** no rollback is necessary. Otherwise, at least a savepoint + ** transaction must be rolled back to restore the database to a + ** consistent state. + ** + ** Even if the statement is read-only, it is important to perform + ** a statement or transaction rollback operation. If the error + ** occurred while writing to the journal, sub-journal or database + ** file as part of an effort to free up cache space (see function + ** pagerStress() in pager.c), the rollback is required to restore + ** the pager to a consistent state. + */ + if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){ + if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && p->usesStmtJournal ){ + eStatementOp = SAVEPOINT_ROLLBACK; + }else{ + /* We are forced to roll back the active transaction. Before doing + ** so, abort any other statements this handle currently has active. + */ + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); + sqlite3CloseSavepoints(db); + db->autoCommit = 1; + p->nChange = 0; + } + } + } + + /* Check for immediate foreign key violations. */ + if( p->rc==SQLITE_OK ){ + sqlite3VdbeCheckFk(p, 0); + } + + /* If the auto-commit flag is set and this is the only active writer + ** VM, then we do either a commit or rollback of the current transaction. + ** + ** Note: This block also runs if one of the special errors handled + ** above has occurred. + */ + if( !sqlite3VtabInSync(db) + && db->autoCommit + && db->nVdbeWrite==(p->readOnly==0) + ){ + if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ + rc = sqlite3VdbeCheckFk(p, 1); + if( rc!=SQLITE_OK ){ + if( NEVER(p->readOnly) ){ + sqlite3VdbeLeave(p); + return SQLITE_ERROR; + } + rc = SQLITE_CONSTRAINT_FOREIGNKEY; + }else{ + /* The auto-commit flag is true, the vdbe program was successful + ** or hit an 'OR FAIL' constraint and there are no deferred foreign + ** key constraints to hold up the transaction. This means a commit + ** is required. */ + rc = vdbeCommit(db, p); + } + if( rc==SQLITE_BUSY && p->readOnly ){ + sqlite3VdbeLeave(p); + return SQLITE_BUSY; + }else if( rc!=SQLITE_OK ){ + p->rc = rc; + sqlite3RollbackAll(db, SQLITE_OK); + p->nChange = 0; + }else{ + db->nDeferredCons = 0; + db->nDeferredImmCons = 0; + db->flags &= ~SQLITE_DeferFKs; + sqlite3CommitInternalChanges(db); + } + }else{ + sqlite3RollbackAll(db, SQLITE_OK); + p->nChange = 0; + } + db->nStatement = 0; + }else if( eStatementOp==0 ){ + if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ + eStatementOp = SAVEPOINT_RELEASE; + }else if( p->errorAction==OE_Abort ){ + eStatementOp = SAVEPOINT_ROLLBACK; + }else{ + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); + sqlite3CloseSavepoints(db); + db->autoCommit = 1; + p->nChange = 0; + } + } + + /* If eStatementOp is non-zero, then a statement transaction needs to + ** be committed or rolled back. Call sqlite3VdbeCloseStatement() to + ** do so. If this operation returns an error, and the current statement + ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the + ** current statement error code. + */ + if( eStatementOp ){ + rc = sqlite3VdbeCloseStatement(p, eStatementOp); + if( rc ){ + if( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ){ + p->rc = rc; + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = 0; + } + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); + sqlite3CloseSavepoints(db); + db->autoCommit = 1; + p->nChange = 0; + } + } + + /* If this was an INSERT, UPDATE or DELETE and no statement transaction + ** has been rolled back, update the database connection change-counter. + */ + if( p->changeCntOn ){ + if( eStatementOp!=SAVEPOINT_ROLLBACK ){ + sqlite3VdbeSetChanges(db, p->nChange); + }else{ + sqlite3VdbeSetChanges(db, 0); + } + p->nChange = 0; + } + + /* Release the locks */ + sqlite3VdbeLeave(p); + } + + /* We have successfully halted and closed the VM. Record this fact. */ + if( p->pc>=0 ){ + db->nVdbeActive--; + if( !p->readOnly ) db->nVdbeWrite--; + if( p->bIsReader ) db->nVdbeRead--; + assert( db->nVdbeActive>=db->nVdbeRead ); + assert( db->nVdbeRead>=db->nVdbeWrite ); + assert( db->nVdbeWrite>=0 ); + } + p->magic = VDBE_MAGIC_HALT; + checkActiveVdbeCnt(db); + if( p->db->mallocFailed ){ + p->rc = SQLITE_NOMEM; + } + + /* If the auto-commit flag is set to true, then any locks that were held + ** by connection db have now been released. Call sqlite3ConnectionUnlocked() + ** to invoke any required unlock-notify callbacks. + */ + if( db->autoCommit ){ + sqlite3ConnectionUnlocked(db); + } + + assert( db->nVdbeActive>0 || db->autoCommit==0 || db->nStatement==0 ); + return (p->rc==SQLITE_BUSY ? SQLITE_BUSY : SQLITE_OK); +} + + +/* +** Each VDBE holds the result of the most recent sqlite3_step() call +** in p->rc. This routine sets that result back to SQLITE_OK. +*/ +SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe *p){ + p->rc = SQLITE_OK; +} + +/* +** Copy the error code and error message belonging to the VDBE passed +** as the first argument to its database handle (so that they will be +** returned by calls to sqlite3_errcode() and sqlite3_errmsg()). +** +** This function does not clear the VDBE error code or message, just +** copies them to the database handle. +*/ +SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){ + sqlite3 *db = p->db; + int rc = p->rc; + if( p->zErrMsg ){ + u8 mallocFailed = db->mallocFailed; + sqlite3BeginBenignMalloc(); + if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db); + sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); + sqlite3EndBenignMalloc(); + db->mallocFailed = mallocFailed; + db->errCode = rc; + }else{ + sqlite3Error(db, rc); + } + return rc; +} + +#ifdef SQLITE_ENABLE_SQLLOG +/* +** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run, +** invoke it. +*/ +static void vdbeInvokeSqllog(Vdbe *v){ + if( sqlite3GlobalConfig.xSqllog && v->rc==SQLITE_OK && v->zSql && v->pc>=0 ){ + char *zExpanded = sqlite3VdbeExpandSql(v, v->zSql); + assert( v->db->init.busy==0 ); + if( zExpanded ){ + sqlite3GlobalConfig.xSqllog( + sqlite3GlobalConfig.pSqllogArg, v->db, zExpanded, 1 + ); + sqlite3DbFree(v->db, zExpanded); + } + } +} +#else +# define vdbeInvokeSqllog(x) +#endif + +/* +** Clean up a VDBE after execution but do not delete the VDBE just yet. +** Write any error messages into *pzErrMsg. Return the result code. +** +** After this routine is run, the VDBE should be ready to be executed +** again. +** +** To look at it another way, this routine resets the state of the +** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to +** VDBE_MAGIC_INIT. +*/ +SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ + sqlite3 *db; + db = p->db; + + /* If the VM did not run to completion or if it encountered an + ** error, then it might not have been halted properly. So halt + ** it now. + */ + sqlite3VdbeHalt(p); + + /* If the VDBE has be run even partially, then transfer the error code + ** and error message from the VDBE into the main database structure. But + ** if the VDBE has just been set to run but has not actually executed any + ** instructions yet, leave the main database error information unchanged. + */ + if( p->pc>=0 ){ + vdbeInvokeSqllog(p); + sqlite3VdbeTransferError(p); + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = 0; + if( p->runOnlyOnce ) p->expired = 1; + }else if( p->rc && p->expired ){ + /* The expired flag was set on the VDBE before the first call + ** to sqlite3_step(). For consistency (since sqlite3_step() was + ** called), set the database error in this case as well. + */ + sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = 0; + } + + /* Reclaim all memory used by the VDBE + */ + Cleanup(p); + + /* Save profiling information from this VDBE run. + */ +#ifdef VDBE_PROFILE + { + FILE *out = fopen("vdbe_profile.out", "a"); + if( out ){ + int i; + fprintf(out, "---- "); + for(i=0; inOp; i++){ + fprintf(out, "%02x", p->aOp[i].opcode); + } + fprintf(out, "\n"); + if( p->zSql ){ + char c, pc = 0; + fprintf(out, "-- "); + for(i=0; (c = p->zSql[i])!=0; i++){ + if( pc=='\n' ) fprintf(out, "-- "); + putc(c, out); + pc = c; + } + if( pc!='\n' ) fprintf(out, "\n"); + } + for(i=0; inOp; i++){ + char zHdr[100]; + sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ", + p->aOp[i].cnt, + p->aOp[i].cycles, + p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0 + ); + fprintf(out, "%s", zHdr); + sqlite3VdbePrintOp(out, i, &p->aOp[i]); + } + fclose(out); + } + } +#endif + p->iCurrentTime = 0; + p->magic = VDBE_MAGIC_INIT; + return p->rc & db->errMask; +} + +/* +** Clean up and delete a VDBE after execution. Return an integer which is +** the result code. Write any error message text into *pzErrMsg. +*/ +SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){ + int rc = SQLITE_OK; + if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){ + rc = sqlite3VdbeReset(p); + assert( (rc & p->db->errMask)==rc ); + } + sqlite3VdbeDelete(p); + return rc; +} + +/* +** If parameter iOp is less than zero, then invoke the destructor for +** all auxiliary data pointers currently cached by the VM passed as +** the first argument. +** +** Or, if iOp is greater than or equal to zero, then the destructor is +** only invoked for those auxiliary data pointers created by the user +** function invoked by the OP_Function opcode at instruction iOp of +** VM pVdbe, and only then if: +** +** * the associated function parameter is the 32nd or later (counting +** from left to right), or +** +** * the corresponding bit in argument mask is clear (where the first +** function parameter corresponds to bit 0 etc.). +*/ +SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){ + AuxData **pp = &pVdbe->pAuxData; + while( *pp ){ + AuxData *pAux = *pp; + if( (iOp<0) + || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & MASKBIT32(pAux->iArg)))) + ){ + testcase( pAux->iArg==31 ); + if( pAux->xDelete ){ + pAux->xDelete(pAux->pAux); + } + *pp = pAux->pNext; + sqlite3DbFree(pVdbe->db, pAux); + }else{ + pp= &pAux->pNext; + } + } +} + +/* +** Free all memory associated with the Vdbe passed as the second argument, +** except for object itself, which is preserved. +** +** The difference between this function and sqlite3VdbeDelete() is that +** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with +** the database connection and frees the object itself. +*/ +SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ + SubProgram *pSub, *pNext; + int i; + assert( p->db==0 || p->db==db ); + releaseMemArray(p->aVar, p->nVar); + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + for(pSub=p->pProgram; pSub; pSub=pNext){ + pNext = pSub->pNext; + vdbeFreeOpArray(db, pSub->aOp, pSub->nOp); + sqlite3DbFree(db, pSub); + } + for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); + vdbeFreeOpArray(db, p->aOp, p->nOp); + sqlite3DbFree(db, p->aColName); + sqlite3DbFree(db, p->zSql); + sqlite3DbFree(db, p->pFree); +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + for(i=0; inScan; i++){ + sqlite3DbFree(db, p->aScan[i].zName); + } + sqlite3DbFree(db, p->aScan); +#endif +} + +/* +** Delete an entire VDBE. +*/ +SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){ + sqlite3 *db; + + if( NEVER(p==0) ) return; + db = p->db; + assert( sqlite3_mutex_held(db->mutex) ); + sqlite3VdbeClearObject(db, p); + if( p->pPrev ){ + p->pPrev->pNext = p->pNext; + }else{ + assert( db->pVdbe==p ); + db->pVdbe = p->pNext; + } + if( p->pNext ){ + p->pNext->pPrev = p->pPrev; + } + p->magic = VDBE_MAGIC_DEAD; + p->db = 0; + sqlite3DbFree(db, p); +} + +/* +** The cursor "p" has a pending seek operation that has not yet been +** carried out. Seek the cursor now. If an error occurs, return +** the appropriate error code. +*/ +static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){ + int res, rc; +#ifdef SQLITE_TEST + extern int sqlite3_search_count; +#endif + assert( p->deferredMoveto ); + assert( p->isTable ); + rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res); + if( rc ) return rc; + if( res!=0 ) return SQLITE_CORRUPT_BKPT; +#ifdef SQLITE_TEST + sqlite3_search_count++; +#endif + p->deferredMoveto = 0; + p->cacheStatus = CACHE_STALE; + return SQLITE_OK; +} + +/* +** Something has moved cursor "p" out of place. Maybe the row it was +** pointed to was deleted out from under it. Or maybe the btree was +** rebalanced. Whatever the cause, try to restore "p" to the place it +** is supposed to be pointing. If the row was deleted out from under the +** cursor, set the cursor to point to a NULL row. +*/ +static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){ + int isDifferentRow, rc; + assert( p->pCursor!=0 ); + assert( sqlite3BtreeCursorHasMoved(p->pCursor) ); + rc = sqlite3BtreeCursorRestore(p->pCursor, &isDifferentRow); + p->cacheStatus = CACHE_STALE; + if( isDifferentRow ) p->nullRow = 1; + return rc; +} + +/* +** Check to ensure that the cursor is valid. Restore the cursor +** if need be. Return any I/O error from the restore operation. +*/ +SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){ + if( sqlite3BtreeCursorHasMoved(p->pCursor) ){ + return handleMovedCursor(p); + } + return SQLITE_OK; +} + +/* +** Make sure the cursor p is ready to read or write the row to which it +** was last positioned. Return an error code if an OOM fault or I/O error +** prevents us from positioning the cursor to its correct position. +** +** If a MoveTo operation is pending on the given cursor, then do that +** MoveTo now. If no move is pending, check to see if the row has been +** deleted out from under the cursor and if it has, mark the row as +** a NULL row. +** +** If the cursor is already pointing to the correct row and that row has +** not been deleted out from under the cursor, then this routine is a no-op. +*/ +SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){ + if( p->deferredMoveto ){ + return handleDeferredMoveto(p); + } + if( p->pCursor && sqlite3BtreeCursorHasMoved(p->pCursor) ){ + return handleMovedCursor(p); + } + return SQLITE_OK; +} + +/* +** The following functions: +** +** sqlite3VdbeSerialType() +** sqlite3VdbeSerialTypeLen() +** sqlite3VdbeSerialLen() +** sqlite3VdbeSerialPut() +** sqlite3VdbeSerialGet() +** +** encapsulate the code that serializes values for storage in SQLite +** data and index records. Each serialized value consists of a +** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned +** integer, stored as a varint. +** +** In an SQLite index record, the serial type is stored directly before +** the blob of data that it corresponds to. In a table record, all serial +** types are stored at the start of the record, and the blobs of data at +** the end. Hence these functions allow the caller to handle the +** serial-type and data blob separately. +** +** The following table describes the various storage classes for data: +** +** serial type bytes of data type +** -------------- --------------- --------------- +** 0 0 NULL +** 1 1 signed integer +** 2 2 signed integer +** 3 3 signed integer +** 4 4 signed integer +** 5 6 signed integer +** 6 8 signed integer +** 7 8 IEEE float +** 8 0 Integer constant 0 +** 9 0 Integer constant 1 +** 10,11 reserved for expansion +** N>=12 and even (N-12)/2 BLOB +** N>=13 and odd (N-13)/2 text +** +** The 8 and 9 types were added in 3.3.0, file format 4. Prior versions +** of SQLite will not understand those serial types. +*/ + +/* +** Return the serial-type for the value stored in pMem. +*/ +SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){ + int flags = pMem->flags; + u32 n; + + if( flags&MEM_Null ){ + return 0; + } + if( flags&MEM_Int ){ + /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ +# define MAX_6BYTE ((((i64)0x00008000)<<32)-1) + i64 i = pMem->u.i; + u64 u; + if( i<0 ){ + u = ~i; + }else{ + u = i; + } + if( u<=127 ){ + return ((i&1)==i && file_format>=4) ? 8+(u32)u : 1; + } + if( u<=32767 ) return 2; + if( u<=8388607 ) return 3; + if( u<=2147483647 ) return 4; + if( u<=MAX_6BYTE ) return 5; + return 6; + } + if( flags&MEM_Real ){ + return 7; + } + assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) ); + assert( pMem->n>=0 ); + n = (u32)pMem->n; + if( flags & MEM_Zero ){ + n += pMem->u.nZero; + } + return ((n*2) + 12 + ((flags&MEM_Str)!=0)); +} + +/* +** The sizes for serial types less than 12 +*/ +static const u8 sqlite3SmallTypeSizes[] = { + 0, 1, 2, 3, 4, 6, 8, 8, 0, 0, 0, 0 +}; + +/* +** Return the length of the data corresponding to the supplied serial-type. +*/ +SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32 serial_type){ + if( serial_type>=12 ){ + return (serial_type-12)/2; + }else{ + return sqlite3SmallTypeSizes[serial_type]; + } +} + +/* +** If we are on an architecture with mixed-endian floating +** points (ex: ARM7) then swap the lower 4 bytes with the +** upper 4 bytes. Return the result. +** +** For most architectures, this is a no-op. +** +** (later): It is reported to me that the mixed-endian problem +** on ARM7 is an issue with GCC, not with the ARM7 chip. It seems +** that early versions of GCC stored the two words of a 64-bit +** float in the wrong order. And that error has been propagated +** ever since. The blame is not necessarily with GCC, though. +** GCC might have just copying the problem from a prior compiler. +** I am also told that newer versions of GCC that follow a different +** ABI get the byte order right. +** +** Developers using SQLite on an ARM7 should compile and run their +** application using -DSQLITE_DEBUG=1 at least once. With DEBUG +** enabled, some asserts below will ensure that the byte order of +** floating point values is correct. +** +** (2007-08-30) Frank van Vugt has studied this problem closely +** and has send his findings to the SQLite developers. Frank +** writes that some Linux kernels offer floating point hardware +** emulation that uses only 32-bit mantissas instead of a full +** 48-bits as required by the IEEE standard. (This is the +** CONFIG_FPE_FASTFPE option.) On such systems, floating point +** byte swapping becomes very complicated. To avoid problems, +** the necessary byte swapping is carried out using a 64-bit integer +** rather than a 64-bit float. Frank assures us that the code here +** works for him. We, the developers, have no way to independently +** verify this, but Frank seems to know what he is talking about +** so we trust him. +*/ +#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT +static u64 floatSwap(u64 in){ + union { + u64 r; + u32 i[2]; + } u; + u32 t; + + u.r = in; + t = u.i[0]; + u.i[0] = u.i[1]; + u.i[1] = t; + return u.r; +} +# define swapMixedEndianFloat(X) X = floatSwap(X) +#else +# define swapMixedEndianFloat(X) +#endif + +/* +** Write the serialized data blob for the value stored in pMem into +** buf. It is assumed that the caller has allocated sufficient space. +** Return the number of bytes written. +** +** nBuf is the amount of space left in buf[]. The caller is responsible +** for allocating enough space to buf[] to hold the entire field, exclusive +** of the pMem->u.nZero bytes for a MEM_Zero value. +** +** Return the number of bytes actually written into buf[]. The number +** of bytes in the zero-filled tail is included in the return value only +** if those bytes were zeroed in buf[]. +*/ +SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ + u32 len; + + /* Integer and Real */ + if( serial_type<=7 && serial_type>0 ){ + u64 v; + u32 i; + if( serial_type==7 ){ + assert( sizeof(v)==sizeof(pMem->u.r) ); + memcpy(&v, &pMem->u.r, sizeof(v)); + swapMixedEndianFloat(v); + }else{ + v = pMem->u.i; + } + len = i = sqlite3SmallTypeSizes[serial_type]; + assert( i>0 ); + do{ + buf[--i] = (u8)(v&0xFF); + v >>= 8; + }while( i ); + return len; + } + + /* String or blob */ + if( serial_type>=12 ){ + assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0) + == (int)sqlite3VdbeSerialTypeLen(serial_type) ); + len = pMem->n; + memcpy(buf, pMem->z, len); + return len; + } + + /* NULL or constants 0 or 1 */ + return 0; +} + +/* Input "x" is a sequence of unsigned characters that represent a +** big-endian integer. Return the equivalent native integer +*/ +#define ONE_BYTE_INT(x) ((i8)(x)[0]) +#define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1]) +#define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2]) +#define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) +#define FOUR_BYTE_INT(x) (16777216*(i8)((x)[0])|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) + +/* +** Deserialize the data blob pointed to by buf as serial type serial_type +** and store the result in pMem. Return the number of bytes read. +** +** This function is implemented as two separate routines for performance. +** The few cases that require local variables are broken out into a separate +** routine so that in most cases the overhead of moving the stack pointer +** is avoided. +*/ +static u32 SQLITE_NOINLINE serialGet( + const unsigned char *buf, /* Buffer to deserialize from */ + u32 serial_type, /* Serial type to deserialize */ + Mem *pMem /* Memory cell to write value into */ +){ + u64 x = FOUR_BYTE_UINT(buf); + u32 y = FOUR_BYTE_UINT(buf+4); + x = (x<<32) + y; + if( serial_type==6 ){ + /* EVIDENCE-OF: R-29851-52272 Value is a big-endian 64-bit + ** twos-complement integer. */ + pMem->u.i = *(i64*)&x; + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + }else{ + /* EVIDENCE-OF: R-57343-49114 Value is a big-endian IEEE 754-2008 64-bit + ** floating point number. */ +#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) + /* Verify that integers and floating point values use the same + ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is + ** defined that 64-bit floating point values really are mixed + ** endian. + */ + static const u64 t1 = ((u64)0x3ff00000)<<32; + static const double r1 = 1.0; + u64 t2 = t1; + swapMixedEndianFloat(t2); + assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); +#endif + assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 ); + swapMixedEndianFloat(x); + memcpy(&pMem->u.r, &x, sizeof(x)); + pMem->flags = sqlite3IsNaN(pMem->u.r) ? MEM_Null : MEM_Real; + } + return 8; +} +SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( + const unsigned char *buf, /* Buffer to deserialize from */ + u32 serial_type, /* Serial type to deserialize */ + Mem *pMem /* Memory cell to write value into */ +){ + switch( serial_type ){ + case 10: /* Reserved for future use */ + case 11: /* Reserved for future use */ + case 0: { /* Null */ + /* EVIDENCE-OF: R-24078-09375 Value is a NULL. */ + pMem->flags = MEM_Null; + break; + } + case 1: { + /* EVIDENCE-OF: R-44885-25196 Value is an 8-bit twos-complement + ** integer. */ + pMem->u.i = ONE_BYTE_INT(buf); + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + return 1; + } + case 2: { /* 2-byte signed integer */ + /* EVIDENCE-OF: R-49794-35026 Value is a big-endian 16-bit + ** twos-complement integer. */ + pMem->u.i = TWO_BYTE_INT(buf); + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + return 2; + } + case 3: { /* 3-byte signed integer */ + /* EVIDENCE-OF: R-37839-54301 Value is a big-endian 24-bit + ** twos-complement integer. */ + pMem->u.i = THREE_BYTE_INT(buf); + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + return 3; + } + case 4: { /* 4-byte signed integer */ + /* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit + ** twos-complement integer. */ + pMem->u.i = FOUR_BYTE_INT(buf); + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + return 4; + } + case 5: { /* 6-byte signed integer */ + /* EVIDENCE-OF: R-50385-09674 Value is a big-endian 48-bit + ** twos-complement integer. */ + pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + return 6; + } + case 6: /* 8-byte signed integer */ + case 7: { /* IEEE floating point */ + /* These use local variables, so do them in a separate routine + ** to avoid having to move the frame pointer in the common case */ + return serialGet(buf,serial_type,pMem); + } + case 8: /* Integer 0 */ + case 9: { /* Integer 1 */ + /* EVIDENCE-OF: R-12976-22893 Value is the integer 0. */ + /* EVIDENCE-OF: R-18143-12121 Value is the integer 1. */ + pMem->u.i = serial_type-8; + pMem->flags = MEM_Int; + return 0; + } + default: { + /* EVIDENCE-OF: R-14606-31564 Value is a BLOB that is (N-12)/2 bytes in + ** length. + ** EVIDENCE-OF: R-28401-00140 Value is a string in the text encoding and + ** (N-13)/2 bytes in length. */ + static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem }; + pMem->z = (char *)buf; + pMem->n = (serial_type-12)/2; + pMem->flags = aFlag[serial_type&1]; + return pMem->n; + } + } + return 0; +} +/* +** This routine is used to allocate sufficient space for an UnpackedRecord +** structure large enough to be used with sqlite3VdbeRecordUnpack() if +** the first argument is a pointer to KeyInfo structure pKeyInfo. +** +** The space is either allocated using sqlite3DbMallocRaw() or from within +** the unaligned buffer passed via the second and third arguments (presumably +** stack space). If the former, then *ppFree is set to a pointer that should +** be eventually freed by the caller using sqlite3DbFree(). Or, if the +** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL +** before returning. +** +** If an OOM error occurs, NULL is returned. +*/ +SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( + KeyInfo *pKeyInfo, /* Description of the record */ + char *pSpace, /* Unaligned space available */ + int szSpace, /* Size of pSpace[] in bytes */ + char **ppFree /* OUT: Caller should free this pointer */ +){ + UnpackedRecord *p; /* Unpacked record to return */ + int nOff; /* Increment pSpace by nOff to align it */ + int nByte; /* Number of bytes required for *p */ + + /* We want to shift the pointer pSpace up such that it is 8-byte aligned. + ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift + ** it by. If pSpace is already 8-byte aligned, nOff should be zero. + */ + nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7; + nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1); + if( nByte>szSpace+nOff ){ + p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); + *ppFree = (char *)p; + if( !p ) return 0; + }else{ + p = (UnpackedRecord*)&pSpace[nOff]; + *ppFree = 0; + } + + p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; + assert( pKeyInfo->aSortOrder!=0 ); + p->pKeyInfo = pKeyInfo; + p->nField = pKeyInfo->nField + 1; + return p; +} + +/* +** Given the nKey-byte encoding of a record in pKey[], populate the +** UnpackedRecord structure indicated by the fourth argument with the +** contents of the decoded record. +*/ +SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( + KeyInfo *pKeyInfo, /* Information about the record format */ + int nKey, /* Size of the binary record */ + const void *pKey, /* The binary record */ + UnpackedRecord *p /* Populate this structure before returning. */ +){ + const unsigned char *aKey = (const unsigned char *)pKey; + int d; + u32 idx; /* Offset in aKey[] to read from */ + u16 u; /* Unsigned loop counter */ + u32 szHdr; + Mem *pMem = p->aMem; + + p->default_rc = 0; + assert( EIGHT_BYTE_ALIGNMENT(pMem) ); + idx = getVarint32(aKey, szHdr); + d = szHdr; + u = 0; + while( idxenc = pKeyInfo->enc; + pMem->db = pKeyInfo->db; + /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */ + pMem->szMalloc = 0; + d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); + pMem++; + if( (++u)>=p->nField ) break; + } + assert( u<=pKeyInfo->nField + 1 ); + p->nField = u; +} + +#if SQLITE_DEBUG +/* +** This function compares two index or table record keys in the same way +** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(), +** this function deserializes and compares values using the +** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used +** in assert() statements to ensure that the optimized code in +** sqlite3VdbeRecordCompare() returns results with these two primitives. +** +** Return true if the result of comparison is equivalent to desiredResult. +** Return false if there is a disagreement. +*/ +static int vdbeRecordCompareDebug( + int nKey1, const void *pKey1, /* Left key */ + const UnpackedRecord *pPKey2, /* Right key */ + int desiredResult /* Correct answer */ +){ + u32 d1; /* Offset into aKey[] of next data element */ + u32 idx1; /* Offset into aKey[] of next header element */ + u32 szHdr1; /* Number of bytes in header */ + int i = 0; + int rc = 0; + const unsigned char *aKey1 = (const unsigned char *)pKey1; + KeyInfo *pKeyInfo; + Mem mem1; + + pKeyInfo = pPKey2->pKeyInfo; + if( pKeyInfo->db==0 ) return 1; + mem1.enc = pKeyInfo->enc; + mem1.db = pKeyInfo->db; + /* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */ + VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ + + /* Compilers may complain that mem1.u.i is potentially uninitialized. + ** We could initialize it, as shown here, to silence those complaints. + ** But in fact, mem1.u.i will never actually be used uninitialized, and doing + ** the unnecessary initialization has a measurable negative performance + ** impact, since this routine is a very high runner. And so, we choose + ** to ignore the compiler warnings and leave this variable uninitialized. + */ + /* mem1.u.i = 0; // not needed, here to silence compiler warning */ + + idx1 = getVarint32(aKey1, szHdr1); + if( szHdr1>98307 ) return SQLITE_CORRUPT; + d1 = szHdr1; + assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB ); + assert( pKeyInfo->aSortOrder!=0 ); + assert( pKeyInfo->nField>0 ); + assert( idx1<=szHdr1 || CORRUPT_DB ); + do{ + u32 serial_type1; + + /* Read the serial types for the next element in each key. */ + idx1 += getVarint32( aKey1+idx1, serial_type1 ); + + /* Verify that there is enough key space remaining to avoid + ** a buffer overread. The "d1+serial_type1+2" subexpression will + ** always be greater than or equal to the amount of required key space. + ** Use that approximation to avoid the more expensive call to + ** sqlite3VdbeSerialTypeLen() in the common case. + */ + if( d1+serial_type1+2>(u32)nKey1 + && d1+sqlite3VdbeSerialTypeLen(serial_type1)>(u32)nKey1 + ){ + break; + } + + /* Extract the values to be compared. + */ + d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); + + /* Do the comparison + */ + rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]); + if( rc!=0 ){ + assert( mem1.szMalloc==0 ); /* See comment below */ + if( pKeyInfo->aSortOrder[i] ){ + rc = -rc; /* Invert the result for DESC sort order. */ + } + goto debugCompareEnd; + } + i++; + }while( idx1nField ); + + /* No memory allocation is ever used on mem1. Prove this using + ** the following assert(). If the assert() fails, it indicates a + ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). + */ + assert( mem1.szMalloc==0 ); + + /* rc==0 here means that one of the keys ran out of fields and + ** all the fields up to that point were equal. Return the default_rc + ** value. */ + rc = pPKey2->default_rc; + +debugCompareEnd: + if( desiredResult==0 && rc==0 ) return 1; + if( desiredResult<0 && rc<0 ) return 1; + if( desiredResult>0 && rc>0 ) return 1; + if( CORRUPT_DB ) return 1; + if( pKeyInfo->db->mallocFailed ) return 1; + return 0; +} +#endif + +#if SQLITE_DEBUG +/* +** Count the number of fields (a.k.a. columns) in the record given by +** pKey,nKey. The verify that this count is less than or equal to the +** limit given by pKeyInfo->nField + pKeyInfo->nXField. +** +** If this constraint is not satisfied, it means that the high-speed +** vdbeRecordCompareInt() and vdbeRecordCompareString() routines will +** not work correctly. If this assert() ever fires, it probably means +** that the KeyInfo.nField or KeyInfo.nXField values were computed +** incorrectly. +*/ +static void vdbeAssertFieldCountWithinLimits( + int nKey, const void *pKey, /* The record to verify */ + const KeyInfo *pKeyInfo /* Compare size with this KeyInfo */ +){ + int nField = 0; + u32 szHdr; + u32 idx; + u32 notUsed; + const unsigned char *aKey = (const unsigned char*)pKey; + + if( CORRUPT_DB ) return; + idx = getVarint32(aKey, szHdr); + assert( nKey>=0 ); + assert( szHdr<=(u32)nKey ); + while( idxnField+pKeyInfo->nXField ); +} +#else +# define vdbeAssertFieldCountWithinLimits(A,B,C) +#endif + +/* +** Both *pMem1 and *pMem2 contain string values. Compare the two values +** using the collation sequence pColl. As usual, return a negative , zero +** or positive value if *pMem1 is less than, equal to or greater than +** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);". +*/ +static int vdbeCompareMemString( + const Mem *pMem1, + const Mem *pMem2, + const CollSeq *pColl, + u8 *prcErr /* If an OOM occurs, set to SQLITE_NOMEM */ +){ + if( pMem1->enc==pColl->enc ){ + /* The strings are already in the correct encoding. Call the + ** comparison function directly */ + return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); + }else{ + int rc; + const void *v1, *v2; + int n1, n2; + Mem c1; + Mem c2; + sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null); + sqlite3VdbeMemInit(&c2, pMem1->db, MEM_Null); + sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); + sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); + v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); + n1 = v1==0 ? 0 : c1.n; + v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); + n2 = v2==0 ? 0 : c2.n; + rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); + sqlite3VdbeMemRelease(&c1); + sqlite3VdbeMemRelease(&c2); + if( (v1==0 || v2==0) && prcErr ) *prcErr = SQLITE_NOMEM; + return rc; + } +} + +/* +** Compare two blobs. Return negative, zero, or positive if the first +** is less than, equal to, or greater than the second, respectively. +** If one blob is a prefix of the other, then the shorter is the lessor. +*/ +static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){ + int c = memcmp(pB1->z, pB2->z, pB1->n>pB2->n ? pB2->n : pB1->n); + if( c ) return c; + return pB1->n - pB2->n; +} + + +/* +** Compare the values contained by the two memory cells, returning +** negative, zero or positive if pMem1 is less than, equal to, or greater +** than pMem2. Sorting order is NULL's first, followed by numbers (integers +** and reals) sorted numerically, followed by text ordered by the collating +** sequence pColl and finally blob's ordered by memcmp(). +** +** Two NULL values are considered equal by this function. +*/ +SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ + int f1, f2; + int combined_flags; + + f1 = pMem1->flags; + f2 = pMem2->flags; + combined_flags = f1|f2; + assert( (combined_flags & MEM_RowSet)==0 ); + + /* If one value is NULL, it is less than the other. If both values + ** are NULL, return 0. + */ + if( combined_flags&MEM_Null ){ + return (f2&MEM_Null) - (f1&MEM_Null); + } + + /* If one value is a number and the other is not, the number is less. + ** If both are numbers, compare as reals if one is a real, or as integers + ** if both values are integers. + */ + if( combined_flags&(MEM_Int|MEM_Real) ){ + double r1, r2; + if( (f1 & f2 & MEM_Int)!=0 ){ + if( pMem1->u.i < pMem2->u.i ) return -1; + if( pMem1->u.i > pMem2->u.i ) return 1; + return 0; + } + if( (f1&MEM_Real)!=0 ){ + r1 = pMem1->u.r; + }else if( (f1&MEM_Int)!=0 ){ + r1 = (double)pMem1->u.i; + }else{ + return 1; + } + if( (f2&MEM_Real)!=0 ){ + r2 = pMem2->u.r; + }else if( (f2&MEM_Int)!=0 ){ + r2 = (double)pMem2->u.i; + }else{ + return -1; + } + if( r1r2 ) return 1; + return 0; + } + + /* If one value is a string and the other is a blob, the string is less. + ** If both are strings, compare using the collating functions. + */ + if( combined_flags&MEM_Str ){ + if( (f1 & MEM_Str)==0 ){ + return 1; + } + if( (f2 & MEM_Str)==0 ){ + return -1; + } + + assert( pMem1->enc==pMem2->enc ); + assert( pMem1->enc==SQLITE_UTF8 || + pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); + + /* The collation sequence must be defined at this point, even if + ** the user deletes the collation sequence after the vdbe program is + ** compiled (this was not always the case). + */ + assert( !pColl || pColl->xCmp ); + + if( pColl ){ + return vdbeCompareMemString(pMem1, pMem2, pColl, 0); + } + /* If a NULL pointer was passed as the collate function, fall through + ** to the blob case and use memcmp(). */ + } + + /* Both values must be blobs. Compare using memcmp(). */ + return sqlite3BlobCompare(pMem1, pMem2); +} + + +/* +** The first argument passed to this function is a serial-type that +** corresponds to an integer - all values between 1 and 9 inclusive +** except 7. The second points to a buffer containing an integer value +** serialized according to serial_type. This function deserializes +** and returns the value. +*/ +static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ + u32 y; + assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) ); + switch( serial_type ){ + case 0: + case 1: + testcase( aKey[0]&0x80 ); + return ONE_BYTE_INT(aKey); + case 2: + testcase( aKey[0]&0x80 ); + return TWO_BYTE_INT(aKey); + case 3: + testcase( aKey[0]&0x80 ); + return THREE_BYTE_INT(aKey); + case 4: { + testcase( aKey[0]&0x80 ); + y = FOUR_BYTE_UINT(aKey); + return (i64)*(int*)&y; + } + case 5: { + testcase( aKey[0]&0x80 ); + return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); + } + case 6: { + u64 x = FOUR_BYTE_UINT(aKey); + testcase( aKey[0]&0x80 ); + x = (x<<32) | FOUR_BYTE_UINT(aKey+4); + return (i64)*(i64*)&x; + } + } + + return (serial_type - 8); +} + +/* +** This function compares the two table rows or index records +** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero +** or positive integer if key1 is less than, equal to or +** greater than key2. The {nKey1, pKey1} key must be a blob +** created by the OP_MakeRecord opcode of the VDBE. The pPKey2 +** key must be a parsed key such as obtained from +** sqlite3VdbeParseRecord. +** +** If argument bSkip is non-zero, it is assumed that the caller has already +** determined that the first fields of the keys are equal. +** +** Key1 and Key2 do not have to contain the same number of fields. If all +** fields that appear in both keys are equal, then pPKey2->default_rc is +** returned. +** +** If database corruption is discovered, set pPKey2->errCode to +** SQLITE_CORRUPT and return 0. If an OOM error is encountered, +** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the +** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db). +*/ +SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( + int nKey1, const void *pKey1, /* Left key */ + UnpackedRecord *pPKey2, /* Right key */ + int bSkip /* If true, skip the first field */ +){ + u32 d1; /* Offset into aKey[] of next data element */ + int i; /* Index of next field to compare */ + u32 szHdr1; /* Size of record header in bytes */ + u32 idx1; /* Offset of first type in header */ + int rc = 0; /* Return value */ + Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */ + KeyInfo *pKeyInfo = pPKey2->pKeyInfo; + const unsigned char *aKey1 = (const unsigned char *)pKey1; + Mem mem1; + + /* If bSkip is true, then the caller has already determined that the first + ** two elements in the keys are equal. Fix the various stack variables so + ** that this routine begins comparing at the second field. */ + if( bSkip ){ + u32 s1; + idx1 = 1 + getVarint32(&aKey1[1], s1); + szHdr1 = aKey1[0]; + d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1); + i = 1; + pRhs++; + }else{ + idx1 = getVarint32(aKey1, szHdr1); + d1 = szHdr1; + if( d1>(unsigned)nKey1 ){ + pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; + return 0; /* Corruption */ + } + i = 0; + } + + VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ + assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField + || CORRUPT_DB ); + assert( pPKey2->pKeyInfo->aSortOrder!=0 ); + assert( pPKey2->pKeyInfo->nField>0 ); + assert( idx1<=szHdr1 || CORRUPT_DB ); + do{ + u32 serial_type; + + /* RHS is an integer */ + if( pRhs->flags & MEM_Int ){ + serial_type = aKey1[idx1]; + testcase( serial_type==12 ); + if( serial_type>=10 ){ + rc = +1; + }else if( serial_type==0 ){ + rc = -1; + }else if( serial_type==7 ){ + double rhs = (double)pRhs->u.i; + sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); + if( mem1.u.rrhs ){ + rc = +1; + } + }else{ + i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]); + i64 rhs = pRhs->u.i; + if( lhsrhs ){ + rc = +1; + } + } + } + + /* RHS is real */ + else if( pRhs->flags & MEM_Real ){ + serial_type = aKey1[idx1]; + if( serial_type>=10 ){ + /* Serial types 12 or greater are strings and blobs (greater than + ** numbers). Types 10 and 11 are currently "reserved for future + ** use", so it doesn't really matter what the results of comparing + ** them to numberic values are. */ + rc = +1; + }else if( serial_type==0 ){ + rc = -1; + }else{ + double rhs = pRhs->u.r; + double lhs; + sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); + if( serial_type==7 ){ + lhs = mem1.u.r; + }else{ + lhs = (double)mem1.u.i; + } + if( lhsrhs ){ + rc = +1; + } + } + } + + /* RHS is a string */ + else if( pRhs->flags & MEM_Str ){ + getVarint32(&aKey1[idx1], serial_type); + testcase( serial_type==12 ); + if( serial_type<12 ){ + rc = -1; + }else if( !(serial_type & 0x01) ){ + rc = +1; + }else{ + mem1.n = (serial_type - 12) / 2; + testcase( (d1+mem1.n)==(unsigned)nKey1 ); + testcase( (d1+mem1.n+1)==(unsigned)nKey1 ); + if( (d1+mem1.n) > (unsigned)nKey1 ){ + pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; + return 0; /* Corruption */ + }else if( pKeyInfo->aColl[i] ){ + mem1.enc = pKeyInfo->enc; + mem1.db = pKeyInfo->db; + mem1.flags = MEM_Str; + mem1.z = (char*)&aKey1[d1]; + rc = vdbeCompareMemString( + &mem1, pRhs, pKeyInfo->aColl[i], &pPKey2->errCode + ); + }else{ + int nCmp = MIN(mem1.n, pRhs->n); + rc = memcmp(&aKey1[d1], pRhs->z, nCmp); + if( rc==0 ) rc = mem1.n - pRhs->n; + } + } + } + + /* RHS is a blob */ + else if( pRhs->flags & MEM_Blob ){ + getVarint32(&aKey1[idx1], serial_type); + testcase( serial_type==12 ); + if( serial_type<12 || (serial_type & 0x01) ){ + rc = -1; + }else{ + int nStr = (serial_type - 12) / 2; + testcase( (d1+nStr)==(unsigned)nKey1 ); + testcase( (d1+nStr+1)==(unsigned)nKey1 ); + if( (d1+nStr) > (unsigned)nKey1 ){ + pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; + return 0; /* Corruption */ + }else{ + int nCmp = MIN(nStr, pRhs->n); + rc = memcmp(&aKey1[d1], pRhs->z, nCmp); + if( rc==0 ) rc = nStr - pRhs->n; + } + } + } + + /* RHS is null */ + else{ + serial_type = aKey1[idx1]; + rc = (serial_type!=0); + } + + if( rc!=0 ){ + if( pKeyInfo->aSortOrder[i] ){ + rc = -rc; + } + assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) ); + assert( mem1.szMalloc==0 ); /* See comment below */ + return rc; + } + + i++; + pRhs++; + d1 += sqlite3VdbeSerialTypeLen(serial_type); + idx1 += sqlite3VarintLen(serial_type); + }while( idx1<(unsigned)szHdr1 && inField && d1<=(unsigned)nKey1 ); + + /* No memory allocation is ever used on mem1. Prove this using + ** the following assert(). If the assert() fails, it indicates a + ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */ + assert( mem1.szMalloc==0 ); + + /* rc==0 here means that one or both of the keys ran out of fields and + ** all the fields up to that point were equal. Return the default_rc + ** value. */ + assert( CORRUPT_DB + || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc) + || pKeyInfo->db->mallocFailed + ); + return pPKey2->default_rc; +} +SQLITE_PRIVATE int sqlite3VdbeRecordCompare( + int nKey1, const void *pKey1, /* Left key */ + UnpackedRecord *pPKey2 /* Right key */ +){ + return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0); +} + + +/* +** This function is an optimized version of sqlite3VdbeRecordCompare() +** that (a) the first field of pPKey2 is an integer, and (b) the +** size-of-header varint at the start of (pKey1/nKey1) fits in a single +** byte (i.e. is less than 128). +** +** To avoid concerns about buffer overreads, this routine is only used +** on schemas where the maximum valid header size is 63 bytes or less. +*/ +static int vdbeRecordCompareInt( + int nKey1, const void *pKey1, /* Left key */ + UnpackedRecord *pPKey2 /* Right key */ +){ + const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F]; + int serial_type = ((const u8*)pKey1)[1]; + int res; + u32 y; + u64 x; + i64 v = pPKey2->aMem[0].u.i; + i64 lhs; + + vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); + assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB ); + switch( serial_type ){ + case 1: { /* 1-byte signed integer */ + lhs = ONE_BYTE_INT(aKey); + testcase( lhs<0 ); + break; + } + case 2: { /* 2-byte signed integer */ + lhs = TWO_BYTE_INT(aKey); + testcase( lhs<0 ); + break; + } + case 3: { /* 3-byte signed integer */ + lhs = THREE_BYTE_INT(aKey); + testcase( lhs<0 ); + break; + } + case 4: { /* 4-byte signed integer */ + y = FOUR_BYTE_UINT(aKey); + lhs = (i64)*(int*)&y; + testcase( lhs<0 ); + break; + } + case 5: { /* 6-byte signed integer */ + lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); + testcase( lhs<0 ); + break; + } + case 6: { /* 8-byte signed integer */ + x = FOUR_BYTE_UINT(aKey); + x = (x<<32) | FOUR_BYTE_UINT(aKey+4); + lhs = *(i64*)&x; + testcase( lhs<0 ); + break; + } + case 8: + lhs = 0; + break; + case 9: + lhs = 1; + break; + + /* This case could be removed without changing the results of running + ** this code. Including it causes gcc to generate a faster switch + ** statement (since the range of switch targets now starts at zero and + ** is contiguous) but does not cause any duplicate code to be generated + ** (as gcc is clever enough to combine the two like cases). Other + ** compilers might be similar. */ + case 0: case 7: + return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2); + + default: + return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2); + } + + if( v>lhs ){ + res = pPKey2->r1; + }else if( vr2; + }else if( pPKey2->nField>1 ){ + /* The first fields of the two keys are equal. Compare the trailing + ** fields. */ + res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); + }else{ + /* The first fields of the two keys are equal and there are no trailing + ** fields. Return pPKey2->default_rc in this case. */ + res = pPKey2->default_rc; + } + + assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) ); + return res; +} + +/* +** This function is an optimized version of sqlite3VdbeRecordCompare() +** that (a) the first field of pPKey2 is a string, that (b) the first field +** uses the collation sequence BINARY and (c) that the size-of-header varint +** at the start of (pKey1/nKey1) fits in a single byte. +*/ +static int vdbeRecordCompareString( + int nKey1, const void *pKey1, /* Left key */ + UnpackedRecord *pPKey2 /* Right key */ +){ + const u8 *aKey1 = (const u8*)pKey1; + int serial_type; + int res; + + vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); + getVarint32(&aKey1[1], serial_type); + if( serial_type<12 ){ + res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */ + }else if( !(serial_type & 0x01) ){ + res = pPKey2->r2; /* (pKey1/nKey1) is a blob */ + }else{ + int nCmp; + int nStr; + int szHdr = aKey1[0]; + + nStr = (serial_type-12) / 2; + if( (szHdr + nStr) > nKey1 ){ + pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; + return 0; /* Corruption */ + } + nCmp = MIN( pPKey2->aMem[0].n, nStr ); + res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp); + + if( res==0 ){ + res = nStr - pPKey2->aMem[0].n; + if( res==0 ){ + if( pPKey2->nField>1 ){ + res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); + }else{ + res = pPKey2->default_rc; + } + }else if( res>0 ){ + res = pPKey2->r2; + }else{ + res = pPKey2->r1; + } + }else if( res>0 ){ + res = pPKey2->r2; + }else{ + res = pPKey2->r1; + } + } + + assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) + || CORRUPT_DB + || pPKey2->pKeyInfo->db->mallocFailed + ); + return res; +} + +/* +** Return a pointer to an sqlite3VdbeRecordCompare() compatible function +** suitable for comparing serialized records to the unpacked record passed +** as the only argument. +*/ +SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ + /* varintRecordCompareInt() and varintRecordCompareString() both assume + ** that the size-of-header varint that occurs at the start of each record + ** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt() + ** also assumes that it is safe to overread a buffer by at least the + ** maximum possible legal header size plus 8 bytes. Because there is + ** guaranteed to be at least 74 (but not 136) bytes of padding following each + ** buffer passed to varintRecordCompareInt() this makes it convenient to + ** limit the size of the header to 64 bytes in cases where the first field + ** is an integer. + ** + ** The easiest way to enforce this limit is to consider only records with + ** 13 fields or less. If the first field is an integer, the maximum legal + ** header size is (12*5 + 1 + 1) bytes. */ + if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){ + int flags = p->aMem[0].flags; + if( p->pKeyInfo->aSortOrder[0] ){ + p->r1 = 1; + p->r2 = -1; + }else{ + p->r1 = -1; + p->r2 = 1; + } + if( (flags & MEM_Int) ){ + return vdbeRecordCompareInt; + } + testcase( flags & MEM_Real ); + testcase( flags & MEM_Null ); + testcase( flags & MEM_Blob ); + if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){ + assert( flags & MEM_Str ); + return vdbeRecordCompareString; + } + } + + return sqlite3VdbeRecordCompare; +} + +/* +** pCur points at an index entry created using the OP_MakeRecord opcode. +** Read the rowid (the last field in the record) and store it in *rowid. +** Return SQLITE_OK if everything works, or an error code otherwise. +** +** pCur might be pointing to text obtained from a corrupt database file. +** So the content cannot be trusted. Do appropriate checks on the content. +*/ +SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ + i64 nCellKey = 0; + int rc; + u32 szHdr; /* Size of the header */ + u32 typeRowid; /* Serial type of the rowid */ + u32 lenRowid; /* Size of the rowid */ + Mem m, v; + + /* Get the size of the index entry. Only indices entries of less + ** than 2GiB are support - anything large must be database corruption. + ** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so + ** this code can safely assume that nCellKey is 32-bits + */ + assert( sqlite3BtreeCursorIsValid(pCur) ); + VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey); + assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ + assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey ); + + /* Read in the complete content of the index entry */ + sqlite3VdbeMemInit(&m, db, 0); + rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m); + if( rc ){ + return rc; + } + + /* The index entry must begin with a header size */ + (void)getVarint32((u8*)m.z, szHdr); + testcase( szHdr==3 ); + testcase( szHdr==m.n ); + if( unlikely(szHdr<3 || (int)szHdr>m.n) ){ + goto idx_rowid_corruption; + } + + /* The last field of the index should be an integer - the ROWID. + ** Verify that the last entry really is an integer. */ + (void)getVarint32((u8*)&m.z[szHdr-1], typeRowid); + testcase( typeRowid==1 ); + testcase( typeRowid==2 ); + testcase( typeRowid==3 ); + testcase( typeRowid==4 ); + testcase( typeRowid==5 ); + testcase( typeRowid==6 ); + testcase( typeRowid==8 ); + testcase( typeRowid==9 ); + if( unlikely(typeRowid<1 || typeRowid>9 || typeRowid==7) ){ + goto idx_rowid_corruption; + } + lenRowid = sqlite3SmallTypeSizes[typeRowid]; + testcase( (u32)m.n==szHdr+lenRowid ); + if( unlikely((u32)m.npCursor; + Mem m; + + assert( sqlite3BtreeCursorIsValid(pCur) ); + VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey); + assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ + /* nCellKey will always be between 0 and 0xffffffff because of the way + ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ + if( nCellKey<=0 || nCellKey>0x7fffffff ){ + *res = 0; + return SQLITE_CORRUPT_BKPT; + } + sqlite3VdbeMemInit(&m, db, 0); + rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (u32)nCellKey, 1, &m); + if( rc ){ + return rc; + } + *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked); + sqlite3VdbeMemRelease(&m); + return SQLITE_OK; +} + +/* +** This routine sets the value to be returned by subsequent calls to +** sqlite3_changes() on the database handle 'db'. +*/ +SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){ + assert( sqlite3_mutex_held(db->mutex) ); + db->nChange = nChange; + db->nTotalChange += nChange; +} + +/* +** Set a flag in the vdbe to update the change counter when it is finalised +** or reset. +*/ +SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe *v){ + v->changeCntOn = 1; +} + +/* +** Mark every prepared statement associated with a database connection +** as expired. +** +** An expired statement means that recompilation of the statement is +** recommend. Statements expire when things happen that make their +** programs obsolete. Removing user-defined functions or collating +** sequences, or changing an authorization function are the types of +** things that make prepared statements obsolete. +*/ +SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db){ + Vdbe *p; + for(p = db->pVdbe; p; p=p->pNext){ + p->expired = 1; + } +} + +/* +** Return the database associated with the Vdbe. +*/ +SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){ + return v->db; +} + +/* +** Return a pointer to an sqlite3_value structure containing the value bound +** parameter iVar of VM v. Except, if the value is an SQL NULL, return +** 0 instead. Unless it is NULL, apply affinity aff (one of the SQLITE_AFF_* +** constants) to the value before returning it. +** +** The returned value must be freed by the caller using sqlite3ValueFree(). +*/ +SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){ + assert( iVar>0 ); + if( v ){ + Mem *pMem = &v->aVar[iVar-1]; + if( 0==(pMem->flags & MEM_Null) ){ + sqlite3_value *pRet = sqlite3ValueNew(v->db); + if( pRet ){ + sqlite3VdbeMemCopy((Mem *)pRet, pMem); + sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8); + } + return pRet; + } + } + return 0; +} + +/* +** Configure SQL variable iVar so that binding a new value to it signals +** to sqlite3_reoptimize() that re-preparing the statement may result +** in a better query plan. +*/ +SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ + assert( iVar>0 ); + if( iVar>32 ){ + v->expmask = 0xffffffff; + }else{ + v->expmask |= ((u32)1 << (iVar-1)); + } +} + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* +** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored +** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored +** in memory obtained from sqlite3DbMalloc). +*/ +SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){ + sqlite3 *db = p->db; + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg); + sqlite3_free(pVtab->zErrMsg); + pVtab->zErrMsg = 0; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +/************** End of vdbeaux.c *********************************************/ +/************** Begin file vdbeapi.c *****************************************/ +/* +** 2004 May 26 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains code use to implement APIs that are part of the +** VDBE. +*/ +/* #include "sqliteInt.h" */ +/* #include "vdbeInt.h" */ + +#ifndef SQLITE_OMIT_DEPRECATED +/* +** Return TRUE (non-zero) of the statement supplied as an argument needs +** to be recompiled. A statement needs to be recompiled whenever the +** execution environment changes in a way that would alter the program +** that sqlite3_prepare() generates. For example, if new functions or +** collating sequences are registered or if an authorizer function is +** added or changed. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt *pStmt){ + Vdbe *p = (Vdbe*)pStmt; + return p==0 || p->expired; +} +#endif + +/* +** Check on a Vdbe to make sure it has not been finalized. Log +** an error and return true if it has been finalized (or is otherwise +** invalid). Return false if it is ok. +*/ +static int vdbeSafety(Vdbe *p){ + if( p->db==0 ){ + sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement"); + return 1; + }else{ + return 0; + } +} +static int vdbeSafetyNotNull(Vdbe *p){ + if( p==0 ){ + sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement"); + return 1; + }else{ + return vdbeSafety(p); + } +} + +#ifndef SQLITE_OMIT_TRACE +/* +** Invoke the profile callback. This routine is only called if we already +** know that the profile callback is defined and needs to be invoked. +*/ +static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){ + sqlite3_int64 iNow; + assert( p->startTime>0 ); + assert( db->xProfile!=0 ); + assert( db->init.busy==0 ); + assert( p->zSql!=0 ); + sqlite3OsCurrentTimeInt64(db->pVfs, &iNow); + db->xProfile(db->pProfileArg, p->zSql, (iNow - p->startTime)*1000000); + p->startTime = 0; +} +/* +** The checkProfileCallback(DB,P) macro checks to see if a profile callback +** is needed, and it invokes the callback if it is needed. +*/ +# define checkProfileCallback(DB,P) \ + if( ((P)->startTime)>0 ){ invokeProfileCallback(DB,P); } +#else +# define checkProfileCallback(DB,P) /*no-op*/ +#endif + +/* +** The following routine destroys a virtual machine that is created by +** the sqlite3_compile() routine. The integer returned is an SQLITE_ +** success/failure code that describes the result of executing the virtual +** machine. +** +** This routine sets the error code and string returned by +** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt){ + int rc; + if( pStmt==0 ){ + /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL + ** pointer is a harmless no-op. */ + rc = SQLITE_OK; + }else{ + Vdbe *v = (Vdbe*)pStmt; + sqlite3 *db = v->db; + if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; + sqlite3_mutex_enter(db->mutex); + checkProfileCallback(db, v); + rc = sqlite3VdbeFinalize(v); + rc = sqlite3ApiExit(db, rc); + sqlite3LeaveMutexAndCloseZombie(db); + } + return rc; +} + +/* +** Terminate the current execution of an SQL statement and reset it +** back to its starting state so that it can be reused. A success code from +** the prior execution is returned. +** +** This routine sets the error code and string returned by +** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt){ + int rc; + if( pStmt==0 ){ + rc = SQLITE_OK; + }else{ + Vdbe *v = (Vdbe*)pStmt; + sqlite3 *db = v->db; + sqlite3_mutex_enter(db->mutex); + checkProfileCallback(db, v); + rc = sqlite3VdbeReset(v); + sqlite3VdbeRewind(v); + assert( (rc & (db->errMask))==rc ); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + } + return rc; +} + +/* +** Set all the parameters in the compiled SQL statement to NULL. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt *pStmt){ + int i; + int rc = SQLITE_OK; + Vdbe *p = (Vdbe*)pStmt; +#if SQLITE_THREADSAFE + sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex; +#endif + sqlite3_mutex_enter(mutex); + for(i=0; inVar; i++){ + sqlite3VdbeMemRelease(&p->aVar[i]); + p->aVar[i].flags = MEM_Null; + } + if( p->isPrepareV2 && p->expmask ){ + p->expired = 1; + } + sqlite3_mutex_leave(mutex); + return rc; +} + + +/**************************** sqlite3_value_ ******************************* +** The following routines extract information from a Mem or sqlite3_value +** structure. +*/ +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value *pVal){ + Mem *p = (Mem*)pVal; + if( p->flags & (MEM_Blob|MEM_Str) ){ + if( sqlite3VdbeMemExpandBlob(p)!=SQLITE_OK ){ + assert( p->flags==MEM_Null && p->z==0 ); + return 0; + } + p->flags |= MEM_Blob; + return p->n ? p->z : 0; + }else{ + return sqlite3_value_text(pVal); + } +} +SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value *pVal){ + return sqlite3ValueBytes(pVal, SQLITE_UTF8); +} +SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value *pVal){ + return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE); +} +SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value *pVal){ + return sqlite3VdbeRealValue((Mem*)pVal); +} +SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value *pVal){ + return (int)sqlite3VdbeIntValue((Mem*)pVal); +} +SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value *pVal){ + return sqlite3VdbeIntValue((Mem*)pVal); +} +SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value *pVal){ + return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); +} +#ifndef SQLITE_OMIT_UTF16 +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value* pVal){ + return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); +} +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value *pVal){ + return sqlite3ValueText(pVal, SQLITE_UTF16BE); +} +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value *pVal){ + return sqlite3ValueText(pVal, SQLITE_UTF16LE); +} +#endif /* SQLITE_OMIT_UTF16 */ +/* EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five +** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating +** point number string BLOB NULL +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value* pVal){ + static const u8 aType[] = { + SQLITE_BLOB, /* 0x00 */ + SQLITE_NULL, /* 0x01 */ + SQLITE_TEXT, /* 0x02 */ + SQLITE_NULL, /* 0x03 */ + SQLITE_INTEGER, /* 0x04 */ + SQLITE_NULL, /* 0x05 */ + SQLITE_INTEGER, /* 0x06 */ + SQLITE_NULL, /* 0x07 */ + SQLITE_FLOAT, /* 0x08 */ + SQLITE_NULL, /* 0x09 */ + SQLITE_FLOAT, /* 0x0a */ + SQLITE_NULL, /* 0x0b */ + SQLITE_INTEGER, /* 0x0c */ + SQLITE_NULL, /* 0x0d */ + SQLITE_INTEGER, /* 0x0e */ + SQLITE_NULL, /* 0x0f */ + SQLITE_BLOB, /* 0x10 */ + SQLITE_NULL, /* 0x11 */ + SQLITE_TEXT, /* 0x12 */ + SQLITE_NULL, /* 0x13 */ + SQLITE_INTEGER, /* 0x14 */ + SQLITE_NULL, /* 0x15 */ + SQLITE_INTEGER, /* 0x16 */ + SQLITE_NULL, /* 0x17 */ + SQLITE_FLOAT, /* 0x18 */ + SQLITE_NULL, /* 0x19 */ + SQLITE_FLOAT, /* 0x1a */ + SQLITE_NULL, /* 0x1b */ + SQLITE_INTEGER, /* 0x1c */ + SQLITE_NULL, /* 0x1d */ + SQLITE_INTEGER, /* 0x1e */ + SQLITE_NULL, /* 0x1f */ + }; + return aType[pVal->flags&MEM_AffMask]; +} + +/* Make a copy of an sqlite3_value object +*/ +SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value *pOrig){ + sqlite3_value *pNew; + if( pOrig==0 ) return 0; + pNew = sqlite3_malloc( sizeof(*pNew) ); + if( pNew==0 ) return 0; + memset(pNew, 0, sizeof(*pNew)); + memcpy(pNew, pOrig, MEMCELLSIZE); + pNew->flags &= ~MEM_Dyn; + pNew->db = 0; + if( pNew->flags&(MEM_Str|MEM_Blob) ){ + pNew->flags &= ~(MEM_Static|MEM_Dyn); + pNew->flags |= MEM_Ephem; + if( sqlite3VdbeMemMakeWriteable(pNew)!=SQLITE_OK ){ + sqlite3ValueFree(pNew); + pNew = 0; + } + } + return pNew; +} + +/* Destroy an sqlite3_value object previously obtained from +** sqlite3_value_dup(). +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value *pOld){ + sqlite3ValueFree(pOld); +} + + +/**************************** sqlite3_result_ ******************************* +** The following routines are used by user-defined functions to specify +** the function result. +** +** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the +** result as a string or blob but if the string or blob is too large, it +** then sets the error code to SQLITE_TOOBIG +** +** The invokeValueDestructor(P,X) routine invokes destructor function X() +** on value P is not going to be used and need to be destroyed. +*/ +static void setResultStrOrError( + sqlite3_context *pCtx, /* Function context */ + const char *z, /* String pointer */ + int n, /* Bytes in string, or negative */ + u8 enc, /* Encoding of z. 0 for BLOBs */ + void (*xDel)(void*) /* Destructor function */ +){ + if( sqlite3VdbeMemSetStr(pCtx->pOut, z, n, enc, xDel)==SQLITE_TOOBIG ){ + sqlite3_result_error_toobig(pCtx); + } +} +static int invokeValueDestructor( + const void *p, /* Value to destroy */ + void (*xDel)(void*), /* The destructor */ + sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if no NULL */ +){ + assert( xDel!=SQLITE_DYNAMIC ); + if( xDel==0 ){ + /* noop */ + }else if( xDel==SQLITE_TRANSIENT ){ + /* noop */ + }else{ + xDel((void*)p); + } + if( pCtx ) sqlite3_result_error_toobig(pCtx); + return SQLITE_TOOBIG; +} +SQLITE_API void SQLITE_STDCALL sqlite3_result_blob( + sqlite3_context *pCtx, + const void *z, + int n, + void (*xDel)(void *) +){ + assert( n>=0 ); + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + setResultStrOrError(pCtx, z, n, 0, xDel); +} +SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64( + sqlite3_context *pCtx, + const void *z, + sqlite3_uint64 n, + void (*xDel)(void *) +){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + assert( xDel!=SQLITE_DYNAMIC ); + if( n>0x7fffffff ){ + (void)invokeValueDestructor(z, xDel, pCtx); + }else{ + setResultStrOrError(pCtx, z, (int)n, 0, xDel); + } +} +SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context *pCtx, double rVal){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + sqlite3VdbeMemSetDouble(pCtx->pOut, rVal); +} +SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + pCtx->isError = SQLITE_ERROR; + pCtx->fErrorOrAux = 1; + sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); +} +#ifndef SQLITE_OMIT_UTF16 +SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + pCtx->isError = SQLITE_ERROR; + pCtx->fErrorOrAux = 1; + sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); +} +#endif +SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context *pCtx, int iVal){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + sqlite3VdbeMemSetInt64(pCtx->pOut, (i64)iVal); +} +SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + sqlite3VdbeMemSetInt64(pCtx->pOut, iVal); +} +SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + sqlite3VdbeMemSetNull(pCtx->pOut); +} +SQLITE_API void SQLITE_STDCALL sqlite3_result_text( + sqlite3_context *pCtx, + const char *z, + int n, + void (*xDel)(void *) +){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel); +} +SQLITE_API void SQLITE_STDCALL sqlite3_result_text64( + sqlite3_context *pCtx, + const char *z, + sqlite3_uint64 n, + void (*xDel)(void *), + unsigned char enc +){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + assert( xDel!=SQLITE_DYNAMIC ); + if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; + if( n>0x7fffffff ){ + (void)invokeValueDestructor(z, xDel, pCtx); + }else{ + setResultStrOrError(pCtx, z, (int)n, enc, xDel); + } +} +#ifndef SQLITE_OMIT_UTF16 +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16( + sqlite3_context *pCtx, + const void *z, + int n, + void (*xDel)(void *) +){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel); +} +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be( + sqlite3_context *pCtx, + const void *z, + int n, + void (*xDel)(void *) +){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel); +} +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le( + sqlite3_context *pCtx, + const void *z, + int n, + void (*xDel)(void *) +){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel); +} +#endif /* SQLITE_OMIT_UTF16 */ +SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + sqlite3VdbeMemCopy(pCtx->pOut, pValue); +} +SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n); +} +SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ + Mem *pOut = pCtx->pOut; + assert( sqlite3_mutex_held(pOut->db->mutex) ); + if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){ + return SQLITE_TOOBIG; + } + sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n); + return SQLITE_OK; +} +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ + pCtx->isError = errCode; + pCtx->fErrorOrAux = 1; +#ifdef SQLITE_DEBUG + if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; +#endif + if( pCtx->pOut->flags & MEM_Null ){ + sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1, + SQLITE_UTF8, SQLITE_STATIC); + } +} + +/* Force an SQLITE_TOOBIG error. */ +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + pCtx->isError = SQLITE_TOOBIG; + pCtx->fErrorOrAux = 1; + sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1, + SQLITE_UTF8, SQLITE_STATIC); +} + +/* An SQLITE_NOMEM error. */ +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + sqlite3VdbeMemSetNull(pCtx->pOut); + pCtx->isError = SQLITE_NOMEM; + pCtx->fErrorOrAux = 1; + pCtx->pOut->db->mallocFailed = 1; +} + +/* +** This function is called after a transaction has been committed. It +** invokes callbacks registered with sqlite3_wal_hook() as required. +*/ +static int doWalCallbacks(sqlite3 *db){ + int rc = SQLITE_OK; +#ifndef SQLITE_OMIT_WAL + int i; + for(i=0; inDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + int nEntry; + sqlite3BtreeEnter(pBt); + nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); + sqlite3BtreeLeave(pBt); + if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ + rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); + } + } + } +#endif + return rc; +} + + +/* +** Execute the statement pStmt, either until a row of data is ready, the +** statement is completely executed or an error occurs. +** +** This routine implements the bulk of the logic behind the sqlite_step() +** API. The only thing omitted is the automatic recompile if a +** schema change has occurred. That detail is handled by the +** outer sqlite3_step() wrapper procedure. +*/ +static int sqlite3Step(Vdbe *p){ + sqlite3 *db; + int rc; + + assert(p); + if( p->magic!=VDBE_MAGIC_RUN ){ + /* We used to require that sqlite3_reset() be called before retrying + ** sqlite3_step() after any error or after SQLITE_DONE. But beginning + ** with version 3.7.0, we changed this so that sqlite3_reset() would + ** be called automatically instead of throwing the SQLITE_MISUSE error. + ** This "automatic-reset" change is not technically an incompatibility, + ** since any application that receives an SQLITE_MISUSE is broken by + ** definition. + ** + ** Nevertheless, some published applications that were originally written + ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE + ** returns, and those were broken by the automatic-reset change. As a + ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the + ** legacy behavior of returning SQLITE_MISUSE for cases where the + ** previous sqlite3_step() returned something other than a SQLITE_LOCKED + ** or SQLITE_BUSY error. + */ +#ifdef SQLITE_OMIT_AUTORESET + if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){ + sqlite3_reset((sqlite3_stmt*)p); + }else{ + return SQLITE_MISUSE_BKPT; + } +#else + sqlite3_reset((sqlite3_stmt*)p); +#endif + } + + /* Check that malloc() has not failed. If it has, return early. */ + db = p->db; + if( db->mallocFailed ){ + p->rc = SQLITE_NOMEM; + return SQLITE_NOMEM; + } + + if( p->pc<=0 && p->expired ){ + p->rc = SQLITE_SCHEMA; + rc = SQLITE_ERROR; + goto end_of_step; + } + if( p->pc<0 ){ + /* If there are no other statements currently running, then + ** reset the interrupt flag. This prevents a call to sqlite3_interrupt + ** from interrupting a statement that has not yet started. + */ + if( db->nVdbeActive==0 ){ + db->u1.isInterrupted = 0; + } + + assert( db->nVdbeWrite>0 || db->autoCommit==0 + || (db->nDeferredCons==0 && db->nDeferredImmCons==0) + ); + +#ifndef SQLITE_OMIT_TRACE + if( db->xProfile && !db->init.busy && p->zSql ){ + sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); + }else{ + assert( p->startTime==0 ); + } +#endif + + db->nVdbeActive++; + if( p->readOnly==0 ) db->nVdbeWrite++; + if( p->bIsReader ) db->nVdbeRead++; + p->pc = 0; + } +#ifdef SQLITE_DEBUG + p->rcApp = SQLITE_OK; +#endif +#ifndef SQLITE_OMIT_EXPLAIN + if( p->explain ){ + rc = sqlite3VdbeList(p); + }else +#endif /* SQLITE_OMIT_EXPLAIN */ + { + db->nVdbeExec++; + rc = sqlite3VdbeExec(p); + db->nVdbeExec--; + } + +#ifndef SQLITE_OMIT_TRACE + /* If the statement completed successfully, invoke the profile callback */ + if( rc!=SQLITE_ROW ) checkProfileCallback(db, p); +#endif + + if( rc==SQLITE_DONE ){ + assert( p->rc==SQLITE_OK ); + p->rc = doWalCallbacks(db); + if( p->rc!=SQLITE_OK ){ + rc = SQLITE_ERROR; + } + } + + db->errCode = rc; + if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){ + p->rc = SQLITE_NOMEM; + } +end_of_step: + /* At this point local variable rc holds the value that should be + ** returned if this statement was compiled using the legacy + ** sqlite3_prepare() interface. According to the docs, this can only + ** be one of the values in the first assert() below. Variable p->rc + ** contains the value that would be returned if sqlite3_finalize() + ** were called on statement p. + */ + assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR + || rc==SQLITE_BUSY || rc==SQLITE_MISUSE + ); + assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp ); + if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){ + /* If this statement was prepared using sqlite3_prepare_v2(), and an + ** error has occurred, then return the error code in p->rc to the + ** caller. Set the error code in the database handle to the same value. + */ + rc = sqlite3VdbeTransferError(p); + } + return (rc&db->errMask); +} + +/* +** This is the top-level implementation of sqlite3_step(). Call +** sqlite3Step() to do most of the work. If a schema error occurs, +** call sqlite3Reprepare() and try again. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt *pStmt){ + int rc = SQLITE_OK; /* Result from sqlite3Step() */ + int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */ + Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */ + int cnt = 0; /* Counter to prevent infinite loop of reprepares */ + sqlite3 *db; /* The database connection */ + + if( vdbeSafetyNotNull(v) ){ + return SQLITE_MISUSE_BKPT; + } + db = v->db; + sqlite3_mutex_enter(db->mutex); + v->doingRerun = 0; + while( (rc = sqlite3Step(v))==SQLITE_SCHEMA + && cnt++ < SQLITE_MAX_SCHEMA_RETRY ){ + int savedPc = v->pc; + rc2 = rc = sqlite3Reprepare(v); + if( rc!=SQLITE_OK) break; + sqlite3_reset(pStmt); + if( savedPc>=0 ) v->doingRerun = 1; + assert( v->expired==0 ); + } + if( rc2!=SQLITE_OK ){ + /* This case occurs after failing to recompile an sql statement. + ** The error message from the SQL compiler has already been loaded + ** into the database handle. This block copies the error message + ** from the database handle into the statement and sets the statement + ** program counter to 0 to ensure that when the statement is + ** finalized or reset the parser error message is available via + ** sqlite3_errmsg() and sqlite3_errcode(). + */ + const char *zErr = (const char *)sqlite3_value_text(db->pErr); + sqlite3DbFree(db, v->zErrMsg); + if( !db->mallocFailed ){ + v->zErrMsg = sqlite3DbStrDup(db, zErr); + v->rc = rc2; + } else { + v->zErrMsg = 0; + v->rc = rc = SQLITE_NOMEM; + } + } + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + + +/* +** Extract the user data from a sqlite3_context structure and return a +** pointer to it. +*/ +SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context *p){ + assert( p && p->pFunc ); + return p->pFunc->pUserData; +} + +/* +** Extract the user data from a sqlite3_context structure and return a +** pointer to it. +** +** IMPLEMENTATION-OF: R-46798-50301 The sqlite3_context_db_handle() interface +** returns a copy of the pointer to the database connection (the 1st +** parameter) of the sqlite3_create_function() and +** sqlite3_create_function16() routines that originally registered the +** application defined function. +*/ +SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context *p){ + assert( p && p->pFunc ); + return p->pOut->db; +} + +/* +** Return the current time for a statement. If the current time +** is requested more than once within the same run of a single prepared +** statement, the exact same time is returned for each invocation regardless +** of the amount of time that elapses between invocations. In other words, +** the time returned is always the time of the first call. +*/ +SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){ + int rc; +#ifndef SQLITE_ENABLE_STAT3_OR_STAT4 + sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime; + assert( p->pVdbe!=0 ); +#else + sqlite3_int64 iTime = 0; + sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime; +#endif + if( *piTime==0 ){ + rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime); + if( rc ) *piTime = 0; + } + return *piTime; +} + +/* +** The following is the implementation of an SQL function that always +** fails with an error message stating that the function is used in the +** wrong context. The sqlite3_overload_function() API might construct +** SQL function that use this routine so that the functions will exist +** for name resolution but are actually overloaded by the xFindFunction +** method of virtual tables. +*/ +SQLITE_PRIVATE void sqlite3InvalidFunction( + sqlite3_context *context, /* The function calling context */ + int NotUsed, /* Number of arguments to the function */ + sqlite3_value **NotUsed2 /* Value of each argument */ +){ + const char *zName = context->pFunc->zName; + char *zErr; + UNUSED_PARAMETER2(NotUsed, NotUsed2); + zErr = sqlite3_mprintf( + "unable to use function %s in the requested context", zName); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); +} + +/* +** Create a new aggregate context for p and return a pointer to +** its pMem->z element. +*/ +static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){ + Mem *pMem = p->pMem; + assert( (pMem->flags & MEM_Agg)==0 ); + if( nByte<=0 ){ + sqlite3VdbeMemSetNull(pMem); + pMem->z = 0; + }else{ + sqlite3VdbeMemClearAndResize(pMem, nByte); + pMem->flags = MEM_Agg; + pMem->u.pDef = p->pFunc; + if( pMem->z ){ + memset(pMem->z, 0, nByte); + } + } + return (void*)pMem->z; +} + +/* +** Allocate or return the aggregate context for a user function. A new +** context is allocated on the first call. Subsequent calls return the +** same context that was returned on prior calls. +*/ +SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context *p, int nByte){ + assert( p && p->pFunc && p->pFunc->xStep ); + assert( sqlite3_mutex_held(p->pOut->db->mutex) ); + testcase( nByte<0 ); + if( (p->pMem->flags & MEM_Agg)==0 ){ + return createAggContext(p, nByte); + }else{ + return (void*)p->pMem->z; + } +} + +/* +** Return the auxiliary data pointer, if any, for the iArg'th argument to +** the user-function defined by pCtx. +*/ +SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ + AuxData *pAuxData; + + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); +#if SQLITE_ENABLE_STAT3_OR_STAT4 + if( pCtx->pVdbe==0 ) return 0; +#else + assert( pCtx->pVdbe!=0 ); +#endif + for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){ + if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break; + } + + return (pAuxData ? pAuxData->pAux : 0); +} + +/* +** Set the auxiliary data pointer and delete function, for the iArg'th +** argument to the user-function defined by pCtx. Any previous value is +** deleted by calling the delete function specified when it was set. +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata( + sqlite3_context *pCtx, + int iArg, + void *pAux, + void (*xDelete)(void*) +){ + AuxData *pAuxData; + Vdbe *pVdbe = pCtx->pVdbe; + + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + if( iArg<0 ) goto failed; +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( pVdbe==0 ) goto failed; +#else + assert( pVdbe!=0 ); +#endif + + for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){ + if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break; + } + if( pAuxData==0 ){ + pAuxData = sqlite3DbMallocZero(pVdbe->db, sizeof(AuxData)); + if( !pAuxData ) goto failed; + pAuxData->iOp = pCtx->iOp; + pAuxData->iArg = iArg; + pAuxData->pNext = pVdbe->pAuxData; + pVdbe->pAuxData = pAuxData; + if( pCtx->fErrorOrAux==0 ){ + pCtx->isError = 0; + pCtx->fErrorOrAux = 1; + } + }else if( pAuxData->xDelete ){ + pAuxData->xDelete(pAuxData->pAux); + } + + pAuxData->pAux = pAux; + pAuxData->xDelete = xDelete; + return; + +failed: + if( xDelete ){ + xDelete(pAux); + } +} + +#ifndef SQLITE_OMIT_DEPRECATED +/* +** Return the number of times the Step function of an aggregate has been +** called. +** +** This function is deprecated. Do not use it for new code. It is +** provide only to avoid breaking legacy code. New aggregate function +** implementations should keep their own counts within their aggregate +** context. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context *p){ + assert( p && p->pMem && p->pFunc && p->pFunc->xStep ); + return p->pMem->n; +} +#endif + +/* +** Return the number of columns in the result set for the statement pStmt. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt){ + Vdbe *pVm = (Vdbe *)pStmt; + return pVm ? pVm->nResColumn : 0; +} + +/* +** Return the number of values available from the current row of the +** currently executing statement pStmt. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt){ + Vdbe *pVm = (Vdbe *)pStmt; + if( pVm==0 || pVm->pResultSet==0 ) return 0; + return pVm->nResColumn; +} + +/* +** Return a pointer to static memory containing an SQL NULL value. +*/ +static const Mem *columnNullValue(void){ + /* Even though the Mem structure contains an element + ** of type i64, on certain architectures (x86) with certain compiler + ** switches (-Os), gcc may align this Mem object on a 4-byte boundary + ** instead of an 8-byte one. This all works fine, except that when + ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s + ** that a Mem structure is located on an 8-byte boundary. To prevent + ** these assert()s from failing, when building with SQLITE_DEBUG defined + ** using gcc, we force nullMem to be 8-byte aligned using the magical + ** __attribute__((aligned(8))) macro. */ + static const Mem nullMem +#if defined(SQLITE_DEBUG) && defined(__GNUC__) + __attribute__((aligned(8))) +#endif + = { + /* .u = */ {0}, + /* .flags = */ MEM_Null, + /* .enc = */ 0, + /* .n = */ 0, + /* .z = */ 0, + /* .zMalloc = */ 0, + /* .szMalloc = */ 0, + /* .iPadding1 = */ 0, + /* .db = */ 0, + /* .xDel = */ 0, +#ifdef SQLITE_DEBUG + /* .pScopyFrom = */ 0, + /* .pFiller = */ 0, +#endif + }; + return &nullMem; +} + +/* +** Check to see if column iCol of the given statement is valid. If +** it is, return a pointer to the Mem for the value of that column. +** If iCol is not valid, return a pointer to a Mem which has a value +** of NULL. +*/ +static Mem *columnMem(sqlite3_stmt *pStmt, int i){ + Vdbe *pVm; + Mem *pOut; + + pVm = (Vdbe *)pStmt; + if( pVm && pVm->pResultSet!=0 && inResColumn && i>=0 ){ + sqlite3_mutex_enter(pVm->db->mutex); + pOut = &pVm->pResultSet[i]; + }else{ + if( pVm && ALWAYS(pVm->db) ){ + sqlite3_mutex_enter(pVm->db->mutex); + sqlite3Error(pVm->db, SQLITE_RANGE); + } + pOut = (Mem*)columnNullValue(); + } + return pOut; +} + +/* +** This function is called after invoking an sqlite3_value_XXX function on a +** column value (i.e. a value returned by evaluating an SQL expression in the +** select list of a SELECT statement) that may cause a malloc() failure. If +** malloc() has failed, the threads mallocFailed flag is cleared and the result +** code of statement pStmt set to SQLITE_NOMEM. +** +** Specifically, this is called from within: +** +** sqlite3_column_int() +** sqlite3_column_int64() +** sqlite3_column_text() +** sqlite3_column_text16() +** sqlite3_column_real() +** sqlite3_column_bytes() +** sqlite3_column_bytes16() +** sqiite3_column_blob() +*/ +static void columnMallocFailure(sqlite3_stmt *pStmt) +{ + /* If malloc() failed during an encoding conversion within an + ** sqlite3_column_XXX API, then set the return code of the statement to + ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR + ** and _finalize() will return NOMEM. + */ + Vdbe *p = (Vdbe *)pStmt; + if( p ){ + p->rc = sqlite3ApiExit(p->db, p->rc); + sqlite3_mutex_leave(p->db->mutex); + } +} + +/**************************** sqlite3_column_ ******************************* +** The following routines are used to access elements of the current row +** in the result set. +*/ +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ + const void *val; + val = sqlite3_value_blob( columnMem(pStmt,i) ); + /* Even though there is no encoding conversion, value_blob() might + ** need to call malloc() to expand the result of a zeroblob() + ** expression. + */ + columnMallocFailure(pStmt); + return val; +} +SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ + int val = sqlite3_value_bytes( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ + int val = sqlite3_value_bytes16( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt *pStmt, int i){ + double val = sqlite3_value_double( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt *pStmt, int i){ + int val = sqlite3_value_int( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ + sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt *pStmt, int i){ + const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt *pStmt, int i){ + Mem *pOut = columnMem(pStmt, i); + if( pOut->flags&MEM_Static ){ + pOut->flags &= ~MEM_Static; + pOut->flags |= MEM_Ephem; + } + columnMallocFailure(pStmt); + return (sqlite3_value *)pOut; +} +#ifndef SQLITE_OMIT_UTF16 +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ + const void *val = sqlite3_value_text16( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +#endif /* SQLITE_OMIT_UTF16 */ +SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt *pStmt, int i){ + int iType = sqlite3_value_type( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return iType; +} + +/* +** Convert the N-th element of pStmt->pColName[] into a string using +** xFunc() then return that string. If N is out of range, return 0. +** +** There are up to 5 names for each column. useType determines which +** name is returned. Here are the names: +** +** 0 The column name as it should be displayed for output +** 1 The datatype name for the column +** 2 The name of the database that the column derives from +** 3 The name of the table that the column derives from +** 4 The name of the table column that the result column derives from +** +** If the result is not a simple column reference (if it is an expression +** or a constant) then useTypes 2, 3, and 4 return NULL. +*/ +static const void *columnName( + sqlite3_stmt *pStmt, + int N, + const void *(*xFunc)(Mem*), + int useType +){ + const void *ret; + Vdbe *p; + int n; + sqlite3 *db; +#ifdef SQLITE_ENABLE_API_ARMOR + if( pStmt==0 ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + ret = 0; + p = (Vdbe *)pStmt; + db = p->db; + assert( db!=0 ); + n = sqlite3_column_count(pStmt); + if( N=0 ){ + N += useType*n; + sqlite3_mutex_enter(db->mutex); + assert( db->mallocFailed==0 ); + ret = xFunc(&p->aColName[N]); + /* A malloc may have failed inside of the xFunc() call. If this + ** is the case, clear the mallocFailed flag and return NULL. + */ + if( db->mallocFailed ){ + db->mallocFailed = 0; + ret = 0; + } + sqlite3_mutex_leave(db->mutex); + } + return ret; +} + +/* +** Return the name of the Nth column of the result set returned by SQL +** statement pStmt. +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME); +} +#ifndef SQLITE_OMIT_UTF16 +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME); +} +#endif + +/* +** Constraint: If you have ENABLE_COLUMN_METADATA then you must +** not define OMIT_DECLTYPE. +*/ +#if defined(SQLITE_OMIT_DECLTYPE) && defined(SQLITE_ENABLE_COLUMN_METADATA) +# error "Must not define both SQLITE_OMIT_DECLTYPE \ + and SQLITE_ENABLE_COLUMN_METADATA" +#endif + +#ifndef SQLITE_OMIT_DECLTYPE +/* +** Return the column declaration type (if applicable) of the 'i'th column +** of the result set of SQL statement pStmt. +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE); +} +#ifndef SQLITE_OMIT_UTF16 +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE); +} +#endif /* SQLITE_OMIT_UTF16 */ +#endif /* SQLITE_OMIT_DECLTYPE */ + +#ifdef SQLITE_ENABLE_COLUMN_METADATA +/* +** Return the name of the database from which a result column derives. +** NULL is returned if the result column is an expression or constant or +** anything else which is not an unambiguous reference to a database column. +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE); +} +#ifndef SQLITE_OMIT_UTF16 +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE); +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** Return the name of the table from which a result column derives. +** NULL is returned if the result column is an expression or constant or +** anything else which is not an unambiguous reference to a database column. +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE); +} +#ifndef SQLITE_OMIT_UTF16 +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE); +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** Return the name of the table column from which a result column derives. +** NULL is returned if the result column is an expression or constant or +** anything else which is not an unambiguous reference to a database column. +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN); +} +#ifndef SQLITE_OMIT_UTF16 +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN); +} +#endif /* SQLITE_OMIT_UTF16 */ +#endif /* SQLITE_ENABLE_COLUMN_METADATA */ + + +/******************************* sqlite3_bind_ *************************** +** +** Routines used to attach values to wildcards in a compiled SQL statement. +*/ +/* +** Unbind the value bound to variable i in virtual machine p. This is the +** the same as binding a NULL value to the column. If the "i" parameter is +** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK. +** +** A successful evaluation of this routine acquires the mutex on p. +** the mutex is released if any kind of error occurs. +** +** The error code stored in database p->db is overwritten with the return +** value in any case. +*/ +static int vdbeUnbind(Vdbe *p, int i){ + Mem *pVar; + if( vdbeSafetyNotNull(p) ){ + return SQLITE_MISUSE_BKPT; + } + sqlite3_mutex_enter(p->db->mutex); + if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ + sqlite3Error(p->db, SQLITE_MISUSE); + sqlite3_mutex_leave(p->db->mutex); + sqlite3_log(SQLITE_MISUSE, + "bind on a busy prepared statement: [%s]", p->zSql); + return SQLITE_MISUSE_BKPT; + } + if( i<1 || i>p->nVar ){ + sqlite3Error(p->db, SQLITE_RANGE); + sqlite3_mutex_leave(p->db->mutex); + return SQLITE_RANGE; + } + i--; + pVar = &p->aVar[i]; + sqlite3VdbeMemRelease(pVar); + pVar->flags = MEM_Null; + sqlite3Error(p->db, SQLITE_OK); + + /* If the bit corresponding to this variable in Vdbe.expmask is set, then + ** binding a new value to this variable invalidates the current query plan. + ** + ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host + ** parameter in the WHERE clause might influence the choice of query plan + ** for a statement, then the statement will be automatically recompiled, + ** as if there had been a schema change, on the first sqlite3_step() call + ** following any change to the bindings of that parameter. + */ + if( p->isPrepareV2 && + ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff) + ){ + p->expired = 1; + } + return SQLITE_OK; +} + +/* +** Bind a text or BLOB value. +*/ +static int bindText( + sqlite3_stmt *pStmt, /* The statement to bind against */ + int i, /* Index of the parameter to bind */ + const void *zData, /* Pointer to the data to be bound */ + int nData, /* Number of bytes of data to be bound */ + void (*xDel)(void*), /* Destructor for the data */ + u8 encoding /* Encoding for the data */ +){ + Vdbe *p = (Vdbe *)pStmt; + Mem *pVar; + int rc; + + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + if( zData!=0 ){ + pVar = &p->aVar[i-1]; + rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); + if( rc==SQLITE_OK && encoding!=0 ){ + rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); + } + sqlite3Error(p->db, rc); + rc = sqlite3ApiExit(p->db, rc); + } + sqlite3_mutex_leave(p->db->mutex); + }else if( xDel!=SQLITE_STATIC && xDel!=SQLITE_TRANSIENT ){ + xDel((void*)zData); + } + return rc; +} + + +/* +** Bind a blob value to an SQL statement variable. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob( + sqlite3_stmt *pStmt, + int i, + const void *zData, + int nData, + void (*xDel)(void*) +){ + return bindText(pStmt, i, zData, nData, xDel, 0); +} +SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64( + sqlite3_stmt *pStmt, + int i, + const void *zData, + sqlite3_uint64 nData, + void (*xDel)(void*) +){ + assert( xDel!=SQLITE_DYNAMIC ); + if( nData>0x7fffffff ){ + return invokeValueDestructor(zData, xDel, 0); + }else{ + return bindText(pStmt, i, zData, (int)nData, xDel, 0); + } +} +SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ + int rc; + Vdbe *p = (Vdbe *)pStmt; + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue); + sqlite3_mutex_leave(p->db->mutex); + } + return rc; +} +SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ + return sqlite3_bind_int64(p, i, (i64)iValue); +} +SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ + int rc; + Vdbe *p = (Vdbe *)pStmt; + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue); + sqlite3_mutex_leave(p->db->mutex); + } + return rc; +} +SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ + int rc; + Vdbe *p = (Vdbe*)pStmt; + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + sqlite3_mutex_leave(p->db->mutex); + } + return rc; +} +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text( + sqlite3_stmt *pStmt, + int i, + const char *zData, + int nData, + void (*xDel)(void*) +){ + return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8); +} +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64( + sqlite3_stmt *pStmt, + int i, + const char *zData, + sqlite3_uint64 nData, + void (*xDel)(void*), + unsigned char enc +){ + assert( xDel!=SQLITE_DYNAMIC ); + if( nData>0x7fffffff ){ + return invokeValueDestructor(zData, xDel, 0); + }else{ + if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; + return bindText(pStmt, i, zData, (int)nData, xDel, enc); + } +} +#ifndef SQLITE_OMIT_UTF16 +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16( + sqlite3_stmt *pStmt, + int i, + const void *zData, + int nData, + void (*xDel)(void*) +){ + return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE); +} +#endif /* SQLITE_OMIT_UTF16 */ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ + int rc; + switch( sqlite3_value_type((sqlite3_value*)pValue) ){ + case SQLITE_INTEGER: { + rc = sqlite3_bind_int64(pStmt, i, pValue->u.i); + break; + } + case SQLITE_FLOAT: { + rc = sqlite3_bind_double(pStmt, i, pValue->u.r); + break; + } + case SQLITE_BLOB: { + if( pValue->flags & MEM_Zero ){ + rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero); + }else{ + rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT); + } + break; + } + case SQLITE_TEXT: { + rc = bindText(pStmt,i, pValue->z, pValue->n, SQLITE_TRANSIENT, + pValue->enc); + break; + } + default: { + rc = sqlite3_bind_null(pStmt, i); + break; + } + } + return rc; +} +SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ + int rc; + Vdbe *p = (Vdbe *)pStmt; + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); + sqlite3_mutex_leave(p->db->mutex); + } + return rc; +} +SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){ + int rc; + Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); + if( n>(u64)p->db->aLimit[SQLITE_LIMIT_LENGTH] ){ + rc = SQLITE_TOOBIG; + }else{ + assert( (n & 0x7FFFFFFF)==n ); + rc = sqlite3_bind_zeroblob(pStmt, i, n); + } + rc = sqlite3ApiExit(p->db, rc); + sqlite3_mutex_leave(p->db->mutex); + return rc; +} + +/* +** Return the number of wildcards that can be potentially bound to. +** This routine is added to support DBD::SQLite. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ + Vdbe *p = (Vdbe*)pStmt; + return p ? p->nVar : 0; +} + +/* +** Return the name of a wildcard parameter. Return NULL if the index +** is out of range or if the wildcard is unnamed. +** +** The result is always UTF-8. +*/ +SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ + Vdbe *p = (Vdbe*)pStmt; + if( p==0 || i<1 || i>p->nzVar ){ + return 0; + } + return p->azVar[i-1]; +} + +/* +** Given a wildcard parameter name, return the index of the variable +** with that name. If there is no variable with the given name, +** return 0. +*/ +SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){ + int i; + if( p==0 ){ + return 0; + } + if( zName ){ + for(i=0; inzVar; i++){ + const char *z = p->azVar[i]; + if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){ + return i+1; + } + } + } + return 0; +} +SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ + return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName)); +} + +/* +** Transfer all bindings from the first statement over to the second. +*/ +SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ + Vdbe *pFrom = (Vdbe*)pFromStmt; + Vdbe *pTo = (Vdbe*)pToStmt; + int i; + assert( pTo->db==pFrom->db ); + assert( pTo->nVar==pFrom->nVar ); + sqlite3_mutex_enter(pTo->db->mutex); + for(i=0; inVar; i++){ + sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]); + } + sqlite3_mutex_leave(pTo->db->mutex); + return SQLITE_OK; +} + +#ifndef SQLITE_OMIT_DEPRECATED +/* +** Deprecated external interface. Internal/core SQLite code +** should call sqlite3TransferBindings. +** +** It is misuse to call this routine with statements from different +** database connections. But as this is a deprecated interface, we +** will not bother to check for that condition. +** +** If the two statements contain a different number of bindings, then +** an SQLITE_ERROR is returned. Nothing else can go wrong, so otherwise +** SQLITE_OK is returned. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ + Vdbe *pFrom = (Vdbe*)pFromStmt; + Vdbe *pTo = (Vdbe*)pToStmt; + if( pFrom->nVar!=pTo->nVar ){ + return SQLITE_ERROR; + } + if( pTo->isPrepareV2 && pTo->expmask ){ + pTo->expired = 1; + } + if( pFrom->isPrepareV2 && pFrom->expmask ){ + pFrom->expired = 1; + } + return sqlite3TransferBindings(pFromStmt, pToStmt); +} +#endif + +/* +** Return the sqlite3* database handle to which the prepared statement given +** in the argument belongs. This is the same database handle that was +** the first argument to the sqlite3_prepare() that was used to create +** the statement in the first place. +*/ +SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt *pStmt){ + return pStmt ? ((Vdbe*)pStmt)->db : 0; +} + +/* +** Return true if the prepared statement is guaranteed to not modify the +** database. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ + return pStmt ? ((Vdbe*)pStmt)->readOnly : 1; +} + +/* +** Return true if the prepared statement is in need of being reset. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt *pStmt){ + Vdbe *v = (Vdbe*)pStmt; + return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN; +} + +/* +** Return a pointer to the next prepared statement after pStmt associated +** with database connection pDb. If pStmt is NULL, return the first +** prepared statement for the database connection. Return NULL if there +** are no more. +*/ +SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ + sqlite3_stmt *pNext; +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(pDb) ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + sqlite3_mutex_enter(pDb->mutex); + if( pStmt==0 ){ + pNext = (sqlite3_stmt*)pDb->pVdbe; + }else{ + pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pNext; + } + sqlite3_mutex_leave(pDb->mutex); + return pNext; +} + +/* +** Return the value of a status counter for a prepared statement +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ + Vdbe *pVdbe = (Vdbe*)pStmt; + u32 v; +#ifdef SQLITE_ENABLE_API_ARMOR + if( !pStmt ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + v = pVdbe->aCounter[op]; + if( resetFlag ) pVdbe->aCounter[op] = 0; + return (int)v; +} + +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS +/* +** Return status data for a single loop within query pStmt. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( + sqlite3_stmt *pStmt, /* Prepared statement being queried */ + int idx, /* Index of loop to report on */ + int iScanStatusOp, /* Which metric to return */ + void *pOut /* OUT: Write the answer here */ +){ + Vdbe *p = (Vdbe*)pStmt; + ScanStatus *pScan; + if( idx<0 || idx>=p->nScan ) return 1; + pScan = &p->aScan[idx]; + switch( iScanStatusOp ){ + case SQLITE_SCANSTAT_NLOOP: { + *(sqlite3_int64*)pOut = p->anExec[pScan->addrLoop]; + break; + } + case SQLITE_SCANSTAT_NVISIT: { + *(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit]; + break; + } + case SQLITE_SCANSTAT_EST: { + double r = 1.0; + LogEst x = pScan->nEst; + while( x<100 ){ + x += 10; + r *= 0.5; + } + *(double*)pOut = r*sqlite3LogEstToInt(x); + break; + } + case SQLITE_SCANSTAT_NAME: { + *(const char**)pOut = pScan->zName; + break; + } + case SQLITE_SCANSTAT_EXPLAIN: { + if( pScan->addrExplain ){ + *(const char**)pOut = p->aOp[ pScan->addrExplain ].p4.z; + }else{ + *(const char**)pOut = 0; + } + break; + } + case SQLITE_SCANSTAT_SELECTID: { + if( pScan->addrExplain ){ + *(int*)pOut = p->aOp[ pScan->addrExplain ].p1; + }else{ + *(int*)pOut = -1; + } + break; + } + default: { + return 1; + } + } + return 0; +} + +/* +** Zero all counters associated with the sqlite3_stmt_scanstatus() data. +*/ +SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ + Vdbe *p = (Vdbe*)pStmt; + memset(p->anExec, 0, p->nOp * sizeof(i64)); +} +#endif /* SQLITE_ENABLE_STMT_SCANSTATUS */ + +/************** End of vdbeapi.c *********************************************/ +/************** Begin file vdbetrace.c ***************************************/ +/* +** 2009 November 25 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains code used to insert the values of host parameters +** (aka "wildcards") into the SQL text output by sqlite3_trace(). +** +** The Vdbe parse-tree explainer is also found here. +*/ +/* #include "sqliteInt.h" */ +/* #include "vdbeInt.h" */ + +#ifndef SQLITE_OMIT_TRACE + +/* +** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of +** bytes in this text up to but excluding the first character in +** a host parameter. If the text contains no host parameters, return +** the total number of bytes in the text. +*/ +static int findNextHostParameter(const char *zSql, int *pnToken){ + int tokenType; + int nTotal = 0; + int n; + + *pnToken = 0; + while( zSql[0] ){ + n = sqlite3GetToken((u8*)zSql, &tokenType); + assert( n>0 && tokenType!=TK_ILLEGAL ); + if( tokenType==TK_VARIABLE ){ + *pnToken = n; + break; + } + nTotal += n; + zSql += n; + } + return nTotal; +} + +/* +** This function returns a pointer to a nul-terminated string in memory +** obtained from sqlite3DbMalloc(). If sqlite3.nVdbeExec is 1, then the +** string contains a copy of zRawSql but with host parameters expanded to +** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1, +** then the returned string holds a copy of zRawSql with "-- " prepended +** to each line of text. +** +** If the SQLITE_TRACE_SIZE_LIMIT macro is defined to an integer, then +** then long strings and blobs are truncated to that many bytes. This +** can be used to prevent unreasonably large trace strings when dealing +** with large (multi-megabyte) strings and blobs. +** +** The calling function is responsible for making sure the memory returned +** is eventually freed. +** +** ALGORITHM: Scan the input string looking for host parameters in any of +** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within +** string literals, quoted identifier names, and comments. For text forms, +** the host parameter index is found by scanning the prepared +** statement for the corresponding OP_Variable opcode. Once the host +** parameter index is known, locate the value in p->aVar[]. Then render +** the value as a literal in place of the host parameter name. +*/ +SQLITE_PRIVATE char *sqlite3VdbeExpandSql( + Vdbe *p, /* The prepared statement being evaluated */ + const char *zRawSql /* Raw text of the SQL statement */ +){ + sqlite3 *db; /* The database connection */ + int idx = 0; /* Index of a host parameter */ + int nextIndex = 1; /* Index of next ? host parameter */ + int n; /* Length of a token prefix */ + int nToken; /* Length of the parameter token */ + int i; /* Loop counter */ + Mem *pVar; /* Value of a host parameter */ + StrAccum out; /* Accumulate the output here */ + char zBase[100]; /* Initial working space */ + + db = p->db; + sqlite3StrAccumInit(&out, db, zBase, sizeof(zBase), + db->aLimit[SQLITE_LIMIT_LENGTH]); + if( db->nVdbeExec>1 ){ + while( *zRawSql ){ + const char *zStart = zRawSql; + while( *(zRawSql++)!='\n' && *zRawSql ); + sqlite3StrAccumAppend(&out, "-- ", 3); + assert( (zRawSql - zStart) > 0 ); + sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); + } + }else if( p->nVar==0 ){ + sqlite3StrAccumAppend(&out, zRawSql, sqlite3Strlen30(zRawSql)); + }else{ + while( zRawSql[0] ){ + n = findNextHostParameter(zRawSql, &nToken); + assert( n>0 ); + sqlite3StrAccumAppend(&out, zRawSql, n); + zRawSql += n; + assert( zRawSql[0] || nToken==0 ); + if( nToken==0 ) break; + if( zRawSql[0]=='?' ){ + if( nToken>1 ){ + assert( sqlite3Isdigit(zRawSql[1]) ); + sqlite3GetInt32(&zRawSql[1], &idx); + }else{ + idx = nextIndex; + } + }else{ + assert( zRawSql[0]==':' || zRawSql[0]=='$' || + zRawSql[0]=='@' || zRawSql[0]=='#' ); + testcase( zRawSql[0]==':' ); + testcase( zRawSql[0]=='$' ); + testcase( zRawSql[0]=='@' ); + testcase( zRawSql[0]=='#' ); + idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken); + assert( idx>0 ); + } + zRawSql += nToken; + nextIndex = idx + 1; + assert( idx>0 && idx<=p->nVar ); + pVar = &p->aVar[idx-1]; + if( pVar->flags & MEM_Null ){ + sqlite3StrAccumAppend(&out, "NULL", 4); + }else if( pVar->flags & MEM_Int ){ + sqlite3XPrintf(&out, 0, "%lld", pVar->u.i); + }else if( pVar->flags & MEM_Real ){ + sqlite3XPrintf(&out, 0, "%!.15g", pVar->u.r); + }else if( pVar->flags & MEM_Str ){ + int nOut; /* Number of bytes of the string text to include in output */ +#ifndef SQLITE_OMIT_UTF16 + u8 enc = ENC(db); + Mem utf8; + if( enc!=SQLITE_UTF8 ){ + memset(&utf8, 0, sizeof(utf8)); + utf8.db = db; + sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); + sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8); + pVar = &utf8; + } +#endif + nOut = pVar->n; +#ifdef SQLITE_TRACE_SIZE_LIMIT + if( nOut>SQLITE_TRACE_SIZE_LIMIT ){ + nOut = SQLITE_TRACE_SIZE_LIMIT; + while( nOutn && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } + } +#endif + sqlite3XPrintf(&out, 0, "'%.*q'", nOut, pVar->z); +#ifdef SQLITE_TRACE_SIZE_LIMIT + if( nOutn ){ + sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); + } +#endif +#ifndef SQLITE_OMIT_UTF16 + if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); +#endif + }else if( pVar->flags & MEM_Zero ){ + sqlite3XPrintf(&out, 0, "zeroblob(%d)", pVar->u.nZero); + }else{ + int nOut; /* Number of bytes of the blob to include in output */ + assert( pVar->flags & MEM_Blob ); + sqlite3StrAccumAppend(&out, "x'", 2); + nOut = pVar->n; +#ifdef SQLITE_TRACE_SIZE_LIMIT + if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; +#endif + for(i=0; iz[i]&0xff); + } + sqlite3StrAccumAppend(&out, "'", 1); +#ifdef SQLITE_TRACE_SIZE_LIMIT + if( nOutn ){ + sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); + } +#endif + } + } + } + return sqlite3StrAccumFinish(&out); +} + +#endif /* #ifndef SQLITE_OMIT_TRACE */ + +/************** End of vdbetrace.c *******************************************/ +/************** Begin file vdbe.c ********************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** The code in this file implements the function that runs the +** bytecode of a prepared statement. +** +** Various scripts scan this source file in order to generate HTML +** documentation, headers files, or other derived files. The formatting +** of the code in this file is, therefore, important. See other comments +** in this file for details. If in doubt, do not deviate from existing +** commenting and indentation practices when changing or adding code. +*/ +/* #include "sqliteInt.h" */ +/* #include "vdbeInt.h" */ + +/* +** Invoke this macro on memory cells just prior to changing the +** value of the cell. This macro verifies that shallow copies are +** not misused. A shallow copy of a string or blob just copies a +** pointer to the string or blob, not the content. If the original +** is changed while the copy is still in use, the string or blob might +** be changed out from under the copy. This macro verifies that nothing +** like that ever happens. +*/ +#ifdef SQLITE_DEBUG +# define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M) +#else +# define memAboutToChange(P,M) +#endif + +/* +** The following global variable is incremented every time a cursor +** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test +** procedures use this information to make sure that indices are +** working correctly. This variable has no function other than to +** help verify the correct operation of the library. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_search_count = 0; +#endif + +/* +** When this global variable is positive, it gets decremented once before +** each instruction in the VDBE. When it reaches zero, the u1.isInterrupted +** field of the sqlite3 structure is set in order to simulate an interrupt. +** +** This facility is used for testing purposes only. It does not function +** in an ordinary build. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_interrupt_count = 0; +#endif + +/* +** The next global variable is incremented each type the OP_Sort opcode +** is executed. The test procedures use this information to make sure that +** sorting is occurring or not occurring at appropriate times. This variable +** has no function other than to help verify the correct operation of the +** library. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_sort_count = 0; +#endif + +/* +** The next global variable records the size of the largest MEM_Blob +** or MEM_Str that has been used by a VDBE opcode. The test procedures +** use this information to make sure that the zero-blob functionality +** is working correctly. This variable has no function other than to +** help verify the correct operation of the library. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_max_blobsize = 0; +static void updateMaxBlobsize(Mem *p){ + if( (p->flags & (MEM_Str|MEM_Blob))!=0 && p->n>sqlite3_max_blobsize ){ + sqlite3_max_blobsize = p->n; + } +} +#endif + +/* +** The next global variable is incremented each time the OP_Found opcode +** is executed. This is used to test whether or not the foreign key +** operation implemented using OP_FkIsZero is working. This variable +** has no function other than to help verify the correct operation of the +** library. +*/ +#ifdef SQLITE_TEST +SQLITE_API int sqlite3_found_count = 0; +#endif + +/* +** Test a register to see if it exceeds the current maximum blob size. +** If it does, record the new maximum blob size. +*/ +#if defined(SQLITE_TEST) && !defined(SQLITE_OMIT_BUILTIN_TEST) +# define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P) +#else +# define UPDATE_MAX_BLOBSIZE(P) +#endif + +/* +** Invoke the VDBE coverage callback, if that callback is defined. This +** feature is used for test suite validation only and does not appear an +** production builds. +** +** M is an integer, 2 or 3, that indices how many different ways the +** branch can go. It is usually 2. "I" is the direction the branch +** goes. 0 means falls through. 1 means branch is taken. 2 means the +** second alternative branch is taken. +** +** iSrcLine is the source code line (from the __LINE__ macro) that +** generated the VDBE instruction. This instrumentation assumes that all +** source code is in a single file (the amalgamation). Special values 1 +** and 2 for the iSrcLine parameter mean that this particular branch is +** always taken or never taken, respectively. +*/ +#if !defined(SQLITE_VDBE_COVERAGE) +# define VdbeBranchTaken(I,M) +#else +# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M) + static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){ + if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){ + M = iSrcLine; + /* Assert the truth of VdbeCoverageAlwaysTaken() and + ** VdbeCoverageNeverTaken() */ + assert( (M & I)==I ); + }else{ + if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ + sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, + iSrcLine,I,M); + } + } +#endif + +/* +** Convert the given register into a string if it isn't one +** already. Return non-zero if a malloc() fails. +*/ +#define Stringify(P, enc) \ + if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc,0)) \ + { goto no_mem; } + +/* +** An ephemeral string value (signified by the MEM_Ephem flag) contains +** a pointer to a dynamically allocated string where some other entity +** is responsible for deallocating that string. Because the register +** does not control the string, it might be deleted without the register +** knowing it. +** +** This routine converts an ephemeral string into a dynamically allocated +** string that the register itself controls. In other words, it +** converts an MEM_Ephem string into a string with P.z==P.zMalloc. +*/ +#define Deephemeralize(P) \ + if( ((P)->flags&MEM_Ephem)!=0 \ + && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} + +/* Return true if the cursor was opened using the OP_OpenSorter opcode. */ +#define isSorter(x) ((x)->pSorter!=0) + +/* +** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL +** if we run out of memory. +*/ +static VdbeCursor *allocateCursor( + Vdbe *p, /* The virtual machine */ + int iCur, /* Index of the new VdbeCursor */ + int nField, /* Number of fields in the table or index */ + int iDb, /* Database the cursor belongs to, or -1 */ + int isBtreeCursor /* True for B-Tree. False for pseudo-table or vtab */ +){ + /* Find the memory cell that will be used to store the blob of memory + ** required for this VdbeCursor structure. It is convenient to use a + ** vdbe memory cell to manage the memory allocation required for a + ** VdbeCursor structure for the following reasons: + ** + ** * Sometimes cursor numbers are used for a couple of different + ** purposes in a vdbe program. The different uses might require + ** different sized allocations. Memory cells provide growable + ** allocations. + ** + ** * When using ENABLE_MEMORY_MANAGEMENT, memory cell buffers can + ** be freed lazily via the sqlite3_release_memory() API. This + ** minimizes the number of malloc calls made by the system. + ** + ** Memory cells for cursors are allocated at the top of the address + ** space. Memory cell (p->nMem) corresponds to cursor 0. Space for + ** cursor 1 is managed by memory cell (p->nMem-1), etc. + */ + Mem *pMem = &p->aMem[p->nMem-iCur]; + + int nByte; + VdbeCursor *pCx = 0; + nByte = + ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField + + (isBtreeCursor?sqlite3BtreeCursorSize():0); + + assert( iCurnCursor ); + if( p->apCsr[iCur] ){ + sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); + p->apCsr[iCur] = 0; + } + if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){ + p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z; + memset(pCx, 0, sizeof(VdbeCursor)); + pCx->iDb = iDb; + pCx->nField = nField; + pCx->aOffset = &pCx->aType[nField]; + if( isBtreeCursor ){ + pCx->pCursor = (BtCursor*) + &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField]; + sqlite3BtreeCursorZero(pCx->pCursor); + } + } + return pCx; +} + +/* +** Try to convert a value into a numeric representation if we can +** do so without loss of information. In other words, if the string +** looks like a number, convert it into a number. If it does not +** look like a number, leave it alone. +** +** If the bTryForInt flag is true, then extra effort is made to give +** an integer representation. Strings that look like floating point +** values but which have no fractional component (example: '48.00') +** will have a MEM_Int representation when bTryForInt is true. +** +** If bTryForInt is false, then if the input string contains a decimal +** point or exponential notation, the result is only MEM_Real, even +** if there is an exact integer representation of the quantity. +*/ +static void applyNumericAffinity(Mem *pRec, int bTryForInt){ + double rValue; + i64 iValue; + u8 enc = pRec->enc; + assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real))==MEM_Str ); + if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return; + if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){ + pRec->u.i = iValue; + pRec->flags |= MEM_Int; + }else{ + pRec->u.r = rValue; + pRec->flags |= MEM_Real; + if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec); + } +} + +/* +** Processing is determine by the affinity parameter: +** +** SQLITE_AFF_INTEGER: +** SQLITE_AFF_REAL: +** SQLITE_AFF_NUMERIC: +** Try to convert pRec to an integer representation or a +** floating-point representation if an integer representation +** is not possible. Note that the integer representation is +** always preferred, even if the affinity is REAL, because +** an integer representation is more space efficient on disk. +** +** SQLITE_AFF_TEXT: +** Convert pRec to a text representation. +** +** SQLITE_AFF_BLOB: +** No-op. pRec is unchanged. +*/ +static void applyAffinity( + Mem *pRec, /* The value to apply affinity to */ + char affinity, /* The affinity to be applied */ + u8 enc /* Use this text encoding */ +){ + if( affinity>=SQLITE_AFF_NUMERIC ){ + assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL + || affinity==SQLITE_AFF_NUMERIC ); + if( (pRec->flags & MEM_Int)==0 ){ + if( (pRec->flags & MEM_Real)==0 ){ + if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1); + }else{ + sqlite3VdbeIntegerAffinity(pRec); + } + } + }else if( affinity==SQLITE_AFF_TEXT ){ + /* Only attempt the conversion to TEXT if there is an integer or real + ** representation (blob and NULL do not get converted) but no string + ** representation. + */ + if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){ + sqlite3VdbeMemStringify(pRec, enc, 1); + } + pRec->flags &= ~(MEM_Real|MEM_Int); + } +} + +/* +** Try to convert the type of a function argument or a result column +** into a numeric representation. Use either INTEGER or REAL whichever +** is appropriate. But only do the conversion if it is possible without +** loss of information and return the revised type of the argument. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value *pVal){ + int eType = sqlite3_value_type(pVal); + if( eType==SQLITE_TEXT ){ + Mem *pMem = (Mem*)pVal; + applyNumericAffinity(pMem, 0); + eType = sqlite3_value_type(pVal); + } + return eType; +} + +/* +** Exported version of applyAffinity(). This one works on sqlite3_value*, +** not the internal Mem* type. +*/ +SQLITE_PRIVATE void sqlite3ValueApplyAffinity( + sqlite3_value *pVal, + u8 affinity, + u8 enc +){ + applyAffinity((Mem *)pVal, affinity, enc); +} + +/* +** pMem currently only holds a string type (or maybe a BLOB that we can +** interpret as a string if we want to). Compute its corresponding +** numeric type, if has one. Set the pMem->u.r and pMem->u.i fields +** accordingly. +*/ +static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ + assert( (pMem->flags & (MEM_Int|MEM_Real))==0 ); + assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ); + if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){ + return 0; + } + if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){ + return MEM_Int; + } + return MEM_Real; +} + +/* +** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or +** none. +** +** Unlike applyNumericAffinity(), this routine does not modify pMem->flags. +** But it does set pMem->u.r and pMem->u.i appropriately. +*/ +static u16 numericType(Mem *pMem){ + if( pMem->flags & (MEM_Int|MEM_Real) ){ + return pMem->flags & (MEM_Int|MEM_Real); + } + if( pMem->flags & (MEM_Str|MEM_Blob) ){ + return computeNumericType(pMem); + } + return 0; +} + +#ifdef SQLITE_DEBUG +/* +** Write a nice string representation of the contents of cell pMem +** into buffer zBuf, length nBuf. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ + char *zCsr = zBuf; + int f = pMem->flags; + + static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"}; + + if( f&MEM_Blob ){ + int i; + char c; + if( f & MEM_Dyn ){ + c = 'z'; + assert( (f & (MEM_Static|MEM_Ephem))==0 ); + }else if( f & MEM_Static ){ + c = 't'; + assert( (f & (MEM_Dyn|MEM_Ephem))==0 ); + }else if( f & MEM_Ephem ){ + c = 'e'; + assert( (f & (MEM_Static|MEM_Dyn))==0 ); + }else{ + c = 's'; + } + + sqlite3_snprintf(100, zCsr, "%c", c); + zCsr += sqlite3Strlen30(zCsr); + sqlite3_snprintf(100, zCsr, "%d[", pMem->n); + zCsr += sqlite3Strlen30(zCsr); + for(i=0; i<16 && in; i++){ + sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF)); + zCsr += sqlite3Strlen30(zCsr); + } + for(i=0; i<16 && in; i++){ + char z = pMem->z[i]; + if( z<32 || z>126 ) *zCsr++ = '.'; + else *zCsr++ = z; + } + + sqlite3_snprintf(100, zCsr, "]%s", encnames[pMem->enc]); + zCsr += sqlite3Strlen30(zCsr); + if( f & MEM_Zero ){ + sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero); + zCsr += sqlite3Strlen30(zCsr); + } + *zCsr = '\0'; + }else if( f & MEM_Str ){ + int j, k; + zBuf[0] = ' '; + if( f & MEM_Dyn ){ + zBuf[1] = 'z'; + assert( (f & (MEM_Static|MEM_Ephem))==0 ); + }else if( f & MEM_Static ){ + zBuf[1] = 't'; + assert( (f & (MEM_Dyn|MEM_Ephem))==0 ); + }else if( f & MEM_Ephem ){ + zBuf[1] = 'e'; + assert( (f & (MEM_Static|MEM_Dyn))==0 ); + }else{ + zBuf[1] = 's'; + } + k = 2; + sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n); + k += sqlite3Strlen30(&zBuf[k]); + zBuf[k++] = '['; + for(j=0; j<15 && jn; j++){ + u8 c = pMem->z[j]; + if( c>=0x20 && c<0x7f ){ + zBuf[k++] = c; + }else{ + zBuf[k++] = '.'; + } + } + zBuf[k++] = ']'; + sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]); + k += sqlite3Strlen30(&zBuf[k]); + zBuf[k++] = 0; + } +} +#endif + +#ifdef SQLITE_DEBUG +/* +** Print the value of a register for tracing purposes: +*/ +static void memTracePrint(Mem *p){ + if( p->flags & MEM_Undefined ){ + printf(" undefined"); + }else if( p->flags & MEM_Null ){ + printf(" NULL"); + }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ + printf(" si:%lld", p->u.i); + }else if( p->flags & MEM_Int ){ + printf(" i:%lld", p->u.i); +#ifndef SQLITE_OMIT_FLOATING_POINT + }else if( p->flags & MEM_Real ){ + printf(" r:%g", p->u.r); +#endif + }else if( p->flags & MEM_RowSet ){ + printf(" (rowset)"); + }else{ + char zBuf[200]; + sqlite3VdbeMemPrettyPrint(p, zBuf); + printf(" %s", zBuf); + } +} +static void registerTrace(int iReg, Mem *p){ + printf("REG[%d] = ", iReg); + memTracePrint(p); + printf("\n"); +} +#endif + +#ifdef SQLITE_DEBUG +# define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M) +#else +# define REGISTER_TRACE(R,M) +#endif + + +#ifdef VDBE_PROFILE + +/* +** hwtime.h contains inline assembler code for implementing +** high-performance timing routines. +*/ +/************** Include hwtime.h in the middle of vdbe.c *********************/ +/************** Begin file hwtime.h ******************************************/ +/* +** 2008 May 27 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains inline asm code for retrieving "high-performance" +** counters for x86 class CPUs. +*/ +#ifndef _HWTIME_H_ +#define _HWTIME_H_ + +/* +** The following routine only works on pentium-class (or newer) processors. +** It uses the RDTSC opcode to read the cycle count value out of the +** processor and returns that value. This can be used for high-res +** profiling. +*/ +#if (defined(__GNUC__) || defined(_MSC_VER)) && \ + (defined(i386) || defined(__i386__) || defined(_M_IX86)) + + #if defined(__GNUC__) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned int lo, hi; + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + return (sqlite_uint64)hi << 32 | lo; + } + + #elif defined(_MSC_VER) + + __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ + __asm { + rdtsc + ret ; return value at EDX:EAX + } + } + + #endif + +#elif (defined(__GNUC__) && defined(__x86_64__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long val; + __asm__ __volatile__ ("rdtsc" : "=A" (val)); + return val; + } + +#elif (defined(__GNUC__) && defined(__ppc__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long long retval; + unsigned long junk; + __asm__ __volatile__ ("\n\ + 1: mftbu %1\n\ + mftb %L0\n\ + mftbu %0\n\ + cmpw %0,%1\n\ + bne 1b" + : "=r" (retval), "=r" (junk)); + return retval; + } + +#else + + #error Need implementation of sqlite3Hwtime() for your platform. + + /* + ** To compile without implementing sqlite3Hwtime() for your platform, + ** you can remove the above #error and use the following + ** stub function. You will lose timing support for many + ** of the debugging and testing utilities, but it should at + ** least compile and run. + */ +SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } + +#endif + +#endif /* !defined(_HWTIME_H_) */ + +/************** End of hwtime.h **********************************************/ +/************** Continuing where we left off in vdbe.c ***********************/ + +#endif + +#ifndef NDEBUG +/* +** This function is only called from within an assert() expression. It +** checks that the sqlite3.nTransaction variable is correctly set to +** the number of non-transaction savepoints currently in the +** linked list starting at sqlite3.pSavepoint. +** +** Usage: +** +** assert( checkSavepointCount(db) ); +*/ +static int checkSavepointCount(sqlite3 *db){ + int n = 0; + Savepoint *p; + for(p=db->pSavepoint; p; p=p->pNext) n++; + assert( n==(db->nSavepoint + db->isTransactionSavepoint) ); + return 1; +} +#endif + +/* +** Return the register of pOp->p2 after first preparing it to be +** overwritten with an integer value. +*/ +static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){ + Mem *pOut; + assert( pOp->p2>0 ); + assert( pOp->p2<=(p->nMem-p->nCursor) ); + pOut = &p->aMem[pOp->p2]; + memAboutToChange(p, pOut); + if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut); + pOut->flags = MEM_Int; + return pOut; +} + + +/* +** Execute as much of a VDBE program as we can. +** This is the core of sqlite3_step(). +*/ +SQLITE_PRIVATE int sqlite3VdbeExec( + Vdbe *p /* The VDBE */ +){ + Op *aOp = p->aOp; /* Copy of p->aOp */ + Op *pOp = aOp; /* Current operation */ +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) + Op *pOrigOp; /* Value of pOp at the top of the loop */ +#endif + int rc = SQLITE_OK; /* Value to return */ + sqlite3 *db = p->db; /* The database */ + u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ + u8 encoding = ENC(db); /* The database encoding */ + int iCompare = 0; /* Result of last OP_Compare operation */ + unsigned nVmStep = 0; /* Number of virtual machine steps */ +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */ +#endif + Mem *aMem = p->aMem; /* Copy of p->aMem */ + Mem *pIn1 = 0; /* 1st input operand */ + Mem *pIn2 = 0; /* 2nd input operand */ + Mem *pIn3 = 0; /* 3rd input operand */ + Mem *pOut = 0; /* Output operand */ + int *aPermute = 0; /* Permutation of columns for OP_Compare */ + i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */ +#ifdef VDBE_PROFILE + u64 start; /* CPU clock count at start of opcode */ +#endif + /*** INSERT STACK UNION HERE ***/ + + assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ + sqlite3VdbeEnter(p); + if( p->rc==SQLITE_NOMEM ){ + /* This happens if a malloc() inside a call to sqlite3_column_text() or + ** sqlite3_column_text16() failed. */ + goto no_mem; + } + assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); + assert( p->bIsReader || p->readOnly!=0 ); + p->rc = SQLITE_OK; + p->iCurrentTime = 0; + assert( p->explain==0 ); + p->pResultSet = 0; + db->busyHandler.nBusy = 0; + if( db->u1.isInterrupted ) goto abort_due_to_interrupt; + sqlite3VdbeIOTraceSql(p); +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + if( db->xProgress ){ + u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP]; + assert( 0 < db->nProgressOps ); + nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps); + } +#endif +#ifdef SQLITE_DEBUG + sqlite3BeginBenignMalloc(); + if( p->pc==0 + && (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0 + ){ + int i; + int once = 1; + sqlite3VdbePrintSql(p); + if( p->db->flags & SQLITE_VdbeListing ){ + printf("VDBE Program Listing:\n"); + for(i=0; inOp; i++){ + sqlite3VdbePrintOp(stdout, i, &aOp[i]); + } + } + if( p->db->flags & SQLITE_VdbeEQP ){ + for(i=0; inOp; i++){ + if( aOp[i].opcode==OP_Explain ){ + if( once ) printf("VDBE Query Plan:\n"); + printf("%s\n", aOp[i].p4.z); + once = 0; + } + } + } + if( p->db->flags & SQLITE_VdbeTrace ) printf("VDBE Trace:\n"); + } + sqlite3EndBenignMalloc(); +#endif + for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){ + assert( pOp>=aOp && pOp<&aOp[p->nOp]); + if( db->mallocFailed ) goto no_mem; +#ifdef VDBE_PROFILE + start = sqlite3Hwtime(); +#endif + nVmStep++; +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + if( p->anExec ) p->anExec[(int)(pOp-aOp)]++; +#endif + + /* Only allow tracing if SQLITE_DEBUG is defined. + */ +#ifdef SQLITE_DEBUG + if( db->flags & SQLITE_VdbeTrace ){ + sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp); + } +#endif + + + /* Check to see if we need to simulate an interrupt. This only happens + ** if we have a special test build. + */ +#ifdef SQLITE_TEST + if( sqlite3_interrupt_count>0 ){ + sqlite3_interrupt_count--; + if( sqlite3_interrupt_count==0 ){ + sqlite3_interrupt(db); + } + } +#endif + + /* Sanity checking on other operands */ +#ifdef SQLITE_DEBUG + assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] ); + if( (pOp->opflags & OPFLG_IN1)!=0 ){ + assert( pOp->p1>0 ); + assert( pOp->p1<=(p->nMem-p->nCursor) ); + assert( memIsValid(&aMem[pOp->p1]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) ); + REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]); + } + if( (pOp->opflags & OPFLG_IN2)!=0 ){ + assert( pOp->p2>0 ); + assert( pOp->p2<=(p->nMem-p->nCursor) ); + assert( memIsValid(&aMem[pOp->p2]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) ); + REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]); + } + if( (pOp->opflags & OPFLG_IN3)!=0 ){ + assert( pOp->p3>0 ); + assert( pOp->p3<=(p->nMem-p->nCursor) ); + assert( memIsValid(&aMem[pOp->p3]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) ); + REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]); + } + if( (pOp->opflags & OPFLG_OUT2)!=0 ){ + assert( pOp->p2>0 ); + assert( pOp->p2<=(p->nMem-p->nCursor) ); + memAboutToChange(p, &aMem[pOp->p2]); + } + if( (pOp->opflags & OPFLG_OUT3)!=0 ){ + assert( pOp->p3>0 ); + assert( pOp->p3<=(p->nMem-p->nCursor) ); + memAboutToChange(p, &aMem[pOp->p3]); + } +#endif +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) + pOrigOp = pOp; +#endif + + switch( pOp->opcode ){ + +/***************************************************************************** +** What follows is a massive switch statement where each case implements a +** separate instruction in the virtual machine. If we follow the usual +** indentation conventions, each case should be indented by 6 spaces. But +** that is a lot of wasted space on the left margin. So the code within +** the switch statement will break with convention and be flush-left. Another +** big comment (similar to this one) will mark the point in the code where +** we transition back to normal indentation. +** +** The formatting of each case is important. The makefile for SQLite +** generates two C files "opcodes.h" and "opcodes.c" by scanning this +** file looking for lines that begin with "case OP_". The opcodes.h files +** will be filled with #defines that give unique integer values to each +** opcode and the opcodes.c file is filled with an array of strings where +** each string is the symbolic name for the corresponding opcode. If the +** case statement is followed by a comment of the form "/# same as ... #/" +** that comment is used to determine the particular value of the opcode. +** +** Other keywords in the comment that follows each case are used to +** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[]. +** Keywords include: in1, in2, in3, out2, out3. See +** the mkopcodeh.awk script for additional information. +** +** Documentation about VDBE opcodes is generated by scanning this file +** for lines of that contain "Opcode:". That line and all subsequent +** comment lines are used in the generation of the opcode.html documentation +** file. +** +** SUMMARY: +** +** Formatting is important to scripts that scan this file. +** Do not deviate from the formatting style currently in use. +** +*****************************************************************************/ + +/* Opcode: Goto * P2 * * * +** +** An unconditional jump to address P2. +** The next instruction executed will be +** the one at index P2 from the beginning of +** the program. +** +** The P1 parameter is not actually used by this opcode. However, it +** is sometimes set to 1 instead of 0 as a hint to the command-line shell +** that this Goto is the bottom of a loop and that the lines from P2 down +** to the current line should be indented for EXPLAIN output. +*/ +case OP_Goto: { /* jump */ +jump_to_p2_and_check_for_interrupt: + pOp = &aOp[pOp->p2 - 1]; + + /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, + ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon + ** completion. Check to see if sqlite3_interrupt() has been called + ** or if the progress callback needs to be invoked. + ** + ** This code uses unstructured "goto" statements and does not look clean. + ** But that is not due to sloppy coding habits. The code is written this + ** way for performance, to avoid having to run the interrupt and progress + ** checks on every opcode. This helps sqlite3_step() to run about 1.5% + ** faster according to "valgrind --tool=cachegrind" */ +check_for_interrupt: + if( db->u1.isInterrupted ) goto abort_due_to_interrupt; +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + /* Call the progress callback if it is configured and the required number + ** of VDBE ops have been executed (either since this invocation of + ** sqlite3VdbeExec() or since last time the progress callback was called). + ** If the progress callback returns non-zero, exit the virtual machine with + ** a return code SQLITE_ABORT. + */ + if( db->xProgress!=0 && nVmStep>=nProgressLimit ){ + assert( db->nProgressOps!=0 ); + nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps); + if( db->xProgress(db->pProgressArg) ){ + rc = SQLITE_INTERRUPT; + goto vdbe_error_halt; + } + } +#endif + + break; +} + +/* Opcode: Gosub P1 P2 * * * +** +** Write the current address onto register P1 +** and then jump to address P2. +*/ +case OP_Gosub: { /* jump */ + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); + pIn1 = &aMem[pOp->p1]; + assert( VdbeMemDynamic(pIn1)==0 ); + memAboutToChange(p, pIn1); + pIn1->flags = MEM_Int; + pIn1->u.i = (int)(pOp-aOp); + REGISTER_TRACE(pOp->p1, pIn1); + + /* Most jump operations do a goto to this spot in order to update + ** the pOp pointer. */ +jump_to_p2: + pOp = &aOp[pOp->p2 - 1]; + break; +} + +/* Opcode: Return P1 * * * * +** +** Jump to the next instruction after the address in register P1. After +** the jump, register P1 becomes undefined. +*/ +case OP_Return: { /* in1 */ + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags==MEM_Int ); + pOp = &aOp[pIn1->u.i]; + pIn1->flags = MEM_Undefined; + break; +} + +/* Opcode: InitCoroutine P1 P2 P3 * * +** +** Set up register P1 so that it will Yield to the coroutine +** located at address P3. +** +** If P2!=0 then the coroutine implementation immediately follows +** this opcode. So jump over the coroutine implementation to +** address P2. +** +** See also: EndCoroutine +*/ +case OP_InitCoroutine: { /* jump */ + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); + assert( pOp->p2>=0 && pOp->p2nOp ); + assert( pOp->p3>=0 && pOp->p3nOp ); + pOut = &aMem[pOp->p1]; + assert( !VdbeMemDynamic(pOut) ); + pOut->u.i = pOp->p3 - 1; + pOut->flags = MEM_Int; + if( pOp->p2 ) goto jump_to_p2; + break; +} + +/* Opcode: EndCoroutine P1 * * * * +** +** The instruction at the address in register P1 is a Yield. +** Jump to the P2 parameter of that Yield. +** After the jump, register P1 becomes undefined. +** +** See also: InitCoroutine +*/ +case OP_EndCoroutine: { /* in1 */ + VdbeOp *pCaller; + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags==MEM_Int ); + assert( pIn1->u.i>=0 && pIn1->u.inOp ); + pCaller = &aOp[pIn1->u.i]; + assert( pCaller->opcode==OP_Yield ); + assert( pCaller->p2>=0 && pCaller->p2nOp ); + pOp = &aOp[pCaller->p2 - 1]; + pIn1->flags = MEM_Undefined; + break; +} + +/* Opcode: Yield P1 P2 * * * +** +** Swap the program counter with the value in register P1. This +** has the effect of yielding to a coroutine. +** +** If the coroutine that is launched by this instruction ends with +** Yield or Return then continue to the next instruction. But if +** the coroutine launched by this instruction ends with +** EndCoroutine, then jump to P2 rather than continuing with the +** next instruction. +** +** See also: InitCoroutine +*/ +case OP_Yield: { /* in1, jump */ + int pcDest; + pIn1 = &aMem[pOp->p1]; + assert( VdbeMemDynamic(pIn1)==0 ); + pIn1->flags = MEM_Int; + pcDest = (int)pIn1->u.i; + pIn1->u.i = (int)(pOp - aOp); + REGISTER_TRACE(pOp->p1, pIn1); + pOp = &aOp[pcDest]; + break; +} + +/* Opcode: HaltIfNull P1 P2 P3 P4 P5 +** Synopsis: if r[P3]=null halt +** +** Check the value in register P3. If it is NULL then Halt using +** parameter P1, P2, and P4 as if this were a Halt instruction. If the +** value in register P3 is not NULL, then this routine is a no-op. +** The P5 parameter should be 1. +*/ +case OP_HaltIfNull: { /* in3 */ + pIn3 = &aMem[pOp->p3]; + if( (pIn3->flags & MEM_Null)==0 ) break; + /* Fall through into OP_Halt */ +} + +/* Opcode: Halt P1 P2 * P4 P5 +** +** Exit immediately. All open cursors, etc are closed +** automatically. +** +** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(), +** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0). +** For errors, it can be some other value. If P1!=0 then P2 will determine +** whether or not to rollback the current transaction. Do not rollback +** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort, +** then back out all changes that have occurred during this execution of the +** VDBE, but do not rollback the transaction. +** +** If P4 is not null then it is an error message string. +** +** P5 is a value between 0 and 4, inclusive, that modifies the P4 string. +** +** 0: (no change) +** 1: NOT NULL contraint failed: P4 +** 2: UNIQUE constraint failed: P4 +** 3: CHECK constraint failed: P4 +** 4: FOREIGN KEY constraint failed: P4 +** +** If P5 is not zero and P4 is NULL, then everything after the ":" is +** omitted. +** +** There is an implied "Halt 0 0 0" instruction inserted at the very end of +** every program. So a jump past the last instruction of the program +** is the same as executing Halt. +*/ +case OP_Halt: { + const char *zType; + const char *zLogFmt; + VdbeFrame *pFrame; + int pcx; + + pcx = (int)(pOp - aOp); + if( pOp->p1==SQLITE_OK && p->pFrame ){ + /* Halt the sub-program. Return control to the parent frame. */ + pFrame = p->pFrame; + p->pFrame = pFrame->pParent; + p->nFrame--; + sqlite3VdbeSetChanges(db, p->nChange); + pcx = sqlite3VdbeFrameRestore(pFrame); + lastRowid = db->lastRowid; + if( pOp->p2==OE_Ignore ){ + /* Instruction pcx is the OP_Program that invoked the sub-program + ** currently being halted. If the p2 instruction of this OP_Halt + ** instruction is set to OE_Ignore, then the sub-program is throwing + ** an IGNORE exception. In this case jump to the address specified + ** as the p2 of the calling OP_Program. */ + pcx = p->aOp[pcx].p2-1; + } + aOp = p->aOp; + aMem = p->aMem; + pOp = &aOp[pcx]; + break; + } + p->rc = pOp->p1; + p->errorAction = (u8)pOp->p2; + p->pc = pcx; + if( p->rc ){ + if( pOp->p5 ){ + static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK", + "FOREIGN KEY" }; + assert( pOp->p5>=1 && pOp->p5<=4 ); + testcase( pOp->p5==1 ); + testcase( pOp->p5==2 ); + testcase( pOp->p5==3 ); + testcase( pOp->p5==4 ); + zType = azType[pOp->p5-1]; + }else{ + zType = 0; + } + assert( zType!=0 || pOp->p4.z!=0 ); + zLogFmt = "abort at %d in [%s]: %s"; + if( zType && pOp->p4.z ){ + sqlite3VdbeError(p, "%s constraint failed: %s", zType, pOp->p4.z); + }else if( pOp->p4.z ){ + sqlite3VdbeError(p, "%s", pOp->p4.z); + }else{ + sqlite3VdbeError(p, "%s constraint failed", zType); + } + sqlite3_log(pOp->p1, zLogFmt, pcx, p->zSql, p->zErrMsg); + } + rc = sqlite3VdbeHalt(p); + assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); + if( rc==SQLITE_BUSY ){ + p->rc = rc = SQLITE_BUSY; + }else{ + assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ); + assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 ); + rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; + } + goto vdbe_return; +} + +/* Opcode: Integer P1 P2 * * * +** Synopsis: r[P2]=P1 +** +** The 32-bit integer value P1 is written into register P2. +*/ +case OP_Integer: { /* out2 */ + pOut = out2Prerelease(p, pOp); + pOut->u.i = pOp->p1; + break; +} + +/* Opcode: Int64 * P2 * P4 * +** Synopsis: r[P2]=P4 +** +** P4 is a pointer to a 64-bit integer value. +** Write that value into register P2. +*/ +case OP_Int64: { /* out2 */ + pOut = out2Prerelease(p, pOp); + assert( pOp->p4.pI64!=0 ); + pOut->u.i = *pOp->p4.pI64; + break; +} + +#ifndef SQLITE_OMIT_FLOATING_POINT +/* Opcode: Real * P2 * P4 * +** Synopsis: r[P2]=P4 +** +** P4 is a pointer to a 64-bit floating point value. +** Write that value into register P2. +*/ +case OP_Real: { /* same as TK_FLOAT, out2 */ + pOut = out2Prerelease(p, pOp); + pOut->flags = MEM_Real; + assert( !sqlite3IsNaN(*pOp->p4.pReal) ); + pOut->u.r = *pOp->p4.pReal; + break; +} +#endif + +/* Opcode: String8 * P2 * P4 * +** Synopsis: r[P2]='P4' +** +** P4 points to a nul terminated UTF-8 string. This opcode is transformed +** into a String opcode before it is executed for the first time. During +** this transformation, the length of string P4 is computed and stored +** as the P1 parameter. +*/ +case OP_String8: { /* same as TK_STRING, out2 */ + assert( pOp->p4.z!=0 ); + pOut = out2Prerelease(p, pOp); + pOp->opcode = OP_String; + pOp->p1 = sqlite3Strlen30(pOp->p4.z); + +#ifndef SQLITE_OMIT_UTF16 + if( encoding!=SQLITE_UTF8 ){ + rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC); + if( rc==SQLITE_TOOBIG ) goto too_big; + if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; + assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z ); + assert( VdbeMemDynamic(pOut)==0 ); + pOut->szMalloc = 0; + pOut->flags |= MEM_Static; + if( pOp->p4type==P4_DYNAMIC ){ + sqlite3DbFree(db, pOp->p4.z); + } + pOp->p4type = P4_DYNAMIC; + pOp->p4.z = pOut->z; + pOp->p1 = pOut->n; + } +#endif + if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + /* Fall through to the next case, OP_String */ +} + +/* Opcode: String P1 P2 P3 P4 P5 +** Synopsis: r[P2]='P4' (len=P1) +** +** The string value P4 of length P1 (bytes) is stored in register P2. +** +** If P5!=0 and the content of register P3 is greater than zero, then +** the datatype of the register P2 is converted to BLOB. The content is +** the same sequence of bytes, it is merely interpreted as a BLOB instead +** of a string, as if it had been CAST. +*/ +case OP_String: { /* out2 */ + assert( pOp->p4.z!=0 ); + pOut = out2Prerelease(p, pOp); + pOut->flags = MEM_Str|MEM_Static|MEM_Term; + pOut->z = pOp->p4.z; + pOut->n = pOp->p1; + pOut->enc = encoding; + UPDATE_MAX_BLOBSIZE(pOut); + if( pOp->p5 ){ + assert( pOp->p3>0 ); + assert( pOp->p3<=(p->nMem-p->nCursor) ); + pIn3 = &aMem[pOp->p3]; + assert( pIn3->flags & MEM_Int ); + if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term; + } + break; +} + +/* Opcode: Null P1 P2 P3 * * +** Synopsis: r[P2..P3]=NULL +** +** Write a NULL into registers P2. If P3 greater than P2, then also write +** NULL into register P3 and every register in between P2 and P3. If P3 +** is less than P2 (typically P3 is zero) then only register P2 is +** set to NULL. +** +** If the P1 value is non-zero, then also set the MEM_Cleared flag so that +** NULL values will not compare equal even if SQLITE_NULLEQ is set on +** OP_Ne or OP_Eq. +*/ +case OP_Null: { /* out2 */ + int cnt; + u16 nullFlag; + pOut = out2Prerelease(p, pOp); + cnt = pOp->p3-pOp->p2; + assert( pOp->p3<=(p->nMem-p->nCursor) ); + pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; + while( cnt>0 ){ + pOut++; + memAboutToChange(p, pOut); + sqlite3VdbeMemSetNull(pOut); + pOut->flags = nullFlag; + cnt--; + } + break; +} + +/* Opcode: SoftNull P1 * * * * +** Synopsis: r[P1]=NULL +** +** Set register P1 to have the value NULL as seen by the OP_MakeRecord +** instruction, but do not free any string or blob memory associated with +** the register, so that if the value was a string or blob that was +** previously copied using OP_SCopy, the copies will continue to be valid. +*/ +case OP_SoftNull: { + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); + pOut = &aMem[pOp->p1]; + pOut->flags = (pOut->flags|MEM_Null)&~MEM_Undefined; + break; +} + +/* Opcode: Blob P1 P2 * P4 * +** Synopsis: r[P2]=P4 (len=P1) +** +** P4 points to a blob of data P1 bytes long. Store this +** blob in register P2. +*/ +case OP_Blob: { /* out2 */ + assert( pOp->p1 <= SQLITE_MAX_LENGTH ); + pOut = out2Prerelease(p, pOp); + sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); + pOut->enc = encoding; + UPDATE_MAX_BLOBSIZE(pOut); + break; +} + +/* Opcode: Variable P1 P2 * P4 * +** Synopsis: r[P2]=parameter(P1,P4) +** +** Transfer the values of bound parameter P1 into register P2 +** +** If the parameter is named, then its name appears in P4. +** The P4 value is used by sqlite3_bind_parameter_name(). +*/ +case OP_Variable: { /* out2 */ + Mem *pVar; /* Value being transferred */ + + assert( pOp->p1>0 && pOp->p1<=p->nVar ); + assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] ); + pVar = &p->aVar[pOp->p1 - 1]; + if( sqlite3VdbeMemTooBig(pVar) ){ + goto too_big; + } + pOut = out2Prerelease(p, pOp); + sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static); + UPDATE_MAX_BLOBSIZE(pOut); + break; +} + +/* Opcode: Move P1 P2 P3 * * +** Synopsis: r[P2@P3]=r[P1@P3] +** +** Move the P3 values in register P1..P1+P3-1 over into +** registers P2..P2+P3-1. Registers P1..P1+P3-1 are +** left holding a NULL. It is an error for register ranges +** P1..P1+P3-1 and P2..P2+P3-1 to overlap. It is an error +** for P3 to be less than 1. +*/ +case OP_Move: { + int n; /* Number of registers left to copy */ + int p1; /* Register to copy from */ + int p2; /* Register to copy to */ + + n = pOp->p3; + p1 = pOp->p1; + p2 = pOp->p2; + assert( n>0 && p1>0 && p2>0 ); + assert( p1+n<=p2 || p2+n<=p1 ); + + pIn1 = &aMem[p1]; + pOut = &aMem[p2]; + do{ + assert( pOut<=&aMem[(p->nMem-p->nCursor)] ); + assert( pIn1<=&aMem[(p->nMem-p->nCursor)] ); + assert( memIsValid(pIn1) ); + memAboutToChange(p, pOut); + sqlite3VdbeMemMove(pOut, pIn1); +#ifdef SQLITE_DEBUG + if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrompScopyFrom += pOp->p2 - p1; + } +#endif + Deephemeralize(pOut); + REGISTER_TRACE(p2++, pOut); + pIn1++; + pOut++; + }while( --n ); + break; +} + +/* Opcode: Copy P1 P2 P3 * * +** Synopsis: r[P2@P3+1]=r[P1@P3+1] +** +** Make a copy of registers P1..P1+P3 into registers P2..P2+P3. +** +** This instruction makes a deep copy of the value. A duplicate +** is made of any string or blob constant. See also OP_SCopy. +*/ +case OP_Copy: { + int n; + + n = pOp->p3; + pIn1 = &aMem[pOp->p1]; + pOut = &aMem[pOp->p2]; + assert( pOut!=pIn1 ); + while( 1 ){ + sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); + Deephemeralize(pOut); +#ifdef SQLITE_DEBUG + pOut->pScopyFrom = 0; +#endif + REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut); + if( (n--)==0 ) break; + pOut++; + pIn1++; + } + break; +} + +/* Opcode: SCopy P1 P2 * * * +** Synopsis: r[P2]=r[P1] +** +** Make a shallow copy of register P1 into register P2. +** +** This instruction makes a shallow copy of the value. If the value +** is a string or blob, then the copy is only a pointer to the +** original and hence if the original changes so will the copy. +** Worse, if the original is deallocated, the copy becomes invalid. +** Thus the program must guarantee that the original will not change +** during the lifetime of the copy. Use OP_Copy to make a complete +** copy. +*/ +case OP_SCopy: { /* out2 */ + pIn1 = &aMem[pOp->p1]; + pOut = &aMem[pOp->p2]; + assert( pOut!=pIn1 ); + sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); +#ifdef SQLITE_DEBUG + if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1; +#endif + break; +} + +/* Opcode: ResultRow P1 P2 * * * +** Synopsis: output=r[P1@P2] +** +** The registers P1 through P1+P2-1 contain a single row of +** results. This opcode causes the sqlite3_step() call to terminate +** with an SQLITE_ROW return code and it sets up the sqlite3_stmt +** structure to provide access to the r(P1)..r(P1+P2-1) values as +** the result row. +*/ +case OP_ResultRow: { + Mem *pMem; + int i; + assert( p->nResColumn==pOp->p2 ); + assert( pOp->p1>0 ); + assert( pOp->p1+pOp->p2<=(p->nMem-p->nCursor)+1 ); + +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + /* Run the progress counter just before returning. + */ + if( db->xProgress!=0 + && nVmStep>=nProgressLimit + && db->xProgress(db->pProgressArg)!=0 + ){ + rc = SQLITE_INTERRUPT; + goto vdbe_error_halt; + } +#endif + + /* If this statement has violated immediate foreign key constraints, do + ** not return the number of rows modified. And do not RELEASE the statement + ** transaction. It needs to be rolled back. */ + if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){ + assert( db->flags&SQLITE_CountRows ); + assert( p->usesStmtJournal ); + break; + } + + /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then + ** DML statements invoke this opcode to return the number of rows + ** modified to the user. This is the only way that a VM that + ** opens a statement transaction may invoke this opcode. + ** + ** In case this is such a statement, close any statement transaction + ** opened by this VM before returning control to the user. This is to + ** ensure that statement-transactions are always nested, not overlapping. + ** If the open statement-transaction is not closed here, then the user + ** may step another VM that opens its own statement transaction. This + ** may lead to overlapping statement transactions. + ** + ** The statement transaction is never a top-level transaction. Hence + ** the RELEASE call below can never fail. + */ + assert( p->iStatement==0 || db->flags&SQLITE_CountRows ); + rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE); + if( NEVER(rc!=SQLITE_OK) ){ + break; + } + + /* Invalidate all ephemeral cursor row caches */ + p->cacheCtr = (p->cacheCtr + 2)|1; + + /* Make sure the results of the current row are \000 terminated + ** and have an assigned type. The results are de-ephemeralized as + ** a side effect. + */ + pMem = p->pResultSet = &aMem[pOp->p1]; + for(i=0; ip2; i++){ + assert( memIsValid(&pMem[i]) ); + Deephemeralize(&pMem[i]); + assert( (pMem[i].flags & MEM_Ephem)==0 + || (pMem[i].flags & (MEM_Str|MEM_Blob))==0 ); + sqlite3VdbeMemNulTerminate(&pMem[i]); + REGISTER_TRACE(pOp->p1+i, &pMem[i]); + } + if( db->mallocFailed ) goto no_mem; + + /* Return SQLITE_ROW + */ + p->pc = (int)(pOp - aOp) + 1; + rc = SQLITE_ROW; + goto vdbe_return; +} + +/* Opcode: Concat P1 P2 P3 * * +** Synopsis: r[P3]=r[P2]+r[P1] +** +** Add the text in register P1 onto the end of the text in +** register P2 and store the result in register P3. +** If either the P1 or P2 text are NULL then store NULL in P3. +** +** P3 = P2 || P1 +** +** It is illegal for P1 and P3 to be the same register. Sometimes, +** if P3 is the same register as P2, the implementation is able +** to avoid a memcpy(). +*/ +case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ + i64 nByte; + + pIn1 = &aMem[pOp->p1]; + pIn2 = &aMem[pOp->p2]; + pOut = &aMem[pOp->p3]; + assert( pIn1!=pOut ); + if( (pIn1->flags | pIn2->flags) & MEM_Null ){ + sqlite3VdbeMemSetNull(pOut); + break; + } + if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem; + Stringify(pIn1, encoding); + Stringify(pIn2, encoding); + nByte = pIn1->n + pIn2->n; + if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){ + goto no_mem; + } + MemSetTypeFlag(pOut, MEM_Str); + if( pOut!=pIn2 ){ + memcpy(pOut->z, pIn2->z, pIn2->n); + } + memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n); + pOut->z[nByte]=0; + pOut->z[nByte+1] = 0; + pOut->flags |= MEM_Term; + pOut->n = (int)nByte; + pOut->enc = encoding; + UPDATE_MAX_BLOBSIZE(pOut); + break; +} + +/* Opcode: Add P1 P2 P3 * * +** Synopsis: r[P3]=r[P1]+r[P2] +** +** Add the value in register P1 to the value in register P2 +** and store the result in register P3. +** If either input is NULL, the result is NULL. +*/ +/* Opcode: Multiply P1 P2 P3 * * +** Synopsis: r[P3]=r[P1]*r[P2] +** +** +** Multiply the value in register P1 by the value in register P2 +** and store the result in register P3. +** If either input is NULL, the result is NULL. +*/ +/* Opcode: Subtract P1 P2 P3 * * +** Synopsis: r[P3]=r[P2]-r[P1] +** +** Subtract the value in register P1 from the value in register P2 +** and store the result in register P3. +** If either input is NULL, the result is NULL. +*/ +/* Opcode: Divide P1 P2 P3 * * +** Synopsis: r[P3]=r[P2]/r[P1] +** +** Divide the value in register P1 by the value in register P2 +** and store the result in register P3 (P3=P2/P1). If the value in +** register P1 is zero, then the result is NULL. If either input is +** NULL, the result is NULL. +*/ +/* Opcode: Remainder P1 P2 P3 * * +** Synopsis: r[P3]=r[P2]%r[P1] +** +** Compute the remainder after integer register P2 is divided by +** register P1 and store the result in register P3. +** If the value in register P1 is zero the result is NULL. +** If either operand is NULL, the result is NULL. +*/ +case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ +case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ +case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ +case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ +case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ + char bIntint; /* Started out as two integer operands */ + u16 flags; /* Combined MEM_* flags from both inputs */ + u16 type1; /* Numeric type of left operand */ + u16 type2; /* Numeric type of right operand */ + i64 iA; /* Integer value of left operand */ + i64 iB; /* Integer value of right operand */ + double rA; /* Real value of left operand */ + double rB; /* Real value of right operand */ + + pIn1 = &aMem[pOp->p1]; + type1 = numericType(pIn1); + pIn2 = &aMem[pOp->p2]; + type2 = numericType(pIn2); + pOut = &aMem[pOp->p3]; + flags = pIn1->flags | pIn2->flags; + if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; + if( (type1 & type2 & MEM_Int)!=0 ){ + iA = pIn1->u.i; + iB = pIn2->u.i; + bIntint = 1; + switch( pOp->opcode ){ + case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break; + case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break; + case OP_Multiply: if( sqlite3MulInt64(&iB,iA) ) goto fp_math; break; + case OP_Divide: { + if( iA==0 ) goto arithmetic_result_is_null; + if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math; + iB /= iA; + break; + } + default: { + if( iA==0 ) goto arithmetic_result_is_null; + if( iA==-1 ) iA = 1; + iB %= iA; + break; + } + } + pOut->u.i = iB; + MemSetTypeFlag(pOut, MEM_Int); + }else{ + bIntint = 0; +fp_math: + rA = sqlite3VdbeRealValue(pIn1); + rB = sqlite3VdbeRealValue(pIn2); + switch( pOp->opcode ){ + case OP_Add: rB += rA; break; + case OP_Subtract: rB -= rA; break; + case OP_Multiply: rB *= rA; break; + case OP_Divide: { + /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ + if( rA==(double)0 ) goto arithmetic_result_is_null; + rB /= rA; + break; + } + default: { + iA = (i64)rA; + iB = (i64)rB; + if( iA==0 ) goto arithmetic_result_is_null; + if( iA==-1 ) iA = 1; + rB = (double)(iB % iA); + break; + } + } +#ifdef SQLITE_OMIT_FLOATING_POINT + pOut->u.i = rB; + MemSetTypeFlag(pOut, MEM_Int); +#else + if( sqlite3IsNaN(rB) ){ + goto arithmetic_result_is_null; + } + pOut->u.r = rB; + MemSetTypeFlag(pOut, MEM_Real); + if( ((type1|type2)&MEM_Real)==0 && !bIntint ){ + sqlite3VdbeIntegerAffinity(pOut); + } +#endif + } + break; + +arithmetic_result_is_null: + sqlite3VdbeMemSetNull(pOut); + break; +} + +/* Opcode: CollSeq P1 * * P4 +** +** P4 is a pointer to a CollSeq struct. If the next call to a user function +** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will +** be returned. This is used by the built-in min(), max() and nullif() +** functions. +** +** If P1 is not zero, then it is a register that a subsequent min() or +** max() aggregate will set to 1 if the current row is not the minimum or +** maximum. The P1 register is initialized to 0 by this instruction. +** +** The interface used by the implementation of the aforementioned functions +** to retrieve the collation sequence set by this opcode is not available +** publicly. Only built-in functions have access to this feature. +*/ +case OP_CollSeq: { + assert( pOp->p4type==P4_COLLSEQ ); + if( pOp->p1 ){ + sqlite3VdbeMemSetInt64(&aMem[pOp->p1], 0); + } + break; +} + +/* Opcode: Function0 P1 P2 P3 P4 P5 +** Synopsis: r[P3]=func(r[P2@P5]) +** +** Invoke a user function (P4 is a pointer to a FuncDef object that +** defines the function) with P5 arguments taken from register P2 and +** successors. The result of the function is stored in register P3. +** Register P3 must not be one of the function inputs. +** +** P1 is a 32-bit bitmask indicating whether or not each argument to the +** function was determined to be constant at compile time. If the first +** argument was constant then bit 0 of P1 is set. This is used to determine +** whether meta data associated with a user function argument using the +** sqlite3_set_auxdata() API may be safely retained until the next +** invocation of this opcode. +** +** See also: Function, AggStep, AggFinal +*/ +/* Opcode: Function P1 P2 P3 P4 P5 +** Synopsis: r[P3]=func(r[P2@P5]) +** +** Invoke a user function (P4 is a pointer to an sqlite3_context object that +** contains a pointer to the function to be run) with P5 arguments taken +** from register P2 and successors. The result of the function is stored +** in register P3. Register P3 must not be one of the function inputs. +** +** P1 is a 32-bit bitmask indicating whether or not each argument to the +** function was determined to be constant at compile time. If the first +** argument was constant then bit 0 of P1 is set. This is used to determine +** whether meta data associated with a user function argument using the +** sqlite3_set_auxdata() API may be safely retained until the next +** invocation of this opcode. +** +** SQL functions are initially coded as OP_Function0 with P4 pointing +** to a FuncDef object. But on first evaluation, the P4 operand is +** automatically converted into an sqlite3_context object and the operation +** changed to this OP_Function opcode. In this way, the initialization of +** the sqlite3_context object occurs only once, rather than once for each +** evaluation of the function. +** +** See also: Function0, AggStep, AggFinal +*/ +case OP_Function0: { + int n; + sqlite3_context *pCtx; + + assert( pOp->p4type==P4_FUNCDEF ); + n = pOp->p5; + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); + assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); + assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); + pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); + if( pCtx==0 ) goto no_mem; + pCtx->pOut = 0; + pCtx->pFunc = pOp->p4.pFunc; + pCtx->iOp = (int)(pOp - aOp); + pCtx->pVdbe = p; + pCtx->argc = n; + pOp->p4type = P4_FUNCCTX; + pOp->p4.pCtx = pCtx; + pOp->opcode = OP_Function; + /* Fall through into OP_Function */ +} +case OP_Function: { + int i; + sqlite3_context *pCtx; + + assert( pOp->p4type==P4_FUNCCTX ); + pCtx = pOp->p4.pCtx; + + /* If this function is inside of a trigger, the register array in aMem[] + ** might change from one evaluation to the next. The next block of code + ** checks to see if the register array has changed, and if so it + ** reinitializes the relavant parts of the sqlite3_context object */ + pOut = &aMem[pOp->p3]; + if( pCtx->pOut != pOut ){ + pCtx->pOut = pOut; + for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; + } + + memAboutToChange(p, pCtx->pOut); +#ifdef SQLITE_DEBUG + for(i=0; iargc; i++){ + assert( memIsValid(pCtx->argv[i]) ); + REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]); + } +#endif + MemSetTypeFlag(pCtx->pOut, MEM_Null); + pCtx->fErrorOrAux = 0; + db->lastRowid = lastRowid; + (*pCtx->pFunc->xFunc)(pCtx, pCtx->argc, pCtx->argv); /* IMP: R-24505-23230 */ + lastRowid = db->lastRowid; /* Remember rowid changes made by xFunc */ + + /* If the function returned an error, throw an exception */ + if( pCtx->fErrorOrAux ){ + if( pCtx->isError ){ + sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); + rc = pCtx->isError; + } + sqlite3VdbeDeleteAuxData(p, pCtx->iOp, pOp->p1); + } + + /* Copy the result of the function into register P3 */ + if( pOut->flags & (MEM_Str|MEM_Blob) ){ + sqlite3VdbeChangeEncoding(pCtx->pOut, encoding); + if( sqlite3VdbeMemTooBig(pCtx->pOut) ) goto too_big; + } + + REGISTER_TRACE(pOp->p3, pCtx->pOut); + UPDATE_MAX_BLOBSIZE(pCtx->pOut); + break; +} + +/* Opcode: BitAnd P1 P2 P3 * * +** Synopsis: r[P3]=r[P1]&r[P2] +** +** Take the bit-wise AND of the values in register P1 and P2 and +** store the result in register P3. +** If either input is NULL, the result is NULL. +*/ +/* Opcode: BitOr P1 P2 P3 * * +** Synopsis: r[P3]=r[P1]|r[P2] +** +** Take the bit-wise OR of the values in register P1 and P2 and +** store the result in register P3. +** If either input is NULL, the result is NULL. +*/ +/* Opcode: ShiftLeft P1 P2 P3 * * +** Synopsis: r[P3]=r[P2]<>r[P1] +** +** Shift the integer value in register P2 to the right by the +** number of bits specified by the integer in register P1. +** Store the result in register P3. +** If either input is NULL, the result is NULL. +*/ +case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */ +case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */ +case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */ +case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ + i64 iA; + u64 uA; + i64 iB; + u8 op; + + pIn1 = &aMem[pOp->p1]; + pIn2 = &aMem[pOp->p2]; + pOut = &aMem[pOp->p3]; + if( (pIn1->flags | pIn2->flags) & MEM_Null ){ + sqlite3VdbeMemSetNull(pOut); + break; + } + iA = sqlite3VdbeIntValue(pIn2); + iB = sqlite3VdbeIntValue(pIn1); + op = pOp->opcode; + if( op==OP_BitAnd ){ + iA &= iB; + }else if( op==OP_BitOr ){ + iA |= iB; + }else if( iB!=0 ){ + assert( op==OP_ShiftRight || op==OP_ShiftLeft ); + + /* If shifting by a negative amount, shift in the other direction */ + if( iB<0 ){ + assert( OP_ShiftRight==OP_ShiftLeft+1 ); + op = 2*OP_ShiftLeft + 1 - op; + iB = iB>(-64) ? -iB : 64; + } + + if( iB>=64 ){ + iA = (iA>=0 || op==OP_ShiftLeft) ? 0 : -1; + }else{ + memcpy(&uA, &iA, sizeof(uA)); + if( op==OP_ShiftLeft ){ + uA <<= iB; + }else{ + uA >>= iB; + /* Sign-extend on a right shift of a negative number */ + if( iA<0 ) uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-iB); + } + memcpy(&iA, &uA, sizeof(iA)); + } + } + pOut->u.i = iA; + MemSetTypeFlag(pOut, MEM_Int); + break; +} + +/* Opcode: AddImm P1 P2 * * * +** Synopsis: r[P1]=r[P1]+P2 +** +** Add the constant P2 to the value in register P1. +** The result is always an integer. +** +** To force any register to be an integer, just add 0. +*/ +case OP_AddImm: { /* in1 */ + pIn1 = &aMem[pOp->p1]; + memAboutToChange(p, pIn1); + sqlite3VdbeMemIntegerify(pIn1); + pIn1->u.i += pOp->p2; + break; +} + +/* Opcode: MustBeInt P1 P2 * * * +** +** Force the value in register P1 to be an integer. If the value +** in P1 is not an integer and cannot be converted into an integer +** without data loss, then jump immediately to P2, or if P2==0 +** raise an SQLITE_MISMATCH exception. +*/ +case OP_MustBeInt: { /* jump, in1 */ + pIn1 = &aMem[pOp->p1]; + if( (pIn1->flags & MEM_Int)==0 ){ + applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); + VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2); + if( (pIn1->flags & MEM_Int)==0 ){ + if( pOp->p2==0 ){ + rc = SQLITE_MISMATCH; + goto abort_due_to_error; + }else{ + goto jump_to_p2; + } + } + } + MemSetTypeFlag(pIn1, MEM_Int); + break; +} + +#ifndef SQLITE_OMIT_FLOATING_POINT +/* Opcode: RealAffinity P1 * * * * +** +** If register P1 holds an integer convert it to a real value. +** +** This opcode is used when extracting information from a column that +** has REAL affinity. Such column values may still be stored as +** integers, for space efficiency, but after extraction we want them +** to have only a real value. +*/ +case OP_RealAffinity: { /* in1 */ + pIn1 = &aMem[pOp->p1]; + if( pIn1->flags & MEM_Int ){ + sqlite3VdbeMemRealify(pIn1); + } + break; +} +#endif + +#ifndef SQLITE_OMIT_CAST +/* Opcode: Cast P1 P2 * * * +** Synopsis: affinity(r[P1]) +** +** Force the value in register P1 to be the type defined by P2. +** +**
      +**
    • TEXT +**
    • BLOB +**
    • NUMERIC +**
    • INTEGER +**
    • REAL +**
    +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_Cast: { /* in1 */ + assert( pOp->p2>=SQLITE_AFF_BLOB && pOp->p2<=SQLITE_AFF_REAL ); + testcase( pOp->p2==SQLITE_AFF_TEXT ); + testcase( pOp->p2==SQLITE_AFF_BLOB ); + testcase( pOp->p2==SQLITE_AFF_NUMERIC ); + testcase( pOp->p2==SQLITE_AFF_INTEGER ); + testcase( pOp->p2==SQLITE_AFF_REAL ); + pIn1 = &aMem[pOp->p1]; + memAboutToChange(p, pIn1); + rc = ExpandBlob(pIn1); + sqlite3VdbeMemCast(pIn1, pOp->p2, encoding); + UPDATE_MAX_BLOBSIZE(pIn1); + break; +} +#endif /* SQLITE_OMIT_CAST */ + +/* Opcode: Lt P1 P2 P3 P4 P5 +** Synopsis: if r[P1]r[P3] goto P2 +** +** This works just like the Lt opcode except that the jump is taken if +** the content of register P3 is greater than the content of +** register P1. See the Lt opcode for additional information. +*/ +/* Opcode: Ge P1 P2 P3 P4 P5 +** Synopsis: if r[P1]>=r[P3] goto P2 +** +** This works just like the Lt opcode except that the jump is taken if +** the content of register P3 is greater than or equal to the content of +** register P1. See the Lt opcode for additional information. +*/ +case OP_Eq: /* same as TK_EQ, jump, in1, in3 */ +case OP_Ne: /* same as TK_NE, jump, in1, in3 */ +case OP_Lt: /* same as TK_LT, jump, in1, in3 */ +case OP_Le: /* same as TK_LE, jump, in1, in3 */ +case OP_Gt: /* same as TK_GT, jump, in1, in3 */ +case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ + int res; /* Result of the comparison of pIn1 against pIn3 */ + char affinity; /* Affinity to use for comparison */ + u16 flags1; /* Copy of initial value of pIn1->flags */ + u16 flags3; /* Copy of initial value of pIn3->flags */ + + pIn1 = &aMem[pOp->p1]; + pIn3 = &aMem[pOp->p3]; + flags1 = pIn1->flags; + flags3 = pIn3->flags; + if( (flags1 | flags3)&MEM_Null ){ + /* One or both operands are NULL */ + if( pOp->p5 & SQLITE_NULLEQ ){ + /* If SQLITE_NULLEQ is set (which will only happen if the operator is + ** OP_Eq or OP_Ne) then take the jump or not depending on whether + ** or not both operands are null. + */ + assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); + assert( (flags1 & MEM_Cleared)==0 ); + assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); + if( (flags1&MEM_Null)!=0 + && (flags3&MEM_Null)!=0 + && (flags3&MEM_Cleared)==0 + ){ + res = 0; /* Results are equal */ + }else{ + res = 1; /* Results are not equal */ + } + }else{ + /* SQLITE_NULLEQ is clear and at least one operand is NULL, + ** then the result is always NULL. + ** The jump is taken if the SQLITE_JUMPIFNULL bit is set. + */ + if( pOp->p5 & SQLITE_STOREP2 ){ + pOut = &aMem[pOp->p2]; + MemSetTypeFlag(pOut, MEM_Null); + REGISTER_TRACE(pOp->p2, pOut); + }else{ + VdbeBranchTaken(2,3); + if( pOp->p5 & SQLITE_JUMPIFNULL ){ + goto jump_to_p2; + } + } + break; + } + }else{ + /* Neither operand is NULL. Do a comparison. */ + affinity = pOp->p5 & SQLITE_AFF_MASK; + if( affinity>=SQLITE_AFF_NUMERIC ){ + if( (pIn1->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ + applyNumericAffinity(pIn1,0); + } + if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ + applyNumericAffinity(pIn3,0); + } + }else if( affinity==SQLITE_AFF_TEXT ){ + if( (pIn1->flags & MEM_Str)==0 && (pIn1->flags & (MEM_Int|MEM_Real))!=0 ){ + testcase( pIn1->flags & MEM_Int ); + testcase( pIn1->flags & MEM_Real ); + sqlite3VdbeMemStringify(pIn1, encoding, 1); + testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); + flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); + } + if( (pIn3->flags & MEM_Str)==0 && (pIn3->flags & (MEM_Int|MEM_Real))!=0 ){ + testcase( pIn3->flags & MEM_Int ); + testcase( pIn3->flags & MEM_Real ); + sqlite3VdbeMemStringify(pIn3, encoding, 1); + testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) ); + flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask); + } + } + assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); + if( pIn1->flags & MEM_Zero ){ + sqlite3VdbeMemExpandBlob(pIn1); + flags1 &= ~MEM_Zero; + } + if( pIn3->flags & MEM_Zero ){ + sqlite3VdbeMemExpandBlob(pIn3); + flags3 &= ~MEM_Zero; + } + if( db->mallocFailed ) goto no_mem; + res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); + } + switch( pOp->opcode ){ + case OP_Eq: res = res==0; break; + case OP_Ne: res = res!=0; break; + case OP_Lt: res = res<0; break; + case OP_Le: res = res<=0; break; + case OP_Gt: res = res>0; break; + default: res = res>=0; break; + } + + /* Undo any changes made by applyAffinity() to the input registers. */ + assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) ); + pIn1->flags = flags1; + assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) ); + pIn3->flags = flags3; + + if( pOp->p5 & SQLITE_STOREP2 ){ + pOut = &aMem[pOp->p2]; + memAboutToChange(p, pOut); + MemSetTypeFlag(pOut, MEM_Int); + pOut->u.i = res; + REGISTER_TRACE(pOp->p2, pOut); + }else{ + VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); + if( res ){ + goto jump_to_p2; + } + } + break; +} + +/* Opcode: Permutation * * * P4 * +** +** Set the permutation used by the OP_Compare operator to be the array +** of integers in P4. +** +** The permutation is only valid until the next OP_Compare that has +** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should +** occur immediately prior to the OP_Compare. +*/ +case OP_Permutation: { + assert( pOp->p4type==P4_INTARRAY ); + assert( pOp->p4.ai ); + aPermute = pOp->p4.ai; + break; +} + +/* Opcode: Compare P1 P2 P3 P4 P5 +** Synopsis: r[P1@P3] <-> r[P2@P3] +** +** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this +** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of +** the comparison for use by the next OP_Jump instruct. +** +** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is +** determined by the most recent OP_Permutation operator. If the +** OPFLAG_PERMUTE bit is clear, then register are compared in sequential +** order. +** +** P4 is a KeyInfo structure that defines collating sequences and sort +** orders for the comparison. The permutation applies to registers +** only. The KeyInfo elements are used sequentially. +** +** The comparison is a sort comparison, so NULLs compare equal, +** NULLs are less than numbers, numbers are less than strings, +** and strings are less than blobs. +*/ +case OP_Compare: { + int n; + int i; + int p1; + int p2; + const KeyInfo *pKeyInfo; + int idx; + CollSeq *pColl; /* Collating sequence to use on this term */ + int bRev; /* True for DESCENDING sort order */ + + if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0; + n = pOp->p3; + pKeyInfo = pOp->p4.pKeyInfo; + assert( n>0 ); + assert( pKeyInfo!=0 ); + p1 = pOp->p1; + p2 = pOp->p2; +#if SQLITE_DEBUG + if( aPermute ){ + int k, mx = 0; + for(k=0; kmx ) mx = aPermute[k]; + assert( p1>0 && p1+mx<=(p->nMem-p->nCursor)+1 ); + assert( p2>0 && p2+mx<=(p->nMem-p->nCursor)+1 ); + }else{ + assert( p1>0 && p1+n<=(p->nMem-p->nCursor)+1 ); + assert( p2>0 && p2+n<=(p->nMem-p->nCursor)+1 ); + } +#endif /* SQLITE_DEBUG */ + for(i=0; inField ); + pColl = pKeyInfo->aColl[i]; + bRev = pKeyInfo->aSortOrder[i]; + iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl); + if( iCompare ){ + if( bRev ) iCompare = -iCompare; + break; + } + } + aPermute = 0; + break; +} + +/* Opcode: Jump P1 P2 P3 * * +** +** Jump to the instruction at address P1, P2, or P3 depending on whether +** in the most recent OP_Compare instruction the P1 vector was less than +** equal to, or greater than the P2 vector, respectively. +*/ +case OP_Jump: { /* jump */ + if( iCompare<0 ){ + VdbeBranchTaken(0,3); pOp = &aOp[pOp->p1 - 1]; + }else if( iCompare==0 ){ + VdbeBranchTaken(1,3); pOp = &aOp[pOp->p2 - 1]; + }else{ + VdbeBranchTaken(2,3); pOp = &aOp[pOp->p3 - 1]; + } + break; +} + +/* Opcode: And P1 P2 P3 * * +** Synopsis: r[P3]=(r[P1] && r[P2]) +** +** Take the logical AND of the values in registers P1 and P2 and +** write the result into register P3. +** +** If either P1 or P2 is 0 (false) then the result is 0 even if +** the other input is NULL. A NULL and true or two NULLs give +** a NULL output. +*/ +/* Opcode: Or P1 P2 P3 * * +** Synopsis: r[P3]=(r[P1] || r[P2]) +** +** Take the logical OR of the values in register P1 and P2 and +** store the answer in register P3. +** +** If either P1 or P2 is nonzero (true) then the result is 1 (true) +** even if the other input is NULL. A NULL and false or two NULLs +** give a NULL output. +*/ +case OP_And: /* same as TK_AND, in1, in2, out3 */ +case OP_Or: { /* same as TK_OR, in1, in2, out3 */ + int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ + int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ + + pIn1 = &aMem[pOp->p1]; + if( pIn1->flags & MEM_Null ){ + v1 = 2; + }else{ + v1 = sqlite3VdbeIntValue(pIn1)!=0; + } + pIn2 = &aMem[pOp->p2]; + if( pIn2->flags & MEM_Null ){ + v2 = 2; + }else{ + v2 = sqlite3VdbeIntValue(pIn2)!=0; + } + if( pOp->opcode==OP_And ){ + static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; + v1 = and_logic[v1*3+v2]; + }else{ + static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; + v1 = or_logic[v1*3+v2]; + } + pOut = &aMem[pOp->p3]; + if( v1==2 ){ + MemSetTypeFlag(pOut, MEM_Null); + }else{ + pOut->u.i = v1; + MemSetTypeFlag(pOut, MEM_Int); + } + break; +} + +/* Opcode: Not P1 P2 * * * +** Synopsis: r[P2]= !r[P1] +** +** Interpret the value in register P1 as a boolean value. Store the +** boolean complement in register P2. If the value in register P1 is +** NULL, then a NULL is stored in P2. +*/ +case OP_Not: { /* same as TK_NOT, in1, out2 */ + pIn1 = &aMem[pOp->p1]; + pOut = &aMem[pOp->p2]; + sqlite3VdbeMemSetNull(pOut); + if( (pIn1->flags & MEM_Null)==0 ){ + pOut->flags = MEM_Int; + pOut->u.i = !sqlite3VdbeIntValue(pIn1); + } + break; +} + +/* Opcode: BitNot P1 P2 * * * +** Synopsis: r[P1]= ~r[P1] +** +** Interpret the content of register P1 as an integer. Store the +** ones-complement of the P1 value into register P2. If P1 holds +** a NULL then store a NULL in P2. +*/ +case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */ + pIn1 = &aMem[pOp->p1]; + pOut = &aMem[pOp->p2]; + sqlite3VdbeMemSetNull(pOut); + if( (pIn1->flags & MEM_Null)==0 ){ + pOut->flags = MEM_Int; + pOut->u.i = ~sqlite3VdbeIntValue(pIn1); + } + break; +} + +/* Opcode: Once P1 P2 * * * +** +** Check the "once" flag number P1. If it is set, jump to instruction P2. +** Otherwise, set the flag and fall through to the next instruction. +** In other words, this opcode causes all following opcodes up through P2 +** (but not including P2) to run just once and to be skipped on subsequent +** times through the loop. +** +** All "once" flags are initially cleared whenever a prepared statement +** first begins to run. +*/ +case OP_Once: { /* jump */ + assert( pOp->p1nOnceFlag ); + VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2); + if( p->aOnceFlag[pOp->p1] ){ + goto jump_to_p2; + }else{ + p->aOnceFlag[pOp->p1] = 1; + } + break; +} + +/* Opcode: If P1 P2 P3 * * +** +** Jump to P2 if the value in register P1 is true. The value +** is considered true if it is numeric and non-zero. If the value +** in P1 is NULL then take the jump if and only if P3 is non-zero. +*/ +/* Opcode: IfNot P1 P2 P3 * * +** +** Jump to P2 if the value in register P1 is False. The value +** is considered false if it has a numeric value of zero. If the value +** in P1 is NULL then take the jump if and only if P3 is non-zero. +*/ +case OP_If: /* jump, in1 */ +case OP_IfNot: { /* jump, in1 */ + int c; + pIn1 = &aMem[pOp->p1]; + if( pIn1->flags & MEM_Null ){ + c = pOp->p3; + }else{ +#ifdef SQLITE_OMIT_FLOATING_POINT + c = sqlite3VdbeIntValue(pIn1)!=0; +#else + c = sqlite3VdbeRealValue(pIn1)!=0.0; +#endif + if( pOp->opcode==OP_IfNot ) c = !c; + } + VdbeBranchTaken(c!=0, 2); + if( c ){ + goto jump_to_p2; + } + break; +} + +/* Opcode: IsNull P1 P2 * * * +** Synopsis: if r[P1]==NULL goto P2 +** +** Jump to P2 if the value in register P1 is NULL. +*/ +case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ + pIn1 = &aMem[pOp->p1]; + VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2); + if( (pIn1->flags & MEM_Null)!=0 ){ + goto jump_to_p2; + } + break; +} + +/* Opcode: NotNull P1 P2 * * * +** Synopsis: if r[P1]!=NULL goto P2 +** +** Jump to P2 if the value in register P1 is not NULL. +*/ +case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ + pIn1 = &aMem[pOp->p1]; + VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2); + if( (pIn1->flags & MEM_Null)==0 ){ + goto jump_to_p2; + } + break; +} + +/* Opcode: Column P1 P2 P3 P4 P5 +** Synopsis: r[P3]=PX +** +** Interpret the data that cursor P1 points to as a structure built using +** the MakeRecord instruction. (See the MakeRecord opcode for additional +** information about the format of the data.) Extract the P2-th column +** from this record. If there are less that (P2+1) +** values in the record, extract a NULL. +** +** The value extracted is stored in register P3. +** +** If the column contains fewer than P2 fields, then extract a NULL. Or, +** if the P4 argument is a P4_MEM use the value of the P4 argument as +** the result. +** +** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor, +** then the cache of the cursor is reset prior to extracting the column. +** The first OP_Column against a pseudo-table after the value of the content +** register has changed should have this bit set. +** +** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 when +** the result is guaranteed to only be used as the argument of a length() +** or typeof() function, respectively. The loading of large blobs can be +** skipped for length() and all content loading can be skipped for typeof(). +*/ +case OP_Column: { + i64 payloadSize64; /* Number of bytes in the record */ + int p2; /* column number to retrieve */ + VdbeCursor *pC; /* The VDBE cursor */ + BtCursor *pCrsr; /* The BTree cursor */ + u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ + int len; /* The length of the serialized data for the column */ + int i; /* Loop counter */ + Mem *pDest; /* Where to write the extracted value */ + Mem sMem; /* For storing the record being decoded */ + const u8 *zData; /* Part of the record being decoded */ + const u8 *zHdr; /* Next unparsed byte of the header */ + const u8 *zEndHdr; /* Pointer to first byte after the header */ + u32 offset; /* Offset into the data */ + u32 szField; /* Number of bytes in the content of a field */ + u32 avail; /* Number of bytes of available data */ + u32 t; /* A type code from the record header */ + u16 fx; /* pDest->flags value */ + Mem *pReg; /* PseudoTable input register */ + + p2 = pOp->p2; + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); + pDest = &aMem[pOp->p3]; + memAboutToChange(p, pDest); + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( p2nField ); + aOffset = pC->aOffset; +#ifndef SQLITE_OMIT_VIRTUALTABLE + assert( pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */ +#endif + pCrsr = pC->pCursor; + assert( pCrsr!=0 || pC->pseudoTableReg>0 ); /* pCrsr NULL on PseudoTables */ + assert( pCrsr!=0 || pC->nullRow ); /* pC->nullRow on PseudoTables */ + + /* If the cursor cache is stale, bring it up-to-date */ + rc = sqlite3VdbeCursorMoveto(pC); + if( rc ) goto abort_due_to_error; + if( pC->cacheStatus!=p->cacheCtr ){ + if( pC->nullRow ){ + if( pCrsr==0 ){ + assert( pC->pseudoTableReg>0 ); + pReg = &aMem[pC->pseudoTableReg]; + assert( pReg->flags & MEM_Blob ); + assert( memIsValid(pReg) ); + pC->payloadSize = pC->szRow = avail = pReg->n; + pC->aRow = (u8*)pReg->z; + }else{ + sqlite3VdbeMemSetNull(pDest); + goto op_column_out; + } + }else{ + assert( pCrsr ); + if( pC->isTable==0 ){ + assert( sqlite3BtreeCursorIsValid(pCrsr) ); + VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &payloadSize64); + assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ + /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the + ** payload size, so it is impossible for payloadSize64 to be + ** larger than 32 bits. */ + assert( (payloadSize64 & SQLITE_MAX_U32)==(u64)payloadSize64 ); + pC->aRow = sqlite3BtreeKeyFetch(pCrsr, &avail); + pC->payloadSize = (u32)payloadSize64; + }else{ + assert( sqlite3BtreeCursorIsValid(pCrsr) ); + VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &pC->payloadSize); + assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ + pC->aRow = sqlite3BtreeDataFetch(pCrsr, &avail); + } + assert( avail<=65536 ); /* Maximum page size is 64KiB */ + if( pC->payloadSize <= (u32)avail ){ + pC->szRow = pC->payloadSize; + }else{ + pC->szRow = avail; + } + if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + } + pC->cacheStatus = p->cacheCtr; + pC->iHdrOffset = getVarint32(pC->aRow, offset); + pC->nHdrParsed = 0; + aOffset[0] = offset; + + /* Make sure a corrupt database has not given us an oversize header. + ** Do this now to avoid an oversize memory allocation. + ** + ** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte + ** types use so much data space that there can only be 4096 and 32 of + ** them, respectively. So the maximum header length results from a + ** 3-byte type for each of the maximum of 32768 columns plus three + ** extra bytes for the header length itself. 32768*3 + 3 = 98307. + */ + if( offset > 98307 || offset > pC->payloadSize ){ + rc = SQLITE_CORRUPT_BKPT; + goto op_column_error; + } + + if( availaRow does not have to hold the entire row, but it does at least + ** need to cover the header of the record. If pC->aRow does not contain + ** the complete header, then set it to zero, forcing the header to be + ** dynamically allocated. */ + pC->aRow = 0; + pC->szRow = 0; + } + + /* The following goto is an optimization. It can be omitted and + ** everything will still work. But OP_Column is measurably faster + ** by skipping the subsequent conditional, which is always true. + */ + assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */ + goto op_column_read_header; + } + + /* Make sure at least the first p2+1 entries of the header have been + ** parsed and valid information is in aOffset[] and pC->aType[]. + */ + if( pC->nHdrParsed<=p2 ){ + /* If there is more header available for parsing in the record, try + ** to extract additional fields up through the p2+1-th field + */ + op_column_read_header: + if( pC->iHdrOffsetaRow==0 ){ + memset(&sMem, 0, sizeof(sMem)); + rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], + !pC->isTable, &sMem); + if( rc!=SQLITE_OK ){ + goto op_column_error; + } + zData = (u8*)sMem.z; + }else{ + zData = pC->aRow; + } + + /* Fill in pC->aType[i] and aOffset[i] values through the p2-th field. */ + i = pC->nHdrParsed; + offset = aOffset[i]; + zHdr = zData + pC->iHdrOffset; + zEndHdr = zData + aOffset[0]; + assert( i<=p2 && zHdraType[i] = t; + szField = sqlite3VdbeSerialTypeLen(t); + offset += szField; + if( offsetnHdrParsed = i; + pC->iHdrOffset = (u32)(zHdr - zData); + if( pC->aRow==0 ){ + sqlite3VdbeMemRelease(&sMem); + sMem.flags = MEM_Null; + } + + /* The record is corrupt if any of the following are true: + ** (1) the bytes of the header extend past the declared header size + ** (zHdr>zEndHdr) + ** (2) the entire header was used but not all data was used + ** (zHdr==zEndHdr && offset!=pC->payloadSize) + ** (3) the end of the data extends beyond the end of the record. + ** (offset > pC->payloadSize) + */ + if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset!=pC->payloadSize)) + || (offset > pC->payloadSize) + ){ + rc = SQLITE_CORRUPT_BKPT; + goto op_column_error; + } + } + + /* If after trying to extract new entries from the header, nHdrParsed is + ** still not up to p2, that means that the record has fewer than p2 + ** columns. So the result will be either the default value or a NULL. + */ + if( pC->nHdrParsed<=p2 ){ + if( pOp->p4type==P4_MEM ){ + sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static); + }else{ + sqlite3VdbeMemSetNull(pDest); + } + goto op_column_out; + } + } + + /* Extract the content for the p2+1-th column. Control can only + ** reach this point if aOffset[p2], aOffset[p2+1], and pC->aType[p2] are + ** all valid. + */ + assert( p2nHdrParsed ); + assert( rc==SQLITE_OK ); + assert( sqlite3VdbeCheckMemInvariants(pDest) ); + if( VdbeMemDynamic(pDest) ) sqlite3VdbeMemSetNull(pDest); + t = pC->aType[p2]; + if( pC->szRow>=aOffset[p2+1] ){ + /* This is the common case where the desired content fits on the original + ** page - where the content is not on an overflow page */ + sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], t, pDest); + }else{ + /* This branch happens only when content is on overflow pages */ + if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 + && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)) + || (len = sqlite3VdbeSerialTypeLen(t))==0 + ){ + /* Content is irrelevant for + ** 1. the typeof() function, + ** 2. the length(X) function if X is a blob, and + ** 3. if the content length is zero. + ** So we might as well use bogus content rather than reading + ** content from disk. NULL will work for the value for strings + ** and blobs and whatever is in the payloadSize64 variable + ** will work for everything else. */ + sqlite3VdbeSerialGet(t<=13 ? (u8*)&payloadSize64 : 0, t, pDest); + }else{ + rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable, + pDest); + if( rc!=SQLITE_OK ){ + goto op_column_error; + } + sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest); + pDest->flags &= ~MEM_Ephem; + } + } + pDest->enc = encoding; + +op_column_out: + /* If the column value is an ephemeral string, go ahead and persist + ** that string in case the cursor moves before the column value is + ** used. The following code does the equivalent of Deephemeralize() + ** but does it faster. */ + if( (pDest->flags & MEM_Ephem)!=0 && pDest->z ){ + fx = pDest->flags & (MEM_Str|MEM_Blob); + assert( fx!=0 ); + zData = (const u8*)pDest->z; + len = pDest->n; + if( sqlite3VdbeMemClearAndResize(pDest, len+2) ) goto no_mem; + memcpy(pDest->z, zData, len); + pDest->z[len] = 0; + pDest->z[len+1] = 0; + pDest->flags = fx|MEM_Term; + } +op_column_error: + UPDATE_MAX_BLOBSIZE(pDest); + REGISTER_TRACE(pOp->p3, pDest); + break; +} + +/* Opcode: Affinity P1 P2 * P4 * +** Synopsis: affinity(r[P1@P2]) +** +** Apply affinities to a range of P2 registers starting with P1. +** +** P4 is a string that is P2 characters long. The nth character of the +** string indicates the column affinity that should be used for the nth +** memory cell in the range. +*/ +case OP_Affinity: { + const char *zAffinity; /* The affinity to be applied */ + char cAff; /* A single character of affinity */ + + zAffinity = pOp->p4.z; + assert( zAffinity!=0 ); + assert( zAffinity[pOp->p2]==0 ); + pIn1 = &aMem[pOp->p1]; + while( (cAff = *(zAffinity++))!=0 ){ + assert( pIn1 <= &p->aMem[(p->nMem-p->nCursor)] ); + assert( memIsValid(pIn1) ); + applyAffinity(pIn1, cAff, encoding); + pIn1++; + } + break; +} + +/* Opcode: MakeRecord P1 P2 P3 P4 * +** Synopsis: r[P3]=mkrec(r[P1@P2]) +** +** Convert P2 registers beginning with P1 into the [record format] +** use as a data record in a database table or as a key +** in an index. The OP_Column opcode can decode the record later. +** +** P4 may be a string that is P2 characters long. The nth character of the +** string indicates the column affinity that should be used for the nth +** field of the index key. +** +** The mapping from character to affinity is given by the SQLITE_AFF_ +** macros defined in sqliteInt.h. +** +** If P4 is NULL then all index fields have the affinity BLOB. +*/ +case OP_MakeRecord: { + u8 *zNewRecord; /* A buffer to hold the data for the new record */ + Mem *pRec; /* The new record */ + u64 nData; /* Number of bytes of data space */ + int nHdr; /* Number of bytes of header space */ + i64 nByte; /* Data space required for this record */ + i64 nZero; /* Number of zero bytes at the end of the record */ + int nVarint; /* Number of bytes in a varint */ + u32 serial_type; /* Type field */ + Mem *pData0; /* First field to be combined into the record */ + Mem *pLast; /* Last field of the record */ + int nField; /* Number of fields in the record */ + char *zAffinity; /* The affinity string for the record */ + int file_format; /* File format to use for encoding */ + int i; /* Space used in zNewRecord[] header */ + int j; /* Space used in zNewRecord[] content */ + int len; /* Length of a field */ + + /* Assuming the record contains N fields, the record format looks + ** like this: + ** + ** ------------------------------------------------------------------------ + ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | + ** ------------------------------------------------------------------------ + ** + ** Data(0) is taken from register P1. Data(1) comes from register P1+1 + ** and so forth. + ** + ** Each type field is a varint representing the serial type of the + ** corresponding data element (see sqlite3VdbeSerialType()). The + ** hdr-size field is also a varint which is the offset from the beginning + ** of the record to data0. + */ + nData = 0; /* Number of bytes of data space */ + nHdr = 0; /* Number of bytes of header space */ + nZero = 0; /* Number of zero bytes at the end of the record */ + nField = pOp->p1; + zAffinity = pOp->p4.z; + assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem-p->nCursor)+1 ); + pData0 = &aMem[nField]; + nField = pOp->p2; + pLast = &pData0[nField-1]; + file_format = p->minWriteFileFormat; + + /* Identify the output register */ + assert( pOp->p3p1 || pOp->p3>=pOp->p1+pOp->p2 ); + pOut = &aMem[pOp->p3]; + memAboutToChange(p, pOut); + + /* Apply the requested affinity to all inputs + */ + assert( pData0<=pLast ); + if( zAffinity ){ + pRec = pData0; + do{ + applyAffinity(pRec++, *(zAffinity++), encoding); + assert( zAffinity[0]==0 || pRec<=pLast ); + }while( zAffinity[0] ); + } + + /* Loop through the elements that will make up the record to figure + ** out how much space is required for the new record. + */ + pRec = pLast; + do{ + assert( memIsValid(pRec) ); + pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format); + len = sqlite3VdbeSerialTypeLen(serial_type); + if( pRec->flags & MEM_Zero ){ + if( nData ){ + if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; + }else{ + nZero += pRec->u.nZero; + len -= pRec->u.nZero; + } + } + nData += len; + testcase( serial_type==127 ); + testcase( serial_type==128 ); + nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type); + }while( (--pRec)>=pData0 ); + + /* EVIDENCE-OF: R-22564-11647 The header begins with a single varint + ** which determines the total number of bytes in the header. The varint + ** value is the size of the header in bytes including the size varint + ** itself. */ + testcase( nHdr==126 ); + testcase( nHdr==127 ); + if( nHdr<=126 ){ + /* The common case */ + nHdr += 1; + }else{ + /* Rare case of a really large header */ + nVarint = sqlite3VarintLen(nHdr); + nHdr += nVarint; + if( nVarintdb->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + + /* Make sure the output register has a buffer large enough to store + ** the new record. The output register (pOp->p3) is not allowed to + ** be one of the input registers (because the following call to + ** sqlite3VdbeMemClearAndResize() could clobber the value before it is used). + */ + if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ + goto no_mem; + } + zNewRecord = (u8 *)pOut->z; + + /* Write the record */ + i = putVarint32(zNewRecord, nHdr); + j = nHdr; + assert( pData0<=pLast ); + pRec = pData0; + do{ + serial_type = pRec->uTemp; + /* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more + ** additional varints, one per column. */ + i += putVarint32(&zNewRecord[i], serial_type); /* serial type */ + /* EVIDENCE-OF: R-64536-51728 The values for each column in the record + ** immediately follow the header. */ + j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */ + }while( (++pRec)<=pLast ); + assert( i==nHdr ); + assert( j==nByte ); + + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); + pOut->n = (int)nByte; + pOut->flags = MEM_Blob; + if( nZero ){ + pOut->u.nZero = nZero; + pOut->flags |= MEM_Zero; + } + pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */ + REGISTER_TRACE(pOp->p3, pOut); + UPDATE_MAX_BLOBSIZE(pOut); + break; +} + +/* Opcode: Count P1 P2 * * * +** Synopsis: r[P2]=count() +** +** Store the number of entries (an integer value) in the table or index +** opened by cursor P1 in register P2 +*/ +#ifndef SQLITE_OMIT_BTREECOUNT +case OP_Count: { /* out2 */ + i64 nEntry; + BtCursor *pCrsr; + + pCrsr = p->apCsr[pOp->p1]->pCursor; + assert( pCrsr ); + nEntry = 0; /* Not needed. Only used to silence a warning. */ + rc = sqlite3BtreeCount(pCrsr, &nEntry); + pOut = out2Prerelease(p, pOp); + pOut->u.i = nEntry; + break; +} +#endif + +/* Opcode: Savepoint P1 * * P4 * +** +** Open, release or rollback the savepoint named by parameter P4, depending +** on the value of P1. To open a new savepoint, P1==0. To release (commit) an +** existing savepoint, P1==1, or to rollback an existing savepoint P1==2. +*/ +case OP_Savepoint: { + int p1; /* Value of P1 operand */ + char *zName; /* Name of savepoint */ + int nName; + Savepoint *pNew; + Savepoint *pSavepoint; + Savepoint *pTmp; + int iSavepoint; + int ii; + + p1 = pOp->p1; + zName = pOp->p4.z; + + /* Assert that the p1 parameter is valid. Also that if there is no open + ** transaction, then there cannot be any savepoints. + */ + assert( db->pSavepoint==0 || db->autoCommit==0 ); + assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK ); + assert( db->pSavepoint || db->isTransactionSavepoint==0 ); + assert( checkSavepointCount(db) ); + assert( p->bIsReader ); + + if( p1==SAVEPOINT_BEGIN ){ + if( db->nVdbeWrite>0 ){ + /* A new savepoint cannot be created if there are active write + ** statements (i.e. open read/write incremental blob handles). + */ + sqlite3VdbeError(p, "cannot open savepoint - SQL statements in progress"); + rc = SQLITE_BUSY; + }else{ + nName = sqlite3Strlen30(zName); + +#ifndef SQLITE_OMIT_VIRTUALTABLE + /* This call is Ok even if this savepoint is actually a transaction + ** savepoint (and therefore should not prompt xSavepoint()) callbacks. + ** If this is a transaction savepoint being opened, it is guaranteed + ** that the db->aVTrans[] array is empty. */ + assert( db->autoCommit==0 || db->nVTrans==0 ); + rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, + db->nStatement+db->nSavepoint); + if( rc!=SQLITE_OK ) goto abort_due_to_error; +#endif + + /* Create a new savepoint structure. */ + pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+nName+1); + if( pNew ){ + pNew->zName = (char *)&pNew[1]; + memcpy(pNew->zName, zName, nName+1); + + /* If there is no open transaction, then mark this as a special + ** "transaction savepoint". */ + if( db->autoCommit ){ + db->autoCommit = 0; + db->isTransactionSavepoint = 1; + }else{ + db->nSavepoint++; + } + + /* Link the new savepoint into the database handle's list. */ + pNew->pNext = db->pSavepoint; + db->pSavepoint = pNew; + pNew->nDeferredCons = db->nDeferredCons; + pNew->nDeferredImmCons = db->nDeferredImmCons; + } + } + }else{ + iSavepoint = 0; + + /* Find the named savepoint. If there is no such savepoint, then an + ** an error is returned to the user. */ + for( + pSavepoint = db->pSavepoint; + pSavepoint && sqlite3StrICmp(pSavepoint->zName, zName); + pSavepoint = pSavepoint->pNext + ){ + iSavepoint++; + } + if( !pSavepoint ){ + sqlite3VdbeError(p, "no such savepoint: %s", zName); + rc = SQLITE_ERROR; + }else if( db->nVdbeWrite>0 && p1==SAVEPOINT_RELEASE ){ + /* It is not possible to release (commit) a savepoint if there are + ** active write statements. + */ + sqlite3VdbeError(p, "cannot release savepoint - " + "SQL statements in progress"); + rc = SQLITE_BUSY; + }else{ + + /* Determine whether or not this is a transaction savepoint. If so, + ** and this is a RELEASE command, then the current transaction + ** is committed. + */ + int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint; + if( isTransaction && p1==SAVEPOINT_RELEASE ){ + if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ + goto vdbe_return; + } + db->autoCommit = 1; + if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ + p->pc = (int)(pOp - aOp); + db->autoCommit = 0; + p->rc = rc = SQLITE_BUSY; + goto vdbe_return; + } + db->isTransactionSavepoint = 0; + rc = p->rc; + }else{ + int isSchemaChange; + iSavepoint = db->nSavepoint - iSavepoint - 1; + if( p1==SAVEPOINT_ROLLBACK ){ + isSchemaChange = (db->flags & SQLITE_InternChanges)!=0; + for(ii=0; iinDb; ii++){ + rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, + SQLITE_ABORT_ROLLBACK, + isSchemaChange==0); + if( rc!=SQLITE_OK ) goto abort_due_to_error; + } + }else{ + isSchemaChange = 0; + } + for(ii=0; iinDb; ii++){ + rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + } + if( isSchemaChange ){ + sqlite3ExpirePreparedStatements(db); + sqlite3ResetAllSchemasOfConnection(db); + db->flags = (db->flags | SQLITE_InternChanges); + } + } + + /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all + ** savepoints nested inside of the savepoint being operated on. */ + while( db->pSavepoint!=pSavepoint ){ + pTmp = db->pSavepoint; + db->pSavepoint = pTmp->pNext; + sqlite3DbFree(db, pTmp); + db->nSavepoint--; + } + + /* If it is a RELEASE, then destroy the savepoint being operated on + ** too. If it is a ROLLBACK TO, then set the number of deferred + ** constraint violations present in the database to the value stored + ** when the savepoint was created. */ + if( p1==SAVEPOINT_RELEASE ){ + assert( pSavepoint==db->pSavepoint ); + db->pSavepoint = pSavepoint->pNext; + sqlite3DbFree(db, pSavepoint); + if( !isTransaction ){ + db->nSavepoint--; + } + }else{ + db->nDeferredCons = pSavepoint->nDeferredCons; + db->nDeferredImmCons = pSavepoint->nDeferredImmCons; + } + + if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){ + rc = sqlite3VtabSavepoint(db, p1, iSavepoint); + if( rc!=SQLITE_OK ) goto abort_due_to_error; + } + } + } + + break; +} + +/* Opcode: AutoCommit P1 P2 * * * +** +** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll +** back any currently active btree transactions. If there are any active +** VMs (apart from this one), then a ROLLBACK fails. A COMMIT fails if +** there are active writing VMs or active VMs that use shared cache. +** +** This instruction causes the VM to halt. +*/ +case OP_AutoCommit: { + int desiredAutoCommit; + int iRollback; + int turnOnAC; + + desiredAutoCommit = pOp->p1; + iRollback = pOp->p2; + turnOnAC = desiredAutoCommit && !db->autoCommit; + assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); + assert( desiredAutoCommit==1 || iRollback==0 ); + assert( db->nVdbeActive>0 ); /* At least this one VM is active */ + assert( p->bIsReader ); + + if( turnOnAC && !iRollback && db->nVdbeWrite>0 ){ + /* If this instruction implements a COMMIT and other VMs are writing + ** return an error indicating that the other VMs must complete first. + */ + sqlite3VdbeError(p, "cannot commit transaction - " + "SQL statements in progress"); + rc = SQLITE_BUSY; + }else if( desiredAutoCommit!=db->autoCommit ){ + if( iRollback ){ + assert( desiredAutoCommit==1 ); + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); + db->autoCommit = 1; + }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ + goto vdbe_return; + }else{ + db->autoCommit = (u8)desiredAutoCommit; + if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ + p->pc = (int)(pOp - aOp); + db->autoCommit = (u8)(1-desiredAutoCommit); + p->rc = rc = SQLITE_BUSY; + goto vdbe_return; + } + } + assert( db->nStatement==0 ); + sqlite3CloseSavepoints(db); + if( p->rc==SQLITE_OK ){ + rc = SQLITE_DONE; + }else{ + rc = SQLITE_ERROR; + } + goto vdbe_return; + }else{ + sqlite3VdbeError(p, + (!desiredAutoCommit)?"cannot start a transaction within a transaction":( + (iRollback)?"cannot rollback - no transaction is active": + "cannot commit - no transaction is active")); + + rc = SQLITE_ERROR; + } + break; +} + +/* Opcode: Transaction P1 P2 P3 P4 P5 +** +** Begin a transaction on database P1 if a transaction is not already +** active. +** If P2 is non-zero, then a write-transaction is started, or if a +** read-transaction is already active, it is upgraded to a write-transaction. +** If P2 is zero, then a read-transaction is started. +** +** P1 is the index of the database file on which the transaction is +** started. Index 0 is the main database file and index 1 is the +** file used for temporary tables. Indices of 2 or more are used for +** attached databases. +** +** If a write-transaction is started and the Vdbe.usesStmtJournal flag is +** true (this flag is set if the Vdbe may modify more than one row and may +** throw an ABORT exception), a statement transaction may also be opened. +** More specifically, a statement transaction is opened iff the database +** connection is currently not in autocommit mode, or if there are other +** active statements. A statement transaction allows the changes made by this +** VDBE to be rolled back after an error without having to roll back the +** entire transaction. If no error is encountered, the statement transaction +** will automatically commit when the VDBE halts. +** +** If P5!=0 then this opcode also checks the schema cookie against P3 +** and the schema generation counter against P4. +** The cookie changes its value whenever the database schema changes. +** This operation is used to detect when that the cookie has changed +** and that the current process needs to reread the schema. If the schema +** cookie in P3 differs from the schema cookie in the database header or +** if the schema generation counter in P4 differs from the current +** generation counter, then an SQLITE_SCHEMA error is raised and execution +** halts. The sqlite3_step() wrapper function might then reprepare the +** statement and rerun it from the beginning. +*/ +case OP_Transaction: { + Btree *pBt; + int iMeta; + int iGen; + + assert( p->bIsReader ); + assert( p->readOnly==0 || pOp->p2==0 ); + assert( pOp->p1>=0 && pOp->p1nDb ); + assert( DbMaskTest(p->btreeMask, pOp->p1) ); + if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){ + rc = SQLITE_READONLY; + goto abort_due_to_error; + } + pBt = db->aDb[pOp->p1].pBt; + + if( pBt ){ + rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); + if( rc==SQLITE_BUSY ){ + p->pc = (int)(pOp - aOp); + p->rc = rc = SQLITE_BUSY; + goto vdbe_return; + } + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + + if( pOp->p2 && p->usesStmtJournal + && (db->autoCommit==0 || db->nVdbeRead>1) + ){ + assert( sqlite3BtreeIsInTrans(pBt) ); + if( p->iStatement==0 ){ + assert( db->nStatement>=0 && db->nSavepoint>=0 ); + db->nStatement++; + p->iStatement = db->nSavepoint + db->nStatement; + } + + rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeBeginStmt(pBt, p->iStatement); + } + + /* Store the current value of the database handles deferred constraint + ** counter. If the statement transaction needs to be rolled back, + ** the value of this counter needs to be restored too. */ + p->nStmtDefCons = db->nDeferredCons; + p->nStmtDefImmCons = db->nDeferredImmCons; + } + + /* Gather the schema version number for checking: + ** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite + ** each time a query is executed to ensure that the internal cache of the + ** schema used when compiling the SQL query matches the schema of the + ** database against which the compiled query is actually executed. + */ + sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); + iGen = db->aDb[pOp->p1].pSchema->iGeneration; + }else{ + iGen = iMeta = 0; + } + assert( pOp->p5==0 || pOp->p4type==P4_INT32 ); + if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){ + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); + /* If the schema-cookie from the database file matches the cookie + ** stored with the in-memory representation of the schema, do + ** not reload the schema from the database file. + ** + ** If virtual-tables are in use, this is not just an optimization. + ** Often, v-tables store their data in other SQLite tables, which + ** are queried from within xNext() and other v-table methods using + ** prepared queries. If such a query is out-of-date, we do not want to + ** discard the database schema, as the user code implementing the + ** v-table would have to be ready for the sqlite3_vtab structure itself + ** to be invalidated whenever sqlite3_step() is called from within + ** a v-table method. + */ + if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){ + sqlite3ResetOneSchema(db, pOp->p1); + } + p->expired = 1; + rc = SQLITE_SCHEMA; + } + break; +} + +/* Opcode: ReadCookie P1 P2 P3 * * +** +** Read cookie number P3 from database P1 and write it into register P2. +** P3==1 is the schema version. P3==2 is the database format. +** P3==3 is the recommended pager cache size, and so forth. P1==0 is +** the main database file and P1==1 is the database file used to store +** temporary tables. +** +** There must be a read-lock on the database (either a transaction +** must be started or there must be an open cursor) before +** executing this instruction. +*/ +case OP_ReadCookie: { /* out2 */ + int iMeta; + int iDb; + int iCookie; + + assert( p->bIsReader ); + iDb = pOp->p1; + iCookie = pOp->p3; + assert( pOp->p3=0 && iDbnDb ); + assert( db->aDb[iDb].pBt!=0 ); + assert( DbMaskTest(p->btreeMask, iDb) ); + + sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta); + pOut = out2Prerelease(p, pOp); + pOut->u.i = iMeta; + break; +} + +/* Opcode: SetCookie P1 P2 P3 * * +** +** Write the content of register P3 (interpreted as an integer) +** into cookie number P2 of database P1. P2==1 is the schema version. +** P2==2 is the database format. P2==3 is the recommended pager cache +** size, and so forth. P1==0 is the main database file and P1==1 is the +** database file used to store temporary tables. +** +** A transaction must be started before executing this opcode. +*/ +case OP_SetCookie: { /* in3 */ + Db *pDb; + assert( pOp->p2p1>=0 && pOp->p1nDb ); + assert( DbMaskTest(p->btreeMask, pOp->p1) ); + assert( p->readOnly==0 ); + pDb = &db->aDb[pOp->p1]; + assert( pDb->pBt!=0 ); + assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); + pIn3 = &aMem[pOp->p3]; + sqlite3VdbeMemIntegerify(pIn3); + /* See note about index shifting on OP_ReadCookie */ + rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, (int)pIn3->u.i); + if( pOp->p2==BTREE_SCHEMA_VERSION ){ + /* When the schema cookie changes, record the new cookie internally */ + pDb->pSchema->schema_cookie = (int)pIn3->u.i; + db->flags |= SQLITE_InternChanges; + }else if( pOp->p2==BTREE_FILE_FORMAT ){ + /* Record changes in the file format */ + pDb->pSchema->file_format = (u8)pIn3->u.i; + } + if( pOp->p1==1 ){ + /* Invalidate all prepared statements whenever the TEMP database + ** schema is changed. Ticket #1644 */ + sqlite3ExpirePreparedStatements(db); + p->expired = 0; + } + break; +} + +/* Opcode: OpenRead P1 P2 P3 P4 P5 +** Synopsis: root=P2 iDb=P3 +** +** Open a read-only cursor for the database table whose root page is +** P2 in a database file. The database file is determined by P3. +** P3==0 means the main database, P3==1 means the database used for +** temporary tables, and P3>1 means used the corresponding attached +** database. Give the new cursor an identifier of P1. The P1 +** values need not be contiguous but all P1 values should be small integers. +** It is an error for P1 to be negative. +** +** If P5!=0 then use the content of register P2 as the root page, not +** the value of P2 itself. +** +** There will be a read lock on the database whenever there is an +** open cursor. If the database was unlocked prior to this instruction +** then a read lock is acquired as part of this instruction. A read +** lock allows other processes to read the database but prohibits +** any other process from modifying the database. The read lock is +** released when all cursors are closed. If this instruction attempts +** to get a read lock but fails, the script terminates with an +** SQLITE_BUSY error code. +** +** The P4 value may be either an integer (P4_INT32) or a pointer to +** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo +** structure, then said structure defines the content and collating +** sequence of the index being opened. Otherwise, if P4 is an integer +** value, it is set to the number of columns in the table. +** +** See also: OpenWrite, ReopenIdx +*/ +/* Opcode: ReopenIdx P1 P2 P3 P4 P5 +** Synopsis: root=P2 iDb=P3 +** +** The ReopenIdx opcode works exactly like ReadOpen except that it first +** checks to see if the cursor on P1 is already open with a root page +** number of P2 and if it is this opcode becomes a no-op. In other words, +** if the cursor is already open, do not reopen it. +** +** The ReopenIdx opcode may only be used with P5==0 and with P4 being +** a P4_KEYINFO object. Furthermore, the P3 value must be the same as +** every other ReopenIdx or OpenRead for the same cursor number. +** +** See the OpenRead opcode documentation for additional information. +*/ +/* Opcode: OpenWrite P1 P2 P3 P4 P5 +** Synopsis: root=P2 iDb=P3 +** +** Open a read/write cursor named P1 on the table or index whose root +** page is P2. Or if P5!=0 use the content of register P2 to find the +** root page. +** +** The P4 value may be either an integer (P4_INT32) or a pointer to +** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo +** structure, then said structure defines the content and collating +** sequence of the index being opened. Otherwise, if P4 is an integer +** value, it is set to the number of columns in the table, or to the +** largest index of any column of the table that is actually used. +** +** This instruction works just like OpenRead except that it opens the cursor +** in read/write mode. For a given table, there can be one or more read-only +** cursors or a single read/write cursor but not both. +** +** See also OpenRead. +*/ +case OP_ReopenIdx: { + int nField; + KeyInfo *pKeyInfo; + int p2; + int iDb; + int wrFlag; + Btree *pX; + VdbeCursor *pCur; + Db *pDb; + + assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); + assert( pOp->p4type==P4_KEYINFO ); + pCur = p->apCsr[pOp->p1]; + if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){ + assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */ + goto open_cursor_set_hints; + } + /* If the cursor is not currently open or is open on a different + ** index, then fall through into OP_OpenRead to force a reopen */ +case OP_OpenRead: +case OP_OpenWrite: + + assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR|OPFLAG_SEEKEQ))==pOp->p5 ); + assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); + assert( p->bIsReader ); + assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx + || p->readOnly==0 ); + + if( p->expired ){ + rc = SQLITE_ABORT_ROLLBACK; + break; + } + + nField = 0; + pKeyInfo = 0; + p2 = pOp->p2; + iDb = pOp->p3; + assert( iDb>=0 && iDbnDb ); + assert( DbMaskTest(p->btreeMask, iDb) ); + pDb = &db->aDb[iDb]; + pX = pDb->pBt; + assert( pX!=0 ); + if( pOp->opcode==OP_OpenWrite ){ + wrFlag = 1; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + if( pDb->pSchema->file_format < p->minWriteFileFormat ){ + p->minWriteFileFormat = pDb->pSchema->file_format; + } + }else{ + wrFlag = 0; + } + if( pOp->p5 & OPFLAG_P2ISREG ){ + assert( p2>0 ); + assert( p2<=(p->nMem-p->nCursor) ); + pIn2 = &aMem[p2]; + assert( memIsValid(pIn2) ); + assert( (pIn2->flags & MEM_Int)!=0 ); + sqlite3VdbeMemIntegerify(pIn2); + p2 = (int)pIn2->u.i; + /* The p2 value always comes from a prior OP_CreateTable opcode and + ** that opcode will always set the p2 value to 2 or more or else fail. + ** If there were a failure, the prepared statement would have halted + ** before reaching this instruction. */ + if( NEVER(p2<2) ) { + rc = SQLITE_CORRUPT_BKPT; + goto abort_due_to_error; + } + } + if( pOp->p4type==P4_KEYINFO ){ + pKeyInfo = pOp->p4.pKeyInfo; + assert( pKeyInfo->enc==ENC(db) ); + assert( pKeyInfo->db==db ); + nField = pKeyInfo->nField+pKeyInfo->nXField; + }else if( pOp->p4type==P4_INT32 ){ + nField = pOp->p4.i; + } + assert( pOp->p1>=0 ); + assert( nField>=0 ); + testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */ + pCur = allocateCursor(p, pOp->p1, nField, iDb, 1); + if( pCur==0 ) goto no_mem; + pCur->nullRow = 1; + pCur->isOrdered = 1; + pCur->pgnoRoot = p2; + rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); + pCur->pKeyInfo = pKeyInfo; + /* Set the VdbeCursor.isTable variable. Previous versions of + ** SQLite used to check if the root-page flags were sane at this point + ** and report database corruption if they were not, but this check has + ** since moved into the btree layer. */ + pCur->isTable = pOp->p4type!=P4_KEYINFO; + +open_cursor_set_hints: + assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); + assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ ); + sqlite3BtreeCursorHints(pCur->pCursor, + (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ))); + break; +} + +/* Opcode: OpenEphemeral P1 P2 * P4 P5 +** Synopsis: nColumn=P2 +** +** Open a new cursor P1 to a transient table. +** The cursor is always opened read/write even if +** the main database is read-only. The ephemeral +** table is deleted automatically when the cursor is closed. +** +** P2 is the number of columns in the ephemeral table. +** The cursor points to a BTree table if P4==0 and to a BTree index +** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure +** that defines the format of keys in the index. +** +** The P5 parameter can be a mask of the BTREE_* flags defined +** in btree.h. These flags control aspects of the operation of +** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are +** added automatically. +*/ +/* Opcode: OpenAutoindex P1 P2 * P4 * +** Synopsis: nColumn=P2 +** +** This opcode works the same as OP_OpenEphemeral. It has a +** different name to distinguish its use. Tables created using +** by this opcode will be used for automatically created transient +** indices in joins. +*/ +case OP_OpenAutoindex: +case OP_OpenEphemeral: { + VdbeCursor *pCx; + KeyInfo *pKeyInfo; + + static const int vfsFlags = + SQLITE_OPEN_READWRITE | + SQLITE_OPEN_CREATE | + SQLITE_OPEN_EXCLUSIVE | + SQLITE_OPEN_DELETEONCLOSE | + SQLITE_OPEN_TRANSIENT_DB; + assert( pOp->p1>=0 ); + assert( pOp->p2>=0 ); + pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); + if( pCx==0 ) goto no_mem; + pCx->nullRow = 1; + pCx->isEphemeral = 1; + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt, + BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeBeginTrans(pCx->pBt, 1); + } + if( rc==SQLITE_OK ){ + /* If a transient index is required, create it by calling + ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before + ** opening it. If a transient table is required, just use the + ** automatically created table with root-page 1 (an BLOB_INTKEY table). + */ + if( (pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ + int pgno; + assert( pOp->p4type==P4_KEYINFO ); + rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5); + if( rc==SQLITE_OK ){ + assert( pgno==MASTER_ROOT+1 ); + assert( pKeyInfo->db==db ); + assert( pKeyInfo->enc==ENC(db) ); + pCx->pKeyInfo = pKeyInfo; + rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, pKeyInfo, pCx->pCursor); + } + pCx->isTable = 0; + }else{ + rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor); + pCx->isTable = 1; + } + } + pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); + break; +} + +/* Opcode: SorterOpen P1 P2 P3 P4 * +** +** This opcode works like OP_OpenEphemeral except that it opens +** a transient index that is specifically designed to sort large +** tables using an external merge-sort algorithm. +** +** If argument P3 is non-zero, then it indicates that the sorter may +** assume that a stable sort considering the first P3 fields of each +** key is sufficient to produce the required results. +*/ +case OP_SorterOpen: { + VdbeCursor *pCx; + + assert( pOp->p1>=0 ); + assert( pOp->p2>=0 ); + pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); + if( pCx==0 ) goto no_mem; + pCx->pKeyInfo = pOp->p4.pKeyInfo; + assert( pCx->pKeyInfo->db==db ); + assert( pCx->pKeyInfo->enc==ENC(db) ); + rc = sqlite3VdbeSorterInit(db, pOp->p3, pCx); + break; +} + +/* Opcode: SequenceTest P1 P2 * * * +** Synopsis: if( cursor[P1].ctr++ ) pc = P2 +** +** P1 is a sorter cursor. If the sequence counter is currently zero, jump +** to P2. Regardless of whether or not the jump is taken, increment the +** the sequence value. +*/ +case OP_SequenceTest: { + VdbeCursor *pC; + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC->pSorter ); + if( (pC->seqCount++)==0 ){ + goto jump_to_p2; + } + break; +} + +/* Opcode: OpenPseudo P1 P2 P3 * * +** Synopsis: P3 columns in r[P2] +** +** Open a new cursor that points to a fake table that contains a single +** row of data. The content of that one row is the content of memory +** register P2. In other words, cursor P1 becomes an alias for the +** MEM_Blob content contained in register P2. +** +** A pseudo-table created by this opcode is used to hold a single +** row output from the sorter so that the row can be decomposed into +** individual columns using the OP_Column opcode. The OP_Column opcode +** is the only cursor opcode that works with a pseudo-table. +** +** P3 is the number of fields in the records that will be stored by +** the pseudo-table. +*/ +case OP_OpenPseudo: { + VdbeCursor *pCx; + + assert( pOp->p1>=0 ); + assert( pOp->p3>=0 ); + pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0); + if( pCx==0 ) goto no_mem; + pCx->nullRow = 1; + pCx->pseudoTableReg = pOp->p2; + pCx->isTable = 1; + assert( pOp->p5==0 ); + break; +} + +/* Opcode: Close P1 * * * * +** +** Close a cursor previously opened as P1. If P1 is not +** currently open, this instruction is a no-op. +*/ +case OP_Close: { + assert( pOp->p1>=0 && pOp->p1nCursor ); + sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]); + p->apCsr[pOp->p1] = 0; + break; +} + +#ifdef SQLITE_ENABLE_COLUMN_USED_MASK +/* Opcode: ColumnsUsed P1 * * P4 * +** +** This opcode (which only exists if SQLite was compiled with +** SQLITE_ENABLE_COLUMN_USED_MASK) identifies which columns of the +** table or index for cursor P1 are used. P4 is a 64-bit integer +** (P4_INT64) in which the first 63 bits are one for each of the +** first 63 columns of the table or index that are actually used +** by the cursor. The high-order bit is set if any column after +** the 64th is used. +*/ +case OP_ColumnsUsed: { + VdbeCursor *pC; + pC = p->apCsr[pOp->p1]; + assert( pC->pCursor ); + pC->maskUsed = *(u64*)pOp->p4.pI64; + break; +} +#endif + +/* Opcode: SeekGE P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] +** +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as the key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. +** +** Reposition cursor P1 so that it points to the smallest entry that +** is greater than or equal to the key value. If there are no records +** greater than or equal to the key and P2 is not zero, then jump to P2. +** +** This opcode leaves the cursor configured to move in forward order, +** from the beginning toward the end. In other words, the cursor is +** configured to use Next, not Prev. +** +** See also: Found, NotFound, SeekLt, SeekGt, SeekLe +*/ +/* Opcode: SeekGT P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] +** +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. +** +** Reposition cursor P1 so that it points to the smallest entry that +** is greater than the key value. If there are no records greater than +** the key and P2 is not zero, then jump to P2. +** +** This opcode leaves the cursor configured to move in forward order, +** from the beginning toward the end. In other words, the cursor is +** configured to use Next, not Prev. +** +** See also: Found, NotFound, SeekLt, SeekGe, SeekLe +*/ +/* Opcode: SeekLT P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] +** +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. +** +** Reposition cursor P1 so that it points to the largest entry that +** is less than the key value. If there are no records less than +** the key and P2 is not zero, then jump to P2. +** +** This opcode leaves the cursor configured to move in reverse order, +** from the end toward the beginning. In other words, the cursor is +** configured to use Prev, not Next. +** +** See also: Found, NotFound, SeekGt, SeekGe, SeekLe +*/ +/* Opcode: SeekLE P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] +** +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. +** +** Reposition cursor P1 so that it points to the largest entry that +** is less than or equal to the key value. If there are no records +** less than or equal to the key and P2 is not zero, then jump to P2. +** +** This opcode leaves the cursor configured to move in reverse order, +** from the end toward the beginning. In other words, the cursor is +** configured to use Prev, not Next. +** +** See also: Found, NotFound, SeekGt, SeekGe, SeekLt +*/ +case OP_SeekLT: /* jump, in3 */ +case OP_SeekLE: /* jump, in3 */ +case OP_SeekGE: /* jump, in3 */ +case OP_SeekGT: { /* jump, in3 */ + int res; + int oc; + VdbeCursor *pC; + UnpackedRecord r; + int nField; + i64 iKey; /* The rowid we are to seek to */ + + assert( pOp->p1>=0 && pOp->p1nCursor ); + assert( pOp->p2!=0 ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->pseudoTableReg==0 ); + assert( OP_SeekLE == OP_SeekLT+1 ); + assert( OP_SeekGE == OP_SeekLT+2 ); + assert( OP_SeekGT == OP_SeekLT+3 ); + assert( pC->isOrdered ); + assert( pC->pCursor!=0 ); + oc = pOp->opcode; + pC->nullRow = 0; +#ifdef SQLITE_DEBUG + pC->seekOp = pOp->opcode; +#endif + + /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and + ** OP_SeekLE opcodes are allowed, and these must be immediately followed + ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key. + */ +#ifdef SQLITE_DEBUG + if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){ + assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE ); + assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); + assert( pOp[1].p1==pOp[0].p1 ); + assert( pOp[1].p2==pOp[0].p2 ); + assert( pOp[1].p3==pOp[0].p3 ); + assert( pOp[1].p4.i==pOp[0].p4.i ); + } +#endif + + if( pC->isTable ){ + /* The input value in P3 might be of any type: integer, real, string, + ** blob, or NULL. But it needs to be an integer before we can do + ** the seek, so convert it. */ + pIn3 = &aMem[pOp->p3]; + if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ + applyNumericAffinity(pIn3, 0); + } + iKey = sqlite3VdbeIntValue(pIn3); + + /* If the P3 value could not be converted into an integer without + ** loss of information, then special processing is required... */ + if( (pIn3->flags & MEM_Int)==0 ){ + if( (pIn3->flags & MEM_Real)==0 ){ + /* If the P3 value cannot be converted into any kind of a number, + ** then the seek is not possible, so jump to P2 */ + VdbeBranchTaken(1,2); goto jump_to_p2; + break; + } + + /* If the approximation iKey is larger than the actual real search + ** term, substitute >= for > and < for <=. e.g. if the search term + ** is 4.9 and the integer approximation 5: + ** + ** (x > 4.9) -> (x >= 5) + ** (x <= 4.9) -> (x < 5) + */ + if( pIn3->u.r<(double)iKey ){ + assert( OP_SeekGE==(OP_SeekGT-1) ); + assert( OP_SeekLT==(OP_SeekLE-1) ); + assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) ); + if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--; + } + + /* If the approximation iKey is smaller than the actual real search + ** term, substitute <= for < and > for >=. */ + else if( pIn3->u.r>(double)iKey ){ + assert( OP_SeekLE==(OP_SeekLT+1) ); + assert( OP_SeekGT==(OP_SeekGE+1) ); + assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) ); + if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++; + } + } + rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res); + pC->movetoTarget = iKey; /* Used by OP_Delete */ + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + }else{ + nField = pOp->p4.i; + assert( pOp->p4type==P4_INT32 ); + assert( nField>0 ); + r.pKeyInfo = pC->pKeyInfo; + r.nField = (u16)nField; + + /* The next line of code computes as follows, only faster: + ** if( oc==OP_SeekGT || oc==OP_SeekLE ){ + ** r.default_rc = -1; + ** }else{ + ** r.default_rc = +1; + ** } + */ + r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1); + assert( oc!=OP_SeekGT || r.default_rc==-1 ); + assert( oc!=OP_SeekLE || r.default_rc==-1 ); + assert( oc!=OP_SeekGE || r.default_rc==+1 ); + assert( oc!=OP_SeekLT || r.default_rc==+1 ); + + r.aMem = &aMem[pOp->p3]; +#ifdef SQLITE_DEBUG + { int i; for(i=0; ipCursor, &r, 0, 0, &res); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + } + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; +#ifdef SQLITE_TEST + sqlite3_search_count++; +#endif + if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT ); + if( res<0 || (res==0 && oc==OP_SeekGT) ){ + res = 0; + rc = sqlite3BtreeNext(pC->pCursor, &res); + if( rc!=SQLITE_OK ) goto abort_due_to_error; + }else{ + res = 0; + } + }else{ + assert( oc==OP_SeekLT || oc==OP_SeekLE ); + if( res>0 || (res==0 && oc==OP_SeekLT) ){ + res = 0; + rc = sqlite3BtreePrevious(pC->pCursor, &res); + if( rc!=SQLITE_OK ) goto abort_due_to_error; + }else{ + /* res might be negative because the table is empty. Check to + ** see if this is the case. + */ + res = sqlite3BtreeEof(pC->pCursor); + } + } + assert( pOp->p2>0 ); + VdbeBranchTaken(res!=0,2); + if( res ){ + goto jump_to_p2; + } + break; +} + +/* Opcode: Seek P1 P2 * * * +** Synopsis: intkey=r[P2] +** +** P1 is an open table cursor and P2 is a rowid integer. Arrange +** for P1 to move so that it points to the rowid given by P2. +** +** This is actually a deferred seek. Nothing actually happens until +** the cursor is used to read a record. That way, if no reads +** occur, no unnecessary I/O happens. +*/ +case OP_Seek: { /* in2 */ + VdbeCursor *pC; + + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->pCursor!=0 ); + assert( pC->isTable ); + pC->nullRow = 0; + pIn2 = &aMem[pOp->p2]; + pC->movetoTarget = sqlite3VdbeIntValue(pIn2); + pC->deferredMoveto = 1; + break; +} + + +/* Opcode: Found P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] +** +** If P4==0 then register P3 holds a blob constructed by MakeRecord. If +** P4>0 then register P3 is the first of P4 registers that form an unpacked +** record. +** +** Cursor P1 is on an index btree. If the record identified by P3 and P4 +** is a prefix of any entry in P1 then a jump is made to P2 and +** P1 is left pointing at the matching entry. +** +** This operation leaves the cursor in a state where it can be +** advanced in the forward direction. The Next instruction will work, +** but not the Prev instruction. +** +** See also: NotFound, NoConflict, NotExists. SeekGe +*/ +/* Opcode: NotFound P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] +** +** If P4==0 then register P3 holds a blob constructed by MakeRecord. If +** P4>0 then register P3 is the first of P4 registers that form an unpacked +** record. +** +** Cursor P1 is on an index btree. If the record identified by P3 and P4 +** is not the prefix of any entry in P1 then a jump is made to P2. If P1 +** does contain an entry whose prefix matches the P3/P4 record then control +** falls through to the next instruction and P1 is left pointing at the +** matching entry. +** +** This operation leaves the cursor in a state where it cannot be +** advanced in either direction. In other words, the Next and Prev +** opcodes do not work after this operation. +** +** See also: Found, NotExists, NoConflict +*/ +/* Opcode: NoConflict P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] +** +** If P4==0 then register P3 holds a blob constructed by MakeRecord. If +** P4>0 then register P3 is the first of P4 registers that form an unpacked +** record. +** +** Cursor P1 is on an index btree. If the record identified by P3 and P4 +** contains any NULL value, jump immediately to P2. If all terms of the +** record are not-NULL then a check is done to determine if any row in the +** P1 index btree has a matching key prefix. If there are no matches, jump +** immediately to P2. If there is a match, fall through and leave the P1 +** cursor pointing to the matching row. +** +** This opcode is similar to OP_NotFound with the exceptions that the +** branch is always taken if any part of the search key input is NULL. +** +** This operation leaves the cursor in a state where it cannot be +** advanced in either direction. In other words, the Next and Prev +** opcodes do not work after this operation. +** +** See also: NotFound, Found, NotExists +*/ +case OP_NoConflict: /* jump, in3 */ +case OP_NotFound: /* jump, in3 */ +case OP_Found: { /* jump, in3 */ + int alreadyExists; + int takeJump; + int ii; + VdbeCursor *pC; + int res; + char *pFree; + UnpackedRecord *pIdxKey; + UnpackedRecord r; + char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7]; + +#ifdef SQLITE_TEST + if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++; +#endif + + assert( pOp->p1>=0 && pOp->p1nCursor ); + assert( pOp->p4type==P4_INT32 ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); +#ifdef SQLITE_DEBUG + pC->seekOp = pOp->opcode; +#endif + pIn3 = &aMem[pOp->p3]; + assert( pC->pCursor!=0 ); + assert( pC->isTable==0 ); + pFree = 0; + if( pOp->p4.i>0 ){ + r.pKeyInfo = pC->pKeyInfo; + r.nField = (u16)pOp->p4.i; + r.aMem = pIn3; + for(ii=0; iip3+ii, &r.aMem[ii]); +#endif + } + pIdxKey = &r; + }else{ + pIdxKey = sqlite3VdbeAllocUnpackedRecord( + pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree + ); + if( pIdxKey==0 ) goto no_mem; + assert( pIn3->flags & MEM_Blob ); + ExpandBlob(pIn3); + sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); + } + pIdxKey->default_rc = 0; + takeJump = 0; + if( pOp->opcode==OP_NoConflict ){ + /* For the OP_NoConflict opcode, take the jump if any of the + ** input fields are NULL, since any key with a NULL will not + ** conflict */ + for(ii=0; iinField; ii++){ + if( pIdxKey->aMem[ii].flags & MEM_Null ){ + takeJump = 1; + break; + } + } + } + rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res); + sqlite3DbFree(db, pFree); + if( rc!=SQLITE_OK ){ + break; + } + pC->seekResult = res; + alreadyExists = (res==0); + pC->nullRow = 1-alreadyExists; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + if( pOp->opcode==OP_Found ){ + VdbeBranchTaken(alreadyExists!=0,2); + if( alreadyExists ) goto jump_to_p2; + }else{ + VdbeBranchTaken(takeJump||alreadyExists==0,2); + if( takeJump || !alreadyExists ) goto jump_to_p2; + } + break; +} + +/* Opcode: NotExists P1 P2 P3 * * +** Synopsis: intkey=r[P3] +** +** P1 is the index of a cursor open on an SQL table btree (with integer +** keys). P3 is an integer rowid. If P1 does not contain a record with +** rowid P3 then jump immediately to P2. If P1 does contain a record +** with rowid P3 then leave the cursor pointing at that record and fall +** through to the next instruction. +** +** The OP_NotFound opcode performs the same operation on index btrees +** (with arbitrary multi-value keys). +** +** This opcode leaves the cursor in a state where it cannot be advanced +** in either direction. In other words, the Next and Prev opcodes will +** not work following this opcode. +** +** See also: Found, NotFound, NoConflict +*/ +case OP_NotExists: { /* jump, in3 */ + VdbeCursor *pC; + BtCursor *pCrsr; + int res; + u64 iKey; + + pIn3 = &aMem[pOp->p3]; + assert( pIn3->flags & MEM_Int ); + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); +#ifdef SQLITE_DEBUG + pC->seekOp = 0; +#endif + assert( pC->isTable ); + assert( pC->pseudoTableReg==0 ); + pCrsr = pC->pCursor; + assert( pCrsr!=0 ); + res = 0; + iKey = pIn3->u.i; + rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res); + pC->movetoTarget = iKey; /* Used by OP_Delete */ + pC->nullRow = 0; + pC->cacheStatus = CACHE_STALE; + pC->deferredMoveto = 0; + VdbeBranchTaken(res!=0,2); + pC->seekResult = res; + if( res!=0 ) goto jump_to_p2; + break; +} + +/* Opcode: Sequence P1 P2 * * * +** Synopsis: r[P2]=cursor[P1].ctr++ +** +** Find the next available sequence number for cursor P1. +** Write the sequence number into register P2. +** The sequence number on the cursor is incremented after this +** instruction. +*/ +case OP_Sequence: { /* out2 */ + assert( pOp->p1>=0 && pOp->p1nCursor ); + assert( p->apCsr[pOp->p1]!=0 ); + pOut = out2Prerelease(p, pOp); + pOut->u.i = p->apCsr[pOp->p1]->seqCount++; + break; +} + + +/* Opcode: NewRowid P1 P2 P3 * * +** Synopsis: r[P2]=rowid +** +** Get a new integer record number (a.k.a "rowid") used as the key to a table. +** The record number is not previously used as a key in the database +** table that cursor P1 points to. The new record number is written +** written to register P2. +** +** If P3>0 then P3 is a register in the root frame of this VDBE that holds +** the largest previously generated record number. No new record numbers are +** allowed to be less than this value. When this value reaches its maximum, +** an SQLITE_FULL error is generated. The P3 register is updated with the ' +** generated record number. This P3 mechanism is used to help implement the +** AUTOINCREMENT feature. +*/ +case OP_NewRowid: { /* out2 */ + i64 v; /* The new rowid */ + VdbeCursor *pC; /* Cursor of table to get the new rowid */ + int res; /* Result of an sqlite3BtreeLast() */ + int cnt; /* Counter to limit the number of searches */ + Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */ + VdbeFrame *pFrame; /* Root frame of VDBE */ + + v = 0; + res = 0; + pOut = out2Prerelease(p, pOp); + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->pCursor!=0 ); + { + /* The next rowid or record number (different terms for the same + ** thing) is obtained in a two-step algorithm. + ** + ** First we attempt to find the largest existing rowid and add one + ** to that. But if the largest existing rowid is already the maximum + ** positive integer, we have to fall through to the second + ** probabilistic algorithm + ** + ** The second algorithm is to select a rowid at random and see if + ** it already exists in the table. If it does not exist, we have + ** succeeded. If the random rowid does exist, we select a new one + ** and try again, up to 100 times. + */ + assert( pC->isTable ); + +#ifdef SQLITE_32BIT_ROWID +# define MAX_ROWID 0x7fffffff +#else + /* Some compilers complain about constants of the form 0x7fffffffffffffff. + ** Others complain about 0x7ffffffffffffffffLL. The following macro seems + ** to provide the constant while making all compilers happy. + */ +# define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff ) +#endif + + if( !pC->useRandomRowid ){ + rc = sqlite3BtreeLast(pC->pCursor, &res); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + if( res ){ + v = 1; /* IMP: R-61914-48074 */ + }else{ + assert( sqlite3BtreeCursorIsValid(pC->pCursor) ); + rc = sqlite3BtreeKeySize(pC->pCursor, &v); + assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ + if( v>=MAX_ROWID ){ + pC->useRandomRowid = 1; + }else{ + v++; /* IMP: R-29538-34987 */ + } + } + } + +#ifndef SQLITE_OMIT_AUTOINCREMENT + if( pOp->p3 ){ + /* Assert that P3 is a valid memory cell. */ + assert( pOp->p3>0 ); + if( p->pFrame ){ + for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); + /* Assert that P3 is a valid memory cell. */ + assert( pOp->p3<=pFrame->nMem ); + pMem = &pFrame->aMem[pOp->p3]; + }else{ + /* Assert that P3 is a valid memory cell. */ + assert( pOp->p3<=(p->nMem-p->nCursor) ); + pMem = &aMem[pOp->p3]; + memAboutToChange(p, pMem); + } + assert( memIsValid(pMem) ); + + REGISTER_TRACE(pOp->p3, pMem); + sqlite3VdbeMemIntegerify(pMem); + assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ + if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ + rc = SQLITE_FULL; /* IMP: R-12275-61338 */ + goto abort_due_to_error; + } + if( vu.i+1 ){ + v = pMem->u.i + 1; + } + pMem->u.i = v; + } +#endif + if( pC->useRandomRowid ){ + /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the + ** largest possible integer (9223372036854775807) then the database + ** engine starts picking positive candidate ROWIDs at random until + ** it finds one that is not previously used. */ + assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is + ** an AUTOINCREMENT table. */ + cnt = 0; + do{ + sqlite3_randomness(sizeof(v), &v); + v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */ + }while( ((rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)v, + 0, &res))==SQLITE_OK) + && (res==0) + && (++cnt<100)); + if( rc==SQLITE_OK && res==0 ){ + rc = SQLITE_FULL; /* IMP: R-38219-53002 */ + goto abort_due_to_error; + } + assert( v>0 ); /* EV: R-40812-03570 */ + } + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + } + pOut->u.i = v; + break; +} + +/* Opcode: Insert P1 P2 P3 P4 P5 +** Synopsis: intkey=r[P3] data=r[P2] +** +** Write an entry into the table of cursor P1. A new entry is +** created if it doesn't already exist or the data for an existing +** entry is overwritten. The data is the value MEM_Blob stored in register +** number P2. The key is stored in register P3. The key must +** be a MEM_Int. +** +** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is +** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set, +** then rowid is stored for subsequent return by the +** sqlite3_last_insert_rowid() function (otherwise it is unmodified). +** +** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of +** the last seek operation (OP_NotExists) was a success, then this +** operation will not attempt to find the appropriate row before doing +** the insert but will instead overwrite the row that the cursor is +** currently pointing to. Presumably, the prior OP_NotExists opcode +** has already positioned the cursor correctly. This is an optimization +** that boosts performance by avoiding redundant seeks. +** +** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an +** UPDATE operation. Otherwise (if the flag is clear) then this opcode +** is part of an INSERT operation. The difference is only important to +** the update hook. +** +** Parameter P4 may point to a string containing the table-name, or +** may be NULL. If it is not NULL, then the update-hook +** (sqlite3.xUpdateCallback) is invoked following a successful insert. +** +** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically +** allocated, then ownership of P2 is transferred to the pseudo-cursor +** and register P2 becomes ephemeral. If the cursor is changed, the +** value of register P2 will then change. Make sure this does not +** cause any problems.) +** +** This instruction only works on tables. The equivalent instruction +** for indices is OP_IdxInsert. +*/ +/* Opcode: InsertInt P1 P2 P3 P4 P5 +** Synopsis: intkey=P3 data=r[P2] +** +** This works exactly like OP_Insert except that the key is the +** integer value P3, not the value of the integer stored in register P3. +*/ +case OP_Insert: +case OP_InsertInt: { + Mem *pData; /* MEM cell holding data for the record to be inserted */ + Mem *pKey; /* MEM cell holding key for the record */ + i64 iKey; /* The integer ROWID or key for the record to be inserted */ + VdbeCursor *pC; /* Cursor to table into which insert is written */ + int nZero; /* Number of zero-bytes to append */ + int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */ + const char *zDb; /* database name - used by the update hook */ + const char *zTbl; /* Table name - used by the opdate hook */ + int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ + + pData = &aMem[pOp->p2]; + assert( pOp->p1>=0 && pOp->p1nCursor ); + assert( memIsValid(pData) ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->pCursor!=0 ); + assert( pC->pseudoTableReg==0 ); + assert( pC->isTable ); + REGISTER_TRACE(pOp->p2, pData); + + if( pOp->opcode==OP_Insert ){ + pKey = &aMem[pOp->p3]; + assert( pKey->flags & MEM_Int ); + assert( memIsValid(pKey) ); + REGISTER_TRACE(pOp->p3, pKey); + iKey = pKey->u.i; + }else{ + assert( pOp->opcode==OP_InsertInt ); + iKey = pOp->p3; + } + + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; + if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = iKey; + if( pData->flags & MEM_Null ){ + pData->z = 0; + pData->n = 0; + }else{ + assert( pData->flags & (MEM_Blob|MEM_Str) ); + } + seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0); + if( pData->flags & MEM_Zero ){ + nZero = pData->u.nZero; + }else{ + nZero = 0; + } + rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, + pData->z, pData->n, nZero, + (pOp->p5 & OPFLAG_APPEND)!=0, seekResult + ); + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + + /* Invoke the update-hook if required. */ + if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ + zDb = db->aDb[pC->iDb].zName; + zTbl = pOp->p4.z; + op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); + assert( pC->isTable ); + db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey); + assert( pC->iDb>=0 ); + } + break; +} + +/* Opcode: Delete P1 P2 * P4 * +** +** Delete the record at which the P1 cursor is currently pointing. +** +** The cursor will be left pointing at either the next or the previous +** record in the table. If it is left pointing at the next record, then +** the next Next instruction will be a no-op. Hence it is OK to delete +** a record from within a Next loop. +** +** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is +** incremented (otherwise not). +** +** P1 must not be pseudo-table. It has to be a real table with +** multiple rows. +** +** If P4 is not NULL, then it is the name of the table that P1 is +** pointing to. The update hook will be invoked, if it exists. +** If P4 is not NULL then the P1 cursor must have been positioned +** using OP_NotFound prior to invoking this opcode. +*/ +case OP_Delete: { + VdbeCursor *pC; + + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */ + assert( pC->deferredMoveto==0 ); + +#ifdef SQLITE_DEBUG + /* The seek operation that positioned the cursor prior to OP_Delete will + ** have also set the pC->movetoTarget field to the rowid of the row that + ** is being deleted */ + if( pOp->p4.z && pC->isTable ){ + i64 iKey = 0; + sqlite3BtreeKeySize(pC->pCursor, &iKey); + assert( pC->movetoTarget==iKey ); + } +#endif + + rc = sqlite3BtreeDelete(pC->pCursor); + pC->cacheStatus = CACHE_STALE; + + /* Invoke the update-hook if required. */ + if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z && pC->isTable ){ + db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, + db->aDb[pC->iDb].zName, pOp->p4.z, pC->movetoTarget); + assert( pC->iDb>=0 ); + } + if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; + break; +} +/* Opcode: ResetCount * * * * * +** +** The value of the change counter is copied to the database handle +** change counter (returned by subsequent calls to sqlite3_changes()). +** Then the VMs internal change counter resets to 0. +** This is used by trigger programs. +*/ +case OP_ResetCount: { + sqlite3VdbeSetChanges(db, p->nChange); + p->nChange = 0; + break; +} + +/* Opcode: SorterCompare P1 P2 P3 P4 +** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2 +** +** P1 is a sorter cursor. This instruction compares a prefix of the +** record blob in register P3 against a prefix of the entry that +** the sorter cursor currently points to. Only the first P4 fields +** of r[P3] and the sorter record are compared. +** +** If either P3 or the sorter contains a NULL in one of their significant +** fields (not counting the P4 fields at the end which are ignored) then +** the comparison is assumed to be equal. +** +** Fall through to next instruction if the two records compare equal to +** each other. Jump to P2 if they are different. +*/ +case OP_SorterCompare: { + VdbeCursor *pC; + int res; + int nKeyCol; + + pC = p->apCsr[pOp->p1]; + assert( isSorter(pC) ); + assert( pOp->p4type==P4_INT32 ); + pIn3 = &aMem[pOp->p3]; + nKeyCol = pOp->p4.i; + res = 0; + rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res); + VdbeBranchTaken(res!=0,2); + if( res ) goto jump_to_p2; + break; +}; + +/* Opcode: SorterData P1 P2 P3 * * +** Synopsis: r[P2]=data +** +** Write into register P2 the current sorter data for sorter cursor P1. +** Then clear the column header cache on cursor P3. +** +** This opcode is normally use to move a record out of the sorter and into +** a register that is the source for a pseudo-table cursor created using +** OpenPseudo. That pseudo-table cursor is the one that is identified by +** parameter P3. Clearing the P3 column cache as part of this opcode saves +** us from having to issue a separate NullRow instruction to clear that cache. +*/ +case OP_SorterData: { + VdbeCursor *pC; + + pOut = &aMem[pOp->p2]; + pC = p->apCsr[pOp->p1]; + assert( isSorter(pC) ); + rc = sqlite3VdbeSorterRowkey(pC, pOut); + assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) ); + assert( pOp->p1>=0 && pOp->p1nCursor ); + p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE; + break; +} + +/* Opcode: RowData P1 P2 * * * +** Synopsis: r[P2]=data +** +** Write into register P2 the complete row data for cursor P1. +** There is no interpretation of the data. +** It is just copied onto the P2 register exactly as +** it is found in the database file. +** +** If the P1 cursor must be pointing to a valid row (not a NULL row) +** of a real table, not a pseudo-table. +*/ +/* Opcode: RowKey P1 P2 * * * +** Synopsis: r[P2]=key +** +** Write into register P2 the complete row key for cursor P1. +** There is no interpretation of the data. +** The key is copied onto the P2 register exactly as +** it is found in the database file. +** +** If the P1 cursor must be pointing to a valid row (not a NULL row) +** of a real table, not a pseudo-table. +*/ +case OP_RowKey: +case OP_RowData: { + VdbeCursor *pC; + BtCursor *pCrsr; + u32 n; + i64 n64; + + pOut = &aMem[pOp->p2]; + memAboutToChange(p, pOut); + + /* Note that RowKey and RowData are really exactly the same instruction */ + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( isSorter(pC)==0 ); + assert( pC->isTable || pOp->opcode!=OP_RowData ); + assert( pC->isTable==0 || pOp->opcode==OP_RowData ); + assert( pC!=0 ); + assert( pC->nullRow==0 ); + assert( pC->pseudoTableReg==0 ); + assert( pC->pCursor!=0 ); + pCrsr = pC->pCursor; + + /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or + ** OP_Rewind/Op_Next with no intervening instructions that might invalidate + ** the cursor. If this where not the case, on of the following assert()s + ** would fail. Should this ever change (because of changes in the code + ** generator) then the fix would be to insert a call to + ** sqlite3VdbeCursorMoveto(). + */ + assert( pC->deferredMoveto==0 ); + assert( sqlite3BtreeCursorIsValid(pCrsr) ); +#if 0 /* Not required due to the previous to assert() statements */ + rc = sqlite3VdbeCursorMoveto(pC); + if( rc!=SQLITE_OK ) goto abort_due_to_error; +#endif + + if( pC->isTable==0 ){ + assert( !pC->isTable ); + VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &n64); + assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ + if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + n = (u32)n64; + }else{ + VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &n); + assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ + if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + } + testcase( n==0 ); + if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){ + goto no_mem; + } + pOut->n = n; + MemSetTypeFlag(pOut, MEM_Blob); + if( pC->isTable==0 ){ + rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z); + }else{ + rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z); + } + pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ + UPDATE_MAX_BLOBSIZE(pOut); + REGISTER_TRACE(pOp->p2, pOut); + break; +} + +/* Opcode: Rowid P1 P2 * * * +** Synopsis: r[P2]=rowid +** +** Store in register P2 an integer which is the key of the table entry that +** P1 is currently point to. +** +** P1 can be either an ordinary table or a virtual table. There used to +** be a separate OP_VRowid opcode for use with virtual tables, but this +** one opcode now works for both table types. +*/ +case OP_Rowid: { /* out2 */ + VdbeCursor *pC; + i64 v; + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + + pOut = out2Prerelease(p, pOp); + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->pseudoTableReg==0 || pC->nullRow ); + if( pC->nullRow ){ + pOut->flags = MEM_Null; + break; + }else if( pC->deferredMoveto ){ + v = pC->movetoTarget; +#ifndef SQLITE_OMIT_VIRTUALTABLE + }else if( pC->pVtabCursor ){ + pVtab = pC->pVtabCursor->pVtab; + pModule = pVtab->pModule; + assert( pModule->xRowid ); + rc = pModule->xRowid(pC->pVtabCursor, &v); + sqlite3VtabImportErrmsg(p, pVtab); +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + }else{ + assert( pC->pCursor!=0 ); + rc = sqlite3VdbeCursorRestore(pC); + if( rc ) goto abort_due_to_error; + if( pC->nullRow ){ + pOut->flags = MEM_Null; + break; + } + rc = sqlite3BtreeKeySize(pC->pCursor, &v); + assert( rc==SQLITE_OK ); /* Always so because of CursorRestore() above */ + } + pOut->u.i = v; + break; +} + +/* Opcode: NullRow P1 * * * * +** +** Move the cursor P1 to a null row. Any OP_Column operations +** that occur while the cursor is on the null row will always +** write a NULL. +*/ +case OP_NullRow: { + VdbeCursor *pC; + + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + pC->nullRow = 1; + pC->cacheStatus = CACHE_STALE; + if( pC->pCursor ){ + sqlite3BtreeClearCursor(pC->pCursor); + } + break; +} + +/* Opcode: Last P1 P2 P3 * * +** +** The next use of the Rowid or Column or Prev instruction for P1 +** will refer to the last entry in the database table or index. +** If the table or index is empty and P2>0, then jump immediately to P2. +** If P2 is 0 or if the table or index is not empty, fall through +** to the following instruction. +** +** This opcode leaves the cursor configured to move in reverse order, +** from the end toward the beginning. In other words, the cursor is +** configured to use Prev, not Next. +*/ +case OP_Last: { /* jump */ + VdbeCursor *pC; + BtCursor *pCrsr; + int res; + + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + pCrsr = pC->pCursor; + res = 0; + assert( pCrsr!=0 ); + rc = sqlite3BtreeLast(pCrsr, &res); + pC->nullRow = (u8)res; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + pC->seekResult = pOp->p3; +#ifdef SQLITE_DEBUG + pC->seekOp = OP_Last; +#endif + if( pOp->p2>0 ){ + VdbeBranchTaken(res!=0,2); + if( res ) goto jump_to_p2; + } + break; +} + + +/* Opcode: Sort P1 P2 * * * +** +** This opcode does exactly the same thing as OP_Rewind except that +** it increments an undocumented global variable used for testing. +** +** Sorting is accomplished by writing records into a sorting index, +** then rewinding that index and playing it back from beginning to +** end. We use the OP_Sort opcode instead of OP_Rewind to do the +** rewinding so that the global variable will be incremented and +** regression tests can determine whether or not the optimizer is +** correctly optimizing out sorts. +*/ +case OP_SorterSort: /* jump */ +case OP_Sort: { /* jump */ +#ifdef SQLITE_TEST + sqlite3_sort_count++; + sqlite3_search_count--; +#endif + p->aCounter[SQLITE_STMTSTATUS_SORT]++; + /* Fall through into OP_Rewind */ +} +/* Opcode: Rewind P1 P2 * * * +** +** The next use of the Rowid or Column or Next instruction for P1 +** will refer to the first entry in the database table or index. +** If the table or index is empty, jump immediately to P2. +** If the table or index is not empty, fall through to the following +** instruction. +** +** This opcode leaves the cursor configured to move in forward order, +** from the beginning toward the end. In other words, the cursor is +** configured to use Next, not Prev. +*/ +case OP_Rewind: { /* jump */ + VdbeCursor *pC; + BtCursor *pCrsr; + int res; + + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) ); + res = 1; +#ifdef SQLITE_DEBUG + pC->seekOp = OP_Rewind; +#endif + if( isSorter(pC) ){ + rc = sqlite3VdbeSorterRewind(pC, &res); + }else{ + pCrsr = pC->pCursor; + assert( pCrsr ); + rc = sqlite3BtreeFirst(pCrsr, &res); + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + } + pC->nullRow = (u8)res; + assert( pOp->p2>0 && pOp->p2nOp ); + VdbeBranchTaken(res!=0,2); + if( res ) goto jump_to_p2; + break; +} + +/* Opcode: Next P1 P2 P3 P4 P5 +** +** Advance cursor P1 so that it points to the next key/data pair in its +** table or index. If there are no more key/value pairs then fall through +** to the following instruction. But if the cursor advance was successful, +** jump immediately to P2. +** +** The Next opcode is only valid following an SeekGT, SeekGE, or +** OP_Rewind opcode used to position the cursor. Next is not allowed +** to follow SeekLT, SeekLE, or OP_Last. +** +** The P1 cursor must be for a real table, not a pseudo-table. P1 must have +** been opened prior to this opcode or the program will segfault. +** +** The P3 value is a hint to the btree implementation. If P3==1, that +** means P1 is an SQL index and that this instruction could have been +** omitted if that index had been unique. P3 is usually 0. P3 is +** always either 0 or 1. +** +** P4 is always of type P4_ADVANCE. The function pointer points to +** sqlite3BtreeNext(). +** +** If P5 is positive and the jump is taken, then event counter +** number P5-1 in the prepared statement is incremented. +** +** See also: Prev, NextIfOpen +*/ +/* Opcode: NextIfOpen P1 P2 P3 P4 P5 +** +** This opcode works just like Next except that if cursor P1 is not +** open it behaves a no-op. +*/ +/* Opcode: Prev P1 P2 P3 P4 P5 +** +** Back up cursor P1 so that it points to the previous key/data pair in its +** table or index. If there is no previous key/value pairs then fall through +** to the following instruction. But if the cursor backup was successful, +** jump immediately to P2. +** +** +** The Prev opcode is only valid following an SeekLT, SeekLE, or +** OP_Last opcode used to position the cursor. Prev is not allowed +** to follow SeekGT, SeekGE, or OP_Rewind. +** +** The P1 cursor must be for a real table, not a pseudo-table. If P1 is +** not open then the behavior is undefined. +** +** The P3 value is a hint to the btree implementation. If P3==1, that +** means P1 is an SQL index and that this instruction could have been +** omitted if that index had been unique. P3 is usually 0. P3 is +** always either 0 or 1. +** +** P4 is always of type P4_ADVANCE. The function pointer points to +** sqlite3BtreePrevious(). +** +** If P5 is positive and the jump is taken, then event counter +** number P5-1 in the prepared statement is incremented. +*/ +/* Opcode: PrevIfOpen P1 P2 P3 P4 P5 +** +** This opcode works just like Prev except that if cursor P1 is not +** open it behaves a no-op. +*/ +case OP_SorterNext: { /* jump */ + VdbeCursor *pC; + int res; + + pC = p->apCsr[pOp->p1]; + assert( isSorter(pC) ); + res = 0; + rc = sqlite3VdbeSorterNext(db, pC, &res); + goto next_tail; +case OP_PrevIfOpen: /* jump */ +case OP_NextIfOpen: /* jump */ + if( p->apCsr[pOp->p1]==0 ) break; + /* Fall through */ +case OP_Prev: /* jump */ +case OP_Next: /* jump */ + assert( pOp->p1>=0 && pOp->p1nCursor ); + assert( pOp->p5aCounter) ); + pC = p->apCsr[pOp->p1]; + res = pOp->p3; + assert( pC!=0 ); + assert( pC->deferredMoveto==0 ); + assert( pC->pCursor ); + assert( res==0 || (res==1 && pC->isTable==0) ); + testcase( res==1 ); + assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext ); + assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious ); + assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext ); + assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious); + + /* The Next opcode is only used after SeekGT, SeekGE, and Rewind. + ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */ + assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen + || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE + || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found); + assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen + || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE + || pC->seekOp==OP_Last ); + + rc = pOp->p4.xAdvance(pC->pCursor, &res); +next_tail: + pC->cacheStatus = CACHE_STALE; + VdbeBranchTaken(res==0,2); + if( res==0 ){ + pC->nullRow = 0; + p->aCounter[pOp->p5]++; +#ifdef SQLITE_TEST + sqlite3_search_count++; +#endif + goto jump_to_p2_and_check_for_interrupt; + }else{ + pC->nullRow = 1; + } + goto check_for_interrupt; +} + +/* Opcode: IdxInsert P1 P2 P3 * P5 +** Synopsis: key=r[P2] +** +** Register P2 holds an SQL index key made using the +** MakeRecord instructions. This opcode writes that key +** into the index P1. Data for the entry is nil. +** +** P3 is a flag that provides a hint to the b-tree layer that this +** insert is likely to be an append. +** +** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is +** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear, +** then the change counter is unchanged. +** +** If P5 has the OPFLAG_USESEEKRESULT bit set, then the cursor must have +** just done a seek to the spot where the new entry is to be inserted. +** This flag avoids doing an extra seek. +** +** This instruction only works for indices. The equivalent instruction +** for tables is OP_Insert. +*/ +case OP_SorterInsert: /* in2 */ +case OP_IdxInsert: { /* in2 */ + VdbeCursor *pC; + int nKey; + const char *zKey; + + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) ); + pIn2 = &aMem[pOp->p2]; + assert( pIn2->flags & MEM_Blob ); + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; + assert( pC->pCursor!=0 ); + assert( pC->isTable==0 ); + rc = ExpandBlob(pIn2); + if( rc==SQLITE_OK ){ + if( pOp->opcode==OP_SorterInsert ){ + rc = sqlite3VdbeSorterWrite(pC, pIn2); + }else{ + nKey = pIn2->n; + zKey = pIn2->z; + rc = sqlite3BtreeInsert(pC->pCursor, zKey, nKey, "", 0, 0, pOp->p3, + ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) + ); + assert( pC->deferredMoveto==0 ); + pC->cacheStatus = CACHE_STALE; + } + } + break; +} + +/* Opcode: IdxDelete P1 P2 P3 * * +** Synopsis: key=r[P2@P3] +** +** The content of P3 registers starting at register P2 form +** an unpacked index key. This opcode removes that entry from the +** index opened by cursor P1. +*/ +case OP_IdxDelete: { + VdbeCursor *pC; + BtCursor *pCrsr; + int res; + UnpackedRecord r; + + assert( pOp->p3>0 ); + assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem-p->nCursor)+1 ); + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + pCrsr = pC->pCursor; + assert( pCrsr!=0 ); + assert( pOp->p5==0 ); + r.pKeyInfo = pC->pKeyInfo; + r.nField = (u16)pOp->p3; + r.default_rc = 0; + r.aMem = &aMem[pOp->p2]; +#ifdef SQLITE_DEBUG + { int i; for(i=0; ideferredMoveto==0 ); + pC->cacheStatus = CACHE_STALE; + break; +} + +/* Opcode: IdxRowid P1 P2 * * * +** Synopsis: r[P2]=rowid +** +** Write into register P2 an integer which is the last entry in the record at +** the end of the index key pointed to by cursor P1. This integer should be +** the rowid of the table entry to which this index entry points. +** +** See also: Rowid, MakeRecord. +*/ +case OP_IdxRowid: { /* out2 */ + BtCursor *pCrsr; + VdbeCursor *pC; + i64 rowid; + + pOut = out2Prerelease(p, pOp); + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + pCrsr = pC->pCursor; + assert( pCrsr!=0 ); + pOut->flags = MEM_Null; + assert( pC->isTable==0 ); + assert( pC->deferredMoveto==0 ); + + /* sqlite3VbeCursorRestore() can only fail if the record has been deleted + ** out from under the cursor. That will never happend for an IdxRowid + ** opcode, hence the NEVER() arround the check of the return value. + */ + rc = sqlite3VdbeCursorRestore(pC); + if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; + + if( !pC->nullRow ){ + rowid = 0; /* Not needed. Only used to silence a warning. */ + rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + pOut->u.i = rowid; + pOut->flags = MEM_Int; + } + break; +} + +/* Opcode: IdxGE P1 P2 P3 P4 P5 +** Synopsis: key=r[P3@P4] +** +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY. Compare this key value against the index +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID +** fields at the end. +** +** If the P1 index entry is greater than or equal to the key value +** then jump to P2. Otherwise fall through to the next instruction. +*/ +/* Opcode: IdxGT P1 P2 P3 P4 P5 +** Synopsis: key=r[P3@P4] +** +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY. Compare this key value against the index +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID +** fields at the end. +** +** If the P1 index entry is greater than the key value +** then jump to P2. Otherwise fall through to the next instruction. +*/ +/* Opcode: IdxLT P1 P2 P3 P4 P5 +** Synopsis: key=r[P3@P4] +** +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY or ROWID. Compare this key value against +** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or +** ROWID on the P1 index. +** +** If the P1 index entry is less than the key value then jump to P2. +** Otherwise fall through to the next instruction. +*/ +/* Opcode: IdxLE P1 P2 P3 P4 P5 +** Synopsis: key=r[P3@P4] +** +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY or ROWID. Compare this key value against +** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or +** ROWID on the P1 index. +** +** If the P1 index entry is less than or equal to the key value then jump +** to P2. Otherwise fall through to the next instruction. +*/ +case OP_IdxLE: /* jump */ +case OP_IdxGT: /* jump */ +case OP_IdxLT: /* jump */ +case OP_IdxGE: { /* jump */ + VdbeCursor *pC; + int res; + UnpackedRecord r; + + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->isOrdered ); + assert( pC->pCursor!=0); + assert( pC->deferredMoveto==0 ); + assert( pOp->p5==0 || pOp->p5==1 ); + assert( pOp->p4type==P4_INT32 ); + r.pKeyInfo = pC->pKeyInfo; + r.nField = (u16)pOp->p4.i; + if( pOp->opcodeopcode==OP_IdxLE || pOp->opcode==OP_IdxGT ); + r.default_rc = -1; + }else{ + assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT ); + r.default_rc = 0; + } + r.aMem = &aMem[pOp->p3]; +#ifdef SQLITE_DEBUG + { int i; for(i=0; iopcode&1)==(OP_IdxLT&1) ){ + assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT ); + res = -res; + }else{ + assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT ); + res++; + } + VdbeBranchTaken(res>0,2); + if( res>0 ) goto jump_to_p2; + break; +} + +/* Opcode: Destroy P1 P2 P3 * * +** +** Delete an entire database table or index whose root page in the database +** file is given by P1. +** +** The table being destroyed is in the main database file if P3==0. If +** P3==1 then the table to be clear is in the auxiliary database file +** that is used to store tables create using CREATE TEMPORARY TABLE. +** +** If AUTOVACUUM is enabled then it is possible that another root page +** might be moved into the newly deleted root page in order to keep all +** root pages contiguous at the beginning of the database. The former +** value of the root page that moved - its value before the move occurred - +** is stored in register P2. If no page +** movement was required (because the table being dropped was already +** the last one in the database) then a zero is stored in register P2. +** If AUTOVACUUM is disabled then a zero is stored in register P2. +** +** See also: Clear +*/ +case OP_Destroy: { /* out2 */ + int iMoved; + int iDb; + + assert( p->readOnly==0 ); + pOut = out2Prerelease(p, pOp); + pOut->flags = MEM_Null; + if( db->nVdbeRead > db->nVDestroy+1 ){ + rc = SQLITE_LOCKED; + p->errorAction = OE_Abort; + }else{ + iDb = pOp->p3; + assert( DbMaskTest(p->btreeMask, iDb) ); + iMoved = 0; /* Not needed. Only to silence a warning. */ + rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved); + pOut->flags = MEM_Int; + pOut->u.i = iMoved; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( rc==SQLITE_OK && iMoved!=0 ){ + sqlite3RootPageMoved(db, iDb, iMoved, pOp->p1); + /* All OP_Destroy operations occur on the same btree */ + assert( resetSchemaOnFault==0 || resetSchemaOnFault==iDb+1 ); + resetSchemaOnFault = iDb+1; + } +#endif + } + break; +} + +/* Opcode: Clear P1 P2 P3 +** +** Delete all contents of the database table or index whose root page +** in the database file is given by P1. But, unlike Destroy, do not +** remove the table or index from the database file. +** +** The table being clear is in the main database file if P2==0. If +** P2==1 then the table to be clear is in the auxiliary database file +** that is used to store tables create using CREATE TEMPORARY TABLE. +** +** If the P3 value is non-zero, then the table referred to must be an +** intkey table (an SQL table, not an index). In this case the row change +** count is incremented by the number of rows in the table being cleared. +** If P3 is greater than zero, then the value stored in register P3 is +** also incremented by the number of rows in the table being cleared. +** +** See also: Destroy +*/ +case OP_Clear: { + int nChange; + + nChange = 0; + assert( p->readOnly==0 ); + assert( DbMaskTest(p->btreeMask, pOp->p2) ); + rc = sqlite3BtreeClearTable( + db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0) + ); + if( pOp->p3 ){ + p->nChange += nChange; + if( pOp->p3>0 ){ + assert( memIsValid(&aMem[pOp->p3]) ); + memAboutToChange(p, &aMem[pOp->p3]); + aMem[pOp->p3].u.i += nChange; + } + } + break; +} + +/* Opcode: ResetSorter P1 * * * * +** +** Delete all contents from the ephemeral table or sorter +** that is open on cursor P1. +** +** This opcode only works for cursors used for sorting and +** opened with OP_OpenEphemeral or OP_SorterOpen. +*/ +case OP_ResetSorter: { + VdbeCursor *pC; + + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + if( pC->pSorter ){ + sqlite3VdbeSorterReset(db, pC->pSorter); + }else{ + assert( pC->isEphemeral ); + rc = sqlite3BtreeClearTableOfCursor(pC->pCursor); + } + break; +} + +/* Opcode: CreateTable P1 P2 * * * +** Synopsis: r[P2]=root iDb=P1 +** +** Allocate a new table in the main database file if P1==0 or in the +** auxiliary database file if P1==1 or in an attached database if +** P1>1. Write the root page number of the new table into +** register P2 +** +** The difference between a table and an index is this: A table must +** have a 4-byte integer key and can have arbitrary data. An index +** has an arbitrary key but no data. +** +** See also: CreateIndex +*/ +/* Opcode: CreateIndex P1 P2 * * * +** Synopsis: r[P2]=root iDb=P1 +** +** Allocate a new index in the main database file if P1==0 or in the +** auxiliary database file if P1==1 or in an attached database if +** P1>1. Write the root page number of the new table into +** register P2. +** +** See documentation on OP_CreateTable for additional information. +*/ +case OP_CreateIndex: /* out2 */ +case OP_CreateTable: { /* out2 */ + int pgno; + int flags; + Db *pDb; + + pOut = out2Prerelease(p, pOp); + pgno = 0; + assert( pOp->p1>=0 && pOp->p1nDb ); + assert( DbMaskTest(p->btreeMask, pOp->p1) ); + assert( p->readOnly==0 ); + pDb = &db->aDb[pOp->p1]; + assert( pDb->pBt!=0 ); + if( pOp->opcode==OP_CreateTable ){ + /* flags = BTREE_INTKEY; */ + flags = BTREE_INTKEY; + }else{ + flags = BTREE_BLOBKEY; + } + rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); + pOut->u.i = pgno; + break; +} + +/* Opcode: ParseSchema P1 * * P4 * +** +** Read and parse all entries from the SQLITE_MASTER table of database P1 +** that match the WHERE clause P4. +** +** This opcode invokes the parser to create a new virtual machine, +** then runs the new virtual machine. It is thus a re-entrant opcode. +*/ +case OP_ParseSchema: { + int iDb; + const char *zMaster; + char *zSql; + InitData initData; + + /* Any prepared statement that invokes this opcode will hold mutexes + ** on every btree. This is a prerequisite for invoking + ** sqlite3InitCallback(). + */ +#ifdef SQLITE_DEBUG + for(iDb=0; iDbnDb; iDb++){ + assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); + } +#endif + + iDb = pOp->p1; + assert( iDb>=0 && iDbnDb ); + assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); + /* Used to be a conditional */ { + zMaster = SCHEMA_TABLE(iDb); + initData.db = db; + initData.iDb = pOp->p1; + initData.pzErrMsg = &p->zErrMsg; + zSql = sqlite3MPrintf(db, + "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", + db->aDb[iDb].zName, zMaster, pOp->p4.z); + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + assert( db->init.busy==0 ); + db->init.busy = 1; + initData.rc = SQLITE_OK; + assert( !db->mallocFailed ); + rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); + if( rc==SQLITE_OK ) rc = initData.rc; + sqlite3DbFree(db, zSql); + db->init.busy = 0; + } + } + if( rc ) sqlite3ResetAllSchemasOfConnection(db); + if( rc==SQLITE_NOMEM ){ + goto no_mem; + } + break; +} + +#if !defined(SQLITE_OMIT_ANALYZE) +/* Opcode: LoadAnalysis P1 * * * * +** +** Read the sqlite_stat1 table for database P1 and load the content +** of that table into the internal index hash table. This will cause +** the analysis to be used when preparing all subsequent queries. +*/ +case OP_LoadAnalysis: { + assert( pOp->p1>=0 && pOp->p1nDb ); + rc = sqlite3AnalysisLoad(db, pOp->p1); + break; +} +#endif /* !defined(SQLITE_OMIT_ANALYZE) */ + +/* Opcode: DropTable P1 * * P4 * +** +** Remove the internal (in-memory) data structures that describe +** the table named P4 in database P1. This is called after a table +** is dropped from disk (using the Destroy opcode) in order to keep +** the internal representation of the +** schema consistent with what is on disk. +*/ +case OP_DropTable: { + sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z); + break; +} + +/* Opcode: DropIndex P1 * * P4 * +** +** Remove the internal (in-memory) data structures that describe +** the index named P4 in database P1. This is called after an index +** is dropped from disk (using the Destroy opcode) +** in order to keep the internal representation of the +** schema consistent with what is on disk. +*/ +case OP_DropIndex: { + sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z); + break; +} + +/* Opcode: DropTrigger P1 * * P4 * +** +** Remove the internal (in-memory) data structures that describe +** the trigger named P4 in database P1. This is called after a trigger +** is dropped from disk (using the Destroy opcode) in order to keep +** the internal representation of the +** schema consistent with what is on disk. +*/ +case OP_DropTrigger: { + sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z); + break; +} + + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* Opcode: IntegrityCk P1 P2 P3 * P5 +** +** Do an analysis of the currently open database. Store in +** register P1 the text of an error message describing any problems. +** If no problems are found, store a NULL in register P1. +** +** The register P3 contains the maximum number of allowed errors. +** At most reg(P3) errors will be reported. +** In other words, the analysis stops as soon as reg(P1) errors are +** seen. Reg(P1) is updated with the number of errors remaining. +** +** The root page numbers of all tables in the database are integer +** stored in reg(P1), reg(P1+1), reg(P1+2), .... There are P2 tables +** total. +** +** If P5 is not zero, the check is done on the auxiliary database +** file, not the main database file. +** +** This opcode is used to implement the integrity_check pragma. +*/ +case OP_IntegrityCk: { + int nRoot; /* Number of tables to check. (Number of root pages.) */ + int *aRoot; /* Array of rootpage numbers for tables to be checked */ + int j; /* Loop counter */ + int nErr; /* Number of errors reported */ + char *z; /* Text of the error report */ + Mem *pnErr; /* Register keeping track of errors remaining */ + + assert( p->bIsReader ); + nRoot = pOp->p2; + assert( nRoot>0 ); + aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) ); + if( aRoot==0 ) goto no_mem; + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); + pnErr = &aMem[pOp->p3]; + assert( (pnErr->flags & MEM_Int)!=0 ); + assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); + pIn1 = &aMem[pOp->p1]; + for(j=0; jp5nDb ); + assert( DbMaskTest(p->btreeMask, pOp->p5) ); + z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, + (int)pnErr->u.i, &nErr); + sqlite3DbFree(db, aRoot); + pnErr->u.i -= nErr; + sqlite3VdbeMemSetNull(pIn1); + if( nErr==0 ){ + assert( z==0 ); + }else if( z==0 ){ + goto no_mem; + }else{ + sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free); + } + UPDATE_MAX_BLOBSIZE(pIn1); + sqlite3VdbeChangeEncoding(pIn1, encoding); + break; +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +/* Opcode: RowSetAdd P1 P2 * * * +** Synopsis: rowset(P1)=r[P2] +** +** Insert the integer value held by register P2 into a boolean index +** held in register P1. +** +** An assertion fails if P2 is not an integer. +*/ +case OP_RowSetAdd: { /* in1, in2 */ + pIn1 = &aMem[pOp->p1]; + pIn2 = &aMem[pOp->p2]; + assert( (pIn2->flags & MEM_Int)!=0 ); + if( (pIn1->flags & MEM_RowSet)==0 ){ + sqlite3VdbeMemSetRowSet(pIn1); + if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem; + } + sqlite3RowSetInsert(pIn1->u.pRowSet, pIn2->u.i); + break; +} + +/* Opcode: RowSetRead P1 P2 P3 * * +** Synopsis: r[P3]=rowset(P1) +** +** Extract the smallest value from boolean index P1 and put that value into +** register P3. Or, if boolean index P1 is initially empty, leave P3 +** unchanged and jump to instruction P2. +*/ +case OP_RowSetRead: { /* jump, in1, out3 */ + i64 val; + + pIn1 = &aMem[pOp->p1]; + if( (pIn1->flags & MEM_RowSet)==0 + || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0 + ){ + /* The boolean index is empty */ + sqlite3VdbeMemSetNull(pIn1); + VdbeBranchTaken(1,2); + goto jump_to_p2_and_check_for_interrupt; + }else{ + /* A value was pulled from the index */ + VdbeBranchTaken(0,2); + sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); + } + goto check_for_interrupt; +} + +/* Opcode: RowSetTest P1 P2 P3 P4 +** Synopsis: if r[P3] in rowset(P1) goto P2 +** +** Register P3 is assumed to hold a 64-bit integer value. If register P1 +** contains a RowSet object and that RowSet object contains +** the value held in P3, jump to register P2. Otherwise, insert the +** integer in P3 into the RowSet and continue on to the +** next opcode. +** +** The RowSet object is optimized for the case where successive sets +** of integers, where each set contains no duplicates. Each set +** of values is identified by a unique P4 value. The first set +** must have P4==0, the final set P4=-1. P4 must be either -1 or +** non-negative. For non-negative values of P4 only the lower 4 +** bits are significant. +** +** This allows optimizations: (a) when P4==0 there is no need to test +** the rowset object for P3, as it is guaranteed not to contain it, +** (b) when P4==-1 there is no need to insert the value, as it will +** never be tested for, and (c) when a value that is part of set X is +** inserted, there is no need to search to see if the same value was +** previously inserted as part of set X (only if it was previously +** inserted as part of some other set). +*/ +case OP_RowSetTest: { /* jump, in1, in3 */ + int iSet; + int exists; + + pIn1 = &aMem[pOp->p1]; + pIn3 = &aMem[pOp->p3]; + iSet = pOp->p4.i; + assert( pIn3->flags&MEM_Int ); + + /* If there is anything other than a rowset object in memory cell P1, + ** delete it now and initialize P1 with an empty rowset + */ + if( (pIn1->flags & MEM_RowSet)==0 ){ + sqlite3VdbeMemSetRowSet(pIn1); + if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem; + } + + assert( pOp->p4type==P4_INT32 ); + assert( iSet==-1 || iSet>=0 ); + if( iSet ){ + exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i); + VdbeBranchTaken(exists!=0,2); + if( exists ) goto jump_to_p2; + } + if( iSet>=0 ){ + sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i); + } + break; +} + + +#ifndef SQLITE_OMIT_TRIGGER + +/* Opcode: Program P1 P2 P3 P4 P5 +** +** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). +** +** P1 contains the address of the memory cell that contains the first memory +** cell in an array of values used as arguments to the sub-program. P2 +** contains the address to jump to if the sub-program throws an IGNORE +** exception using the RAISE() function. Register P3 contains the address +** of a memory cell in this (the parent) VM that is used to allocate the +** memory required by the sub-vdbe at runtime. +** +** P4 is a pointer to the VM containing the trigger program. +** +** If P5 is non-zero, then recursive program invocation is enabled. +*/ +case OP_Program: { /* jump */ + int nMem; /* Number of memory registers for sub-program */ + int nByte; /* Bytes of runtime space required for sub-program */ + Mem *pRt; /* Register to allocate runtime space */ + Mem *pMem; /* Used to iterate through memory cells */ + Mem *pEnd; /* Last memory cell in new array */ + VdbeFrame *pFrame; /* New vdbe frame to execute in */ + SubProgram *pProgram; /* Sub-program to execute */ + void *t; /* Token identifying trigger */ + + pProgram = pOp->p4.pProgram; + pRt = &aMem[pOp->p3]; + assert( pProgram->nOp>0 ); + + /* If the p5 flag is clear, then recursive invocation of triggers is + ** disabled for backwards compatibility (p5 is set if this sub-program + ** is really a trigger, not a foreign key action, and the flag set + ** and cleared by the "PRAGMA recursive_triggers" command is clear). + ** + ** It is recursive invocation of triggers, at the SQL level, that is + ** disabled. In some cases a single trigger may generate more than one + ** SubProgram (if the trigger may be executed with more than one different + ** ON CONFLICT algorithm). SubProgram structures associated with a + ** single trigger all have the same value for the SubProgram.token + ** variable. */ + if( pOp->p5 ){ + t = pProgram->token; + for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent); + if( pFrame ) break; + } + + if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){ + rc = SQLITE_ERROR; + sqlite3VdbeError(p, "too many levels of trigger recursion"); + break; + } + + /* Register pRt is used to store the memory required to save the state + ** of the current program, and the memory required at runtime to execute + ** the trigger program. If this trigger has been fired before, then pRt + ** is already allocated. Otherwise, it must be initialized. */ + if( (pRt->flags&MEM_Frame)==0 ){ + /* SubProgram.nMem is set to the number of memory cells used by the + ** program stored in SubProgram.aOp. As well as these, one memory + ** cell is required for each cursor used by the program. Set local + ** variable nMem (and later, VdbeFrame.nChildMem) to this value. + */ + nMem = pProgram->nMem + pProgram->nCsr; + nByte = ROUND8(sizeof(VdbeFrame)) + + nMem * sizeof(Mem) + + pProgram->nCsr * sizeof(VdbeCursor *) + + pProgram->nOnce * sizeof(u8); + pFrame = sqlite3DbMallocZero(db, nByte); + if( !pFrame ){ + goto no_mem; + } + sqlite3VdbeMemRelease(pRt); + pRt->flags = MEM_Frame; + pRt->u.pFrame = pFrame; + + pFrame->v = p; + pFrame->nChildMem = nMem; + pFrame->nChildCsr = pProgram->nCsr; + pFrame->pc = (int)(pOp - aOp); + pFrame->aMem = p->aMem; + pFrame->nMem = p->nMem; + pFrame->apCsr = p->apCsr; + pFrame->nCursor = p->nCursor; + pFrame->aOp = p->aOp; + pFrame->nOp = p->nOp; + pFrame->token = pProgram->token; + pFrame->aOnceFlag = p->aOnceFlag; + pFrame->nOnceFlag = p->nOnceFlag; +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + pFrame->anExec = p->anExec; +#endif + + pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; + for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ + pMem->flags = MEM_Undefined; + pMem->db = db; + } + }else{ + pFrame = pRt->u.pFrame; + assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem ); + assert( pProgram->nCsr==pFrame->nChildCsr ); + assert( (int)(pOp - aOp)==pFrame->pc ); + } + + p->nFrame++; + pFrame->pParent = p->pFrame; + pFrame->lastRowid = lastRowid; + pFrame->nChange = p->nChange; + pFrame->nDbChange = p->db->nChange; + p->nChange = 0; + p->pFrame = pFrame; + p->aMem = aMem = &VdbeFrameMem(pFrame)[-1]; + p->nMem = pFrame->nChildMem; + p->nCursor = (u16)pFrame->nChildCsr; + p->apCsr = (VdbeCursor **)&aMem[p->nMem+1]; + p->aOp = aOp = pProgram->aOp; + p->nOp = pProgram->nOp; + p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor]; + p->nOnceFlag = pProgram->nOnce; +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + p->anExec = 0; +#endif + pOp = &aOp[-1]; + memset(p->aOnceFlag, 0, p->nOnceFlag); + + break; +} + +/* Opcode: Param P1 P2 * * * +** +** This opcode is only ever present in sub-programs called via the +** OP_Program instruction. Copy a value currently stored in a memory +** cell of the calling (parent) frame to cell P2 in the current frames +** address space. This is used by trigger programs to access the new.* +** and old.* values. +** +** The address of the cell in the parent frame is determined by adding +** the value of the P1 argument to the value of the P1 argument to the +** calling OP_Program instruction. +*/ +case OP_Param: { /* out2 */ + VdbeFrame *pFrame; + Mem *pIn; + pOut = out2Prerelease(p, pOp); + pFrame = p->pFrame; + pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1]; + sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem); + break; +} + +#endif /* #ifndef SQLITE_OMIT_TRIGGER */ + +#ifndef SQLITE_OMIT_FOREIGN_KEY +/* Opcode: FkCounter P1 P2 * * * +** Synopsis: fkctr[P1]+=P2 +** +** Increment a "constraint counter" by P2 (P2 may be negative or positive). +** If P1 is non-zero, the database constraint counter is incremented +** (deferred foreign key constraints). Otherwise, if P1 is zero, the +** statement counter is incremented (immediate foreign key constraints). +*/ +case OP_FkCounter: { + if( db->flags & SQLITE_DeferFKs ){ + db->nDeferredImmCons += pOp->p2; + }else if( pOp->p1 ){ + db->nDeferredCons += pOp->p2; + }else{ + p->nFkConstraint += pOp->p2; + } + break; +} + +/* Opcode: FkIfZero P1 P2 * * * +** Synopsis: if fkctr[P1]==0 goto P2 +** +** This opcode tests if a foreign key constraint-counter is currently zero. +** If so, jump to instruction P2. Otherwise, fall through to the next +** instruction. +** +** If P1 is non-zero, then the jump is taken if the database constraint-counter +** is zero (the one that counts deferred constraint violations). If P1 is +** zero, the jump is taken if the statement constraint-counter is zero +** (immediate foreign key constraint violations). +*/ +case OP_FkIfZero: { /* jump */ + if( pOp->p1 ){ + VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2); + if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) goto jump_to_p2; + }else{ + VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2); + if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) goto jump_to_p2; + } + break; +} +#endif /* #ifndef SQLITE_OMIT_FOREIGN_KEY */ + +#ifndef SQLITE_OMIT_AUTOINCREMENT +/* Opcode: MemMax P1 P2 * * * +** Synopsis: r[P1]=max(r[P1],r[P2]) +** +** P1 is a register in the root frame of this VM (the root frame is +** different from the current frame if this instruction is being executed +** within a sub-program). Set the value of register P1 to the maximum of +** its current value and the value in register P2. +** +** This instruction throws an error if the memory cell is not initially +** an integer. +*/ +case OP_MemMax: { /* in2 */ + VdbeFrame *pFrame; + if( p->pFrame ){ + for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); + pIn1 = &pFrame->aMem[pOp->p1]; + }else{ + pIn1 = &aMem[pOp->p1]; + } + assert( memIsValid(pIn1) ); + sqlite3VdbeMemIntegerify(pIn1); + pIn2 = &aMem[pOp->p2]; + sqlite3VdbeMemIntegerify(pIn2); + if( pIn1->u.iu.i){ + pIn1->u.i = pIn2->u.i; + } + break; +} +#endif /* SQLITE_OMIT_AUTOINCREMENT */ + +/* Opcode: IfPos P1 P2 * * * +** Synopsis: if r[P1]>0 goto P2 +** +** Register P1 must contain an integer. +** If the value of register P1 is 1 or greater, jump to P2 and +** add the literal value P3 to register P1. +** +** If the initial value of register P1 is less than 1, then the +** value is unchanged and control passes through to the next instruction. +*/ +case OP_IfPos: { /* jump, in1 */ + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags&MEM_Int ); + VdbeBranchTaken( pIn1->u.i>0, 2); + if( pIn1->u.i>0 ) goto jump_to_p2; + break; +} + +/* Opcode: IfNeg P1 P2 P3 * * +** Synopsis: r[P1]+=P3, if r[P1]<0 goto P2 +** +** Register P1 must contain an integer. Add literal P3 to the value in +** register P1 then if the value of register P1 is less than zero, jump to P2. +*/ +case OP_IfNeg: { /* jump, in1 */ + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags&MEM_Int ); + pIn1->u.i += pOp->p3; + VdbeBranchTaken(pIn1->u.i<0, 2); + if( pIn1->u.i<0 ) goto jump_to_p2; + break; +} + +/* Opcode: IfNotZero P1 P2 P3 * * +** Synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2 +** +** Register P1 must contain an integer. If the content of register P1 is +** initially nonzero, then add P3 to P1 and jump to P2. If register P1 is +** initially zero, leave it unchanged and fall through. +*/ +case OP_IfNotZero: { /* jump, in1 */ + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags&MEM_Int ); + VdbeBranchTaken(pIn1->u.i<0, 2); + if( pIn1->u.i ){ + pIn1->u.i += pOp->p3; + goto jump_to_p2; + } + break; +} + +/* Opcode: DecrJumpZero P1 P2 * * * +** Synopsis: if (--r[P1])==0 goto P2 +** +** Register P1 must hold an integer. Decrement the value in register P1 +** then jump to P2 if the new value is exactly zero. +*/ +case OP_DecrJumpZero: { /* jump, in1 */ + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags&MEM_Int ); + pIn1->u.i--; + VdbeBranchTaken(pIn1->u.i==0, 2); + if( pIn1->u.i==0 ) goto jump_to_p2; + break; +} + + +/* Opcode: JumpZeroIncr P1 P2 * * * +** Synopsis: if (r[P1]++)==0 ) goto P2 +** +** The register P1 must contain an integer. If register P1 is initially +** zero, then jump to P2. Increment register P1 regardless of whether or +** not the jump is taken. +*/ +case OP_JumpZeroIncr: { /* jump, in1 */ + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags&MEM_Int ); + VdbeBranchTaken(pIn1->u.i==0, 2); + if( (pIn1->u.i++)==0 ) goto jump_to_p2; + break; +} + +/* Opcode: AggStep0 * P2 P3 P4 P5 +** Synopsis: accum=r[P3] step(r[P2@P5]) +** +** Execute the step function for an aggregate. The +** function has P5 arguments. P4 is a pointer to the FuncDef +** structure that specifies the function. Register P3 is the +** accumulator. +** +** The P5 arguments are taken from register P2 and its +** successors. +*/ +/* Opcode: AggStep * P2 P3 P4 P5 +** Synopsis: accum=r[P3] step(r[P2@P5]) +** +** Execute the step function for an aggregate. The +** function has P5 arguments. P4 is a pointer to an sqlite3_context +** object that is used to run the function. Register P3 is +** as the accumulator. +** +** The P5 arguments are taken from register P2 and its +** successors. +** +** This opcode is initially coded as OP_AggStep0. On first evaluation, +** the FuncDef stored in P4 is converted into an sqlite3_context and +** the opcode is changed. In this way, the initialization of the +** sqlite3_context only happens once, instead of on each call to the +** step function. +*/ +case OP_AggStep0: { + int n; + sqlite3_context *pCtx; + + assert( pOp->p4type==P4_FUNCDEF ); + n = pOp->p5; + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); + assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); + assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); + pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); + if( pCtx==0 ) goto no_mem; + pCtx->pMem = 0; + pCtx->pFunc = pOp->p4.pFunc; + pCtx->iOp = (int)(pOp - aOp); + pCtx->pVdbe = p; + pCtx->argc = n; + pOp->p4type = P4_FUNCCTX; + pOp->p4.pCtx = pCtx; + pOp->opcode = OP_AggStep; + /* Fall through into OP_AggStep */ +} +case OP_AggStep: { + int i; + sqlite3_context *pCtx; + Mem *pMem; + Mem t; + + assert( pOp->p4type==P4_FUNCCTX ); + pCtx = pOp->p4.pCtx; + pMem = &aMem[pOp->p3]; + + /* If this function is inside of a trigger, the register array in aMem[] + ** might change from one evaluation to the next. The next block of code + ** checks to see if the register array has changed, and if so it + ** reinitializes the relavant parts of the sqlite3_context object */ + if( pCtx->pMem != pMem ){ + pCtx->pMem = pMem; + for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; + } + +#ifdef SQLITE_DEBUG + for(i=0; iargc; i++){ + assert( memIsValid(pCtx->argv[i]) ); + REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]); + } +#endif + + pMem->n++; + sqlite3VdbeMemInit(&t, db, MEM_Null); + pCtx->pOut = &t; + pCtx->fErrorOrAux = 0; + pCtx->skipFlag = 0; + (pCtx->pFunc->xStep)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */ + if( pCtx->fErrorOrAux ){ + if( pCtx->isError ){ + sqlite3VdbeError(p, "%s", sqlite3_value_text(&t)); + rc = pCtx->isError; + } + sqlite3VdbeMemRelease(&t); + }else{ + assert( t.flags==MEM_Null ); + } + if( pCtx->skipFlag ){ + assert( pOp[-1].opcode==OP_CollSeq ); + i = pOp[-1].p1; + if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); + } + break; +} + +/* Opcode: AggFinal P1 P2 * P4 * +** Synopsis: accum=r[P1] N=P2 +** +** Execute the finalizer function for an aggregate. P1 is +** the memory location that is the accumulator for the aggregate. +** +** P2 is the number of arguments that the step function takes and +** P4 is a pointer to the FuncDef for this function. The P2 +** argument is not used by this opcode. It is only there to disambiguate +** functions that can take varying numbers of arguments. The +** P4 argument is only needed for the degenerate case where +** the step function was not previously called. +*/ +case OP_AggFinal: { + Mem *pMem; + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); + pMem = &aMem[pOp->p1]; + assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); + rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); + if( rc ){ + sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem)); + } + sqlite3VdbeChangeEncoding(pMem, encoding); + UPDATE_MAX_BLOBSIZE(pMem); + if( sqlite3VdbeMemTooBig(pMem) ){ + goto too_big; + } + break; +} + +#ifndef SQLITE_OMIT_WAL +/* Opcode: Checkpoint P1 P2 P3 * * +** +** Checkpoint database P1. This is a no-op if P1 is not currently in +** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL, +** RESTART, or TRUNCATE. Write 1 or 0 into mem[P3] if the checkpoint returns +** SQLITE_BUSY or not, respectively. Write the number of pages in the +** WAL after the checkpoint into mem[P3+1] and the number of pages +** in the WAL that have been checkpointed after the checkpoint +** completes into mem[P3+2]. However on an error, mem[P3+1] and +** mem[P3+2] are initialized to -1. +*/ +case OP_Checkpoint: { + int i; /* Loop counter */ + int aRes[3]; /* Results */ + Mem *pMem; /* Write results here */ + + assert( p->readOnly==0 ); + aRes[0] = 0; + aRes[1] = aRes[2] = -1; + assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE + || pOp->p2==SQLITE_CHECKPOINT_FULL + || pOp->p2==SQLITE_CHECKPOINT_RESTART + || pOp->p2==SQLITE_CHECKPOINT_TRUNCATE + ); + rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]); + if( rc==SQLITE_BUSY ){ + rc = SQLITE_OK; + aRes[0] = 1; + } + for(i=0, pMem = &aMem[pOp->p3]; i<3; i++, pMem++){ + sqlite3VdbeMemSetInt64(pMem, (i64)aRes[i]); + } + break; +}; +#endif + +#ifndef SQLITE_OMIT_PRAGMA +/* Opcode: JournalMode P1 P2 P3 * * +** +** Change the journal mode of database P1 to P3. P3 must be one of the +** PAGER_JOURNALMODE_XXX values. If changing between the various rollback +** modes (delete, truncate, persist, off and memory), this is a simple +** operation. No IO is required. +** +** If changing into or out of WAL mode the procedure is more complicated. +** +** Write a string containing the final journal-mode to register P2. +*/ +case OP_JournalMode: { /* out2 */ + Btree *pBt; /* Btree to change journal mode of */ + Pager *pPager; /* Pager associated with pBt */ + int eNew; /* New journal mode */ + int eOld; /* The old journal mode */ +#ifndef SQLITE_OMIT_WAL + const char *zFilename; /* Name of database file for pPager */ +#endif + + pOut = out2Prerelease(p, pOp); + eNew = pOp->p3; + assert( eNew==PAGER_JOURNALMODE_DELETE + || eNew==PAGER_JOURNALMODE_TRUNCATE + || eNew==PAGER_JOURNALMODE_PERSIST + || eNew==PAGER_JOURNALMODE_OFF + || eNew==PAGER_JOURNALMODE_MEMORY + || eNew==PAGER_JOURNALMODE_WAL + || eNew==PAGER_JOURNALMODE_QUERY + ); + assert( pOp->p1>=0 && pOp->p1nDb ); + assert( p->readOnly==0 ); + + pBt = db->aDb[pOp->p1].pBt; + pPager = sqlite3BtreePager(pBt); + eOld = sqlite3PagerGetJournalMode(pPager); + if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld; + if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld; + +#ifndef SQLITE_OMIT_WAL + zFilename = sqlite3PagerFilename(pPager, 1); + + /* Do not allow a transition to journal_mode=WAL for a database + ** in temporary storage or if the VFS does not support shared memory + */ + if( eNew==PAGER_JOURNALMODE_WAL + && (sqlite3Strlen30(zFilename)==0 /* Temp file */ + || !sqlite3PagerWalSupported(pPager)) /* No shared-memory support */ + ){ + eNew = eOld; + } + + if( (eNew!=eOld) + && (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL) + ){ + if( !db->autoCommit || db->nVdbeRead>1 ){ + rc = SQLITE_ERROR; + sqlite3VdbeError(p, + "cannot change %s wal mode from within a transaction", + (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of") + ); + break; + }else{ + + if( eOld==PAGER_JOURNALMODE_WAL ){ + /* If leaving WAL mode, close the log file. If successful, the call + ** to PagerCloseWal() checkpoints and deletes the write-ahead-log + ** file. An EXCLUSIVE lock may still be held on the database file + ** after a successful return. + */ + rc = sqlite3PagerCloseWal(pPager); + if( rc==SQLITE_OK ){ + sqlite3PagerSetJournalMode(pPager, eNew); + } + }else if( eOld==PAGER_JOURNALMODE_MEMORY ){ + /* Cannot transition directly from MEMORY to WAL. Use mode OFF + ** as an intermediate */ + sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF); + } + + /* Open a transaction on the database file. Regardless of the journal + ** mode, this transaction always uses a rollback journal. + */ + assert( sqlite3BtreeIsInTrans(pBt)==0 ); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1)); + } + } + } +#endif /* ifndef SQLITE_OMIT_WAL */ + + if( rc ){ + eNew = eOld; + } + eNew = sqlite3PagerSetJournalMode(pPager, eNew); + + pOut->flags = MEM_Str|MEM_Static|MEM_Term; + pOut->z = (char *)sqlite3JournalModename(eNew); + pOut->n = sqlite3Strlen30(pOut->z); + pOut->enc = SQLITE_UTF8; + sqlite3VdbeChangeEncoding(pOut, encoding); + break; +}; +#endif /* SQLITE_OMIT_PRAGMA */ + +#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) +/* Opcode: Vacuum * * * * * +** +** Vacuum the entire database. This opcode will cause other virtual +** machines to be created and run. It may not be called from within +** a transaction. +*/ +case OP_Vacuum: { + assert( p->readOnly==0 ); + rc = sqlite3RunVacuum(&p->zErrMsg, db); + break; +} +#endif + +#if !defined(SQLITE_OMIT_AUTOVACUUM) +/* Opcode: IncrVacuum P1 P2 * * * +** +** Perform a single step of the incremental vacuum procedure on +** the P1 database. If the vacuum has finished, jump to instruction +** P2. Otherwise, fall through to the next instruction. +*/ +case OP_IncrVacuum: { /* jump */ + Btree *pBt; + + assert( pOp->p1>=0 && pOp->p1nDb ); + assert( DbMaskTest(p->btreeMask, pOp->p1) ); + assert( p->readOnly==0 ); + pBt = db->aDb[pOp->p1].pBt; + rc = sqlite3BtreeIncrVacuum(pBt); + VdbeBranchTaken(rc==SQLITE_DONE,2); + if( rc==SQLITE_DONE ){ + rc = SQLITE_OK; + goto jump_to_p2; + } + break; +} +#endif + +/* Opcode: Expire P1 * * * * +** +** Cause precompiled statements to expire. When an expired statement +** is executed using sqlite3_step() it will either automatically +** reprepare itself (if it was originally created using sqlite3_prepare_v2()) +** or it will fail with SQLITE_SCHEMA. +** +** If P1 is 0, then all SQL statements become expired. If P1 is non-zero, +** then only the currently executing statement is expired. +*/ +case OP_Expire: { + if( !pOp->p1 ){ + sqlite3ExpirePreparedStatements(db); + }else{ + p->expired = 1; + } + break; +} + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* Opcode: TableLock P1 P2 P3 P4 * +** Synopsis: iDb=P1 root=P2 write=P3 +** +** Obtain a lock on a particular table. This instruction is only used when +** the shared-cache feature is enabled. +** +** P1 is the index of the database in sqlite3.aDb[] of the database +** on which the lock is acquired. A readlock is obtained if P3==0 or +** a write lock if P3==1. +** +** P2 contains the root-page of the table to lock. +** +** P4 contains a pointer to the name of the table being locked. This is only +** used to generate an error message if the lock cannot be obtained. +*/ +case OP_TableLock: { + u8 isWriteLock = (u8)pOp->p3; + if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){ + int p1 = pOp->p1; + assert( p1>=0 && p1nDb ); + assert( DbMaskTest(p->btreeMask, p1) ); + assert( isWriteLock==0 || isWriteLock==1 ); + rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock); + if( (rc&0xFF)==SQLITE_LOCKED ){ + const char *z = pOp->p4.z; + sqlite3VdbeError(p, "database table is locked: %s", z); + } + } + break; +} +#endif /* SQLITE_OMIT_SHARED_CACHE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VBegin * * * P4 * +** +** P4 may be a pointer to an sqlite3_vtab structure. If so, call the +** xBegin method for that table. +** +** Also, whether or not P4 is set, check that this is not being called from +** within a callback to a virtual table xSync() method. If it is, the error +** code will be set to SQLITE_LOCKED. +*/ +case OP_VBegin: { + VTable *pVTab; + pVTab = pOp->p4.pVtab; + rc = sqlite3VtabBegin(db, pVTab); + if( pVTab ) sqlite3VtabImportErrmsg(p, pVTab->pVtab); + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VCreate P1 P2 * * * +** +** P2 is a register that holds the name of a virtual table in database +** P1. Call the xCreate method for that table. +*/ +case OP_VCreate: { + Mem sMem; /* For storing the record being decoded */ + const char *zTab; /* Name of the virtual table */ + + memset(&sMem, 0, sizeof(sMem)); + sMem.db = db; + /* Because P2 is always a static string, it is impossible for the + ** sqlite3VdbeMemCopy() to fail */ + assert( (aMem[pOp->p2].flags & MEM_Str)!=0 ); + assert( (aMem[pOp->p2].flags & MEM_Static)!=0 ); + rc = sqlite3VdbeMemCopy(&sMem, &aMem[pOp->p2]); + assert( rc==SQLITE_OK ); + zTab = (const char*)sqlite3_value_text(&sMem); + assert( zTab || db->mallocFailed ); + if( zTab ){ + rc = sqlite3VtabCallCreate(db, pOp->p1, zTab, &p->zErrMsg); + } + sqlite3VdbeMemRelease(&sMem); + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VDestroy P1 * * P4 * +** +** P4 is the name of a virtual table in database P1. Call the xDestroy method +** of that table. +*/ +case OP_VDestroy: { + db->nVDestroy++; + rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z); + db->nVDestroy--; + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VOpen P1 * * P4 * +** +** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. +** P1 is a cursor number. This opcode opens a cursor to the virtual +** table and stores that cursor in P1. +*/ +case OP_VOpen: { + VdbeCursor *pCur; + sqlite3_vtab_cursor *pVtabCursor; + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + + assert( p->bIsReader ); + pCur = 0; + pVtabCursor = 0; + pVtab = pOp->p4.pVtab->pVtab; + if( pVtab==0 || NEVER(pVtab->pModule==0) ){ + rc = SQLITE_LOCKED; + break; + } + pModule = pVtab->pModule; + rc = pModule->xOpen(pVtab, &pVtabCursor); + sqlite3VtabImportErrmsg(p, pVtab); + if( SQLITE_OK==rc ){ + /* Initialize sqlite3_vtab_cursor base class */ + pVtabCursor->pVtab = pVtab; + + /* Initialize vdbe cursor object */ + pCur = allocateCursor(p, pOp->p1, 0, -1, 0); + if( pCur ){ + pCur->pVtabCursor = pVtabCursor; + pVtab->nRef++; + }else{ + assert( db->mallocFailed ); + pModule->xClose(pVtabCursor); + goto no_mem; + } + } + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VFilter P1 P2 P3 P4 * +** Synopsis: iplan=r[P3] zplan='P4' +** +** P1 is a cursor opened using VOpen. P2 is an address to jump to if +** the filtered result set is empty. +** +** P4 is either NULL or a string that was generated by the xBestIndex +** method of the module. The interpretation of the P4 string is left +** to the module implementation. +** +** This opcode invokes the xFilter method on the virtual table specified +** by P1. The integer query plan parameter to xFilter is stored in register +** P3. Register P3+1 stores the argc parameter to be passed to the +** xFilter method. Registers P3+2..P3+1+argc are the argc +** additional parameters which are passed to +** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter. +** +** A jump is made to P2 if the result set after filtering would be empty. +*/ +case OP_VFilter: { /* jump */ + int nArg; + int iQuery; + const sqlite3_module *pModule; + Mem *pQuery; + Mem *pArgc; + sqlite3_vtab_cursor *pVtabCursor; + sqlite3_vtab *pVtab; + VdbeCursor *pCur; + int res; + int i; + Mem **apArg; + + pQuery = &aMem[pOp->p3]; + pArgc = &pQuery[1]; + pCur = p->apCsr[pOp->p1]; + assert( memIsValid(pQuery) ); + REGISTER_TRACE(pOp->p3, pQuery); + assert( pCur->pVtabCursor ); + pVtabCursor = pCur->pVtabCursor; + pVtab = pVtabCursor->pVtab; + pModule = pVtab->pModule; + + /* Grab the index number and argc parameters */ + assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int ); + nArg = (int)pArgc->u.i; + iQuery = (int)pQuery->u.i; + + /* Invoke the xFilter method */ + res = 0; + apArg = p->apArg; + for(i = 0; ixFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg); + sqlite3VtabImportErrmsg(p, pVtab); + if( rc==SQLITE_OK ){ + res = pModule->xEof(pVtabCursor); + } + pCur->nullRow = 0; + VdbeBranchTaken(res!=0,2); + if( res ) goto jump_to_p2; + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VColumn P1 P2 P3 * * +** Synopsis: r[P3]=vcolumn(P2) +** +** Store the value of the P2-th column of +** the row of the virtual-table that the +** P1 cursor is pointing to into register P3. +*/ +case OP_VColumn: { + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + Mem *pDest; + sqlite3_context sContext; + + VdbeCursor *pCur = p->apCsr[pOp->p1]; + assert( pCur->pVtabCursor ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); + pDest = &aMem[pOp->p3]; + memAboutToChange(p, pDest); + if( pCur->nullRow ){ + sqlite3VdbeMemSetNull(pDest); + break; + } + pVtab = pCur->pVtabCursor->pVtab; + pModule = pVtab->pModule; + assert( pModule->xColumn ); + memset(&sContext, 0, sizeof(sContext)); + sContext.pOut = pDest; + MemSetTypeFlag(pDest, MEM_Null); + rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2); + sqlite3VtabImportErrmsg(p, pVtab); + if( sContext.isError ){ + rc = sContext.isError; + } + sqlite3VdbeChangeEncoding(pDest, encoding); + REGISTER_TRACE(pOp->p3, pDest); + UPDATE_MAX_BLOBSIZE(pDest); + + if( sqlite3VdbeMemTooBig(pDest) ){ + goto too_big; + } + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VNext P1 P2 * * * +** +** Advance virtual table P1 to the next row in its result set and +** jump to instruction P2. Or, if the virtual table has reached +** the end of its result set, then fall through to the next instruction. +*/ +case OP_VNext: { /* jump */ + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + int res; + VdbeCursor *pCur; + + res = 0; + pCur = p->apCsr[pOp->p1]; + assert( pCur->pVtabCursor ); + if( pCur->nullRow ){ + break; + } + pVtab = pCur->pVtabCursor->pVtab; + pModule = pVtab->pModule; + assert( pModule->xNext ); + + /* Invoke the xNext() method of the module. There is no way for the + ** underlying implementation to return an error if one occurs during + ** xNext(). Instead, if an error occurs, true is returned (indicating that + ** data is available) and the error code returned when xColumn or + ** some other method is next invoked on the save virtual table cursor. + */ + rc = pModule->xNext(pCur->pVtabCursor); + sqlite3VtabImportErrmsg(p, pVtab); + if( rc==SQLITE_OK ){ + res = pModule->xEof(pCur->pVtabCursor); + } + VdbeBranchTaken(!res,2); + if( !res ){ + /* If there is data, jump to P2 */ + goto jump_to_p2_and_check_for_interrupt; + } + goto check_for_interrupt; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VRename P1 * * P4 * +** +** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. +** This opcode invokes the corresponding xRename method. The value +** in register P1 is passed as the zName argument to the xRename method. +*/ +case OP_VRename: { + sqlite3_vtab *pVtab; + Mem *pName; + + pVtab = pOp->p4.pVtab->pVtab; + pName = &aMem[pOp->p1]; + assert( pVtab->pModule->xRename ); + assert( memIsValid(pName) ); + assert( p->readOnly==0 ); + REGISTER_TRACE(pOp->p1, pName); + assert( pName->flags & MEM_Str ); + testcase( pName->enc==SQLITE_UTF8 ); + testcase( pName->enc==SQLITE_UTF16BE ); + testcase( pName->enc==SQLITE_UTF16LE ); + rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8); + if( rc==SQLITE_OK ){ + rc = pVtab->pModule->xRename(pVtab, pName->z); + sqlite3VtabImportErrmsg(p, pVtab); + p->expired = 0; + } + break; +} +#endif + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VUpdate P1 P2 P3 P4 P5 +** Synopsis: data=r[P3@P2] +** +** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. +** This opcode invokes the corresponding xUpdate method. P2 values +** are contiguous memory cells starting at P3 to pass to the xUpdate +** invocation. The value in register (P3+P2-1) corresponds to the +** p2th element of the argv array passed to xUpdate. +** +** The xUpdate method will do a DELETE or an INSERT or both. +** The argv[0] element (which corresponds to memory cell P3) +** is the rowid of a row to delete. If argv[0] is NULL then no +** deletion occurs. The argv[1] element is the rowid of the new +** row. This can be NULL to have the virtual table select the new +** rowid for itself. The subsequent elements in the array are +** the values of columns in the new row. +** +** If P2==1 then no insert is performed. argv[0] is the rowid of +** a row to delete. +** +** P1 is a boolean flag. If it is set to true and the xUpdate call +** is successful, then the value returned by sqlite3_last_insert_rowid() +** is set to the value of the rowid for the row just inserted. +** +** P5 is the error actions (OE_Replace, OE_Fail, OE_Ignore, etc) to +** apply in the case of a constraint failure on an insert or update. +*/ +case OP_VUpdate: { + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + int nArg; + int i; + sqlite_int64 rowid; + Mem **apArg; + Mem *pX; + + assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback + || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace + ); + assert( p->readOnly==0 ); + pVtab = pOp->p4.pVtab->pVtab; + if( pVtab==0 || NEVER(pVtab->pModule==0) ){ + rc = SQLITE_LOCKED; + break; + } + pModule = pVtab->pModule; + nArg = pOp->p2; + assert( pOp->p4type==P4_VTAB ); + if( ALWAYS(pModule->xUpdate) ){ + u8 vtabOnConflict = db->vtabOnConflict; + apArg = p->apArg; + pX = &aMem[pOp->p3]; + for(i=0; ivtabOnConflict = pOp->p5; + rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid); + db->vtabOnConflict = vtabOnConflict; + sqlite3VtabImportErrmsg(p, pVtab); + if( rc==SQLITE_OK && pOp->p1 ){ + assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) ); + db->lastRowid = lastRowid = rowid; + } + if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){ + if( pOp->p5==OE_Ignore ){ + rc = SQLITE_OK; + }else{ + p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5); + } + }else{ + p->nChange++; + } + } + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +/* Opcode: Pagecount P1 P2 * * * +** +** Write the current number of pages in database P1 to memory cell P2. +*/ +case OP_Pagecount: { /* out2 */ + pOut = out2Prerelease(p, pOp); + pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt); + break; +} +#endif + + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +/* Opcode: MaxPgcnt P1 P2 P3 * * +** +** Try to set the maximum page count for database P1 to the value in P3. +** Do not let the maximum page count fall below the current page count and +** do not change the maximum page count value if P3==0. +** +** Store the maximum page count after the change in register P2. +*/ +case OP_MaxPgcnt: { /* out2 */ + unsigned int newMax; + Btree *pBt; + + pOut = out2Prerelease(p, pOp); + pBt = db->aDb[pOp->p1].pBt; + newMax = 0; + if( pOp->p3 ){ + newMax = sqlite3BtreeLastPage(pBt); + if( newMax < (unsigned)pOp->p3 ) newMax = (unsigned)pOp->p3; + } + pOut->u.i = sqlite3BtreeMaxPageCount(pBt, newMax); + break; +} +#endif + + +/* Opcode: Init * P2 * P4 * +** Synopsis: Start at P2 +** +** Programs contain a single instance of this opcode as the very first +** opcode. +** +** If tracing is enabled (by the sqlite3_trace()) interface, then +** the UTF-8 string contained in P4 is emitted on the trace callback. +** Or if P4 is blank, use the string returned by sqlite3_sql(). +** +** If P2 is not zero, jump to instruction P2. +*/ +case OP_Init: { /* jump */ + char *zTrace; + char *z; + +#ifndef SQLITE_OMIT_TRACE + if( db->xTrace + && !p->doingRerun + && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 + ){ + z = sqlite3VdbeExpandSql(p, zTrace); + db->xTrace(db->pTraceArg, z); + sqlite3DbFree(db, z); + } +#ifdef SQLITE_USE_FCNTL_TRACE + zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); + if( zTrace ){ + int i; + for(i=0; inDb; i++){ + if( DbMaskTest(p->btreeMask, i)==0 ) continue; + sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace); + } + } +#endif /* SQLITE_USE_FCNTL_TRACE */ +#ifdef SQLITE_DEBUG + if( (db->flags & SQLITE_SqlTrace)!=0 + && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 + ){ + sqlite3DebugPrintf("SQL-trace: %s\n", zTrace); + } +#endif /* SQLITE_DEBUG */ +#endif /* SQLITE_OMIT_TRACE */ + if( pOp->p2 ) goto jump_to_p2; + break; +} + + +/* Opcode: Noop * * * * * +** +** Do nothing. This instruction is often useful as a jump +** destination. +*/ +/* +** The magic Explain opcode are only inserted when explain==2 (which +** is to say when the EXPLAIN QUERY PLAN syntax is used.) +** This opcode records information from the optimizer. It is the +** the same as a no-op. This opcodesnever appears in a real VM program. +*/ +default: { /* This is really OP_Noop and OP_Explain */ + assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain ); + break; +} + +/***************************************************************************** +** The cases of the switch statement above this line should all be indented +** by 6 spaces. But the left-most 6 spaces have been removed to improve the +** readability. From this point on down, the normal indentation rules are +** restored. +*****************************************************************************/ + } + +#ifdef VDBE_PROFILE + { + u64 endTime = sqlite3Hwtime(); + if( endTime>start ) pOrigOp->cycles += endTime - start; + pOrigOp->cnt++; + } +#endif + + /* The following code adds nothing to the actual functionality + ** of the program. It is only here for testing and debugging. + ** On the other hand, it does burn CPU cycles every time through + ** the evaluator loop. So we can leave it out when NDEBUG is defined. + */ +#ifndef NDEBUG + assert( pOp>=&aOp[-1] && pOp<&aOp[p->nOp-1] ); + +#ifdef SQLITE_DEBUG + if( db->flags & SQLITE_VdbeTrace ){ + if( rc!=0 ) printf("rc=%d\n",rc); + if( pOrigOp->opflags & (OPFLG_OUT2) ){ + registerTrace(pOrigOp->p2, &aMem[pOrigOp->p2]); + } + if( pOrigOp->opflags & OPFLG_OUT3 ){ + registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]); + } + } +#endif /* SQLITE_DEBUG */ +#endif /* NDEBUG */ + } /* The end of the for(;;) loop the loops through opcodes */ + + /* If we reach this point, it means that execution is finished with + ** an error of some kind. + */ +vdbe_error_halt: + assert( rc ); + p->rc = rc; + testcase( sqlite3GlobalConfig.xLog!=0 ); + sqlite3_log(rc, "statement aborts at %d: [%s] %s", + (int)(pOp - aOp), p->zSql, p->zErrMsg); + sqlite3VdbeHalt(p); + if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; + rc = SQLITE_ERROR; + if( resetSchemaOnFault>0 ){ + sqlite3ResetOneSchema(db, resetSchemaOnFault-1); + } + + /* This is the only way out of this procedure. We have to + ** release the mutexes on btrees that were acquired at the + ** top. */ +vdbe_return: + db->lastRowid = lastRowid; + testcase( nVmStep>0 ); + p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; + sqlite3VdbeLeave(p); + return rc; + + /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH + ** is encountered. + */ +too_big: + sqlite3VdbeError(p, "string or blob too big"); + rc = SQLITE_TOOBIG; + goto vdbe_error_halt; + + /* Jump to here if a malloc() fails. + */ +no_mem: + db->mallocFailed = 1; + sqlite3VdbeError(p, "out of memory"); + rc = SQLITE_NOMEM; + goto vdbe_error_halt; + + /* Jump to here for any other kind of fatal error. The "rc" variable + ** should hold the error number. + */ +abort_due_to_error: + assert( p->zErrMsg==0 ); + if( db->mallocFailed ) rc = SQLITE_NOMEM; + if( rc!=SQLITE_IOERR_NOMEM ){ + sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); + } + goto vdbe_error_halt; + + /* Jump to here if the sqlite3_interrupt() API sets the interrupt + ** flag. + */ +abort_due_to_interrupt: + assert( db->u1.isInterrupted ); + rc = SQLITE_INTERRUPT; + p->rc = rc; + sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); + goto vdbe_error_halt; +} + + +/************** End of vdbe.c ************************************************/ +/************** Begin file vdbeblob.c ****************************************/ +/* +** 2007 May 1 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains code used to implement incremental BLOB I/O. +*/ + +/* #include "sqliteInt.h" */ +/* #include "vdbeInt.h" */ + +#ifndef SQLITE_OMIT_INCRBLOB + +/* +** Valid sqlite3_blob* handles point to Incrblob structures. +*/ +typedef struct Incrblob Incrblob; +struct Incrblob { + int flags; /* Copy of "flags" passed to sqlite3_blob_open() */ + int nByte; /* Size of open blob, in bytes */ + int iOffset; /* Byte offset of blob in cursor data */ + int iCol; /* Table column this handle is open on */ + BtCursor *pCsr; /* Cursor pointing at blob row */ + sqlite3_stmt *pStmt; /* Statement holding cursor open */ + sqlite3 *db; /* The associated database */ +}; + + +/* +** This function is used by both blob_open() and blob_reopen(). It seeks +** the b-tree cursor associated with blob handle p to point to row iRow. +** If successful, SQLITE_OK is returned and subsequent calls to +** sqlite3_blob_read() or sqlite3_blob_write() access the specified row. +** +** If an error occurs, or if the specified row does not exist or does not +** contain a value of type TEXT or BLOB in the column nominated when the +** blob handle was opened, then an error code is returned and *pzErr may +** be set to point to a buffer containing an error message. It is the +** responsibility of the caller to free the error message buffer using +** sqlite3DbFree(). +** +** If an error does occur, then the b-tree cursor is closed. All subsequent +** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will +** immediately return SQLITE_ABORT. +*/ +static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ + int rc; /* Error code */ + char *zErr = 0; /* Error message */ + Vdbe *v = (Vdbe *)p->pStmt; + + /* Set the value of the SQL statements only variable to integer iRow. + ** This is done directly instead of using sqlite3_bind_int64() to avoid + ** triggering asserts related to mutexes. + */ + assert( v->aVar[0].flags&MEM_Int ); + v->aVar[0].u.i = iRow; + + rc = sqlite3_step(p->pStmt); + if( rc==SQLITE_ROW ){ + VdbeCursor *pC = v->apCsr[0]; + u32 type = pC->aType[p->iCol]; + if( type<12 ){ + zErr = sqlite3MPrintf(p->db, "cannot open value of type %s", + type==0?"null": type==7?"real": "integer" + ); + rc = SQLITE_ERROR; + sqlite3_finalize(p->pStmt); + p->pStmt = 0; + }else{ + p->iOffset = pC->aType[p->iCol + pC->nField]; + p->nByte = sqlite3VdbeSerialTypeLen(type); + p->pCsr = pC->pCursor; + sqlite3BtreeIncrblobCursor(p->pCsr); + } + } + + if( rc==SQLITE_ROW ){ + rc = SQLITE_OK; + }else if( p->pStmt ){ + rc = sqlite3_finalize(p->pStmt); + p->pStmt = 0; + if( rc==SQLITE_OK ){ + zErr = sqlite3MPrintf(p->db, "no such rowid: %lld", iRow); + rc = SQLITE_ERROR; + }else{ + zErr = sqlite3MPrintf(p->db, "%s", sqlite3_errmsg(p->db)); + } + } + + assert( rc!=SQLITE_OK || zErr==0 ); + assert( rc!=SQLITE_ROW && rc!=SQLITE_DONE ); + + *pzErr = zErr; + return rc; +} + +/* +** Open a blob handle. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( + sqlite3* db, /* The database connection */ + const char *zDb, /* The attached database containing the blob */ + const char *zTable, /* The table containing the blob */ + const char *zColumn, /* The column containing the blob */ + sqlite_int64 iRow, /* The row containing the glob */ + int flags, /* True -> read/write access, false -> read-only */ + sqlite3_blob **ppBlob /* Handle for accessing the blob returned here */ +){ + int nAttempt = 0; + int iCol; /* Index of zColumn in row-record */ + + /* This VDBE program seeks a btree cursor to the identified + ** db/table/row entry. The reason for using a vdbe program instead + ** of writing code to use the b-tree layer directly is that the + ** vdbe program will take advantage of the various transaction, + ** locking and error handling infrastructure built into the vdbe. + ** + ** After seeking the cursor, the vdbe executes an OP_ResultRow. + ** Code external to the Vdbe then "borrows" the b-tree cursor and + ** uses it to implement the blob_read(), blob_write() and + ** blob_bytes() functions. + ** + ** The sqlite3_blob_close() function finalizes the vdbe program, + ** which closes the b-tree cursor and (possibly) commits the + ** transaction. + */ + static const int iLn = VDBE_OFFSET_LINENO(4); + static const VdbeOpList openBlob[] = { + /* {OP_Transaction, 0, 0, 0}, // 0: Inserted separately */ + {OP_TableLock, 0, 0, 0}, /* 1: Acquire a read or write lock */ + /* One of the following two instructions is replaced by an OP_Noop. */ + {OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */ + {OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */ + {OP_Variable, 1, 1, 1}, /* 4: Push the rowid to the stack */ + {OP_NotExists, 0, 10, 1}, /* 5: Seek the cursor */ + {OP_Column, 0, 0, 1}, /* 6 */ + {OP_ResultRow, 1, 0, 0}, /* 7 */ + {OP_Goto, 0, 4, 0}, /* 8 */ + {OP_Close, 0, 0, 0}, /* 9 */ + {OP_Halt, 0, 0, 0}, /* 10 */ + }; + + int rc = SQLITE_OK; + char *zErr = 0; + Table *pTab; + Parse *pParse = 0; + Incrblob *pBlob = 0; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( ppBlob==0 ){ + return SQLITE_MISUSE_BKPT; + } +#endif + *ppBlob = 0; +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) || zTable==0 ){ + return SQLITE_MISUSE_BKPT; + } +#endif + flags = !!flags; /* flags = (flags ? 1 : 0); */ + + sqlite3_mutex_enter(db->mutex); + + pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob)); + if( !pBlob ) goto blob_open_out; + pParse = sqlite3StackAllocRaw(db, sizeof(*pParse)); + if( !pParse ) goto blob_open_out; + + do { + memset(pParse, 0, sizeof(Parse)); + pParse->db = db; + sqlite3DbFree(db, zErr); + zErr = 0; + + sqlite3BtreeEnterAll(db); + pTab = sqlite3LocateTable(pParse, 0, zTable, zDb); + if( pTab && IsVirtual(pTab) ){ + pTab = 0; + sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable); + } + if( pTab && !HasRowid(pTab) ){ + pTab = 0; + sqlite3ErrorMsg(pParse, "cannot open table without rowid: %s", zTable); + } +#ifndef SQLITE_OMIT_VIEW + if( pTab && pTab->pSelect ){ + pTab = 0; + sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable); + } +#endif + if( !pTab ){ + if( pParse->zErrMsg ){ + sqlite3DbFree(db, zErr); + zErr = pParse->zErrMsg; + pParse->zErrMsg = 0; + } + rc = SQLITE_ERROR; + sqlite3BtreeLeaveAll(db); + goto blob_open_out; + } + + /* Now search pTab for the exact column. */ + for(iCol=0; iColnCol; iCol++) { + if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){ + break; + } + } + if( iCol==pTab->nCol ){ + sqlite3DbFree(db, zErr); + zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn); + rc = SQLITE_ERROR; + sqlite3BtreeLeaveAll(db); + goto blob_open_out; + } + + /* If the value is being opened for writing, check that the + ** column is not indexed, and that it is not part of a foreign key. + ** It is against the rules to open a column to which either of these + ** descriptions applies for writing. */ + if( flags ){ + const char *zFault = 0; + Index *pIdx; +#ifndef SQLITE_OMIT_FOREIGN_KEY + if( db->flags&SQLITE_ForeignKeys ){ + /* Check that the column is not part of an FK child key definition. It + ** is not necessary to check if it is part of a parent key, as parent + ** key columns must be indexed. The check below will pick up this + ** case. */ + FKey *pFKey; + for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ + int j; + for(j=0; jnCol; j++){ + if( pFKey->aCol[j].iFrom==iCol ){ + zFault = "foreign key"; + } + } + } + } +#endif + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + int j; + for(j=0; jnKeyCol; j++){ + if( pIdx->aiColumn[j]==iCol ){ + zFault = "indexed"; + } + } + } + if( zFault ){ + sqlite3DbFree(db, zErr); + zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault); + rc = SQLITE_ERROR; + sqlite3BtreeLeaveAll(db); + goto blob_open_out; + } + } + + pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse); + assert( pBlob->pStmt || db->mallocFailed ); + if( pBlob->pStmt ){ + Vdbe *v = (Vdbe *)pBlob->pStmt; + int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + + + sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags, + pTab->pSchema->schema_cookie, + pTab->pSchema->iGeneration); + sqlite3VdbeChangeP5(v, 1); + sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn); + + /* Make sure a mutex is held on the table to be accessed */ + sqlite3VdbeUsesBtree(v, iDb); + + /* Configure the OP_TableLock instruction */ +#ifdef SQLITE_OMIT_SHARED_CACHE + sqlite3VdbeChangeToNoop(v, 1); +#else + sqlite3VdbeChangeP1(v, 1, iDb); + sqlite3VdbeChangeP2(v, 1, pTab->tnum); + sqlite3VdbeChangeP3(v, 1, flags); + sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT); +#endif + + /* Remove either the OP_OpenWrite or OpenRead. Set the P2 + ** parameter of the other to pTab->tnum. */ + sqlite3VdbeChangeToNoop(v, 3 - flags); + sqlite3VdbeChangeP2(v, 2 + flags, pTab->tnum); + sqlite3VdbeChangeP3(v, 2 + flags, iDb); + + /* Configure the number of columns. Configure the cursor to + ** think that the table has one more column than it really + ** does. An OP_Column to retrieve this imaginary column will + ** always return an SQL NULL. This is useful because it means + ** we can invoke OP_Column to fill in the vdbe cursors type + ** and offset cache without causing any IO. + */ + sqlite3VdbeChangeP4(v, 2+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32); + sqlite3VdbeChangeP2(v, 6, pTab->nCol); + if( !db->mallocFailed ){ + pParse->nVar = 1; + pParse->nMem = 1; + pParse->nTab = 1; + sqlite3VdbeMakeReady(v, pParse); + } + } + + pBlob->flags = flags; + pBlob->iCol = iCol; + pBlob->db = db; + sqlite3BtreeLeaveAll(db); + if( db->mallocFailed ){ + goto blob_open_out; + } + sqlite3_bind_int64(pBlob->pStmt, 1, iRow); + rc = blobSeekToRow(pBlob, iRow, &zErr); + } while( (++nAttempt)mallocFailed==0 ){ + *ppBlob = (sqlite3_blob *)pBlob; + }else{ + if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); + sqlite3DbFree(db, pBlob); + } + sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); + sqlite3DbFree(db, zErr); + sqlite3ParserReset(pParse); + sqlite3StackFree(db, pParse); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Close a blob handle that was previously created using +** sqlite3_blob_open(). +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *pBlob){ + Incrblob *p = (Incrblob *)pBlob; + int rc; + sqlite3 *db; + + if( p ){ + db = p->db; + sqlite3_mutex_enter(db->mutex); + rc = sqlite3_finalize(p->pStmt); + sqlite3DbFree(db, p); + sqlite3_mutex_leave(db->mutex); + }else{ + rc = SQLITE_OK; + } + return rc; +} + +/* +** Perform a read or write operation on a blob +*/ +static int blobReadWrite( + sqlite3_blob *pBlob, + void *z, + int n, + int iOffset, + int (*xCall)(BtCursor*, u32, u32, void*) +){ + int rc; + Incrblob *p = (Incrblob *)pBlob; + Vdbe *v; + sqlite3 *db; + + if( p==0 ) return SQLITE_MISUSE_BKPT; + db = p->db; + sqlite3_mutex_enter(db->mutex); + v = (Vdbe*)p->pStmt; + + if( n<0 || iOffset<0 || ((sqlite3_int64)iOffset+n)>p->nByte ){ + /* Request is out of range. Return a transient error. */ + rc = SQLITE_ERROR; + }else if( v==0 ){ + /* If there is no statement handle, then the blob-handle has + ** already been invalidated. Return SQLITE_ABORT in this case. + */ + rc = SQLITE_ABORT; + }else{ + /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is + ** returned, clean-up the statement handle. + */ + assert( db == v->db ); + sqlite3BtreeEnterCursor(p->pCsr); + rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); + sqlite3BtreeLeaveCursor(p->pCsr); + if( rc==SQLITE_ABORT ){ + sqlite3VdbeFinalize(v); + p->pStmt = 0; + }else{ + v->rc = rc; + } + } + sqlite3Error(db, rc); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Read data from a blob handle. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ + return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData); +} + +/* +** Write data to a blob handle. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ + return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData); +} + +/* +** Query a blob handle for the size of the data. +** +** The Incrblob.nByte field is fixed for the lifetime of the Incrblob +** so no mutex is required for access. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *pBlob){ + Incrblob *p = (Incrblob *)pBlob; + return (p && p->pStmt) ? p->nByte : 0; +} + +/* +** Move an existing blob handle to point to a different row of the same +** database table. +** +** If an error occurs, or if the specified row does not exist or does not +** contain a blob or text value, then an error code is returned and the +** database handle error code and message set. If this happens, then all +** subsequent calls to sqlite3_blob_xxx() functions (except blob_close()) +** immediately return SQLITE_ABORT. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ + int rc; + Incrblob *p = (Incrblob *)pBlob; + sqlite3 *db; + + if( p==0 ) return SQLITE_MISUSE_BKPT; + db = p->db; + sqlite3_mutex_enter(db->mutex); + + if( p->pStmt==0 ){ + /* If there is no statement handle, then the blob-handle has + ** already been invalidated. Return SQLITE_ABORT in this case. + */ + rc = SQLITE_ABORT; + }else{ + char *zErr; + rc = blobSeekToRow(p, iRow, &zErr); + if( rc!=SQLITE_OK ){ + sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); + sqlite3DbFree(db, zErr); + } + assert( rc!=SQLITE_SCHEMA ); + } + + rc = sqlite3ApiExit(db, rc); + assert( rc==SQLITE_OK || p->pStmt==0 ); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +#endif /* #ifndef SQLITE_OMIT_INCRBLOB */ + +/************** End of vdbeblob.c ********************************************/ +/************** Begin file vdbesort.c ****************************************/ +/* +** 2011-07-09 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code for the VdbeSorter object, used in concert with +** a VdbeCursor to sort large numbers of keys for CREATE INDEX statements +** or by SELECT statements with ORDER BY clauses that cannot be satisfied +** using indexes and without LIMIT clauses. +** +** The VdbeSorter object implements a multi-threaded external merge sort +** algorithm that is efficient even if the number of elements being sorted +** exceeds the available memory. +** +** Here is the (internal, non-API) interface between this module and the +** rest of the SQLite system: +** +** sqlite3VdbeSorterInit() Create a new VdbeSorter object. +** +** sqlite3VdbeSorterWrite() Add a single new row to the VdbeSorter +** object. The row is a binary blob in the +** OP_MakeRecord format that contains both +** the ORDER BY key columns and result columns +** in the case of a SELECT w/ ORDER BY, or +** the complete record for an index entry +** in the case of a CREATE INDEX. +** +** sqlite3VdbeSorterRewind() Sort all content previously added. +** Position the read cursor on the +** first sorted element. +** +** sqlite3VdbeSorterNext() Advance the read cursor to the next sorted +** element. +** +** sqlite3VdbeSorterRowkey() Return the complete binary blob for the +** row currently under the read cursor. +** +** sqlite3VdbeSorterCompare() Compare the binary blob for the row +** currently under the read cursor against +** another binary blob X and report if +** X is strictly less than the read cursor. +** Used to enforce uniqueness in a +** CREATE UNIQUE INDEX statement. +** +** sqlite3VdbeSorterClose() Close the VdbeSorter object and reclaim +** all resources. +** +** sqlite3VdbeSorterReset() Refurbish the VdbeSorter for reuse. This +** is like Close() followed by Init() only +** much faster. +** +** The interfaces above must be called in a particular order. Write() can +** only occur in between Init()/Reset() and Rewind(). Next(), Rowkey(), and +** Compare() can only occur in between Rewind() and Close()/Reset(). i.e. +** +** Init() +** for each record: Write() +** Rewind() +** Rowkey()/Compare() +** Next() +** Close() +** +** Algorithm: +** +** Records passed to the sorter via calls to Write() are initially held +** unsorted in main memory. Assuming the amount of memory used never exceeds +** a threshold, when Rewind() is called the set of records is sorted using +** an in-memory merge sort. In this case, no temporary files are required +** and subsequent calls to Rowkey(), Next() and Compare() read records +** directly from main memory. +** +** If the amount of space used to store records in main memory exceeds the +** threshold, then the set of records currently in memory are sorted and +** written to a temporary file in "Packed Memory Array" (PMA) format. +** A PMA created at this point is known as a "level-0 PMA". Higher levels +** of PMAs may be created by merging existing PMAs together - for example +** merging two or more level-0 PMAs together creates a level-1 PMA. +** +** The threshold for the amount of main memory to use before flushing +** records to a PMA is roughly the same as the limit configured for the +** page-cache of the main database. Specifically, the threshold is set to +** the value returned by "PRAGMA main.page_size" multipled by +** that returned by "PRAGMA main.cache_size", in bytes. +** +** If the sorter is running in single-threaded mode, then all PMAs generated +** are appended to a single temporary file. Or, if the sorter is running in +** multi-threaded mode then up to (N+1) temporary files may be opened, where +** N is the configured number of worker threads. In this case, instead of +** sorting the records and writing the PMA to a temporary file itself, the +** calling thread usually launches a worker thread to do so. Except, if +** there are already N worker threads running, the main thread does the work +** itself. +** +** The sorter is running in multi-threaded mode if (a) the library was built +** with pre-processor symbol SQLITE_MAX_WORKER_THREADS set to a value greater +** than zero, and (b) worker threads have been enabled at runtime by calling +** "PRAGMA threads=N" with some value of N greater than 0. +** +** When Rewind() is called, any data remaining in memory is flushed to a +** final PMA. So at this point the data is stored in some number of sorted +** PMAs within temporary files on disk. +** +** If there are fewer than SORTER_MAX_MERGE_COUNT PMAs in total and the +** sorter is running in single-threaded mode, then these PMAs are merged +** incrementally as keys are retreived from the sorter by the VDBE. The +** MergeEngine object, described in further detail below, performs this +** merge. +** +** Or, if running in multi-threaded mode, then a background thread is +** launched to merge the existing PMAs. Once the background thread has +** merged T bytes of data into a single sorted PMA, the main thread +** begins reading keys from that PMA while the background thread proceeds +** with merging the next T bytes of data. And so on. +** +** Parameter T is set to half the value of the memory threshold used +** by Write() above to determine when to create a new PMA. +** +** If there are more than SORTER_MAX_MERGE_COUNT PMAs in total when +** Rewind() is called, then a hierarchy of incremental-merges is used. +** First, T bytes of data from the first SORTER_MAX_MERGE_COUNT PMAs on +** disk are merged together. Then T bytes of data from the second set, and +** so on, such that no operation ever merges more than SORTER_MAX_MERGE_COUNT +** PMAs at a time. This done is to improve locality. +** +** If running in multi-threaded mode and there are more than +** SORTER_MAX_MERGE_COUNT PMAs on disk when Rewind() is called, then more +** than one background thread may be created. Specifically, there may be +** one background thread for each temporary file on disk, and one background +** thread to merge the output of each of the others to a single PMA for +** the main thread to read from. +*/ +/* #include "sqliteInt.h" */ +/* #include "vdbeInt.h" */ + +/* +** If SQLITE_DEBUG_SORTER_THREADS is defined, this module outputs various +** messages to stderr that may be helpful in understanding the performance +** characteristics of the sorter in multi-threaded mode. +*/ +#if 0 +# define SQLITE_DEBUG_SORTER_THREADS 1 +#endif + +/* +** Hard-coded maximum amount of data to accumulate in memory before flushing +** to a level 0 PMA. The purpose of this limit is to prevent various integer +** overflows. 512MiB. +*/ +#define SQLITE_MAX_PMASZ (1<<29) + +/* +** Private objects used by the sorter +*/ +typedef struct MergeEngine MergeEngine; /* Merge PMAs together */ +typedef struct PmaReader PmaReader; /* Incrementally read one PMA */ +typedef struct PmaWriter PmaWriter; /* Incrementally write one PMA */ +typedef struct SorterRecord SorterRecord; /* A record being sorted */ +typedef struct SortSubtask SortSubtask; /* A sub-task in the sort process */ +typedef struct SorterFile SorterFile; /* Temporary file object wrapper */ +typedef struct SorterList SorterList; /* In-memory list of records */ +typedef struct IncrMerger IncrMerger; /* Read & merge multiple PMAs */ + +/* +** A container for a temp file handle and the current amount of data +** stored in the file. +*/ +struct SorterFile { + sqlite3_file *pFd; /* File handle */ + i64 iEof; /* Bytes of data stored in pFd */ +}; + +/* +** An in-memory list of objects to be sorted. +** +** If aMemory==0 then each object is allocated separately and the objects +** are connected using SorterRecord.u.pNext. If aMemory!=0 then all objects +** are stored in the aMemory[] bulk memory, one right after the other, and +** are connected using SorterRecord.u.iNext. +*/ +struct SorterList { + SorterRecord *pList; /* Linked list of records */ + u8 *aMemory; /* If non-NULL, bulk memory to hold pList */ + int szPMA; /* Size of pList as PMA in bytes */ +}; + +/* +** The MergeEngine object is used to combine two or more smaller PMAs into +** one big PMA using a merge operation. Separate PMAs all need to be +** combined into one big PMA in order to be able to step through the sorted +** records in order. +** +** The aReadr[] array contains a PmaReader object for each of the PMAs being +** merged. An aReadr[] object either points to a valid key or else is at EOF. +** ("EOF" means "End Of File". When aReadr[] is at EOF there is no more data.) +** For the purposes of the paragraphs below, we assume that the array is +** actually N elements in size, where N is the smallest power of 2 greater +** to or equal to the number of PMAs being merged. The extra aReadr[] elements +** are treated as if they are empty (always at EOF). +** +** The aTree[] array is also N elements in size. The value of N is stored in +** the MergeEngine.nTree variable. +** +** The final (N/2) elements of aTree[] contain the results of comparing +** pairs of PMA keys together. Element i contains the result of +** comparing aReadr[2*i-N] and aReadr[2*i-N+1]. Whichever key is smaller, the +** aTree element is set to the index of it. +** +** For the purposes of this comparison, EOF is considered greater than any +** other key value. If the keys are equal (only possible with two EOF +** values), it doesn't matter which index is stored. +** +** The (N/4) elements of aTree[] that precede the final (N/2) described +** above contains the index of the smallest of each block of 4 PmaReaders +** And so on. So that aTree[1] contains the index of the PmaReader that +** currently points to the smallest key value. aTree[0] is unused. +** +** Example: +** +** aReadr[0] -> Banana +** aReadr[1] -> Feijoa +** aReadr[2] -> Elderberry +** aReadr[3] -> Currant +** aReadr[4] -> Grapefruit +** aReadr[5] -> Apple +** aReadr[6] -> Durian +** aReadr[7] -> EOF +** +** aTree[] = { X, 5 0, 5 0, 3, 5, 6 } +** +** The current element is "Apple" (the value of the key indicated by +** PmaReader 5). When the Next() operation is invoked, PmaReader 5 will +** be advanced to the next key in its segment. Say the next key is +** "Eggplant": +** +** aReadr[5] -> Eggplant +** +** The contents of aTree[] are updated first by comparing the new PmaReader +** 5 key to the current key of PmaReader 4 (still "Grapefruit"). The PmaReader +** 5 value is still smaller, so aTree[6] is set to 5. And so on up the tree. +** The value of PmaReader 6 - "Durian" - is now smaller than that of PmaReader +** 5, so aTree[3] is set to 6. Key 0 is smaller than key 6 (Bananafile2. And instead of using a +** background thread to prepare data for the PmaReader, with a single +** threaded IncrMerger the allocate part of pTask->file2 is "refilled" with +** keys from pMerger by the calling thread whenever the PmaReader runs out +** of data. +*/ +struct IncrMerger { + SortSubtask *pTask; /* Task that owns this merger */ + MergeEngine *pMerger; /* Merge engine thread reads data from */ + i64 iStartOff; /* Offset to start writing file at */ + int mxSz; /* Maximum bytes of data to store */ + int bEof; /* Set to true when merge is finished */ + int bUseThread; /* True to use a bg thread for this object */ + SorterFile aFile[2]; /* aFile[0] for reading, [1] for writing */ +}; + +/* +** An instance of this object is used for writing a PMA. +** +** The PMA is written one record at a time. Each record is of an arbitrary +** size. But I/O is more efficient if it occurs in page-sized blocks where +** each block is aligned on a page boundary. This object caches writes to +** the PMA so that aligned, page-size blocks are written. +*/ +struct PmaWriter { + int eFWErr; /* Non-zero if in an error state */ + u8 *aBuffer; /* Pointer to write buffer */ + int nBuffer; /* Size of write buffer in bytes */ + int iBufStart; /* First byte of buffer to write */ + int iBufEnd; /* Last byte of buffer to write */ + i64 iWriteOff; /* Offset of start of buffer in file */ + sqlite3_file *pFd; /* File handle to write to */ +}; + +/* +** This object is the header on a single record while that record is being +** held in memory and prior to being written out as part of a PMA. +** +** How the linked list is connected depends on how memory is being managed +** by this module. If using a separate allocation for each in-memory record +** (VdbeSorter.list.aMemory==0), then the list is always connected using the +** SorterRecord.u.pNext pointers. +** +** Or, if using the single large allocation method (VdbeSorter.list.aMemory!=0), +** then while records are being accumulated the list is linked using the +** SorterRecord.u.iNext offset. This is because the aMemory[] array may +** be sqlite3Realloc()ed while records are being accumulated. Once the VM +** has finished passing records to the sorter, or when the in-memory buffer +** is full, the list is sorted. As part of the sorting process, it is +** converted to use the SorterRecord.u.pNext pointers. See function +** vdbeSorterSort() for details. +*/ +struct SorterRecord { + int nVal; /* Size of the record in bytes */ + union { + SorterRecord *pNext; /* Pointer to next record in list */ + int iNext; /* Offset within aMemory of next record */ + } u; + /* The data for the record immediately follows this header */ +}; + +/* Return a pointer to the buffer containing the record data for SorterRecord +** object p. Should be used as if: +** +** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; } +*/ +#define SRVAL(p) ((void*)((SorterRecord*)(p) + 1)) + + +/* Maximum number of PMAs that a single MergeEngine can merge */ +#define SORTER_MAX_MERGE_COUNT 16 + +static int vdbeIncrSwap(IncrMerger*); +static void vdbeIncrFree(IncrMerger *); + +/* +** Free all memory belonging to the PmaReader object passed as the +** argument. All structure fields are set to zero before returning. +*/ +static void vdbePmaReaderClear(PmaReader *pReadr){ + sqlite3_free(pReadr->aAlloc); + sqlite3_free(pReadr->aBuffer); + if( pReadr->aMap ) sqlite3OsUnfetch(pReadr->pFd, 0, pReadr->aMap); + vdbeIncrFree(pReadr->pIncr); + memset(pReadr, 0, sizeof(PmaReader)); +} + +/* +** Read the next nByte bytes of data from the PMA p. +** If successful, set *ppOut to point to a buffer containing the data +** and return SQLITE_OK. Otherwise, if an error occurs, return an SQLite +** error code. +** +** The buffer returned in *ppOut is only valid until the +** next call to this function. +*/ +static int vdbePmaReadBlob( + PmaReader *p, /* PmaReader from which to take the blob */ + int nByte, /* Bytes of data to read */ + u8 **ppOut /* OUT: Pointer to buffer containing data */ +){ + int iBuf; /* Offset within buffer to read from */ + int nAvail; /* Bytes of data available in buffer */ + + if( p->aMap ){ + *ppOut = &p->aMap[p->iReadOff]; + p->iReadOff += nByte; + return SQLITE_OK; + } + + assert( p->aBuffer ); + + /* If there is no more data to be read from the buffer, read the next + ** p->nBuffer bytes of data from the file into it. Or, if there are less + ** than p->nBuffer bytes remaining in the PMA, read all remaining data. */ + iBuf = p->iReadOff % p->nBuffer; + if( iBuf==0 ){ + int nRead; /* Bytes to read from disk */ + int rc; /* sqlite3OsRead() return code */ + + /* Determine how many bytes of data to read. */ + if( (p->iEof - p->iReadOff) > (i64)p->nBuffer ){ + nRead = p->nBuffer; + }else{ + nRead = (int)(p->iEof - p->iReadOff); + } + assert( nRead>0 ); + + /* Readr data from the file. Return early if an error occurs. */ + rc = sqlite3OsRead(p->pFd, p->aBuffer, nRead, p->iReadOff); + assert( rc!=SQLITE_IOERR_SHORT_READ ); + if( rc!=SQLITE_OK ) return rc; + } + nAvail = p->nBuffer - iBuf; + + if( nByte<=nAvail ){ + /* The requested data is available in the in-memory buffer. In this + ** case there is no need to make a copy of the data, just return a + ** pointer into the buffer to the caller. */ + *ppOut = &p->aBuffer[iBuf]; + p->iReadOff += nByte; + }else{ + /* The requested data is not all available in the in-memory buffer. + ** In this case, allocate space at p->aAlloc[] to copy the requested + ** range into. Then return a copy of pointer p->aAlloc to the caller. */ + int nRem; /* Bytes remaining to copy */ + + /* Extend the p->aAlloc[] allocation if required. */ + if( p->nAllocnAlloc*2); + while( nByte>nNew ) nNew = nNew*2; + aNew = sqlite3Realloc(p->aAlloc, nNew); + if( !aNew ) return SQLITE_NOMEM; + p->nAlloc = nNew; + p->aAlloc = aNew; + } + + /* Copy as much data as is available in the buffer into the start of + ** p->aAlloc[]. */ + memcpy(p->aAlloc, &p->aBuffer[iBuf], nAvail); + p->iReadOff += nAvail; + nRem = nByte - nAvail; + + /* The following loop copies up to p->nBuffer bytes per iteration into + ** the p->aAlloc[] buffer. */ + while( nRem>0 ){ + int rc; /* vdbePmaReadBlob() return code */ + int nCopy; /* Number of bytes to copy */ + u8 *aNext; /* Pointer to buffer to copy data from */ + + nCopy = nRem; + if( nRem>p->nBuffer ) nCopy = p->nBuffer; + rc = vdbePmaReadBlob(p, nCopy, &aNext); + if( rc!=SQLITE_OK ) return rc; + assert( aNext!=p->aAlloc ); + memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy); + nRem -= nCopy; + } + + *ppOut = p->aAlloc; + } + + return SQLITE_OK; +} + +/* +** Read a varint from the stream of data accessed by p. Set *pnOut to +** the value read. +*/ +static int vdbePmaReadVarint(PmaReader *p, u64 *pnOut){ + int iBuf; + + if( p->aMap ){ + p->iReadOff += sqlite3GetVarint(&p->aMap[p->iReadOff], pnOut); + }else{ + iBuf = p->iReadOff % p->nBuffer; + if( iBuf && (p->nBuffer-iBuf)>=9 ){ + p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut); + }else{ + u8 aVarint[16], *a; + int i = 0, rc; + do{ + rc = vdbePmaReadBlob(p, 1, &a); + if( rc ) return rc; + aVarint[(i++)&0xf] = a[0]; + }while( (a[0]&0x80)!=0 ); + sqlite3GetVarint(aVarint, pnOut); + } + } + + return SQLITE_OK; +} + +/* +** Attempt to memory map file pFile. If successful, set *pp to point to the +** new mapping and return SQLITE_OK. If the mapping is not attempted +** (because the file is too large or the VFS layer is configured not to use +** mmap), return SQLITE_OK and set *pp to NULL. +** +** Or, if an error occurs, return an SQLite error code. The final value of +** *pp is undefined in this case. +*/ +static int vdbeSorterMapFile(SortSubtask *pTask, SorterFile *pFile, u8 **pp){ + int rc = SQLITE_OK; + if( pFile->iEof<=(i64)(pTask->pSorter->db->nMaxSorterMmap) ){ + sqlite3_file *pFd = pFile->pFd; + if( pFd->pMethods->iVersion>=3 ){ + rc = sqlite3OsFetch(pFd, 0, (int)pFile->iEof, (void**)pp); + testcase( rc!=SQLITE_OK ); + } + } + return rc; +} + +/* +** Attach PmaReader pReadr to file pFile (if it is not already attached to +** that file) and seek it to offset iOff within the file. Return SQLITE_OK +** if successful, or an SQLite error code if an error occurs. +*/ +static int vdbePmaReaderSeek( + SortSubtask *pTask, /* Task context */ + PmaReader *pReadr, /* Reader whose cursor is to be moved */ + SorterFile *pFile, /* Sorter file to read from */ + i64 iOff /* Offset in pFile */ +){ + int rc = SQLITE_OK; + + assert( pReadr->pIncr==0 || pReadr->pIncr->bEof==0 ); + + if( sqlite3FaultSim(201) ) return SQLITE_IOERR_READ; + if( pReadr->aMap ){ + sqlite3OsUnfetch(pReadr->pFd, 0, pReadr->aMap); + pReadr->aMap = 0; + } + pReadr->iReadOff = iOff; + pReadr->iEof = pFile->iEof; + pReadr->pFd = pFile->pFd; + + rc = vdbeSorterMapFile(pTask, pFile, &pReadr->aMap); + if( rc==SQLITE_OK && pReadr->aMap==0 ){ + int pgsz = pTask->pSorter->pgsz; + int iBuf = pReadr->iReadOff % pgsz; + if( pReadr->aBuffer==0 ){ + pReadr->aBuffer = (u8*)sqlite3Malloc(pgsz); + if( pReadr->aBuffer==0 ) rc = SQLITE_NOMEM; + pReadr->nBuffer = pgsz; + } + if( rc==SQLITE_OK && iBuf ){ + int nRead = pgsz - iBuf; + if( (pReadr->iReadOff + nRead) > pReadr->iEof ){ + nRead = (int)(pReadr->iEof - pReadr->iReadOff); + } + rc = sqlite3OsRead( + pReadr->pFd, &pReadr->aBuffer[iBuf], nRead, pReadr->iReadOff + ); + testcase( rc!=SQLITE_OK ); + } + } + + return rc; +} + +/* +** Advance PmaReader pReadr to the next key in its PMA. Return SQLITE_OK if +** no error occurs, or an SQLite error code if one does. +*/ +static int vdbePmaReaderNext(PmaReader *pReadr){ + int rc = SQLITE_OK; /* Return Code */ + u64 nRec = 0; /* Size of record in bytes */ + + + if( pReadr->iReadOff>=pReadr->iEof ){ + IncrMerger *pIncr = pReadr->pIncr; + int bEof = 1; + if( pIncr ){ + rc = vdbeIncrSwap(pIncr); + if( rc==SQLITE_OK && pIncr->bEof==0 ){ + rc = vdbePmaReaderSeek( + pIncr->pTask, pReadr, &pIncr->aFile[0], pIncr->iStartOff + ); + bEof = 0; + } + } + + if( bEof ){ + /* This is an EOF condition */ + vdbePmaReaderClear(pReadr); + testcase( rc!=SQLITE_OK ); + return rc; + } + } + + if( rc==SQLITE_OK ){ + rc = vdbePmaReadVarint(pReadr, &nRec); + } + if( rc==SQLITE_OK ){ + pReadr->nKey = (int)nRec; + rc = vdbePmaReadBlob(pReadr, (int)nRec, &pReadr->aKey); + testcase( rc!=SQLITE_OK ); + } + + return rc; +} + +/* +** Initialize PmaReader pReadr to scan through the PMA stored in file pFile +** starting at offset iStart and ending at offset iEof-1. This function +** leaves the PmaReader pointing to the first key in the PMA (or EOF if the +** PMA is empty). +** +** If the pnByte parameter is NULL, then it is assumed that the file +** contains a single PMA, and that that PMA omits the initial length varint. +*/ +static int vdbePmaReaderInit( + SortSubtask *pTask, /* Task context */ + SorterFile *pFile, /* Sorter file to read from */ + i64 iStart, /* Start offset in pFile */ + PmaReader *pReadr, /* PmaReader to populate */ + i64 *pnByte /* IN/OUT: Increment this value by PMA size */ +){ + int rc; + + assert( pFile->iEof>iStart ); + assert( pReadr->aAlloc==0 && pReadr->nAlloc==0 ); + assert( pReadr->aBuffer==0 ); + assert( pReadr->aMap==0 ); + + rc = vdbePmaReaderSeek(pTask, pReadr, pFile, iStart); + if( rc==SQLITE_OK ){ + u64 nByte; /* Size of PMA in bytes */ + rc = vdbePmaReadVarint(pReadr, &nByte); + pReadr->iEof = pReadr->iReadOff + nByte; + *pnByte += nByte; + } + + if( rc==SQLITE_OK ){ + rc = vdbePmaReaderNext(pReadr); + } + return rc; +} + +/* +** A version of vdbeSorterCompare() that assumes that it has already been +** determined that the first field of key1 is equal to the first field of +** key2. +*/ +static int vdbeSorterCompareTail( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + UnpackedRecord *r2 = pTask->pUnpacked; + if( *pbKey2Cached==0 ){ + sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); + *pbKey2Cached = 1; + } + return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1); +} + +/* +** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, +** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences +** used by the comparison. Return the result of the comparison. +** +** If IN/OUT parameter *pbKey2Cached is true when this function is called, +** it is assumed that (pTask->pUnpacked) contains the unpacked version +** of key2. If it is false, (pTask->pUnpacked) is populated with the unpacked +** version of key2 and *pbKey2Cached set to true before returning. +** +** If an OOM error is encountered, (pTask->pUnpacked->error_rc) is set +** to SQLITE_NOMEM. +*/ +static int vdbeSorterCompare( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + UnpackedRecord *r2 = pTask->pUnpacked; + if( !*pbKey2Cached ){ + sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); + *pbKey2Cached = 1; + } + return sqlite3VdbeRecordCompare(nKey1, pKey1, r2); +} + +/* +** A specially optimized version of vdbeSorterCompare() that assumes that +** the first field of each key is a TEXT value and that the collation +** sequence to compare them with is BINARY. +*/ +static int vdbeSorterCompareText( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + const u8 * const p1 = (const u8 * const)pKey1; + const u8 * const p2 = (const u8 * const)pKey2; + const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */ + const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */ + + int n1; + int n2; + int res; + + getVarint32(&p1[1], n1); n1 = (n1 - 13) / 2; + getVarint32(&p2[1], n2); n2 = (n2 - 13) / 2; + res = memcmp(v1, v2, MIN(n1, n2)); + if( res==0 ){ + res = n1 - n2; + } + + if( res==0 ){ + if( pTask->pSorter->pKeyInfo->nField>1 ){ + res = vdbeSorterCompareTail( + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 + ); + } + }else{ + if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + res = res * -1; + } + } + + return res; +} + +/* +** A specially optimized version of vdbeSorterCompare() that assumes that +** the first field of each key is an INTEGER value. +*/ +static int vdbeSorterCompareInt( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + const u8 * const p1 = (const u8 * const)pKey1; + const u8 * const p2 = (const u8 * const)pKey2; + const int s1 = p1[1]; /* Left hand serial type */ + const int s2 = p2[1]; /* Right hand serial type */ + const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */ + const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */ + int res; /* Return value */ + + assert( (s1>0 && s1<7) || s1==8 || s1==9 ); + assert( (s2>0 && s2<7) || s2==8 || s2==9 ); + + if( s1>7 && s2>7 ){ + res = s1 - s2; + }else{ + if( s1==s2 ){ + if( (*v1 ^ *v2) & 0x80 ){ + /* The two values have different signs */ + res = (*v1 & 0x80) ? -1 : +1; + }else{ + /* The two values have the same sign. Compare using memcmp(). */ + static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8 }; + int i; + res = 0; + for(i=0; i7 ){ + res = +1; + }else if( s1>7 ){ + res = -1; + }else{ + res = s1 - s2; + } + assert( res!=0 ); + + if( res>0 ){ + if( *v1 & 0x80 ) res = -1; + }else{ + if( *v2 & 0x80 ) res = +1; + } + } + } + + if( res==0 ){ + if( pTask->pSorter->pKeyInfo->nField>1 ){ + res = vdbeSorterCompareTail( + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 + ); + } + }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + res = res * -1; + } + + return res; +} + +/* +** Initialize the temporary index cursor just opened as a sorter cursor. +** +** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nField) +** to determine the number of fields that should be compared from the +** records being sorted. However, if the value passed as argument nField +** is non-zero and the sorter is able to guarantee a stable sort, nField +** is used instead. This is used when sorting records for a CREATE INDEX +** statement. In this case, keys are always delivered to the sorter in +** order of the primary key, which happens to be make up the final part +** of the records being sorted. So if the sort is stable, there is never +** any reason to compare PK fields and they can be ignored for a small +** performance boost. +** +** The sorter can guarantee a stable sort when running in single-threaded +** mode, but not in multi-threaded mode. +** +** SQLITE_OK is returned if successful, or an SQLite error code otherwise. +*/ +SQLITE_PRIVATE int sqlite3VdbeSorterInit( + sqlite3 *db, /* Database connection (for malloc()) */ + int nField, /* Number of key fields in each record */ + VdbeCursor *pCsr /* Cursor that holds the new sorter */ +){ + int pgsz; /* Page size of main database */ + int i; /* Used to iterate through aTask[] */ + int mxCache; /* Cache size */ + VdbeSorter *pSorter; /* The new sorter */ + KeyInfo *pKeyInfo; /* Copy of pCsr->pKeyInfo with db==0 */ + int szKeyInfo; /* Size of pCsr->pKeyInfo in bytes */ + int sz; /* Size of pSorter in bytes */ + int rc = SQLITE_OK; +#if SQLITE_MAX_WORKER_THREADS==0 +# define nWorker 0 +#else + int nWorker; +#endif + + /* Initialize the upper limit on the number of worker threads */ +#if SQLITE_MAX_WORKER_THREADS>0 + if( sqlite3TempInMemory(db) || sqlite3GlobalConfig.bCoreMutex==0 ){ + nWorker = 0; + }else{ + nWorker = db->aLimit[SQLITE_LIMIT_WORKER_THREADS]; + } +#endif + + /* Do not allow the total number of threads (main thread + all workers) + ** to exceed the maximum merge count */ +#if SQLITE_MAX_WORKER_THREADS>=SORTER_MAX_MERGE_COUNT + if( nWorker>=SORTER_MAX_MERGE_COUNT ){ + nWorker = SORTER_MAX_MERGE_COUNT-1; + } +#endif + + assert( pCsr->pKeyInfo && pCsr->pBt==0 ); + szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nField-1)*sizeof(CollSeq*); + sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask); + + pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo); + pCsr->pSorter = pSorter; + if( pSorter==0 ){ + rc = SQLITE_NOMEM; + }else{ + pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz); + memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo); + pKeyInfo->db = 0; + if( nField && nWorker==0 ){ + pKeyInfo->nXField += (pKeyInfo->nField - nField); + pKeyInfo->nField = nField; + } + pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt); + pSorter->nTask = nWorker + 1; + pSorter->iPrev = nWorker-1; + pSorter->bUseThreads = (pSorter->nTask>1); + pSorter->db = db; + for(i=0; inTask; i++){ + SortSubtask *pTask = &pSorter->aTask[i]; + pTask->pSorter = pSorter; + } + + if( !sqlite3TempInMemory(db) ){ + u32 szPma = sqlite3GlobalConfig.szPma; + pSorter->mnPmaSize = szPma * pgsz; + mxCache = db->aDb[0].pSchema->cache_size; + if( mxCache<(int)szPma ) mxCache = (int)szPma; + pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ); + + /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of + ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary + ** large heap allocations. + */ + if( sqlite3GlobalConfig.pScratch==0 ){ + assert( pSorter->iMemory==0 ); + pSorter->nMemory = pgsz; + pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz); + if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM; + } + } + + if( (pKeyInfo->nField+pKeyInfo->nXField)<13 + && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl) + ){ + pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; + } + } + + return rc; +} +#undef nWorker /* Defined at the top of this function */ + +/* +** Free the list of sorted records starting at pRecord. +*/ +static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){ + SorterRecord *p; + SorterRecord *pNext; + for(p=pRecord; p; p=pNext){ + pNext = p->u.pNext; + sqlite3DbFree(db, p); + } +} + +/* +** Free all resources owned by the object indicated by argument pTask. All +** fields of *pTask are zeroed before returning. +*/ +static void vdbeSortSubtaskCleanup(sqlite3 *db, SortSubtask *pTask){ + sqlite3DbFree(db, pTask->pUnpacked); +#if SQLITE_MAX_WORKER_THREADS>0 + /* pTask->list.aMemory can only be non-zero if it was handed memory + ** from the main thread. That only occurs SQLITE_MAX_WORKER_THREADS>0 */ + if( pTask->list.aMemory ){ + sqlite3_free(pTask->list.aMemory); + }else +#endif + { + assert( pTask->list.aMemory==0 ); + vdbeSorterRecordFree(0, pTask->list.pList); + } + if( pTask->file.pFd ){ + sqlite3OsCloseFree(pTask->file.pFd); + } + if( pTask->file2.pFd ){ + sqlite3OsCloseFree(pTask->file2.pFd); + } + memset(pTask, 0, sizeof(SortSubtask)); +} + +#ifdef SQLITE_DEBUG_SORTER_THREADS +static void vdbeSorterWorkDebug(SortSubtask *pTask, const char *zEvent){ + i64 t; + int iTask = (pTask - pTask->pSorter->aTask); + sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t); + fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent); +} +static void vdbeSorterRewindDebug(const char *zEvent){ + i64 t; + sqlite3OsCurrentTimeInt64(sqlite3_vfs_find(0), &t); + fprintf(stderr, "%lld:X %s\n", t, zEvent); +} +static void vdbeSorterPopulateDebug( + SortSubtask *pTask, + const char *zEvent +){ + i64 t; + int iTask = (pTask - pTask->pSorter->aTask); + sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t); + fprintf(stderr, "%lld:bg%d %s\n", t, iTask, zEvent); +} +static void vdbeSorterBlockDebug( + SortSubtask *pTask, + int bBlocked, + const char *zEvent +){ + if( bBlocked ){ + i64 t; + sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t); + fprintf(stderr, "%lld:main %s\n", t, zEvent); + } +} +#else +# define vdbeSorterWorkDebug(x,y) +# define vdbeSorterRewindDebug(y) +# define vdbeSorterPopulateDebug(x,y) +# define vdbeSorterBlockDebug(x,y,z) +#endif + +#if SQLITE_MAX_WORKER_THREADS>0 +/* +** Join thread pTask->thread. +*/ +static int vdbeSorterJoinThread(SortSubtask *pTask){ + int rc = SQLITE_OK; + if( pTask->pThread ){ +#ifdef SQLITE_DEBUG_SORTER_THREADS + int bDone = pTask->bDone; +#endif + void *pRet = SQLITE_INT_TO_PTR(SQLITE_ERROR); + vdbeSorterBlockDebug(pTask, !bDone, "enter"); + (void)sqlite3ThreadJoin(pTask->pThread, &pRet); + vdbeSorterBlockDebug(pTask, !bDone, "exit"); + rc = SQLITE_PTR_TO_INT(pRet); + assert( pTask->bDone==1 ); + pTask->bDone = 0; + pTask->pThread = 0; + } + return rc; +} + +/* +** Launch a background thread to run xTask(pIn). +*/ +static int vdbeSorterCreateThread( + SortSubtask *pTask, /* Thread will use this task object */ + void *(*xTask)(void*), /* Routine to run in a separate thread */ + void *pIn /* Argument passed into xTask() */ +){ + assert( pTask->pThread==0 && pTask->bDone==0 ); + return sqlite3ThreadCreate(&pTask->pThread, xTask, pIn); +} + +/* +** Join all outstanding threads launched by SorterWrite() to create +** level-0 PMAs. +*/ +static int vdbeSorterJoinAll(VdbeSorter *pSorter, int rcin){ + int rc = rcin; + int i; + + /* This function is always called by the main user thread. + ** + ** If this function is being called after SorterRewind() has been called, + ** it is possible that thread pSorter->aTask[pSorter->nTask-1].pThread + ** is currently attempt to join one of the other threads. To avoid a race + ** condition where this thread also attempts to join the same object, join + ** thread pSorter->aTask[pSorter->nTask-1].pThread first. */ + for(i=pSorter->nTask-1; i>=0; i--){ + SortSubtask *pTask = &pSorter->aTask[i]; + int rc2 = vdbeSorterJoinThread(pTask); + if( rc==SQLITE_OK ) rc = rc2; + } + return rc; +} +#else +# define vdbeSorterJoinAll(x,rcin) (rcin) +# define vdbeSorterJoinThread(pTask) SQLITE_OK +#endif + +/* +** Allocate a new MergeEngine object capable of handling up to +** nReader PmaReader inputs. +** +** nReader is automatically rounded up to the next power of two. +** nReader may not exceed SORTER_MAX_MERGE_COUNT even after rounding up. +*/ +static MergeEngine *vdbeMergeEngineNew(int nReader){ + int N = 2; /* Smallest power of two >= nReader */ + int nByte; /* Total bytes of space to allocate */ + MergeEngine *pNew; /* Pointer to allocated object to return */ + + assert( nReader<=SORTER_MAX_MERGE_COUNT ); + + while( NnTree = N; + pNew->pTask = 0; + pNew->aReadr = (PmaReader*)&pNew[1]; + pNew->aTree = (int*)&pNew->aReadr[N]; + } + return pNew; +} + +/* +** Free the MergeEngine object passed as the only argument. +*/ +static void vdbeMergeEngineFree(MergeEngine *pMerger){ + int i; + if( pMerger ){ + for(i=0; inTree; i++){ + vdbePmaReaderClear(&pMerger->aReadr[i]); + } + } + sqlite3_free(pMerger); +} + +/* +** Free all resources associated with the IncrMerger object indicated by +** the first argument. +*/ +static void vdbeIncrFree(IncrMerger *pIncr){ + if( pIncr ){ +#if SQLITE_MAX_WORKER_THREADS>0 + if( pIncr->bUseThread ){ + vdbeSorterJoinThread(pIncr->pTask); + if( pIncr->aFile[0].pFd ) sqlite3OsCloseFree(pIncr->aFile[0].pFd); + if( pIncr->aFile[1].pFd ) sqlite3OsCloseFree(pIncr->aFile[1].pFd); + } +#endif + vdbeMergeEngineFree(pIncr->pMerger); + sqlite3_free(pIncr); + } +} + +/* +** Reset a sorting cursor back to its original empty state. +*/ +SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){ + int i; + (void)vdbeSorterJoinAll(pSorter, SQLITE_OK); + assert( pSorter->bUseThreads || pSorter->pReader==0 ); +#if SQLITE_MAX_WORKER_THREADS>0 + if( pSorter->pReader ){ + vdbePmaReaderClear(pSorter->pReader); + sqlite3DbFree(db, pSorter->pReader); + pSorter->pReader = 0; + } +#endif + vdbeMergeEngineFree(pSorter->pMerger); + pSorter->pMerger = 0; + for(i=0; inTask; i++){ + SortSubtask *pTask = &pSorter->aTask[i]; + vdbeSortSubtaskCleanup(db, pTask); + pTask->pSorter = pSorter; + } + if( pSorter->list.aMemory==0 ){ + vdbeSorterRecordFree(0, pSorter->list.pList); + } + pSorter->list.pList = 0; + pSorter->list.szPMA = 0; + pSorter->bUsePMA = 0; + pSorter->iMemory = 0; + pSorter->mxKeysize = 0; + sqlite3DbFree(db, pSorter->pUnpacked); + pSorter->pUnpacked = 0; +} + +/* +** Free any cursor components allocated by sqlite3VdbeSorterXXX routines. +*/ +SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){ + VdbeSorter *pSorter = pCsr->pSorter; + if( pSorter ){ + sqlite3VdbeSorterReset(db, pSorter); + sqlite3_free(pSorter->list.aMemory); + sqlite3DbFree(db, pSorter); + pCsr->pSorter = 0; + } +} + +#if SQLITE_MAX_MMAP_SIZE>0 +/* +** The first argument is a file-handle open on a temporary file. The file +** is guaranteed to be nByte bytes or smaller in size. This function +** attempts to extend the file to nByte bytes in size and to ensure that +** the VFS has memory mapped it. +** +** Whether or not the file does end up memory mapped of course depends on +** the specific VFS implementation. +*/ +static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){ + if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){ + void *p = 0; + int chunksize = 4*1024; + sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize); + sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte); + sqlite3OsFetch(pFd, 0, (int)nByte, &p); + sqlite3OsUnfetch(pFd, 0, p); + } +} +#else +# define vdbeSorterExtendFile(x,y,z) +#endif + +/* +** Allocate space for a file-handle and open a temporary file. If successful, +** set *ppFd to point to the malloc'd file-handle and return SQLITE_OK. +** Otherwise, set *ppFd to 0 and return an SQLite error code. +*/ +static int vdbeSorterOpenTempFile( + sqlite3 *db, /* Database handle doing sort */ + i64 nExtend, /* Attempt to extend file to this size */ + sqlite3_file **ppFd +){ + int rc; + if( sqlite3FaultSim(202) ) return SQLITE_IOERR_ACCESS; + rc = sqlite3OsOpenMalloc(db->pVfs, 0, ppFd, + SQLITE_OPEN_TEMP_JOURNAL | + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | + SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &rc + ); + if( rc==SQLITE_OK ){ + i64 max = SQLITE_MAX_MMAP_SIZE; + sqlite3OsFileControlHint(*ppFd, SQLITE_FCNTL_MMAP_SIZE, (void*)&max); + if( nExtend>0 ){ + vdbeSorterExtendFile(db, *ppFd, nExtend); + } + } + return rc; +} + +/* +** If it has not already been allocated, allocate the UnpackedRecord +** structure at pTask->pUnpacked. Return SQLITE_OK if successful (or +** if no allocation was required), or SQLITE_NOMEM otherwise. +*/ +static int vdbeSortAllocUnpacked(SortSubtask *pTask){ + if( pTask->pUnpacked==0 ){ + char *pFree; + pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord( + pTask->pSorter->pKeyInfo, 0, 0, &pFree + ); + assert( pTask->pUnpacked==(UnpackedRecord*)pFree ); + if( pFree==0 ) return SQLITE_NOMEM; + pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField; + pTask->pUnpacked->errCode = 0; + } + return SQLITE_OK; +} + + +/* +** Merge the two sorted lists p1 and p2 into a single list. +** Set *ppOut to the head of the new list. +*/ +static void vdbeSorterMerge( + SortSubtask *pTask, /* Calling thread context */ + SorterRecord *p1, /* First list to merge */ + SorterRecord *p2, /* Second list to merge */ + SorterRecord **ppOut /* OUT: Head of merged list */ +){ + SorterRecord *pFinal = 0; + SorterRecord **pp = &pFinal; + int bCached = 0; + + while( p1 && p2 ){ + int res; + res = pTask->xCompare( + pTask, &bCached, SRVAL(p1), p1->nVal, SRVAL(p2), p2->nVal + ); + + if( res<=0 ){ + *pp = p1; + pp = &p1->u.pNext; + p1 = p1->u.pNext; + }else{ + *pp = p2; + pp = &p2->u.pNext; + p2 = p2->u.pNext; + bCached = 0; + } + } + *pp = p1 ? p1 : p2; + *ppOut = pFinal; +} + +/* +** Return the SorterCompare function to compare values collected by the +** sorter object passed as the only argument. +*/ +static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){ + if( p->typeMask==SORTER_TYPE_INTEGER ){ + return vdbeSorterCompareInt; + }else if( p->typeMask==SORTER_TYPE_TEXT ){ + return vdbeSorterCompareText; + } + return vdbeSorterCompare; +} + +/* +** Sort the linked list of records headed at pTask->pList. Return +** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if +** an error occurs. +*/ +static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){ + int i; + SorterRecord **aSlot; + SorterRecord *p; + int rc; + + rc = vdbeSortAllocUnpacked(pTask); + if( rc!=SQLITE_OK ) return rc; + + p = pList->pList; + pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter); + + aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *)); + if( !aSlot ){ + return SQLITE_NOMEM; + } + + while( p ){ + SorterRecord *pNext; + if( pList->aMemory ){ + if( (u8*)p==pList->aMemory ){ + pNext = 0; + }else{ + assert( p->u.iNextaMemory) ); + pNext = (SorterRecord*)&pList->aMemory[p->u.iNext]; + } + }else{ + pNext = p->u.pNext; + } + + p->u.pNext = 0; + for(i=0; aSlot[i]; i++){ + vdbeSorterMerge(pTask, p, aSlot[i], &p); + aSlot[i] = 0; + } + aSlot[i] = p; + p = pNext; + } + + p = 0; + for(i=0; i<64; i++){ + vdbeSorterMerge(pTask, p, aSlot[i], &p); + } + pList->pList = p; + + sqlite3_free(aSlot); + assert( pTask->pUnpacked->errCode==SQLITE_OK + || pTask->pUnpacked->errCode==SQLITE_NOMEM + ); + return pTask->pUnpacked->errCode; +} + +/* +** Initialize a PMA-writer object. +*/ +static void vdbePmaWriterInit( + sqlite3_file *pFd, /* File handle to write to */ + PmaWriter *p, /* Object to populate */ + int nBuf, /* Buffer size */ + i64 iStart /* Offset of pFd to begin writing at */ +){ + memset(p, 0, sizeof(PmaWriter)); + p->aBuffer = (u8*)sqlite3Malloc(nBuf); + if( !p->aBuffer ){ + p->eFWErr = SQLITE_NOMEM; + }else{ + p->iBufEnd = p->iBufStart = (iStart % nBuf); + p->iWriteOff = iStart - p->iBufStart; + p->nBuffer = nBuf; + p->pFd = pFd; + } +} + +/* +** Write nData bytes of data to the PMA. Return SQLITE_OK +** if successful, or an SQLite error code if an error occurs. +*/ +static void vdbePmaWriteBlob(PmaWriter *p, u8 *pData, int nData){ + int nRem = nData; + while( nRem>0 && p->eFWErr==0 ){ + int nCopy = nRem; + if( nCopy>(p->nBuffer - p->iBufEnd) ){ + nCopy = p->nBuffer - p->iBufEnd; + } + + memcpy(&p->aBuffer[p->iBufEnd], &pData[nData-nRem], nCopy); + p->iBufEnd += nCopy; + if( p->iBufEnd==p->nBuffer ){ + p->eFWErr = sqlite3OsWrite(p->pFd, + &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, + p->iWriteOff + p->iBufStart + ); + p->iBufStart = p->iBufEnd = 0; + p->iWriteOff += p->nBuffer; + } + assert( p->iBufEndnBuffer ); + + nRem -= nCopy; + } +} + +/* +** Flush any buffered data to disk and clean up the PMA-writer object. +** The results of using the PMA-writer after this call are undefined. +** Return SQLITE_OK if flushing the buffered data succeeds or is not +** required. Otherwise, return an SQLite error code. +** +** Before returning, set *piEof to the offset immediately following the +** last byte written to the file. +*/ +static int vdbePmaWriterFinish(PmaWriter *p, i64 *piEof){ + int rc; + if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){ + p->eFWErr = sqlite3OsWrite(p->pFd, + &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, + p->iWriteOff + p->iBufStart + ); + } + *piEof = (p->iWriteOff + p->iBufEnd); + sqlite3_free(p->aBuffer); + rc = p->eFWErr; + memset(p, 0, sizeof(PmaWriter)); + return rc; +} + +/* +** Write value iVal encoded as a varint to the PMA. Return +** SQLITE_OK if successful, or an SQLite error code if an error occurs. +*/ +static void vdbePmaWriteVarint(PmaWriter *p, u64 iVal){ + int nByte; + u8 aByte[10]; + nByte = sqlite3PutVarint(aByte, iVal); + vdbePmaWriteBlob(p, aByte, nByte); +} + +/* +** Write the current contents of in-memory linked-list pList to a level-0 +** PMA in the temp file belonging to sub-task pTask. Return SQLITE_OK if +** successful, or an SQLite error code otherwise. +** +** The format of a PMA is: +** +** * A varint. This varint contains the total number of bytes of content +** in the PMA (not including the varint itself). +** +** * One or more records packed end-to-end in order of ascending keys. +** Each record consists of a varint followed by a blob of data (the +** key). The varint is the number of bytes in the blob of data. +*/ +static int vdbeSorterListToPMA(SortSubtask *pTask, SorterList *pList){ + sqlite3 *db = pTask->pSorter->db; + int rc = SQLITE_OK; /* Return code */ + PmaWriter writer; /* Object used to write to the file */ + +#ifdef SQLITE_DEBUG + /* Set iSz to the expected size of file pTask->file after writing the PMA. + ** This is used by an assert() statement at the end of this function. */ + i64 iSz = pList->szPMA + sqlite3VarintLen(pList->szPMA) + pTask->file.iEof; +#endif + + vdbeSorterWorkDebug(pTask, "enter"); + memset(&writer, 0, sizeof(PmaWriter)); + assert( pList->szPMA>0 ); + + /* If the first temporary PMA file has not been opened, open it now. */ + if( pTask->file.pFd==0 ){ + rc = vdbeSorterOpenTempFile(db, 0, &pTask->file.pFd); + assert( rc!=SQLITE_OK || pTask->file.pFd ); + assert( pTask->file.iEof==0 ); + assert( pTask->nPMA==0 ); + } + + /* Try to get the file to memory map */ + if( rc==SQLITE_OK ){ + vdbeSorterExtendFile(db, pTask->file.pFd, pTask->file.iEof+pList->szPMA+9); + } + + /* Sort the list */ + if( rc==SQLITE_OK ){ + rc = vdbeSorterSort(pTask, pList); + } + + if( rc==SQLITE_OK ){ + SorterRecord *p; + SorterRecord *pNext = 0; + + vdbePmaWriterInit(pTask->file.pFd, &writer, pTask->pSorter->pgsz, + pTask->file.iEof); + pTask->nPMA++; + vdbePmaWriteVarint(&writer, pList->szPMA); + for(p=pList->pList; p; p=pNext){ + pNext = p->u.pNext; + vdbePmaWriteVarint(&writer, p->nVal); + vdbePmaWriteBlob(&writer, SRVAL(p), p->nVal); + if( pList->aMemory==0 ) sqlite3_free(p); + } + pList->pList = p; + rc = vdbePmaWriterFinish(&writer, &pTask->file.iEof); + } + + vdbeSorterWorkDebug(pTask, "exit"); + assert( rc!=SQLITE_OK || pList->pList==0 ); + assert( rc!=SQLITE_OK || pTask->file.iEof==iSz ); + return rc; +} + +/* +** Advance the MergeEngine to its next entry. +** Set *pbEof to true there is no next entry because +** the MergeEngine has reached the end of all its inputs. +** +** Return SQLITE_OK if successful or an error code if an error occurs. +*/ +static int vdbeMergeEngineStep( + MergeEngine *pMerger, /* The merge engine to advance to the next row */ + int *pbEof /* Set TRUE at EOF. Set false for more content */ +){ + int rc; + int iPrev = pMerger->aTree[1];/* Index of PmaReader to advance */ + SortSubtask *pTask = pMerger->pTask; + + /* Advance the current PmaReader */ + rc = vdbePmaReaderNext(&pMerger->aReadr[iPrev]); + + /* Update contents of aTree[] */ + if( rc==SQLITE_OK ){ + int i; /* Index of aTree[] to recalculate */ + PmaReader *pReadr1; /* First PmaReader to compare */ + PmaReader *pReadr2; /* Second PmaReader to compare */ + int bCached = 0; + + /* Find the first two PmaReaders to compare. The one that was just + ** advanced (iPrev) and the one next to it in the array. */ + pReadr1 = &pMerger->aReadr[(iPrev & 0xFFFE)]; + pReadr2 = &pMerger->aReadr[(iPrev | 0x0001)]; + + for(i=(pMerger->nTree+iPrev)/2; i>0; i=i/2){ + /* Compare pReadr1 and pReadr2. Store the result in variable iRes. */ + int iRes; + if( pReadr1->pFd==0 ){ + iRes = +1; + }else if( pReadr2->pFd==0 ){ + iRes = -1; + }else{ + iRes = pTask->xCompare(pTask, &bCached, + pReadr1->aKey, pReadr1->nKey, pReadr2->aKey, pReadr2->nKey + ); + } + + /* If pReadr1 contained the smaller value, set aTree[i] to its index. + ** Then set pReadr2 to the next PmaReader to compare to pReadr1. In this + ** case there is no cache of pReadr2 in pTask->pUnpacked, so set + ** pKey2 to point to the record belonging to pReadr2. + ** + ** Alternatively, if pReadr2 contains the smaller of the two values, + ** set aTree[i] to its index and update pReadr1. If vdbeSorterCompare() + ** was actually called above, then pTask->pUnpacked now contains + ** a value equivalent to pReadr2. So set pKey2 to NULL to prevent + ** vdbeSorterCompare() from decoding pReadr2 again. + ** + ** If the two values were equal, then the value from the oldest + ** PMA should be considered smaller. The VdbeSorter.aReadr[] array + ** is sorted from oldest to newest, so pReadr1 contains older values + ** than pReadr2 iff (pReadr1aTree[i] = (int)(pReadr1 - pMerger->aReadr); + pReadr2 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; + bCached = 0; + }else{ + if( pReadr1->pFd ) bCached = 0; + pMerger->aTree[i] = (int)(pReadr2 - pMerger->aReadr); + pReadr1 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; + } + } + *pbEof = (pMerger->aReadr[pMerger->aTree[1]].pFd==0); + } + + return (rc==SQLITE_OK ? pTask->pUnpacked->errCode : rc); +} + +#if SQLITE_MAX_WORKER_THREADS>0 +/* +** The main routine for background threads that write level-0 PMAs. +*/ +static void *vdbeSorterFlushThread(void *pCtx){ + SortSubtask *pTask = (SortSubtask*)pCtx; + int rc; /* Return code */ + assert( pTask->bDone==0 ); + rc = vdbeSorterListToPMA(pTask, &pTask->list); + pTask->bDone = 1; + return SQLITE_INT_TO_PTR(rc); +} +#endif /* SQLITE_MAX_WORKER_THREADS>0 */ + +/* +** Flush the current contents of VdbeSorter.list to a new PMA, possibly +** using a background thread. +*/ +static int vdbeSorterFlushPMA(VdbeSorter *pSorter){ +#if SQLITE_MAX_WORKER_THREADS==0 + pSorter->bUsePMA = 1; + return vdbeSorterListToPMA(&pSorter->aTask[0], &pSorter->list); +#else + int rc = SQLITE_OK; + int i; + SortSubtask *pTask = 0; /* Thread context used to create new PMA */ + int nWorker = (pSorter->nTask-1); + + /* Set the flag to indicate that at least one PMA has been written. + ** Or will be, anyhow. */ + pSorter->bUsePMA = 1; + + /* Select a sub-task to sort and flush the current list of in-memory + ** records to disk. If the sorter is running in multi-threaded mode, + ** round-robin between the first (pSorter->nTask-1) tasks. Except, if + ** the background thread from a sub-tasks previous turn is still running, + ** skip it. If the first (pSorter->nTask-1) sub-tasks are all still busy, + ** fall back to using the final sub-task. The first (pSorter->nTask-1) + ** sub-tasks are prefered as they use background threads - the final + ** sub-task uses the main thread. */ + for(i=0; iiPrev + i + 1) % nWorker; + pTask = &pSorter->aTask[iTest]; + if( pTask->bDone ){ + rc = vdbeSorterJoinThread(pTask); + } + if( rc!=SQLITE_OK || pTask->pThread==0 ) break; + } + + if( rc==SQLITE_OK ){ + if( i==nWorker ){ + /* Use the foreground thread for this operation */ + rc = vdbeSorterListToPMA(&pSorter->aTask[nWorker], &pSorter->list); + }else{ + /* Launch a background thread for this operation */ + u8 *aMem = pTask->list.aMemory; + void *pCtx = (void*)pTask; + + assert( pTask->pThread==0 && pTask->bDone==0 ); + assert( pTask->list.pList==0 ); + assert( pTask->list.aMemory==0 || pSorter->list.aMemory!=0 ); + + pSorter->iPrev = (u8)(pTask - pSorter->aTask); + pTask->list = pSorter->list; + pSorter->list.pList = 0; + pSorter->list.szPMA = 0; + if( aMem ){ + pSorter->list.aMemory = aMem; + pSorter->nMemory = sqlite3MallocSize(aMem); + }else if( pSorter->list.aMemory ){ + pSorter->list.aMemory = sqlite3Malloc(pSorter->nMemory); + if( !pSorter->list.aMemory ) return SQLITE_NOMEM; + } + + rc = vdbeSorterCreateThread(pTask, vdbeSorterFlushThread, pCtx); + } + } + + return rc; +#endif /* SQLITE_MAX_WORKER_THREADS!=0 */ +} + +/* +** Add a record to the sorter. +*/ +SQLITE_PRIVATE int sqlite3VdbeSorterWrite( + const VdbeCursor *pCsr, /* Sorter cursor */ + Mem *pVal /* Memory cell containing record */ +){ + VdbeSorter *pSorter = pCsr->pSorter; + int rc = SQLITE_OK; /* Return Code */ + SorterRecord *pNew; /* New list element */ + + int bFlush; /* True to flush contents of memory to PMA */ + int nReq; /* Bytes of memory required */ + int nPMA; /* Bytes of PMA space required */ + int t; /* serial type of first record field */ + + getVarint32((const u8*)&pVal->z[1], t); + if( t>0 && t<10 && t!=7 ){ + pSorter->typeMask &= SORTER_TYPE_INTEGER; + }else if( t>10 && (t & 0x01) ){ + pSorter->typeMask &= SORTER_TYPE_TEXT; + }else{ + pSorter->typeMask = 0; + } + + assert( pSorter ); + + /* Figure out whether or not the current contents of memory should be + ** flushed to a PMA before continuing. If so, do so. + ** + ** If using the single large allocation mode (pSorter->aMemory!=0), then + ** flush the contents of memory to a new PMA if (a) at least one value is + ** already in memory and (b) the new value will not fit in memory. + ** + ** Or, if using separate allocations for each record, flush the contents + ** of memory to a PMA if either of the following are true: + ** + ** * The total memory allocated for the in-memory list is greater + ** than (page-size * cache-size), or + ** + ** * The total memory allocated for the in-memory list is greater + ** than (page-size * 10) and sqlite3HeapNearlyFull() returns true. + */ + nReq = pVal->n + sizeof(SorterRecord); + nPMA = pVal->n + sqlite3VarintLen(pVal->n); + if( pSorter->mxPmaSize ){ + if( pSorter->list.aMemory ){ + bFlush = pSorter->iMemory && (pSorter->iMemory+nReq) > pSorter->mxPmaSize; + }else{ + bFlush = ( + (pSorter->list.szPMA > pSorter->mxPmaSize) + || (pSorter->list.szPMA > pSorter->mnPmaSize && sqlite3HeapNearlyFull()) + ); + } + if( bFlush ){ + rc = vdbeSorterFlushPMA(pSorter); + pSorter->list.szPMA = 0; + pSorter->iMemory = 0; + assert( rc!=SQLITE_OK || pSorter->list.pList==0 ); + } + } + + pSorter->list.szPMA += nPMA; + if( nPMA>pSorter->mxKeysize ){ + pSorter->mxKeysize = nPMA; + } + + if( pSorter->list.aMemory ){ + int nMin = pSorter->iMemory + nReq; + + if( nMin>pSorter->nMemory ){ + u8 *aNew; + int nNew = pSorter->nMemory * 2; + while( nNew < nMin ) nNew = nNew*2; + if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize; + if( nNew < nMin ) nNew = nMin; + + aNew = sqlite3Realloc(pSorter->list.aMemory, nNew); + if( !aNew ) return SQLITE_NOMEM; + pSorter->list.pList = (SorterRecord*)( + aNew + ((u8*)pSorter->list.pList - pSorter->list.aMemory) + ); + pSorter->list.aMemory = aNew; + pSorter->nMemory = nNew; + } + + pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory]; + pSorter->iMemory += ROUND8(nReq); + pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory); + }else{ + pNew = (SorterRecord *)sqlite3Malloc(nReq); + if( pNew==0 ){ + return SQLITE_NOMEM; + } + pNew->u.pNext = pSorter->list.pList; + } + + memcpy(SRVAL(pNew), pVal->z, pVal->n); + pNew->nVal = pVal->n; + pSorter->list.pList = pNew; + + return rc; +} + +/* +** Read keys from pIncr->pMerger and populate pIncr->aFile[1]. The format +** of the data stored in aFile[1] is the same as that used by regular PMAs, +** except that the number-of-bytes varint is omitted from the start. +*/ +static int vdbeIncrPopulate(IncrMerger *pIncr){ + int rc = SQLITE_OK; + int rc2; + i64 iStart = pIncr->iStartOff; + SorterFile *pOut = &pIncr->aFile[1]; + SortSubtask *pTask = pIncr->pTask; + MergeEngine *pMerger = pIncr->pMerger; + PmaWriter writer; + assert( pIncr->bEof==0 ); + + vdbeSorterPopulateDebug(pTask, "enter"); + + vdbePmaWriterInit(pOut->pFd, &writer, pTask->pSorter->pgsz, iStart); + while( rc==SQLITE_OK ){ + int dummy; + PmaReader *pReader = &pMerger->aReadr[ pMerger->aTree[1] ]; + int nKey = pReader->nKey; + i64 iEof = writer.iWriteOff + writer.iBufEnd; + + /* Check if the output file is full or if the input has been exhausted. + ** In either case exit the loop. */ + if( pReader->pFd==0 ) break; + if( (iEof + nKey + sqlite3VarintLen(nKey))>(iStart + pIncr->mxSz) ) break; + + /* Write the next key to the output. */ + vdbePmaWriteVarint(&writer, nKey); + vdbePmaWriteBlob(&writer, pReader->aKey, nKey); + assert( pIncr->pMerger->pTask==pTask ); + rc = vdbeMergeEngineStep(pIncr->pMerger, &dummy); + } + + rc2 = vdbePmaWriterFinish(&writer, &pOut->iEof); + if( rc==SQLITE_OK ) rc = rc2; + vdbeSorterPopulateDebug(pTask, "exit"); + return rc; +} + +#if SQLITE_MAX_WORKER_THREADS>0 +/* +** The main routine for background threads that populate aFile[1] of +** multi-threaded IncrMerger objects. +*/ +static void *vdbeIncrPopulateThread(void *pCtx){ + IncrMerger *pIncr = (IncrMerger*)pCtx; + void *pRet = SQLITE_INT_TO_PTR( vdbeIncrPopulate(pIncr) ); + pIncr->pTask->bDone = 1; + return pRet; +} + +/* +** Launch a background thread to populate aFile[1] of pIncr. +*/ +static int vdbeIncrBgPopulate(IncrMerger *pIncr){ + void *p = (void*)pIncr; + assert( pIncr->bUseThread ); + return vdbeSorterCreateThread(pIncr->pTask, vdbeIncrPopulateThread, p); +} +#endif + +/* +** This function is called when the PmaReader corresponding to pIncr has +** finished reading the contents of aFile[0]. Its purpose is to "refill" +** aFile[0] such that the PmaReader should start rereading it from the +** beginning. +** +** For single-threaded objects, this is accomplished by literally reading +** keys from pIncr->pMerger and repopulating aFile[0]. +** +** For multi-threaded objects, all that is required is to wait until the +** background thread is finished (if it is not already) and then swap +** aFile[0] and aFile[1] in place. If the contents of pMerger have not +** been exhausted, this function also launches a new background thread +** to populate the new aFile[1]. +** +** SQLITE_OK is returned on success, or an SQLite error code otherwise. +*/ +static int vdbeIncrSwap(IncrMerger *pIncr){ + int rc = SQLITE_OK; + +#if SQLITE_MAX_WORKER_THREADS>0 + if( pIncr->bUseThread ){ + rc = vdbeSorterJoinThread(pIncr->pTask); + + if( rc==SQLITE_OK ){ + SorterFile f0 = pIncr->aFile[0]; + pIncr->aFile[0] = pIncr->aFile[1]; + pIncr->aFile[1] = f0; + } + + if( rc==SQLITE_OK ){ + if( pIncr->aFile[0].iEof==pIncr->iStartOff ){ + pIncr->bEof = 1; + }else{ + rc = vdbeIncrBgPopulate(pIncr); + } + } + }else +#endif + { + rc = vdbeIncrPopulate(pIncr); + pIncr->aFile[0] = pIncr->aFile[1]; + if( pIncr->aFile[0].iEof==pIncr->iStartOff ){ + pIncr->bEof = 1; + } + } + + return rc; +} + +/* +** Allocate and return a new IncrMerger object to read data from pMerger. +** +** If an OOM condition is encountered, return NULL. In this case free the +** pMerger argument before returning. +*/ +static int vdbeIncrMergerNew( + SortSubtask *pTask, /* The thread that will be using the new IncrMerger */ + MergeEngine *pMerger, /* The MergeEngine that the IncrMerger will control */ + IncrMerger **ppOut /* Write the new IncrMerger here */ +){ + int rc = SQLITE_OK; + IncrMerger *pIncr = *ppOut = (IncrMerger*) + (sqlite3FaultSim(100) ? 0 : sqlite3MallocZero(sizeof(*pIncr))); + if( pIncr ){ + pIncr->pMerger = pMerger; + pIncr->pTask = pTask; + pIncr->mxSz = MAX(pTask->pSorter->mxKeysize+9,pTask->pSorter->mxPmaSize/2); + pTask->file2.iEof += pIncr->mxSz; + }else{ + vdbeMergeEngineFree(pMerger); + rc = SQLITE_NOMEM; + } + return rc; +} + +#if SQLITE_MAX_WORKER_THREADS>0 +/* +** Set the "use-threads" flag on object pIncr. +*/ +static void vdbeIncrMergerSetThreads(IncrMerger *pIncr){ + pIncr->bUseThread = 1; + pIncr->pTask->file2.iEof -= pIncr->mxSz; +} +#endif /* SQLITE_MAX_WORKER_THREADS>0 */ + + + +/* +** Recompute pMerger->aTree[iOut] by comparing the next keys on the +** two PmaReaders that feed that entry. Neither of the PmaReaders +** are advanced. This routine merely does the comparison. +*/ +static void vdbeMergeEngineCompare( + MergeEngine *pMerger, /* Merge engine containing PmaReaders to compare */ + int iOut /* Store the result in pMerger->aTree[iOut] */ +){ + int i1; + int i2; + int iRes; + PmaReader *p1; + PmaReader *p2; + + assert( iOutnTree && iOut>0 ); + + if( iOut>=(pMerger->nTree/2) ){ + i1 = (iOut - pMerger->nTree/2) * 2; + i2 = i1 + 1; + }else{ + i1 = pMerger->aTree[iOut*2]; + i2 = pMerger->aTree[iOut*2+1]; + } + + p1 = &pMerger->aReadr[i1]; + p2 = &pMerger->aReadr[i2]; + + if( p1->pFd==0 ){ + iRes = i2; + }else if( p2->pFd==0 ){ + iRes = i1; + }else{ + SortSubtask *pTask = pMerger->pTask; + int bCached = 0; + int res; + assert( pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */ + res = pTask->xCompare( + pTask, &bCached, p1->aKey, p1->nKey, p2->aKey, p2->nKey + ); + if( res<=0 ){ + iRes = i1; + }else{ + iRes = i2; + } + } + + pMerger->aTree[iOut] = iRes; +} + +/* +** Allowed values for the eMode parameter to vdbeMergeEngineInit() +** and vdbePmaReaderIncrMergeInit(). +** +** Only INCRINIT_NORMAL is valid in single-threaded builds (when +** SQLITE_MAX_WORKER_THREADS==0). The other values are only used +** when there exists one or more separate worker threads. +*/ +#define INCRINIT_NORMAL 0 +#define INCRINIT_TASK 1 +#define INCRINIT_ROOT 2 + +/* +** Forward reference required as the vdbeIncrMergeInit() and +** vdbePmaReaderIncrInit() routines are called mutually recursively when +** building a merge tree. +*/ +static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode); + +/* +** Initialize the MergeEngine object passed as the second argument. Once this +** function returns, the first key of merged data may be read from the +** MergeEngine object in the usual fashion. +** +** If argument eMode is INCRINIT_ROOT, then it is assumed that any IncrMerge +** objects attached to the PmaReader objects that the merger reads from have +** already been populated, but that they have not yet populated aFile[0] and +** set the PmaReader objects up to read from it. In this case all that is +** required is to call vdbePmaReaderNext() on each PmaReader to point it at +** its first key. +** +** Otherwise, if eMode is any value other than INCRINIT_ROOT, then use +** vdbePmaReaderIncrMergeInit() to initialize each PmaReader that feeds data +** to pMerger. +** +** SQLITE_OK is returned if successful, or an SQLite error code otherwise. +*/ +static int vdbeMergeEngineInit( + SortSubtask *pTask, /* Thread that will run pMerger */ + MergeEngine *pMerger, /* MergeEngine to initialize */ + int eMode /* One of the INCRINIT_XXX constants */ +){ + int rc = SQLITE_OK; /* Return code */ + int i; /* For looping over PmaReader objects */ + int nTree = pMerger->nTree; + + /* eMode is always INCRINIT_NORMAL in single-threaded mode */ + assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL ); + + /* Verify that the MergeEngine is assigned to a single thread */ + assert( pMerger->pTask==0 ); + pMerger->pTask = pTask; + + for(i=0; i0 && eMode==INCRINIT_ROOT ){ + /* PmaReaders should be normally initialized in order, as if they are + ** reading from the same temp file this makes for more linear file IO. + ** However, in the INCRINIT_ROOT case, if PmaReader aReadr[nTask-1] is + ** in use it will block the vdbePmaReaderNext() call while it uses + ** the main thread to fill its buffer. So calling PmaReaderNext() + ** on this PmaReader before any of the multi-threaded PmaReaders takes + ** better advantage of multi-processor hardware. */ + rc = vdbePmaReaderNext(&pMerger->aReadr[nTree-i-1]); + }else{ + rc = vdbePmaReaderIncrInit(&pMerger->aReadr[i], INCRINIT_NORMAL); + } + if( rc!=SQLITE_OK ) return rc; + } + + for(i=pMerger->nTree-1; i>0; i--){ + vdbeMergeEngineCompare(pMerger, i); + } + return pTask->pUnpacked->errCode; +} + +/* +** The PmaReader passed as the first argument is guaranteed to be an +** incremental-reader (pReadr->pIncr!=0). This function serves to open +** and/or initialize the temp file related fields of the IncrMerge +** object at (pReadr->pIncr). +** +** If argument eMode is set to INCRINIT_NORMAL, then all PmaReaders +** in the sub-tree headed by pReadr are also initialized. Data is then +** loaded into the buffers belonging to pReadr and it is set to point to +** the first key in its range. +** +** If argument eMode is set to INCRINIT_TASK, then pReadr is guaranteed +** to be a multi-threaded PmaReader and this function is being called in a +** background thread. In this case all PmaReaders in the sub-tree are +** initialized as for INCRINIT_NORMAL and the aFile[1] buffer belonging to +** pReadr is populated. However, pReadr itself is not set up to point +** to its first key. A call to vdbePmaReaderNext() is still required to do +** that. +** +** The reason this function does not call vdbePmaReaderNext() immediately +** in the INCRINIT_TASK case is that vdbePmaReaderNext() assumes that it has +** to block on thread (pTask->thread) before accessing aFile[1]. But, since +** this entire function is being run by thread (pTask->thread), that will +** lead to the current background thread attempting to join itself. +** +** Finally, if argument eMode is set to INCRINIT_ROOT, it may be assumed +** that pReadr->pIncr is a multi-threaded IncrMerge objects, and that all +** child-trees have already been initialized using IncrInit(INCRINIT_TASK). +** In this case vdbePmaReaderNext() is called on all child PmaReaders and +** the current PmaReader set to point to the first key in its range. +** +** SQLITE_OK is returned if successful, or an SQLite error code otherwise. +*/ +static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){ + int rc = SQLITE_OK; + IncrMerger *pIncr = pReadr->pIncr; + SortSubtask *pTask = pIncr->pTask; + sqlite3 *db = pTask->pSorter->db; + + /* eMode is always INCRINIT_NORMAL in single-threaded mode */ + assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL ); + + rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode); + + /* Set up the required files for pIncr. A multi-theaded IncrMerge object + ** requires two temp files to itself, whereas a single-threaded object + ** only requires a region of pTask->file2. */ + if( rc==SQLITE_OK ){ + int mxSz = pIncr->mxSz; +#if SQLITE_MAX_WORKER_THREADS>0 + if( pIncr->bUseThread ){ + rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd); + if( rc==SQLITE_OK ){ + rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd); + } + }else +#endif + /*if( !pIncr->bUseThread )*/{ + if( pTask->file2.pFd==0 ){ + assert( pTask->file2.iEof>0 ); + rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd); + pTask->file2.iEof = 0; + } + if( rc==SQLITE_OK ){ + pIncr->aFile[1].pFd = pTask->file2.pFd; + pIncr->iStartOff = pTask->file2.iEof; + pTask->file2.iEof += mxSz; + } + } + } + +#if SQLITE_MAX_WORKER_THREADS>0 + if( rc==SQLITE_OK && pIncr->bUseThread ){ + /* Use the current thread to populate aFile[1], even though this + ** PmaReader is multi-threaded. If this is an INCRINIT_TASK object, + ** then this function is already running in background thread + ** pIncr->pTask->thread. + ** + ** If this is the INCRINIT_ROOT object, then it is running in the + ** main VDBE thread. But that is Ok, as that thread cannot return + ** control to the VDBE or proceed with anything useful until the + ** first results are ready from this merger object anyway. + */ + assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK ); + rc = vdbeIncrPopulate(pIncr); + } +#endif + + if( rc==SQLITE_OK && (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK) ){ + rc = vdbePmaReaderNext(pReadr); + } + + return rc; +} + +#if SQLITE_MAX_WORKER_THREADS>0 +/* +** The main routine for vdbePmaReaderIncrMergeInit() operations run in +** background threads. +*/ +static void *vdbePmaReaderBgIncrInit(void *pCtx){ + PmaReader *pReader = (PmaReader*)pCtx; + void *pRet = SQLITE_INT_TO_PTR( + vdbePmaReaderIncrMergeInit(pReader,INCRINIT_TASK) + ); + pReader->pIncr->pTask->bDone = 1; + return pRet; +} +#endif + +/* +** If the PmaReader passed as the first argument is not an incremental-reader +** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it invokes +** the vdbePmaReaderIncrMergeInit() function with the parameters passed to +** this routine to initialize the incremental merge. +** +** If the IncrMerger object is multi-threaded (IncrMerger.bUseThread==1), +** then a background thread is launched to call vdbePmaReaderIncrMergeInit(). +** Or, if the IncrMerger is single threaded, the same function is called +** using the current thread. +*/ +static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode){ + IncrMerger *pIncr = pReadr->pIncr; /* Incremental merger */ + int rc = SQLITE_OK; /* Return code */ + if( pIncr ){ +#if SQLITE_MAX_WORKER_THREADS>0 + assert( pIncr->bUseThread==0 || eMode==INCRINIT_TASK ); + if( pIncr->bUseThread ){ + void *pCtx = (void*)pReadr; + rc = vdbeSorterCreateThread(pIncr->pTask, vdbePmaReaderBgIncrInit, pCtx); + }else +#endif + { + rc = vdbePmaReaderIncrMergeInit(pReadr, eMode); + } + } + return rc; +} + +/* +** Allocate a new MergeEngine object to merge the contents of nPMA level-0 +** PMAs from pTask->file. If no error occurs, set *ppOut to point to +** the new object and return SQLITE_OK. Or, if an error does occur, set *ppOut +** to NULL and return an SQLite error code. +** +** When this function is called, *piOffset is set to the offset of the +** first PMA to read from pTask->file. Assuming no error occurs, it is +** set to the offset immediately following the last byte of the last +** PMA before returning. If an error does occur, then the final value of +** *piOffset is undefined. +*/ +static int vdbeMergeEngineLevel0( + SortSubtask *pTask, /* Sorter task to read from */ + int nPMA, /* Number of PMAs to read */ + i64 *piOffset, /* IN/OUT: Readr offset in pTask->file */ + MergeEngine **ppOut /* OUT: New merge-engine */ +){ + MergeEngine *pNew; /* Merge engine to return */ + i64 iOff = *piOffset; + int i; + int rc = SQLITE_OK; + + *ppOut = pNew = vdbeMergeEngineNew(nPMA); + if( pNew==0 ) rc = SQLITE_NOMEM; + + for(i=0; iaReadr[i]; + rc = vdbePmaReaderInit(pTask, &pTask->file, iOff, pReadr, &nDummy); + iOff = pReadr->iEof; + } + + if( rc!=SQLITE_OK ){ + vdbeMergeEngineFree(pNew); + *ppOut = 0; + } + *piOffset = iOff; + return rc; +} + +/* +** Return the depth of a tree comprising nPMA PMAs, assuming a fanout of +** SORTER_MAX_MERGE_COUNT. The returned value does not include leaf nodes. +** +** i.e. +** +** nPMA<=16 -> TreeDepth() == 0 +** nPMA<=256 -> TreeDepth() == 1 +** nPMA<=65536 -> TreeDepth() == 2 +*/ +static int vdbeSorterTreeDepth(int nPMA){ + int nDepth = 0; + i64 nDiv = SORTER_MAX_MERGE_COUNT; + while( nDiv < (i64)nPMA ){ + nDiv = nDiv * SORTER_MAX_MERGE_COUNT; + nDepth++; + } + return nDepth; +} + +/* +** pRoot is the root of an incremental merge-tree with depth nDepth (according +** to vdbeSorterTreeDepth()). pLeaf is the iSeq'th leaf to be added to the +** tree, counting from zero. This function adds pLeaf to the tree. +** +** If successful, SQLITE_OK is returned. If an error occurs, an SQLite error +** code is returned and pLeaf is freed. +*/ +static int vdbeSorterAddToTree( + SortSubtask *pTask, /* Task context */ + int nDepth, /* Depth of tree according to TreeDepth() */ + int iSeq, /* Sequence number of leaf within tree */ + MergeEngine *pRoot, /* Root of tree */ + MergeEngine *pLeaf /* Leaf to add to tree */ +){ + int rc = SQLITE_OK; + int nDiv = 1; + int i; + MergeEngine *p = pRoot; + IncrMerger *pIncr; + + rc = vdbeIncrMergerNew(pTask, pLeaf, &pIncr); + + for(i=1; iaReadr[iIter]; + + if( pReadr->pIncr==0 ){ + MergeEngine *pNew = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT); + if( pNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = vdbeIncrMergerNew(pTask, pNew, &pReadr->pIncr); + } + } + if( rc==SQLITE_OK ){ + p = pReadr->pIncr->pMerger; + nDiv = nDiv / SORTER_MAX_MERGE_COUNT; + } + } + + if( rc==SQLITE_OK ){ + p->aReadr[iSeq % SORTER_MAX_MERGE_COUNT].pIncr = pIncr; + }else{ + vdbeIncrFree(pIncr); + } + return rc; +} + +/* +** This function is called as part of a SorterRewind() operation on a sorter +** that has already written two or more level-0 PMAs to one or more temp +** files. It builds a tree of MergeEngine/IncrMerger/PmaReader objects that +** can be used to incrementally merge all PMAs on disk. +** +** If successful, SQLITE_OK is returned and *ppOut set to point to the +** MergeEngine object at the root of the tree before returning. Or, if an +** error occurs, an SQLite error code is returned and the final value +** of *ppOut is undefined. +*/ +static int vdbeSorterMergeTreeBuild( + VdbeSorter *pSorter, /* The VDBE cursor that implements the sort */ + MergeEngine **ppOut /* Write the MergeEngine here */ +){ + MergeEngine *pMain = 0; + int rc = SQLITE_OK; + int iTask; + +#if SQLITE_MAX_WORKER_THREADS>0 + /* If the sorter uses more than one task, then create the top-level + ** MergeEngine here. This MergeEngine will read data from exactly + ** one PmaReader per sub-task. */ + assert( pSorter->bUseThreads || pSorter->nTask==1 ); + if( pSorter->nTask>1 ){ + pMain = vdbeMergeEngineNew(pSorter->nTask); + if( pMain==0 ) rc = SQLITE_NOMEM; + } +#endif + + for(iTask=0; rc==SQLITE_OK && iTasknTask; iTask++){ + SortSubtask *pTask = &pSorter->aTask[iTask]; + assert( pTask->nPMA>0 || SQLITE_MAX_WORKER_THREADS>0 ); + if( SQLITE_MAX_WORKER_THREADS==0 || pTask->nPMA ){ + MergeEngine *pRoot = 0; /* Root node of tree for this task */ + int nDepth = vdbeSorterTreeDepth(pTask->nPMA); + i64 iReadOff = 0; + + if( pTask->nPMA<=SORTER_MAX_MERGE_COUNT ){ + rc = vdbeMergeEngineLevel0(pTask, pTask->nPMA, &iReadOff, &pRoot); + }else{ + int i; + int iSeq = 0; + pRoot = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT); + if( pRoot==0 ) rc = SQLITE_NOMEM; + for(i=0; inPMA && rc==SQLITE_OK; i += SORTER_MAX_MERGE_COUNT){ + MergeEngine *pMerger = 0; /* New level-0 PMA merger */ + int nReader; /* Number of level-0 PMAs to merge */ + + nReader = MIN(pTask->nPMA - i, SORTER_MAX_MERGE_COUNT); + rc = vdbeMergeEngineLevel0(pTask, nReader, &iReadOff, &pMerger); + if( rc==SQLITE_OK ){ + rc = vdbeSorterAddToTree(pTask, nDepth, iSeq++, pRoot, pMerger); + } + } + } + + if( rc==SQLITE_OK ){ +#if SQLITE_MAX_WORKER_THREADS>0 + if( pMain!=0 ){ + rc = vdbeIncrMergerNew(pTask, pRoot, &pMain->aReadr[iTask].pIncr); + }else +#endif + { + assert( pMain==0 ); + pMain = pRoot; + } + }else{ + vdbeMergeEngineFree(pRoot); + } + } + } + + if( rc!=SQLITE_OK ){ + vdbeMergeEngineFree(pMain); + pMain = 0; + } + *ppOut = pMain; + return rc; +} + +/* +** This function is called as part of an sqlite3VdbeSorterRewind() operation +** on a sorter that has written two or more PMAs to temporary files. It sets +** up either VdbeSorter.pMerger (for single threaded sorters) or pReader +** (for multi-threaded sorters) so that it can be used to iterate through +** all records stored in the sorter. +** +** SQLITE_OK is returned if successful, or an SQLite error code otherwise. +*/ +static int vdbeSorterSetupMerge(VdbeSorter *pSorter){ + int rc; /* Return code */ + SortSubtask *pTask0 = &pSorter->aTask[0]; + MergeEngine *pMain = 0; +#if SQLITE_MAX_WORKER_THREADS + sqlite3 *db = pTask0->pSorter->db; + int i; + SorterCompare xCompare = vdbeSorterGetCompare(pSorter); + for(i=0; inTask; i++){ + pSorter->aTask[i].xCompare = xCompare; + } +#endif + + rc = vdbeSorterMergeTreeBuild(pSorter, &pMain); + if( rc==SQLITE_OK ){ +#if SQLITE_MAX_WORKER_THREADS + assert( pSorter->bUseThreads==0 || pSorter->nTask>1 ); + if( pSorter->bUseThreads ){ + int iTask; + PmaReader *pReadr = 0; + SortSubtask *pLast = &pSorter->aTask[pSorter->nTask-1]; + rc = vdbeSortAllocUnpacked(pLast); + if( rc==SQLITE_OK ){ + pReadr = (PmaReader*)sqlite3DbMallocZero(db, sizeof(PmaReader)); + pSorter->pReader = pReadr; + if( pReadr==0 ) rc = SQLITE_NOMEM; + } + if( rc==SQLITE_OK ){ + rc = vdbeIncrMergerNew(pLast, pMain, &pReadr->pIncr); + if( rc==SQLITE_OK ){ + vdbeIncrMergerSetThreads(pReadr->pIncr); + for(iTask=0; iTask<(pSorter->nTask-1); iTask++){ + IncrMerger *pIncr; + if( (pIncr = pMain->aReadr[iTask].pIncr) ){ + vdbeIncrMergerSetThreads(pIncr); + assert( pIncr->pTask!=pLast ); + } + } + for(iTask=0; rc==SQLITE_OK && iTasknTask; iTask++){ + /* Check that: + ** + ** a) The incremental merge object is configured to use the + ** right task, and + ** b) If it is using task (nTask-1), it is configured to run + ** in single-threaded mode. This is important, as the + ** root merge (INCRINIT_ROOT) will be using the same task + ** object. + */ + PmaReader *p = &pMain->aReadr[iTask]; + assert( p->pIncr==0 || ( + (p->pIncr->pTask==&pSorter->aTask[iTask]) /* a */ + && (iTask!=pSorter->nTask-1 || p->pIncr->bUseThread==0) /* b */ + )); + rc = vdbePmaReaderIncrInit(p, INCRINIT_TASK); + } + } + pMain = 0; + } + if( rc==SQLITE_OK ){ + rc = vdbePmaReaderIncrMergeInit(pReadr, INCRINIT_ROOT); + } + }else +#endif + { + rc = vdbeMergeEngineInit(pTask0, pMain, INCRINIT_NORMAL); + pSorter->pMerger = pMain; + pMain = 0; + } + } + + if( rc!=SQLITE_OK ){ + vdbeMergeEngineFree(pMain); + } + return rc; +} + + +/* +** Once the sorter has been populated by calls to sqlite3VdbeSorterWrite, +** this function is called to prepare for iterating through the records +** in sorted order. +*/ +SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *pCsr, int *pbEof){ + VdbeSorter *pSorter = pCsr->pSorter; + int rc = SQLITE_OK; /* Return code */ + + assert( pSorter ); + + /* If no data has been written to disk, then do not do so now. Instead, + ** sort the VdbeSorter.pRecord list. The vdbe layer will read data directly + ** from the in-memory list. */ + if( pSorter->bUsePMA==0 ){ + if( pSorter->list.pList ){ + *pbEof = 0; + rc = vdbeSorterSort(&pSorter->aTask[0], &pSorter->list); + }else{ + *pbEof = 1; + } + return rc; + } + + /* Write the current in-memory list to a PMA. When the VdbeSorterWrite() + ** function flushes the contents of memory to disk, it immediately always + ** creates a new list consisting of a single key immediately afterwards. + ** So the list is never empty at this point. */ + assert( pSorter->list.pList ); + rc = vdbeSorterFlushPMA(pSorter); + + /* Join all threads */ + rc = vdbeSorterJoinAll(pSorter, rc); + + vdbeSorterRewindDebug("rewind"); + + /* Assuming no errors have occurred, set up a merger structure to + ** incrementally read and merge all remaining PMAs. */ + assert( pSorter->pReader==0 ); + if( rc==SQLITE_OK ){ + rc = vdbeSorterSetupMerge(pSorter); + *pbEof = 0; + } + + vdbeSorterRewindDebug("rewinddone"); + return rc; +} + +/* +** Advance to the next element in the sorter. +*/ +SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ + VdbeSorter *pSorter = pCsr->pSorter; + int rc; /* Return code */ + + assert( pSorter->bUsePMA || (pSorter->pReader==0 && pSorter->pMerger==0) ); + if( pSorter->bUsePMA ){ + assert( pSorter->pReader==0 || pSorter->pMerger==0 ); + assert( pSorter->bUseThreads==0 || pSorter->pReader ); + assert( pSorter->bUseThreads==1 || pSorter->pMerger ); +#if SQLITE_MAX_WORKER_THREADS>0 + if( pSorter->bUseThreads ){ + rc = vdbePmaReaderNext(pSorter->pReader); + *pbEof = (pSorter->pReader->pFd==0); + }else +#endif + /*if( !pSorter->bUseThreads )*/ { + assert( pSorter->pMerger!=0 ); + assert( pSorter->pMerger->pTask==(&pSorter->aTask[0]) ); + rc = vdbeMergeEngineStep(pSorter->pMerger, pbEof); + } + }else{ + SorterRecord *pFree = pSorter->list.pList; + pSorter->list.pList = pFree->u.pNext; + pFree->u.pNext = 0; + if( pSorter->list.aMemory==0 ) vdbeSorterRecordFree(db, pFree); + *pbEof = !pSorter->list.pList; + rc = SQLITE_OK; + } + return rc; +} + +/* +** Return a pointer to a buffer owned by the sorter that contains the +** current key. +*/ +static void *vdbeSorterRowkey( + const VdbeSorter *pSorter, /* Sorter object */ + int *pnKey /* OUT: Size of current key in bytes */ +){ + void *pKey; + if( pSorter->bUsePMA ){ + PmaReader *pReader; +#if SQLITE_MAX_WORKER_THREADS>0 + if( pSorter->bUseThreads ){ + pReader = pSorter->pReader; + }else +#endif + /*if( !pSorter->bUseThreads )*/{ + pReader = &pSorter->pMerger->aReadr[pSorter->pMerger->aTree[1]]; + } + *pnKey = pReader->nKey; + pKey = pReader->aKey; + }else{ + *pnKey = pSorter->list.pList->nVal; + pKey = SRVAL(pSorter->list.pList); + } + return pKey; +} + +/* +** Copy the current sorter key into the memory cell pOut. +*/ +SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){ + VdbeSorter *pSorter = pCsr->pSorter; + void *pKey; int nKey; /* Sorter key to copy into pOut */ + + pKey = vdbeSorterRowkey(pSorter, &nKey); + if( sqlite3VdbeMemClearAndResize(pOut, nKey) ){ + return SQLITE_NOMEM; + } + pOut->n = nKey; + MemSetTypeFlag(pOut, MEM_Blob); + memcpy(pOut->z, pKey, nKey); + + return SQLITE_OK; +} + +/* +** Compare the key in memory cell pVal with the key that the sorter cursor +** passed as the first argument currently points to. For the purposes of +** the comparison, ignore the rowid field at the end of each record. +** +** If the sorter cursor key contains any NULL values, consider it to be +** less than pVal. Even if pVal also contains NULL values. +** +** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM). +** Otherwise, set *pRes to a negative, zero or positive value if the +** key in pVal is smaller than, equal to or larger than the current sorter +** key. +** +** This routine forms the core of the OP_SorterCompare opcode, which in +** turn is used to verify uniqueness when constructing a UNIQUE INDEX. +*/ +SQLITE_PRIVATE int sqlite3VdbeSorterCompare( + const VdbeCursor *pCsr, /* Sorter cursor */ + Mem *pVal, /* Value to compare to current sorter key */ + int nKeyCol, /* Compare this many columns */ + int *pRes /* OUT: Result of comparison */ +){ + VdbeSorter *pSorter = pCsr->pSorter; + UnpackedRecord *r2 = pSorter->pUnpacked; + KeyInfo *pKeyInfo = pCsr->pKeyInfo; + int i; + void *pKey; int nKey; /* Sorter key to compare pVal with */ + + if( r2==0 ){ + char *p; + r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo,0,0,&p); + assert( pSorter->pUnpacked==(UnpackedRecord*)p ); + if( r2==0 ) return SQLITE_NOMEM; + r2->nField = nKeyCol; + } + assert( r2->nField==nKeyCol ); + + pKey = vdbeSorterRowkey(pSorter, &nKey); + sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, r2); + for(i=0; iaMem[i].flags & MEM_Null ){ + *pRes = -1; + return SQLITE_OK; + } + } + + *pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2); + return SQLITE_OK; +} + +/************** End of vdbesort.c ********************************************/ +/************** Begin file journal.c *****************************************/ +/* +** 2007 August 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file implements a special kind of sqlite3_file object used +** by SQLite to create journal files if the atomic-write optimization +** is enabled. +** +** The distinctive characteristic of this sqlite3_file is that the +** actual on disk file is created lazily. When the file is created, +** the caller specifies a buffer size for an in-memory buffer to +** be used to service read() and write() requests. The actual file +** on disk is not created or populated until either: +** +** 1) The in-memory representation grows too large for the allocated +** buffer, or +** 2) The sqlite3JournalCreate() function is called. +*/ +#ifdef SQLITE_ENABLE_ATOMIC_WRITE +/* #include "sqliteInt.h" */ + + +/* +** A JournalFile object is a subclass of sqlite3_file used by +** as an open file handle for journal files. +*/ +struct JournalFile { + sqlite3_io_methods *pMethod; /* I/O methods on journal files */ + int nBuf; /* Size of zBuf[] in bytes */ + char *zBuf; /* Space to buffer journal writes */ + int iSize; /* Amount of zBuf[] currently used */ + int flags; /* xOpen flags */ + sqlite3_vfs *pVfs; /* The "real" underlying VFS */ + sqlite3_file *pReal; /* The "real" underlying file descriptor */ + const char *zJournal; /* Name of the journal file */ +}; +typedef struct JournalFile JournalFile; + +/* +** If it does not already exists, create and populate the on-disk file +** for JournalFile p. +*/ +static int createFile(JournalFile *p){ + int rc = SQLITE_OK; + if( !p->pReal ){ + sqlite3_file *pReal = (sqlite3_file *)&p[1]; + rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0); + if( rc==SQLITE_OK ){ + p->pReal = pReal; + if( p->iSize>0 ){ + assert(p->iSize<=p->nBuf); + rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); + } + if( rc!=SQLITE_OK ){ + /* If an error occurred while writing to the file, close it before + ** returning. This way, SQLite uses the in-memory journal data to + ** roll back changes made to the internal page-cache before this + ** function was called. */ + sqlite3OsClose(pReal); + p->pReal = 0; + } + } + } + return rc; +} + +/* +** Close the file. +*/ +static int jrnlClose(sqlite3_file *pJfd){ + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + sqlite3OsClose(p->pReal); + } + sqlite3_free(p->zBuf); + return SQLITE_OK; +} + +/* +** Read data from the file. +*/ +static int jrnlRead( + sqlite3_file *pJfd, /* The journal file from which to read */ + void *zBuf, /* Put the results here */ + int iAmt, /* Number of bytes to read */ + sqlite_int64 iOfst /* Begin reading at this offset */ +){ + int rc = SQLITE_OK; + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); + }else if( (iAmt+iOfst)>p->iSize ){ + rc = SQLITE_IOERR_SHORT_READ; + }else{ + memcpy(zBuf, &p->zBuf[iOfst], iAmt); + } + return rc; +} + +/* +** Write data to the file. +*/ +static int jrnlWrite( + sqlite3_file *pJfd, /* The journal file into which to write */ + const void *zBuf, /* Take data to be written from here */ + int iAmt, /* Number of bytes to write */ + sqlite_int64 iOfst /* Begin writing at this offset into the file */ +){ + int rc = SQLITE_OK; + JournalFile *p = (JournalFile *)pJfd; + if( !p->pReal && (iOfst+iAmt)>p->nBuf ){ + rc = createFile(p); + } + if( rc==SQLITE_OK ){ + if( p->pReal ){ + rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); + }else{ + memcpy(&p->zBuf[iOfst], zBuf, iAmt); + if( p->iSize<(iOfst+iAmt) ){ + p->iSize = (iOfst+iAmt); + } + } + } + return rc; +} + +/* +** Truncate the file. +*/ +static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ + int rc = SQLITE_OK; + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + rc = sqlite3OsTruncate(p->pReal, size); + }else if( sizeiSize ){ + p->iSize = size; + } + return rc; +} + +/* +** Sync the file. +*/ +static int jrnlSync(sqlite3_file *pJfd, int flags){ + int rc; + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + rc = sqlite3OsSync(p->pReal, flags); + }else{ + rc = SQLITE_OK; + } + return rc; +} + +/* +** Query the size of the file in bytes. +*/ +static int jrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){ + int rc = SQLITE_OK; + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + rc = sqlite3OsFileSize(p->pReal, pSize); + }else{ + *pSize = (sqlite_int64) p->iSize; + } + return rc; +} + +/* +** Table of methods for JournalFile sqlite3_file object. +*/ +static struct sqlite3_io_methods JournalFileMethods = { + 1, /* iVersion */ + jrnlClose, /* xClose */ + jrnlRead, /* xRead */ + jrnlWrite, /* xWrite */ + jrnlTruncate, /* xTruncate */ + jrnlSync, /* xSync */ + jrnlFileSize, /* xFileSize */ + 0, /* xLock */ + 0, /* xUnlock */ + 0, /* xCheckReservedLock */ + 0, /* xFileControl */ + 0, /* xSectorSize */ + 0, /* xDeviceCharacteristics */ + 0, /* xShmMap */ + 0, /* xShmLock */ + 0, /* xShmBarrier */ + 0 /* xShmUnmap */ +}; + +/* +** Open a journal file. +*/ +SQLITE_PRIVATE int sqlite3JournalOpen( + sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */ + const char *zName, /* Name of the journal file */ + sqlite3_file *pJfd, /* Preallocated, blank file handle */ + int flags, /* Opening flags */ + int nBuf /* Bytes buffered before opening the file */ +){ + JournalFile *p = (JournalFile *)pJfd; + memset(p, 0, sqlite3JournalSize(pVfs)); + if( nBuf>0 ){ + p->zBuf = sqlite3MallocZero(nBuf); + if( !p->zBuf ){ + return SQLITE_NOMEM; + } + }else{ + return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); + } + p->pMethod = &JournalFileMethods; + p->nBuf = nBuf; + p->flags = flags; + p->zJournal = zName; + p->pVfs = pVfs; + return SQLITE_OK; +} + +/* +** If the argument p points to a JournalFile structure, and the underlying +** file has not yet been created, create it now. +*/ +SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){ + if( p->pMethods!=&JournalFileMethods ){ + return SQLITE_OK; + } + return createFile((JournalFile *)p); +} + +/* +** The file-handle passed as the only argument is guaranteed to be an open +** file. It may or may not be of class JournalFile. If the file is a +** JournalFile, and the underlying file on disk has not yet been opened, +** return 0. Otherwise, return 1. +*/ +SQLITE_PRIVATE int sqlite3JournalExists(sqlite3_file *p){ + return (p->pMethods!=&JournalFileMethods || ((JournalFile *)p)->pReal!=0); +} + +/* +** Return the number of bytes required to store a JournalFile that uses vfs +** pVfs to create the underlying on-disk files. +*/ +SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){ + return (pVfs->szOsFile+sizeof(JournalFile)); +} +#endif + +/************** End of journal.c *********************************************/ +/************** Begin file memjournal.c **************************************/ +/* +** 2008 October 7 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains code use to implement an in-memory rollback journal. +** The in-memory rollback journal is used to journal transactions for +** ":memory:" databases and when the journal_mode=MEMORY pragma is used. +*/ +/* #include "sqliteInt.h" */ + +/* Forward references to internal structures */ +typedef struct MemJournal MemJournal; +typedef struct FilePoint FilePoint; +typedef struct FileChunk FileChunk; + +/* Space to hold the rollback journal is allocated in increments of +** this many bytes. +** +** The size chosen is a little less than a power of two. That way, +** the FileChunk object will have a size that almost exactly fills +** a power-of-two allocation. This minimizes wasted space in power-of-two +** memory allocators. +*/ +#define JOURNAL_CHUNKSIZE ((int)(1024-sizeof(FileChunk*))) + +/* +** The rollback journal is composed of a linked list of these structures. +*/ +struct FileChunk { + FileChunk *pNext; /* Next chunk in the journal */ + u8 zChunk[JOURNAL_CHUNKSIZE]; /* Content of this chunk */ +}; + +/* +** An instance of this object serves as a cursor into the rollback journal. +** The cursor can be either for reading or writing. +*/ +struct FilePoint { + sqlite3_int64 iOffset; /* Offset from the beginning of the file */ + FileChunk *pChunk; /* Specific chunk into which cursor points */ +}; + +/* +** This subclass is a subclass of sqlite3_file. Each open memory-journal +** is an instance of this class. +*/ +struct MemJournal { + sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */ + FileChunk *pFirst; /* Head of in-memory chunk-list */ + FilePoint endpoint; /* Pointer to the end of the file */ + FilePoint readpoint; /* Pointer to the end of the last xRead() */ +}; + +/* +** Read data from the in-memory journal file. This is the implementation +** of the sqlite3_vfs.xRead method. +*/ +static int memjrnlRead( + sqlite3_file *pJfd, /* The journal file from which to read */ + void *zBuf, /* Put the results here */ + int iAmt, /* Number of bytes to read */ + sqlite_int64 iOfst /* Begin reading at this offset */ +){ + MemJournal *p = (MemJournal *)pJfd; + u8 *zOut = zBuf; + int nRead = iAmt; + int iChunkOffset; + FileChunk *pChunk; + + /* SQLite never tries to read past the end of a rollback journal file */ + assert( iOfst+iAmt<=p->endpoint.iOffset ); + + if( p->readpoint.iOffset!=iOfst || iOfst==0 ){ + sqlite3_int64 iOff = 0; + for(pChunk=p->pFirst; + ALWAYS(pChunk) && (iOff+JOURNAL_CHUNKSIZE)<=iOfst; + pChunk=pChunk->pNext + ){ + iOff += JOURNAL_CHUNKSIZE; + } + }else{ + pChunk = p->readpoint.pChunk; + } + + iChunkOffset = (int)(iOfst%JOURNAL_CHUNKSIZE); + do { + int iSpace = JOURNAL_CHUNKSIZE - iChunkOffset; + int nCopy = MIN(nRead, (JOURNAL_CHUNKSIZE - iChunkOffset)); + memcpy(zOut, &pChunk->zChunk[iChunkOffset], nCopy); + zOut += nCopy; + nRead -= iSpace; + iChunkOffset = 0; + } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 ); + p->readpoint.iOffset = iOfst+iAmt; + p->readpoint.pChunk = pChunk; + + return SQLITE_OK; +} + +/* +** Write data to the file. +*/ +static int memjrnlWrite( + sqlite3_file *pJfd, /* The journal file into which to write */ + const void *zBuf, /* Take data to be written from here */ + int iAmt, /* Number of bytes to write */ + sqlite_int64 iOfst /* Begin writing at this offset into the file */ +){ + MemJournal *p = (MemJournal *)pJfd; + int nWrite = iAmt; + u8 *zWrite = (u8 *)zBuf; + + /* An in-memory journal file should only ever be appended to. Random + ** access writes are not required by sqlite. + */ + assert( iOfst==p->endpoint.iOffset ); + UNUSED_PARAMETER(iOfst); + + while( nWrite>0 ){ + FileChunk *pChunk = p->endpoint.pChunk; + int iChunkOffset = (int)(p->endpoint.iOffset%JOURNAL_CHUNKSIZE); + int iSpace = MIN(nWrite, JOURNAL_CHUNKSIZE - iChunkOffset); + + if( iChunkOffset==0 ){ + /* New chunk is required to extend the file. */ + FileChunk *pNew = sqlite3_malloc(sizeof(FileChunk)); + if( !pNew ){ + return SQLITE_IOERR_NOMEM; + } + pNew->pNext = 0; + if( pChunk ){ + assert( p->pFirst ); + pChunk->pNext = pNew; + }else{ + assert( !p->pFirst ); + p->pFirst = pNew; + } + p->endpoint.pChunk = pNew; + } + + memcpy(&p->endpoint.pChunk->zChunk[iChunkOffset], zWrite, iSpace); + zWrite += iSpace; + nWrite -= iSpace; + p->endpoint.iOffset += iSpace; + } + + return SQLITE_OK; +} + +/* +** Truncate the file. +*/ +static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ + MemJournal *p = (MemJournal *)pJfd; + FileChunk *pChunk; + assert(size==0); + UNUSED_PARAMETER(size); + pChunk = p->pFirst; + while( pChunk ){ + FileChunk *pTmp = pChunk; + pChunk = pChunk->pNext; + sqlite3_free(pTmp); + } + sqlite3MemJournalOpen(pJfd); + return SQLITE_OK; +} + +/* +** Close the file. +*/ +static int memjrnlClose(sqlite3_file *pJfd){ + memjrnlTruncate(pJfd, 0); + return SQLITE_OK; +} + + +/* +** Sync the file. +** +** Syncing an in-memory journal is a no-op. And, in fact, this routine +** is never called in a working implementation. This implementation +** exists purely as a contingency, in case some malfunction in some other +** part of SQLite causes Sync to be called by mistake. +*/ +static int memjrnlSync(sqlite3_file *NotUsed, int NotUsed2){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); + return SQLITE_OK; +} + +/* +** Query the size of the file in bytes. +*/ +static int memjrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){ + MemJournal *p = (MemJournal *)pJfd; + *pSize = (sqlite_int64) p->endpoint.iOffset; + return SQLITE_OK; +} + +/* +** Table of methods for MemJournal sqlite3_file object. +*/ +static const struct sqlite3_io_methods MemJournalMethods = { + 1, /* iVersion */ + memjrnlClose, /* xClose */ + memjrnlRead, /* xRead */ + memjrnlWrite, /* xWrite */ + memjrnlTruncate, /* xTruncate */ + memjrnlSync, /* xSync */ + memjrnlFileSize, /* xFileSize */ + 0, /* xLock */ + 0, /* xUnlock */ + 0, /* xCheckReservedLock */ + 0, /* xFileControl */ + 0, /* xSectorSize */ + 0, /* xDeviceCharacteristics */ + 0, /* xShmMap */ + 0, /* xShmLock */ + 0, /* xShmBarrier */ + 0, /* xShmUnmap */ + 0, /* xFetch */ + 0 /* xUnfetch */ +}; + +/* +** Open a journal file. +*/ +SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){ + MemJournal *p = (MemJournal *)pJfd; + assert( EIGHT_BYTE_ALIGNMENT(p) ); + memset(p, 0, sqlite3MemJournalSize()); + p->pMethod = (sqlite3_io_methods*)&MemJournalMethods; +} + +/* +** Return true if the file-handle passed as an argument is +** an in-memory journal +*/ +SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *pJfd){ + return pJfd->pMethods==&MemJournalMethods; +} + +/* +** Return the number of bytes required to store a MemJournal file descriptor. +*/ +SQLITE_PRIVATE int sqlite3MemJournalSize(void){ + return sizeof(MemJournal); +} + +/************** End of memjournal.c ******************************************/ +/************** Begin file walker.c ******************************************/ +/* +** 2008 August 16 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains routines used for walking the parser tree for +** an SQL statement. +*/ +/* #include "sqliteInt.h" */ +/* #include */ +/* #include */ + + +/* +** Walk an expression tree. Invoke the callback once for each node +** of the expression, while descending. (In other words, the callback +** is invoked before visiting children.) +** +** The return value from the callback should be one of the WRC_* +** constants to specify how to proceed with the walk. +** +** WRC_Continue Continue descending down the tree. +** +** WRC_Prune Do not descend into child nodes. But allow +** the walk to continue with sibling nodes. +** +** WRC_Abort Do no more callbacks. Unwind the stack and +** return the top-level walk call. +** +** The return value from this routine is WRC_Abort to abandon the tree walk +** and WRC_Continue to continue. +*/ +SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){ + int rc; + if( pExpr==0 ) return WRC_Continue; + testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); + testcase( ExprHasProperty(pExpr, EP_Reduced) ); + rc = pWalker->xExprCallback(pWalker, pExpr); + if( rc==WRC_Continue + && !ExprHasProperty(pExpr,EP_TokenOnly) ){ + if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; + if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; + }else{ + if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; + } + } + return rc & WRC_Abort; +} + +/* +** Call sqlite3WalkExpr() for every expression in list p or until +** an abort request is seen. +*/ +SQLITE_PRIVATE int sqlite3WalkExprList(Walker *pWalker, ExprList *p){ + int i; + struct ExprList_item *pItem; + if( p ){ + for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){ + if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort; + } + } + return WRC_Continue; +} + +/* +** Walk all expressions associated with SELECT statement p. Do +** not invoke the SELECT callback on p, but do (of course) invoke +** any expr callbacks and SELECT callbacks that come from subqueries. +** Return WRC_Abort or WRC_Continue. +*/ +SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){ + if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort; + if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort; + if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort; + if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort; + if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort; + if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort; + if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort; + return WRC_Continue; +} + +/* +** Walk the parse trees associated with all subqueries in the +** FROM clause of SELECT statement p. Do not invoke the select +** callback on p, but do invoke it on each FROM clause subquery +** and on any subqueries further down in the tree. Return +** WRC_Abort or WRC_Continue; +*/ +SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){ + SrcList *pSrc; + int i; + struct SrcList_item *pItem; + + pSrc = p->pSrc; + if( ALWAYS(pSrc) ){ + for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ + if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){ + return WRC_Abort; + } + } + } + return WRC_Continue; +} + +/* +** Call sqlite3WalkExpr() for every expression in Select statement p. +** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and +** on the compound select chain, p->pPrior. +** +** If it is not NULL, the xSelectCallback() callback is invoked before +** the walk of the expressions and FROM clause. The xSelectCallback2() +** method, if it is not NULL, is invoked following the walk of the +** expressions and FROM clause. +** +** Return WRC_Continue under normal conditions. Return WRC_Abort if +** there is an abort request. +** +** If the Walker does not have an xSelectCallback() then this routine +** is a no-op returning WRC_Continue. +*/ +SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){ + int rc; + if( p==0 || (pWalker->xSelectCallback==0 && pWalker->xSelectCallback2==0) ){ + return WRC_Continue; + } + rc = WRC_Continue; + pWalker->walkerDepth++; + while( p ){ + if( pWalker->xSelectCallback ){ + rc = pWalker->xSelectCallback(pWalker, p); + if( rc ) break; + } + if( sqlite3WalkSelectExpr(pWalker, p) + || sqlite3WalkSelectFrom(pWalker, p) + ){ + pWalker->walkerDepth--; + return WRC_Abort; + } + if( pWalker->xSelectCallback2 ){ + pWalker->xSelectCallback2(pWalker, p); + } + p = p->pPrior; + } + pWalker->walkerDepth--; + return rc & WRC_Abort; +} + +/************** End of walker.c **********************************************/ +/************** Begin file resolve.c *****************************************/ +/* +** 2008 August 18 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains routines used for walking the parser tree and +** resolve all identifiers by associating them with a particular +** table and column. +*/ +/* #include "sqliteInt.h" */ +/* #include */ +/* #include */ + +/* +** Walk the expression tree pExpr and increase the aggregate function +** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node. +** This needs to occur when copying a TK_AGG_FUNCTION node from an +** outer query into an inner subquery. +** +** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..) +** is a helper function - a callback for the tree walker. +*/ +static int incrAggDepth(Walker *pWalker, Expr *pExpr){ + if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n; + return WRC_Continue; +} +static void incrAggFunctionDepth(Expr *pExpr, int N){ + if( N>0 ){ + Walker w; + memset(&w, 0, sizeof(w)); + w.xExprCallback = incrAggDepth; + w.u.n = N; + sqlite3WalkExpr(&w, pExpr); + } +} + +/* +** Turn the pExpr expression into an alias for the iCol-th column of the +** result set in pEList. +** +** If the result set column is a simple column reference, then this routine +** makes an exact copy. But for any other kind of expression, this +** routine make a copy of the result set column as the argument to the +** TK_AS operator. The TK_AS operator causes the expression to be +** evaluated just once and then reused for each alias. +** +** The reason for suppressing the TK_AS term when the expression is a simple +** column reference is so that the column reference will be recognized as +** usable by indices within the WHERE clause processing logic. +** +** The TK_AS operator is inhibited if zType[0]=='G'. This means +** that in a GROUP BY clause, the expression is evaluated twice. Hence: +** +** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x +** +** Is equivalent to: +** +** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 +** +** The result of random()%5 in the GROUP BY clause is probably different +** from the result in the result-set. On the other hand Standard SQL does +** not allow the GROUP BY clause to contain references to result-set columns. +** So this should never come up in well-formed queries. +** +** If the reference is followed by a COLLATE operator, then make sure +** the COLLATE operator is preserved. For example: +** +** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase; +** +** Should be transformed into: +** +** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase; +** +** The nSubquery parameter specifies how many levels of subquery the +** alias is removed from the original expression. The usual value is +** zero but it might be more if the alias is contained within a subquery +** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION +** structures must be increased by the nSubquery amount. +*/ +static void resolveAlias( + Parse *pParse, /* Parsing context */ + ExprList *pEList, /* A result set */ + int iCol, /* A column in the result set. 0..pEList->nExpr-1 */ + Expr *pExpr, /* Transform this into an alias to the result set */ + const char *zType, /* "GROUP" or "ORDER" or "" */ + int nSubquery /* Number of subqueries that the label is moving */ +){ + Expr *pOrig; /* The iCol-th column of the result set */ + Expr *pDup; /* Copy of pOrig */ + sqlite3 *db; /* The database connection */ + + assert( iCol>=0 && iColnExpr ); + pOrig = pEList->a[iCol].pExpr; + assert( pOrig!=0 ); + db = pParse->db; + pDup = sqlite3ExprDup(db, pOrig, 0); + if( pDup==0 ) return; + if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){ + incrAggFunctionDepth(pDup, nSubquery); + pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0); + if( pDup==0 ) return; + ExprSetProperty(pDup, EP_Skip); + if( pEList->a[iCol].u.x.iAlias==0 ){ + pEList->a[iCol].u.x.iAlias = (u16)(++pParse->nAlias); + } + pDup->iTable = pEList->a[iCol].u.x.iAlias; + } + if( pExpr->op==TK_COLLATE ){ + pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); + } + + /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This + ** prevents ExprDelete() from deleting the Expr structure itself, + ** allowing it to be repopulated by the memcpy() on the following line. + ** The pExpr->u.zToken might point into memory that will be freed by the + ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to + ** make a copy of the token before doing the sqlite3DbFree(). + */ + ExprSetProperty(pExpr, EP_Static); + sqlite3ExprDelete(db, pExpr); + memcpy(pExpr, pDup, sizeof(*pExpr)); + if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ + assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); + pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); + pExpr->flags |= EP_MemToken; + } + sqlite3DbFree(db, pDup); +} + + +/* +** Return TRUE if the name zCol occurs anywhere in the USING clause. +** +** Return FALSE if the USING clause is NULL or if it does not contain +** zCol. +*/ +static int nameInUsingClause(IdList *pUsing, const char *zCol){ + if( pUsing ){ + int k; + for(k=0; knId; k++){ + if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1; + } + } + return 0; +} + +/* +** Subqueries stores the original database, table and column names for their +** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN". +** Check to see if the zSpan given to this routine matches the zDb, zTab, +** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will +** match anything. +*/ +SQLITE_PRIVATE int sqlite3MatchSpanName( + const char *zSpan, + const char *zCol, + const char *zTab, + const char *zDb +){ + int n; + for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} + if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){ + return 0; + } + zSpan += n+1; + for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} + if( zTab && (sqlite3StrNICmp(zSpan, zTab, n)!=0 || zTab[n]!=0) ){ + return 0; + } + zSpan += n+1; + if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){ + return 0; + } + return 1; +} + +/* +** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up +** that name in the set of source tables in pSrcList and make the pExpr +** expression node refer back to that source column. The following changes +** are made to pExpr: +** +** pExpr->iDb Set the index in db->aDb[] of the database X +** (even if X is implied). +** pExpr->iTable Set to the cursor number for the table obtained +** from pSrcList. +** pExpr->pTab Points to the Table structure of X.Y (even if +** X and/or Y are implied.) +** pExpr->iColumn Set to the column number within the table. +** pExpr->op Set to TK_COLUMN. +** pExpr->pLeft Any expression this points to is deleted +** pExpr->pRight Any expression this points to is deleted. +** +** The zDb variable is the name of the database (the "X"). This value may be +** NULL meaning that name is of the form Y.Z or Z. Any available database +** can be used. The zTable variable is the name of the table (the "Y"). This +** value can be NULL if zDb is also NULL. If zTable is NULL it +** means that the form of the name is Z and that columns from any table +** can be used. +** +** If the name cannot be resolved unambiguously, leave an error message +** in pParse and return WRC_Abort. Return WRC_Prune on success. +*/ +static int lookupName( + Parse *pParse, /* The parsing context */ + const char *zDb, /* Name of the database containing table, or NULL */ + const char *zTab, /* Name of table containing column, or NULL */ + const char *zCol, /* Name of the column. */ + NameContext *pNC, /* The name context used to resolve the name */ + Expr *pExpr /* Make this EXPR node point to the selected column */ +){ + int i, j; /* Loop counters */ + int cnt = 0; /* Number of matching column names */ + int cntTab = 0; /* Number of matching table names */ + int nSubquery = 0; /* How many levels of subquery */ + sqlite3 *db = pParse->db; /* The database connection */ + struct SrcList_item *pItem; /* Use for looping over pSrcList items */ + struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ + NameContext *pTopNC = pNC; /* First namecontext in the list */ + Schema *pSchema = 0; /* Schema of the expression */ + int isTrigger = 0; /* True if resolved to a trigger column */ + Table *pTab = 0; /* Table hold the row */ + Column *pCol; /* A column of pTab */ + + assert( pNC ); /* the name context cannot be NULL. */ + assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ + assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); + + /* Initialize the node to no-match */ + pExpr->iTable = -1; + pExpr->pTab = 0; + ExprSetVVAProperty(pExpr, EP_NoReduce); + + /* Translate the schema name in zDb into a pointer to the corresponding + ** schema. If not found, pSchema will remain NULL and nothing will match + ** resulting in an appropriate error message toward the end of this routine + */ + if( zDb ){ + testcase( pNC->ncFlags & NC_PartIdx ); + testcase( pNC->ncFlags & NC_IsCheck ); + if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){ + /* Silently ignore database qualifiers inside CHECK constraints and + ** partial indices. Do not raise errors because that might break + ** legacy and because it does not hurt anything to just ignore the + ** database name. */ + zDb = 0; + }else{ + for(i=0; inDb; i++){ + assert( db->aDb[i].zName ); + if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){ + pSchema = db->aDb[i].pSchema; + break; + } + } + } + } + + /* Start at the inner-most context and move outward until a match is found */ + while( pNC && cnt==0 ){ + ExprList *pEList; + SrcList *pSrcList = pNC->pSrcList; + + if( pSrcList ){ + for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){ + pTab = pItem->pTab; + assert( pTab!=0 && pTab->zName!=0 ); + assert( pTab->nCol>0 ); + if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ + int hit = 0; + pEList = pItem->pSelect->pEList; + for(j=0; jnExpr; j++){ + if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){ + cnt++; + cntTab = 2; + pMatch = pItem; + pExpr->iColumn = j; + hit = 1; + } + } + if( hit || zTab==0 ) continue; + } + if( zDb && pTab->pSchema!=pSchema ){ + continue; + } + if( zTab ){ + const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; + assert( zTabName!=0 ); + if( sqlite3StrICmp(zTabName, zTab)!=0 ){ + continue; + } + } + if( 0==(cntTab++) ){ + pMatch = pItem; + } + for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){ + if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + /* If there has been exactly one prior match and this match + ** is for the right-hand table of a NATURAL JOIN or is in a + ** USING clause, then skip this match. + */ + if( cnt==1 ){ + if( pItem->jointype & JT_NATURAL ) continue; + if( nameInUsingClause(pItem->pUsing, zCol) ) continue; + } + cnt++; + pMatch = pItem; + /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ + pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; + break; + } + } + } + if( pMatch ){ + pExpr->iTable = pMatch->iCursor; + pExpr->pTab = pMatch->pTab; + /* RIGHT JOIN not (yet) supported */ + assert( (pMatch->jointype & JT_RIGHT)==0 ); + if( (pMatch->jointype & JT_LEFT)!=0 ){ + ExprSetProperty(pExpr, EP_CanBeNull); + } + pSchema = pExpr->pTab->pSchema; + } + } /* if( pSrcList ) */ + +#ifndef SQLITE_OMIT_TRIGGER + /* If we have not already resolved the name, then maybe + ** it is a new.* or old.* trigger argument reference + */ + if( zDb==0 && zTab!=0 && cntTab==0 && pParse->pTriggerTab!=0 ){ + int op = pParse->eTriggerOp; + assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); + if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){ + pExpr->iTable = 1; + pTab = pParse->pTriggerTab; + }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){ + pExpr->iTable = 0; + pTab = pParse->pTriggerTab; + }else{ + pTab = 0; + } + + if( pTab ){ + int iCol; + pSchema = pTab->pSchema; + cntTab++; + for(iCol=0, pCol=pTab->aCol; iColnCol; iCol++, pCol++){ + if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + if( iCol==pTab->iPKey ){ + iCol = -1; + } + break; + } + } + if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){ + /* IMP: R-51414-32910 */ + /* IMP: R-44911-55124 */ + iCol = -1; + } + if( iColnCol ){ + cnt++; + if( iCol<0 ){ + pExpr->affinity = SQLITE_AFF_INTEGER; + }else if( pExpr->iTable==0 ){ + testcase( iCol==31 ); + testcase( iCol==32 ); + pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<iColumn = (i16)iCol; + pExpr->pTab = pTab; + isTrigger = 1; + } + } + } +#endif /* !defined(SQLITE_OMIT_TRIGGER) */ + + /* + ** Perhaps the name is a reference to the ROWID + */ + if( cnt==0 && cntTab==1 && pMatch && sqlite3IsRowid(zCol) + && VisibleRowid(pMatch->pTab) ){ + cnt = 1; + pExpr->iColumn = -1; /* IMP: R-44911-55124 */ + pExpr->affinity = SQLITE_AFF_INTEGER; + } + + /* + ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z + ** might refer to an result-set alias. This happens, for example, when + ** we are resolving names in the WHERE clause of the following command: + ** + ** SELECT a+b AS x FROM table WHERE x<10; + ** + ** In cases like this, replace pExpr with a copy of the expression that + ** forms the result set entry ("a+b" in the example) and return immediately. + ** Note that the expression in the result set should have already been + ** resolved by the time the WHERE clause is resolved. + ** + ** The ability to use an output result-set column in the WHERE, GROUP BY, + ** or HAVING clauses, or as part of a larger expression in the ORDRE BY + ** clause is not standard SQL. This is a (goofy) SQLite extension, that + ** is supported for backwards compatibility only. TO DO: Issue a warning + ** on sqlite3_log() whenever the capability is used. + */ + if( (pEList = pNC->pEList)!=0 + && zTab==0 + && cnt==0 + ){ + for(j=0; jnExpr; j++){ + char *zAs = pEList->a[j].zName; + if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ + Expr *pOrig; + assert( pExpr->pLeft==0 && pExpr->pRight==0 ); + assert( pExpr->x.pList==0 ); + assert( pExpr->x.pSelect==0 ); + pOrig = pEList->a[j].pExpr; + if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){ + sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); + return WRC_Abort; + } + resolveAlias(pParse, pEList, j, pExpr, "", nSubquery); + cnt = 1; + pMatch = 0; + assert( zTab==0 && zDb==0 ); + goto lookupname_end; + } + } + } + + /* Advance to the next name context. The loop will exit when either + ** we have a match (cnt>0) or when we run out of name contexts. + */ + if( cnt==0 ){ + pNC = pNC->pNext; + nSubquery++; + } + } + + /* + ** If X and Y are NULL (in other words if only the column name Z is + ** supplied) and the value of Z is enclosed in double-quotes, then + ** Z is a string literal if it doesn't match any column names. In that + ** case, we need to return right away and not make any changes to + ** pExpr. + ** + ** Because no reference was made to outer contexts, the pNC->nRef + ** fields are not changed in any context. + */ + if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){ + pExpr->op = TK_STRING; + pExpr->pTab = 0; + return WRC_Prune; + } + + /* + ** cnt==0 means there was not match. cnt>1 means there were two or + ** more matches. Either way, we have an error. + */ + if( cnt!=1 ){ + const char *zErr; + zErr = cnt==0 ? "no such column" : "ambiguous column name"; + if( zDb ){ + sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol); + }else if( zTab ){ + sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol); + }else{ + sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol); + } + pParse->checkSchema = 1; + pTopNC->nErr++; + } + + /* If a column from a table in pSrcList is referenced, then record + ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes + ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the + ** column number is greater than the number of bits in the bitmask + ** then set the high-order bit of the bitmask. + */ + if( pExpr->iColumn>=0 && pMatch!=0 ){ + int n = pExpr->iColumn; + testcase( n==BMS-1 ); + if( n>=BMS ){ + n = BMS-1; + } + assert( pMatch->iCursor==pExpr->iTable ); + pMatch->colUsed |= ((Bitmask)1)<pLeft); + pExpr->pLeft = 0; + sqlite3ExprDelete(db, pExpr->pRight); + pExpr->pRight = 0; + pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN); +lookupname_end: + if( cnt==1 ){ + assert( pNC!=0 ); + if( pExpr->op!=TK_AS ){ + sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); + } + /* Increment the nRef value on all name contexts from TopNC up to + ** the point where the name matched. */ + for(;;){ + assert( pTopNC!=0 ); + pTopNC->nRef++; + if( pTopNC==pNC ) break; + pTopNC = pTopNC->pNext; + } + return WRC_Prune; + } else { + return WRC_Abort; + } +} + +/* +** Allocate and return a pointer to an expression to load the column iCol +** from datasource iSrc in SrcList pSrc. +*/ +SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){ + Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0); + if( p ){ + struct SrcList_item *pItem = &pSrc->a[iSrc]; + p->pTab = pItem->pTab; + p->iTable = pItem->iCursor; + if( p->pTab->iPKey==iCol ){ + p->iColumn = -1; + }else{ + p->iColumn = (ynVar)iCol; + testcase( iCol==BMS ); + testcase( iCol==BMS-1 ); + pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol); + } + ExprSetProperty(p, EP_Resolved); + } + return p; +} + +/* +** Report an error that an expression is not valid for a partial index WHERE +** clause. +*/ +static void notValidPartIdxWhere( + Parse *pParse, /* Leave error message here */ + NameContext *pNC, /* The name context */ + const char *zMsg /* Type of error */ +){ + if( (pNC->ncFlags & NC_PartIdx)!=0 ){ + sqlite3ErrorMsg(pParse, "%s prohibited in partial index WHERE clauses", + zMsg); + } +} + +#ifndef SQLITE_OMIT_CHECK +/* +** Report an error that an expression is not valid for a CHECK constraint. +*/ +static void notValidCheckConstraint( + Parse *pParse, /* Leave error message here */ + NameContext *pNC, /* The name context */ + const char *zMsg /* Type of error */ +){ + if( (pNC->ncFlags & NC_IsCheck)!=0 ){ + sqlite3ErrorMsg(pParse,"%s prohibited in CHECK constraints", zMsg); + } +} +#else +# define notValidCheckConstraint(P,N,M) +#endif + +/* +** Expression p should encode a floating point value between 1.0 and 0.0. +** Return 1024 times this value. Or return -1 if p is not a floating point +** value between 1.0 and 0.0. +*/ +static int exprProbability(Expr *p){ + double r = -1.0; + if( p->op!=TK_FLOAT ) return -1; + sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8); + assert( r>=0.0 ); + if( r>1.0 ) return -1; + return (int)(r*134217728.0); +} + +/* +** This routine is callback for sqlite3WalkExpr(). +** +** Resolve symbolic names into TK_COLUMN operators for the current +** node in the expression tree. Return 0 to continue the search down +** the tree or 2 to abort the tree walk. +** +** This routine also does error checking and name resolution for +** function names. The operator for aggregate functions is changed +** to TK_AGG_FUNCTION. +*/ +static int resolveExprStep(Walker *pWalker, Expr *pExpr){ + NameContext *pNC; + Parse *pParse; + + pNC = pWalker->u.pNC; + assert( pNC!=0 ); + pParse = pNC->pParse; + assert( pParse==pWalker->pParse ); + + if( ExprHasProperty(pExpr, EP_Resolved) ) return WRC_Prune; + ExprSetProperty(pExpr, EP_Resolved); +#ifndef NDEBUG + if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){ + SrcList *pSrcList = pNC->pSrcList; + int i; + for(i=0; ipSrcList->nSrc; i++){ + assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursornTab); + } + } +#endif + switch( pExpr->op ){ + +#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) + /* The special operator TK_ROW means use the rowid for the first + ** column in the FROM clause. This is used by the LIMIT and ORDER BY + ** clause processing on UPDATE and DELETE statements. + */ + case TK_ROW: { + SrcList *pSrcList = pNC->pSrcList; + struct SrcList_item *pItem; + assert( pSrcList && pSrcList->nSrc==1 ); + pItem = pSrcList->a; + pExpr->op = TK_COLUMN; + pExpr->pTab = pItem->pTab; + pExpr->iTable = pItem->iCursor; + pExpr->iColumn = -1; + pExpr->affinity = SQLITE_AFF_INTEGER; + break; + } +#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) + && !defined(SQLITE_OMIT_SUBQUERY) */ + + /* A lone identifier is the name of a column. + */ + case TK_ID: { + return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr); + } + + /* A table name and column name: ID.ID + ** Or a database, table and column: ID.ID.ID + */ + case TK_DOT: { + const char *zColumn; + const char *zTable; + const char *zDb; + Expr *pRight; + + /* if( pSrcList==0 ) break; */ + pRight = pExpr->pRight; + if( pRight->op==TK_ID ){ + zDb = 0; + zTable = pExpr->pLeft->u.zToken; + zColumn = pRight->u.zToken; + }else{ + assert( pRight->op==TK_DOT ); + zDb = pExpr->pLeft->u.zToken; + zTable = pRight->pLeft->u.zToken; + zColumn = pRight->pRight->u.zToken; + } + return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); + } + + /* Resolve function names + */ + case TK_FUNCTION: { + ExprList *pList = pExpr->x.pList; /* The argument list */ + int n = pList ? pList->nExpr : 0; /* Number of arguments */ + int no_such_func = 0; /* True if no such function exists */ + int wrong_num_args = 0; /* True if wrong number of arguments */ + int is_agg = 0; /* True if is an aggregate function */ + int auth; /* Authorization to use the function */ + int nId; /* Number of characters in function name */ + const char *zId; /* The function name. */ + FuncDef *pDef; /* Information about the function */ + u8 enc = ENC(pParse->db); /* The database encoding */ + + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + notValidPartIdxWhere(pParse, pNC, "functions"); + zId = pExpr->u.zToken; + nId = sqlite3Strlen30(zId); + pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); + if( pDef==0 ){ + pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); + if( pDef==0 ){ + no_such_func = 1; + }else{ + wrong_num_args = 1; + } + }else{ + is_agg = pDef->xFunc==0; + if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ + ExprSetProperty(pExpr, EP_Unlikely|EP_Skip); + if( n==2 ){ + pExpr->iTable = exprProbability(pList->a[1].pExpr); + if( pExpr->iTable<0 ){ + sqlite3ErrorMsg(pParse, + "second argument to likelihood() must be a " + "constant between 0.0 and 1.0"); + pNC->nErr++; + } + }else{ + /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is + ** equivalent to likelihood(X, 0.0625). + ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is + ** short-hand for likelihood(X,0.0625). + ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand + ** for likelihood(X,0.9375). + ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent + ** to likelihood(X,0.9375). */ + /* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */ + pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120; + } + } +#ifndef SQLITE_OMIT_AUTHORIZATION + auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); + if( auth!=SQLITE_OK ){ + if( auth==SQLITE_DENY ){ + sqlite3ErrorMsg(pParse, "not authorized to use function: %s", + pDef->zName); + pNC->nErr++; + } + pExpr->op = TK_NULL; + return WRC_Prune; + } +#endif + if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ){ + ExprSetProperty(pExpr,EP_ConstFunc); + } + } + if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ + sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); + pNC->nErr++; + is_agg = 0; + }else if( no_such_func && pParse->db->init.busy==0 ){ + sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); + pNC->nErr++; + }else if( wrong_num_args ){ + sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", + nId, zId); + pNC->nErr++; + } + if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg; + sqlite3WalkExprList(pWalker, pList); + if( is_agg ){ + NameContext *pNC2 = pNC; + pExpr->op = TK_AGG_FUNCTION; + pExpr->op2 = 0; + while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){ + pExpr->op2++; + pNC2 = pNC2->pNext; + } + assert( pDef!=0 ); + if( pNC2 ){ + assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); + testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); + pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX); + + } + pNC->ncFlags |= NC_AllowAgg; + } + /* FIX ME: Compute pExpr->affinity based on the expected return + ** type of the function + */ + return WRC_Prune; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_SELECT: + case TK_EXISTS: testcase( pExpr->op==TK_EXISTS ); +#endif + case TK_IN: { + testcase( pExpr->op==TK_IN ); + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + int nRef = pNC->nRef; + notValidCheckConstraint(pParse, pNC, "subqueries"); + notValidPartIdxWhere(pParse, pNC, "subqueries"); + sqlite3WalkSelect(pWalker, pExpr->x.pSelect); + assert( pNC->nRef>=nRef ); + if( nRef!=pNC->nRef ){ + ExprSetProperty(pExpr, EP_VarSelect); + } + } + break; + } + case TK_VARIABLE: { + notValidCheckConstraint(pParse, pNC, "parameters"); + notValidPartIdxWhere(pParse, pNC, "parameters"); + break; + } + } + return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue; +} + +/* +** pEList is a list of expressions which are really the result set of the +** a SELECT statement. pE is a term in an ORDER BY or GROUP BY clause. +** This routine checks to see if pE is a simple identifier which corresponds +** to the AS-name of one of the terms of the expression list. If it is, +** this routine return an integer between 1 and N where N is the number of +** elements in pEList, corresponding to the matching entry. If there is +** no match, or if pE is not a simple identifier, then this routine +** return 0. +** +** pEList has been resolved. pE has not. +*/ +static int resolveAsName( + Parse *pParse, /* Parsing context for error messages */ + ExprList *pEList, /* List of expressions to scan */ + Expr *pE /* Expression we are trying to match */ +){ + int i; /* Loop counter */ + + UNUSED_PARAMETER(pParse); + + if( pE->op==TK_ID ){ + char *zCol = pE->u.zToken; + for(i=0; inExpr; i++){ + char *zAs = pEList->a[i].zName; + if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ + return i+1; + } + } + } + return 0; +} + +/* +** pE is a pointer to an expression which is a single term in the +** ORDER BY of a compound SELECT. The expression has not been +** name resolved. +** +** At the point this routine is called, we already know that the +** ORDER BY term is not an integer index into the result set. That +** case is handled by the calling routine. +** +** Attempt to match pE against result set columns in the left-most +** SELECT statement. Return the index i of the matching column, +** as an indication to the caller that it should sort by the i-th column. +** The left-most column is 1. In other words, the value returned is the +** same integer value that would be used in the SQL statement to indicate +** the column. +** +** If there is no match, return 0. Return -1 if an error occurs. +*/ +static int resolveOrderByTermToExprList( + Parse *pParse, /* Parsing context for error messages */ + Select *pSelect, /* The SELECT statement with the ORDER BY clause */ + Expr *pE /* The specific ORDER BY term */ +){ + int i; /* Loop counter */ + ExprList *pEList; /* The columns of the result set */ + NameContext nc; /* Name context for resolving pE */ + sqlite3 *db; /* Database connection */ + int rc; /* Return code from subprocedures */ + u8 savedSuppErr; /* Saved value of db->suppressErr */ + + assert( sqlite3ExprIsInteger(pE, &i)==0 ); + pEList = pSelect->pEList; + + /* Resolve all names in the ORDER BY term expression + */ + memset(&nc, 0, sizeof(nc)); + nc.pParse = pParse; + nc.pSrcList = pSelect->pSrc; + nc.pEList = pEList; + nc.ncFlags = NC_AllowAgg; + nc.nErr = 0; + db = pParse->db; + savedSuppErr = db->suppressErr; + db->suppressErr = 1; + rc = sqlite3ResolveExprNames(&nc, pE); + db->suppressErr = savedSuppErr; + if( rc ) return 0; + + /* Try to match the ORDER BY expression against an expression + ** in the result set. Return an 1-based index of the matching + ** result-set entry. + */ + for(i=0; inExpr; i++){ + if( sqlite3ExprCompare(pEList->a[i].pExpr, pE, -1)<2 ){ + return i+1; + } + } + + /* If no match, return 0. */ + return 0; +} + +/* +** Generate an ORDER BY or GROUP BY term out-of-range error. +*/ +static void resolveOutOfRangeError( + Parse *pParse, /* The error context into which to write the error */ + const char *zType, /* "ORDER" or "GROUP" */ + int i, /* The index (1-based) of the term out of range */ + int mx /* Largest permissible value of i */ +){ + sqlite3ErrorMsg(pParse, + "%r %s BY term out of range - should be " + "between 1 and %d", i, zType, mx); +} + +/* +** Analyze the ORDER BY clause in a compound SELECT statement. Modify +** each term of the ORDER BY clause is a constant integer between 1 +** and N where N is the number of columns in the compound SELECT. +** +** ORDER BY terms that are already an integer between 1 and N are +** unmodified. ORDER BY terms that are integers outside the range of +** 1 through N generate an error. ORDER BY terms that are expressions +** are matched against result set expressions of compound SELECT +** beginning with the left-most SELECT and working toward the right. +** At the first match, the ORDER BY expression is transformed into +** the integer column number. +** +** Return the number of errors seen. +*/ +static int resolveCompoundOrderBy( + Parse *pParse, /* Parsing context. Leave error messages here */ + Select *pSelect /* The SELECT statement containing the ORDER BY */ +){ + int i; + ExprList *pOrderBy; + ExprList *pEList; + sqlite3 *db; + int moreToDo = 1; + + pOrderBy = pSelect->pOrderBy; + if( pOrderBy==0 ) return 0; + db = pParse->db; +#if SQLITE_MAX_COLUMN + if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ + sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause"); + return 1; + } +#endif + for(i=0; inExpr; i++){ + pOrderBy->a[i].done = 0; + } + pSelect->pNext = 0; + while( pSelect->pPrior ){ + pSelect->pPrior->pNext = pSelect; + pSelect = pSelect->pPrior; + } + while( pSelect && moreToDo ){ + struct ExprList_item *pItem; + moreToDo = 0; + pEList = pSelect->pEList; + assert( pEList!=0 ); + for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ + int iCol = -1; + Expr *pE, *pDup; + if( pItem->done ) continue; + pE = sqlite3ExprSkipCollate(pItem->pExpr); + if( sqlite3ExprIsInteger(pE, &iCol) ){ + if( iCol<=0 || iCol>pEList->nExpr ){ + resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); + return 1; + } + }else{ + iCol = resolveAsName(pParse, pEList, pE); + if( iCol==0 ){ + pDup = sqlite3ExprDup(db, pE, 0); + if( !db->mallocFailed ){ + assert(pDup); + iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup); + } + sqlite3ExprDelete(db, pDup); + } + } + if( iCol>0 ){ + /* Convert the ORDER BY term into an integer column number iCol, + ** taking care to preserve the COLLATE clause if it exists */ + Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); + if( pNew==0 ) return 1; + pNew->flags |= EP_IntValue; + pNew->u.iValue = iCol; + if( pItem->pExpr==pE ){ + pItem->pExpr = pNew; + }else{ + Expr *pParent = pItem->pExpr; + assert( pParent->op==TK_COLLATE ); + while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft; + assert( pParent->pLeft==pE ); + pParent->pLeft = pNew; + } + sqlite3ExprDelete(db, pE); + pItem->u.x.iOrderByCol = (u16)iCol; + pItem->done = 1; + }else{ + moreToDo = 1; + } + } + pSelect = pSelect->pNext; + } + for(i=0; inExpr; i++){ + if( pOrderBy->a[i].done==0 ){ + sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any " + "column in the result set", i+1); + return 1; + } + } + return 0; +} + +/* +** Check every term in the ORDER BY or GROUP BY clause pOrderBy of +** the SELECT statement pSelect. If any term is reference to a +** result set expression (as determined by the ExprList.a.u.x.iOrderByCol +** field) then convert that term into a copy of the corresponding result set +** column. +** +** If any errors are detected, add an error message to pParse and +** return non-zero. Return zero if no errors are seen. +*/ +SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy( + Parse *pParse, /* Parsing context. Leave error messages here */ + Select *pSelect, /* The SELECT statement containing the clause */ + ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */ + const char *zType /* "ORDER" or "GROUP" */ +){ + int i; + sqlite3 *db = pParse->db; + ExprList *pEList; + struct ExprList_item *pItem; + + if( pOrderBy==0 || pParse->db->mallocFailed ) return 0; +#if SQLITE_MAX_COLUMN + if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ + sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType); + return 1; + } +#endif + pEList = pSelect->pEList; + assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */ + for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ + if( pItem->u.x.iOrderByCol ){ + if( pItem->u.x.iOrderByCol>pEList->nExpr ){ + resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr); + return 1; + } + resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, + zType,0); + } + } + return 0; +} + +/* +** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect. +** The Name context of the SELECT statement is pNC. zType is either +** "ORDER" or "GROUP" depending on which type of clause pOrderBy is. +** +** This routine resolves each term of the clause into an expression. +** If the order-by term is an integer I between 1 and N (where N is the +** number of columns in the result set of the SELECT) then the expression +** in the resolution is a copy of the I-th result-set expression. If +** the order-by term is an identifier that corresponds to the AS-name of +** a result-set expression, then the term resolves to a copy of the +** result-set expression. Otherwise, the expression is resolved in +** the usual way - using sqlite3ResolveExprNames(). +** +** This routine returns the number of errors. If errors occur, then +** an appropriate error message might be left in pParse. (OOM errors +** excepted.) +*/ +static int resolveOrderGroupBy( + NameContext *pNC, /* The name context of the SELECT statement */ + Select *pSelect, /* The SELECT statement holding pOrderBy */ + ExprList *pOrderBy, /* An ORDER BY or GROUP BY clause to resolve */ + const char *zType /* Either "ORDER" or "GROUP", as appropriate */ +){ + int i, j; /* Loop counters */ + int iCol; /* Column number */ + struct ExprList_item *pItem; /* A term of the ORDER BY clause */ + Parse *pParse; /* Parsing context */ + int nResult; /* Number of terms in the result set */ + + if( pOrderBy==0 ) return 0; + nResult = pSelect->pEList->nExpr; + pParse = pNC->pParse; + for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ + Expr *pE = pItem->pExpr; + Expr *pE2 = sqlite3ExprSkipCollate(pE); + if( zType[0]!='G' ){ + iCol = resolveAsName(pParse, pSelect->pEList, pE2); + if( iCol>0 ){ + /* If an AS-name match is found, mark this ORDER BY column as being + ** a copy of the iCol-th result-set column. The subsequent call to + ** sqlite3ResolveOrderGroupBy() will convert the expression to a + ** copy of the iCol-th result-set expression. */ + pItem->u.x.iOrderByCol = (u16)iCol; + continue; + } + } + if( sqlite3ExprIsInteger(pE2, &iCol) ){ + /* The ORDER BY term is an integer constant. Again, set the column + ** number so that sqlite3ResolveOrderGroupBy() will convert the + ** order-by term to a copy of the result-set expression */ + if( iCol<1 || iCol>0xffff ){ + resolveOutOfRangeError(pParse, zType, i+1, nResult); + return 1; + } + pItem->u.x.iOrderByCol = (u16)iCol; + continue; + } + + /* Otherwise, treat the ORDER BY term as an ordinary expression */ + pItem->u.x.iOrderByCol = 0; + if( sqlite3ResolveExprNames(pNC, pE) ){ + return 1; + } + for(j=0; jpEList->nExpr; j++){ + if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ + pItem->u.x.iOrderByCol = j+1; + } + } + } + return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType); +} + +/* +** Resolve names in the SELECT statement p and all of its descendants. +*/ +static int resolveSelectStep(Walker *pWalker, Select *p){ + NameContext *pOuterNC; /* Context that contains this SELECT */ + NameContext sNC; /* Name context of this SELECT */ + int isCompound; /* True if p is a compound select */ + int nCompound; /* Number of compound terms processed so far */ + Parse *pParse; /* Parsing context */ + ExprList *pEList; /* Result set expression list */ + int i; /* Loop counter */ + ExprList *pGroupBy; /* The GROUP BY clause */ + Select *pLeftmost; /* Left-most of SELECT of a compound */ + sqlite3 *db; /* Database connection */ + + + assert( p!=0 ); + if( p->selFlags & SF_Resolved ){ + return WRC_Prune; + } + pOuterNC = pWalker->u.pNC; + pParse = pWalker->pParse; + db = pParse->db; + + /* Normally sqlite3SelectExpand() will be called first and will have + ** already expanded this SELECT. However, if this is a subquery within + ** an expression, sqlite3ResolveExprNames() will be called without a + ** prior call to sqlite3SelectExpand(). When that happens, let + ** sqlite3SelectPrep() do all of the processing for this SELECT. + ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and + ** this routine in the correct order. + */ + if( (p->selFlags & SF_Expanded)==0 ){ + sqlite3SelectPrep(pParse, p, pOuterNC); + return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune; + } + + isCompound = p->pPrior!=0; + nCompound = 0; + pLeftmost = p; + while( p ){ + assert( (p->selFlags & SF_Expanded)!=0 ); + assert( (p->selFlags & SF_Resolved)==0 ); + p->selFlags |= SF_Resolved; + + /* Resolve the expressions in the LIMIT and OFFSET clauses. These + ** are not allowed to refer to any names, so pass an empty NameContext. + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + if( sqlite3ResolveExprNames(&sNC, p->pLimit) || + sqlite3ResolveExprNames(&sNC, p->pOffset) ){ + return WRC_Abort; + } + + /* If the SF_Converted flags is set, then this Select object was + ** was created by the convertCompoundSelectToSubquery() function. + ** In this case the ORDER BY clause (p->pOrderBy) should be resolved + ** as if it were part of the sub-query, not the parent. This block + ** moves the pOrderBy down to the sub-query. It will be moved back + ** after the names have been resolved. */ + if( p->selFlags & SF_Converted ){ + Select *pSub = p->pSrc->a[0].pSelect; + assert( p->pSrc->nSrc==1 && p->pOrderBy ); + assert( pSub->pPrior && pSub->pOrderBy==0 ); + pSub->pOrderBy = p->pOrderBy; + p->pOrderBy = 0; + } + + /* Recursively resolve names in all subqueries + */ + for(i=0; ipSrc->nSrc; i++){ + struct SrcList_item *pItem = &p->pSrc->a[i]; + if( pItem->pSelect ){ + NameContext *pNC; /* Used to iterate name contexts */ + int nRef = 0; /* Refcount for pOuterNC and outer contexts */ + const char *zSavedContext = pParse->zAuthContext; + + /* Count the total number of references to pOuterNC and all of its + ** parent contexts. After resolving references to expressions in + ** pItem->pSelect, check if this value has changed. If so, then + ** SELECT statement pItem->pSelect must be correlated. Set the + ** pItem->isCorrelated flag if this is the case. */ + for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef; + + if( pItem->zName ) pParse->zAuthContext = pItem->zName; + sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC); + pParse->zAuthContext = zSavedContext; + if( pParse->nErr || db->mallocFailed ) return WRC_Abort; + + for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; + assert( pItem->isCorrelated==0 && nRef<=0 ); + pItem->isCorrelated = (nRef!=0); + } + } + + /* Set up the local name-context to pass to sqlite3ResolveExprNames() to + ** resolve the result-set expression list. + */ + sNC.ncFlags = NC_AllowAgg; + sNC.pSrcList = p->pSrc; + sNC.pNext = pOuterNC; + + /* Resolve names in the result set. */ + pEList = p->pEList; + assert( pEList!=0 ); + for(i=0; inExpr; i++){ + Expr *pX = pEList->a[i].pExpr; + if( sqlite3ResolveExprNames(&sNC, pX) ){ + return WRC_Abort; + } + } + + /* If there are no aggregate functions in the result-set, and no GROUP BY + ** expression, do not allow aggregates in any of the other expressions. + */ + assert( (p->selFlags & SF_Aggregate)==0 ); + pGroupBy = p->pGroupBy; + if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){ + assert( NC_MinMaxAgg==SF_MinMaxAgg ); + p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg); + }else{ + sNC.ncFlags &= ~NC_AllowAgg; + } + + /* If a HAVING clause is present, then there must be a GROUP BY clause. + */ + if( p->pHaving && !pGroupBy ){ + sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); + return WRC_Abort; + } + + /* Add the output column list to the name-context before parsing the + ** other expressions in the SELECT statement. This is so that + ** expressions in the WHERE clause (etc.) can refer to expressions by + ** aliases in the result set. + ** + ** Minor point: If this is the case, then the expression will be + ** re-evaluated for each reference to it. + */ + sNC.pEList = p->pEList; + if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; + if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort; + + /* The ORDER BY and GROUP BY clauses may not refer to terms in + ** outer queries + */ + sNC.pNext = 0; + sNC.ncFlags |= NC_AllowAgg; + + /* If this is a converted compound query, move the ORDER BY clause from + ** the sub-query back to the parent query. At this point each term + ** within the ORDER BY clause has been transformed to an integer value. + ** These integers will be replaced by copies of the corresponding result + ** set expressions by the call to resolveOrderGroupBy() below. */ + if( p->selFlags & SF_Converted ){ + Select *pSub = p->pSrc->a[0].pSelect; + p->pOrderBy = pSub->pOrderBy; + pSub->pOrderBy = 0; + } + + /* Process the ORDER BY clause for singleton SELECT statements. + ** The ORDER BY clause for compounds SELECT statements is handled + ** below, after all of the result-sets for all of the elements of + ** the compound have been resolved. + ** + ** If there is an ORDER BY clause on a term of a compound-select other + ** than the right-most term, then that is a syntax error. But the error + ** is not detected until much later, and so we need to go ahead and + ** resolve those symbols on the incorrect ORDER BY for consistency. + */ + if( isCompound<=nCompound /* Defer right-most ORDER BY of a compound */ + && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") + ){ + return WRC_Abort; + } + if( db->mallocFailed ){ + return WRC_Abort; + } + + /* Resolve the GROUP BY clause. At the same time, make sure + ** the GROUP BY clause does not contain aggregate functions. + */ + if( pGroupBy ){ + struct ExprList_item *pItem; + + if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){ + return WRC_Abort; + } + for(i=0, pItem=pGroupBy->a; inExpr; i++, pItem++){ + if( ExprHasProperty(pItem->pExpr, EP_Agg) ){ + sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in " + "the GROUP BY clause"); + return WRC_Abort; + } + } + } + + /* If this is part of a compound SELECT, check that it has the right + ** number of expressions in the select list. */ + if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){ + sqlite3SelectWrongNumTermsError(pParse, p->pNext); + return WRC_Abort; + } + + /* Advance to the next term of the compound + */ + p = p->pPrior; + nCompound++; + } + + /* Resolve the ORDER BY on a compound SELECT after all terms of + ** the compound have been resolved. + */ + if( isCompound && resolveCompoundOrderBy(pParse, pLeftmost) ){ + return WRC_Abort; + } + + return WRC_Prune; +} + +/* +** This routine walks an expression tree and resolves references to +** table columns and result-set columns. At the same time, do error +** checking on function usage and set a flag if any aggregate functions +** are seen. +** +** To resolve table columns references we look for nodes (or subtrees) of the +** form X.Y.Z or Y.Z or just Z where +** +** X: The name of a database. Ex: "main" or "temp" or +** the symbolic name assigned to an ATTACH-ed database. +** +** Y: The name of a table in a FROM clause. Or in a trigger +** one of the special names "old" or "new". +** +** Z: The name of a column in table Y. +** +** The node at the root of the subtree is modified as follows: +** +** Expr.op Changed to TK_COLUMN +** Expr.pTab Points to the Table object for X.Y +** Expr.iColumn The column index in X.Y. -1 for the rowid. +** Expr.iTable The VDBE cursor number for X.Y +** +** +** To resolve result-set references, look for expression nodes of the +** form Z (with no X and Y prefix) where the Z matches the right-hand +** size of an AS clause in the result-set of a SELECT. The Z expression +** is replaced by a copy of the left-hand side of the result-set expression. +** Table-name and function resolution occurs on the substituted expression +** tree. For example, in: +** +** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x; +** +** The "x" term of the order by is replaced by "a+b" to render: +** +** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b; +** +** Function calls are checked to make sure that the function is +** defined and that the correct number of arguments are specified. +** If the function is an aggregate function, then the NC_HasAgg flag is +** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION. +** If an expression contains aggregate functions then the EP_Agg +** property on the expression is set. +** +** An error message is left in pParse if anything is amiss. The number +** if errors is returned. +*/ +SQLITE_PRIVATE int sqlite3ResolveExprNames( + NameContext *pNC, /* Namespace to resolve expressions in. */ + Expr *pExpr /* The expression to be analyzed. */ +){ + u16 savedHasAgg; + Walker w; + + if( pExpr==0 ) return 0; +#if SQLITE_MAX_EXPR_DEPTH>0 + { + Parse *pParse = pNC->pParse; + if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){ + return 1; + } + pParse->nHeight += pExpr->nHeight; + } +#endif + savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg); + pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg); + memset(&w, 0, sizeof(w)); + w.xExprCallback = resolveExprStep; + w.xSelectCallback = resolveSelectStep; + w.pParse = pNC->pParse; + w.u.pNC = pNC; + sqlite3WalkExpr(&w, pExpr); +#if SQLITE_MAX_EXPR_DEPTH>0 + pNC->pParse->nHeight -= pExpr->nHeight; +#endif + if( pNC->nErr>0 || w.pParse->nErr>0 ){ + ExprSetProperty(pExpr, EP_Error); + } + if( pNC->ncFlags & NC_HasAgg ){ + ExprSetProperty(pExpr, EP_Agg); + } + pNC->ncFlags |= savedHasAgg; + return ExprHasProperty(pExpr, EP_Error); +} + + +/* +** Resolve all names in all expressions of a SELECT and in all +** decendents of the SELECT, including compounds off of p->pPrior, +** subqueries in expressions, and subqueries used as FROM clause +** terms. +** +** See sqlite3ResolveExprNames() for a description of the kinds of +** transformations that occur. +** +** All SELECT statements should have been expanded using +** sqlite3SelectExpand() prior to invoking this routine. +*/ +SQLITE_PRIVATE void sqlite3ResolveSelectNames( + Parse *pParse, /* The parser context */ + Select *p, /* The SELECT statement being coded. */ + NameContext *pOuterNC /* Name context for parent SELECT statement */ +){ + Walker w; + + assert( p!=0 ); + memset(&w, 0, sizeof(w)); + w.xExprCallback = resolveExprStep; + w.xSelectCallback = resolveSelectStep; + w.pParse = pParse; + w.u.pNC = pOuterNC; + sqlite3WalkSelect(&w, p); +} + +/* +** Resolve names in expressions that can only reference a single table: +** +** * CHECK constraints +** * WHERE clauses on partial indices +** +** The Expr.iTable value for Expr.op==TK_COLUMN nodes of the expression +** is set to -1 and the Expr.iColumn value is set to the column number. +** +** Any errors cause an error message to be set in pParse. +*/ +SQLITE_PRIVATE void sqlite3ResolveSelfReference( + Parse *pParse, /* Parsing context */ + Table *pTab, /* The table being referenced */ + int type, /* NC_IsCheck or NC_PartIdx */ + Expr *pExpr, /* Expression to resolve. May be NULL. */ + ExprList *pList /* Expression list to resolve. May be NUL. */ +){ + SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ + NameContext sNC; /* Name context for pParse->pNewTable */ + int i; /* Loop counter */ + + assert( type==NC_IsCheck || type==NC_PartIdx ); + memset(&sNC, 0, sizeof(sNC)); + memset(&sSrc, 0, sizeof(sSrc)); + sSrc.nSrc = 1; + sSrc.a[0].zName = pTab->zName; + sSrc.a[0].pTab = pTab; + sSrc.a[0].iCursor = -1; + sNC.pParse = pParse; + sNC.pSrcList = &sSrc; + sNC.ncFlags = type; + if( sqlite3ResolveExprNames(&sNC, pExpr) ) return; + if( pList ){ + for(i=0; inExpr; i++){ + if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){ + return; + } + } + } +} + +/************** End of resolve.c *********************************************/ +/************** Begin file expr.c ********************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains routines used for analyzing expressions and +** for generating VDBE code that evaluates expressions in SQLite. +*/ +/* #include "sqliteInt.h" */ + +/* +** Return the 'affinity' of the expression pExpr if any. +** +** If pExpr is a column, a reference to a column via an 'AS' alias, +** or a sub-select with a column as the return value, then the +** affinity of that column is returned. Otherwise, 0x00 is returned, +** indicating no affinity for the expression. +** +** i.e. the WHERE clause expressions in the following statements all +** have an affinity: +** +** CREATE TABLE t1(a); +** SELECT * FROM t1 WHERE a; +** SELECT a AS b FROM t1 WHERE b; +** SELECT * FROM t1 WHERE (select a from t1); +*/ +SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ + int op; + pExpr = sqlite3ExprSkipCollate(pExpr); + if( pExpr->flags & EP_Generic ) return 0; + op = pExpr->op; + if( op==TK_SELECT ){ + assert( pExpr->flags&EP_xIsSelect ); + return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); + } +#ifndef SQLITE_OMIT_CAST + if( op==TK_CAST ){ + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + return sqlite3AffinityType(pExpr->u.zToken, 0); + } +#endif + if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) + && pExpr->pTab!=0 + ){ + /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally + ** a TK_COLUMN but was previously evaluated and cached in a register */ + int j = pExpr->iColumn; + if( j<0 ) return SQLITE_AFF_INTEGER; + assert( pExpr->pTab && jpTab->nCol ); + return pExpr->pTab->aCol[j].affinity; + } + return pExpr->affinity; +} + +/* +** Set the collating sequence for expression pExpr to be the collating +** sequence named by pToken. Return a pointer to a new Expr node that +** implements the COLLATE operator. +** +** If a memory allocation error occurs, that fact is recorded in pParse->db +** and the pExpr parameter is returned unchanged. +*/ +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken( + Parse *pParse, /* Parsing context */ + Expr *pExpr, /* Add the "COLLATE" clause to this expression */ + const Token *pCollName, /* Name of collating sequence */ + int dequote /* True to dequote pCollName */ +){ + if( pCollName->n>0 ){ + Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote); + if( pNew ){ + pNew->pLeft = pExpr; + pNew->flags |= EP_Collate|EP_Skip; + pExpr = pNew; + } + } + return pExpr; +} +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ + Token s; + assert( zC!=0 ); + s.z = zC; + s.n = sqlite3Strlen30(s.z); + return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0); +} + +/* +** Skip over any TK_COLLATE or TK_AS operators and any unlikely() +** or likelihood() function at the root of an expression. +*/ +SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){ + while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){ + if( ExprHasProperty(pExpr, EP_Unlikely) ){ + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( pExpr->x.pList->nExpr>0 ); + assert( pExpr->op==TK_FUNCTION ); + pExpr = pExpr->x.pList->a[0].pExpr; + }else{ + assert( pExpr->op==TK_COLLATE || pExpr->op==TK_AS ); + pExpr = pExpr->pLeft; + } + } + return pExpr; +} + +/* +** Return the collation sequence for the expression pExpr. If +** there is no defined collating sequence, return NULL. +** +** The collating sequence might be determined by a COLLATE operator +** or by the presence of a column with a defined collating sequence. +** COLLATE operators take first precedence. Left operands take +** precedence over right operands. +*/ +SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ + sqlite3 *db = pParse->db; + CollSeq *pColl = 0; + Expr *p = pExpr; + while( p ){ + int op = p->op; + if( p->flags & EP_Generic ) break; + if( op==TK_CAST || op==TK_UPLUS ){ + p = p->pLeft; + continue; + } + if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){ + pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); + break; + } + if( (op==TK_AGG_COLUMN || op==TK_COLUMN + || op==TK_REGISTER || op==TK_TRIGGER) + && p->pTab!=0 + ){ + /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally + ** a TK_COLUMN but was previously evaluated and cached in a register */ + int j = p->iColumn; + if( j>=0 ){ + const char *zColl = p->pTab->aCol[j].zColl; + pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); + } + break; + } + if( p->flags & EP_Collate ){ + if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ + p = p->pLeft; + }else{ + Expr *pNext = p->pRight; + /* The Expr.x union is never used at the same time as Expr.pRight */ + assert( p->x.pList==0 || p->pRight==0 ); + /* p->flags holds EP_Collate and p->pLeft->flags does not. And + ** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at + ** least one EP_Collate. Thus the following two ALWAYS. */ + if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){ + int i; + for(i=0; ALWAYS(ix.pList->nExpr); i++){ + if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ + pNext = p->x.pList->a[i].pExpr; + break; + } + } + } + p = pNext; + } + }else{ + break; + } + } + if( sqlite3CheckCollSeq(pParse, pColl) ){ + pColl = 0; + } + return pColl; +} + +/* +** pExpr is an operand of a comparison operator. aff2 is the +** type affinity of the other operand. This routine returns the +** type affinity that should be used for the comparison operator. +*/ +SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2){ + char aff1 = sqlite3ExprAffinity(pExpr); + if( aff1 && aff2 ){ + /* Both sides of the comparison are columns. If one has numeric + ** affinity, use that. Otherwise use no affinity. + */ + if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){ + return SQLITE_AFF_NUMERIC; + }else{ + return SQLITE_AFF_BLOB; + } + }else if( !aff1 && !aff2 ){ + /* Neither side of the comparison is a column. Compare the + ** results directly. + */ + return SQLITE_AFF_BLOB; + }else{ + /* One side is a column, the other is not. Use the columns affinity. */ + assert( aff1==0 || aff2==0 ); + return (aff1 + aff2); + } +} + +/* +** pExpr is a comparison operator. Return the type affinity that should +** be applied to both operands prior to doing the comparison. +*/ +static char comparisonAffinity(Expr *pExpr){ + char aff; + assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT || + pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE || + pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT ); + assert( pExpr->pLeft ); + aff = sqlite3ExprAffinity(pExpr->pLeft); + if( pExpr->pRight ){ + aff = sqlite3CompareAffinity(pExpr->pRight, aff); + }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff); + }else if( !aff ){ + aff = SQLITE_AFF_BLOB; + } + return aff; +} + +/* +** pExpr is a comparison expression, eg. '=', '<', IN(...) etc. +** idx_affinity is the affinity of an indexed column. Return true +** if the index with affinity idx_affinity may be used to implement +** the comparison in pExpr. +*/ +SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ + char aff = comparisonAffinity(pExpr); + switch( aff ){ + case SQLITE_AFF_BLOB: + return 1; + case SQLITE_AFF_TEXT: + return idx_affinity==SQLITE_AFF_TEXT; + default: + return sqlite3IsNumericAffinity(idx_affinity); + } +} + +/* +** Return the P5 value that should be used for a binary comparison +** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2. +*/ +static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){ + u8 aff = (char)sqlite3ExprAffinity(pExpr2); + aff = (u8)sqlite3CompareAffinity(pExpr1, aff) | (u8)jumpIfNull; + return aff; +} + +/* +** Return a pointer to the collation sequence that should be used by +** a binary comparison operator comparing pLeft and pRight. +** +** If the left hand expression has a collating sequence type, then it is +** used. Otherwise the collation sequence for the right hand expression +** is used, or the default (BINARY) if neither expression has a collating +** type. +** +** Argument pRight (but not pLeft) may be a null pointer. In this case, +** it is not considered. +*/ +SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq( + Parse *pParse, + Expr *pLeft, + Expr *pRight +){ + CollSeq *pColl; + assert( pLeft ); + if( pLeft->flags & EP_Collate ){ + pColl = sqlite3ExprCollSeq(pParse, pLeft); + }else if( pRight && (pRight->flags & EP_Collate)!=0 ){ + pColl = sqlite3ExprCollSeq(pParse, pRight); + }else{ + pColl = sqlite3ExprCollSeq(pParse, pLeft); + if( !pColl ){ + pColl = sqlite3ExprCollSeq(pParse, pRight); + } + } + return pColl; +} + +/* +** Generate code for a comparison operator. +*/ +static int codeCompare( + Parse *pParse, /* The parsing (and code generating) context */ + Expr *pLeft, /* The left operand */ + Expr *pRight, /* The right operand */ + int opcode, /* The comparison opcode */ + int in1, int in2, /* Register holding operands */ + int dest, /* Jump here if true. */ + int jumpIfNull /* If true, jump if either operand is NULL */ +){ + int p5; + int addr; + CollSeq *p4; + + p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); + p5 = binaryCompareP5(pLeft, pRight, jumpIfNull); + addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1, + (void*)p4, P4_COLLSEQ); + sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5); + return addr; +} + +#if SQLITE_MAX_EXPR_DEPTH>0 +/* +** Check that argument nHeight is less than or equal to the maximum +** expression depth allowed. If it is not, leave an error message in +** pParse. +*/ +SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse *pParse, int nHeight){ + int rc = SQLITE_OK; + int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH]; + if( nHeight>mxHeight ){ + sqlite3ErrorMsg(pParse, + "Expression tree is too large (maximum depth %d)", mxHeight + ); + rc = SQLITE_ERROR; + } + return rc; +} + +/* The following three functions, heightOfExpr(), heightOfExprList() +** and heightOfSelect(), are used to determine the maximum height +** of any expression tree referenced by the structure passed as the +** first argument. +** +** If this maximum height is greater than the current value pointed +** to by pnHeight, the second parameter, then set *pnHeight to that +** value. +*/ +static void heightOfExpr(Expr *p, int *pnHeight){ + if( p ){ + if( p->nHeight>*pnHeight ){ + *pnHeight = p->nHeight; + } + } +} +static void heightOfExprList(ExprList *p, int *pnHeight){ + if( p ){ + int i; + for(i=0; inExpr; i++){ + heightOfExpr(p->a[i].pExpr, pnHeight); + } + } +} +static void heightOfSelect(Select *p, int *pnHeight){ + if( p ){ + heightOfExpr(p->pWhere, pnHeight); + heightOfExpr(p->pHaving, pnHeight); + heightOfExpr(p->pLimit, pnHeight); + heightOfExpr(p->pOffset, pnHeight); + heightOfExprList(p->pEList, pnHeight); + heightOfExprList(p->pGroupBy, pnHeight); + heightOfExprList(p->pOrderBy, pnHeight); + heightOfSelect(p->pPrior, pnHeight); + } +} + +/* +** Set the Expr.nHeight variable in the structure passed as an +** argument. An expression with no children, Expr.pList or +** Expr.pSelect member has a height of 1. Any other expression +** has a height equal to the maximum height of any other +** referenced Expr plus one. +** +** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags, +** if appropriate. +*/ +static void exprSetHeight(Expr *p){ + int nHeight = 0; + heightOfExpr(p->pLeft, &nHeight); + heightOfExpr(p->pRight, &nHeight); + if( ExprHasProperty(p, EP_xIsSelect) ){ + heightOfSelect(p->x.pSelect, &nHeight); + }else if( p->x.pList ){ + heightOfExprList(p->x.pList, &nHeight); + p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); + } + p->nHeight = nHeight + 1; +} + +/* +** Set the Expr.nHeight variable using the exprSetHeight() function. If +** the height is greater than the maximum allowed expression depth, +** leave an error in pParse. +** +** Also propagate all EP_Propagate flags from the Expr.x.pList into +** Expr.flags. +*/ +SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ + if( pParse->nErr ) return; + exprSetHeight(p); + sqlite3ExprCheckHeight(pParse, p->nHeight); +} + +/* +** Return the maximum height of any expression tree referenced +** by the select statement passed as an argument. +*/ +SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){ + int nHeight = 0; + heightOfSelect(p, &nHeight); + return nHeight; +} +#else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */ +/* +** Propagate all EP_Propagate flags from the Expr.x.pList into +** Expr.flags. +*/ +SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ + if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){ + p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); + } +} +#define exprSetHeight(y) +#endif /* SQLITE_MAX_EXPR_DEPTH>0 */ + +/* +** This routine is the core allocator for Expr nodes. +** +** Construct a new expression node and return a pointer to it. Memory +** for this node and for the pToken argument is a single allocation +** obtained from sqlite3DbMalloc(). The calling function +** is responsible for making sure the node eventually gets freed. +** +** If dequote is true, then the token (if it exists) is dequoted. +** If dequote is false, no dequoting is performance. The deQuote +** parameter is ignored if pToken is NULL or if the token does not +** appear to be quoted. If the quotes were of the form "..." (double-quotes) +** then the EP_DblQuoted flag is set on the expression node. +** +** Special case: If op==TK_INTEGER and pToken points to a string that +** can be translated into a 32-bit integer, then the token is not +** stored in u.zToken. Instead, the integer values is written +** into u.iValue and the EP_IntValue flag is set. No extra storage +** is allocated to hold the integer text and the dequote flag is ignored. +*/ +SQLITE_PRIVATE Expr *sqlite3ExprAlloc( + sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ + int op, /* Expression opcode */ + const Token *pToken, /* Token argument. Might be NULL */ + int dequote /* True to dequote */ +){ + Expr *pNew; + int nExtra = 0; + int iValue = 0; + + if( pToken ){ + if( op!=TK_INTEGER || pToken->z==0 + || sqlite3GetInt32(pToken->z, &iValue)==0 ){ + nExtra = pToken->n+1; + assert( iValue>=0 ); + } + } + pNew = sqlite3DbMallocZero(db, sizeof(Expr)+nExtra); + if( pNew ){ + pNew->op = (u8)op; + pNew->iAgg = -1; + if( pToken ){ + if( nExtra==0 ){ + pNew->flags |= EP_IntValue; + pNew->u.iValue = iValue; + }else{ + int c; + pNew->u.zToken = (char*)&pNew[1]; + assert( pToken->z!=0 || pToken->n==0 ); + if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n); + pNew->u.zToken[pToken->n] = 0; + if( dequote && nExtra>=3 + && ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){ + sqlite3Dequote(pNew->u.zToken); + if( c=='"' ) pNew->flags |= EP_DblQuoted; + } + } + } +#if SQLITE_MAX_EXPR_DEPTH>0 + pNew->nHeight = 1; +#endif + } + return pNew; +} + +/* +** Allocate a new expression node from a zero-terminated token that has +** already been dequoted. +*/ +SQLITE_PRIVATE Expr *sqlite3Expr( + sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ + int op, /* Expression opcode */ + const char *zToken /* Token argument. Might be NULL */ +){ + Token x; + x.z = zToken; + x.n = zToken ? sqlite3Strlen30(zToken) : 0; + return sqlite3ExprAlloc(db, op, &x, 0); +} + +/* +** Attach subtrees pLeft and pRight to the Expr node pRoot. +** +** If pRoot==NULL that means that a memory allocation error has occurred. +** In that case, delete the subtrees pLeft and pRight. +*/ +SQLITE_PRIVATE void sqlite3ExprAttachSubtrees( + sqlite3 *db, + Expr *pRoot, + Expr *pLeft, + Expr *pRight +){ + if( pRoot==0 ){ + assert( db->mallocFailed ); + sqlite3ExprDelete(db, pLeft); + sqlite3ExprDelete(db, pRight); + }else{ + if( pRight ){ + pRoot->pRight = pRight; + pRoot->flags |= EP_Propagate & pRight->flags; + } + if( pLeft ){ + pRoot->pLeft = pLeft; + pRoot->flags |= EP_Propagate & pLeft->flags; + } + exprSetHeight(pRoot); + } +} + +/* +** Allocate an Expr node which joins as many as two subtrees. +** +** One or both of the subtrees can be NULL. Return a pointer to the new +** Expr node. Or, if an OOM error occurs, set pParse->db->mallocFailed, +** free the subtrees and return NULL. +*/ +SQLITE_PRIVATE Expr *sqlite3PExpr( + Parse *pParse, /* Parsing context */ + int op, /* Expression opcode */ + Expr *pLeft, /* Left operand */ + Expr *pRight, /* Right operand */ + const Token *pToken /* Argument token */ +){ + Expr *p; + if( op==TK_AND && pLeft && pRight && pParse->nErr==0 ){ + /* Take advantage of short-circuit false optimization for AND */ + p = sqlite3ExprAnd(pParse->db, pLeft, pRight); + }else{ + p = sqlite3ExprAlloc(pParse->db, op, pToken, 1); + sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); + } + if( p ) { + sqlite3ExprCheckHeight(pParse, p->nHeight); + } + return p; +} + +/* +** If the expression is always either TRUE or FALSE (respectively), +** then return 1. If one cannot determine the truth value of the +** expression at compile-time return 0. +** +** This is an optimization. If is OK to return 0 here even if +** the expression really is always false or false (a false negative). +** But it is a bug to return 1 if the expression might have different +** boolean values in different circumstances (a false positive.) +** +** Note that if the expression is part of conditional for a +** LEFT JOIN, then we cannot determine at compile-time whether or not +** is it true or false, so always return 0. +*/ +static int exprAlwaysTrue(Expr *p){ + int v = 0; + if( ExprHasProperty(p, EP_FromJoin) ) return 0; + if( !sqlite3ExprIsInteger(p, &v) ) return 0; + return v!=0; +} +static int exprAlwaysFalse(Expr *p){ + int v = 0; + if( ExprHasProperty(p, EP_FromJoin) ) return 0; + if( !sqlite3ExprIsInteger(p, &v) ) return 0; + return v==0; +} + +/* +** Join two expressions using an AND operator. If either expression is +** NULL, then just return the other expression. +** +** If one side or the other of the AND is known to be false, then instead +** of returning an AND expression, just return a constant expression with +** a value of false. +*/ +SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){ + if( pLeft==0 ){ + return pRight; + }else if( pRight==0 ){ + return pLeft; + }else if( exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight) ){ + sqlite3ExprDelete(db, pLeft); + sqlite3ExprDelete(db, pRight); + return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0); + }else{ + Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0); + sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight); + return pNew; + } +} + +/* +** Construct a new expression node for a function with multiple +** arguments. +*/ +SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ + Expr *pNew; + sqlite3 *db = pParse->db; + assert( pToken ); + pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1); + if( pNew==0 ){ + sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ + return 0; + } + pNew->x.pList = pList; + assert( !ExprHasProperty(pNew, EP_xIsSelect) ); + sqlite3ExprSetHeightAndFlags(pParse, pNew); + return pNew; +} + +/* +** Assign a variable number to an expression that encodes a wildcard +** in the original SQL statement. +** +** Wildcards consisting of a single "?" are assigned the next sequential +** variable number. +** +** Wildcards of the form "?nnn" are assigned the number "nnn". We make +** sure "nnn" is not too be to avoid a denial of service attack when +** the SQL statement comes from an external source. +** +** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number +** as the previous instance of the same wildcard. Or if this is the first +** instance of the wildcard, the next sequential variable number is +** assigned. +*/ +SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ + sqlite3 *db = pParse->db; + const char *z; + + if( pExpr==0 ) return; + assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) ); + z = pExpr->u.zToken; + assert( z!=0 ); + assert( z[0]!=0 ); + if( z[1]==0 ){ + /* Wildcard of the form "?". Assign the next variable number */ + assert( z[0]=='?' ); + pExpr->iColumn = (ynVar)(++pParse->nVar); + }else{ + ynVar x = 0; + u32 n = sqlite3Strlen30(z); + if( z[0]=='?' ){ + /* Wildcard of the form "?nnn". Convert "nnn" to an integer and + ** use it as the variable number */ + i64 i; + int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8); + pExpr->iColumn = x = (ynVar)i; + testcase( i==0 ); + testcase( i==1 ); + testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); + testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); + if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ + sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", + db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); + x = 0; + } + if( i>pParse->nVar ){ + pParse->nVar = (int)i; + } + }else{ + /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable + ** number as the prior appearance of the same name, or if the name + ** has never appeared before, reuse the same variable number + */ + ynVar i; + for(i=0; inzVar; i++){ + if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){ + pExpr->iColumn = x = (ynVar)i+1; + break; + } + } + if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar); + } + if( x>0 ){ + if( x>pParse->nzVar ){ + char **a; + a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0])); + if( a==0 ) return; /* Error reported through db->mallocFailed */ + pParse->azVar = a; + memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0])); + pParse->nzVar = x; + } + if( z[0]!='?' || pParse->azVar[x-1]==0 ){ + sqlite3DbFree(db, pParse->azVar[x-1]); + pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n); + } + } + } + if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ + sqlite3ErrorMsg(pParse, "too many SQL variables"); + } +} + +/* +** Recursively delete an expression tree. +*/ +SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){ + if( p==0 ) return; + /* Sanity check: Assert that the IntValue is non-negative if it exists */ + assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); + if( !ExprHasProperty(p, EP_TokenOnly) ){ + /* The Expr.x union is never used at the same time as Expr.pRight */ + assert( p->x.pList==0 || p->pRight==0 ); + sqlite3ExprDelete(db, p->pLeft); + sqlite3ExprDelete(db, p->pRight); + if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); + if( ExprHasProperty(p, EP_xIsSelect) ){ + sqlite3SelectDelete(db, p->x.pSelect); + }else{ + sqlite3ExprListDelete(db, p->x.pList); + } + } + if( !ExprHasProperty(p, EP_Static) ){ + sqlite3DbFree(db, p); + } +} + +/* +** Return the number of bytes allocated for the expression structure +** passed as the first argument. This is always one of EXPR_FULLSIZE, +** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE. +*/ +static int exprStructSize(Expr *p){ + if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE; + if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE; + return EXPR_FULLSIZE; +} + +/* +** The dupedExpr*Size() routines each return the number of bytes required +** to store a copy of an expression or expression tree. They differ in +** how much of the tree is measured. +** +** dupedExprStructSize() Size of only the Expr structure +** dupedExprNodeSize() Size of Expr + space for token +** dupedExprSize() Expr + token + subtree components +** +*************************************************************************** +** +** The dupedExprStructSize() function returns two values OR-ed together: +** (1) the space required for a copy of the Expr structure only and +** (2) the EP_xxx flags that indicate what the structure size should be. +** The return values is always one of: +** +** EXPR_FULLSIZE +** EXPR_REDUCEDSIZE | EP_Reduced +** EXPR_TOKENONLYSIZE | EP_TokenOnly +** +** The size of the structure can be found by masking the return value +** of this routine with 0xfff. The flags can be found by masking the +** return value with EP_Reduced|EP_TokenOnly. +** +** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size +** (unreduced) Expr objects as they or originally constructed by the parser. +** During expression analysis, extra information is computed and moved into +** later parts of teh Expr object and that extra information might get chopped +** off if the expression is reduced. Note also that it does not work to +** make an EXPRDUP_REDUCE copy of a reduced expression. It is only legal +** to reduce a pristine expression tree from the parser. The implementation +** of dupedExprStructSize() contain multiple assert() statements that attempt +** to enforce this constraint. +*/ +static int dupedExprStructSize(Expr *p, int flags){ + int nSize; + assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */ + assert( EXPR_FULLSIZE<=0xfff ); + assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 ); + if( 0==(flags&EXPRDUP_REDUCE) ){ + nSize = EXPR_FULLSIZE; + }else{ + assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasProperty(p, EP_FromJoin) ); + assert( !ExprHasProperty(p, EP_MemToken) ); + assert( !ExprHasProperty(p, EP_NoReduce) ); + if( p->pLeft || p->x.pList ){ + nSize = EXPR_REDUCEDSIZE | EP_Reduced; + }else{ + assert( p->pRight==0 ); + nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; + } + } + return nSize; +} + +/* +** This function returns the space in bytes required to store the copy +** of the Expr structure and a copy of the Expr.u.zToken string (if that +** string is defined.) +*/ +static int dupedExprNodeSize(Expr *p, int flags){ + int nByte = dupedExprStructSize(p, flags) & 0xfff; + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + nByte += sqlite3Strlen30(p->u.zToken)+1; + } + return ROUND8(nByte); +} + +/* +** Return the number of bytes required to create a duplicate of the +** expression passed as the first argument. The second argument is a +** mask containing EXPRDUP_XXX flags. +** +** The value returned includes space to create a copy of the Expr struct +** itself and the buffer referred to by Expr.u.zToken, if any. +** +** If the EXPRDUP_REDUCE flag is set, then the return value includes +** space to duplicate all Expr nodes in the tree formed by Expr.pLeft +** and Expr.pRight variables (but not for any structures pointed to or +** descended from the Expr.x.pList or Expr.x.pSelect variables). +*/ +static int dupedExprSize(Expr *p, int flags){ + int nByte = 0; + if( p ){ + nByte = dupedExprNodeSize(p, flags); + if( flags&EXPRDUP_REDUCE ){ + nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags); + } + } + return nByte; +} + +/* +** This function is similar to sqlite3ExprDup(), except that if pzBuffer +** is not NULL then *pzBuffer is assumed to point to a buffer large enough +** to store the copy of expression p, the copies of p->u.zToken +** (if applicable), and the copies of the p->pLeft and p->pRight expressions, +** if any. Before returning, *pzBuffer is set to the first byte past the +** portion of the buffer copied into by this function. +*/ +static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ + Expr *pNew = 0; /* Value to return */ + if( p ){ + const int isReduced = (flags&EXPRDUP_REDUCE); + u8 *zAlloc; + u32 staticFlag = 0; + + assert( pzBuffer==0 || isReduced ); + + /* Figure out where to write the new Expr structure. */ + if( pzBuffer ){ + zAlloc = *pzBuffer; + staticFlag = EP_Static; + }else{ + zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags)); + } + pNew = (Expr *)zAlloc; + + if( pNew ){ + /* Set nNewSize to the size allocated for the structure pointed to + ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or + ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed + ** by the copy of the p->u.zToken string (if any). + */ + const unsigned nStructSize = dupedExprStructSize(p, flags); + const int nNewSize = nStructSize & 0xfff; + int nToken; + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + nToken = sqlite3Strlen30(p->u.zToken) + 1; + }else{ + nToken = 0; + } + if( isReduced ){ + assert( ExprHasProperty(p, EP_Reduced)==0 ); + memcpy(zAlloc, p, nNewSize); + }else{ + int nSize = exprStructSize(p); + memcpy(zAlloc, p, nSize); + memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize); + } + + /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */ + pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken); + pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly); + pNew->flags |= staticFlag; + + /* Copy the p->u.zToken string, if any. */ + if( nToken ){ + char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; + memcpy(zToken, p->u.zToken, nToken); + } + + if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){ + /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ + if( ExprHasProperty(p, EP_xIsSelect) ){ + pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced); + }else{ + pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, isReduced); + } + } + + /* Fill in pNew->pLeft and pNew->pRight. */ + if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ + zAlloc += dupedExprNodeSize(p, flags); + if( ExprHasProperty(pNew, EP_Reduced) ){ + pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc); + pNew->pRight = exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc); + } + if( pzBuffer ){ + *pzBuffer = zAlloc; + } + }else{ + if( !ExprHasProperty(p, EP_TokenOnly) ){ + pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); + pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); + } + } + + } + } + return pNew; +} + +/* +** Create and return a deep copy of the object passed as the second +** argument. If an OOM condition is encountered, NULL is returned +** and the db->mallocFailed flag set. +*/ +#ifndef SQLITE_OMIT_CTE +static With *withDup(sqlite3 *db, With *p){ + With *pRet = 0; + if( p ){ + int nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1); + pRet = sqlite3DbMallocZero(db, nByte); + if( pRet ){ + int i; + pRet->nCte = p->nCte; + for(i=0; inCte; i++){ + pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0); + pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0); + pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName); + } + } + } + return pRet; +} +#else +# define withDup(x,y) 0 +#endif + +/* +** The following group of routines make deep copies of expressions, +** expression lists, ID lists, and select statements. The copies can +** be deleted (by being passed to their respective ...Delete() routines) +** without effecting the originals. +** +** The expression list, ID, and source lists return by sqlite3ExprListDup(), +** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded +** by subsequent calls to sqlite*ListAppend() routines. +** +** Any tables that the SrcList might point to are not duplicated. +** +** The flags parameter contains a combination of the EXPRDUP_XXX flags. +** If the EXPRDUP_REDUCE flag is set, then the structure returned is a +** truncated version of the usual Expr structure that will be stored as +** part of the in-memory representation of the database schema. +*/ +SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){ + return exprDup(db, p, flags, 0); +} +SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ + ExprList *pNew; + struct ExprList_item *pItem, *pOldItem; + int i; + if( p==0 ) return 0; + pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); + if( pNew==0 ) return 0; + pNew->nExpr = i = p->nExpr; + if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; inExpr; i+=i){} + pNew->a = pItem = sqlite3DbMallocRaw(db, i*sizeof(p->a[0]) ); + if( pItem==0 ){ + sqlite3DbFree(db, pNew); + return 0; + } + pOldItem = p->a; + for(i=0; inExpr; i++, pItem++, pOldItem++){ + Expr *pOldExpr = pOldItem->pExpr; + pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags); + pItem->zName = sqlite3DbStrDup(db, pOldItem->zName); + pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan); + pItem->sortOrder = pOldItem->sortOrder; + pItem->done = 0; + pItem->bSpanIsTab = pOldItem->bSpanIsTab; + pItem->u = pOldItem->u; + } + return pNew; +} + +/* +** If cursors, triggers, views and subqueries are all omitted from +** the build, then none of the following routines, except for +** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes +** called with a NULL argument. +*/ +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \ + || !defined(SQLITE_OMIT_SUBQUERY) +SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){ + SrcList *pNew; + int i; + int nByte; + if( p==0 ) return 0; + nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); + pNew = sqlite3DbMallocRaw(db, nByte ); + if( pNew==0 ) return 0; + pNew->nSrc = pNew->nAlloc = p->nSrc; + for(i=0; inSrc; i++){ + struct SrcList_item *pNewItem = &pNew->a[i]; + struct SrcList_item *pOldItem = &p->a[i]; + Table *pTab; + pNewItem->pSchema = pOldItem->pSchema; + pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase); + pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); + pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); + pNewItem->jointype = pOldItem->jointype; + pNewItem->iCursor = pOldItem->iCursor; + pNewItem->addrFillSub = pOldItem->addrFillSub; + pNewItem->regReturn = pOldItem->regReturn; + pNewItem->isCorrelated = pOldItem->isCorrelated; + pNewItem->viaCoroutine = pOldItem->viaCoroutine; + pNewItem->isRecursive = pOldItem->isRecursive; + pNewItem->zIndexedBy = sqlite3DbStrDup(db, pOldItem->zIndexedBy); + pNewItem->notIndexed = pOldItem->notIndexed; + pNewItem->pIndex = pOldItem->pIndex; + pTab = pNewItem->pTab = pOldItem->pTab; + if( pTab ){ + pTab->nRef++; + } + pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags); + pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags); + pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing); + pNewItem->colUsed = pOldItem->colUsed; + } + return pNew; +} +SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){ + IdList *pNew; + int i; + if( p==0 ) return 0; + pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); + if( pNew==0 ) return 0; + pNew->nId = p->nId; + pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) ); + if( pNew->a==0 ){ + sqlite3DbFree(db, pNew); + return 0; + } + /* Note that because the size of the allocation for p->a[] is not + ** necessarily a power of two, sqlite3IdListAppend() may not be called + ** on the duplicate created by this function. */ + for(i=0; inId; i++){ + struct IdList_item *pNewItem = &pNew->a[i]; + struct IdList_item *pOldItem = &p->a[i]; + pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); + pNewItem->idx = pOldItem->idx; + } + return pNew; +} +SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ + Select *pNew, *pPrior; + if( p==0 ) return 0; + pNew = sqlite3DbMallocRaw(db, sizeof(*p) ); + if( pNew==0 ) return 0; + pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags); + pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags); + pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags); + pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags); + pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags); + pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags); + pNew->op = p->op; + pNew->pPrior = pPrior = sqlite3SelectDup(db, p->pPrior, flags); + if( pPrior ) pPrior->pNext = pNew; + pNew->pNext = 0; + pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); + pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags); + pNew->iLimit = 0; + pNew->iOffset = 0; + pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; + pNew->nSelectRow = p->nSelectRow; + pNew->pWith = withDup(db, p->pWith); + sqlite3SelectSetName(pNew, p->zSelName); + return pNew; +} +#else +SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ + assert( p==0 ); + return 0; +} +#endif + + +/* +** Add a new element to the end of an expression list. If pList is +** initially NULL, then create a new expression list. +** +** If a memory allocation error occurs, the entire list is freed and +** NULL is returned. If non-NULL is returned, then it is guaranteed +** that the new entry was successfully appended. +*/ +SQLITE_PRIVATE ExprList *sqlite3ExprListAppend( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List to which to append. Might be NULL */ + Expr *pExpr /* Expression to be appended. Might be NULL */ +){ + sqlite3 *db = pParse->db; + if( pList==0 ){ + pList = sqlite3DbMallocZero(db, sizeof(ExprList) ); + if( pList==0 ){ + goto no_mem; + } + pList->a = sqlite3DbMallocRaw(db, sizeof(pList->a[0])); + if( pList->a==0 ) goto no_mem; + }else if( (pList->nExpr & (pList->nExpr-1))==0 ){ + struct ExprList_item *a; + assert( pList->nExpr>0 ); + a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0])); + if( a==0 ){ + goto no_mem; + } + pList->a = a; + } + assert( pList->a!=0 ); + if( 1 ){ + struct ExprList_item *pItem = &pList->a[pList->nExpr++]; + memset(pItem, 0, sizeof(*pItem)); + pItem->pExpr = pExpr; + } + return pList; + +no_mem: + /* Avoid leaking memory if malloc has failed. */ + sqlite3ExprDelete(db, pExpr); + sqlite3ExprListDelete(db, pList); + return 0; +} + +/* +** Set the ExprList.a[].zName element of the most recently added item +** on the expression list. +** +** pList might be NULL following an OOM error. But pName should never be +** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag +** is set. +*/ +SQLITE_PRIVATE void sqlite3ExprListSetName( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List to which to add the span. */ + Token *pName, /* Name to be added */ + int dequote /* True to cause the name to be dequoted */ +){ + assert( pList!=0 || pParse->db->mallocFailed!=0 ); + if( pList ){ + struct ExprList_item *pItem; + assert( pList->nExpr>0 ); + pItem = &pList->a[pList->nExpr-1]; + assert( pItem->zName==0 ); + pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n); + if( dequote && pItem->zName ) sqlite3Dequote(pItem->zName); + } +} + +/* +** Set the ExprList.a[].zSpan element of the most recently added item +** on the expression list. +** +** pList might be NULL following an OOM error. But pSpan should never be +** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag +** is set. +*/ +SQLITE_PRIVATE void sqlite3ExprListSetSpan( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List to which to add the span. */ + ExprSpan *pSpan /* The span to be added */ +){ + sqlite3 *db = pParse->db; + assert( pList!=0 || db->mallocFailed!=0 ); + if( pList ){ + struct ExprList_item *pItem = &pList->a[pList->nExpr-1]; + assert( pList->nExpr>0 ); + assert( db->mallocFailed || pItem->pExpr==pSpan->pExpr ); + sqlite3DbFree(db, pItem->zSpan); + pItem->zSpan = sqlite3DbStrNDup(db, (char*)pSpan->zStart, + (int)(pSpan->zEnd - pSpan->zStart)); + } +} + +/* +** If the expression list pEList contains more than iLimit elements, +** leave an error message in pParse. +*/ +SQLITE_PRIVATE void sqlite3ExprListCheckLength( + Parse *pParse, + ExprList *pEList, + const char *zObject +){ + int mx = pParse->db->aLimit[SQLITE_LIMIT_COLUMN]; + testcase( pEList && pEList->nExpr==mx ); + testcase( pEList && pEList->nExpr==mx+1 ); + if( pEList && pEList->nExpr>mx ){ + sqlite3ErrorMsg(pParse, "too many columns in %s", zObject); + } +} + +/* +** Delete an entire expression list. +*/ +SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ + int i; + struct ExprList_item *pItem; + if( pList==0 ) return; + assert( pList->a!=0 || pList->nExpr==0 ); + for(pItem=pList->a, i=0; inExpr; i++, pItem++){ + sqlite3ExprDelete(db, pItem->pExpr); + sqlite3DbFree(db, pItem->zName); + sqlite3DbFree(db, pItem->zSpan); + } + sqlite3DbFree(db, pList->a); + sqlite3DbFree(db, pList); +} + +/* +** Return the bitwise-OR of all Expr.flags fields in the given +** ExprList. +*/ +SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){ + int i; + u32 m = 0; + if( pList ){ + for(i=0; inExpr; i++){ + Expr *pExpr = pList->a[i].pExpr; + if( ALWAYS(pExpr) ) m |= pExpr->flags; + } + } + return m; +} + +/* +** These routines are Walker callbacks used to check expressions to +** see if they are "constant" for some definition of constant. The +** Walker.eCode value determines the type of "constant" we are looking +** for. +** +** These callback routines are used to implement the following: +** +** sqlite3ExprIsConstant() pWalker->eCode==1 +** sqlite3ExprIsConstantNotJoin() pWalker->eCode==2 +** sqlite3ExprIsTableConstant() pWalker->eCode==3 +** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5 +** +** In all cases, the callbacks set Walker.eCode=0 and abort if the expression +** is found to not be a constant. +** +** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions +** in a CREATE TABLE statement. The Walker.eCode value is 5 when parsing +** an existing schema and 4 when processing a new statement. A bound +** parameter raises an error for new statements, but is silently converted +** to NULL for existing schemas. This allows sqlite_master tables that +** contain a bound parameter because they were generated by older versions +** of SQLite to be parsed by newer versions of SQLite without raising a +** malformed schema error. +*/ +static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ + + /* If pWalker->eCode is 2 then any term of the expression that comes from + ** the ON or USING clauses of a left join disqualifies the expression + ** from being considered constant. */ + if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_FromJoin) ){ + pWalker->eCode = 0; + return WRC_Abort; + } + + switch( pExpr->op ){ + /* Consider functions to be constant if all their arguments are constant + ** and either pWalker->eCode==4 or 5 or the function has the + ** SQLITE_FUNC_CONST flag. */ + case TK_FUNCTION: + if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){ + return WRC_Continue; + }else{ + pWalker->eCode = 0; + return WRC_Abort; + } + case TK_ID: + case TK_COLUMN: + case TK_AGG_FUNCTION: + case TK_AGG_COLUMN: + testcase( pExpr->op==TK_ID ); + testcase( pExpr->op==TK_COLUMN ); + testcase( pExpr->op==TK_AGG_FUNCTION ); + testcase( pExpr->op==TK_AGG_COLUMN ); + if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){ + return WRC_Continue; + }else{ + pWalker->eCode = 0; + return WRC_Abort; + } + case TK_VARIABLE: + if( pWalker->eCode==5 ){ + /* Silently convert bound parameters that appear inside of CREATE + ** statements into a NULL when parsing the CREATE statement text out + ** of the sqlite_master table */ + pExpr->op = TK_NULL; + }else if( pWalker->eCode==4 ){ + /* A bound parameter in a CREATE statement that originates from + ** sqlite3_prepare() causes an error */ + pWalker->eCode = 0; + return WRC_Abort; + } + /* Fall through */ + default: + testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */ + testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */ + return WRC_Continue; + } +} +static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){ + UNUSED_PARAMETER(NotUsed); + pWalker->eCode = 0; + return WRC_Abort; +} +static int exprIsConst(Expr *p, int initFlag, int iCur){ + Walker w; + memset(&w, 0, sizeof(w)); + w.eCode = initFlag; + w.xExprCallback = exprNodeIsConstant; + w.xSelectCallback = selectNodeIsConstant; + w.u.iCur = iCur; + sqlite3WalkExpr(&w, p); + return w.eCode; +} + +/* +** Walk an expression tree. Return non-zero if the expression is constant +** and 0 if it involves variables or function calls. +** +** For the purposes of this function, a double-quoted string (ex: "abc") +** is considered a variable but a single-quoted string (ex: 'abc') is +** a constant. +*/ +SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){ + return exprIsConst(p, 1, 0); +} + +/* +** Walk an expression tree. Return non-zero if the expression is constant +** that does no originate from the ON or USING clauses of a join. +** Return 0 if it involves variables or function calls or terms from +** an ON or USING clause. +*/ +SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){ + return exprIsConst(p, 2, 0); +} + +/* +** Walk an expression tree. Return non-zero if the expression is constant +** for any single row of the table with cursor iCur. In other words, the +** expression must not refer to any non-deterministic function nor any +** table other than iCur. +*/ +SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){ + return exprIsConst(p, 3, iCur); +} + +/* +** Walk an expression tree. Return non-zero if the expression is constant +** or a function call with constant arguments. Return and 0 if there +** are any variables. +** +** For the purposes of this function, a double-quoted string (ex: "abc") +** is considered a variable but a single-quoted string (ex: 'abc') is +** a constant. +*/ +SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ + assert( isInit==0 || isInit==1 ); + return exprIsConst(p, 4+isInit, 0); +} + +/* +** If the expression p codes a constant integer that is small enough +** to fit in a 32-bit integer, return 1 and put the value of the integer +** in *pValue. If the expression is not an integer or if it is too big +** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. +*/ +SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){ + int rc = 0; + + /* If an expression is an integer literal that fits in a signed 32-bit + ** integer, then the EP_IntValue flag will have already been set */ + assert( p->op!=TK_INTEGER || (p->flags & EP_IntValue)!=0 + || sqlite3GetInt32(p->u.zToken, &rc)==0 ); + + if( p->flags & EP_IntValue ){ + *pValue = p->u.iValue; + return 1; + } + switch( p->op ){ + case TK_UPLUS: { + rc = sqlite3ExprIsInteger(p->pLeft, pValue); + break; + } + case TK_UMINUS: { + int v; + if( sqlite3ExprIsInteger(p->pLeft, &v) ){ + assert( v!=(-2147483647-1) ); + *pValue = -v; + rc = 1; + } + break; + } + default: break; + } + return rc; +} + +/* +** Return FALSE if there is no chance that the expression can be NULL. +** +** If the expression might be NULL or if the expression is too complex +** to tell return TRUE. +** +** This routine is used as an optimization, to skip OP_IsNull opcodes +** when we know that a value cannot be NULL. Hence, a false positive +** (returning TRUE when in fact the expression can never be NULL) might +** be a small performance hit but is otherwise harmless. On the other +** hand, a false negative (returning FALSE when the result could be NULL) +** will likely result in an incorrect answer. So when in doubt, return +** TRUE. +*/ +SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){ + u8 op; + while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; } + op = p->op; + if( op==TK_REGISTER ) op = p->op2; + switch( op ){ + case TK_INTEGER: + case TK_STRING: + case TK_FLOAT: + case TK_BLOB: + return 0; + case TK_COLUMN: + assert( p->pTab!=0 ); + return ExprHasProperty(p, EP_CanBeNull) || + (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); + default: + return 1; + } +} + +/* +** Return TRUE if the given expression is a constant which would be +** unchanged by OP_Affinity with the affinity given in the second +** argument. +** +** This routine is used to determine if the OP_Affinity operation +** can be omitted. When in doubt return FALSE. A false negative +** is harmless. A false positive, however, can result in the wrong +** answer. +*/ +SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){ + u8 op; + if( aff==SQLITE_AFF_BLOB ) return 1; + while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; } + op = p->op; + if( op==TK_REGISTER ) op = p->op2; + switch( op ){ + case TK_INTEGER: { + return aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC; + } + case TK_FLOAT: { + return aff==SQLITE_AFF_REAL || aff==SQLITE_AFF_NUMERIC; + } + case TK_STRING: { + return aff==SQLITE_AFF_TEXT; + } + case TK_BLOB: { + return 1; + } + case TK_COLUMN: { + assert( p->iTable>=0 ); /* p cannot be part of a CHECK constraint */ + return p->iColumn<0 + && (aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC); + } + default: { + return 0; + } + } +} + +/* +** Return TRUE if the given string is a row-id column name. +*/ +SQLITE_PRIVATE int sqlite3IsRowid(const char *z){ + if( sqlite3StrICmp(z, "_ROWID_")==0 ) return 1; + if( sqlite3StrICmp(z, "ROWID")==0 ) return 1; + if( sqlite3StrICmp(z, "OID")==0 ) return 1; + return 0; +} + +/* +** Return true if we are able to the IN operator optimization on a +** query of the form +** +** x IN (SELECT ...) +** +** Where the SELECT... clause is as specified by the parameter to this +** routine. +** +** The Select object passed in has already been preprocessed and no +** errors have been found. +*/ +#ifndef SQLITE_OMIT_SUBQUERY +static int isCandidateForInOpt(Select *p){ + SrcList *pSrc; + ExprList *pEList; + Table *pTab; + if( p==0 ) return 0; /* right-hand side of IN is SELECT */ + if( p->pPrior ) return 0; /* Not a compound SELECT */ + if( p->selFlags & (SF_Distinct|SF_Aggregate) ){ + testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); + testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); + return 0; /* No DISTINCT keyword and no aggregate functions */ + } + assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */ + if( p->pLimit ) return 0; /* Has no LIMIT clause */ + assert( p->pOffset==0 ); /* No LIMIT means no OFFSET */ + if( p->pWhere ) return 0; /* Has no WHERE clause */ + pSrc = p->pSrc; + assert( pSrc!=0 ); + if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */ + if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */ + pTab = pSrc->a[0].pTab; + if( NEVER(pTab==0) ) return 0; + assert( pTab->pSelect==0 ); /* FROM clause is not a view */ + if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */ + pEList = p->pEList; + if( pEList->nExpr!=1 ) return 0; /* One column in the result set */ + if( pEList->a[0].pExpr->op!=TK_COLUMN ) return 0; /* Result is a column */ + return 1; +} +#endif /* SQLITE_OMIT_SUBQUERY */ + +/* +** Code an OP_Once instruction and allocate space for its flag. Return the +** address of the new instruction. +*/ +SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){ + Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ + return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++); +} + +/* +** Generate code that checks the left-most column of index table iCur to see if +** it contains any NULL entries. Cause the register at regHasNull to be set +** to a non-NULL value if iCur contains no NULLs. Cause register regHasNull +** to be set to NULL if iCur contains one or more NULL values. +*/ +static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){ + int j1; + sqlite3VdbeAddOp2(v, OP_Integer, 0, regHasNull); + j1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, regHasNull); + sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); + VdbeComment((v, "first_entry_in(%d)", iCur)); + sqlite3VdbeJumpHere(v, j1); +} + + +#ifndef SQLITE_OMIT_SUBQUERY +/* +** The argument is an IN operator with a list (not a subquery) on the +** right-hand side. Return TRUE if that list is constant. +*/ +static int sqlite3InRhsIsConstant(Expr *pIn){ + Expr *pLHS; + int res; + assert( !ExprHasProperty(pIn, EP_xIsSelect) ); + pLHS = pIn->pLeft; + pIn->pLeft = 0; + res = sqlite3ExprIsConstant(pIn); + pIn->pLeft = pLHS; + return res; +} +#endif + +/* +** This function is used by the implementation of the IN (...) operator. +** The pX parameter is the expression on the RHS of the IN operator, which +** might be either a list of expressions or a subquery. +** +** The job of this routine is to find or create a b-tree object that can +** be used either to test for membership in the RHS set or to iterate through +** all members of the RHS set, skipping duplicates. +** +** A cursor is opened on the b-tree object that is the RHS of the IN operator +** and pX->iTable is set to the index of that cursor. +** +** The returned value of this function indicates the b-tree type, as follows: +** +** IN_INDEX_ROWID - The cursor was opened on a database table. +** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index. +** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index. +** IN_INDEX_EPH - The cursor was opened on a specially created and +** populated epheremal table. +** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be +** implemented as a sequence of comparisons. +** +** An existing b-tree might be used if the RHS expression pX is a simple +** subquery such as: +** +** SELECT FROM +** +** If the RHS of the IN operator is a list or a more complex subquery, then +** an ephemeral table might need to be generated from the RHS and then +** pX->iTable made to point to the ephemeral table instead of an +** existing table. +** +** The inFlags parameter must contain exactly one of the bits +** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP. If inFlags contains +** IN_INDEX_MEMBERSHIP, then the generated table will be used for a +** fast membership test. When the IN_INDEX_LOOP bit is set, the +** IN index will be used to loop over all values of the RHS of the +** IN operator. +** +** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate +** through the set members) then the b-tree must not contain duplicates. +** An epheremal table must be used unless the selected is guaranteed +** to be unique - either because it is an INTEGER PRIMARY KEY or it +** has a UNIQUE constraint or UNIQUE index. +** +** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used +** for fast set membership tests) then an epheremal table must +** be used unless is an INTEGER PRIMARY KEY or an index can +** be found with as its left-most column. +** +** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and +** if the RHS of the IN operator is a list (not a subquery) then this +** routine might decide that creating an ephemeral b-tree for membership +** testing is too expensive and return IN_INDEX_NOOP. In that case, the +** calling routine should implement the IN operator using a sequence +** of Eq or Ne comparison operations. +** +** When the b-tree is being used for membership tests, the calling function +** might need to know whether or not the RHS side of the IN operator +** contains a NULL. If prRhsHasNull is not a NULL pointer and +** if there is any chance that the (...) might contain a NULL value at +** runtime, then a register is allocated and the register number written +** to *prRhsHasNull. If there is no chance that the (...) contains a +** NULL value, then *prRhsHasNull is left unchanged. +** +** If a register is allocated and its location stored in *prRhsHasNull, then +** the value in that register will be NULL if the b-tree contains one or more +** NULL values, and it will be some non-NULL value if the b-tree contains no +** NULL values. +*/ +#ifndef SQLITE_OMIT_SUBQUERY +SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){ + Select *p; /* SELECT to the right of IN operator */ + int eType = 0; /* Type of RHS table. IN_INDEX_* */ + int iTab = pParse->nTab++; /* Cursor of the RHS table */ + int mustBeUnique; /* True if RHS must be unique */ + Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ + + assert( pX->op==TK_IN ); + mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0; + + /* Check to see if an existing table or index can be used to + ** satisfy the query. This is preferable to generating a new + ** ephemeral table. + */ + p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0); + if( pParse->nErr==0 && isCandidateForInOpt(p) ){ + sqlite3 *db = pParse->db; /* Database connection */ + Table *pTab; /* Table
    . */ + Expr *pExpr; /* Expression */ + i16 iCol; /* Index of column */ + i16 iDb; /* Database idx for pTab */ + + assert( p ); /* Because of isCandidateForInOpt(p) */ + assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ + assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ + assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ + pTab = p->pSrc->a[0].pTab; + pExpr = p->pEList->a[0].pExpr; + iCol = (i16)pExpr->iColumn; + + /* Code an OP_Transaction and OP_TableLock for
    . */ + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + sqlite3CodeVerifySchema(pParse, iDb); + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); + + /* This function is only called from two places. In both cases the vdbe + ** has already been allocated. So assume sqlite3GetVdbe() is always + ** successful here. + */ + assert(v); + if( iCol<0 ){ + int iAddr = sqlite3CodeOnce(pParse); + VdbeCoverage(v); + + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); + eType = IN_INDEX_ROWID; + + sqlite3VdbeJumpHere(v, iAddr); + }else{ + Index *pIdx; /* Iterator variable */ + + /* The collation sequence used by the comparison. If an index is to + ** be used in place of a temp-table, it must be ordered according + ** to this collation sequence. */ + CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr); + + /* Check that the affinity that will be used to perform the + ** comparison is the same as the affinity of the column. If + ** it is not, it is not possible to use any index. + */ + int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity); + + for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){ + if( (pIdx->aiColumn[0]==iCol) + && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq + && (!mustBeUnique || (pIdx->nKeyCol==1 && IsUniqueIndex(pIdx))) + ){ + int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); + sqlite3VdbeSetP4KeyInfo(pParse, pIdx); + VdbeComment((v, "%s", pIdx->zName)); + assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); + eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; + + if( prRhsHasNull && !pTab->aCol[iCol].notNull ){ + *prRhsHasNull = ++pParse->nMem; + sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull); + } + sqlite3VdbeJumpHere(v, iAddr); + } + } + } + } + + /* If no preexisting index is available for the IN clause + ** and IN_INDEX_NOOP is an allowed reply + ** and the RHS of the IN operator is a list, not a subquery + ** and the RHS is not contant or has two or fewer terms, + ** then it is not worth creating an ephemeral table to evaluate + ** the IN operator so return IN_INDEX_NOOP. + */ + if( eType==0 + && (inFlags & IN_INDEX_NOOP_OK) + && !ExprHasProperty(pX, EP_xIsSelect) + && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2) + ){ + eType = IN_INDEX_NOOP; + } + + + if( eType==0 ){ + /* Could not find an existing table or index to use as the RHS b-tree. + ** We will have to generate an ephemeral table to do the job. + */ + u32 savedNQueryLoop = pParse->nQueryLoop; + int rMayHaveNull = 0; + eType = IN_INDEX_EPH; + if( inFlags & IN_INDEX_LOOP ){ + pParse->nQueryLoop = 0; + if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){ + eType = IN_INDEX_ROWID; + } + }else if( prRhsHasNull ){ + *prRhsHasNull = rMayHaveNull = ++pParse->nMem; + } + sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID); + pParse->nQueryLoop = savedNQueryLoop; + }else{ + pX->iTable = iTab; + } + return eType; +} +#endif + +/* +** Generate code for scalar subqueries used as a subquery expression, EXISTS, +** or IN operators. Examples: +** +** (SELECT a FROM b) -- subquery +** EXISTS (SELECT a FROM b) -- EXISTS subquery +** x IN (4,5,11) -- IN operator with list on right-hand side +** x IN (SELECT a FROM b) -- IN operator with subquery on the right +** +** The pExpr parameter describes the expression that contains the IN +** operator or subquery. +** +** If parameter isRowid is non-zero, then expression pExpr is guaranteed +** to be of the form " IN (?, ?, ?)", where is a reference +** to some integer key column of a table B-Tree. In this case, use an +** intkey B-Tree to store the set of IN(...) values instead of the usual +** (slower) variable length keys B-Tree. +** +** If rMayHaveNull is non-zero, that means that the operation is an IN +** (not a SELECT or EXISTS) and that the RHS might contains NULLs. +** All this routine does is initialize the register given by rMayHaveNull +** to NULL. Calling routines will take care of changing this register +** value to non-NULL if the RHS is NULL-free. +** +** For a SELECT or EXISTS operator, return the register that holds the +** result. For IN operators or if an error occurs, the return value is 0. +*/ +#ifndef SQLITE_OMIT_SUBQUERY +SQLITE_PRIVATE int sqlite3CodeSubselect( + Parse *pParse, /* Parsing context */ + Expr *pExpr, /* The IN, SELECT, or EXISTS operator */ + int rHasNullFlag, /* Register that records whether NULLs exist in RHS */ + int isRowid /* If true, LHS of IN operator is a rowid */ +){ + int jmpIfDynamic = -1; /* One-time test address */ + int rReg = 0; /* Register storing resulting */ + Vdbe *v = sqlite3GetVdbe(pParse); + if( NEVER(v==0) ) return 0; + sqlite3ExprCachePush(pParse); + + /* This code must be run in its entirety every time it is encountered + ** if any of the following is true: + ** + ** * The right-hand side is a correlated subquery + ** * The right-hand side is an expression list containing variables + ** * We are inside a trigger + ** + ** If all of the above are false, then we can run this code just once + ** save the results, and reuse the same result on subsequent invocations. + */ + if( !ExprHasProperty(pExpr, EP_VarSelect) ){ + jmpIfDynamic = sqlite3CodeOnce(pParse); VdbeCoverage(v); + } + +#ifndef SQLITE_OMIT_EXPLAIN + if( pParse->explain==2 ){ + char *zMsg = sqlite3MPrintf( + pParse->db, "EXECUTE %s%s SUBQUERY %d", jmpIfDynamic>=0?"":"CORRELATED ", + pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId + ); + sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); + } +#endif + + switch( pExpr->op ){ + case TK_IN: { + char affinity; /* Affinity of the LHS of the IN */ + int addr; /* Address of OP_OpenEphemeral instruction */ + Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */ + KeyInfo *pKeyInfo = 0; /* Key information */ + + affinity = sqlite3ExprAffinity(pLeft); + + /* Whether this is an 'x IN(SELECT...)' or an 'x IN()' + ** expression it is handled the same way. An ephemeral table is + ** filled with single-field index keys representing the results + ** from the SELECT or the . + ** + ** If the 'x' expression is a column value, or the SELECT... + ** statement returns a column value, then the affinity of that + ** column is used to build the index keys. If both 'x' and the + ** SELECT... statement are columns, then numeric affinity is used + ** if either column has NUMERIC or INTEGER affinity. If neither + ** 'x' nor the SELECT... statement are columns, then numeric affinity + ** is used. + */ + pExpr->iTable = pParse->nTab++; + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); + pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1, 1); + + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + /* Case 1: expr IN (SELECT ...) + ** + ** Generate code to write the results of the select into the temporary + ** table allocated and opened above. + */ + Select *pSelect = pExpr->x.pSelect; + SelectDest dest; + ExprList *pEList; + + assert( !isRowid ); + sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); + dest.affSdst = (u8)affinity; + assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); + pSelect->iLimit = 0; + testcase( pSelect->selFlags & SF_Distinct ); + testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */ + if( sqlite3Select(pParse, pSelect, &dest) ){ + sqlite3KeyInfoUnref(pKeyInfo); + return 0; + } + pEList = pSelect->pEList; + assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */ + assert( pEList!=0 ); + assert( pEList->nExpr>0 ); + assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); + pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, + pEList->a[0].pExpr); + }else if( ALWAYS(pExpr->x.pList!=0) ){ + /* Case 2: expr IN (exprlist) + ** + ** For each expression, build an index key from the evaluation and + ** store it in the temporary table. If is a column, then use + ** that columns affinity when building index keys. If is not + ** a column, use numeric affinity. + */ + int i; + ExprList *pList = pExpr->x.pList; + struct ExprList_item *pItem; + int r1, r2, r3; + + if( !affinity ){ + affinity = SQLITE_AFF_BLOB; + } + if( pKeyInfo ){ + assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); + pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft); + } + + /* Loop through each expression in . */ + r1 = sqlite3GetTempReg(pParse); + r2 = sqlite3GetTempReg(pParse); + if( isRowid ) sqlite3VdbeAddOp2(v, OP_Null, 0, r2); + for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ + Expr *pE2 = pItem->pExpr; + int iValToIns; + + /* If the expression is not constant then we will need to + ** disable the test that was generated above that makes sure + ** this code only executes once. Because for a non-constant + ** expression we need to rerun this code each time. + */ + if( jmpIfDynamic>=0 && !sqlite3ExprIsConstant(pE2) ){ + sqlite3VdbeChangeToNoop(v, jmpIfDynamic); + jmpIfDynamic = -1; + } + + /* Evaluate the expression and insert it into the temp table */ + if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){ + sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns); + }else{ + r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); + if( isRowid ){ + sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, + sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); + }else{ + sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); + sqlite3ExprCacheAffinityChange(pParse, r3, 1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); + } + } + } + sqlite3ReleaseTempReg(pParse, r1); + sqlite3ReleaseTempReg(pParse, r2); + } + if( pKeyInfo ){ + sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO); + } + break; + } + + case TK_EXISTS: + case TK_SELECT: + default: { + /* If this has to be a scalar SELECT. Generate code to put the + ** value of this select in a memory cell and record the number + ** of the memory cell in iColumn. If this is an EXISTS, write + ** an integer 0 (not exists) or 1 (exists) into a memory cell + ** and record that memory cell in iColumn. + */ + Select *pSel; /* SELECT statement to encode */ + SelectDest dest; /* How to deal with SELECt result */ + + testcase( pExpr->op==TK_EXISTS ); + testcase( pExpr->op==TK_SELECT ); + assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); + + assert( ExprHasProperty(pExpr, EP_xIsSelect) ); + pSel = pExpr->x.pSelect; + sqlite3SelectDestInit(&dest, 0, ++pParse->nMem); + if( pExpr->op==TK_SELECT ){ + dest.eDest = SRT_Mem; + dest.iSdst = dest.iSDParm; + sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iSDParm); + VdbeComment((v, "Init subquery result")); + }else{ + dest.eDest = SRT_Exists; + sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm); + VdbeComment((v, "Init EXISTS result")); + } + sqlite3ExprDelete(pParse->db, pSel->pLimit); + pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, + &sqlite3IntTokens[1]); + pSel->iLimit = 0; + pSel->selFlags &= ~SF_MultiValue; + if( sqlite3Select(pParse, pSel, &dest) ){ + return 0; + } + rReg = dest.iSDParm; + ExprSetVVAProperty(pExpr, EP_NoReduce); + break; + } + } + + if( rHasNullFlag ){ + sqlite3SetHasNullFlag(v, pExpr->iTable, rHasNullFlag); + } + + if( jmpIfDynamic>=0 ){ + sqlite3VdbeJumpHere(v, jmpIfDynamic); + } + sqlite3ExprCachePop(pParse); + + return rReg; +} +#endif /* SQLITE_OMIT_SUBQUERY */ + +#ifndef SQLITE_OMIT_SUBQUERY +/* +** Generate code for an IN expression. +** +** x IN (SELECT ...) +** x IN (value, value, ...) +** +** The left-hand side (LHS) is a scalar expression. The right-hand side (RHS) +** is an array of zero or more values. The expression is true if the LHS is +** contained within the RHS. The value of the expression is unknown (NULL) +** if the LHS is NULL or if the LHS is not contained within the RHS and the +** RHS contains one or more NULL values. +** +** This routine generates code that jumps to destIfFalse if the LHS is not +** contained within the RHS. If due to NULLs we cannot determine if the LHS +** is contained in the RHS then jump to destIfNull. If the LHS is contained +** within the RHS then fall through. +*/ +static void sqlite3ExprCodeIN( + Parse *pParse, /* Parsing and code generating context */ + Expr *pExpr, /* The IN expression */ + int destIfFalse, /* Jump here if LHS is not contained in the RHS */ + int destIfNull /* Jump here if the results are unknown due to NULLs */ +){ + int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */ + char affinity; /* Comparison affinity to use */ + int eType; /* Type of the RHS */ + int r1; /* Temporary use register */ + Vdbe *v; /* Statement under construction */ + + /* Compute the RHS. After this step, the table with cursor + ** pExpr->iTable will contains the values that make up the RHS. + */ + v = pParse->pVdbe; + assert( v!=0 ); /* OOM detected prior to this routine */ + VdbeNoopComment((v, "begin IN expr")); + eType = sqlite3FindInIndex(pParse, pExpr, + IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK, + destIfFalse==destIfNull ? 0 : &rRhsHasNull); + + /* Figure out the affinity to use to create a key from the results + ** of the expression. affinityStr stores a static string suitable for + ** P4 of OP_MakeRecord. + */ + affinity = comparisonAffinity(pExpr); + + /* Code the LHS, the from " IN (...)". + */ + sqlite3ExprCachePush(pParse); + r1 = sqlite3GetTempReg(pParse); + sqlite3ExprCode(pParse, pExpr->pLeft, r1); + + /* If sqlite3FindInIndex() did not find or create an index that is + ** suitable for evaluating the IN operator, then evaluate using a + ** sequence of comparisons. + */ + if( eType==IN_INDEX_NOOP ){ + ExprList *pList = pExpr->x.pList; + CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); + int labelOk = sqlite3VdbeMakeLabel(v); + int r2, regToFree; + int regCkNull = 0; + int ii; + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + if( destIfNull!=destIfFalse ){ + regCkNull = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_BitAnd, r1, r1, regCkNull); + } + for(ii=0; iinExpr; ii++){ + r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree); + if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){ + sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull); + } + if( iinExpr-1 || destIfNull!=destIfFalse ){ + sqlite3VdbeAddOp4(v, OP_Eq, r1, labelOk, r2, + (void*)pColl, P4_COLLSEQ); + VdbeCoverageIf(v, iinExpr-1); + VdbeCoverageIf(v, ii==pList->nExpr-1); + sqlite3VdbeChangeP5(v, affinity); + }else{ + assert( destIfNull==destIfFalse ); + sqlite3VdbeAddOp4(v, OP_Ne, r1, destIfFalse, r2, + (void*)pColl, P4_COLLSEQ); VdbeCoverage(v); + sqlite3VdbeChangeP5(v, affinity | SQLITE_JUMPIFNULL); + } + sqlite3ReleaseTempReg(pParse, regToFree); + } + if( regCkNull ){ + sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); + } + sqlite3VdbeResolveLabel(v, labelOk); + sqlite3ReleaseTempReg(pParse, regCkNull); + }else{ + + /* If the LHS is NULL, then the result is either false or NULL depending + ** on whether the RHS is empty or not, respectively. + */ + if( sqlite3ExprCanBeNull(pExpr->pLeft) ){ + if( destIfNull==destIfFalse ){ + /* Shortcut for the common case where the false and NULL outcomes are + ** the same. */ + sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v); + }else{ + int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); + VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); + sqlite3VdbeJumpHere(v, addr1); + } + } + + if( eType==IN_INDEX_ROWID ){ + /* In this case, the RHS is the ROWID of table b-tree + */ + sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1); + VdbeCoverage(v); + }else{ + /* In this case, the RHS is an index b-tree. + */ + sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1); + + /* If the set membership test fails, then the result of the + ** "x IN (...)" expression must be either 0 or NULL. If the set + ** contains no NULL values, then the result is 0. If the set + ** contains one or more NULL values, then the result of the + ** expression is also NULL. + */ + assert( destIfFalse!=destIfNull || rRhsHasNull==0 ); + if( rRhsHasNull==0 ){ + /* This branch runs if it is known at compile time that the RHS + ** cannot contain NULL values. This happens as the result + ** of a "NOT NULL" constraint in the database schema. + ** + ** Also run this branch if NULL is equivalent to FALSE + ** for this particular IN operator. + */ + sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1); + VdbeCoverage(v); + }else{ + /* In this branch, the RHS of the IN might contain a NULL and + ** the presence of a NULL on the RHS makes a difference in the + ** outcome. + */ + int j1; + + /* First check to see if the LHS is contained in the RHS. If so, + ** then the answer is TRUE the presence of NULLs in the RHS does + ** not matter. If the LHS is not contained in the RHS, then the + ** answer is NULL if the RHS contains NULLs and the answer is + ** FALSE if the RHS is NULL-free. + */ + j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1); + VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_IsNull, rRhsHasNull, destIfNull); + VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); + sqlite3VdbeJumpHere(v, j1); + } + } + } + sqlite3ReleaseTempReg(pParse, r1); + sqlite3ExprCachePop(pParse); + VdbeComment((v, "end IN expr")); +} +#endif /* SQLITE_OMIT_SUBQUERY */ + +#ifndef SQLITE_OMIT_FLOATING_POINT +/* +** Generate an instruction that will put the floating point +** value described by z[0..n-1] into register iMem. +** +** The z[] string will probably not be zero-terminated. But the +** z[n] character is guaranteed to be something that does not look +** like the continuation of the number. +*/ +static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ + if( ALWAYS(z!=0) ){ + double value; + sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); + assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */ + if( negateFlag ) value = -value; + sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL); + } +} +#endif + + +/* +** Generate an instruction that will put the integer describe by +** text z[0..n-1] into register iMem. +** +** Expr.u.zToken is always UTF8 and zero-terminated. +*/ +static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ + Vdbe *v = pParse->pVdbe; + if( pExpr->flags & EP_IntValue ){ + int i = pExpr->u.iValue; + assert( i>=0 ); + if( negFlag ) i = -i; + sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); + }else{ + int c; + i64 value; + const char *z = pExpr->u.zToken; + assert( z!=0 ); + c = sqlite3DecOrHexToI64(z, &value); + if( c==0 || (c==2 && negFlag) ){ + if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; } + sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64); + }else{ +#ifdef SQLITE_OMIT_FLOATING_POINT + sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); +#else +#ifndef SQLITE_OMIT_HEX_INTEGER + if( sqlite3_strnicmp(z,"0x",2)==0 ){ + sqlite3ErrorMsg(pParse, "hex literal too big: %s", z); + }else +#endif + { + codeReal(v, z, negFlag, iMem); + } +#endif + } + } +} + +/* +** Clear a cache entry. +*/ +static void cacheEntryClear(Parse *pParse, struct yColCache *p){ + if( p->tempReg ){ + if( pParse->nTempRegaTempReg) ){ + pParse->aTempReg[pParse->nTempReg++] = p->iReg; + } + p->tempReg = 0; + } +} + + +/* +** Record in the column cache that a particular column from a +** particular table is stored in a particular register. +*/ +SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ + int i; + int minLru; + int idxLru; + struct yColCache *p; + + /* Unless an error has occurred, register numbers are always positive. */ + assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed ); + assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ + + /* The SQLITE_ColumnCache flag disables the column cache. This is used + ** for testing only - to verify that SQLite always gets the same answer + ** with and without the column cache. + */ + if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return; + + /* First replace any existing entry. + ** + ** Actually, the way the column cache is currently used, we are guaranteed + ** that the object will never already be in cache. Verify this guarantee. + */ +#ifndef NDEBUG + for(i=0, p=pParse->aColCache; iiReg==0 || p->iTable!=iTab || p->iColumn!=iCol ); + } +#endif + + /* Find an empty slot and replace it */ + for(i=0, p=pParse->aColCache; iiReg==0 ){ + p->iLevel = pParse->iCacheLevel; + p->iTable = iTab; + p->iColumn = iCol; + p->iReg = iReg; + p->tempReg = 0; + p->lru = pParse->iCacheCnt++; + return; + } + } + + /* Replace the last recently used */ + minLru = 0x7fffffff; + idxLru = -1; + for(i=0, p=pParse->aColCache; ilrulru; + } + } + if( ALWAYS(idxLru>=0) ){ + p = &pParse->aColCache[idxLru]; + p->iLevel = pParse->iCacheLevel; + p->iTable = iTab; + p->iColumn = iCol; + p->iReg = iReg; + p->tempReg = 0; + p->lru = pParse->iCacheCnt++; + return; + } +} + +/* +** Indicate that registers between iReg..iReg+nReg-1 are being overwritten. +** Purge the range of registers from the column cache. +*/ +SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){ + int i; + int iLast = iReg + nReg - 1; + struct yColCache *p; + for(i=0, p=pParse->aColCache; iiReg; + if( r>=iReg && r<=iLast ){ + cacheEntryClear(pParse, p); + p->iReg = 0; + } + } +} + +/* +** Remember the current column cache context. Any new entries added +** added to the column cache after this call are removed when the +** corresponding pop occurs. +*/ +SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){ + pParse->iCacheLevel++; +#ifdef SQLITE_DEBUG + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ + printf("PUSH to %d\n", pParse->iCacheLevel); + } +#endif +} + +/* +** Remove from the column cache any entries that were added since the +** the previous sqlite3ExprCachePush operation. In other words, restore +** the cache to the state it was in prior the most recent Push. +*/ +SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){ + int i; + struct yColCache *p; + assert( pParse->iCacheLevel>=1 ); + pParse->iCacheLevel--; +#ifdef SQLITE_DEBUG + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ + printf("POP to %d\n", pParse->iCacheLevel); + } +#endif + for(i=0, p=pParse->aColCache; iiReg && p->iLevel>pParse->iCacheLevel ){ + cacheEntryClear(pParse, p); + p->iReg = 0; + } + } +} + +/* +** When a cached column is reused, make sure that its register is +** no longer available as a temp register. ticket #3879: that same +** register might be in the cache in multiple places, so be sure to +** get them all. +*/ +static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ + int i; + struct yColCache *p; + for(i=0, p=pParse->aColCache; iiReg==iReg ){ + p->tempReg = 0; + } + } +} + +/* +** Generate code to extract the value of the iCol-th column of a table. +*/ +SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable( + Vdbe *v, /* The VDBE under construction */ + Table *pTab, /* The table containing the value */ + int iTabCur, /* The table cursor. Or the PK cursor for WITHOUT ROWID */ + int iCol, /* Index of the column to extract */ + int regOut /* Extract the value into this register */ +){ + if( iCol<0 || iCol==pTab->iPKey ){ + sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut); + }else{ + int op = IsVirtual(pTab) ? OP_VColumn : OP_Column; + int x = iCol; + if( !HasRowid(pTab) ){ + x = sqlite3ColumnOfIndex(sqlite3PrimaryKeyIndex(pTab), iCol); + } + sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut); + } + if( iCol>=0 ){ + sqlite3ColumnDefault(v, pTab, iCol, regOut); + } +} + +/* +** Generate code that will extract the iColumn-th column from +** table pTab and store the column value in a register. An effort +** is made to store the column value in register iReg, but this is +** not guaranteed. The location of the column value is returned. +** +** There must be an open cursor to pTab in iTable when this routine +** is called. If iColumn<0 then code is generated that extracts the rowid. +*/ +SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( + Parse *pParse, /* Parsing and code generating context */ + Table *pTab, /* Description of the table we are reading from */ + int iColumn, /* Index of the table column */ + int iTable, /* The cursor pointing to the table */ + int iReg, /* Store results here */ + u8 p5 /* P5 value for OP_Column */ +){ + Vdbe *v = pParse->pVdbe; + int i; + struct yColCache *p; + + for(i=0, p=pParse->aColCache; iiReg>0 && p->iTable==iTable && p->iColumn==iColumn ){ + p->lru = pParse->iCacheCnt++; + sqlite3ExprCachePinRegister(pParse, p->iReg); + return p->iReg; + } + } + assert( v!=0 ); + sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg); + if( p5 ){ + sqlite3VdbeChangeP5(v, p5); + }else{ + sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg); + } + return iReg; +} + +/* +** Clear all column cache entries. +*/ +SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ + int i; + struct yColCache *p; + +#if SQLITE_DEBUG + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ + printf("CLEAR\n"); + } +#endif + for(i=0, p=pParse->aColCache; iiReg ){ + cacheEntryClear(pParse, p); + p->iReg = 0; + } + } +} + +/* +** Record the fact that an affinity change has occurred on iCount +** registers starting with iStart. +*/ +SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){ + sqlite3ExprCacheRemove(pParse, iStart, iCount); +} + +/* +** Generate code to move content from registers iFrom...iFrom+nReg-1 +** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. +*/ +SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ + assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo ); + sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg); + sqlite3ExprCacheRemove(pParse, iFrom, nReg); +} + +#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) +/* +** Return true if any register in the range iFrom..iTo (inclusive) +** is used as part of the column cache. +** +** This routine is used within assert() and testcase() macros only +** and does not appear in a normal build. +*/ +static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ + int i; + struct yColCache *p; + for(i=0, p=pParse->aColCache; iiReg; + if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/ + } + return 0; +} +#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */ + +/* +** Convert an expression node to a TK_REGISTER +*/ +static void exprToRegister(Expr *p, int iReg){ + p->op2 = p->op; + p->op = TK_REGISTER; + p->iTable = iReg; + ExprClearProperty(p, EP_Skip); +} + +/* +** Generate code into the current Vdbe to evaluate the given +** expression. Attempt to store the results in register "target". +** Return the register where results are stored. +** +** With this routine, there is no guarantee that results will +** be stored in target. The result might be stored in some other +** register if it is convenient to do so. The calling function +** must check the return code and move the results to the desired +** register. +*/ +SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ + Vdbe *v = pParse->pVdbe; /* The VM under construction */ + int op; /* The opcode being coded */ + int inReg = target; /* Results stored in register inReg */ + int regFree1 = 0; /* If non-zero free this temporary register */ + int regFree2 = 0; /* If non-zero free this temporary register */ + int r1, r2, r3, r4; /* Various register numbers */ + sqlite3 *db = pParse->db; /* The database connection */ + Expr tempX; /* Temporary expression node */ + + assert( target>0 && target<=pParse->nMem ); + if( v==0 ){ + assert( pParse->db->mallocFailed ); + return 0; + } + + if( pExpr==0 ){ + op = TK_NULL; + }else{ + op = pExpr->op; + } + switch( op ){ + case TK_AGG_COLUMN: { + AggInfo *pAggInfo = pExpr->pAggInfo; + struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg]; + if( !pAggInfo->directMode ){ + assert( pCol->iMem>0 ); + inReg = pCol->iMem; + break; + }else if( pAggInfo->useSortingIdx ){ + sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, + pCol->iSorterColumn, target); + break; + } + /* Otherwise, fall thru into the TK_COLUMN case */ + } + case TK_COLUMN: { + int iTab = pExpr->iTable; + if( iTab<0 ){ + if( pParse->ckBase>0 ){ + /* Generating CHECK constraints or inserting into partial index */ + inReg = pExpr->iColumn + pParse->ckBase; + break; + }else{ + /* Deleting from a partial index */ + iTab = pParse->iPartIdxTab; + } + } + inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, + pExpr->iColumn, iTab, target, + pExpr->op2); + break; + } + case TK_INTEGER: { + codeInteger(pParse, pExpr, 0, target); + break; + } +#ifndef SQLITE_OMIT_FLOATING_POINT + case TK_FLOAT: { + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + codeReal(v, pExpr->u.zToken, 0, target); + break; + } +#endif + case TK_STRING: { + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0); + break; + } + case TK_NULL: { + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + break; + } +#ifndef SQLITE_OMIT_BLOB_LITERAL + case TK_BLOB: { + int n; + const char *z; + char *zBlob; + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); + assert( pExpr->u.zToken[1]=='\'' ); + z = &pExpr->u.zToken[2]; + n = sqlite3Strlen30(z) - 1; + assert( z[n]=='\'' ); + zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n); + sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC); + break; + } +#endif + case TK_VARIABLE: { + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + assert( pExpr->u.zToken!=0 ); + assert( pExpr->u.zToken[0]!=0 ); + sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target); + if( pExpr->u.zToken[1]!=0 ){ + assert( pExpr->u.zToken[0]=='?' + || strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 ); + sqlite3VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC); + } + break; + } + case TK_REGISTER: { + inReg = pExpr->iTable; + break; + } + case TK_AS: { + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + break; + } +#ifndef SQLITE_OMIT_CAST + case TK_CAST: { + /* Expressions of the form: CAST(pLeft AS token) */ + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + if( inReg!=target ){ + sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); + inReg = target; + } + sqlite3VdbeAddOp2(v, OP_Cast, target, + sqlite3AffinityType(pExpr->u.zToken, 0)); + testcase( usedAsColumnCache(pParse, inReg, inReg) ); + sqlite3ExprCacheAffinityChange(pParse, inReg, 1); + break; + } +#endif /* SQLITE_OMIT_CAST */ + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_NE: + case TK_EQ: { + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + r1, r2, inReg, SQLITE_STOREP2); + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + break; + } + case TK_IS: + case TK_ISNOT: { + testcase( op==TK_IS ); + testcase( op==TK_ISNOT ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + op = (op==TK_IS) ? TK_EQ : TK_NE; + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ); + VdbeCoverageIf(v, op==TK_EQ); + VdbeCoverageIf(v, op==TK_NE); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + break; + } + case TK_AND: + case TK_OR: + case TK_PLUS: + case TK_STAR: + case TK_MINUS: + case TK_REM: + case TK_BITAND: + case TK_BITOR: + case TK_SLASH: + case TK_LSHIFT: + case TK_RSHIFT: + case TK_CONCAT: { + assert( TK_AND==OP_And ); testcase( op==TK_AND ); + assert( TK_OR==OP_Or ); testcase( op==TK_OR ); + assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS ); + assert( TK_MINUS==OP_Subtract ); testcase( op==TK_MINUS ); + assert( TK_REM==OP_Remainder ); testcase( op==TK_REM ); + assert( TK_BITAND==OP_BitAnd ); testcase( op==TK_BITAND ); + assert( TK_BITOR==OP_BitOr ); testcase( op==TK_BITOR ); + assert( TK_SLASH==OP_Divide ); testcase( op==TK_SLASH ); + assert( TK_LSHIFT==OP_ShiftLeft ); testcase( op==TK_LSHIFT ); + assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT ); + assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + sqlite3VdbeAddOp3(v, op, r2, r1, target); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + break; + } + case TK_UMINUS: { + Expr *pLeft = pExpr->pLeft; + assert( pLeft ); + if( pLeft->op==TK_INTEGER ){ + codeInteger(pParse, pLeft, 1, target); +#ifndef SQLITE_OMIT_FLOATING_POINT + }else if( pLeft->op==TK_FLOAT ){ + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + codeReal(v, pLeft->u.zToken, 1, target); +#endif + }else{ + tempX.op = TK_INTEGER; + tempX.flags = EP_IntValue|EP_TokenOnly; + tempX.u.iValue = 0; + r1 = sqlite3ExprCodeTemp(pParse, &tempX, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2); + sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); + testcase( regFree2==0 ); + } + inReg = target; + break; + } + case TK_BITNOT: + case TK_NOT: { + assert( TK_BITNOT==OP_BitNot ); testcase( op==TK_BITNOT ); + assert( TK_NOT==OP_Not ); testcase( op==TK_NOT ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + testcase( regFree1==0 ); + inReg = target; + sqlite3VdbeAddOp2(v, op, r1, inReg); + break; + } + case TK_ISNULL: + case TK_NOTNULL: { + int addr; + assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL ); + assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL ); + sqlite3VdbeAddOp2(v, OP_Integer, 1, target); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + testcase( regFree1==0 ); + addr = sqlite3VdbeAddOp1(v, op, r1); + VdbeCoverageIf(v, op==TK_ISNULL); + VdbeCoverageIf(v, op==TK_NOTNULL); + sqlite3VdbeAddOp2(v, OP_Integer, 0, target); + sqlite3VdbeJumpHere(v, addr); + break; + } + case TK_AGG_FUNCTION: { + AggInfo *pInfo = pExpr->pAggInfo; + if( pInfo==0 ){ + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken); + }else{ + inReg = pInfo->aFunc[pExpr->iAgg].iMem; + } + break; + } + case TK_FUNCTION: { + ExprList *pFarg; /* List of function arguments */ + int nFarg; /* Number of function arguments */ + FuncDef *pDef; /* The function definition object */ + int nId; /* Length of the function name in bytes */ + const char *zId; /* The function name */ + u32 constMask = 0; /* Mask of function arguments that are constant */ + int i; /* Loop counter */ + u8 enc = ENC(db); /* The text encoding used by this database */ + CollSeq *pColl = 0; /* A collating sequence */ + + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + if( ExprHasProperty(pExpr, EP_TokenOnly) ){ + pFarg = 0; + }else{ + pFarg = pExpr->x.pList; + } + nFarg = pFarg ? pFarg->nExpr : 0; + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + zId = pExpr->u.zToken; + nId = sqlite3Strlen30(zId); + pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0); + if( pDef==0 || pDef->xFunc==0 ){ + sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId); + break; + } + + /* Attempt a direct implementation of the built-in COALESCE() and + ** IFNULL() functions. This avoids unnecessary evaluation of + ** arguments past the first non-NULL argument. + */ + if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){ + int endCoalesce = sqlite3VdbeMakeLabel(v); + assert( nFarg>=2 ); + sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); + for(i=1; ia[i].pExpr, target); + sqlite3ExprCachePop(pParse); + } + sqlite3VdbeResolveLabel(v, endCoalesce); + break; + } + + /* The UNLIKELY() function is a no-op. The result is the value + ** of the first argument. + */ + if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ + assert( nFarg>=1 ); + inReg = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target); + break; + } + + for(i=0; ia[i].pExpr) ){ + testcase( i==31 ); + constMask |= MASKBIT32(i); + } + if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ + pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr); + } + } + if( pFarg ){ + if( constMask ){ + r1 = pParse->nMem+1; + pParse->nMem += nFarg; + }else{ + r1 = sqlite3GetTempRange(pParse, nFarg); + } + + /* For length() and typeof() functions with a column argument, + ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG + ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data + ** loading. + */ + if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){ + u8 exprOp; + assert( nFarg==1 ); + assert( pFarg->a[0].pExpr!=0 ); + exprOp = pFarg->a[0].pExpr->op; + if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){ + assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG ); + assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG ); + testcase( pDef->funcFlags & OPFLAG_LENGTHARG ); + pFarg->a[0].pExpr->op2 = + pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG); + } + } + + sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ + sqlite3ExprCodeExprList(pParse, pFarg, r1, + SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); + sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */ + }else{ + r1 = 0; + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + /* Possibly overload the function if the first argument is + ** a virtual table column. + ** + ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the + ** second argument, not the first, as the argument to test to + ** see if it is a column in a virtual table. This is done because + ** the left operand of infix functions (the operand we want to + ** control overloading) ends up as the second argument to the + ** function. The expression "A glob B" is equivalent to + ** "glob(B,A). We want to use the A in "A glob B" to test + ** for function overloading. But we use the B term in "glob(B,A)". + */ + if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){ + pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr); + }else if( nFarg>0 ){ + pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr); + } +#endif + if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){ + if( !pColl ) pColl = db->pDfltColl; + sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); + } + sqlite3VdbeAddOp4(v, OP_Function0, constMask, r1, target, + (char*)pDef, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, (u8)nFarg); + if( nFarg && constMask==0 ){ + sqlite3ReleaseTempRange(pParse, r1, nFarg); + } + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_EXISTS: + case TK_SELECT: { + testcase( op==TK_EXISTS ); + testcase( op==TK_SELECT ); + inReg = sqlite3CodeSubselect(pParse, pExpr, 0, 0); + break; + } + case TK_IN: { + int destIfFalse = sqlite3VdbeMakeLabel(v); + int destIfNull = sqlite3VdbeMakeLabel(v); + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull); + sqlite3VdbeAddOp2(v, OP_Integer, 1, target); + sqlite3VdbeResolveLabel(v, destIfFalse); + sqlite3VdbeAddOp2(v, OP_AddImm, target, 0); + sqlite3VdbeResolveLabel(v, destIfNull); + break; + } +#endif /* SQLITE_OMIT_SUBQUERY */ + + + /* + ** x BETWEEN y AND z + ** + ** This is equivalent to + ** + ** x>=y AND x<=z + ** + ** X is stored in pExpr->pLeft. + ** Y is stored in pExpr->pList->a[0].pExpr. + ** Z is stored in pExpr->pList->a[1].pExpr. + */ + case TK_BETWEEN: { + Expr *pLeft = pExpr->pLeft; + struct ExprList_item *pLItem = pExpr->x.pList->a; + Expr *pRight = pLItem->pExpr; + + r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + r3 = sqlite3GetTempReg(pParse); + r4 = sqlite3GetTempReg(pParse); + codeCompare(pParse, pLeft, pRight, OP_Ge, + r1, r2, r3, SQLITE_STOREP2); VdbeCoverage(v); + pLItem++; + pRight = pLItem->pExpr; + sqlite3ReleaseTempReg(pParse, regFree2); + r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); + testcase( regFree2==0 ); + codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); + VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); + sqlite3ReleaseTempReg(pParse, r3); + sqlite3ReleaseTempReg(pParse, r4); + break; + } + case TK_COLLATE: + case TK_UPLUS: { + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + break; + } + + case TK_TRIGGER: { + /* If the opcode is TK_TRIGGER, then the expression is a reference + ** to a column in the new.* or old.* pseudo-tables available to + ** trigger programs. In this case Expr.iTable is set to 1 for the + ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn + ** is set to the column of the pseudo-table to read, or to -1 to + ** read the rowid field. + ** + ** The expression is implemented using an OP_Param opcode. The p1 + ** parameter is set to 0 for an old.rowid reference, or to (i+1) + ** to reference another column of the old.* pseudo-table, where + ** i is the index of the column. For a new.rowid reference, p1 is + ** set to (n+1), where n is the number of columns in each pseudo-table. + ** For a reference to any other column in the new.* pseudo-table, p1 + ** is set to (n+2+i), where n and i are as defined previously. For + ** example, if the table on which triggers are being fired is + ** declared as: + ** + ** CREATE TABLE t1(a, b); + ** + ** Then p1 is interpreted as follows: + ** + ** p1==0 -> old.rowid p1==3 -> new.rowid + ** p1==1 -> old.a p1==4 -> new.a + ** p1==2 -> old.b p1==5 -> new.b + */ + Table *pTab = pExpr->pTab; + int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn; + + assert( pExpr->iTable==0 || pExpr->iTable==1 ); + assert( pExpr->iColumn>=-1 && pExpr->iColumnnCol ); + assert( pTab->iPKey<0 || pExpr->iColumn!=pTab->iPKey ); + assert( p1>=0 && p1<(pTab->nCol*2+2) ); + + sqlite3VdbeAddOp2(v, OP_Param, p1, target); + VdbeComment((v, "%s.%s -> $%d", + (pExpr->iTable ? "new" : "old"), + (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName), + target + )); + +#ifndef SQLITE_OMIT_FLOATING_POINT + /* If the column has REAL affinity, it may currently be stored as an + ** integer. Use OP_RealAffinity to make sure it is really real. + ** + ** EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to + ** floating point when extracting it from the record. */ + if( pExpr->iColumn>=0 + && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL + ){ + sqlite3VdbeAddOp1(v, OP_RealAffinity, target); + } +#endif + break; + } + + + /* + ** Form A: + ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END + ** + ** Form B: + ** CASE WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END + ** + ** Form A is can be transformed into the equivalent form B as follows: + ** CASE WHEN x=e1 THEN r1 WHEN x=e2 THEN r2 ... + ** WHEN x=eN THEN rN ELSE y END + ** + ** X (if it exists) is in pExpr->pLeft. + ** Y is in the last element of pExpr->x.pList if pExpr->x.pList->nExpr is + ** odd. The Y is also optional. If the number of elements in x.pList + ** is even, then Y is omitted and the "otherwise" result is NULL. + ** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1]. + ** + ** The result of the expression is the Ri for the first matching Ei, + ** or if there is no matching Ei, the ELSE term Y, or if there is + ** no ELSE term, NULL. + */ + default: assert( op==TK_CASE ); { + int endLabel; /* GOTO label for end of CASE stmt */ + int nextCase; /* GOTO label for next WHEN clause */ + int nExpr; /* 2x number of WHEN terms */ + int i; /* Loop counter */ + ExprList *pEList; /* List of WHEN terms */ + struct ExprList_item *aListelem; /* Array of WHEN terms */ + Expr opCompare; /* The X==Ei expression */ + Expr *pX; /* The X expression */ + Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ + VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; ) + + assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); + assert(pExpr->x.pList->nExpr > 0); + pEList = pExpr->x.pList; + aListelem = pEList->a; + nExpr = pEList->nExpr; + endLabel = sqlite3VdbeMakeLabel(v); + if( (pX = pExpr->pLeft)!=0 ){ + tempX = *pX; + testcase( pX->op==TK_COLUMN ); + exprToRegister(&tempX, sqlite3ExprCodeTemp(pParse, pX, ®Free1)); + testcase( regFree1==0 ); + opCompare.op = TK_EQ; + opCompare.pLeft = &tempX; + pTest = &opCompare; + /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001: + ** The value in regFree1 might get SCopy-ed into the file result. + ** So make sure that the regFree1 register is not reused for other + ** purposes and possibly overwritten. */ + regFree1 = 0; + } + for(i=0; iop==TK_COLUMN ); + sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL); + testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); + sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); + sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel); + sqlite3ExprCachePop(pParse); + sqlite3VdbeResolveLabel(v, nextCase); + } + if( (nExpr&1)!=0 ){ + sqlite3ExprCachePush(pParse); + sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target); + sqlite3ExprCachePop(pParse); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + } + assert( db->mallocFailed || pParse->nErr>0 + || pParse->iCacheLevel==iCacheLevel ); + sqlite3VdbeResolveLabel(v, endLabel); + break; + } +#ifndef SQLITE_OMIT_TRIGGER + case TK_RAISE: { + assert( pExpr->affinity==OE_Rollback + || pExpr->affinity==OE_Abort + || pExpr->affinity==OE_Fail + || pExpr->affinity==OE_Ignore + ); + if( !pParse->pTriggerTab ){ + sqlite3ErrorMsg(pParse, + "RAISE() may only be used within a trigger-program"); + return 0; + } + if( pExpr->affinity==OE_Abort ){ + sqlite3MayAbort(pParse); + } + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + if( pExpr->affinity==OE_Ignore ){ + sqlite3VdbeAddOp4( + v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0); + VdbeCoverage(v); + }else{ + sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER, + pExpr->affinity, pExpr->u.zToken, 0, 0); + } + + break; + } +#endif + } + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); + return inReg; +} + +/* +** Factor out the code of the given expression to initialization time. +*/ +SQLITE_PRIVATE void sqlite3ExprCodeAtInit( + Parse *pParse, /* Parsing context */ + Expr *pExpr, /* The expression to code when the VDBE initializes */ + int regDest, /* Store the value in this register */ + u8 reusable /* True if this expression is reusable */ +){ + ExprList *p; + assert( ConstFactorOk(pParse) ); + p = pParse->pConstExpr; + pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); + p = sqlite3ExprListAppend(pParse, p, pExpr); + if( p ){ + struct ExprList_item *pItem = &p->a[p->nExpr-1]; + pItem->u.iConstExprReg = regDest; + pItem->reusable = reusable; + } + pParse->pConstExpr = p; +} + +/* +** Generate code to evaluate an expression and store the results +** into a register. Return the register number where the results +** are stored. +** +** If the register is a temporary register that can be deallocated, +** then write its number into *pReg. If the result register is not +** a temporary, then set *pReg to zero. +** +** If pExpr is a constant, then this routine might generate this +** code to fill the register in the initialization section of the +** VDBE program, in order to factor it out of the evaluation loop. +*/ +SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ + int r2; + pExpr = sqlite3ExprSkipCollate(pExpr); + if( ConstFactorOk(pParse) + && pExpr->op!=TK_REGISTER + && sqlite3ExprIsConstantNotJoin(pExpr) + ){ + ExprList *p = pParse->pConstExpr; + int i; + *pReg = 0; + if( p ){ + struct ExprList_item *pItem; + for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){ + if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){ + return pItem->u.iConstExprReg; + } + } + } + r2 = ++pParse->nMem; + sqlite3ExprCodeAtInit(pParse, pExpr, r2, 1); + }else{ + int r1 = sqlite3GetTempReg(pParse); + r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); + if( r2==r1 ){ + *pReg = r1; + }else{ + sqlite3ReleaseTempReg(pParse, r1); + *pReg = 0; + } + } + return r2; +} + +/* +** Generate code that will evaluate expression pExpr and store the +** results in register target. The results are guaranteed to appear +** in register target. +*/ +SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ + int inReg; + + assert( target>0 && target<=pParse->nMem ); + if( pExpr && pExpr->op==TK_REGISTER ){ + sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target); + }else{ + inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); + assert( pParse->pVdbe || pParse->db->mallocFailed ); + if( inReg!=target && pParse->pVdbe ){ + sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target); + } + } +} + +/* +** Generate code that will evaluate expression pExpr and store the +** results in register target. The results are guaranteed to appear +** in register target. If the expression is constant, then this routine +** might choose to code the expression at initialization time. +*/ +SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){ + if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){ + sqlite3ExprCodeAtInit(pParse, pExpr, target, 0); + }else{ + sqlite3ExprCode(pParse, pExpr, target); + } +} + +/* +** Generate code that evaluates the given expression and puts the result +** in register target. +** +** Also make a copy of the expression results into another "cache" register +** and modify the expression so that the next time it is evaluated, +** the result is a copy of the cache register. +** +** This routine is used for expressions that are used multiple +** times. They are evaluated once and the results of the expression +** are reused. +*/ +SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){ + Vdbe *v = pParse->pVdbe; + int iMem; + + assert( target>0 ); + assert( pExpr->op!=TK_REGISTER ); + sqlite3ExprCode(pParse, pExpr, target); + iMem = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Copy, target, iMem); + exprToRegister(pExpr, iMem); +} + +/* +** Generate code that pushes the value of every element of the given +** expression list into a sequence of registers beginning at target. +** +** Return the number of elements evaluated. +** +** The SQLITE_ECEL_DUP flag prevents the arguments from being +** filled using OP_SCopy. OP_Copy must be used instead. +** +** The SQLITE_ECEL_FACTOR argument allows constant arguments to be +** factored out into initialization code. +*/ +SQLITE_PRIVATE int sqlite3ExprCodeExprList( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* The expression list to be coded */ + int target, /* Where to write results */ + u8 flags /* SQLITE_ECEL_* flags */ +){ + struct ExprList_item *pItem; + int i, n; + u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy; + assert( pList!=0 ); + assert( target>0 ); + assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ + n = pList->nExpr; + if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; + for(pItem=pList->a, i=0; ipExpr; + if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ + sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0); + }else{ + int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); + if( inReg!=target+i ){ + VdbeOp *pOp; + Vdbe *v = pParse->pVdbe; + if( copyOp==OP_Copy + && (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy + && pOp->p1+pOp->p3+1==inReg + && pOp->p2+pOp->p3+1==target+i + ){ + pOp->p3++; + }else{ + sqlite3VdbeAddOp2(v, copyOp, inReg, target+i); + } + } + } + } + return n; +} + +/* +** Generate code for a BETWEEN operator. +** +** x BETWEEN y AND z +** +** The above is equivalent to +** +** x>=y AND x<=z +** +** Code it as such, taking care to do the common subexpression +** elimination of x. +*/ +static void exprCodeBetween( + Parse *pParse, /* Parsing and code generating context */ + Expr *pExpr, /* The BETWEEN expression */ + int dest, /* Jump here if the jump is taken */ + int jumpIfTrue, /* Take the jump if the BETWEEN is true */ + int jumpIfNull /* Take the jump if the BETWEEN is NULL */ +){ + Expr exprAnd; /* The AND operator in x>=y AND x<=z */ + Expr compLeft; /* The x>=y term */ + Expr compRight; /* The x<=z term */ + Expr exprX; /* The x subexpression */ + int regFree1 = 0; /* Temporary use register */ + + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + exprX = *pExpr->pLeft; + exprAnd.op = TK_AND; + exprAnd.pLeft = &compLeft; + exprAnd.pRight = &compRight; + compLeft.op = TK_GE; + compLeft.pLeft = &exprX; + compLeft.pRight = pExpr->x.pList->a[0].pExpr; + compRight.op = TK_LE; + compRight.pLeft = &exprX; + compRight.pRight = pExpr->x.pList->a[1].pExpr; + exprToRegister(&exprX, sqlite3ExprCodeTemp(pParse, &exprX, ®Free1)); + if( jumpIfTrue ){ + sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull); + }else{ + sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull); + } + sqlite3ReleaseTempReg(pParse, regFree1); + + /* Ensure adequate test coverage */ + testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1==0 ); + testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1!=0 ); + testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1==0 ); + testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1!=0 ); + testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1==0 ); + testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1!=0 ); + testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1==0 ); + testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1!=0 ); +} + +/* +** Generate code for a boolean expression such that a jump is made +** to the label "dest" if the expression is true but execution +** continues straight thru if the expression is false. +** +** If the expression evaluates to NULL (neither true nor false), then +** take the jump if the jumpIfNull flag is SQLITE_JUMPIFNULL. +** +** This code depends on the fact that certain token values (ex: TK_EQ) +** are the same as opcode values (ex: OP_Eq) that implement the corresponding +** operation. Special comments in vdbe.c and the mkopcodeh.awk script in +** the make process cause these values to align. Assert()s in the code +** below verify that the numbers are aligned correctly. +*/ +SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ + Vdbe *v = pParse->pVdbe; + int op = 0; + int regFree1 = 0; + int regFree2 = 0; + int r1, r2; + + assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); + if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */ + if( NEVER(pExpr==0) ) return; /* No way this can happen */ + op = pExpr->op; + switch( op ){ + case TK_AND: { + int d2 = sqlite3VdbeMakeLabel(v); + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); + sqlite3ExprCachePush(pParse); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); + sqlite3ExprCachePop(pParse); + break; + } + case TK_OR: { + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprCachePush(pParse); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3ExprCachePop(pParse); + break; + } + case TK_NOT: { + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + break; + } + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_NE: + case TK_EQ: { + testcase( jumpIfNull==0 ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + r1, r2, dest, jumpIfNull); + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + break; + } + case TK_IS: + case TK_ISNOT: { + testcase( op==TK_IS ); + testcase( op==TK_ISNOT ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + op = (op==TK_IS) ? TK_EQ : TK_NE; + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + r1, r2, dest, SQLITE_NULLEQ); + VdbeCoverageIf(v, op==TK_EQ); + VdbeCoverageIf(v, op==TK_NE); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + break; + } + case TK_ISNULL: + case TK_NOTNULL: { + assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL ); + assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + sqlite3VdbeAddOp2(v, op, r1, dest); + VdbeCoverageIf(v, op==TK_ISNULL); + VdbeCoverageIf(v, op==TK_NOTNULL); + testcase( regFree1==0 ); + break; + } + case TK_BETWEEN: { + testcase( jumpIfNull==0 ); + exprCodeBetween(pParse, pExpr, dest, 1, jumpIfNull); + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_IN: { + int destIfFalse = sqlite3VdbeMakeLabel(v); + int destIfNull = jumpIfNull ? dest : destIfFalse; + sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull); + sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); + sqlite3VdbeResolveLabel(v, destIfFalse); + break; + } +#endif + default: { + if( exprAlwaysTrue(pExpr) ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); + }else if( exprAlwaysFalse(pExpr) ){ + /* No-op */ + }else{ + r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); + sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0); + VdbeCoverage(v); + testcase( regFree1==0 ); + testcase( jumpIfNull==0 ); + } + break; + } + } + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); +} + +/* +** Generate code for a boolean expression such that a jump is made +** to the label "dest" if the expression is false but execution +** continues straight thru if the expression is true. +** +** If the expression evaluates to NULL (neither true nor false) then +** jump if jumpIfNull is SQLITE_JUMPIFNULL or fall through if jumpIfNull +** is 0. +*/ +SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ + Vdbe *v = pParse->pVdbe; + int op = 0; + int regFree1 = 0; + int regFree2 = 0; + int r1, r2; + + assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); + if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */ + if( pExpr==0 ) return; + + /* The value of pExpr->op and op are related as follows: + ** + ** pExpr->op op + ** --------- ---------- + ** TK_ISNULL OP_NotNull + ** TK_NOTNULL OP_IsNull + ** TK_NE OP_Eq + ** TK_EQ OP_Ne + ** TK_GT OP_Le + ** TK_LE OP_Gt + ** TK_GE OP_Lt + ** TK_LT OP_Ge + ** + ** For other values of pExpr->op, op is undefined and unused. + ** The value of TK_ and OP_ constants are arranged such that we + ** can compute the mapping above using the following expression. + ** Assert()s verify that the computation is correct. + */ + op = ((pExpr->op+(TK_ISNULL&1))^1)-(TK_ISNULL&1); + + /* Verify correct alignment of TK_ and OP_ constants + */ + assert( pExpr->op!=TK_ISNULL || op==OP_NotNull ); + assert( pExpr->op!=TK_NOTNULL || op==OP_IsNull ); + assert( pExpr->op!=TK_NE || op==OP_Eq ); + assert( pExpr->op!=TK_EQ || op==OP_Ne ); + assert( pExpr->op!=TK_LT || op==OP_Ge ); + assert( pExpr->op!=TK_LE || op==OP_Gt ); + assert( pExpr->op!=TK_GT || op==OP_Le ); + assert( pExpr->op!=TK_GE || op==OP_Lt ); + + switch( pExpr->op ){ + case TK_AND: { + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprCachePush(pParse); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3ExprCachePop(pParse); + break; + } + case TK_OR: { + int d2 = sqlite3VdbeMakeLabel(v); + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); + sqlite3ExprCachePush(pParse); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); + sqlite3ExprCachePop(pParse); + break; + } + case TK_NOT: { + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + break; + } + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_NE: + case TK_EQ: { + testcase( jumpIfNull==0 ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + r1, r2, dest, jumpIfNull); + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + break; + } + case TK_IS: + case TK_ISNOT: { + testcase( pExpr->op==TK_IS ); + testcase( pExpr->op==TK_ISNOT ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + r1, r2, dest, SQLITE_NULLEQ); + VdbeCoverageIf(v, op==TK_EQ); + VdbeCoverageIf(v, op==TK_NE); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + break; + } + case TK_ISNULL: + case TK_NOTNULL: { + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + sqlite3VdbeAddOp2(v, op, r1, dest); + testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL); + testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL); + testcase( regFree1==0 ); + break; + } + case TK_BETWEEN: { + testcase( jumpIfNull==0 ); + exprCodeBetween(pParse, pExpr, dest, 0, jumpIfNull); + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_IN: { + if( jumpIfNull ){ + sqlite3ExprCodeIN(pParse, pExpr, dest, dest); + }else{ + int destIfNull = sqlite3VdbeMakeLabel(v); + sqlite3ExprCodeIN(pParse, pExpr, dest, destIfNull); + sqlite3VdbeResolveLabel(v, destIfNull); + } + break; + } +#endif + default: { + if( exprAlwaysFalse(pExpr) ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); + }else if( exprAlwaysTrue(pExpr) ){ + /* no-op */ + }else{ + r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); + sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0); + VdbeCoverage(v); + testcase( regFree1==0 ); + testcase( jumpIfNull==0 ); + } + break; + } + } + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); +} + +/* +** Like sqlite3ExprIfFalse() except that a copy is made of pExpr before +** code generation, and that copy is deleted after code generation. This +** ensures that the original pExpr is unchanged. +*/ +SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,int jumpIfNull){ + sqlite3 *db = pParse->db; + Expr *pCopy = sqlite3ExprDup(db, pExpr, 0); + if( db->mallocFailed==0 ){ + sqlite3ExprIfFalse(pParse, pCopy, dest, jumpIfNull); + } + sqlite3ExprDelete(db, pCopy); +} + + +/* +** Do a deep comparison of two expression trees. Return 0 if the two +** expressions are completely identical. Return 1 if they differ only +** by a COLLATE operator at the top level. Return 2 if there are differences +** other than the top-level COLLATE operator. +** +** If any subelement of pB has Expr.iTable==(-1) then it is allowed +** to compare equal to an equivalent element in pA with Expr.iTable==iTab. +** +** The pA side might be using TK_REGISTER. If that is the case and pB is +** not using TK_REGISTER but is otherwise equivalent, then still return 0. +** +** Sometimes this routine will return 2 even if the two expressions +** really are equivalent. If we cannot prove that the expressions are +** identical, we return 2 just to be safe. So if this routine +** returns 2, then you do not really know for certain if the two +** expressions are the same. But if you get a 0 or 1 return, then you +** can be sure the expressions are the same. In the places where +** this routine is used, it does not hurt to get an extra 2 - that +** just might result in some slightly slower code. But returning +** an incorrect 0 or 1 could lead to a malfunction. +*/ +SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ + u32 combinedFlags; + if( pA==0 || pB==0 ){ + return pB==pA ? 0 : 2; + } + combinedFlags = pA->flags | pB->flags; + if( combinedFlags & EP_IntValue ){ + if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){ + return 0; + } + return 2; + } + if( pA->op!=pB->op ){ + if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){ + return 1; + } + if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft, iTab)<2 ){ + return 1; + } + return 2; + } + if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken ){ + if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ + return pA->op==TK_COLLATE ? 1 : 2; + } + } + if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; + if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){ + if( combinedFlags & EP_xIsSelect ) return 2; + if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2; + if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2; + if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; + if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){ + if( pA->iColumn!=pB->iColumn ) return 2; + if( pA->iTable!=pB->iTable + && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; + } + } + return 0; +} + +/* +** Compare two ExprList objects. Return 0 if they are identical and +** non-zero if they differ in any way. +** +** If any subelement of pB has Expr.iTable==(-1) then it is allowed +** to compare equal to an equivalent element in pA with Expr.iTable==iTab. +** +** This routine might return non-zero for equivalent ExprLists. The +** only consequence will be disabled optimizations. But this routine +** must never return 0 if the two ExprList objects are different, or +** a malfunction will result. +** +** Two NULL pointers are considered to be the same. But a NULL pointer +** always differs from a non-NULL pointer. +*/ +SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){ + int i; + if( pA==0 && pB==0 ) return 0; + if( pA==0 || pB==0 ) return 1; + if( pA->nExpr!=pB->nExpr ) return 1; + for(i=0; inExpr; i++){ + Expr *pExprA = pA->a[i].pExpr; + Expr *pExprB = pB->a[i].pExpr; + if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1; + if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1; + } + return 0; +} + +/* +** Return true if we can prove the pE2 will always be true if pE1 is +** true. Return false if we cannot complete the proof or if pE2 might +** be false. Examples: +** +** pE1: x==5 pE2: x==5 Result: true +** pE1: x>0 pE2: x==5 Result: false +** pE1: x=21 pE2: x=21 OR y=43 Result: true +** pE1: x!=123 pE2: x IS NOT NULL Result: true +** pE1: x!=?1 pE2: x IS NOT NULL Result: true +** pE1: x IS NULL pE2: x IS NOT NULL Result: false +** pE1: x IS ?2 pE2: x IS NOT NULL Reuslt: false +** +** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has +** Expr.iTable<0 then assume a table number given by iTab. +** +** When in doubt, return false. Returning true might give a performance +** improvement. Returning false might cause a performance reduction, but +** it will always give the correct answer and is hence always safe. +*/ +SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){ + if( sqlite3ExprCompare(pE1, pE2, iTab)==0 ){ + return 1; + } + if( pE2->op==TK_OR + && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab) + || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) ) + ){ + return 1; + } + if( pE2->op==TK_NOTNULL + && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0 + && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS) + ){ + return 1; + } + return 0; +} + +/* +** An instance of the following structure is used by the tree walker +** to count references to table columns in the arguments of an +** aggregate function, in order to implement the +** sqlite3FunctionThisSrc() routine. +*/ +struct SrcCount { + SrcList *pSrc; /* One particular FROM clause in a nested query */ + int nThis; /* Number of references to columns in pSrcList */ + int nOther; /* Number of references to columns in other FROM clauses */ +}; + +/* +** Count the number of references to columns. +*/ +static int exprSrcCount(Walker *pWalker, Expr *pExpr){ + /* The NEVER() on the second term is because sqlite3FunctionUsesThisSrc() + ** is always called before sqlite3ExprAnalyzeAggregates() and so the + ** TK_COLUMNs have not yet been converted into TK_AGG_COLUMN. If + ** sqlite3FunctionUsesThisSrc() is used differently in the future, the + ** NEVER() will need to be removed. */ + if( pExpr->op==TK_COLUMN || NEVER(pExpr->op==TK_AGG_COLUMN) ){ + int i; + struct SrcCount *p = pWalker->u.pSrcCount; + SrcList *pSrc = p->pSrc; + int nSrc = pSrc ? pSrc->nSrc : 0; + for(i=0; iiTable==pSrc->a[i].iCursor ) break; + } + if( inThis++; + }else{ + p->nOther++; + } + } + return WRC_Continue; +} + +/* +** Determine if any of the arguments to the pExpr Function reference +** pSrcList. Return true if they do. Also return true if the function +** has no arguments or has only constant arguments. Return false if pExpr +** references columns but not columns of tables found in pSrcList. +*/ +SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){ + Walker w; + struct SrcCount cnt; + assert( pExpr->op==TK_AGG_FUNCTION ); + memset(&w, 0, sizeof(w)); + w.xExprCallback = exprSrcCount; + w.u.pSrcCount = &cnt; + cnt.pSrc = pSrcList; + cnt.nThis = 0; + cnt.nOther = 0; + sqlite3WalkExprList(&w, pExpr->x.pList); + return cnt.nThis>0 || cnt.nOther==0; +} + +/* +** Add a new element to the pAggInfo->aCol[] array. Return the index of +** the new element. Return a negative number if malloc fails. +*/ +static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){ + int i; + pInfo->aCol = sqlite3ArrayAllocate( + db, + pInfo->aCol, + sizeof(pInfo->aCol[0]), + &pInfo->nColumn, + &i + ); + return i; +} + +/* +** Add a new element to the pAggInfo->aFunc[] array. Return the index of +** the new element. Return a negative number if malloc fails. +*/ +static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){ + int i; + pInfo->aFunc = sqlite3ArrayAllocate( + db, + pInfo->aFunc, + sizeof(pInfo->aFunc[0]), + &pInfo->nFunc, + &i + ); + return i; +} + +/* +** This is the xExprCallback for a tree walker. It is used to +** implement sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates +** for additional information. +*/ +static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ + int i; + NameContext *pNC = pWalker->u.pNC; + Parse *pParse = pNC->pParse; + SrcList *pSrcList = pNC->pSrcList; + AggInfo *pAggInfo = pNC->pAggInfo; + + switch( pExpr->op ){ + case TK_AGG_COLUMN: + case TK_COLUMN: { + testcase( pExpr->op==TK_AGG_COLUMN ); + testcase( pExpr->op==TK_COLUMN ); + /* Check to see if the column is in one of the tables in the FROM + ** clause of the aggregate query */ + if( ALWAYS(pSrcList!=0) ){ + struct SrcList_item *pItem = pSrcList->a; + for(i=0; inSrc; i++, pItem++){ + struct AggInfo_col *pCol; + assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); + if( pExpr->iTable==pItem->iCursor ){ + /* If we reach this point, it means that pExpr refers to a table + ** that is in the FROM clause of the aggregate query. + ** + ** Make an entry for the column in pAggInfo->aCol[] if there + ** is not an entry there already. + */ + int k; + pCol = pAggInfo->aCol; + for(k=0; knColumn; k++, pCol++){ + if( pCol->iTable==pExpr->iTable && + pCol->iColumn==pExpr->iColumn ){ + break; + } + } + if( (k>=pAggInfo->nColumn) + && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 + ){ + pCol = &pAggInfo->aCol[k]; + pCol->pTab = pExpr->pTab; + pCol->iTable = pExpr->iTable; + pCol->iColumn = pExpr->iColumn; + pCol->iMem = ++pParse->nMem; + pCol->iSorterColumn = -1; + pCol->pExpr = pExpr; + if( pAggInfo->pGroupBy ){ + int j, n; + ExprList *pGB = pAggInfo->pGroupBy; + struct ExprList_item *pTerm = pGB->a; + n = pGB->nExpr; + for(j=0; jpExpr; + if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable && + pE->iColumn==pExpr->iColumn ){ + pCol->iSorterColumn = j; + break; + } + } + } + if( pCol->iSorterColumn<0 ){ + pCol->iSorterColumn = pAggInfo->nSortingColumn++; + } + } + /* There is now an entry for pExpr in pAggInfo->aCol[] (either + ** because it was there before or because we just created it). + ** Convert the pExpr to be a TK_AGG_COLUMN referring to that + ** pAggInfo->aCol[] entry. + */ + ExprSetVVAProperty(pExpr, EP_NoReduce); + pExpr->pAggInfo = pAggInfo; + pExpr->op = TK_AGG_COLUMN; + pExpr->iAgg = (i16)k; + break; + } /* endif pExpr->iTable==pItem->iCursor */ + } /* end loop over pSrcList */ + } + return WRC_Prune; + } + case TK_AGG_FUNCTION: { + if( (pNC->ncFlags & NC_InAggFunc)==0 + && pWalker->walkerDepth==pExpr->op2 + ){ + /* Check to see if pExpr is a duplicate of another aggregate + ** function that is already in the pAggInfo structure + */ + struct AggInfo_func *pItem = pAggInfo->aFunc; + for(i=0; inFunc; i++, pItem++){ + if( sqlite3ExprCompare(pItem->pExpr, pExpr, -1)==0 ){ + break; + } + } + if( i>=pAggInfo->nFunc ){ + /* pExpr is original. Make a new entry in pAggInfo->aFunc[] + */ + u8 enc = ENC(pParse->db); + i = addAggInfoFunc(pParse->db, pAggInfo); + if( i>=0 ){ + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + pItem = &pAggInfo->aFunc[i]; + pItem->pExpr = pExpr; + pItem->iMem = ++pParse->nMem; + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + pItem->pFunc = sqlite3FindFunction(pParse->db, + pExpr->u.zToken, sqlite3Strlen30(pExpr->u.zToken), + pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); + if( pExpr->flags & EP_Distinct ){ + pItem->iDistinct = pParse->nTab++; + }else{ + pItem->iDistinct = -1; + } + } + } + /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry + */ + assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); + ExprSetVVAProperty(pExpr, EP_NoReduce); + pExpr->iAgg = (i16)i; + pExpr->pAggInfo = pAggInfo; + return WRC_Prune; + }else{ + return WRC_Continue; + } + } + } + return WRC_Continue; +} +static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ + UNUSED_PARAMETER(pWalker); + UNUSED_PARAMETER(pSelect); + return WRC_Continue; +} + +/* +** Analyze the pExpr expression looking for aggregate functions and +** for variables that need to be added to AggInfo object that pNC->pAggInfo +** points to. Additional entries are made on the AggInfo object as +** necessary. +** +** This routine should only be called after the expression has been +** analyzed by sqlite3ResolveExprNames(). +*/ +SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ + Walker w; + memset(&w, 0, sizeof(w)); + w.xExprCallback = analyzeAggregate; + w.xSelectCallback = analyzeAggregatesInSelect; + w.u.pNC = pNC; + assert( pNC->pSrcList!=0 ); + sqlite3WalkExpr(&w, pExpr); +} + +/* +** Call sqlite3ExprAnalyzeAggregates() for every expression in an +** expression list. Return the number of errors. +** +** If an error is found, the analysis is cut short. +*/ +SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){ + struct ExprList_item *pItem; + int i; + if( pList ){ + for(pItem=pList->a, i=0; inExpr; i++, pItem++){ + sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr); + } + } +} + +/* +** Allocate a single new register for use to hold some intermediate result. +*/ +SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){ + if( pParse->nTempReg==0 ){ + return ++pParse->nMem; + } + return pParse->aTempReg[--pParse->nTempReg]; +} + +/* +** Deallocate a register, making available for reuse for some other +** purpose. +** +** If a register is currently being used by the column cache, then +** the deallocation is deferred until the column cache line that uses +** the register becomes stale. +*/ +SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ + if( iReg && pParse->nTempRegaTempReg) ){ + int i; + struct yColCache *p; + for(i=0, p=pParse->aColCache; iiReg==iReg ){ + p->tempReg = 1; + return; + } + } + pParse->aTempReg[pParse->nTempReg++] = iReg; + } +} + +/* +** Allocate or deallocate a block of nReg consecutive registers +*/ +SQLITE_PRIVATE int sqlite3GetTempRange(Parse *pParse, int nReg){ + int i, n; + i = pParse->iRangeReg; + n = pParse->nRangeReg; + if( nReg<=n ){ + assert( !usedAsColumnCache(pParse, i, i+n-1) ); + pParse->iRangeReg += nReg; + pParse->nRangeReg -= nReg; + }else{ + i = pParse->nMem+1; + pParse->nMem += nReg; + } + return i; +} +SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){ + sqlite3ExprCacheRemove(pParse, iReg, nReg); + if( nReg>pParse->nRangeReg ){ + pParse->nRangeReg = nReg; + pParse->iRangeReg = iReg; + } +} + +/* +** Mark all temporary registers as being unavailable for reuse. +*/ +SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse *pParse){ + pParse->nTempReg = 0; + pParse->nRangeReg = 0; +} + +/************** End of expr.c ************************************************/ +/************** Begin file alter.c *******************************************/ +/* +** 2005 February 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains C code routines that used to generate VDBE code +** that implements the ALTER TABLE command. +*/ +/* #include "sqliteInt.h" */ + +/* +** The code in this file only exists if we are not omitting the +** ALTER TABLE logic from the build. +*/ +#ifndef SQLITE_OMIT_ALTERTABLE + + +/* +** This function is used by SQL generated to implement the +** ALTER TABLE command. The first argument is the text of a CREATE TABLE or +** CREATE INDEX command. The second is a table name. The table name in +** the CREATE TABLE or CREATE INDEX statement is replaced with the third +** argument and the result returned. Examples: +** +** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def') +** -> 'CREATE TABLE def(a, b, c)' +** +** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def') +** -> 'CREATE INDEX i ON def(a, b, c)' +*/ +static void renameTableFunc( + sqlite3_context *context, + int NotUsed, + sqlite3_value **argv +){ + unsigned char const *zSql = sqlite3_value_text(argv[0]); + unsigned char const *zTableName = sqlite3_value_text(argv[1]); + + int token; + Token tname; + unsigned char const *zCsr = zSql; + int len = 0; + char *zRet; + + sqlite3 *db = sqlite3_context_db_handle(context); + + UNUSED_PARAMETER(NotUsed); + + /* The principle used to locate the table name in the CREATE TABLE + ** statement is that the table name is the first non-space token that + ** is immediately followed by a TK_LP or TK_USING token. + */ + if( zSql ){ + do { + if( !*zCsr ){ + /* Ran out of input before finding an opening bracket. Return NULL. */ + return; + } + + /* Store the token that zCsr points to in tname. */ + tname.z = (char*)zCsr; + tname.n = len; + + /* Advance zCsr to the next token. Store that token type in 'token', + ** and its length in 'len' (to be used next iteration of this loop). + */ + do { + zCsr += len; + len = sqlite3GetToken(zCsr, &token); + } while( token==TK_SPACE ); + assert( len>0 ); + } while( token!=TK_LP && token!=TK_USING ); + + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), + zSql, zTableName, tname.z+tname.n); + sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); + } +} + +/* +** This C function implements an SQL user function that is used by SQL code +** generated by the ALTER TABLE ... RENAME command to modify the definition +** of any foreign key constraints that use the table being renamed as the +** parent table. It is passed three arguments: +** +** 1) The complete text of the CREATE TABLE statement being modified, +** 2) The old name of the table being renamed, and +** 3) The new name of the table being renamed. +** +** It returns the new CREATE TABLE statement. For example: +** +** sqlite_rename_parent('CREATE TABLE t1(a REFERENCES t2)', 't2', 't3') +** -> 'CREATE TABLE t1(a REFERENCES t3)' +*/ +#ifndef SQLITE_OMIT_FOREIGN_KEY +static void renameParentFunc( + sqlite3_context *context, + int NotUsed, + sqlite3_value **argv +){ + sqlite3 *db = sqlite3_context_db_handle(context); + char *zOutput = 0; + char *zResult; + unsigned char const *zInput = sqlite3_value_text(argv[0]); + unsigned char const *zOld = sqlite3_value_text(argv[1]); + unsigned char const *zNew = sqlite3_value_text(argv[2]); + + unsigned const char *z; /* Pointer to token */ + int n; /* Length of token z */ + int token; /* Type of token */ + + UNUSED_PARAMETER(NotUsed); + if( zInput==0 || zOld==0 ) return; + for(z=zInput; *z; z=z+n){ + n = sqlite3GetToken(z, &token); + if( token==TK_REFERENCES ){ + char *zParent; + do { + z += n; + n = sqlite3GetToken(z, &token); + }while( token==TK_SPACE ); + + if( token==TK_ILLEGAL ) break; + zParent = sqlite3DbStrNDup(db, (const char *)z, n); + if( zParent==0 ) break; + sqlite3Dequote(zParent); + if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){ + char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"", + (zOutput?zOutput:""), (int)(z-zInput), zInput, (const char *)zNew + ); + sqlite3DbFree(db, zOutput); + zOutput = zOut; + zInput = &z[n]; + } + sqlite3DbFree(db, zParent); + } + } + + zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput), + sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC); + sqlite3DbFree(db, zOutput); +} +#endif + +#ifndef SQLITE_OMIT_TRIGGER +/* This function is used by SQL generated to implement the +** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER +** statement. The second is a table name. The table name in the CREATE +** TRIGGER statement is replaced with the third argument and the result +** returned. This is analagous to renameTableFunc() above, except for CREATE +** TRIGGER, not CREATE INDEX and CREATE TABLE. +*/ +static void renameTriggerFunc( + sqlite3_context *context, + int NotUsed, + sqlite3_value **argv +){ + unsigned char const *zSql = sqlite3_value_text(argv[0]); + unsigned char const *zTableName = sqlite3_value_text(argv[1]); + + int token; + Token tname; + int dist = 3; + unsigned char const *zCsr = zSql; + int len = 0; + char *zRet; + sqlite3 *db = sqlite3_context_db_handle(context); + + UNUSED_PARAMETER(NotUsed); + + /* The principle used to locate the table name in the CREATE TRIGGER + ** statement is that the table name is the first token that is immediately + ** preceded by either TK_ON or TK_DOT and immediately followed by one + ** of TK_WHEN, TK_BEGIN or TK_FOR. + */ + if( zSql ){ + do { + + if( !*zCsr ){ + /* Ran out of input before finding the table name. Return NULL. */ + return; + } + + /* Store the token that zCsr points to in tname. */ + tname.z = (char*)zCsr; + tname.n = len; + + /* Advance zCsr to the next token. Store that token type in 'token', + ** and its length in 'len' (to be used next iteration of this loop). + */ + do { + zCsr += len; + len = sqlite3GetToken(zCsr, &token); + }while( token==TK_SPACE ); + assert( len>0 ); + + /* Variable 'dist' stores the number of tokens read since the most + ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN + ** token is read and 'dist' equals 2, the condition stated above + ** to be met. + ** + ** Note that ON cannot be a database, table or column name, so + ** there is no need to worry about syntax like + ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc. + */ + dist++; + if( token==TK_DOT || token==TK_ON ){ + dist = 0; + } + } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) ); + + /* Variable tname now contains the token that is the old table-name + ** in the CREATE TRIGGER statement. + */ + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), + zSql, zTableName, tname.z+tname.n); + sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); + } +} +#endif /* !SQLITE_OMIT_TRIGGER */ + +/* +** Register built-in functions used to help implement ALTER TABLE +*/ +SQLITE_PRIVATE void sqlite3AlterFunctions(void){ + static SQLITE_WSD FuncDef aAlterTableFuncs[] = { + FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc), +#ifndef SQLITE_OMIT_TRIGGER + FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc), +#endif +#ifndef SQLITE_OMIT_FOREIGN_KEY + FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc), +#endif + }; + int i; + FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); + FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAlterTableFuncs); + + for(i=0; i OR name= OR ... +** +** If argument zWhere is NULL, then a pointer string containing the text +** "name=" is returned, where is the quoted version +** of the string passed as argument zConstant. The returned buffer is +** allocated using sqlite3DbMalloc(). It is the responsibility of the +** caller to ensure that it is eventually freed. +** +** If argument zWhere is not NULL, then the string returned is +** " OR name=", where is the contents of zWhere. +** In this case zWhere is passed to sqlite3DbFree() before returning. +** +*/ +static char *whereOrName(sqlite3 *db, char *zWhere, char *zConstant){ + char *zNew; + if( !zWhere ){ + zNew = sqlite3MPrintf(db, "name=%Q", zConstant); + }else{ + zNew = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, zConstant); + sqlite3DbFree(db, zWhere); + } + return zNew; +} + +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) +/* +** Generate the text of a WHERE expression which can be used to select all +** tables that have foreign key constraints that refer to table pTab (i.e. +** constraints for which pTab is the parent table) from the sqlite_master +** table. +*/ +static char *whereForeignKeys(Parse *pParse, Table *pTab){ + FKey *p; + char *zWhere = 0; + for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ + zWhere = whereOrName(pParse->db, zWhere, p->pFrom->zName); + } + return zWhere; +} +#endif + +/* +** Generate the text of a WHERE expression which can be used to select all +** temporary triggers on table pTab from the sqlite_temp_master table. If +** table pTab has no temporary triggers, or is itself stored in the +** temporary database, NULL is returned. +*/ +static char *whereTempTriggers(Parse *pParse, Table *pTab){ + Trigger *pTrig; + char *zWhere = 0; + const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */ + + /* If the table is not located in the temp-db (in which case NULL is + ** returned, loop through the tables list of triggers. For each trigger + ** that is not part of the temp-db schema, add a clause to the WHERE + ** expression being built up in zWhere. + */ + if( pTab->pSchema!=pTempSchema ){ + sqlite3 *db = pParse->db; + for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ + if( pTrig->pSchema==pTempSchema ){ + zWhere = whereOrName(db, zWhere, pTrig->zName); + } + } + } + if( zWhere ){ + char *zNew = sqlite3MPrintf(pParse->db, "type='trigger' AND (%s)", zWhere); + sqlite3DbFree(pParse->db, zWhere); + zWhere = zNew; + } + return zWhere; +} + +/* +** Generate code to drop and reload the internal representation of table +** pTab from the database, including triggers and temporary triggers. +** Argument zName is the name of the table in the database schema at +** the time the generated code is executed. This can be different from +** pTab->zName if this function is being called to code part of an +** "ALTER TABLE RENAME TO" statement. +*/ +static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ + Vdbe *v; + char *zWhere; + int iDb; /* Index of database containing pTab */ +#ifndef SQLITE_OMIT_TRIGGER + Trigger *pTrig; +#endif + + v = sqlite3GetVdbe(pParse); + if( NEVER(v==0) ) return; + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( iDb>=0 ); + +#ifndef SQLITE_OMIT_TRIGGER + /* Drop any table triggers from the internal schema. */ + for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ + int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); + assert( iTrigDb==iDb || iTrigDb==1 ); + sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->zName, 0); + } +#endif + + /* Drop the table and index from the internal schema. */ + sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); + + /* Reload the table, index and permanent trigger schemas. */ + zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName); + if( !zWhere ) return; + sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); + +#ifndef SQLITE_OMIT_TRIGGER + /* Now, if the table is not stored in the temp database, reload any temp + ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined. + */ + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ + sqlite3VdbeAddParseSchemaOp(v, 1, zWhere); + } +#endif +} + +/* +** Parameter zName is the name of a table that is about to be altered +** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN). +** If the table is a system table, this function leaves an error message +** in pParse->zErr (system tables may not be altered) and returns non-zero. +** +** Or, if zName is not a system table, zero is returned. +*/ +static int isSystemTable(Parse *pParse, const char *zName){ + if( sqlite3Strlen30(zName)>6 && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ + sqlite3ErrorMsg(pParse, "table %s may not be altered", zName); + return 1; + } + return 0; +} + +/* +** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" +** command. +*/ +SQLITE_PRIVATE void sqlite3AlterRenameTable( + Parse *pParse, /* Parser context. */ + SrcList *pSrc, /* The table to rename. */ + Token *pName /* The new table name. */ +){ + int iDb; /* Database that contains the table */ + char *zDb; /* Name of database iDb */ + Table *pTab; /* Table being renamed */ + char *zName = 0; /* NULL-terminated version of pName */ + sqlite3 *db = pParse->db; /* Database connection */ + int nTabName; /* Number of UTF-8 characters in zTabName */ + const char *zTabName; /* Original name of the table */ + Vdbe *v; +#ifndef SQLITE_OMIT_TRIGGER + char *zWhere = 0; /* Where clause to locate temp triggers */ +#endif + VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ + int savedDbFlags; /* Saved value of db->flags */ + + savedDbFlags = db->flags; + if( NEVER(db->mallocFailed) ) goto exit_rename_table; + assert( pSrc->nSrc==1 ); + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + + pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); + if( !pTab ) goto exit_rename_table; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + zDb = db->aDb[iDb].zName; + db->flags |= SQLITE_PreferBuiltin; + + /* Get a NULL terminated version of the new table name. */ + zName = sqlite3NameFromToken(db, pName); + if( !zName ) goto exit_rename_table; + + /* Check that a table or index named 'zName' does not already exist + ** in database iDb. If so, this is an error. + */ + if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){ + sqlite3ErrorMsg(pParse, + "there is already another table or index with this name: %s", zName); + goto exit_rename_table; + } + + /* Make sure it is not a system table being altered, or a reserved name + ** that the table is being renamed to. + */ + if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){ + goto exit_rename_table; + } + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto + exit_rename_table; + } + +#ifndef SQLITE_OMIT_VIEW + if( pTab->pSelect ){ + sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName); + goto exit_rename_table; + } +#endif + +#ifndef SQLITE_OMIT_AUTHORIZATION + /* Invoke the authorization callback. */ + if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ + goto exit_rename_table; + } +#endif + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto exit_rename_table; + } + if( IsVirtual(pTab) ){ + pVTab = sqlite3GetVTable(db, pTab); + if( pVTab->pVtab->pModule->xRename==0 ){ + pVTab = 0; + } + } +#endif + + /* Begin a transaction for database iDb. + ** Then modify the schema cookie (since the ALTER TABLE modifies the + ** schema). Open a statement transaction if the table is a virtual + ** table. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ){ + goto exit_rename_table; + } + sqlite3BeginWriteOperation(pParse, pVTab!=0, iDb); + sqlite3ChangeCookie(pParse, iDb); + + /* If this is a virtual table, invoke the xRename() function if + ** one is defined. The xRename() callback will modify the names + ** of any resources used by the v-table implementation (including other + ** SQLite tables) that are identified by the name of the virtual table. + */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pVTab ){ + int i = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_String8, 0, i, 0, zName, 0); + sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); + sqlite3MayAbort(pParse); + } +#endif + + /* figure out how many UTF-8 characters are in zName */ + zTabName = pTab->zName; + nTabName = sqlite3Utf8CharLen(zTabName, -1); + +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) + if( db->flags&SQLITE_ForeignKeys ){ + /* If foreign-key support is enabled, rewrite the CREATE TABLE + ** statements corresponding to all child tables of foreign key constraints + ** for which the renamed table is the parent table. */ + if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){ + sqlite3NestedParse(pParse, + "UPDATE \"%w\".%s SET " + "sql = sqlite_rename_parent(sql, %Q, %Q) " + "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere); + sqlite3DbFree(db, zWhere); + } + } +#endif + + /* Modify the sqlite_master table to use the new table name. */ + sqlite3NestedParse(pParse, + "UPDATE %Q.%s SET " +#ifdef SQLITE_OMIT_TRIGGER + "sql = sqlite_rename_table(sql, %Q), " +#else + "sql = CASE " + "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)" + "ELSE sqlite_rename_table(sql, %Q) END, " +#endif + "tbl_name = %Q, " + "name = CASE " + "WHEN type='table' THEN %Q " + "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " + "'sqlite_autoindex_' || %Q || substr(name,%d+18) " + "ELSE name END " + "WHERE tbl_name=%Q COLLATE nocase AND " + "(type='table' OR type='index' OR type='trigger');", + zDb, SCHEMA_TABLE(iDb), zName, zName, zName, +#ifndef SQLITE_OMIT_TRIGGER + zName, +#endif + zName, nTabName, zTabName + ); + +#ifndef SQLITE_OMIT_AUTOINCREMENT + /* If the sqlite_sequence table exists in this database, then update + ** it with the new table name. + */ + if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){ + sqlite3NestedParse(pParse, + "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q", + zDb, zName, pTab->zName); + } +#endif + +#ifndef SQLITE_OMIT_TRIGGER + /* If there are TEMP triggers on this table, modify the sqlite_temp_master + ** table. Don't do this if the table being ALTERed is itself located in + ** the temp database. + */ + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ + sqlite3NestedParse(pParse, + "UPDATE sqlite_temp_master SET " + "sql = sqlite_rename_trigger(sql, %Q), " + "tbl_name = %Q " + "WHERE %s;", zName, zName, zWhere); + sqlite3DbFree(db, zWhere); + } +#endif + +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) + if( db->flags&SQLITE_ForeignKeys ){ + FKey *p; + for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ + Table *pFrom = p->pFrom; + if( pFrom!=pTab ){ + reloadTableSchema(pParse, p->pFrom, pFrom->zName); + } + } + } +#endif + + /* Drop and reload the internal table schema. */ + reloadTableSchema(pParse, pTab, zName); + +exit_rename_table: + sqlite3SrcListDelete(db, pSrc); + sqlite3DbFree(db, zName); + db->flags = savedDbFlags; +} + + +/* +** Generate code to make sure the file format number is at least minFormat. +** The generated code will increase the file format number if necessary. +*/ +SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ + Vdbe *v; + v = sqlite3GetVdbe(pParse); + /* The VDBE should have been allocated before this routine is called. + ** If that allocation failed, we would have quit before reaching this + ** point */ + if( ALWAYS(v) ){ + int r1 = sqlite3GetTempReg(pParse); + int r2 = sqlite3GetTempReg(pParse); + int j1; + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); + sqlite3VdbeUsesBtree(v, iDb); + sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); + j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2); + sqlite3VdbeJumpHere(v, j1); + sqlite3ReleaseTempReg(pParse, r1); + sqlite3ReleaseTempReg(pParse, r2); + } +} + +/* +** This function is called after an "ALTER TABLE ... ADD" statement +** has been parsed. Argument pColDef contains the text of the new +** column definition. +** +** The Table structure pParse->pNewTable was extended to include +** the new column during parsing. +*/ +SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ + Table *pNew; /* Copy of pParse->pNewTable */ + Table *pTab; /* Table being altered */ + int iDb; /* Database number */ + const char *zDb; /* Database name */ + const char *zTab; /* Table name */ + char *zCol; /* Null-terminated column definition */ + Column *pCol; /* The new column */ + Expr *pDflt; /* Default value for the new column */ + sqlite3 *db; /* The database connection; */ + + db = pParse->db; + if( pParse->nErr || db->mallocFailed ) return; + pNew = pParse->pNewTable; + assert( pNew ); + + assert( sqlite3BtreeHoldsAllMutexes(db) ); + iDb = sqlite3SchemaToIndex(db, pNew->pSchema); + zDb = db->aDb[iDb].zName; + zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ + pCol = &pNew->aCol[pNew->nCol-1]; + pDflt = pCol->pDflt; + pTab = sqlite3FindTable(db, zTab, zDb); + assert( pTab ); + +#ifndef SQLITE_OMIT_AUTHORIZATION + /* Invoke the authorization callback. */ + if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ + return; + } +#endif + + /* If the default value for the new column was specified with a + ** literal NULL, then set pDflt to 0. This simplifies checking + ** for an SQL NULL default below. + */ + if( pDflt && pDflt->op==TK_NULL ){ + pDflt = 0; + } + + /* Check that the new column is not specified as PRIMARY KEY or UNIQUE. + ** If there is a NOT NULL constraint, then the default value for the + ** column must not be NULL. + */ + if( pCol->colFlags & COLFLAG_PRIMKEY ){ + sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column"); + return; + } + if( pNew->pIndex ){ + sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column"); + return; + } + if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){ + sqlite3ErrorMsg(pParse, + "Cannot add a REFERENCES column with non-NULL default value"); + return; + } + if( pCol->notNull && !pDflt ){ + sqlite3ErrorMsg(pParse, + "Cannot add a NOT NULL column with default value NULL"); + return; + } + + /* Ensure the default expression is something that sqlite3ValueFromExpr() + ** can handle (i.e. not CURRENT_TIME etc.) + */ + if( pDflt ){ + sqlite3_value *pVal = 0; + int rc; + rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal); + assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); + if( rc!=SQLITE_OK ){ + db->mallocFailed = 1; + return; + } + if( !pVal ){ + sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default"); + return; + } + sqlite3ValueFree(pVal); + } + + /* Modify the CREATE TABLE statement. */ + zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); + if( zCol ){ + char *zEnd = &zCol[pColDef->n-1]; + int savedDbFlags = db->flags; + while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){ + *zEnd-- = '\0'; + } + db->flags |= SQLITE_PreferBuiltin; + sqlite3NestedParse(pParse, + "UPDATE \"%w\".%s SET " + "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) " + "WHERE type = 'table' AND name = %Q", + zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1, + zTab + ); + sqlite3DbFree(db, zCol); + db->flags = savedDbFlags; + } + + /* If the default value of the new column is NULL, then set the file + ** format to 2. If the default value of the new column is not NULL, + ** the file format becomes 3. + */ + sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2); + + /* Reload the schema of the modified table. */ + reloadTableSchema(pParse, pTab, pTab->zName); +} + +/* +** This function is called by the parser after the table-name in +** an "ALTER TABLE ADD" statement is parsed. Argument +** pSrc is the full-name of the table being altered. +** +** This routine makes a (partial) copy of the Table structure +** for the table being altered and sets Parse.pNewTable to point +** to it. Routines called by the parser as the column definition +** is parsed (i.e. sqlite3AddColumn()) add the new Column data to +** the copy. The copy of the Table structure is deleted by tokenize.c +** after parsing is finished. +** +** Routine sqlite3AlterFinishAddColumn() will be called to complete +** coding the "ALTER TABLE ... ADD" statement. +*/ +SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ + Table *pNew; + Table *pTab; + Vdbe *v; + int iDb; + int i; + int nAlloc; + sqlite3 *db = pParse->db; + + /* Look up the table being altered. */ + assert( pParse->pNewTable==0 ); + assert( sqlite3BtreeHoldsAllMutexes(db) ); + if( db->mallocFailed ) goto exit_begin_add_column; + pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); + if( !pTab ) goto exit_begin_add_column; + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + sqlite3ErrorMsg(pParse, "virtual tables may not be altered"); + goto exit_begin_add_column; + } +#endif + + /* Make sure this is not an attempt to ALTER a view. */ + if( pTab->pSelect ){ + sqlite3ErrorMsg(pParse, "Cannot add a column to a view"); + goto exit_begin_add_column; + } + if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){ + goto exit_begin_add_column; + } + + assert( pTab->addColOffset>0 ); + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + + /* Put a copy of the Table struct in Parse.pNewTable for the + ** sqlite3AddColumn() function and friends to modify. But modify + ** the name by adding an "sqlite_altertab_" prefix. By adding this + ** prefix, we insure that the name will not collide with an existing + ** table because user table are not allowed to have the "sqlite_" + ** prefix on their name. + */ + pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table)); + if( !pNew ) goto exit_begin_add_column; + pParse->pNewTable = pNew; + pNew->nRef = 1; + pNew->nCol = pTab->nCol; + assert( pNew->nCol>0 ); + nAlloc = (((pNew->nCol-1)/8)*8)+8; + assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); + pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); + pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); + if( !pNew->aCol || !pNew->zName ){ + db->mallocFailed = 1; + goto exit_begin_add_column; + } + memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); + for(i=0; inCol; i++){ + Column *pCol = &pNew->aCol[i]; + pCol->zName = sqlite3DbStrDup(db, pCol->zName); + pCol->zColl = 0; + pCol->zType = 0; + pCol->pDflt = 0; + pCol->zDflt = 0; + } + pNew->pSchema = db->aDb[iDb].pSchema; + pNew->addColOffset = pTab->addColOffset; + pNew->nRef = 1; + + /* Begin a transaction and increment the schema cookie. */ + sqlite3BeginWriteOperation(pParse, 0, iDb); + v = sqlite3GetVdbe(pParse); + if( !v ) goto exit_begin_add_column; + sqlite3ChangeCookie(pParse, iDb); + +exit_begin_add_column: + sqlite3SrcListDelete(db, pSrc); + return; +} +#endif /* SQLITE_ALTER_TABLE */ + +/************** End of alter.c ***********************************************/ +/************** Begin file analyze.c *****************************************/ +/* +** 2005-07-08 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code associated with the ANALYZE command. +** +** The ANALYZE command gather statistics about the content of tables +** and indices. These statistics are made available to the query planner +** to help it make better decisions about how to perform queries. +** +** The following system tables are or have been supported: +** +** CREATE TABLE sqlite_stat1(tbl, idx, stat); +** CREATE TABLE sqlite_stat2(tbl, idx, sampleno, sample); +** CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample); +** CREATE TABLE sqlite_stat4(tbl, idx, nEq, nLt, nDLt, sample); +** +** Additional tables might be added in future releases of SQLite. +** The sqlite_stat2 table is not created or used unless the SQLite version +** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled +** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated. +** The sqlite_stat2 table is superseded by sqlite_stat3, which is only +** created and used by SQLite versions 3.7.9 and later and with +** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3 +** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced +** version of sqlite_stat3 and is only available when compiled with +** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later. It is +** not possible to enable both STAT3 and STAT4 at the same time. If they +** are both enabled, then STAT4 takes precedence. +** +** For most applications, sqlite_stat1 provides all the statistics required +** for the query planner to make good choices. +** +** Format of sqlite_stat1: +** +** There is normally one row per index, with the index identified by the +** name in the idx column. The tbl column is the name of the table to +** which the index belongs. In each such row, the stat column will be +** a string consisting of a list of integers. The first integer in this +** list is the number of rows in the index. (This is the same as the +** number of rows in the table, except for partial indices.) The second +** integer is the average number of rows in the index that have the same +** value in the first column of the index. The third integer is the average +** number of rows in the index that have the same value for the first two +** columns. The N-th integer (for N>1) is the average number of rows in +** the index which have the same value for the first N-1 columns. For +** a K-column index, there will be K+1 integers in the stat column. If +** the index is unique, then the last integer will be 1. +** +** The list of integers in the stat column can optionally be followed +** by the keyword "unordered". The "unordered" keyword, if it is present, +** must be separated from the last integer by a single space. If the +** "unordered" keyword is present, then the query planner assumes that +** the index is unordered and will not use the index for a range query. +** +** If the sqlite_stat1.idx column is NULL, then the sqlite_stat1.stat +** column contains a single integer which is the (estimated) number of +** rows in the table identified by sqlite_stat1.tbl. +** +** Format of sqlite_stat2: +** +** The sqlite_stat2 is only created and is only used if SQLite is compiled +** with SQLITE_ENABLE_STAT2 and if the SQLite version number is between +** 3.6.18 and 3.7.8. The "stat2" table contains additional information +** about the distribution of keys within an index. The index is identified by +** the "idx" column and the "tbl" column is the name of the table to which +** the index belongs. There are usually 10 rows in the sqlite_stat2 +** table for each index. +** +** The sqlite_stat2 entries for an index that have sampleno between 0 and 9 +** inclusive are samples of the left-most key value in the index taken at +** evenly spaced points along the index. Let the number of samples be S +** (10 in the standard build) and let C be the number of rows in the index. +** Then the sampled rows are given by: +** +** rownumber = (i*C*2 + C)/(S*2) +** +** For i between 0 and S-1. Conceptually, the index space is divided into +** S uniform buckets and the samples are the middle row from each bucket. +** +** The format for sqlite_stat2 is recorded here for legacy reference. This +** version of SQLite does not support sqlite_stat2. It neither reads nor +** writes the sqlite_stat2 table. This version of SQLite only supports +** sqlite_stat3. +** +** Format for sqlite_stat3: +** +** The sqlite_stat3 format is a subset of sqlite_stat4. Hence, the +** sqlite_stat4 format will be described first. Further information +** about sqlite_stat3 follows the sqlite_stat4 description. +** +** Format for sqlite_stat4: +** +** As with sqlite_stat2, the sqlite_stat4 table contains histogram data +** to aid the query planner in choosing good indices based on the values +** that indexed columns are compared against in the WHERE clauses of +** queries. +** +** The sqlite_stat4 table contains multiple entries for each index. +** The idx column names the index and the tbl column is the table of the +** index. If the idx and tbl columns are the same, then the sample is +** of the INTEGER PRIMARY KEY. The sample column is a blob which is the +** binary encoding of a key from the index. The nEq column is a +** list of integers. The first integer is the approximate number +** of entries in the index whose left-most column exactly matches +** the left-most column of the sample. The second integer in nEq +** is the approximate number of entries in the index where the +** first two columns match the first two columns of the sample. +** And so forth. nLt is another list of integers that show the approximate +** number of entries that are strictly less than the sample. The first +** integer in nLt contains the number of entries in the index where the +** left-most column is less than the left-most column of the sample. +** The K-th integer in the nLt entry is the number of index entries +** where the first K columns are less than the first K columns of the +** sample. The nDLt column is like nLt except that it contains the +** number of distinct entries in the index that are less than the +** sample. +** +** There can be an arbitrary number of sqlite_stat4 entries per index. +** The ANALYZE command will typically generate sqlite_stat4 tables +** that contain between 10 and 40 samples which are distributed across +** the key space, though not uniformly, and which include samples with +** large nEq values. +** +** Format for sqlite_stat3 redux: +** +** The sqlite_stat3 table is like sqlite_stat4 except that it only +** looks at the left-most column of the index. The sqlite_stat3.sample +** column contains the actual value of the left-most column instead +** of a blob encoding of the complete index key as is found in +** sqlite_stat4.sample. The nEq, nLt, and nDLt entries of sqlite_stat3 +** all contain just a single integer which is the same as the first +** integer in the equivalent columns in sqlite_stat4. +*/ +#ifndef SQLITE_OMIT_ANALYZE +/* #include "sqliteInt.h" */ + +#if defined(SQLITE_ENABLE_STAT4) +# define IsStat4 1 +# define IsStat3 0 +#elif defined(SQLITE_ENABLE_STAT3) +# define IsStat4 0 +# define IsStat3 1 +#else +# define IsStat4 0 +# define IsStat3 0 +# undef SQLITE_STAT4_SAMPLES +# define SQLITE_STAT4_SAMPLES 1 +#endif +#define IsStat34 (IsStat3+IsStat4) /* 1 for STAT3 or STAT4. 0 otherwise */ + +/* +** This routine generates code that opens the sqlite_statN tables. +** The sqlite_stat1 table is always relevant. sqlite_stat2 is now +** obsolete. sqlite_stat3 and sqlite_stat4 are only opened when +** appropriate compile-time options are provided. +** +** If the sqlite_statN tables do not previously exist, it is created. +** +** Argument zWhere may be a pointer to a buffer containing a table name, +** or it may be a NULL pointer. If it is not NULL, then all entries in +** the sqlite_statN tables associated with the named table are deleted. +** If zWhere==0, then code is generated to delete all stat table entries. +*/ +static void openStatTable( + Parse *pParse, /* Parsing context */ + int iDb, /* The database we are looking in */ + int iStatCur, /* Open the sqlite_stat1 table on this cursor */ + const char *zWhere, /* Delete entries for this table or index */ + const char *zWhereType /* Either "tbl" or "idx" */ +){ + static const struct { + const char *zName; + const char *zCols; + } aTable[] = { + { "sqlite_stat1", "tbl,idx,stat" }, +#if defined(SQLITE_ENABLE_STAT4) + { "sqlite_stat4", "tbl,idx,neq,nlt,ndlt,sample" }, + { "sqlite_stat3", 0 }, +#elif defined(SQLITE_ENABLE_STAT3) + { "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" }, + { "sqlite_stat4", 0 }, +#else + { "sqlite_stat3", 0 }, + { "sqlite_stat4", 0 }, +#endif + }; + int i; + sqlite3 *db = pParse->db; + Db *pDb; + Vdbe *v = sqlite3GetVdbe(pParse); + int aRoot[ArraySize(aTable)]; + u8 aCreateTbl[ArraySize(aTable)]; + + if( v==0 ) return; + assert( sqlite3BtreeHoldsAllMutexes(db) ); + assert( sqlite3VdbeDb(v)==db ); + pDb = &db->aDb[iDb]; + + /* Create new statistic tables if they do not exist, or clear them + ** if they do already exist. + */ + for(i=0; izName))==0 ){ + if( aTable[i].zCols ){ + /* The sqlite_statN table does not exist. Create it. Note that a + ** side-effect of the CREATE TABLE statement is to leave the rootpage + ** of the new table in register pParse->regRoot. This is important + ** because the OpenWrite opcode below will be needing it. */ + sqlite3NestedParse(pParse, + "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols + ); + aRoot[i] = pParse->regRoot; + aCreateTbl[i] = OPFLAG_P2ISREG; + } + }else{ + /* The table already exists. If zWhere is not NULL, delete all entries + ** associated with the table zWhere. If zWhere is NULL, delete the + ** entire contents of the table. */ + aRoot[i] = pStat->tnum; + aCreateTbl[i] = 0; + sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab); + if( zWhere ){ + sqlite3NestedParse(pParse, + "DELETE FROM %Q.%s WHERE %s=%Q", + pDb->zName, zTab, zWhereType, zWhere + ); + }else{ + /* The sqlite_stat[134] table already exists. Delete all rows. */ + sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb); + } + } + } + + /* Open the sqlite_stat[134] tables for writing. */ + for(i=0; aTable[i].zCols; i++){ + assert( inRowid ){ + sqlite3DbFree(db, p->u.aRowid); + p->nRowid = 0; + } +} +#endif + +/* Initialize the BLOB value of a ROWID +*/ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){ + assert( db!=0 ); + if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); + p->u.aRowid = sqlite3DbMallocRaw(db, n); + if( p->u.aRowid ){ + p->nRowid = n; + memcpy(p->u.aRowid, pData, n); + }else{ + p->nRowid = 0; + } +} +#endif + +/* Initialize the INTEGER value of a ROWID. +*/ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){ + assert( db!=0 ); + if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); + p->nRowid = 0; + p->u.iRowid = iRowid; +} +#endif + + +/* +** Copy the contents of object (*pFrom) into (*pTo). +*/ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){ + pTo->isPSample = pFrom->isPSample; + pTo->iCol = pFrom->iCol; + pTo->iHash = pFrom->iHash; + memcpy(pTo->anEq, pFrom->anEq, sizeof(tRowcnt)*p->nCol); + memcpy(pTo->anLt, pFrom->anLt, sizeof(tRowcnt)*p->nCol); + memcpy(pTo->anDLt, pFrom->anDLt, sizeof(tRowcnt)*p->nCol); + if( pFrom->nRowid ){ + sampleSetRowid(p->db, pTo, pFrom->nRowid, pFrom->u.aRowid); + }else{ + sampleSetRowidInt64(p->db, pTo, pFrom->u.iRowid); + } +} +#endif + +/* +** Reclaim all memory of a Stat4Accum structure. +*/ +static void stat4Destructor(void *pOld){ + Stat4Accum *p = (Stat4Accum*)pOld; +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + int i; + for(i=0; inCol; i++) sampleClear(p->db, p->aBest+i); + for(i=0; imxSample; i++) sampleClear(p->db, p->a+i); + sampleClear(p->db, &p->current); +#endif + sqlite3DbFree(p->db, p); +} + +/* +** Implementation of the stat_init(N,K,C) SQL function. The three parameters +** are: +** N: The number of columns in the index including the rowid/pk (note 1) +** K: The number of columns in the index excluding the rowid/pk. +** C: The number of rows in the index (note 2) +** +** Note 1: In the special case of the covering index that implements a +** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the +** total number of columns in the table. +** +** Note 2: C is only used for STAT3 and STAT4. +** +** For indexes on ordinary rowid tables, N==K+1. But for indexes on +** WITHOUT ROWID tables, N=K+P where P is the number of columns in the +** PRIMARY KEY of the table. The covering index that implements the +** original WITHOUT ROWID table as N==K as a special case. +** +** This routine allocates the Stat4Accum object in heap memory. The return +** value is a pointer to the Stat4Accum object. The datatype of the +** return value is BLOB, but it is really just a pointer to the Stat4Accum +** object. +*/ +static void statInit( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + Stat4Accum *p; + int nCol; /* Number of columns in index being sampled */ + int nKeyCol; /* Number of key columns */ + int nColUp; /* nCol rounded up for alignment */ + int n; /* Bytes of space to allocate */ + sqlite3 *db; /* Database connection */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + int mxSample = SQLITE_STAT4_SAMPLES; +#endif + + /* Decode the three function arguments */ + UNUSED_PARAMETER(argc); + nCol = sqlite3_value_int(argv[0]); + assert( nCol>0 ); + nColUp = sizeof(tRowcnt)<8 ? (nCol+1)&~1 : nCol; + nKeyCol = sqlite3_value_int(argv[1]); + assert( nKeyCol<=nCol ); + assert( nKeyCol>0 ); + + /* Allocate the space required for the Stat4Accum object */ + n = sizeof(*p) + + sizeof(tRowcnt)*nColUp /* Stat4Accum.anEq */ + + sizeof(tRowcnt)*nColUp /* Stat4Accum.anDLt */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + + sizeof(tRowcnt)*nColUp /* Stat4Accum.anLt */ + + sizeof(Stat4Sample)*(nCol+mxSample) /* Stat4Accum.aBest[], a[] */ + + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample) +#endif + ; + db = sqlite3_context_db_handle(context); + p = sqlite3DbMallocZero(db, n); + if( p==0 ){ + sqlite3_result_error_nomem(context); + return; + } + + p->db = db; + p->nRow = 0; + p->nCol = nCol; + p->nKeyCol = nKeyCol; + p->current.anDLt = (tRowcnt*)&p[1]; + p->current.anEq = &p->current.anDLt[nColUp]; + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + { + u8 *pSpace; /* Allocated space not yet assigned */ + int i; /* Used to iterate through p->aSample[] */ + + p->iGet = -1; + p->mxSample = mxSample; + p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1); + p->current.anLt = &p->current.anEq[nColUp]; + p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]); + + /* Set up the Stat4Accum.a[] and aBest[] arrays */ + p->a = (struct Stat4Sample*)&p->current.anLt[nColUp]; + p->aBest = &p->a[mxSample]; + pSpace = (u8*)(&p->a[mxSample+nCol]); + for(i=0; i<(mxSample+nCol); i++){ + p->a[i].anEq = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp); + p->a[i].anLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp); + p->a[i].anDLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp); + } + assert( (pSpace - (u8*)p)==n ); + + for(i=0; iaBest[i].iCol = i; + } + } +#endif + + /* Return a pointer to the allocated object to the caller. Note that + ** only the pointer (the 2nd parameter) matters. The size of the object + ** (given by the 3rd parameter) is never used and can be any positive + ** value. */ + sqlite3_result_blob(context, p, sizeof(*p), stat4Destructor); +} +static const FuncDef statInitFuncdef = { + 2+IsStat34, /* nArg */ + SQLITE_UTF8, /* funcFlags */ + 0, /* pUserData */ + 0, /* pNext */ + statInit, /* xFunc */ + 0, /* xStep */ + 0, /* xFinalize */ + "stat_init", /* zName */ + 0, /* pHash */ + 0 /* pDestructor */ +}; + +#ifdef SQLITE_ENABLE_STAT4 +/* +** pNew and pOld are both candidate non-periodic samples selected for +** the same column (pNew->iCol==pOld->iCol). Ignoring this column and +** considering only any trailing columns and the sample hash value, this +** function returns true if sample pNew is to be preferred over pOld. +** In other words, if we assume that the cardinalities of the selected +** column for pNew and pOld are equal, is pNew to be preferred over pOld. +** +** This function assumes that for each argument sample, the contents of +** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid. +*/ +static int sampleIsBetterPost( + Stat4Accum *pAccum, + Stat4Sample *pNew, + Stat4Sample *pOld +){ + int nCol = pAccum->nCol; + int i; + assert( pNew->iCol==pOld->iCol ); + for(i=pNew->iCol+1; ianEq[i]>pOld->anEq[i] ) return 1; + if( pNew->anEq[i]anEq[i] ) return 0; + } + if( pNew->iHash>pOld->iHash ) return 1; + return 0; +} +#endif + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +/* +** Return true if pNew is to be preferred over pOld. +** +** This function assumes that for each argument sample, the contents of +** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid. +*/ +static int sampleIsBetter( + Stat4Accum *pAccum, + Stat4Sample *pNew, + Stat4Sample *pOld +){ + tRowcnt nEqNew = pNew->anEq[pNew->iCol]; + tRowcnt nEqOld = pOld->anEq[pOld->iCol]; + + assert( pOld->isPSample==0 && pNew->isPSample==0 ); + assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) ); + + if( (nEqNew>nEqOld) ) return 1; +#ifdef SQLITE_ENABLE_STAT4 + if( nEqNew==nEqOld ){ + if( pNew->iColiCol ) return 1; + return (pNew->iCol==pOld->iCol && sampleIsBetterPost(pAccum, pNew, pOld)); + } + return 0; +#else + return (nEqNew==nEqOld && pNew->iHash>pOld->iHash); +#endif +} + +/* +** Copy the contents of sample *pNew into the p->a[] array. If necessary, +** remove the least desirable sample from p->a[] to make room. +*/ +static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ + Stat4Sample *pSample = 0; + int i; + + assert( IsStat4 || nEqZero==0 ); + +#ifdef SQLITE_ENABLE_STAT4 + if( pNew->isPSample==0 ){ + Stat4Sample *pUpgrade = 0; + assert( pNew->anEq[pNew->iCol]>0 ); + + /* This sample is being added because the prefix that ends in column + ** iCol occurs many times in the table. However, if we have already + ** added a sample that shares this prefix, there is no need to add + ** this one. Instead, upgrade the priority of the highest priority + ** existing sample that shares this prefix. */ + for(i=p->nSample-1; i>=0; i--){ + Stat4Sample *pOld = &p->a[i]; + if( pOld->anEq[pNew->iCol]==0 ){ + if( pOld->isPSample ) return; + assert( pOld->iCol>pNew->iCol ); + assert( sampleIsBetter(p, pNew, pOld) ); + if( pUpgrade==0 || sampleIsBetter(p, pOld, pUpgrade) ){ + pUpgrade = pOld; + } + } + } + if( pUpgrade ){ + pUpgrade->iCol = pNew->iCol; + pUpgrade->anEq[pUpgrade->iCol] = pNew->anEq[pUpgrade->iCol]; + goto find_new_min; + } + } +#endif + + /* If necessary, remove sample iMin to make room for the new sample. */ + if( p->nSample>=p->mxSample ){ + Stat4Sample *pMin = &p->a[p->iMin]; + tRowcnt *anEq = pMin->anEq; + tRowcnt *anLt = pMin->anLt; + tRowcnt *anDLt = pMin->anDLt; + sampleClear(p->db, pMin); + memmove(pMin, &pMin[1], sizeof(p->a[0])*(p->nSample-p->iMin-1)); + pSample = &p->a[p->nSample-1]; + pSample->nRowid = 0; + pSample->anEq = anEq; + pSample->anDLt = anDLt; + pSample->anLt = anLt; + p->nSample = p->mxSample-1; + } + + /* The "rows less-than" for the rowid column must be greater than that + ** for the last sample in the p->a[] array. Otherwise, the samples would + ** be out of order. */ +#ifdef SQLITE_ENABLE_STAT4 + assert( p->nSample==0 + || pNew->anLt[p->nCol-1] > p->a[p->nSample-1].anLt[p->nCol-1] ); +#endif + + /* Insert the new sample */ + pSample = &p->a[p->nSample]; + sampleCopy(p, pSample, pNew); + p->nSample++; + + /* Zero the first nEqZero entries in the anEq[] array. */ + memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero); + +#ifdef SQLITE_ENABLE_STAT4 + find_new_min: +#endif + if( p->nSample>=p->mxSample ){ + int iMin = -1; + for(i=0; imxSample; i++){ + if( p->a[i].isPSample ) continue; + if( iMin<0 || sampleIsBetter(p, &p->a[iMin], &p->a[i]) ){ + iMin = i; + } + } + assert( iMin>=0 ); + p->iMin = iMin; + } +} +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ + +/* +** Field iChng of the index being scanned has changed. So at this point +** p->current contains a sample that reflects the previous row of the +** index. The value of anEq[iChng] and subsequent anEq[] elements are +** correct at this point. +*/ +static void samplePushPrevious(Stat4Accum *p, int iChng){ +#ifdef SQLITE_ENABLE_STAT4 + int i; + + /* Check if any samples from the aBest[] array should be pushed + ** into IndexSample.a[] at this point. */ + for(i=(p->nCol-2); i>=iChng; i--){ + Stat4Sample *pBest = &p->aBest[i]; + pBest->anEq[i] = p->current.anEq[i]; + if( p->nSamplemxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){ + sampleInsert(p, pBest, i); + } + } + + /* Update the anEq[] fields of any samples already collected. */ + for(i=p->nSample-1; i>=0; i--){ + int j; + for(j=iChng; jnCol; j++){ + if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j]; + } + } +#endif + +#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4) + if( iChng==0 ){ + tRowcnt nLt = p->current.anLt[0]; + tRowcnt nEq = p->current.anEq[0]; + + /* Check if this is to be a periodic sample. If so, add it. */ + if( (nLt/p->nPSample)!=(nLt+nEq)/p->nPSample ){ + p->current.isPSample = 1; + sampleInsert(p, &p->current, 0); + p->current.isPSample = 0; + }else + + /* Or if it is a non-periodic sample. Add it in this case too. */ + if( p->nSamplemxSample + || sampleIsBetter(p, &p->current, &p->a[p->iMin]) + ){ + sampleInsert(p, &p->current, 0); + } + } +#endif + +#ifndef SQLITE_ENABLE_STAT3_OR_STAT4 + UNUSED_PARAMETER( p ); + UNUSED_PARAMETER( iChng ); +#endif +} + +/* +** Implementation of the stat_push SQL function: stat_push(P,C,R) +** Arguments: +** +** P Pointer to the Stat4Accum object created by stat_init() +** C Index of left-most column to differ from previous row +** R Rowid for the current row. Might be a key record for +** WITHOUT ROWID tables. +** +** This SQL function always returns NULL. It's purpose it to accumulate +** statistical data and/or samples in the Stat4Accum object about the +** index being analyzed. The stat_get() SQL function will later be used to +** extract relevant information for constructing the sqlite_statN tables. +** +** The R parameter is only used for STAT3 and STAT4 +*/ +static void statPush( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int i; + + /* The three function arguments */ + Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]); + int iChng = sqlite3_value_int(argv[1]); + + UNUSED_PARAMETER( argc ); + UNUSED_PARAMETER( context ); + assert( p->nCol>0 ); + assert( iChngnCol ); + + if( p->nRow==0 ){ + /* This is the first call to this function. Do initialization. */ + for(i=0; inCol; i++) p->current.anEq[i] = 1; + }else{ + /* Second and subsequent calls get processed here */ + samplePushPrevious(p, iChng); + + /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply + ** to the current row of the index. */ + for(i=0; icurrent.anEq[i]++; + } + for(i=iChng; inCol; i++){ + p->current.anDLt[i]++; +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + p->current.anLt[i] += p->current.anEq[i]; +#endif + p->current.anEq[i] = 1; + } + } + p->nRow++; +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){ + sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2])); + }else{ + sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]), + sqlite3_value_blob(argv[2])); + } + p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345; +#endif + +#ifdef SQLITE_ENABLE_STAT4 + { + tRowcnt nLt = p->current.anLt[p->nCol-1]; + + /* Check if this is to be a periodic sample. If so, add it. */ + if( (nLt/p->nPSample)!=(nLt+1)/p->nPSample ){ + p->current.isPSample = 1; + p->current.iCol = 0; + sampleInsert(p, &p->current, p->nCol-1); + p->current.isPSample = 0; + } + + /* Update the aBest[] array. */ + for(i=0; i<(p->nCol-1); i++){ + p->current.iCol = i; + if( i>=iChng || sampleIsBetterPost(p, &p->current, &p->aBest[i]) ){ + sampleCopy(p, &p->aBest[i], &p->current); + } + } + } +#endif +} +static const FuncDef statPushFuncdef = { + 2+IsStat34, /* nArg */ + SQLITE_UTF8, /* funcFlags */ + 0, /* pUserData */ + 0, /* pNext */ + statPush, /* xFunc */ + 0, /* xStep */ + 0, /* xFinalize */ + "stat_push", /* zName */ + 0, /* pHash */ + 0 /* pDestructor */ +}; + +#define STAT_GET_STAT1 0 /* "stat" column of stat1 table */ +#define STAT_GET_ROWID 1 /* "rowid" column of stat[34] entry */ +#define STAT_GET_NEQ 2 /* "neq" column of stat[34] entry */ +#define STAT_GET_NLT 3 /* "nlt" column of stat[34] entry */ +#define STAT_GET_NDLT 4 /* "ndlt" column of stat[34] entry */ + +/* +** Implementation of the stat_get(P,J) SQL function. This routine is +** used to query statistical information that has been gathered into +** the Stat4Accum object by prior calls to stat_push(). The P parameter +** has type BLOB but it is really just a pointer to the Stat4Accum object. +** The content to returned is determined by the parameter J +** which is one of the STAT_GET_xxxx values defined above. +** +** If neither STAT3 nor STAT4 are enabled, then J is always +** STAT_GET_STAT1 and is hence omitted and this routine becomes +** a one-parameter function, stat_get(P), that always returns the +** stat1 table entry information. +*/ +static void statGet( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]); +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + /* STAT3 and STAT4 have a parameter on this routine. */ + int eCall = sqlite3_value_int(argv[1]); + assert( argc==2 ); + assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ + || eCall==STAT_GET_ROWID || eCall==STAT_GET_NLT + || eCall==STAT_GET_NDLT + ); + if( eCall==STAT_GET_STAT1 ) +#else + assert( argc==1 ); +#endif + { + /* Return the value to store in the "stat" column of the sqlite_stat1 + ** table for this index. + ** + ** The value is a string composed of a list of integers describing + ** the index. The first integer in the list is the total number of + ** entries in the index. There is one additional integer in the list + ** for each indexed column. This additional integer is an estimate of + ** the number of rows matched by a stabbing query on the index using + ** a key with the corresponding number of fields. In other words, + ** if the index is on columns (a,b) and the sqlite_stat1 value is + ** "100 10 2", then SQLite estimates that: + ** + ** * the index contains 100 rows, + ** * "WHERE a=?" matches 10 rows, and + ** * "WHERE a=? AND b=?" matches 2 rows. + ** + ** If D is the count of distinct values and K is the total number of + ** rows, then each estimate is computed as: + ** + ** I = (K+D-1)/D + */ + char *z; + int i; + + char *zRet = sqlite3MallocZero( (p->nKeyCol+1)*25 ); + if( zRet==0 ){ + sqlite3_result_error_nomem(context); + return; + } + + sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow); + z = zRet + sqlite3Strlen30(zRet); + for(i=0; inKeyCol; i++){ + u64 nDistinct = p->current.anDLt[i] + 1; + u64 iVal = (p->nRow + nDistinct - 1) / nDistinct; + sqlite3_snprintf(24, z, " %llu", iVal); + z += sqlite3Strlen30(z); + assert( p->current.anEq[i] ); + } + assert( z[0]=='\0' && z>zRet ); + + sqlite3_result_text(context, zRet, -1, sqlite3_free); + } +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + else if( eCall==STAT_GET_ROWID ){ + if( p->iGet<0 ){ + samplePushPrevious(p, 0); + p->iGet = 0; + } + if( p->iGetnSample ){ + Stat4Sample *pS = p->a + p->iGet; + if( pS->nRowid==0 ){ + sqlite3_result_int64(context, pS->u.iRowid); + }else{ + sqlite3_result_blob(context, pS->u.aRowid, pS->nRowid, + SQLITE_TRANSIENT); + } + } + }else{ + tRowcnt *aCnt = 0; + + assert( p->iGetnSample ); + switch( eCall ){ + case STAT_GET_NEQ: aCnt = p->a[p->iGet].anEq; break; + case STAT_GET_NLT: aCnt = p->a[p->iGet].anLt; break; + default: { + aCnt = p->a[p->iGet].anDLt; + p->iGet++; + break; + } + } + + if( IsStat3 ){ + sqlite3_result_int64(context, (i64)aCnt[0]); + }else{ + char *zRet = sqlite3MallocZero(p->nCol * 25); + if( zRet==0 ){ + sqlite3_result_error_nomem(context); + }else{ + int i; + char *z = zRet; + for(i=0; inCol; i++){ + sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]); + z += sqlite3Strlen30(z); + } + assert( z[0]=='\0' && z>zRet ); + z[-1] = '\0'; + sqlite3_result_text(context, zRet, -1, sqlite3_free); + } + } + } +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ +#ifndef SQLITE_DEBUG + UNUSED_PARAMETER( argc ); +#endif +} +static const FuncDef statGetFuncdef = { + 1+IsStat34, /* nArg */ + SQLITE_UTF8, /* funcFlags */ + 0, /* pUserData */ + 0, /* pNext */ + statGet, /* xFunc */ + 0, /* xStep */ + 0, /* xFinalize */ + "stat_get", /* zName */ + 0, /* pHash */ + 0 /* pDestructor */ +}; + +static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){ + assert( regOut!=regStat4 && regOut!=regStat4+1 ); +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1); +#elif SQLITE_DEBUG + assert( iParam==STAT_GET_STAT1 ); +#else + UNUSED_PARAMETER( iParam ); +#endif + sqlite3VdbeAddOp3(v, OP_Function0, 0, regStat4, regOut); + sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, 1 + IsStat34); +} + +/* +** Generate code to do an analysis of all indices associated with +** a single table. +*/ +static void analyzeOneTable( + Parse *pParse, /* Parser context */ + Table *pTab, /* Table whose indices are to be analyzed */ + Index *pOnlyIdx, /* If not NULL, only analyze this one index */ + int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */ + int iMem, /* Available memory locations begin here */ + int iTab /* Next available cursor */ +){ + sqlite3 *db = pParse->db; /* Database handle */ + Index *pIdx; /* An index to being analyzed */ + int iIdxCur; /* Cursor open on index being analyzed */ + int iTabCur; /* Table cursor */ + Vdbe *v; /* The virtual machine being built up */ + int i; /* Loop counter */ + int jZeroRows = -1; /* Jump from here if number of rows is zero */ + int iDb; /* Index of database containing pTab */ + u8 needTableCnt = 1; /* True to count the table */ + int regNewRowid = iMem++; /* Rowid for the inserted record */ + int regStat4 = iMem++; /* Register to hold Stat4Accum object */ + int regChng = iMem++; /* Index of changed index field */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + int regRowid = iMem++; /* Rowid argument passed to stat_push() */ +#endif + int regTemp = iMem++; /* Temporary use register */ + int regTabname = iMem++; /* Register containing table name */ + int regIdxname = iMem++; /* Register containing index name */ + int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */ + int regPrev = iMem; /* MUST BE LAST (see below) */ + + pParse->nMem = MAX(pParse->nMem, iMem); + v = sqlite3GetVdbe(pParse); + if( v==0 || NEVER(pTab==0) ){ + return; + } + if( pTab->tnum==0 ){ + /* Do not gather statistics on views or virtual tables */ + return; + } + if( sqlite3_strnicmp(pTab->zName, "sqlite_", 7)==0 ){ + /* Do not gather statistics on system tables */ + return; + } + assert( sqlite3BtreeHoldsAllMutexes(db) ); + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( iDb>=0 ); + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); +#ifndef SQLITE_OMIT_AUTHORIZATION + if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, + db->aDb[iDb].zName ) ){ + return; + } +#endif + + /* Establish a read-lock on the table at the shared-cache level. + ** Open a read-only cursor on the table. Also allocate a cursor number + ** to use for scanning indexes (iIdxCur). No index cursor is opened at + ** this time though. */ + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); + iTabCur = iTab++; + iIdxCur = iTab++; + pParse->nTab = MAX(pParse->nTab, iTab); + sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); + sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0); + + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + int nCol; /* Number of columns in pIdx. "N" */ + int addrRewind; /* Address of "OP_Rewind iIdxCur" */ + int addrNextRow; /* Address of "next_row:" */ + const char *zIdxName; /* Name of the index */ + int nColTest; /* Number of columns to test for changes */ + + if( pOnlyIdx && pOnlyIdx!=pIdx ) continue; + if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0; + if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIdx) ){ + nCol = pIdx->nKeyCol; + zIdxName = pTab->zName; + nColTest = nCol - 1; + }else{ + nCol = pIdx->nColumn; + zIdxName = pIdx->zName; + nColTest = pIdx->uniqNotNull ? pIdx->nKeyCol-1 : nCol-1; + } + + /* Populate the register containing the index name. */ + sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, zIdxName, 0); + VdbeComment((v, "Analysis for %s.%s", pTab->zName, zIdxName)); + + /* + ** Pseudo-code for loop that calls stat_push(): + ** + ** Rewind csr + ** if eof(csr) goto end_of_scan; + ** regChng = 0 + ** goto chng_addr_0; + ** + ** next_row: + ** regChng = 0 + ** if( idx(0) != regPrev(0) ) goto chng_addr_0 + ** regChng = 1 + ** if( idx(1) != regPrev(1) ) goto chng_addr_1 + ** ... + ** regChng = N + ** goto chng_addr_N + ** + ** chng_addr_0: + ** regPrev(0) = idx(0) + ** chng_addr_1: + ** regPrev(1) = idx(1) + ** ... + ** + ** endDistinctTest: + ** regRowid = idx(rowid) + ** stat_push(P, regChng, regRowid) + ** Next csr + ** if !eof(csr) goto next_row; + ** + ** end_of_scan: + */ + + /* Make sure there are enough memory cells allocated to accommodate + ** the regPrev array and a trailing rowid (the rowid slot is required + ** when building a record to insert into the sample column of + ** the sqlite_stat4 table. */ + pParse->nMem = MAX(pParse->nMem, regPrev+nColTest); + + /* Open a read-only cursor on the index being analyzed. */ + assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) ); + sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb); + sqlite3VdbeSetP4KeyInfo(pParse, pIdx); + VdbeComment((v, "%s", pIdx->zName)); + + /* Invoke the stat_init() function. The arguments are: + ** + ** (1) the number of columns in the index including the rowid + ** (or for a WITHOUT ROWID table, the number of PK columns), + ** (2) the number of columns in the key without the rowid/pk + ** (3) the number of rows in the index, + ** + ** + ** The third argument is only used for STAT3 and STAT4 + */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3); +#endif + sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1); + sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2); + sqlite3VdbeAddOp3(v, OP_Function0, 0, regStat4+1, regStat4); + sqlite3VdbeChangeP4(v, -1, (char*)&statInitFuncdef, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, 2+IsStat34); + + /* Implementation of the following: + ** + ** Rewind csr + ** if eof(csr) goto end_of_scan; + ** regChng = 0 + ** goto next_push_0; + ** + */ + addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur); + VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng); + addrNextRow = sqlite3VdbeCurrentAddr(v); + + if( nColTest>0 ){ + int endDistinctTest = sqlite3VdbeMakeLabel(v); + int *aGotoChng; /* Array of jump instruction addresses */ + aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*nColTest); + if( aGotoChng==0 ) continue; + + /* + ** next_row: + ** regChng = 0 + ** if( idx(0) != regPrev(0) ) goto chng_addr_0 + ** regChng = 1 + ** if( idx(1) != regPrev(1) ) goto chng_addr_1 + ** ... + ** regChng = N + ** goto endDistinctTest + */ + sqlite3VdbeAddOp0(v, OP_Goto); + addrNextRow = sqlite3VdbeCurrentAddr(v); + if( nColTest==1 && pIdx->nKeyCol==1 && IsUniqueIndex(pIdx) ){ + /* For a single-column UNIQUE index, once we have found a non-NULL + ** row, we know that all the rest will be distinct, so skip + ** subsequent distinctness tests. */ + sqlite3VdbeAddOp2(v, OP_NotNull, regPrev, endDistinctTest); + VdbeCoverage(v); + } + for(i=0; iazColl[i]); + sqlite3VdbeAddOp2(v, OP_Integer, i, regChng); + sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp); + aGotoChng[i] = + sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ); + sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); + VdbeCoverage(v); + } + sqlite3VdbeAddOp2(v, OP_Integer, nColTest, regChng); + sqlite3VdbeAddOp2(v, OP_Goto, 0, endDistinctTest); + + + /* + ** chng_addr_0: + ** regPrev(0) = idx(0) + ** chng_addr_1: + ** regPrev(1) = idx(1) + ** ... + */ + sqlite3VdbeJumpHere(v, addrNextRow-1); + for(i=0; ipTable); + int j, k, regKey; + regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol); + for(j=0; jnKeyCol; j++){ + k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]); + sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j); + VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName)); + } + sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid); + sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol); + } +#endif + assert( regChng==(regStat4+1) ); + sqlite3VdbeAddOp3(v, OP_Function0, 1, regStat4, regTemp); + sqlite3VdbeChangeP4(v, -1, (char*)&statPushFuncdef, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, 2+IsStat34); + sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v); + + /* Add the entry to the stat1 table. */ + callStatGet(v, regStat4, STAT_GET_STAT1, regStat1); + assert( "BBB"[0]==SQLITE_AFF_TEXT ); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0); + sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); + sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); + + /* Add the entries to the stat3 or stat4 table. */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + { + int regEq = regStat1; + int regLt = regStat1+1; + int regDLt = regStat1+2; + int regSample = regStat1+3; + int regCol = regStat1+4; + int regSampleRowid = regCol + nCol; + int addrNext; + int addrIsNull; + u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound; + + pParse->nMem = MAX(pParse->nMem, regCol+nCol); + + addrNext = sqlite3VdbeCurrentAddr(v); + callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid); + addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid); + VdbeCoverage(v); + callStatGet(v, regStat4, STAT_GET_NEQ, regEq); + callStatGet(v, regStat4, STAT_GET_NLT, regLt); + callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); + sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); + /* We know that the regSampleRowid row exists because it was read by + ** the previous loop. Thus the not-found jump of seekOp will never + ** be taken */ + VdbeCoverageNeverTaken(v); +#ifdef SQLITE_ENABLE_STAT3 + sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, + pIdx->aiColumn[0], regSample); +#else + for(i=0; iaiColumn[i]; + sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regCol+i); + } + sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol, regSample); +#endif + sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp); + sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid); + sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid); + sqlite3VdbeAddOp2(v, OP_Goto, 1, addrNext); /* P1==1 for end-of-loop */ + sqlite3VdbeJumpHere(v, addrIsNull); + } +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ + + /* End of analysis */ + sqlite3VdbeJumpHere(v, addrRewind); + } + + + /* Create a single sqlite_stat1 entry containing NULL as the index + ** name and the row count as the content. + */ + if( pOnlyIdx==0 && needTableCnt ){ + VdbeComment((v, "%s", pTab->zName)); + sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1); + jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname); + assert( "BBB"[0]==SQLITE_AFF_TEXT ); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0); + sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); + sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); + sqlite3VdbeJumpHere(v, jZeroRows); + } +} + + +/* +** Generate code that will cause the most recent index analysis to +** be loaded into internal hash tables where is can be used. +*/ +static void loadAnalysis(Parse *pParse, int iDb){ + Vdbe *v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp1(v, OP_LoadAnalysis, iDb); + } +} + +/* +** Generate code that will do an analysis of an entire database +*/ +static void analyzeDatabase(Parse *pParse, int iDb){ + sqlite3 *db = pParse->db; + Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */ + HashElem *k; + int iStatCur; + int iMem; + int iTab; + + sqlite3BeginWriteOperation(pParse, 0, iDb); + iStatCur = pParse->nTab; + pParse->nTab += 3; + openStatTable(pParse, iDb, iStatCur, 0, 0); + iMem = pParse->nMem+1; + iTab = pParse->nTab; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ + Table *pTab = (Table*)sqliteHashData(k); + analyzeOneTable(pParse, pTab, 0, iStatCur, iMem, iTab); + } + loadAnalysis(pParse, iDb); +} + +/* +** Generate code that will do an analysis of a single table in +** a database. If pOnlyIdx is not NULL then it is a single index +** in pTab that should be analyzed. +*/ +static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){ + int iDb; + int iStatCur; + + assert( pTab!=0 ); + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + sqlite3BeginWriteOperation(pParse, 0, iDb); + iStatCur = pParse->nTab; + pParse->nTab += 3; + if( pOnlyIdx ){ + openStatTable(pParse, iDb, iStatCur, pOnlyIdx->zName, "idx"); + }else{ + openStatTable(pParse, iDb, iStatCur, pTab->zName, "tbl"); + } + analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur,pParse->nMem+1,pParse->nTab); + loadAnalysis(pParse, iDb); +} + +/* +** Generate code for the ANALYZE command. The parser calls this routine +** when it recognizes an ANALYZE command. +** +** ANALYZE -- 1 +** ANALYZE -- 2 +** ANALYZE ?.? -- 3 +** +** Form 1 causes all indices in all attached databases to be analyzed. +** Form 2 analyzes all indices the single database named. +** Form 3 analyzes all indices associated with the named table. +*/ +SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ + sqlite3 *db = pParse->db; + int iDb; + int i; + char *z, *zDb; + Table *pTab; + Index *pIdx; + Token *pTableName; + Vdbe *v; + + /* Read the database schema. If an error occurs, leave an error message + ** and code in pParse and return NULL. */ + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + return; + } + + assert( pName2!=0 || pName1==0 ); + if( pName1==0 ){ + /* Form 1: Analyze everything */ + for(i=0; inDb; i++){ + if( i==1 ) continue; /* Do not analyze the TEMP database */ + analyzeDatabase(pParse, i); + } + }else if( pName2->n==0 ){ + /* Form 2: Analyze the database or table named */ + iDb = sqlite3FindDb(db, pName1); + if( iDb>=0 ){ + analyzeDatabase(pParse, iDb); + }else{ + z = sqlite3NameFromToken(db, pName1); + if( z ){ + if( (pIdx = sqlite3FindIndex(db, z, 0))!=0 ){ + analyzeTable(pParse, pIdx->pTable, pIdx); + }else if( (pTab = sqlite3LocateTable(pParse, 0, z, 0))!=0 ){ + analyzeTable(pParse, pTab, 0); + } + sqlite3DbFree(db, z); + } + } + }else{ + /* Form 3: Analyze the fully qualified table name */ + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); + if( iDb>=0 ){ + zDb = db->aDb[iDb].zName; + z = sqlite3NameFromToken(db, pTableName); + if( z ){ + if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){ + analyzeTable(pParse, pIdx->pTable, pIdx); + }else if( (pTab = sqlite3LocateTable(pParse, 0, z, zDb))!=0 ){ + analyzeTable(pParse, pTab, 0); + } + sqlite3DbFree(db, z); + } + } + } + v = sqlite3GetVdbe(pParse); + if( v ) sqlite3VdbeAddOp0(v, OP_Expire); +} + +/* +** Used to pass information from the analyzer reader through to the +** callback routine. +*/ +typedef struct analysisInfo analysisInfo; +struct analysisInfo { + sqlite3 *db; + const char *zDatabase; +}; + +/* +** The first argument points to a nul-terminated string containing a +** list of space separated integers. Read the first nOut of these into +** the array aOut[]. +*/ +static void decodeIntArray( + char *zIntArray, /* String containing int array to decode */ + int nOut, /* Number of slots in aOut[] */ + tRowcnt *aOut, /* Store integers here */ + LogEst *aLog, /* Or, if aOut==0, here */ + Index *pIndex /* Handle extra flags for this index, if not NULL */ +){ + char *z = zIntArray; + int c; + int i; + tRowcnt v; + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( z==0 ) z = ""; +#else + assert( z!=0 ); +#endif + for(i=0; *z && i='0' && c<='9' ){ + v = v*10 + c - '0'; + z++; + } +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( aOut ) aOut[i] = v; + if( aLog ) aLog[i] = sqlite3LogEst(v); +#else + assert( aOut==0 ); + UNUSED_PARAMETER(aOut); + assert( aLog!=0 ); + aLog[i] = sqlite3LogEst(v); +#endif + if( *z==' ' ) z++; + } +#ifndef SQLITE_ENABLE_STAT3_OR_STAT4 + assert( pIndex!=0 ); { +#else + if( pIndex ){ +#endif + pIndex->bUnordered = 0; + pIndex->noSkipScan = 0; + while( z[0] ){ + if( sqlite3_strglob("unordered*", z)==0 ){ + pIndex->bUnordered = 1; + }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){ + pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3)); + }else if( sqlite3_strglob("noskipscan*", z)==0 ){ + pIndex->noSkipScan = 1; + } +#ifdef SQLITE_ENABLE_COSTMULT + else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){ + pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9)); + } +#endif + while( z[0]!=0 && z[0]!=' ' ) z++; + while( z[0]==' ' ) z++; + } + } +} + +/* +** This callback is invoked once for each index when reading the +** sqlite_stat1 table. +** +** argv[0] = name of the table +** argv[1] = name of the index (might be NULL) +** argv[2] = results of analysis - on integer for each column +** +** Entries for which argv[1]==NULL simply record the number of rows in +** the table. +*/ +static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){ + analysisInfo *pInfo = (analysisInfo*)pData; + Index *pIndex; + Table *pTable; + const char *z; + + assert( argc==3 ); + UNUSED_PARAMETER2(NotUsed, argc); + + if( argv==0 || argv[0]==0 || argv[2]==0 ){ + return 0; + } + pTable = sqlite3FindTable(pInfo->db, argv[0], pInfo->zDatabase); + if( pTable==0 ){ + return 0; + } + if( argv[1]==0 ){ + pIndex = 0; + }else if( sqlite3_stricmp(argv[0],argv[1])==0 ){ + pIndex = sqlite3PrimaryKeyIndex(pTable); + }else{ + pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase); + } + z = argv[2]; + + if( pIndex ){ + tRowcnt *aiRowEst = 0; + int nCol = pIndex->nKeyCol+1; +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + /* Index.aiRowEst may already be set here if there are duplicate + ** sqlite_stat1 entries for this index. In that case just clobber + ** the old data with the new instead of allocating a new array. */ + if( pIndex->aiRowEst==0 ){ + pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol); + if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1; + } + aiRowEst = pIndex->aiRowEst; +#endif + pIndex->bUnordered = 0; + decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex); + if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0]; + }else{ + Index fakeIdx; + fakeIdx.szIdxRow = pTable->szTabRow; +#ifdef SQLITE_ENABLE_COSTMULT + fakeIdx.pTable = pTable; +#endif + decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx); + pTable->szTabRow = fakeIdx.szIdxRow; + } + + return 0; +} + +/* +** If the Index.aSample variable is not NULL, delete the aSample[] array +** and its contents. +*/ +SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( pIdx->aSample ){ + int j; + for(j=0; jnSample; j++){ + IndexSample *p = &pIdx->aSample[j]; + sqlite3DbFree(db, p->p); + } + sqlite3DbFree(db, pIdx->aSample); + } + if( db && db->pnBytesFreed==0 ){ + pIdx->nSample = 0; + pIdx->aSample = 0; + } +#else + UNUSED_PARAMETER(db); + UNUSED_PARAMETER(pIdx); +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ +} + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +/* +** Populate the pIdx->aAvgEq[] array based on the samples currently +** stored in pIdx->aSample[]. +*/ +static void initAvgEq(Index *pIdx){ + if( pIdx ){ + IndexSample *aSample = pIdx->aSample; + IndexSample *pFinal = &aSample[pIdx->nSample-1]; + int iCol; + int nCol = 1; + if( pIdx->nSampleCol>1 ){ + /* If this is stat4 data, then calculate aAvgEq[] values for all + ** sample columns except the last. The last is always set to 1, as + ** once the trailing PK fields are considered all index keys are + ** unique. */ + nCol = pIdx->nSampleCol-1; + pIdx->aAvgEq[nCol] = 1; + } + for(iCol=0; iColnSample; + int i; /* Used to iterate through samples */ + tRowcnt sumEq = 0; /* Sum of the nEq values */ + tRowcnt avgEq = 0; + tRowcnt nRow; /* Number of rows in index */ + i64 nSum100 = 0; /* Number of terms contributing to sumEq */ + i64 nDist100; /* Number of distinct values in index */ + + if( !pIdx->aiRowEst || iCol>=pIdx->nKeyCol || pIdx->aiRowEst[iCol+1]==0 ){ + nRow = pFinal->anLt[iCol]; + nDist100 = (i64)100 * pFinal->anDLt[iCol]; + nSample--; + }else{ + nRow = pIdx->aiRowEst[0]; + nDist100 = ((i64)100 * pIdx->aiRowEst[0]) / pIdx->aiRowEst[iCol+1]; + } + pIdx->nRowEst0 = nRow; + + /* Set nSum to the number of distinct (iCol+1) field prefixes that + ** occur in the stat4 table for this index. Set sumEq to the sum of + ** the nEq values for column iCol for the same set (adding the value + ** only once where there exist duplicate prefixes). */ + for(i=0; inSample-1) + || aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] + ){ + sumEq += aSample[i].anEq[iCol]; + nSum100 += 100; + } + } + + if( nDist100>nSum100 ){ + avgEq = ((i64)100 * (nRow - sumEq))/(nDist100 - nSum100); + } + if( avgEq==0 ) avgEq = 1; + pIdx->aAvgEq[iCol] = avgEq; + } + } +} + +/* +** Look up an index by name. Or, if the name of a WITHOUT ROWID table +** is supplied instead, find the PRIMARY KEY index for that table. +*/ +static Index *findIndexOrPrimaryKey( + sqlite3 *db, + const char *zName, + const char *zDb +){ + Index *pIdx = sqlite3FindIndex(db, zName, zDb); + if( pIdx==0 ){ + Table *pTab = sqlite3FindTable(db, zName, zDb); + if( pTab && !HasRowid(pTab) ) pIdx = sqlite3PrimaryKeyIndex(pTab); + } + return pIdx; +} + +/* +** Load the content from either the sqlite_stat4 or sqlite_stat3 table +** into the relevant Index.aSample[] arrays. +** +** Arguments zSql1 and zSql2 must point to SQL statements that return +** data equivalent to the following (statements are different for stat3, +** see the caller of this function for details): +** +** zSql1: SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx +** zSql2: SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4 +** +** where %Q is replaced with the database name before the SQL is executed. +*/ +static int loadStatTbl( + sqlite3 *db, /* Database handle */ + int bStat3, /* Assume single column records only */ + const char *zSql1, /* SQL statement 1 (see above) */ + const char *zSql2, /* SQL statement 2 (see above) */ + const char *zDb /* Database name (e.g. "main") */ +){ + int rc; /* Result codes from subroutines */ + sqlite3_stmt *pStmt = 0; /* An SQL statement being run */ + char *zSql; /* Text of the SQL statement */ + Index *pPrevIdx = 0; /* Previous index in the loop */ + IndexSample *pSample; /* A slot in pIdx->aSample[] */ + + assert( db->lookaside.bEnabled==0 ); + zSql = sqlite3MPrintf(db, zSql1, zDb); + if( !zSql ){ + return SQLITE_NOMEM; + } + rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); + sqlite3DbFree(db, zSql); + if( rc ) return rc; + + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + int nIdxCol = 1; /* Number of columns in stat4 records */ + + char *zIndex; /* Index name */ + Index *pIdx; /* Pointer to the index object */ + int nSample; /* Number of samples */ + int nByte; /* Bytes of space required */ + int i; /* Bytes of space required */ + tRowcnt *pSpace; + + zIndex = (char *)sqlite3_column_text(pStmt, 0); + if( zIndex==0 ) continue; + nSample = sqlite3_column_int(pStmt, 1); + pIdx = findIndexOrPrimaryKey(db, zIndex, zDb); + assert( pIdx==0 || bStat3 || pIdx->nSample==0 ); + /* Index.nSample is non-zero at this point if data has already been + ** loaded from the stat4 table. In this case ignore stat3 data. */ + if( pIdx==0 || pIdx->nSample ) continue; + if( bStat3==0 ){ + assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 ); + if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){ + nIdxCol = pIdx->nKeyCol; + }else{ + nIdxCol = pIdx->nColumn; + } + } + pIdx->nSampleCol = nIdxCol; + nByte = sizeof(IndexSample) * nSample; + nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample; + nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */ + + pIdx->aSample = sqlite3DbMallocZero(db, nByte); + if( pIdx->aSample==0 ){ + sqlite3_finalize(pStmt); + return SQLITE_NOMEM; + } + pSpace = (tRowcnt*)&pIdx->aSample[nSample]; + pIdx->aAvgEq = pSpace; pSpace += nIdxCol; + for(i=0; iaSample[i].anEq = pSpace; pSpace += nIdxCol; + pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol; + pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol; + } + assert( ((u8*)pSpace)-nByte==(u8*)(pIdx->aSample) ); + } + rc = sqlite3_finalize(pStmt); + if( rc ) return rc; + + zSql = sqlite3MPrintf(db, zSql2, zDb); + if( !zSql ){ + return SQLITE_NOMEM; + } + rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); + sqlite3DbFree(db, zSql); + if( rc ) return rc; + + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + char *zIndex; /* Index name */ + Index *pIdx; /* Pointer to the index object */ + int nCol = 1; /* Number of columns in index */ + + zIndex = (char *)sqlite3_column_text(pStmt, 0); + if( zIndex==0 ) continue; + pIdx = findIndexOrPrimaryKey(db, zIndex, zDb); + if( pIdx==0 ) continue; + /* This next condition is true if data has already been loaded from + ** the sqlite_stat4 table. In this case ignore stat3 data. */ + nCol = pIdx->nSampleCol; + if( bStat3 && nCol>1 ) continue; + if( pIdx!=pPrevIdx ){ + initAvgEq(pPrevIdx); + pPrevIdx = pIdx; + } + pSample = &pIdx->aSample[pIdx->nSample]; + decodeIntArray((char*)sqlite3_column_text(pStmt,1),nCol,pSample->anEq,0,0); + decodeIntArray((char*)sqlite3_column_text(pStmt,2),nCol,pSample->anLt,0,0); + decodeIntArray((char*)sqlite3_column_text(pStmt,3),nCol,pSample->anDLt,0,0); + + /* Take a copy of the sample. Add two 0x00 bytes the end of the buffer. + ** This is in case the sample record is corrupted. In that case, the + ** sqlite3VdbeRecordCompare() may read up to two varints past the + ** end of the allocated buffer before it realizes it is dealing with + ** a corrupt record. Adding the two 0x00 bytes prevents this from causing + ** a buffer overread. */ + pSample->n = sqlite3_column_bytes(pStmt, 4); + pSample->p = sqlite3DbMallocZero(db, pSample->n + 2); + if( pSample->p==0 ){ + sqlite3_finalize(pStmt); + return SQLITE_NOMEM; + } + memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n); + pIdx->nSample++; + } + rc = sqlite3_finalize(pStmt); + if( rc==SQLITE_OK ) initAvgEq(pPrevIdx); + return rc; +} + +/* +** Load content from the sqlite_stat4 and sqlite_stat3 tables into +** the Index.aSample[] arrays of all indices. +*/ +static int loadStat4(sqlite3 *db, const char *zDb){ + int rc = SQLITE_OK; /* Result codes from subroutines */ + + assert( db->lookaside.bEnabled==0 ); + if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){ + rc = loadStatTbl(db, 0, + "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", + "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4", + zDb + ); + } + + if( rc==SQLITE_OK && sqlite3FindTable(db, "sqlite_stat3", zDb) ){ + rc = loadStatTbl(db, 1, + "SELECT idx,count(*) FROM %Q.sqlite_stat3 GROUP BY idx", + "SELECT idx,neq,nlt,ndlt,sqlite_record(sample) FROM %Q.sqlite_stat3", + zDb + ); + } + + return rc; +} +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ + +/* +** Load the content of the sqlite_stat1 and sqlite_stat3/4 tables. The +** contents of sqlite_stat1 are used to populate the Index.aiRowEst[] +** arrays. The contents of sqlite_stat3/4 are used to populate the +** Index.aSample[] arrays. +** +** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR +** is returned. In this case, even if SQLITE_ENABLE_STAT3/4 was defined +** during compilation and the sqlite_stat3/4 table is present, no data is +** read from it. +** +** If SQLITE_ENABLE_STAT3/4 was defined during compilation and the +** sqlite_stat4 table is not present in the database, SQLITE_ERROR is +** returned. However, in this case, data is read from the sqlite_stat1 +** table (if it is present) before returning. +** +** If an OOM error occurs, this function always sets db->mallocFailed. +** This means if the caller does not care about other errors, the return +** code may be ignored. +*/ +SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ + analysisInfo sInfo; + HashElem *i; + char *zSql; + int rc; + + assert( iDb>=0 && iDbnDb ); + assert( db->aDb[iDb].pBt!=0 ); + + /* Clear any prior statistics */ + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ + Index *pIdx = sqliteHashData(i); + sqlite3DefaultRowEst(pIdx); +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + sqlite3DeleteIndexSamples(db, pIdx); + pIdx->aSample = 0; +#endif + } + + /* Check to make sure the sqlite_stat1 table exists */ + sInfo.db = db; + sInfo.zDatabase = db->aDb[iDb].zName; + if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){ + return SQLITE_ERROR; + } + + /* Load new statistics out of the sqlite_stat1 table */ + zSql = sqlite3MPrintf(db, + "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase); + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); + sqlite3DbFree(db, zSql); + } + + + /* Load the statistics from the sqlite_stat4 table. */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ + int lookasideEnabled = db->lookaside.bEnabled; + db->lookaside.bEnabled = 0; + rc = loadStat4(db, sInfo.zDatabase); + db->lookaside.bEnabled = lookasideEnabled; + } + for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ + Index *pIdx = sqliteHashData(i); + sqlite3_free(pIdx->aiRowEst); + pIdx->aiRowEst = 0; + } +#endif + + if( rc==SQLITE_NOMEM ){ + db->mallocFailed = 1; + } + return rc; +} + + +#endif /* SQLITE_OMIT_ANALYZE */ + +/************** End of analyze.c *********************************************/ +/************** Begin file attach.c ******************************************/ +/* +** 2003 April 6 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code used to implement the ATTACH and DETACH commands. +*/ +/* #include "sqliteInt.h" */ + +#ifndef SQLITE_OMIT_ATTACH +/* +** Resolve an expression that was part of an ATTACH or DETACH statement. This +** is slightly different from resolving a normal SQL expression, because simple +** identifiers are treated as strings, not possible column names or aliases. +** +** i.e. if the parser sees: +** +** ATTACH DATABASE abc AS def +** +** it treats the two expressions as literal strings 'abc' and 'def' instead of +** looking for columns of the same name. +** +** This only applies to the root node of pExpr, so the statement: +** +** ATTACH DATABASE abc||def AS 'db2' +** +** will fail because neither abc or def can be resolved. +*/ +static int resolveAttachExpr(NameContext *pName, Expr *pExpr) +{ + int rc = SQLITE_OK; + if( pExpr ){ + if( pExpr->op!=TK_ID ){ + rc = sqlite3ResolveExprNames(pName, pExpr); + }else{ + pExpr->op = TK_STRING; + } + } + return rc; +} + +/* +** An SQL user-function registered to do the work of an ATTACH statement. The +** three arguments to the function come directly from an attach statement: +** +** ATTACH DATABASE x AS y KEY z +** +** SELECT sqlite_attach(x, y, z) +** +** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the +** third argument. +*/ +static void attachFunc( + sqlite3_context *context, + int NotUsed, + sqlite3_value **argv +){ + int i; + int rc = 0; + sqlite3 *db = sqlite3_context_db_handle(context); + const char *zName; + const char *zFile; + char *zPath = 0; + char *zErr = 0; + unsigned int flags; + Db *aNew; + char *zErrDyn = 0; + sqlite3_vfs *pVfs; + + UNUSED_PARAMETER(NotUsed); + + zFile = (const char *)sqlite3_value_text(argv[0]); + zName = (const char *)sqlite3_value_text(argv[1]); + if( zFile==0 ) zFile = ""; + if( zName==0 ) zName = ""; + + /* Check for the following errors: + ** + ** * Too many attached databases, + ** * Transaction currently open + ** * Specified database name already being used. + */ + if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ + zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", + db->aLimit[SQLITE_LIMIT_ATTACHED] + ); + goto attach_error; + } + if( !db->autoCommit ){ + zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction"); + goto attach_error; + } + for(i=0; inDb; i++){ + char *z = db->aDb[i].zName; + assert( z && zName ); + if( sqlite3StrICmp(z, zName)==0 ){ + zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); + goto attach_error; + } + } + + /* Allocate the new entry in the db->aDb[] array and initialize the schema + ** hash tables. + */ + if( db->aDb==db->aDbStatic ){ + aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 ); + if( aNew==0 ) return; + memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); + }else{ + aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); + if( aNew==0 ) return; + } + db->aDb = aNew; + aNew = &db->aDb[db->nDb]; + memset(aNew, 0, sizeof(*aNew)); + + /* Open the database file. If the btree is successfully opened, use + ** it to obtain the database schema. At this point the schema may + ** or may not be initialized. + */ + flags = db->openFlags; + rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); + return; + } + assert( pVfs ); + flags |= SQLITE_OPEN_MAIN_DB; + rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags); + sqlite3_free( zPath ); + db->nDb++; + if( rc==SQLITE_CONSTRAINT ){ + rc = SQLITE_ERROR; + zErrDyn = sqlite3MPrintf(db, "database is already attached"); + }else if( rc==SQLITE_OK ){ + Pager *pPager; + aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt); + if( !aNew->pSchema ){ + rc = SQLITE_NOMEM; + }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ + zErrDyn = sqlite3MPrintf(db, + "attached databases must use the same text encoding as main database"); + rc = SQLITE_ERROR; + } + sqlite3BtreeEnter(aNew->pBt); + pPager = sqlite3BtreePager(aNew->pBt); + sqlite3PagerLockingMode(pPager, db->dfltLockMode); + sqlite3BtreeSecureDelete(aNew->pBt, + sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); +#ifndef SQLITE_OMIT_PAGER_PRAGMAS + sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK)); +#endif + sqlite3BtreeLeave(aNew->pBt); + } + aNew->safety_level = 3; + aNew->zName = sqlite3DbStrDup(db, zName); + if( rc==SQLITE_OK && aNew->zName==0 ){ + rc = SQLITE_NOMEM; + } + + +#ifdef SQLITE_HAS_CODEC + if( rc==SQLITE_OK ){ + extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); + extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); + int nKey; + char *zKey; + int t = sqlite3_value_type(argv[2]); + switch( t ){ + case SQLITE_INTEGER: + case SQLITE_FLOAT: + zErrDyn = sqlite3DbStrDup(db, "Invalid key value"); + rc = SQLITE_ERROR; + break; + + case SQLITE_TEXT: + case SQLITE_BLOB: + nKey = sqlite3_value_bytes(argv[2]); + zKey = (char *)sqlite3_value_blob(argv[2]); + rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); + break; + + case SQLITE_NULL: + /* No key specified. Use the key from the main database */ + sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); + if( nKey>0 || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){ + rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); + } + break; + } + } +#endif + + /* If the file was opened successfully, read the schema for the new database. + ** If this fails, or if opening the file failed, then close the file and + ** remove the entry from the db->aDb[] array. i.e. put everything back the way + ** we found it. + */ + if( rc==SQLITE_OK ){ + sqlite3BtreeEnterAll(db); + rc = sqlite3Init(db, &zErrDyn); + sqlite3BtreeLeaveAll(db); + } +#ifdef SQLITE_USER_AUTHENTICATION + if( rc==SQLITE_OK ){ + u8 newAuth = 0; + rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth); + if( newAuthauth.authLevel ){ + rc = SQLITE_AUTH_USER; + } + } +#endif + if( rc ){ + int iDb = db->nDb - 1; + assert( iDb>=2 ); + if( db->aDb[iDb].pBt ){ + sqlite3BtreeClose(db->aDb[iDb].pBt); + db->aDb[iDb].pBt = 0; + db->aDb[iDb].pSchema = 0; + } + sqlite3ResetAllSchemasOfConnection(db); + db->nDb = iDb; + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + db->mallocFailed = 1; + sqlite3DbFree(db, zErrDyn); + zErrDyn = sqlite3MPrintf(db, "out of memory"); + }else if( zErrDyn==0 ){ + zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); + } + goto attach_error; + } + + return; + +attach_error: + /* Return an error if we get here */ + if( zErrDyn ){ + sqlite3_result_error(context, zErrDyn, -1); + sqlite3DbFree(db, zErrDyn); + } + if( rc ) sqlite3_result_error_code(context, rc); +} + +/* +** An SQL user-function registered to do the work of an DETACH statement. The +** three arguments to the function come directly from a detach statement: +** +** DETACH DATABASE x +** +** SELECT sqlite_detach(x) +*/ +static void detachFunc( + sqlite3_context *context, + int NotUsed, + sqlite3_value **argv +){ + const char *zName = (const char *)sqlite3_value_text(argv[0]); + sqlite3 *db = sqlite3_context_db_handle(context); + int i; + Db *pDb = 0; + char zErr[128]; + + UNUSED_PARAMETER(NotUsed); + + if( zName==0 ) zName = ""; + for(i=0; inDb; i++){ + pDb = &db->aDb[i]; + if( pDb->pBt==0 ) continue; + if( sqlite3StrICmp(pDb->zName, zName)==0 ) break; + } + + if( i>=db->nDb ){ + sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName); + goto detach_error; + } + if( i<2 ){ + sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName); + goto detach_error; + } + if( !db->autoCommit ){ + sqlite3_snprintf(sizeof(zErr), zErr, + "cannot DETACH database within transaction"); + goto detach_error; + } + if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){ + sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName); + goto detach_error; + } + + sqlite3BtreeClose(pDb->pBt); + pDb->pBt = 0; + pDb->pSchema = 0; + sqlite3CollapseDatabaseArray(db); + return; + +detach_error: + sqlite3_result_error(context, zErr, -1); +} + +/* +** This procedure generates VDBE code for a single invocation of either the +** sqlite_detach() or sqlite_attach() SQL user functions. +*/ +static void codeAttach( + Parse *pParse, /* The parser context */ + int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */ + FuncDef const *pFunc,/* FuncDef wrapper for detachFunc() or attachFunc() */ + Expr *pAuthArg, /* Expression to pass to authorization callback */ + Expr *pFilename, /* Name of database file */ + Expr *pDbname, /* Name of the database to use internally */ + Expr *pKey /* Database key for encryption extension */ +){ + int rc; + NameContext sName; + Vdbe *v; + sqlite3* db = pParse->db; + int regArgs; + + memset(&sName, 0, sizeof(NameContext)); + sName.pParse = pParse; + + if( + SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) || + SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) || + SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey)) + ){ + goto attach_end; + } + +#ifndef SQLITE_OMIT_AUTHORIZATION + if( pAuthArg ){ + char *zAuthArg; + if( pAuthArg->op==TK_STRING ){ + zAuthArg = pAuthArg->u.zToken; + }else{ + zAuthArg = 0; + } + rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); + if(rc!=SQLITE_OK ){ + goto attach_end; + } + } +#endif /* SQLITE_OMIT_AUTHORIZATION */ + + + v = sqlite3GetVdbe(pParse); + regArgs = sqlite3GetTempRange(pParse, 4); + sqlite3ExprCode(pParse, pFilename, regArgs); + sqlite3ExprCode(pParse, pDbname, regArgs+1); + sqlite3ExprCode(pParse, pKey, regArgs+2); + + assert( v || db->mallocFailed ); + if( v ){ + sqlite3VdbeAddOp3(v, OP_Function0, 0, regArgs+3-pFunc->nArg, regArgs+3); + assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg ); + sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg)); + sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF); + + /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this + ** statement only). For DETACH, set it to false (expire all existing + ** statements). + */ + sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH)); + } + +attach_end: + sqlite3ExprDelete(db, pFilename); + sqlite3ExprDelete(db, pDbname); + sqlite3ExprDelete(db, pKey); +} + +/* +** Called by the parser to compile a DETACH statement. +** +** DETACH pDbname +*/ +SQLITE_PRIVATE void sqlite3Detach(Parse *pParse, Expr *pDbname){ + static const FuncDef detach_func = { + 1, /* nArg */ + SQLITE_UTF8, /* funcFlags */ + 0, /* pUserData */ + 0, /* pNext */ + detachFunc, /* xFunc */ + 0, /* xStep */ + 0, /* xFinalize */ + "sqlite_detach", /* zName */ + 0, /* pHash */ + 0 /* pDestructor */ + }; + codeAttach(pParse, SQLITE_DETACH, &detach_func, pDbname, 0, 0, pDbname); +} + +/* +** Called by the parser to compile an ATTACH statement. +** +** ATTACH p AS pDbname KEY pKey +*/ +SQLITE_PRIVATE void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){ + static const FuncDef attach_func = { + 3, /* nArg */ + SQLITE_UTF8, /* funcFlags */ + 0, /* pUserData */ + 0, /* pNext */ + attachFunc, /* xFunc */ + 0, /* xStep */ + 0, /* xFinalize */ + "sqlite_attach", /* zName */ + 0, /* pHash */ + 0 /* pDestructor */ + }; + codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey); +} +#endif /* SQLITE_OMIT_ATTACH */ + +/* +** Initialize a DbFixer structure. This routine must be called prior +** to passing the structure to one of the sqliteFixAAAA() routines below. +*/ +SQLITE_PRIVATE void sqlite3FixInit( + DbFixer *pFix, /* The fixer to be initialized */ + Parse *pParse, /* Error messages will be written here */ + int iDb, /* This is the database that must be used */ + const char *zType, /* "view", "trigger", or "index" */ + const Token *pName /* Name of the view, trigger, or index */ +){ + sqlite3 *db; + + db = pParse->db; + assert( db->nDb>iDb ); + pFix->pParse = pParse; + pFix->zDb = db->aDb[iDb].zName; + pFix->pSchema = db->aDb[iDb].pSchema; + pFix->zType = zType; + pFix->pName = pName; + pFix->bVarOnly = (iDb==1); +} + +/* +** The following set of routines walk through the parse tree and assign +** a specific database to all table references where the database name +** was left unspecified in the original SQL statement. The pFix structure +** must have been initialized by a prior call to sqlite3FixInit(). +** +** These routines are used to make sure that an index, trigger, or +** view in one database does not refer to objects in a different database. +** (Exception: indices, triggers, and views in the TEMP database are +** allowed to refer to anything.) If a reference is explicitly made +** to an object in a different database, an error message is added to +** pParse->zErrMsg and these routines return non-zero. If everything +** checks out, these routines return 0. +*/ +SQLITE_PRIVATE int sqlite3FixSrcList( + DbFixer *pFix, /* Context of the fixation */ + SrcList *pList /* The Source list to check and modify */ +){ + int i; + const char *zDb; + struct SrcList_item *pItem; + + if( NEVER(pList==0) ) return 0; + zDb = pFix->zDb; + for(i=0, pItem=pList->a; inSrc; i++, pItem++){ + if( pFix->bVarOnly==0 ){ + if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){ + sqlite3ErrorMsg(pFix->pParse, + "%s %T cannot reference objects in database %s", + pFix->zType, pFix->pName, pItem->zDatabase); + return 1; + } + sqlite3DbFree(pFix->pParse->db, pItem->zDatabase); + pItem->zDatabase = 0; + pItem->pSchema = pFix->pSchema; + } +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) + if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; + if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; +#endif + } + return 0; +} +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) +SQLITE_PRIVATE int sqlite3FixSelect( + DbFixer *pFix, /* Context of the fixation */ + Select *pSelect /* The SELECT statement to be fixed to one database */ +){ + while( pSelect ){ + if( sqlite3FixExprList(pFix, pSelect->pEList) ){ + return 1; + } + if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pSelect->pWhere) ){ + return 1; + } + if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pSelect->pHaving) ){ + return 1; + } + if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pSelect->pLimit) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pSelect->pOffset) ){ + return 1; + } + pSelect = pSelect->pPrior; + } + return 0; +} +SQLITE_PRIVATE int sqlite3FixExpr( + DbFixer *pFix, /* Context of the fixation */ + Expr *pExpr /* The expression to be fixed to one database */ +){ + while( pExpr ){ + if( pExpr->op==TK_VARIABLE ){ + if( pFix->pParse->db->init.busy ){ + pExpr->op = TK_NULL; + }else{ + sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType); + return 1; + } + } + if( ExprHasProperty(pExpr, EP_TokenOnly) ) break; + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; + }else{ + if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; + } + if( sqlite3FixExpr(pFix, pExpr->pRight) ){ + return 1; + } + pExpr = pExpr->pLeft; + } + return 0; +} +SQLITE_PRIVATE int sqlite3FixExprList( + DbFixer *pFix, /* Context of the fixation */ + ExprList *pList /* The expression to be fixed to one database */ +){ + int i; + struct ExprList_item *pItem; + if( pList==0 ) return 0; + for(i=0, pItem=pList->a; inExpr; i++, pItem++){ + if( sqlite3FixExpr(pFix, pItem->pExpr) ){ + return 1; + } + } + return 0; +} +#endif + +#ifndef SQLITE_OMIT_TRIGGER +SQLITE_PRIVATE int sqlite3FixTriggerStep( + DbFixer *pFix, /* Context of the fixation */ + TriggerStep *pStep /* The trigger step be fixed to one database */ +){ + while( pStep ){ + if( sqlite3FixSelect(pFix, pStep->pSelect) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pStep->pWhere) ){ + return 1; + } + if( sqlite3FixExprList(pFix, pStep->pExprList) ){ + return 1; + } + pStep = pStep->pNext; + } + return 0; +} +#endif + +/************** End of attach.c **********************************************/ +/************** Begin file auth.c ********************************************/ +/* +** 2003 January 11 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code used to implement the sqlite3_set_authorizer() +** API. This facility is an optional feature of the library. Embedded +** systems that do not need this facility may omit it by recompiling +** the library with -DSQLITE_OMIT_AUTHORIZATION=1 +*/ +/* #include "sqliteInt.h" */ + +/* +** All of the code in this file may be omitted by defining a single +** macro. +*/ +#ifndef SQLITE_OMIT_AUTHORIZATION + +/* +** Set or clear the access authorization function. +** +** The access authorization function is be called during the compilation +** phase to verify that the user has read and/or write access permission on +** various fields of the database. The first argument to the auth function +** is a copy of the 3rd argument to this routine. The second argument +** to the auth function is one of these constants: +** +** SQLITE_CREATE_INDEX +** SQLITE_CREATE_TABLE +** SQLITE_CREATE_TEMP_INDEX +** SQLITE_CREATE_TEMP_TABLE +** SQLITE_CREATE_TEMP_TRIGGER +** SQLITE_CREATE_TEMP_VIEW +** SQLITE_CREATE_TRIGGER +** SQLITE_CREATE_VIEW +** SQLITE_DELETE +** SQLITE_DROP_INDEX +** SQLITE_DROP_TABLE +** SQLITE_DROP_TEMP_INDEX +** SQLITE_DROP_TEMP_TABLE +** SQLITE_DROP_TEMP_TRIGGER +** SQLITE_DROP_TEMP_VIEW +** SQLITE_DROP_TRIGGER +** SQLITE_DROP_VIEW +** SQLITE_INSERT +** SQLITE_PRAGMA +** SQLITE_READ +** SQLITE_SELECT +** SQLITE_TRANSACTION +** SQLITE_UPDATE +** +** The third and fourth arguments to the auth function are the name of +** the table and the column that are being accessed. The auth function +** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE. If +** SQLITE_OK is returned, it means that access is allowed. SQLITE_DENY +** means that the SQL statement will never-run - the sqlite3_exec() call +** will return with an error. SQLITE_IGNORE means that the SQL statement +** should run but attempts to read the specified column will return NULL +** and attempts to write the column will be ignored. +** +** Setting the auth function to NULL disables this hook. The default +** setting of the auth function is NULL. +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( + sqlite3 *db, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pArg +){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; +#endif + sqlite3_mutex_enter(db->mutex); + db->xAuth = (sqlite3_xauth)xAuth; + db->pAuthArg = pArg; + sqlite3ExpirePreparedStatements(db); + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + +/* +** Write an error message into pParse->zErrMsg that explains that the +** user-supplied authorization function returned an illegal value. +*/ +static void sqliteAuthBadReturnCode(Parse *pParse){ + sqlite3ErrorMsg(pParse, "authorizer malfunction"); + pParse->rc = SQLITE_ERROR; +} + +/* +** Invoke the authorization callback for permission to read column zCol from +** table zTab in database zDb. This function assumes that an authorization +** callback has been registered (i.e. that sqlite3.xAuth is not NULL). +** +** If SQLITE_IGNORE is returned and pExpr is not NULL, then pExpr is changed +** to an SQL NULL expression. Otherwise, if pExpr is NULL, then SQLITE_IGNORE +** is treated as SQLITE_DENY. In this case an error is left in pParse. +*/ +SQLITE_PRIVATE int sqlite3AuthReadCol( + Parse *pParse, /* The parser context */ + const char *zTab, /* Table name */ + const char *zCol, /* Column name */ + int iDb /* Index of containing database. */ +){ + sqlite3 *db = pParse->db; /* Database handle */ + char *zDb = db->aDb[iDb].zName; /* Name of attached database */ + int rc; /* Auth callback return code */ + + rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext +#ifdef SQLITE_USER_AUTHENTICATION + ,db->auth.zAuthUser +#endif + ); + if( rc==SQLITE_DENY ){ + if( db->nDb>2 || iDb!=0 ){ + sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol); + }else{ + sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited", zTab, zCol); + } + pParse->rc = SQLITE_AUTH; + }else if( rc!=SQLITE_IGNORE && rc!=SQLITE_OK ){ + sqliteAuthBadReturnCode(pParse); + } + return rc; +} + +/* +** The pExpr should be a TK_COLUMN expression. The table referred to +** is in pTabList or else it is the NEW or OLD table of a trigger. +** Check to see if it is OK to read this particular column. +** +** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN +** instruction into a TK_NULL. If the auth function returns SQLITE_DENY, +** then generate an error. +*/ +SQLITE_PRIVATE void sqlite3AuthRead( + Parse *pParse, /* The parser context */ + Expr *pExpr, /* The expression to check authorization on */ + Schema *pSchema, /* The schema of the expression */ + SrcList *pTabList /* All table that pExpr might refer to */ +){ + sqlite3 *db = pParse->db; + Table *pTab = 0; /* The table being read */ + const char *zCol; /* Name of the column of the table */ + int iSrc; /* Index in pTabList->a[] of table being read */ + int iDb; /* The index of the database the expression refers to */ + int iCol; /* Index of column in table */ + + if( db->xAuth==0 ) return; + iDb = sqlite3SchemaToIndex(pParse->db, pSchema); + if( iDb<0 ){ + /* An attempt to read a column out of a subquery or other + ** temporary table. */ + return; + } + + assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); + if( pExpr->op==TK_TRIGGER ){ + pTab = pParse->pTriggerTab; + }else{ + assert( pTabList ); + for(iSrc=0; ALWAYS(iSrcnSrc); iSrc++){ + if( pExpr->iTable==pTabList->a[iSrc].iCursor ){ + pTab = pTabList->a[iSrc].pTab; + break; + } + } + } + iCol = pExpr->iColumn; + if( NEVER(pTab==0) ) return; + + if( iCol>=0 ){ + assert( iColnCol ); + zCol = pTab->aCol[iCol].zName; + }else if( pTab->iPKey>=0 ){ + assert( pTab->iPKeynCol ); + zCol = pTab->aCol[pTab->iPKey].zName; + }else{ + zCol = "ROWID"; + } + assert( iDb>=0 && iDbnDb ); + if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){ + pExpr->op = TK_NULL; + } +} + +/* +** Do an authorization check using the code and arguments given. Return +** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY +** is returned, then the error count and error message in pParse are +** modified appropriately. +*/ +SQLITE_PRIVATE int sqlite3AuthCheck( + Parse *pParse, + int code, + const char *zArg1, + const char *zArg2, + const char *zArg3 +){ + sqlite3 *db = pParse->db; + int rc; + + /* Don't do any authorization checks if the database is initialising + ** or if the parser is being invoked from within sqlite3_declare_vtab. + */ + if( db->init.busy || IN_DECLARE_VTAB ){ + return SQLITE_OK; + } + + if( db->xAuth==0 ){ + return SQLITE_OK; + } + rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext +#ifdef SQLITE_USER_AUTHENTICATION + ,db->auth.zAuthUser +#endif + ); + if( rc==SQLITE_DENY ){ + sqlite3ErrorMsg(pParse, "not authorized"); + pParse->rc = SQLITE_AUTH; + }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){ + rc = SQLITE_DENY; + sqliteAuthBadReturnCode(pParse); + } + return rc; +} + +/* +** Push an authorization context. After this routine is called, the +** zArg3 argument to authorization callbacks will be zContext until +** popped. Or if pParse==0, this routine is a no-op. +*/ +SQLITE_PRIVATE void sqlite3AuthContextPush( + Parse *pParse, + AuthContext *pContext, + const char *zContext +){ + assert( pParse ); + pContext->pParse = pParse; + pContext->zAuthContext = pParse->zAuthContext; + pParse->zAuthContext = zContext; +} + +/* +** Pop an authorization context that was previously pushed +** by sqlite3AuthContextPush +*/ +SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext *pContext){ + if( pContext->pParse ){ + pContext->pParse->zAuthContext = pContext->zAuthContext; + pContext->pParse = 0; + } +} + +#endif /* SQLITE_OMIT_AUTHORIZATION */ + +/************** End of auth.c ************************************************/ +/************** Begin file build.c *******************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains C code routines that are called by the SQLite parser +** when syntax rules are reduced. The routines in this file handle the +** following kinds of SQL syntax: +** +** CREATE TABLE +** DROP TABLE +** CREATE INDEX +** DROP INDEX +** creating ID lists +** BEGIN TRANSACTION +** COMMIT +** ROLLBACK +*/ +/* #include "sqliteInt.h" */ + +/* +** This routine is called when a new SQL statement is beginning to +** be parsed. Initialize the pParse structure as needed. +*/ +SQLITE_PRIVATE void sqlite3BeginParse(Parse *pParse, int explainFlag){ + pParse->explain = (u8)explainFlag; + pParse->nVar = 0; +} + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** The TableLock structure is only used by the sqlite3TableLock() and +** codeTableLocks() functions. +*/ +struct TableLock { + int iDb; /* The database containing the table to be locked */ + int iTab; /* The root page of the table to be locked */ + u8 isWriteLock; /* True for write lock. False for a read lock */ + const char *zName; /* Name of the table */ +}; + +/* +** Record the fact that we want to lock a table at run-time. +** +** The table to be locked has root page iTab and is found in database iDb. +** A read or a write lock can be taken depending on isWritelock. +** +** This routine just records the fact that the lock is desired. The +** code to make the lock occur is generated by a later call to +** codeTableLocks() which occurs during sqlite3FinishCoding(). +*/ +SQLITE_PRIVATE void sqlite3TableLock( + Parse *pParse, /* Parsing context */ + int iDb, /* Index of the database containing the table to lock */ + int iTab, /* Root page number of the table to be locked */ + u8 isWriteLock, /* True for a write lock */ + const char *zName /* Name of the table to be locked */ +){ + Parse *pToplevel = sqlite3ParseToplevel(pParse); + int i; + int nBytes; + TableLock *p; + assert( iDb>=0 ); + + for(i=0; inTableLock; i++){ + p = &pToplevel->aTableLock[i]; + if( p->iDb==iDb && p->iTab==iTab ){ + p->isWriteLock = (p->isWriteLock || isWriteLock); + return; + } + } + + nBytes = sizeof(TableLock) * (pToplevel->nTableLock+1); + pToplevel->aTableLock = + sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes); + if( pToplevel->aTableLock ){ + p = &pToplevel->aTableLock[pToplevel->nTableLock++]; + p->iDb = iDb; + p->iTab = iTab; + p->isWriteLock = isWriteLock; + p->zName = zName; + }else{ + pToplevel->nTableLock = 0; + pToplevel->db->mallocFailed = 1; + } +} + +/* +** Code an OP_TableLock instruction for each table locked by the +** statement (configured by calls to sqlite3TableLock()). +*/ +static void codeTableLocks(Parse *pParse){ + int i; + Vdbe *pVdbe; + + pVdbe = sqlite3GetVdbe(pParse); + assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */ + + for(i=0; inTableLock; i++){ + TableLock *p = &pParse->aTableLock[i]; + int p1 = p->iDb; + sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock, + p->zName, P4_STATIC); + } +} +#else + #define codeTableLocks(x) +#endif + +/* +** Return TRUE if the given yDbMask object is empty - if it contains no +** 1 bits. This routine is used by the DbMaskAllZero() and DbMaskNotZero() +** macros when SQLITE_MAX_ATTACHED is greater than 30. +*/ +#if SQLITE_MAX_ATTACHED>30 +SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask m){ + int i; + for(i=0; ipToplevel==0 ); + db = pParse->db; + if( pParse->nested ) return; + if( db->mallocFailed || pParse->nErr ){ + if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR; + return; + } + + /* Begin by generating some termination code at the end of the + ** vdbe program + */ + v = sqlite3GetVdbe(pParse); + assert( !pParse->isMultiWrite + || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); + if( v ){ + while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){} + sqlite3VdbeAddOp0(v, OP_Halt); + +#if SQLITE_USER_AUTHENTICATION + if( pParse->nTableLock>0 && db->init.busy==0 ){ + sqlite3UserAuthInit(db); + if( db->auth.authLevelrc = SQLITE_AUTH_USER; + sqlite3ErrorMsg(pParse, "user not authenticated"); + return; + } + } +#endif + + /* The cookie mask contains one bit for each database file open. + ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are + ** set for each database that is used. Generate code to start a + ** transaction on each used database and to verify the schema cookie + ** on each used database. + */ + if( db->mallocFailed==0 + && (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr) + ){ + int iDb, i; + assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init ); + sqlite3VdbeJumpHere(v, 0); + for(iDb=0; iDbnDb; iDb++){ + if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue; + sqlite3VdbeUsesBtree(v, iDb); + sqlite3VdbeAddOp4Int(v, + OP_Transaction, /* Opcode */ + iDb, /* P1 */ + DbMaskTest(pParse->writeMask,iDb), /* P2 */ + pParse->cookieValue[iDb], /* P3 */ + db->aDb[iDb].pSchema->iGeneration /* P4 */ + ); + if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + for(i=0; inVtabLock; i++){ + char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]); + sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); + } + pParse->nVtabLock = 0; +#endif + + /* Once all the cookies have been verified and transactions opened, + ** obtain the required table-locks. This is a no-op unless the + ** shared-cache feature is enabled. + */ + codeTableLocks(pParse); + + /* Initialize any AUTOINCREMENT data structures required. + */ + sqlite3AutoincrementBegin(pParse); + + /* Code constant expressions that where factored out of inner loops */ + if( pParse->pConstExpr ){ + ExprList *pEL = pParse->pConstExpr; + pParse->okConstFactor = 0; + for(i=0; inExpr; i++){ + sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg); + } + } + + /* Finally, jump back to the beginning of the executable code. */ + sqlite3VdbeAddOp2(v, OP_Goto, 0, 1); + } + } + + + /* Get the VDBE program ready for execution + */ + if( v && pParse->nErr==0 && !db->mallocFailed ){ + assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */ + /* A minimum of one cursor is required if autoincrement is used + * See ticket [a696379c1f08866] */ + if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1; + sqlite3VdbeMakeReady(v, pParse); + pParse->rc = SQLITE_DONE; + pParse->colNamesSet = 0; + }else{ + pParse->rc = SQLITE_ERROR; + } + pParse->nTab = 0; + pParse->nMem = 0; + pParse->nSet = 0; + pParse->nVar = 0; + DbMaskZero(pParse->cookieMask); +} + +/* +** Run the parser and code generator recursively in order to generate +** code for the SQL statement given onto the end of the pParse context +** currently under construction. When the parser is run recursively +** this way, the final OP_Halt is not appended and other initialization +** and finalization steps are omitted because those are handling by the +** outermost parser. +** +** Not everything is nestable. This facility is designed to permit +** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use +** care if you decide to try to use this routine for some other purposes. +*/ +SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ + va_list ap; + char *zSql; + char *zErrMsg = 0; + sqlite3 *db = pParse->db; +# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar)) + char saveBuf[SAVE_SZ]; + + if( pParse->nErr ) return; + assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ + va_start(ap, zFormat); + zSql = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + if( zSql==0 ){ + return; /* A malloc must have failed */ + } + pParse->nested++; + memcpy(saveBuf, &pParse->nVar, SAVE_SZ); + memset(&pParse->nVar, 0, SAVE_SZ); + sqlite3RunParser(pParse, zSql, &zErrMsg); + sqlite3DbFree(db, zErrMsg); + sqlite3DbFree(db, zSql); + memcpy(&pParse->nVar, saveBuf, SAVE_SZ); + pParse->nested--; +} + +#if SQLITE_USER_AUTHENTICATION +/* +** Return TRUE if zTable is the name of the system table that stores the +** list of users and their access credentials. +*/ +SQLITE_PRIVATE int sqlite3UserAuthTable(const char *zTable){ + return sqlite3_stricmp(zTable, "sqlite_user")==0; +} +#endif + +/* +** Locate the in-memory structure that describes a particular database +** table given the name of that table and (optionally) the name of the +** database containing the table. Return NULL if not found. +** +** If zDatabase is 0, all databases are searched for the table and the +** first matching table is returned. (No checking for duplicate table +** names is done.) The search order is TEMP first, then MAIN, then any +** auxiliary databases added using the ATTACH command. +** +** See also sqlite3LocateTable(). +*/ +SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ + Table *p = 0; + int i; + + /* All mutexes are required for schema access. Make sure we hold them. */ + assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) ); +#if SQLITE_USER_AUTHENTICATION + /* Only the admin user is allowed to know that the sqlite_user table + ** exists */ + if( db->auth.authLevelnDb; i++){ + int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ + if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; + assert( sqlite3SchemaMutexHeld(db, j, 0) ); + p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName); + if( p ) break; + } + return p; +} + +/* +** Locate the in-memory structure that describes a particular database +** table given the name of that table and (optionally) the name of the +** database containing the table. Return NULL if not found. Also leave an +** error message in pParse->zErrMsg. +** +** The difference between this routine and sqlite3FindTable() is that this +** routine leaves an error message in pParse->zErrMsg where +** sqlite3FindTable() does not. +*/ +SQLITE_PRIVATE Table *sqlite3LocateTable( + Parse *pParse, /* context in which to report errors */ + int isView, /* True if looking for a VIEW rather than a TABLE */ + const char *zName, /* Name of the table we are looking for */ + const char *zDbase /* Name of the database. Might be NULL */ +){ + Table *p; + + /* Read the database schema. If an error occurs, leave an error message + ** and code in pParse and return NULL. */ + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + return 0; + } + + p = sqlite3FindTable(pParse->db, zName, zDbase); + if( p==0 ){ + const char *zMsg = isView ? "no such view" : "no such table"; + if( zDbase ){ + sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName); + }else{ + sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName); + } + pParse->checkSchema = 1; + } +#if SQLITE_USER_AUTHENICATION + else if( pParse->db->auth.authLevelpSchema) if it is not NULL. p->pSchema may be +** non-NULL if it is part of a view or trigger program definition. See +** sqlite3FixSrcList() for details. +*/ +SQLITE_PRIVATE Table *sqlite3LocateTableItem( + Parse *pParse, + int isView, + struct SrcList_item *p +){ + const char *zDb; + assert( p->pSchema==0 || p->zDatabase==0 ); + if( p->pSchema ){ + int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema); + zDb = pParse->db->aDb[iDb].zName; + }else{ + zDb = p->zDatabase; + } + return sqlite3LocateTable(pParse, isView, p->zName, zDb); +} + +/* +** Locate the in-memory structure that describes +** a particular index given the name of that index +** and the name of the database that contains the index. +** Return NULL if not found. +** +** If zDatabase is 0, all databases are searched for the +** table and the first matching index is returned. (No checking +** for duplicate index names is done.) The search order is +** TEMP first, then MAIN, then any auxiliary databases added +** using the ATTACH command. +*/ +SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ + Index *p = 0; + int i; + /* All mutexes are required for schema access. Make sure we hold them. */ + assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); + for(i=OMIT_TEMPDB; inDb; i++){ + int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ + Schema *pSchema = db->aDb[j].pSchema; + assert( pSchema ); + if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; + assert( sqlite3SchemaMutexHeld(db, j, 0) ); + p = sqlite3HashFind(&pSchema->idxHash, zName); + if( p ) break; + } + return p; +} + +/* +** Reclaim the memory used by an index +*/ +static void freeIndex(sqlite3 *db, Index *p){ +#ifndef SQLITE_OMIT_ANALYZE + sqlite3DeleteIndexSamples(db, p); +#endif + sqlite3ExprDelete(db, p->pPartIdxWhere); + sqlite3DbFree(db, p->zColAff); + if( p->isResized ) sqlite3DbFree(db, p->azColl); +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + sqlite3_free(p->aiRowEst); +#endif + sqlite3DbFree(db, p); +} + +/* +** For the index called zIdxName which is found in the database iDb, +** unlike that index from its Table then remove the index from +** the index hash table and free all memory structures associated +** with the index. +*/ +SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ + Index *pIndex; + Hash *pHash; + + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + pHash = &db->aDb[iDb].pSchema->idxHash; + pIndex = sqlite3HashInsert(pHash, zIdxName, 0); + if( ALWAYS(pIndex) ){ + if( pIndex->pTable->pIndex==pIndex ){ + pIndex->pTable->pIndex = pIndex->pNext; + }else{ + Index *p; + /* Justification of ALWAYS(); The index must be on the list of + ** indices. */ + p = pIndex->pTable->pIndex; + while( ALWAYS(p) && p->pNext!=pIndex ){ p = p->pNext; } + if( ALWAYS(p && p->pNext==pIndex) ){ + p->pNext = pIndex->pNext; + } + } + freeIndex(db, pIndex); + } + db->flags |= SQLITE_InternChanges; +} + +/* +** Look through the list of open database files in db->aDb[] and if +** any have been closed, remove them from the list. Reallocate the +** db->aDb[] structure to a smaller size, if possible. +** +** Entry 0 (the "main" database) and entry 1 (the "temp" database) +** are never candidates for being collapsed. +*/ +SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3 *db){ + int i, j; + for(i=j=2; inDb; i++){ + struct Db *pDb = &db->aDb[i]; + if( pDb->pBt==0 ){ + sqlite3DbFree(db, pDb->zName); + pDb->zName = 0; + continue; + } + if( jaDb[j] = db->aDb[i]; + } + j++; + } + memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j])); + db->nDb = j; + if( db->nDb<=2 && db->aDb!=db->aDbStatic ){ + memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0])); + sqlite3DbFree(db, db->aDb); + db->aDb = db->aDbStatic; + } +} + +/* +** Reset the schema for the database at index iDb. Also reset the +** TEMP schema. +*/ +SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){ + Db *pDb; + assert( iDbnDb ); + + /* Case 1: Reset the single schema identified by iDb */ + pDb = &db->aDb[iDb]; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + assert( pDb->pSchema!=0 ); + sqlite3SchemaClear(pDb->pSchema); + + /* If any database other than TEMP is reset, then also reset TEMP + ** since TEMP might be holding triggers that reference tables in the + ** other database. + */ + if( iDb!=1 ){ + pDb = &db->aDb[1]; + assert( pDb->pSchema!=0 ); + sqlite3SchemaClear(pDb->pSchema); + } + return; +} + +/* +** Erase all schema information from all attached databases (including +** "main" and "temp") for a single database connection. +*/ +SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){ + int i; + sqlite3BtreeEnterAll(db); + for(i=0; inDb; i++){ + Db *pDb = &db->aDb[i]; + if( pDb->pSchema ){ + sqlite3SchemaClear(pDb->pSchema); + } + } + db->flags &= ~SQLITE_InternChanges; + sqlite3VtabUnlockList(db); + sqlite3BtreeLeaveAll(db); + sqlite3CollapseDatabaseArray(db); +} + +/* +** This routine is called when a commit occurs. +*/ +SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){ + db->flags &= ~SQLITE_InternChanges; +} + +/* +** Delete memory allocated for the column names of a table or view (the +** Table.aCol[] array). +*/ +static void sqliteDeleteColumnNames(sqlite3 *db, Table *pTable){ + int i; + Column *pCol; + assert( pTable!=0 ); + if( (pCol = pTable->aCol)!=0 ){ + for(i=0; inCol; i++, pCol++){ + sqlite3DbFree(db, pCol->zName); + sqlite3ExprDelete(db, pCol->pDflt); + sqlite3DbFree(db, pCol->zDflt); + sqlite3DbFree(db, pCol->zType); + sqlite3DbFree(db, pCol->zColl); + } + sqlite3DbFree(db, pTable->aCol); + } +} + +/* +** Remove the memory data structures associated with the given +** Table. No changes are made to disk by this routine. +** +** This routine just deletes the data structure. It does not unlink +** the table data structure from the hash table. But it does destroy +** memory structures of the indices and foreign keys associated with +** the table. +** +** The db parameter is optional. It is needed if the Table object +** contains lookaside memory. (Table objects in the schema do not use +** lookaside memory, but some ephemeral Table objects do.) Or the +** db parameter can be used with db->pnBytesFreed to measure the memory +** used by the Table object. +*/ +SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ + Index *pIndex, *pNext; + TESTONLY( int nLookaside; ) /* Used to verify lookaside not used for schema */ + + assert( !pTable || pTable->nRef>0 ); + + /* Do not delete the table until the reference count reaches zero. */ + if( !pTable ) return; + if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return; + + /* Record the number of outstanding lookaside allocations in schema Tables + ** prior to doing any free() operations. Since schema Tables do not use + ** lookaside, this number should not change. */ + TESTONLY( nLookaside = (db && (pTable->tabFlags & TF_Ephemeral)==0) ? + db->lookaside.nOut : 0 ); + + /* Delete all indices associated with this table. */ + for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ + pNext = pIndex->pNext; + assert( pIndex->pSchema==pTable->pSchema ); + if( !db || db->pnBytesFreed==0 ){ + char *zName = pIndex->zName; + TESTONLY ( Index *pOld = ) sqlite3HashInsert( + &pIndex->pSchema->idxHash, zName, 0 + ); + assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); + assert( pOld==pIndex || pOld==0 ); + } + freeIndex(db, pIndex); + } + + /* Delete any foreign keys attached to this table. */ + sqlite3FkDelete(db, pTable); + + /* Delete the Table structure itself. + */ + sqliteDeleteColumnNames(db, pTable); + sqlite3DbFree(db, pTable->zName); + sqlite3DbFree(db, pTable->zColAff); + sqlite3SelectDelete(db, pTable->pSelect); +#ifndef SQLITE_OMIT_CHECK + sqlite3ExprListDelete(db, pTable->pCheck); +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3VtabClear(db, pTable); +#endif + sqlite3DbFree(db, pTable); + + /* Verify that no lookaside memory was used by schema tables */ + assert( nLookaside==0 || nLookaside==db->lookaside.nOut ); +} + +/* +** Unlink the given table from the hash tables and the delete the +** table structure with all its indices and foreign keys. +*/ +SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ + Table *p; + Db *pDb; + + assert( db!=0 ); + assert( iDb>=0 && iDbnDb ); + assert( zTabName ); + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */ + pDb = &db->aDb[iDb]; + p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, 0); + sqlite3DeleteTable(db, p); + db->flags |= SQLITE_InternChanges; +} + +/* +** Given a token, return a string that consists of the text of that +** token. Space to hold the returned string +** is obtained from sqliteMalloc() and must be freed by the calling +** function. +** +** Any quotation marks (ex: "name", 'name', [name], or `name`) that +** surround the body of the token are removed. +** +** Tokens are often just pointers into the original SQL text and so +** are not \000 terminated and are not persistent. The returned string +** is \000 terminated and is persistent. +*/ +SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, Token *pName){ + char *zName; + if( pName ){ + zName = sqlite3DbStrNDup(db, (char*)pName->z, pName->n); + sqlite3Dequote(zName); + }else{ + zName = 0; + } + return zName; +} + +/* +** Open the sqlite_master table stored in database number iDb for +** writing. The table is opened using cursor 0. +*/ +SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){ + Vdbe *v = sqlite3GetVdbe(p); + sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb)); + sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5); + if( p->nTab==0 ){ + p->nTab = 1; + } +} + +/* +** Parameter zName points to a nul-terminated buffer containing the name +** of a database ("main", "temp" or the name of an attached db). This +** function returns the index of the named database in db->aDb[], or +** -1 if the named db cannot be found. +*/ +SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *db, const char *zName){ + int i = -1; /* Database number */ + if( zName ){ + Db *pDb; + int n = sqlite3Strlen30(zName); + for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){ + if( (!OMIT_TEMPDB || i!=1 ) && n==sqlite3Strlen30(pDb->zName) && + 0==sqlite3StrICmp(pDb->zName, zName) ){ + break; + } + } + } + return i; +} + +/* +** The token *pName contains the name of a database (either "main" or +** "temp" or the name of an attached db). This routine returns the +** index of the named database in db->aDb[], or -1 if the named db +** does not exist. +*/ +SQLITE_PRIVATE int sqlite3FindDb(sqlite3 *db, Token *pName){ + int i; /* Database number */ + char *zName; /* Name we are searching for */ + zName = sqlite3NameFromToken(db, pName); + i = sqlite3FindDbName(db, zName); + sqlite3DbFree(db, zName); + return i; +} + +/* The table or view or trigger name is passed to this routine via tokens +** pName1 and pName2. If the table name was fully qualified, for example: +** +** CREATE TABLE xxx.yyy (...); +** +** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if +** the table name is not fully qualified, i.e.: +** +** CREATE TABLE yyy(...); +** +** Then pName1 is set to "yyy" and pName2 is "". +** +** This routine sets the *ppUnqual pointer to point at the token (pName1 or +** pName2) that stores the unqualified table name. The index of the +** database "xxx" is returned. +*/ +SQLITE_PRIVATE int sqlite3TwoPartName( + Parse *pParse, /* Parsing and code generating context */ + Token *pName1, /* The "xxx" in the name "xxx.yyy" or "xxx" */ + Token *pName2, /* The "yyy" in the name "xxx.yyy" */ + Token **pUnqual /* Write the unqualified object name here */ +){ + int iDb; /* Database holding the object */ + sqlite3 *db = pParse->db; + + if( ALWAYS(pName2!=0) && pName2->n>0 ){ + if( db->init.busy ) { + sqlite3ErrorMsg(pParse, "corrupt database"); + return -1; + } + *pUnqual = pName2; + iDb = sqlite3FindDb(db, pName1); + if( iDb<0 ){ + sqlite3ErrorMsg(pParse, "unknown database %T", pName1); + return -1; + } + }else{ + assert( db->init.iDb==0 || db->init.busy ); + iDb = db->init.iDb; + *pUnqual = pName1; + } + return iDb; +} + +/* +** This routine is used to check if the UTF-8 string zName is a legal +** unqualified name for a new schema object (table, index, view or +** trigger). All names are legal except those that begin with the string +** "sqlite_" (in upper, lower or mixed case). This portion of the namespace +** is reserved for internal use. +*/ +SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *pParse, const char *zName){ + if( !pParse->db->init.busy && pParse->nested==0 + && (pParse->db->flags & SQLITE_WriteSchema)==0 + && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ + sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName); + return SQLITE_ERROR; + } + return SQLITE_OK; +} + +/* +** Return the PRIMARY KEY index of a table +*/ +SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table *pTab){ + Index *p; + for(p=pTab->pIndex; p && !IsPrimaryKeyIndex(p); p=p->pNext){} + return p; +} + +/* +** Return the column of index pIdx that corresponds to table +** column iCol. Return -1 if not found. +*/ +SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index *pIdx, i16 iCol){ + int i; + for(i=0; inColumn; i++){ + if( iCol==pIdx->aiColumn[i] ) return i; + } + return -1; +} + +/* +** Begin constructing a new table representation in memory. This is +** the first of several action routines that get called in response +** to a CREATE TABLE statement. In particular, this routine is called +** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp +** flag is true if the table should be stored in the auxiliary database +** file instead of in the main database file. This is normally the case +** when the "TEMP" or "TEMPORARY" keyword occurs in between +** CREATE and TABLE. +** +** The new table record is initialized and put in pParse->pNewTable. +** As more of the CREATE TABLE statement is parsed, additional action +** routines will be called to add more information to this record. +** At the end of the CREATE TABLE statement, the sqlite3EndTable() routine +** is called to complete the construction of the new table record. +*/ +SQLITE_PRIVATE void sqlite3StartTable( + Parse *pParse, /* Parser context */ + Token *pName1, /* First part of the name of the table or view */ + Token *pName2, /* Second part of the name of the table or view */ + int isTemp, /* True if this is a TEMP table */ + int isView, /* True if this is a VIEW */ + int isVirtual, /* True if this is a VIRTUAL table */ + int noErr /* Do nothing if table already exists */ +){ + Table *pTable; + char *zName = 0; /* The name of the new table */ + sqlite3 *db = pParse->db; + Vdbe *v; + int iDb; /* Database number to create the table in */ + Token *pName; /* Unqualified name of the table to create */ + + /* The table or view name to create is passed to this routine via tokens + ** pName1 and pName2. If the table name was fully qualified, for example: + ** + ** CREATE TABLE xxx.yyy (...); + ** + ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if + ** the table name is not fully qualified, i.e.: + ** + ** CREATE TABLE yyy(...); + ** + ** Then pName1 is set to "yyy" and pName2 is "". + ** + ** The call below sets the pName pointer to point at the token (pName1 or + ** pName2) that stores the unqualified table name. The variable iDb is + ** set to the index of the database that the table or view is to be + ** created in. + */ + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); + if( iDb<0 ) return; + if( !OMIT_TEMPDB && isTemp && pName2->n>0 && iDb!=1 ){ + /* If creating a temp table, the name may not be qualified. Unless + ** the database name is "temp" anyway. */ + sqlite3ErrorMsg(pParse, "temporary table name must be unqualified"); + return; + } + if( !OMIT_TEMPDB && isTemp ) iDb = 1; + + pParse->sNameToken = *pName; + zName = sqlite3NameFromToken(db, pName); + if( zName==0 ) return; + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto begin_table_error; + } + if( db->init.iDb==1 ) isTemp = 1; +#ifndef SQLITE_OMIT_AUTHORIZATION + assert( (isTemp & 1)==isTemp ); + { + int code; + char *zDb = db->aDb[iDb].zName; + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ + goto begin_table_error; + } + if( isView ){ + if( !OMIT_TEMPDB && isTemp ){ + code = SQLITE_CREATE_TEMP_VIEW; + }else{ + code = SQLITE_CREATE_VIEW; + } + }else{ + if( !OMIT_TEMPDB && isTemp ){ + code = SQLITE_CREATE_TEMP_TABLE; + }else{ + code = SQLITE_CREATE_TABLE; + } + } + if( !isVirtual && sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){ + goto begin_table_error; + } + } +#endif + + /* Make sure the new table name does not collide with an existing + ** index or table name in the same database. Issue an error message if + ** it does. The exception is if the statement being parsed was passed + ** to an sqlite3_declare_vtab() call. In that case only the column names + ** and types will be used, so there is no need to test for namespace + ** collisions. + */ + if( !IN_DECLARE_VTAB ){ + char *zDb = db->aDb[iDb].zName; + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + goto begin_table_error; + } + pTable = sqlite3FindTable(db, zName, zDb); + if( pTable ){ + if( !noErr ){ + sqlite3ErrorMsg(pParse, "table %T already exists", pName); + }else{ + assert( !db->init.busy || CORRUPT_DB ); + sqlite3CodeVerifySchema(pParse, iDb); + } + goto begin_table_error; + } + if( sqlite3FindIndex(db, zName, zDb)!=0 ){ + sqlite3ErrorMsg(pParse, "there is already an index named %s", zName); + goto begin_table_error; + } + } + + pTable = sqlite3DbMallocZero(db, sizeof(Table)); + if( pTable==0 ){ + db->mallocFailed = 1; + pParse->rc = SQLITE_NOMEM; + pParse->nErr++; + goto begin_table_e